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 Files[fnum].reserved = False;
1195 return(UNIXERROR(ERRDOS,ERRnoaccess));
1198 unixmode = unix_mode(cnum,aARCH);
1200 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1201 oplock_request,&rmode,NULL);
1207 if((errno == ENOENT) && bad_path)
1209 unix_ERR_class = ERRDOS;
1210 unix_ERR_code = ERRbadpath;
1212 Files[fnum].reserved = False;
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 /* Breakout the oplock request bits so we can set the
1259 reply bits separately. */
1260 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1261 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1262 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1264 int open_flags = SVAL(inbuf,smb_vwv2);
1265 int smb_sattr = SVAL(inbuf,smb_vwv4);
1266 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1268 int smb_ofun = SVAL(inbuf,smb_vwv8);
1270 int size=0,fmode=0,mtime=0,rmode=0;
1273 BOOL bad_path = False;
1276 /* If it's an IPC, pass off the pipe handler. */
1278 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1280 /* XXXX we need to handle passed times, sattr and flags */
1282 pstrcpy(fname,smb_buf(inbuf));
1283 unix_convert(fname,cnum,0,&bad_path);
1285 fnum = find_free_file();
1287 return(ERROR(ERRSRV,ERRnofids));
1289 if (!check_name(fname,cnum))
1291 if((errno == ENOENT) && bad_path)
1293 unix_ERR_class = ERRDOS;
1294 unix_ERR_code = ERRbadpath;
1296 Files[fnum].reserved = False;
1297 return(UNIXERROR(ERRDOS,ERRnoaccess));
1300 unixmode = unix_mode(cnum,smb_attr | aARCH);
1302 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1303 oplock_request, &rmode,&smb_action);
1309 if((errno == ENOENT) && bad_path)
1311 unix_ERR_class = ERRDOS;
1312 unix_ERR_code = ERRbadpath;
1314 Files[fnum].reserved = False;
1315 return(UNIXERROR(ERRDOS,ERRnoaccess));
1318 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1319 close_file(fnum,False);
1320 return(ERROR(ERRDOS,ERRnoaccess));
1323 size = sbuf.st_size;
1324 fmode = dos_mode(cnum,fname,&sbuf);
1325 mtime = sbuf.st_mtime;
1327 close_file(fnum,False);
1328 return(ERROR(ERRDOS,ERRnoaccess));
1331 /* If the caller set the extended oplock request bit
1332 and we granted one (by whatever means) - set the
1333 correct bit for extended oplock reply.
1336 if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1337 smb_action |= EXTENDED_OPLOCK_GRANTED;
1340 if(ex_oplock_request && fsp->granted_oplock) {
1341 smb_action |= EXTENDED_OPLOCK_GRANTED;
1344 /* If the caller set the core oplock request bit
1345 and we granted one (by whatever means) - set the
1346 correct bit for core oplock reply.
1349 if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1350 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1353 if(core_oplock_request && fsp->granted_oplock) {
1354 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1357 set_message(outbuf,15,0,True);
1358 SSVAL(outbuf,smb_vwv2,fnum);
1359 SSVAL(outbuf,smb_vwv3,fmode);
1360 put_dos_date3(outbuf,smb_vwv4,mtime);
1361 SIVAL(outbuf,smb_vwv6,size);
1362 SSVAL(outbuf,smb_vwv8,rmode);
1363 SSVAL(outbuf,smb_vwv11,smb_action);
1367 return chain_reply(inbuf,outbuf,length,bufsize);
1371 /****************************************************************************
1372 reply to a SMBulogoffX
1373 ****************************************************************************/
1374 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1376 uint16 vuid = SVAL(inbuf,smb_uid);
1377 user_struct *vuser = get_valid_user_struct(vuid);
1380 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1383 /* in user level security we are supposed to close any files
1384 open by this user */
1385 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1387 for (i=0;i<MAX_OPEN_FILES;i++)
1388 if (Files[i].uid == vuser->uid && Files[i].open) {
1389 close_file(i,False);
1393 invalidate_vuid(vuid);
1395 set_message(outbuf,2,0,True);
1397 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1399 return chain_reply(inbuf,outbuf,length,bufsize);
1403 /****************************************************************************
1404 reply to a mknew or a create
1405 ****************************************************************************/
1406 int reply_mknew(char *inbuf,char *outbuf)
1415 BOOL bad_path = False;
1417 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1419 com = SVAL(inbuf,smb_com);
1420 cnum = SVAL(inbuf,smb_tid);
1422 createmode = SVAL(inbuf,smb_vwv0);
1423 pstrcpy(fname,smb_buf(inbuf)+1);
1424 unix_convert(fname,cnum,0,&bad_path);
1426 if (createmode & aVOLID)
1428 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1431 unixmode = unix_mode(cnum,createmode);
1433 fnum = find_free_file();
1435 return(ERROR(ERRSRV,ERRnofids));
1437 if (!check_name(fname,cnum))
1439 if((errno == ENOENT) && bad_path)
1441 unix_ERR_class = ERRDOS;
1442 unix_ERR_code = ERRbadpath;
1444 Files[fnum].reserved = False;
1445 return(UNIXERROR(ERRDOS,ERRnoaccess));
1450 /* We should fail if file exists. */
1455 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1459 /* Open file in dos compatibility share mode. */
1460 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1461 oplock_request, NULL, NULL);
1467 if((errno == ENOENT) && bad_path)
1469 unix_ERR_class = ERRDOS;
1470 unix_ERR_code = ERRbadpath;
1472 Files[fnum].reserved = False;
1473 return(UNIXERROR(ERRDOS,ERRnoaccess));
1476 outsize = set_message(outbuf,1,0,True);
1477 SSVAL(outbuf,smb_vwv0,fnum);
1479 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1480 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1483 if(fsp->granted_oplock)
1484 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1486 DEBUG(2,("new file %s\n",fname));
1487 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));
1493 /****************************************************************************
1494 reply to a create temporary file
1495 ****************************************************************************/
1496 int reply_ctemp(char *inbuf,char *outbuf)
1505 BOOL bad_path = False;
1507 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1509 cnum = SVAL(inbuf,smb_tid);
1510 createmode = SVAL(inbuf,smb_vwv0);
1511 pstrcpy(fname,smb_buf(inbuf)+1);
1512 strcat(fname,"/TMXXXXXX");
1513 unix_convert(fname,cnum,0,&bad_path);
1515 unixmode = unix_mode(cnum,createmode);
1517 fnum = find_free_file();
1519 return(ERROR(ERRSRV,ERRnofids));
1521 if (!check_name(fname,cnum))
1523 if((errno == ENOENT) && bad_path)
1525 unix_ERR_class = ERRDOS;
1526 unix_ERR_code = ERRbadpath;
1528 Files[fnum].reserved = False;
1529 return(UNIXERROR(ERRDOS,ERRnoaccess));
1532 strcpy(fname2,(char *)mktemp(fname));
1534 /* Open file in dos compatibility share mode. */
1535 /* We should fail if file exists. */
1536 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1537 oplock_request, NULL, NULL);
1543 if((errno == ENOENT) && bad_path)
1545 unix_ERR_class = ERRDOS;
1546 unix_ERR_code = ERRbadpath;
1548 Files[fnum].reserved = False;
1549 return(UNIXERROR(ERRDOS,ERRnoaccess));
1552 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1553 SSVAL(outbuf,smb_vwv0,fnum);
1554 CVAL(smb_buf(outbuf),0) = 4;
1555 strcpy(smb_buf(outbuf) + 1,fname2);
1557 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1558 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1561 if(fsp->granted_oplock)
1562 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1564 DEBUG(2,("created temp file %s\n",fname2));
1565 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));
1571 /*******************************************************************
1572 check if a user is allowed to delete a file
1573 ********************************************************************/
1574 static BOOL can_delete(char *fname,int cnum,int dirtype)
1579 if (!CAN_WRITE(cnum)) return(False);
1581 if (sys_lstat(fname,&sbuf) != 0) return(False);
1582 fmode = dos_mode(cnum,fname,&sbuf);
1583 if (fmode & aDIR) return(False);
1584 if (!lp_delete_readonly(SNUM(cnum))) {
1585 if (fmode & aRONLY) return(False);
1587 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1589 if (!check_file_sharing(cnum,fname)) return(False);
1593 /****************************************************************************
1595 ****************************************************************************/
1596 int reply_unlink(char *inbuf,char *outbuf)
1606 int error = ERRnoaccess;
1609 BOOL bad_path = False;
1611 *directory = *mask = 0;
1613 cnum = SVAL(inbuf,smb_tid);
1614 dirtype = SVAL(inbuf,smb_vwv0);
1616 pstrcpy(name,smb_buf(inbuf) + 1);
1618 DEBUG(3,("reply_unlink : %s\n",name));
1620 unix_convert(name,cnum,0,&bad_path);
1622 p = strrchr(name,'/');
1624 strcpy(directory,"./");
1628 strcpy(directory,name);
1632 if (is_mangled(mask))
1633 check_mangled_stack(mask);
1635 has_wild = strchr(mask,'*') || strchr(mask,'?');
1638 strcat(directory,"/");
1639 strcat(directory,mask);
1640 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1641 if (!count) exists = file_exist(directory,NULL);
1643 void *dirptr = NULL;
1646 if (check_name(directory,cnum))
1647 dirptr = OpenDir(cnum, directory, True);
1649 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1650 the pattern matches against the long name, otherwise the short name
1651 We don't implement this yet XXXX
1658 if (strequal(mask,"????????.???"))
1661 while ((dname = ReadDirName(dirptr)))
1664 pstrcpy(fname,dname);
1666 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1668 error = ERRnoaccess;
1669 sprintf(fname,"%s/%s",directory,dname);
1670 if (!can_delete(fname,cnum,dirtype)) continue;
1671 if (!sys_unlink(fname)) count++;
1672 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1680 return(ERROR(ERRDOS,error));
1683 if((errno == ENOENT) && bad_path)
1685 unix_ERR_class = ERRDOS;
1686 unix_ERR_code = ERRbadpath;
1688 return(UNIXERROR(ERRDOS,error));
1692 outsize = set_message(outbuf,0,0,True);
1698 /****************************************************************************
1699 reply to a readbraw (core+ protocol)
1700 ****************************************************************************/
1701 int reply_readbraw(char *inbuf, char *outbuf)
1703 int cnum,maxcount,mincount,fnum;
1706 char *header = outbuf;
1712 * Special check if an oplock break has been issued
1713 * and the readraw request croses on the wire, we must
1714 * return a zero length response here.
1717 if(global_oplock_break)
1719 _smb_setlen(header,0);
1720 transfer_file(0,Client,0,header,4,0);
1721 DEBUG(5,("readbraw - oplock break finished\n"));
1725 cnum = SVAL(inbuf,smb_tid);
1726 fnum = GETFNUM(inbuf,smb_vwv0);
1728 startpos = IVAL(inbuf,smb_vwv1);
1729 maxcount = SVAL(inbuf,smb_vwv3);
1730 mincount = SVAL(inbuf,smb_vwv4);
1732 /* ensure we don't overrun the packet size */
1733 maxcount = MIN(65535,maxcount);
1734 maxcount = MAX(mincount,maxcount);
1736 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1738 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1739 _smb_setlen(header,0);
1740 transfer_file(0,Client,0,header,4,0);
1745 fd = Files[fnum].fd_ptr->fd;
1746 fname = Files[fnum].name;
1750 if (!is_locked(fnum,cnum,maxcount,startpos))
1752 int size = Files[fnum].size;
1753 int sizeneeded = startpos + maxcount;
1755 if (size < sizeneeded) {
1757 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1759 if (!Files[fnum].can_write)
1760 Files[fnum].size = size;
1763 nread = MIN(maxcount,(int)(size - startpos));
1766 if (nread < mincount)
1769 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1772 maxcount,mincount,nread));
1777 _smb_setlen(header,nread);
1779 #if USE_READ_PREDICTION
1780 if (!Files[fnum].can_write)
1781 predict = read_predict(fd,startpos,header+4,NULL,nread);
1784 if ((nread-predict) > 0)
1785 seek_file(fnum,startpos + predict);
1787 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1792 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1793 fname,startpos,nread,ret));
1796 ret = read_file(fnum,header+4,startpos,nread);
1797 if (ret < mincount) ret = 0;
1799 _smb_setlen(header,ret);
1800 transfer_file(0,Client,0,header,4+ret,0);
1803 DEBUG(5,("readbraw finished\n"));
1808 /****************************************************************************
1809 reply to a lockread (core+ protocol)
1810 ****************************************************************************/
1811 int reply_lockread(char *inbuf,char *outbuf)
1817 uint32 startpos, numtoread;
1821 cnum = SVAL(inbuf,smb_tid);
1822 fnum = GETFNUM(inbuf,smb_vwv0);
1824 CHECK_FNUM(fnum,cnum);
1828 numtoread = SVAL(inbuf,smb_vwv1);
1829 startpos = IVAL(inbuf,smb_vwv2);
1831 outsize = set_message(outbuf,5,3,True);
1832 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1833 data = smb_buf(outbuf) + 3;
1835 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1836 return (ERROR(eclass,ecode));
1838 nread = read_file(fnum,data,startpos,numtoread);
1841 return(UNIXERROR(ERRDOS,ERRnoaccess));
1844 SSVAL(outbuf,smb_vwv0,nread);
1845 SSVAL(outbuf,smb_vwv5,nread+3);
1846 SSVAL(smb_buf(outbuf),1,nread);
1848 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1854 /****************************************************************************
1856 ****************************************************************************/
1857 int reply_read(char *inbuf,char *outbuf)
1859 int cnum,numtoread,fnum;
1865 cnum = SVAL(inbuf,smb_tid);
1866 fnum = GETFNUM(inbuf,smb_vwv0);
1868 CHECK_FNUM(fnum,cnum);
1872 numtoread = SVAL(inbuf,smb_vwv1);
1873 startpos = IVAL(inbuf,smb_vwv2);
1875 outsize = set_message(outbuf,5,3,True);
1876 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1877 data = smb_buf(outbuf) + 3;
1879 if (is_locked(fnum,cnum,numtoread,startpos))
1880 return(ERROR(ERRDOS,ERRlock));
1883 nread = read_file(fnum,data,startpos,numtoread);
1886 return(UNIXERROR(ERRDOS,ERRnoaccess));
1889 SSVAL(outbuf,smb_vwv0,nread);
1890 SSVAL(outbuf,smb_vwv5,nread+3);
1891 CVAL(smb_buf(outbuf),0) = 1;
1892 SSVAL(smb_buf(outbuf),1,nread);
1894 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1900 /****************************************************************************
1901 reply to a read and X
1902 ****************************************************************************/
1903 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1905 int fnum = GETFNUM(inbuf,smb_vwv2);
1906 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1907 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1908 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1914 cnum = SVAL(inbuf,smb_tid);
1916 CHECK_FNUM(fnum,cnum);
1920 set_message(outbuf,12,0,True);
1921 data = smb_buf(outbuf);
1923 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1924 return(ERROR(ERRDOS,ERRlock));
1925 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1929 return(UNIXERROR(ERRDOS,ERRnoaccess));
1931 SSVAL(outbuf,smb_vwv5,nread);
1932 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1933 SSVAL(smb_buf(outbuf),-2,nread);
1935 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1936 timestring(),fnum,cnum,
1937 smb_mincnt,smb_maxcnt,nread));
1941 return chain_reply(inbuf,outbuf,length,bufsize);
1945 /****************************************************************************
1946 reply to a writebraw (core+ or LANMAN1.0 protocol)
1947 ****************************************************************************/
1948 int reply_writebraw(char *inbuf,char *outbuf)
1951 int total_written=0;
1960 cnum = SVAL(inbuf,smb_tid);
1961 fnum = GETFNUM(inbuf,smb_vwv0);
1963 CHECK_FNUM(fnum,cnum);
1967 tcount = IVAL(inbuf,smb_vwv1);
1968 startpos = IVAL(inbuf,smb_vwv3);
1969 write_through = BITSETW(inbuf+smb_vwv7,0);
1971 /* We have to deal with slightly different formats depending
1972 on whether we are using the core+ or lanman1.0 protocol */
1973 if(Protocol <= PROTOCOL_COREPLUS) {
1974 numtowrite = SVAL(smb_buf(inbuf),-2);
1975 data = smb_buf(inbuf);
1977 numtowrite = SVAL(inbuf,smb_vwv10);
1978 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1981 /* force the error type */
1982 CVAL(inbuf,smb_com) = SMBwritec;
1983 CVAL(outbuf,smb_com) = SMBwritec;
1985 if (is_locked(fnum,cnum,tcount,startpos))
1986 return(ERROR(ERRDOS,ERRlock));
1988 if (seek_file(fnum,startpos) != startpos)
1989 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1992 nwritten = write_file(fnum,data,numtowrite);
1994 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1995 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1997 if (nwritten < numtowrite)
1998 return(UNIXERROR(ERRHRD,ERRdiskfull));
2000 total_written = nwritten;
2002 /* Return a message to the redirector to tell it
2003 to send more bytes */
2004 CVAL(outbuf,smb_com) = SMBwritebraw;
2005 SSVALS(outbuf,smb_vwv0,-1);
2006 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2007 send_smb(Client,outbuf);
2009 /* Now read the raw data into the buffer and write it */
2010 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2011 exit_server("secondary writebraw failed");
2014 /* Even though this is not an smb message, smb_len
2015 returns the generic length of an smb message */
2016 numtowrite = smb_len(inbuf);
2018 if (tcount > nwritten+numtowrite) {
2019 DEBUG(3,("Client overestimated the write %d %d %d\n",
2020 tcount,nwritten,numtowrite));
2023 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
2025 total_written += nwritten;
2027 /* Set up outbuf to return the correct return */
2028 outsize = set_message(outbuf,1,0,True);
2029 CVAL(outbuf,smb_com) = SMBwritec;
2030 SSVAL(outbuf,smb_vwv0,total_written);
2032 if (nwritten < numtowrite) {
2033 CVAL(outbuf,smb_rcls) = ERRHRD;
2034 SSVAL(outbuf,smb_err,ERRdiskfull);
2037 if (lp_syncalways(SNUM(cnum)) || write_through)
2040 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
2041 timestring(),fnum,cnum,startpos,numtowrite,total_written));
2043 /* we won't return a status if write through is not selected - this
2044 follows what WfWg does */
2045 if (!write_through && total_written==tcount)
2052 /****************************************************************************
2053 reply to a writeunlock (core+)
2054 ****************************************************************************/
2055 int reply_writeunlock(char *inbuf,char *outbuf)
2061 uint32 numtowrite,startpos;
2065 cnum = SVAL(inbuf,smb_tid);
2066 fnum = GETFNUM(inbuf,smb_vwv0);
2068 CHECK_FNUM(fnum,cnum);
2072 numtowrite = SVAL(inbuf,smb_vwv1);
2073 startpos = IVAL(inbuf,smb_vwv2);
2074 data = smb_buf(inbuf) + 3;
2076 if (is_locked(fnum,cnum,numtowrite,startpos))
2077 return(ERROR(ERRDOS,ERRlock));
2079 seek_file(fnum,startpos);
2081 /* The special X/Open SMB protocol handling of
2082 zero length writes is *NOT* done for
2087 nwritten = write_file(fnum,data,numtowrite);
2089 if (lp_syncalways(SNUM(cnum)))
2092 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2093 return(UNIXERROR(ERRDOS,ERRnoaccess));
2095 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2096 return(ERROR(eclass,ecode));
2098 outsize = set_message(outbuf,1,0,True);
2100 SSVAL(outbuf,smb_vwv0,nwritten);
2102 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2103 timestring(),fnum,cnum,numtowrite,nwritten));
2109 /****************************************************************************
2111 ****************************************************************************/
2112 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
2114 int cnum,numtowrite,fnum;
2123 cnum = SVAL(inbuf,smb_tid);
2124 fnum = GETFNUM(inbuf,smb_vwv0);
2126 CHECK_FNUM(fnum,cnum);
2130 numtowrite = SVAL(inbuf,smb_vwv1);
2131 startpos = IVAL(inbuf,smb_vwv2);
2132 data = smb_buf(inbuf) + 3;
2134 if (is_locked(fnum,cnum,numtowrite,startpos))
2135 return(ERROR(ERRDOS,ERRlock));
2137 seek_file(fnum,startpos);
2139 /* X/Open SMB protocol says that if smb_vwv1 is
2140 zero then the file size should be extended or
2141 truncated to the size given in smb_vwv[2-3] */
2143 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2145 nwritten = write_file(fnum,data,numtowrite);
2147 if (lp_syncalways(SNUM(cnum)))
2150 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2151 return(UNIXERROR(ERRDOS,ERRnoaccess));
2153 outsize = set_message(outbuf,1,0,True);
2155 SSVAL(outbuf,smb_vwv0,nwritten);
2157 if (nwritten < numtowrite) {
2158 CVAL(outbuf,smb_rcls) = ERRHRD;
2159 SSVAL(outbuf,smb_err,ERRdiskfull);
2162 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2168 /****************************************************************************
2169 reply to a write and X
2170 ****************************************************************************/
2171 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2173 int fnum = GETFNUM(inbuf,smb_vwv2);
2174 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2175 int smb_dsize = SVAL(inbuf,smb_vwv10);
2176 int smb_doff = SVAL(inbuf,smb_vwv11);
2177 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2182 cnum = SVAL(inbuf,smb_tid);
2184 CHECK_FNUM(fnum,cnum);
2188 data = smb_base(inbuf) + smb_doff;
2190 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2191 return(ERROR(ERRDOS,ERRlock));
2193 seek_file(fnum,smb_offs);
2195 /* X/Open SMB protocol says that, unlike SMBwrite
2196 if the length is zero then NO truncation is
2197 done, just a write of zero. To truncate a file,
2202 nwritten = write_file(fnum,data,smb_dsize);
2204 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2205 return(UNIXERROR(ERRDOS,ERRnoaccess));
2207 set_message(outbuf,6,0,True);
2209 SSVAL(outbuf,smb_vwv2,nwritten);
2211 if (nwritten < smb_dsize) {
2212 CVAL(outbuf,smb_rcls) = ERRHRD;
2213 SSVAL(outbuf,smb_err,ERRdiskfull);
2216 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2220 if (lp_syncalways(SNUM(cnum)) || write_through)
2223 return chain_reply(inbuf,outbuf,length,bufsize);
2227 /****************************************************************************
2229 ****************************************************************************/
2230 int reply_lseek(char *inbuf,char *outbuf)
2238 cnum = SVAL(inbuf,smb_tid);
2239 fnum = GETFNUM(inbuf,smb_vwv0);
2241 CHECK_FNUM(fnum,cnum);
2244 mode = SVAL(inbuf,smb_vwv1) & 3;
2245 startpos = IVAL(inbuf,smb_vwv2);
2249 case 0: umode = SEEK_SET; break;
2250 case 1: umode = SEEK_CUR; break;
2251 case 2: umode = SEEK_END; break;
2253 umode = SEEK_SET; break;
2256 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2257 Files[fnum].pos = res;
2259 outsize = set_message(outbuf,2,0,True);
2260 SIVALS(outbuf,smb_vwv0,res);
2262 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2268 /****************************************************************************
2270 ****************************************************************************/
2271 int reply_flush(char *inbuf,char *outbuf)
2274 int outsize = set_message(outbuf,0,0,True);
2276 cnum = SVAL(inbuf,smb_tid);
2277 fnum = GETFNUM(inbuf,smb_vwv0);
2279 if (fnum != 0xFFFF) {
2280 CHECK_FNUM(fnum,cnum);
2287 for (i=0;i<MAX_OPEN_FILES;i++)
2294 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2299 /****************************************************************************
2301 ****************************************************************************/
2302 int reply_exit(char *inbuf,char *outbuf)
2304 int outsize = set_message(outbuf,0,0,True);
2305 DEBUG(3,("%s exit\n",timestring()));
2311 /****************************************************************************
2313 ****************************************************************************/
2314 int reply_close(char *inbuf,char *outbuf)
2319 int32 eclass = 0, err = 0;
2321 outsize = set_message(outbuf,0,0,True);
2323 cnum = SVAL(inbuf,smb_tid);
2325 /* If it's an IPC, pass off to the pipe handler. */
2327 return reply_pipe_close(inbuf,outbuf);
2329 fnum = GETFNUM(inbuf,smb_vwv0);
2331 CHECK_FNUM(fnum,cnum);
2333 if(HAS_CACHED_ERROR(fnum)) {
2334 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2335 err = Files[fnum].wbmpx_ptr->wr_error;
2338 mtime = make_unix_date3(inbuf+smb_vwv1);
2340 /* try and set the date */
2341 set_filetime(cnum, Files[fnum].name,mtime);
2343 close_file(fnum,True);
2345 /* We have a cached error */
2347 return(ERROR(eclass,err));
2349 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2350 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2351 Connections[cnum].num_files_open));
2357 /****************************************************************************
2358 reply to a writeclose (Core+ protocol)
2359 ****************************************************************************/
2360 int reply_writeclose(char *inbuf,char *outbuf)
2362 int cnum,numtowrite,fnum;
2369 cnum = SVAL(inbuf,smb_tid);
2370 fnum = GETFNUM(inbuf,smb_vwv0);
2372 CHECK_FNUM(fnum,cnum);
2376 numtowrite = SVAL(inbuf,smb_vwv1);
2377 startpos = IVAL(inbuf,smb_vwv2);
2378 mtime = make_unix_date3(inbuf+smb_vwv4);
2379 data = smb_buf(inbuf) + 1;
2381 if (is_locked(fnum,cnum,numtowrite,startpos))
2382 return(ERROR(ERRDOS,ERRlock));
2384 seek_file(fnum,startpos);
2386 nwritten = write_file(fnum,data,numtowrite);
2388 set_filetime(cnum, Files[fnum].name,mtime);
2390 close_file(fnum,True);
2392 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2393 timestring(),fnum,cnum,numtowrite,nwritten,
2394 Connections[cnum].num_files_open));
2397 return(UNIXERROR(ERRDOS,ERRnoaccess));
2399 outsize = set_message(outbuf,1,0,True);
2401 SSVAL(outbuf,smb_vwv0,nwritten);
2406 /****************************************************************************
2408 ****************************************************************************/
2409 int reply_lock(char *inbuf,char *outbuf)
2412 int outsize = set_message(outbuf,0,0,True);
2413 uint32 count,offset;
2417 cnum = SVAL(inbuf,smb_tid);
2418 fnum = GETFNUM(inbuf,smb_vwv0);
2420 CHECK_FNUM(fnum,cnum);
2423 count = IVAL(inbuf,smb_vwv1);
2424 offset = IVAL(inbuf,smb_vwv3);
2426 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));
2428 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2429 return (ERROR(eclass,ecode));
2435 /****************************************************************************
2437 ****************************************************************************/
2438 int reply_unlock(char *inbuf,char *outbuf)
2441 int outsize = set_message(outbuf,0,0,True);
2442 uint32 count,offset;
2446 cnum = SVAL(inbuf,smb_tid);
2447 fnum = GETFNUM(inbuf,smb_vwv0);
2449 CHECK_FNUM(fnum,cnum);
2452 count = IVAL(inbuf,smb_vwv1);
2453 offset = IVAL(inbuf,smb_vwv3);
2455 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2456 return (ERROR(eclass,ecode));
2458 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));
2464 /****************************************************************************
2466 ****************************************************************************/
2467 int reply_tdis(char *inbuf,char *outbuf)
2470 int outsize = set_message(outbuf,0,0,True);
2473 cnum = SVAL(inbuf,smb_tid);
2474 vuid = SVAL(inbuf,smb_uid);
2476 if (!OPEN_CNUM(cnum)) {
2477 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2478 return(ERROR(ERRSRV,ERRinvnid));
2481 Connections[cnum].used = False;
2483 close_cnum(cnum,vuid);
2485 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2492 /****************************************************************************
2494 ****************************************************************************/
2495 int reply_echo(char *inbuf,char *outbuf)
2498 int smb_reverb = SVAL(inbuf,smb_vwv0);
2500 int data_len = smb_buflen(inbuf);
2501 int outsize = set_message(outbuf,1,data_len,True);
2503 cnum = SVAL(inbuf,smb_tid);
2505 /* According to the latest CIFS spec we shouldn't
2506 care what the TID is.
2510 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2512 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2513 return(ERROR(ERRSRV,ERRinvnid));
2517 /* copy any incoming data back out */
2519 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2521 if (smb_reverb > 100)
2523 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2527 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2529 SSVAL(outbuf,smb_vwv0,seq_num);
2531 smb_setlen(outbuf,outsize - 4);
2533 send_smb(Client,outbuf);
2536 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2542 /****************************************************************************
2543 reply to a printopen
2544 ****************************************************************************/
2545 int reply_printopen(char *inbuf,char *outbuf)
2553 *fname = *fname2 = 0;
2555 cnum = SVAL(inbuf,smb_tid);
2557 if (!CAN_PRINT(cnum))
2558 return(ERROR(ERRDOS,ERRnoaccess));
2563 pstrcpy(s,smb_buf(inbuf)+1);
2567 if (!(isalnum(*p) || strchr("._-",*p)))
2572 if (strlen(s) > 10) s[10] = 0;
2574 sprintf(fname,"%s.XXXXXX",s);
2577 fnum = find_free_file();
2579 return(ERROR(ERRSRV,ERRnofids));
2581 strcpy(fname2,(char *)mktemp(fname));
2583 if (!check_name(fname2,cnum)) {
2584 Files[fnum].reserved = False;
2585 return(ERROR(ERRDOS,ERRnoaccess));
2588 /* Open for exclusive use, write only. */
2589 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2592 if (!Files[fnum].open) {
2593 Files[fnum].reserved = False;
2594 return(UNIXERROR(ERRDOS,ERRnoaccess));
2597 /* force it to be a print file */
2598 Files[fnum].print_file = True;
2600 outsize = set_message(outbuf,1,0,True);
2601 SSVAL(outbuf,smb_vwv0,fnum);
2603 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2609 /****************************************************************************
2610 reply to a printclose
2611 ****************************************************************************/
2612 int reply_printclose(char *inbuf,char *outbuf)
2615 int outsize = set_message(outbuf,0,0,True);
2617 cnum = SVAL(inbuf,smb_tid);
2618 fnum = GETFNUM(inbuf,smb_vwv0);
2620 CHECK_FNUM(fnum,cnum);
2623 if (!CAN_PRINT(cnum))
2624 return(ERROR(ERRDOS,ERRnoaccess));
2626 close_file(fnum,True);
2628 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2634 /****************************************************************************
2635 reply to a printqueue
2636 ****************************************************************************/
2637 int reply_printqueue(char *inbuf,char *outbuf)
2640 int outsize = set_message(outbuf,2,3,True);
2641 int max_count = SVAL(inbuf,smb_vwv0);
2642 int start_index = SVAL(inbuf,smb_vwv1);
2645 cnum = SVAL(inbuf,smb_tid);
2646 vuid = SVAL(inbuf,smb_uid);
2648 /* allow checking the queue for anyone */
2650 if (!CAN_PRINT(cnum))
2651 return(ERROR(ERRDOS,ERRnoaccess));
2654 SSVAL(outbuf,smb_vwv0,0);
2655 SSVAL(outbuf,smb_vwv1,0);
2656 CVAL(smb_buf(outbuf),0) = 1;
2657 SSVAL(smb_buf(outbuf),1,0);
2659 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2660 timestring(),cnum,start_index,max_count));
2662 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2667 for (i=0;i<MAX_CONNECTIONS;i++)
2668 if (CAN_PRINT(i) && Connections[i].printer)
2672 for (i=0;i<MAX_CONNECTIONS;i++)
2676 if (!OPEN_CNUM(cnum))
2677 return(ERROR(ERRSRV,ERRinvnid));
2679 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2682 if (!become_user(&Connections[cnum], cnum, vuid))
2683 return(ERROR(ERRSRV,ERRinvnid));
2686 print_queue_struct *queue = NULL;
2687 char *p = smb_buf(outbuf) + 3;
2688 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2689 int num_to_get = ABS(max_count);
2690 int first = (max_count>0?start_index:start_index+max_count+1);
2696 num_to_get = MIN(num_to_get,count-first);
2699 for (i=first;i<first+num_to_get;i++)
2701 put_dos_date2(p,0,queue[i].time);
2702 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2703 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2704 SIVAL(p,7,queue[i].size);
2706 StrnCpy(p+12,queue[i].user,16);
2712 outsize = set_message(outbuf,2,28*count+3,False);
2713 SSVAL(outbuf,smb_vwv0,count);
2714 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2715 CVAL(smb_buf(outbuf),0) = 1;
2716 SSVAL(smb_buf(outbuf),1,28*count);
2719 if (queue) free(queue);
2721 DEBUG(3,("%d entries returned in queue\n",count));
2728 /****************************************************************************
2729 reply to a printwrite
2730 ****************************************************************************/
2731 int reply_printwrite(char *inbuf,char *outbuf)
2733 int cnum,numtowrite,fnum;
2734 int outsize = set_message(outbuf,0,0,True);
2737 cnum = SVAL(inbuf,smb_tid);
2739 if (!CAN_PRINT(cnum))
2740 return(ERROR(ERRDOS,ERRnoaccess));
2742 fnum = GETFNUM(inbuf,smb_vwv0);
2744 CHECK_FNUM(fnum,cnum);
2748 numtowrite = SVAL(smb_buf(inbuf),1);
2749 data = smb_buf(inbuf) + 3;
2751 if (write_file(fnum,data,numtowrite) != numtowrite)
2752 return(UNIXERROR(ERRDOS,ERRnoaccess));
2754 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2760 /****************************************************************************
2762 ****************************************************************************/
2763 int reply_mkdir(char *inbuf,char *outbuf)
2767 int outsize,ret= -1;
2768 BOOL bad_path = False;
2770 pstrcpy(directory,smb_buf(inbuf) + 1);
2771 cnum = SVAL(inbuf,smb_tid);
2772 unix_convert(directory,cnum,0,&bad_path);
2774 if (check_name(directory,cnum))
2775 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2779 if((errno == ENOENT) && bad_path)
2781 unix_ERR_class = ERRDOS;
2782 unix_ERR_code = ERRbadpath;
2784 return(UNIXERROR(ERRDOS,ERRnoaccess));
2787 outsize = set_message(outbuf,0,0,True);
2789 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2794 /****************************************************************************
2795 Static function used by reply_rmdir to delete an entire directory
2797 ****************************************************************************/
2798 static BOOL recursive_rmdir(char *directory)
2802 void *dirptr = OpenDir(-1, directory, False);
2807 while((dname = ReadDirName(dirptr)))
2812 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2815 /* Construct the full name. */
2816 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2822 strcpy(fullname, directory);
2823 strcat(fullname, "/");
2824 strcat(fullname, dname);
2826 if(sys_lstat(fullname, &st) != 0)
2832 if(st.st_mode & S_IFDIR)
2834 if(recursive_rmdir(fullname)!=0)
2839 if(sys_rmdir(fullname) != 0)
2845 else if(sys_unlink(fullname) != 0)
2855 /****************************************************************************
2857 ****************************************************************************/
2858 int reply_rmdir(char *inbuf,char *outbuf)
2864 BOOL bad_path = False;
2866 cnum = SVAL(inbuf,smb_tid);
2867 pstrcpy(directory,smb_buf(inbuf) + 1);
2868 unix_convert(directory,cnum,0,&bad_path);
2870 if (check_name(directory,cnum))
2873 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2874 ok = (sys_rmdir(directory) == 0);
2875 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2877 /* Check to see if the only thing in this directory are
2878 vetoed files/directories. If so then delete them and
2879 retry. If we fail to delete any of them (and we *don't*
2880 do a recursive delete) then fail the rmdir. */
2881 BOOL all_veto_files = True;
2883 void *dirptr = OpenDir(cnum, directory, False);
2887 int dirpos = TellDir(dirptr);
2888 while ((dname = ReadDirName(dirptr)))
2890 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2892 if(!IS_VETO_PATH(cnum, dname))
2894 all_veto_files = False;
2900 SeekDir(dirptr,dirpos);
2901 while ((dname = ReadDirName(dirptr)))
2906 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2909 /* Construct the full name. */
2910 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2915 pstrcpy(fullname, directory);
2916 strcat(fullname, "/");
2917 strcat(fullname, dname);
2919 if(sys_lstat(fullname, &st) != 0)
2921 if(st.st_mode & S_IFDIR)
2923 if(lp_recursive_veto_delete(SNUM(cnum)))
2925 if(recursive_rmdir(fullname) != 0)
2928 if(sys_rmdir(fullname) != 0)
2931 else if(sys_unlink(fullname) != 0)
2935 /* Retry the rmdir */
2936 ok = (sys_rmdir(directory) == 0);
2946 DEBUG(3,("couldn't remove directory %s : %s\n",
2947 directory,strerror(errno)));
2952 if((errno == ENOENT) && bad_path)
2954 unix_ERR_class = ERRDOS;
2955 unix_ERR_code = ERRbadpath;
2957 return(UNIXERROR(ERRDOS,ERRbadpath));
2960 outsize = set_message(outbuf,0,0,True);
2962 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2968 /*******************************************************************
2969 resolve wildcards in a filename rename
2970 ********************************************************************/
2971 static BOOL resolve_wildcards(char *name1,char *name2)
2973 fstring root1,root2;
2977 name1 = strrchr(name1,'/');
2978 name2 = strrchr(name2,'/');
2980 if (!name1 || !name2) return(False);
2982 fstrcpy(root1,name1);
2983 fstrcpy(root2,name2);
2984 p = strrchr(root1,'.');
2991 p = strrchr(root2,'.');
3023 strcpy(name2,root2);
3032 /*******************************************************************
3033 check if a user is allowed to rename a file
3034 ********************************************************************/
3035 static BOOL can_rename(char *fname,int cnum)
3039 if (!CAN_WRITE(cnum)) return(False);
3041 if (sys_lstat(fname,&sbuf) != 0) return(False);
3042 if (!check_file_sharing(cnum,fname)) return(False);
3047 /****************************************************************************
3049 ****************************************************************************/
3050 int reply_mv(char *inbuf,char *outbuf)
3056 pstring mask,newname;
3057 pstring newname_last_component;
3060 int error = ERRnoaccess;
3063 BOOL bad_path1 = False;
3064 BOOL bad_path2 = False;
3066 *directory = *mask = 0;
3068 cnum = SVAL(inbuf,smb_tid);
3070 pstrcpy(name,smb_buf(inbuf) + 1);
3071 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3073 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3075 unix_convert(name,cnum,0,&bad_path1);
3076 unix_convert(newname,cnum,newname_last_component,&bad_path2);
3079 * Split the old name into directory and last component
3080 * strings. Note that unix_convert may have stripped off a
3081 * leading ./ from both name and newname if the rename is
3082 * at the root of the share. We need to make sure either both
3083 * name and newname contain a / character or neither of them do
3084 * as this is checked in resolve_wildcards().
3087 p = strrchr(name,'/');
3089 strcpy(directory,".");
3093 strcpy(directory,name);
3095 *p = '/'; /* Replace needed for exceptional test below. */
3098 if (is_mangled(mask))
3099 check_mangled_stack(mask);
3101 has_wild = strchr(mask,'*') || strchr(mask,'?');
3104 BOOL is_short_name = is_8_3(name, True);
3106 /* Add a terminating '/' to the directory name. */
3107 strcat(directory,"/");
3108 strcat(directory,mask);
3110 /* Ensure newname contains a '/' also */
3111 if(strrchr(newname,'/') == 0) {
3114 strcpy(tmpstr, "./");
3115 strcat(tmpstr, newname);
3116 strcpy(newname, tmpstr);
3119 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",
3120 case_sensitive, case_preserve, short_case_preserve, directory,
3121 newname, newname_last_component, is_short_name));
3124 * Check for special case with case preserving and not
3125 * case sensitive, if directory and newname are identical,
3126 * and the old last component differs from the original
3127 * last component only by case, then we should allow
3128 * the rename (user is trying to change the case of the
3131 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3132 ((short_case_preserve == True) && (is_short_name == True))) &&
3133 strcsequal(directory, newname)) {
3134 pstring newname_modified_last_component;
3137 * Get the last component of the modified name.
3138 * Note that we guarantee that newname contains a '/'
3141 p = strrchr(newname,'/');
3142 strcpy(newname_modified_last_component,p+1);
3144 if(strcsequal(newname_modified_last_component,
3145 newname_last_component) == False) {
3147 * Replace the modified last component with
3150 strcpy(p+1, newname_last_component);
3154 if (resolve_wildcards(directory,newname) &&
3155 can_rename(directory,cnum) &&
3156 !file_exist(newname,NULL) &&
3157 !sys_rename(directory,newname)) count++;
3159 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3160 directory,newname));
3162 if (!count) exists = file_exist(directory,NULL);
3163 if (!count && exists && file_exist(newname,NULL)) {
3168 void *dirptr = NULL;
3172 if (check_name(directory,cnum))
3173 dirptr = OpenDir(cnum, directory, True);
3179 if (strequal(mask,"????????.???"))
3182 while ((dname = ReadDirName(dirptr)))
3185 pstrcpy(fname,dname);
3187 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3189 error = ERRnoaccess;
3190 sprintf(fname,"%s/%s",directory,dname);
3191 if (!can_rename(fname,cnum)) {
3192 DEBUG(6,("rename %s refused\n", fname));
3195 pstrcpy(destname,newname);
3197 if (!resolve_wildcards(fname,destname)) {
3198 DEBUG(6,("resolve_wildcards %s %s failed\n",
3203 if (file_exist(destname,NULL)) {
3204 DEBUG(6,("file_exist %s\n",
3209 if (!sys_rename(fname,destname)) count++;
3210 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3218 return(ERROR(ERRDOS,error));
3221 if((errno == ENOENT) && (bad_path1 || bad_path2))
3223 unix_ERR_class = ERRDOS;
3224 unix_ERR_code = ERRbadpath;
3226 return(UNIXERROR(ERRDOS,error));
3230 outsize = set_message(outbuf,0,0,True);
3235 /*******************************************************************
3236 copy a file as part of a reply_copy
3237 ******************************************************************/
3238 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3239 int count,BOOL target_is_directory)
3247 pstrcpy(dest,dest1);
3248 if (target_is_directory) {
3249 char *p = strrchr(src,'/');
3258 if (!file_exist(src,&st)) return(False);
3260 fnum1 = find_free_file();
3261 if (fnum1<0) return(False);
3262 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3263 1,0,0,&Access,&action);
3265 if (!Files[fnum1].open) {
3266 Files[fnum1].reserved = False;
3270 if (!target_is_directory && count)
3273 fnum2 = find_free_file();
3275 close_file(fnum1,False);
3278 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3279 ofun,st.st_mode,0,&Access,&action);
3281 if (!Files[fnum2].open) {
3282 close_file(fnum1,False);
3283 Files[fnum2].reserved = False;
3287 if ((ofun&3) == 1) {
3288 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3292 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3294 close_file(fnum1,False);
3295 close_file(fnum2,False);
3297 return(ret == st.st_size);
3302 /****************************************************************************
3303 reply to a file copy.
3304 ****************************************************************************/
3305 int reply_copy(char *inbuf,char *outbuf)
3311 pstring mask,newname;
3314 int error = ERRnoaccess;
3317 int tid2 = SVAL(inbuf,smb_vwv0);
3318 int ofun = SVAL(inbuf,smb_vwv1);
3319 int flags = SVAL(inbuf,smb_vwv2);
3320 BOOL target_is_directory=False;
3321 BOOL bad_path1 = False;
3322 BOOL bad_path2 = False;
3324 *directory = *mask = 0;
3326 cnum = SVAL(inbuf,smb_tid);
3328 pstrcpy(name,smb_buf(inbuf));
3329 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3331 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3334 /* can't currently handle inter share copies XXXX */
3335 DEBUG(3,("Rejecting inter-share copy\n"));
3336 return(ERROR(ERRSRV,ERRinvdevice));
3339 unix_convert(name,cnum,0,&bad_path1);
3340 unix_convert(newname,cnum,0,&bad_path2);
3342 target_is_directory = directory_exist(newname,NULL);
3344 if ((flags&1) && target_is_directory) {
3345 return(ERROR(ERRDOS,ERRbadfile));
3348 if ((flags&2) && !target_is_directory) {
3349 return(ERROR(ERRDOS,ERRbadpath));
3352 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3353 /* wants a tree copy! XXXX */
3354 DEBUG(3,("Rejecting tree copy\n"));
3355 return(ERROR(ERRSRV,ERRerror));
3358 p = strrchr(name,'/');
3360 strcpy(directory,"./");
3364 strcpy(directory,name);
3368 if (is_mangled(mask))
3369 check_mangled_stack(mask);
3371 has_wild = strchr(mask,'*') || strchr(mask,'?');
3374 strcat(directory,"/");
3375 strcat(directory,mask);
3376 if (resolve_wildcards(directory,newname) &&
3377 copy_file(directory,newname,cnum,ofun,
3378 count,target_is_directory)) count++;
3379 if (!count) exists = file_exist(directory,NULL);
3381 void *dirptr = NULL;
3385 if (check_name(directory,cnum))
3386 dirptr = OpenDir(cnum, directory, True);
3392 if (strequal(mask,"????????.???"))
3395 while ((dname = ReadDirName(dirptr)))
3398 pstrcpy(fname,dname);
3400 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3402 error = ERRnoaccess;
3403 sprintf(fname,"%s/%s",directory,dname);
3404 strcpy(destname,newname);
3405 if (resolve_wildcards(fname,destname) &&
3406 copy_file(directory,newname,cnum,ofun,
3407 count,target_is_directory)) count++;
3408 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3416 return(ERROR(ERRDOS,error));
3419 if((errno == ENOENT) && (bad_path1 || bad_path2))
3421 unix_ERR_class = ERRDOS;
3422 unix_ERR_code = ERRbadpath;
3424 return(UNIXERROR(ERRDOS,error));
3428 outsize = set_message(outbuf,1,0,True);
3429 SSVAL(outbuf,smb_vwv0,count);
3436 /****************************************************************************
3438 ****************************************************************************/
3439 int reply_setdir(char *inbuf,char *outbuf)
3446 cnum = SVAL(inbuf,smb_tid);
3448 snum = Connections[cnum].service;
3449 if (!CAN_SETDIR(snum))
3450 return(ERROR(ERRDOS,ERRnoaccess));
3452 pstrcpy(newdir,smb_buf(inbuf) + 1);
3455 if (strlen(newdir) == 0)
3459 ok = directory_exist(newdir,NULL);
3461 string_set(&Connections[cnum].connectpath,newdir);
3465 return(ERROR(ERRDOS,ERRbadpath));
3467 outsize = set_message(outbuf,0,0,True);
3468 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3470 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3476 /****************************************************************************
3477 reply to a lockingX request
3478 ****************************************************************************/
3479 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3481 int fnum = GETFNUM(inbuf,smb_vwv2);
3482 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3484 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3486 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3487 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3488 uint32 count, offset;
3493 uint32 ecode=0, dummy2;
3494 int eclass=0, dummy1;
3496 cnum = SVAL(inbuf,smb_tid);
3498 CHECK_FNUM(fnum,cnum);
3501 data = smb_buf(inbuf);
3503 /* Check if this is an oplock break on a file
3504 we have granted an oplock on.
3506 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3509 files_struct *fsp = &Files[fnum];
3510 uint32 dev = fsp->fd_ptr->dev;
3511 uint32 inode = fsp->fd_ptr->inode;
3513 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3516 * Make sure we have granted an oplock on this file.
3518 if(!fsp->granted_oplock)
3520 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3521 no oplock granted on this file.\n", fnum));
3522 return ERROR(ERRDOS,ERRlock);
3525 /* Remove the oplock flag from the sharemode. */
3526 lock_share_entry(fsp->cnum, dev, inode, &token);
3527 if(remove_share_oplock( fnum, token)==False) {
3528 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3529 dev = %x, inode = %x\n",
3531 unlock_share_entry(fsp->cnum, dev, inode, token);
3533 unlock_share_entry(fsp->cnum, dev, inode, token);
3535 /* Clear the granted flag and return. */
3536 fsp->granted_oplock = False;
3539 /* if this is a pure oplock break request then don't send a reply */
3540 if (num_locks == 0 && num_ulocks == 0)
3542 /* Sanity check - ensure a pure oplock break is not a
3544 if(CVAL(inbuf,smb_vwv0) != 0xff)
3545 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3546 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3551 /* Data now points at the beginning of the list
3552 of smb_unlkrng structs */
3553 for(i = 0; i < (int)num_ulocks; i++) {
3554 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3555 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3556 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3557 return ERROR(eclass,ecode);
3560 /* Now do any requested locks */
3561 data += 10*num_ulocks;
3562 /* Data now points at the beginning of the list
3563 of smb_lkrng structs */
3564 for(i = 0; i < (int)num_locks; i++) {
3565 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3566 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3567 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3571 /* If any of the above locks failed, then we must unlock
3572 all of the previous locks (X/Open spec). */
3573 if(i != num_locks && num_locks != 0) {
3574 for(; i >= 0; i--) {
3575 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3576 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3577 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3579 return ERROR(eclass,ecode);
3582 set_message(outbuf,2,0,True);
3584 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3585 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3589 return chain_reply(inbuf,outbuf,length,bufsize);
3593 /****************************************************************************
3594 reply to a SMBreadbmpx (read block multiplex) request
3595 ****************************************************************************/
3596 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3603 int outsize, mincount, maxcount;
3608 /* this function doesn't seem to work - disable by default */
3610 return(ERROR(ERRSRV,ERRuseSTD));
3612 outsize = set_message(outbuf,8,0,True);
3614 cnum = SVAL(inbuf,smb_tid);
3615 fnum = GETFNUM(inbuf,smb_vwv0);
3617 CHECK_FNUM(fnum,cnum);
3621 startpos = IVAL(inbuf,smb_vwv1);
3622 maxcount = SVAL(inbuf,smb_vwv3);
3623 mincount = SVAL(inbuf,smb_vwv4);
3625 data = smb_buf(outbuf);
3626 pad = ((long)data)%4;
3627 if (pad) pad = 4 - pad;
3630 max_per_packet = bufsize-(outsize+pad);
3634 if (is_locked(fnum,cnum,maxcount,startpos))
3635 return(ERROR(ERRDOS,ERRlock));
3639 int N = MIN(max_per_packet,tcount-total_read);
3641 nread = read_file(fnum,data,startpos,N);
3643 if (nread <= 0) nread = 0;
3646 tcount = total_read + nread;
3648 set_message(outbuf,8,nread,False);
3649 SIVAL(outbuf,smb_vwv0,startpos);
3650 SSVAL(outbuf,smb_vwv2,tcount);
3651 SSVAL(outbuf,smb_vwv6,nread);
3652 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3654 send_smb(Client,outbuf);
3656 total_read += nread;
3659 while (total_read < tcount);
3665 /****************************************************************************
3666 reply to a SMBwritebmpx (write block multiplex primary) request
3667 ****************************************************************************/
3668 int reply_writebmpx(char *inbuf,char *outbuf)
3670 int cnum,numtowrite,fnum;
3674 int tcount, write_through, smb_doff;
3677 cnum = SVAL(inbuf,smb_tid);
3678 fnum = GETFNUM(inbuf,smb_vwv0);
3680 CHECK_FNUM(fnum,cnum);
3684 tcount = SVAL(inbuf,smb_vwv1);
3685 startpos = IVAL(inbuf,smb_vwv3);
3686 write_through = BITSETW(inbuf+smb_vwv7,0);
3687 numtowrite = SVAL(inbuf,smb_vwv10);
3688 smb_doff = SVAL(inbuf,smb_vwv11);
3690 data = smb_base(inbuf) + smb_doff;
3692 /* If this fails we need to send an SMBwriteC response,
3693 not an SMBwritebmpx - set this up now so we don't forget */
3694 CVAL(outbuf,smb_com) = SMBwritec;
3696 if (is_locked(fnum,cnum,tcount,startpos))
3697 return(ERROR(ERRDOS,ERRlock));
3699 seek_file(fnum,startpos);
3700 nwritten = write_file(fnum,data,numtowrite);
3702 if(lp_syncalways(SNUM(cnum)) || write_through)
3705 if(nwritten < numtowrite)
3706 return(UNIXERROR(ERRHRD,ERRdiskfull));
3708 /* If the maximum to be written to this file
3709 is greater than what we just wrote then set
3710 up a secondary struct to be attached to this
3711 fd, we will use this to cache error messages etc. */
3712 if(tcount > nwritten)
3714 write_bmpx_struct *wbms;
3715 if(Files[fnum].wbmpx_ptr != NULL)
3716 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3718 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3721 DEBUG(0,("Out of memory in reply_readmpx\n"));
3722 return(ERROR(ERRSRV,ERRnoresource));
3724 wbms->wr_mode = write_through;
3725 wbms->wr_discard = False; /* No errors yet */
3726 wbms->wr_total_written = nwritten;
3727 wbms->wr_errclass = 0;
3729 Files[fnum].wbmpx_ptr = wbms;
3732 /* We are returning successfully, set the message type back to
3734 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3736 outsize = set_message(outbuf,1,0,True);
3738 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3740 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3741 timestring(),fnum,cnum,numtowrite,nwritten));
3743 if (write_through && tcount==nwritten) {
3744 /* we need to send both a primary and a secondary response */
3745 smb_setlen(outbuf,outsize - 4);
3746 send_smb(Client,outbuf);
3748 /* now the secondary */
3749 outsize = set_message(outbuf,1,0,True);
3750 CVAL(outbuf,smb_com) = SMBwritec;
3751 SSVAL(outbuf,smb_vwv0,nwritten);
3758 /****************************************************************************
3759 reply to a SMBwritebs (write block multiplex secondary) request
3760 ****************************************************************************/
3761 int reply_writebs(char *inbuf,char *outbuf)
3763 int cnum,numtowrite,fnum;
3767 int tcount, write_through, smb_doff;
3769 write_bmpx_struct *wbms;
3770 BOOL send_response = False;
3772 cnum = SVAL(inbuf,smb_tid);
3773 fnum = GETFNUM(inbuf,smb_vwv0);
3774 CHECK_FNUM(fnum,cnum);
3777 tcount = SVAL(inbuf,smb_vwv1);
3778 startpos = IVAL(inbuf,smb_vwv2);
3779 numtowrite = SVAL(inbuf,smb_vwv6);
3780 smb_doff = SVAL(inbuf,smb_vwv7);
3782 data = smb_base(inbuf) + smb_doff;
3784 /* We need to send an SMBwriteC response, not an SMBwritebs */
3785 CVAL(outbuf,smb_com) = SMBwritec;
3787 /* This fd should have an auxiliary struct attached,
3788 check that it does */
3789 wbms = Files[fnum].wbmpx_ptr;
3790 if(!wbms) return(-1);
3792 /* If write through is set we can return errors, else we must
3794 write_through = wbms->wr_mode;
3796 /* Check for an earlier error */
3797 if(wbms->wr_discard)
3798 return -1; /* Just discard the packet */
3800 seek_file(fnum,startpos);
3801 nwritten = write_file(fnum,data,numtowrite);
3803 if(lp_syncalways(SNUM(cnum)) || write_through)
3806 if (nwritten < numtowrite)
3809 /* We are returning an error - we can delete the aux struct */
3810 if (wbms) free((char *)wbms);
3811 Files[fnum].wbmpx_ptr = NULL;
3812 return(ERROR(ERRHRD,ERRdiskfull));
3814 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3817 /* Increment the total written, if this matches tcount
3818 we can discard the auxiliary struct (hurrah !) and return a writeC */
3819 wbms->wr_total_written += nwritten;
3820 if(wbms->wr_total_written >= tcount)
3822 if (write_through) {
3823 outsize = set_message(outbuf,1,0,True);
3824 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3825 send_response = True;
3829 Files[fnum].wbmpx_ptr = NULL;
3839 /****************************************************************************
3840 reply to a SMBsetattrE
3841 ****************************************************************************/
3842 int reply_setattrE(char *inbuf,char *outbuf)
3845 struct utimbuf unix_times;
3848 outsize = set_message(outbuf,0,0,True);
3850 cnum = SVAL(inbuf,smb_tid);
3851 fnum = GETFNUM(inbuf,smb_vwv0);
3853 CHECK_FNUM(fnum,cnum);
3856 /* Convert the DOS times into unix times. Ignore create
3857 time as UNIX can't set this.
3859 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3860 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3863 * Patch from Ray Frush <frush@engr.colostate.edu>
3864 * Sometimes times are sent as zero - ignore them.
3867 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3869 /* Ignore request */
3870 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3871 not setting timestamps of 0\n",
3872 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3875 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3877 /* set modify time = to access time if modify time was 0 */
3878 unix_times.modtime = unix_times.actime;
3881 /* Set the date on this file */
3882 if(file_utime(cnum, Files[fnum].name, &unix_times))
3883 return(ERROR(ERRDOS,ERRnoaccess));
3885 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3886 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3892 /****************************************************************************
3893 reply to a SMBgetattrE
3894 ****************************************************************************/
3895 int reply_getattrE(char *inbuf,char *outbuf)
3902 outsize = set_message(outbuf,11,0,True);
3904 cnum = SVAL(inbuf,smb_tid);
3905 fnum = GETFNUM(inbuf,smb_vwv0);
3907 CHECK_FNUM(fnum,cnum);
3910 /* Do an fstat on this file */
3911 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3912 return(UNIXERROR(ERRDOS,ERRnoaccess));
3914 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3916 /* Convert the times into dos times. Set create
3917 date to be last modify date as UNIX doesn't save
3919 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3920 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3921 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3924 SIVAL(outbuf,smb_vwv6,0);
3925 SIVAL(outbuf,smb_vwv8,0);
3929 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3930 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3932 SSVAL(outbuf,smb_vwv10, mode);
3934 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));