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;
85 case 0x81: /* session request */
86 CVAL(outbuf,0) = 0x82;
88 if (name_len(inbuf+4) > 50 ||
89 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
90 DEBUG(0,("Invalid name length in session request\n"));
93 name_extract(inbuf,4,name1);
94 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
95 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
98 fstrcpy(remote_machine,name2);
99 trim_string(remote_machine," "," ");
100 p = strchr(remote_machine,' ');
101 strlower(remote_machine);
104 fstrcpy(local_machine,name1);
105 trim_string(local_machine," "," ");
106 len = strlen(local_machine);
108 name_type = local_machine[15];
109 local_machine[15] = 0;
111 p = strchr(local_machine,' ');
112 strlower(local_machine);
115 if (name_type == 'R') {
116 /* We are being asked for a pathworks session ---
118 CVAL(outbuf, 0) = 0x83;
122 add_session_user(remote_machine);
124 reload_services(True);
129 case 0x89: /* session keepalive request
130 (some old clients produce this?) */
131 CVAL(outbuf,0) = 0x85;
135 case 0x82: /* positive session response */
136 case 0x83: /* negative session response */
137 case 0x84: /* retarget session response */
138 DEBUG(0,("Unexpected session response\n"));
141 case 0x85: /* session keepalive */
146 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",
147 timestring(),msg_type,msg_flags));
153 /*******************************************************************
154 work out what error to give to a failed connection
155 ********************************************************************/
156 static int connection_error(char *inbuf,char *outbuf,int connection_num)
158 switch (connection_num)
161 return(ERROR(ERRSRV,ERRnoresource));
163 return(ERROR(ERRSRV,ERRbaduid));
165 return(ERROR(ERRSRV,ERRinvdevice));
167 return(ERROR(ERRSRV,ERRinvnetname));
169 return(ERROR(ERRSRV,ERRaccess));
171 return(ERROR(ERRDOS,ERRnoipc));
173 return(ERROR(ERRSRV,ERRinvnetname));
175 return(ERROR(ERRSRV,ERRbadpw));
180 /****************************************************************************
181 parse a share descriptor string
182 ****************************************************************************/
183 static void parse_connect(char *p,char *service,char *user,
184 char *password,int *pwlen,char *dev)
188 DEBUG(4,("parsing connect string %s\n",p));
190 p2 = strrchr(p,'\\');
194 fstrcpy(service,p2+1);
199 *pwlen = strlen(password);
206 p = strchr(service,'%');
217 /****************************************************************************
219 ****************************************************************************/
220 int reply_tcon(char *inbuf,char *outbuf)
228 uint16 vuid = SVAL(inbuf,smb_uid);
231 *service = *user = *password = *dev = 0;
233 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
235 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
237 if (connection_num < 0)
238 return(connection_error(inbuf,outbuf,connection_num));
240 outsize = set_message(outbuf,2,0,True);
241 SSVAL(outbuf,smb_vwv0,max_recv);
242 SSVAL(outbuf,smb_vwv1,connection_num);
243 SSVAL(outbuf,smb_tid,connection_num);
245 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
251 /****************************************************************************
252 reply to a tcon and X
253 ****************************************************************************/
254 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
261 uint16 vuid = SVAL(inbuf,smb_uid);
262 int passlen = SVAL(inbuf,smb_vwv3);
263 BOOL doencrypt = SMBENCRYPT();
265 *service = *user = *password = *devicename = 0;
267 /* we might have to close an old one */
268 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
269 close_cnum(SVAL(inbuf,smb_tid),vuid);
271 if (passlen > MAX_PASS_LEN) {
272 overflow_attack(passlen);
278 memcpy(password,smb_buf(inbuf),passlen);
280 path = smb_buf(inbuf) + passlen;
282 if (!doencrypt || passlen != 24) {
283 if (strequal(password," "))
285 passlen = strlen(password);
288 fstrcpy(service,path+2);
289 p = strchr(service,'\\');
291 return(ERROR(ERRSRV,ERRinvnetname));
293 fstrcpy(service,p+1);
294 p = strchr(service,'%');
300 StrnCpy(devicename,path + strlen(path) + 1,6);
301 DEBUG(4,("Got device type %s\n",devicename));
304 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
306 if (connection_num < 0)
307 return(connection_error(inbuf,outbuf,connection_num));
309 if (Protocol < PROTOCOL_NT1)
311 set_message(outbuf,2,strlen(devicename)+1,True);
312 strcpy(smb_buf(outbuf),devicename);
316 char *fsname = "SAMBA";
319 set_message(outbuf,3,3,True);
322 strcpy(p,devicename); p = skip_string(p,1); /* device name */
323 strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
325 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
327 SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
330 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
332 /* set the incoming and outgoing tid to the just created one */
333 SSVAL(inbuf,smb_tid,connection_num);
334 SSVAL(outbuf,smb_tid,connection_num);
336 return chain_reply(inbuf,outbuf,length,bufsize);
340 /****************************************************************************
341 reply to an unknown type
342 ****************************************************************************/
343 int reply_unknown(char *inbuf,char *outbuf)
347 cnum = SVAL(inbuf,smb_tid);
348 type = CVAL(inbuf,smb_com);
350 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
355 return(ERROR(ERRSRV,ERRunknownsmb));
359 /****************************************************************************
361 ****************************************************************************/
362 int reply_ioctl(char *inbuf,char *outbuf)
364 DEBUG(3,("ignoring ioctl\n"));
366 /* we just say it succeeds and hope its all OK.
367 some day it would be nice to interpret them individually */
368 return set_message(outbuf,1,0,True);
370 return(ERROR(ERRSRV,ERRnosupport));
375 /****************************************************************************
376 reply to a session setup command
377 ****************************************************************************/
378 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
387 int smb_apasslen = 0;
389 int smb_ntpasslen = 0;
390 pstring smb_ntpasswd;
391 BOOL valid_nt_password = False;
394 BOOL computer_id=False;
395 static BOOL done_sesssetup = False;
396 BOOL doencrypt = SMBENCRYPT();
402 smb_bufsize = SVAL(inbuf,smb_vwv2);
403 smb_mpxmax = SVAL(inbuf,smb_vwv3);
404 smb_vc_num = SVAL(inbuf,smb_vwv4);
405 smb_sesskey = IVAL(inbuf,smb_vwv5);
407 if (Protocol < PROTOCOL_NT1) {
408 smb_apasslen = SVAL(inbuf,smb_vwv7);
409 if (smb_apasslen > MAX_PASS_LEN)
411 overflow_attack(smb_apasslen);
414 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
415 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
417 if (lp_security() != SEC_SERVER && !doencrypt) {
418 smb_apasslen = strlen(smb_apasswd);
421 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
422 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
423 uint32 client_caps = IVAL(inbuf,smb_vwv11);
424 enum remote_arch_types ra_type = get_remote_arch();
426 char *p = smb_buf(inbuf);
428 /* client_caps is used as final determination if client is NT or Win95.
429 This is needed to return the correct error codes in some
433 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
435 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
436 set_remote_arch( RA_WINNT);
438 set_remote_arch( RA_WIN95);
441 if (passlen1 != 24 && passlen2 != 24)
444 if (passlen1 > MAX_PASS_LEN) {
445 overflow_attack(passlen1);
448 passlen1 = MIN(passlen1, MAX_PASS_LEN);
449 passlen2 = MIN(passlen2, MAX_PASS_LEN);
452 /* Save the lanman2 password and the NT md4 password. */
453 smb_apasslen = passlen1;
454 memcpy(smb_apasswd,p,smb_apasslen);
455 smb_ntpasslen = passlen2;
456 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
458 /* both Win95 and WinNT stuff up the password lengths for
459 non-encrypting systems. Uggh.
461 if passlen1==24 its a win95 system, and its setting the
462 password length incorrectly. Luckily it still works with the
463 default code because Win95 will null terminate the password
466 if passlen1>0 and passlen2>0 then maybe its a NT box and its
467 setting passlen2 to some random value which really stuffs
468 things up. we need to fix that one. */
469 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
473 /* we use the first password that they gave */
474 smb_apasslen = passlen1;
475 StrnCpy(smb_apasswd,p,smb_apasslen);
477 /* trim the password */
478 smb_apasslen = strlen(smb_apasswd);
480 /* wfwg sometimes uses a space instead of a null */
481 if (strequal(smb_apasswd," ")) {
487 p += passlen1 + passlen2;
488 fstrcpy(user,p); p = skip_string(p,1);
491 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
492 domain,skip_string(p,1),skip_string(p,2)));
496 DEBUG(3,("sesssetupX:name=[%s]\n",user));
498 /* If name ends in $ then I think it's asking about whether a */
499 /* computer with that name (minus the $) has access. For now */
500 /* say yes to everything ending in $. */
501 if (user[strlen(user) - 1] == '$')
504 struct smb_passwd *smb_pass; /* To check if machine account exists */
506 PAXX: Ack. We don't want to do this. The workstation trust account
507 with a $ on the end should exist in the local password database
508 or be mapped to something generic, but not modified. For NT
509 domain support we must reject this used in certain circumstances
510 with a code to indicate to the client that it is an invalid use
511 of a workstation trust account. NTWKS needs this error to join
512 a domain. This may be the source of future bugs if we cannot
513 be sure whether to reject this or not.
515 /* non-null user name indicates search by username not by smb userid */
516 smb_pass = get_smbpwd_entry(user, 0);
520 /* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */
521 DEBUG(4,("Workstation trust account %s doesn't exist.",user));
522 SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
523 CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
524 return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */
528 /* PAXX: This is the NO LOGON workstation trust account stuff */
529 /* lkclXXXX: if the workstation *does* exist, indicate failure differently! */
530 DEBUG(4,("No Workstation trust account %s",user));
531 SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
532 CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
533 return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */
537 #else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */
538 user[strlen(user) - 1] = '\0';
543 /* If no username is sent use the guest account */
546 strcpy(user,lp_guestaccount(-1));
547 /* If no user and no password then set guest flag. */
548 if( *smb_apasswd == 0)
554 strcpy(sesssetup_user,user);
556 reload_services(True);
558 add_session_user(user);
560 /* Check if the given username was the guest user with no password.
561 We need to do this check after add_session_user() as that
562 call can potentially change the username (via map_user).
565 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
568 if (!guest && !(lp_security() == SEC_SERVER &&
569 server_validate(user, domain,
570 smb_apasswd, smb_apasslen,
571 smb_ntpasswd, smb_ntpasslen)) &&
572 !check_hosts_equiv(user))
575 /* now check if it's a valid username/password */
576 /* If an NT password was supplied try and validate with that
577 first. This is superior as the passwords are mixed case
578 128 length unicode */
581 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
582 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
584 valid_nt_password = True;
586 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
588 if (!computer_id && lp_security() >= SEC_USER) {
589 #if (GUEST_SESSSETUP == 0)
590 return(ERROR(ERRSRV,ERRbadpw));
592 #if (GUEST_SESSSETUP == 1)
593 if (Get_Pwnam(user,True))
594 return(ERROR(ERRSRV,ERRbadpw));
597 if (*smb_apasswd || !Get_Pwnam(user,True))
598 strcpy(user,lp_guestaccount(-1));
599 DEBUG(3,("Registered username %s for guest access\n",user));
604 if (!Get_Pwnam(user,True)) {
605 DEBUG(3,("No such user %s - using guest account\n",user));
606 strcpy(user,lp_guestaccount(-1));
610 if (!strequal(user,lp_guestaccount(-1)) &&
611 lp_servicenumber(user) < 0)
613 int homes = lp_servicenumber(HOMES_NAME);
614 char *home = get_home_dir(user);
615 if (homes >= 0 && home)
616 lp_add_home(user,homes,home);
620 /* it's ok - setup a reply */
621 if (Protocol < PROTOCOL_NT1) {
622 set_message(outbuf,3,0,True);
625 set_message(outbuf,3,3,True);
627 strcpy(p,"Unix"); p = skip_string(p,1);
628 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
629 strcpy(p,myworkgroup); p = skip_string(p,1);
630 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
631 /* perhaps grab OS version here?? */
634 /* Set the correct uid in the outgoing and incoming packets
635 We will use this on future requests to determine which
636 user we should become.
639 struct passwd *pw = Get_Pwnam(user,False);
641 DEBUG(1,("Username %s is invalid on this system\n",user));
642 return(ERROR(ERRSRV,ERRbadpw));
648 if (guest && !computer_id)
649 SSVAL(outbuf,smb_vwv2,1);
651 /* register the name and uid as being validated, so further connections
652 to a uid can get through without a password, on the same VC */
653 sess_vuid = register_vuid(uid,gid,user,guest);
655 SSVAL(outbuf,smb_uid,sess_vuid);
656 SSVAL(inbuf,smb_uid,sess_vuid);
659 max_send = MIN(max_send,smb_bufsize);
661 DEBUG(6,("Client requested max send size of %d\n", max_send));
663 done_sesssetup = True;
665 return chain_reply(inbuf,outbuf,length,bufsize);
669 /****************************************************************************
671 ****************************************************************************/
672 int reply_chkpth(char *inbuf,char *outbuf)
678 BOOL bad_path = False;
680 cnum = SVAL(inbuf,smb_tid);
682 pstrcpy(name,smb_buf(inbuf) + 1);
683 unix_convert(name,cnum,0,&bad_path);
685 mode = SVAL(inbuf,smb_vwv0);
687 if (check_name(name,cnum))
688 ok = directory_exist(name,NULL);
692 /* We special case this - as when a Windows machine
693 is parsing a path is steps through the components
694 one at a time - if a component fails it expects
695 ERRbadpath, not ERRbadfile.
699 unix_ERR_class = ERRDOS;
700 unix_ERR_code = ERRbadpath;
704 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
705 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
706 (get_remote_arch() == RA_WINNT))
708 unix_ERR_class = ERRDOS;
709 unix_ERR_code = ERRbaddirectory;
713 return(UNIXERROR(ERRDOS,ERRbadpath));
716 outsize = set_message(outbuf,0,0,True);
718 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
724 /****************************************************************************
726 ****************************************************************************/
727 int reply_getatr(char *inbuf,char *outbuf)
737 BOOL bad_path = False;
739 cnum = SVAL(inbuf,smb_tid);
741 pstrcpy(fname,smb_buf(inbuf) + 1);
742 unix_convert(fname,cnum,0,&bad_path);
744 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
745 under WfWg - weird! */
748 mode = aHIDDEN | aDIR;
749 if (!CAN_WRITE(cnum)) mode |= aRONLY;
755 if (check_name(fname,cnum))
757 if (sys_stat(fname,&sbuf) == 0)
759 mode = dos_mode(cnum,fname,&sbuf);
761 mtime = sbuf.st_mtime;
767 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
772 if((errno == ENOENT) && bad_path)
774 unix_ERR_class = ERRDOS;
775 unix_ERR_code = ERRbadpath;
778 return(UNIXERROR(ERRDOS,ERRbadfile));
781 outsize = set_message(outbuf,10,0,True);
783 SSVAL(outbuf,smb_vwv0,mode);
784 put_dos_date3(outbuf,smb_vwv1,mtime);
785 SIVAL(outbuf,smb_vwv3,size);
787 if (Protocol >= PROTOCOL_NT1) {
788 char *p = strrchr(fname,'/');
789 uint16 flg2 = SVAL(outbuf,smb_flg2);
791 if (!is_8_3(fname, True))
792 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
795 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
801 /****************************************************************************
803 ****************************************************************************/
804 int reply_setatr(char *inbuf,char *outbuf)
812 BOOL bad_path = False;
814 cnum = SVAL(inbuf,smb_tid);
816 pstrcpy(fname,smb_buf(inbuf) + 1);
817 unix_convert(fname,cnum,0,&bad_path);
819 mode = SVAL(inbuf,smb_vwv0);
820 mtime = make_unix_date3(inbuf+smb_vwv1);
822 if (directory_exist(fname,NULL))
824 if (check_name(fname,cnum))
825 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
827 ok = set_filetime(cnum,fname,mtime);
831 if((errno == ENOENT) && bad_path)
833 unix_ERR_class = ERRDOS;
834 unix_ERR_code = ERRbadpath;
837 return(UNIXERROR(ERRDOS,ERRnoaccess));
840 outsize = set_message(outbuf,0,0,True);
842 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
848 /****************************************************************************
850 ****************************************************************************/
851 int reply_dskattr(char *inbuf,char *outbuf)
855 int dfree,dsize,bsize;
857 cnum = SVAL(inbuf,smb_tid);
859 sys_disk_free(".",&bsize,&dfree,&dsize);
861 outsize = set_message(outbuf,5,0,True);
863 SSVAL(outbuf,smb_vwv0,dsize);
864 SSVAL(outbuf,smb_vwv1,bsize/512);
865 SSVAL(outbuf,smb_vwv2,512);
866 SSVAL(outbuf,smb_vwv3,dfree);
868 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
874 /****************************************************************************
876 Can be called from SMBsearch, SMBffirst or SMBfunique.
877 ****************************************************************************/
878 int reply_search(char *inbuf,char *outbuf)
889 BOOL finished = False;
898 BOOL check_descend = False;
899 BOOL expect_close = False;
900 BOOL can_open = True;
901 BOOL bad_path = False;
903 *mask = *directory = *fname = 0;
905 /* If we were called as SMBffirst then we must expect close. */
906 if(CVAL(inbuf,smb_com) == SMBffirst)
909 cnum = SVAL(inbuf,smb_tid);
911 outsize = set_message(outbuf,1,3,True);
912 maxentries = SVAL(inbuf,smb_vwv0);
913 dirtype = SVAL(inbuf,smb_vwv1);
914 path = smb_buf(inbuf) + 1;
915 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
918 /* dirtype &= ~aDIR; */
920 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
927 pstrcpy(directory,smb_buf(inbuf)+1);
928 pstrcpy(dir2,smb_buf(inbuf)+1);
929 unix_convert(directory,cnum,0,&bad_path);
932 if (!check_name(directory,cnum))
935 p = strrchr(dir2,'/');
947 p = strrchr(directory,'/');
953 if (strlen(directory) == 0)
954 strcpy(directory,"./");
956 CVAL(status,0) = dirtype;
960 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
961 memcpy(mask,status+1,11);
963 dirtype = CVAL(status,0) & 0x1F;
964 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
965 if (!Connections[cnum].dirptr)
967 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
972 /* turn strings of spaces into a . */
974 trim_string(mask,NULL," ");
975 if ((p = strrchr(mask,' ')))
980 trim_string(mask,NULL," ");
987 for (p=mask; *p; p++)
989 if (*p != '?' && *p != '*' && !isdoschar(*p))
991 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
997 if (!strchr(mask,'.') && strlen(mask)>8)
1000 fstrcpy(tmp,&mask[8]);
1006 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1010 p = smb_buf(outbuf) + 3;
1014 if (status_len == 0)
1016 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
1021 if((errno == ENOENT) && bad_path)
1023 unix_ERR_class = ERRDOS;
1024 unix_ERR_code = ERRbadpath;
1026 return (UNIXERROR(ERRDOS,ERRnofids));
1028 return(ERROR(ERRDOS,ERRnofids));
1032 DEBUG(4,("dptr_num is %d\n",dptr_num));
1036 if ((dirtype&0x1F) == aVOLID)
1038 memcpy(p,status,21);
1039 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
1040 dptr_fill(p+12,dptr_num);
1041 if (dptr_zero(p+12) && (status_len==0))
1045 p += DIR_STRUCT_SIZE;
1049 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
1050 if (in_list(Connections[cnum].dirpath,
1051 lp_dontdescend(SNUM(cnum)),True))
1052 check_descend = True;
1054 for (i=numentries;(i<maxentries) && !finished;i++)
1057 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
1060 memcpy(p,status,21);
1061 make_dir_struct(p,mask,fname,size,mode,date);
1062 dptr_fill(p+12,dptr_num);
1065 p += DIR_STRUCT_SIZE;
1074 if (numentries == 0 || !ok)
1076 CVAL(outbuf,smb_rcls) = ERRDOS;
1077 SSVAL(outbuf,smb_err,ERRnofiles);
1080 /* If we were called as SMBffirst with smb_search_id == NULL
1081 and no entries were found then return error and close dirptr
1084 if(ok && expect_close && numentries == 0 && status_len == 0)
1086 CVAL(outbuf,smb_rcls) = ERRDOS;
1087 SSVAL(outbuf,smb_err,ERRnofiles);
1088 /* Also close the dptr - we know it's gone */
1089 dptr_close(dptr_num);
1092 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1093 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1094 dptr_close(dptr_num);
1096 SSVAL(outbuf,smb_vwv0,numentries);
1097 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1098 CVAL(smb_buf(outbuf),0) = 5;
1099 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1101 if (Protocol >= PROTOCOL_NT1) {
1102 uint16 flg2 = SVAL(outbuf,smb_flg2);
1103 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1106 outsize += DIR_STRUCT_SIZE*numentries;
1107 smb_setlen(outbuf,outsize - 4);
1109 if ((! *directory) && dptr_path(dptr_num))
1110 sprintf(directory,"(%s)",dptr_path(dptr_num));
1112 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1114 smb_fn_name(CVAL(inbuf,smb_com)),
1115 mask,directory,cnum,dirtype,numentries,maxentries));
1121 /****************************************************************************
1122 reply to a fclose (stop directory search)
1123 ****************************************************************************/
1124 int reply_fclose(char *inbuf,char *outbuf)
1133 cnum = SVAL(inbuf,smb_tid);
1135 outsize = set_message(outbuf,1,0,True);
1136 path = smb_buf(inbuf) + 1;
1137 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1140 if (status_len == 0)
1141 return(ERROR(ERRSRV,ERRsrverror));
1143 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1145 if(dptr_fetch(status+12,&dptr_num)) {
1146 /* Close the dptr - we know it's gone */
1147 dptr_close(dptr_num);
1150 SSVAL(outbuf,smb_vwv0,0);
1152 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1158 /****************************************************************************
1160 ****************************************************************************/
1161 int reply_open(char *inbuf,char *outbuf)
1174 BOOL bad_path = False;
1176 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1178 cnum = SVAL(inbuf,smb_tid);
1180 share_mode = SVAL(inbuf,smb_vwv0);
1182 pstrcpy(fname,smb_buf(inbuf)+1);
1183 unix_convert(fname,cnum,0,&bad_path);
1185 fnum = find_free_file();
1187 return(ERROR(ERRSRV,ERRnofids));
1189 if (!check_name(fname,cnum))
1191 if((errno == ENOENT) && bad_path)
1193 unix_ERR_class = ERRDOS;
1194 unix_ERR_code = ERRbadpath;
1196 return(UNIXERROR(ERRDOS,ERRnoaccess));
1199 unixmode = unix_mode(cnum,aARCH);
1201 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1202 oplock_request,&rmode,NULL);
1208 if((errno == ENOENT) && bad_path)
1210 unix_ERR_class = ERRDOS;
1211 unix_ERR_code = ERRbadpath;
1213 return(UNIXERROR(ERRDOS,ERRnoaccess));
1216 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1217 close_file(fnum,False);
1218 return(ERROR(ERRDOS,ERRnoaccess));
1221 size = sbuf.st_size;
1222 fmode = dos_mode(cnum,fname,&sbuf);
1223 mtime = sbuf.st_mtime;
1226 DEBUG(3,("attempt to open a directory %s\n",fname));
1227 close_file(fnum,False);
1228 return(ERROR(ERRDOS,ERRnoaccess));
1231 outsize = set_message(outbuf,7,0,True);
1232 SSVAL(outbuf,smb_vwv0,fnum);
1233 SSVAL(outbuf,smb_vwv1,fmode);
1234 put_dos_date3(outbuf,smb_vwv2,mtime);
1235 SIVAL(outbuf,smb_vwv4,size);
1236 SSVAL(outbuf,smb_vwv6,rmode);
1238 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1239 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1242 if(fsp->granted_oplock)
1243 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1248 /****************************************************************************
1249 reply to an open and X
1250 ****************************************************************************/
1251 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1254 int cnum = SVAL(inbuf,smb_tid);
1256 int smb_mode = SVAL(inbuf,smb_vwv3);
1257 int smb_attr = SVAL(inbuf,smb_vwv5);
1258 BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1260 int open_flags = SVAL(inbuf,smb_vwv2);
1261 int smb_sattr = SVAL(inbuf,smb_vwv4);
1262 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1264 int smb_ofun = SVAL(inbuf,smb_vwv8);
1266 int size=0,fmode=0,mtime=0,rmode=0;
1269 BOOL bad_path = False;
1272 /* If it's an IPC, pass off the pipe handler. */
1274 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1276 /* XXXX we need to handle passed times, sattr and flags */
1278 pstrcpy(fname,smb_buf(inbuf));
1279 unix_convert(fname,cnum,0,&bad_path);
1281 fnum = find_free_file();
1283 return(ERROR(ERRSRV,ERRnofids));
1285 if (!check_name(fname,cnum))
1287 if((errno == ENOENT) && bad_path)
1289 unix_ERR_class = ERRDOS;
1290 unix_ERR_code = ERRbadpath;
1292 return(UNIXERROR(ERRDOS,ERRnoaccess));
1295 unixmode = unix_mode(cnum,smb_attr | aARCH);
1297 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1298 oplock_request, &rmode,&smb_action);
1304 if((errno == ENOENT) && bad_path)
1306 unix_ERR_class = ERRDOS;
1307 unix_ERR_code = ERRbadpath;
1309 return(UNIXERROR(ERRDOS,ERRnoaccess));
1312 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1313 close_file(fnum,False);
1314 return(ERROR(ERRDOS,ERRnoaccess));
1317 size = sbuf.st_size;
1318 fmode = dos_mode(cnum,fname,&sbuf);
1319 mtime = sbuf.st_mtime;
1321 close_file(fnum,False);
1322 return(ERROR(ERRDOS,ERRnoaccess));
1325 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1326 smb_action |= EXTENDED_OPLOCK_GRANTED;
1327 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1330 if(fsp->granted_oplock) {
1331 smb_action |= EXTENDED_OPLOCK_GRANTED;
1332 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1335 set_message(outbuf,15,0,True);
1336 SSVAL(outbuf,smb_vwv2,fnum);
1337 SSVAL(outbuf,smb_vwv3,fmode);
1338 put_dos_date3(outbuf,smb_vwv4,mtime);
1339 SIVAL(outbuf,smb_vwv6,size);
1340 SSVAL(outbuf,smb_vwv8,rmode);
1341 SSVAL(outbuf,smb_vwv11,smb_action);
1345 return chain_reply(inbuf,outbuf,length,bufsize);
1349 /****************************************************************************
1350 reply to a SMBulogoffX
1351 ****************************************************************************/
1352 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1354 uint16 vuid = SVAL(inbuf,smb_uid);
1355 user_struct *vuser = get_valid_user_struct(vuid);
1358 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1361 /* in user level security we are supposed to close any files
1362 open by this user */
1363 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1365 for (i=0;i<MAX_OPEN_FILES;i++)
1366 if (Files[i].uid == vuser->uid && Files[i].open) {
1367 close_file(i,False);
1371 invalidate_vuid(vuid);
1373 set_message(outbuf,2,0,True);
1375 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1377 return chain_reply(inbuf,outbuf,length,bufsize);
1381 /****************************************************************************
1382 reply to a mknew or a create
1383 ****************************************************************************/
1384 int reply_mknew(char *inbuf,char *outbuf)
1393 BOOL bad_path = False;
1395 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1397 com = SVAL(inbuf,smb_com);
1398 cnum = SVAL(inbuf,smb_tid);
1400 createmode = SVAL(inbuf,smb_vwv0);
1401 pstrcpy(fname,smb_buf(inbuf)+1);
1402 unix_convert(fname,cnum,0,&bad_path);
1404 if (createmode & aVOLID)
1406 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1409 unixmode = unix_mode(cnum,createmode);
1411 fnum = find_free_file();
1413 return(ERROR(ERRSRV,ERRnofids));
1415 if (!check_name(fname,cnum))
1417 if((errno == ENOENT) && bad_path)
1419 unix_ERR_class = ERRDOS;
1420 unix_ERR_code = ERRbadpath;
1422 return(UNIXERROR(ERRDOS,ERRnoaccess));
1427 /* We should fail if file exists. */
1432 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1436 /* Open file in dos compatibility share mode. */
1437 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1438 oplock_request, NULL, NULL);
1444 if((errno == ENOENT) && bad_path)
1446 unix_ERR_class = ERRDOS;
1447 unix_ERR_code = ERRbadpath;
1449 return(UNIXERROR(ERRDOS,ERRnoaccess));
1452 outsize = set_message(outbuf,1,0,True);
1453 SSVAL(outbuf,smb_vwv0,fnum);
1455 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1456 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1459 if(fsp->granted_oplock)
1460 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1462 DEBUG(2,("new file %s\n",fname));
1463 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));
1469 /****************************************************************************
1470 reply to a create temporary file
1471 ****************************************************************************/
1472 int reply_ctemp(char *inbuf,char *outbuf)
1481 BOOL bad_path = False;
1483 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1485 cnum = SVAL(inbuf,smb_tid);
1486 createmode = SVAL(inbuf,smb_vwv0);
1487 pstrcpy(fname,smb_buf(inbuf)+1);
1488 strcat(fname,"/TMXXXXXX");
1489 unix_convert(fname,cnum,0,&bad_path);
1491 unixmode = unix_mode(cnum,createmode);
1493 fnum = find_free_file();
1495 return(ERROR(ERRSRV,ERRnofids));
1497 if (!check_name(fname,cnum))
1499 if((errno == ENOENT) && bad_path)
1501 unix_ERR_class = ERRDOS;
1502 unix_ERR_code = ERRbadpath;
1504 return(UNIXERROR(ERRDOS,ERRnoaccess));
1507 strcpy(fname2,(char *)mktemp(fname));
1509 /* Open file in dos compatibility share mode. */
1510 /* We should fail if file exists. */
1511 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1512 oplock_request, NULL, NULL);
1518 if((errno == ENOENT) && bad_path)
1520 unix_ERR_class = ERRDOS;
1521 unix_ERR_code = ERRbadpath;
1523 return(UNIXERROR(ERRDOS,ERRnoaccess));
1526 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1527 SSVAL(outbuf,smb_vwv0,fnum);
1528 CVAL(smb_buf(outbuf),0) = 4;
1529 strcpy(smb_buf(outbuf) + 1,fname2);
1531 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1532 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1535 if(fsp->granted_oplock)
1536 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1538 DEBUG(2,("created temp file %s\n",fname2));
1539 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));
1545 /*******************************************************************
1546 check if a user is allowed to delete a file
1547 ********************************************************************/
1548 static BOOL can_delete(char *fname,int cnum,int dirtype)
1553 if (!CAN_WRITE(cnum)) return(False);
1555 if (sys_lstat(fname,&sbuf) != 0) return(False);
1556 fmode = dos_mode(cnum,fname,&sbuf);
1557 if (fmode & aDIR) return(False);
1558 if (!lp_delete_readonly(SNUM(cnum))) {
1559 if (fmode & aRONLY) return(False);
1561 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1563 if (!check_file_sharing(cnum,fname)) return(False);
1567 /****************************************************************************
1569 ****************************************************************************/
1570 int reply_unlink(char *inbuf,char *outbuf)
1580 int error = ERRnoaccess;
1583 BOOL bad_path = False;
1585 *directory = *mask = 0;
1587 cnum = SVAL(inbuf,smb_tid);
1588 dirtype = SVAL(inbuf,smb_vwv0);
1590 pstrcpy(name,smb_buf(inbuf) + 1);
1592 DEBUG(3,("reply_unlink : %s\n",name));
1594 unix_convert(name,cnum,0,&bad_path);
1596 p = strrchr(name,'/');
1598 strcpy(directory,"./");
1602 strcpy(directory,name);
1606 if (is_mangled(mask))
1607 check_mangled_stack(mask);
1609 has_wild = strchr(mask,'*') || strchr(mask,'?');
1612 strcat(directory,"/");
1613 strcat(directory,mask);
1614 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1615 if (!count) exists = file_exist(directory,NULL);
1617 void *dirptr = NULL;
1620 if (check_name(directory,cnum))
1621 dirptr = OpenDir(cnum, directory, True);
1623 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1624 the pattern matches against the long name, otherwise the short name
1625 We don't implement this yet XXXX
1632 if (strequal(mask,"????????.???"))
1635 while ((dname = ReadDirName(dirptr)))
1638 pstrcpy(fname,dname);
1640 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1642 error = ERRnoaccess;
1643 sprintf(fname,"%s/%s",directory,dname);
1644 if (!can_delete(fname,cnum,dirtype)) continue;
1645 if (!sys_unlink(fname)) count++;
1646 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1654 return(ERROR(ERRDOS,error));
1657 if((errno == ENOENT) && bad_path)
1659 unix_ERR_class = ERRDOS;
1660 unix_ERR_code = ERRbadpath;
1662 return(UNIXERROR(ERRDOS,error));
1666 outsize = set_message(outbuf,0,0,True);
1672 /****************************************************************************
1673 reply to a readbraw (core+ protocol)
1674 ****************************************************************************/
1675 int reply_readbraw(char *inbuf, char *outbuf)
1677 int cnum,maxcount,mincount,fnum;
1680 char *header = outbuf;
1686 * Special check if an oplock break has been issued
1687 * and the readraw request croses on the wire, we must
1688 * return a zero length response here.
1691 if(global_oplock_break)
1693 _smb_setlen(header,0);
1694 transfer_file(0,Client,0,header,4,0);
1695 DEBUG(5,("readbraw - oplock break finished\n"));
1699 cnum = SVAL(inbuf,smb_tid);
1700 fnum = GETFNUM(inbuf,smb_vwv0);
1702 startpos = IVAL(inbuf,smb_vwv1);
1703 maxcount = SVAL(inbuf,smb_vwv3);
1704 mincount = SVAL(inbuf,smb_vwv4);
1706 /* ensure we don't overrun the packet size */
1707 maxcount = MIN(65535,maxcount);
1708 maxcount = MAX(mincount,maxcount);
1710 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1712 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1713 _smb_setlen(header,0);
1714 transfer_file(0,Client,0,header,4,0);
1719 fd = Files[fnum].fd_ptr->fd;
1720 fname = Files[fnum].name;
1724 if (!is_locked(fnum,cnum,maxcount,startpos))
1726 int size = Files[fnum].size;
1727 int sizeneeded = startpos + maxcount;
1729 if (size < sizeneeded) {
1731 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1733 if (!Files[fnum].can_write)
1734 Files[fnum].size = size;
1737 nread = MIN(maxcount,(int)(size - startpos));
1740 if (nread < mincount)
1743 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1746 maxcount,mincount,nread));
1751 _smb_setlen(header,nread);
1753 #if USE_READ_PREDICTION
1754 if (!Files[fnum].can_write)
1755 predict = read_predict(fd,startpos,header+4,NULL,nread);
1758 if ((nread-predict) > 0)
1759 seek_file(fnum,startpos + predict);
1761 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1766 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1767 fname,startpos,nread,ret));
1770 ret = read_file(fnum,header+4,startpos,nread);
1771 if (ret < mincount) ret = 0;
1773 _smb_setlen(header,ret);
1774 transfer_file(0,Client,0,header,4+ret,0);
1777 DEBUG(5,("readbraw finished\n"));
1782 /****************************************************************************
1783 reply to a lockread (core+ protocol)
1784 ****************************************************************************/
1785 int reply_lockread(char *inbuf,char *outbuf)
1791 uint32 startpos, numtoread;
1795 cnum = SVAL(inbuf,smb_tid);
1796 fnum = GETFNUM(inbuf,smb_vwv0);
1798 CHECK_FNUM(fnum,cnum);
1802 numtoread = SVAL(inbuf,smb_vwv1);
1803 startpos = IVAL(inbuf,smb_vwv2);
1805 outsize = set_message(outbuf,5,3,True);
1806 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1807 data = smb_buf(outbuf) + 3;
1809 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1810 return (ERROR(eclass,ecode));
1812 nread = read_file(fnum,data,startpos,numtoread);
1815 return(UNIXERROR(ERRDOS,ERRnoaccess));
1818 SSVAL(outbuf,smb_vwv0,nread);
1819 SSVAL(outbuf,smb_vwv5,nread+3);
1820 SSVAL(smb_buf(outbuf),1,nread);
1822 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1828 /****************************************************************************
1830 ****************************************************************************/
1831 int reply_read(char *inbuf,char *outbuf)
1833 int cnum,numtoread,fnum;
1839 cnum = SVAL(inbuf,smb_tid);
1840 fnum = GETFNUM(inbuf,smb_vwv0);
1842 CHECK_FNUM(fnum,cnum);
1846 numtoread = SVAL(inbuf,smb_vwv1);
1847 startpos = IVAL(inbuf,smb_vwv2);
1849 outsize = set_message(outbuf,5,3,True);
1850 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1851 data = smb_buf(outbuf) + 3;
1853 if (is_locked(fnum,cnum,numtoread,startpos))
1854 return(ERROR(ERRDOS,ERRlock));
1857 nread = read_file(fnum,data,startpos,numtoread);
1860 return(UNIXERROR(ERRDOS,ERRnoaccess));
1863 SSVAL(outbuf,smb_vwv0,nread);
1864 SSVAL(outbuf,smb_vwv5,nread+3);
1865 CVAL(smb_buf(outbuf),0) = 1;
1866 SSVAL(smb_buf(outbuf),1,nread);
1868 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1874 /****************************************************************************
1875 reply to a read and X
1876 ****************************************************************************/
1877 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1879 int fnum = GETFNUM(inbuf,smb_vwv2);
1880 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1881 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1882 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1888 cnum = SVAL(inbuf,smb_tid);
1890 CHECK_FNUM(fnum,cnum);
1894 set_message(outbuf,12,0,True);
1895 data = smb_buf(outbuf);
1897 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1898 return(ERROR(ERRDOS,ERRlock));
1899 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1903 return(UNIXERROR(ERRDOS,ERRnoaccess));
1905 SSVAL(outbuf,smb_vwv5,nread);
1906 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1907 SSVAL(smb_buf(outbuf),-2,nread);
1909 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1910 timestring(),fnum,cnum,
1911 smb_mincnt,smb_maxcnt,nread));
1915 return chain_reply(inbuf,outbuf,length,bufsize);
1919 /****************************************************************************
1920 reply to a writebraw (core+ or LANMAN1.0 protocol)
1921 ****************************************************************************/
1922 int reply_writebraw(char *inbuf,char *outbuf)
1925 int total_written=0;
1934 cnum = SVAL(inbuf,smb_tid);
1935 fnum = GETFNUM(inbuf,smb_vwv0);
1937 CHECK_FNUM(fnum,cnum);
1941 tcount = IVAL(inbuf,smb_vwv1);
1942 startpos = IVAL(inbuf,smb_vwv3);
1943 write_through = BITSETW(inbuf+smb_vwv7,0);
1945 /* We have to deal with slightly different formats depending
1946 on whether we are using the core+ or lanman1.0 protocol */
1947 if(Protocol <= PROTOCOL_COREPLUS) {
1948 numtowrite = SVAL(smb_buf(inbuf),-2);
1949 data = smb_buf(inbuf);
1951 numtowrite = SVAL(inbuf,smb_vwv10);
1952 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1955 /* force the error type */
1956 CVAL(inbuf,smb_com) = SMBwritec;
1957 CVAL(outbuf,smb_com) = SMBwritec;
1959 if (is_locked(fnum,cnum,tcount,startpos))
1960 return(ERROR(ERRDOS,ERRlock));
1962 if (seek_file(fnum,startpos) != startpos)
1963 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1966 nwritten = write_file(fnum,data,numtowrite);
1968 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1969 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1971 if (nwritten < numtowrite)
1972 return(UNIXERROR(ERRHRD,ERRdiskfull));
1974 total_written = nwritten;
1976 /* Return a message to the redirector to tell it
1977 to send more bytes */
1978 CVAL(outbuf,smb_com) = SMBwritebraw;
1979 SSVALS(outbuf,smb_vwv0,-1);
1980 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1981 send_smb(Client,outbuf);
1983 /* Now read the raw data into the buffer and write it */
1984 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1985 exit_server("secondary writebraw failed");
1988 /* Even though this is not an smb message, smb_len
1989 returns the generic length of an smb message */
1990 numtowrite = smb_len(inbuf);
1992 if (tcount > nwritten+numtowrite) {
1993 DEBUG(3,("Client overestimated the write %d %d %d\n",
1994 tcount,nwritten,numtowrite));
1997 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1999 total_written += nwritten;
2001 /* Set up outbuf to return the correct return */
2002 outsize = set_message(outbuf,1,0,True);
2003 CVAL(outbuf,smb_com) = SMBwritec;
2004 SSVAL(outbuf,smb_vwv0,total_written);
2006 if (nwritten < numtowrite) {
2007 CVAL(outbuf,smb_rcls) = ERRHRD;
2008 SSVAL(outbuf,smb_err,ERRdiskfull);
2011 if (lp_syncalways(SNUM(cnum)) || write_through)
2014 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
2015 timestring(),fnum,cnum,startpos,numtowrite,total_written));
2017 /* we won't return a status if write through is not selected - this
2018 follows what WfWg does */
2019 if (!write_through && total_written==tcount)
2026 /****************************************************************************
2027 reply to a writeunlock (core+)
2028 ****************************************************************************/
2029 int reply_writeunlock(char *inbuf,char *outbuf)
2035 uint32 numtowrite,startpos;
2039 cnum = SVAL(inbuf,smb_tid);
2040 fnum = GETFNUM(inbuf,smb_vwv0);
2042 CHECK_FNUM(fnum,cnum);
2046 numtowrite = SVAL(inbuf,smb_vwv1);
2047 startpos = IVAL(inbuf,smb_vwv2);
2048 data = smb_buf(inbuf) + 3;
2050 if (is_locked(fnum,cnum,numtowrite,startpos))
2051 return(ERROR(ERRDOS,ERRlock));
2053 seek_file(fnum,startpos);
2055 /* The special X/Open SMB protocol handling of
2056 zero length writes is *NOT* done for
2061 nwritten = write_file(fnum,data,numtowrite);
2063 if (lp_syncalways(SNUM(cnum)))
2066 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2067 return(UNIXERROR(ERRDOS,ERRnoaccess));
2069 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2070 return(ERROR(eclass,ecode));
2072 outsize = set_message(outbuf,1,0,True);
2074 SSVAL(outbuf,smb_vwv0,nwritten);
2076 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2077 timestring(),fnum,cnum,numtowrite,nwritten));
2083 /****************************************************************************
2085 ****************************************************************************/
2086 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
2088 int cnum,numtowrite,fnum;
2097 cnum = SVAL(inbuf,smb_tid);
2098 fnum = GETFNUM(inbuf,smb_vwv0);
2100 CHECK_FNUM(fnum,cnum);
2104 numtowrite = SVAL(inbuf,smb_vwv1);
2105 startpos = IVAL(inbuf,smb_vwv2);
2106 data = smb_buf(inbuf) + 3;
2108 if (is_locked(fnum,cnum,numtowrite,startpos))
2109 return(ERROR(ERRDOS,ERRlock));
2111 seek_file(fnum,startpos);
2113 /* X/Open SMB protocol says that if smb_vwv1 is
2114 zero then the file size should be extended or
2115 truncated to the size given in smb_vwv[2-3] */
2117 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2119 nwritten = write_file(fnum,data,numtowrite);
2121 if (lp_syncalways(SNUM(cnum)))
2124 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2125 return(UNIXERROR(ERRDOS,ERRnoaccess));
2127 outsize = set_message(outbuf,1,0,True);
2129 SSVAL(outbuf,smb_vwv0,nwritten);
2131 if (nwritten < numtowrite) {
2132 CVAL(outbuf,smb_rcls) = ERRHRD;
2133 SSVAL(outbuf,smb_err,ERRdiskfull);
2136 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2142 /****************************************************************************
2143 reply to a write and X
2144 ****************************************************************************/
2145 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2147 int fnum = GETFNUM(inbuf,smb_vwv2);
2148 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2149 int smb_dsize = SVAL(inbuf,smb_vwv10);
2150 int smb_doff = SVAL(inbuf,smb_vwv11);
2151 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2156 cnum = SVAL(inbuf,smb_tid);
2158 CHECK_FNUM(fnum,cnum);
2162 data = smb_base(inbuf) + smb_doff;
2164 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2165 return(ERROR(ERRDOS,ERRlock));
2167 seek_file(fnum,smb_offs);
2169 /* X/Open SMB protocol says that, unlike SMBwrite
2170 if the length is zero then NO truncation is
2171 done, just a write of zero. To truncate a file,
2176 nwritten = write_file(fnum,data,smb_dsize);
2178 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2179 return(UNIXERROR(ERRDOS,ERRnoaccess));
2181 set_message(outbuf,6,0,True);
2183 SSVAL(outbuf,smb_vwv2,nwritten);
2185 if (nwritten < smb_dsize) {
2186 CVAL(outbuf,smb_rcls) = ERRHRD;
2187 SSVAL(outbuf,smb_err,ERRdiskfull);
2190 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2194 if (lp_syncalways(SNUM(cnum)) || write_through)
2197 return chain_reply(inbuf,outbuf,length,bufsize);
2201 /****************************************************************************
2203 ****************************************************************************/
2204 int reply_lseek(char *inbuf,char *outbuf)
2212 cnum = SVAL(inbuf,smb_tid);
2213 fnum = GETFNUM(inbuf,smb_vwv0);
2215 CHECK_FNUM(fnum,cnum);
2218 mode = SVAL(inbuf,smb_vwv1) & 3;
2219 startpos = IVAL(inbuf,smb_vwv2);
2223 case 0: umode = SEEK_SET; break;
2224 case 1: umode = SEEK_CUR; break;
2225 case 2: umode = SEEK_END; break;
2227 umode = SEEK_SET; break;
2230 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2231 Files[fnum].pos = res;
2233 outsize = set_message(outbuf,2,0,True);
2234 SIVALS(outbuf,smb_vwv0,res);
2236 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2242 /****************************************************************************
2244 ****************************************************************************/
2245 int reply_flush(char *inbuf,char *outbuf)
2248 int outsize = set_message(outbuf,0,0,True);
2250 cnum = SVAL(inbuf,smb_tid);
2251 fnum = GETFNUM(inbuf,smb_vwv0);
2253 if (fnum != 0xFFFF) {
2254 CHECK_FNUM(fnum,cnum);
2261 for (i=0;i<MAX_OPEN_FILES;i++)
2268 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2273 /****************************************************************************
2275 ****************************************************************************/
2276 int reply_exit(char *inbuf,char *outbuf)
2278 int outsize = set_message(outbuf,0,0,True);
2279 DEBUG(3,("%s exit\n",timestring()));
2285 /****************************************************************************
2287 ****************************************************************************/
2288 int reply_close(char *inbuf,char *outbuf)
2293 int32 eclass = 0, err = 0;
2295 outsize = set_message(outbuf,0,0,True);
2297 cnum = SVAL(inbuf,smb_tid);
2299 /* If it's an IPC, pass off to the pipe handler. */
2301 return reply_pipe_close(inbuf,outbuf);
2303 fnum = GETFNUM(inbuf,smb_vwv0);
2305 CHECK_FNUM(fnum,cnum);
2307 if(HAS_CACHED_ERROR(fnum)) {
2308 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2309 err = Files[fnum].wbmpx_ptr->wr_error;
2312 mtime = make_unix_date3(inbuf+smb_vwv1);
2314 /* try and set the date */
2315 set_filetime(cnum, Files[fnum].name,mtime);
2317 close_file(fnum,True);
2319 /* We have a cached error */
2321 return(ERROR(eclass,err));
2323 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2324 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2325 Connections[cnum].num_files_open));
2331 /****************************************************************************
2332 reply to a writeclose (Core+ protocol)
2333 ****************************************************************************/
2334 int reply_writeclose(char *inbuf,char *outbuf)
2336 int cnum,numtowrite,fnum;
2343 cnum = SVAL(inbuf,smb_tid);
2344 fnum = GETFNUM(inbuf,smb_vwv0);
2346 CHECK_FNUM(fnum,cnum);
2350 numtowrite = SVAL(inbuf,smb_vwv1);
2351 startpos = IVAL(inbuf,smb_vwv2);
2352 mtime = make_unix_date3(inbuf+smb_vwv4);
2353 data = smb_buf(inbuf) + 1;
2355 if (is_locked(fnum,cnum,numtowrite,startpos))
2356 return(ERROR(ERRDOS,ERRlock));
2358 seek_file(fnum,startpos);
2360 nwritten = write_file(fnum,data,numtowrite);
2362 set_filetime(cnum, Files[fnum].name,mtime);
2364 close_file(fnum,True);
2366 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2367 timestring(),fnum,cnum,numtowrite,nwritten,
2368 Connections[cnum].num_files_open));
2371 return(UNIXERROR(ERRDOS,ERRnoaccess));
2373 outsize = set_message(outbuf,1,0,True);
2375 SSVAL(outbuf,smb_vwv0,nwritten);
2380 /****************************************************************************
2382 ****************************************************************************/
2383 int reply_lock(char *inbuf,char *outbuf)
2386 int outsize = set_message(outbuf,0,0,True);
2387 uint32 count,offset;
2391 cnum = SVAL(inbuf,smb_tid);
2392 fnum = GETFNUM(inbuf,smb_vwv0);
2394 CHECK_FNUM(fnum,cnum);
2397 count = IVAL(inbuf,smb_vwv1);
2398 offset = IVAL(inbuf,smb_vwv3);
2400 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));
2402 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2403 return (ERROR(eclass,ecode));
2409 /****************************************************************************
2411 ****************************************************************************/
2412 int reply_unlock(char *inbuf,char *outbuf)
2415 int outsize = set_message(outbuf,0,0,True);
2416 uint32 count,offset;
2420 cnum = SVAL(inbuf,smb_tid);
2421 fnum = GETFNUM(inbuf,smb_vwv0);
2423 CHECK_FNUM(fnum,cnum);
2426 count = IVAL(inbuf,smb_vwv1);
2427 offset = IVAL(inbuf,smb_vwv3);
2429 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2430 return (ERROR(eclass,ecode));
2432 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));
2438 /****************************************************************************
2440 ****************************************************************************/
2441 int reply_tdis(char *inbuf,char *outbuf)
2444 int outsize = set_message(outbuf,0,0,True);
2447 cnum = SVAL(inbuf,smb_tid);
2448 vuid = SVAL(inbuf,smb_uid);
2450 if (!OPEN_CNUM(cnum)) {
2451 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2452 return(ERROR(ERRSRV,ERRinvnid));
2455 Connections[cnum].used = False;
2457 close_cnum(cnum,vuid);
2459 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2466 /****************************************************************************
2468 ****************************************************************************/
2469 int reply_echo(char *inbuf,char *outbuf)
2472 int smb_reverb = SVAL(inbuf,smb_vwv0);
2474 int data_len = smb_buflen(inbuf);
2475 int outsize = set_message(outbuf,1,data_len,True);
2477 cnum = SVAL(inbuf,smb_tid);
2479 /* According to the latest CIFS spec we shouldn't
2480 care what the TID is.
2484 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2486 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2487 return(ERROR(ERRSRV,ERRinvnid));
2491 /* copy any incoming data back out */
2493 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2495 if (smb_reverb > 100)
2497 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2501 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2503 SSVAL(outbuf,smb_vwv0,seq_num);
2505 smb_setlen(outbuf,outsize - 4);
2507 send_smb(Client,outbuf);
2510 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2516 /****************************************************************************
2517 reply to a printopen
2518 ****************************************************************************/
2519 int reply_printopen(char *inbuf,char *outbuf)
2527 *fname = *fname2 = 0;
2529 cnum = SVAL(inbuf,smb_tid);
2531 if (!CAN_PRINT(cnum))
2532 return(ERROR(ERRDOS,ERRnoaccess));
2537 pstrcpy(s,smb_buf(inbuf)+1);
2541 if (!(isalnum(*p) || strchr("._-",*p)))
2546 if (strlen(s) > 10) s[10] = 0;
2548 sprintf(fname,"%s.XXXXXX",s);
2551 fnum = find_free_file();
2553 return(ERROR(ERRSRV,ERRnofids));
2555 strcpy(fname2,(char *)mktemp(fname));
2557 if (!check_name(fname2,cnum))
2558 return(ERROR(ERRDOS,ERRnoaccess));
2560 /* Open for exclusive use, write only. */
2561 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2564 if (!Files[fnum].open)
2565 return(UNIXERROR(ERRDOS,ERRnoaccess));
2567 /* force it to be a print file */
2568 Files[fnum].print_file = True;
2570 outsize = set_message(outbuf,1,0,True);
2571 SSVAL(outbuf,smb_vwv0,fnum);
2573 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2579 /****************************************************************************
2580 reply to a printclose
2581 ****************************************************************************/
2582 int reply_printclose(char *inbuf,char *outbuf)
2585 int outsize = set_message(outbuf,0,0,True);
2587 cnum = SVAL(inbuf,smb_tid);
2588 fnum = GETFNUM(inbuf,smb_vwv0);
2590 CHECK_FNUM(fnum,cnum);
2593 if (!CAN_PRINT(cnum))
2594 return(ERROR(ERRDOS,ERRnoaccess));
2596 close_file(fnum,True);
2598 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2604 /****************************************************************************
2605 reply to a printqueue
2606 ****************************************************************************/
2607 int reply_printqueue(char *inbuf,char *outbuf)
2610 int outsize = set_message(outbuf,2,3,True);
2611 int max_count = SVAL(inbuf,smb_vwv0);
2612 int start_index = SVAL(inbuf,smb_vwv1);
2615 cnum = SVAL(inbuf,smb_tid);
2616 vuid = SVAL(inbuf,smb_uid);
2618 /* allow checking the queue for anyone */
2620 if (!CAN_PRINT(cnum))
2621 return(ERROR(ERRDOS,ERRnoaccess));
2624 SSVAL(outbuf,smb_vwv0,0);
2625 SSVAL(outbuf,smb_vwv1,0);
2626 CVAL(smb_buf(outbuf),0) = 1;
2627 SSVAL(smb_buf(outbuf),1,0);
2629 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2630 timestring(),cnum,start_index,max_count));
2632 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2637 for (i=0;i<MAX_CONNECTIONS;i++)
2638 if (CAN_PRINT(i) && Connections[i].printer)
2642 for (i=0;i<MAX_CONNECTIONS;i++)
2646 if (!OPEN_CNUM(cnum))
2647 return(ERROR(ERRSRV,ERRinvnid));
2649 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2652 if (!become_user(&Connections[cnum], cnum, vuid))
2653 return(ERROR(ERRSRV,ERRinvnid));
2656 print_queue_struct *queue = NULL;
2657 char *p = smb_buf(outbuf) + 3;
2658 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2659 int num_to_get = ABS(max_count);
2660 int first = (max_count>0?start_index:start_index+max_count+1);
2666 num_to_get = MIN(num_to_get,count-first);
2669 for (i=first;i<first+num_to_get;i++)
2671 put_dos_date2(p,0,queue[i].time);
2672 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2673 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2674 SIVAL(p,7,queue[i].size);
2676 StrnCpy(p+12,queue[i].user,16);
2682 outsize = set_message(outbuf,2,28*count+3,False);
2683 SSVAL(outbuf,smb_vwv0,count);
2684 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2685 CVAL(smb_buf(outbuf),0) = 1;
2686 SSVAL(smb_buf(outbuf),1,28*count);
2689 if (queue) free(queue);
2691 DEBUG(3,("%d entries returned in queue\n",count));
2698 /****************************************************************************
2699 reply to a printwrite
2700 ****************************************************************************/
2701 int reply_printwrite(char *inbuf,char *outbuf)
2703 int cnum,numtowrite,fnum;
2704 int outsize = set_message(outbuf,0,0,True);
2707 cnum = SVAL(inbuf,smb_tid);
2709 if (!CAN_PRINT(cnum))
2710 return(ERROR(ERRDOS,ERRnoaccess));
2712 fnum = GETFNUM(inbuf,smb_vwv0);
2714 CHECK_FNUM(fnum,cnum);
2718 numtowrite = SVAL(smb_buf(inbuf),1);
2719 data = smb_buf(inbuf) + 3;
2721 if (write_file(fnum,data,numtowrite) != numtowrite)
2722 return(UNIXERROR(ERRDOS,ERRnoaccess));
2724 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2730 /****************************************************************************
2732 ****************************************************************************/
2733 int reply_mkdir(char *inbuf,char *outbuf)
2737 int outsize,ret= -1;
2738 BOOL bad_path = False;
2740 pstrcpy(directory,smb_buf(inbuf) + 1);
2741 cnum = SVAL(inbuf,smb_tid);
2742 unix_convert(directory,cnum,0,&bad_path);
2744 if (check_name(directory,cnum))
2745 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2749 if((errno == ENOENT) && bad_path)
2751 unix_ERR_class = ERRDOS;
2752 unix_ERR_code = ERRbadpath;
2754 return(UNIXERROR(ERRDOS,ERRnoaccess));
2757 outsize = set_message(outbuf,0,0,True);
2759 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2764 /****************************************************************************
2765 Static function used by reply_rmdir to delete an entire directory
2767 ****************************************************************************/
2768 static BOOL recursive_rmdir(char *directory)
2772 void *dirptr = OpenDir(-1, directory, False);
2777 while((dname = ReadDirName(dirptr)))
2782 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2785 /* Construct the full name. */
2786 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2792 strcpy(fullname, directory);
2793 strcat(fullname, "/");
2794 strcat(fullname, dname);
2796 if(sys_lstat(fullname, &st) != 0)
2802 if(st.st_mode & S_IFDIR)
2804 if(recursive_rmdir(fullname)!=0)
2809 if(sys_rmdir(fullname) != 0)
2815 else if(sys_unlink(fullname) != 0)
2825 /****************************************************************************
2827 ****************************************************************************/
2828 int reply_rmdir(char *inbuf,char *outbuf)
2834 BOOL bad_path = False;
2836 cnum = SVAL(inbuf,smb_tid);
2837 pstrcpy(directory,smb_buf(inbuf) + 1);
2838 unix_convert(directory,cnum,0,&bad_path);
2840 if (check_name(directory,cnum))
2843 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2844 ok = (sys_rmdir(directory) == 0);
2845 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2847 /* Check to see if the only thing in this directory are
2848 vetoed files/directories. If so then delete them and
2849 retry. If we fail to delete any of them (and we *don't*
2850 do a recursive delete) then fail the rmdir. */
2851 BOOL all_veto_files = True;
2853 void *dirptr = OpenDir(cnum, directory, False);
2857 int dirpos = TellDir(dirptr);
2858 while ((dname = ReadDirName(dirptr)))
2860 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2862 if(!IS_VETO_PATH(cnum, dname))
2864 all_veto_files = False;
2870 SeekDir(dirptr,dirpos);
2871 while ((dname = ReadDirName(dirptr)))
2876 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2879 /* Construct the full name. */
2880 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2885 pstrcpy(fullname, directory);
2886 strcat(fullname, "/");
2887 strcat(fullname, dname);
2889 if(sys_lstat(fullname, &st) != 0)
2891 if(st.st_mode & S_IFDIR)
2893 if(lp_recursive_veto_delete(SNUM(cnum)))
2895 if(recursive_rmdir(fullname) != 0)
2898 if(sys_rmdir(fullname) != 0)
2901 else if(sys_unlink(fullname) != 0)
2905 /* Retry the rmdir */
2906 ok = (sys_rmdir(directory) == 0);
2916 DEBUG(3,("couldn't remove directory %s : %s\n",
2917 directory,strerror(errno)));
2922 if((errno == ENOENT) && bad_path)
2924 unix_ERR_class = ERRDOS;
2925 unix_ERR_code = ERRbadpath;
2927 return(UNIXERROR(ERRDOS,ERRbadpath));
2930 outsize = set_message(outbuf,0,0,True);
2932 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2938 /*******************************************************************
2939 resolve wildcards in a filename rename
2940 ********************************************************************/
2941 static BOOL resolve_wildcards(char *name1,char *name2)
2943 fstring root1,root2;
2947 name1 = strrchr(name1,'/');
2948 name2 = strrchr(name2,'/');
2950 if (!name1 || !name2) return(False);
2952 fstrcpy(root1,name1);
2953 fstrcpy(root2,name2);
2954 p = strrchr(root1,'.');
2961 p = strrchr(root2,'.');
2993 strcpy(name2,root2);
3002 /*******************************************************************
3003 check if a user is allowed to rename a file
3004 ********************************************************************/
3005 static BOOL can_rename(char *fname,int cnum)
3009 if (!CAN_WRITE(cnum)) return(False);
3011 if (sys_lstat(fname,&sbuf) != 0) return(False);
3012 if (!check_file_sharing(cnum,fname)) return(False);
3017 /****************************************************************************
3019 ****************************************************************************/
3020 int reply_mv(char *inbuf,char *outbuf)
3026 pstring mask,newname;
3027 pstring newname_last_component;
3030 int error = ERRnoaccess;
3033 BOOL bad_path1 = False;
3034 BOOL bad_path2 = False;
3036 *directory = *mask = 0;
3038 cnum = SVAL(inbuf,smb_tid);
3040 pstrcpy(name,smb_buf(inbuf) + 1);
3041 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3043 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3045 unix_convert(name,cnum,0,&bad_path1);
3046 unix_convert(newname,cnum,newname_last_component,&bad_path2);
3049 * Split the old name into directory and last component
3050 * strings. Note that unix_convert may have stripped off a
3051 * leading ./ from both name and newname if the rename is
3052 * at the root of the share. We need to make sure either both
3053 * name and newname contain a / character or neither of them do
3054 * as this is checked in resolve_wildcards().
3057 p = strrchr(name,'/');
3059 strcpy(directory,".");
3063 strcpy(directory,name);
3065 *p = '/'; /* Replace needed for exceptional test below. */
3068 if (is_mangled(mask))
3069 check_mangled_stack(mask);
3071 has_wild = strchr(mask,'*') || strchr(mask,'?');
3074 BOOL is_short_name = is_8_3(name, True);
3076 /* Add a terminating '/' to the directory name. */
3077 strcat(directory,"/");
3078 strcat(directory,mask);
3080 /* Ensure newname contains a '/' also */
3081 if(strrchr(newname,'/') == 0) {
3084 strcpy(tmpstr, "./");
3085 strcat(tmpstr, newname);
3086 strcpy(newname, tmpstr);
3089 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",
3090 case_sensitive, case_preserve, short_case_preserve, directory,
3091 newname, newname_last_component, is_short_name));
3094 * Check for special case with case preserving and not
3095 * case sensitive, if directory and newname are identical,
3096 * and the old last component differs from the original
3097 * last component only by case, then we should allow
3098 * the rename (user is trying to change the case of the
3101 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3102 ((short_case_preserve == True) && (is_short_name == True))) &&
3103 strcsequal(directory, newname)) {
3104 pstring newname_modified_last_component;
3107 * Get the last component of the modified name.
3108 * Note that we guarantee that newname contains a '/'
3111 p = strrchr(newname,'/');
3112 strcpy(newname_modified_last_component,p+1);
3114 if(strcsequal(newname_modified_last_component,
3115 newname_last_component) == False) {
3117 * Replace the modified last component with
3120 strcpy(p+1, newname_last_component);
3124 if (resolve_wildcards(directory,newname) &&
3125 can_rename(directory,cnum) &&
3126 !file_exist(newname,NULL) &&
3127 !sys_rename(directory,newname)) count++;
3129 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3130 directory,newname));
3132 if (!count) exists = file_exist(directory,NULL);
3133 if (!count && exists && file_exist(newname,NULL)) {
3138 void *dirptr = NULL;
3142 if (check_name(directory,cnum))
3143 dirptr = OpenDir(cnum, directory, True);
3149 if (strequal(mask,"????????.???"))
3152 while ((dname = ReadDirName(dirptr)))
3155 pstrcpy(fname,dname);
3157 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3159 error = ERRnoaccess;
3160 sprintf(fname,"%s/%s",directory,dname);
3161 if (!can_rename(fname,cnum)) continue;
3162 pstrcpy(destname,newname);
3164 if (!resolve_wildcards(fname,destname)) continue;
3166 if (file_exist(destname,NULL)) {
3170 if (!sys_rename(fname,destname)) count++;
3171 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3179 return(ERROR(ERRDOS,error));
3182 if((errno == ENOENT) && (bad_path1 || bad_path2))
3184 unix_ERR_class = ERRDOS;
3185 unix_ERR_code = ERRbadpath;
3187 return(UNIXERROR(ERRDOS,error));
3191 outsize = set_message(outbuf,0,0,True);
3196 /*******************************************************************
3197 copy a file as part of a reply_copy
3198 ******************************************************************/
3199 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3200 int count,BOOL target_is_directory)
3208 pstrcpy(dest,dest1);
3209 if (target_is_directory) {
3210 char *p = strrchr(src,'/');
3219 if (!file_exist(src,&st)) return(False);
3221 fnum1 = find_free_file();
3222 if (fnum1<0) return(False);
3223 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3224 1,0,0,&Access,&action);
3226 if (!Files[fnum1].open) return(False);
3228 if (!target_is_directory && count)
3231 fnum2 = find_free_file();
3233 close_file(fnum1,False);
3236 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3237 ofun,st.st_mode,0,&Access,&action);
3239 if (!Files[fnum2].open) {
3240 close_file(fnum1,False);
3244 if ((ofun&3) == 1) {
3245 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3249 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3251 close_file(fnum1,False);
3252 close_file(fnum2,False);
3254 return(ret == st.st_size);
3259 /****************************************************************************
3260 reply to a file copy.
3261 ****************************************************************************/
3262 int reply_copy(char *inbuf,char *outbuf)
3268 pstring mask,newname;
3271 int error = ERRnoaccess;
3274 int tid2 = SVAL(inbuf,smb_vwv0);
3275 int ofun = SVAL(inbuf,smb_vwv1);
3276 int flags = SVAL(inbuf,smb_vwv2);
3277 BOOL target_is_directory=False;
3278 BOOL bad_path1 = False;
3279 BOOL bad_path2 = False;
3281 *directory = *mask = 0;
3283 cnum = SVAL(inbuf,smb_tid);
3285 pstrcpy(name,smb_buf(inbuf));
3286 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3288 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3291 /* can't currently handle inter share copies XXXX */
3292 DEBUG(3,("Rejecting inter-share copy\n"));
3293 return(ERROR(ERRSRV,ERRinvdevice));
3296 unix_convert(name,cnum,0,&bad_path1);
3297 unix_convert(newname,cnum,0,&bad_path2);
3299 target_is_directory = directory_exist(newname,NULL);
3301 if ((flags&1) && target_is_directory) {
3302 return(ERROR(ERRDOS,ERRbadfile));
3305 if ((flags&2) && !target_is_directory) {
3306 return(ERROR(ERRDOS,ERRbadpath));
3309 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3310 /* wants a tree copy! XXXX */
3311 DEBUG(3,("Rejecting tree copy\n"));
3312 return(ERROR(ERRSRV,ERRerror));
3315 p = strrchr(name,'/');
3317 strcpy(directory,"./");
3321 strcpy(directory,name);
3325 if (is_mangled(mask))
3326 check_mangled_stack(mask);
3328 has_wild = strchr(mask,'*') || strchr(mask,'?');
3331 strcat(directory,"/");
3332 strcat(directory,mask);
3333 if (resolve_wildcards(directory,newname) &&
3334 copy_file(directory,newname,cnum,ofun,
3335 count,target_is_directory)) count++;
3336 if (!count) exists = file_exist(directory,NULL);
3338 void *dirptr = NULL;
3342 if (check_name(directory,cnum))
3343 dirptr = OpenDir(cnum, directory, True);
3349 if (strequal(mask,"????????.???"))
3352 while ((dname = ReadDirName(dirptr)))
3355 pstrcpy(fname,dname);
3357 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3359 error = ERRnoaccess;
3360 sprintf(fname,"%s/%s",directory,dname);
3361 strcpy(destname,newname);
3362 if (resolve_wildcards(fname,destname) &&
3363 copy_file(directory,newname,cnum,ofun,
3364 count,target_is_directory)) count++;
3365 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3373 return(ERROR(ERRDOS,error));
3376 if((errno == ENOENT) && (bad_path1 || bad_path2))
3378 unix_ERR_class = ERRDOS;
3379 unix_ERR_code = ERRbadpath;
3381 return(UNIXERROR(ERRDOS,error));
3385 outsize = set_message(outbuf,1,0,True);
3386 SSVAL(outbuf,smb_vwv0,count);
3393 /****************************************************************************
3395 ****************************************************************************/
3396 int reply_setdir(char *inbuf,char *outbuf)
3403 cnum = SVAL(inbuf,smb_tid);
3405 snum = Connections[cnum].service;
3406 if (!CAN_SETDIR(snum))
3407 return(ERROR(ERRDOS,ERRnoaccess));
3409 pstrcpy(newdir,smb_buf(inbuf) + 1);
3412 if (strlen(newdir) == 0)
3416 ok = directory_exist(newdir,NULL);
3418 string_set(&Connections[cnum].connectpath,newdir);
3422 return(ERROR(ERRDOS,ERRbadpath));
3424 outsize = set_message(outbuf,0,0,True);
3425 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3427 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3433 /****************************************************************************
3434 reply to a lockingX request
3435 ****************************************************************************/
3436 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3438 int fnum = GETFNUM(inbuf,smb_vwv2);
3439 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3441 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3443 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3444 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3445 uint32 count, offset;
3450 uint32 ecode=0, dummy2;
3451 int eclass=0, dummy1;
3453 cnum = SVAL(inbuf,smb_tid);
3455 CHECK_FNUM(fnum,cnum);
3458 data = smb_buf(inbuf);
3460 /* Check if this is an oplock break on a file
3461 we have granted an oplock on.
3463 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3466 files_struct *fsp = &Files[fnum];
3467 uint32 dev = fsp->fd_ptr->dev;
3468 uint32 inode = fsp->fd_ptr->inode;
3470 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3473 * Make sure we have granted an oplock on this file.
3475 if(!fsp->granted_oplock)
3477 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3478 no oplock granted on this file.\n", fnum));
3479 return ERROR(ERRDOS,ERRlock);
3482 /* Remove the oplock flag from the sharemode. */
3483 lock_share_entry(fsp->cnum, dev, inode, &token);
3484 if(remove_share_oplock( fnum, token)==False) {
3485 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3486 dev = %x, inode = %x\n",
3488 unlock_share_entry(fsp->cnum, dev, inode, token);
3490 unlock_share_entry(fsp->cnum, dev, inode, token);
3492 /* Clear the granted flag and return. */
3493 fsp->granted_oplock = False;
3496 /* if this is a pure oplock break request then don't send a reply */
3497 if (num_locks == 0 && num_ulocks == 0)
3499 /* Sanity check - ensure a pure oplock break is not a
3501 if(CVAL(inbuf,smb_vwv0) != 0xff)
3502 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3503 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3508 /* Data now points at the beginning of the list
3509 of smb_unlkrng structs */
3510 for(i = 0; i < (int)num_ulocks; i++) {
3511 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3512 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3513 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3514 return ERROR(eclass,ecode);
3517 /* Now do any requested locks */
3518 data += 10*num_ulocks;
3519 /* Data now points at the beginning of the list
3520 of smb_lkrng structs */
3521 for(i = 0; i < (int)num_locks; i++) {
3522 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3523 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3524 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3528 /* If any of the above locks failed, then we must unlock
3529 all of the previous locks (X/Open spec). */
3530 if(i != num_locks && num_locks != 0) {
3531 for(; i >= 0; i--) {
3532 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3533 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3534 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3536 return ERROR(eclass,ecode);
3539 set_message(outbuf,2,0,True);
3541 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3542 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3546 return chain_reply(inbuf,outbuf,length,bufsize);
3550 /****************************************************************************
3551 reply to a SMBreadbmpx (read block multiplex) request
3552 ****************************************************************************/
3553 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3560 int outsize, mincount, maxcount;
3565 /* this function doesn't seem to work - disable by default */
3567 return(ERROR(ERRSRV,ERRuseSTD));
3569 outsize = set_message(outbuf,8,0,True);
3571 cnum = SVAL(inbuf,smb_tid);
3572 fnum = GETFNUM(inbuf,smb_vwv0);
3574 CHECK_FNUM(fnum,cnum);
3578 startpos = IVAL(inbuf,smb_vwv1);
3579 maxcount = SVAL(inbuf,smb_vwv3);
3580 mincount = SVAL(inbuf,smb_vwv4);
3582 data = smb_buf(outbuf);
3583 pad = ((long)data)%4;
3584 if (pad) pad = 4 - pad;
3587 max_per_packet = bufsize-(outsize+pad);
3591 if (is_locked(fnum,cnum,maxcount,startpos))
3592 return(ERROR(ERRDOS,ERRlock));
3596 int N = MIN(max_per_packet,tcount-total_read);
3598 nread = read_file(fnum,data,startpos,N);
3600 if (nread <= 0) nread = 0;
3603 tcount = total_read + nread;
3605 set_message(outbuf,8,nread,False);
3606 SIVAL(outbuf,smb_vwv0,startpos);
3607 SSVAL(outbuf,smb_vwv2,tcount);
3608 SSVAL(outbuf,smb_vwv6,nread);
3609 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3611 send_smb(Client,outbuf);
3613 total_read += nread;
3616 while (total_read < tcount);
3622 /****************************************************************************
3623 reply to a SMBwritebmpx (write block multiplex primary) request
3624 ****************************************************************************/
3625 int reply_writebmpx(char *inbuf,char *outbuf)
3627 int cnum,numtowrite,fnum;
3631 int tcount, write_through, smb_doff;
3634 cnum = SVAL(inbuf,smb_tid);
3635 fnum = GETFNUM(inbuf,smb_vwv0);
3637 CHECK_FNUM(fnum,cnum);
3641 tcount = SVAL(inbuf,smb_vwv1);
3642 startpos = IVAL(inbuf,smb_vwv3);
3643 write_through = BITSETW(inbuf+smb_vwv7,0);
3644 numtowrite = SVAL(inbuf,smb_vwv10);
3645 smb_doff = SVAL(inbuf,smb_vwv11);
3647 data = smb_base(inbuf) + smb_doff;
3649 /* If this fails we need to send an SMBwriteC response,
3650 not an SMBwritebmpx - set this up now so we don't forget */
3651 CVAL(outbuf,smb_com) = SMBwritec;
3653 if (is_locked(fnum,cnum,tcount,startpos))
3654 return(ERROR(ERRDOS,ERRlock));
3656 seek_file(fnum,startpos);
3657 nwritten = write_file(fnum,data,numtowrite);
3659 if(lp_syncalways(SNUM(cnum)) || write_through)
3662 if(nwritten < numtowrite)
3663 return(UNIXERROR(ERRHRD,ERRdiskfull));
3665 /* If the maximum to be written to this file
3666 is greater than what we just wrote then set
3667 up a secondary struct to be attached to this
3668 fd, we will use this to cache error messages etc. */
3669 if(tcount > nwritten)
3671 write_bmpx_struct *wbms;
3672 if(Files[fnum].wbmpx_ptr != NULL)
3673 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3675 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3678 DEBUG(0,("Out of memory in reply_readmpx\n"));
3679 return(ERROR(ERRSRV,ERRnoresource));
3681 wbms->wr_mode = write_through;
3682 wbms->wr_discard = False; /* No errors yet */
3683 wbms->wr_total_written = nwritten;
3684 wbms->wr_errclass = 0;
3686 Files[fnum].wbmpx_ptr = wbms;
3689 /* We are returning successfully, set the message type back to
3691 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3693 outsize = set_message(outbuf,1,0,True);
3695 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3697 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3698 timestring(),fnum,cnum,numtowrite,nwritten));
3700 if (write_through && tcount==nwritten) {
3701 /* we need to send both a primary and a secondary response */
3702 smb_setlen(outbuf,outsize - 4);
3703 send_smb(Client,outbuf);
3705 /* now the secondary */
3706 outsize = set_message(outbuf,1,0,True);
3707 CVAL(outbuf,smb_com) = SMBwritec;
3708 SSVAL(outbuf,smb_vwv0,nwritten);
3715 /****************************************************************************
3716 reply to a SMBwritebs (write block multiplex secondary) request
3717 ****************************************************************************/
3718 int reply_writebs(char *inbuf,char *outbuf)
3720 int cnum,numtowrite,fnum;
3724 int tcount, write_through, smb_doff;
3726 write_bmpx_struct *wbms;
3727 BOOL send_response = False;
3729 cnum = SVAL(inbuf,smb_tid);
3730 fnum = GETFNUM(inbuf,smb_vwv0);
3731 CHECK_FNUM(fnum,cnum);
3734 tcount = SVAL(inbuf,smb_vwv1);
3735 startpos = IVAL(inbuf,smb_vwv2);
3736 numtowrite = SVAL(inbuf,smb_vwv6);
3737 smb_doff = SVAL(inbuf,smb_vwv7);
3739 data = smb_base(inbuf) + smb_doff;
3741 /* We need to send an SMBwriteC response, not an SMBwritebs */
3742 CVAL(outbuf,smb_com) = SMBwritec;
3744 /* This fd should have an auxiliary struct attached,
3745 check that it does */
3746 wbms = Files[fnum].wbmpx_ptr;
3747 if(!wbms) return(-1);
3749 /* If write through is set we can return errors, else we must
3751 write_through = wbms->wr_mode;
3753 /* Check for an earlier error */
3754 if(wbms->wr_discard)
3755 return -1; /* Just discard the packet */
3757 seek_file(fnum,startpos);
3758 nwritten = write_file(fnum,data,numtowrite);
3760 if(lp_syncalways(SNUM(cnum)) || write_through)
3763 if (nwritten < numtowrite)
3766 /* We are returning an error - we can delete the aux struct */
3767 if (wbms) free((char *)wbms);
3768 Files[fnum].wbmpx_ptr = NULL;
3769 return(ERROR(ERRHRD,ERRdiskfull));
3771 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3774 /* Increment the total written, if this matches tcount
3775 we can discard the auxiliary struct (hurrah !) and return a writeC */
3776 wbms->wr_total_written += nwritten;
3777 if(wbms->wr_total_written >= tcount)
3779 if (write_through) {
3780 outsize = set_message(outbuf,1,0,True);
3781 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3782 send_response = True;
3786 Files[fnum].wbmpx_ptr = NULL;
3796 /****************************************************************************
3797 reply to a SMBsetattrE
3798 ****************************************************************************/
3799 int reply_setattrE(char *inbuf,char *outbuf)
3802 struct utimbuf unix_times;
3805 outsize = set_message(outbuf,0,0,True);
3807 cnum = SVAL(inbuf,smb_tid);
3808 fnum = GETFNUM(inbuf,smb_vwv0);
3810 CHECK_FNUM(fnum,cnum);
3813 /* Convert the DOS times into unix times. Ignore create
3814 time as UNIX can't set this.
3816 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3817 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3820 * Patch from Ray Frush <frush@engr.colostate.edu>
3821 * Sometimes times are sent as zero - ignore them.
3824 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3826 /* Ignore request */
3827 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3828 not setting timestamps of 0\n",
3829 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3832 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3834 /* set modify time = to access time if modify time was 0 */
3835 unix_times.modtime = unix_times.actime;
3838 /* Set the date on this file */
3839 if(file_utime(cnum, Files[fnum].name, &unix_times))
3840 return(ERROR(ERRDOS,ERRnoaccess));
3842 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3843 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3849 /****************************************************************************
3850 reply to a SMBgetattrE
3851 ****************************************************************************/
3852 int reply_getattrE(char *inbuf,char *outbuf)
3859 outsize = set_message(outbuf,11,0,True);
3861 cnum = SVAL(inbuf,smb_tid);
3862 fnum = GETFNUM(inbuf,smb_vwv0);
3864 CHECK_FNUM(fnum,cnum);
3867 /* Do an fstat on this file */
3868 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3869 return(UNIXERROR(ERRDOS,ERRnoaccess));
3871 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3873 /* Convert the times into dos times. Set create
3874 date to be last modify date as UNIX doesn't save
3876 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3877 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3878 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3881 SIVAL(outbuf,smb_vwv6,0);
3882 SIVAL(outbuf,smb_vwv8,0);
3886 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3887 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3889 SSVAL(outbuf,smb_vwv10, mode);
3891 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));