2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
30 /* look in server.c for some explanation of these variables */
32 extern int DEBUGLEVEL;
34 extern int chain_fnum;
35 extern char magic_char;
36 extern connection_struct Connections[];
37 extern files_struct Files[];
38 extern BOOL case_sensitive;
39 extern pstring sesssetup_user;
42 /* this macro should always be used to extract an fnum (smb_fid) from
43 a packet to ensure chaining works correctly */
44 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
47 /****************************************************************************
48 reply to an special message
49 ****************************************************************************/
50 int reply_special(char *inbuf,char *outbuf)
53 int msg_type = CVAL(inbuf,0);
54 int msg_flags = CVAL(inbuf,1);
56 extern fstring remote_machine;
57 extern fstring local_machine;
66 case 0x81: /* session request */
67 CVAL(outbuf,0) = 0x82;
69 if (name_len(inbuf+4) > 50)
71 DEBUG(0,("Invalid name length in session request\n"));
74 name_extract(inbuf,4,name1);
75 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
76 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2));
78 strcpy(remote_machine,name2);
79 trim_string(remote_machine," "," ");
80 p = strchr(remote_machine,' ');
81 strlower(remote_machine);
84 strcpy(local_machine,name1);
85 trim_string(local_machine," "," ");
86 p = strchr(local_machine,' ');
87 strlower(local_machine);
90 add_session_user(remote_machine);
92 reload_services(True);
96 case 0x85: /* session keepalive */
101 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags));
107 /*******************************************************************
108 work out what error to give to a failed connection
109 ********************************************************************/
110 static int connection_error(char *inbuf,char *outbuf,int connection_num)
112 switch (connection_num)
115 return(ERROR(ERRSRV,ERRnoresource));
117 return(ERROR(ERRSRV,ERRbaduid));
119 return(ERROR(ERRSRV,ERRinvdevice));
121 return(ERROR(ERRSRV,ERRinvnetname));
123 return(ERROR(ERRSRV,ERRaccess));
125 return(ERROR(ERRDOS,ERRnoipc));
127 return(ERROR(ERRSRV,ERRinvnetname));
129 return(ERROR(ERRSRV,ERRbadpw));
134 /****************************************************************************
135 parse a share descriptor string
136 ****************************************************************************/
137 static void parse_connect(char *p,char *service,char *user,
138 char *password,int *pwlen,char *dev)
142 DEBUG(4,("parsing connect string %s\n",p));
144 p2 = strrchr(p,'\\');
148 strcpy(service,p2+1);
153 *pwlen = strlen(password);
160 p = strchr(service,'%');
171 /****************************************************************************
173 ****************************************************************************/
174 int reply_tcon(char *inbuf,char *outbuf)
182 int uid = SVAL(inbuf,smb_uid);
186 *service = *user = *password = *dev = 0;
188 vuid = valid_uid(uid);
190 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
192 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
194 if (connection_num < 0)
195 return(connection_error(inbuf,outbuf,connection_num));
197 outsize = set_message(outbuf,2,0,True);
198 SSVAL(outbuf,smb_vwv0,maxxmit);
199 SSVAL(outbuf,smb_vwv1,connection_num);
200 SSVAL(outbuf,smb_tid,connection_num);
202 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
208 /****************************************************************************
209 reply to a tcon and X
210 ****************************************************************************/
211 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
218 int uid = SVAL(inbuf,smb_uid);
220 int passlen = SVAL(inbuf,smb_vwv3);
222 *service = *user = *password = *devicename = 0;
224 /* we might have to close an old one */
225 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
226 close_cnum(SVAL(inbuf,smb_tid),uid);
228 vuid = valid_uid(uid);
233 memcpy(password,smb_buf(inbuf),passlen);
235 path = smb_buf(inbuf) + passlen;
236 DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
237 strcpy(service,path+2);
238 p = strchr(service,'\\');
240 return(ERROR(ERRSRV,ERRinvnetname));
243 p = strchr(service,'%');
249 StrnCpy(devicename,path + strlen(path) + 1,6);
250 DEBUG(4,("Got device type %s\n",devicename));
253 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
255 if (connection_num < 0)
256 return(connection_error(inbuf,outbuf,connection_num));
258 set_message(outbuf,2,strlen(devicename)+1,True);
260 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
262 /* set the incoming and outgoing tid to the just created one */
263 SSVAL(inbuf,smb_tid,connection_num);
264 SSVAL(outbuf,smb_tid,connection_num);
266 strcpy(smb_buf(outbuf),devicename);
268 return chain_reply(inbuf,outbuf,length,bufsize);
272 /****************************************************************************
273 reply to an unknown type
274 ****************************************************************************/
275 int reply_unknown(char *inbuf,char *outbuf)
279 cnum = SVAL(inbuf,smb_tid);
280 type = CVAL(inbuf,smb_com);
282 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
287 return(ERROR(ERRSRV,ERRunknownsmb));
291 /****************************************************************************
293 ****************************************************************************/
294 int reply_ioctl(char *inbuf,char *outbuf)
296 DEBUG(3,("ignoring ioctl\n"));
298 return(ERROR(ERRSRV,ERRnosupport));
302 /****************************************************************************
303 reply to a session setup command
304 ****************************************************************************/
305 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
315 int smb_ntpasslen = 0;
316 pstring smb_ntpasswd;
317 BOOL valid_nt_password = False;
320 BOOL computer_id=False;
324 sess_uid = SVAL(inbuf,smb_uid);
325 smb_bufsize = SVAL(inbuf,smb_vwv2);
326 smb_mpxmax = SVAL(inbuf,smb_vwv3);
327 smb_vc_num = SVAL(inbuf,smb_vwv4);
328 smb_sesskey = IVAL(inbuf,smb_vwv5);
330 if (Protocol < PROTOCOL_NT1) {
331 smb_apasslen = SVAL(inbuf,smb_vwv7);
332 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
333 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
335 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
336 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
337 BOOL doencrypt = SMBENCRYPT();
338 char *p = smb_buf(inbuf);
339 if (passlen1 > 256) passlen1 = 0;
340 if (passlen2 > 256) passlen2 = 0; /* I don't know why NT gives weird
343 /* Save the lanman2 password and the NT md4 password. */
344 smb_apasslen = passlen1;
345 memcpy(smb_apasswd,p,smb_apasslen);
346 smb_ntpasslen = passlen2;
347 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
350 if (passlen1 > passlen2) {
351 smb_apasslen = passlen1;
352 StrnCpy(smb_apasswd,p,smb_apasslen);
354 smb_apasslen = passlen2;
355 StrnCpy(smb_apasswd,p + passlen1,smb_apasslen);
360 /* apparently NT sometimes sets passlen2 to 1 when it means 0. This
361 tries to work around that problem */
365 p += passlen1 + passlen2;
366 strcpy(user,p); p = skip_string(p,1);
367 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
368 p,skip_string(p,1),skip_string(p,2)));
372 DEBUG(3,("sesssetupX:name=[%s]\n",user));
374 /* If name ends in $ then I think it's asking about whether a */
375 /* computer with that name (minus the $) has access. For now */
376 /* say yes to everything ending in $. */
377 if (user[strlen(user) - 1] == '$') {
379 user[strlen(user) - 1] = '\0';
384 strcpy(user,lp_guestaccount(-1));
388 strcpy(sesssetup_user,user);
390 reload_services(True);
392 add_session_user(user);
395 if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
396 !check_hosts_equiv(user))
399 if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
402 /* now check if it's a valid username/password */
403 /* If an NT password was supplied try and validate with that
404 first. This is superior as the passwords are mixed case 128 length unicode */
405 if(smb_ntpasslen && !guest)
407 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL,True))
408 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
410 valid_nt_password = True;
412 if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL,False))
414 if (!computer_id && lp_security() >= SEC_USER) {
415 #if (GUEST_SESSSETUP == 0)
416 return(ERROR(ERRSRV,ERRbadpw));
418 #if (GUEST_SESSSETUP == 1)
419 if (Get_Pwnam(user,True))
420 return(ERROR(ERRSRV,ERRbadpw));
423 if (*smb_apasswd || !Get_Pwnam(user,True))
424 strcpy(user,lp_guestaccount(-1));
425 DEBUG(3,("Registered username %s for guest access\n",user));
430 if (!Get_Pwnam(user,True)) {
431 DEBUG(3,("No such user %s - using guest account\n",user));
432 strcpy(user,lp_guestaccount(-1));
436 if (!strequal(user,lp_guestaccount(-1)) &&
437 lp_servicenumber(user) < 0)
439 int homes = lp_servicenumber(HOMES_NAME);
440 char *home = get_home_dir(user);
441 if (homes >= 0 && home)
442 lp_add_home(user,homes,home);
446 /* it's ok - setup a reply */
447 if (Protocol < PROTOCOL_NT1) {
448 set_message(outbuf,3,0,True);
451 set_message(outbuf,3,3,True);
453 strcpy(p,"Unix"); p = skip_string(p,1);
454 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
455 strcpy(p,lp_workgroup()); p = skip_string(p,1);
456 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
457 /* perhaps grab OS version here?? */
460 /* Set the correct uid in the outgoing and incoming packets
461 We will use this on future requests to determine which
462 user we should become.
465 struct passwd *pw = Get_Pwnam(user,False);
467 DEBUG(1,("Username %s is invalid on this system\n",user));
468 return(ERROR(ERRSRV,ERRbadpw));
471 SSVAL(outbuf,smb_uid,(uint16)pw->pw_uid);
472 SSVAL(inbuf,smb_uid,(uint16)pw->pw_uid);
475 if (guest && !computer_id)
476 SSVAL(outbuf,smb_vwv2,1);
478 /* register the name and uid as being validated, so further connections
479 to a uid can get through without a password, on the same VC */
480 register_uid(SVAL(inbuf,smb_uid),gid,user,guest);
482 maxxmit = MIN(maxxmit,smb_bufsize);
484 return chain_reply(inbuf,outbuf,length,bufsize);
488 /****************************************************************************
490 ****************************************************************************/
491 int reply_chkpth(char *inbuf,char *outbuf)
498 cnum = SVAL(inbuf,smb_tid);
500 strcpy(name,smb_buf(inbuf) + 1);
501 unix_convert(name,cnum);
503 mode = SVAL(inbuf,smb_vwv0);
505 if (check_name(name,cnum))
506 ok = directory_exist(name,NULL);
509 return(ERROR(ERRDOS,ERRbadpath));
511 outsize = set_message(outbuf,0,0,True);
513 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
519 /****************************************************************************
521 ****************************************************************************/
522 int reply_getatr(char *inbuf,char *outbuf)
533 cnum = SVAL(inbuf,smb_tid);
535 strcpy(fname,smb_buf(inbuf) + 1);
536 unix_convert(fname,cnum);
538 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
539 under WfWg - weird! */
542 mode = aHIDDEN | aDIR;
543 if (!CAN_WRITE(cnum)) mode |= aRONLY;
549 if (check_name(fname,cnum))
551 if (sys_stat(fname,&sbuf) == 0)
553 mode = dos_mode(cnum,fname,&sbuf);
555 mtime = sbuf.st_mtime;
561 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
565 return(UNIXERROR(ERRDOS,ERRbadfile));
567 outsize = set_message(outbuf,10,0,True);
569 SSVAL(outbuf,smb_vwv0,mode);
570 put_dos_date3(outbuf,smb_vwv1,mtime);
571 SIVAL(outbuf,smb_vwv3,size);
573 if (Protocol >= PROTOCOL_NT1) {
574 char *p = strrchr(fname,'/');
575 uint16 flg2 = SVAL(outbuf,smb_flg2);
578 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
581 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
587 /****************************************************************************
589 ****************************************************************************/
590 int reply_setatr(char *inbuf,char *outbuf)
599 cnum = SVAL(inbuf,smb_tid);
601 strcpy(fname,smb_buf(inbuf) + 1);
602 unix_convert(fname,cnum);
604 mode = SVAL(inbuf,smb_vwv0);
605 mtime = make_unix_date3(inbuf+smb_vwv1);
607 if (directory_exist(fname,NULL))
609 if (check_name(fname,cnum))
610 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
612 ok = set_filetime(fname,mtime);
615 return(UNIXERROR(ERRDOS,ERRnoaccess));
617 outsize = set_message(outbuf,0,0,True);
619 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
625 /****************************************************************************
627 ****************************************************************************/
628 int reply_dskattr(char *inbuf,char *outbuf)
632 int dfree,dsize,bsize;
634 cnum = SVAL(inbuf,smb_tid);
636 sys_disk_free(".",&bsize,&dfree,&dsize);
638 outsize = set_message(outbuf,5,0,True);
640 SSVAL(outbuf,smb_vwv0,dsize);
641 SSVAL(outbuf,smb_vwv1,bsize/512);
642 SSVAL(outbuf,smb_vwv2,512);
643 SSVAL(outbuf,smb_vwv3,dfree);
645 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
651 /****************************************************************************
653 Can be called from SMBsearch, SMBffirst or SMBfunique.
654 ****************************************************************************/
655 int reply_search(char *inbuf,char *outbuf)
666 BOOL finished = False;
675 BOOL check_descend = False;
676 BOOL expect_close = False;
677 BOOL can_open = True;
679 *mask = *directory = *fname = 0;
681 /* If we were called as SMBffirst then we must expect close. */
682 if(CVAL(inbuf,smb_com) == SMBffirst)
685 cnum = SVAL(inbuf,smb_tid);
687 outsize = set_message(outbuf,1,3,True);
688 maxentries = SVAL(inbuf,smb_vwv0);
689 dirtype = SVAL(inbuf,smb_vwv1);
690 path = smb_buf(inbuf) + 1;
691 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
694 /* dirtype &= ~aDIR; */
696 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
703 strcpy(directory,smb_buf(inbuf)+1);
704 strcpy(dir2,smb_buf(inbuf)+1);
705 unix_convert(directory,cnum);
708 if (!check_name(directory,cnum))
711 p = strrchr(dir2,'/');
713 {strcpy(mask,dir2);*dir2 = 0;}
715 {*p = 0;strcpy(mask,p+1);}
717 p = strrchr(directory,'/');
723 if (strlen(directory) == 0)
724 strcpy(directory,"./");
726 CVAL(status,0) = dirtype;
730 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
731 memcpy(mask,status+1,11);
733 dirtype = CVAL(status,0) & 0x1F;
734 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
735 if (!Connections[cnum].dirptr)
737 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
742 /* turn strings of spaces into a . */
744 trim_string(mask,NULL," ");
745 if ((p = strrchr(mask,' ')))
750 trim_string(mask,NULL," ");
757 for (p=mask; *p; p++)
759 if (*p != '?' && *p != '*' && !isdoschar(*p))
761 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
767 if (!strchr(mask,'.') && strlen(mask)>8)
770 strcpy(tmp,&mask[8]);
776 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
780 p = smb_buf(outbuf) + 3;
786 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
788 return(ERROR(ERRDOS,ERRnofids));
791 DEBUG(4,("dptr_num is %d\n",dptr_num));
795 if ((dirtype&0x1F) == aVOLID)
798 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
799 dptr_fill(p+12,dptr_num);
800 if (dptr_zero(p+12) && (status_len==0))
804 p += DIR_STRUCT_SIZE;
808 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
809 if (in_list(Connections[cnum].dirpath,
810 lp_dontdescend(SNUM(cnum)),True))
811 check_descend = True;
813 for (i=numentries;(i<maxentries) && !finished;i++)
816 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
820 make_dir_struct(p,mask,fname,size,mode,date);
821 dptr_fill(p+12,dptr_num);
824 p += DIR_STRUCT_SIZE;
833 if (numentries == 0 || !ok)
835 CVAL(outbuf,smb_rcls) = ERRDOS;
836 SSVAL(outbuf,smb_err,ERRnofiles);
839 /* If we were called as SMBffirst with smb_search_id == NULL
840 and no entries were found then return error and close dirptr
843 if(ok && expect_close && numentries == 0 && status_len == 0)
845 CVAL(outbuf,smb_rcls) = ERRDOS;
846 SSVAL(outbuf,smb_err,ERRnofiles);
847 /* Also close the dptr - we know it's gone */
848 dptr_close(dptr_num);
851 /* If we were called as SMBfunique, then we can close the dirptr now ! */
852 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
853 dptr_close(dptr_num);
855 SSVAL(outbuf,smb_vwv0,numentries);
856 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
857 CVAL(smb_buf(outbuf),0) = 5;
858 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
860 if (Protocol >= PROTOCOL_NT1) {
861 uint16 flg2 = SVAL(outbuf,smb_flg2);
862 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
865 outsize += DIR_STRUCT_SIZE*numentries;
866 smb_setlen(outbuf,outsize - 4);
868 if ((! *directory) && dptr_path(dptr_num))
869 sprintf(directory,"(%s)",dptr_path(dptr_num));
871 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
873 smb_fn_name(CVAL(inbuf,smb_com)),
874 mask,directory,cnum,dirtype,numentries,maxentries));
880 /****************************************************************************
881 reply to a fclose (stop directory search)
882 ****************************************************************************/
883 int reply_fclose(char *inbuf,char *outbuf)
892 cnum = SVAL(inbuf,smb_tid);
894 outsize = set_message(outbuf,1,0,True);
895 path = smb_buf(inbuf) + 1;
896 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
900 return(ERROR(ERRSRV,ERRsrverror));
902 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
904 if(dptr_fetch(status+12,&dptr_num)) {
905 /* Close the dptr - we know it's gone */
906 dptr_close(dptr_num);
909 SSVAL(outbuf,smb_vwv0,0);
911 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
917 /****************************************************************************
919 ****************************************************************************/
920 int reply_open(char *inbuf,char *outbuf)
934 cnum = SVAL(inbuf,smb_tid);
936 share_mode = SVAL(inbuf,smb_vwv0);
938 strcpy(fname,smb_buf(inbuf)+1);
939 unix_convert(fname,cnum);
941 fnum = find_free_file();
943 return(ERROR(ERRSRV,ERRnofids));
945 if (!check_name(fname,cnum))
946 return(UNIXERROR(ERRDOS,ERRnoaccess));
948 unixmode = unix_mode(cnum,aARCH);
950 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
952 if (!Files[fnum].open)
953 return(UNIXERROR(ERRDOS,ERRnoaccess));
955 if (fstat(Files[fnum].fd,&sbuf) != 0) {
957 return(ERROR(ERRDOS,ERRnoaccess));
961 fmode = dos_mode(cnum,fname,&sbuf);
962 mtime = sbuf.st_mtime;
965 DEBUG(3,("attempt to open a directory %s\n",fname));
967 return(ERROR(ERRDOS,ERRnoaccess));
970 outsize = set_message(outbuf,7,0,True);
971 SSVAL(outbuf,smb_vwv0,fnum);
972 SSVAL(outbuf,smb_vwv1,fmode);
973 put_dos_date3(outbuf,smb_vwv2,mtime);
974 SIVAL(outbuf,smb_vwv4,size);
975 SSVAL(outbuf,smb_vwv6,rmode);
981 /****************************************************************************
982 reply to an open and X
983 ****************************************************************************/
984 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
987 int cnum = SVAL(inbuf,smb_tid);
990 int smb_mode = SVAL(inbuf,smb_vwv3);
991 int smb_attr = SVAL(inbuf,smb_vwv5);
993 int open_flags = SVAL(inbuf,smb_vwv2);
994 int smb_sattr = SVAL(inbuf,smb_vwv4);
995 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
997 int smb_ofun = SVAL(inbuf,smb_vwv8);
999 int size=0,fmode=0,mtime=0,rmode=0;
1003 /* If it's an IPC, pass off the pipe handler. */
1005 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1007 /* XXXX we need to handle passed times, sattr and flags */
1009 strcpy(fname,smb_buf(inbuf));
1010 unix_convert(fname,cnum);
1012 /* now add create and trunc bits */
1013 if (smb_ofun & 0x10)
1014 openmode |= O_CREAT;
1015 if ((smb_ofun & 0x3) == 2)
1016 openmode |= O_TRUNC;
1018 fnum = find_free_file();
1020 return(ERROR(ERRSRV,ERRnofids));
1022 if (!check_name(fname,cnum))
1023 return(UNIXERROR(ERRDOS,ERRnoaccess));
1025 unixmode = unix_mode(cnum,smb_attr | aARCH);
1027 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1028 &rmode,&smb_action);
1030 if (!Files[fnum].open)
1031 return(UNIXERROR(ERRDOS,ERRnoaccess));
1033 if (fstat(Files[fnum].fd,&sbuf) != 0) {
1035 return(ERROR(ERRDOS,ERRnoaccess));
1038 size = sbuf.st_size;
1039 fmode = dos_mode(cnum,fname,&sbuf);
1040 mtime = sbuf.st_mtime;
1043 return(ERROR(ERRDOS,ERRnoaccess));
1046 set_message(outbuf,15,0,True);
1047 SSVAL(outbuf,smb_vwv2,fnum);
1048 SSVAL(outbuf,smb_vwv3,fmode);
1049 put_dos_date3(outbuf,smb_vwv4,mtime);
1050 SIVAL(outbuf,smb_vwv6,size);
1051 SSVAL(outbuf,smb_vwv8,rmode);
1052 SSVAL(outbuf,smb_vwv11,smb_action);
1056 return chain_reply(inbuf,outbuf,length,bufsize);
1060 /****************************************************************************
1061 reply to a SMBulogoffX
1062 ****************************************************************************/
1063 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1065 int uid = SVAL(inbuf,smb_uid);
1067 invalidate_uid(uid);
1069 set_message(outbuf,2,0,True);
1071 DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid));
1073 return chain_reply(inbuf,outbuf,length,bufsize);
1077 /****************************************************************************
1079 ****************************************************************************/
1080 int reply_mknew(char *inbuf,char *outbuf)
1089 com = SVAL(inbuf,smb_com);
1090 cnum = SVAL(inbuf,smb_tid);
1092 createmode = SVAL(inbuf,smb_vwv0);
1093 strcpy(fname,smb_buf(inbuf)+1);
1094 unix_convert(fname,cnum);
1096 if (createmode & aVOLID)
1098 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1101 unixmode = unix_mode(cnum,createmode);
1103 if (com == SMBmknew && file_exist(fname,NULL))
1104 return(ERROR(ERRDOS,ERRfilexists));
1106 fnum = find_free_file();
1108 return(ERROR(ERRSRV,ERRnofids));
1110 if (!check_name(fname,cnum))
1111 return(UNIXERROR(ERRDOS,ERRnoaccess));
1113 open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1115 if (!Files[fnum].open)
1116 return(UNIXERROR(ERRDOS,ERRnoaccess));
1118 outsize = set_message(outbuf,1,0,True);
1119 SSVAL(outbuf,smb_vwv0,fnum);
1121 DEBUG(2,("new file %s\n",fname));
1122 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));
1128 /****************************************************************************
1129 reply to a create temporary file
1130 ****************************************************************************/
1131 int reply_ctemp(char *inbuf,char *outbuf)
1141 cnum = SVAL(inbuf,smb_tid);
1142 createmode = SVAL(inbuf,smb_vwv0);
1143 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1144 unix_convert(fname,cnum);
1146 unixmode = unix_mode(cnum,createmode);
1148 fnum = find_free_file();
1150 return(ERROR(ERRSRV,ERRnofids));
1152 if (!check_name(fname,cnum))
1153 return(UNIXERROR(ERRDOS,ERRnoaccess));
1155 strcpy(fname2,(char *)mktemp(fname));
1157 open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1159 if (!Files[fnum].open)
1160 return(UNIXERROR(ERRDOS,ERRnoaccess));
1162 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1163 SSVAL(outbuf,smb_vwv0,fnum);
1164 CVAL(smb_buf(outbuf),0) = 4;
1165 strcpy(smb_buf(outbuf) + 1,fname2);
1167 DEBUG(2,("created temp file %s\n",fname2));
1168 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));
1174 /*******************************************************************
1175 check if a user is allowed to delete a file
1176 ********************************************************************/
1177 static BOOL can_delete(char *fname,int cnum,int dirtype)
1182 if (!CAN_WRITE(cnum)) return(False);
1184 if (sys_lstat(fname,&sbuf) != 0) return(False);
1185 fmode = dos_mode(cnum,fname,&sbuf);
1186 if (fmode & aDIR) return(False);
1187 if (!lp_delete_readonly(SNUM(cnum))) {
1188 if (fmode & aRONLY) return(False);
1190 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1192 if (!check_file_sharing(cnum,fname)) return(False);
1196 /****************************************************************************
1198 ****************************************************************************/
1199 int reply_unlink(char *inbuf,char *outbuf)
1209 int error = ERRnoaccess;
1213 *directory = *mask = 0;
1215 cnum = SVAL(inbuf,smb_tid);
1216 dirtype = SVAL(inbuf,smb_vwv0);
1218 strcpy(name,smb_buf(inbuf) + 1);
1220 DEBUG(3,("reply_unlink : %s\n",name));
1222 unix_convert(name,cnum);
1224 p = strrchr(name,'/');
1226 strcpy(directory,"./");
1230 strcpy(directory,name);
1234 if (is_mangled(mask))
1235 check_mangled_stack(mask);
1237 has_wild = strchr(mask,'*') || strchr(mask,'?');
1240 strcat(directory,"/");
1241 strcat(directory,mask);
1242 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1243 if (!count) exists = file_exist(directory,NULL);
1245 void *dirptr = NULL;
1248 if (check_name(directory,cnum))
1249 dirptr = OpenDir(directory);
1251 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1252 the pattern matches against the long name, otherwise the short name
1253 We don't implement this yet XXXX
1260 if (strequal(mask,"????????.???"))
1263 while ((dname = ReadDirName(dirptr)))
1266 strcpy(fname,dname);
1268 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1270 error = ERRnoaccess;
1271 sprintf(fname,"%s/%s",directory,dname);
1272 if (!can_delete(fname,cnum,dirtype)) continue;
1273 if (!sys_unlink(fname)) count++;
1274 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1282 return(ERROR(ERRDOS,error));
1284 return(UNIXERROR(ERRDOS,error));
1287 outsize = set_message(outbuf,0,0,True);
1293 /****************************************************************************
1294 reply to a readbraw (core+ protocol)
1295 ****************************************************************************/
1296 int reply_readbraw(char *inbuf, char *outbuf)
1298 int cnum,maxcount,mincount,fnum;
1301 char *header = outbuf;
1306 cnum = SVAL(inbuf,smb_tid);
1307 fnum = GETFNUM(inbuf,smb_vwv0);
1309 startpos = IVAL(inbuf,smb_vwv1);
1310 maxcount = SVAL(inbuf,smb_vwv3);
1311 mincount = SVAL(inbuf,smb_vwv4);
1313 /* ensure we don't overrun the packet size */
1314 maxcount = MIN(65535,maxcount);
1315 maxcount = MAX(mincount,maxcount);
1317 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1319 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1320 _smb_setlen(header,0);
1321 transfer_file(0,Client,0,header,4,0);
1326 fd = Files[fnum].fd;
1327 fname = Files[fnum].name;
1331 if (!is_locked(fnum,cnum,maxcount,startpos))
1333 int size = Files[fnum].size;
1334 int sizeneeded = startpos + maxcount;
1336 if (size < sizeneeded) {
1338 if (fstat(Files[fnum].fd,&st) == 0)
1340 if (!Files[fnum].can_write)
1341 Files[fnum].size = size;
1344 nread = MIN(maxcount,size - startpos);
1347 if (nread < mincount)
1350 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1353 maxcount,mincount,nread));
1358 _smb_setlen(header,nread);
1360 if (!Files[fnum].can_write)
1361 predict = read_predict(fd,startpos,header+4,NULL,nread);
1363 if ((nread-predict) > 0)
1364 seek_file(fnum,startpos + predict);
1366 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1371 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1372 fname,startpos,nread,ret));
1375 ret = read_file(fnum,header+4,startpos,nread);
1376 if (ret < mincount) ret = 0;
1378 _smb_setlen(header,ret);
1379 transfer_file(0,Client,0,header,4+ret,0);
1382 DEBUG(5,("readbraw finished\n"));
1387 /****************************************************************************
1388 reply to a lockread (core+ protocol)
1389 ****************************************************************************/
1390 int reply_lockread(char *inbuf,char *outbuf)
1396 uint32 startpos, numtoread;
1400 cnum = SVAL(inbuf,smb_tid);
1401 fnum = GETFNUM(inbuf,smb_vwv0);
1403 CHECK_FNUM(fnum,cnum);
1407 numtoread = SVAL(inbuf,smb_vwv1);
1408 startpos = IVAL(inbuf,smb_vwv2);
1410 outsize = set_message(outbuf,5,3,True);
1411 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1412 data = smb_buf(outbuf) + 3;
1414 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1415 return (ERROR(eclass,ecode));
1417 nread = read_file(fnum,data,startpos,numtoread);
1420 return(UNIXERROR(ERRDOS,ERRnoaccess));
1423 SSVAL(outbuf,smb_vwv0,nread);
1424 SSVAL(outbuf,smb_vwv5,nread+3);
1425 SSVAL(smb_buf(outbuf),1,nread);
1427 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1433 /****************************************************************************
1435 ****************************************************************************/
1436 int reply_read(char *inbuf,char *outbuf)
1438 int cnum,numtoread,fnum;
1444 cnum = SVAL(inbuf,smb_tid);
1445 fnum = GETFNUM(inbuf,smb_vwv0);
1447 CHECK_FNUM(fnum,cnum);
1451 numtoread = SVAL(inbuf,smb_vwv1);
1452 startpos = IVAL(inbuf,smb_vwv2);
1454 outsize = set_message(outbuf,5,3,True);
1455 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1456 data = smb_buf(outbuf) + 3;
1458 if (is_locked(fnum,cnum,numtoread,startpos))
1459 return(ERROR(ERRDOS,ERRlock));
1462 nread = read_file(fnum,data,startpos,numtoread);
1465 return(UNIXERROR(ERRDOS,ERRnoaccess));
1468 SSVAL(outbuf,smb_vwv0,nread);
1469 SSVAL(outbuf,smb_vwv5,nread+3);
1470 CVAL(smb_buf(outbuf),0) = 1;
1471 SSVAL(smb_buf(outbuf),1,nread);
1473 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1479 /****************************************************************************
1480 reply to a read and X
1481 ****************************************************************************/
1482 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1484 int fnum = GETFNUM(inbuf,smb_vwv2);
1485 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1486 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1487 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1493 cnum = SVAL(inbuf,smb_tid);
1495 CHECK_FNUM(fnum,cnum);
1499 set_message(outbuf,12,0,True);
1500 data = smb_buf(outbuf);
1502 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1503 return(ERROR(ERRDOS,ERRlock));
1504 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1508 return(UNIXERROR(ERRDOS,ERRnoaccess));
1510 SSVAL(outbuf,smb_vwv5,nread);
1511 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1512 SSVAL(smb_buf(outbuf),-2,nread);
1514 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1515 timestring(),fnum,cnum,
1516 smb_mincnt,smb_maxcnt,nread));
1520 return chain_reply(inbuf,outbuf,length,bufsize);
1524 /****************************************************************************
1525 reply to a writebraw (core+ or LANMAN1.0 protocol)
1526 ****************************************************************************/
1527 int reply_writebraw(char *inbuf,char *outbuf)
1530 int total_written=0;
1539 cnum = SVAL(inbuf,smb_tid);
1540 fnum = GETFNUM(inbuf,smb_vwv0);
1542 CHECK_FNUM(fnum,cnum);
1546 tcount = IVAL(inbuf,smb_vwv1);
1547 startpos = IVAL(inbuf,smb_vwv3);
1548 write_through = BITSETW(inbuf+smb_vwv7,0);
1550 /* We have to deal with slightly different formats depending
1551 on whether we are using the core+ or lanman1.0 protocol */
1552 if(Protocol <= PROTOCOL_COREPLUS) {
1553 numtowrite = SVAL(smb_buf(inbuf),-2);
1554 data = smb_buf(inbuf);
1556 numtowrite = SVAL(inbuf,smb_vwv10);
1557 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1560 /* force the error type */
1561 CVAL(inbuf,smb_com) = SMBwritec;
1562 CVAL(outbuf,smb_com) = SMBwritec;
1564 if (is_locked(fnum,cnum,tcount,startpos))
1565 return(ERROR(ERRDOS,ERRlock));
1567 if (seek_file(fnum,startpos) != startpos)
1568 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1571 nwritten = write_file(fnum,data,numtowrite);
1573 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1574 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1576 if (nwritten < numtowrite)
1577 return(UNIXERROR(ERRHRD,ERRdiskfull));
1579 total_written = nwritten;
1581 /* Return a message to the redirector to tell it
1582 to send more bytes */
1583 CVAL(outbuf,smb_com) = SMBwritebraw;
1584 SSVALS(outbuf,smb_vwv0,-1);
1585 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1586 send_smb(Client,outbuf);
1588 /* Now read the raw data into the buffer and write it */
1589 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1590 exit_server("secondary writebraw failed");
1593 /* Even though this is not an smb message, smb_len
1594 returns the generic length of an smb message */
1595 numtowrite = smb_len(inbuf);
1597 if (tcount > nwritten+numtowrite) {
1598 DEBUG(3,("Client overestimated the write %d %d %d\n",
1599 tcount,nwritten,numtowrite));
1602 nwritten = transfer_file(Client,Files[fnum].fd,numtowrite,NULL,0,
1604 total_written += nwritten;
1606 /* Set up outbuf to return the correct return */
1607 outsize = set_message(outbuf,1,0,True);
1608 CVAL(outbuf,smb_com) = SMBwritec;
1609 SSVAL(outbuf,smb_vwv0,total_written);
1611 if (nwritten < numtowrite) {
1612 CVAL(outbuf,smb_rcls) = ERRHRD;
1613 SSVAL(outbuf,smb_err,ERRdiskfull);
1616 if (lp_syncalways(SNUM(cnum)) || write_through)
1619 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1620 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1622 /* we won't return a status if write through is not selected - this
1623 follows what WfWg does */
1624 if (!write_through && total_written==tcount)
1631 /****************************************************************************
1632 reply to a writeunlock (core+)
1633 ****************************************************************************/
1634 int reply_writeunlock(char *inbuf,char *outbuf)
1640 uint32 numtowrite,startpos;
1644 cnum = SVAL(inbuf,smb_tid);
1645 fnum = GETFNUM(inbuf,smb_vwv0);
1647 CHECK_FNUM(fnum,cnum);
1651 numtowrite = SVAL(inbuf,smb_vwv1);
1652 startpos = IVAL(inbuf,smb_vwv2);
1653 data = smb_buf(inbuf) + 3;
1655 if (is_locked(fnum,cnum,numtowrite,startpos))
1656 return(ERROR(ERRDOS,ERRlock));
1658 seek_file(fnum,startpos);
1660 /* The special X/Open SMB protocol handling of
1661 zero length writes is *NOT* done for
1666 nwritten = write_file(fnum,data,numtowrite);
1668 if (lp_syncalways(SNUM(cnum)))
1671 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1672 return(UNIXERROR(ERRDOS,ERRnoaccess));
1674 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1675 return(ERROR(eclass,ecode));
1677 outsize = set_message(outbuf,1,0,True);
1679 SSVAL(outbuf,smb_vwv0,nwritten);
1681 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1682 timestring(),fnum,cnum,numtowrite,nwritten));
1688 /****************************************************************************
1690 ****************************************************************************/
1691 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1693 int cnum,numtowrite,fnum;
1702 cnum = SVAL(inbuf,smb_tid);
1703 fnum = GETFNUM(inbuf,smb_vwv0);
1705 CHECK_FNUM(fnum,cnum);
1709 numtowrite = SVAL(inbuf,smb_vwv1);
1710 startpos = IVAL(inbuf,smb_vwv2);
1711 data = smb_buf(inbuf) + 3;
1713 if (is_locked(fnum,cnum,numtowrite,startpos))
1714 return(ERROR(ERRDOS,ERRlock));
1716 seek_file(fnum,startpos);
1718 /* X/Open SMB protocol says that if smb_vwv1 is
1719 zero then the file size should be extended or
1720 truncated to the size given in smb_vwv[2-3] */
1722 nwritten = set_filelen(Files[fnum].fd, startpos);
1724 nwritten = write_file(fnum,data,numtowrite);
1726 if (lp_syncalways(SNUM(cnum)))
1729 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1730 return(UNIXERROR(ERRDOS,ERRnoaccess));
1732 outsize = set_message(outbuf,1,0,True);
1734 SSVAL(outbuf,smb_vwv0,nwritten);
1736 if (nwritten < numtowrite) {
1737 CVAL(outbuf,smb_rcls) = ERRHRD;
1738 SSVAL(outbuf,smb_err,ERRdiskfull);
1741 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1747 /****************************************************************************
1748 reply to a write and X
1749 ****************************************************************************/
1750 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1752 int fnum = GETFNUM(inbuf,smb_vwv2);
1753 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1754 int smb_dsize = SVAL(inbuf,smb_vwv10);
1755 int smb_doff = SVAL(inbuf,smb_vwv11);
1756 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1761 cnum = SVAL(inbuf,smb_tid);
1763 CHECK_FNUM(fnum,cnum);
1767 data = smb_base(inbuf) + smb_doff;
1769 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1770 return(ERROR(ERRDOS,ERRlock));
1772 seek_file(fnum,smb_offs);
1774 /* X/Open SMB protocol says that, unlike SMBwrite
1775 if the length is zero then NO truncation is
1776 done, just a write of zero. To truncate a file,
1781 nwritten = write_file(fnum,data,smb_dsize);
1783 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1784 return(UNIXERROR(ERRDOS,ERRnoaccess));
1786 set_message(outbuf,6,0,True);
1788 SSVAL(outbuf,smb_vwv2,nwritten);
1790 if (nwritten < smb_dsize) {
1791 CVAL(outbuf,smb_rcls) = ERRHRD;
1792 SSVAL(outbuf,smb_err,ERRdiskfull);
1795 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1799 if (lp_syncalways(SNUM(cnum)) || write_through)
1802 return chain_reply(inbuf,outbuf,length,bufsize);
1806 /****************************************************************************
1808 ****************************************************************************/
1809 int reply_lseek(char *inbuf,char *outbuf)
1817 cnum = SVAL(inbuf,smb_tid);
1818 fnum = GETFNUM(inbuf,smb_vwv0);
1820 CHECK_FNUM(fnum,cnum);
1823 mode = SVAL(inbuf,smb_vwv1) & 3;
1824 startpos = IVAL(inbuf,smb_vwv2);
1828 case 0: umode = SEEK_SET; break;
1829 case 1: umode = SEEK_CUR; break;
1830 case 2: umode = SEEK_END; break;
1832 umode = SEEK_SET; break;
1835 res = lseek(Files[fnum].fd,startpos,umode);
1836 Files[fnum].pos = res;
1838 outsize = set_message(outbuf,2,0,True);
1839 SIVALS(outbuf,smb_vwv0,res);
1841 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1847 /****************************************************************************
1849 ****************************************************************************/
1850 int reply_flush(char *inbuf,char *outbuf)
1853 int outsize = set_message(outbuf,0,0,True);
1855 cnum = SVAL(inbuf,smb_tid);
1856 fnum = GETFNUM(inbuf,smb_vwv0);
1858 if (fnum != 0xFFFF) {
1859 CHECK_FNUM(fnum,cnum);
1866 for (i=0;i<MAX_OPEN_FILES;i++)
1873 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1878 /****************************************************************************
1880 ****************************************************************************/
1881 int reply_exit(char *inbuf,char *outbuf)
1883 int outsize = set_message(outbuf,0,0,True);
1884 DEBUG(3,("%s exit\n",timestring()));
1890 /****************************************************************************
1892 ****************************************************************************/
1893 int reply_close(char *inbuf,char *outbuf)
1898 int32 eclass = 0, err = 0;
1900 outsize = set_message(outbuf,0,0,True);
1902 cnum = SVAL(inbuf,smb_tid);
1904 fnum = GETFNUM(inbuf,smb_vwv0);
1905 CHECK_FNUM(fnum,cnum);
1907 if(HAS_CACHED_ERROR(fnum)) {
1908 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1909 err = Files[fnum].wbmpx_ptr->wr_error;
1912 mtime = make_unix_date3(inbuf+smb_vwv1);
1914 /* try and set the date */
1915 set_filetime(Files[fnum].name,mtime);
1919 /* We have a cached error */
1921 return(ERROR(eclass,err));
1923 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
1924 timestring(),Files[fnum].fd,fnum,cnum,
1925 Connections[cnum].num_files_open));
1931 /****************************************************************************
1932 reply to a writeclose (Core+ protocol)
1933 ****************************************************************************/
1934 int reply_writeclose(char *inbuf,char *outbuf)
1936 int cnum,numtowrite,fnum;
1943 cnum = SVAL(inbuf,smb_tid);
1944 fnum = GETFNUM(inbuf,smb_vwv0);
1946 CHECK_FNUM(fnum,cnum);
1950 numtowrite = SVAL(inbuf,smb_vwv1);
1951 startpos = IVAL(inbuf,smb_vwv2);
1952 mtime = make_unix_date3(inbuf+smb_vwv4);
1953 data = smb_buf(inbuf) + 1;
1955 if (is_locked(fnum,cnum,numtowrite,startpos))
1956 return(ERROR(ERRDOS,ERRlock));
1958 seek_file(fnum,startpos);
1960 nwritten = write_file(fnum,data,numtowrite);
1962 set_filetime(Files[fnum].name,mtime);
1966 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
1967 timestring(),fnum,cnum,numtowrite,nwritten,
1968 Connections[cnum].num_files_open));
1971 return(UNIXERROR(ERRDOS,ERRnoaccess));
1973 outsize = set_message(outbuf,1,0,True);
1975 SSVAL(outbuf,smb_vwv0,nwritten);
1980 /****************************************************************************
1982 ****************************************************************************/
1983 int reply_lock(char *inbuf,char *outbuf)
1986 int outsize = set_message(outbuf,0,0,True);
1987 uint32 count,offset;
1991 cnum = SVAL(inbuf,smb_tid);
1992 fnum = GETFNUM(inbuf,smb_vwv0);
1994 CHECK_FNUM(fnum,cnum);
1997 count = IVAL(inbuf,smb_vwv1);
1998 offset = IVAL(inbuf,smb_vwv3);
2000 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2002 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2003 return (ERROR(eclass,ecode));
2009 /****************************************************************************
2011 ****************************************************************************/
2012 int reply_unlock(char *inbuf,char *outbuf)
2015 int outsize = set_message(outbuf,0,0,True);
2016 uint32 count,offset;
2020 cnum = SVAL(inbuf,smb_tid);
2021 fnum = GETFNUM(inbuf,smb_vwv0);
2023 CHECK_FNUM(fnum,cnum);
2026 count = IVAL(inbuf,smb_vwv1);
2027 offset = IVAL(inbuf,smb_vwv3);
2029 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2030 return (ERROR(eclass,ecode));
2032 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2038 /****************************************************************************
2040 ****************************************************************************/
2041 int reply_tdis(char *inbuf,char *outbuf)
2044 int outsize = set_message(outbuf,0,0,True);
2046 cnum = SVAL(inbuf,smb_tid);
2047 uid = SVAL(inbuf,smb_uid);
2049 if (!OPEN_CNUM(cnum)) {
2050 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2051 return(ERROR(ERRSRV,ERRinvnid));
2054 Connections[cnum].used = False;
2056 close_cnum(cnum,uid);
2058 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2065 /****************************************************************************
2067 ****************************************************************************/
2068 int reply_echo(char *inbuf,char *outbuf)
2071 int smb_reverb = SVAL(inbuf,smb_vwv0);
2073 int data_len = smb_buflen(inbuf);
2074 int outsize = set_message(outbuf,1,data_len,True);
2076 cnum = SVAL(inbuf,smb_tid);
2078 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2080 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2081 return(ERROR(ERRSRV,ERRinvnid));
2084 /* copy any incoming data back out */
2086 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2088 if (smb_reverb > 100)
2090 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2094 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2096 SSVAL(outbuf,smb_vwv0,seq_num);
2098 smb_setlen(outbuf,outsize - 4);
2100 send_smb(Client,outbuf);
2103 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2109 /****************************************************************************
2110 reply to a printopen
2111 ****************************************************************************/
2112 int reply_printopen(char *inbuf,char *outbuf)
2120 *fname = *fname2 = 0;
2122 cnum = SVAL(inbuf,smb_tid);
2124 if (!CAN_PRINT(cnum))
2125 return(ERROR(ERRDOS,ERRnoaccess));
2130 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2134 if (!(isalnum(*p) || strchr("._-",*p)))
2139 if (strlen(s) > 10) s[10] = 0;
2141 sprintf(fname,"%s.XXXXXX",s);
2144 fnum = find_free_file();
2146 return(ERROR(ERRSRV,ERRnofids));
2148 strcpy(fname2,(char *)mktemp(fname));
2150 if (!check_name(fname2,cnum))
2151 return(ERROR(ERRDOS,ERRnoaccess));
2153 open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC,
2156 if (!Files[fnum].open)
2157 return(UNIXERROR(ERRDOS,ERRnoaccess));
2159 /* force it to be a print file */
2160 Files[fnum].print_file = True;
2162 outsize = set_message(outbuf,1,0,True);
2163 SSVAL(outbuf,smb_vwv0,fnum);
2165 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum));
2171 /****************************************************************************
2172 reply to a printclose
2173 ****************************************************************************/
2174 int reply_printclose(char *inbuf,char *outbuf)
2177 int outsize = set_message(outbuf,0,0,True);
2179 cnum = SVAL(inbuf,smb_tid);
2180 fnum = GETFNUM(inbuf,smb_vwv0);
2182 CHECK_FNUM(fnum,cnum);
2185 if (!CAN_PRINT(cnum))
2186 return(ERROR(ERRDOS,ERRnoaccess));
2190 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum));
2196 /****************************************************************************
2197 reply to a printqueue
2198 ****************************************************************************/
2199 int reply_printqueue(char *inbuf,char *outbuf)
2202 int outsize = set_message(outbuf,2,3,True);
2203 int max_count = SVAL(inbuf,smb_vwv0);
2204 int start_index = SVAL(inbuf,smb_vwv1);
2206 cnum = SVAL(inbuf,smb_tid);
2207 uid = SVAL(inbuf,smb_uid);
2209 /* allow checking the queue for anyone */
2211 if (!CAN_PRINT(cnum))
2212 return(ERROR(ERRDOS,ERRnoaccess));
2215 SSVAL(outbuf,smb_vwv0,0);
2216 SSVAL(outbuf,smb_vwv1,0);
2217 CVAL(smb_buf(outbuf),0) = 1;
2218 SSVAL(smb_buf(outbuf),1,0);
2220 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2221 timestring(),cnum,start_index,max_count));
2223 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2228 for (i=0;i<MAX_CONNECTIONS;i++)
2229 if (CAN_PRINT(i) && Connections[i].printer)
2233 for (i=0;i<MAX_CONNECTIONS;i++)
2237 if (!OPEN_CNUM(cnum))
2238 return(ERROR(ERRSRV,ERRinvnid));
2240 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2243 if (!become_user(cnum,uid))
2244 return(ERROR(ERRSRV,ERRinvnid));
2247 print_queue_struct *queue = NULL;
2248 char *p = smb_buf(outbuf) + 3;
2249 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2250 int num_to_get = ABS(max_count);
2251 int first = (max_count>0?start_index:start_index+max_count+1);
2257 num_to_get = MIN(num_to_get,count-first);
2260 for (i=first;i<first+num_to_get;i++)
2262 put_dos_date2(p,0,queue[i].time);
2263 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2264 SSVAL(p,5,queue[i].job);
2265 SIVAL(p,7,queue[i].size);
2267 StrnCpy(p+12,queue[i].user,16);
2273 outsize = set_message(outbuf,2,28*count+3,False);
2274 SSVAL(outbuf,smb_vwv0,count);
2275 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2276 CVAL(smb_buf(outbuf),0) = 1;
2277 SSVAL(smb_buf(outbuf),1,28*count);
2280 if (queue) free(queue);
2282 DEBUG(3,("%d entries returned in queue\n",count));
2289 /****************************************************************************
2290 reply to a printwrite
2291 ****************************************************************************/
2292 int reply_printwrite(char *inbuf,char *outbuf)
2294 int cnum,numtowrite,fnum;
2295 int outsize = set_message(outbuf,0,0,True);
2298 cnum = SVAL(inbuf,smb_tid);
2300 if (!CAN_PRINT(cnum))
2301 return(ERROR(ERRDOS,ERRnoaccess));
2303 fnum = GETFNUM(inbuf,smb_vwv0);
2305 CHECK_FNUM(fnum,cnum);
2309 numtowrite = SVAL(smb_buf(inbuf),1);
2310 data = smb_buf(inbuf) + 3;
2312 if (write_file(fnum,data,numtowrite) != numtowrite)
2313 return(UNIXERROR(ERRDOS,ERRnoaccess));
2315 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2321 /****************************************************************************
2323 ****************************************************************************/
2324 int reply_mkdir(char *inbuf,char *outbuf)
2328 int outsize,ret= -1;
2330 strcpy(directory,smb_buf(inbuf) + 1);
2331 cnum = SVAL(inbuf,smb_tid);
2332 unix_convert(directory,cnum);
2334 if (check_name(directory,cnum))
2335 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2338 return(UNIXERROR(ERRDOS,ERRnoaccess));
2340 outsize = set_message(outbuf,0,0,True);
2342 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2348 /****************************************************************************
2350 ****************************************************************************/
2351 int reply_rmdir(char *inbuf,char *outbuf)
2358 cnum = SVAL(inbuf,smb_tid);
2359 strcpy(directory,smb_buf(inbuf) + 1);
2360 unix_convert(directory,cnum);
2362 if (check_name(directory,cnum))
2364 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2365 ok = (sys_rmdir(directory) == 0);
2367 DEBUG(3,("couldn't remove directory %s : %s\n",
2368 directory,strerror(errno)));
2372 return(UNIXERROR(ERRDOS,ERRbadpath));
2374 outsize = set_message(outbuf,0,0,True);
2376 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2382 /*******************************************************************
2383 resolve wildcards in a filename rename
2384 ********************************************************************/
2385 static BOOL resolve_wildcards(char *name1,char *name2)
2387 fstring root1,root2;
2391 name1 = strrchr(name1,'/');
2392 name2 = strrchr(name2,'/');
2394 if (!name1 || !name2) return(False);
2396 strcpy(root1,name1);
2397 strcpy(root2,name2);
2398 p = strrchr(root1,'.');
2405 p = strrchr(root2,'.');
2437 strcpy(name2,root2);
2446 /*******************************************************************
2447 check if a user is allowed to rename a file
2448 ********************************************************************/
2449 static BOOL can_rename(char *fname,int cnum)
2453 if (!CAN_WRITE(cnum)) return(False);
2455 if (sys_lstat(fname,&sbuf) != 0) return(False);
2456 if (!check_file_sharing(cnum,fname)) return(False);
2461 /****************************************************************************
2463 ****************************************************************************/
2464 int reply_mv(char *inbuf,char *outbuf)
2470 pstring mask,newname;
2473 int error = ERRnoaccess;
2477 *directory = *mask = 0;
2479 cnum = SVAL(inbuf,smb_tid);
2481 strcpy(name,smb_buf(inbuf) + 1);
2482 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2484 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2486 unix_convert(name,cnum);
2487 unix_convert(newname,cnum);
2489 p = strrchr(name,'/');
2491 strcpy(directory,"./");
2495 strcpy(directory,name);
2499 if (is_mangled(mask))
2500 check_mangled_stack(mask);
2502 has_wild = strchr(mask,'*') || strchr(mask,'?');
2505 strcat(directory,"/");
2506 strcat(directory,mask);
2507 if (resolve_wildcards(directory,newname) &&
2508 can_rename(directory,cnum) &&
2509 !file_exist(newname,NULL) &&
2510 !sys_rename(directory,newname)) count++;
2511 if (!count) exists = file_exist(directory,NULL);
2512 if (!count && exists && file_exist(newname,NULL)) {
2517 void *dirptr = NULL;
2521 if (check_name(directory,cnum))
2522 dirptr = OpenDir(directory);
2528 if (strequal(mask,"????????.???"))
2531 while ((dname = ReadDirName(dirptr)))
2534 strcpy(fname,dname);
2536 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2538 error = ERRnoaccess;
2539 sprintf(fname,"%s/%s",directory,dname);
2540 if (!can_rename(fname,cnum)) continue;
2541 strcpy(destname,newname);
2543 if (!resolve_wildcards(fname,destname)) continue;
2545 if (file_exist(destname,NULL)) {
2549 if (!sys_rename(fname,destname)) count++;
2550 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2558 return(ERROR(ERRDOS,error));
2560 return(UNIXERROR(ERRDOS,error));
2563 outsize = set_message(outbuf,0,0,True);
2568 /*******************************************************************
2569 copy a file as part of a reply_copy
2570 ******************************************************************/
2571 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2572 int count,BOOL target_is_directory)
2581 if (target_is_directory) {
2582 char *p = strrchr(src,'/');
2591 if (!file_exist(src,&st)) return(False);
2593 fnum1 = find_free_file();
2594 if (fnum1<0) return(False);
2595 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2596 1,0,&Access,&action);
2598 if (!Files[fnum1].open) return(False);
2600 if (!target_is_directory && count)
2603 fnum2 = find_free_file();
2608 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2609 ofun,st.st_mode,&Access,&action);
2611 if (!Files[fnum2].open) {
2616 if ((ofun&3) == 1) {
2617 lseek(Files[fnum2].fd,0,SEEK_END);
2621 ret = transfer_file(Files[fnum1].fd,Files[fnum2].fd,st.st_size,NULL,0,0);
2626 return(ret == st.st_size);
2631 /****************************************************************************
2632 reply to a file copy.
2633 ****************************************************************************/
2634 int reply_copy(char *inbuf,char *outbuf)
2640 pstring mask,newname;
2643 int error = ERRnoaccess;
2646 int tid2 = SVAL(inbuf,smb_vwv0);
2647 int ofun = SVAL(inbuf,smb_vwv1);
2648 int flags = SVAL(inbuf,smb_vwv2);
2649 BOOL target_is_directory=False;
2651 *directory = *mask = 0;
2653 cnum = SVAL(inbuf,smb_tid);
2655 strcpy(name,smb_buf(inbuf));
2656 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2658 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2661 /* can't currently handle inter share copies XXXX */
2662 DEBUG(3,("Rejecting inter-share copy\n"));
2663 return(ERROR(ERRSRV,ERRinvdevice));
2666 unix_convert(name,cnum);
2667 unix_convert(newname,cnum);
2669 target_is_directory = directory_exist(newname,NULL);
2671 if ((flags&1) && target_is_directory) {
2672 return(ERROR(ERRDOS,ERRbadfile));
2675 if ((flags&2) && !target_is_directory) {
2676 return(ERROR(ERRDOS,ERRbadpath));
2679 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2680 /* wants a tree copy! XXXX */
2681 DEBUG(3,("Rejecting tree copy\n"));
2682 return(ERROR(ERRSRV,ERRerror));
2685 p = strrchr(name,'/');
2687 strcpy(directory,"./");
2691 strcpy(directory,name);
2695 if (is_mangled(mask))
2696 check_mangled_stack(mask);
2698 has_wild = strchr(mask,'*') || strchr(mask,'?');
2701 strcat(directory,"/");
2702 strcat(directory,mask);
2703 if (resolve_wildcards(directory,newname) &&
2704 copy_file(directory,newname,cnum,ofun,
2705 count,target_is_directory)) count++;
2706 if (!count) exists = file_exist(directory,NULL);
2708 void *dirptr = NULL;
2712 if (check_name(directory,cnum))
2713 dirptr = OpenDir(directory);
2719 if (strequal(mask,"????????.???"))
2722 while ((dname = ReadDirName(dirptr)))
2725 strcpy(fname,dname);
2727 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2729 error = ERRnoaccess;
2730 sprintf(fname,"%s/%s",directory,dname);
2731 strcpy(destname,newname);
2732 if (resolve_wildcards(fname,destname) &&
2733 copy_file(directory,newname,cnum,ofun,
2734 count,target_is_directory)) count++;
2735 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2743 return(ERROR(ERRDOS,error));
2745 return(UNIXERROR(ERRDOS,error));
2748 outsize = set_message(outbuf,1,0,True);
2749 SSVAL(outbuf,smb_vwv0,count);
2756 /****************************************************************************
2758 ****************************************************************************/
2759 int reply_setdir(char *inbuf,char *outbuf)
2766 cnum = SVAL(inbuf,smb_tid);
2768 snum = Connections[cnum].service;
2769 if (!CAN_SETDIR(snum))
2770 return(ERROR(ERRDOS,ERRnoaccess));
2772 strcpy(newdir,smb_buf(inbuf) + 1);
2775 if (strlen(newdir) == 0)
2779 ok = directory_exist(newdir,NULL);
2781 string_set(&Connections[cnum].connectpath,newdir);
2785 return(ERROR(ERRDOS,ERRbadpath));
2787 outsize = set_message(outbuf,0,0,True);
2788 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
2790 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
2796 /****************************************************************************
2797 reply to a lockingX request
2798 ****************************************************************************/
2799 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
2801 int fnum = GETFNUM(inbuf,smb_vwv2);
2802 uint16 locktype = SVAL(inbuf,smb_vwv3);
2803 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
2804 uint16 num_locks = SVAL(inbuf,smb_vwv7);
2805 uint32 count, offset;
2810 uint32 ecode=0, dummy2;
2811 int eclass=0, dummy1;
2813 cnum = SVAL(inbuf,smb_tid);
2815 CHECK_FNUM(fnum,cnum);
2818 data = smb_buf(inbuf);
2819 /* Data now points at the beginning of the list
2820 of smb_unlkrng structs */
2821 for(i = 0; i < (int)num_ulocks; i++) {
2822 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2823 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2824 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
2825 return ERROR(eclass,ecode);
2828 /* Now do any requested locks */
2829 data += 10*num_ulocks;
2830 /* Data now points at the beginning of the list
2831 of smb_lkrng structs */
2832 for(i = 0; i < (int)num_locks; i++) {
2833 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2834 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2835 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
2839 /* If any of the above locks failed, then we must unlock
2840 all of the previous locks (X/Open spec). */
2841 if(i != num_locks && num_locks != 0) {
2842 for(; i >= 0; i--) {
2843 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2844 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2845 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
2847 return ERROR(eclass,ecode);
2850 set_message(outbuf,2,0,True);
2852 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
2853 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
2857 return chain_reply(inbuf,outbuf,length,bufsize);
2861 /****************************************************************************
2862 reply to a SMBreadbmpx (read block multiplex) request
2863 ****************************************************************************/
2864 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
2871 int outsize, mincount, maxcount;
2876 /* this function doesn't seem to work - disable by default */
2878 return(ERROR(ERRSRV,ERRuseSTD));
2880 outsize = set_message(outbuf,8,0,True);
2882 cnum = SVAL(inbuf,smb_tid);
2883 fnum = GETFNUM(inbuf,smb_vwv0);
2885 CHECK_FNUM(fnum,cnum);
2889 startpos = IVAL(inbuf,smb_vwv1);
2890 maxcount = SVAL(inbuf,smb_vwv3);
2891 mincount = SVAL(inbuf,smb_vwv4);
2893 data = smb_buf(outbuf);
2894 pad = ((int)data)%4;
2895 if (pad) pad = 4 - pad;
2898 max_per_packet = bufsize-(outsize+pad);
2902 if (is_locked(fnum,cnum,maxcount,startpos))
2903 return(ERROR(ERRDOS,ERRlock));
2907 int N = MIN(max_per_packet,tcount-total_read);
2909 nread = read_file(fnum,data,startpos,N);
2911 if (nread <= 0) nread = 0;
2914 tcount = total_read + nread;
2916 set_message(outbuf,8,nread,False);
2917 SIVAL(outbuf,smb_vwv0,startpos);
2918 SSVAL(outbuf,smb_vwv2,tcount);
2919 SSVAL(outbuf,smb_vwv6,nread);
2920 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
2922 send_smb(Client,outbuf);
2924 total_read += nread;
2927 while (total_read < tcount);
2933 /****************************************************************************
2934 reply to a SMBwritebmpx (write block multiplex primary) request
2935 ****************************************************************************/
2936 int reply_writebmpx(char *inbuf,char *outbuf)
2938 int cnum,numtowrite,fnum;
2942 int tcount, write_through, smb_doff;
2945 cnum = SVAL(inbuf,smb_tid);
2946 fnum = GETFNUM(inbuf,smb_vwv0);
2948 CHECK_FNUM(fnum,cnum);
2952 tcount = SVAL(inbuf,smb_vwv1);
2953 startpos = IVAL(inbuf,smb_vwv3);
2954 write_through = BITSETW(inbuf+smb_vwv7,0);
2955 numtowrite = SVAL(inbuf,smb_vwv10);
2956 smb_doff = SVAL(inbuf,smb_vwv11);
2958 data = smb_base(inbuf) + smb_doff;
2960 /* If this fails we need to send an SMBwriteC response,
2961 not an SMBwritebmpx - set this up now so we don't forget */
2962 CVAL(outbuf,smb_com) = SMBwritec;
2964 if (is_locked(fnum,cnum,tcount,startpos))
2965 return(ERROR(ERRDOS,ERRlock));
2967 seek_file(fnum,startpos);
2968 nwritten = write_file(fnum,data,numtowrite);
2970 if(lp_syncalways(SNUM(cnum)) || write_through)
2973 if(nwritten < numtowrite)
2974 return(UNIXERROR(ERRHRD,ERRdiskfull));
2976 /* If the maximum to be written to this file
2977 is greater than what we just wrote then set
2978 up a secondary struct to be attached to this
2979 fd, we will use this to cache error messages etc. */
2980 if(tcount > nwritten)
2982 write_bmpx_struct *wbms;
2983 if(Files[fnum].wbmpx_ptr != NULL)
2984 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
2986 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
2989 DEBUG(0,("Out of memory in reply_readmpx\n"));
2990 return(ERROR(ERRSRV,ERRnoresource));
2992 wbms->wr_mode = write_through;
2993 wbms->wr_discard = False; /* No errors yet */
2994 wbms->wr_total_written = nwritten;
2995 wbms->wr_errclass = 0;
2997 Files[fnum].wbmpx_ptr = wbms;
3000 /* We are returning successfully, set the message type back to
3002 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3004 outsize = set_message(outbuf,1,0,True);
3006 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3008 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3009 timestring(),fnum,cnum,numtowrite,nwritten));
3011 if (write_through && tcount==nwritten) {
3012 /* we need to send both a primary and a secondary response */
3013 smb_setlen(outbuf,outsize - 4);
3014 send_smb(Client,outbuf);
3016 /* now the secondary */
3017 outsize = set_message(outbuf,1,0,True);
3018 CVAL(outbuf,smb_com) = SMBwritec;
3019 SSVAL(outbuf,smb_vwv0,nwritten);
3026 /****************************************************************************
3027 reply to a SMBwritebs (write block multiplex secondary) request
3028 ****************************************************************************/
3029 int reply_writebs(char *inbuf,char *outbuf)
3031 int cnum,numtowrite,fnum;
3035 int tcount, write_through, smb_doff;
3037 write_bmpx_struct *wbms;
3038 BOOL send_response = False;
3040 cnum = SVAL(inbuf,smb_tid);
3041 fnum = GETFNUM(inbuf,smb_vwv0);
3042 CHECK_FNUM(fnum,cnum);
3045 tcount = SVAL(inbuf,smb_vwv1);
3046 startpos = IVAL(inbuf,smb_vwv2);
3047 numtowrite = SVAL(inbuf,smb_vwv6);
3048 smb_doff = SVAL(inbuf,smb_vwv7);
3050 data = smb_base(inbuf) + smb_doff;
3052 /* We need to send an SMBwriteC response, not an SMBwritebs */
3053 CVAL(outbuf,smb_com) = SMBwritec;
3055 /* This fd should have an auxiliary struct attached,
3056 check that it does */
3057 wbms = Files[fnum].wbmpx_ptr;
3058 if(!wbms) return(-1);
3060 /* If write through is set we can return errors, else we must
3062 write_through = wbms->wr_mode;
3064 /* Check for an earlier error */
3065 if(wbms->wr_discard)
3066 return -1; /* Just discard the packet */
3068 seek_file(fnum,startpos);
3069 nwritten = write_file(fnum,data,numtowrite);
3071 if(lp_syncalways(SNUM(cnum)) || write_through)
3074 if (nwritten < numtowrite)
3077 /* We are returning an error - we can delete the aux struct */
3078 if (wbms) free((char *)wbms);
3079 Files[fnum].wbmpx_ptr = NULL;
3080 return(ERROR(ERRHRD,ERRdiskfull));
3082 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3085 /* Increment the total written, if this matches tcount
3086 we can discard the auxiliary struct (hurrah !) and return a writeC */
3087 wbms->wr_total_written += nwritten;
3088 if(wbms->wr_total_written >= tcount)
3090 if (write_through) {
3091 outsize = set_message(outbuf,1,0,True);
3092 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3093 send_response = True;
3097 Files[fnum].wbmpx_ptr = NULL;
3107 /****************************************************************************
3108 reply to a SMBsetattrE
3109 ****************************************************************************/
3110 int reply_setattrE(char *inbuf,char *outbuf)
3113 struct utimbuf unix_times;
3116 outsize = set_message(outbuf,0,0,True);
3118 cnum = SVAL(inbuf,smb_tid);
3119 fnum = GETFNUM(inbuf,smb_vwv0);
3121 CHECK_FNUM(fnum,cnum);
3124 /* Convert the DOS times into unix times. Ignore create
3125 time as UNIX can't set this.
3127 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3128 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3130 /* Set the date on this file */
3131 if(sys_utime(Files[fnum].name, &unix_times))
3132 return(ERROR(ERRDOS,ERRnoaccess));
3134 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3140 /****************************************************************************
3141 reply to a SMBgetattrE
3142 ****************************************************************************/
3143 int reply_getattrE(char *inbuf,char *outbuf)
3150 outsize = set_message(outbuf,11,0,True);
3152 cnum = SVAL(inbuf,smb_tid);
3153 fnum = GETFNUM(inbuf,smb_vwv0);
3155 CHECK_FNUM(fnum,cnum);
3158 /* Do an fstat on this file */
3159 if(fstat(Files[fnum].fd, &sbuf))
3160 return(UNIXERROR(ERRDOS,ERRnoaccess));
3162 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3164 /* Convert the times into dos times. Set create
3165 date to be last modify date as UNIX doesn't save
3167 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3168 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3169 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3172 SIVAL(outbuf,smb_vwv6,0);
3173 SIVAL(outbuf,smb_vwv8,0);
3177 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3178 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3180 SSVAL(outbuf,smb_vwv10, mode);
3182 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));