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 struct smb_passwd *smb_pass; /* To check if machine account exists */
485 PAXX: Ack. We don't want to do this. The workstation trust account
486 with a $ on the end should exist in the local password database
487 or be mapped to something generic, but not modified. For NT
488 domain support we must reject this used in certain circumstances
489 with a code to indicate to the client that it is an invalid use
490 of a workstation trust account. NTWKS needs this error to join
491 a domain. This may be the source of future bugs if we cannot
492 be sure whether to reject this or not.
494 smb_pass = get_smbpwnam(user);
497 /* PAXX: This is the NO LOGON workstation trust account stuff */
498 DEBUG(4,("Rejecting workstation trust account %s",user));
499 SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
500 CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
501 return(ERROR(0x99,0xc000)); /* 0x99 NT error, 0xc00 */
504 #else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */
505 user[strlen(user) - 1] = '\0';
510 /* If no username is sent use the guest account */
513 strcpy(user,lp_guestaccount(-1));
514 /* If no user and no password then set guest flag. */
515 if( *smb_apasswd == 0)
521 strcpy(sesssetup_user,user);
523 reload_services(True);
525 add_session_user(user);
527 /* Check if the given username was the guest user with no password.
528 We need to do this check after add_session_user() as that
529 call can potentially change the username (via map_user).
532 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
535 if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
536 !check_hosts_equiv(user))
539 /* now check if it's a valid username/password */
540 /* If an NT password was supplied try and validate with that
541 first. This is superior as the passwords are mixed case
542 128 length unicode */
545 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
546 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
548 valid_nt_password = True;
550 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
552 if (!computer_id && lp_security() >= SEC_USER) {
553 #if (GUEST_SESSSETUP == 0)
554 return(ERROR(ERRSRV,ERRbadpw));
556 #if (GUEST_SESSSETUP == 1)
557 if (Get_Pwnam(user,True))
558 return(ERROR(ERRSRV,ERRbadpw));
561 if (*smb_apasswd || !Get_Pwnam(user,True))
562 strcpy(user,lp_guestaccount(-1));
563 DEBUG(3,("Registered username %s for guest access\n",user));
568 if (!Get_Pwnam(user,True)) {
569 DEBUG(3,("No such user %s - using guest account\n",user));
570 strcpy(user,lp_guestaccount(-1));
574 if (!strequal(user,lp_guestaccount(-1)) &&
575 lp_servicenumber(user) < 0)
577 int homes = lp_servicenumber(HOMES_NAME);
578 char *home = get_home_dir(user);
579 if (homes >= 0 && home)
580 lp_add_home(user,homes,home);
584 /* it's ok - setup a reply */
585 if (Protocol < PROTOCOL_NT1) {
586 set_message(outbuf,3,0,True);
589 set_message(outbuf,3,3,True);
591 strcpy(p,"Unix"); p = skip_string(p,1);
592 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
593 strcpy(p,myworkgroup); p = skip_string(p,1);
594 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
595 /* perhaps grab OS version here?? */
598 /* Set the correct uid in the outgoing and incoming packets
599 We will use this on future requests to determine which
600 user we should become.
603 struct passwd *pw = Get_Pwnam(user,False);
605 DEBUG(1,("Username %s is invalid on this system\n",user));
606 return(ERROR(ERRSRV,ERRbadpw));
612 if (guest && !computer_id)
613 SSVAL(outbuf,smb_vwv2,1);
615 /* register the name and uid as being validated, so further connections
616 to a uid can get through without a password, on the same VC */
617 sess_vuid = register_vuid(uid,gid,user,guest);
619 SSVAL(outbuf,smb_uid,sess_vuid);
620 SSVAL(inbuf,smb_uid,sess_vuid);
623 max_send = MIN(max_send,smb_bufsize);
625 DEBUG(6,("Client requested max send size of %d\n", max_send));
627 done_sesssetup = True;
629 return chain_reply(inbuf,outbuf,length,bufsize);
633 /****************************************************************************
635 ****************************************************************************/
636 int reply_chkpth(char *inbuf,char *outbuf)
642 BOOL bad_path = False;
644 cnum = SVAL(inbuf,smb_tid);
646 pstrcpy(name,smb_buf(inbuf) + 1);
647 unix_convert(name,cnum,0,&bad_path);
649 mode = SVAL(inbuf,smb_vwv0);
651 if (check_name(name,cnum))
652 ok = directory_exist(name,NULL);
656 /* We special case this - as when a Windows machine
657 is parsing a path is steps through the components
658 one at a time - if a component fails it expects
659 ERRbadpath, not ERRbadfile.
663 unix_ERR_class = ERRDOS;
664 unix_ERR_code = ERRbadpath;
668 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
669 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
670 (get_remote_arch() == RA_WINNT))
672 unix_ERR_class = ERRDOS;
673 unix_ERR_code = ERRbaddirectory;
677 return(UNIXERROR(ERRDOS,ERRbadpath));
680 outsize = set_message(outbuf,0,0,True);
682 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
688 /****************************************************************************
690 ****************************************************************************/
691 int reply_getatr(char *inbuf,char *outbuf)
701 BOOL bad_path = False;
703 cnum = SVAL(inbuf,smb_tid);
705 pstrcpy(fname,smb_buf(inbuf) + 1);
706 unix_convert(fname,cnum,0,&bad_path);
708 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
709 under WfWg - weird! */
712 mode = aHIDDEN | aDIR;
713 if (!CAN_WRITE(cnum)) mode |= aRONLY;
719 if (check_name(fname,cnum))
721 if (sys_stat(fname,&sbuf) == 0)
723 mode = dos_mode(cnum,fname,&sbuf);
725 mtime = sbuf.st_mtime;
731 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
736 if((errno == ENOENT) && bad_path)
738 unix_ERR_class = ERRDOS;
739 unix_ERR_code = ERRbadpath;
742 return(UNIXERROR(ERRDOS,ERRbadfile));
745 outsize = set_message(outbuf,10,0,True);
747 SSVAL(outbuf,smb_vwv0,mode);
748 put_dos_date3(outbuf,smb_vwv1,mtime);
749 SIVAL(outbuf,smb_vwv3,size);
751 if (Protocol >= PROTOCOL_NT1) {
752 char *p = strrchr(fname,'/');
753 uint16 flg2 = SVAL(outbuf,smb_flg2);
755 if (!is_8_3(fname, True))
756 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
759 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
765 /****************************************************************************
767 ****************************************************************************/
768 int reply_setatr(char *inbuf,char *outbuf)
776 BOOL bad_path = False;
778 cnum = SVAL(inbuf,smb_tid);
780 pstrcpy(fname,smb_buf(inbuf) + 1);
781 unix_convert(fname,cnum,0,&bad_path);
783 mode = SVAL(inbuf,smb_vwv0);
784 mtime = make_unix_date3(inbuf+smb_vwv1);
786 if (directory_exist(fname,NULL))
788 if (check_name(fname,cnum))
789 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
791 ok = set_filetime(fname,mtime);
795 if((errno == ENOENT) && bad_path)
797 unix_ERR_class = ERRDOS;
798 unix_ERR_code = ERRbadpath;
801 return(UNIXERROR(ERRDOS,ERRnoaccess));
804 outsize = set_message(outbuf,0,0,True);
806 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
812 /****************************************************************************
814 ****************************************************************************/
815 int reply_dskattr(char *inbuf,char *outbuf)
819 int dfree,dsize,bsize;
821 cnum = SVAL(inbuf,smb_tid);
823 sys_disk_free(".",&bsize,&dfree,&dsize);
825 outsize = set_message(outbuf,5,0,True);
827 SSVAL(outbuf,smb_vwv0,dsize);
828 SSVAL(outbuf,smb_vwv1,bsize/512);
829 SSVAL(outbuf,smb_vwv2,512);
830 SSVAL(outbuf,smb_vwv3,dfree);
832 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
838 /****************************************************************************
840 Can be called from SMBsearch, SMBffirst or SMBfunique.
841 ****************************************************************************/
842 int reply_search(char *inbuf,char *outbuf)
853 BOOL finished = False;
862 BOOL check_descend = False;
863 BOOL expect_close = False;
864 BOOL can_open = True;
865 BOOL bad_path = False;
867 *mask = *directory = *fname = 0;
869 /* If we were called as SMBffirst then we must expect close. */
870 if(CVAL(inbuf,smb_com) == SMBffirst)
873 cnum = SVAL(inbuf,smb_tid);
875 outsize = set_message(outbuf,1,3,True);
876 maxentries = SVAL(inbuf,smb_vwv0);
877 dirtype = SVAL(inbuf,smb_vwv1);
878 path = smb_buf(inbuf) + 1;
879 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
882 /* dirtype &= ~aDIR; */
884 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
891 pstrcpy(directory,smb_buf(inbuf)+1);
892 pstrcpy(dir2,smb_buf(inbuf)+1);
893 unix_convert(directory,cnum,0,&bad_path);
896 if (!check_name(directory,cnum))
899 p = strrchr(dir2,'/');
911 p = strrchr(directory,'/');
917 if (strlen(directory) == 0)
918 strcpy(directory,"./");
920 CVAL(status,0) = dirtype;
924 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
925 memcpy(mask,status+1,11);
927 dirtype = CVAL(status,0) & 0x1F;
928 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
929 if (!Connections[cnum].dirptr)
931 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
936 /* turn strings of spaces into a . */
938 trim_string(mask,NULL," ");
939 if ((p = strrchr(mask,' ')))
944 trim_string(mask,NULL," ");
951 for (p=mask; *p; p++)
953 if (*p != '?' && *p != '*' && !isdoschar(*p))
955 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
961 if (!strchr(mask,'.') && strlen(mask)>8)
964 fstrcpy(tmp,&mask[8]);
970 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
974 p = smb_buf(outbuf) + 3;
980 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
985 if((errno == ENOENT) && bad_path)
987 unix_ERR_class = ERRDOS;
988 unix_ERR_code = ERRbadpath;
990 return (UNIXERROR(ERRDOS,ERRnofids));
992 return(ERROR(ERRDOS,ERRnofids));
996 DEBUG(4,("dptr_num is %d\n",dptr_num));
1000 if ((dirtype&0x1F) == aVOLID)
1002 memcpy(p,status,21);
1003 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
1004 dptr_fill(p+12,dptr_num);
1005 if (dptr_zero(p+12) && (status_len==0))
1009 p += DIR_STRUCT_SIZE;
1013 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
1014 if (in_list(Connections[cnum].dirpath,
1015 lp_dontdescend(SNUM(cnum)),True))
1016 check_descend = True;
1018 for (i=numentries;(i<maxentries) && !finished;i++)
1021 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
1024 memcpy(p,status,21);
1025 make_dir_struct(p,mask,fname,size,mode,date);
1026 dptr_fill(p+12,dptr_num);
1029 p += DIR_STRUCT_SIZE;
1038 if (numentries == 0 || !ok)
1040 CVAL(outbuf,smb_rcls) = ERRDOS;
1041 SSVAL(outbuf,smb_err,ERRnofiles);
1044 /* If we were called as SMBffirst with smb_search_id == NULL
1045 and no entries were found then return error and close dirptr
1048 if(ok && expect_close && numentries == 0 && status_len == 0)
1050 CVAL(outbuf,smb_rcls) = ERRDOS;
1051 SSVAL(outbuf,smb_err,ERRnofiles);
1052 /* Also close the dptr - we know it's gone */
1053 dptr_close(dptr_num);
1056 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1057 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1058 dptr_close(dptr_num);
1060 SSVAL(outbuf,smb_vwv0,numentries);
1061 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1062 CVAL(smb_buf(outbuf),0) = 5;
1063 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1065 if (Protocol >= PROTOCOL_NT1) {
1066 uint16 flg2 = SVAL(outbuf,smb_flg2);
1067 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1070 outsize += DIR_STRUCT_SIZE*numentries;
1071 smb_setlen(outbuf,outsize - 4);
1073 if ((! *directory) && dptr_path(dptr_num))
1074 sprintf(directory,"(%s)",dptr_path(dptr_num));
1076 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1078 smb_fn_name(CVAL(inbuf,smb_com)),
1079 mask,directory,cnum,dirtype,numentries,maxentries));
1085 /****************************************************************************
1086 reply to a fclose (stop directory search)
1087 ****************************************************************************/
1088 int reply_fclose(char *inbuf,char *outbuf)
1097 cnum = SVAL(inbuf,smb_tid);
1099 outsize = set_message(outbuf,1,0,True);
1100 path = smb_buf(inbuf) + 1;
1101 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1104 if (status_len == 0)
1105 return(ERROR(ERRSRV,ERRsrverror));
1107 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1109 if(dptr_fetch(status+12,&dptr_num)) {
1110 /* Close the dptr - we know it's gone */
1111 dptr_close(dptr_num);
1114 SSVAL(outbuf,smb_vwv0,0);
1116 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1122 /****************************************************************************
1124 ****************************************************************************/
1125 int reply_open(char *inbuf,char *outbuf)
1138 BOOL bad_path = False;
1140 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1142 cnum = SVAL(inbuf,smb_tid);
1144 share_mode = SVAL(inbuf,smb_vwv0);
1146 pstrcpy(fname,smb_buf(inbuf)+1);
1147 unix_convert(fname,cnum,0,&bad_path);
1149 fnum = find_free_file();
1151 return(ERROR(ERRSRV,ERRnofids));
1153 if (!check_name(fname,cnum))
1155 if((errno == ENOENT) && bad_path)
1157 unix_ERR_class = ERRDOS;
1158 unix_ERR_code = ERRbadpath;
1160 return(UNIXERROR(ERRDOS,ERRnoaccess));
1163 unixmode = unix_mode(cnum,aARCH);
1165 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1166 oplock_request,&rmode,NULL);
1172 if((errno == ENOENT) && bad_path)
1174 unix_ERR_class = ERRDOS;
1175 unix_ERR_code = ERRbadpath;
1177 return(UNIXERROR(ERRDOS,ERRnoaccess));
1180 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1181 close_file(fnum,False);
1182 return(ERROR(ERRDOS,ERRnoaccess));
1185 size = sbuf.st_size;
1186 fmode = dos_mode(cnum,fname,&sbuf);
1187 mtime = sbuf.st_mtime;
1190 DEBUG(3,("attempt to open a directory %s\n",fname));
1191 close_file(fnum,False);
1192 return(ERROR(ERRDOS,ERRnoaccess));
1195 outsize = set_message(outbuf,7,0,True);
1196 SSVAL(outbuf,smb_vwv0,fnum);
1197 SSVAL(outbuf,smb_vwv1,fmode);
1198 put_dos_date3(outbuf,smb_vwv2,mtime);
1199 SIVAL(outbuf,smb_vwv4,size);
1200 SSVAL(outbuf,smb_vwv6,rmode);
1202 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1203 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1206 if(fsp->granted_oplock)
1207 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1212 /****************************************************************************
1213 reply to an open and X
1214 ****************************************************************************/
1215 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1218 int cnum = SVAL(inbuf,smb_tid);
1220 int smb_mode = SVAL(inbuf,smb_vwv3);
1221 int smb_attr = SVAL(inbuf,smb_vwv5);
1222 BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1224 int open_flags = SVAL(inbuf,smb_vwv2);
1225 int smb_sattr = SVAL(inbuf,smb_vwv4);
1226 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1228 int smb_ofun = SVAL(inbuf,smb_vwv8);
1230 int size=0,fmode=0,mtime=0,rmode=0;
1233 BOOL bad_path = False;
1236 /* If it's an IPC, pass off the pipe handler. */
1238 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1240 /* XXXX we need to handle passed times, sattr and flags */
1242 pstrcpy(fname,smb_buf(inbuf));
1243 unix_convert(fname,cnum,0,&bad_path);
1245 fnum = find_free_file();
1247 return(ERROR(ERRSRV,ERRnofids));
1249 if (!check_name(fname,cnum))
1251 if((errno == ENOENT) && bad_path)
1253 unix_ERR_class = ERRDOS;
1254 unix_ERR_code = ERRbadpath;
1256 return(UNIXERROR(ERRDOS,ERRnoaccess));
1259 unixmode = unix_mode(cnum,smb_attr | aARCH);
1261 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1262 oplock_request, &rmode,&smb_action);
1268 if((errno == ENOENT) && bad_path)
1270 unix_ERR_class = ERRDOS;
1271 unix_ERR_code = ERRbadpath;
1273 return(UNIXERROR(ERRDOS,ERRnoaccess));
1276 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1277 close_file(fnum,False);
1278 return(ERROR(ERRDOS,ERRnoaccess));
1281 size = sbuf.st_size;
1282 fmode = dos_mode(cnum,fname,&sbuf);
1283 mtime = sbuf.st_mtime;
1285 close_file(fnum,False);
1286 return(ERROR(ERRDOS,ERRnoaccess));
1289 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1290 smb_action |= EXTENDED_OPLOCK_GRANTED;
1291 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1294 if(fsp->granted_oplock) {
1295 smb_action |= EXTENDED_OPLOCK_GRANTED;
1296 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1299 set_message(outbuf,15,0,True);
1300 SSVAL(outbuf,smb_vwv2,fnum);
1301 SSVAL(outbuf,smb_vwv3,fmode);
1302 put_dos_date3(outbuf,smb_vwv4,mtime);
1303 SIVAL(outbuf,smb_vwv6,size);
1304 SSVAL(outbuf,smb_vwv8,rmode);
1305 SSVAL(outbuf,smb_vwv11,smb_action);
1309 return chain_reply(inbuf,outbuf,length,bufsize);
1313 /****************************************************************************
1314 reply to a SMBulogoffX
1315 ****************************************************************************/
1316 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1318 uint16 vuid = SVAL(inbuf,smb_uid);
1319 user_struct *vuser = get_valid_user_struct(vuid);
1322 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1325 /* in user level security we are supposed to close any files
1326 open by this user */
1327 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1329 for (i=0;i<MAX_OPEN_FILES;i++)
1330 if (Files[i].uid == vuser->uid && Files[i].open) {
1331 close_file(i,False);
1335 invalidate_vuid(vuid);
1337 set_message(outbuf,2,0,True);
1339 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1341 return chain_reply(inbuf,outbuf,length,bufsize);
1345 /****************************************************************************
1346 reply to a mknew or a create
1347 ****************************************************************************/
1348 int reply_mknew(char *inbuf,char *outbuf)
1357 BOOL bad_path = False;
1359 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1361 com = SVAL(inbuf,smb_com);
1362 cnum = SVAL(inbuf,smb_tid);
1364 createmode = SVAL(inbuf,smb_vwv0);
1365 pstrcpy(fname,smb_buf(inbuf)+1);
1366 unix_convert(fname,cnum,0,&bad_path);
1368 if (createmode & aVOLID)
1370 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1373 unixmode = unix_mode(cnum,createmode);
1375 fnum = find_free_file();
1377 return(ERROR(ERRSRV,ERRnofids));
1379 if (!check_name(fname,cnum))
1381 if((errno == ENOENT) && bad_path)
1383 unix_ERR_class = ERRDOS;
1384 unix_ERR_code = ERRbadpath;
1386 return(UNIXERROR(ERRDOS,ERRnoaccess));
1391 /* We should fail if file exists. */
1396 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1400 /* Open file in dos compatibility share mode. */
1401 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1402 oplock_request, NULL, NULL);
1408 if((errno == ENOENT) && bad_path)
1410 unix_ERR_class = ERRDOS;
1411 unix_ERR_code = ERRbadpath;
1413 return(UNIXERROR(ERRDOS,ERRnoaccess));
1416 outsize = set_message(outbuf,1,0,True);
1417 SSVAL(outbuf,smb_vwv0,fnum);
1419 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1420 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1423 if(fsp->granted_oplock)
1424 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1426 DEBUG(2,("new file %s\n",fname));
1427 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));
1433 /****************************************************************************
1434 reply to a create temporary file
1435 ****************************************************************************/
1436 int reply_ctemp(char *inbuf,char *outbuf)
1445 BOOL bad_path = False;
1447 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1449 cnum = SVAL(inbuf,smb_tid);
1450 createmode = SVAL(inbuf,smb_vwv0);
1451 pstrcpy(fname,smb_buf(inbuf)+1);
1452 strcat(fname,"/TMXXXXXX");
1453 unix_convert(fname,cnum,0,&bad_path);
1455 unixmode = unix_mode(cnum,createmode);
1457 fnum = find_free_file();
1459 return(ERROR(ERRSRV,ERRnofids));
1461 if (!check_name(fname,cnum))
1463 if((errno == ENOENT) && bad_path)
1465 unix_ERR_class = ERRDOS;
1466 unix_ERR_code = ERRbadpath;
1468 return(UNIXERROR(ERRDOS,ERRnoaccess));
1471 strcpy(fname2,(char *)mktemp(fname));
1473 /* Open file in dos compatibility share mode. */
1474 /* We should fail if file exists. */
1475 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1476 oplock_request, NULL, NULL);
1482 if((errno == ENOENT) && bad_path)
1484 unix_ERR_class = ERRDOS;
1485 unix_ERR_code = ERRbadpath;
1487 return(UNIXERROR(ERRDOS,ERRnoaccess));
1490 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1491 SSVAL(outbuf,smb_vwv0,fnum);
1492 CVAL(smb_buf(outbuf),0) = 4;
1493 strcpy(smb_buf(outbuf) + 1,fname2);
1495 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1496 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1499 if(fsp->granted_oplock)
1500 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1502 DEBUG(2,("created temp file %s\n",fname2));
1503 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));
1509 /*******************************************************************
1510 check if a user is allowed to delete a file
1511 ********************************************************************/
1512 static BOOL can_delete(char *fname,int cnum,int dirtype)
1517 if (!CAN_WRITE(cnum)) return(False);
1519 if (sys_lstat(fname,&sbuf) != 0) return(False);
1520 fmode = dos_mode(cnum,fname,&sbuf);
1521 if (fmode & aDIR) return(False);
1522 if (!lp_delete_readonly(SNUM(cnum))) {
1523 if (fmode & aRONLY) return(False);
1525 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1527 if (!check_file_sharing(cnum,fname)) return(False);
1531 /****************************************************************************
1533 ****************************************************************************/
1534 int reply_unlink(char *inbuf,char *outbuf)
1544 int error = ERRnoaccess;
1547 BOOL bad_path = False;
1549 *directory = *mask = 0;
1551 cnum = SVAL(inbuf,smb_tid);
1552 dirtype = SVAL(inbuf,smb_vwv0);
1554 pstrcpy(name,smb_buf(inbuf) + 1);
1556 DEBUG(3,("reply_unlink : %s\n",name));
1558 unix_convert(name,cnum,0,&bad_path);
1560 p = strrchr(name,'/');
1562 strcpy(directory,"./");
1566 strcpy(directory,name);
1570 if (is_mangled(mask))
1571 check_mangled_stack(mask);
1573 has_wild = strchr(mask,'*') || strchr(mask,'?');
1576 strcat(directory,"/");
1577 strcat(directory,mask);
1578 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1579 if (!count) exists = file_exist(directory,NULL);
1581 void *dirptr = NULL;
1584 if (check_name(directory,cnum))
1585 dirptr = OpenDir(cnum, directory, True);
1587 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1588 the pattern matches against the long name, otherwise the short name
1589 We don't implement this yet XXXX
1596 if (strequal(mask,"????????.???"))
1599 while ((dname = ReadDirName(dirptr)))
1602 pstrcpy(fname,dname);
1604 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1606 error = ERRnoaccess;
1607 sprintf(fname,"%s/%s",directory,dname);
1608 if (!can_delete(fname,cnum,dirtype)) continue;
1609 if (!sys_unlink(fname)) count++;
1610 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1618 return(ERROR(ERRDOS,error));
1621 if((errno == ENOENT) && bad_path)
1623 unix_ERR_class = ERRDOS;
1624 unix_ERR_code = ERRbadpath;
1626 return(UNIXERROR(ERRDOS,error));
1630 outsize = set_message(outbuf,0,0,True);
1636 /****************************************************************************
1637 reply to a readbraw (core+ protocol)
1638 ****************************************************************************/
1639 int reply_readbraw(char *inbuf, char *outbuf)
1641 int cnum,maxcount,mincount,fnum;
1644 char *header = outbuf;
1650 * Special check if an oplock break has been issued
1651 * and the readraw request croses on the wire, we must
1652 * return a zero length response here.
1655 if(global_oplock_break)
1657 _smb_setlen(header,0);
1658 transfer_file(0,Client,0,header,4,0);
1659 DEBUG(5,("readbraw - oplock break finished\n"));
1663 cnum = SVAL(inbuf,smb_tid);
1664 fnum = GETFNUM(inbuf,smb_vwv0);
1666 startpos = IVAL(inbuf,smb_vwv1);
1667 maxcount = SVAL(inbuf,smb_vwv3);
1668 mincount = SVAL(inbuf,smb_vwv4);
1670 /* ensure we don't overrun the packet size */
1671 maxcount = MIN(65535,maxcount);
1672 maxcount = MAX(mincount,maxcount);
1674 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1676 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1677 _smb_setlen(header,0);
1678 transfer_file(0,Client,0,header,4,0);
1683 fd = Files[fnum].fd_ptr->fd;
1684 fname = Files[fnum].name;
1688 if (!is_locked(fnum,cnum,maxcount,startpos))
1690 int size = Files[fnum].size;
1691 int sizeneeded = startpos + maxcount;
1693 if (size < sizeneeded) {
1695 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1697 if (!Files[fnum].can_write)
1698 Files[fnum].size = size;
1701 nread = MIN(maxcount,(int)(size - startpos));
1704 if (nread < mincount)
1707 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1710 maxcount,mincount,nread));
1715 _smb_setlen(header,nread);
1717 if (!Files[fnum].can_write)
1718 predict = read_predict(fd,startpos,header+4,NULL,nread);
1720 if ((nread-predict) > 0)
1721 seek_file(fnum,startpos + predict);
1723 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1728 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1729 fname,startpos,nread,ret));
1732 ret = read_file(fnum,header+4,startpos,nread);
1733 if (ret < mincount) ret = 0;
1735 _smb_setlen(header,ret);
1736 transfer_file(0,Client,0,header,4+ret,0);
1739 DEBUG(5,("readbraw finished\n"));
1744 /****************************************************************************
1745 reply to a lockread (core+ protocol)
1746 ****************************************************************************/
1747 int reply_lockread(char *inbuf,char *outbuf)
1753 uint32 startpos, numtoread;
1757 cnum = SVAL(inbuf,smb_tid);
1758 fnum = GETFNUM(inbuf,smb_vwv0);
1760 CHECK_FNUM(fnum,cnum);
1764 numtoread = SVAL(inbuf,smb_vwv1);
1765 startpos = IVAL(inbuf,smb_vwv2);
1767 outsize = set_message(outbuf,5,3,True);
1768 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1769 data = smb_buf(outbuf) + 3;
1771 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1772 return (ERROR(eclass,ecode));
1774 nread = read_file(fnum,data,startpos,numtoread);
1777 return(UNIXERROR(ERRDOS,ERRnoaccess));
1780 SSVAL(outbuf,smb_vwv0,nread);
1781 SSVAL(outbuf,smb_vwv5,nread+3);
1782 SSVAL(smb_buf(outbuf),1,nread);
1784 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1790 /****************************************************************************
1792 ****************************************************************************/
1793 int reply_read(char *inbuf,char *outbuf)
1795 int cnum,numtoread,fnum;
1801 cnum = SVAL(inbuf,smb_tid);
1802 fnum = GETFNUM(inbuf,smb_vwv0);
1804 CHECK_FNUM(fnum,cnum);
1808 numtoread = SVAL(inbuf,smb_vwv1);
1809 startpos = IVAL(inbuf,smb_vwv2);
1811 outsize = set_message(outbuf,5,3,True);
1812 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1813 data = smb_buf(outbuf) + 3;
1815 if (is_locked(fnum,cnum,numtoread,startpos))
1816 return(ERROR(ERRDOS,ERRlock));
1819 nread = read_file(fnum,data,startpos,numtoread);
1822 return(UNIXERROR(ERRDOS,ERRnoaccess));
1825 SSVAL(outbuf,smb_vwv0,nread);
1826 SSVAL(outbuf,smb_vwv5,nread+3);
1827 CVAL(smb_buf(outbuf),0) = 1;
1828 SSVAL(smb_buf(outbuf),1,nread);
1830 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1836 /****************************************************************************
1837 reply to a read and X
1838 ****************************************************************************/
1839 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1841 int fnum = GETFNUM(inbuf,smb_vwv2);
1842 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1843 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1844 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1850 cnum = SVAL(inbuf,smb_tid);
1852 CHECK_FNUM(fnum,cnum);
1856 set_message(outbuf,12,0,True);
1857 data = smb_buf(outbuf);
1859 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1860 return(ERROR(ERRDOS,ERRlock));
1861 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1865 return(UNIXERROR(ERRDOS,ERRnoaccess));
1867 SSVAL(outbuf,smb_vwv5,nread);
1868 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1869 SSVAL(smb_buf(outbuf),-2,nread);
1871 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1872 timestring(),fnum,cnum,
1873 smb_mincnt,smb_maxcnt,nread));
1877 return chain_reply(inbuf,outbuf,length,bufsize);
1881 /****************************************************************************
1882 reply to a writebraw (core+ or LANMAN1.0 protocol)
1883 ****************************************************************************/
1884 int reply_writebraw(char *inbuf,char *outbuf)
1887 int total_written=0;
1896 cnum = SVAL(inbuf,smb_tid);
1897 fnum = GETFNUM(inbuf,smb_vwv0);
1899 CHECK_FNUM(fnum,cnum);
1903 tcount = IVAL(inbuf,smb_vwv1);
1904 startpos = IVAL(inbuf,smb_vwv3);
1905 write_through = BITSETW(inbuf+smb_vwv7,0);
1907 /* We have to deal with slightly different formats depending
1908 on whether we are using the core+ or lanman1.0 protocol */
1909 if(Protocol <= PROTOCOL_COREPLUS) {
1910 numtowrite = SVAL(smb_buf(inbuf),-2);
1911 data = smb_buf(inbuf);
1913 numtowrite = SVAL(inbuf,smb_vwv10);
1914 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1917 /* force the error type */
1918 CVAL(inbuf,smb_com) = SMBwritec;
1919 CVAL(outbuf,smb_com) = SMBwritec;
1921 if (is_locked(fnum,cnum,tcount,startpos))
1922 return(ERROR(ERRDOS,ERRlock));
1924 if (seek_file(fnum,startpos) != startpos)
1925 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1928 nwritten = write_file(fnum,data,numtowrite);
1930 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1931 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1933 if (nwritten < numtowrite)
1934 return(UNIXERROR(ERRHRD,ERRdiskfull));
1936 total_written = nwritten;
1938 /* Return a message to the redirector to tell it
1939 to send more bytes */
1940 CVAL(outbuf,smb_com) = SMBwritebraw;
1941 SSVALS(outbuf,smb_vwv0,-1);
1942 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1943 send_smb(Client,outbuf);
1945 /* Now read the raw data into the buffer and write it */
1946 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1947 exit_server("secondary writebraw failed");
1950 /* Even though this is not an smb message, smb_len
1951 returns the generic length of an smb message */
1952 numtowrite = smb_len(inbuf);
1954 if (tcount > nwritten+numtowrite) {
1955 DEBUG(3,("Client overestimated the write %d %d %d\n",
1956 tcount,nwritten,numtowrite));
1959 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1961 total_written += nwritten;
1963 /* Set up outbuf to return the correct return */
1964 outsize = set_message(outbuf,1,0,True);
1965 CVAL(outbuf,smb_com) = SMBwritec;
1966 SSVAL(outbuf,smb_vwv0,total_written);
1968 if (nwritten < numtowrite) {
1969 CVAL(outbuf,smb_rcls) = ERRHRD;
1970 SSVAL(outbuf,smb_err,ERRdiskfull);
1973 if (lp_syncalways(SNUM(cnum)) || write_through)
1976 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1977 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1979 /* we won't return a status if write through is not selected - this
1980 follows what WfWg does */
1981 if (!write_through && total_written==tcount)
1988 /****************************************************************************
1989 reply to a writeunlock (core+)
1990 ****************************************************************************/
1991 int reply_writeunlock(char *inbuf,char *outbuf)
1997 uint32 numtowrite,startpos;
2001 cnum = SVAL(inbuf,smb_tid);
2002 fnum = GETFNUM(inbuf,smb_vwv0);
2004 CHECK_FNUM(fnum,cnum);
2008 numtowrite = SVAL(inbuf,smb_vwv1);
2009 startpos = IVAL(inbuf,smb_vwv2);
2010 data = smb_buf(inbuf) + 3;
2012 if (is_locked(fnum,cnum,numtowrite,startpos))
2013 return(ERROR(ERRDOS,ERRlock));
2015 seek_file(fnum,startpos);
2017 /* The special X/Open SMB protocol handling of
2018 zero length writes is *NOT* done for
2023 nwritten = write_file(fnum,data,numtowrite);
2025 if (lp_syncalways(SNUM(cnum)))
2028 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2029 return(UNIXERROR(ERRDOS,ERRnoaccess));
2031 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2032 return(ERROR(eclass,ecode));
2034 outsize = set_message(outbuf,1,0,True);
2036 SSVAL(outbuf,smb_vwv0,nwritten);
2038 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2039 timestring(),fnum,cnum,numtowrite,nwritten));
2045 /****************************************************************************
2047 ****************************************************************************/
2048 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
2050 int cnum,numtowrite,fnum;
2059 cnum = SVAL(inbuf,smb_tid);
2060 fnum = GETFNUM(inbuf,smb_vwv0);
2062 CHECK_FNUM(fnum,cnum);
2066 numtowrite = SVAL(inbuf,smb_vwv1);
2067 startpos = IVAL(inbuf,smb_vwv2);
2068 data = smb_buf(inbuf) + 3;
2070 if (is_locked(fnum,cnum,numtowrite,startpos))
2071 return(ERROR(ERRDOS,ERRlock));
2073 seek_file(fnum,startpos);
2075 /* X/Open SMB protocol says that if smb_vwv1 is
2076 zero then the file size should be extended or
2077 truncated to the size given in smb_vwv[2-3] */
2079 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2081 nwritten = write_file(fnum,data,numtowrite);
2083 if (lp_syncalways(SNUM(cnum)))
2086 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2087 return(UNIXERROR(ERRDOS,ERRnoaccess));
2089 outsize = set_message(outbuf,1,0,True);
2091 SSVAL(outbuf,smb_vwv0,nwritten);
2093 if (nwritten < numtowrite) {
2094 CVAL(outbuf,smb_rcls) = ERRHRD;
2095 SSVAL(outbuf,smb_err,ERRdiskfull);
2098 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2104 /****************************************************************************
2105 reply to a write and X
2106 ****************************************************************************/
2107 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2109 int fnum = GETFNUM(inbuf,smb_vwv2);
2110 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2111 int smb_dsize = SVAL(inbuf,smb_vwv10);
2112 int smb_doff = SVAL(inbuf,smb_vwv11);
2113 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2118 cnum = SVAL(inbuf,smb_tid);
2120 CHECK_FNUM(fnum,cnum);
2124 data = smb_base(inbuf) + smb_doff;
2126 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2127 return(ERROR(ERRDOS,ERRlock));
2129 seek_file(fnum,smb_offs);
2131 /* X/Open SMB protocol says that, unlike SMBwrite
2132 if the length is zero then NO truncation is
2133 done, just a write of zero. To truncate a file,
2138 nwritten = write_file(fnum,data,smb_dsize);
2140 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2141 return(UNIXERROR(ERRDOS,ERRnoaccess));
2143 set_message(outbuf,6,0,True);
2145 SSVAL(outbuf,smb_vwv2,nwritten);
2147 if (nwritten < smb_dsize) {
2148 CVAL(outbuf,smb_rcls) = ERRHRD;
2149 SSVAL(outbuf,smb_err,ERRdiskfull);
2152 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2156 if (lp_syncalways(SNUM(cnum)) || write_through)
2159 return chain_reply(inbuf,outbuf,length,bufsize);
2163 /****************************************************************************
2165 ****************************************************************************/
2166 int reply_lseek(char *inbuf,char *outbuf)
2174 cnum = SVAL(inbuf,smb_tid);
2175 fnum = GETFNUM(inbuf,smb_vwv0);
2177 CHECK_FNUM(fnum,cnum);
2180 mode = SVAL(inbuf,smb_vwv1) & 3;
2181 startpos = IVAL(inbuf,smb_vwv2);
2185 case 0: umode = SEEK_SET; break;
2186 case 1: umode = SEEK_CUR; break;
2187 case 2: umode = SEEK_END; break;
2189 umode = SEEK_SET; break;
2192 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2193 Files[fnum].pos = res;
2195 outsize = set_message(outbuf,2,0,True);
2196 SIVALS(outbuf,smb_vwv0,res);
2198 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2204 /****************************************************************************
2206 ****************************************************************************/
2207 int reply_flush(char *inbuf,char *outbuf)
2210 int outsize = set_message(outbuf,0,0,True);
2212 cnum = SVAL(inbuf,smb_tid);
2213 fnum = GETFNUM(inbuf,smb_vwv0);
2215 if (fnum != 0xFFFF) {
2216 CHECK_FNUM(fnum,cnum);
2223 for (i=0;i<MAX_OPEN_FILES;i++)
2230 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2235 /****************************************************************************
2237 ****************************************************************************/
2238 int reply_exit(char *inbuf,char *outbuf)
2240 int outsize = set_message(outbuf,0,0,True);
2241 DEBUG(3,("%s exit\n",timestring()));
2247 /****************************************************************************
2249 ****************************************************************************/
2250 int reply_close(char *inbuf,char *outbuf)
2255 int32 eclass = 0, err = 0;
2257 outsize = set_message(outbuf,0,0,True);
2259 cnum = SVAL(inbuf,smb_tid);
2261 fnum = GETFNUM(inbuf,smb_vwv0);
2262 CHECK_FNUM(fnum,cnum);
2264 if(HAS_CACHED_ERROR(fnum)) {
2265 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2266 err = Files[fnum].wbmpx_ptr->wr_error;
2269 mtime = make_unix_date3(inbuf+smb_vwv1);
2271 /* try and set the date */
2272 set_filetime(Files[fnum].name,mtime);
2274 close_file(fnum,True);
2276 /* We have a cached error */
2278 return(ERROR(eclass,err));
2280 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2281 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2282 Connections[cnum].num_files_open));
2288 /****************************************************************************
2289 reply to a writeclose (Core+ protocol)
2290 ****************************************************************************/
2291 int reply_writeclose(char *inbuf,char *outbuf)
2293 int cnum,numtowrite,fnum;
2300 cnum = SVAL(inbuf,smb_tid);
2301 fnum = GETFNUM(inbuf,smb_vwv0);
2303 CHECK_FNUM(fnum,cnum);
2307 numtowrite = SVAL(inbuf,smb_vwv1);
2308 startpos = IVAL(inbuf,smb_vwv2);
2309 mtime = make_unix_date3(inbuf+smb_vwv4);
2310 data = smb_buf(inbuf) + 1;
2312 if (is_locked(fnum,cnum,numtowrite,startpos))
2313 return(ERROR(ERRDOS,ERRlock));
2315 seek_file(fnum,startpos);
2317 nwritten = write_file(fnum,data,numtowrite);
2319 set_filetime(Files[fnum].name,mtime);
2321 close_file(fnum,True);
2323 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2324 timestring(),fnum,cnum,numtowrite,nwritten,
2325 Connections[cnum].num_files_open));
2328 return(UNIXERROR(ERRDOS,ERRnoaccess));
2330 outsize = set_message(outbuf,1,0,True);
2332 SSVAL(outbuf,smb_vwv0,nwritten);
2337 /****************************************************************************
2339 ****************************************************************************/
2340 int reply_lock(char *inbuf,char *outbuf)
2343 int outsize = set_message(outbuf,0,0,True);
2344 uint32 count,offset;
2348 cnum = SVAL(inbuf,smb_tid);
2349 fnum = GETFNUM(inbuf,smb_vwv0);
2351 CHECK_FNUM(fnum,cnum);
2354 count = IVAL(inbuf,smb_vwv1);
2355 offset = IVAL(inbuf,smb_vwv3);
2357 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));
2359 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2360 return (ERROR(eclass,ecode));
2366 /****************************************************************************
2368 ****************************************************************************/
2369 int reply_unlock(char *inbuf,char *outbuf)
2372 int outsize = set_message(outbuf,0,0,True);
2373 uint32 count,offset;
2377 cnum = SVAL(inbuf,smb_tid);
2378 fnum = GETFNUM(inbuf,smb_vwv0);
2380 CHECK_FNUM(fnum,cnum);
2383 count = IVAL(inbuf,smb_vwv1);
2384 offset = IVAL(inbuf,smb_vwv3);
2386 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2387 return (ERROR(eclass,ecode));
2389 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));
2395 /****************************************************************************
2397 ****************************************************************************/
2398 int reply_tdis(char *inbuf,char *outbuf)
2401 int outsize = set_message(outbuf,0,0,True);
2404 cnum = SVAL(inbuf,smb_tid);
2405 vuid = SVAL(inbuf,smb_uid);
2407 if (!OPEN_CNUM(cnum)) {
2408 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2409 return(ERROR(ERRSRV,ERRinvnid));
2412 Connections[cnum].used = False;
2414 close_cnum(cnum,vuid);
2416 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2423 /****************************************************************************
2425 ****************************************************************************/
2426 int reply_echo(char *inbuf,char *outbuf)
2429 int smb_reverb = SVAL(inbuf,smb_vwv0);
2431 int data_len = smb_buflen(inbuf);
2432 int outsize = set_message(outbuf,1,data_len,True);
2434 cnum = SVAL(inbuf,smb_tid);
2436 /* According to the latest CIFS spec we shouldn't
2437 care what the TID is.
2441 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2443 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2444 return(ERROR(ERRSRV,ERRinvnid));
2448 /* copy any incoming data back out */
2450 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2452 if (smb_reverb > 100)
2454 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2458 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2460 SSVAL(outbuf,smb_vwv0,seq_num);
2462 smb_setlen(outbuf,outsize - 4);
2464 send_smb(Client,outbuf);
2467 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2473 /****************************************************************************
2474 reply to a printopen
2475 ****************************************************************************/
2476 int reply_printopen(char *inbuf,char *outbuf)
2484 *fname = *fname2 = 0;
2486 cnum = SVAL(inbuf,smb_tid);
2488 if (!CAN_PRINT(cnum))
2489 return(ERROR(ERRDOS,ERRnoaccess));
2494 pstrcpy(s,smb_buf(inbuf)+1);
2498 if (!(isalnum(*p) || strchr("._-",*p)))
2503 if (strlen(s) > 10) s[10] = 0;
2505 sprintf(fname,"%s.XXXXXX",s);
2508 fnum = find_free_file();
2510 return(ERROR(ERRSRV,ERRnofids));
2512 strcpy(fname2,(char *)mktemp(fname));
2514 if (!check_name(fname2,cnum))
2515 return(ERROR(ERRDOS,ERRnoaccess));
2517 /* Open for exclusive use, write only. */
2518 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2521 if (!Files[fnum].open)
2522 return(UNIXERROR(ERRDOS,ERRnoaccess));
2524 /* force it to be a print file */
2525 Files[fnum].print_file = True;
2527 outsize = set_message(outbuf,1,0,True);
2528 SSVAL(outbuf,smb_vwv0,fnum);
2530 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2536 /****************************************************************************
2537 reply to a printclose
2538 ****************************************************************************/
2539 int reply_printclose(char *inbuf,char *outbuf)
2542 int outsize = set_message(outbuf,0,0,True);
2544 cnum = SVAL(inbuf,smb_tid);
2545 fnum = GETFNUM(inbuf,smb_vwv0);
2547 CHECK_FNUM(fnum,cnum);
2550 if (!CAN_PRINT(cnum))
2551 return(ERROR(ERRDOS,ERRnoaccess));
2553 close_file(fnum,True);
2555 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2561 /****************************************************************************
2562 reply to a printqueue
2563 ****************************************************************************/
2564 int reply_printqueue(char *inbuf,char *outbuf)
2567 int outsize = set_message(outbuf,2,3,True);
2568 int max_count = SVAL(inbuf,smb_vwv0);
2569 int start_index = SVAL(inbuf,smb_vwv1);
2572 cnum = SVAL(inbuf,smb_tid);
2573 vuid = SVAL(inbuf,smb_uid);
2575 /* allow checking the queue for anyone */
2577 if (!CAN_PRINT(cnum))
2578 return(ERROR(ERRDOS,ERRnoaccess));
2581 SSVAL(outbuf,smb_vwv0,0);
2582 SSVAL(outbuf,smb_vwv1,0);
2583 CVAL(smb_buf(outbuf),0) = 1;
2584 SSVAL(smb_buf(outbuf),1,0);
2586 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2587 timestring(),cnum,start_index,max_count));
2589 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2594 for (i=0;i<MAX_CONNECTIONS;i++)
2595 if (CAN_PRINT(i) && Connections[i].printer)
2599 for (i=0;i<MAX_CONNECTIONS;i++)
2603 if (!OPEN_CNUM(cnum))
2604 return(ERROR(ERRSRV,ERRinvnid));
2606 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2609 if (!become_user(cnum,vuid))
2610 return(ERROR(ERRSRV,ERRinvnid));
2613 print_queue_struct *queue = NULL;
2614 char *p = smb_buf(outbuf) + 3;
2615 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2616 int num_to_get = ABS(max_count);
2617 int first = (max_count>0?start_index:start_index+max_count+1);
2623 num_to_get = MIN(num_to_get,count-first);
2626 for (i=first;i<first+num_to_get;i++)
2628 put_dos_date2(p,0,queue[i].time);
2629 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2630 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2631 SIVAL(p,7,queue[i].size);
2633 StrnCpy(p+12,queue[i].user,16);
2639 outsize = set_message(outbuf,2,28*count+3,False);
2640 SSVAL(outbuf,smb_vwv0,count);
2641 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2642 CVAL(smb_buf(outbuf),0) = 1;
2643 SSVAL(smb_buf(outbuf),1,28*count);
2646 if (queue) free(queue);
2648 DEBUG(3,("%d entries returned in queue\n",count));
2655 /****************************************************************************
2656 reply to a printwrite
2657 ****************************************************************************/
2658 int reply_printwrite(char *inbuf,char *outbuf)
2660 int cnum,numtowrite,fnum;
2661 int outsize = set_message(outbuf,0,0,True);
2664 cnum = SVAL(inbuf,smb_tid);
2666 if (!CAN_PRINT(cnum))
2667 return(ERROR(ERRDOS,ERRnoaccess));
2669 fnum = GETFNUM(inbuf,smb_vwv0);
2671 CHECK_FNUM(fnum,cnum);
2675 numtowrite = SVAL(smb_buf(inbuf),1);
2676 data = smb_buf(inbuf) + 3;
2678 if (write_file(fnum,data,numtowrite) != numtowrite)
2679 return(UNIXERROR(ERRDOS,ERRnoaccess));
2681 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2687 /****************************************************************************
2689 ****************************************************************************/
2690 int reply_mkdir(char *inbuf,char *outbuf)
2694 int outsize,ret= -1;
2695 BOOL bad_path = False;
2697 pstrcpy(directory,smb_buf(inbuf) + 1);
2698 cnum = SVAL(inbuf,smb_tid);
2699 unix_convert(directory,cnum,0,&bad_path);
2701 if (check_name(directory,cnum))
2702 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2706 if((errno == ENOENT) && bad_path)
2708 unix_ERR_class = ERRDOS;
2709 unix_ERR_code = ERRbadpath;
2711 return(UNIXERROR(ERRDOS,ERRnoaccess));
2714 outsize = set_message(outbuf,0,0,True);
2716 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2721 /****************************************************************************
2722 Static function used by reply_rmdir to delete an entire directory
2724 ****************************************************************************/
2725 static BOOL recursive_rmdir(char *directory)
2729 void *dirptr = OpenDir(-1, directory, False);
2734 while((dname = ReadDirName(dirptr)))
2739 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2742 /* Construct the full name. */
2743 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2749 strcpy(fullname, directory);
2750 strcat(fullname, "/");
2751 strcat(fullname, dname);
2753 if(sys_lstat(fullname, &st) != 0)
2759 if(st.st_mode & S_IFDIR)
2761 if(recursive_rmdir(fullname)!=0)
2766 if(sys_rmdir(fullname) != 0)
2772 else if(sys_unlink(fullname) != 0)
2782 /****************************************************************************
2784 ****************************************************************************/
2785 int reply_rmdir(char *inbuf,char *outbuf)
2791 BOOL bad_path = False;
2793 cnum = SVAL(inbuf,smb_tid);
2794 pstrcpy(directory,smb_buf(inbuf) + 1);
2795 unix_convert(directory,cnum,0,&bad_path);
2797 if (check_name(directory,cnum))
2800 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2801 ok = (sys_rmdir(directory) == 0);
2802 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2804 /* Check to see if the only thing in this directory are
2805 vetoed files/directories. If so then delete them and
2806 retry. If we fail to delete any of them (and we *don't*
2807 do a recursive delete) then fail the rmdir. */
2808 BOOL all_veto_files = True;
2810 void *dirptr = OpenDir(cnum, directory, False);
2814 int dirpos = TellDir(dirptr);
2815 while ((dname = ReadDirName(dirptr)))
2817 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2819 if(!IS_VETO_PATH(cnum, dname))
2821 all_veto_files = False;
2827 SeekDir(dirptr,dirpos);
2828 while ((dname = ReadDirName(dirptr)))
2833 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2836 /* Construct the full name. */
2837 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2842 pstrcpy(fullname, directory);
2843 strcat(fullname, "/");
2844 strcat(fullname, dname);
2846 if(sys_lstat(fullname, &st) != 0)
2848 if(st.st_mode & S_IFDIR)
2850 if(lp_recursive_veto_delete(SNUM(cnum)))
2852 if(recursive_rmdir(fullname) != 0)
2855 if(sys_rmdir(fullname) != 0)
2858 else if(sys_unlink(fullname) != 0)
2862 /* Retry the rmdir */
2863 ok = (sys_rmdir(directory) == 0);
2873 DEBUG(3,("couldn't remove directory %s : %s\n",
2874 directory,strerror(errno)));
2879 if((errno == ENOENT) && bad_path)
2881 unix_ERR_class = ERRDOS;
2882 unix_ERR_code = ERRbadpath;
2884 return(UNIXERROR(ERRDOS,ERRbadpath));
2887 outsize = set_message(outbuf,0,0,True);
2889 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2895 /*******************************************************************
2896 resolve wildcards in a filename rename
2897 ********************************************************************/
2898 static BOOL resolve_wildcards(char *name1,char *name2)
2900 fstring root1,root2;
2904 name1 = strrchr(name1,'/');
2905 name2 = strrchr(name2,'/');
2907 if (!name1 || !name2) return(False);
2909 fstrcpy(root1,name1);
2910 fstrcpy(root2,name2);
2911 p = strrchr(root1,'.');
2918 p = strrchr(root2,'.');
2950 strcpy(name2,root2);
2959 /*******************************************************************
2960 check if a user is allowed to rename a file
2961 ********************************************************************/
2962 static BOOL can_rename(char *fname,int cnum)
2966 if (!CAN_WRITE(cnum)) return(False);
2968 if (sys_lstat(fname,&sbuf) != 0) return(False);
2969 if (!check_file_sharing(cnum,fname)) return(False);
2974 /****************************************************************************
2976 ****************************************************************************/
2977 int reply_mv(char *inbuf,char *outbuf)
2983 pstring mask,newname;
2984 pstring newname_last_component;
2987 int error = ERRnoaccess;
2990 BOOL bad_path1 = False;
2991 BOOL bad_path2 = False;
2993 *directory = *mask = 0;
2995 cnum = SVAL(inbuf,smb_tid);
2997 pstrcpy(name,smb_buf(inbuf) + 1);
2998 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3000 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3002 unix_convert(name,cnum,0,&bad_path1);
3003 unix_convert(newname,cnum,newname_last_component,&bad_path2);
3006 * Split the old name into directory and last component
3007 * strings. Note that unix_convert may have stripped off a
3008 * leading ./ from both name and newname if the rename is
3009 * at the root of the share. We need to make sure either both
3010 * name and newname contain a / character or neither of them do
3011 * as this is checked in resolve_wildcards().
3014 p = strrchr(name,'/');
3016 strcpy(directory,".");
3020 strcpy(directory,name);
3022 *p = '/'; /* Replace needed for exceptional test below. */
3025 if (is_mangled(mask))
3026 check_mangled_stack(mask);
3028 has_wild = strchr(mask,'*') || strchr(mask,'?');
3031 BOOL is_short_name = is_8_3(name, True);
3033 /* Add a terminating '/' to the directory name. */
3034 strcat(directory,"/");
3035 strcat(directory,mask);
3037 /* Ensure newname contains a '/' also */
3038 if(strrchr(newname,'/') == 0) {
3041 strcpy(tmpstr, "./");
3042 strcat(tmpstr, newname);
3043 strcpy(newname, tmpstr);
3046 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",
3047 case_sensitive, case_preserve, short_case_preserve, directory,
3048 newname, newname_last_component, is_short_name));
3051 * Check for special case with case preserving and not
3052 * case sensitive, if directory and newname are identical,
3053 * and the old last component differs from the original
3054 * last component only by case, then we should allow
3055 * the rename (user is trying to change the case of the
3058 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3059 ((short_case_preserve == True) && (is_short_name == True))) &&
3060 strcsequal(directory, newname)) {
3061 pstring newname_modified_last_component;
3064 * Get the last component of the modified name.
3065 * Note that we guarantee that newname contains a '/'
3068 p = strrchr(newname,'/');
3069 strcpy(newname_modified_last_component,p+1);
3071 if(strcsequal(newname_modified_last_component,
3072 newname_last_component) == False) {
3074 * Replace the modified last component with
3077 strcpy(p+1, newname_last_component);
3081 if (resolve_wildcards(directory,newname) &&
3082 can_rename(directory,cnum) &&
3083 !file_exist(newname,NULL) &&
3084 !sys_rename(directory,newname)) count++;
3086 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3087 directory,newname));
3089 if (!count) exists = file_exist(directory,NULL);
3090 if (!count && exists && file_exist(newname,NULL)) {
3095 void *dirptr = NULL;
3099 if (check_name(directory,cnum))
3100 dirptr = OpenDir(cnum, directory, True);
3106 if (strequal(mask,"????????.???"))
3109 while ((dname = ReadDirName(dirptr)))
3112 pstrcpy(fname,dname);
3114 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3116 error = ERRnoaccess;
3117 sprintf(fname,"%s/%s",directory,dname);
3118 if (!can_rename(fname,cnum)) continue;
3119 pstrcpy(destname,newname);
3121 if (!resolve_wildcards(fname,destname)) continue;
3123 if (file_exist(destname,NULL)) {
3127 if (!sys_rename(fname,destname)) count++;
3128 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3136 return(ERROR(ERRDOS,error));
3139 if((errno == ENOENT) && (bad_path1 || bad_path2))
3141 unix_ERR_class = ERRDOS;
3142 unix_ERR_code = ERRbadpath;
3144 return(UNIXERROR(ERRDOS,error));
3148 outsize = set_message(outbuf,0,0,True);
3153 /*******************************************************************
3154 copy a file as part of a reply_copy
3155 ******************************************************************/
3156 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3157 int count,BOOL target_is_directory)
3165 pstrcpy(dest,dest1);
3166 if (target_is_directory) {
3167 char *p = strrchr(src,'/');
3176 if (!file_exist(src,&st)) return(False);
3178 fnum1 = find_free_file();
3179 if (fnum1<0) return(False);
3180 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3181 1,0,0,&Access,&action);
3183 if (!Files[fnum1].open) return(False);
3185 if (!target_is_directory && count)
3188 fnum2 = find_free_file();
3190 close_file(fnum1,False);
3193 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3194 ofun,st.st_mode,0,&Access,&action);
3196 if (!Files[fnum2].open) {
3197 close_file(fnum1,False);
3201 if ((ofun&3) == 1) {
3202 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3206 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3208 close_file(fnum1,False);
3209 close_file(fnum2,False);
3211 return(ret == st.st_size);
3216 /****************************************************************************
3217 reply to a file copy.
3218 ****************************************************************************/
3219 int reply_copy(char *inbuf,char *outbuf)
3225 pstring mask,newname;
3228 int error = ERRnoaccess;
3231 int tid2 = SVAL(inbuf,smb_vwv0);
3232 int ofun = SVAL(inbuf,smb_vwv1);
3233 int flags = SVAL(inbuf,smb_vwv2);
3234 BOOL target_is_directory=False;
3235 BOOL bad_path1 = False;
3236 BOOL bad_path2 = False;
3238 *directory = *mask = 0;
3240 cnum = SVAL(inbuf,smb_tid);
3242 pstrcpy(name,smb_buf(inbuf));
3243 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3245 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3248 /* can't currently handle inter share copies XXXX */
3249 DEBUG(3,("Rejecting inter-share copy\n"));
3250 return(ERROR(ERRSRV,ERRinvdevice));
3253 unix_convert(name,cnum,0,&bad_path1);
3254 unix_convert(newname,cnum,0,&bad_path2);
3256 target_is_directory = directory_exist(newname,NULL);
3258 if ((flags&1) && target_is_directory) {
3259 return(ERROR(ERRDOS,ERRbadfile));
3262 if ((flags&2) && !target_is_directory) {
3263 return(ERROR(ERRDOS,ERRbadpath));
3266 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3267 /* wants a tree copy! XXXX */
3268 DEBUG(3,("Rejecting tree copy\n"));
3269 return(ERROR(ERRSRV,ERRerror));
3272 p = strrchr(name,'/');
3274 strcpy(directory,"./");
3278 strcpy(directory,name);
3282 if (is_mangled(mask))
3283 check_mangled_stack(mask);
3285 has_wild = strchr(mask,'*') || strchr(mask,'?');
3288 strcat(directory,"/");
3289 strcat(directory,mask);
3290 if (resolve_wildcards(directory,newname) &&
3291 copy_file(directory,newname,cnum,ofun,
3292 count,target_is_directory)) count++;
3293 if (!count) exists = file_exist(directory,NULL);
3295 void *dirptr = NULL;
3299 if (check_name(directory,cnum))
3300 dirptr = OpenDir(cnum, directory, True);
3306 if (strequal(mask,"????????.???"))
3309 while ((dname = ReadDirName(dirptr)))
3312 pstrcpy(fname,dname);
3314 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3316 error = ERRnoaccess;
3317 sprintf(fname,"%s/%s",directory,dname);
3318 strcpy(destname,newname);
3319 if (resolve_wildcards(fname,destname) &&
3320 copy_file(directory,newname,cnum,ofun,
3321 count,target_is_directory)) count++;
3322 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3330 return(ERROR(ERRDOS,error));
3333 if((errno == ENOENT) && (bad_path1 || bad_path2))
3335 unix_ERR_class = ERRDOS;
3336 unix_ERR_code = ERRbadpath;
3338 return(UNIXERROR(ERRDOS,error));
3342 outsize = set_message(outbuf,1,0,True);
3343 SSVAL(outbuf,smb_vwv0,count);
3350 /****************************************************************************
3352 ****************************************************************************/
3353 int reply_setdir(char *inbuf,char *outbuf)
3360 cnum = SVAL(inbuf,smb_tid);
3362 snum = Connections[cnum].service;
3363 if (!CAN_SETDIR(snum))
3364 return(ERROR(ERRDOS,ERRnoaccess));
3366 pstrcpy(newdir,smb_buf(inbuf) + 1);
3369 if (strlen(newdir) == 0)
3373 ok = directory_exist(newdir,NULL);
3375 string_set(&Connections[cnum].connectpath,newdir);
3379 return(ERROR(ERRDOS,ERRbadpath));
3381 outsize = set_message(outbuf,0,0,True);
3382 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3384 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3390 /****************************************************************************
3391 reply to a lockingX request
3392 ****************************************************************************/
3393 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3395 int fnum = GETFNUM(inbuf,smb_vwv2);
3396 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3398 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3400 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3401 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3402 uint32 count, offset;
3407 uint32 ecode=0, dummy2;
3408 int eclass=0, dummy1;
3410 cnum = SVAL(inbuf,smb_tid);
3412 CHECK_FNUM(fnum,cnum);
3415 data = smb_buf(inbuf);
3417 /* Check if this is an oplock break on a file
3418 we have granted an oplock on.
3420 if((locktype == LOCKING_ANDX_OPLOCK_RELEASE) &&
3421 (num_ulocks == 0) && (num_locks == 0) &&
3422 (CVAL(inbuf,smb_vwv0) == 0xFF))
3424 share_lock_token token;
3425 files_struct *fsp = &Files[fnum];
3426 uint32 dev = fsp->fd_ptr->dev;
3427 uint32 inode = fsp->fd_ptr->inode;
3429 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3432 * Make sure we have granted an oplock on this file.
3434 if(!fsp->granted_oplock)
3436 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3437 no oplock granted on this file.\n", fnum));
3438 return ERROR(ERRDOS,ERRlock);
3441 /* Remove the oplock flag from the sharemode. */
3442 lock_share_entry(fsp->cnum, dev, inode, &token);
3443 if(remove_share_oplock( fnum, token)==False)
3445 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3446 dev = %x, inode = %x\n", fnum, dev, inode));
3447 unlock_share_entry(fsp->cnum, dev, inode, token);
3450 unlock_share_entry(fsp->cnum, dev, inode, token);
3452 /* Clear the granted flag and return. */
3454 fsp->granted_oplock = False;
3458 /* Data now points at the beginning of the list
3459 of smb_unlkrng structs */
3460 for(i = 0; i < (int)num_ulocks; i++) {
3461 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3462 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3463 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3464 return ERROR(eclass,ecode);
3467 /* Now do any requested locks */
3468 data += 10*num_ulocks;
3469 /* Data now points at the beginning of the list
3470 of smb_lkrng structs */
3471 for(i = 0; i < (int)num_locks; i++) {
3472 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3473 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3474 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3478 /* If any of the above locks failed, then we must unlock
3479 all of the previous locks (X/Open spec). */
3480 if(i != num_locks && num_locks != 0) {
3481 for(; i >= 0; i--) {
3482 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3483 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3484 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3486 return ERROR(eclass,ecode);
3489 set_message(outbuf,2,0,True);
3491 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3492 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3496 return chain_reply(inbuf,outbuf,length,bufsize);
3500 /****************************************************************************
3501 reply to a SMBreadbmpx (read block multiplex) request
3502 ****************************************************************************/
3503 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3510 int outsize, mincount, maxcount;
3515 /* this function doesn't seem to work - disable by default */
3517 return(ERROR(ERRSRV,ERRuseSTD));
3519 outsize = set_message(outbuf,8,0,True);
3521 cnum = SVAL(inbuf,smb_tid);
3522 fnum = GETFNUM(inbuf,smb_vwv0);
3524 CHECK_FNUM(fnum,cnum);
3528 startpos = IVAL(inbuf,smb_vwv1);
3529 maxcount = SVAL(inbuf,smb_vwv3);
3530 mincount = SVAL(inbuf,smb_vwv4);
3532 data = smb_buf(outbuf);
3533 pad = ((long)data)%4;
3534 if (pad) pad = 4 - pad;
3537 max_per_packet = bufsize-(outsize+pad);
3541 if (is_locked(fnum,cnum,maxcount,startpos))
3542 return(ERROR(ERRDOS,ERRlock));
3546 int N = MIN(max_per_packet,tcount-total_read);
3548 nread = read_file(fnum,data,startpos,N);
3550 if (nread <= 0) nread = 0;
3553 tcount = total_read + nread;
3555 set_message(outbuf,8,nread,False);
3556 SIVAL(outbuf,smb_vwv0,startpos);
3557 SSVAL(outbuf,smb_vwv2,tcount);
3558 SSVAL(outbuf,smb_vwv6,nread);
3559 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3561 send_smb(Client,outbuf);
3563 total_read += nread;
3566 while (total_read < tcount);
3572 /****************************************************************************
3573 reply to a SMBwritebmpx (write block multiplex primary) request
3574 ****************************************************************************/
3575 int reply_writebmpx(char *inbuf,char *outbuf)
3577 int cnum,numtowrite,fnum;
3581 int tcount, write_through, smb_doff;
3584 cnum = SVAL(inbuf,smb_tid);
3585 fnum = GETFNUM(inbuf,smb_vwv0);
3587 CHECK_FNUM(fnum,cnum);
3591 tcount = SVAL(inbuf,smb_vwv1);
3592 startpos = IVAL(inbuf,smb_vwv3);
3593 write_through = BITSETW(inbuf+smb_vwv7,0);
3594 numtowrite = SVAL(inbuf,smb_vwv10);
3595 smb_doff = SVAL(inbuf,smb_vwv11);
3597 data = smb_base(inbuf) + smb_doff;
3599 /* If this fails we need to send an SMBwriteC response,
3600 not an SMBwritebmpx - set this up now so we don't forget */
3601 CVAL(outbuf,smb_com) = SMBwritec;
3603 if (is_locked(fnum,cnum,tcount,startpos))
3604 return(ERROR(ERRDOS,ERRlock));
3606 seek_file(fnum,startpos);
3607 nwritten = write_file(fnum,data,numtowrite);
3609 if(lp_syncalways(SNUM(cnum)) || write_through)
3612 if(nwritten < numtowrite)
3613 return(UNIXERROR(ERRHRD,ERRdiskfull));
3615 /* If the maximum to be written to this file
3616 is greater than what we just wrote then set
3617 up a secondary struct to be attached to this
3618 fd, we will use this to cache error messages etc. */
3619 if(tcount > nwritten)
3621 write_bmpx_struct *wbms;
3622 if(Files[fnum].wbmpx_ptr != NULL)
3623 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3625 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3628 DEBUG(0,("Out of memory in reply_readmpx\n"));
3629 return(ERROR(ERRSRV,ERRnoresource));
3631 wbms->wr_mode = write_through;
3632 wbms->wr_discard = False; /* No errors yet */
3633 wbms->wr_total_written = nwritten;
3634 wbms->wr_errclass = 0;
3636 Files[fnum].wbmpx_ptr = wbms;
3639 /* We are returning successfully, set the message type back to
3641 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3643 outsize = set_message(outbuf,1,0,True);
3645 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3647 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3648 timestring(),fnum,cnum,numtowrite,nwritten));
3650 if (write_through && tcount==nwritten) {
3651 /* we need to send both a primary and a secondary response */
3652 smb_setlen(outbuf,outsize - 4);
3653 send_smb(Client,outbuf);
3655 /* now the secondary */
3656 outsize = set_message(outbuf,1,0,True);
3657 CVAL(outbuf,smb_com) = SMBwritec;
3658 SSVAL(outbuf,smb_vwv0,nwritten);
3665 /****************************************************************************
3666 reply to a SMBwritebs (write block multiplex secondary) request
3667 ****************************************************************************/
3668 int reply_writebs(char *inbuf,char *outbuf)
3670 int cnum,numtowrite,fnum;
3674 int tcount, write_through, smb_doff;
3676 write_bmpx_struct *wbms;
3677 BOOL send_response = False;
3679 cnum = SVAL(inbuf,smb_tid);
3680 fnum = GETFNUM(inbuf,smb_vwv0);
3681 CHECK_FNUM(fnum,cnum);
3684 tcount = SVAL(inbuf,smb_vwv1);
3685 startpos = IVAL(inbuf,smb_vwv2);
3686 numtowrite = SVAL(inbuf,smb_vwv6);
3687 smb_doff = SVAL(inbuf,smb_vwv7);
3689 data = smb_base(inbuf) + smb_doff;
3691 /* We need to send an SMBwriteC response, not an SMBwritebs */
3692 CVAL(outbuf,smb_com) = SMBwritec;
3694 /* This fd should have an auxiliary struct attached,
3695 check that it does */
3696 wbms = Files[fnum].wbmpx_ptr;
3697 if(!wbms) return(-1);
3699 /* If write through is set we can return errors, else we must
3701 write_through = wbms->wr_mode;
3703 /* Check for an earlier error */
3704 if(wbms->wr_discard)
3705 return -1; /* Just discard the packet */
3707 seek_file(fnum,startpos);
3708 nwritten = write_file(fnum,data,numtowrite);
3710 if(lp_syncalways(SNUM(cnum)) || write_through)
3713 if (nwritten < numtowrite)
3716 /* We are returning an error - we can delete the aux struct */
3717 if (wbms) free((char *)wbms);
3718 Files[fnum].wbmpx_ptr = NULL;
3719 return(ERROR(ERRHRD,ERRdiskfull));
3721 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3724 /* Increment the total written, if this matches tcount
3725 we can discard the auxiliary struct (hurrah !) and return a writeC */
3726 wbms->wr_total_written += nwritten;
3727 if(wbms->wr_total_written >= tcount)
3729 if (write_through) {
3730 outsize = set_message(outbuf,1,0,True);
3731 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3732 send_response = True;
3736 Files[fnum].wbmpx_ptr = NULL;
3746 /****************************************************************************
3747 reply to a SMBsetattrE
3748 ****************************************************************************/
3749 int reply_setattrE(char *inbuf,char *outbuf)
3752 struct utimbuf unix_times;
3755 outsize = set_message(outbuf,0,0,True);
3757 cnum = SVAL(inbuf,smb_tid);
3758 fnum = GETFNUM(inbuf,smb_vwv0);
3760 CHECK_FNUM(fnum,cnum);
3763 /* Convert the DOS times into unix times. Ignore create
3764 time as UNIX can't set this.
3766 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3767 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3770 * Patch from Ray Frush <frush@engr.colostate.edu>
3771 * Sometimes times are sent as zero - ignore them.
3774 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3776 /* Ignore request */
3777 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3778 not setting timestamps of 0\n",
3779 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3782 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3784 /* set modify time = to access time if modify time was 0 */
3785 unix_times.modtime = unix_times.actime;
3788 /* Set the date on this file */
3789 if(sys_utime(Files[fnum].name, &unix_times))
3790 return(ERROR(ERRDOS,ERRnoaccess));
3792 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3793 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3799 /****************************************************************************
3800 reply to a SMBgetattrE
3801 ****************************************************************************/
3802 int reply_getattrE(char *inbuf,char *outbuf)
3809 outsize = set_message(outbuf,11,0,True);
3811 cnum = SVAL(inbuf,smb_tid);
3812 fnum = GETFNUM(inbuf,smb_vwv0);
3814 CHECK_FNUM(fnum,cnum);
3817 /* Do an fstat on this file */
3818 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3819 return(UNIXERROR(ERRDOS,ERRnoaccess));
3821 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3823 /* Convert the times into dos times. Set create
3824 date to be last modify date as UNIX doesn't save
3826 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3827 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3828 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3831 SIVAL(outbuf,smb_vwv6,0);
3832 SIVAL(outbuf,smb_vwv8,0);
3836 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3837 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3839 SSVAL(outbuf,smb_vwv10, mode);
3841 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));