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;
45 extern int global_oplock_break;
47 /* this macro should always be used to extract an fnum (smb_fid) from
48 a packet to ensure chaining works correctly */
49 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
52 /****************************************************************************
53 report a possible attack via the password buffer overflow bug
54 ****************************************************************************/
55 static void overflow_attack(int len)
57 DEBUG(0,("ERROR: Invalid password length %d\n", len));
58 DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n"));
59 DEBUG(0,("Attack was from IP=%s\n", client_addr()));
60 exit_server("possible attack");
64 /****************************************************************************
65 reply to an special message
66 ****************************************************************************/
67 int reply_special(char *inbuf,char *outbuf)
70 int msg_type = CVAL(inbuf,0);
71 int msg_flags = CVAL(inbuf,1);
73 extern fstring remote_machine;
74 extern fstring local_machine;
82 case 0x81: /* session request */
83 CVAL(outbuf,0) = 0x82;
85 if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
86 DEBUG(0,("Invalid name length in session request\n"));
89 name_extract(inbuf,4,name1);
90 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
91 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
94 fstrcpy(remote_machine,name2);
95 trim_string(remote_machine," "," ");
96 p = strchr(remote_machine,' ');
97 strlower(remote_machine);
100 fstrcpy(local_machine,name1);
101 trim_string(local_machine," "," ");
102 p = strchr(local_machine,' ');
103 strlower(local_machine);
106 add_session_user(remote_machine);
108 reload_services(True);
113 case 0x89: /* session keepalive request
114 (some old clients produce this?) */
115 CVAL(outbuf,0) = 0x85;
119 case 0x82: /* positive session response */
120 case 0x83: /* negative session response */
121 case 0x84: /* retarget session response */
122 DEBUG(0,("Unexpected session response\n"));
125 case 0x85: /* session keepalive */
130 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",
131 timestring(),msg_type,msg_flags));
137 /*******************************************************************
138 work out what error to give to a failed connection
139 ********************************************************************/
140 static int connection_error(char *inbuf,char *outbuf,int connection_num)
142 switch (connection_num)
145 return(ERROR(ERRSRV,ERRnoresource));
147 return(ERROR(ERRSRV,ERRbaduid));
149 return(ERROR(ERRSRV,ERRinvdevice));
151 return(ERROR(ERRSRV,ERRinvnetname));
153 return(ERROR(ERRSRV,ERRaccess));
155 return(ERROR(ERRDOS,ERRnoipc));
157 return(ERROR(ERRSRV,ERRinvnetname));
159 return(ERROR(ERRSRV,ERRbadpw));
164 /****************************************************************************
165 parse a share descriptor string
166 ****************************************************************************/
167 static void parse_connect(char *p,char *service,char *user,
168 char *password,int *pwlen,char *dev)
172 DEBUG(4,("parsing connect string %s\n",p));
174 p2 = strrchr(p,'\\');
178 fstrcpy(service,p2+1);
183 *pwlen = strlen(password);
190 p = strchr(service,'%');
201 /****************************************************************************
203 ****************************************************************************/
204 int reply_tcon(char *inbuf,char *outbuf)
212 uint16 vuid = SVAL(inbuf,smb_uid);
215 *service = *user = *password = *dev = 0;
217 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
219 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
221 if (connection_num < 0)
222 return(connection_error(inbuf,outbuf,connection_num));
224 outsize = set_message(outbuf,2,0,True);
225 SSVAL(outbuf,smb_vwv0,max_recv);
226 SSVAL(outbuf,smb_vwv1,connection_num);
227 SSVAL(outbuf,smb_tid,connection_num);
229 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
235 /****************************************************************************
236 reply to a tcon and X
237 ****************************************************************************/
238 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
245 uint16 vuid = SVAL(inbuf,smb_uid);
246 int passlen = SVAL(inbuf,smb_vwv3);
247 BOOL doencrypt = SMBENCRYPT();
249 *service = *user = *password = *devicename = 0;
251 /* we might have to close an old one */
252 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
253 close_cnum(SVAL(inbuf,smb_tid),vuid);
255 if (passlen > MAX_PASS_LEN) {
256 overflow_attack(passlen);
262 memcpy(password,smb_buf(inbuf),passlen);
264 path = smb_buf(inbuf) + passlen;
266 if (!doencrypt || passlen != 24) {
267 if (strequal(password," "))
269 passlen = strlen(password);
272 fstrcpy(service,path+2);
273 p = strchr(service,'\\');
275 return(ERROR(ERRSRV,ERRinvnetname));
277 fstrcpy(service,p+1);
278 p = strchr(service,'%');
284 StrnCpy(devicename,path + strlen(path) + 1,6);
285 DEBUG(4,("Got device type %s\n",devicename));
288 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
290 if (connection_num < 0)
291 return(connection_error(inbuf,outbuf,connection_num));
293 if (Protocol < PROTOCOL_NT1)
295 set_message(outbuf,2,strlen(devicename)+1,True);
296 strcpy(smb_buf(outbuf),devicename);
300 char *fsname = "SAMBA";
303 set_message(outbuf,3,3,True);
306 strcpy(p,devicename); p = skip_string(p,1); /* device name */
307 strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
309 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
311 SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
314 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
316 /* set the incoming and outgoing tid to the just created one */
317 SSVAL(inbuf,smb_tid,connection_num);
318 SSVAL(outbuf,smb_tid,connection_num);
320 return chain_reply(inbuf,outbuf,length,bufsize);
324 /****************************************************************************
325 reply to an unknown type
326 ****************************************************************************/
327 int reply_unknown(char *inbuf,char *outbuf)
331 cnum = SVAL(inbuf,smb_tid);
332 type = CVAL(inbuf,smb_com);
334 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
339 return(ERROR(ERRSRV,ERRunknownsmb));
343 /****************************************************************************
345 ****************************************************************************/
346 int reply_ioctl(char *inbuf,char *outbuf)
348 DEBUG(3,("ignoring ioctl\n"));
350 /* we just say it succeeds and hope its all OK.
351 some day it would be nice to interpret them individually */
352 return set_message(outbuf,1,0,True);
354 return(ERROR(ERRSRV,ERRnosupport));
359 /****************************************************************************
360 reply to a session setup command
361 ****************************************************************************/
362 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
371 int smb_apasslen = 0;
373 int smb_ntpasslen = 0;
374 pstring smb_ntpasswd;
375 BOOL valid_nt_password = False;
378 BOOL computer_id=False;
379 static BOOL done_sesssetup = False;
380 BOOL doencrypt = SMBENCRYPT();
384 smb_bufsize = SVAL(inbuf,smb_vwv2);
385 smb_mpxmax = SVAL(inbuf,smb_vwv3);
386 smb_vc_num = SVAL(inbuf,smb_vwv4);
387 smb_sesskey = IVAL(inbuf,smb_vwv5);
389 if (Protocol < PROTOCOL_NT1) {
390 smb_apasslen = SVAL(inbuf,smb_vwv7);
391 if (smb_apasslen > MAX_PASS_LEN)
393 overflow_attack(smb_apasslen);
396 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
397 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
399 if (lp_security() != SEC_SERVER && !doencrypt) {
400 smb_apasslen = strlen(smb_apasswd);
403 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
404 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
405 uint32 client_caps = IVAL(inbuf,smb_vwv11);
406 enum remote_arch_types ra_type = get_remote_arch();
408 char *p = smb_buf(inbuf);
410 /* client_caps is used as final determination if client is NT or Win95.
411 This is needed to return the correct error codes in some
415 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
417 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
418 set_remote_arch( RA_WINNT);
420 set_remote_arch( RA_WIN95);
423 if (passlen1 != 24 && passlen2 != 24)
426 if (passlen1 > MAX_PASS_LEN) {
427 overflow_attack(passlen1);
430 passlen1 = MIN(passlen1, MAX_PASS_LEN);
431 passlen2 = MIN(passlen2, MAX_PASS_LEN);
434 /* Save the lanman2 password and the NT md4 password. */
435 smb_apasslen = passlen1;
436 memcpy(smb_apasswd,p,smb_apasslen);
437 smb_ntpasslen = passlen2;
438 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
440 /* both Win95 and WinNT stuff up the password lengths for
441 non-encrypting systems. Uggh.
443 if passlen1==24 its a win95 system, and its setting the
444 password length incorrectly. Luckily it still works with the
445 default code because Win95 will null terminate the password
448 if passlen1>0 and passlen2>0 then maybe its a NT box and its
449 setting passlen2 to some random value which really stuffs
450 things up. we need to fix that one. */
451 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
455 /* we use the first password that they gave */
456 smb_apasslen = passlen1;
457 StrnCpy(smb_apasswd,p,smb_apasslen);
459 /* trim the password */
460 smb_apasslen = strlen(smb_apasswd);
462 /* wfwg sometimes uses a space instead of a null */
463 if (strequal(smb_apasswd," ")) {
469 p += passlen1 + passlen2;
470 fstrcpy(user,p); p = skip_string(p,1);
471 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
472 p,skip_string(p,1),skip_string(p,2)));
476 DEBUG(3,("sesssetupX:name=[%s]\n",user));
478 /* If name ends in $ then I think it's asking about whether a */
479 /* computer with that name (minus the $) has access. For now */
480 /* say yes to everything ending in $. */
481 if (user[strlen(user) - 1] == '$') {
483 user[strlen(user) - 1] = '\0';
487 /* If no username is sent use the guest account */
490 strcpy(user,lp_guestaccount(-1));
491 /* If no user and no password then set guest flag. */
492 if( *smb_apasswd == 0)
498 strcpy(sesssetup_user,user);
500 reload_services(True);
502 add_session_user(user);
504 /* Check if the given username was the guest user with no password.
505 We need to do this check after add_session_user() as that
506 call can potentially change the username (via map_user).
509 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
512 if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
513 !check_hosts_equiv(user))
516 /* now check if it's a valid username/password */
517 /* If an NT password was supplied try and validate with that
518 first. This is superior as the passwords are mixed case
519 128 length unicode */
522 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
523 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
525 valid_nt_password = True;
527 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
529 if (!computer_id && lp_security() >= SEC_USER) {
530 #if (GUEST_SESSSETUP == 0)
531 return(ERROR(ERRSRV,ERRbadpw));
533 #if (GUEST_SESSSETUP == 1)
534 if (Get_Pwnam(user,True))
535 return(ERROR(ERRSRV,ERRbadpw));
538 if (*smb_apasswd || !Get_Pwnam(user,True))
539 strcpy(user,lp_guestaccount(-1));
540 DEBUG(3,("Registered username %s for guest access\n",user));
545 if (!Get_Pwnam(user,True)) {
546 DEBUG(3,("No such user %s - using guest account\n",user));
547 strcpy(user,lp_guestaccount(-1));
551 if (!strequal(user,lp_guestaccount(-1)) &&
552 lp_servicenumber(user) < 0)
554 int homes = lp_servicenumber(HOMES_NAME);
555 char *home = get_home_dir(user);
556 if (homes >= 0 && home)
557 lp_add_home(user,homes,home);
561 /* it's ok - setup a reply */
562 if (Protocol < PROTOCOL_NT1) {
563 set_message(outbuf,3,0,True);
566 set_message(outbuf,3,3,True);
568 strcpy(p,"Unix"); p = skip_string(p,1);
569 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
570 strcpy(p,myworkgroup); p = skip_string(p,1);
571 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
572 /* perhaps grab OS version here?? */
575 /* Set the correct uid in the outgoing and incoming packets
576 We will use this on future requests to determine which
577 user we should become.
580 struct passwd *pw = Get_Pwnam(user,False);
582 DEBUG(1,("Username %s is invalid on this system\n",user));
583 return(ERROR(ERRSRV,ERRbadpw));
589 if (guest && !computer_id)
590 SSVAL(outbuf,smb_vwv2,1);
592 /* register the name and uid as being validated, so further connections
593 to a uid can get through without a password, on the same VC */
594 sess_vuid = register_vuid(uid,gid,user,guest);
596 SSVAL(outbuf,smb_uid,sess_vuid);
597 SSVAL(inbuf,smb_uid,sess_vuid);
600 max_send = MIN(max_send,smb_bufsize);
602 DEBUG(6,("Client requested max send size of %d\n", max_send));
604 done_sesssetup = True;
606 return chain_reply(inbuf,outbuf,length,bufsize);
610 /****************************************************************************
612 ****************************************************************************/
613 int reply_chkpth(char *inbuf,char *outbuf)
619 BOOL bad_path = False;
621 cnum = SVAL(inbuf,smb_tid);
623 pstrcpy(name,smb_buf(inbuf) + 1);
624 unix_convert(name,cnum,0,&bad_path);
626 mode = SVAL(inbuf,smb_vwv0);
628 if (check_name(name,cnum))
629 ok = directory_exist(name,NULL);
633 /* We special case this - as when a Windows machine
634 is parsing a path is steps through the components
635 one at a time - if a component fails it expects
636 ERRbadpath, not ERRbadfile.
640 unix_ERR_class = ERRDOS;
641 unix_ERR_code = ERRbadpath;
644 /* Ugly - NT specific hack - but needed (JRA) */
645 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
646 (get_remote_arch() == RA_WINNT))
648 unix_ERR_class = ERRDOS;
649 unix_ERR_code = ERRbaddirectory;
652 return(UNIXERROR(ERRDOS,ERRbadpath));
655 outsize = set_message(outbuf,0,0,True);
657 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
663 /****************************************************************************
665 ****************************************************************************/
666 int reply_getatr(char *inbuf,char *outbuf)
676 BOOL bad_path = False;
678 cnum = SVAL(inbuf,smb_tid);
680 pstrcpy(fname,smb_buf(inbuf) + 1);
681 unix_convert(fname,cnum,0,&bad_path);
683 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
684 under WfWg - weird! */
687 mode = aHIDDEN | aDIR;
688 if (!CAN_WRITE(cnum)) mode |= aRONLY;
694 if (check_name(fname,cnum))
696 if (sys_stat(fname,&sbuf) == 0)
698 mode = dos_mode(cnum,fname,&sbuf);
700 mtime = sbuf.st_mtime;
706 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
711 if((errno == ENOENT) && bad_path)
713 unix_ERR_class = ERRDOS;
714 unix_ERR_code = ERRbadpath;
717 return(UNIXERROR(ERRDOS,ERRbadfile));
720 outsize = set_message(outbuf,10,0,True);
722 SSVAL(outbuf,smb_vwv0,mode);
723 put_dos_date3(outbuf,smb_vwv1,mtime);
724 SIVAL(outbuf,smb_vwv3,size);
726 if (Protocol >= PROTOCOL_NT1) {
727 char *p = strrchr(fname,'/');
728 uint16 flg2 = SVAL(outbuf,smb_flg2);
730 if (!is_8_3(fname, True))
731 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
734 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
740 /****************************************************************************
742 ****************************************************************************/
743 int reply_setatr(char *inbuf,char *outbuf)
751 BOOL bad_path = False;
753 cnum = SVAL(inbuf,smb_tid);
755 pstrcpy(fname,smb_buf(inbuf) + 1);
756 unix_convert(fname,cnum,0,&bad_path);
758 mode = SVAL(inbuf,smb_vwv0);
759 mtime = make_unix_date3(inbuf+smb_vwv1);
761 if (directory_exist(fname,NULL))
763 if (check_name(fname,cnum))
764 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
766 ok = set_filetime(fname,mtime);
770 if((errno == ENOENT) && bad_path)
772 unix_ERR_class = ERRDOS;
773 unix_ERR_code = ERRbadpath;
776 return(UNIXERROR(ERRDOS,ERRnoaccess));
779 outsize = set_message(outbuf,0,0,True);
781 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
787 /****************************************************************************
789 ****************************************************************************/
790 int reply_dskattr(char *inbuf,char *outbuf)
794 int dfree,dsize,bsize;
796 cnum = SVAL(inbuf,smb_tid);
798 sys_disk_free(".",&bsize,&dfree,&dsize);
800 outsize = set_message(outbuf,5,0,True);
802 SSVAL(outbuf,smb_vwv0,dsize);
803 SSVAL(outbuf,smb_vwv1,bsize/512);
804 SSVAL(outbuf,smb_vwv2,512);
805 SSVAL(outbuf,smb_vwv3,dfree);
807 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
813 /****************************************************************************
815 Can be called from SMBsearch, SMBffirst or SMBfunique.
816 ****************************************************************************/
817 int reply_search(char *inbuf,char *outbuf)
828 BOOL finished = False;
837 BOOL check_descend = False;
838 BOOL expect_close = False;
839 BOOL can_open = True;
840 BOOL bad_path = False;
842 *mask = *directory = *fname = 0;
844 /* If we were called as SMBffirst then we must expect close. */
845 if(CVAL(inbuf,smb_com) == SMBffirst)
848 cnum = SVAL(inbuf,smb_tid);
850 outsize = set_message(outbuf,1,3,True);
851 maxentries = SVAL(inbuf,smb_vwv0);
852 dirtype = SVAL(inbuf,smb_vwv1);
853 path = smb_buf(inbuf) + 1;
854 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
857 /* dirtype &= ~aDIR; */
859 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
866 pstrcpy(directory,smb_buf(inbuf)+1);
867 pstrcpy(dir2,smb_buf(inbuf)+1);
868 unix_convert(directory,cnum,0,&bad_path);
871 if (!check_name(directory,cnum))
874 p = strrchr(dir2,'/');
886 p = strrchr(directory,'/');
892 if (strlen(directory) == 0)
893 strcpy(directory,"./");
895 CVAL(status,0) = dirtype;
899 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
900 memcpy(mask,status+1,11);
902 dirtype = CVAL(status,0) & 0x1F;
903 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
904 if (!Connections[cnum].dirptr)
906 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
911 /* turn strings of spaces into a . */
913 trim_string(mask,NULL," ");
914 if ((p = strrchr(mask,' ')))
919 trim_string(mask,NULL," ");
926 for (p=mask; *p; p++)
928 if (*p != '?' && *p != '*' && !isdoschar(*p))
930 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
936 if (!strchr(mask,'.') && strlen(mask)>8)
939 fstrcpy(tmp,&mask[8]);
945 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
949 p = smb_buf(outbuf) + 3;
955 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
960 if((errno == ENOENT) && bad_path)
962 unix_ERR_class = ERRDOS;
963 unix_ERR_code = ERRbadpath;
965 return (UNIXERROR(ERRDOS,ERRnofids));
967 return(ERROR(ERRDOS,ERRnofids));
971 DEBUG(4,("dptr_num is %d\n",dptr_num));
975 if ((dirtype&0x1F) == aVOLID)
978 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
979 dptr_fill(p+12,dptr_num);
980 if (dptr_zero(p+12) && (status_len==0))
984 p += DIR_STRUCT_SIZE;
988 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
989 if (in_list(Connections[cnum].dirpath,
990 lp_dontdescend(SNUM(cnum)),True))
991 check_descend = True;
993 for (i=numentries;(i<maxentries) && !finished;i++)
996 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
1000 make_dir_struct(p,mask,fname,size,mode,date);
1001 dptr_fill(p+12,dptr_num);
1004 p += DIR_STRUCT_SIZE;
1013 if (numentries == 0 || !ok)
1015 CVAL(outbuf,smb_rcls) = ERRDOS;
1016 SSVAL(outbuf,smb_err,ERRnofiles);
1019 /* If we were called as SMBffirst with smb_search_id == NULL
1020 and no entries were found then return error and close dirptr
1023 if(ok && expect_close && numentries == 0 && status_len == 0)
1025 CVAL(outbuf,smb_rcls) = ERRDOS;
1026 SSVAL(outbuf,smb_err,ERRnofiles);
1027 /* Also close the dptr - we know it's gone */
1028 dptr_close(dptr_num);
1031 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1032 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1033 dptr_close(dptr_num);
1035 SSVAL(outbuf,smb_vwv0,numentries);
1036 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1037 CVAL(smb_buf(outbuf),0) = 5;
1038 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1040 if (Protocol >= PROTOCOL_NT1) {
1041 uint16 flg2 = SVAL(outbuf,smb_flg2);
1042 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1045 outsize += DIR_STRUCT_SIZE*numentries;
1046 smb_setlen(outbuf,outsize - 4);
1048 if ((! *directory) && dptr_path(dptr_num))
1049 sprintf(directory,"(%s)",dptr_path(dptr_num));
1051 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1053 smb_fn_name(CVAL(inbuf,smb_com)),
1054 mask,directory,cnum,dirtype,numentries,maxentries));
1060 /****************************************************************************
1061 reply to a fclose (stop directory search)
1062 ****************************************************************************/
1063 int reply_fclose(char *inbuf,char *outbuf)
1072 cnum = SVAL(inbuf,smb_tid);
1074 outsize = set_message(outbuf,1,0,True);
1075 path = smb_buf(inbuf) + 1;
1076 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1079 if (status_len == 0)
1080 return(ERROR(ERRSRV,ERRsrverror));
1082 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1084 if(dptr_fetch(status+12,&dptr_num)) {
1085 /* Close the dptr - we know it's gone */
1086 dptr_close(dptr_num);
1089 SSVAL(outbuf,smb_vwv0,0);
1091 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1097 /****************************************************************************
1099 ****************************************************************************/
1100 int reply_open(char *inbuf,char *outbuf)
1113 BOOL bad_path = False;
1115 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1117 cnum = SVAL(inbuf,smb_tid);
1119 share_mode = SVAL(inbuf,smb_vwv0);
1121 pstrcpy(fname,smb_buf(inbuf)+1);
1122 unix_convert(fname,cnum,0,&bad_path);
1124 fnum = find_free_file();
1126 return(ERROR(ERRSRV,ERRnofids));
1128 if (!check_name(fname,cnum))
1130 if((errno == ENOENT) && bad_path)
1132 unix_ERR_class = ERRDOS;
1133 unix_ERR_code = ERRbadpath;
1135 return(UNIXERROR(ERRDOS,ERRnoaccess));
1138 unixmode = unix_mode(cnum,aARCH);
1140 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1141 oplock_request,&rmode,NULL);
1147 if((errno == ENOENT) && bad_path)
1149 unix_ERR_class = ERRDOS;
1150 unix_ERR_code = ERRbadpath;
1152 return(UNIXERROR(ERRDOS,ERRnoaccess));
1155 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1157 return(ERROR(ERRDOS,ERRnoaccess));
1160 size = sbuf.st_size;
1161 fmode = dos_mode(cnum,fname,&sbuf);
1162 mtime = sbuf.st_mtime;
1165 DEBUG(3,("attempt to open a directory %s\n",fname));
1167 return(ERROR(ERRDOS,ERRnoaccess));
1170 outsize = set_message(outbuf,7,0,True);
1171 SSVAL(outbuf,smb_vwv0,fnum);
1172 SSVAL(outbuf,smb_vwv1,fmode);
1173 put_dos_date3(outbuf,smb_vwv2,mtime);
1174 SIVAL(outbuf,smb_vwv4,size);
1175 SSVAL(outbuf,smb_vwv6,rmode);
1177 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1178 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1181 if(fsp->granted_oplock)
1182 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1187 /****************************************************************************
1188 reply to an open and X
1189 ****************************************************************************/
1190 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1193 int cnum = SVAL(inbuf,smb_tid);
1195 int smb_mode = SVAL(inbuf,smb_vwv3);
1196 int smb_attr = SVAL(inbuf,smb_vwv5);
1197 BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1199 int open_flags = SVAL(inbuf,smb_vwv2);
1200 int smb_sattr = SVAL(inbuf,smb_vwv4);
1201 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1203 int smb_ofun = SVAL(inbuf,smb_vwv8);
1205 int size=0,fmode=0,mtime=0,rmode=0;
1208 BOOL bad_path = False;
1211 /* If it's an IPC, pass off the pipe handler. */
1213 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1215 /* XXXX we need to handle passed times, sattr and flags */
1217 pstrcpy(fname,smb_buf(inbuf));
1218 unix_convert(fname,cnum,0,&bad_path);
1220 fnum = find_free_file();
1222 return(ERROR(ERRSRV,ERRnofids));
1224 if (!check_name(fname,cnum))
1226 if((errno == ENOENT) && bad_path)
1228 unix_ERR_class = ERRDOS;
1229 unix_ERR_code = ERRbadpath;
1231 return(UNIXERROR(ERRDOS,ERRnoaccess));
1234 unixmode = unix_mode(cnum,smb_attr | aARCH);
1236 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1237 oplock_request, &rmode,&smb_action);
1243 if((errno == ENOENT) && bad_path)
1245 unix_ERR_class = ERRDOS;
1246 unix_ERR_code = ERRbadpath;
1248 return(UNIXERROR(ERRDOS,ERRnoaccess));
1251 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1253 return(ERROR(ERRDOS,ERRnoaccess));
1256 size = sbuf.st_size;
1257 fmode = dos_mode(cnum,fname,&sbuf);
1258 mtime = sbuf.st_mtime;
1261 return(ERROR(ERRDOS,ERRnoaccess));
1264 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1265 smb_action |= EXTENDED_OPLOCK_GRANTED;
1266 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1269 if(fsp->granted_oplock) {
1270 smb_action |= EXTENDED_OPLOCK_GRANTED;
1271 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1274 set_message(outbuf,15,0,True);
1275 SSVAL(outbuf,smb_vwv2,fnum);
1276 SSVAL(outbuf,smb_vwv3,fmode);
1277 put_dos_date3(outbuf,smb_vwv4,mtime);
1278 SIVAL(outbuf,smb_vwv6,size);
1279 SSVAL(outbuf,smb_vwv8,rmode);
1280 SSVAL(outbuf,smb_vwv11,smb_action);
1284 return chain_reply(inbuf,outbuf,length,bufsize);
1288 /****************************************************************************
1289 reply to a SMBulogoffX
1290 ****************************************************************************/
1291 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1293 uint16 vuid = SVAL(inbuf,smb_uid);
1294 user_struct *vuser = get_valid_user_struct(vuid);
1297 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1300 /* in user level security we are supposed to close any files
1301 open by this user */
1302 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1304 for (i=0;i<MAX_OPEN_FILES;i++)
1305 if (Files[i].uid == vuser->uid && Files[i].open) {
1310 invalidate_vuid(vuid);
1312 set_message(outbuf,2,0,True);
1314 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1316 return chain_reply(inbuf,outbuf,length,bufsize);
1320 /****************************************************************************
1321 reply to a mknew or a create
1322 ****************************************************************************/
1323 int reply_mknew(char *inbuf,char *outbuf)
1332 BOOL bad_path = False;
1334 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1336 com = SVAL(inbuf,smb_com);
1337 cnum = SVAL(inbuf,smb_tid);
1339 createmode = SVAL(inbuf,smb_vwv0);
1340 pstrcpy(fname,smb_buf(inbuf)+1);
1341 unix_convert(fname,cnum,0,&bad_path);
1343 if (createmode & aVOLID)
1345 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1348 unixmode = unix_mode(cnum,createmode);
1350 fnum = find_free_file();
1352 return(ERROR(ERRSRV,ERRnofids));
1354 if (!check_name(fname,cnum))
1356 if((errno == ENOENT) && bad_path)
1358 unix_ERR_class = ERRDOS;
1359 unix_ERR_code = ERRbadpath;
1361 return(UNIXERROR(ERRDOS,ERRnoaccess));
1366 /* We should fail if file exists. */
1371 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1375 /* Open file in dos compatibility share mode. */
1376 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1377 oplock_request, NULL, NULL);
1383 if((errno == ENOENT) && bad_path)
1385 unix_ERR_class = ERRDOS;
1386 unix_ERR_code = ERRbadpath;
1388 return(UNIXERROR(ERRDOS,ERRnoaccess));
1391 outsize = set_message(outbuf,1,0,True);
1392 SSVAL(outbuf,smb_vwv0,fnum);
1394 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1395 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1398 if(fsp->granted_oplock)
1399 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1401 DEBUG(2,("new file %s\n",fname));
1402 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));
1408 /****************************************************************************
1409 reply to a create temporary file
1410 ****************************************************************************/
1411 int reply_ctemp(char *inbuf,char *outbuf)
1420 BOOL bad_path = False;
1422 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1424 cnum = SVAL(inbuf,smb_tid);
1425 createmode = SVAL(inbuf,smb_vwv0);
1426 pstrcpy(fname,smb_buf(inbuf)+1);
1427 strcat(fname,"/TMXXXXXX");
1428 unix_convert(fname,cnum,0,&bad_path);
1430 unixmode = unix_mode(cnum,createmode);
1432 fnum = find_free_file();
1434 return(ERROR(ERRSRV,ERRnofids));
1436 if (!check_name(fname,cnum))
1438 if((errno == ENOENT) && bad_path)
1440 unix_ERR_class = ERRDOS;
1441 unix_ERR_code = ERRbadpath;
1443 return(UNIXERROR(ERRDOS,ERRnoaccess));
1446 strcpy(fname2,(char *)mktemp(fname));
1448 /* Open file in dos compatibility share mode. */
1449 /* We should fail if file exists. */
1450 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1451 oplock_request, NULL, NULL);
1457 if((errno == ENOENT) && bad_path)
1459 unix_ERR_class = ERRDOS;
1460 unix_ERR_code = ERRbadpath;
1462 return(UNIXERROR(ERRDOS,ERRnoaccess));
1465 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1466 SSVAL(outbuf,smb_vwv0,fnum);
1467 CVAL(smb_buf(outbuf),0) = 4;
1468 strcpy(smb_buf(outbuf) + 1,fname2);
1470 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1471 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1474 if(fsp->granted_oplock)
1475 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1477 DEBUG(2,("created temp file %s\n",fname2));
1478 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));
1484 /*******************************************************************
1485 check if a user is allowed to delete a file
1486 ********************************************************************/
1487 static BOOL can_delete(char *fname,int cnum,int dirtype)
1492 if (!CAN_WRITE(cnum)) return(False);
1494 if (sys_lstat(fname,&sbuf) != 0) return(False);
1495 fmode = dos_mode(cnum,fname,&sbuf);
1496 if (fmode & aDIR) return(False);
1497 if (!lp_delete_readonly(SNUM(cnum))) {
1498 if (fmode & aRONLY) return(False);
1500 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1502 if (!check_file_sharing(cnum,fname)) return(False);
1506 /****************************************************************************
1508 ****************************************************************************/
1509 int reply_unlink(char *inbuf,char *outbuf)
1519 int error = ERRnoaccess;
1522 BOOL bad_path = False;
1524 *directory = *mask = 0;
1526 cnum = SVAL(inbuf,smb_tid);
1527 dirtype = SVAL(inbuf,smb_vwv0);
1529 pstrcpy(name,smb_buf(inbuf) + 1);
1531 DEBUG(3,("reply_unlink : %s\n",name));
1533 unix_convert(name,cnum,0,&bad_path);
1535 p = strrchr(name,'/');
1537 strcpy(directory,"./");
1541 strcpy(directory,name);
1545 if (is_mangled(mask))
1546 check_mangled_stack(mask);
1548 has_wild = strchr(mask,'*') || strchr(mask,'?');
1551 strcat(directory,"/");
1552 strcat(directory,mask);
1553 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1554 if (!count) exists = file_exist(directory,NULL);
1556 void *dirptr = NULL;
1559 if (check_name(directory,cnum))
1560 dirptr = OpenDir(cnum, directory, True);
1562 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1563 the pattern matches against the long name, otherwise the short name
1564 We don't implement this yet XXXX
1571 if (strequal(mask,"????????.???"))
1574 while ((dname = ReadDirName(dirptr)))
1577 pstrcpy(fname,dname);
1579 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1581 error = ERRnoaccess;
1582 sprintf(fname,"%s/%s",directory,dname);
1583 if (!can_delete(fname,cnum,dirtype)) continue;
1584 if (!sys_unlink(fname)) count++;
1585 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1593 return(ERROR(ERRDOS,error));
1596 if((errno == ENOENT) && bad_path)
1598 unix_ERR_class = ERRDOS;
1599 unix_ERR_code = ERRbadpath;
1601 return(UNIXERROR(ERRDOS,error));
1605 outsize = set_message(outbuf,0,0,True);
1611 /****************************************************************************
1612 reply to a readbraw (core+ protocol)
1613 ****************************************************************************/
1614 int reply_readbraw(char *inbuf, char *outbuf)
1616 int cnum,maxcount,mincount,fnum;
1619 char *header = outbuf;
1625 * Special check if an oplock break has been issued
1626 * and the readraw request croses on the wire, we must
1627 * return a zero length response here.
1630 if(global_oplock_break)
1632 _smb_setlen(header,0);
1633 transfer_file(0,Client,0,header,4,0);
1634 DEBUG(5,("readbraw - oplock break finished\n"));
1638 cnum = SVAL(inbuf,smb_tid);
1639 fnum = GETFNUM(inbuf,smb_vwv0);
1641 startpos = IVAL(inbuf,smb_vwv1);
1642 maxcount = SVAL(inbuf,smb_vwv3);
1643 mincount = SVAL(inbuf,smb_vwv4);
1645 /* ensure we don't overrun the packet size */
1646 maxcount = MIN(65535,maxcount);
1647 maxcount = MAX(mincount,maxcount);
1649 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1651 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1652 _smb_setlen(header,0);
1653 transfer_file(0,Client,0,header,4,0);
1658 fd = Files[fnum].fd_ptr->fd;
1659 fname = Files[fnum].name;
1663 if (!is_locked(fnum,cnum,maxcount,startpos))
1665 int size = Files[fnum].size;
1666 int sizeneeded = startpos + maxcount;
1668 if (size < sizeneeded) {
1670 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1672 if (!Files[fnum].can_write)
1673 Files[fnum].size = size;
1676 nread = MIN(maxcount,(int)(size - startpos));
1679 if (nread < mincount)
1682 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1685 maxcount,mincount,nread));
1690 _smb_setlen(header,nread);
1692 if (!Files[fnum].can_write)
1693 predict = read_predict(fd,startpos,header+4,NULL,nread);
1695 if ((nread-predict) > 0)
1696 seek_file(fnum,startpos + predict);
1698 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1703 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1704 fname,startpos,nread,ret));
1707 ret = read_file(fnum,header+4,startpos,nread);
1708 if (ret < mincount) ret = 0;
1710 _smb_setlen(header,ret);
1711 transfer_file(0,Client,0,header,4+ret,0);
1714 DEBUG(5,("readbraw finished\n"));
1719 /****************************************************************************
1720 reply to a lockread (core+ protocol)
1721 ****************************************************************************/
1722 int reply_lockread(char *inbuf,char *outbuf)
1728 uint32 startpos, numtoread;
1732 cnum = SVAL(inbuf,smb_tid);
1733 fnum = GETFNUM(inbuf,smb_vwv0);
1735 CHECK_FNUM(fnum,cnum);
1739 numtoread = SVAL(inbuf,smb_vwv1);
1740 startpos = IVAL(inbuf,smb_vwv2);
1742 outsize = set_message(outbuf,5,3,True);
1743 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1744 data = smb_buf(outbuf) + 3;
1746 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1747 return (ERROR(eclass,ecode));
1749 nread = read_file(fnum,data,startpos,numtoread);
1752 return(UNIXERROR(ERRDOS,ERRnoaccess));
1755 SSVAL(outbuf,smb_vwv0,nread);
1756 SSVAL(outbuf,smb_vwv5,nread+3);
1757 SSVAL(smb_buf(outbuf),1,nread);
1759 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1765 /****************************************************************************
1767 ****************************************************************************/
1768 int reply_read(char *inbuf,char *outbuf)
1770 int cnum,numtoread,fnum;
1776 cnum = SVAL(inbuf,smb_tid);
1777 fnum = GETFNUM(inbuf,smb_vwv0);
1779 CHECK_FNUM(fnum,cnum);
1783 numtoread = SVAL(inbuf,smb_vwv1);
1784 startpos = IVAL(inbuf,smb_vwv2);
1786 outsize = set_message(outbuf,5,3,True);
1787 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1788 data = smb_buf(outbuf) + 3;
1790 if (is_locked(fnum,cnum,numtoread,startpos))
1791 return(ERROR(ERRDOS,ERRlock));
1794 nread = read_file(fnum,data,startpos,numtoread);
1797 return(UNIXERROR(ERRDOS,ERRnoaccess));
1800 SSVAL(outbuf,smb_vwv0,nread);
1801 SSVAL(outbuf,smb_vwv5,nread+3);
1802 CVAL(smb_buf(outbuf),0) = 1;
1803 SSVAL(smb_buf(outbuf),1,nread);
1805 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1811 /****************************************************************************
1812 reply to a read and X
1813 ****************************************************************************/
1814 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1816 int fnum = GETFNUM(inbuf,smb_vwv2);
1817 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1818 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1819 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1825 cnum = SVAL(inbuf,smb_tid);
1827 CHECK_FNUM(fnum,cnum);
1831 set_message(outbuf,12,0,True);
1832 data = smb_buf(outbuf);
1834 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1835 return(ERROR(ERRDOS,ERRlock));
1836 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1840 return(UNIXERROR(ERRDOS,ERRnoaccess));
1842 SSVAL(outbuf,smb_vwv5,nread);
1843 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1844 SSVAL(smb_buf(outbuf),-2,nread);
1846 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1847 timestring(),fnum,cnum,
1848 smb_mincnt,smb_maxcnt,nread));
1852 return chain_reply(inbuf,outbuf,length,bufsize);
1856 /****************************************************************************
1857 reply to a writebraw (core+ or LANMAN1.0 protocol)
1858 ****************************************************************************/
1859 int reply_writebraw(char *inbuf,char *outbuf)
1862 int total_written=0;
1871 cnum = SVAL(inbuf,smb_tid);
1872 fnum = GETFNUM(inbuf,smb_vwv0);
1874 CHECK_FNUM(fnum,cnum);
1878 tcount = IVAL(inbuf,smb_vwv1);
1879 startpos = IVAL(inbuf,smb_vwv3);
1880 write_through = BITSETW(inbuf+smb_vwv7,0);
1882 /* We have to deal with slightly different formats depending
1883 on whether we are using the core+ or lanman1.0 protocol */
1884 if(Protocol <= PROTOCOL_COREPLUS) {
1885 numtowrite = SVAL(smb_buf(inbuf),-2);
1886 data = smb_buf(inbuf);
1888 numtowrite = SVAL(inbuf,smb_vwv10);
1889 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1892 /* force the error type */
1893 CVAL(inbuf,smb_com) = SMBwritec;
1894 CVAL(outbuf,smb_com) = SMBwritec;
1896 if (is_locked(fnum,cnum,tcount,startpos))
1897 return(ERROR(ERRDOS,ERRlock));
1899 if (seek_file(fnum,startpos) != startpos)
1900 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1903 nwritten = write_file(fnum,data,numtowrite);
1905 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1906 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1908 if (nwritten < numtowrite)
1909 return(UNIXERROR(ERRHRD,ERRdiskfull));
1911 total_written = nwritten;
1913 /* Return a message to the redirector to tell it
1914 to send more bytes */
1915 CVAL(outbuf,smb_com) = SMBwritebraw;
1916 SSVALS(outbuf,smb_vwv0,-1);
1917 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1918 send_smb(Client,outbuf);
1920 /* Now read the raw data into the buffer and write it */
1921 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1922 exit_server("secondary writebraw failed");
1925 /* Even though this is not an smb message, smb_len
1926 returns the generic length of an smb message */
1927 numtowrite = smb_len(inbuf);
1929 if (tcount > nwritten+numtowrite) {
1930 DEBUG(3,("Client overestimated the write %d %d %d\n",
1931 tcount,nwritten,numtowrite));
1934 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1936 total_written += nwritten;
1938 /* Set up outbuf to return the correct return */
1939 outsize = set_message(outbuf,1,0,True);
1940 CVAL(outbuf,smb_com) = SMBwritec;
1941 SSVAL(outbuf,smb_vwv0,total_written);
1943 if (nwritten < numtowrite) {
1944 CVAL(outbuf,smb_rcls) = ERRHRD;
1945 SSVAL(outbuf,smb_err,ERRdiskfull);
1948 if (lp_syncalways(SNUM(cnum)) || write_through)
1951 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1952 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1954 /* we won't return a status if write through is not selected - this
1955 follows what WfWg does */
1956 if (!write_through && total_written==tcount)
1963 /****************************************************************************
1964 reply to a writeunlock (core+)
1965 ****************************************************************************/
1966 int reply_writeunlock(char *inbuf,char *outbuf)
1972 uint32 numtowrite,startpos;
1976 cnum = SVAL(inbuf,smb_tid);
1977 fnum = GETFNUM(inbuf,smb_vwv0);
1979 CHECK_FNUM(fnum,cnum);
1983 numtowrite = SVAL(inbuf,smb_vwv1);
1984 startpos = IVAL(inbuf,smb_vwv2);
1985 data = smb_buf(inbuf) + 3;
1987 if (is_locked(fnum,cnum,numtowrite,startpos))
1988 return(ERROR(ERRDOS,ERRlock));
1990 seek_file(fnum,startpos);
1992 /* The special X/Open SMB protocol handling of
1993 zero length writes is *NOT* done for
1998 nwritten = write_file(fnum,data,numtowrite);
2000 if (lp_syncalways(SNUM(cnum)))
2003 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2004 return(UNIXERROR(ERRDOS,ERRnoaccess));
2006 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2007 return(ERROR(eclass,ecode));
2009 outsize = set_message(outbuf,1,0,True);
2011 SSVAL(outbuf,smb_vwv0,nwritten);
2013 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2014 timestring(),fnum,cnum,numtowrite,nwritten));
2020 /****************************************************************************
2022 ****************************************************************************/
2023 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
2025 int cnum,numtowrite,fnum;
2034 cnum = SVAL(inbuf,smb_tid);
2035 fnum = GETFNUM(inbuf,smb_vwv0);
2037 CHECK_FNUM(fnum,cnum);
2041 numtowrite = SVAL(inbuf,smb_vwv1);
2042 startpos = IVAL(inbuf,smb_vwv2);
2043 data = smb_buf(inbuf) + 3;
2045 if (is_locked(fnum,cnum,numtowrite,startpos))
2046 return(ERROR(ERRDOS,ERRlock));
2048 seek_file(fnum,startpos);
2050 /* X/Open SMB protocol says that if smb_vwv1 is
2051 zero then the file size should be extended or
2052 truncated to the size given in smb_vwv[2-3] */
2054 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2056 nwritten = write_file(fnum,data,numtowrite);
2058 if (lp_syncalways(SNUM(cnum)))
2061 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2062 return(UNIXERROR(ERRDOS,ERRnoaccess));
2064 outsize = set_message(outbuf,1,0,True);
2066 SSVAL(outbuf,smb_vwv0,nwritten);
2068 if (nwritten < numtowrite) {
2069 CVAL(outbuf,smb_rcls) = ERRHRD;
2070 SSVAL(outbuf,smb_err,ERRdiskfull);
2073 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2079 /****************************************************************************
2080 reply to a write and X
2081 ****************************************************************************/
2082 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2084 int fnum = GETFNUM(inbuf,smb_vwv2);
2085 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2086 int smb_dsize = SVAL(inbuf,smb_vwv10);
2087 int smb_doff = SVAL(inbuf,smb_vwv11);
2088 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2093 cnum = SVAL(inbuf,smb_tid);
2095 CHECK_FNUM(fnum,cnum);
2099 data = smb_base(inbuf) + smb_doff;
2101 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2102 return(ERROR(ERRDOS,ERRlock));
2104 seek_file(fnum,smb_offs);
2106 /* X/Open SMB protocol says that, unlike SMBwrite
2107 if the length is zero then NO truncation is
2108 done, just a write of zero. To truncate a file,
2113 nwritten = write_file(fnum,data,smb_dsize);
2115 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2116 return(UNIXERROR(ERRDOS,ERRnoaccess));
2118 set_message(outbuf,6,0,True);
2120 SSVAL(outbuf,smb_vwv2,nwritten);
2122 if (nwritten < smb_dsize) {
2123 CVAL(outbuf,smb_rcls) = ERRHRD;
2124 SSVAL(outbuf,smb_err,ERRdiskfull);
2127 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2131 if (lp_syncalways(SNUM(cnum)) || write_through)
2134 return chain_reply(inbuf,outbuf,length,bufsize);
2138 /****************************************************************************
2140 ****************************************************************************/
2141 int reply_lseek(char *inbuf,char *outbuf)
2149 cnum = SVAL(inbuf,smb_tid);
2150 fnum = GETFNUM(inbuf,smb_vwv0);
2152 CHECK_FNUM(fnum,cnum);
2155 mode = SVAL(inbuf,smb_vwv1) & 3;
2156 startpos = IVAL(inbuf,smb_vwv2);
2160 case 0: umode = SEEK_SET; break;
2161 case 1: umode = SEEK_CUR; break;
2162 case 2: umode = SEEK_END; break;
2164 umode = SEEK_SET; break;
2167 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2168 Files[fnum].pos = res;
2170 outsize = set_message(outbuf,2,0,True);
2171 SIVALS(outbuf,smb_vwv0,res);
2173 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2179 /****************************************************************************
2181 ****************************************************************************/
2182 int reply_flush(char *inbuf,char *outbuf)
2185 int outsize = set_message(outbuf,0,0,True);
2187 cnum = SVAL(inbuf,smb_tid);
2188 fnum = GETFNUM(inbuf,smb_vwv0);
2190 if (fnum != 0xFFFF) {
2191 CHECK_FNUM(fnum,cnum);
2198 for (i=0;i<MAX_OPEN_FILES;i++)
2205 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2210 /****************************************************************************
2212 ****************************************************************************/
2213 int reply_exit(char *inbuf,char *outbuf)
2215 int outsize = set_message(outbuf,0,0,True);
2216 DEBUG(3,("%s exit\n",timestring()));
2222 /****************************************************************************
2224 ****************************************************************************/
2225 int reply_close(char *inbuf,char *outbuf)
2230 int32 eclass = 0, err = 0;
2232 outsize = set_message(outbuf,0,0,True);
2234 cnum = SVAL(inbuf,smb_tid);
2236 fnum = GETFNUM(inbuf,smb_vwv0);
2237 CHECK_FNUM(fnum,cnum);
2239 if(HAS_CACHED_ERROR(fnum)) {
2240 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2241 err = Files[fnum].wbmpx_ptr->wr_error;
2244 mtime = make_unix_date3(inbuf+smb_vwv1);
2246 /* try and set the date */
2247 set_filetime(Files[fnum].name,mtime);
2251 /* We have a cached error */
2253 return(ERROR(eclass,err));
2255 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2256 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2257 Connections[cnum].num_files_open));
2263 /****************************************************************************
2264 reply to a writeclose (Core+ protocol)
2265 ****************************************************************************/
2266 int reply_writeclose(char *inbuf,char *outbuf)
2268 int cnum,numtowrite,fnum;
2275 cnum = SVAL(inbuf,smb_tid);
2276 fnum = GETFNUM(inbuf,smb_vwv0);
2278 CHECK_FNUM(fnum,cnum);
2282 numtowrite = SVAL(inbuf,smb_vwv1);
2283 startpos = IVAL(inbuf,smb_vwv2);
2284 mtime = make_unix_date3(inbuf+smb_vwv4);
2285 data = smb_buf(inbuf) + 1;
2287 if (is_locked(fnum,cnum,numtowrite,startpos))
2288 return(ERROR(ERRDOS,ERRlock));
2290 seek_file(fnum,startpos);
2292 nwritten = write_file(fnum,data,numtowrite);
2294 set_filetime(Files[fnum].name,mtime);
2298 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2299 timestring(),fnum,cnum,numtowrite,nwritten,
2300 Connections[cnum].num_files_open));
2303 return(UNIXERROR(ERRDOS,ERRnoaccess));
2305 outsize = set_message(outbuf,1,0,True);
2307 SSVAL(outbuf,smb_vwv0,nwritten);
2312 /****************************************************************************
2314 ****************************************************************************/
2315 int reply_lock(char *inbuf,char *outbuf)
2318 int outsize = set_message(outbuf,0,0,True);
2319 uint32 count,offset;
2323 cnum = SVAL(inbuf,smb_tid);
2324 fnum = GETFNUM(inbuf,smb_vwv0);
2326 CHECK_FNUM(fnum,cnum);
2329 count = IVAL(inbuf,smb_vwv1);
2330 offset = IVAL(inbuf,smb_vwv3);
2332 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));
2334 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2335 return (ERROR(eclass,ecode));
2341 /****************************************************************************
2343 ****************************************************************************/
2344 int reply_unlock(char *inbuf,char *outbuf)
2347 int outsize = set_message(outbuf,0,0,True);
2348 uint32 count,offset;
2352 cnum = SVAL(inbuf,smb_tid);
2353 fnum = GETFNUM(inbuf,smb_vwv0);
2355 CHECK_FNUM(fnum,cnum);
2358 count = IVAL(inbuf,smb_vwv1);
2359 offset = IVAL(inbuf,smb_vwv3);
2361 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2362 return (ERROR(eclass,ecode));
2364 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));
2370 /****************************************************************************
2372 ****************************************************************************/
2373 int reply_tdis(char *inbuf,char *outbuf)
2376 int outsize = set_message(outbuf,0,0,True);
2379 cnum = SVAL(inbuf,smb_tid);
2380 vuid = SVAL(inbuf,smb_uid);
2382 if (!OPEN_CNUM(cnum)) {
2383 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2384 return(ERROR(ERRSRV,ERRinvnid));
2387 Connections[cnum].used = False;
2389 close_cnum(cnum,vuid);
2391 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2398 /****************************************************************************
2400 ****************************************************************************/
2401 int reply_echo(char *inbuf,char *outbuf)
2404 int smb_reverb = SVAL(inbuf,smb_vwv0);
2406 int data_len = smb_buflen(inbuf);
2407 int outsize = set_message(outbuf,1,data_len,True);
2409 cnum = SVAL(inbuf,smb_tid);
2411 /* According to the latest CIFS spec we shouldn't
2412 care what the TID is.
2416 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2418 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2419 return(ERROR(ERRSRV,ERRinvnid));
2423 /* copy any incoming data back out */
2425 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2427 if (smb_reverb > 100)
2429 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2433 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2435 SSVAL(outbuf,smb_vwv0,seq_num);
2437 smb_setlen(outbuf,outsize - 4);
2439 send_smb(Client,outbuf);
2442 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2448 /****************************************************************************
2449 reply to a printopen
2450 ****************************************************************************/
2451 int reply_printopen(char *inbuf,char *outbuf)
2459 *fname = *fname2 = 0;
2461 cnum = SVAL(inbuf,smb_tid);
2463 if (!CAN_PRINT(cnum))
2464 return(ERROR(ERRDOS,ERRnoaccess));
2469 pstrcpy(s,smb_buf(inbuf)+1);
2473 if (!(isalnum(*p) || strchr("._-",*p)))
2478 if (strlen(s) > 10) s[10] = 0;
2480 sprintf(fname,"%s.XXXXXX",s);
2483 fnum = find_free_file();
2485 return(ERROR(ERRSRV,ERRnofids));
2487 strcpy(fname2,(char *)mktemp(fname));
2489 if (!check_name(fname2,cnum))
2490 return(ERROR(ERRDOS,ERRnoaccess));
2492 /* Open for exclusive use, write only. */
2493 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2496 if (!Files[fnum].open)
2497 return(UNIXERROR(ERRDOS,ERRnoaccess));
2499 /* force it to be a print file */
2500 Files[fnum].print_file = True;
2502 outsize = set_message(outbuf,1,0,True);
2503 SSVAL(outbuf,smb_vwv0,fnum);
2505 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2511 /****************************************************************************
2512 reply to a printclose
2513 ****************************************************************************/
2514 int reply_printclose(char *inbuf,char *outbuf)
2517 int outsize = set_message(outbuf,0,0,True);
2519 cnum = SVAL(inbuf,smb_tid);
2520 fnum = GETFNUM(inbuf,smb_vwv0);
2522 CHECK_FNUM(fnum,cnum);
2525 if (!CAN_PRINT(cnum))
2526 return(ERROR(ERRDOS,ERRnoaccess));
2530 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2536 /****************************************************************************
2537 reply to a printqueue
2538 ****************************************************************************/
2539 int reply_printqueue(char *inbuf,char *outbuf)
2542 int outsize = set_message(outbuf,2,3,True);
2543 int max_count = SVAL(inbuf,smb_vwv0);
2544 int start_index = SVAL(inbuf,smb_vwv1);
2547 cnum = SVAL(inbuf,smb_tid);
2548 vuid = SVAL(inbuf,smb_uid);
2550 /* allow checking the queue for anyone */
2552 if (!CAN_PRINT(cnum))
2553 return(ERROR(ERRDOS,ERRnoaccess));
2556 SSVAL(outbuf,smb_vwv0,0);
2557 SSVAL(outbuf,smb_vwv1,0);
2558 CVAL(smb_buf(outbuf),0) = 1;
2559 SSVAL(smb_buf(outbuf),1,0);
2561 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2562 timestring(),cnum,start_index,max_count));
2564 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2569 for (i=0;i<MAX_CONNECTIONS;i++)
2570 if (CAN_PRINT(i) && Connections[i].printer)
2574 for (i=0;i<MAX_CONNECTIONS;i++)
2578 if (!OPEN_CNUM(cnum))
2579 return(ERROR(ERRSRV,ERRinvnid));
2581 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2584 if (!become_user(cnum,vuid))
2585 return(ERROR(ERRSRV,ERRinvnid));
2588 print_queue_struct *queue = NULL;
2589 char *p = smb_buf(outbuf) + 3;
2590 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2591 int num_to_get = ABS(max_count);
2592 int first = (max_count>0?start_index:start_index+max_count+1);
2598 num_to_get = MIN(num_to_get,count-first);
2601 for (i=first;i<first+num_to_get;i++)
2603 put_dos_date2(p,0,queue[i].time);
2604 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2605 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2606 SIVAL(p,7,queue[i].size);
2608 StrnCpy(p+12,queue[i].user,16);
2614 outsize = set_message(outbuf,2,28*count+3,False);
2615 SSVAL(outbuf,smb_vwv0,count);
2616 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2617 CVAL(smb_buf(outbuf),0) = 1;
2618 SSVAL(smb_buf(outbuf),1,28*count);
2621 if (queue) free(queue);
2623 DEBUG(3,("%d entries returned in queue\n",count));
2630 /****************************************************************************
2631 reply to a printwrite
2632 ****************************************************************************/
2633 int reply_printwrite(char *inbuf,char *outbuf)
2635 int cnum,numtowrite,fnum;
2636 int outsize = set_message(outbuf,0,0,True);
2639 cnum = SVAL(inbuf,smb_tid);
2641 if (!CAN_PRINT(cnum))
2642 return(ERROR(ERRDOS,ERRnoaccess));
2644 fnum = GETFNUM(inbuf,smb_vwv0);
2646 CHECK_FNUM(fnum,cnum);
2650 numtowrite = SVAL(smb_buf(inbuf),1);
2651 data = smb_buf(inbuf) + 3;
2653 if (write_file(fnum,data,numtowrite) != numtowrite)
2654 return(UNIXERROR(ERRDOS,ERRnoaccess));
2656 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2662 /****************************************************************************
2664 ****************************************************************************/
2665 int reply_mkdir(char *inbuf,char *outbuf)
2669 int outsize,ret= -1;
2670 BOOL bad_path = False;
2672 pstrcpy(directory,smb_buf(inbuf) + 1);
2673 cnum = SVAL(inbuf,smb_tid);
2674 unix_convert(directory,cnum,0,&bad_path);
2676 if (check_name(directory,cnum))
2677 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2681 if((errno == ENOENT) && bad_path)
2683 unix_ERR_class = ERRDOS;
2684 unix_ERR_code = ERRbadpath;
2686 return(UNIXERROR(ERRDOS,ERRnoaccess));
2689 outsize = set_message(outbuf,0,0,True);
2691 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2696 /****************************************************************************
2697 Static function used by reply_rmdir to delete an entire directory
2699 ****************************************************************************/
2700 static BOOL recursive_rmdir(char *directory)
2704 void *dirptr = OpenDir(-1, directory, False);
2709 while((dname = ReadDirName(dirptr)))
2714 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2717 /* Construct the full name. */
2718 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2724 strcpy(fullname, directory);
2725 strcat(fullname, "/");
2726 strcat(fullname, dname);
2728 if(sys_lstat(fullname, &st) != 0)
2734 if(st.st_mode & S_IFDIR)
2736 if(recursive_rmdir(fullname)!=0)
2741 if(sys_rmdir(fullname) != 0)
2747 else if(sys_unlink(fullname) != 0)
2757 /****************************************************************************
2759 ****************************************************************************/
2760 int reply_rmdir(char *inbuf,char *outbuf)
2766 BOOL bad_path = False;
2768 cnum = SVAL(inbuf,smb_tid);
2769 pstrcpy(directory,smb_buf(inbuf) + 1);
2770 unix_convert(directory,cnum,0,&bad_path);
2772 if (check_name(directory,cnum))
2775 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2776 ok = (sys_rmdir(directory) == 0);
2777 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2779 /* Check to see if the only thing in this directory are
2780 vetoed files/directories. If so then delete them and
2781 retry. If we fail to delete any of them (and we *don't*
2782 do a recursive delete) then fail the rmdir. */
2783 BOOL all_veto_files = True;
2785 void *dirptr = OpenDir(cnum, directory, False);
2789 int dirpos = TellDir(dirptr);
2790 while ((dname = ReadDirName(dirptr)))
2792 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2794 if(!IS_VETO_PATH(cnum, dname))
2796 all_veto_files = False;
2802 SeekDir(dirptr,dirpos);
2803 while ((dname = ReadDirName(dirptr)))
2808 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2811 /* Construct the full name. */
2812 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2817 pstrcpy(fullname, directory);
2818 strcat(fullname, "/");
2819 strcat(fullname, dname);
2821 if(sys_lstat(fullname, &st) != 0)
2823 if(st.st_mode & S_IFDIR)
2825 if(lp_recursive_veto_delete(SNUM(cnum)))
2827 if(recursive_rmdir(fullname) != 0)
2830 if(sys_rmdir(fullname) != 0)
2833 else if(sys_unlink(fullname) != 0)
2837 /* Retry the rmdir */
2838 ok = (sys_rmdir(directory) == 0);
2848 DEBUG(3,("couldn't remove directory %s : %s\n",
2849 directory,strerror(errno)));
2854 if((errno == ENOENT) && bad_path)
2856 unix_ERR_class = ERRDOS;
2857 unix_ERR_code = ERRbadpath;
2859 return(UNIXERROR(ERRDOS,ERRbadpath));
2862 outsize = set_message(outbuf,0,0,True);
2864 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2870 /*******************************************************************
2871 resolve wildcards in a filename rename
2872 ********************************************************************/
2873 static BOOL resolve_wildcards(char *name1,char *name2)
2875 fstring root1,root2;
2879 name1 = strrchr(name1,'/');
2880 name2 = strrchr(name2,'/');
2882 if (!name1 || !name2) return(False);
2884 fstrcpy(root1,name1);
2885 fstrcpy(root2,name2);
2886 p = strrchr(root1,'.');
2893 p = strrchr(root2,'.');
2925 strcpy(name2,root2);
2934 /*******************************************************************
2935 check if a user is allowed to rename a file
2936 ********************************************************************/
2937 static BOOL can_rename(char *fname,int cnum)
2941 if (!CAN_WRITE(cnum)) return(False);
2943 if (sys_lstat(fname,&sbuf) != 0) return(False);
2944 if (!check_file_sharing(cnum,fname)) return(False);
2949 /****************************************************************************
2951 ****************************************************************************/
2952 int reply_mv(char *inbuf,char *outbuf)
2958 pstring mask,newname;
2959 pstring newname_last_component;
2962 int error = ERRnoaccess;
2965 BOOL bad_path1 = False;
2966 BOOL bad_path2 = False;
2968 *directory = *mask = 0;
2970 cnum = SVAL(inbuf,smb_tid);
2972 pstrcpy(name,smb_buf(inbuf) + 1);
2973 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2975 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2977 unix_convert(name,cnum,0,&bad_path1);
2978 unix_convert(newname,cnum,newname_last_component,&bad_path2);
2981 * Split the old name into directory and last component
2982 * strings. Note that unix_convert may have stripped off a
2983 * leading ./ from both name and newname if the rename is
2984 * at the root of the share. We need to make sure either both
2985 * name and newname contain a / character or neither of them do
2986 * as this is checked in resolve_wildcards().
2989 p = strrchr(name,'/');
2991 strcpy(directory,".");
2995 strcpy(directory,name);
2997 *p = '/'; /* Replace needed for exceptional test below. */
3000 if (is_mangled(mask))
3001 check_mangled_stack(mask);
3003 has_wild = strchr(mask,'*') || strchr(mask,'?');
3006 BOOL is_short_name = is_8_3(name, True);
3008 /* Add a terminating '/' to the directory name. */
3009 strcat(directory,"/");
3010 strcat(directory,mask);
3012 /* Ensure newname contains a '/' also */
3013 if(strrchr(newname,'/') == 0) {
3016 strcpy(tmpstr, "./");
3017 strcat(tmpstr, newname);
3018 strcpy(newname, tmpstr);
3021 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",
3022 case_sensitive, case_preserve, short_case_preserve, directory,
3023 newname, newname_last_component, is_short_name));
3026 * Check for special case with case preserving and not
3027 * case sensitive, if directory and newname are identical,
3028 * and the old last component differs from the original
3029 * last component only by case, then we should allow
3030 * the rename (user is trying to change the case of the
3033 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3034 ((short_case_preserve == True) && (is_short_name == True))) &&
3035 strcsequal(directory, newname)) {
3036 pstring newname_modified_last_component;
3039 * Get the last component of the modified name.
3040 * Note that we guarantee that newname contains a '/'
3043 p = strrchr(newname,'/');
3044 strcpy(newname_modified_last_component,p+1);
3046 if(strcsequal(newname_modified_last_component,
3047 newname_last_component) == False) {
3049 * Replace the modified last component with
3052 strcpy(p+1, newname_last_component);
3056 if (resolve_wildcards(directory,newname) &&
3057 can_rename(directory,cnum) &&
3058 !file_exist(newname,NULL) &&
3059 !sys_rename(directory,newname)) count++;
3061 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3062 directory,newname));
3064 if (!count) exists = file_exist(directory,NULL);
3065 if (!count && exists && file_exist(newname,NULL)) {
3070 void *dirptr = NULL;
3074 if (check_name(directory,cnum))
3075 dirptr = OpenDir(cnum, directory, True);
3081 if (strequal(mask,"????????.???"))
3084 while ((dname = ReadDirName(dirptr)))
3087 pstrcpy(fname,dname);
3089 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3091 error = ERRnoaccess;
3092 sprintf(fname,"%s/%s",directory,dname);
3093 if (!can_rename(fname,cnum)) continue;
3094 pstrcpy(destname,newname);
3096 if (!resolve_wildcards(fname,destname)) continue;
3098 if (file_exist(destname,NULL)) {
3102 if (!sys_rename(fname,destname)) count++;
3103 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3111 return(ERROR(ERRDOS,error));
3114 if((errno == ENOENT) && (bad_path1 || bad_path2))
3116 unix_ERR_class = ERRDOS;
3117 unix_ERR_code = ERRbadpath;
3119 return(UNIXERROR(ERRDOS,error));
3123 outsize = set_message(outbuf,0,0,True);
3128 /*******************************************************************
3129 copy a file as part of a reply_copy
3130 ******************************************************************/
3131 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3132 int count,BOOL target_is_directory)
3140 pstrcpy(dest,dest1);
3141 if (target_is_directory) {
3142 char *p = strrchr(src,'/');
3151 if (!file_exist(src,&st)) return(False);
3153 fnum1 = find_free_file();
3154 if (fnum1<0) return(False);
3155 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3156 1,0,0,&Access,&action);
3158 if (!Files[fnum1].open) return(False);
3160 if (!target_is_directory && count)
3163 fnum2 = find_free_file();
3168 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3169 ofun,st.st_mode,0,&Access,&action);
3171 if (!Files[fnum2].open) {
3176 if ((ofun&3) == 1) {
3177 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3181 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3186 return(ret == st.st_size);
3191 /****************************************************************************
3192 reply to a file copy.
3193 ****************************************************************************/
3194 int reply_copy(char *inbuf,char *outbuf)
3200 pstring mask,newname;
3203 int error = ERRnoaccess;
3206 int tid2 = SVAL(inbuf,smb_vwv0);
3207 int ofun = SVAL(inbuf,smb_vwv1);
3208 int flags = SVAL(inbuf,smb_vwv2);
3209 BOOL target_is_directory=False;
3210 BOOL bad_path1 = False;
3211 BOOL bad_path2 = False;
3213 *directory = *mask = 0;
3215 cnum = SVAL(inbuf,smb_tid);
3217 pstrcpy(name,smb_buf(inbuf));
3218 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3220 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3223 /* can't currently handle inter share copies XXXX */
3224 DEBUG(3,("Rejecting inter-share copy\n"));
3225 return(ERROR(ERRSRV,ERRinvdevice));
3228 unix_convert(name,cnum,0,&bad_path1);
3229 unix_convert(newname,cnum,0,&bad_path2);
3231 target_is_directory = directory_exist(newname,NULL);
3233 if ((flags&1) && target_is_directory) {
3234 return(ERROR(ERRDOS,ERRbadfile));
3237 if ((flags&2) && !target_is_directory) {
3238 return(ERROR(ERRDOS,ERRbadpath));
3241 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3242 /* wants a tree copy! XXXX */
3243 DEBUG(3,("Rejecting tree copy\n"));
3244 return(ERROR(ERRSRV,ERRerror));
3247 p = strrchr(name,'/');
3249 strcpy(directory,"./");
3253 strcpy(directory,name);
3257 if (is_mangled(mask))
3258 check_mangled_stack(mask);
3260 has_wild = strchr(mask,'*') || strchr(mask,'?');
3263 strcat(directory,"/");
3264 strcat(directory,mask);
3265 if (resolve_wildcards(directory,newname) &&
3266 copy_file(directory,newname,cnum,ofun,
3267 count,target_is_directory)) count++;
3268 if (!count) exists = file_exist(directory,NULL);
3270 void *dirptr = NULL;
3274 if (check_name(directory,cnum))
3275 dirptr = OpenDir(cnum, directory, True);
3281 if (strequal(mask,"????????.???"))
3284 while ((dname = ReadDirName(dirptr)))
3287 pstrcpy(fname,dname);
3289 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3291 error = ERRnoaccess;
3292 sprintf(fname,"%s/%s",directory,dname);
3293 strcpy(destname,newname);
3294 if (resolve_wildcards(fname,destname) &&
3295 copy_file(directory,newname,cnum,ofun,
3296 count,target_is_directory)) count++;
3297 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3305 return(ERROR(ERRDOS,error));
3308 if((errno == ENOENT) && (bad_path1 || bad_path2))
3310 unix_ERR_class = ERRDOS;
3311 unix_ERR_code = ERRbadpath;
3313 return(UNIXERROR(ERRDOS,error));
3317 outsize = set_message(outbuf,1,0,True);
3318 SSVAL(outbuf,smb_vwv0,count);
3325 /****************************************************************************
3327 ****************************************************************************/
3328 int reply_setdir(char *inbuf,char *outbuf)
3335 cnum = SVAL(inbuf,smb_tid);
3337 snum = Connections[cnum].service;
3338 if (!CAN_SETDIR(snum))
3339 return(ERROR(ERRDOS,ERRnoaccess));
3341 pstrcpy(newdir,smb_buf(inbuf) + 1);
3344 if (strlen(newdir) == 0)
3348 ok = directory_exist(newdir,NULL);
3350 string_set(&Connections[cnum].connectpath,newdir);
3354 return(ERROR(ERRDOS,ERRbadpath));
3356 outsize = set_message(outbuf,0,0,True);
3357 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3359 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3365 /****************************************************************************
3366 reply to a lockingX request
3367 ****************************************************************************/
3368 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3370 int fnum = GETFNUM(inbuf,smb_vwv2);
3371 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3373 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3375 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3376 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3377 uint32 count, offset;
3382 uint32 ecode=0, dummy2;
3383 int eclass=0, dummy1;
3385 cnum = SVAL(inbuf,smb_tid);
3387 CHECK_FNUM(fnum,cnum);
3390 data = smb_buf(inbuf);
3392 /* Check if this is an oplock break on a file
3393 we have granted an oplock on.
3395 if((locktype == LOCKING_ANDX_OPLOCK_RELEASE) &&
3396 (num_ulocks == 0) && (num_locks == 0) &&
3397 (CVAL(inbuf,smb_vwv0) == 0xFF))
3399 share_lock_token token;
3400 files_struct *fsp = &Files[fnum];
3401 uint32 dev = fsp->fd_ptr->dev;
3402 uint32 inode = fsp->fd_ptr->inode;
3404 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3407 * Make sure we have granted an oplock on this file.
3409 if(!fsp->granted_oplock)
3411 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3412 no oplock granted on this file.\n", fnum));
3413 return ERROR(ERRDOS,ERRlock);
3416 /* Remove the oplock flag from the sharemode. */
3417 lock_share_entry(fsp->cnum, dev, inode, &token);
3418 if(remove_share_oplock( fnum, token)==False)
3420 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3421 dev = %x, inode = %x\n", fnum, dev, inode));
3422 unlock_share_entry(fsp->cnum, dev, inode, token);
3425 unlock_share_entry(fsp->cnum, dev, inode, token);
3427 /* Clear the granted flag and return. */
3429 fsp->granted_oplock = False;
3433 /* Data now points at the beginning of the list
3434 of smb_unlkrng structs */
3435 for(i = 0; i < (int)num_ulocks; i++) {
3436 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3437 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3438 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3439 return ERROR(eclass,ecode);
3442 /* Now do any requested locks */
3443 data += 10*num_ulocks;
3444 /* Data now points at the beginning of the list
3445 of smb_lkrng structs */
3446 for(i = 0; i < (int)num_locks; i++) {
3447 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3448 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3449 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3453 /* If any of the above locks failed, then we must unlock
3454 all of the previous locks (X/Open spec). */
3455 if(i != num_locks && num_locks != 0) {
3456 for(; i >= 0; i--) {
3457 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3458 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3459 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3461 return ERROR(eclass,ecode);
3464 set_message(outbuf,2,0,True);
3466 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3467 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3471 return chain_reply(inbuf,outbuf,length,bufsize);
3475 /****************************************************************************
3476 reply to a SMBreadbmpx (read block multiplex) request
3477 ****************************************************************************/
3478 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3485 int outsize, mincount, maxcount;
3490 /* this function doesn't seem to work - disable by default */
3492 return(ERROR(ERRSRV,ERRuseSTD));
3494 outsize = set_message(outbuf,8,0,True);
3496 cnum = SVAL(inbuf,smb_tid);
3497 fnum = GETFNUM(inbuf,smb_vwv0);
3499 CHECK_FNUM(fnum,cnum);
3503 startpos = IVAL(inbuf,smb_vwv1);
3504 maxcount = SVAL(inbuf,smb_vwv3);
3505 mincount = SVAL(inbuf,smb_vwv4);
3507 data = smb_buf(outbuf);
3508 pad = ((long)data)%4;
3509 if (pad) pad = 4 - pad;
3512 max_per_packet = bufsize-(outsize+pad);
3516 if (is_locked(fnum,cnum,maxcount,startpos))
3517 return(ERROR(ERRDOS,ERRlock));
3521 int N = MIN(max_per_packet,tcount-total_read);
3523 nread = read_file(fnum,data,startpos,N);
3525 if (nread <= 0) nread = 0;
3528 tcount = total_read + nread;
3530 set_message(outbuf,8,nread,False);
3531 SIVAL(outbuf,smb_vwv0,startpos);
3532 SSVAL(outbuf,smb_vwv2,tcount);
3533 SSVAL(outbuf,smb_vwv6,nread);
3534 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3536 send_smb(Client,outbuf);
3538 total_read += nread;
3541 while (total_read < tcount);
3547 /****************************************************************************
3548 reply to a SMBwritebmpx (write block multiplex primary) request
3549 ****************************************************************************/
3550 int reply_writebmpx(char *inbuf,char *outbuf)
3552 int cnum,numtowrite,fnum;
3556 int tcount, write_through, smb_doff;
3559 cnum = SVAL(inbuf,smb_tid);
3560 fnum = GETFNUM(inbuf,smb_vwv0);
3562 CHECK_FNUM(fnum,cnum);
3566 tcount = SVAL(inbuf,smb_vwv1);
3567 startpos = IVAL(inbuf,smb_vwv3);
3568 write_through = BITSETW(inbuf+smb_vwv7,0);
3569 numtowrite = SVAL(inbuf,smb_vwv10);
3570 smb_doff = SVAL(inbuf,smb_vwv11);
3572 data = smb_base(inbuf) + smb_doff;
3574 /* If this fails we need to send an SMBwriteC response,
3575 not an SMBwritebmpx - set this up now so we don't forget */
3576 CVAL(outbuf,smb_com) = SMBwritec;
3578 if (is_locked(fnum,cnum,tcount,startpos))
3579 return(ERROR(ERRDOS,ERRlock));
3581 seek_file(fnum,startpos);
3582 nwritten = write_file(fnum,data,numtowrite);
3584 if(lp_syncalways(SNUM(cnum)) || write_through)
3587 if(nwritten < numtowrite)
3588 return(UNIXERROR(ERRHRD,ERRdiskfull));
3590 /* If the maximum to be written to this file
3591 is greater than what we just wrote then set
3592 up a secondary struct to be attached to this
3593 fd, we will use this to cache error messages etc. */
3594 if(tcount > nwritten)
3596 write_bmpx_struct *wbms;
3597 if(Files[fnum].wbmpx_ptr != NULL)
3598 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3600 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3603 DEBUG(0,("Out of memory in reply_readmpx\n"));
3604 return(ERROR(ERRSRV,ERRnoresource));
3606 wbms->wr_mode = write_through;
3607 wbms->wr_discard = False; /* No errors yet */
3608 wbms->wr_total_written = nwritten;
3609 wbms->wr_errclass = 0;
3611 Files[fnum].wbmpx_ptr = wbms;
3614 /* We are returning successfully, set the message type back to
3616 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3618 outsize = set_message(outbuf,1,0,True);
3620 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3622 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3623 timestring(),fnum,cnum,numtowrite,nwritten));
3625 if (write_through && tcount==nwritten) {
3626 /* we need to send both a primary and a secondary response */
3627 smb_setlen(outbuf,outsize - 4);
3628 send_smb(Client,outbuf);
3630 /* now the secondary */
3631 outsize = set_message(outbuf,1,0,True);
3632 CVAL(outbuf,smb_com) = SMBwritec;
3633 SSVAL(outbuf,smb_vwv0,nwritten);
3640 /****************************************************************************
3641 reply to a SMBwritebs (write block multiplex secondary) request
3642 ****************************************************************************/
3643 int reply_writebs(char *inbuf,char *outbuf)
3645 int cnum,numtowrite,fnum;
3649 int tcount, write_through, smb_doff;
3651 write_bmpx_struct *wbms;
3652 BOOL send_response = False;
3654 cnum = SVAL(inbuf,smb_tid);
3655 fnum = GETFNUM(inbuf,smb_vwv0);
3656 CHECK_FNUM(fnum,cnum);
3659 tcount = SVAL(inbuf,smb_vwv1);
3660 startpos = IVAL(inbuf,smb_vwv2);
3661 numtowrite = SVAL(inbuf,smb_vwv6);
3662 smb_doff = SVAL(inbuf,smb_vwv7);
3664 data = smb_base(inbuf) + smb_doff;
3666 /* We need to send an SMBwriteC response, not an SMBwritebs */
3667 CVAL(outbuf,smb_com) = SMBwritec;
3669 /* This fd should have an auxiliary struct attached,
3670 check that it does */
3671 wbms = Files[fnum].wbmpx_ptr;
3672 if(!wbms) return(-1);
3674 /* If write through is set we can return errors, else we must
3676 write_through = wbms->wr_mode;
3678 /* Check for an earlier error */
3679 if(wbms->wr_discard)
3680 return -1; /* Just discard the packet */
3682 seek_file(fnum,startpos);
3683 nwritten = write_file(fnum,data,numtowrite);
3685 if(lp_syncalways(SNUM(cnum)) || write_through)
3688 if (nwritten < numtowrite)
3691 /* We are returning an error - we can delete the aux struct */
3692 if (wbms) free((char *)wbms);
3693 Files[fnum].wbmpx_ptr = NULL;
3694 return(ERROR(ERRHRD,ERRdiskfull));
3696 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3699 /* Increment the total written, if this matches tcount
3700 we can discard the auxiliary struct (hurrah !) and return a writeC */
3701 wbms->wr_total_written += nwritten;
3702 if(wbms->wr_total_written >= tcount)
3704 if (write_through) {
3705 outsize = set_message(outbuf,1,0,True);
3706 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3707 send_response = True;
3711 Files[fnum].wbmpx_ptr = NULL;
3721 /****************************************************************************
3722 reply to a SMBsetattrE
3723 ****************************************************************************/
3724 int reply_setattrE(char *inbuf,char *outbuf)
3727 struct utimbuf unix_times;
3730 outsize = set_message(outbuf,0,0,True);
3732 cnum = SVAL(inbuf,smb_tid);
3733 fnum = GETFNUM(inbuf,smb_vwv0);
3735 CHECK_FNUM(fnum,cnum);
3738 /* Convert the DOS times into unix times. Ignore create
3739 time as UNIX can't set this.
3741 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3742 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3745 * Patch from Ray Frush <frush@engr.colostate.edu>
3746 * Sometimes times are sent as zero - ignore them.
3749 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3751 /* Ignore request */
3752 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3753 not setting timestamps of 0\n",
3754 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3757 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3759 /* set modify time = to access time if modify time was 0 */
3760 unix_times.modtime = unix_times.actime;
3763 /* Set the date on this file */
3764 if(sys_utime(Files[fnum].name, &unix_times))
3765 return(ERROR(ERRDOS,ERRnoaccess));
3767 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3768 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3774 /****************************************************************************
3775 reply to a SMBgetattrE
3776 ****************************************************************************/
3777 int reply_getattrE(char *inbuf,char *outbuf)
3784 outsize = set_message(outbuf,11,0,True);
3786 cnum = SVAL(inbuf,smb_tid);
3787 fnum = GETFNUM(inbuf,smb_vwv0);
3789 CHECK_FNUM(fnum,cnum);
3792 /* Do an fstat on this file */
3793 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3794 return(UNIXERROR(ERRDOS,ERRnoaccess));
3796 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3798 /* Convert the times into dos times. Set create
3799 date to be last modify date as UNIX doesn't save
3801 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3802 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3803 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3806 SIVAL(outbuf,smb_vwv6,0);
3807 SIVAL(outbuf,smb_vwv8,0);
3811 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3812 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3814 SSVAL(outbuf,smb_vwv10, mode);
3816 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));