2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1997
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;
35 extern int chain_fnum;
36 extern char magic_char;
37 extern connection_struct Connections[];
38 extern files_struct Files[];
39 extern BOOL case_sensitive;
40 extern BOOL case_preserve;
41 extern BOOL short_case_preserve;
42 extern pstring sesssetup_user;
43 extern fstring myworkgroup;
46 /* this macro should always be used to extract an fnum (smb_fid) from
47 a packet to ensure chaining works correctly */
48 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
51 /****************************************************************************
52 reply to an special message
53 ****************************************************************************/
54 int reply_special(char *inbuf,char *outbuf)
57 int msg_type = CVAL(inbuf,0);
58 int msg_flags = CVAL(inbuf,1);
60 extern fstring remote_machine;
61 extern fstring local_machine;
70 case 0x81: /* session request */
71 CVAL(outbuf,0) = 0x82;
73 if (name_len(inbuf+4) > 50)
75 DEBUG(0,("Invalid name length in session request\n"));
78 name_extract(inbuf,4,name1);
79 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
80 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2));
82 strcpy(remote_machine,name2);
83 trim_string(remote_machine," "," ");
84 p = strchr(remote_machine,' ');
85 strlower(remote_machine);
88 strcpy(local_machine,name1);
89 trim_string(local_machine," "," ");
90 p = strchr(local_machine,' ');
91 strlower(local_machine);
94 add_session_user(remote_machine);
96 reload_services(True);
100 case 0x85: /* session keepalive */
105 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags));
111 /*******************************************************************
112 work out what error to give to a failed connection
113 ********************************************************************/
114 static int connection_error(char *inbuf,char *outbuf,int connection_num)
116 switch (connection_num)
119 return(ERROR(ERRSRV,ERRnoresource));
121 return(ERROR(ERRSRV,ERRbaduid));
123 return(ERROR(ERRSRV,ERRinvdevice));
125 return(ERROR(ERRSRV,ERRinvnetname));
127 return(ERROR(ERRSRV,ERRaccess));
129 return(ERROR(ERRDOS,ERRnoipc));
131 return(ERROR(ERRSRV,ERRinvnetname));
133 return(ERROR(ERRSRV,ERRbadpw));
138 /****************************************************************************
139 parse a share descriptor string
140 ****************************************************************************/
141 static void parse_connect(char *p,char *service,char *user,
142 char *password,int *pwlen,char *dev)
146 DEBUG(4,("parsing connect string %s\n",p));
148 p2 = strrchr(p,'\\');
152 strcpy(service,p2+1);
157 *pwlen = strlen(password);
164 p = strchr(service,'%');
175 /****************************************************************************
177 ****************************************************************************/
178 int reply_tcon(char *inbuf,char *outbuf)
186 uint16 vuid = SVAL(inbuf,smb_uid);
189 *service = *user = *password = *dev = 0;
191 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
193 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
195 if (connection_num < 0)
196 return(connection_error(inbuf,outbuf,connection_num));
198 outsize = set_message(outbuf,2,0,True);
199 SSVAL(outbuf,smb_vwv0,max_recv);
200 SSVAL(outbuf,smb_vwv1,connection_num);
201 SSVAL(outbuf,smb_tid,connection_num);
203 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
209 /****************************************************************************
210 reply to a tcon and X
211 ****************************************************************************/
212 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
219 uint16 vuid = SVAL(inbuf,smb_uid);
220 int passlen = SVAL(inbuf,smb_vwv3);
221 BOOL doencrypt = SMBENCRYPT();
223 *service = *user = *password = *devicename = 0;
225 /* we might have to close an old one */
226 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
227 close_cnum(SVAL(inbuf,smb_tid),vuid);
232 memcpy(password,smb_buf(inbuf),passlen);
234 path = smb_buf(inbuf) + passlen;
236 if (!doencrypt || passlen != 24) {
237 if (strequal(password," "))
239 passlen = strlen(password);
242 DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
243 strcpy(service,path+2);
244 p = strchr(service,'\\');
246 return(ERROR(ERRSRV,ERRinvnetname));
249 p = strchr(service,'%');
255 StrnCpy(devicename,path + strlen(path) + 1,6);
256 DEBUG(4,("Got device type %s\n",devicename));
259 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
261 if (connection_num < 0)
262 return(connection_error(inbuf,outbuf,connection_num));
264 set_message(outbuf,2,strlen(devicename)+1,True);
266 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
268 /* set the incoming and outgoing tid to the just created one */
269 SSVAL(inbuf,smb_tid,connection_num);
270 SSVAL(outbuf,smb_tid,connection_num);
272 strcpy(smb_buf(outbuf),devicename);
274 return chain_reply(inbuf,outbuf,length,bufsize);
278 /****************************************************************************
279 reply to an unknown type
280 ****************************************************************************/
281 int reply_unknown(char *inbuf,char *outbuf)
285 cnum = SVAL(inbuf,smb_tid);
286 type = CVAL(inbuf,smb_com);
288 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
293 return(ERROR(ERRSRV,ERRunknownsmb));
297 /****************************************************************************
299 ****************************************************************************/
300 int reply_ioctl(char *inbuf,char *outbuf)
302 DEBUG(3,("ignoring ioctl\n"));
304 /* we just say it succeeds and hope its all OK.
305 some day it would be nice to interpret them individually */
306 return set_message(outbuf,1,0,True);
308 return(ERROR(ERRSRV,ERRnosupport));
313 /****************************************************************************
314 reply to a session setup command
315 ****************************************************************************/
316 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
325 int smb_apasslen = 0;
327 int smb_ntpasslen = 0;
328 pstring smb_ntpasswd;
329 BOOL valid_nt_password = False;
332 BOOL computer_id=False;
333 static BOOL done_sesssetup = False;
334 BOOL doencrypt = SMBENCRYPT();
338 smb_bufsize = SVAL(inbuf,smb_vwv2);
339 smb_mpxmax = SVAL(inbuf,smb_vwv3);
340 smb_vc_num = SVAL(inbuf,smb_vwv4);
341 smb_sesskey = IVAL(inbuf,smb_vwv5);
343 if (Protocol < PROTOCOL_NT1) {
344 smb_apasslen = SVAL(inbuf,smb_vwv7);
345 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
346 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
348 if (lp_security() != SEC_SERVER && !doencrypt)
349 smb_apasslen = strlen(smb_apasswd);
351 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
352 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
353 char *p = smb_buf(inbuf);
355 if (passlen1 != 24 && passlen2 != 24)
359 /* Save the lanman2 password and the NT md4 password. */
360 smb_apasslen = passlen1;
361 memcpy(smb_apasswd,p,smb_apasslen);
362 smb_ntpasslen = passlen2;
363 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
365 /* both Win95 and WinNT stuff up the password lengths for
366 non-encrypting systems. Uggh.
368 if passlen1==24 its a win95 system, and its setting the
369 password length incorrectly. Luckily it still works with the
370 default code because Win95 will null terminate the password
373 if passlen1>0 and passlen2>0 then maybe its a NT box and its
374 setting passlen2 to some random value which really stuffs
375 things up. we need to fix that one. */
376 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
380 /* we use the first password that they gave */
381 smb_apasslen = passlen1;
382 StrnCpy(smb_apasswd,p,smb_apasslen);
384 /* trim the password */
385 smb_apasslen = strlen(smb_apasswd);
387 /* wfwg sometimes uses a space instead of a null */
388 if (strequal(smb_apasswd," ")) {
394 p += passlen1 + passlen2;
395 strcpy(user,p); p = skip_string(p,1);
396 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
397 p,skip_string(p,1),skip_string(p,2)));
401 DEBUG(3,("sesssetupX:name=[%s]\n",user));
403 /* If name ends in $ then I think it's asking about whether a */
404 /* computer with that name (minus the $) has access. For now */
405 /* say yes to everything ending in $. */
406 if (user[strlen(user) - 1] == '$') {
408 user[strlen(user) - 1] = '\0';
412 /* If no username is sent use the guest account */
415 strcpy(user,lp_guestaccount(-1));
416 /* If no user and no password then set guest flag. */
417 if( *smb_apasswd == 0)
423 strcpy(sesssetup_user,user);
425 reload_services(True);
427 add_session_user(user);
430 if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
431 !check_hosts_equiv(user))
434 /* now check if it's a valid username/password */
435 /* If an NT password was supplied try and validate with that
436 first. This is superior as the passwords are mixed case
437 128 length unicode */
440 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
441 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
443 valid_nt_password = True;
445 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
447 if (!computer_id && lp_security() >= SEC_USER) {
448 #if (GUEST_SESSSETUP == 0)
449 return(ERROR(ERRSRV,ERRbadpw));
451 #if (GUEST_SESSSETUP == 1)
452 if (Get_Pwnam(user,True))
453 return(ERROR(ERRSRV,ERRbadpw));
456 if (*smb_apasswd || !Get_Pwnam(user,True))
457 strcpy(user,lp_guestaccount(-1));
458 DEBUG(3,("Registered username %s for guest access\n",user));
463 if (!Get_Pwnam(user,True)) {
464 DEBUG(3,("No such user %s - using guest account\n",user));
465 strcpy(user,lp_guestaccount(-1));
469 if (!strequal(user,lp_guestaccount(-1)) &&
470 lp_servicenumber(user) < 0)
472 int homes = lp_servicenumber(HOMES_NAME);
473 char *home = get_home_dir(user);
474 if (homes >= 0 && home)
475 lp_add_home(user,homes,home);
479 /* it's ok - setup a reply */
480 if (Protocol < PROTOCOL_NT1) {
481 set_message(outbuf,3,0,True);
484 set_message(outbuf,3,3,True);
486 strcpy(p,"Unix"); p = skip_string(p,1);
487 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
488 strcpy(p,myworkgroup); p = skip_string(p,1);
489 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
490 /* perhaps grab OS version here?? */
493 /* Set the correct uid in the outgoing and incoming packets
494 We will use this on future requests to determine which
495 user we should become.
498 struct passwd *pw = Get_Pwnam(user,False);
500 DEBUG(1,("Username %s is invalid on this system\n",user));
501 return(ERROR(ERRSRV,ERRbadpw));
507 if (guest && !computer_id)
508 SSVAL(outbuf,smb_vwv2,1);
510 /* register the name and uid as being validated, so further connections
511 to a uid can get through without a password, on the same VC */
512 sess_vuid = register_vuid(uid,gid,user,guest);
514 SSVAL(outbuf,smb_uid,sess_vuid);
515 SSVAL(inbuf,smb_uid,sess_vuid);
518 max_send = MIN(max_send,smb_bufsize);
520 DEBUG(1,(" Client requested max send size of %d\n", max_send));
522 done_sesssetup = True;
524 return chain_reply(inbuf,outbuf,length,bufsize);
528 /****************************************************************************
530 ****************************************************************************/
531 int reply_chkpth(char *inbuf,char *outbuf)
538 cnum = SVAL(inbuf,smb_tid);
540 strcpy(name,smb_buf(inbuf) + 1);
541 unix_convert(name,cnum,0);
543 mode = SVAL(inbuf,smb_vwv0);
545 if (check_name(name,cnum))
546 ok = directory_exist(name,NULL);
549 return(UNIXERROR(ERRDOS,ERRbadpath));
551 outsize = set_message(outbuf,0,0,True);
553 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
559 /****************************************************************************
561 ****************************************************************************/
562 int reply_getatr(char *inbuf,char *outbuf)
573 cnum = SVAL(inbuf,smb_tid);
575 strcpy(fname,smb_buf(inbuf) + 1);
576 unix_convert(fname,cnum,0);
578 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
579 under WfWg - weird! */
582 mode = aHIDDEN | aDIR;
583 if (!CAN_WRITE(cnum)) mode |= aRONLY;
589 if (check_name(fname,cnum))
591 if (sys_stat(fname,&sbuf) == 0)
593 mode = dos_mode(cnum,fname,&sbuf);
595 mtime = sbuf.st_mtime;
601 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
605 return(UNIXERROR(ERRDOS,ERRbadfile));
607 outsize = set_message(outbuf,10,0,True);
609 SSVAL(outbuf,smb_vwv0,mode);
610 put_dos_date3(outbuf,smb_vwv1,mtime);
611 SIVAL(outbuf,smb_vwv3,size);
613 if (Protocol >= PROTOCOL_NT1) {
614 char *p = strrchr(fname,'/');
615 uint16 flg2 = SVAL(outbuf,smb_flg2);
617 if (!is_8_3(fname, True))
618 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
621 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
627 /****************************************************************************
629 ****************************************************************************/
630 int reply_setatr(char *inbuf,char *outbuf)
639 cnum = SVAL(inbuf,smb_tid);
641 strcpy(fname,smb_buf(inbuf) + 1);
642 unix_convert(fname,cnum,0);
644 mode = SVAL(inbuf,smb_vwv0);
645 mtime = make_unix_date3(inbuf+smb_vwv1);
647 if (directory_exist(fname,NULL))
649 if (check_name(fname,cnum))
650 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
652 ok = set_filetime(fname,mtime);
655 return(UNIXERROR(ERRDOS,ERRnoaccess));
657 outsize = set_message(outbuf,0,0,True);
659 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
665 /****************************************************************************
667 ****************************************************************************/
668 int reply_dskattr(char *inbuf,char *outbuf)
672 int dfree,dsize,bsize;
674 cnum = SVAL(inbuf,smb_tid);
676 sys_disk_free(".",&bsize,&dfree,&dsize);
678 outsize = set_message(outbuf,5,0,True);
680 SSVAL(outbuf,smb_vwv0,dsize);
681 SSVAL(outbuf,smb_vwv1,bsize/512);
682 SSVAL(outbuf,smb_vwv2,512);
683 SSVAL(outbuf,smb_vwv3,dfree);
685 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
691 /****************************************************************************
693 Can be called from SMBsearch, SMBffirst or SMBfunique.
694 ****************************************************************************/
695 int reply_search(char *inbuf,char *outbuf)
706 BOOL finished = False;
715 BOOL check_descend = False;
716 BOOL expect_close = False;
717 BOOL can_open = True;
719 *mask = *directory = *fname = 0;
721 /* If we were called as SMBffirst then we must expect close. */
722 if(CVAL(inbuf,smb_com) == SMBffirst)
725 cnum = SVAL(inbuf,smb_tid);
727 outsize = set_message(outbuf,1,3,True);
728 maxentries = SVAL(inbuf,smb_vwv0);
729 dirtype = SVAL(inbuf,smb_vwv1);
730 path = smb_buf(inbuf) + 1;
731 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
734 /* dirtype &= ~aDIR; */
736 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
743 strcpy(directory,smb_buf(inbuf)+1);
744 strcpy(dir2,smb_buf(inbuf)+1);
745 unix_convert(directory,cnum,0);
748 if (!check_name(directory,cnum))
751 p = strrchr(dir2,'/');
753 {strcpy(mask,dir2);*dir2 = 0;}
755 {*p = 0;strcpy(mask,p+1);}
757 p = strrchr(directory,'/');
763 if (strlen(directory) == 0)
764 strcpy(directory,"./");
766 CVAL(status,0) = dirtype;
770 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
771 memcpy(mask,status+1,11);
773 dirtype = CVAL(status,0) & 0x1F;
774 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
775 if (!Connections[cnum].dirptr)
777 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
782 /* turn strings of spaces into a . */
784 trim_string(mask,NULL," ");
785 if ((p = strrchr(mask,' ')))
790 trim_string(mask,NULL," ");
797 for (p=mask; *p; p++)
799 if (*p != '?' && *p != '*' && !isdoschar(*p))
801 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
807 if (!strchr(mask,'.') && strlen(mask)>8)
810 strcpy(tmp,&mask[8]);
816 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
820 p = smb_buf(outbuf) + 3;
826 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
830 return (UNIXERROR(ERRDOS,ERRnofids));
831 return(ERROR(ERRDOS,ERRnofids));
835 DEBUG(4,("dptr_num is %d\n",dptr_num));
839 if ((dirtype&0x1F) == aVOLID)
842 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
843 dptr_fill(p+12,dptr_num);
844 if (dptr_zero(p+12) && (status_len==0))
848 p += DIR_STRUCT_SIZE;
852 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
853 if (in_list(Connections[cnum].dirpath,
854 lp_dontdescend(SNUM(cnum)),True))
855 check_descend = True;
857 for (i=numentries;(i<maxentries) && !finished;i++)
860 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
864 make_dir_struct(p,mask,fname,size,mode,date);
865 dptr_fill(p+12,dptr_num);
868 p += DIR_STRUCT_SIZE;
877 if (numentries == 0 || !ok)
879 CVAL(outbuf,smb_rcls) = ERRDOS;
880 SSVAL(outbuf,smb_err,ERRnofiles);
883 /* If we were called as SMBffirst with smb_search_id == NULL
884 and no entries were found then return error and close dirptr
887 if(ok && expect_close && numentries == 0 && status_len == 0)
889 CVAL(outbuf,smb_rcls) = ERRDOS;
890 SSVAL(outbuf,smb_err,ERRnofiles);
891 /* Also close the dptr - we know it's gone */
892 dptr_close(dptr_num);
895 /* If we were called as SMBfunique, then we can close the dirptr now ! */
896 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
897 dptr_close(dptr_num);
899 SSVAL(outbuf,smb_vwv0,numentries);
900 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
901 CVAL(smb_buf(outbuf),0) = 5;
902 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
904 if (Protocol >= PROTOCOL_NT1) {
905 uint16 flg2 = SVAL(outbuf,smb_flg2);
906 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
909 outsize += DIR_STRUCT_SIZE*numentries;
910 smb_setlen(outbuf,outsize - 4);
912 if ((! *directory) && dptr_path(dptr_num))
913 sprintf(directory,"(%s)",dptr_path(dptr_num));
915 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
917 smb_fn_name(CVAL(inbuf,smb_com)),
918 mask,directory,cnum,dirtype,numentries,maxentries));
924 /****************************************************************************
925 reply to a fclose (stop directory search)
926 ****************************************************************************/
927 int reply_fclose(char *inbuf,char *outbuf)
936 cnum = SVAL(inbuf,smb_tid);
938 outsize = set_message(outbuf,1,0,True);
939 path = smb_buf(inbuf) + 1;
940 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
944 return(ERROR(ERRSRV,ERRsrverror));
946 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
948 if(dptr_fetch(status+12,&dptr_num)) {
949 /* Close the dptr - we know it's gone */
950 dptr_close(dptr_num);
953 SSVAL(outbuf,smb_vwv0,0);
955 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
961 /****************************************************************************
963 ****************************************************************************/
964 int reply_open(char *inbuf,char *outbuf)
978 cnum = SVAL(inbuf,smb_tid);
980 share_mode = SVAL(inbuf,smb_vwv0);
982 strcpy(fname,smb_buf(inbuf)+1);
983 unix_convert(fname,cnum,0);
985 fnum = find_free_file();
987 return(ERROR(ERRSRV,ERRnofids));
989 if (!check_name(fname,cnum))
990 return(UNIXERROR(ERRDOS,ERRnoaccess));
992 unixmode = unix_mode(cnum,aARCH);
994 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
996 if (!Files[fnum].open)
997 return(UNIXERROR(ERRDOS,ERRnoaccess));
999 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1001 return(ERROR(ERRDOS,ERRnoaccess));
1004 size = sbuf.st_size;
1005 fmode = dos_mode(cnum,fname,&sbuf);
1006 mtime = sbuf.st_mtime;
1009 DEBUG(3,("attempt to open a directory %s\n",fname));
1011 return(ERROR(ERRDOS,ERRnoaccess));
1014 outsize = set_message(outbuf,7,0,True);
1015 SSVAL(outbuf,smb_vwv0,fnum);
1016 SSVAL(outbuf,smb_vwv1,fmode);
1017 put_dos_date3(outbuf,smb_vwv2,mtime);
1018 SIVAL(outbuf,smb_vwv4,size);
1019 SSVAL(outbuf,smb_vwv6,rmode);
1021 if (lp_fake_oplocks(SNUM(cnum))) {
1022 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1029 /****************************************************************************
1030 reply to an open and X
1031 ****************************************************************************/
1032 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1035 int cnum = SVAL(inbuf,smb_tid);
1037 int smb_mode = SVAL(inbuf,smb_vwv3);
1038 int smb_attr = SVAL(inbuf,smb_vwv5);
1039 BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
1041 int open_flags = SVAL(inbuf,smb_vwv2);
1042 int smb_sattr = SVAL(inbuf,smb_vwv4);
1043 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1045 int smb_ofun = SVAL(inbuf,smb_vwv8);
1047 int size=0,fmode=0,mtime=0,rmode=0;
1051 /* If it's an IPC, pass off the pipe handler. */
1053 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1055 /* XXXX we need to handle passed times, sattr and flags */
1057 strcpy(fname,smb_buf(inbuf));
1058 unix_convert(fname,cnum,0);
1060 fnum = find_free_file();
1062 return(ERROR(ERRSRV,ERRnofids));
1064 if (!check_name(fname,cnum))
1065 return(UNIXERROR(ERRDOS,ERRnoaccess));
1067 unixmode = unix_mode(cnum,smb_attr | aARCH);
1069 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1070 &rmode,&smb_action);
1072 if (!Files[fnum].open)
1073 return(UNIXERROR(ERRDOS,ERRnoaccess));
1075 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1077 return(ERROR(ERRDOS,ERRnoaccess));
1080 size = sbuf.st_size;
1081 fmode = dos_mode(cnum,fname,&sbuf);
1082 mtime = sbuf.st_mtime;
1085 return(ERROR(ERRDOS,ERRnoaccess));
1088 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1089 smb_action |= (1<<15);
1092 set_message(outbuf,15,0,True);
1093 SSVAL(outbuf,smb_vwv2,fnum);
1094 SSVAL(outbuf,smb_vwv3,fmode);
1095 put_dos_date3(outbuf,smb_vwv4,mtime);
1096 SIVAL(outbuf,smb_vwv6,size);
1097 SSVAL(outbuf,smb_vwv8,rmode);
1098 SSVAL(outbuf,smb_vwv11,smb_action);
1102 return chain_reply(inbuf,outbuf,length,bufsize);
1106 /****************************************************************************
1107 reply to a SMBulogoffX
1108 ****************************************************************************/
1109 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1111 uint16 vuid = SVAL(inbuf,smb_uid);
1112 user_struct *vuser = get_valid_user_struct(vuid);
1115 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1118 /* in user level security we are supposed to close any files
1119 open by this user */
1120 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1122 for (i=0;i<MAX_OPEN_FILES;i++)
1123 if (Files[i].uid == vuser->uid && Files[i].open) {
1128 invalidate_vuid(vuid);
1130 set_message(outbuf,2,0,True);
1132 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1134 return chain_reply(inbuf,outbuf,length,bufsize);
1138 /****************************************************************************
1139 reply to a mknew or a create
1140 ****************************************************************************/
1141 int reply_mknew(char *inbuf,char *outbuf)
1151 com = SVAL(inbuf,smb_com);
1152 cnum = SVAL(inbuf,smb_tid);
1154 createmode = SVAL(inbuf,smb_vwv0);
1155 strcpy(fname,smb_buf(inbuf)+1);
1156 unix_convert(fname,cnum,0);
1158 if (createmode & aVOLID)
1160 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1163 unixmode = unix_mode(cnum,createmode);
1165 fnum = find_free_file();
1167 return(ERROR(ERRSRV,ERRnofids));
1169 if (!check_name(fname,cnum))
1170 return(UNIXERROR(ERRDOS,ERRnoaccess));
1174 /* We should fail if file exists. */
1179 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1183 /* Open file in dos compatibility share mode. */
1184 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL);
1186 if (!Files[fnum].open)
1187 return(UNIXERROR(ERRDOS,ERRnoaccess));
1189 outsize = set_message(outbuf,1,0,True);
1190 SSVAL(outbuf,smb_vwv0,fnum);
1192 if (lp_fake_oplocks(SNUM(cnum))) {
1193 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1196 DEBUG(2,("new file %s\n",fname));
1197 DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
1203 /****************************************************************************
1204 reply to a create temporary file
1205 ****************************************************************************/
1206 int reply_ctemp(char *inbuf,char *outbuf)
1216 cnum = SVAL(inbuf,smb_tid);
1217 createmode = SVAL(inbuf,smb_vwv0);
1218 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1219 unix_convert(fname,cnum,0);
1221 unixmode = unix_mode(cnum,createmode);
1223 fnum = find_free_file();
1225 return(ERROR(ERRSRV,ERRnofids));
1227 if (!check_name(fname,cnum))
1228 return(UNIXERROR(ERRDOS,ERRnoaccess));
1230 strcpy(fname2,(char *)mktemp(fname));
1232 /* Open file in dos compatibility share mode. */
1233 /* We should fail if file exists. */
1234 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL);
1236 if (!Files[fnum].open)
1237 return(UNIXERROR(ERRDOS,ERRnoaccess));
1239 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1240 SSVAL(outbuf,smb_vwv0,fnum);
1241 CVAL(smb_buf(outbuf),0) = 4;
1242 strcpy(smb_buf(outbuf) + 1,fname2);
1244 if (lp_fake_oplocks(SNUM(cnum))) {
1245 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1248 DEBUG(2,("created temp file %s\n",fname2));
1249 DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
1255 /*******************************************************************
1256 check if a user is allowed to delete a file
1257 ********************************************************************/
1258 static BOOL can_delete(char *fname,int cnum,int dirtype)
1263 if (!CAN_WRITE(cnum)) return(False);
1265 if (sys_lstat(fname,&sbuf) != 0) return(False);
1266 fmode = dos_mode(cnum,fname,&sbuf);
1267 if (fmode & aDIR) return(False);
1268 if (!lp_delete_readonly(SNUM(cnum))) {
1269 if (fmode & aRONLY) return(False);
1271 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1273 if (!check_file_sharing(cnum,fname)) return(False);
1277 /****************************************************************************
1279 ****************************************************************************/
1280 int reply_unlink(char *inbuf,char *outbuf)
1290 int error = ERRnoaccess;
1294 *directory = *mask = 0;
1296 cnum = SVAL(inbuf,smb_tid);
1297 dirtype = SVAL(inbuf,smb_vwv0);
1299 strcpy(name,smb_buf(inbuf) + 1);
1301 DEBUG(3,("reply_unlink : %s\n",name));
1303 unix_convert(name,cnum,0);
1305 p = strrchr(name,'/');
1307 strcpy(directory,"./");
1311 strcpy(directory,name);
1315 if (is_mangled(mask))
1316 check_mangled_stack(mask);
1318 has_wild = strchr(mask,'*') || strchr(mask,'?');
1321 strcat(directory,"/");
1322 strcat(directory,mask);
1323 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1324 if (!count) exists = file_exist(directory,NULL);
1326 void *dirptr = NULL;
1329 if (check_name(directory,cnum))
1330 dirptr = OpenDir(cnum, directory, True);
1332 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1333 the pattern matches against the long name, otherwise the short name
1334 We don't implement this yet XXXX
1341 if (strequal(mask,"????????.???"))
1344 while ((dname = ReadDirName(dirptr)))
1347 strcpy(fname,dname);
1349 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1351 error = ERRnoaccess;
1352 sprintf(fname,"%s/%s",directory,dname);
1353 if (!can_delete(fname,cnum,dirtype)) continue;
1354 if (!sys_unlink(fname)) count++;
1355 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1363 return(ERROR(ERRDOS,error));
1365 return(UNIXERROR(ERRDOS,error));
1368 outsize = set_message(outbuf,0,0,True);
1374 /****************************************************************************
1375 reply to a readbraw (core+ protocol)
1376 ****************************************************************************/
1377 int reply_readbraw(char *inbuf, char *outbuf)
1379 int cnum,maxcount,mincount,fnum;
1382 char *header = outbuf;
1387 cnum = SVAL(inbuf,smb_tid);
1388 fnum = GETFNUM(inbuf,smb_vwv0);
1390 startpos = IVAL(inbuf,smb_vwv1);
1391 maxcount = SVAL(inbuf,smb_vwv3);
1392 mincount = SVAL(inbuf,smb_vwv4);
1394 /* ensure we don't overrun the packet size */
1395 maxcount = MIN(65535,maxcount);
1396 maxcount = MAX(mincount,maxcount);
1398 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1400 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1401 _smb_setlen(header,0);
1402 transfer_file(0,Client,0,header,4,0);
1407 fd = Files[fnum].fd_ptr->fd;
1408 fname = Files[fnum].name;
1412 if (!is_locked(fnum,cnum,maxcount,startpos))
1414 int size = Files[fnum].size;
1415 int sizeneeded = startpos + maxcount;
1417 if (size < sizeneeded) {
1419 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1421 if (!Files[fnum].can_write)
1422 Files[fnum].size = size;
1425 nread = MIN(maxcount,(int)(size - startpos));
1428 if (nread < mincount)
1431 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1434 maxcount,mincount,nread));
1439 _smb_setlen(header,nread);
1441 if (!Files[fnum].can_write)
1442 predict = read_predict(fd,startpos,header+4,NULL,nread);
1444 if ((nread-predict) > 0)
1445 seek_file(fnum,startpos + predict);
1447 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1452 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1453 fname,startpos,nread,ret));
1456 ret = read_file(fnum,header+4,startpos,nread);
1457 if (ret < mincount) ret = 0;
1459 _smb_setlen(header,ret);
1460 transfer_file(0,Client,0,header,4+ret,0);
1463 DEBUG(5,("readbraw finished\n"));
1468 /****************************************************************************
1469 reply to a lockread (core+ protocol)
1470 ****************************************************************************/
1471 int reply_lockread(char *inbuf,char *outbuf)
1477 uint32 startpos, numtoread;
1481 cnum = SVAL(inbuf,smb_tid);
1482 fnum = GETFNUM(inbuf,smb_vwv0);
1484 CHECK_FNUM(fnum,cnum);
1488 numtoread = SVAL(inbuf,smb_vwv1);
1489 startpos = IVAL(inbuf,smb_vwv2);
1491 outsize = set_message(outbuf,5,3,True);
1492 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1493 data = smb_buf(outbuf) + 3;
1495 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1496 return (ERROR(eclass,ecode));
1498 nread = read_file(fnum,data,startpos,numtoread);
1501 return(UNIXERROR(ERRDOS,ERRnoaccess));
1504 SSVAL(outbuf,smb_vwv0,nread);
1505 SSVAL(outbuf,smb_vwv5,nread+3);
1506 SSVAL(smb_buf(outbuf),1,nread);
1508 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1514 /****************************************************************************
1516 ****************************************************************************/
1517 int reply_read(char *inbuf,char *outbuf)
1519 int cnum,numtoread,fnum;
1525 cnum = SVAL(inbuf,smb_tid);
1526 fnum = GETFNUM(inbuf,smb_vwv0);
1528 CHECK_FNUM(fnum,cnum);
1532 numtoread = SVAL(inbuf,smb_vwv1);
1533 startpos = IVAL(inbuf,smb_vwv2);
1535 outsize = set_message(outbuf,5,3,True);
1536 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1537 data = smb_buf(outbuf) + 3;
1539 if (is_locked(fnum,cnum,numtoread,startpos))
1540 return(ERROR(ERRDOS,ERRlock));
1543 nread = read_file(fnum,data,startpos,numtoread);
1546 return(UNIXERROR(ERRDOS,ERRnoaccess));
1549 SSVAL(outbuf,smb_vwv0,nread);
1550 SSVAL(outbuf,smb_vwv5,nread+3);
1551 CVAL(smb_buf(outbuf),0) = 1;
1552 SSVAL(smb_buf(outbuf),1,nread);
1554 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1560 /****************************************************************************
1561 reply to a read and X
1562 ****************************************************************************/
1563 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1565 int fnum = GETFNUM(inbuf,smb_vwv2);
1566 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1567 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1568 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1574 cnum = SVAL(inbuf,smb_tid);
1576 CHECK_FNUM(fnum,cnum);
1580 set_message(outbuf,12,0,True);
1581 data = smb_buf(outbuf);
1583 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1584 return(ERROR(ERRDOS,ERRlock));
1585 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1589 return(UNIXERROR(ERRDOS,ERRnoaccess));
1591 SSVAL(outbuf,smb_vwv5,nread);
1592 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1593 SSVAL(smb_buf(outbuf),-2,nread);
1595 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1596 timestring(),fnum,cnum,
1597 smb_mincnt,smb_maxcnt,nread));
1601 return chain_reply(inbuf,outbuf,length,bufsize);
1605 /****************************************************************************
1606 reply to a writebraw (core+ or LANMAN1.0 protocol)
1607 ****************************************************************************/
1608 int reply_writebraw(char *inbuf,char *outbuf)
1611 int total_written=0;
1620 cnum = SVAL(inbuf,smb_tid);
1621 fnum = GETFNUM(inbuf,smb_vwv0);
1623 CHECK_FNUM(fnum,cnum);
1627 tcount = IVAL(inbuf,smb_vwv1);
1628 startpos = IVAL(inbuf,smb_vwv3);
1629 write_through = BITSETW(inbuf+smb_vwv7,0);
1631 /* We have to deal with slightly different formats depending
1632 on whether we are using the core+ or lanman1.0 protocol */
1633 if(Protocol <= PROTOCOL_COREPLUS) {
1634 numtowrite = SVAL(smb_buf(inbuf),-2);
1635 data = smb_buf(inbuf);
1637 numtowrite = SVAL(inbuf,smb_vwv10);
1638 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1641 /* force the error type */
1642 CVAL(inbuf,smb_com) = SMBwritec;
1643 CVAL(outbuf,smb_com) = SMBwritec;
1645 if (is_locked(fnum,cnum,tcount,startpos))
1646 return(ERROR(ERRDOS,ERRlock));
1648 if (seek_file(fnum,startpos) != startpos)
1649 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1652 nwritten = write_file(fnum,data,numtowrite);
1654 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1655 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1657 if (nwritten < numtowrite)
1658 return(UNIXERROR(ERRHRD,ERRdiskfull));
1660 total_written = nwritten;
1662 /* Return a message to the redirector to tell it
1663 to send more bytes */
1664 CVAL(outbuf,smb_com) = SMBwritebraw;
1665 SSVALS(outbuf,smb_vwv0,-1);
1666 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1667 send_smb(Client,outbuf);
1669 /* Now read the raw data into the buffer and write it */
1670 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1671 exit_server("secondary writebraw failed");
1674 /* Even though this is not an smb message, smb_len
1675 returns the generic length of an smb message */
1676 numtowrite = smb_len(inbuf);
1678 if (tcount > nwritten+numtowrite) {
1679 DEBUG(3,("Client overestimated the write %d %d %d\n",
1680 tcount,nwritten,numtowrite));
1683 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1685 total_written += nwritten;
1687 /* Set up outbuf to return the correct return */
1688 outsize = set_message(outbuf,1,0,True);
1689 CVAL(outbuf,smb_com) = SMBwritec;
1690 SSVAL(outbuf,smb_vwv0,total_written);
1692 if (nwritten < numtowrite) {
1693 CVAL(outbuf,smb_rcls) = ERRHRD;
1694 SSVAL(outbuf,smb_err,ERRdiskfull);
1697 if (lp_syncalways(SNUM(cnum)) || write_through)
1700 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1701 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1703 /* we won't return a status if write through is not selected - this
1704 follows what WfWg does */
1705 if (!write_through && total_written==tcount)
1712 /****************************************************************************
1713 reply to a writeunlock (core+)
1714 ****************************************************************************/
1715 int reply_writeunlock(char *inbuf,char *outbuf)
1721 uint32 numtowrite,startpos;
1725 cnum = SVAL(inbuf,smb_tid);
1726 fnum = GETFNUM(inbuf,smb_vwv0);
1728 CHECK_FNUM(fnum,cnum);
1732 numtowrite = SVAL(inbuf,smb_vwv1);
1733 startpos = IVAL(inbuf,smb_vwv2);
1734 data = smb_buf(inbuf) + 3;
1736 if (is_locked(fnum,cnum,numtowrite,startpos))
1737 return(ERROR(ERRDOS,ERRlock));
1739 seek_file(fnum,startpos);
1741 /* The special X/Open SMB protocol handling of
1742 zero length writes is *NOT* done for
1747 nwritten = write_file(fnum,data,numtowrite);
1749 if (lp_syncalways(SNUM(cnum)))
1752 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1753 return(UNIXERROR(ERRDOS,ERRnoaccess));
1755 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1756 return(ERROR(eclass,ecode));
1758 outsize = set_message(outbuf,1,0,True);
1760 SSVAL(outbuf,smb_vwv0,nwritten);
1762 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1763 timestring(),fnum,cnum,numtowrite,nwritten));
1769 /****************************************************************************
1771 ****************************************************************************/
1772 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1774 int cnum,numtowrite,fnum;
1783 cnum = SVAL(inbuf,smb_tid);
1784 fnum = GETFNUM(inbuf,smb_vwv0);
1786 CHECK_FNUM(fnum,cnum);
1790 numtowrite = SVAL(inbuf,smb_vwv1);
1791 startpos = IVAL(inbuf,smb_vwv2);
1792 data = smb_buf(inbuf) + 3;
1794 if (is_locked(fnum,cnum,numtowrite,startpos))
1795 return(ERROR(ERRDOS,ERRlock));
1797 seek_file(fnum,startpos);
1799 /* X/Open SMB protocol says that if smb_vwv1 is
1800 zero then the file size should be extended or
1801 truncated to the size given in smb_vwv[2-3] */
1803 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
1805 nwritten = write_file(fnum,data,numtowrite);
1807 if (lp_syncalways(SNUM(cnum)))
1810 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1811 return(UNIXERROR(ERRDOS,ERRnoaccess));
1813 outsize = set_message(outbuf,1,0,True);
1815 SSVAL(outbuf,smb_vwv0,nwritten);
1817 if (nwritten < numtowrite) {
1818 CVAL(outbuf,smb_rcls) = ERRHRD;
1819 SSVAL(outbuf,smb_err,ERRdiskfull);
1822 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1828 /****************************************************************************
1829 reply to a write and X
1830 ****************************************************************************/
1831 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1833 int fnum = GETFNUM(inbuf,smb_vwv2);
1834 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1835 int smb_dsize = SVAL(inbuf,smb_vwv10);
1836 int smb_doff = SVAL(inbuf,smb_vwv11);
1837 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1842 cnum = SVAL(inbuf,smb_tid);
1844 CHECK_FNUM(fnum,cnum);
1848 data = smb_base(inbuf) + smb_doff;
1850 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1851 return(ERROR(ERRDOS,ERRlock));
1853 seek_file(fnum,smb_offs);
1855 /* X/Open SMB protocol says that, unlike SMBwrite
1856 if the length is zero then NO truncation is
1857 done, just a write of zero. To truncate a file,
1862 nwritten = write_file(fnum,data,smb_dsize);
1864 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1865 return(UNIXERROR(ERRDOS,ERRnoaccess));
1867 set_message(outbuf,6,0,True);
1869 SSVAL(outbuf,smb_vwv2,nwritten);
1871 if (nwritten < smb_dsize) {
1872 CVAL(outbuf,smb_rcls) = ERRHRD;
1873 SSVAL(outbuf,smb_err,ERRdiskfull);
1876 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1880 if (lp_syncalways(SNUM(cnum)) || write_through)
1883 return chain_reply(inbuf,outbuf,length,bufsize);
1887 /****************************************************************************
1889 ****************************************************************************/
1890 int reply_lseek(char *inbuf,char *outbuf)
1898 cnum = SVAL(inbuf,smb_tid);
1899 fnum = GETFNUM(inbuf,smb_vwv0);
1901 CHECK_FNUM(fnum,cnum);
1904 mode = SVAL(inbuf,smb_vwv1) & 3;
1905 startpos = IVAL(inbuf,smb_vwv2);
1909 case 0: umode = SEEK_SET; break;
1910 case 1: umode = SEEK_CUR; break;
1911 case 2: umode = SEEK_END; break;
1913 umode = SEEK_SET; break;
1916 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
1917 Files[fnum].pos = res;
1919 outsize = set_message(outbuf,2,0,True);
1920 SIVALS(outbuf,smb_vwv0,res);
1922 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1928 /****************************************************************************
1930 ****************************************************************************/
1931 int reply_flush(char *inbuf,char *outbuf)
1934 int outsize = set_message(outbuf,0,0,True);
1936 cnum = SVAL(inbuf,smb_tid);
1937 fnum = GETFNUM(inbuf,smb_vwv0);
1939 if (fnum != 0xFFFF) {
1940 CHECK_FNUM(fnum,cnum);
1947 for (i=0;i<MAX_OPEN_FILES;i++)
1954 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1959 /****************************************************************************
1961 ****************************************************************************/
1962 int reply_exit(char *inbuf,char *outbuf)
1964 int outsize = set_message(outbuf,0,0,True);
1965 DEBUG(3,("%s exit\n",timestring()));
1971 /****************************************************************************
1973 ****************************************************************************/
1974 int reply_close(char *inbuf,char *outbuf)
1979 int32 eclass = 0, err = 0;
1981 outsize = set_message(outbuf,0,0,True);
1983 cnum = SVAL(inbuf,smb_tid);
1985 fnum = GETFNUM(inbuf,smb_vwv0);
1986 CHECK_FNUM(fnum,cnum);
1988 if(HAS_CACHED_ERROR(fnum)) {
1989 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1990 err = Files[fnum].wbmpx_ptr->wr_error;
1993 mtime = make_unix_date3(inbuf+smb_vwv1);
1995 /* try and set the date */
1996 set_filetime(Files[fnum].name,mtime);
2000 /* We have a cached error */
2002 return(ERROR(eclass,err));
2004 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2005 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2006 Connections[cnum].num_files_open));
2012 /****************************************************************************
2013 reply to a writeclose (Core+ protocol)
2014 ****************************************************************************/
2015 int reply_writeclose(char *inbuf,char *outbuf)
2017 int cnum,numtowrite,fnum;
2024 cnum = SVAL(inbuf,smb_tid);
2025 fnum = GETFNUM(inbuf,smb_vwv0);
2027 CHECK_FNUM(fnum,cnum);
2031 numtowrite = SVAL(inbuf,smb_vwv1);
2032 startpos = IVAL(inbuf,smb_vwv2);
2033 mtime = make_unix_date3(inbuf+smb_vwv4);
2034 data = smb_buf(inbuf) + 1;
2036 if (is_locked(fnum,cnum,numtowrite,startpos))
2037 return(ERROR(ERRDOS,ERRlock));
2039 seek_file(fnum,startpos);
2041 nwritten = write_file(fnum,data,numtowrite);
2043 set_filetime(Files[fnum].name,mtime);
2047 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2048 timestring(),fnum,cnum,numtowrite,nwritten,
2049 Connections[cnum].num_files_open));
2052 return(UNIXERROR(ERRDOS,ERRnoaccess));
2054 outsize = set_message(outbuf,1,0,True);
2056 SSVAL(outbuf,smb_vwv0,nwritten);
2061 /****************************************************************************
2063 ****************************************************************************/
2064 int reply_lock(char *inbuf,char *outbuf)
2067 int outsize = set_message(outbuf,0,0,True);
2068 uint32 count,offset;
2072 cnum = SVAL(inbuf,smb_tid);
2073 fnum = GETFNUM(inbuf,smb_vwv0);
2075 CHECK_FNUM(fnum,cnum);
2078 count = IVAL(inbuf,smb_vwv1);
2079 offset = IVAL(inbuf,smb_vwv3);
2081 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count));
2083 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2084 return (ERROR(eclass,ecode));
2090 /****************************************************************************
2092 ****************************************************************************/
2093 int reply_unlock(char *inbuf,char *outbuf)
2096 int outsize = set_message(outbuf,0,0,True);
2097 uint32 count,offset;
2101 cnum = SVAL(inbuf,smb_tid);
2102 fnum = GETFNUM(inbuf,smb_vwv0);
2104 CHECK_FNUM(fnum,cnum);
2107 count = IVAL(inbuf,smb_vwv1);
2108 offset = IVAL(inbuf,smb_vwv3);
2110 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2111 return (ERROR(eclass,ecode));
2113 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count));
2119 /****************************************************************************
2121 ****************************************************************************/
2122 int reply_tdis(char *inbuf,char *outbuf)
2125 int outsize = set_message(outbuf,0,0,True);
2128 cnum = SVAL(inbuf,smb_tid);
2129 vuid = SVAL(inbuf,smb_uid);
2131 if (!OPEN_CNUM(cnum)) {
2132 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2133 return(ERROR(ERRSRV,ERRinvnid));
2136 Connections[cnum].used = False;
2138 close_cnum(cnum,vuid);
2140 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2147 /****************************************************************************
2149 ****************************************************************************/
2150 int reply_echo(char *inbuf,char *outbuf)
2153 int smb_reverb = SVAL(inbuf,smb_vwv0);
2155 int data_len = smb_buflen(inbuf);
2156 int outsize = set_message(outbuf,1,data_len,True);
2158 cnum = SVAL(inbuf,smb_tid);
2160 /* According to the latest CIFS spec we shouldn't
2161 care what the TID is.
2165 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2167 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2168 return(ERROR(ERRSRV,ERRinvnid));
2172 /* copy any incoming data back out */
2174 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2176 if (smb_reverb > 100)
2178 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2182 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2184 SSVAL(outbuf,smb_vwv0,seq_num);
2186 smb_setlen(outbuf,outsize - 4);
2188 send_smb(Client,outbuf);
2191 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2197 /****************************************************************************
2198 reply to a printopen
2199 ****************************************************************************/
2200 int reply_printopen(char *inbuf,char *outbuf)
2208 *fname = *fname2 = 0;
2210 cnum = SVAL(inbuf,smb_tid);
2212 if (!CAN_PRINT(cnum))
2213 return(ERROR(ERRDOS,ERRnoaccess));
2218 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2222 if (!(isalnum(*p) || strchr("._-",*p)))
2227 if (strlen(s) > 10) s[10] = 0;
2229 sprintf(fname,"%s.XXXXXX",s);
2232 fnum = find_free_file();
2234 return(ERROR(ERRSRV,ERRnofids));
2236 strcpy(fname2,(char *)mktemp(fname));
2238 if (!check_name(fname2,cnum))
2239 return(ERROR(ERRDOS,ERRnoaccess));
2241 /* Open for exclusive use, write only. */
2242 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL);
2244 if (!Files[fnum].open)
2245 return(UNIXERROR(ERRDOS,ERRnoaccess));
2247 /* force it to be a print file */
2248 Files[fnum].print_file = True;
2250 outsize = set_message(outbuf,1,0,True);
2251 SSVAL(outbuf,smb_vwv0,fnum);
2253 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2259 /****************************************************************************
2260 reply to a printclose
2261 ****************************************************************************/
2262 int reply_printclose(char *inbuf,char *outbuf)
2265 int outsize = set_message(outbuf,0,0,True);
2267 cnum = SVAL(inbuf,smb_tid);
2268 fnum = GETFNUM(inbuf,smb_vwv0);
2270 CHECK_FNUM(fnum,cnum);
2273 if (!CAN_PRINT(cnum))
2274 return(ERROR(ERRDOS,ERRnoaccess));
2278 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2284 /****************************************************************************
2285 reply to a printqueue
2286 ****************************************************************************/
2287 int reply_printqueue(char *inbuf,char *outbuf)
2290 int outsize = set_message(outbuf,2,3,True);
2291 int max_count = SVAL(inbuf,smb_vwv0);
2292 int start_index = SVAL(inbuf,smb_vwv1);
2295 cnum = SVAL(inbuf,smb_tid);
2296 vuid = SVAL(inbuf,smb_uid);
2298 /* allow checking the queue for anyone */
2300 if (!CAN_PRINT(cnum))
2301 return(ERROR(ERRDOS,ERRnoaccess));
2304 SSVAL(outbuf,smb_vwv0,0);
2305 SSVAL(outbuf,smb_vwv1,0);
2306 CVAL(smb_buf(outbuf),0) = 1;
2307 SSVAL(smb_buf(outbuf),1,0);
2309 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2310 timestring(),cnum,start_index,max_count));
2312 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2317 for (i=0;i<MAX_CONNECTIONS;i++)
2318 if (CAN_PRINT(i) && Connections[i].printer)
2322 for (i=0;i<MAX_CONNECTIONS;i++)
2326 if (!OPEN_CNUM(cnum))
2327 return(ERROR(ERRSRV,ERRinvnid));
2329 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2332 if (!become_user(cnum,vuid))
2333 return(ERROR(ERRSRV,ERRinvnid));
2336 print_queue_struct *queue = NULL;
2337 char *p = smb_buf(outbuf) + 3;
2338 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2339 int num_to_get = ABS(max_count);
2340 int first = (max_count>0?start_index:start_index+max_count+1);
2346 num_to_get = MIN(num_to_get,count-first);
2349 for (i=first;i<first+num_to_get;i++)
2351 put_dos_date2(p,0,queue[i].time);
2352 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2353 SSVAL(p,5,queue[i].job);
2354 SIVAL(p,7,queue[i].size);
2356 StrnCpy(p+12,queue[i].user,16);
2362 outsize = set_message(outbuf,2,28*count+3,False);
2363 SSVAL(outbuf,smb_vwv0,count);
2364 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2365 CVAL(smb_buf(outbuf),0) = 1;
2366 SSVAL(smb_buf(outbuf),1,28*count);
2369 if (queue) free(queue);
2371 DEBUG(3,("%d entries returned in queue\n",count));
2378 /****************************************************************************
2379 reply to a printwrite
2380 ****************************************************************************/
2381 int reply_printwrite(char *inbuf,char *outbuf)
2383 int cnum,numtowrite,fnum;
2384 int outsize = set_message(outbuf,0,0,True);
2387 cnum = SVAL(inbuf,smb_tid);
2389 if (!CAN_PRINT(cnum))
2390 return(ERROR(ERRDOS,ERRnoaccess));
2392 fnum = GETFNUM(inbuf,smb_vwv0);
2394 CHECK_FNUM(fnum,cnum);
2398 numtowrite = SVAL(smb_buf(inbuf),1);
2399 data = smb_buf(inbuf) + 3;
2401 if (write_file(fnum,data,numtowrite) != numtowrite)
2402 return(UNIXERROR(ERRDOS,ERRnoaccess));
2404 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2410 /****************************************************************************
2412 ****************************************************************************/
2413 int reply_mkdir(char *inbuf,char *outbuf)
2417 int outsize,ret= -1;
2419 strcpy(directory,smb_buf(inbuf) + 1);
2420 cnum = SVAL(inbuf,smb_tid);
2421 unix_convert(directory,cnum,0);
2423 if (check_name(directory,cnum))
2424 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2427 return(UNIXERROR(ERRDOS,ERRnoaccess));
2429 outsize = set_message(outbuf,0,0,True);
2431 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2437 /****************************************************************************
2439 ****************************************************************************/
2440 int reply_rmdir(char *inbuf,char *outbuf)
2447 cnum = SVAL(inbuf,smb_tid);
2448 strcpy(directory,smb_buf(inbuf) + 1);
2449 unix_convert(directory,cnum,0);
2451 if (check_name(directory,cnum))
2454 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2455 ok = (sys_rmdir(directory) == 0);
2456 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2458 /* Check to see if the only thing in this directory are
2459 vetoed files/directories. If so then delete them and
2460 retry. If we fail to delete any of them (and we *don't*
2461 do a recursive delete) then fail the rmdir. */
2462 BOOL all_veto_files = True;
2464 void *dirptr = OpenDir(cnum, directory, False);
2468 int dirpos = TellDir(dirptr);
2469 while ((dname = ReadDirName(dirptr)))
2471 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2473 if(!IS_VETO_PATH(cnum, dname))
2475 all_veto_files = False;
2481 SeekDir(dirptr,dirpos);
2482 while ((dname = ReadDirName(dirptr)))
2487 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2490 /* Construct the full name. */
2491 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2496 strcpy(fullname, directory);
2497 strcat(fullname, "/");
2498 strcat(fullname, dname);
2500 if(sys_lstat(fullname, &st) != 0)
2502 if(st.st_mode & S_IFDIR)
2504 if(sys_rmdir(fullname) != 0)
2507 else if(sys_unlink(fullname) != 0)
2511 /* Retry the rmdir */
2512 ok = (sys_rmdir(directory) == 0);
2522 DEBUG(3,("couldn't remove directory %s : %s\n",
2523 directory,strerror(errno)));
2527 return(UNIXERROR(ERRDOS,ERRbadpath));
2529 outsize = set_message(outbuf,0,0,True);
2531 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2537 /*******************************************************************
2538 resolve wildcards in a filename rename
2539 ********************************************************************/
2540 static BOOL resolve_wildcards(char *name1,char *name2)
2542 fstring root1,root2;
2546 name1 = strrchr(name1,'/');
2547 name2 = strrchr(name2,'/');
2549 if (!name1 || !name2) return(False);
2551 strcpy(root1,name1);
2552 strcpy(root2,name2);
2553 p = strrchr(root1,'.');
2560 p = strrchr(root2,'.');
2592 strcpy(name2,root2);
2601 /*******************************************************************
2602 check if a user is allowed to rename a file
2603 ********************************************************************/
2604 static BOOL can_rename(char *fname,int cnum)
2608 if (!CAN_WRITE(cnum)) return(False);
2610 if (sys_lstat(fname,&sbuf) != 0) return(False);
2611 if (!check_file_sharing(cnum,fname)) return(False);
2616 /****************************************************************************
2618 ****************************************************************************/
2619 int reply_mv(char *inbuf,char *outbuf)
2625 pstring mask,newname;
2626 pstring newname_last_component;
2629 int error = ERRnoaccess;
2633 *directory = *mask = 0;
2635 cnum = SVAL(inbuf,smb_tid);
2637 strcpy(name,smb_buf(inbuf) + 1);
2638 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2640 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2642 unix_convert(name,cnum,0);
2643 unix_convert(newname,cnum,newname_last_component);
2646 * Split the old name into directory and last component
2647 * strings. Note that unix_convert may have stripped off a
2648 * leading ./ from both name and newname if the rename is
2649 * at the root of the share. We need to make sure either both
2650 * name and newname contain a / character or neither of them do
2651 * as this is checked in resolve_wildcards().
2654 p = strrchr(name,'/');
2656 strcpy(directory,".");
2660 strcpy(directory,name);
2662 *p = '/'; /* Replace needed for exceptional test below. */
2665 if (is_mangled(mask))
2666 check_mangled_stack(mask);
2668 has_wild = strchr(mask,'*') || strchr(mask,'?');
2671 BOOL is_short_name = is_8_3(name, True);
2673 /* Add a terminating '/' to the directory name. */
2674 strcat(directory,"/");
2675 strcat(directory,mask);
2677 /* Ensure newname contains a '/' also */
2678 if(strrchr(newname,'/') == 0) {
2681 strcpy(tmpstr, "./");
2682 strcat(tmpstr, newname);
2683 strcpy(newname, tmpstr);
2686 DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
2687 case_sensitive, case_preserve, short_case_preserve, directory,
2688 newname, newname_last_component, is_short_name));
2691 * Check for special case with case preserving and not
2692 * case sensitive, if directory and newname are identical,
2693 * and the old last component differs from the original
2694 * last component only by case, then we should allow
2695 * the rename (user is trying to change the case of the
2698 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
2699 ((short_case_preserve == True) && (is_short_name == True))) &&
2700 strcsequal(directory, newname)) {
2701 pstring newname_modified_last_component;
2704 * Get the last component of the modified name.
2705 * Note that we guarantee that newname contains a '/'
2708 p = strrchr(newname,'/');
2709 strcpy(newname_modified_last_component,p+1);
2711 if(strcsequal(newname_modified_last_component,
2712 newname_last_component) == False) {
2714 * Replace the modified last component with
2717 strcpy(p+1, newname_last_component);
2721 if (resolve_wildcards(directory,newname) &&
2722 can_rename(directory,cnum) &&
2723 !file_exist(newname,NULL) &&
2724 !sys_rename(directory,newname)) count++;
2726 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
2727 directory,newname));
2729 if (!count) exists = file_exist(directory,NULL);
2730 if (!count && exists && file_exist(newname,NULL)) {
2735 void *dirptr = NULL;
2739 if (check_name(directory,cnum))
2740 dirptr = OpenDir(cnum, directory, True);
2746 if (strequal(mask,"????????.???"))
2749 while ((dname = ReadDirName(dirptr)))
2752 strcpy(fname,dname);
2754 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2756 error = ERRnoaccess;
2757 sprintf(fname,"%s/%s",directory,dname);
2758 if (!can_rename(fname,cnum)) continue;
2759 strcpy(destname,newname);
2761 if (!resolve_wildcards(fname,destname)) continue;
2763 if (file_exist(destname,NULL)) {
2767 if (!sys_rename(fname,destname)) count++;
2768 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2776 return(ERROR(ERRDOS,error));
2778 return(UNIXERROR(ERRDOS,error));
2781 outsize = set_message(outbuf,0,0,True);
2786 /*******************************************************************
2787 copy a file as part of a reply_copy
2788 ******************************************************************/
2789 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2790 int count,BOOL target_is_directory)
2799 if (target_is_directory) {
2800 char *p = strrchr(src,'/');
2809 if (!file_exist(src,&st)) return(False);
2811 fnum1 = find_free_file();
2812 if (fnum1<0) return(False);
2813 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2814 1,0,&Access,&action);
2816 if (!Files[fnum1].open) return(False);
2818 if (!target_is_directory && count)
2821 fnum2 = find_free_file();
2826 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2827 ofun,st.st_mode,&Access,&action);
2829 if (!Files[fnum2].open) {
2834 if ((ofun&3) == 1) {
2835 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
2839 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
2844 return(ret == st.st_size);
2849 /****************************************************************************
2850 reply to a file copy.
2851 ****************************************************************************/
2852 int reply_copy(char *inbuf,char *outbuf)
2858 pstring mask,newname;
2861 int error = ERRnoaccess;
2864 int tid2 = SVAL(inbuf,smb_vwv0);
2865 int ofun = SVAL(inbuf,smb_vwv1);
2866 int flags = SVAL(inbuf,smb_vwv2);
2867 BOOL target_is_directory=False;
2869 *directory = *mask = 0;
2871 cnum = SVAL(inbuf,smb_tid);
2873 strcpy(name,smb_buf(inbuf));
2874 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2876 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2879 /* can't currently handle inter share copies XXXX */
2880 DEBUG(3,("Rejecting inter-share copy\n"));
2881 return(ERROR(ERRSRV,ERRinvdevice));
2884 unix_convert(name,cnum,0);
2885 unix_convert(newname,cnum,0);
2887 target_is_directory = directory_exist(newname,NULL);
2889 if ((flags&1) && target_is_directory) {
2890 return(ERROR(ERRDOS,ERRbadfile));
2893 if ((flags&2) && !target_is_directory) {
2894 return(ERROR(ERRDOS,ERRbadpath));
2897 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2898 /* wants a tree copy! XXXX */
2899 DEBUG(3,("Rejecting tree copy\n"));
2900 return(ERROR(ERRSRV,ERRerror));
2903 p = strrchr(name,'/');
2905 strcpy(directory,"./");
2909 strcpy(directory,name);
2913 if (is_mangled(mask))
2914 check_mangled_stack(mask);
2916 has_wild = strchr(mask,'*') || strchr(mask,'?');
2919 strcat(directory,"/");
2920 strcat(directory,mask);
2921 if (resolve_wildcards(directory,newname) &&
2922 copy_file(directory,newname,cnum,ofun,
2923 count,target_is_directory)) count++;
2924 if (!count) exists = file_exist(directory,NULL);
2926 void *dirptr = NULL;
2930 if (check_name(directory,cnum))
2931 dirptr = OpenDir(cnum, directory, True);
2937 if (strequal(mask,"????????.???"))
2940 while ((dname = ReadDirName(dirptr)))
2943 strcpy(fname,dname);
2945 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2947 error = ERRnoaccess;
2948 sprintf(fname,"%s/%s",directory,dname);
2949 strcpy(destname,newname);
2950 if (resolve_wildcards(fname,destname) &&
2951 copy_file(directory,newname,cnum,ofun,
2952 count,target_is_directory)) count++;
2953 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2961 return(ERROR(ERRDOS,error));
2963 return(UNIXERROR(ERRDOS,error));
2966 outsize = set_message(outbuf,1,0,True);
2967 SSVAL(outbuf,smb_vwv0,count);
2974 /****************************************************************************
2976 ****************************************************************************/
2977 int reply_setdir(char *inbuf,char *outbuf)
2984 cnum = SVAL(inbuf,smb_tid);
2986 snum = Connections[cnum].service;
2987 if (!CAN_SETDIR(snum))
2988 return(ERROR(ERRDOS,ERRnoaccess));
2990 strcpy(newdir,smb_buf(inbuf) + 1);
2993 if (strlen(newdir) == 0)
2997 ok = directory_exist(newdir,NULL);
2999 string_set(&Connections[cnum].connectpath,newdir);
3003 return(ERROR(ERRDOS,ERRbadpath));
3005 outsize = set_message(outbuf,0,0,True);
3006 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3008 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3014 /****************************************************************************
3015 reply to a lockingX request
3016 ****************************************************************************/
3017 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3019 int fnum = GETFNUM(inbuf,smb_vwv2);
3020 uint16 locktype = SVAL(inbuf,smb_vwv3);
3021 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3022 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3023 uint32 count, offset;
3028 uint32 ecode=0, dummy2;
3029 int eclass=0, dummy1;
3031 cnum = SVAL(inbuf,smb_tid);
3033 CHECK_FNUM(fnum,cnum);
3036 data = smb_buf(inbuf);
3037 /* Data now points at the beginning of the list
3038 of smb_unlkrng structs */
3039 for(i = 0; i < (int)num_ulocks; i++) {
3040 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3041 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3042 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3043 return ERROR(eclass,ecode);
3046 /* Now do any requested locks */
3047 data += 10*num_ulocks;
3048 /* Data now points at the beginning of the list
3049 of smb_lkrng structs */
3050 for(i = 0; i < (int)num_locks; i++) {
3051 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3052 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3053 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3057 /* If any of the above locks failed, then we must unlock
3058 all of the previous locks (X/Open spec). */
3059 if(i != num_locks && num_locks != 0) {
3060 for(; i >= 0; i--) {
3061 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3062 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3063 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3065 return ERROR(eclass,ecode);
3068 set_message(outbuf,2,0,True);
3070 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3071 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
3075 return chain_reply(inbuf,outbuf,length,bufsize);
3079 /****************************************************************************
3080 reply to a SMBreadbmpx (read block multiplex) request
3081 ****************************************************************************/
3082 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3089 int outsize, mincount, maxcount;
3094 /* this function doesn't seem to work - disable by default */
3096 return(ERROR(ERRSRV,ERRuseSTD));
3098 outsize = set_message(outbuf,8,0,True);
3100 cnum = SVAL(inbuf,smb_tid);
3101 fnum = GETFNUM(inbuf,smb_vwv0);
3103 CHECK_FNUM(fnum,cnum);
3107 startpos = IVAL(inbuf,smb_vwv1);
3108 maxcount = SVAL(inbuf,smb_vwv3);
3109 mincount = SVAL(inbuf,smb_vwv4);
3111 data = smb_buf(outbuf);
3112 pad = ((long)data)%4;
3113 if (pad) pad = 4 - pad;
3116 max_per_packet = bufsize-(outsize+pad);
3120 if (is_locked(fnum,cnum,maxcount,startpos))
3121 return(ERROR(ERRDOS,ERRlock));
3125 int N = MIN(max_per_packet,tcount-total_read);
3127 nread = read_file(fnum,data,startpos,N);
3129 if (nread <= 0) nread = 0;
3132 tcount = total_read + nread;
3134 set_message(outbuf,8,nread,False);
3135 SIVAL(outbuf,smb_vwv0,startpos);
3136 SSVAL(outbuf,smb_vwv2,tcount);
3137 SSVAL(outbuf,smb_vwv6,nread);
3138 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3140 send_smb(Client,outbuf);
3142 total_read += nread;
3145 while (total_read < tcount);
3151 /****************************************************************************
3152 reply to a SMBwritebmpx (write block multiplex primary) request
3153 ****************************************************************************/
3154 int reply_writebmpx(char *inbuf,char *outbuf)
3156 int cnum,numtowrite,fnum;
3160 int tcount, write_through, smb_doff;
3163 cnum = SVAL(inbuf,smb_tid);
3164 fnum = GETFNUM(inbuf,smb_vwv0);
3166 CHECK_FNUM(fnum,cnum);
3170 tcount = SVAL(inbuf,smb_vwv1);
3171 startpos = IVAL(inbuf,smb_vwv3);
3172 write_through = BITSETW(inbuf+smb_vwv7,0);
3173 numtowrite = SVAL(inbuf,smb_vwv10);
3174 smb_doff = SVAL(inbuf,smb_vwv11);
3176 data = smb_base(inbuf) + smb_doff;
3178 /* If this fails we need to send an SMBwriteC response,
3179 not an SMBwritebmpx - set this up now so we don't forget */
3180 CVAL(outbuf,smb_com) = SMBwritec;
3182 if (is_locked(fnum,cnum,tcount,startpos))
3183 return(ERROR(ERRDOS,ERRlock));
3185 seek_file(fnum,startpos);
3186 nwritten = write_file(fnum,data,numtowrite);
3188 if(lp_syncalways(SNUM(cnum)) || write_through)
3191 if(nwritten < numtowrite)
3192 return(UNIXERROR(ERRHRD,ERRdiskfull));
3194 /* If the maximum to be written to this file
3195 is greater than what we just wrote then set
3196 up a secondary struct to be attached to this
3197 fd, we will use this to cache error messages etc. */
3198 if(tcount > nwritten)
3200 write_bmpx_struct *wbms;
3201 if(Files[fnum].wbmpx_ptr != NULL)
3202 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3204 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3207 DEBUG(0,("Out of memory in reply_readmpx\n"));
3208 return(ERROR(ERRSRV,ERRnoresource));
3210 wbms->wr_mode = write_through;
3211 wbms->wr_discard = False; /* No errors yet */
3212 wbms->wr_total_written = nwritten;
3213 wbms->wr_errclass = 0;
3215 Files[fnum].wbmpx_ptr = wbms;
3218 /* We are returning successfully, set the message type back to
3220 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3222 outsize = set_message(outbuf,1,0,True);
3224 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3226 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3227 timestring(),fnum,cnum,numtowrite,nwritten));
3229 if (write_through && tcount==nwritten) {
3230 /* we need to send both a primary and a secondary response */
3231 smb_setlen(outbuf,outsize - 4);
3232 send_smb(Client,outbuf);
3234 /* now the secondary */
3235 outsize = set_message(outbuf,1,0,True);
3236 CVAL(outbuf,smb_com) = SMBwritec;
3237 SSVAL(outbuf,smb_vwv0,nwritten);
3244 /****************************************************************************
3245 reply to a SMBwritebs (write block multiplex secondary) request
3246 ****************************************************************************/
3247 int reply_writebs(char *inbuf,char *outbuf)
3249 int cnum,numtowrite,fnum;
3253 int tcount, write_through, smb_doff;
3255 write_bmpx_struct *wbms;
3256 BOOL send_response = False;
3258 cnum = SVAL(inbuf,smb_tid);
3259 fnum = GETFNUM(inbuf,smb_vwv0);
3260 CHECK_FNUM(fnum,cnum);
3263 tcount = SVAL(inbuf,smb_vwv1);
3264 startpos = IVAL(inbuf,smb_vwv2);
3265 numtowrite = SVAL(inbuf,smb_vwv6);
3266 smb_doff = SVAL(inbuf,smb_vwv7);
3268 data = smb_base(inbuf) + smb_doff;
3270 /* We need to send an SMBwriteC response, not an SMBwritebs */
3271 CVAL(outbuf,smb_com) = SMBwritec;
3273 /* This fd should have an auxiliary struct attached,
3274 check that it does */
3275 wbms = Files[fnum].wbmpx_ptr;
3276 if(!wbms) return(-1);
3278 /* If write through is set we can return errors, else we must
3280 write_through = wbms->wr_mode;
3282 /* Check for an earlier error */
3283 if(wbms->wr_discard)
3284 return -1; /* Just discard the packet */
3286 seek_file(fnum,startpos);
3287 nwritten = write_file(fnum,data,numtowrite);
3289 if(lp_syncalways(SNUM(cnum)) || write_through)
3292 if (nwritten < numtowrite)
3295 /* We are returning an error - we can delete the aux struct */
3296 if (wbms) free((char *)wbms);
3297 Files[fnum].wbmpx_ptr = NULL;
3298 return(ERROR(ERRHRD,ERRdiskfull));
3300 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3303 /* Increment the total written, if this matches tcount
3304 we can discard the auxiliary struct (hurrah !) and return a writeC */
3305 wbms->wr_total_written += nwritten;
3306 if(wbms->wr_total_written >= tcount)
3308 if (write_through) {
3309 outsize = set_message(outbuf,1,0,True);
3310 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3311 send_response = True;
3315 Files[fnum].wbmpx_ptr = NULL;
3325 /****************************************************************************
3326 reply to a SMBsetattrE
3327 ****************************************************************************/
3328 int reply_setattrE(char *inbuf,char *outbuf)
3331 struct utimbuf unix_times;
3334 outsize = set_message(outbuf,0,0,True);
3336 cnum = SVAL(inbuf,smb_tid);
3337 fnum = GETFNUM(inbuf,smb_vwv0);
3339 CHECK_FNUM(fnum,cnum);
3342 /* Convert the DOS times into unix times. Ignore create
3343 time as UNIX can't set this.
3345 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3346 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3348 /* Set the date on this file */
3349 if(sys_utime(Files[fnum].name, &unix_times))
3350 return(ERROR(ERRDOS,ERRnoaccess));
3352 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3358 /****************************************************************************
3359 reply to a SMBgetattrE
3360 ****************************************************************************/
3361 int reply_getattrE(char *inbuf,char *outbuf)
3368 outsize = set_message(outbuf,11,0,True);
3370 cnum = SVAL(inbuf,smb_tid);
3371 fnum = GETFNUM(inbuf,smb_vwv0);
3373 CHECK_FNUM(fnum,cnum);
3376 /* Do an fstat on this file */
3377 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3378 return(UNIXERROR(ERRDOS,ERRnoaccess));
3380 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3382 /* Convert the times into dos times. Set create
3383 date to be last modify date as UNIX doesn't save
3385 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3386 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3387 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3390 SIVAL(outbuf,smb_vwv6,0);
3391 SIVAL(outbuf,smb_vwv8,0);
3395 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3396 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3398 SSVAL(outbuf,smb_vwv10, mode);
3400 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));