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 /* we just say it succeeds and hope its all OK.
299 some day it would be nice to interpret them individually */
300 return set_message(outbuf,1,0,True);
302 return(ERROR(ERRSRV,ERRnosupport));
307 /****************************************************************************
308 reply to a session setup command
309 ****************************************************************************/
310 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
320 int smb_ntpasslen = 0;
321 pstring smb_ntpasswd;
322 BOOL valid_nt_password = False;
325 BOOL computer_id=False;
326 static BOOL done_sesssetup = False;
330 sess_uid = SVAL(inbuf,smb_uid);
331 smb_bufsize = SVAL(inbuf,smb_vwv2);
332 smb_mpxmax = SVAL(inbuf,smb_vwv3);
333 smb_vc_num = SVAL(inbuf,smb_vwv4);
334 smb_sesskey = IVAL(inbuf,smb_vwv5);
336 if (Protocol < PROTOCOL_NT1) {
337 smb_apasslen = SVAL(inbuf,smb_vwv7);
338 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
339 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
341 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
342 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
343 BOOL doencrypt = SMBENCRYPT();
344 char *p = smb_buf(inbuf);
347 /* Save the lanman2 password and the NT md4 password. */
348 smb_apasslen = passlen1;
349 memcpy(smb_apasswd,p,smb_apasslen);
350 smb_ntpasslen = passlen2;
351 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
353 /* both Win95 and WinNT stuff up the password lengths for
354 non-encrypting systems. Uggh.
356 if passlen1==24 its a win95 system, and its setting the
357 password length incorrectly. Luckily it still works with the
358 default code because Win95 will null terminate the password
361 if passlen1>0 and passlen2>0 then its a NT box and its
362 setting passlen2 to some random value which really stuffs
363 things up. we need to fix that one. */
364 if (passlen1 > 0 && passlen2 > 0) {
367 /* we use the first password that they gave */
368 smb_apasslen = passlen1;
369 StrnCpy(smb_apasswd,p,smb_apasslen);
372 p += passlen1 + passlen2;
373 strcpy(user,p); p = skip_string(p,1);
374 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
375 p,skip_string(p,1),skip_string(p,2)));
377 /* now work around the Win95 bug */
378 if(!doencrypt && smb_apasslen==24)
379 smb_apasslen = strlen(smb_apasswd);
383 DEBUG(3,("sesssetupX:name=[%s]\n",user));
385 /* If name ends in $ then I think it's asking about whether a */
386 /* computer with that name (minus the $) has access. For now */
387 /* say yes to everything ending in $. */
388 if (user[strlen(user) - 1] == '$') {
390 user[strlen(user) - 1] = '\0';
395 strcpy(user,lp_guestaccount(-1));
399 strcpy(sesssetup_user,user);
401 reload_services(True);
403 add_session_user(user);
406 if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
407 !check_hosts_equiv(user))
410 if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
413 /* now check if it's a valid username/password */
414 /* If an NT password was supplied try and validate with that
415 first. This is superior as the passwords are mixed case 128 length unicode */
416 if(smb_ntpasslen && !guest)
418 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
419 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
421 valid_nt_password = True;
423 if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
425 if (!computer_id && lp_security() >= SEC_USER) {
426 #if (GUEST_SESSSETUP == 0)
427 return(ERROR(ERRSRV,ERRbadpw));
429 #if (GUEST_SESSSETUP == 1)
430 if (Get_Pwnam(user,True))
431 return(ERROR(ERRSRV,ERRbadpw));
434 if (*smb_apasswd || !Get_Pwnam(user,True))
435 strcpy(user,lp_guestaccount(-1));
436 DEBUG(3,("Registered username %s for guest access\n",user));
441 if (!Get_Pwnam(user,True)) {
442 DEBUG(3,("No such user %s - using guest account\n",user));
443 strcpy(user,lp_guestaccount(-1));
447 if (!strequal(user,lp_guestaccount(-1)) &&
448 lp_servicenumber(user) < 0)
450 int homes = lp_servicenumber(HOMES_NAME);
451 char *home = get_home_dir(user);
452 if (homes >= 0 && home)
453 lp_add_home(user,homes,home);
457 /* it's ok - setup a reply */
458 if (Protocol < PROTOCOL_NT1) {
459 set_message(outbuf,3,0,True);
462 set_message(outbuf,3,3,True);
464 strcpy(p,"Unix"); p = skip_string(p,1);
465 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
466 strcpy(p,lp_workgroup()); p = skip_string(p,1);
467 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
468 /* perhaps grab OS version here?? */
471 /* Set the correct uid in the outgoing and incoming packets
472 We will use this on future requests to determine which
473 user we should become.
476 struct passwd *pw = Get_Pwnam(user,False);
478 DEBUG(1,("Username %s is invalid on this system\n",user));
479 return(ERROR(ERRSRV,ERRbadpw));
482 SSVAL(outbuf,smb_uid,(uint16)pw->pw_uid);
483 SSVAL(inbuf,smb_uid,(uint16)pw->pw_uid);
486 if (guest && !computer_id)
487 SSVAL(outbuf,smb_vwv2,1);
489 /* register the name and uid as being validated, so further connections
490 to a uid can get through without a password, on the same VC */
491 register_uid(SVAL(inbuf,smb_uid),gid,user,guest);
494 maxxmit = MIN(maxxmit,smb_bufsize);
496 done_sesssetup = True;
498 return chain_reply(inbuf,outbuf,length,bufsize);
502 /****************************************************************************
504 ****************************************************************************/
505 int reply_chkpth(char *inbuf,char *outbuf)
512 cnum = SVAL(inbuf,smb_tid);
514 strcpy(name,smb_buf(inbuf) + 1);
515 unix_convert(name,cnum);
517 mode = SVAL(inbuf,smb_vwv0);
519 if (check_name(name,cnum))
520 ok = directory_exist(name,NULL);
523 return(ERROR(ERRDOS,ERRbadpath));
525 outsize = set_message(outbuf,0,0,True);
527 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
533 /****************************************************************************
535 ****************************************************************************/
536 int reply_getatr(char *inbuf,char *outbuf)
547 cnum = SVAL(inbuf,smb_tid);
549 strcpy(fname,smb_buf(inbuf) + 1);
550 unix_convert(fname,cnum);
552 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
553 under WfWg - weird! */
556 mode = aHIDDEN | aDIR;
557 if (!CAN_WRITE(cnum)) mode |= aRONLY;
563 if (check_name(fname,cnum))
565 if (sys_stat(fname,&sbuf) == 0)
567 mode = dos_mode(cnum,fname,&sbuf);
569 mtime = sbuf.st_mtime;
575 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
579 return(UNIXERROR(ERRDOS,ERRbadfile));
581 outsize = set_message(outbuf,10,0,True);
583 SSVAL(outbuf,smb_vwv0,mode);
584 put_dos_date3(outbuf,smb_vwv1,mtime);
585 SIVAL(outbuf,smb_vwv3,size);
587 if (Protocol >= PROTOCOL_NT1) {
588 char *p = strrchr(fname,'/');
589 uint16 flg2 = SVAL(outbuf,smb_flg2);
592 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
595 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
601 /****************************************************************************
603 ****************************************************************************/
604 int reply_setatr(char *inbuf,char *outbuf)
613 cnum = SVAL(inbuf,smb_tid);
615 strcpy(fname,smb_buf(inbuf) + 1);
616 unix_convert(fname,cnum);
618 mode = SVAL(inbuf,smb_vwv0);
619 mtime = make_unix_date3(inbuf+smb_vwv1);
621 if (directory_exist(fname,NULL))
623 if (check_name(fname,cnum))
624 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
626 ok = set_filetime(fname,mtime);
629 return(UNIXERROR(ERRDOS,ERRnoaccess));
631 outsize = set_message(outbuf,0,0,True);
633 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
639 /****************************************************************************
641 ****************************************************************************/
642 int reply_dskattr(char *inbuf,char *outbuf)
646 int dfree,dsize,bsize;
648 cnum = SVAL(inbuf,smb_tid);
650 sys_disk_free(".",&bsize,&dfree,&dsize);
652 outsize = set_message(outbuf,5,0,True);
654 SSVAL(outbuf,smb_vwv0,dsize);
655 SSVAL(outbuf,smb_vwv1,bsize/512);
656 SSVAL(outbuf,smb_vwv2,512);
657 SSVAL(outbuf,smb_vwv3,dfree);
659 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
665 /****************************************************************************
667 Can be called from SMBsearch, SMBffirst or SMBfunique.
668 ****************************************************************************/
669 int reply_search(char *inbuf,char *outbuf)
680 BOOL finished = False;
689 BOOL check_descend = False;
690 BOOL expect_close = False;
691 BOOL can_open = True;
693 *mask = *directory = *fname = 0;
695 /* If we were called as SMBffirst then we must expect close. */
696 if(CVAL(inbuf,smb_com) == SMBffirst)
699 cnum = SVAL(inbuf,smb_tid);
701 outsize = set_message(outbuf,1,3,True);
702 maxentries = SVAL(inbuf,smb_vwv0);
703 dirtype = SVAL(inbuf,smb_vwv1);
704 path = smb_buf(inbuf) + 1;
705 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
708 /* dirtype &= ~aDIR; */
710 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
717 strcpy(directory,smb_buf(inbuf)+1);
718 strcpy(dir2,smb_buf(inbuf)+1);
719 unix_convert(directory,cnum);
722 if (!check_name(directory,cnum))
725 p = strrchr(dir2,'/');
727 {strcpy(mask,dir2);*dir2 = 0;}
729 {*p = 0;strcpy(mask,p+1);}
731 p = strrchr(directory,'/');
737 if (strlen(directory) == 0)
738 strcpy(directory,"./");
740 CVAL(status,0) = dirtype;
744 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
745 memcpy(mask,status+1,11);
747 dirtype = CVAL(status,0) & 0x1F;
748 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
749 if (!Connections[cnum].dirptr)
751 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
756 /* turn strings of spaces into a . */
758 trim_string(mask,NULL," ");
759 if ((p = strrchr(mask,' ')))
764 trim_string(mask,NULL," ");
771 for (p=mask; *p; p++)
773 if (*p != '?' && *p != '*' && !isdoschar(*p))
775 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
781 if (!strchr(mask,'.') && strlen(mask)>8)
784 strcpy(tmp,&mask[8]);
790 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
794 p = smb_buf(outbuf) + 3;
800 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
802 return(ERROR(ERRDOS,ERRnofids));
805 DEBUG(4,("dptr_num is %d\n",dptr_num));
809 if ((dirtype&0x1F) == aVOLID)
812 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
813 dptr_fill(p+12,dptr_num);
814 if (dptr_zero(p+12) && (status_len==0))
818 p += DIR_STRUCT_SIZE;
822 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
823 if (in_list(Connections[cnum].dirpath,
824 lp_dontdescend(SNUM(cnum)),True))
825 check_descend = True;
827 for (i=numentries;(i<maxentries) && !finished;i++)
830 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
834 make_dir_struct(p,mask,fname,size,mode,date);
835 dptr_fill(p+12,dptr_num);
838 p += DIR_STRUCT_SIZE;
847 if (numentries == 0 || !ok)
849 CVAL(outbuf,smb_rcls) = ERRDOS;
850 SSVAL(outbuf,smb_err,ERRnofiles);
853 /* If we were called as SMBffirst with smb_search_id == NULL
854 and no entries were found then return error and close dirptr
857 if(ok && expect_close && numentries == 0 && status_len == 0)
859 CVAL(outbuf,smb_rcls) = ERRDOS;
860 SSVAL(outbuf,smb_err,ERRnofiles);
861 /* Also close the dptr - we know it's gone */
862 dptr_close(dptr_num);
865 /* If we were called as SMBfunique, then we can close the dirptr now ! */
866 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
867 dptr_close(dptr_num);
869 SSVAL(outbuf,smb_vwv0,numentries);
870 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
871 CVAL(smb_buf(outbuf),0) = 5;
872 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
874 if (Protocol >= PROTOCOL_NT1) {
875 uint16 flg2 = SVAL(outbuf,smb_flg2);
876 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
879 outsize += DIR_STRUCT_SIZE*numentries;
880 smb_setlen(outbuf,outsize - 4);
882 if ((! *directory) && dptr_path(dptr_num))
883 sprintf(directory,"(%s)",dptr_path(dptr_num));
885 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
887 smb_fn_name(CVAL(inbuf,smb_com)),
888 mask,directory,cnum,dirtype,numentries,maxentries));
894 /****************************************************************************
895 reply to a fclose (stop directory search)
896 ****************************************************************************/
897 int reply_fclose(char *inbuf,char *outbuf)
906 cnum = SVAL(inbuf,smb_tid);
908 outsize = set_message(outbuf,1,0,True);
909 path = smb_buf(inbuf) + 1;
910 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
914 return(ERROR(ERRSRV,ERRsrverror));
916 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
918 if(dptr_fetch(status+12,&dptr_num)) {
919 /* Close the dptr - we know it's gone */
920 dptr_close(dptr_num);
923 SSVAL(outbuf,smb_vwv0,0);
925 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
931 /****************************************************************************
933 ****************************************************************************/
934 int reply_open(char *inbuf,char *outbuf)
948 cnum = SVAL(inbuf,smb_tid);
950 share_mode = SVAL(inbuf,smb_vwv0);
952 strcpy(fname,smb_buf(inbuf)+1);
953 unix_convert(fname,cnum);
955 fnum = find_free_file();
957 return(ERROR(ERRSRV,ERRnofids));
959 if (!check_name(fname,cnum))
960 return(UNIXERROR(ERRDOS,ERRnoaccess));
962 unixmode = unix_mode(cnum,aARCH);
964 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
966 if (!Files[fnum].open)
967 return(UNIXERROR(ERRDOS,ERRnoaccess));
969 if (fstat(Files[fnum].fd,&sbuf) != 0) {
971 return(ERROR(ERRDOS,ERRnoaccess));
975 fmode = dos_mode(cnum,fname,&sbuf);
976 mtime = sbuf.st_mtime;
979 DEBUG(3,("attempt to open a directory %s\n",fname));
981 return(ERROR(ERRDOS,ERRnoaccess));
984 outsize = set_message(outbuf,7,0,True);
985 SSVAL(outbuf,smb_vwv0,fnum);
986 SSVAL(outbuf,smb_vwv1,fmode);
987 put_dos_date3(outbuf,smb_vwv2,mtime);
988 SIVAL(outbuf,smb_vwv4,size);
989 SSVAL(outbuf,smb_vwv6,rmode);
991 if (lp_fake_oplocks(SNUM(cnum))) {
992 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
999 /****************************************************************************
1000 reply to an open and X
1001 ****************************************************************************/
1002 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1005 int cnum = SVAL(inbuf,smb_tid);
1008 int smb_mode = SVAL(inbuf,smb_vwv3);
1009 int smb_attr = SVAL(inbuf,smb_vwv5);
1010 BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
1012 int open_flags = SVAL(inbuf,smb_vwv2);
1013 int smb_sattr = SVAL(inbuf,smb_vwv4);
1014 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1016 int smb_ofun = SVAL(inbuf,smb_vwv8);
1018 int size=0,fmode=0,mtime=0,rmode=0;
1022 /* If it's an IPC, pass off the pipe handler. */
1024 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1026 /* XXXX we need to handle passed times, sattr and flags */
1028 strcpy(fname,smb_buf(inbuf));
1029 unix_convert(fname,cnum);
1031 /* now add create and trunc bits */
1032 if (smb_ofun & 0x10)
1033 openmode |= O_CREAT;
1034 if ((smb_ofun & 0x3) == 2)
1035 openmode |= O_TRUNC;
1037 fnum = find_free_file();
1039 return(ERROR(ERRSRV,ERRnofids));
1041 if (!check_name(fname,cnum))
1042 return(UNIXERROR(ERRDOS,ERRnoaccess));
1044 unixmode = unix_mode(cnum,smb_attr | aARCH);
1046 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1047 &rmode,&smb_action);
1049 if (!Files[fnum].open)
1050 return(UNIXERROR(ERRDOS,ERRnoaccess));
1052 if (fstat(Files[fnum].fd,&sbuf) != 0) {
1054 return(ERROR(ERRDOS,ERRnoaccess));
1057 size = sbuf.st_size;
1058 fmode = dos_mode(cnum,fname,&sbuf);
1059 mtime = sbuf.st_mtime;
1062 return(ERROR(ERRDOS,ERRnoaccess));
1065 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1066 smb_action |= (1<<15);
1069 set_message(outbuf,15,0,True);
1070 SSVAL(outbuf,smb_vwv2,fnum);
1071 SSVAL(outbuf,smb_vwv3,fmode);
1072 put_dos_date3(outbuf,smb_vwv4,mtime);
1073 SIVAL(outbuf,smb_vwv6,size);
1074 SSVAL(outbuf,smb_vwv8,rmode);
1075 SSVAL(outbuf,smb_vwv11,smb_action);
1079 return chain_reply(inbuf,outbuf,length,bufsize);
1083 /****************************************************************************
1084 reply to a SMBulogoffX
1085 ****************************************************************************/
1086 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1088 int uid = SVAL(inbuf,smb_uid);
1090 invalidate_uid(uid);
1092 /* in user level security we are supposed to close any files
1093 open by this user */
1094 if (lp_security() != SEC_SHARE) {
1096 for (i=0;i<MAX_OPEN_FILES;i++)
1097 if (Files[i].uid == uid && Files[i].open) {
1102 set_message(outbuf,2,0,True);
1104 DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid));
1106 return chain_reply(inbuf,outbuf,length,bufsize);
1110 /****************************************************************************
1112 ****************************************************************************/
1113 int reply_mknew(char *inbuf,char *outbuf)
1122 com = SVAL(inbuf,smb_com);
1123 cnum = SVAL(inbuf,smb_tid);
1125 createmode = SVAL(inbuf,smb_vwv0);
1126 strcpy(fname,smb_buf(inbuf)+1);
1127 unix_convert(fname,cnum);
1129 if (createmode & aVOLID)
1131 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1134 unixmode = unix_mode(cnum,createmode);
1136 if (com == SMBmknew && file_exist(fname,NULL))
1137 return(ERROR(ERRDOS,ERRfilexists));
1139 fnum = find_free_file();
1141 return(ERROR(ERRSRV,ERRnofids));
1143 if (!check_name(fname,cnum))
1144 return(UNIXERROR(ERRDOS,ERRnoaccess));
1146 open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1148 if (!Files[fnum].open)
1149 return(UNIXERROR(ERRDOS,ERRnoaccess));
1151 outsize = set_message(outbuf,1,0,True);
1152 SSVAL(outbuf,smb_vwv0,fnum);
1154 if (lp_fake_oplocks(SNUM(cnum))) {
1155 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1158 DEBUG(2,("new file %s\n",fname));
1159 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));
1165 /****************************************************************************
1166 reply to a create temporary file
1167 ****************************************************************************/
1168 int reply_ctemp(char *inbuf,char *outbuf)
1178 cnum = SVAL(inbuf,smb_tid);
1179 createmode = SVAL(inbuf,smb_vwv0);
1180 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1181 unix_convert(fname,cnum);
1183 unixmode = unix_mode(cnum,createmode);
1185 fnum = find_free_file();
1187 return(ERROR(ERRSRV,ERRnofids));
1189 if (!check_name(fname,cnum))
1190 return(UNIXERROR(ERRDOS,ERRnoaccess));
1192 strcpy(fname2,(char *)mktemp(fname));
1194 open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1196 if (!Files[fnum].open)
1197 return(UNIXERROR(ERRDOS,ERRnoaccess));
1199 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1200 SSVAL(outbuf,smb_vwv0,fnum);
1201 CVAL(smb_buf(outbuf),0) = 4;
1202 strcpy(smb_buf(outbuf) + 1,fname2);
1204 if (lp_fake_oplocks(SNUM(cnum))) {
1205 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1208 DEBUG(2,("created temp file %s\n",fname2));
1209 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));
1215 /*******************************************************************
1216 check if a user is allowed to delete a file
1217 ********************************************************************/
1218 static BOOL can_delete(char *fname,int cnum,int dirtype)
1223 if (!CAN_WRITE(cnum)) return(False);
1225 if (sys_lstat(fname,&sbuf) != 0) return(False);
1226 fmode = dos_mode(cnum,fname,&sbuf);
1227 if (fmode & aDIR) return(False);
1228 if (!lp_delete_readonly(SNUM(cnum))) {
1229 if (fmode & aRONLY) return(False);
1231 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1233 if (!check_file_sharing(cnum,fname)) return(False);
1237 /****************************************************************************
1239 ****************************************************************************/
1240 int reply_unlink(char *inbuf,char *outbuf)
1250 int error = ERRnoaccess;
1254 *directory = *mask = 0;
1256 cnum = SVAL(inbuf,smb_tid);
1257 dirtype = SVAL(inbuf,smb_vwv0);
1259 strcpy(name,smb_buf(inbuf) + 1);
1261 DEBUG(3,("reply_unlink : %s\n",name));
1263 unix_convert(name,cnum);
1265 p = strrchr(name,'/');
1267 strcpy(directory,"./");
1271 strcpy(directory,name);
1275 if (is_mangled(mask))
1276 check_mangled_stack(mask);
1278 has_wild = strchr(mask,'*') || strchr(mask,'?');
1281 strcat(directory,"/");
1282 strcat(directory,mask);
1283 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1284 if (!count) exists = file_exist(directory,NULL);
1286 void *dirptr = NULL;
1289 if (check_name(directory,cnum))
1290 dirptr = OpenDir(directory);
1292 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1293 the pattern matches against the long name, otherwise the short name
1294 We don't implement this yet XXXX
1301 if (strequal(mask,"????????.???"))
1304 while ((dname = ReadDirName(dirptr)))
1307 strcpy(fname,dname);
1309 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1311 error = ERRnoaccess;
1312 sprintf(fname,"%s/%s",directory,dname);
1313 if (!can_delete(fname,cnum,dirtype)) continue;
1314 if (!sys_unlink(fname)) count++;
1315 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1323 return(ERROR(ERRDOS,error));
1325 return(UNIXERROR(ERRDOS,error));
1328 outsize = set_message(outbuf,0,0,True);
1334 /****************************************************************************
1335 reply to a readbraw (core+ protocol)
1336 ****************************************************************************/
1337 int reply_readbraw(char *inbuf, char *outbuf)
1339 int cnum,maxcount,mincount,fnum;
1342 char *header = outbuf;
1347 cnum = SVAL(inbuf,smb_tid);
1348 fnum = GETFNUM(inbuf,smb_vwv0);
1350 startpos = IVAL(inbuf,smb_vwv1);
1351 maxcount = SVAL(inbuf,smb_vwv3);
1352 mincount = SVAL(inbuf,smb_vwv4);
1354 /* ensure we don't overrun the packet size */
1355 maxcount = MIN(65535,maxcount);
1356 maxcount = MAX(mincount,maxcount);
1358 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1360 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1361 _smb_setlen(header,0);
1362 transfer_file(0,Client,0,header,4,0);
1367 fd = Files[fnum].fd;
1368 fname = Files[fnum].name;
1372 if (!is_locked(fnum,cnum,maxcount,startpos))
1374 int size = Files[fnum].size;
1375 int sizeneeded = startpos + maxcount;
1377 if (size < sizeneeded) {
1379 if (fstat(Files[fnum].fd,&st) == 0)
1381 if (!Files[fnum].can_write)
1382 Files[fnum].size = size;
1385 nread = MIN(maxcount,size - startpos);
1388 if (nread < mincount)
1391 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1394 maxcount,mincount,nread));
1399 _smb_setlen(header,nread);
1401 if (!Files[fnum].can_write)
1402 predict = read_predict(fd,startpos,header+4,NULL,nread);
1404 if ((nread-predict) > 0)
1405 seek_file(fnum,startpos + predict);
1407 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1412 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1413 fname,startpos,nread,ret));
1416 ret = read_file(fnum,header+4,startpos,nread);
1417 if (ret < mincount) ret = 0;
1419 _smb_setlen(header,ret);
1420 transfer_file(0,Client,0,header,4+ret,0);
1423 DEBUG(5,("readbraw finished\n"));
1428 /****************************************************************************
1429 reply to a lockread (core+ protocol)
1430 ****************************************************************************/
1431 int reply_lockread(char *inbuf,char *outbuf)
1437 uint32 startpos, numtoread;
1441 cnum = SVAL(inbuf,smb_tid);
1442 fnum = GETFNUM(inbuf,smb_vwv0);
1444 CHECK_FNUM(fnum,cnum);
1448 numtoread = SVAL(inbuf,smb_vwv1);
1449 startpos = IVAL(inbuf,smb_vwv2);
1451 outsize = set_message(outbuf,5,3,True);
1452 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1453 data = smb_buf(outbuf) + 3;
1455 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1456 return (ERROR(eclass,ecode));
1458 nread = read_file(fnum,data,startpos,numtoread);
1461 return(UNIXERROR(ERRDOS,ERRnoaccess));
1464 SSVAL(outbuf,smb_vwv0,nread);
1465 SSVAL(outbuf,smb_vwv5,nread+3);
1466 SSVAL(smb_buf(outbuf),1,nread);
1468 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1474 /****************************************************************************
1476 ****************************************************************************/
1477 int reply_read(char *inbuf,char *outbuf)
1479 int cnum,numtoread,fnum;
1485 cnum = SVAL(inbuf,smb_tid);
1486 fnum = GETFNUM(inbuf,smb_vwv0);
1488 CHECK_FNUM(fnum,cnum);
1492 numtoread = SVAL(inbuf,smb_vwv1);
1493 startpos = IVAL(inbuf,smb_vwv2);
1495 outsize = set_message(outbuf,5,3,True);
1496 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1497 data = smb_buf(outbuf) + 3;
1499 if (is_locked(fnum,cnum,numtoread,startpos))
1500 return(ERROR(ERRDOS,ERRlock));
1503 nread = read_file(fnum,data,startpos,numtoread);
1506 return(UNIXERROR(ERRDOS,ERRnoaccess));
1509 SSVAL(outbuf,smb_vwv0,nread);
1510 SSVAL(outbuf,smb_vwv5,nread+3);
1511 CVAL(smb_buf(outbuf),0) = 1;
1512 SSVAL(smb_buf(outbuf),1,nread);
1514 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1520 /****************************************************************************
1521 reply to a read and X
1522 ****************************************************************************/
1523 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1525 int fnum = GETFNUM(inbuf,smb_vwv2);
1526 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1527 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1528 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1534 cnum = SVAL(inbuf,smb_tid);
1536 CHECK_FNUM(fnum,cnum);
1540 set_message(outbuf,12,0,True);
1541 data = smb_buf(outbuf);
1543 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1544 return(ERROR(ERRDOS,ERRlock));
1545 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1549 return(UNIXERROR(ERRDOS,ERRnoaccess));
1551 SSVAL(outbuf,smb_vwv5,nread);
1552 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1553 SSVAL(smb_buf(outbuf),-2,nread);
1555 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1556 timestring(),fnum,cnum,
1557 smb_mincnt,smb_maxcnt,nread));
1561 return chain_reply(inbuf,outbuf,length,bufsize);
1565 /****************************************************************************
1566 reply to a writebraw (core+ or LANMAN1.0 protocol)
1567 ****************************************************************************/
1568 int reply_writebraw(char *inbuf,char *outbuf)
1571 int total_written=0;
1580 cnum = SVAL(inbuf,smb_tid);
1581 fnum = GETFNUM(inbuf,smb_vwv0);
1583 CHECK_FNUM(fnum,cnum);
1587 tcount = IVAL(inbuf,smb_vwv1);
1588 startpos = IVAL(inbuf,smb_vwv3);
1589 write_through = BITSETW(inbuf+smb_vwv7,0);
1591 /* We have to deal with slightly different formats depending
1592 on whether we are using the core+ or lanman1.0 protocol */
1593 if(Protocol <= PROTOCOL_COREPLUS) {
1594 numtowrite = SVAL(smb_buf(inbuf),-2);
1595 data = smb_buf(inbuf);
1597 numtowrite = SVAL(inbuf,smb_vwv10);
1598 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1601 /* force the error type */
1602 CVAL(inbuf,smb_com) = SMBwritec;
1603 CVAL(outbuf,smb_com) = SMBwritec;
1605 if (is_locked(fnum,cnum,tcount,startpos))
1606 return(ERROR(ERRDOS,ERRlock));
1608 if (seek_file(fnum,startpos) != startpos)
1609 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1612 nwritten = write_file(fnum,data,numtowrite);
1614 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1615 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1617 if (nwritten < numtowrite)
1618 return(UNIXERROR(ERRHRD,ERRdiskfull));
1620 total_written = nwritten;
1622 /* Return a message to the redirector to tell it
1623 to send more bytes */
1624 CVAL(outbuf,smb_com) = SMBwritebraw;
1625 SSVALS(outbuf,smb_vwv0,-1);
1626 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1627 send_smb(Client,outbuf);
1629 /* Now read the raw data into the buffer and write it */
1630 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1631 exit_server("secondary writebraw failed");
1634 /* Even though this is not an smb message, smb_len
1635 returns the generic length of an smb message */
1636 numtowrite = smb_len(inbuf);
1638 if (tcount > nwritten+numtowrite) {
1639 DEBUG(3,("Client overestimated the write %d %d %d\n",
1640 tcount,nwritten,numtowrite));
1643 nwritten = transfer_file(Client,Files[fnum].fd,numtowrite,NULL,0,
1645 total_written += nwritten;
1647 /* Set up outbuf to return the correct return */
1648 outsize = set_message(outbuf,1,0,True);
1649 CVAL(outbuf,smb_com) = SMBwritec;
1650 SSVAL(outbuf,smb_vwv0,total_written);
1652 if (nwritten < numtowrite) {
1653 CVAL(outbuf,smb_rcls) = ERRHRD;
1654 SSVAL(outbuf,smb_err,ERRdiskfull);
1657 if (lp_syncalways(SNUM(cnum)) || write_through)
1660 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1661 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1663 /* we won't return a status if write through is not selected - this
1664 follows what WfWg does */
1665 if (!write_through && total_written==tcount)
1672 /****************************************************************************
1673 reply to a writeunlock (core+)
1674 ****************************************************************************/
1675 int reply_writeunlock(char *inbuf,char *outbuf)
1681 uint32 numtowrite,startpos;
1685 cnum = SVAL(inbuf,smb_tid);
1686 fnum = GETFNUM(inbuf,smb_vwv0);
1688 CHECK_FNUM(fnum,cnum);
1692 numtowrite = SVAL(inbuf,smb_vwv1);
1693 startpos = IVAL(inbuf,smb_vwv2);
1694 data = smb_buf(inbuf) + 3;
1696 if (is_locked(fnum,cnum,numtowrite,startpos))
1697 return(ERROR(ERRDOS,ERRlock));
1699 seek_file(fnum,startpos);
1701 /* The special X/Open SMB protocol handling of
1702 zero length writes is *NOT* done for
1707 nwritten = write_file(fnum,data,numtowrite);
1709 if (lp_syncalways(SNUM(cnum)))
1712 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1713 return(UNIXERROR(ERRDOS,ERRnoaccess));
1715 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1716 return(ERROR(eclass,ecode));
1718 outsize = set_message(outbuf,1,0,True);
1720 SSVAL(outbuf,smb_vwv0,nwritten);
1722 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1723 timestring(),fnum,cnum,numtowrite,nwritten));
1729 /****************************************************************************
1731 ****************************************************************************/
1732 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1734 int cnum,numtowrite,fnum;
1743 cnum = SVAL(inbuf,smb_tid);
1744 fnum = GETFNUM(inbuf,smb_vwv0);
1746 CHECK_FNUM(fnum,cnum);
1750 numtowrite = SVAL(inbuf,smb_vwv1);
1751 startpos = IVAL(inbuf,smb_vwv2);
1752 data = smb_buf(inbuf) + 3;
1754 if (is_locked(fnum,cnum,numtowrite,startpos))
1755 return(ERROR(ERRDOS,ERRlock));
1757 seek_file(fnum,startpos);
1759 /* X/Open SMB protocol says that if smb_vwv1 is
1760 zero then the file size should be extended or
1761 truncated to the size given in smb_vwv[2-3] */
1763 nwritten = set_filelen(Files[fnum].fd, startpos);
1765 nwritten = write_file(fnum,data,numtowrite);
1767 if (lp_syncalways(SNUM(cnum)))
1770 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1771 return(UNIXERROR(ERRDOS,ERRnoaccess));
1773 outsize = set_message(outbuf,1,0,True);
1775 SSVAL(outbuf,smb_vwv0,nwritten);
1777 if (nwritten < numtowrite) {
1778 CVAL(outbuf,smb_rcls) = ERRHRD;
1779 SSVAL(outbuf,smb_err,ERRdiskfull);
1782 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1788 /****************************************************************************
1789 reply to a write and X
1790 ****************************************************************************/
1791 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1793 int fnum = GETFNUM(inbuf,smb_vwv2);
1794 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1795 int smb_dsize = SVAL(inbuf,smb_vwv10);
1796 int smb_doff = SVAL(inbuf,smb_vwv11);
1797 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1802 cnum = SVAL(inbuf,smb_tid);
1804 CHECK_FNUM(fnum,cnum);
1808 data = smb_base(inbuf) + smb_doff;
1810 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1811 return(ERROR(ERRDOS,ERRlock));
1813 seek_file(fnum,smb_offs);
1815 /* X/Open SMB protocol says that, unlike SMBwrite
1816 if the length is zero then NO truncation is
1817 done, just a write of zero. To truncate a file,
1822 nwritten = write_file(fnum,data,smb_dsize);
1824 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1825 return(UNIXERROR(ERRDOS,ERRnoaccess));
1827 set_message(outbuf,6,0,True);
1829 SSVAL(outbuf,smb_vwv2,nwritten);
1831 if (nwritten < smb_dsize) {
1832 CVAL(outbuf,smb_rcls) = ERRHRD;
1833 SSVAL(outbuf,smb_err,ERRdiskfull);
1836 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1840 if (lp_syncalways(SNUM(cnum)) || write_through)
1843 return chain_reply(inbuf,outbuf,length,bufsize);
1847 /****************************************************************************
1849 ****************************************************************************/
1850 int reply_lseek(char *inbuf,char *outbuf)
1858 cnum = SVAL(inbuf,smb_tid);
1859 fnum = GETFNUM(inbuf,smb_vwv0);
1861 CHECK_FNUM(fnum,cnum);
1864 mode = SVAL(inbuf,smb_vwv1) & 3;
1865 startpos = IVAL(inbuf,smb_vwv2);
1869 case 0: umode = SEEK_SET; break;
1870 case 1: umode = SEEK_CUR; break;
1871 case 2: umode = SEEK_END; break;
1873 umode = SEEK_SET; break;
1876 res = lseek(Files[fnum].fd,startpos,umode);
1877 Files[fnum].pos = res;
1879 outsize = set_message(outbuf,2,0,True);
1880 SIVALS(outbuf,smb_vwv0,res);
1882 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1888 /****************************************************************************
1890 ****************************************************************************/
1891 int reply_flush(char *inbuf,char *outbuf)
1894 int outsize = set_message(outbuf,0,0,True);
1896 cnum = SVAL(inbuf,smb_tid);
1897 fnum = GETFNUM(inbuf,smb_vwv0);
1899 if (fnum != 0xFFFF) {
1900 CHECK_FNUM(fnum,cnum);
1907 for (i=0;i<MAX_OPEN_FILES;i++)
1914 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1919 /****************************************************************************
1921 ****************************************************************************/
1922 int reply_exit(char *inbuf,char *outbuf)
1924 int outsize = set_message(outbuf,0,0,True);
1925 DEBUG(3,("%s exit\n",timestring()));
1931 /****************************************************************************
1933 ****************************************************************************/
1934 int reply_close(char *inbuf,char *outbuf)
1939 int32 eclass = 0, err = 0;
1941 outsize = set_message(outbuf,0,0,True);
1943 cnum = SVAL(inbuf,smb_tid);
1945 fnum = GETFNUM(inbuf,smb_vwv0);
1946 CHECK_FNUM(fnum,cnum);
1948 if(HAS_CACHED_ERROR(fnum)) {
1949 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1950 err = Files[fnum].wbmpx_ptr->wr_error;
1953 mtime = make_unix_date3(inbuf+smb_vwv1);
1955 /* try and set the date */
1956 set_filetime(Files[fnum].name,mtime);
1960 /* We have a cached error */
1962 return(ERROR(eclass,err));
1964 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
1965 timestring(),Files[fnum].fd,fnum,cnum,
1966 Connections[cnum].num_files_open));
1972 /****************************************************************************
1973 reply to a writeclose (Core+ protocol)
1974 ****************************************************************************/
1975 int reply_writeclose(char *inbuf,char *outbuf)
1977 int cnum,numtowrite,fnum;
1984 cnum = SVAL(inbuf,smb_tid);
1985 fnum = GETFNUM(inbuf,smb_vwv0);
1987 CHECK_FNUM(fnum,cnum);
1991 numtowrite = SVAL(inbuf,smb_vwv1);
1992 startpos = IVAL(inbuf,smb_vwv2);
1993 mtime = make_unix_date3(inbuf+smb_vwv4);
1994 data = smb_buf(inbuf) + 1;
1996 if (is_locked(fnum,cnum,numtowrite,startpos))
1997 return(ERROR(ERRDOS,ERRlock));
1999 seek_file(fnum,startpos);
2001 nwritten = write_file(fnum,data,numtowrite);
2003 set_filetime(Files[fnum].name,mtime);
2007 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2008 timestring(),fnum,cnum,numtowrite,nwritten,
2009 Connections[cnum].num_files_open));
2012 return(UNIXERROR(ERRDOS,ERRnoaccess));
2014 outsize = set_message(outbuf,1,0,True);
2016 SSVAL(outbuf,smb_vwv0,nwritten);
2021 /****************************************************************************
2023 ****************************************************************************/
2024 int reply_lock(char *inbuf,char *outbuf)
2027 int outsize = set_message(outbuf,0,0,True);
2028 uint32 count,offset;
2032 cnum = SVAL(inbuf,smb_tid);
2033 fnum = GETFNUM(inbuf,smb_vwv0);
2035 CHECK_FNUM(fnum,cnum);
2038 count = IVAL(inbuf,smb_vwv1);
2039 offset = IVAL(inbuf,smb_vwv3);
2041 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2043 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2044 return (ERROR(eclass,ecode));
2050 /****************************************************************************
2052 ****************************************************************************/
2053 int reply_unlock(char *inbuf,char *outbuf)
2056 int outsize = set_message(outbuf,0,0,True);
2057 uint32 count,offset;
2061 cnum = SVAL(inbuf,smb_tid);
2062 fnum = GETFNUM(inbuf,smb_vwv0);
2064 CHECK_FNUM(fnum,cnum);
2067 count = IVAL(inbuf,smb_vwv1);
2068 offset = IVAL(inbuf,smb_vwv3);
2070 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2071 return (ERROR(eclass,ecode));
2073 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2079 /****************************************************************************
2081 ****************************************************************************/
2082 int reply_tdis(char *inbuf,char *outbuf)
2085 int outsize = set_message(outbuf,0,0,True);
2087 cnum = SVAL(inbuf,smb_tid);
2088 uid = SVAL(inbuf,smb_uid);
2090 if (!OPEN_CNUM(cnum)) {
2091 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2092 return(ERROR(ERRSRV,ERRinvnid));
2095 Connections[cnum].used = False;
2097 close_cnum(cnum,uid);
2099 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2106 /****************************************************************************
2108 ****************************************************************************/
2109 int reply_echo(char *inbuf,char *outbuf)
2112 int smb_reverb = SVAL(inbuf,smb_vwv0);
2114 int data_len = smb_buflen(inbuf);
2115 int outsize = set_message(outbuf,1,data_len,True);
2117 cnum = SVAL(inbuf,smb_tid);
2119 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2121 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2122 return(ERROR(ERRSRV,ERRinvnid));
2125 /* copy any incoming data back out */
2127 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2129 if (smb_reverb > 100)
2131 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2135 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2137 SSVAL(outbuf,smb_vwv0,seq_num);
2139 smb_setlen(outbuf,outsize - 4);
2141 send_smb(Client,outbuf);
2144 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2150 /****************************************************************************
2151 reply to a printopen
2152 ****************************************************************************/
2153 int reply_printopen(char *inbuf,char *outbuf)
2161 *fname = *fname2 = 0;
2163 cnum = SVAL(inbuf,smb_tid);
2165 if (!CAN_PRINT(cnum))
2166 return(ERROR(ERRDOS,ERRnoaccess));
2171 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2175 if (!(isalnum(*p) || strchr("._-",*p)))
2180 if (strlen(s) > 10) s[10] = 0;
2182 sprintf(fname,"%s.XXXXXX",s);
2185 fnum = find_free_file();
2187 return(ERROR(ERRSRV,ERRnofids));
2189 strcpy(fname2,(char *)mktemp(fname));
2191 if (!check_name(fname2,cnum))
2192 return(ERROR(ERRDOS,ERRnoaccess));
2194 open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC,
2197 if (!Files[fnum].open)
2198 return(UNIXERROR(ERRDOS,ERRnoaccess));
2200 /* force it to be a print file */
2201 Files[fnum].print_file = True;
2203 outsize = set_message(outbuf,1,0,True);
2204 SSVAL(outbuf,smb_vwv0,fnum);
2206 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum));
2212 /****************************************************************************
2213 reply to a printclose
2214 ****************************************************************************/
2215 int reply_printclose(char *inbuf,char *outbuf)
2218 int outsize = set_message(outbuf,0,0,True);
2220 cnum = SVAL(inbuf,smb_tid);
2221 fnum = GETFNUM(inbuf,smb_vwv0);
2223 CHECK_FNUM(fnum,cnum);
2226 if (!CAN_PRINT(cnum))
2227 return(ERROR(ERRDOS,ERRnoaccess));
2231 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum));
2237 /****************************************************************************
2238 reply to a printqueue
2239 ****************************************************************************/
2240 int reply_printqueue(char *inbuf,char *outbuf)
2243 int outsize = set_message(outbuf,2,3,True);
2244 int max_count = SVAL(inbuf,smb_vwv0);
2245 int start_index = SVAL(inbuf,smb_vwv1);
2247 cnum = SVAL(inbuf,smb_tid);
2248 uid = SVAL(inbuf,smb_uid);
2250 /* allow checking the queue for anyone */
2252 if (!CAN_PRINT(cnum))
2253 return(ERROR(ERRDOS,ERRnoaccess));
2256 SSVAL(outbuf,smb_vwv0,0);
2257 SSVAL(outbuf,smb_vwv1,0);
2258 CVAL(smb_buf(outbuf),0) = 1;
2259 SSVAL(smb_buf(outbuf),1,0);
2261 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2262 timestring(),cnum,start_index,max_count));
2264 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2269 for (i=0;i<MAX_CONNECTIONS;i++)
2270 if (CAN_PRINT(i) && Connections[i].printer)
2274 for (i=0;i<MAX_CONNECTIONS;i++)
2278 if (!OPEN_CNUM(cnum))
2279 return(ERROR(ERRSRV,ERRinvnid));
2281 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2284 if (!become_user(cnum,uid))
2285 return(ERROR(ERRSRV,ERRinvnid));
2288 print_queue_struct *queue = NULL;
2289 char *p = smb_buf(outbuf) + 3;
2290 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2291 int num_to_get = ABS(max_count);
2292 int first = (max_count>0?start_index:start_index+max_count+1);
2298 num_to_get = MIN(num_to_get,count-first);
2301 for (i=first;i<first+num_to_get;i++)
2303 put_dos_date2(p,0,queue[i].time);
2304 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2305 SSVAL(p,5,queue[i].job);
2306 SIVAL(p,7,queue[i].size);
2308 StrnCpy(p+12,queue[i].user,16);
2314 outsize = set_message(outbuf,2,28*count+3,False);
2315 SSVAL(outbuf,smb_vwv0,count);
2316 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2317 CVAL(smb_buf(outbuf),0) = 1;
2318 SSVAL(smb_buf(outbuf),1,28*count);
2321 if (queue) free(queue);
2323 DEBUG(3,("%d entries returned in queue\n",count));
2330 /****************************************************************************
2331 reply to a printwrite
2332 ****************************************************************************/
2333 int reply_printwrite(char *inbuf,char *outbuf)
2335 int cnum,numtowrite,fnum;
2336 int outsize = set_message(outbuf,0,0,True);
2339 cnum = SVAL(inbuf,smb_tid);
2341 if (!CAN_PRINT(cnum))
2342 return(ERROR(ERRDOS,ERRnoaccess));
2344 fnum = GETFNUM(inbuf,smb_vwv0);
2346 CHECK_FNUM(fnum,cnum);
2350 numtowrite = SVAL(smb_buf(inbuf),1);
2351 data = smb_buf(inbuf) + 3;
2353 if (write_file(fnum,data,numtowrite) != numtowrite)
2354 return(UNIXERROR(ERRDOS,ERRnoaccess));
2356 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2362 /****************************************************************************
2364 ****************************************************************************/
2365 int reply_mkdir(char *inbuf,char *outbuf)
2369 int outsize,ret= -1;
2371 strcpy(directory,smb_buf(inbuf) + 1);
2372 cnum = SVAL(inbuf,smb_tid);
2373 unix_convert(directory,cnum);
2375 if (check_name(directory,cnum))
2376 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2379 return(UNIXERROR(ERRDOS,ERRnoaccess));
2381 outsize = set_message(outbuf,0,0,True);
2383 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2389 /****************************************************************************
2391 ****************************************************************************/
2392 int reply_rmdir(char *inbuf,char *outbuf)
2399 cnum = SVAL(inbuf,smb_tid);
2400 strcpy(directory,smb_buf(inbuf) + 1);
2401 unix_convert(directory,cnum);
2403 if (check_name(directory,cnum))
2405 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2406 ok = (sys_rmdir(directory) == 0);
2408 DEBUG(3,("couldn't remove directory %s : %s\n",
2409 directory,strerror(errno)));
2413 return(UNIXERROR(ERRDOS,ERRbadpath));
2415 outsize = set_message(outbuf,0,0,True);
2417 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2423 /*******************************************************************
2424 resolve wildcards in a filename rename
2425 ********************************************************************/
2426 static BOOL resolve_wildcards(char *name1,char *name2)
2428 fstring root1,root2;
2432 name1 = strrchr(name1,'/');
2433 name2 = strrchr(name2,'/');
2435 if (!name1 || !name2) return(False);
2437 strcpy(root1,name1);
2438 strcpy(root2,name2);
2439 p = strrchr(root1,'.');
2446 p = strrchr(root2,'.');
2478 strcpy(name2,root2);
2487 /*******************************************************************
2488 check if a user is allowed to rename a file
2489 ********************************************************************/
2490 static BOOL can_rename(char *fname,int cnum)
2494 if (!CAN_WRITE(cnum)) return(False);
2496 if (sys_lstat(fname,&sbuf) != 0) return(False);
2497 if (!check_file_sharing(cnum,fname)) return(False);
2502 /****************************************************************************
2504 ****************************************************************************/
2505 int reply_mv(char *inbuf,char *outbuf)
2511 pstring mask,newname;
2514 int error = ERRnoaccess;
2518 *directory = *mask = 0;
2520 cnum = SVAL(inbuf,smb_tid);
2522 strcpy(name,smb_buf(inbuf) + 1);
2523 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2525 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2527 unix_convert(name,cnum);
2528 unix_convert(newname,cnum);
2530 p = strrchr(name,'/');
2532 strcpy(directory,"./");
2536 strcpy(directory,name);
2540 if (is_mangled(mask))
2541 check_mangled_stack(mask);
2543 has_wild = strchr(mask,'*') || strchr(mask,'?');
2546 strcat(directory,"/");
2547 strcat(directory,mask);
2548 if (resolve_wildcards(directory,newname) &&
2549 can_rename(directory,cnum) &&
2550 !file_exist(newname,NULL) &&
2551 !sys_rename(directory,newname)) count++;
2552 if (!count) exists = file_exist(directory,NULL);
2553 if (!count && exists && file_exist(newname,NULL)) {
2558 void *dirptr = NULL;
2562 if (check_name(directory,cnum))
2563 dirptr = OpenDir(directory);
2569 if (strequal(mask,"????????.???"))
2572 while ((dname = ReadDirName(dirptr)))
2575 strcpy(fname,dname);
2577 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2579 error = ERRnoaccess;
2580 sprintf(fname,"%s/%s",directory,dname);
2581 if (!can_rename(fname,cnum)) continue;
2582 strcpy(destname,newname);
2584 if (!resolve_wildcards(fname,destname)) continue;
2586 if (file_exist(destname,NULL)) {
2590 if (!sys_rename(fname,destname)) count++;
2591 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2599 return(ERROR(ERRDOS,error));
2601 return(UNIXERROR(ERRDOS,error));
2604 outsize = set_message(outbuf,0,0,True);
2609 /*******************************************************************
2610 copy a file as part of a reply_copy
2611 ******************************************************************/
2612 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2613 int count,BOOL target_is_directory)
2622 if (target_is_directory) {
2623 char *p = strrchr(src,'/');
2632 if (!file_exist(src,&st)) return(False);
2634 fnum1 = find_free_file();
2635 if (fnum1<0) return(False);
2636 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2637 1,0,&Access,&action);
2639 if (!Files[fnum1].open) return(False);
2641 if (!target_is_directory && count)
2644 fnum2 = find_free_file();
2649 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2650 ofun,st.st_mode,&Access,&action);
2652 if (!Files[fnum2].open) {
2657 if ((ofun&3) == 1) {
2658 lseek(Files[fnum2].fd,0,SEEK_END);
2662 ret = transfer_file(Files[fnum1].fd,Files[fnum2].fd,st.st_size,NULL,0,0);
2667 return(ret == st.st_size);
2672 /****************************************************************************
2673 reply to a file copy.
2674 ****************************************************************************/
2675 int reply_copy(char *inbuf,char *outbuf)
2681 pstring mask,newname;
2684 int error = ERRnoaccess;
2687 int tid2 = SVAL(inbuf,smb_vwv0);
2688 int ofun = SVAL(inbuf,smb_vwv1);
2689 int flags = SVAL(inbuf,smb_vwv2);
2690 BOOL target_is_directory=False;
2692 *directory = *mask = 0;
2694 cnum = SVAL(inbuf,smb_tid);
2696 strcpy(name,smb_buf(inbuf));
2697 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2699 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2702 /* can't currently handle inter share copies XXXX */
2703 DEBUG(3,("Rejecting inter-share copy\n"));
2704 return(ERROR(ERRSRV,ERRinvdevice));
2707 unix_convert(name,cnum);
2708 unix_convert(newname,cnum);
2710 target_is_directory = directory_exist(newname,NULL);
2712 if ((flags&1) && target_is_directory) {
2713 return(ERROR(ERRDOS,ERRbadfile));
2716 if ((flags&2) && !target_is_directory) {
2717 return(ERROR(ERRDOS,ERRbadpath));
2720 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2721 /* wants a tree copy! XXXX */
2722 DEBUG(3,("Rejecting tree copy\n"));
2723 return(ERROR(ERRSRV,ERRerror));
2726 p = strrchr(name,'/');
2728 strcpy(directory,"./");
2732 strcpy(directory,name);
2736 if (is_mangled(mask))
2737 check_mangled_stack(mask);
2739 has_wild = strchr(mask,'*') || strchr(mask,'?');
2742 strcat(directory,"/");
2743 strcat(directory,mask);
2744 if (resolve_wildcards(directory,newname) &&
2745 copy_file(directory,newname,cnum,ofun,
2746 count,target_is_directory)) count++;
2747 if (!count) exists = file_exist(directory,NULL);
2749 void *dirptr = NULL;
2753 if (check_name(directory,cnum))
2754 dirptr = OpenDir(directory);
2760 if (strequal(mask,"????????.???"))
2763 while ((dname = ReadDirName(dirptr)))
2766 strcpy(fname,dname);
2768 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2770 error = ERRnoaccess;
2771 sprintf(fname,"%s/%s",directory,dname);
2772 strcpy(destname,newname);
2773 if (resolve_wildcards(fname,destname) &&
2774 copy_file(directory,newname,cnum,ofun,
2775 count,target_is_directory)) count++;
2776 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2784 return(ERROR(ERRDOS,error));
2786 return(UNIXERROR(ERRDOS,error));
2789 outsize = set_message(outbuf,1,0,True);
2790 SSVAL(outbuf,smb_vwv0,count);
2797 /****************************************************************************
2799 ****************************************************************************/
2800 int reply_setdir(char *inbuf,char *outbuf)
2807 cnum = SVAL(inbuf,smb_tid);
2809 snum = Connections[cnum].service;
2810 if (!CAN_SETDIR(snum))
2811 return(ERROR(ERRDOS,ERRnoaccess));
2813 strcpy(newdir,smb_buf(inbuf) + 1);
2816 if (strlen(newdir) == 0)
2820 ok = directory_exist(newdir,NULL);
2822 string_set(&Connections[cnum].connectpath,newdir);
2826 return(ERROR(ERRDOS,ERRbadpath));
2828 outsize = set_message(outbuf,0,0,True);
2829 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
2831 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
2837 /****************************************************************************
2838 reply to a lockingX request
2839 ****************************************************************************/
2840 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
2842 int fnum = GETFNUM(inbuf,smb_vwv2);
2843 uint16 locktype = SVAL(inbuf,smb_vwv3);
2844 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
2845 uint16 num_locks = SVAL(inbuf,smb_vwv7);
2846 uint32 count, offset;
2851 uint32 ecode=0, dummy2;
2852 int eclass=0, dummy1;
2854 cnum = SVAL(inbuf,smb_tid);
2856 CHECK_FNUM(fnum,cnum);
2859 data = smb_buf(inbuf);
2860 /* Data now points at the beginning of the list
2861 of smb_unlkrng structs */
2862 for(i = 0; i < (int)num_ulocks; i++) {
2863 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2864 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2865 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
2866 return ERROR(eclass,ecode);
2869 /* Now do any requested locks */
2870 data += 10*num_ulocks;
2871 /* Data now points at the beginning of the list
2872 of smb_lkrng structs */
2873 for(i = 0; i < (int)num_locks; i++) {
2874 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2875 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2876 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
2880 /* If any of the above locks failed, then we must unlock
2881 all of the previous locks (X/Open spec). */
2882 if(i != num_locks && num_locks != 0) {
2883 for(; i >= 0; i--) {
2884 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2885 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2886 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
2888 return ERROR(eclass,ecode);
2891 set_message(outbuf,2,0,True);
2893 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
2894 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
2898 return chain_reply(inbuf,outbuf,length,bufsize);
2902 /****************************************************************************
2903 reply to a SMBreadbmpx (read block multiplex) request
2904 ****************************************************************************/
2905 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
2912 int outsize, mincount, maxcount;
2917 /* this function doesn't seem to work - disable by default */
2919 return(ERROR(ERRSRV,ERRuseSTD));
2921 outsize = set_message(outbuf,8,0,True);
2923 cnum = SVAL(inbuf,smb_tid);
2924 fnum = GETFNUM(inbuf,smb_vwv0);
2926 CHECK_FNUM(fnum,cnum);
2930 startpos = IVAL(inbuf,smb_vwv1);
2931 maxcount = SVAL(inbuf,smb_vwv3);
2932 mincount = SVAL(inbuf,smb_vwv4);
2934 data = smb_buf(outbuf);
2935 pad = ((int)data)%4;
2936 if (pad) pad = 4 - pad;
2939 max_per_packet = bufsize-(outsize+pad);
2943 if (is_locked(fnum,cnum,maxcount,startpos))
2944 return(ERROR(ERRDOS,ERRlock));
2948 int N = MIN(max_per_packet,tcount-total_read);
2950 nread = read_file(fnum,data,startpos,N);
2952 if (nread <= 0) nread = 0;
2955 tcount = total_read + nread;
2957 set_message(outbuf,8,nread,False);
2958 SIVAL(outbuf,smb_vwv0,startpos);
2959 SSVAL(outbuf,smb_vwv2,tcount);
2960 SSVAL(outbuf,smb_vwv6,nread);
2961 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
2963 send_smb(Client,outbuf);
2965 total_read += nread;
2968 while (total_read < tcount);
2974 /****************************************************************************
2975 reply to a SMBwritebmpx (write block multiplex primary) request
2976 ****************************************************************************/
2977 int reply_writebmpx(char *inbuf,char *outbuf)
2979 int cnum,numtowrite,fnum;
2983 int tcount, write_through, smb_doff;
2986 cnum = SVAL(inbuf,smb_tid);
2987 fnum = GETFNUM(inbuf,smb_vwv0);
2989 CHECK_FNUM(fnum,cnum);
2993 tcount = SVAL(inbuf,smb_vwv1);
2994 startpos = IVAL(inbuf,smb_vwv3);
2995 write_through = BITSETW(inbuf+smb_vwv7,0);
2996 numtowrite = SVAL(inbuf,smb_vwv10);
2997 smb_doff = SVAL(inbuf,smb_vwv11);
2999 data = smb_base(inbuf) + smb_doff;
3001 /* If this fails we need to send an SMBwriteC response,
3002 not an SMBwritebmpx - set this up now so we don't forget */
3003 CVAL(outbuf,smb_com) = SMBwritec;
3005 if (is_locked(fnum,cnum,tcount,startpos))
3006 return(ERROR(ERRDOS,ERRlock));
3008 seek_file(fnum,startpos);
3009 nwritten = write_file(fnum,data,numtowrite);
3011 if(lp_syncalways(SNUM(cnum)) || write_through)
3014 if(nwritten < numtowrite)
3015 return(UNIXERROR(ERRHRD,ERRdiskfull));
3017 /* If the maximum to be written to this file
3018 is greater than what we just wrote then set
3019 up a secondary struct to be attached to this
3020 fd, we will use this to cache error messages etc. */
3021 if(tcount > nwritten)
3023 write_bmpx_struct *wbms;
3024 if(Files[fnum].wbmpx_ptr != NULL)
3025 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3027 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3030 DEBUG(0,("Out of memory in reply_readmpx\n"));
3031 return(ERROR(ERRSRV,ERRnoresource));
3033 wbms->wr_mode = write_through;
3034 wbms->wr_discard = False; /* No errors yet */
3035 wbms->wr_total_written = nwritten;
3036 wbms->wr_errclass = 0;
3038 Files[fnum].wbmpx_ptr = wbms;
3041 /* We are returning successfully, set the message type back to
3043 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3045 outsize = set_message(outbuf,1,0,True);
3047 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3049 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3050 timestring(),fnum,cnum,numtowrite,nwritten));
3052 if (write_through && tcount==nwritten) {
3053 /* we need to send both a primary and a secondary response */
3054 smb_setlen(outbuf,outsize - 4);
3055 send_smb(Client,outbuf);
3057 /* now the secondary */
3058 outsize = set_message(outbuf,1,0,True);
3059 CVAL(outbuf,smb_com) = SMBwritec;
3060 SSVAL(outbuf,smb_vwv0,nwritten);
3067 /****************************************************************************
3068 reply to a SMBwritebs (write block multiplex secondary) request
3069 ****************************************************************************/
3070 int reply_writebs(char *inbuf,char *outbuf)
3072 int cnum,numtowrite,fnum;
3076 int tcount, write_through, smb_doff;
3078 write_bmpx_struct *wbms;
3079 BOOL send_response = False;
3081 cnum = SVAL(inbuf,smb_tid);
3082 fnum = GETFNUM(inbuf,smb_vwv0);
3083 CHECK_FNUM(fnum,cnum);
3086 tcount = SVAL(inbuf,smb_vwv1);
3087 startpos = IVAL(inbuf,smb_vwv2);
3088 numtowrite = SVAL(inbuf,smb_vwv6);
3089 smb_doff = SVAL(inbuf,smb_vwv7);
3091 data = smb_base(inbuf) + smb_doff;
3093 /* We need to send an SMBwriteC response, not an SMBwritebs */
3094 CVAL(outbuf,smb_com) = SMBwritec;
3096 /* This fd should have an auxiliary struct attached,
3097 check that it does */
3098 wbms = Files[fnum].wbmpx_ptr;
3099 if(!wbms) return(-1);
3101 /* If write through is set we can return errors, else we must
3103 write_through = wbms->wr_mode;
3105 /* Check for an earlier error */
3106 if(wbms->wr_discard)
3107 return -1; /* Just discard the packet */
3109 seek_file(fnum,startpos);
3110 nwritten = write_file(fnum,data,numtowrite);
3112 if(lp_syncalways(SNUM(cnum)) || write_through)
3115 if (nwritten < numtowrite)
3118 /* We are returning an error - we can delete the aux struct */
3119 if (wbms) free((char *)wbms);
3120 Files[fnum].wbmpx_ptr = NULL;
3121 return(ERROR(ERRHRD,ERRdiskfull));
3123 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3126 /* Increment the total written, if this matches tcount
3127 we can discard the auxiliary struct (hurrah !) and return a writeC */
3128 wbms->wr_total_written += nwritten;
3129 if(wbms->wr_total_written >= tcount)
3131 if (write_through) {
3132 outsize = set_message(outbuf,1,0,True);
3133 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3134 send_response = True;
3138 Files[fnum].wbmpx_ptr = NULL;
3148 /****************************************************************************
3149 reply to a SMBsetattrE
3150 ****************************************************************************/
3151 int reply_setattrE(char *inbuf,char *outbuf)
3154 struct utimbuf unix_times;
3157 outsize = set_message(outbuf,0,0,True);
3159 cnum = SVAL(inbuf,smb_tid);
3160 fnum = GETFNUM(inbuf,smb_vwv0);
3162 CHECK_FNUM(fnum,cnum);
3165 /* Convert the DOS times into unix times. Ignore create
3166 time as UNIX can't set this.
3168 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3169 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3171 /* Set the date on this file */
3172 if(sys_utime(Files[fnum].name, &unix_times))
3173 return(ERROR(ERRDOS,ERRnoaccess));
3175 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3181 /****************************************************************************
3182 reply to a SMBgetattrE
3183 ****************************************************************************/
3184 int reply_getattrE(char *inbuf,char *outbuf)
3191 outsize = set_message(outbuf,11,0,True);
3193 cnum = SVAL(inbuf,smb_tid);
3194 fnum = GETFNUM(inbuf,smb_vwv0);
3196 CHECK_FNUM(fnum,cnum);
3199 /* Do an fstat on this file */
3200 if(fstat(Files[fnum].fd, &sbuf))
3201 return(UNIXERROR(ERRDOS,ERRnoaccess));
3203 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3205 /* Convert the times into dos times. Set create
3206 date to be last modify date as UNIX doesn't save
3208 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3209 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3210 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3213 SIVAL(outbuf,smb_vwv6,0);
3214 SIVAL(outbuf,smb_vwv8,0);
3218 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3219 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3221 SSVAL(outbuf,smb_vwv10, mode);
3223 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));