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
31 /* look in server.c for some explanation of these variables */
33 extern int DEBUGLEVEL;
36 extern int chain_fnum;
37 extern char magic_char;
38 extern connection_struct Connections[];
39 extern files_struct Files[];
40 extern BOOL case_sensitive;
41 extern BOOL case_preserve;
42 extern BOOL short_case_preserve;
43 extern pstring sesssetup_user;
44 extern fstring myworkgroup;
46 extern int global_oplock_break;
48 /* this macro should always be used to extract an fnum (smb_fid) from
49 a packet to ensure chaining works correctly */
50 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
53 /****************************************************************************
54 report a possible attack via the password buffer overflow bug
55 ****************************************************************************/
56 static void overflow_attack(int len)
58 DEBUG(0,("ERROR: Invalid password length %d\n", len));
59 DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n"));
60 DEBUG(0,("Attack was from IP=%s\n", client_addr()));
61 exit_server("possible attack");
65 /****************************************************************************
66 reply to an special message
67 ****************************************************************************/
68 int reply_special(char *inbuf,char *outbuf)
71 int msg_type = CVAL(inbuf,0);
72 int msg_flags = CVAL(inbuf,1);
74 extern fstring remote_machine;
75 extern fstring local_machine;
83 case 0x81: /* session request */
84 CVAL(outbuf,0) = 0x82;
86 if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
87 DEBUG(0,("Invalid name length in session request\n"));
90 name_extract(inbuf,4,name1);
91 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
92 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
95 fstrcpy(remote_machine,name2);
96 trim_string(remote_machine," "," ");
97 p = strchr(remote_machine,' ');
98 strlower(remote_machine);
101 fstrcpy(local_machine,name1);
102 trim_string(local_machine," "," ");
103 p = strchr(local_machine,' ');
104 strlower(local_machine);
107 add_session_user(remote_machine);
109 reload_services(True);
114 case 0x89: /* session keepalive request
115 (some old clients produce this?) */
116 CVAL(outbuf,0) = 0x85;
120 case 0x82: /* positive session response */
121 case 0x83: /* negative session response */
122 case 0x84: /* retarget session response */
123 DEBUG(0,("Unexpected session response\n"));
126 case 0x85: /* session keepalive */
131 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",
132 timestring(),msg_type,msg_flags));
138 /*******************************************************************
139 work out what error to give to a failed connection
140 ********************************************************************/
141 static int connection_error(char *inbuf,char *outbuf,int connection_num)
143 switch (connection_num)
146 return(ERROR(ERRSRV,ERRnoresource));
148 return(ERROR(ERRSRV,ERRbaduid));
150 return(ERROR(ERRSRV,ERRinvdevice));
152 return(ERROR(ERRSRV,ERRinvnetname));
154 return(ERROR(ERRSRV,ERRaccess));
156 return(ERROR(ERRDOS,ERRnoipc));
158 return(ERROR(ERRSRV,ERRinvnetname));
160 return(ERROR(ERRSRV,ERRbadpw));
165 /****************************************************************************
166 parse a share descriptor string
167 ****************************************************************************/
168 static void parse_connect(char *p,char *service,char *user,
169 char *password,int *pwlen,char *dev)
173 DEBUG(4,("parsing connect string %s\n",p));
175 p2 = strrchr(p,'\\');
179 fstrcpy(service,p2+1);
184 *pwlen = strlen(password);
191 p = strchr(service,'%');
202 /****************************************************************************
204 ****************************************************************************/
205 int reply_tcon(char *inbuf,char *outbuf)
213 uint16 vuid = SVAL(inbuf,smb_uid);
216 *service = *user = *password = *dev = 0;
218 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
220 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
222 if (connection_num < 0)
223 return(connection_error(inbuf,outbuf,connection_num));
225 outsize = set_message(outbuf,2,0,True);
226 SSVAL(outbuf,smb_vwv0,max_recv);
227 SSVAL(outbuf,smb_vwv1,connection_num);
228 SSVAL(outbuf,smb_tid,connection_num);
230 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
236 /****************************************************************************
237 reply to a tcon and X
238 ****************************************************************************/
239 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
246 uint16 vuid = SVAL(inbuf,smb_uid);
247 int passlen = SVAL(inbuf,smb_vwv3);
248 BOOL doencrypt = SMBENCRYPT();
250 *service = *user = *password = *devicename = 0;
252 /* we might have to close an old one */
253 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
254 close_cnum(SVAL(inbuf,smb_tid),vuid);
256 if (passlen > MAX_PASS_LEN) {
257 overflow_attack(passlen);
263 memcpy(password,smb_buf(inbuf),passlen);
265 path = smb_buf(inbuf) + passlen;
267 if (!doencrypt || passlen != 24) {
268 if (strequal(password," "))
270 passlen = strlen(password);
273 fstrcpy(service,path+2);
274 p = strchr(service,'\\');
276 return(ERROR(ERRSRV,ERRinvnetname));
278 fstrcpy(service,p+1);
279 p = strchr(service,'%');
285 StrnCpy(devicename,path + strlen(path) + 1,6);
286 DEBUG(4,("Got device type %s\n",devicename));
289 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
291 if (connection_num < 0)
292 return(connection_error(inbuf,outbuf,connection_num));
294 if (Protocol < PROTOCOL_NT1)
296 set_message(outbuf,2,strlen(devicename)+1,True);
297 strcpy(smb_buf(outbuf),devicename);
301 char *fsname = "SAMBA";
304 set_message(outbuf,3,3,True);
307 strcpy(p,devicename); p = skip_string(p,1); /* device name */
308 strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
310 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
312 SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
315 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
317 /* set the incoming and outgoing tid to the just created one */
318 SSVAL(inbuf,smb_tid,connection_num);
319 SSVAL(outbuf,smb_tid,connection_num);
321 return chain_reply(inbuf,outbuf,length,bufsize);
325 /****************************************************************************
326 reply to an unknown type
327 ****************************************************************************/
328 int reply_unknown(char *inbuf,char *outbuf)
332 cnum = SVAL(inbuf,smb_tid);
333 type = CVAL(inbuf,smb_com);
335 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
340 return(ERROR(ERRSRV,ERRunknownsmb));
344 /****************************************************************************
346 ****************************************************************************/
347 int reply_ioctl(char *inbuf,char *outbuf)
349 DEBUG(3,("ignoring ioctl\n"));
351 /* we just say it succeeds and hope its all OK.
352 some day it would be nice to interpret them individually */
353 return set_message(outbuf,1,0,True);
355 return(ERROR(ERRSRV,ERRnosupport));
360 /****************************************************************************
361 reply to a session setup command
362 ****************************************************************************/
363 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
372 int smb_apasslen = 0;
374 int smb_ntpasslen = 0;
375 pstring smb_ntpasswd;
376 BOOL valid_nt_password = False;
379 BOOL computer_id=False;
380 static BOOL done_sesssetup = False;
381 BOOL doencrypt = SMBENCRYPT();
387 smb_bufsize = SVAL(inbuf,smb_vwv2);
388 smb_mpxmax = SVAL(inbuf,smb_vwv3);
389 smb_vc_num = SVAL(inbuf,smb_vwv4);
390 smb_sesskey = IVAL(inbuf,smb_vwv5);
392 if (Protocol < PROTOCOL_NT1) {
393 smb_apasslen = SVAL(inbuf,smb_vwv7);
394 if (smb_apasslen > MAX_PASS_LEN)
396 overflow_attack(smb_apasslen);
399 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
400 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
402 if (lp_security() != SEC_SERVER && !doencrypt) {
403 smb_apasslen = strlen(smb_apasswd);
406 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
407 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
408 uint32 client_caps = IVAL(inbuf,smb_vwv11);
409 enum remote_arch_types ra_type = get_remote_arch();
411 char *p = smb_buf(inbuf);
413 /* client_caps is used as final determination if client is NT or Win95.
414 This is needed to return the correct error codes in some
418 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
420 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
421 set_remote_arch( RA_WINNT);
423 set_remote_arch( RA_WIN95);
426 if (passlen1 != 24 && passlen2 != 24)
429 if (passlen1 > MAX_PASS_LEN) {
430 overflow_attack(passlen1);
433 passlen1 = MIN(passlen1, MAX_PASS_LEN);
434 passlen2 = MIN(passlen2, MAX_PASS_LEN);
437 /* Save the lanman2 password and the NT md4 password. */
438 smb_apasslen = passlen1;
439 memcpy(smb_apasswd,p,smb_apasslen);
440 smb_ntpasslen = passlen2;
441 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
443 /* both Win95 and WinNT stuff up the password lengths for
444 non-encrypting systems. Uggh.
446 if passlen1==24 its a win95 system, and its setting the
447 password length incorrectly. Luckily it still works with the
448 default code because Win95 will null terminate the password
451 if passlen1>0 and passlen2>0 then maybe its a NT box and its
452 setting passlen2 to some random value which really stuffs
453 things up. we need to fix that one. */
454 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
458 /* we use the first password that they gave */
459 smb_apasslen = passlen1;
460 StrnCpy(smb_apasswd,p,smb_apasslen);
462 /* trim the password */
463 smb_apasslen = strlen(smb_apasswd);
465 /* wfwg sometimes uses a space instead of a null */
466 if (strequal(smb_apasswd," ")) {
472 p += passlen1 + passlen2;
473 fstrcpy(user,p); p = skip_string(p,1);
476 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
477 domain,skip_string(p,1),skip_string(p,2)));
481 DEBUG(3,("sesssetupX:name=[%s]\n",user));
483 /* If name ends in $ then I think it's asking about whether a */
484 /* computer with that name (minus the $) has access. For now */
485 /* say yes to everything ending in $. */
486 if (user[strlen(user) - 1] == '$') {
488 struct smb_passwd *smb_pass; /* To check if machine account exists */
490 PAXX: Ack. We don't want to do this. The workstation trust account
491 with a $ on the end should exist in the local password database
492 or be mapped to something generic, but not modified. For NT
493 domain support we must reject this used in certain circumstances
494 with a code to indicate to the client that it is an invalid use
495 of a workstation trust account. NTWKS needs this error to join
496 a domain. This may be the source of future bugs if we cannot
497 be sure whether to reject this or not.
499 smb_pass = get_smbpwnam(user);
502 /* PAXX: This is the NO LOGON workstation trust account stuff */
503 DEBUG(4,("Rejecting workstation trust account %s",user));
504 SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
505 CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
506 return(ERROR(NT_STATUS_ALLOTTED_SPACE_EXCEEDED, 0xc000)); /* 0x99 NT error, 0xc00 */
509 #else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */
510 user[strlen(user) - 1] = '\0';
515 /* If no username is sent use the guest account */
518 strcpy(user,lp_guestaccount(-1));
519 /* If no user and no password then set guest flag. */
520 if( *smb_apasswd == 0)
526 strcpy(sesssetup_user,user);
528 reload_services(True);
530 add_session_user(user);
532 /* Check if the given username was the guest user with no password.
533 We need to do this check after add_session_user() as that
534 call can potentially change the username (via map_user).
537 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
540 if (!guest && !(lp_security() == SEC_SERVER &&
541 server_validate(user, domain,
542 smb_apasswd, smb_apasslen,
543 smb_ntpasswd, smb_ntpasslen)) &&
544 !check_hosts_equiv(user))
547 /* now check if it's a valid username/password */
548 /* If an NT password was supplied try and validate with that
549 first. This is superior as the passwords are mixed case
550 128 length unicode */
553 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
554 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
556 valid_nt_password = True;
558 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
560 if (!computer_id && lp_security() >= SEC_USER) {
561 #if (GUEST_SESSSETUP == 0)
562 return(ERROR(ERRSRV,ERRbadpw));
564 #if (GUEST_SESSSETUP == 1)
565 if (Get_Pwnam(user,True))
566 return(ERROR(ERRSRV,ERRbadpw));
569 if (*smb_apasswd || !Get_Pwnam(user,True))
570 strcpy(user,lp_guestaccount(-1));
571 DEBUG(3,("Registered username %s for guest access\n",user));
576 if (!Get_Pwnam(user,True)) {
577 DEBUG(3,("No such user %s - using guest account\n",user));
578 strcpy(user,lp_guestaccount(-1));
582 if (!strequal(user,lp_guestaccount(-1)) &&
583 lp_servicenumber(user) < 0)
585 int homes = lp_servicenumber(HOMES_NAME);
586 char *home = get_home_dir(user);
587 if (homes >= 0 && home)
588 lp_add_home(user,homes,home);
592 /* it's ok - setup a reply */
593 if (Protocol < PROTOCOL_NT1) {
594 set_message(outbuf,3,0,True);
597 set_message(outbuf,3,3,True);
599 strcpy(p,"Unix"); p = skip_string(p,1);
600 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
601 strcpy(p,myworkgroup); p = skip_string(p,1);
602 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
603 /* perhaps grab OS version here?? */
606 /* Set the correct uid in the outgoing and incoming packets
607 We will use this on future requests to determine which
608 user we should become.
611 struct passwd *pw = Get_Pwnam(user,False);
613 DEBUG(1,("Username %s is invalid on this system\n",user));
614 return(ERROR(ERRSRV,ERRbadpw));
620 if (guest && !computer_id)
621 SSVAL(outbuf,smb_vwv2,1);
623 /* register the name and uid as being validated, so further connections
624 to a uid can get through without a password, on the same VC */
625 sess_vuid = register_vuid(uid,gid,user,guest);
627 SSVAL(outbuf,smb_uid,sess_vuid);
628 SSVAL(inbuf,smb_uid,sess_vuid);
631 max_send = MIN(max_send,smb_bufsize);
633 DEBUG(6,("Client requested max send size of %d\n", max_send));
635 done_sesssetup = True;
637 return chain_reply(inbuf,outbuf,length,bufsize);
641 /****************************************************************************
643 ****************************************************************************/
644 int reply_chkpth(char *inbuf,char *outbuf)
650 BOOL bad_path = False;
652 cnum = SVAL(inbuf,smb_tid);
654 pstrcpy(name,smb_buf(inbuf) + 1);
655 unix_convert(name,cnum,0,&bad_path);
657 mode = SVAL(inbuf,smb_vwv0);
659 if (check_name(name,cnum))
660 ok = directory_exist(name,NULL);
664 /* We special case this - as when a Windows machine
665 is parsing a path is steps through the components
666 one at a time - if a component fails it expects
667 ERRbadpath, not ERRbadfile.
671 unix_ERR_class = ERRDOS;
672 unix_ERR_code = ERRbadpath;
676 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
677 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
678 (get_remote_arch() == RA_WINNT))
680 unix_ERR_class = ERRDOS;
681 unix_ERR_code = ERRbaddirectory;
685 return(UNIXERROR(ERRDOS,ERRbadpath));
688 outsize = set_message(outbuf,0,0,True);
690 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
696 /****************************************************************************
698 ****************************************************************************/
699 int reply_getatr(char *inbuf,char *outbuf)
709 BOOL bad_path = False;
711 cnum = SVAL(inbuf,smb_tid);
713 pstrcpy(fname,smb_buf(inbuf) + 1);
714 unix_convert(fname,cnum,0,&bad_path);
716 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
717 under WfWg - weird! */
720 mode = aHIDDEN | aDIR;
721 if (!CAN_WRITE(cnum)) mode |= aRONLY;
727 if (check_name(fname,cnum))
729 if (sys_stat(fname,&sbuf) == 0)
731 mode = dos_mode(cnum,fname,&sbuf);
733 mtime = sbuf.st_mtime;
739 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
744 if((errno == ENOENT) && bad_path)
746 unix_ERR_class = ERRDOS;
747 unix_ERR_code = ERRbadpath;
750 return(UNIXERROR(ERRDOS,ERRbadfile));
753 outsize = set_message(outbuf,10,0,True);
755 SSVAL(outbuf,smb_vwv0,mode);
756 put_dos_date3(outbuf,smb_vwv1,mtime);
757 SIVAL(outbuf,smb_vwv3,size);
759 if (Protocol >= PROTOCOL_NT1) {
760 char *p = strrchr(fname,'/');
761 uint16 flg2 = SVAL(outbuf,smb_flg2);
763 if (!is_8_3(fname, True))
764 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
767 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
773 /****************************************************************************
775 ****************************************************************************/
776 int reply_setatr(char *inbuf,char *outbuf)
784 BOOL bad_path = False;
786 cnum = SVAL(inbuf,smb_tid);
788 pstrcpy(fname,smb_buf(inbuf) + 1);
789 unix_convert(fname,cnum,0,&bad_path);
791 mode = SVAL(inbuf,smb_vwv0);
792 mtime = make_unix_date3(inbuf+smb_vwv1);
794 if (directory_exist(fname,NULL))
796 if (check_name(fname,cnum))
797 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
799 ok = set_filetime(cnum,fname,mtime);
803 if((errno == ENOENT) && bad_path)
805 unix_ERR_class = ERRDOS;
806 unix_ERR_code = ERRbadpath;
809 return(UNIXERROR(ERRDOS,ERRnoaccess));
812 outsize = set_message(outbuf,0,0,True);
814 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
820 /****************************************************************************
822 ****************************************************************************/
823 int reply_dskattr(char *inbuf,char *outbuf)
827 int dfree,dsize,bsize;
829 cnum = SVAL(inbuf,smb_tid);
831 sys_disk_free(".",&bsize,&dfree,&dsize);
833 outsize = set_message(outbuf,5,0,True);
835 SSVAL(outbuf,smb_vwv0,dsize);
836 SSVAL(outbuf,smb_vwv1,bsize/512);
837 SSVAL(outbuf,smb_vwv2,512);
838 SSVAL(outbuf,smb_vwv3,dfree);
840 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
846 /****************************************************************************
848 Can be called from SMBsearch, SMBffirst or SMBfunique.
849 ****************************************************************************/
850 int reply_search(char *inbuf,char *outbuf)
861 BOOL finished = False;
870 BOOL check_descend = False;
871 BOOL expect_close = False;
872 BOOL can_open = True;
873 BOOL bad_path = False;
875 *mask = *directory = *fname = 0;
877 /* If we were called as SMBffirst then we must expect close. */
878 if(CVAL(inbuf,smb_com) == SMBffirst)
881 cnum = SVAL(inbuf,smb_tid);
883 outsize = set_message(outbuf,1,3,True);
884 maxentries = SVAL(inbuf,smb_vwv0);
885 dirtype = SVAL(inbuf,smb_vwv1);
886 path = smb_buf(inbuf) + 1;
887 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
890 /* dirtype &= ~aDIR; */
892 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
899 pstrcpy(directory,smb_buf(inbuf)+1);
900 pstrcpy(dir2,smb_buf(inbuf)+1);
901 unix_convert(directory,cnum,0,&bad_path);
904 if (!check_name(directory,cnum))
907 p = strrchr(dir2,'/');
919 p = strrchr(directory,'/');
925 if (strlen(directory) == 0)
926 strcpy(directory,"./");
928 CVAL(status,0) = dirtype;
932 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
933 memcpy(mask,status+1,11);
935 dirtype = CVAL(status,0) & 0x1F;
936 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
937 if (!Connections[cnum].dirptr)
939 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
944 /* turn strings of spaces into a . */
946 trim_string(mask,NULL," ");
947 if ((p = strrchr(mask,' ')))
952 trim_string(mask,NULL," ");
959 for (p=mask; *p; p++)
961 if (*p != '?' && *p != '*' && !isdoschar(*p))
963 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
969 if (!strchr(mask,'.') && strlen(mask)>8)
972 fstrcpy(tmp,&mask[8]);
978 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
982 p = smb_buf(outbuf) + 3;
988 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
993 if((errno == ENOENT) && bad_path)
995 unix_ERR_class = ERRDOS;
996 unix_ERR_code = ERRbadpath;
998 return (UNIXERROR(ERRDOS,ERRnofids));
1000 return(ERROR(ERRDOS,ERRnofids));
1004 DEBUG(4,("dptr_num is %d\n",dptr_num));
1008 if ((dirtype&0x1F) == aVOLID)
1010 memcpy(p,status,21);
1011 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
1012 dptr_fill(p+12,dptr_num);
1013 if (dptr_zero(p+12) && (status_len==0))
1017 p += DIR_STRUCT_SIZE;
1021 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
1022 if (in_list(Connections[cnum].dirpath,
1023 lp_dontdescend(SNUM(cnum)),True))
1024 check_descend = True;
1026 for (i=numentries;(i<maxentries) && !finished;i++)
1029 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
1032 memcpy(p,status,21);
1033 make_dir_struct(p,mask,fname,size,mode,date);
1034 dptr_fill(p+12,dptr_num);
1037 p += DIR_STRUCT_SIZE;
1046 if (numentries == 0 || !ok)
1048 CVAL(outbuf,smb_rcls) = ERRDOS;
1049 SSVAL(outbuf,smb_err,ERRnofiles);
1052 /* If we were called as SMBffirst with smb_search_id == NULL
1053 and no entries were found then return error and close dirptr
1056 if(ok && expect_close && numentries == 0 && status_len == 0)
1058 CVAL(outbuf,smb_rcls) = ERRDOS;
1059 SSVAL(outbuf,smb_err,ERRnofiles);
1060 /* Also close the dptr - we know it's gone */
1061 dptr_close(dptr_num);
1064 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1065 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1066 dptr_close(dptr_num);
1068 SSVAL(outbuf,smb_vwv0,numentries);
1069 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1070 CVAL(smb_buf(outbuf),0) = 5;
1071 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1073 if (Protocol >= PROTOCOL_NT1) {
1074 uint16 flg2 = SVAL(outbuf,smb_flg2);
1075 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1078 outsize += DIR_STRUCT_SIZE*numentries;
1079 smb_setlen(outbuf,outsize - 4);
1081 if ((! *directory) && dptr_path(dptr_num))
1082 sprintf(directory,"(%s)",dptr_path(dptr_num));
1084 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1086 smb_fn_name(CVAL(inbuf,smb_com)),
1087 mask,directory,cnum,dirtype,numentries,maxentries));
1093 /****************************************************************************
1094 reply to a fclose (stop directory search)
1095 ****************************************************************************/
1096 int reply_fclose(char *inbuf,char *outbuf)
1105 cnum = SVAL(inbuf,smb_tid);
1107 outsize = set_message(outbuf,1,0,True);
1108 path = smb_buf(inbuf) + 1;
1109 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1112 if (status_len == 0)
1113 return(ERROR(ERRSRV,ERRsrverror));
1115 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1117 if(dptr_fetch(status+12,&dptr_num)) {
1118 /* Close the dptr - we know it's gone */
1119 dptr_close(dptr_num);
1122 SSVAL(outbuf,smb_vwv0,0);
1124 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1130 /****************************************************************************
1132 ****************************************************************************/
1133 int reply_open(char *inbuf,char *outbuf)
1146 BOOL bad_path = False;
1148 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1150 cnum = SVAL(inbuf,smb_tid);
1152 share_mode = SVAL(inbuf,smb_vwv0);
1154 pstrcpy(fname,smb_buf(inbuf)+1);
1155 unix_convert(fname,cnum,0,&bad_path);
1157 fnum = find_free_file();
1159 return(ERROR(ERRSRV,ERRnofids));
1161 if (!check_name(fname,cnum))
1163 if((errno == ENOENT) && bad_path)
1165 unix_ERR_class = ERRDOS;
1166 unix_ERR_code = ERRbadpath;
1168 return(UNIXERROR(ERRDOS,ERRnoaccess));
1171 unixmode = unix_mode(cnum,aARCH);
1173 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1174 oplock_request,&rmode,NULL);
1180 if((errno == ENOENT) && bad_path)
1182 unix_ERR_class = ERRDOS;
1183 unix_ERR_code = ERRbadpath;
1185 return(UNIXERROR(ERRDOS,ERRnoaccess));
1188 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1189 close_file(fnum,False);
1190 return(ERROR(ERRDOS,ERRnoaccess));
1193 size = sbuf.st_size;
1194 fmode = dos_mode(cnum,fname,&sbuf);
1195 mtime = sbuf.st_mtime;
1198 DEBUG(3,("attempt to open a directory %s\n",fname));
1199 close_file(fnum,False);
1200 return(ERROR(ERRDOS,ERRnoaccess));
1203 outsize = set_message(outbuf,7,0,True);
1204 SSVAL(outbuf,smb_vwv0,fnum);
1205 SSVAL(outbuf,smb_vwv1,fmode);
1206 put_dos_date3(outbuf,smb_vwv2,mtime);
1207 SIVAL(outbuf,smb_vwv4,size);
1208 SSVAL(outbuf,smb_vwv6,rmode);
1210 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1211 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1214 if(fsp->granted_oplock)
1215 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1220 /****************************************************************************
1221 reply to an open and X
1222 ****************************************************************************/
1223 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1226 int cnum = SVAL(inbuf,smb_tid);
1228 int smb_mode = SVAL(inbuf,smb_vwv3);
1229 int smb_attr = SVAL(inbuf,smb_vwv5);
1230 BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1232 int open_flags = SVAL(inbuf,smb_vwv2);
1233 int smb_sattr = SVAL(inbuf,smb_vwv4);
1234 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1236 int smb_ofun = SVAL(inbuf,smb_vwv8);
1238 int size=0,fmode=0,mtime=0,rmode=0;
1241 BOOL bad_path = False;
1244 /* If it's an IPC, pass off the pipe handler. */
1246 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1248 /* XXXX we need to handle passed times, sattr and flags */
1250 pstrcpy(fname,smb_buf(inbuf));
1251 unix_convert(fname,cnum,0,&bad_path);
1253 fnum = find_free_file();
1255 return(ERROR(ERRSRV,ERRnofids));
1257 if (!check_name(fname,cnum))
1259 if((errno == ENOENT) && bad_path)
1261 unix_ERR_class = ERRDOS;
1262 unix_ERR_code = ERRbadpath;
1264 return(UNIXERROR(ERRDOS,ERRnoaccess));
1267 unixmode = unix_mode(cnum,smb_attr | aARCH);
1269 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1270 oplock_request, &rmode,&smb_action);
1276 if((errno == ENOENT) && bad_path)
1278 unix_ERR_class = ERRDOS;
1279 unix_ERR_code = ERRbadpath;
1281 return(UNIXERROR(ERRDOS,ERRnoaccess));
1284 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1285 close_file(fnum,False);
1286 return(ERROR(ERRDOS,ERRnoaccess));
1289 size = sbuf.st_size;
1290 fmode = dos_mode(cnum,fname,&sbuf);
1291 mtime = sbuf.st_mtime;
1293 close_file(fnum,False);
1294 return(ERROR(ERRDOS,ERRnoaccess));
1297 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1298 smb_action |= EXTENDED_OPLOCK_GRANTED;
1299 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1302 if(fsp->granted_oplock) {
1303 smb_action |= EXTENDED_OPLOCK_GRANTED;
1304 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1307 set_message(outbuf,15,0,True);
1308 SSVAL(outbuf,smb_vwv2,fnum);
1309 SSVAL(outbuf,smb_vwv3,fmode);
1310 put_dos_date3(outbuf,smb_vwv4,mtime);
1311 SIVAL(outbuf,smb_vwv6,size);
1312 SSVAL(outbuf,smb_vwv8,rmode);
1313 SSVAL(outbuf,smb_vwv11,smb_action);
1317 return chain_reply(inbuf,outbuf,length,bufsize);
1321 /****************************************************************************
1322 reply to a SMBulogoffX
1323 ****************************************************************************/
1324 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1326 uint16 vuid = SVAL(inbuf,smb_uid);
1327 user_struct *vuser = get_valid_user_struct(vuid);
1330 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1333 /* in user level security we are supposed to close any files
1334 open by this user */
1335 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1337 for (i=0;i<MAX_OPEN_FILES;i++)
1338 if (Files[i].uid == vuser->uid && Files[i].open) {
1339 close_file(i,False);
1343 invalidate_vuid(vuid);
1345 set_message(outbuf,2,0,True);
1347 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1349 return chain_reply(inbuf,outbuf,length,bufsize);
1353 /****************************************************************************
1354 reply to a mknew or a create
1355 ****************************************************************************/
1356 int reply_mknew(char *inbuf,char *outbuf)
1365 BOOL bad_path = False;
1367 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1369 com = SVAL(inbuf,smb_com);
1370 cnum = SVAL(inbuf,smb_tid);
1372 createmode = SVAL(inbuf,smb_vwv0);
1373 pstrcpy(fname,smb_buf(inbuf)+1);
1374 unix_convert(fname,cnum,0,&bad_path);
1376 if (createmode & aVOLID)
1378 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1381 unixmode = unix_mode(cnum,createmode);
1383 fnum = find_free_file();
1385 return(ERROR(ERRSRV,ERRnofids));
1387 if (!check_name(fname,cnum))
1389 if((errno == ENOENT) && bad_path)
1391 unix_ERR_class = ERRDOS;
1392 unix_ERR_code = ERRbadpath;
1394 return(UNIXERROR(ERRDOS,ERRnoaccess));
1399 /* We should fail if file exists. */
1404 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1408 /* Open file in dos compatibility share mode. */
1409 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1410 oplock_request, NULL, NULL);
1416 if((errno == ENOENT) && bad_path)
1418 unix_ERR_class = ERRDOS;
1419 unix_ERR_code = ERRbadpath;
1421 return(UNIXERROR(ERRDOS,ERRnoaccess));
1424 outsize = set_message(outbuf,1,0,True);
1425 SSVAL(outbuf,smb_vwv0,fnum);
1427 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1428 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1431 if(fsp->granted_oplock)
1432 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1434 DEBUG(2,("new file %s\n",fname));
1435 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));
1441 /****************************************************************************
1442 reply to a create temporary file
1443 ****************************************************************************/
1444 int reply_ctemp(char *inbuf,char *outbuf)
1453 BOOL bad_path = False;
1455 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1457 cnum = SVAL(inbuf,smb_tid);
1458 createmode = SVAL(inbuf,smb_vwv0);
1459 pstrcpy(fname,smb_buf(inbuf)+1);
1460 strcat(fname,"/TMXXXXXX");
1461 unix_convert(fname,cnum,0,&bad_path);
1463 unixmode = unix_mode(cnum,createmode);
1465 fnum = find_free_file();
1467 return(ERROR(ERRSRV,ERRnofids));
1469 if (!check_name(fname,cnum))
1471 if((errno == ENOENT) && bad_path)
1473 unix_ERR_class = ERRDOS;
1474 unix_ERR_code = ERRbadpath;
1476 return(UNIXERROR(ERRDOS,ERRnoaccess));
1479 strcpy(fname2,(char *)mktemp(fname));
1481 /* Open file in dos compatibility share mode. */
1482 /* We should fail if file exists. */
1483 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1484 oplock_request, NULL, NULL);
1490 if((errno == ENOENT) && bad_path)
1492 unix_ERR_class = ERRDOS;
1493 unix_ERR_code = ERRbadpath;
1495 return(UNIXERROR(ERRDOS,ERRnoaccess));
1498 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1499 SSVAL(outbuf,smb_vwv0,fnum);
1500 CVAL(smb_buf(outbuf),0) = 4;
1501 strcpy(smb_buf(outbuf) + 1,fname2);
1503 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1504 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1507 if(fsp->granted_oplock)
1508 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1510 DEBUG(2,("created temp file %s\n",fname2));
1511 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));
1517 /*******************************************************************
1518 check if a user is allowed to delete a file
1519 ********************************************************************/
1520 static BOOL can_delete(char *fname,int cnum,int dirtype)
1525 if (!CAN_WRITE(cnum)) return(False);
1527 if (sys_lstat(fname,&sbuf) != 0) return(False);
1528 fmode = dos_mode(cnum,fname,&sbuf);
1529 if (fmode & aDIR) return(False);
1530 if (!lp_delete_readonly(SNUM(cnum))) {
1531 if (fmode & aRONLY) return(False);
1533 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1535 if (!check_file_sharing(cnum,fname)) return(False);
1539 /****************************************************************************
1541 ****************************************************************************/
1542 int reply_unlink(char *inbuf,char *outbuf)
1552 int error = ERRnoaccess;
1555 BOOL bad_path = False;
1557 *directory = *mask = 0;
1559 cnum = SVAL(inbuf,smb_tid);
1560 dirtype = SVAL(inbuf,smb_vwv0);
1562 pstrcpy(name,smb_buf(inbuf) + 1);
1564 DEBUG(3,("reply_unlink : %s\n",name));
1566 unix_convert(name,cnum,0,&bad_path);
1568 p = strrchr(name,'/');
1570 strcpy(directory,"./");
1574 strcpy(directory,name);
1578 if (is_mangled(mask))
1579 check_mangled_stack(mask);
1581 has_wild = strchr(mask,'*') || strchr(mask,'?');
1584 strcat(directory,"/");
1585 strcat(directory,mask);
1586 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1587 if (!count) exists = file_exist(directory,NULL);
1589 void *dirptr = NULL;
1592 if (check_name(directory,cnum))
1593 dirptr = OpenDir(cnum, directory, True);
1595 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1596 the pattern matches against the long name, otherwise the short name
1597 We don't implement this yet XXXX
1604 if (strequal(mask,"????????.???"))
1607 while ((dname = ReadDirName(dirptr)))
1610 pstrcpy(fname,dname);
1612 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1614 error = ERRnoaccess;
1615 sprintf(fname,"%s/%s",directory,dname);
1616 if (!can_delete(fname,cnum,dirtype)) continue;
1617 if (!sys_unlink(fname)) count++;
1618 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1626 return(ERROR(ERRDOS,error));
1629 if((errno == ENOENT) && bad_path)
1631 unix_ERR_class = ERRDOS;
1632 unix_ERR_code = ERRbadpath;
1634 return(UNIXERROR(ERRDOS,error));
1638 outsize = set_message(outbuf,0,0,True);
1644 /****************************************************************************
1645 reply to a readbraw (core+ protocol)
1646 ****************************************************************************/
1647 int reply_readbraw(char *inbuf, char *outbuf)
1649 int cnum,maxcount,mincount,fnum;
1652 char *header = outbuf;
1658 * Special check if an oplock break has been issued
1659 * and the readraw request croses on the wire, we must
1660 * return a zero length response here.
1663 if(global_oplock_break)
1665 _smb_setlen(header,0);
1666 transfer_file(0,Client,0,header,4,0);
1667 DEBUG(5,("readbraw - oplock break finished\n"));
1671 cnum = SVAL(inbuf,smb_tid);
1672 fnum = GETFNUM(inbuf,smb_vwv0);
1674 startpos = IVAL(inbuf,smb_vwv1);
1675 maxcount = SVAL(inbuf,smb_vwv3);
1676 mincount = SVAL(inbuf,smb_vwv4);
1678 /* ensure we don't overrun the packet size */
1679 maxcount = MIN(65535,maxcount);
1680 maxcount = MAX(mincount,maxcount);
1682 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1684 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1685 _smb_setlen(header,0);
1686 transfer_file(0,Client,0,header,4,0);
1691 fd = Files[fnum].fd_ptr->fd;
1692 fname = Files[fnum].name;
1696 if (!is_locked(fnum,cnum,maxcount,startpos))
1698 int size = Files[fnum].size;
1699 int sizeneeded = startpos + maxcount;
1701 if (size < sizeneeded) {
1703 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1705 if (!Files[fnum].can_write)
1706 Files[fnum].size = size;
1709 nread = MIN(maxcount,(int)(size - startpos));
1712 if (nread < mincount)
1715 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1718 maxcount,mincount,nread));
1723 _smb_setlen(header,nread);
1725 if (!Files[fnum].can_write)
1726 predict = read_predict(fd,startpos,header+4,NULL,nread);
1728 if ((nread-predict) > 0)
1729 seek_file(fnum,startpos + predict);
1731 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1736 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1737 fname,startpos,nread,ret));
1740 ret = read_file(fnum,header+4,startpos,nread);
1741 if (ret < mincount) ret = 0;
1743 _smb_setlen(header,ret);
1744 transfer_file(0,Client,0,header,4+ret,0);
1747 DEBUG(5,("readbraw finished\n"));
1752 /****************************************************************************
1753 reply to a lockread (core+ protocol)
1754 ****************************************************************************/
1755 int reply_lockread(char *inbuf,char *outbuf)
1761 uint32 startpos, numtoread;
1765 cnum = SVAL(inbuf,smb_tid);
1766 fnum = GETFNUM(inbuf,smb_vwv0);
1768 CHECK_FNUM(fnum,cnum);
1772 numtoread = SVAL(inbuf,smb_vwv1);
1773 startpos = IVAL(inbuf,smb_vwv2);
1775 outsize = set_message(outbuf,5,3,True);
1776 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1777 data = smb_buf(outbuf) + 3;
1779 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1780 return (ERROR(eclass,ecode));
1782 nread = read_file(fnum,data,startpos,numtoread);
1785 return(UNIXERROR(ERRDOS,ERRnoaccess));
1788 SSVAL(outbuf,smb_vwv0,nread);
1789 SSVAL(outbuf,smb_vwv5,nread+3);
1790 SSVAL(smb_buf(outbuf),1,nread);
1792 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1798 /****************************************************************************
1800 ****************************************************************************/
1801 int reply_read(char *inbuf,char *outbuf)
1803 int cnum,numtoread,fnum;
1809 cnum = SVAL(inbuf,smb_tid);
1810 fnum = GETFNUM(inbuf,smb_vwv0);
1812 CHECK_FNUM(fnum,cnum);
1816 numtoread = SVAL(inbuf,smb_vwv1);
1817 startpos = IVAL(inbuf,smb_vwv2);
1819 outsize = set_message(outbuf,5,3,True);
1820 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1821 data = smb_buf(outbuf) + 3;
1823 if (is_locked(fnum,cnum,numtoread,startpos))
1824 return(ERROR(ERRDOS,ERRlock));
1827 nread = read_file(fnum,data,startpos,numtoread);
1830 return(UNIXERROR(ERRDOS,ERRnoaccess));
1833 SSVAL(outbuf,smb_vwv0,nread);
1834 SSVAL(outbuf,smb_vwv5,nread+3);
1835 CVAL(smb_buf(outbuf),0) = 1;
1836 SSVAL(smb_buf(outbuf),1,nread);
1838 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1844 /****************************************************************************
1845 reply to a read and X
1846 ****************************************************************************/
1847 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1849 int fnum = GETFNUM(inbuf,smb_vwv2);
1850 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1851 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1852 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1858 cnum = SVAL(inbuf,smb_tid);
1860 CHECK_FNUM(fnum,cnum);
1864 set_message(outbuf,12,0,True);
1865 data = smb_buf(outbuf);
1867 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1868 return(ERROR(ERRDOS,ERRlock));
1869 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1873 return(UNIXERROR(ERRDOS,ERRnoaccess));
1875 SSVAL(outbuf,smb_vwv5,nread);
1876 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1877 SSVAL(smb_buf(outbuf),-2,nread);
1879 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1880 timestring(),fnum,cnum,
1881 smb_mincnt,smb_maxcnt,nread));
1885 return chain_reply(inbuf,outbuf,length,bufsize);
1889 /****************************************************************************
1890 reply to a writebraw (core+ or LANMAN1.0 protocol)
1891 ****************************************************************************/
1892 int reply_writebraw(char *inbuf,char *outbuf)
1895 int total_written=0;
1904 cnum = SVAL(inbuf,smb_tid);
1905 fnum = GETFNUM(inbuf,smb_vwv0);
1907 CHECK_FNUM(fnum,cnum);
1911 tcount = IVAL(inbuf,smb_vwv1);
1912 startpos = IVAL(inbuf,smb_vwv3);
1913 write_through = BITSETW(inbuf+smb_vwv7,0);
1915 /* We have to deal with slightly different formats depending
1916 on whether we are using the core+ or lanman1.0 protocol */
1917 if(Protocol <= PROTOCOL_COREPLUS) {
1918 numtowrite = SVAL(smb_buf(inbuf),-2);
1919 data = smb_buf(inbuf);
1921 numtowrite = SVAL(inbuf,smb_vwv10);
1922 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1925 /* force the error type */
1926 CVAL(inbuf,smb_com) = SMBwritec;
1927 CVAL(outbuf,smb_com) = SMBwritec;
1929 if (is_locked(fnum,cnum,tcount,startpos))
1930 return(ERROR(ERRDOS,ERRlock));
1932 if (seek_file(fnum,startpos) != startpos)
1933 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1936 nwritten = write_file(fnum,data,numtowrite);
1938 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1939 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1941 if (nwritten < numtowrite)
1942 return(UNIXERROR(ERRHRD,ERRdiskfull));
1944 total_written = nwritten;
1946 /* Return a message to the redirector to tell it
1947 to send more bytes */
1948 CVAL(outbuf,smb_com) = SMBwritebraw;
1949 SSVALS(outbuf,smb_vwv0,-1);
1950 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1951 send_smb(Client,outbuf);
1953 /* Now read the raw data into the buffer and write it */
1954 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1955 exit_server("secondary writebraw failed");
1958 /* Even though this is not an smb message, smb_len
1959 returns the generic length of an smb message */
1960 numtowrite = smb_len(inbuf);
1962 if (tcount > nwritten+numtowrite) {
1963 DEBUG(3,("Client overestimated the write %d %d %d\n",
1964 tcount,nwritten,numtowrite));
1967 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1969 total_written += nwritten;
1971 /* Set up outbuf to return the correct return */
1972 outsize = set_message(outbuf,1,0,True);
1973 CVAL(outbuf,smb_com) = SMBwritec;
1974 SSVAL(outbuf,smb_vwv0,total_written);
1976 if (nwritten < numtowrite) {
1977 CVAL(outbuf,smb_rcls) = ERRHRD;
1978 SSVAL(outbuf,smb_err,ERRdiskfull);
1981 if (lp_syncalways(SNUM(cnum)) || write_through)
1984 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1985 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1987 /* we won't return a status if write through is not selected - this
1988 follows what WfWg does */
1989 if (!write_through && total_written==tcount)
1996 /****************************************************************************
1997 reply to a writeunlock (core+)
1998 ****************************************************************************/
1999 int reply_writeunlock(char *inbuf,char *outbuf)
2005 uint32 numtowrite,startpos;
2009 cnum = SVAL(inbuf,smb_tid);
2010 fnum = GETFNUM(inbuf,smb_vwv0);
2012 CHECK_FNUM(fnum,cnum);
2016 numtowrite = SVAL(inbuf,smb_vwv1);
2017 startpos = IVAL(inbuf,smb_vwv2);
2018 data = smb_buf(inbuf) + 3;
2020 if (is_locked(fnum,cnum,numtowrite,startpos))
2021 return(ERROR(ERRDOS,ERRlock));
2023 seek_file(fnum,startpos);
2025 /* The special X/Open SMB protocol handling of
2026 zero length writes is *NOT* done for
2031 nwritten = write_file(fnum,data,numtowrite);
2033 if (lp_syncalways(SNUM(cnum)))
2036 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2037 return(UNIXERROR(ERRDOS,ERRnoaccess));
2039 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2040 return(ERROR(eclass,ecode));
2042 outsize = set_message(outbuf,1,0,True);
2044 SSVAL(outbuf,smb_vwv0,nwritten);
2046 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2047 timestring(),fnum,cnum,numtowrite,nwritten));
2053 /****************************************************************************
2055 ****************************************************************************/
2056 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
2058 int cnum,numtowrite,fnum;
2067 cnum = SVAL(inbuf,smb_tid);
2068 fnum = GETFNUM(inbuf,smb_vwv0);
2070 CHECK_FNUM(fnum,cnum);
2074 numtowrite = SVAL(inbuf,smb_vwv1);
2075 startpos = IVAL(inbuf,smb_vwv2);
2076 data = smb_buf(inbuf) + 3;
2078 if (is_locked(fnum,cnum,numtowrite,startpos))
2079 return(ERROR(ERRDOS,ERRlock));
2081 seek_file(fnum,startpos);
2083 /* X/Open SMB protocol says that if smb_vwv1 is
2084 zero then the file size should be extended or
2085 truncated to the size given in smb_vwv[2-3] */
2087 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2089 nwritten = write_file(fnum,data,numtowrite);
2091 if (lp_syncalways(SNUM(cnum)))
2094 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2095 return(UNIXERROR(ERRDOS,ERRnoaccess));
2097 outsize = set_message(outbuf,1,0,True);
2099 SSVAL(outbuf,smb_vwv0,nwritten);
2101 if (nwritten < numtowrite) {
2102 CVAL(outbuf,smb_rcls) = ERRHRD;
2103 SSVAL(outbuf,smb_err,ERRdiskfull);
2106 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2112 /****************************************************************************
2113 reply to a write and X
2114 ****************************************************************************/
2115 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2117 int fnum = GETFNUM(inbuf,smb_vwv2);
2118 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2119 int smb_dsize = SVAL(inbuf,smb_vwv10);
2120 int smb_doff = SVAL(inbuf,smb_vwv11);
2121 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2126 cnum = SVAL(inbuf,smb_tid);
2128 CHECK_FNUM(fnum,cnum);
2132 data = smb_base(inbuf) + smb_doff;
2134 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2135 return(ERROR(ERRDOS,ERRlock));
2137 seek_file(fnum,smb_offs);
2139 /* X/Open SMB protocol says that, unlike SMBwrite
2140 if the length is zero then NO truncation is
2141 done, just a write of zero. To truncate a file,
2146 nwritten = write_file(fnum,data,smb_dsize);
2148 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2149 return(UNIXERROR(ERRDOS,ERRnoaccess));
2151 set_message(outbuf,6,0,True);
2153 SSVAL(outbuf,smb_vwv2,nwritten);
2155 if (nwritten < smb_dsize) {
2156 CVAL(outbuf,smb_rcls) = ERRHRD;
2157 SSVAL(outbuf,smb_err,ERRdiskfull);
2160 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2164 if (lp_syncalways(SNUM(cnum)) || write_through)
2167 return chain_reply(inbuf,outbuf,length,bufsize);
2171 /****************************************************************************
2173 ****************************************************************************/
2174 int reply_lseek(char *inbuf,char *outbuf)
2182 cnum = SVAL(inbuf,smb_tid);
2183 fnum = GETFNUM(inbuf,smb_vwv0);
2185 CHECK_FNUM(fnum,cnum);
2188 mode = SVAL(inbuf,smb_vwv1) & 3;
2189 startpos = IVAL(inbuf,smb_vwv2);
2193 case 0: umode = SEEK_SET; break;
2194 case 1: umode = SEEK_CUR; break;
2195 case 2: umode = SEEK_END; break;
2197 umode = SEEK_SET; break;
2200 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2201 Files[fnum].pos = res;
2203 outsize = set_message(outbuf,2,0,True);
2204 SIVALS(outbuf,smb_vwv0,res);
2206 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2212 /****************************************************************************
2214 ****************************************************************************/
2215 int reply_flush(char *inbuf,char *outbuf)
2218 int outsize = set_message(outbuf,0,0,True);
2220 cnum = SVAL(inbuf,smb_tid);
2221 fnum = GETFNUM(inbuf,smb_vwv0);
2223 if (fnum != 0xFFFF) {
2224 CHECK_FNUM(fnum,cnum);
2231 for (i=0;i<MAX_OPEN_FILES;i++)
2238 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2243 /****************************************************************************
2245 ****************************************************************************/
2246 int reply_exit(char *inbuf,char *outbuf)
2248 int outsize = set_message(outbuf,0,0,True);
2249 DEBUG(3,("%s exit\n",timestring()));
2255 /****************************************************************************
2257 ****************************************************************************/
2258 int reply_close(char *inbuf,char *outbuf)
2263 int32 eclass = 0, err = 0;
2265 outsize = set_message(outbuf,0,0,True);
2267 cnum = SVAL(inbuf,smb_tid);
2269 fnum = GETFNUM(inbuf,smb_vwv0);
2270 CHECK_FNUM(fnum,cnum);
2272 if(HAS_CACHED_ERROR(fnum)) {
2273 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2274 err = Files[fnum].wbmpx_ptr->wr_error;
2277 mtime = make_unix_date3(inbuf+smb_vwv1);
2279 /* try and set the date */
2280 set_filetime(cnum, Files[fnum].name,mtime);
2282 close_file(fnum,True);
2284 /* We have a cached error */
2286 return(ERROR(eclass,err));
2288 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2289 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2290 Connections[cnum].num_files_open));
2296 /****************************************************************************
2297 reply to a writeclose (Core+ protocol)
2298 ****************************************************************************/
2299 int reply_writeclose(char *inbuf,char *outbuf)
2301 int cnum,numtowrite,fnum;
2308 cnum = SVAL(inbuf,smb_tid);
2309 fnum = GETFNUM(inbuf,smb_vwv0);
2311 CHECK_FNUM(fnum,cnum);
2315 numtowrite = SVAL(inbuf,smb_vwv1);
2316 startpos = IVAL(inbuf,smb_vwv2);
2317 mtime = make_unix_date3(inbuf+smb_vwv4);
2318 data = smb_buf(inbuf) + 1;
2320 if (is_locked(fnum,cnum,numtowrite,startpos))
2321 return(ERROR(ERRDOS,ERRlock));
2323 seek_file(fnum,startpos);
2325 nwritten = write_file(fnum,data,numtowrite);
2327 set_filetime(cnum, Files[fnum].name,mtime);
2329 close_file(fnum,True);
2331 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2332 timestring(),fnum,cnum,numtowrite,nwritten,
2333 Connections[cnum].num_files_open));
2336 return(UNIXERROR(ERRDOS,ERRnoaccess));
2338 outsize = set_message(outbuf,1,0,True);
2340 SSVAL(outbuf,smb_vwv0,nwritten);
2345 /****************************************************************************
2347 ****************************************************************************/
2348 int reply_lock(char *inbuf,char *outbuf)
2351 int outsize = set_message(outbuf,0,0,True);
2352 uint32 count,offset;
2356 cnum = SVAL(inbuf,smb_tid);
2357 fnum = GETFNUM(inbuf,smb_vwv0);
2359 CHECK_FNUM(fnum,cnum);
2362 count = IVAL(inbuf,smb_vwv1);
2363 offset = IVAL(inbuf,smb_vwv3);
2365 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));
2367 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2368 return (ERROR(eclass,ecode));
2374 /****************************************************************************
2376 ****************************************************************************/
2377 int reply_unlock(char *inbuf,char *outbuf)
2380 int outsize = set_message(outbuf,0,0,True);
2381 uint32 count,offset;
2385 cnum = SVAL(inbuf,smb_tid);
2386 fnum = GETFNUM(inbuf,smb_vwv0);
2388 CHECK_FNUM(fnum,cnum);
2391 count = IVAL(inbuf,smb_vwv1);
2392 offset = IVAL(inbuf,smb_vwv3);
2394 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2395 return (ERROR(eclass,ecode));
2397 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));
2403 /****************************************************************************
2405 ****************************************************************************/
2406 int reply_tdis(char *inbuf,char *outbuf)
2409 int outsize = set_message(outbuf,0,0,True);
2412 cnum = SVAL(inbuf,smb_tid);
2413 vuid = SVAL(inbuf,smb_uid);
2415 if (!OPEN_CNUM(cnum)) {
2416 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2417 return(ERROR(ERRSRV,ERRinvnid));
2420 Connections[cnum].used = False;
2422 close_cnum(cnum,vuid);
2424 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2431 /****************************************************************************
2433 ****************************************************************************/
2434 int reply_echo(char *inbuf,char *outbuf)
2437 int smb_reverb = SVAL(inbuf,smb_vwv0);
2439 int data_len = smb_buflen(inbuf);
2440 int outsize = set_message(outbuf,1,data_len,True);
2442 cnum = SVAL(inbuf,smb_tid);
2444 /* According to the latest CIFS spec we shouldn't
2445 care what the TID is.
2449 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2451 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2452 return(ERROR(ERRSRV,ERRinvnid));
2456 /* copy any incoming data back out */
2458 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2460 if (smb_reverb > 100)
2462 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2466 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2468 SSVAL(outbuf,smb_vwv0,seq_num);
2470 smb_setlen(outbuf,outsize - 4);
2472 send_smb(Client,outbuf);
2475 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2481 /****************************************************************************
2482 reply to a printopen
2483 ****************************************************************************/
2484 int reply_printopen(char *inbuf,char *outbuf)
2492 *fname = *fname2 = 0;
2494 cnum = SVAL(inbuf,smb_tid);
2496 if (!CAN_PRINT(cnum))
2497 return(ERROR(ERRDOS,ERRnoaccess));
2502 pstrcpy(s,smb_buf(inbuf)+1);
2506 if (!(isalnum(*p) || strchr("._-",*p)))
2511 if (strlen(s) > 10) s[10] = 0;
2513 sprintf(fname,"%s.XXXXXX",s);
2516 fnum = find_free_file();
2518 return(ERROR(ERRSRV,ERRnofids));
2520 strcpy(fname2,(char *)mktemp(fname));
2522 if (!check_name(fname2,cnum))
2523 return(ERROR(ERRDOS,ERRnoaccess));
2525 /* Open for exclusive use, write only. */
2526 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2529 if (!Files[fnum].open)
2530 return(UNIXERROR(ERRDOS,ERRnoaccess));
2532 /* force it to be a print file */
2533 Files[fnum].print_file = True;
2535 outsize = set_message(outbuf,1,0,True);
2536 SSVAL(outbuf,smb_vwv0,fnum);
2538 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2544 /****************************************************************************
2545 reply to a printclose
2546 ****************************************************************************/
2547 int reply_printclose(char *inbuf,char *outbuf)
2550 int outsize = set_message(outbuf,0,0,True);
2552 cnum = SVAL(inbuf,smb_tid);
2553 fnum = GETFNUM(inbuf,smb_vwv0);
2555 CHECK_FNUM(fnum,cnum);
2558 if (!CAN_PRINT(cnum))
2559 return(ERROR(ERRDOS,ERRnoaccess));
2561 close_file(fnum,True);
2563 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2569 /****************************************************************************
2570 reply to a printqueue
2571 ****************************************************************************/
2572 int reply_printqueue(char *inbuf,char *outbuf)
2575 int outsize = set_message(outbuf,2,3,True);
2576 int max_count = SVAL(inbuf,smb_vwv0);
2577 int start_index = SVAL(inbuf,smb_vwv1);
2580 cnum = SVAL(inbuf,smb_tid);
2581 vuid = SVAL(inbuf,smb_uid);
2583 /* allow checking the queue for anyone */
2585 if (!CAN_PRINT(cnum))
2586 return(ERROR(ERRDOS,ERRnoaccess));
2589 SSVAL(outbuf,smb_vwv0,0);
2590 SSVAL(outbuf,smb_vwv1,0);
2591 CVAL(smb_buf(outbuf),0) = 1;
2592 SSVAL(smb_buf(outbuf),1,0);
2594 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2595 timestring(),cnum,start_index,max_count));
2597 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2602 for (i=0;i<MAX_CONNECTIONS;i++)
2603 if (CAN_PRINT(i) && Connections[i].printer)
2607 for (i=0;i<MAX_CONNECTIONS;i++)
2611 if (!OPEN_CNUM(cnum))
2612 return(ERROR(ERRSRV,ERRinvnid));
2614 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2617 if (!become_user(cnum,vuid))
2618 return(ERROR(ERRSRV,ERRinvnid));
2621 print_queue_struct *queue = NULL;
2622 char *p = smb_buf(outbuf) + 3;
2623 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2624 int num_to_get = ABS(max_count);
2625 int first = (max_count>0?start_index:start_index+max_count+1);
2631 num_to_get = MIN(num_to_get,count-first);
2634 for (i=first;i<first+num_to_get;i++)
2636 put_dos_date2(p,0,queue[i].time);
2637 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2638 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2639 SIVAL(p,7,queue[i].size);
2641 StrnCpy(p+12,queue[i].user,16);
2647 outsize = set_message(outbuf,2,28*count+3,False);
2648 SSVAL(outbuf,smb_vwv0,count);
2649 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2650 CVAL(smb_buf(outbuf),0) = 1;
2651 SSVAL(smb_buf(outbuf),1,28*count);
2654 if (queue) free(queue);
2656 DEBUG(3,("%d entries returned in queue\n",count));
2663 /****************************************************************************
2664 reply to a printwrite
2665 ****************************************************************************/
2666 int reply_printwrite(char *inbuf,char *outbuf)
2668 int cnum,numtowrite,fnum;
2669 int outsize = set_message(outbuf,0,0,True);
2672 cnum = SVAL(inbuf,smb_tid);
2674 if (!CAN_PRINT(cnum))
2675 return(ERROR(ERRDOS,ERRnoaccess));
2677 fnum = GETFNUM(inbuf,smb_vwv0);
2679 CHECK_FNUM(fnum,cnum);
2683 numtowrite = SVAL(smb_buf(inbuf),1);
2684 data = smb_buf(inbuf) + 3;
2686 if (write_file(fnum,data,numtowrite) != numtowrite)
2687 return(UNIXERROR(ERRDOS,ERRnoaccess));
2689 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2695 /****************************************************************************
2697 ****************************************************************************/
2698 int reply_mkdir(char *inbuf,char *outbuf)
2702 int outsize,ret= -1;
2703 BOOL bad_path = False;
2705 pstrcpy(directory,smb_buf(inbuf) + 1);
2706 cnum = SVAL(inbuf,smb_tid);
2707 unix_convert(directory,cnum,0,&bad_path);
2709 if (check_name(directory,cnum))
2710 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2714 if((errno == ENOENT) && bad_path)
2716 unix_ERR_class = ERRDOS;
2717 unix_ERR_code = ERRbadpath;
2719 return(UNIXERROR(ERRDOS,ERRnoaccess));
2722 outsize = set_message(outbuf,0,0,True);
2724 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2729 /****************************************************************************
2730 Static function used by reply_rmdir to delete an entire directory
2732 ****************************************************************************/
2733 static BOOL recursive_rmdir(char *directory)
2737 void *dirptr = OpenDir(-1, directory, False);
2742 while((dname = ReadDirName(dirptr)))
2747 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2750 /* Construct the full name. */
2751 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2757 strcpy(fullname, directory);
2758 strcat(fullname, "/");
2759 strcat(fullname, dname);
2761 if(sys_lstat(fullname, &st) != 0)
2767 if(st.st_mode & S_IFDIR)
2769 if(recursive_rmdir(fullname)!=0)
2774 if(sys_rmdir(fullname) != 0)
2780 else if(sys_unlink(fullname) != 0)
2790 /****************************************************************************
2792 ****************************************************************************/
2793 int reply_rmdir(char *inbuf,char *outbuf)
2799 BOOL bad_path = False;
2801 cnum = SVAL(inbuf,smb_tid);
2802 pstrcpy(directory,smb_buf(inbuf) + 1);
2803 unix_convert(directory,cnum,0,&bad_path);
2805 if (check_name(directory,cnum))
2808 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2809 ok = (sys_rmdir(directory) == 0);
2810 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2812 /* Check to see if the only thing in this directory are
2813 vetoed files/directories. If so then delete them and
2814 retry. If we fail to delete any of them (and we *don't*
2815 do a recursive delete) then fail the rmdir. */
2816 BOOL all_veto_files = True;
2818 void *dirptr = OpenDir(cnum, directory, False);
2822 int dirpos = TellDir(dirptr);
2823 while ((dname = ReadDirName(dirptr)))
2825 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2827 if(!IS_VETO_PATH(cnum, dname))
2829 all_veto_files = False;
2835 SeekDir(dirptr,dirpos);
2836 while ((dname = ReadDirName(dirptr)))
2841 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2844 /* Construct the full name. */
2845 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2850 pstrcpy(fullname, directory);
2851 strcat(fullname, "/");
2852 strcat(fullname, dname);
2854 if(sys_lstat(fullname, &st) != 0)
2856 if(st.st_mode & S_IFDIR)
2858 if(lp_recursive_veto_delete(SNUM(cnum)))
2860 if(recursive_rmdir(fullname) != 0)
2863 if(sys_rmdir(fullname) != 0)
2866 else if(sys_unlink(fullname) != 0)
2870 /* Retry the rmdir */
2871 ok = (sys_rmdir(directory) == 0);
2881 DEBUG(3,("couldn't remove directory %s : %s\n",
2882 directory,strerror(errno)));
2887 if((errno == ENOENT) && bad_path)
2889 unix_ERR_class = ERRDOS;
2890 unix_ERR_code = ERRbadpath;
2892 return(UNIXERROR(ERRDOS,ERRbadpath));
2895 outsize = set_message(outbuf,0,0,True);
2897 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2903 /*******************************************************************
2904 resolve wildcards in a filename rename
2905 ********************************************************************/
2906 static BOOL resolve_wildcards(char *name1,char *name2)
2908 fstring root1,root2;
2912 name1 = strrchr(name1,'/');
2913 name2 = strrchr(name2,'/');
2915 if (!name1 || !name2) return(False);
2917 fstrcpy(root1,name1);
2918 fstrcpy(root2,name2);
2919 p = strrchr(root1,'.');
2926 p = strrchr(root2,'.');
2958 strcpy(name2,root2);
2967 /*******************************************************************
2968 check if a user is allowed to rename a file
2969 ********************************************************************/
2970 static BOOL can_rename(char *fname,int cnum)
2974 if (!CAN_WRITE(cnum)) return(False);
2976 if (sys_lstat(fname,&sbuf) != 0) return(False);
2977 if (!check_file_sharing(cnum,fname)) return(False);
2982 /****************************************************************************
2984 ****************************************************************************/
2985 int reply_mv(char *inbuf,char *outbuf)
2991 pstring mask,newname;
2992 pstring newname_last_component;
2995 int error = ERRnoaccess;
2998 BOOL bad_path1 = False;
2999 BOOL bad_path2 = False;
3001 *directory = *mask = 0;
3003 cnum = SVAL(inbuf,smb_tid);
3005 pstrcpy(name,smb_buf(inbuf) + 1);
3006 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3008 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3010 unix_convert(name,cnum,0,&bad_path1);
3011 unix_convert(newname,cnum,newname_last_component,&bad_path2);
3014 * Split the old name into directory and last component
3015 * strings. Note that unix_convert may have stripped off a
3016 * leading ./ from both name and newname if the rename is
3017 * at the root of the share. We need to make sure either both
3018 * name and newname contain a / character or neither of them do
3019 * as this is checked in resolve_wildcards().
3022 p = strrchr(name,'/');
3024 strcpy(directory,".");
3028 strcpy(directory,name);
3030 *p = '/'; /* Replace needed for exceptional test below. */
3033 if (is_mangled(mask))
3034 check_mangled_stack(mask);
3036 has_wild = strchr(mask,'*') || strchr(mask,'?');
3039 BOOL is_short_name = is_8_3(name, True);
3041 /* Add a terminating '/' to the directory name. */
3042 strcat(directory,"/");
3043 strcat(directory,mask);
3045 /* Ensure newname contains a '/' also */
3046 if(strrchr(newname,'/') == 0) {
3049 strcpy(tmpstr, "./");
3050 strcat(tmpstr, newname);
3051 strcpy(newname, tmpstr);
3054 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",
3055 case_sensitive, case_preserve, short_case_preserve, directory,
3056 newname, newname_last_component, is_short_name));
3059 * Check for special case with case preserving and not
3060 * case sensitive, if directory and newname are identical,
3061 * and the old last component differs from the original
3062 * last component only by case, then we should allow
3063 * the rename (user is trying to change the case of the
3066 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3067 ((short_case_preserve == True) && (is_short_name == True))) &&
3068 strcsequal(directory, newname)) {
3069 pstring newname_modified_last_component;
3072 * Get the last component of the modified name.
3073 * Note that we guarantee that newname contains a '/'
3076 p = strrchr(newname,'/');
3077 strcpy(newname_modified_last_component,p+1);
3079 if(strcsequal(newname_modified_last_component,
3080 newname_last_component) == False) {
3082 * Replace the modified last component with
3085 strcpy(p+1, newname_last_component);
3089 if (resolve_wildcards(directory,newname) &&
3090 can_rename(directory,cnum) &&
3091 !file_exist(newname,NULL) &&
3092 !sys_rename(directory,newname)) count++;
3094 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3095 directory,newname));
3097 if (!count) exists = file_exist(directory,NULL);
3098 if (!count && exists && file_exist(newname,NULL)) {
3103 void *dirptr = NULL;
3107 if (check_name(directory,cnum))
3108 dirptr = OpenDir(cnum, directory, True);
3114 if (strequal(mask,"????????.???"))
3117 while ((dname = ReadDirName(dirptr)))
3120 pstrcpy(fname,dname);
3122 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3124 error = ERRnoaccess;
3125 sprintf(fname,"%s/%s",directory,dname);
3126 if (!can_rename(fname,cnum)) continue;
3127 pstrcpy(destname,newname);
3129 if (!resolve_wildcards(fname,destname)) continue;
3131 if (file_exist(destname,NULL)) {
3135 if (!sys_rename(fname,destname)) count++;
3136 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3144 return(ERROR(ERRDOS,error));
3147 if((errno == ENOENT) && (bad_path1 || bad_path2))
3149 unix_ERR_class = ERRDOS;
3150 unix_ERR_code = ERRbadpath;
3152 return(UNIXERROR(ERRDOS,error));
3156 outsize = set_message(outbuf,0,0,True);
3161 /*******************************************************************
3162 copy a file as part of a reply_copy
3163 ******************************************************************/
3164 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3165 int count,BOOL target_is_directory)
3173 pstrcpy(dest,dest1);
3174 if (target_is_directory) {
3175 char *p = strrchr(src,'/');
3184 if (!file_exist(src,&st)) return(False);
3186 fnum1 = find_free_file();
3187 if (fnum1<0) return(False);
3188 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3189 1,0,0,&Access,&action);
3191 if (!Files[fnum1].open) return(False);
3193 if (!target_is_directory && count)
3196 fnum2 = find_free_file();
3198 close_file(fnum1,False);
3201 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3202 ofun,st.st_mode,0,&Access,&action);
3204 if (!Files[fnum2].open) {
3205 close_file(fnum1,False);
3209 if ((ofun&3) == 1) {
3210 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3214 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3216 close_file(fnum1,False);
3217 close_file(fnum2,False);
3219 return(ret == st.st_size);
3224 /****************************************************************************
3225 reply to a file copy.
3226 ****************************************************************************/
3227 int reply_copy(char *inbuf,char *outbuf)
3233 pstring mask,newname;
3236 int error = ERRnoaccess;
3239 int tid2 = SVAL(inbuf,smb_vwv0);
3240 int ofun = SVAL(inbuf,smb_vwv1);
3241 int flags = SVAL(inbuf,smb_vwv2);
3242 BOOL target_is_directory=False;
3243 BOOL bad_path1 = False;
3244 BOOL bad_path2 = False;
3246 *directory = *mask = 0;
3248 cnum = SVAL(inbuf,smb_tid);
3250 pstrcpy(name,smb_buf(inbuf));
3251 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3253 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3256 /* can't currently handle inter share copies XXXX */
3257 DEBUG(3,("Rejecting inter-share copy\n"));
3258 return(ERROR(ERRSRV,ERRinvdevice));
3261 unix_convert(name,cnum,0,&bad_path1);
3262 unix_convert(newname,cnum,0,&bad_path2);
3264 target_is_directory = directory_exist(newname,NULL);
3266 if ((flags&1) && target_is_directory) {
3267 return(ERROR(ERRDOS,ERRbadfile));
3270 if ((flags&2) && !target_is_directory) {
3271 return(ERROR(ERRDOS,ERRbadpath));
3274 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3275 /* wants a tree copy! XXXX */
3276 DEBUG(3,("Rejecting tree copy\n"));
3277 return(ERROR(ERRSRV,ERRerror));
3280 p = strrchr(name,'/');
3282 strcpy(directory,"./");
3286 strcpy(directory,name);
3290 if (is_mangled(mask))
3291 check_mangled_stack(mask);
3293 has_wild = strchr(mask,'*') || strchr(mask,'?');
3296 strcat(directory,"/");
3297 strcat(directory,mask);
3298 if (resolve_wildcards(directory,newname) &&
3299 copy_file(directory,newname,cnum,ofun,
3300 count,target_is_directory)) count++;
3301 if (!count) exists = file_exist(directory,NULL);
3303 void *dirptr = NULL;
3307 if (check_name(directory,cnum))
3308 dirptr = OpenDir(cnum, directory, True);
3314 if (strequal(mask,"????????.???"))
3317 while ((dname = ReadDirName(dirptr)))
3320 pstrcpy(fname,dname);
3322 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3324 error = ERRnoaccess;
3325 sprintf(fname,"%s/%s",directory,dname);
3326 strcpy(destname,newname);
3327 if (resolve_wildcards(fname,destname) &&
3328 copy_file(directory,newname,cnum,ofun,
3329 count,target_is_directory)) count++;
3330 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3338 return(ERROR(ERRDOS,error));
3341 if((errno == ENOENT) && (bad_path1 || bad_path2))
3343 unix_ERR_class = ERRDOS;
3344 unix_ERR_code = ERRbadpath;
3346 return(UNIXERROR(ERRDOS,error));
3350 outsize = set_message(outbuf,1,0,True);
3351 SSVAL(outbuf,smb_vwv0,count);
3358 /****************************************************************************
3360 ****************************************************************************/
3361 int reply_setdir(char *inbuf,char *outbuf)
3368 cnum = SVAL(inbuf,smb_tid);
3370 snum = Connections[cnum].service;
3371 if (!CAN_SETDIR(snum))
3372 return(ERROR(ERRDOS,ERRnoaccess));
3374 pstrcpy(newdir,smb_buf(inbuf) + 1);
3377 if (strlen(newdir) == 0)
3381 ok = directory_exist(newdir,NULL);
3383 string_set(&Connections[cnum].connectpath,newdir);
3387 return(ERROR(ERRDOS,ERRbadpath));
3389 outsize = set_message(outbuf,0,0,True);
3390 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3392 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3398 /****************************************************************************
3399 reply to a lockingX request
3400 ****************************************************************************/
3401 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3403 int fnum = GETFNUM(inbuf,smb_vwv2);
3404 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3406 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3408 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3409 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3410 uint32 count, offset;
3415 uint32 ecode=0, dummy2;
3416 int eclass=0, dummy1;
3418 cnum = SVAL(inbuf,smb_tid);
3420 CHECK_FNUM(fnum,cnum);
3423 data = smb_buf(inbuf);
3425 /* Check if this is an oplock break on a file
3426 we have granted an oplock on.
3428 if((locktype == LOCKING_ANDX_OPLOCK_RELEASE) &&
3429 (num_ulocks == 0) && (num_locks == 0) &&
3430 (CVAL(inbuf,smb_vwv0) == 0xFF))
3433 files_struct *fsp = &Files[fnum];
3434 uint32 dev = fsp->fd_ptr->dev;
3435 uint32 inode = fsp->fd_ptr->inode;
3437 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3440 * Make sure we have granted an oplock on this file.
3442 if(!fsp->granted_oplock)
3444 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3445 no oplock granted on this file.\n", fnum));
3446 return ERROR(ERRDOS,ERRlock);
3449 /* Remove the oplock flag from the sharemode. */
3450 lock_share_entry(fsp->cnum, dev, inode, &token);
3451 if(remove_share_oplock( fnum, token)==False)
3453 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3454 dev = %x, inode = %x\n", fnum, dev, inode));
3455 unlock_share_entry(fsp->cnum, dev, inode, token);
3458 unlock_share_entry(fsp->cnum, dev, inode, token);
3460 /* Clear the granted flag and return. */
3462 fsp->granted_oplock = False;
3466 /* Data now points at the beginning of the list
3467 of smb_unlkrng structs */
3468 for(i = 0; i < (int)num_ulocks; i++) {
3469 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3470 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3471 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3472 return ERROR(eclass,ecode);
3475 /* Now do any requested locks */
3476 data += 10*num_ulocks;
3477 /* Data now points at the beginning of the list
3478 of smb_lkrng structs */
3479 for(i = 0; i < (int)num_locks; i++) {
3480 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3481 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3482 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3486 /* If any of the above locks failed, then we must unlock
3487 all of the previous locks (X/Open spec). */
3488 if(i != num_locks && num_locks != 0) {
3489 for(; i >= 0; i--) {
3490 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3491 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3492 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3494 return ERROR(eclass,ecode);
3497 set_message(outbuf,2,0,True);
3499 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3500 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3504 return chain_reply(inbuf,outbuf,length,bufsize);
3508 /****************************************************************************
3509 reply to a SMBreadbmpx (read block multiplex) request
3510 ****************************************************************************/
3511 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3518 int outsize, mincount, maxcount;
3523 /* this function doesn't seem to work - disable by default */
3525 return(ERROR(ERRSRV,ERRuseSTD));
3527 outsize = set_message(outbuf,8,0,True);
3529 cnum = SVAL(inbuf,smb_tid);
3530 fnum = GETFNUM(inbuf,smb_vwv0);
3532 CHECK_FNUM(fnum,cnum);
3536 startpos = IVAL(inbuf,smb_vwv1);
3537 maxcount = SVAL(inbuf,smb_vwv3);
3538 mincount = SVAL(inbuf,smb_vwv4);
3540 data = smb_buf(outbuf);
3541 pad = ((long)data)%4;
3542 if (pad) pad = 4 - pad;
3545 max_per_packet = bufsize-(outsize+pad);
3549 if (is_locked(fnum,cnum,maxcount,startpos))
3550 return(ERROR(ERRDOS,ERRlock));
3554 int N = MIN(max_per_packet,tcount-total_read);
3556 nread = read_file(fnum,data,startpos,N);
3558 if (nread <= 0) nread = 0;
3561 tcount = total_read + nread;
3563 set_message(outbuf,8,nread,False);
3564 SIVAL(outbuf,smb_vwv0,startpos);
3565 SSVAL(outbuf,smb_vwv2,tcount);
3566 SSVAL(outbuf,smb_vwv6,nread);
3567 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3569 send_smb(Client,outbuf);
3571 total_read += nread;
3574 while (total_read < tcount);
3580 /****************************************************************************
3581 reply to a SMBwritebmpx (write block multiplex primary) request
3582 ****************************************************************************/
3583 int reply_writebmpx(char *inbuf,char *outbuf)
3585 int cnum,numtowrite,fnum;
3589 int tcount, write_through, smb_doff;
3592 cnum = SVAL(inbuf,smb_tid);
3593 fnum = GETFNUM(inbuf,smb_vwv0);
3595 CHECK_FNUM(fnum,cnum);
3599 tcount = SVAL(inbuf,smb_vwv1);
3600 startpos = IVAL(inbuf,smb_vwv3);
3601 write_through = BITSETW(inbuf+smb_vwv7,0);
3602 numtowrite = SVAL(inbuf,smb_vwv10);
3603 smb_doff = SVAL(inbuf,smb_vwv11);
3605 data = smb_base(inbuf) + smb_doff;
3607 /* If this fails we need to send an SMBwriteC response,
3608 not an SMBwritebmpx - set this up now so we don't forget */
3609 CVAL(outbuf,smb_com) = SMBwritec;
3611 if (is_locked(fnum,cnum,tcount,startpos))
3612 return(ERROR(ERRDOS,ERRlock));
3614 seek_file(fnum,startpos);
3615 nwritten = write_file(fnum,data,numtowrite);
3617 if(lp_syncalways(SNUM(cnum)) || write_through)
3620 if(nwritten < numtowrite)
3621 return(UNIXERROR(ERRHRD,ERRdiskfull));
3623 /* If the maximum to be written to this file
3624 is greater than what we just wrote then set
3625 up a secondary struct to be attached to this
3626 fd, we will use this to cache error messages etc. */
3627 if(tcount > nwritten)
3629 write_bmpx_struct *wbms;
3630 if(Files[fnum].wbmpx_ptr != NULL)
3631 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3633 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3636 DEBUG(0,("Out of memory in reply_readmpx\n"));
3637 return(ERROR(ERRSRV,ERRnoresource));
3639 wbms->wr_mode = write_through;
3640 wbms->wr_discard = False; /* No errors yet */
3641 wbms->wr_total_written = nwritten;
3642 wbms->wr_errclass = 0;
3644 Files[fnum].wbmpx_ptr = wbms;
3647 /* We are returning successfully, set the message type back to
3649 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3651 outsize = set_message(outbuf,1,0,True);
3653 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3655 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3656 timestring(),fnum,cnum,numtowrite,nwritten));
3658 if (write_through && tcount==nwritten) {
3659 /* we need to send both a primary and a secondary response */
3660 smb_setlen(outbuf,outsize - 4);
3661 send_smb(Client,outbuf);
3663 /* now the secondary */
3664 outsize = set_message(outbuf,1,0,True);
3665 CVAL(outbuf,smb_com) = SMBwritec;
3666 SSVAL(outbuf,smb_vwv0,nwritten);
3673 /****************************************************************************
3674 reply to a SMBwritebs (write block multiplex secondary) request
3675 ****************************************************************************/
3676 int reply_writebs(char *inbuf,char *outbuf)
3678 int cnum,numtowrite,fnum;
3682 int tcount, write_through, smb_doff;
3684 write_bmpx_struct *wbms;
3685 BOOL send_response = False;
3687 cnum = SVAL(inbuf,smb_tid);
3688 fnum = GETFNUM(inbuf,smb_vwv0);
3689 CHECK_FNUM(fnum,cnum);
3692 tcount = SVAL(inbuf,smb_vwv1);
3693 startpos = IVAL(inbuf,smb_vwv2);
3694 numtowrite = SVAL(inbuf,smb_vwv6);
3695 smb_doff = SVAL(inbuf,smb_vwv7);
3697 data = smb_base(inbuf) + smb_doff;
3699 /* We need to send an SMBwriteC response, not an SMBwritebs */
3700 CVAL(outbuf,smb_com) = SMBwritec;
3702 /* This fd should have an auxiliary struct attached,
3703 check that it does */
3704 wbms = Files[fnum].wbmpx_ptr;
3705 if(!wbms) return(-1);
3707 /* If write through is set we can return errors, else we must
3709 write_through = wbms->wr_mode;
3711 /* Check for an earlier error */
3712 if(wbms->wr_discard)
3713 return -1; /* Just discard the packet */
3715 seek_file(fnum,startpos);
3716 nwritten = write_file(fnum,data,numtowrite);
3718 if(lp_syncalways(SNUM(cnum)) || write_through)
3721 if (nwritten < numtowrite)
3724 /* We are returning an error - we can delete the aux struct */
3725 if (wbms) free((char *)wbms);
3726 Files[fnum].wbmpx_ptr = NULL;
3727 return(ERROR(ERRHRD,ERRdiskfull));
3729 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3732 /* Increment the total written, if this matches tcount
3733 we can discard the auxiliary struct (hurrah !) and return a writeC */
3734 wbms->wr_total_written += nwritten;
3735 if(wbms->wr_total_written >= tcount)
3737 if (write_through) {
3738 outsize = set_message(outbuf,1,0,True);
3739 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3740 send_response = True;
3744 Files[fnum].wbmpx_ptr = NULL;
3754 /****************************************************************************
3755 reply to a SMBsetattrE
3756 ****************************************************************************/
3757 int reply_setattrE(char *inbuf,char *outbuf)
3760 struct utimbuf unix_times;
3763 outsize = set_message(outbuf,0,0,True);
3765 cnum = SVAL(inbuf,smb_tid);
3766 fnum = GETFNUM(inbuf,smb_vwv0);
3768 CHECK_FNUM(fnum,cnum);
3771 /* Convert the DOS times into unix times. Ignore create
3772 time as UNIX can't set this.
3774 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3775 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3778 * Patch from Ray Frush <frush@engr.colostate.edu>
3779 * Sometimes times are sent as zero - ignore them.
3782 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3784 /* Ignore request */
3785 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3786 not setting timestamps of 0\n",
3787 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3790 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3792 /* set modify time = to access time if modify time was 0 */
3793 unix_times.modtime = unix_times.actime;
3796 /* Set the date on this file */
3797 if(file_utime(cnum, Files[fnum].name, &unix_times))
3798 return(ERROR(ERRDOS,ERRnoaccess));
3800 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3801 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3807 /****************************************************************************
3808 reply to a SMBgetattrE
3809 ****************************************************************************/
3810 int reply_getattrE(char *inbuf,char *outbuf)
3817 outsize = set_message(outbuf,11,0,True);
3819 cnum = SVAL(inbuf,smb_tid);
3820 fnum = GETFNUM(inbuf,smb_vwv0);
3822 CHECK_FNUM(fnum,cnum);
3825 /* Do an fstat on this file */
3826 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3827 return(UNIXERROR(ERRDOS,ERRnoaccess));
3829 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3831 /* Convert the times into dos times. Set create
3832 date to be last modify date as UNIX doesn't save
3834 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3835 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3836 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3839 SIVAL(outbuf,smb_vwv6,0);
3840 SIVAL(outbuf,smb_vwv8,0);
3844 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3845 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3847 SSVAL(outbuf,smb_vwv10, mode);
3849 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));