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(ERROR(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));
828 return(ERROR(ERRDOS,ERRnofids));
831 DEBUG(4,("dptr_num is %d\n",dptr_num));
835 if ((dirtype&0x1F) == aVOLID)
838 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
839 dptr_fill(p+12,dptr_num);
840 if (dptr_zero(p+12) && (status_len==0))
844 p += DIR_STRUCT_SIZE;
848 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
849 if (in_list(Connections[cnum].dirpath,
850 lp_dontdescend(SNUM(cnum)),True))
851 check_descend = True;
853 for (i=numentries;(i<maxentries) && !finished;i++)
856 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
860 make_dir_struct(p,mask,fname,size,mode,date);
861 dptr_fill(p+12,dptr_num);
864 p += DIR_STRUCT_SIZE;
873 if (numentries == 0 || !ok)
875 CVAL(outbuf,smb_rcls) = ERRDOS;
876 SSVAL(outbuf,smb_err,ERRnofiles);
879 /* If we were called as SMBffirst with smb_search_id == NULL
880 and no entries were found then return error and close dirptr
883 if(ok && expect_close && numentries == 0 && status_len == 0)
885 CVAL(outbuf,smb_rcls) = ERRDOS;
886 SSVAL(outbuf,smb_err,ERRnofiles);
887 /* Also close the dptr - we know it's gone */
888 dptr_close(dptr_num);
891 /* If we were called as SMBfunique, then we can close the dirptr now ! */
892 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
893 dptr_close(dptr_num);
895 SSVAL(outbuf,smb_vwv0,numentries);
896 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
897 CVAL(smb_buf(outbuf),0) = 5;
898 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
900 if (Protocol >= PROTOCOL_NT1) {
901 uint16 flg2 = SVAL(outbuf,smb_flg2);
902 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
905 outsize += DIR_STRUCT_SIZE*numentries;
906 smb_setlen(outbuf,outsize - 4);
908 if ((! *directory) && dptr_path(dptr_num))
909 sprintf(directory,"(%s)",dptr_path(dptr_num));
911 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
913 smb_fn_name(CVAL(inbuf,smb_com)),
914 mask,directory,cnum,dirtype,numentries,maxentries));
920 /****************************************************************************
921 reply to a fclose (stop directory search)
922 ****************************************************************************/
923 int reply_fclose(char *inbuf,char *outbuf)
932 cnum = SVAL(inbuf,smb_tid);
934 outsize = set_message(outbuf,1,0,True);
935 path = smb_buf(inbuf) + 1;
936 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
940 return(ERROR(ERRSRV,ERRsrverror));
942 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
944 if(dptr_fetch(status+12,&dptr_num)) {
945 /* Close the dptr - we know it's gone */
946 dptr_close(dptr_num);
949 SSVAL(outbuf,smb_vwv0,0);
951 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
957 /****************************************************************************
959 ****************************************************************************/
960 int reply_open(char *inbuf,char *outbuf)
974 cnum = SVAL(inbuf,smb_tid);
976 share_mode = SVAL(inbuf,smb_vwv0);
978 strcpy(fname,smb_buf(inbuf)+1);
979 unix_convert(fname,cnum,0);
981 fnum = find_free_file();
983 return(ERROR(ERRSRV,ERRnofids));
985 if (!check_name(fname,cnum))
986 return(UNIXERROR(ERRDOS,ERRnoaccess));
988 unixmode = unix_mode(cnum,aARCH);
990 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
992 if (!Files[fnum].open)
993 return(UNIXERROR(ERRDOS,ERRnoaccess));
995 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
997 return(ERROR(ERRDOS,ERRnoaccess));
1000 size = sbuf.st_size;
1001 fmode = dos_mode(cnum,fname,&sbuf);
1002 mtime = sbuf.st_mtime;
1005 DEBUG(3,("attempt to open a directory %s\n",fname));
1007 return(ERROR(ERRDOS,ERRnoaccess));
1010 outsize = set_message(outbuf,7,0,True);
1011 SSVAL(outbuf,smb_vwv0,fnum);
1012 SSVAL(outbuf,smb_vwv1,fmode);
1013 put_dos_date3(outbuf,smb_vwv2,mtime);
1014 SIVAL(outbuf,smb_vwv4,size);
1015 SSVAL(outbuf,smb_vwv6,rmode);
1017 if (lp_fake_oplocks(SNUM(cnum))) {
1018 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1025 /****************************************************************************
1026 reply to an open and X
1027 ****************************************************************************/
1028 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1031 int cnum = SVAL(inbuf,smb_tid);
1033 int smb_mode = SVAL(inbuf,smb_vwv3);
1034 int smb_attr = SVAL(inbuf,smb_vwv5);
1035 BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
1037 int open_flags = SVAL(inbuf,smb_vwv2);
1038 int smb_sattr = SVAL(inbuf,smb_vwv4);
1039 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1041 int smb_ofun = SVAL(inbuf,smb_vwv8);
1043 int size=0,fmode=0,mtime=0,rmode=0;
1047 /* If it's an IPC, pass off the pipe handler. */
1049 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1051 /* XXXX we need to handle passed times, sattr and flags */
1053 strcpy(fname,smb_buf(inbuf));
1054 unix_convert(fname,cnum,0);
1056 fnum = find_free_file();
1058 return(ERROR(ERRSRV,ERRnofids));
1060 if (!check_name(fname,cnum))
1061 return(UNIXERROR(ERRDOS,ERRnoaccess));
1063 unixmode = unix_mode(cnum,smb_attr | aARCH);
1065 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1066 &rmode,&smb_action);
1068 if (!Files[fnum].open)
1069 return(UNIXERROR(ERRDOS,ERRnoaccess));
1071 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1073 return(ERROR(ERRDOS,ERRnoaccess));
1076 size = sbuf.st_size;
1077 fmode = dos_mode(cnum,fname,&sbuf);
1078 mtime = sbuf.st_mtime;
1081 return(ERROR(ERRDOS,ERRnoaccess));
1084 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1085 smb_action |= (1<<15);
1088 set_message(outbuf,15,0,True);
1089 SSVAL(outbuf,smb_vwv2,fnum);
1090 SSVAL(outbuf,smb_vwv3,fmode);
1091 put_dos_date3(outbuf,smb_vwv4,mtime);
1092 SIVAL(outbuf,smb_vwv6,size);
1093 SSVAL(outbuf,smb_vwv8,rmode);
1094 SSVAL(outbuf,smb_vwv11,smb_action);
1098 return chain_reply(inbuf,outbuf,length,bufsize);
1102 /****************************************************************************
1103 reply to a SMBulogoffX
1104 ****************************************************************************/
1105 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1107 uint16 vuid = SVAL(inbuf,smb_uid);
1108 user_struct *vuser = get_valid_user_struct(vuid);
1111 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1114 /* in user level security we are supposed to close any files
1115 open by this user */
1116 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1118 for (i=0;i<MAX_OPEN_FILES;i++)
1119 if (Files[i].uid == vuser->uid && Files[i].open) {
1124 invalidate_vuid(vuid);
1126 set_message(outbuf,2,0,True);
1128 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1130 return chain_reply(inbuf,outbuf,length,bufsize);
1134 /****************************************************************************
1135 reply to a mknew or a create
1136 ****************************************************************************/
1137 int reply_mknew(char *inbuf,char *outbuf)
1147 com = SVAL(inbuf,smb_com);
1148 cnum = SVAL(inbuf,smb_tid);
1150 createmode = SVAL(inbuf,smb_vwv0);
1151 strcpy(fname,smb_buf(inbuf)+1);
1152 unix_convert(fname,cnum,0);
1154 if (createmode & aVOLID)
1156 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1159 unixmode = unix_mode(cnum,createmode);
1161 fnum = find_free_file();
1163 return(ERROR(ERRSRV,ERRnofids));
1165 if (!check_name(fname,cnum))
1166 return(UNIXERROR(ERRDOS,ERRnoaccess));
1170 /* We should fail if file exists. */
1175 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1179 /* Open file in dos compatibility share mode. */
1180 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL);
1182 if (!Files[fnum].open)
1183 return(UNIXERROR(ERRDOS,ERRnoaccess));
1185 outsize = set_message(outbuf,1,0,True);
1186 SSVAL(outbuf,smb_vwv0,fnum);
1188 if (lp_fake_oplocks(SNUM(cnum))) {
1189 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1192 DEBUG(2,("new file %s\n",fname));
1193 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));
1199 /****************************************************************************
1200 reply to a create temporary file
1201 ****************************************************************************/
1202 int reply_ctemp(char *inbuf,char *outbuf)
1212 cnum = SVAL(inbuf,smb_tid);
1213 createmode = SVAL(inbuf,smb_vwv0);
1214 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1215 unix_convert(fname,cnum,0);
1217 unixmode = unix_mode(cnum,createmode);
1219 fnum = find_free_file();
1221 return(ERROR(ERRSRV,ERRnofids));
1223 if (!check_name(fname,cnum))
1224 return(UNIXERROR(ERRDOS,ERRnoaccess));
1226 strcpy(fname2,(char *)mktemp(fname));
1228 /* Open file in dos compatibility share mode. */
1229 /* We should fail if file exists. */
1230 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL);
1232 if (!Files[fnum].open)
1233 return(UNIXERROR(ERRDOS,ERRnoaccess));
1235 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1236 SSVAL(outbuf,smb_vwv0,fnum);
1237 CVAL(smb_buf(outbuf),0) = 4;
1238 strcpy(smb_buf(outbuf) + 1,fname2);
1240 if (lp_fake_oplocks(SNUM(cnum))) {
1241 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1244 DEBUG(2,("created temp file %s\n",fname2));
1245 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));
1251 /*******************************************************************
1252 check if a user is allowed to delete a file
1253 ********************************************************************/
1254 static BOOL can_delete(char *fname,int cnum,int dirtype)
1259 if (!CAN_WRITE(cnum)) return(False);
1261 if (sys_lstat(fname,&sbuf) != 0) return(False);
1262 fmode = dos_mode(cnum,fname,&sbuf);
1263 if (fmode & aDIR) return(False);
1264 if (!lp_delete_readonly(SNUM(cnum))) {
1265 if (fmode & aRONLY) return(False);
1267 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1269 if (!check_file_sharing(cnum,fname)) return(False);
1273 /****************************************************************************
1275 ****************************************************************************/
1276 int reply_unlink(char *inbuf,char *outbuf)
1286 int error = ERRnoaccess;
1290 *directory = *mask = 0;
1292 cnum = SVAL(inbuf,smb_tid);
1293 dirtype = SVAL(inbuf,smb_vwv0);
1295 strcpy(name,smb_buf(inbuf) + 1);
1297 DEBUG(3,("reply_unlink : %s\n",name));
1299 unix_convert(name,cnum,0);
1301 p = strrchr(name,'/');
1303 strcpy(directory,"./");
1307 strcpy(directory,name);
1311 if (is_mangled(mask))
1312 check_mangled_stack(mask);
1314 has_wild = strchr(mask,'*') || strchr(mask,'?');
1317 strcat(directory,"/");
1318 strcat(directory,mask);
1319 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1320 if (!count) exists = file_exist(directory,NULL);
1322 void *dirptr = NULL;
1325 if (check_name(directory,cnum))
1326 dirptr = OpenDir(cnum, directory, True);
1328 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1329 the pattern matches against the long name, otherwise the short name
1330 We don't implement this yet XXXX
1337 if (strequal(mask,"????????.???"))
1340 while ((dname = ReadDirName(dirptr)))
1343 strcpy(fname,dname);
1345 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1347 error = ERRnoaccess;
1348 sprintf(fname,"%s/%s",directory,dname);
1349 if (!can_delete(fname,cnum,dirtype)) continue;
1350 if (!sys_unlink(fname)) count++;
1351 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1359 return(ERROR(ERRDOS,error));
1361 return(UNIXERROR(ERRDOS,error));
1364 outsize = set_message(outbuf,0,0,True);
1370 /****************************************************************************
1371 reply to a readbraw (core+ protocol)
1372 ****************************************************************************/
1373 int reply_readbraw(char *inbuf, char *outbuf)
1375 int cnum,maxcount,mincount,fnum;
1378 char *header = outbuf;
1383 cnum = SVAL(inbuf,smb_tid);
1384 fnum = GETFNUM(inbuf,smb_vwv0);
1386 startpos = IVAL(inbuf,smb_vwv1);
1387 maxcount = SVAL(inbuf,smb_vwv3);
1388 mincount = SVAL(inbuf,smb_vwv4);
1390 /* ensure we don't overrun the packet size */
1391 maxcount = MIN(65535,maxcount);
1392 maxcount = MAX(mincount,maxcount);
1394 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1396 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1397 _smb_setlen(header,0);
1398 transfer_file(0,Client,0,header,4,0);
1403 fd = Files[fnum].fd_ptr->fd;
1404 fname = Files[fnum].name;
1408 if (!is_locked(fnum,cnum,maxcount,startpos))
1410 int size = Files[fnum].size;
1411 int sizeneeded = startpos + maxcount;
1413 if (size < sizeneeded) {
1415 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1417 if (!Files[fnum].can_write)
1418 Files[fnum].size = size;
1421 nread = MIN(maxcount,(int)(size - startpos));
1424 if (nread < mincount)
1427 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1430 maxcount,mincount,nread));
1435 _smb_setlen(header,nread);
1437 if (!Files[fnum].can_write)
1438 predict = read_predict(fd,startpos,header+4,NULL,nread);
1440 if ((nread-predict) > 0)
1441 seek_file(fnum,startpos + predict);
1443 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1448 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1449 fname,startpos,nread,ret));
1452 ret = read_file(fnum,header+4,startpos,nread);
1453 if (ret < mincount) ret = 0;
1455 _smb_setlen(header,ret);
1456 transfer_file(0,Client,0,header,4+ret,0);
1459 DEBUG(5,("readbraw finished\n"));
1464 /****************************************************************************
1465 reply to a lockread (core+ protocol)
1466 ****************************************************************************/
1467 int reply_lockread(char *inbuf,char *outbuf)
1473 uint32 startpos, numtoread;
1477 cnum = SVAL(inbuf,smb_tid);
1478 fnum = GETFNUM(inbuf,smb_vwv0);
1480 CHECK_FNUM(fnum,cnum);
1484 numtoread = SVAL(inbuf,smb_vwv1);
1485 startpos = IVAL(inbuf,smb_vwv2);
1487 outsize = set_message(outbuf,5,3,True);
1488 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1489 data = smb_buf(outbuf) + 3;
1491 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1492 return (ERROR(eclass,ecode));
1494 nread = read_file(fnum,data,startpos,numtoread);
1497 return(UNIXERROR(ERRDOS,ERRnoaccess));
1500 SSVAL(outbuf,smb_vwv0,nread);
1501 SSVAL(outbuf,smb_vwv5,nread+3);
1502 SSVAL(smb_buf(outbuf),1,nread);
1504 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1510 /****************************************************************************
1512 ****************************************************************************/
1513 int reply_read(char *inbuf,char *outbuf)
1515 int cnum,numtoread,fnum;
1521 cnum = SVAL(inbuf,smb_tid);
1522 fnum = GETFNUM(inbuf,smb_vwv0);
1524 CHECK_FNUM(fnum,cnum);
1528 numtoread = SVAL(inbuf,smb_vwv1);
1529 startpos = IVAL(inbuf,smb_vwv2);
1531 outsize = set_message(outbuf,5,3,True);
1532 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1533 data = smb_buf(outbuf) + 3;
1535 if (is_locked(fnum,cnum,numtoread,startpos))
1536 return(ERROR(ERRDOS,ERRlock));
1539 nread = read_file(fnum,data,startpos,numtoread);
1542 return(UNIXERROR(ERRDOS,ERRnoaccess));
1545 SSVAL(outbuf,smb_vwv0,nread);
1546 SSVAL(outbuf,smb_vwv5,nread+3);
1547 CVAL(smb_buf(outbuf),0) = 1;
1548 SSVAL(smb_buf(outbuf),1,nread);
1550 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1556 /****************************************************************************
1557 reply to a read and X
1558 ****************************************************************************/
1559 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1561 int fnum = GETFNUM(inbuf,smb_vwv2);
1562 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1563 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1564 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1570 cnum = SVAL(inbuf,smb_tid);
1572 CHECK_FNUM(fnum,cnum);
1576 set_message(outbuf,12,0,True);
1577 data = smb_buf(outbuf);
1579 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1580 return(ERROR(ERRDOS,ERRlock));
1581 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1585 return(UNIXERROR(ERRDOS,ERRnoaccess));
1587 SSVAL(outbuf,smb_vwv5,nread);
1588 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1589 SSVAL(smb_buf(outbuf),-2,nread);
1591 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1592 timestring(),fnum,cnum,
1593 smb_mincnt,smb_maxcnt,nread));
1597 return chain_reply(inbuf,outbuf,length,bufsize);
1601 /****************************************************************************
1602 reply to a writebraw (core+ or LANMAN1.0 protocol)
1603 ****************************************************************************/
1604 int reply_writebraw(char *inbuf,char *outbuf)
1607 int total_written=0;
1616 cnum = SVAL(inbuf,smb_tid);
1617 fnum = GETFNUM(inbuf,smb_vwv0);
1619 CHECK_FNUM(fnum,cnum);
1623 tcount = IVAL(inbuf,smb_vwv1);
1624 startpos = IVAL(inbuf,smb_vwv3);
1625 write_through = BITSETW(inbuf+smb_vwv7,0);
1627 /* We have to deal with slightly different formats depending
1628 on whether we are using the core+ or lanman1.0 protocol */
1629 if(Protocol <= PROTOCOL_COREPLUS) {
1630 numtowrite = SVAL(smb_buf(inbuf),-2);
1631 data = smb_buf(inbuf);
1633 numtowrite = SVAL(inbuf,smb_vwv10);
1634 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1637 /* force the error type */
1638 CVAL(inbuf,smb_com) = SMBwritec;
1639 CVAL(outbuf,smb_com) = SMBwritec;
1641 if (is_locked(fnum,cnum,tcount,startpos))
1642 return(ERROR(ERRDOS,ERRlock));
1644 if (seek_file(fnum,startpos) != startpos)
1645 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1648 nwritten = write_file(fnum,data,numtowrite);
1650 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1651 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1653 if (nwritten < numtowrite)
1654 return(UNIXERROR(ERRHRD,ERRdiskfull));
1656 total_written = nwritten;
1658 /* Return a message to the redirector to tell it
1659 to send more bytes */
1660 CVAL(outbuf,smb_com) = SMBwritebraw;
1661 SSVALS(outbuf,smb_vwv0,-1);
1662 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1663 send_smb(Client,outbuf);
1665 /* Now read the raw data into the buffer and write it */
1666 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1667 exit_server("secondary writebraw failed");
1670 /* Even though this is not an smb message, smb_len
1671 returns the generic length of an smb message */
1672 numtowrite = smb_len(inbuf);
1674 if (tcount > nwritten+numtowrite) {
1675 DEBUG(3,("Client overestimated the write %d %d %d\n",
1676 tcount,nwritten,numtowrite));
1679 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1681 total_written += nwritten;
1683 /* Set up outbuf to return the correct return */
1684 outsize = set_message(outbuf,1,0,True);
1685 CVAL(outbuf,smb_com) = SMBwritec;
1686 SSVAL(outbuf,smb_vwv0,total_written);
1688 if (nwritten < numtowrite) {
1689 CVAL(outbuf,smb_rcls) = ERRHRD;
1690 SSVAL(outbuf,smb_err,ERRdiskfull);
1693 if (lp_syncalways(SNUM(cnum)) || write_through)
1696 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1697 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1699 /* we won't return a status if write through is not selected - this
1700 follows what WfWg does */
1701 if (!write_through && total_written==tcount)
1708 /****************************************************************************
1709 reply to a writeunlock (core+)
1710 ****************************************************************************/
1711 int reply_writeunlock(char *inbuf,char *outbuf)
1717 uint32 numtowrite,startpos;
1721 cnum = SVAL(inbuf,smb_tid);
1722 fnum = GETFNUM(inbuf,smb_vwv0);
1724 CHECK_FNUM(fnum,cnum);
1728 numtowrite = SVAL(inbuf,smb_vwv1);
1729 startpos = IVAL(inbuf,smb_vwv2);
1730 data = smb_buf(inbuf) + 3;
1732 if (is_locked(fnum,cnum,numtowrite,startpos))
1733 return(ERROR(ERRDOS,ERRlock));
1735 seek_file(fnum,startpos);
1737 /* The special X/Open SMB protocol handling of
1738 zero length writes is *NOT* done for
1743 nwritten = write_file(fnum,data,numtowrite);
1745 if (lp_syncalways(SNUM(cnum)))
1748 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1749 return(UNIXERROR(ERRDOS,ERRnoaccess));
1751 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1752 return(ERROR(eclass,ecode));
1754 outsize = set_message(outbuf,1,0,True);
1756 SSVAL(outbuf,smb_vwv0,nwritten);
1758 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1759 timestring(),fnum,cnum,numtowrite,nwritten));
1765 /****************************************************************************
1767 ****************************************************************************/
1768 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1770 int cnum,numtowrite,fnum;
1779 cnum = SVAL(inbuf,smb_tid);
1780 fnum = GETFNUM(inbuf,smb_vwv0);
1782 CHECK_FNUM(fnum,cnum);
1786 numtowrite = SVAL(inbuf,smb_vwv1);
1787 startpos = IVAL(inbuf,smb_vwv2);
1788 data = smb_buf(inbuf) + 3;
1790 if (is_locked(fnum,cnum,numtowrite,startpos))
1791 return(ERROR(ERRDOS,ERRlock));
1793 seek_file(fnum,startpos);
1795 /* X/Open SMB protocol says that if smb_vwv1 is
1796 zero then the file size should be extended or
1797 truncated to the size given in smb_vwv[2-3] */
1799 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
1801 nwritten = write_file(fnum,data,numtowrite);
1803 if (lp_syncalways(SNUM(cnum)))
1806 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1807 return(UNIXERROR(ERRDOS,ERRnoaccess));
1809 outsize = set_message(outbuf,1,0,True);
1811 SSVAL(outbuf,smb_vwv0,nwritten);
1813 if (nwritten < numtowrite) {
1814 CVAL(outbuf,smb_rcls) = ERRHRD;
1815 SSVAL(outbuf,smb_err,ERRdiskfull);
1818 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1824 /****************************************************************************
1825 reply to a write and X
1826 ****************************************************************************/
1827 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1829 int fnum = GETFNUM(inbuf,smb_vwv2);
1830 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1831 int smb_dsize = SVAL(inbuf,smb_vwv10);
1832 int smb_doff = SVAL(inbuf,smb_vwv11);
1833 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1838 cnum = SVAL(inbuf,smb_tid);
1840 CHECK_FNUM(fnum,cnum);
1844 data = smb_base(inbuf) + smb_doff;
1846 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1847 return(ERROR(ERRDOS,ERRlock));
1849 seek_file(fnum,smb_offs);
1851 /* X/Open SMB protocol says that, unlike SMBwrite
1852 if the length is zero then NO truncation is
1853 done, just a write of zero. To truncate a file,
1858 nwritten = write_file(fnum,data,smb_dsize);
1860 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1861 return(UNIXERROR(ERRDOS,ERRnoaccess));
1863 set_message(outbuf,6,0,True);
1865 SSVAL(outbuf,smb_vwv2,nwritten);
1867 if (nwritten < smb_dsize) {
1868 CVAL(outbuf,smb_rcls) = ERRHRD;
1869 SSVAL(outbuf,smb_err,ERRdiskfull);
1872 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1876 if (lp_syncalways(SNUM(cnum)) || write_through)
1879 return chain_reply(inbuf,outbuf,length,bufsize);
1883 /****************************************************************************
1885 ****************************************************************************/
1886 int reply_lseek(char *inbuf,char *outbuf)
1894 cnum = SVAL(inbuf,smb_tid);
1895 fnum = GETFNUM(inbuf,smb_vwv0);
1897 CHECK_FNUM(fnum,cnum);
1900 mode = SVAL(inbuf,smb_vwv1) & 3;
1901 startpos = IVAL(inbuf,smb_vwv2);
1905 case 0: umode = SEEK_SET; break;
1906 case 1: umode = SEEK_CUR; break;
1907 case 2: umode = SEEK_END; break;
1909 umode = SEEK_SET; break;
1912 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
1913 Files[fnum].pos = res;
1915 outsize = set_message(outbuf,2,0,True);
1916 SIVALS(outbuf,smb_vwv0,res);
1918 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1924 /****************************************************************************
1926 ****************************************************************************/
1927 int reply_flush(char *inbuf,char *outbuf)
1930 int outsize = set_message(outbuf,0,0,True);
1932 cnum = SVAL(inbuf,smb_tid);
1933 fnum = GETFNUM(inbuf,smb_vwv0);
1935 if (fnum != 0xFFFF) {
1936 CHECK_FNUM(fnum,cnum);
1943 for (i=0;i<MAX_OPEN_FILES;i++)
1950 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1955 /****************************************************************************
1957 ****************************************************************************/
1958 int reply_exit(char *inbuf,char *outbuf)
1960 int outsize = set_message(outbuf,0,0,True);
1961 DEBUG(3,("%s exit\n",timestring()));
1967 /****************************************************************************
1969 ****************************************************************************/
1970 int reply_close(char *inbuf,char *outbuf)
1975 int32 eclass = 0, err = 0;
1977 outsize = set_message(outbuf,0,0,True);
1979 cnum = SVAL(inbuf,smb_tid);
1981 fnum = GETFNUM(inbuf,smb_vwv0);
1982 CHECK_FNUM(fnum,cnum);
1984 if(HAS_CACHED_ERROR(fnum)) {
1985 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1986 err = Files[fnum].wbmpx_ptr->wr_error;
1989 mtime = make_unix_date3(inbuf+smb_vwv1);
1991 /* try and set the date */
1992 set_filetime(Files[fnum].name,mtime);
1996 /* We have a cached error */
1998 return(ERROR(eclass,err));
2000 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2001 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2002 Connections[cnum].num_files_open));
2008 /****************************************************************************
2009 reply to a writeclose (Core+ protocol)
2010 ****************************************************************************/
2011 int reply_writeclose(char *inbuf,char *outbuf)
2013 int cnum,numtowrite,fnum;
2020 cnum = SVAL(inbuf,smb_tid);
2021 fnum = GETFNUM(inbuf,smb_vwv0);
2023 CHECK_FNUM(fnum,cnum);
2027 numtowrite = SVAL(inbuf,smb_vwv1);
2028 startpos = IVAL(inbuf,smb_vwv2);
2029 mtime = make_unix_date3(inbuf+smb_vwv4);
2030 data = smb_buf(inbuf) + 1;
2032 if (is_locked(fnum,cnum,numtowrite,startpos))
2033 return(ERROR(ERRDOS,ERRlock));
2035 seek_file(fnum,startpos);
2037 nwritten = write_file(fnum,data,numtowrite);
2039 set_filetime(Files[fnum].name,mtime);
2043 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2044 timestring(),fnum,cnum,numtowrite,nwritten,
2045 Connections[cnum].num_files_open));
2048 return(UNIXERROR(ERRDOS,ERRnoaccess));
2050 outsize = set_message(outbuf,1,0,True);
2052 SSVAL(outbuf,smb_vwv0,nwritten);
2057 /****************************************************************************
2059 ****************************************************************************/
2060 int reply_lock(char *inbuf,char *outbuf)
2063 int outsize = set_message(outbuf,0,0,True);
2064 uint32 count,offset;
2068 cnum = SVAL(inbuf,smb_tid);
2069 fnum = GETFNUM(inbuf,smb_vwv0);
2071 CHECK_FNUM(fnum,cnum);
2074 count = IVAL(inbuf,smb_vwv1);
2075 offset = IVAL(inbuf,smb_vwv3);
2077 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));
2079 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2080 return (ERROR(eclass,ecode));
2086 /****************************************************************************
2088 ****************************************************************************/
2089 int reply_unlock(char *inbuf,char *outbuf)
2092 int outsize = set_message(outbuf,0,0,True);
2093 uint32 count,offset;
2097 cnum = SVAL(inbuf,smb_tid);
2098 fnum = GETFNUM(inbuf,smb_vwv0);
2100 CHECK_FNUM(fnum,cnum);
2103 count = IVAL(inbuf,smb_vwv1);
2104 offset = IVAL(inbuf,smb_vwv3);
2106 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2107 return (ERROR(eclass,ecode));
2109 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));
2115 /****************************************************************************
2117 ****************************************************************************/
2118 int reply_tdis(char *inbuf,char *outbuf)
2121 int outsize = set_message(outbuf,0,0,True);
2124 cnum = SVAL(inbuf,smb_tid);
2125 vuid = SVAL(inbuf,smb_uid);
2127 if (!OPEN_CNUM(cnum)) {
2128 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2129 return(ERROR(ERRSRV,ERRinvnid));
2132 Connections[cnum].used = False;
2134 close_cnum(cnum,vuid);
2136 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2143 /****************************************************************************
2145 ****************************************************************************/
2146 int reply_echo(char *inbuf,char *outbuf)
2149 int smb_reverb = SVAL(inbuf,smb_vwv0);
2151 int data_len = smb_buflen(inbuf);
2152 int outsize = set_message(outbuf,1,data_len,True);
2154 cnum = SVAL(inbuf,smb_tid);
2156 /* According to the latest CIFS spec we shouldn't
2157 care what the TID is.
2161 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2163 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2164 return(ERROR(ERRSRV,ERRinvnid));
2168 /* copy any incoming data back out */
2170 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2172 if (smb_reverb > 100)
2174 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2178 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2180 SSVAL(outbuf,smb_vwv0,seq_num);
2182 smb_setlen(outbuf,outsize - 4);
2184 send_smb(Client,outbuf);
2187 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2193 /****************************************************************************
2194 reply to a printopen
2195 ****************************************************************************/
2196 int reply_printopen(char *inbuf,char *outbuf)
2204 *fname = *fname2 = 0;
2206 cnum = SVAL(inbuf,smb_tid);
2208 if (!CAN_PRINT(cnum))
2209 return(ERROR(ERRDOS,ERRnoaccess));
2214 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2218 if (!(isalnum(*p) || strchr("._-",*p)))
2223 if (strlen(s) > 10) s[10] = 0;
2225 sprintf(fname,"%s.XXXXXX",s);
2228 fnum = find_free_file();
2230 return(ERROR(ERRSRV,ERRnofids));
2232 strcpy(fname2,(char *)mktemp(fname));
2234 if (!check_name(fname2,cnum))
2235 return(ERROR(ERRDOS,ERRnoaccess));
2237 /* Open for exclusive use, write only. */
2238 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL);
2240 if (!Files[fnum].open)
2241 return(UNIXERROR(ERRDOS,ERRnoaccess));
2243 /* force it to be a print file */
2244 Files[fnum].print_file = True;
2246 outsize = set_message(outbuf,1,0,True);
2247 SSVAL(outbuf,smb_vwv0,fnum);
2249 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2255 /****************************************************************************
2256 reply to a printclose
2257 ****************************************************************************/
2258 int reply_printclose(char *inbuf,char *outbuf)
2261 int outsize = set_message(outbuf,0,0,True);
2263 cnum = SVAL(inbuf,smb_tid);
2264 fnum = GETFNUM(inbuf,smb_vwv0);
2266 CHECK_FNUM(fnum,cnum);
2269 if (!CAN_PRINT(cnum))
2270 return(ERROR(ERRDOS,ERRnoaccess));
2274 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2280 /****************************************************************************
2281 reply to a printqueue
2282 ****************************************************************************/
2283 int reply_printqueue(char *inbuf,char *outbuf)
2286 int outsize = set_message(outbuf,2,3,True);
2287 int max_count = SVAL(inbuf,smb_vwv0);
2288 int start_index = SVAL(inbuf,smb_vwv1);
2291 cnum = SVAL(inbuf,smb_tid);
2292 vuid = SVAL(inbuf,smb_uid);
2294 /* allow checking the queue for anyone */
2296 if (!CAN_PRINT(cnum))
2297 return(ERROR(ERRDOS,ERRnoaccess));
2300 SSVAL(outbuf,smb_vwv0,0);
2301 SSVAL(outbuf,smb_vwv1,0);
2302 CVAL(smb_buf(outbuf),0) = 1;
2303 SSVAL(smb_buf(outbuf),1,0);
2305 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2306 timestring(),cnum,start_index,max_count));
2308 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2313 for (i=0;i<MAX_CONNECTIONS;i++)
2314 if (CAN_PRINT(i) && Connections[i].printer)
2318 for (i=0;i<MAX_CONNECTIONS;i++)
2322 if (!OPEN_CNUM(cnum))
2323 return(ERROR(ERRSRV,ERRinvnid));
2325 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2328 if (!become_user(cnum,vuid))
2329 return(ERROR(ERRSRV,ERRinvnid));
2332 print_queue_struct *queue = NULL;
2333 char *p = smb_buf(outbuf) + 3;
2334 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2335 int num_to_get = ABS(max_count);
2336 int first = (max_count>0?start_index:start_index+max_count+1);
2342 num_to_get = MIN(num_to_get,count-first);
2345 for (i=first;i<first+num_to_get;i++)
2347 put_dos_date2(p,0,queue[i].time);
2348 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2349 SSVAL(p,5,queue[i].job);
2350 SIVAL(p,7,queue[i].size);
2352 StrnCpy(p+12,queue[i].user,16);
2358 outsize = set_message(outbuf,2,28*count+3,False);
2359 SSVAL(outbuf,smb_vwv0,count);
2360 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2361 CVAL(smb_buf(outbuf),0) = 1;
2362 SSVAL(smb_buf(outbuf),1,28*count);
2365 if (queue) free(queue);
2367 DEBUG(3,("%d entries returned in queue\n",count));
2374 /****************************************************************************
2375 reply to a printwrite
2376 ****************************************************************************/
2377 int reply_printwrite(char *inbuf,char *outbuf)
2379 int cnum,numtowrite,fnum;
2380 int outsize = set_message(outbuf,0,0,True);
2383 cnum = SVAL(inbuf,smb_tid);
2385 if (!CAN_PRINT(cnum))
2386 return(ERROR(ERRDOS,ERRnoaccess));
2388 fnum = GETFNUM(inbuf,smb_vwv0);
2390 CHECK_FNUM(fnum,cnum);
2394 numtowrite = SVAL(smb_buf(inbuf),1);
2395 data = smb_buf(inbuf) + 3;
2397 if (write_file(fnum,data,numtowrite) != numtowrite)
2398 return(UNIXERROR(ERRDOS,ERRnoaccess));
2400 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2406 /****************************************************************************
2408 ****************************************************************************/
2409 int reply_mkdir(char *inbuf,char *outbuf)
2413 int outsize,ret= -1;
2415 strcpy(directory,smb_buf(inbuf) + 1);
2416 cnum = SVAL(inbuf,smb_tid);
2417 unix_convert(directory,cnum,0);
2419 if (check_name(directory,cnum))
2420 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2423 return(UNIXERROR(ERRDOS,ERRnoaccess));
2425 outsize = set_message(outbuf,0,0,True);
2427 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2433 /****************************************************************************
2435 ****************************************************************************/
2436 int reply_rmdir(char *inbuf,char *outbuf)
2443 cnum = SVAL(inbuf,smb_tid);
2444 strcpy(directory,smb_buf(inbuf) + 1);
2445 unix_convert(directory,cnum,0);
2447 if (check_name(directory,cnum))
2450 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2451 ok = (sys_rmdir(directory) == 0);
2452 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2454 /* Check to see if the only thing in this directory are
2455 vetoed files/directories. If so then delete them and
2456 retry. If we fail to delete any of them (and we *don't*
2457 do a recursive delete) then fail the rmdir. */
2458 BOOL all_veto_files = True;
2460 void *dirptr = OpenDir(cnum, directory, False);
2464 int dirpos = TellDir(dirptr);
2465 while ((dname = ReadDirName(dirptr)))
2467 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2469 if(!IS_VETO_PATH(cnum, dname))
2471 all_veto_files = False;
2477 SeekDir(dirptr,dirpos);
2478 while ((dname = ReadDirName(dirptr)))
2483 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2486 /* Construct the full name. */
2487 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2492 strcpy(fullname, directory);
2493 strcat(fullname, "/");
2494 strcat(fullname, dname);
2496 if(sys_lstat(fullname, &st) != 0)
2498 if(st.st_mode & S_IFDIR)
2500 if(sys_rmdir(fullname) != 0)
2503 else if(sys_unlink(fullname) != 0)
2507 /* Retry the rmdir */
2508 ok = (sys_rmdir(directory) == 0);
2518 DEBUG(3,("couldn't remove directory %s : %s\n",
2519 directory,strerror(errno)));
2523 return(UNIXERROR(ERRDOS,ERRbadpath));
2525 outsize = set_message(outbuf,0,0,True);
2527 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2533 /*******************************************************************
2534 resolve wildcards in a filename rename
2535 ********************************************************************/
2536 static BOOL resolve_wildcards(char *name1,char *name2)
2538 fstring root1,root2;
2542 name1 = strrchr(name1,'/');
2543 name2 = strrchr(name2,'/');
2545 if (!name1 || !name2) return(False);
2547 strcpy(root1,name1);
2548 strcpy(root2,name2);
2549 p = strrchr(root1,'.');
2556 p = strrchr(root2,'.');
2588 strcpy(name2,root2);
2597 /*******************************************************************
2598 check if a user is allowed to rename a file
2599 ********************************************************************/
2600 static BOOL can_rename(char *fname,int cnum)
2604 if (!CAN_WRITE(cnum)) return(False);
2606 if (sys_lstat(fname,&sbuf) != 0) return(False);
2607 if (!check_file_sharing(cnum,fname)) return(False);
2612 /****************************************************************************
2614 ****************************************************************************/
2615 int reply_mv(char *inbuf,char *outbuf)
2621 pstring mask,newname;
2622 pstring newname_last_component;
2625 int error = ERRnoaccess;
2629 *directory = *mask = 0;
2631 cnum = SVAL(inbuf,smb_tid);
2633 strcpy(name,smb_buf(inbuf) + 1);
2634 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2636 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2638 unix_convert(name,cnum,0);
2639 unix_convert(newname,cnum,newname_last_component);
2642 * Split the old name into directory and last component
2643 * strings. Note that unix_convert may have stripped off a
2644 * leading ./ from both name and newname if the rename is
2645 * at the root of the share. We need to make sure either both
2646 * name and newname contain a / character or neither of them do
2647 * as this is checked in resolve_wildcards().
2650 p = strrchr(name,'/');
2652 strcpy(directory,".");
2656 strcpy(directory,name);
2658 *p = '/'; /* Replace needed for exceptional test below. */
2661 if (is_mangled(mask))
2662 check_mangled_stack(mask);
2664 has_wild = strchr(mask,'*') || strchr(mask,'?');
2667 BOOL is_short_name = is_8_3(name, True);
2669 /* Add a terminating '/' to the directory name. */
2670 strcat(directory,"/");
2671 strcat(directory,mask);
2673 /* Ensure newname contains a '/' also */
2674 if(strrchr(newname,'/') == 0) {
2677 strcpy(tmpstr, "./");
2678 strcat(tmpstr, newname);
2679 strcpy(newname, tmpstr);
2682 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",
2683 case_sensitive, case_preserve, short_case_preserve, directory,
2684 newname, newname_last_component, is_short_name));
2687 * Check for special case with case preserving and not
2688 * case sensitive, if directory and newname are identical,
2689 * and the old last component differs from the original
2690 * last component only by case, then we should allow
2691 * the rename (user is trying to change the case of the
2694 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
2695 ((short_case_preserve == True) && (is_short_name == True))) &&
2696 strcsequal(directory, newname)) {
2697 pstring newname_modified_last_component;
2700 * Get the last component of the modified name.
2701 * Note that we guarantee that newname contains a '/'
2704 p = strrchr(newname,'/');
2705 strcpy(newname_modified_last_component,p+1);
2707 if(strcsequal(newname_modified_last_component,
2708 newname_last_component) == False) {
2710 * Replace the modified last component with
2713 strcpy(p+1, newname_last_component);
2717 if (resolve_wildcards(directory,newname) &&
2718 can_rename(directory,cnum) &&
2719 !file_exist(newname,NULL) &&
2720 !sys_rename(directory,newname)) count++;
2722 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
2723 directory,newname));
2725 if (!count) exists = file_exist(directory,NULL);
2726 if (!count && exists && file_exist(newname,NULL)) {
2731 void *dirptr = NULL;
2735 if (check_name(directory,cnum))
2736 dirptr = OpenDir(cnum, directory, True);
2742 if (strequal(mask,"????????.???"))
2745 while ((dname = ReadDirName(dirptr)))
2748 strcpy(fname,dname);
2750 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2752 error = ERRnoaccess;
2753 sprintf(fname,"%s/%s",directory,dname);
2754 if (!can_rename(fname,cnum)) continue;
2755 strcpy(destname,newname);
2757 if (!resolve_wildcards(fname,destname)) continue;
2759 if (file_exist(destname,NULL)) {
2763 if (!sys_rename(fname,destname)) count++;
2764 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2772 return(ERROR(ERRDOS,error));
2774 return(UNIXERROR(ERRDOS,error));
2777 outsize = set_message(outbuf,0,0,True);
2782 /*******************************************************************
2783 copy a file as part of a reply_copy
2784 ******************************************************************/
2785 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2786 int count,BOOL target_is_directory)
2795 if (target_is_directory) {
2796 char *p = strrchr(src,'/');
2805 if (!file_exist(src,&st)) return(False);
2807 fnum1 = find_free_file();
2808 if (fnum1<0) return(False);
2809 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2810 1,0,&Access,&action);
2812 if (!Files[fnum1].open) return(False);
2814 if (!target_is_directory && count)
2817 fnum2 = find_free_file();
2822 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2823 ofun,st.st_mode,&Access,&action);
2825 if (!Files[fnum2].open) {
2830 if ((ofun&3) == 1) {
2831 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
2835 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
2840 return(ret == st.st_size);
2845 /****************************************************************************
2846 reply to a file copy.
2847 ****************************************************************************/
2848 int reply_copy(char *inbuf,char *outbuf)
2854 pstring mask,newname;
2857 int error = ERRnoaccess;
2860 int tid2 = SVAL(inbuf,smb_vwv0);
2861 int ofun = SVAL(inbuf,smb_vwv1);
2862 int flags = SVAL(inbuf,smb_vwv2);
2863 BOOL target_is_directory=False;
2865 *directory = *mask = 0;
2867 cnum = SVAL(inbuf,smb_tid);
2869 strcpy(name,smb_buf(inbuf));
2870 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2872 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2875 /* can't currently handle inter share copies XXXX */
2876 DEBUG(3,("Rejecting inter-share copy\n"));
2877 return(ERROR(ERRSRV,ERRinvdevice));
2880 unix_convert(name,cnum,0);
2881 unix_convert(newname,cnum,0);
2883 target_is_directory = directory_exist(newname,NULL);
2885 if ((flags&1) && target_is_directory) {
2886 return(ERROR(ERRDOS,ERRbadfile));
2889 if ((flags&2) && !target_is_directory) {
2890 return(ERROR(ERRDOS,ERRbadpath));
2893 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2894 /* wants a tree copy! XXXX */
2895 DEBUG(3,("Rejecting tree copy\n"));
2896 return(ERROR(ERRSRV,ERRerror));
2899 p = strrchr(name,'/');
2901 strcpy(directory,"./");
2905 strcpy(directory,name);
2909 if (is_mangled(mask))
2910 check_mangled_stack(mask);
2912 has_wild = strchr(mask,'*') || strchr(mask,'?');
2915 strcat(directory,"/");
2916 strcat(directory,mask);
2917 if (resolve_wildcards(directory,newname) &&
2918 copy_file(directory,newname,cnum,ofun,
2919 count,target_is_directory)) count++;
2920 if (!count) exists = file_exist(directory,NULL);
2922 void *dirptr = NULL;
2926 if (check_name(directory,cnum))
2927 dirptr = OpenDir(cnum, directory, True);
2933 if (strequal(mask,"????????.???"))
2936 while ((dname = ReadDirName(dirptr)))
2939 strcpy(fname,dname);
2941 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2943 error = ERRnoaccess;
2944 sprintf(fname,"%s/%s",directory,dname);
2945 strcpy(destname,newname);
2946 if (resolve_wildcards(fname,destname) &&
2947 copy_file(directory,newname,cnum,ofun,
2948 count,target_is_directory)) count++;
2949 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2957 return(ERROR(ERRDOS,error));
2959 return(UNIXERROR(ERRDOS,error));
2962 outsize = set_message(outbuf,1,0,True);
2963 SSVAL(outbuf,smb_vwv0,count);
2970 /****************************************************************************
2972 ****************************************************************************/
2973 int reply_setdir(char *inbuf,char *outbuf)
2980 cnum = SVAL(inbuf,smb_tid);
2982 snum = Connections[cnum].service;
2983 if (!CAN_SETDIR(snum))
2984 return(ERROR(ERRDOS,ERRnoaccess));
2986 strcpy(newdir,smb_buf(inbuf) + 1);
2989 if (strlen(newdir) == 0)
2993 ok = directory_exist(newdir,NULL);
2995 string_set(&Connections[cnum].connectpath,newdir);
2999 return(ERROR(ERRDOS,ERRbadpath));
3001 outsize = set_message(outbuf,0,0,True);
3002 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3004 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3010 /****************************************************************************
3011 reply to a lockingX request
3012 ****************************************************************************/
3013 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3015 int fnum = GETFNUM(inbuf,smb_vwv2);
3016 uint16 locktype = SVAL(inbuf,smb_vwv3);
3017 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3018 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3019 uint32 count, offset;
3024 uint32 ecode=0, dummy2;
3025 int eclass=0, dummy1;
3027 cnum = SVAL(inbuf,smb_tid);
3029 CHECK_FNUM(fnum,cnum);
3032 data = smb_buf(inbuf);
3033 /* Data now points at the beginning of the list
3034 of smb_unlkrng structs */
3035 for(i = 0; i < (int)num_ulocks; i++) {
3036 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3037 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3038 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3039 return ERROR(eclass,ecode);
3042 /* Now do any requested locks */
3043 data += 10*num_ulocks;
3044 /* Data now points at the beginning of the list
3045 of smb_lkrng structs */
3046 for(i = 0; i < (int)num_locks; i++) {
3047 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3048 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3049 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3053 /* If any of the above locks failed, then we must unlock
3054 all of the previous locks (X/Open spec). */
3055 if(i != num_locks && num_locks != 0) {
3056 for(; i >= 0; i--) {
3057 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3058 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3059 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3061 return ERROR(eclass,ecode);
3064 set_message(outbuf,2,0,True);
3066 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3067 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
3071 return chain_reply(inbuf,outbuf,length,bufsize);
3075 /****************************************************************************
3076 reply to a SMBreadbmpx (read block multiplex) request
3077 ****************************************************************************/
3078 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3085 int outsize, mincount, maxcount;
3090 /* this function doesn't seem to work - disable by default */
3092 return(ERROR(ERRSRV,ERRuseSTD));
3094 outsize = set_message(outbuf,8,0,True);
3096 cnum = SVAL(inbuf,smb_tid);
3097 fnum = GETFNUM(inbuf,smb_vwv0);
3099 CHECK_FNUM(fnum,cnum);
3103 startpos = IVAL(inbuf,smb_vwv1);
3104 maxcount = SVAL(inbuf,smb_vwv3);
3105 mincount = SVAL(inbuf,smb_vwv4);
3107 data = smb_buf(outbuf);
3108 pad = ((long)data)%4;
3109 if (pad) pad = 4 - pad;
3112 max_per_packet = bufsize-(outsize+pad);
3116 if (is_locked(fnum,cnum,maxcount,startpos))
3117 return(ERROR(ERRDOS,ERRlock));
3121 int N = MIN(max_per_packet,tcount-total_read);
3123 nread = read_file(fnum,data,startpos,N);
3125 if (nread <= 0) nread = 0;
3128 tcount = total_read + nread;
3130 set_message(outbuf,8,nread,False);
3131 SIVAL(outbuf,smb_vwv0,startpos);
3132 SSVAL(outbuf,smb_vwv2,tcount);
3133 SSVAL(outbuf,smb_vwv6,nread);
3134 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3136 send_smb(Client,outbuf);
3138 total_read += nread;
3141 while (total_read < tcount);
3147 /****************************************************************************
3148 reply to a SMBwritebmpx (write block multiplex primary) request
3149 ****************************************************************************/
3150 int reply_writebmpx(char *inbuf,char *outbuf)
3152 int cnum,numtowrite,fnum;
3156 int tcount, write_through, smb_doff;
3159 cnum = SVAL(inbuf,smb_tid);
3160 fnum = GETFNUM(inbuf,smb_vwv0);
3162 CHECK_FNUM(fnum,cnum);
3166 tcount = SVAL(inbuf,smb_vwv1);
3167 startpos = IVAL(inbuf,smb_vwv3);
3168 write_through = BITSETW(inbuf+smb_vwv7,0);
3169 numtowrite = SVAL(inbuf,smb_vwv10);
3170 smb_doff = SVAL(inbuf,smb_vwv11);
3172 data = smb_base(inbuf) + smb_doff;
3174 /* If this fails we need to send an SMBwriteC response,
3175 not an SMBwritebmpx - set this up now so we don't forget */
3176 CVAL(outbuf,smb_com) = SMBwritec;
3178 if (is_locked(fnum,cnum,tcount,startpos))
3179 return(ERROR(ERRDOS,ERRlock));
3181 seek_file(fnum,startpos);
3182 nwritten = write_file(fnum,data,numtowrite);
3184 if(lp_syncalways(SNUM(cnum)) || write_through)
3187 if(nwritten < numtowrite)
3188 return(UNIXERROR(ERRHRD,ERRdiskfull));
3190 /* If the maximum to be written to this file
3191 is greater than what we just wrote then set
3192 up a secondary struct to be attached to this
3193 fd, we will use this to cache error messages etc. */
3194 if(tcount > nwritten)
3196 write_bmpx_struct *wbms;
3197 if(Files[fnum].wbmpx_ptr != NULL)
3198 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3200 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3203 DEBUG(0,("Out of memory in reply_readmpx\n"));
3204 return(ERROR(ERRSRV,ERRnoresource));
3206 wbms->wr_mode = write_through;
3207 wbms->wr_discard = False; /* No errors yet */
3208 wbms->wr_total_written = nwritten;
3209 wbms->wr_errclass = 0;
3211 Files[fnum].wbmpx_ptr = wbms;
3214 /* We are returning successfully, set the message type back to
3216 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3218 outsize = set_message(outbuf,1,0,True);
3220 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3222 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3223 timestring(),fnum,cnum,numtowrite,nwritten));
3225 if (write_through && tcount==nwritten) {
3226 /* we need to send both a primary and a secondary response */
3227 smb_setlen(outbuf,outsize - 4);
3228 send_smb(Client,outbuf);
3230 /* now the secondary */
3231 outsize = set_message(outbuf,1,0,True);
3232 CVAL(outbuf,smb_com) = SMBwritec;
3233 SSVAL(outbuf,smb_vwv0,nwritten);
3240 /****************************************************************************
3241 reply to a SMBwritebs (write block multiplex secondary) request
3242 ****************************************************************************/
3243 int reply_writebs(char *inbuf,char *outbuf)
3245 int cnum,numtowrite,fnum;
3249 int tcount, write_through, smb_doff;
3251 write_bmpx_struct *wbms;
3252 BOOL send_response = False;
3254 cnum = SVAL(inbuf,smb_tid);
3255 fnum = GETFNUM(inbuf,smb_vwv0);
3256 CHECK_FNUM(fnum,cnum);
3259 tcount = SVAL(inbuf,smb_vwv1);
3260 startpos = IVAL(inbuf,smb_vwv2);
3261 numtowrite = SVAL(inbuf,smb_vwv6);
3262 smb_doff = SVAL(inbuf,smb_vwv7);
3264 data = smb_base(inbuf) + smb_doff;
3266 /* We need to send an SMBwriteC response, not an SMBwritebs */
3267 CVAL(outbuf,smb_com) = SMBwritec;
3269 /* This fd should have an auxiliary struct attached,
3270 check that it does */
3271 wbms = Files[fnum].wbmpx_ptr;
3272 if(!wbms) return(-1);
3274 /* If write through is set we can return errors, else we must
3276 write_through = wbms->wr_mode;
3278 /* Check for an earlier error */
3279 if(wbms->wr_discard)
3280 return -1; /* Just discard the packet */
3282 seek_file(fnum,startpos);
3283 nwritten = write_file(fnum,data,numtowrite);
3285 if(lp_syncalways(SNUM(cnum)) || write_through)
3288 if (nwritten < numtowrite)
3291 /* We are returning an error - we can delete the aux struct */
3292 if (wbms) free((char *)wbms);
3293 Files[fnum].wbmpx_ptr = NULL;
3294 return(ERROR(ERRHRD,ERRdiskfull));
3296 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3299 /* Increment the total written, if this matches tcount
3300 we can discard the auxiliary struct (hurrah !) and return a writeC */
3301 wbms->wr_total_written += nwritten;
3302 if(wbms->wr_total_written >= tcount)
3304 if (write_through) {
3305 outsize = set_message(outbuf,1,0,True);
3306 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3307 send_response = True;
3311 Files[fnum].wbmpx_ptr = NULL;
3321 /****************************************************************************
3322 reply to a SMBsetattrE
3323 ****************************************************************************/
3324 int reply_setattrE(char *inbuf,char *outbuf)
3327 struct utimbuf unix_times;
3330 outsize = set_message(outbuf,0,0,True);
3332 cnum = SVAL(inbuf,smb_tid);
3333 fnum = GETFNUM(inbuf,smb_vwv0);
3335 CHECK_FNUM(fnum,cnum);
3338 /* Convert the DOS times into unix times. Ignore create
3339 time as UNIX can't set this.
3341 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3342 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3344 /* Set the date on this file */
3345 if(sys_utime(Files[fnum].name, &unix_times))
3346 return(ERROR(ERRDOS,ERRnoaccess));
3348 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3354 /****************************************************************************
3355 reply to a SMBgetattrE
3356 ****************************************************************************/
3357 int reply_getattrE(char *inbuf,char *outbuf)
3364 outsize = set_message(outbuf,11,0,True);
3366 cnum = SVAL(inbuf,smb_tid);
3367 fnum = GETFNUM(inbuf,smb_vwv0);
3369 CHECK_FNUM(fnum,cnum);
3372 /* Do an fstat on this file */
3373 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3374 return(UNIXERROR(ERRDOS,ERRnoaccess));
3376 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3378 /* Convert the times into dos times. Set create
3379 date to be last modify date as UNIX doesn't save
3381 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3382 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3383 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3386 SIVAL(outbuf,smb_vwv6,0);
3387 SIVAL(outbuf,smb_vwv8,0);
3391 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3392 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3394 SSVAL(outbuf,smb_vwv10, mode);
3396 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));