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;
84 case 0x81: /* session request */
85 CVAL(outbuf,0) = 0x82;
87 if (name_len(inbuf+4) > 50 ||
88 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
89 DEBUG(0,("Invalid name length in session request\n"));
92 name_extract(inbuf,4,name1);
93 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
94 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
97 fstrcpy(remote_machine,name2);
98 remote_machine[15] = 0;
99 trim_string(remote_machine," "," ");
100 strlower(remote_machine);
102 fstrcpy(local_machine,name1);
103 len = strlen(local_machine);
105 name_type = local_machine[15];
106 local_machine[15] = 0;
108 trim_string(local_machine," "," ");
109 strlower(local_machine);
111 if (name_type == 'R') {
112 /* We are being asked for a pathworks session ---
114 CVAL(outbuf, 0) = 0x83;
118 add_session_user(remote_machine);
120 reload_services(True);
125 case 0x89: /* session keepalive request
126 (some old clients produce this?) */
127 CVAL(outbuf,0) = 0x85;
131 case 0x82: /* positive session response */
132 case 0x83: /* negative session response */
133 case 0x84: /* retarget session response */
134 DEBUG(0,("Unexpected session response\n"));
137 case 0x85: /* session keepalive */
142 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",
143 timestring(),msg_type,msg_flags));
149 /*******************************************************************
150 work out what error to give to a failed connection
151 ********************************************************************/
152 static int connection_error(char *inbuf,char *outbuf,int connection_num)
154 switch (connection_num)
157 return(ERROR(ERRSRV,ERRnoresource));
159 return(ERROR(ERRSRV,ERRbaduid));
161 return(ERROR(ERRSRV,ERRinvdevice));
163 return(ERROR(ERRSRV,ERRinvnetname));
165 return(ERROR(ERRSRV,ERRaccess));
167 return(ERROR(ERRDOS,ERRnoipc));
169 return(ERROR(ERRSRV,ERRinvnetname));
171 return(ERROR(ERRSRV,ERRbadpw));
176 /****************************************************************************
177 parse a share descriptor string
178 ****************************************************************************/
179 static void parse_connect(char *p,char *service,char *user,
180 char *password,int *pwlen,char *dev)
184 DEBUG(4,("parsing connect string %s\n",p));
186 p2 = strrchr(p,'\\');
190 fstrcpy(service,p2+1);
195 *pwlen = strlen(password);
202 p = strchr(service,'%');
213 /****************************************************************************
215 ****************************************************************************/
216 int reply_tcon(char *inbuf,char *outbuf)
224 uint16 vuid = SVAL(inbuf,smb_uid);
227 *service = *user = *password = *dev = 0;
229 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
231 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
233 if (connection_num < 0)
234 return(connection_error(inbuf,outbuf,connection_num));
236 outsize = set_message(outbuf,2,0,True);
237 SSVAL(outbuf,smb_vwv0,max_recv);
238 SSVAL(outbuf,smb_vwv1,connection_num);
239 SSVAL(outbuf,smb_tid,connection_num);
241 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
247 /****************************************************************************
248 reply to a tcon and X
249 ****************************************************************************/
250 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
257 uint16 vuid = SVAL(inbuf,smb_uid);
258 int passlen = SVAL(inbuf,smb_vwv3);
260 *service = *user = *password = *devicename = 0;
262 /* we might have to close an old one */
263 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
264 close_cnum(SVAL(inbuf,smb_tid),vuid);
266 if (passlen > MAX_PASS_LEN) {
267 overflow_attack(passlen);
273 memcpy(password,smb_buf(inbuf),passlen);
275 path = smb_buf(inbuf) + passlen;
278 if (strequal(password," "))
280 passlen = strlen(password);
283 fstrcpy(service,path+2);
284 p = strchr(service,'\\');
286 return(ERROR(ERRSRV,ERRinvnetname));
288 fstrcpy(service,p+1);
289 p = strchr(service,'%');
295 StrnCpy(devicename,path + strlen(path) + 1,6);
296 DEBUG(4,("Got device type %s\n",devicename));
299 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
301 if (connection_num < 0)
302 return(connection_error(inbuf,outbuf,connection_num));
304 if (Protocol < PROTOCOL_NT1)
306 set_message(outbuf,2,strlen(devicename)+1,True);
307 strcpy(smb_buf(outbuf),devicename);
311 char *fsname = "SAMBA";
314 set_message(outbuf,3,3,True);
317 strcpy(p,devicename); p = skip_string(p,1); /* device name */
318 strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
320 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
322 SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
325 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
327 /* set the incoming and outgoing tid to the just created one */
328 SSVAL(inbuf,smb_tid,connection_num);
329 SSVAL(outbuf,smb_tid,connection_num);
331 return chain_reply(inbuf,outbuf,length,bufsize);
335 /****************************************************************************
336 reply to an unknown type
337 ****************************************************************************/
338 int reply_unknown(char *inbuf,char *outbuf)
342 cnum = SVAL(inbuf,smb_tid);
343 type = CVAL(inbuf,smb_com);
345 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
350 return(ERROR(ERRSRV,ERRunknownsmb));
354 /****************************************************************************
356 ****************************************************************************/
357 int reply_ioctl(char *inbuf,char *outbuf)
359 DEBUG(3,("ignoring ioctl\n"));
361 /* we just say it succeeds and hope its all OK.
362 some day it would be nice to interpret them individually */
363 return set_message(outbuf,1,0,True);
365 return(ERROR(ERRSRV,ERRnosupport));
370 /****************************************************************************
371 reply to a session setup command
372 ****************************************************************************/
373 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
382 int smb_apasslen = 0;
384 int smb_ntpasslen = 0;
385 pstring smb_ntpasswd;
386 BOOL valid_nt_password = False;
389 BOOL computer_id=False;
390 static BOOL done_sesssetup = False;
391 BOOL doencrypt = SMBENCRYPT();
397 smb_bufsize = SVAL(inbuf,smb_vwv2);
398 smb_mpxmax = SVAL(inbuf,smb_vwv3);
399 smb_vc_num = SVAL(inbuf,smb_vwv4);
400 smb_sesskey = IVAL(inbuf,smb_vwv5);
402 if (Protocol < PROTOCOL_NT1) {
403 smb_apasslen = SVAL(inbuf,smb_vwv7);
404 if (smb_apasslen > MAX_PASS_LEN)
406 overflow_attack(smb_apasslen);
409 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
410 smb_apasswd[smb_apasslen] = 0;
411 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
413 if (!doencrypt && (lp_security() != SEC_SERVER)) {
414 smb_apasslen = strlen(smb_apasswd);
417 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
418 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
419 uint32 client_caps = IVAL(inbuf,smb_vwv11);
420 enum remote_arch_types ra_type = get_remote_arch();
422 char *p = smb_buf(inbuf);
424 /* client_caps is used as final determination if client is NT or Win95.
425 This is needed to return the correct error codes in some
429 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
431 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
432 set_remote_arch( RA_WINNT);
434 set_remote_arch( RA_WIN95);
437 if (passlen1 != 24 && passlen2 != 24)
440 if (passlen1 > MAX_PASS_LEN) {
441 overflow_attack(passlen1);
444 passlen1 = MIN(passlen1, MAX_PASS_LEN);
445 passlen2 = MIN(passlen2, MAX_PASS_LEN);
447 if(doencrypt || (lp_security() == SEC_SERVER)) {
448 /* Save the lanman2 password and the NT md4 password. */
449 smb_apasslen = passlen1;
450 memcpy(smb_apasswd,p,smb_apasslen);
451 smb_apasswd[smb_apasslen] = 0;
452 smb_ntpasslen = passlen2;
453 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
454 smb_ntpasswd[smb_ntpasslen] = 0;
456 /* both Win95 and WinNT stuff up the password lengths for
457 non-encrypting systems. Uggh.
459 if passlen1==24 its a win95 system, and its setting the
460 password length incorrectly. Luckily it still works with the
461 default code because Win95 will null terminate the password
464 if passlen1>0 and passlen2>0 then maybe its a NT box and its
465 setting passlen2 to some random value which really stuffs
466 things up. we need to fix that one. */
467 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
471 /* we use the first password that they gave */
472 smb_apasslen = passlen1;
473 StrnCpy(smb_apasswd,p,smb_apasslen);
475 /* trim the password */
476 smb_apasslen = strlen(smb_apasswd);
478 /* wfwg sometimes uses a space instead of a null */
479 if (strequal(smb_apasswd," ")) {
485 p += passlen1 + passlen2;
486 fstrcpy(user,p); p = skip_string(p,1);
489 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
490 domain,skip_string(p,1),skip_string(p,2)));
494 DEBUG(3,("sesssetupX:name=[%s]\n",user));
496 /* If name ends in $ then I think it's asking about whether a */
497 /* computer with that name (minus the $) has access. For now */
498 /* say yes to everything ending in $. */
499 if (user[strlen(user) - 1] == '$')
502 struct smb_passwd *smb_pass; /* To check if machine account exists */
504 PAXX: Ack. We don't want to do this. The workstation trust account
505 with a $ on the end should exist in the local password database
506 or be mapped to something generic, but not modified. For NT
507 domain support we must reject this used in certain circumstances
508 with a code to indicate to the client that it is an invalid use
509 of a workstation trust account. NTWKS needs this error to join
510 a domain. This may be the source of future bugs if we cannot
511 be sure whether to reject this or not.
513 /* non-null user name indicates search by username not by smb userid */
514 smb_pass = get_smbpwd_entry(user, 0);
518 /* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */
519 DEBUG(4,("Workstation trust account %s doesn't exist.",user));
520 SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
521 CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
522 return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */
526 /* PAXX: This is the NO LOGON workstation trust account stuff */
527 /* lkclXXXX: if the workstation *does* exist, indicate failure differently! */
528 DEBUG(4,("No Workstation trust account %s",user));
529 SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
530 CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
531 return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */
535 #else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */
536 user[strlen(user) - 1] = '\0';
541 /* If no username is sent use the guest account */
544 strcpy(user,lp_guestaccount(-1));
545 /* If no user and no password then set guest flag. */
546 if( *smb_apasswd == 0)
552 strcpy(sesssetup_user,user);
554 reload_services(True);
556 add_session_user(user);
558 /* Check if the given username was the guest user with no password.
559 We need to do this check after add_session_user() as that
560 call can potentially change the username (via map_user).
563 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
566 if (!guest && !(lp_security() == SEC_SERVER &&
567 server_validate(user, domain,
568 smb_apasswd, smb_apasslen,
569 smb_ntpasswd, smb_ntpasslen)) &&
570 !check_hosts_equiv(user))
573 /* now check if it's a valid username/password */
574 /* If an NT password was supplied try and validate with that
575 first. This is superior as the passwords are mixed case
576 128 length unicode */
579 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
580 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
582 valid_nt_password = True;
584 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
586 if (!computer_id && lp_security() >= SEC_USER) {
587 #if (GUEST_SESSSETUP == 0)
588 return(ERROR(ERRSRV,ERRbadpw));
590 #if (GUEST_SESSSETUP == 1)
591 if (Get_Pwnam(user,True))
592 return(ERROR(ERRSRV,ERRbadpw));
595 if (*smb_apasswd || !Get_Pwnam(user,True))
596 strcpy(user,lp_guestaccount(-1));
597 DEBUG(3,("Registered username %s for guest access\n",user));
602 if (!Get_Pwnam(user,True)) {
603 DEBUG(3,("No such user %s - using guest account\n",user));
604 strcpy(user,lp_guestaccount(-1));
608 if (!strequal(user,lp_guestaccount(-1)) &&
609 lp_servicenumber(user) < 0)
611 int homes = lp_servicenumber(HOMES_NAME);
612 char *home = get_home_dir(user);
613 if (homes >= 0 && home)
614 lp_add_home(user,homes,home);
618 /* it's ok - setup a reply */
619 if (Protocol < PROTOCOL_NT1) {
620 set_message(outbuf,3,0,True);
623 set_message(outbuf,3,3,True);
625 strcpy(p,"Unix"); p = skip_string(p,1);
626 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
627 strcpy(p,myworkgroup); p = skip_string(p,1);
628 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
629 /* perhaps grab OS version here?? */
632 /* Set the correct uid in the outgoing and incoming packets
633 We will use this on future requests to determine which
634 user we should become.
637 struct passwd *pw = Get_Pwnam(user,False);
639 DEBUG(1,("Username %s is invalid on this system\n",user));
640 return(ERROR(ERRSRV,ERRbadpw));
646 if (guest && !computer_id)
647 SSVAL(outbuf,smb_vwv2,1);
649 /* register the name and uid as being validated, so further connections
650 to a uid can get through without a password, on the same VC */
651 sess_vuid = register_vuid(uid,gid,user,guest);
653 SSVAL(outbuf,smb_uid,sess_vuid);
654 SSVAL(inbuf,smb_uid,sess_vuid);
657 max_send = MIN(max_send,smb_bufsize);
659 DEBUG(6,("Client requested max send size of %d\n", max_send));
661 done_sesssetup = True;
663 return chain_reply(inbuf,outbuf,length,bufsize);
667 /****************************************************************************
669 ****************************************************************************/
670 int reply_chkpth(char *inbuf,char *outbuf)
676 BOOL bad_path = False;
678 cnum = SVAL(inbuf,smb_tid);
680 pstrcpy(name,smb_buf(inbuf) + 1);
681 unix_convert(name,cnum,0,&bad_path);
683 mode = SVAL(inbuf,smb_vwv0);
685 if (check_name(name,cnum))
686 ok = directory_exist(name,NULL);
690 /* We special case this - as when a Windows machine
691 is parsing a path is steps through the components
692 one at a time - if a component fails it expects
693 ERRbadpath, not ERRbadfile.
697 unix_ERR_class = ERRDOS;
698 unix_ERR_code = ERRbadpath;
702 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
703 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
704 (get_remote_arch() == RA_WINNT))
706 unix_ERR_class = ERRDOS;
707 unix_ERR_code = ERRbaddirectory;
711 return(UNIXERROR(ERRDOS,ERRbadpath));
714 outsize = set_message(outbuf,0,0,True);
716 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
722 /****************************************************************************
724 ****************************************************************************/
725 int reply_getatr(char *inbuf,char *outbuf)
735 BOOL bad_path = False;
737 cnum = SVAL(inbuf,smb_tid);
739 pstrcpy(fname,smb_buf(inbuf) + 1);
740 unix_convert(fname,cnum,0,&bad_path);
742 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
743 under WfWg - weird! */
746 mode = aHIDDEN | aDIR;
747 if (!CAN_WRITE(cnum)) mode |= aRONLY;
753 if (check_name(fname,cnum))
755 if (sys_stat(fname,&sbuf) == 0)
757 mode = dos_mode(cnum,fname,&sbuf);
759 mtime = sbuf.st_mtime;
765 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
770 if((errno == ENOENT) && bad_path)
772 unix_ERR_class = ERRDOS;
773 unix_ERR_code = ERRbadpath;
776 return(UNIXERROR(ERRDOS,ERRbadfile));
779 outsize = set_message(outbuf,10,0,True);
781 SSVAL(outbuf,smb_vwv0,mode);
782 put_dos_date3(outbuf,smb_vwv1,mtime);
783 SIVAL(outbuf,smb_vwv3,size);
785 if (Protocol >= PROTOCOL_NT1) {
786 char *p = strrchr(fname,'/');
787 uint16 flg2 = SVAL(outbuf,smb_flg2);
789 if (!is_8_3(fname, True))
790 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
793 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
799 /****************************************************************************
801 ****************************************************************************/
802 int reply_setatr(char *inbuf,char *outbuf)
810 BOOL bad_path = False;
812 cnum = SVAL(inbuf,smb_tid);
814 pstrcpy(fname,smb_buf(inbuf) + 1);
815 unix_convert(fname,cnum,0,&bad_path);
817 mode = SVAL(inbuf,smb_vwv0);
818 mtime = make_unix_date3(inbuf+smb_vwv1);
820 if (directory_exist(fname,NULL))
822 if (check_name(fname,cnum))
823 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
825 ok = set_filetime(cnum,fname,mtime);
829 if((errno == ENOENT) && bad_path)
831 unix_ERR_class = ERRDOS;
832 unix_ERR_code = ERRbadpath;
835 return(UNIXERROR(ERRDOS,ERRnoaccess));
838 outsize = set_message(outbuf,0,0,True);
840 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
846 /****************************************************************************
848 ****************************************************************************/
849 int reply_dskattr(char *inbuf,char *outbuf)
853 int dfree,dsize,bsize;
855 cnum = SVAL(inbuf,smb_tid);
857 sys_disk_free(".",&bsize,&dfree,&dsize);
859 outsize = set_message(outbuf,5,0,True);
861 SSVAL(outbuf,smb_vwv0,dsize);
862 SSVAL(outbuf,smb_vwv1,bsize/512);
863 SSVAL(outbuf,smb_vwv2,512);
864 SSVAL(outbuf,smb_vwv3,dfree);
866 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
872 /****************************************************************************
874 Can be called from SMBsearch, SMBffirst or SMBfunique.
875 ****************************************************************************/
876 int reply_search(char *inbuf,char *outbuf)
887 BOOL finished = False;
896 BOOL check_descend = False;
897 BOOL expect_close = False;
898 BOOL can_open = True;
899 BOOL bad_path = False;
901 *mask = *directory = *fname = 0;
903 /* If we were called as SMBffirst then we must expect close. */
904 if(CVAL(inbuf,smb_com) == SMBffirst)
907 cnum = SVAL(inbuf,smb_tid);
909 outsize = set_message(outbuf,1,3,True);
910 maxentries = SVAL(inbuf,smb_vwv0);
911 dirtype = SVAL(inbuf,smb_vwv1);
912 path = smb_buf(inbuf) + 1;
913 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
916 /* dirtype &= ~aDIR; */
918 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
925 pstrcpy(directory,smb_buf(inbuf)+1);
926 pstrcpy(dir2,smb_buf(inbuf)+1);
927 unix_convert(directory,cnum,0,&bad_path);
930 if (!check_name(directory,cnum))
933 p = strrchr(dir2,'/');
945 p = strrchr(directory,'/');
951 if (strlen(directory) == 0)
952 strcpy(directory,"./");
954 CVAL(status,0) = dirtype;
958 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
959 memcpy(mask,status+1,11);
961 dirtype = CVAL(status,0) & 0x1F;
962 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
963 if (!Connections[cnum].dirptr)
965 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
970 /* turn strings of spaces into a . */
972 trim_string(mask,NULL," ");
973 if ((p = strrchr(mask,' ')))
978 trim_string(mask,NULL," ");
985 for (p=mask; *p; p++)
987 if (*p != '?' && *p != '*' && !isdoschar(*p))
989 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
995 if (!strchr(mask,'.') && strlen(mask)>8)
998 fstrcpy(tmp,&mask[8]);
1004 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1008 p = smb_buf(outbuf) + 3;
1012 if (status_len == 0)
1014 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
1019 if((errno == ENOENT) && bad_path)
1021 unix_ERR_class = ERRDOS;
1022 unix_ERR_code = ERRbadpath;
1024 return (UNIXERROR(ERRDOS,ERRnofids));
1026 return(ERROR(ERRDOS,ERRnofids));
1030 DEBUG(4,("dptr_num is %d\n",dptr_num));
1034 if ((dirtype&0x1F) == aVOLID)
1036 memcpy(p,status,21);
1037 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
1038 dptr_fill(p+12,dptr_num);
1039 if (dptr_zero(p+12) && (status_len==0))
1043 p += DIR_STRUCT_SIZE;
1047 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
1048 if (in_list(Connections[cnum].dirpath,
1049 lp_dontdescend(SNUM(cnum)),True))
1050 check_descend = True;
1052 for (i=numentries;(i<maxentries) && !finished;i++)
1055 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
1058 memcpy(p,status,21);
1059 make_dir_struct(p,mask,fname,size,mode,date);
1060 dptr_fill(p+12,dptr_num);
1063 p += DIR_STRUCT_SIZE;
1072 if (numentries == 0 || !ok)
1074 CVAL(outbuf,smb_rcls) = ERRDOS;
1075 SSVAL(outbuf,smb_err,ERRnofiles);
1078 /* If we were called as SMBffirst with smb_search_id == NULL
1079 and no entries were found then return error and close dirptr
1082 if(ok && expect_close && numentries == 0 && status_len == 0)
1084 CVAL(outbuf,smb_rcls) = ERRDOS;
1085 SSVAL(outbuf,smb_err,ERRnofiles);
1086 /* Also close the dptr - we know it's gone */
1087 dptr_close(dptr_num);
1090 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1091 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1092 dptr_close(dptr_num);
1094 SSVAL(outbuf,smb_vwv0,numentries);
1095 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1096 CVAL(smb_buf(outbuf),0) = 5;
1097 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1099 if (Protocol >= PROTOCOL_NT1) {
1100 uint16 flg2 = SVAL(outbuf,smb_flg2);
1101 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1104 outsize += DIR_STRUCT_SIZE*numentries;
1105 smb_setlen(outbuf,outsize - 4);
1107 if ((! *directory) && dptr_path(dptr_num))
1108 sprintf(directory,"(%s)",dptr_path(dptr_num));
1110 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1112 smb_fn_name(CVAL(inbuf,smb_com)),
1113 mask,directory,cnum,dirtype,numentries,maxentries));
1119 /****************************************************************************
1120 reply to a fclose (stop directory search)
1121 ****************************************************************************/
1122 int reply_fclose(char *inbuf,char *outbuf)
1131 cnum = SVAL(inbuf,smb_tid);
1133 outsize = set_message(outbuf,1,0,True);
1134 path = smb_buf(inbuf) + 1;
1135 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1138 if (status_len == 0)
1139 return(ERROR(ERRSRV,ERRsrverror));
1141 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1143 if(dptr_fetch(status+12,&dptr_num)) {
1144 /* Close the dptr - we know it's gone */
1145 dptr_close(dptr_num);
1148 SSVAL(outbuf,smb_vwv0,0);
1150 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1156 /****************************************************************************
1158 ****************************************************************************/
1159 int reply_open(char *inbuf,char *outbuf)
1172 BOOL bad_path = False;
1174 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1176 cnum = SVAL(inbuf,smb_tid);
1178 share_mode = SVAL(inbuf,smb_vwv0);
1180 pstrcpy(fname,smb_buf(inbuf)+1);
1181 unix_convert(fname,cnum,0,&bad_path);
1183 fnum = find_free_file();
1185 return(ERROR(ERRSRV,ERRnofids));
1187 if (!check_name(fname,cnum))
1189 if((errno == ENOENT) && bad_path)
1191 unix_ERR_class = ERRDOS;
1192 unix_ERR_code = ERRbadpath;
1194 return(UNIXERROR(ERRDOS,ERRnoaccess));
1197 unixmode = unix_mode(cnum,aARCH);
1199 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1200 oplock_request,&rmode,NULL);
1206 if((errno == ENOENT) && bad_path)
1208 unix_ERR_class = ERRDOS;
1209 unix_ERR_code = ERRbadpath;
1211 return(UNIXERROR(ERRDOS,ERRnoaccess));
1214 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1215 close_file(fnum,False);
1216 return(ERROR(ERRDOS,ERRnoaccess));
1219 size = sbuf.st_size;
1220 fmode = dos_mode(cnum,fname,&sbuf);
1221 mtime = sbuf.st_mtime;
1224 DEBUG(3,("attempt to open a directory %s\n",fname));
1225 close_file(fnum,False);
1226 return(ERROR(ERRDOS,ERRnoaccess));
1229 outsize = set_message(outbuf,7,0,True);
1230 SSVAL(outbuf,smb_vwv0,fnum);
1231 SSVAL(outbuf,smb_vwv1,fmode);
1232 put_dos_date3(outbuf,smb_vwv2,mtime);
1233 SIVAL(outbuf,smb_vwv4,size);
1234 SSVAL(outbuf,smb_vwv6,rmode);
1236 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1237 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1240 if(fsp->granted_oplock)
1241 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1246 /****************************************************************************
1247 reply to an open and X
1248 ****************************************************************************/
1249 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1252 int cnum = SVAL(inbuf,smb_tid);
1254 int smb_mode = SVAL(inbuf,smb_vwv3);
1255 int smb_attr = SVAL(inbuf,smb_vwv5);
1256 /* Breakout the oplock request bits so we can set the
1257 reply bits separately. */
1258 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1259 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1260 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1262 int open_flags = SVAL(inbuf,smb_vwv2);
1263 int smb_sattr = SVAL(inbuf,smb_vwv4);
1264 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1266 int smb_ofun = SVAL(inbuf,smb_vwv8);
1268 int size=0,fmode=0,mtime=0,rmode=0;
1271 BOOL bad_path = False;
1274 /* If it's an IPC, pass off the pipe handler. */
1276 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1278 /* XXXX we need to handle passed times, sattr and flags */
1280 pstrcpy(fname,smb_buf(inbuf));
1281 unix_convert(fname,cnum,0,&bad_path);
1283 fnum = find_free_file();
1285 return(ERROR(ERRSRV,ERRnofids));
1287 if (!check_name(fname,cnum))
1289 if((errno == ENOENT) && bad_path)
1291 unix_ERR_class = ERRDOS;
1292 unix_ERR_code = ERRbadpath;
1294 return(UNIXERROR(ERRDOS,ERRnoaccess));
1297 unixmode = unix_mode(cnum,smb_attr | aARCH);
1299 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1300 oplock_request, &rmode,&smb_action);
1306 if((errno == ENOENT) && bad_path)
1308 unix_ERR_class = ERRDOS;
1309 unix_ERR_code = ERRbadpath;
1311 return(UNIXERROR(ERRDOS,ERRnoaccess));
1314 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1315 close_file(fnum,False);
1316 return(ERROR(ERRDOS,ERRnoaccess));
1319 size = sbuf.st_size;
1320 fmode = dos_mode(cnum,fname,&sbuf);
1321 mtime = sbuf.st_mtime;
1323 close_file(fnum,False);
1324 return(ERROR(ERRDOS,ERRnoaccess));
1327 /* If the caller set the extended oplock request bit
1328 and we granted one (by whatever means) - set the
1329 correct bit for extended oplock reply.
1332 if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1333 smb_action |= EXTENDED_OPLOCK_GRANTED;
1336 if(ex_oplock_request && fsp->granted_oplock) {
1337 smb_action |= EXTENDED_OPLOCK_GRANTED;
1340 /* If the caller set the core oplock request bit
1341 and we granted one (by whatever means) - set the
1342 correct bit for core oplock reply.
1345 if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1346 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1349 if(core_oplock_request && fsp->granted_oplock) {
1350 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1353 set_message(outbuf,15,0,True);
1354 SSVAL(outbuf,smb_vwv2,fnum);
1355 SSVAL(outbuf,smb_vwv3,fmode);
1356 put_dos_date3(outbuf,smb_vwv4,mtime);
1357 SIVAL(outbuf,smb_vwv6,size);
1358 SSVAL(outbuf,smb_vwv8,rmode);
1359 SSVAL(outbuf,smb_vwv11,smb_action);
1363 return chain_reply(inbuf,outbuf,length,bufsize);
1367 /****************************************************************************
1368 reply to a SMBulogoffX
1369 ****************************************************************************/
1370 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1372 uint16 vuid = SVAL(inbuf,smb_uid);
1373 user_struct *vuser = get_valid_user_struct(vuid);
1376 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1379 /* in user level security we are supposed to close any files
1380 open by this user */
1381 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1383 for (i=0;i<MAX_OPEN_FILES;i++)
1384 if (Files[i].uid == vuser->uid && Files[i].open) {
1385 close_file(i,False);
1389 invalidate_vuid(vuid);
1391 set_message(outbuf,2,0,True);
1393 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1395 return chain_reply(inbuf,outbuf,length,bufsize);
1399 /****************************************************************************
1400 reply to a mknew or a create
1401 ****************************************************************************/
1402 int reply_mknew(char *inbuf,char *outbuf)
1411 BOOL bad_path = False;
1413 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1415 com = SVAL(inbuf,smb_com);
1416 cnum = SVAL(inbuf,smb_tid);
1418 createmode = SVAL(inbuf,smb_vwv0);
1419 pstrcpy(fname,smb_buf(inbuf)+1);
1420 unix_convert(fname,cnum,0,&bad_path);
1422 if (createmode & aVOLID)
1424 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1427 unixmode = unix_mode(cnum,createmode);
1429 fnum = find_free_file();
1431 return(ERROR(ERRSRV,ERRnofids));
1433 if (!check_name(fname,cnum))
1435 if((errno == ENOENT) && bad_path)
1437 unix_ERR_class = ERRDOS;
1438 unix_ERR_code = ERRbadpath;
1440 return(UNIXERROR(ERRDOS,ERRnoaccess));
1445 /* We should fail if file exists. */
1450 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1454 /* Open file in dos compatibility share mode. */
1455 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1456 oplock_request, NULL, NULL);
1462 if((errno == ENOENT) && bad_path)
1464 unix_ERR_class = ERRDOS;
1465 unix_ERR_code = ERRbadpath;
1467 return(UNIXERROR(ERRDOS,ERRnoaccess));
1470 outsize = set_message(outbuf,1,0,True);
1471 SSVAL(outbuf,smb_vwv0,fnum);
1473 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1474 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1477 if(fsp->granted_oplock)
1478 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1480 DEBUG(2,("new file %s\n",fname));
1481 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));
1487 /****************************************************************************
1488 reply to a create temporary file
1489 ****************************************************************************/
1490 int reply_ctemp(char *inbuf,char *outbuf)
1499 BOOL bad_path = False;
1501 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1503 cnum = SVAL(inbuf,smb_tid);
1504 createmode = SVAL(inbuf,smb_vwv0);
1505 pstrcpy(fname,smb_buf(inbuf)+1);
1506 strcat(fname,"/TMXXXXXX");
1507 unix_convert(fname,cnum,0,&bad_path);
1509 unixmode = unix_mode(cnum,createmode);
1511 fnum = find_free_file();
1513 return(ERROR(ERRSRV,ERRnofids));
1515 if (!check_name(fname,cnum))
1517 if((errno == ENOENT) && bad_path)
1519 unix_ERR_class = ERRDOS;
1520 unix_ERR_code = ERRbadpath;
1522 return(UNIXERROR(ERRDOS,ERRnoaccess));
1525 strcpy(fname2,(char *)mktemp(fname));
1527 /* Open file in dos compatibility share mode. */
1528 /* We should fail if file exists. */
1529 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1530 oplock_request, NULL, NULL);
1536 if((errno == ENOENT) && bad_path)
1538 unix_ERR_class = ERRDOS;
1539 unix_ERR_code = ERRbadpath;
1541 return(UNIXERROR(ERRDOS,ERRnoaccess));
1544 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1545 SSVAL(outbuf,smb_vwv0,fnum);
1546 CVAL(smb_buf(outbuf),0) = 4;
1547 strcpy(smb_buf(outbuf) + 1,fname2);
1549 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1550 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1553 if(fsp->granted_oplock)
1554 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1556 DEBUG(2,("created temp file %s\n",fname2));
1557 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));
1563 /*******************************************************************
1564 check if a user is allowed to delete a file
1565 ********************************************************************/
1566 static BOOL can_delete(char *fname,int cnum,int dirtype)
1571 if (!CAN_WRITE(cnum)) return(False);
1573 if (sys_lstat(fname,&sbuf) != 0) return(False);
1574 fmode = dos_mode(cnum,fname,&sbuf);
1575 if (fmode & aDIR) return(False);
1576 if (!lp_delete_readonly(SNUM(cnum))) {
1577 if (fmode & aRONLY) return(False);
1579 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1581 if (!check_file_sharing(cnum,fname)) return(False);
1585 /****************************************************************************
1587 ****************************************************************************/
1588 int reply_unlink(char *inbuf,char *outbuf)
1598 int error = ERRnoaccess;
1601 BOOL bad_path = False;
1603 *directory = *mask = 0;
1605 cnum = SVAL(inbuf,smb_tid);
1606 dirtype = SVAL(inbuf,smb_vwv0);
1608 pstrcpy(name,smb_buf(inbuf) + 1);
1610 DEBUG(3,("reply_unlink : %s\n",name));
1612 unix_convert(name,cnum,0,&bad_path);
1614 p = strrchr(name,'/');
1616 strcpy(directory,"./");
1620 strcpy(directory,name);
1624 if (is_mangled(mask))
1625 check_mangled_stack(mask);
1627 has_wild = strchr(mask,'*') || strchr(mask,'?');
1630 strcat(directory,"/");
1631 strcat(directory,mask);
1632 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1633 if (!count) exists = file_exist(directory,NULL);
1635 void *dirptr = NULL;
1638 if (check_name(directory,cnum))
1639 dirptr = OpenDir(cnum, directory, True);
1641 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1642 the pattern matches against the long name, otherwise the short name
1643 We don't implement this yet XXXX
1650 if (strequal(mask,"????????.???"))
1653 while ((dname = ReadDirName(dirptr)))
1656 pstrcpy(fname,dname);
1658 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1660 error = ERRnoaccess;
1661 sprintf(fname,"%s/%s",directory,dname);
1662 if (!can_delete(fname,cnum,dirtype)) continue;
1663 if (!sys_unlink(fname)) count++;
1664 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1672 return(ERROR(ERRDOS,error));
1675 if((errno == ENOENT) && bad_path)
1677 unix_ERR_class = ERRDOS;
1678 unix_ERR_code = ERRbadpath;
1680 return(UNIXERROR(ERRDOS,error));
1684 outsize = set_message(outbuf,0,0,True);
1690 /****************************************************************************
1691 reply to a readbraw (core+ protocol)
1692 ****************************************************************************/
1693 int reply_readbraw(char *inbuf, char *outbuf)
1695 int cnum,maxcount,mincount,fnum;
1698 char *header = outbuf;
1704 * Special check if an oplock break has been issued
1705 * and the readraw request croses on the wire, we must
1706 * return a zero length response here.
1709 if(global_oplock_break)
1711 _smb_setlen(header,0);
1712 transfer_file(0,Client,0,header,4,0);
1713 DEBUG(5,("readbraw - oplock break finished\n"));
1717 cnum = SVAL(inbuf,smb_tid);
1718 fnum = GETFNUM(inbuf,smb_vwv0);
1720 startpos = IVAL(inbuf,smb_vwv1);
1721 maxcount = SVAL(inbuf,smb_vwv3);
1722 mincount = SVAL(inbuf,smb_vwv4);
1724 /* ensure we don't overrun the packet size */
1725 maxcount = MIN(65535,maxcount);
1726 maxcount = MAX(mincount,maxcount);
1728 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1730 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1731 _smb_setlen(header,0);
1732 transfer_file(0,Client,0,header,4,0);
1737 fd = Files[fnum].fd_ptr->fd;
1738 fname = Files[fnum].name;
1742 if (!is_locked(fnum,cnum,maxcount,startpos))
1744 int size = Files[fnum].size;
1745 int sizeneeded = startpos + maxcount;
1747 if (size < sizeneeded) {
1749 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1751 if (!Files[fnum].can_write)
1752 Files[fnum].size = size;
1755 nread = MIN(maxcount,(int)(size - startpos));
1758 if (nread < mincount)
1761 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1764 maxcount,mincount,nread));
1769 _smb_setlen(header,nread);
1771 #if USE_READ_PREDICTION
1772 if (!Files[fnum].can_write)
1773 predict = read_predict(fd,startpos,header+4,NULL,nread);
1776 if ((nread-predict) > 0)
1777 seek_file(fnum,startpos + predict);
1779 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1784 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1785 fname,startpos,nread,ret));
1788 ret = read_file(fnum,header+4,startpos,nread);
1789 if (ret < mincount) ret = 0;
1791 _smb_setlen(header,ret);
1792 transfer_file(0,Client,0,header,4+ret,0);
1795 DEBUG(5,("readbraw finished\n"));
1800 /****************************************************************************
1801 reply to a lockread (core+ protocol)
1802 ****************************************************************************/
1803 int reply_lockread(char *inbuf,char *outbuf)
1809 uint32 startpos, numtoread;
1813 cnum = SVAL(inbuf,smb_tid);
1814 fnum = GETFNUM(inbuf,smb_vwv0);
1816 CHECK_FNUM(fnum,cnum);
1820 numtoread = SVAL(inbuf,smb_vwv1);
1821 startpos = IVAL(inbuf,smb_vwv2);
1823 outsize = set_message(outbuf,5,3,True);
1824 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1825 data = smb_buf(outbuf) + 3;
1827 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1828 return (ERROR(eclass,ecode));
1830 nread = read_file(fnum,data,startpos,numtoread);
1833 return(UNIXERROR(ERRDOS,ERRnoaccess));
1836 SSVAL(outbuf,smb_vwv0,nread);
1837 SSVAL(outbuf,smb_vwv5,nread+3);
1838 SSVAL(smb_buf(outbuf),1,nread);
1840 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1846 /****************************************************************************
1848 ****************************************************************************/
1849 int reply_read(char *inbuf,char *outbuf)
1851 int cnum,numtoread,fnum;
1857 cnum = SVAL(inbuf,smb_tid);
1858 fnum = GETFNUM(inbuf,smb_vwv0);
1860 CHECK_FNUM(fnum,cnum);
1864 numtoread = SVAL(inbuf,smb_vwv1);
1865 startpos = IVAL(inbuf,smb_vwv2);
1867 outsize = set_message(outbuf,5,3,True);
1868 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1869 data = smb_buf(outbuf) + 3;
1871 if (is_locked(fnum,cnum,numtoread,startpos))
1872 return(ERROR(ERRDOS,ERRlock));
1875 nread = read_file(fnum,data,startpos,numtoread);
1878 return(UNIXERROR(ERRDOS,ERRnoaccess));
1881 SSVAL(outbuf,smb_vwv0,nread);
1882 SSVAL(outbuf,smb_vwv5,nread+3);
1883 CVAL(smb_buf(outbuf),0) = 1;
1884 SSVAL(smb_buf(outbuf),1,nread);
1886 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1892 /****************************************************************************
1893 reply to a read and X
1894 ****************************************************************************/
1895 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1897 int fnum = GETFNUM(inbuf,smb_vwv2);
1898 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1899 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1900 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1906 cnum = SVAL(inbuf,smb_tid);
1908 CHECK_FNUM(fnum,cnum);
1912 set_message(outbuf,12,0,True);
1913 data = smb_buf(outbuf);
1915 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1916 return(ERROR(ERRDOS,ERRlock));
1917 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1921 return(UNIXERROR(ERRDOS,ERRnoaccess));
1923 SSVAL(outbuf,smb_vwv5,nread);
1924 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1925 SSVAL(smb_buf(outbuf),-2,nread);
1927 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1928 timestring(),fnum,cnum,
1929 smb_mincnt,smb_maxcnt,nread));
1933 return chain_reply(inbuf,outbuf,length,bufsize);
1937 /****************************************************************************
1938 reply to a writebraw (core+ or LANMAN1.0 protocol)
1939 ****************************************************************************/
1940 int reply_writebraw(char *inbuf,char *outbuf)
1943 int total_written=0;
1952 cnum = SVAL(inbuf,smb_tid);
1953 fnum = GETFNUM(inbuf,smb_vwv0);
1955 CHECK_FNUM(fnum,cnum);
1959 tcount = IVAL(inbuf,smb_vwv1);
1960 startpos = IVAL(inbuf,smb_vwv3);
1961 write_through = BITSETW(inbuf+smb_vwv7,0);
1963 /* We have to deal with slightly different formats depending
1964 on whether we are using the core+ or lanman1.0 protocol */
1965 if(Protocol <= PROTOCOL_COREPLUS) {
1966 numtowrite = SVAL(smb_buf(inbuf),-2);
1967 data = smb_buf(inbuf);
1969 numtowrite = SVAL(inbuf,smb_vwv10);
1970 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1973 /* force the error type */
1974 CVAL(inbuf,smb_com) = SMBwritec;
1975 CVAL(outbuf,smb_com) = SMBwritec;
1977 if (is_locked(fnum,cnum,tcount,startpos))
1978 return(ERROR(ERRDOS,ERRlock));
1980 if (seek_file(fnum,startpos) != startpos)
1981 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1984 nwritten = write_file(fnum,data,numtowrite);
1986 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1987 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1989 if (nwritten < numtowrite)
1990 return(UNIXERROR(ERRHRD,ERRdiskfull));
1992 total_written = nwritten;
1994 /* Return a message to the redirector to tell it
1995 to send more bytes */
1996 CVAL(outbuf,smb_com) = SMBwritebraw;
1997 SSVALS(outbuf,smb_vwv0,-1);
1998 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1999 send_smb(Client,outbuf);
2001 /* Now read the raw data into the buffer and write it */
2002 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2003 exit_server("secondary writebraw failed");
2006 /* Even though this is not an smb message, smb_len
2007 returns the generic length of an smb message */
2008 numtowrite = smb_len(inbuf);
2010 if (tcount > nwritten+numtowrite) {
2011 DEBUG(3,("Client overestimated the write %d %d %d\n",
2012 tcount,nwritten,numtowrite));
2015 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
2017 total_written += nwritten;
2019 /* Set up outbuf to return the correct return */
2020 outsize = set_message(outbuf,1,0,True);
2021 CVAL(outbuf,smb_com) = SMBwritec;
2022 SSVAL(outbuf,smb_vwv0,total_written);
2024 if (nwritten < numtowrite) {
2025 CVAL(outbuf,smb_rcls) = ERRHRD;
2026 SSVAL(outbuf,smb_err,ERRdiskfull);
2029 if (lp_syncalways(SNUM(cnum)) || write_through)
2032 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
2033 timestring(),fnum,cnum,startpos,numtowrite,total_written));
2035 /* we won't return a status if write through is not selected - this
2036 follows what WfWg does */
2037 if (!write_through && total_written==tcount)
2044 /****************************************************************************
2045 reply to a writeunlock (core+)
2046 ****************************************************************************/
2047 int reply_writeunlock(char *inbuf,char *outbuf)
2053 uint32 numtowrite,startpos;
2057 cnum = SVAL(inbuf,smb_tid);
2058 fnum = GETFNUM(inbuf,smb_vwv0);
2060 CHECK_FNUM(fnum,cnum);
2064 numtowrite = SVAL(inbuf,smb_vwv1);
2065 startpos = IVAL(inbuf,smb_vwv2);
2066 data = smb_buf(inbuf) + 3;
2068 if (is_locked(fnum,cnum,numtowrite,startpos))
2069 return(ERROR(ERRDOS,ERRlock));
2071 seek_file(fnum,startpos);
2073 /* The special X/Open SMB protocol handling of
2074 zero length writes is *NOT* done for
2079 nwritten = write_file(fnum,data,numtowrite);
2081 if (lp_syncalways(SNUM(cnum)))
2084 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2085 return(UNIXERROR(ERRDOS,ERRnoaccess));
2087 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2088 return(ERROR(eclass,ecode));
2090 outsize = set_message(outbuf,1,0,True);
2092 SSVAL(outbuf,smb_vwv0,nwritten);
2094 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2095 timestring(),fnum,cnum,numtowrite,nwritten));
2101 /****************************************************************************
2103 ****************************************************************************/
2104 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
2106 int cnum,numtowrite,fnum;
2115 cnum = SVAL(inbuf,smb_tid);
2116 fnum = GETFNUM(inbuf,smb_vwv0);
2118 CHECK_FNUM(fnum,cnum);
2122 numtowrite = SVAL(inbuf,smb_vwv1);
2123 startpos = IVAL(inbuf,smb_vwv2);
2124 data = smb_buf(inbuf) + 3;
2126 if (is_locked(fnum,cnum,numtowrite,startpos))
2127 return(ERROR(ERRDOS,ERRlock));
2129 seek_file(fnum,startpos);
2131 /* X/Open SMB protocol says that if smb_vwv1 is
2132 zero then the file size should be extended or
2133 truncated to the size given in smb_vwv[2-3] */
2135 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2137 nwritten = write_file(fnum,data,numtowrite);
2139 if (lp_syncalways(SNUM(cnum)))
2142 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2143 return(UNIXERROR(ERRDOS,ERRnoaccess));
2145 outsize = set_message(outbuf,1,0,True);
2147 SSVAL(outbuf,smb_vwv0,nwritten);
2149 if (nwritten < numtowrite) {
2150 CVAL(outbuf,smb_rcls) = ERRHRD;
2151 SSVAL(outbuf,smb_err,ERRdiskfull);
2154 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2160 /****************************************************************************
2161 reply to a write and X
2162 ****************************************************************************/
2163 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2165 int fnum = GETFNUM(inbuf,smb_vwv2);
2166 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2167 int smb_dsize = SVAL(inbuf,smb_vwv10);
2168 int smb_doff = SVAL(inbuf,smb_vwv11);
2169 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2174 cnum = SVAL(inbuf,smb_tid);
2176 CHECK_FNUM(fnum,cnum);
2180 data = smb_base(inbuf) + smb_doff;
2182 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2183 return(ERROR(ERRDOS,ERRlock));
2185 seek_file(fnum,smb_offs);
2187 /* X/Open SMB protocol says that, unlike SMBwrite
2188 if the length is zero then NO truncation is
2189 done, just a write of zero. To truncate a file,
2194 nwritten = write_file(fnum,data,smb_dsize);
2196 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2197 return(UNIXERROR(ERRDOS,ERRnoaccess));
2199 set_message(outbuf,6,0,True);
2201 SSVAL(outbuf,smb_vwv2,nwritten);
2203 if (nwritten < smb_dsize) {
2204 CVAL(outbuf,smb_rcls) = ERRHRD;
2205 SSVAL(outbuf,smb_err,ERRdiskfull);
2208 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2212 if (lp_syncalways(SNUM(cnum)) || write_through)
2215 return chain_reply(inbuf,outbuf,length,bufsize);
2219 /****************************************************************************
2221 ****************************************************************************/
2222 int reply_lseek(char *inbuf,char *outbuf)
2230 cnum = SVAL(inbuf,smb_tid);
2231 fnum = GETFNUM(inbuf,smb_vwv0);
2233 CHECK_FNUM(fnum,cnum);
2236 mode = SVAL(inbuf,smb_vwv1) & 3;
2237 startpos = IVAL(inbuf,smb_vwv2);
2241 case 0: umode = SEEK_SET; break;
2242 case 1: umode = SEEK_CUR; break;
2243 case 2: umode = SEEK_END; break;
2245 umode = SEEK_SET; break;
2248 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2249 Files[fnum].pos = res;
2251 outsize = set_message(outbuf,2,0,True);
2252 SIVALS(outbuf,smb_vwv0,res);
2254 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2260 /****************************************************************************
2262 ****************************************************************************/
2263 int reply_flush(char *inbuf,char *outbuf)
2266 int outsize = set_message(outbuf,0,0,True);
2268 cnum = SVAL(inbuf,smb_tid);
2269 fnum = GETFNUM(inbuf,smb_vwv0);
2271 if (fnum != 0xFFFF) {
2272 CHECK_FNUM(fnum,cnum);
2279 for (i=0;i<MAX_OPEN_FILES;i++)
2286 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2291 /****************************************************************************
2293 ****************************************************************************/
2294 int reply_exit(char *inbuf,char *outbuf)
2296 int outsize = set_message(outbuf,0,0,True);
2297 DEBUG(3,("%s exit\n",timestring()));
2303 /****************************************************************************
2305 ****************************************************************************/
2306 int reply_close(char *inbuf,char *outbuf)
2311 int32 eclass = 0, err = 0;
2313 outsize = set_message(outbuf,0,0,True);
2315 cnum = SVAL(inbuf,smb_tid);
2317 /* If it's an IPC, pass off to the pipe handler. */
2319 return reply_pipe_close(inbuf,outbuf);
2321 fnum = GETFNUM(inbuf,smb_vwv0);
2323 CHECK_FNUM(fnum,cnum);
2325 if(HAS_CACHED_ERROR(fnum)) {
2326 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2327 err = Files[fnum].wbmpx_ptr->wr_error;
2330 mtime = make_unix_date3(inbuf+smb_vwv1);
2332 /* try and set the date */
2333 set_filetime(cnum, Files[fnum].name,mtime);
2335 close_file(fnum,True);
2337 /* We have a cached error */
2339 return(ERROR(eclass,err));
2341 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2342 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2343 Connections[cnum].num_files_open));
2349 /****************************************************************************
2350 reply to a writeclose (Core+ protocol)
2351 ****************************************************************************/
2352 int reply_writeclose(char *inbuf,char *outbuf)
2354 int cnum,numtowrite,fnum;
2361 cnum = SVAL(inbuf,smb_tid);
2362 fnum = GETFNUM(inbuf,smb_vwv0);
2364 CHECK_FNUM(fnum,cnum);
2368 numtowrite = SVAL(inbuf,smb_vwv1);
2369 startpos = IVAL(inbuf,smb_vwv2);
2370 mtime = make_unix_date3(inbuf+smb_vwv4);
2371 data = smb_buf(inbuf) + 1;
2373 if (is_locked(fnum,cnum,numtowrite,startpos))
2374 return(ERROR(ERRDOS,ERRlock));
2376 seek_file(fnum,startpos);
2378 nwritten = write_file(fnum,data,numtowrite);
2380 set_filetime(cnum, Files[fnum].name,mtime);
2382 close_file(fnum,True);
2384 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2385 timestring(),fnum,cnum,numtowrite,nwritten,
2386 Connections[cnum].num_files_open));
2389 return(UNIXERROR(ERRDOS,ERRnoaccess));
2391 outsize = set_message(outbuf,1,0,True);
2393 SSVAL(outbuf,smb_vwv0,nwritten);
2398 /****************************************************************************
2400 ****************************************************************************/
2401 int reply_lock(char *inbuf,char *outbuf)
2404 int outsize = set_message(outbuf,0,0,True);
2405 uint32 count,offset;
2409 cnum = SVAL(inbuf,smb_tid);
2410 fnum = GETFNUM(inbuf,smb_vwv0);
2412 CHECK_FNUM(fnum,cnum);
2415 count = IVAL(inbuf,smb_vwv1);
2416 offset = IVAL(inbuf,smb_vwv3);
2418 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));
2420 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2421 return (ERROR(eclass,ecode));
2427 /****************************************************************************
2429 ****************************************************************************/
2430 int reply_unlock(char *inbuf,char *outbuf)
2433 int outsize = set_message(outbuf,0,0,True);
2434 uint32 count,offset;
2438 cnum = SVAL(inbuf,smb_tid);
2439 fnum = GETFNUM(inbuf,smb_vwv0);
2441 CHECK_FNUM(fnum,cnum);
2444 count = IVAL(inbuf,smb_vwv1);
2445 offset = IVAL(inbuf,smb_vwv3);
2447 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2448 return (ERROR(eclass,ecode));
2450 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));
2456 /****************************************************************************
2458 ****************************************************************************/
2459 int reply_tdis(char *inbuf,char *outbuf)
2462 int outsize = set_message(outbuf,0,0,True);
2465 cnum = SVAL(inbuf,smb_tid);
2466 vuid = SVAL(inbuf,smb_uid);
2468 if (!OPEN_CNUM(cnum)) {
2469 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2470 return(ERROR(ERRSRV,ERRinvnid));
2473 Connections[cnum].used = False;
2475 close_cnum(cnum,vuid);
2477 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2484 /****************************************************************************
2486 ****************************************************************************/
2487 int reply_echo(char *inbuf,char *outbuf)
2490 int smb_reverb = SVAL(inbuf,smb_vwv0);
2492 int data_len = smb_buflen(inbuf);
2493 int outsize = set_message(outbuf,1,data_len,True);
2495 cnum = SVAL(inbuf,smb_tid);
2497 /* According to the latest CIFS spec we shouldn't
2498 care what the TID is.
2502 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2504 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2505 return(ERROR(ERRSRV,ERRinvnid));
2509 /* copy any incoming data back out */
2511 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2513 if (smb_reverb > 100)
2515 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2519 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2521 SSVAL(outbuf,smb_vwv0,seq_num);
2523 smb_setlen(outbuf,outsize - 4);
2525 send_smb(Client,outbuf);
2528 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2534 /****************************************************************************
2535 reply to a printopen
2536 ****************************************************************************/
2537 int reply_printopen(char *inbuf,char *outbuf)
2545 *fname = *fname2 = 0;
2547 cnum = SVAL(inbuf,smb_tid);
2549 if (!CAN_PRINT(cnum))
2550 return(ERROR(ERRDOS,ERRnoaccess));
2555 pstrcpy(s,smb_buf(inbuf)+1);
2559 if (!(isalnum(*p) || strchr("._-",*p)))
2564 if (strlen(s) > 10) s[10] = 0;
2566 sprintf(fname,"%s.XXXXXX",s);
2569 fnum = find_free_file();
2571 return(ERROR(ERRSRV,ERRnofids));
2573 strcpy(fname2,(char *)mktemp(fname));
2575 if (!check_name(fname2,cnum))
2576 return(ERROR(ERRDOS,ERRnoaccess));
2578 /* Open for exclusive use, write only. */
2579 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2582 if (!Files[fnum].open)
2583 return(UNIXERROR(ERRDOS,ERRnoaccess));
2585 /* force it to be a print file */
2586 Files[fnum].print_file = True;
2588 outsize = set_message(outbuf,1,0,True);
2589 SSVAL(outbuf,smb_vwv0,fnum);
2591 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2597 /****************************************************************************
2598 reply to a printclose
2599 ****************************************************************************/
2600 int reply_printclose(char *inbuf,char *outbuf)
2603 int outsize = set_message(outbuf,0,0,True);
2605 cnum = SVAL(inbuf,smb_tid);
2606 fnum = GETFNUM(inbuf,smb_vwv0);
2608 CHECK_FNUM(fnum,cnum);
2611 if (!CAN_PRINT(cnum))
2612 return(ERROR(ERRDOS,ERRnoaccess));
2614 close_file(fnum,True);
2616 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2622 /****************************************************************************
2623 reply to a printqueue
2624 ****************************************************************************/
2625 int reply_printqueue(char *inbuf,char *outbuf)
2628 int outsize = set_message(outbuf,2,3,True);
2629 int max_count = SVAL(inbuf,smb_vwv0);
2630 int start_index = SVAL(inbuf,smb_vwv1);
2633 cnum = SVAL(inbuf,smb_tid);
2634 vuid = SVAL(inbuf,smb_uid);
2636 /* allow checking the queue for anyone */
2638 if (!CAN_PRINT(cnum))
2639 return(ERROR(ERRDOS,ERRnoaccess));
2642 SSVAL(outbuf,smb_vwv0,0);
2643 SSVAL(outbuf,smb_vwv1,0);
2644 CVAL(smb_buf(outbuf),0) = 1;
2645 SSVAL(smb_buf(outbuf),1,0);
2647 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2648 timestring(),cnum,start_index,max_count));
2650 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2655 for (i=0;i<MAX_CONNECTIONS;i++)
2656 if (CAN_PRINT(i) && Connections[i].printer)
2660 for (i=0;i<MAX_CONNECTIONS;i++)
2664 if (!OPEN_CNUM(cnum))
2665 return(ERROR(ERRSRV,ERRinvnid));
2667 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2670 if (!become_user(&Connections[cnum], cnum, vuid))
2671 return(ERROR(ERRSRV,ERRinvnid));
2674 print_queue_struct *queue = NULL;
2675 char *p = smb_buf(outbuf) + 3;
2676 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2677 int num_to_get = ABS(max_count);
2678 int first = (max_count>0?start_index:start_index+max_count+1);
2684 num_to_get = MIN(num_to_get,count-first);
2687 for (i=first;i<first+num_to_get;i++)
2689 put_dos_date2(p,0,queue[i].time);
2690 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2691 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2692 SIVAL(p,7,queue[i].size);
2694 StrnCpy(p+12,queue[i].user,16);
2700 outsize = set_message(outbuf,2,28*count+3,False);
2701 SSVAL(outbuf,smb_vwv0,count);
2702 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2703 CVAL(smb_buf(outbuf),0) = 1;
2704 SSVAL(smb_buf(outbuf),1,28*count);
2707 if (queue) free(queue);
2709 DEBUG(3,("%d entries returned in queue\n",count));
2716 /****************************************************************************
2717 reply to a printwrite
2718 ****************************************************************************/
2719 int reply_printwrite(char *inbuf,char *outbuf)
2721 int cnum,numtowrite,fnum;
2722 int outsize = set_message(outbuf,0,0,True);
2725 cnum = SVAL(inbuf,smb_tid);
2727 if (!CAN_PRINT(cnum))
2728 return(ERROR(ERRDOS,ERRnoaccess));
2730 fnum = GETFNUM(inbuf,smb_vwv0);
2732 CHECK_FNUM(fnum,cnum);
2736 numtowrite = SVAL(smb_buf(inbuf),1);
2737 data = smb_buf(inbuf) + 3;
2739 if (write_file(fnum,data,numtowrite) != numtowrite)
2740 return(UNIXERROR(ERRDOS,ERRnoaccess));
2742 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2748 /****************************************************************************
2750 ****************************************************************************/
2751 int reply_mkdir(char *inbuf,char *outbuf)
2755 int outsize,ret= -1;
2756 BOOL bad_path = False;
2758 pstrcpy(directory,smb_buf(inbuf) + 1);
2759 cnum = SVAL(inbuf,smb_tid);
2760 unix_convert(directory,cnum,0,&bad_path);
2762 if (check_name(directory,cnum))
2763 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2767 if((errno == ENOENT) && bad_path)
2769 unix_ERR_class = ERRDOS;
2770 unix_ERR_code = ERRbadpath;
2772 return(UNIXERROR(ERRDOS,ERRnoaccess));
2775 outsize = set_message(outbuf,0,0,True);
2777 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2782 /****************************************************************************
2783 Static function used by reply_rmdir to delete an entire directory
2785 ****************************************************************************/
2786 static BOOL recursive_rmdir(char *directory)
2790 void *dirptr = OpenDir(-1, directory, False);
2795 while((dname = ReadDirName(dirptr)))
2800 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2803 /* Construct the full name. */
2804 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2810 strcpy(fullname, directory);
2811 strcat(fullname, "/");
2812 strcat(fullname, dname);
2814 if(sys_lstat(fullname, &st) != 0)
2820 if(st.st_mode & S_IFDIR)
2822 if(recursive_rmdir(fullname)!=0)
2827 if(sys_rmdir(fullname) != 0)
2833 else if(sys_unlink(fullname) != 0)
2843 /****************************************************************************
2845 ****************************************************************************/
2846 int reply_rmdir(char *inbuf,char *outbuf)
2852 BOOL bad_path = False;
2854 cnum = SVAL(inbuf,smb_tid);
2855 pstrcpy(directory,smb_buf(inbuf) + 1);
2856 unix_convert(directory,cnum,0,&bad_path);
2858 if (check_name(directory,cnum))
2861 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2862 ok = (sys_rmdir(directory) == 0);
2863 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2865 /* Check to see if the only thing in this directory are
2866 vetoed files/directories. If so then delete them and
2867 retry. If we fail to delete any of them (and we *don't*
2868 do a recursive delete) then fail the rmdir. */
2869 BOOL all_veto_files = True;
2871 void *dirptr = OpenDir(cnum, directory, False);
2875 int dirpos = TellDir(dirptr);
2876 while ((dname = ReadDirName(dirptr)))
2878 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2880 if(!IS_VETO_PATH(cnum, dname))
2882 all_veto_files = False;
2888 SeekDir(dirptr,dirpos);
2889 while ((dname = ReadDirName(dirptr)))
2894 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2897 /* Construct the full name. */
2898 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2903 pstrcpy(fullname, directory);
2904 strcat(fullname, "/");
2905 strcat(fullname, dname);
2907 if(sys_lstat(fullname, &st) != 0)
2909 if(st.st_mode & S_IFDIR)
2911 if(lp_recursive_veto_delete(SNUM(cnum)))
2913 if(recursive_rmdir(fullname) != 0)
2916 if(sys_rmdir(fullname) != 0)
2919 else if(sys_unlink(fullname) != 0)
2923 /* Retry the rmdir */
2924 ok = (sys_rmdir(directory) == 0);
2934 DEBUG(3,("couldn't remove directory %s : %s\n",
2935 directory,strerror(errno)));
2940 if((errno == ENOENT) && bad_path)
2942 unix_ERR_class = ERRDOS;
2943 unix_ERR_code = ERRbadpath;
2945 return(UNIXERROR(ERRDOS,ERRbadpath));
2948 outsize = set_message(outbuf,0,0,True);
2950 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2956 /*******************************************************************
2957 resolve wildcards in a filename rename
2958 ********************************************************************/
2959 static BOOL resolve_wildcards(char *name1,char *name2)
2961 fstring root1,root2;
2965 name1 = strrchr(name1,'/');
2966 name2 = strrchr(name2,'/');
2968 if (!name1 || !name2) return(False);
2970 fstrcpy(root1,name1);
2971 fstrcpy(root2,name2);
2972 p = strrchr(root1,'.');
2979 p = strrchr(root2,'.');
3011 strcpy(name2,root2);
3020 /*******************************************************************
3021 check if a user is allowed to rename a file
3022 ********************************************************************/
3023 static BOOL can_rename(char *fname,int cnum)
3027 if (!CAN_WRITE(cnum)) return(False);
3029 if (sys_lstat(fname,&sbuf) != 0) return(False);
3030 if (!check_file_sharing(cnum,fname)) return(False);
3035 /****************************************************************************
3037 ****************************************************************************/
3038 int reply_mv(char *inbuf,char *outbuf)
3044 pstring mask,newname;
3045 pstring newname_last_component;
3048 int error = ERRnoaccess;
3051 BOOL bad_path1 = False;
3052 BOOL bad_path2 = False;
3054 *directory = *mask = 0;
3056 cnum = SVAL(inbuf,smb_tid);
3058 pstrcpy(name,smb_buf(inbuf) + 1);
3059 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3061 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3063 unix_convert(name,cnum,0,&bad_path1);
3064 unix_convert(newname,cnum,newname_last_component,&bad_path2);
3067 * Split the old name into directory and last component
3068 * strings. Note that unix_convert may have stripped off a
3069 * leading ./ from both name and newname if the rename is
3070 * at the root of the share. We need to make sure either both
3071 * name and newname contain a / character or neither of them do
3072 * as this is checked in resolve_wildcards().
3075 p = strrchr(name,'/');
3077 strcpy(directory,".");
3081 strcpy(directory,name);
3083 *p = '/'; /* Replace needed for exceptional test below. */
3086 if (is_mangled(mask))
3087 check_mangled_stack(mask);
3089 has_wild = strchr(mask,'*') || strchr(mask,'?');
3092 BOOL is_short_name = is_8_3(name, True);
3094 /* Add a terminating '/' to the directory name. */
3095 strcat(directory,"/");
3096 strcat(directory,mask);
3098 /* Ensure newname contains a '/' also */
3099 if(strrchr(newname,'/') == 0) {
3102 strcpy(tmpstr, "./");
3103 strcat(tmpstr, newname);
3104 strcpy(newname, tmpstr);
3107 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",
3108 case_sensitive, case_preserve, short_case_preserve, directory,
3109 newname, newname_last_component, is_short_name));
3112 * Check for special case with case preserving and not
3113 * case sensitive, if directory and newname are identical,
3114 * and the old last component differs from the original
3115 * last component only by case, then we should allow
3116 * the rename (user is trying to change the case of the
3119 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3120 ((short_case_preserve == True) && (is_short_name == True))) &&
3121 strcsequal(directory, newname)) {
3122 pstring newname_modified_last_component;
3125 * Get the last component of the modified name.
3126 * Note that we guarantee that newname contains a '/'
3129 p = strrchr(newname,'/');
3130 strcpy(newname_modified_last_component,p+1);
3132 if(strcsequal(newname_modified_last_component,
3133 newname_last_component) == False) {
3135 * Replace the modified last component with
3138 strcpy(p+1, newname_last_component);
3142 if (resolve_wildcards(directory,newname) &&
3143 can_rename(directory,cnum) &&
3144 !file_exist(newname,NULL) &&
3145 !sys_rename(directory,newname)) count++;
3147 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3148 directory,newname));
3150 if (!count) exists = file_exist(directory,NULL);
3151 if (!count && exists && file_exist(newname,NULL)) {
3156 void *dirptr = NULL;
3160 if (check_name(directory,cnum))
3161 dirptr = OpenDir(cnum, directory, True);
3167 if (strequal(mask,"????????.???"))
3170 while ((dname = ReadDirName(dirptr)))
3173 pstrcpy(fname,dname);
3175 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3177 error = ERRnoaccess;
3178 sprintf(fname,"%s/%s",directory,dname);
3179 if (!can_rename(fname,cnum)) {
3180 DEBUG(6,("rename %s refused\n", fname));
3183 pstrcpy(destname,newname);
3185 if (!resolve_wildcards(fname,destname)) {
3186 DEBUG(6,("resolve_wildcards %s %s failed\n",
3191 if (file_exist(destname,NULL)) {
3192 DEBUG(6,("file_exist %s\n",
3197 if (!sys_rename(fname,destname)) count++;
3198 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3206 return(ERROR(ERRDOS,error));
3209 if((errno == ENOENT) && (bad_path1 || bad_path2))
3211 unix_ERR_class = ERRDOS;
3212 unix_ERR_code = ERRbadpath;
3214 return(UNIXERROR(ERRDOS,error));
3218 outsize = set_message(outbuf,0,0,True);
3223 /*******************************************************************
3224 copy a file as part of a reply_copy
3225 ******************************************************************/
3226 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3227 int count,BOOL target_is_directory)
3235 pstrcpy(dest,dest1);
3236 if (target_is_directory) {
3237 char *p = strrchr(src,'/');
3246 if (!file_exist(src,&st)) return(False);
3248 fnum1 = find_free_file();
3249 if (fnum1<0) return(False);
3250 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3251 1,0,0,&Access,&action);
3253 if (!Files[fnum1].open) return(False);
3255 if (!target_is_directory && count)
3258 fnum2 = find_free_file();
3260 close_file(fnum1,False);
3263 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3264 ofun,st.st_mode,0,&Access,&action);
3266 if (!Files[fnum2].open) {
3267 close_file(fnum1,False);
3271 if ((ofun&3) == 1) {
3272 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3276 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3278 close_file(fnum1,False);
3279 close_file(fnum2,False);
3281 return(ret == st.st_size);
3286 /****************************************************************************
3287 reply to a file copy.
3288 ****************************************************************************/
3289 int reply_copy(char *inbuf,char *outbuf)
3295 pstring mask,newname;
3298 int error = ERRnoaccess;
3301 int tid2 = SVAL(inbuf,smb_vwv0);
3302 int ofun = SVAL(inbuf,smb_vwv1);
3303 int flags = SVAL(inbuf,smb_vwv2);
3304 BOOL target_is_directory=False;
3305 BOOL bad_path1 = False;
3306 BOOL bad_path2 = False;
3308 *directory = *mask = 0;
3310 cnum = SVAL(inbuf,smb_tid);
3312 pstrcpy(name,smb_buf(inbuf));
3313 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3315 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3318 /* can't currently handle inter share copies XXXX */
3319 DEBUG(3,("Rejecting inter-share copy\n"));
3320 return(ERROR(ERRSRV,ERRinvdevice));
3323 unix_convert(name,cnum,0,&bad_path1);
3324 unix_convert(newname,cnum,0,&bad_path2);
3326 target_is_directory = directory_exist(newname,NULL);
3328 if ((flags&1) && target_is_directory) {
3329 return(ERROR(ERRDOS,ERRbadfile));
3332 if ((flags&2) && !target_is_directory) {
3333 return(ERROR(ERRDOS,ERRbadpath));
3336 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3337 /* wants a tree copy! XXXX */
3338 DEBUG(3,("Rejecting tree copy\n"));
3339 return(ERROR(ERRSRV,ERRerror));
3342 p = strrchr(name,'/');
3344 strcpy(directory,"./");
3348 strcpy(directory,name);
3352 if (is_mangled(mask))
3353 check_mangled_stack(mask);
3355 has_wild = strchr(mask,'*') || strchr(mask,'?');
3358 strcat(directory,"/");
3359 strcat(directory,mask);
3360 if (resolve_wildcards(directory,newname) &&
3361 copy_file(directory,newname,cnum,ofun,
3362 count,target_is_directory)) count++;
3363 if (!count) exists = file_exist(directory,NULL);
3365 void *dirptr = NULL;
3369 if (check_name(directory,cnum))
3370 dirptr = OpenDir(cnum, directory, True);
3376 if (strequal(mask,"????????.???"))
3379 while ((dname = ReadDirName(dirptr)))
3382 pstrcpy(fname,dname);
3384 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3386 error = ERRnoaccess;
3387 sprintf(fname,"%s/%s",directory,dname);
3388 strcpy(destname,newname);
3389 if (resolve_wildcards(fname,destname) &&
3390 copy_file(directory,newname,cnum,ofun,
3391 count,target_is_directory)) count++;
3392 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3400 return(ERROR(ERRDOS,error));
3403 if((errno == ENOENT) && (bad_path1 || bad_path2))
3405 unix_ERR_class = ERRDOS;
3406 unix_ERR_code = ERRbadpath;
3408 return(UNIXERROR(ERRDOS,error));
3412 outsize = set_message(outbuf,1,0,True);
3413 SSVAL(outbuf,smb_vwv0,count);
3420 /****************************************************************************
3422 ****************************************************************************/
3423 int reply_setdir(char *inbuf,char *outbuf)
3430 cnum = SVAL(inbuf,smb_tid);
3432 snum = Connections[cnum].service;
3433 if (!CAN_SETDIR(snum))
3434 return(ERROR(ERRDOS,ERRnoaccess));
3436 pstrcpy(newdir,smb_buf(inbuf) + 1);
3439 if (strlen(newdir) == 0)
3443 ok = directory_exist(newdir,NULL);
3445 string_set(&Connections[cnum].connectpath,newdir);
3449 return(ERROR(ERRDOS,ERRbadpath));
3451 outsize = set_message(outbuf,0,0,True);
3452 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3454 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3460 /****************************************************************************
3461 reply to a lockingX request
3462 ****************************************************************************/
3463 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3465 int fnum = GETFNUM(inbuf,smb_vwv2);
3466 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3468 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3470 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3471 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3472 uint32 count, offset;
3477 uint32 ecode=0, dummy2;
3478 int eclass=0, dummy1;
3480 cnum = SVAL(inbuf,smb_tid);
3482 CHECK_FNUM(fnum,cnum);
3485 data = smb_buf(inbuf);
3487 /* Check if this is an oplock break on a file
3488 we have granted an oplock on.
3490 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3493 files_struct *fsp = &Files[fnum];
3494 uint32 dev = fsp->fd_ptr->dev;
3495 uint32 inode = fsp->fd_ptr->inode;
3497 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3500 * Make sure we have granted an oplock on this file.
3502 if(!fsp->granted_oplock)
3504 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3505 no oplock granted on this file.\n", fnum));
3506 return ERROR(ERRDOS,ERRlock);
3509 /* Remove the oplock flag from the sharemode. */
3510 lock_share_entry(fsp->cnum, dev, inode, &token);
3511 if(remove_share_oplock( fnum, token)==False) {
3512 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3513 dev = %x, inode = %x\n",
3515 unlock_share_entry(fsp->cnum, dev, inode, token);
3517 unlock_share_entry(fsp->cnum, dev, inode, token);
3519 /* Clear the granted flag and return. */
3520 fsp->granted_oplock = False;
3523 /* if this is a pure oplock break request then don't send a reply */
3524 if (num_locks == 0 && num_ulocks == 0)
3526 /* Sanity check - ensure a pure oplock break is not a
3528 if(CVAL(inbuf,smb_vwv0) != 0xff)
3529 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3530 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3535 /* Data now points at the beginning of the list
3536 of smb_unlkrng structs */
3537 for(i = 0; i < (int)num_ulocks; i++) {
3538 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3539 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3540 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3541 return ERROR(eclass,ecode);
3544 /* Now do any requested locks */
3545 data += 10*num_ulocks;
3546 /* Data now points at the beginning of the list
3547 of smb_lkrng structs */
3548 for(i = 0; i < (int)num_locks; i++) {
3549 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3550 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3551 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3555 /* If any of the above locks failed, then we must unlock
3556 all of the previous locks (X/Open spec). */
3557 if(i != num_locks && num_locks != 0) {
3558 for(; i >= 0; i--) {
3559 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3560 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3561 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3563 return ERROR(eclass,ecode);
3566 set_message(outbuf,2,0,True);
3568 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3569 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3573 return chain_reply(inbuf,outbuf,length,bufsize);
3577 /****************************************************************************
3578 reply to a SMBreadbmpx (read block multiplex) request
3579 ****************************************************************************/
3580 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3587 int outsize, mincount, maxcount;
3592 /* this function doesn't seem to work - disable by default */
3594 return(ERROR(ERRSRV,ERRuseSTD));
3596 outsize = set_message(outbuf,8,0,True);
3598 cnum = SVAL(inbuf,smb_tid);
3599 fnum = GETFNUM(inbuf,smb_vwv0);
3601 CHECK_FNUM(fnum,cnum);
3605 startpos = IVAL(inbuf,smb_vwv1);
3606 maxcount = SVAL(inbuf,smb_vwv3);
3607 mincount = SVAL(inbuf,smb_vwv4);
3609 data = smb_buf(outbuf);
3610 pad = ((long)data)%4;
3611 if (pad) pad = 4 - pad;
3614 max_per_packet = bufsize-(outsize+pad);
3618 if (is_locked(fnum,cnum,maxcount,startpos))
3619 return(ERROR(ERRDOS,ERRlock));
3623 int N = MIN(max_per_packet,tcount-total_read);
3625 nread = read_file(fnum,data,startpos,N);
3627 if (nread <= 0) nread = 0;
3630 tcount = total_read + nread;
3632 set_message(outbuf,8,nread,False);
3633 SIVAL(outbuf,smb_vwv0,startpos);
3634 SSVAL(outbuf,smb_vwv2,tcount);
3635 SSVAL(outbuf,smb_vwv6,nread);
3636 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3638 send_smb(Client,outbuf);
3640 total_read += nread;
3643 while (total_read < tcount);
3649 /****************************************************************************
3650 reply to a SMBwritebmpx (write block multiplex primary) request
3651 ****************************************************************************/
3652 int reply_writebmpx(char *inbuf,char *outbuf)
3654 int cnum,numtowrite,fnum;
3658 int tcount, write_through, smb_doff;
3661 cnum = SVAL(inbuf,smb_tid);
3662 fnum = GETFNUM(inbuf,smb_vwv0);
3664 CHECK_FNUM(fnum,cnum);
3668 tcount = SVAL(inbuf,smb_vwv1);
3669 startpos = IVAL(inbuf,smb_vwv3);
3670 write_through = BITSETW(inbuf+smb_vwv7,0);
3671 numtowrite = SVAL(inbuf,smb_vwv10);
3672 smb_doff = SVAL(inbuf,smb_vwv11);
3674 data = smb_base(inbuf) + smb_doff;
3676 /* If this fails we need to send an SMBwriteC response,
3677 not an SMBwritebmpx - set this up now so we don't forget */
3678 CVAL(outbuf,smb_com) = SMBwritec;
3680 if (is_locked(fnum,cnum,tcount,startpos))
3681 return(ERROR(ERRDOS,ERRlock));
3683 seek_file(fnum,startpos);
3684 nwritten = write_file(fnum,data,numtowrite);
3686 if(lp_syncalways(SNUM(cnum)) || write_through)
3689 if(nwritten < numtowrite)
3690 return(UNIXERROR(ERRHRD,ERRdiskfull));
3692 /* If the maximum to be written to this file
3693 is greater than what we just wrote then set
3694 up a secondary struct to be attached to this
3695 fd, we will use this to cache error messages etc. */
3696 if(tcount > nwritten)
3698 write_bmpx_struct *wbms;
3699 if(Files[fnum].wbmpx_ptr != NULL)
3700 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3702 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3705 DEBUG(0,("Out of memory in reply_readmpx\n"));
3706 return(ERROR(ERRSRV,ERRnoresource));
3708 wbms->wr_mode = write_through;
3709 wbms->wr_discard = False; /* No errors yet */
3710 wbms->wr_total_written = nwritten;
3711 wbms->wr_errclass = 0;
3713 Files[fnum].wbmpx_ptr = wbms;
3716 /* We are returning successfully, set the message type back to
3718 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3720 outsize = set_message(outbuf,1,0,True);
3722 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3724 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3725 timestring(),fnum,cnum,numtowrite,nwritten));
3727 if (write_through && tcount==nwritten) {
3728 /* we need to send both a primary and a secondary response */
3729 smb_setlen(outbuf,outsize - 4);
3730 send_smb(Client,outbuf);
3732 /* now the secondary */
3733 outsize = set_message(outbuf,1,0,True);
3734 CVAL(outbuf,smb_com) = SMBwritec;
3735 SSVAL(outbuf,smb_vwv0,nwritten);
3742 /****************************************************************************
3743 reply to a SMBwritebs (write block multiplex secondary) request
3744 ****************************************************************************/
3745 int reply_writebs(char *inbuf,char *outbuf)
3747 int cnum,numtowrite,fnum;
3751 int tcount, write_through, smb_doff;
3753 write_bmpx_struct *wbms;
3754 BOOL send_response = False;
3756 cnum = SVAL(inbuf,smb_tid);
3757 fnum = GETFNUM(inbuf,smb_vwv0);
3758 CHECK_FNUM(fnum,cnum);
3761 tcount = SVAL(inbuf,smb_vwv1);
3762 startpos = IVAL(inbuf,smb_vwv2);
3763 numtowrite = SVAL(inbuf,smb_vwv6);
3764 smb_doff = SVAL(inbuf,smb_vwv7);
3766 data = smb_base(inbuf) + smb_doff;
3768 /* We need to send an SMBwriteC response, not an SMBwritebs */
3769 CVAL(outbuf,smb_com) = SMBwritec;
3771 /* This fd should have an auxiliary struct attached,
3772 check that it does */
3773 wbms = Files[fnum].wbmpx_ptr;
3774 if(!wbms) return(-1);
3776 /* If write through is set we can return errors, else we must
3778 write_through = wbms->wr_mode;
3780 /* Check for an earlier error */
3781 if(wbms->wr_discard)
3782 return -1; /* Just discard the packet */
3784 seek_file(fnum,startpos);
3785 nwritten = write_file(fnum,data,numtowrite);
3787 if(lp_syncalways(SNUM(cnum)) || write_through)
3790 if (nwritten < numtowrite)
3793 /* We are returning an error - we can delete the aux struct */
3794 if (wbms) free((char *)wbms);
3795 Files[fnum].wbmpx_ptr = NULL;
3796 return(ERROR(ERRHRD,ERRdiskfull));
3798 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3801 /* Increment the total written, if this matches tcount
3802 we can discard the auxiliary struct (hurrah !) and return a writeC */
3803 wbms->wr_total_written += nwritten;
3804 if(wbms->wr_total_written >= tcount)
3806 if (write_through) {
3807 outsize = set_message(outbuf,1,0,True);
3808 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3809 send_response = True;
3813 Files[fnum].wbmpx_ptr = NULL;
3823 /****************************************************************************
3824 reply to a SMBsetattrE
3825 ****************************************************************************/
3826 int reply_setattrE(char *inbuf,char *outbuf)
3829 struct utimbuf unix_times;
3832 outsize = set_message(outbuf,0,0,True);
3834 cnum = SVAL(inbuf,smb_tid);
3835 fnum = GETFNUM(inbuf,smb_vwv0);
3837 CHECK_FNUM(fnum,cnum);
3840 /* Convert the DOS times into unix times. Ignore create
3841 time as UNIX can't set this.
3843 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3844 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3847 * Patch from Ray Frush <frush@engr.colostate.edu>
3848 * Sometimes times are sent as zero - ignore them.
3851 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3853 /* Ignore request */
3854 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3855 not setting timestamps of 0\n",
3856 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3859 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3861 /* set modify time = to access time if modify time was 0 */
3862 unix_times.modtime = unix_times.actime;
3865 /* Set the date on this file */
3866 if(file_utime(cnum, Files[fnum].name, &unix_times))
3867 return(ERROR(ERRDOS,ERRnoaccess));
3869 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3870 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3876 /****************************************************************************
3877 reply to a SMBgetattrE
3878 ****************************************************************************/
3879 int reply_getattrE(char *inbuf,char *outbuf)
3886 outsize = set_message(outbuf,11,0,True);
3888 cnum = SVAL(inbuf,smb_tid);
3889 fnum = GETFNUM(inbuf,smb_vwv0);
3891 CHECK_FNUM(fnum,cnum);
3894 /* Do an fstat on this file */
3895 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3896 return(UNIXERROR(ERRDOS,ERRnoaccess));
3898 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3900 /* Convert the times into dos times. Set create
3901 date to be last modify date as UNIX doesn't save
3903 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3904 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3905 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3908 SIVAL(outbuf,smb_vwv6,0);
3909 SIVAL(outbuf,smb_vwv8,0);
3913 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3914 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3916 SSVAL(outbuf,smb_vwv10, mode);
3918 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));