2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
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 global_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,("%s: ERROR: Invalid password length %d\n", timestring(), 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(Client)));
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);
124 claim_connection(-1,"STATUS.",MAXSTATUS,True);
129 case 0x89: /* session keepalive request
130 (some old clients produce this?) */
131 CVAL(outbuf,0) = 0x85;
135 case 0x82: /* positive session response */
136 case 0x83: /* negative session response */
137 case 0x84: /* retarget session response */
138 DEBUG(0,("Unexpected session response\n"));
141 case 0x85: /* session keepalive */
146 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",
147 timestring(),msg_type,msg_flags));
153 /*******************************************************************
154 work out what error to give to a failed connection
155 ********************************************************************/
156 static int connection_error(char *inbuf,char *outbuf,int connection_num)
158 switch (connection_num)
161 return(ERROR(ERRSRV,ERRnoresource));
163 return(ERROR(ERRSRV,ERRbaduid));
165 return(ERROR(ERRSRV,ERRinvdevice));
167 return(ERROR(ERRSRV,ERRinvnetname));
169 return(ERROR(ERRSRV,ERRaccess));
171 return(ERROR(ERRDOS,ERRnoipc));
173 return(ERROR(ERRSRV,ERRinvnetname));
175 return(ERROR(ERRSRV,ERRbadpw));
180 /****************************************************************************
181 parse a share descriptor string
182 ****************************************************************************/
183 static void parse_connect(char *p,char *service,char *user,
184 char *password,int *pwlen,char *dev)
188 DEBUG(4,("parsing connect string %s\n",p));
190 p2 = strrchr(p,'\\');
194 fstrcpy(service,p2+1);
199 *pwlen = strlen(password);
206 p = strchr(service,'%');
217 /****************************************************************************
219 ****************************************************************************/
220 int reply_tcon(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
228 uint16 vuid = SVAL(inbuf,smb_uid);
231 *service = *user = *password = *dev = 0;
233 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
236 * Pass the user through the NT -> unix user mapping
240 (void)map_username(user);
243 * Do any UNIX username case mangling.
245 (void)Get_Pwnam( user, True);
247 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
249 if (connection_num < 0)
250 return(connection_error(inbuf,outbuf,connection_num));
252 outsize = set_message(outbuf,2,0,True);
253 SSVAL(outbuf,smb_vwv0,max_recv);
254 SSVAL(outbuf,smb_vwv1,connection_num);
255 SSVAL(outbuf,smb_tid,connection_num);
257 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
263 /****************************************************************************
264 reply to a tcon and X
265 ****************************************************************************/
266 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
273 uint16 vuid = SVAL(inbuf,smb_uid);
274 int passlen = SVAL(inbuf,smb_vwv3);
276 *service = *user = *password = *devicename = 0;
278 /* we might have to close an old one */
279 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
280 close_cnum(SVAL(inbuf,smb_tid),vuid);
282 if (passlen > MAX_PASS_LEN) {
283 overflow_attack(passlen);
289 memcpy(password,smb_buf(inbuf),passlen);
291 path = smb_buf(inbuf) + passlen;
294 if (strequal(password," "))
296 passlen = strlen(password);
299 fstrcpy(service,path+2);
300 p = strchr(service,'\\');
302 return(ERROR(ERRSRV,ERRinvnetname));
304 fstrcpy(service,p+1);
305 p = strchr(service,'%');
311 StrnCpy(devicename,path + strlen(path) + 1,6);
312 DEBUG(4,("Got device type %s\n",devicename));
316 * Pass the user through the NT -> unix user mapping
320 (void)map_username(user);
323 * Do any UNIX username case mangling.
325 (void)Get_Pwnam( user, True);
327 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
329 if (connection_num < 0)
330 return(connection_error(inbuf,outbuf,connection_num));
332 if (Protocol < PROTOCOL_NT1)
334 set_message(outbuf,2,strlen(devicename)+1,True);
335 pstrcpy(smb_buf(outbuf),devicename);
339 char *fsname = FSTYPE_STRING;
342 set_message(outbuf,3,3,True);
345 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
346 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
348 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
350 SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
353 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
355 /* set the incoming and outgoing tid to the just created one */
356 SSVAL(inbuf,smb_tid,connection_num);
357 SSVAL(outbuf,smb_tid,connection_num);
359 return chain_reply(inbuf,outbuf,length,bufsize);
363 /****************************************************************************
364 reply to an unknown type
365 ****************************************************************************/
366 int reply_unknown(char *inbuf,char *outbuf)
370 cnum = SVAL(inbuf,smb_tid);
371 type = CVAL(inbuf,smb_com);
373 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
378 return(ERROR(ERRSRV,ERRunknownsmb));
382 /****************************************************************************
384 ****************************************************************************/
385 int reply_ioctl(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
387 DEBUG(3,("ignoring ioctl\n"));
389 /* we just say it succeeds and hope its all OK.
390 some day it would be nice to interpret them individually */
391 return set_message(outbuf,1,0,True);
393 return(ERROR(ERRSRV,ERRnosupport));
397 /****************************************************************************
398 always return an error: it's just a matter of which one...
399 ****************************************************************************/
400 static int session_trust_account(char *inbuf, char *outbuf, char *user,
401 char *smb_passwd, int smb_passlen,
402 char *smb_nt_passwd, int smb_nt_passlen)
404 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
405 if (lp_security() == SEC_USER)
407 smb_trust_acct = getsmbpwnam(user);
411 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
412 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
413 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
416 if (smb_trust_acct == NULL)
418 /* lkclXXXX: workstation entry doesn't exist */
419 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
420 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
421 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
425 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
427 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
428 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
429 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
432 if (!smb_password_ok(smb_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
434 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
435 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
436 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
439 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
441 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
442 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
443 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
446 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
448 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
449 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
450 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
453 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
455 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
456 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
457 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
461 /* don't know what to do: indicate logon failure */
462 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
463 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
467 /****************************************************************************
468 reply to a session setup command
469 ****************************************************************************/
470 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
479 int smb_apasslen = 0;
481 int smb_ntpasslen = 0;
482 pstring smb_ntpasswd;
483 BOOL valid_nt_password = False;
487 static BOOL done_sesssetup = False;
488 BOOL doencrypt = SMBENCRYPT();
494 smb_bufsize = SVAL(inbuf,smb_vwv2);
495 smb_mpxmax = SVAL(inbuf,smb_vwv3);
496 smb_vc_num = SVAL(inbuf,smb_vwv4);
497 smb_sesskey = IVAL(inbuf,smb_vwv5);
499 if (Protocol < PROTOCOL_NT1) {
500 smb_apasslen = SVAL(inbuf,smb_vwv7);
501 if (smb_apasslen > MAX_PASS_LEN)
503 overflow_attack(smb_apasslen);
506 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
507 smb_apasswd[smb_apasslen] = 0;
508 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
510 if (!doencrypt && (lp_security() != SEC_SERVER)) {
511 smb_apasslen = strlen(smb_apasswd);
514 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
515 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
516 uint32 client_caps = IVAL(inbuf,smb_vwv11);
517 enum remote_arch_types ra_type = get_remote_arch();
519 char *p = smb_buf(inbuf);
521 /* client_caps is used as final determination if client is NT or Win95.
522 This is needed to return the correct error codes in some
526 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
528 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
529 set_remote_arch( RA_WINNT);
531 set_remote_arch( RA_WIN95);
534 if (passlen1 != 24 && passlen2 != 24)
537 if (passlen1 > MAX_PASS_LEN) {
538 overflow_attack(passlen1);
541 passlen1 = MIN(passlen1, MAX_PASS_LEN);
542 passlen2 = MIN(passlen2, MAX_PASS_LEN);
545 /* both Win95 and WinNT stuff up the password lengths for
546 non-encrypting systems. Uggh.
548 if passlen1==24 its a win95 system, and its setting the
549 password length incorrectly. Luckily it still works with the
550 default code because Win95 will null terminate the password
553 if passlen1>0 and passlen2>0 then maybe its a NT box and its
554 setting passlen2 to some random value which really stuffs
555 things up. we need to fix that one. */
557 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
561 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
562 /* Save the lanman2 password and the NT md4 password. */
563 smb_apasslen = passlen1;
564 memcpy(smb_apasswd,p,smb_apasslen);
565 smb_apasswd[smb_apasslen] = 0;
566 smb_ntpasslen = passlen2;
567 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
568 smb_ntpasswd[smb_ntpasslen] = 0;
570 /* we use the first password that they gave */
571 smb_apasslen = passlen1;
572 StrnCpy(smb_apasswd,p,smb_apasslen);
574 /* trim the password */
575 smb_apasslen = strlen(smb_apasswd);
577 /* wfwg sometimes uses a space instead of a null */
578 if (strequal(smb_apasswd," ")) {
584 p += passlen1 + passlen2;
585 fstrcpy(user,p); p = skip_string(p,1);
588 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
589 domain,skip_string(p,1),skip_string(p,2)));
593 DEBUG(3,("sesssetupX:name=[%s]\n",user));
595 /* If name ends in $ then I think it's asking about whether a */
596 /* computer with that name (minus the $) has access. For now */
597 /* say yes to everything ending in $. */
598 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
600 return session_trust_account(inbuf, outbuf, user,
601 smb_apasswd, smb_apasslen,
602 smb_ntpasswd, smb_ntpasslen);
605 /* If no username is sent use the guest account */
608 pstrcpy(user,lp_guestaccount(-1));
609 /* If no user and no password then set guest flag. */
610 if( *smb_apasswd == 0)
617 * In share level security, only overwrite sesssetup_use if
618 * it's a non null-session share. Helps keep %U and %G
622 if((lp_security() != SEC_SHARE) || *user)
623 pstrcpy(sesssetup_user,user);
625 reload_services(True);
628 * Save the username before mapping. We will use
629 * the original username sent to us for security=server
630 * and security=domain checking.
633 pstrcpy( orig_user, user);
636 * Pass the user through the NT -> unix user mapping
640 (void)map_username(user);
643 * Do any UNIX username case mangling.
645 (void)Get_Pwnam( user, True);
647 add_session_user(user);
650 * Check if the given username was the guest user with no password.
653 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
656 if (!guest && !(lp_security() == SEC_SERVER &&
657 /* Check with orig_user for security=server and
659 server_validate(orig_user, domain,
660 smb_apasswd, smb_apasslen,
661 smb_ntpasswd, smb_ntpasslen)) &&
662 !(lp_security() == SEC_DOMAIN &&
663 domain_client_validate(orig_user, domain,
664 smb_apasswd, smb_apasslen,
665 smb_ntpasswd, smb_ntpasslen)) &&
666 !check_hosts_equiv(user)
670 /* now check if it's a valid username/password */
671 /* If an NT password was supplied try and validate with that
672 first. This is superior as the passwords are mixed case
673 128 length unicode */
676 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
677 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
679 valid_nt_password = True;
681 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
683 if (lp_security() >= SEC_USER) {
684 #if (GUEST_SESSSETUP == 0)
685 return(ERROR(ERRSRV,ERRbadpw));
687 #if (GUEST_SESSSETUP == 1)
688 if (Get_Pwnam(user,True))
689 return(ERROR(ERRSRV,ERRbadpw));
692 if (*smb_apasswd || !Get_Pwnam(user,True))
693 pstrcpy(user,lp_guestaccount(-1));
694 DEBUG(3,("Registered username %s for guest access\n",user));
699 if (!Get_Pwnam(user,True)) {
700 DEBUG(3,("No such user %s - using guest account\n",user));
701 pstrcpy(user,lp_guestaccount(-1));
705 if (!strequal(user,lp_guestaccount(-1)) &&
706 lp_servicenumber(user) < 0)
708 int homes = lp_servicenumber(HOMES_NAME);
709 char *home = get_home_dir(user);
710 if (homes >= 0 && home)
711 lp_add_home(user,homes,home);
715 /* it's ok - setup a reply */
716 if (Protocol < PROTOCOL_NT1) {
717 set_message(outbuf,3,0,True);
720 set_message(outbuf,3,3,True);
722 pstrcpy(p,"Unix"); p = skip_string(p,1);
723 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
724 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
725 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
726 /* perhaps grab OS version here?? */
729 /* Set the correct uid in the outgoing and incoming packets
730 We will use this on future requests to determine which
731 user we should become.
734 struct passwd *pw = Get_Pwnam(user,False);
736 DEBUG(1,("Username %s is invalid on this system\n",user));
737 return(ERROR(ERRSRV,ERRbadpw));
744 SSVAL(outbuf,smb_vwv2,1);
746 /* register the name and uid as being validated, so further connections
747 to a uid can get through without a password, on the same VC */
748 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
750 SSVAL(outbuf,smb_uid,sess_vuid);
751 SSVAL(inbuf,smb_uid,sess_vuid);
754 max_send = MIN(max_send,smb_bufsize);
756 DEBUG(6,("Client requested max send size of %d\n", max_send));
758 done_sesssetup = True;
760 return chain_reply(inbuf,outbuf,length,bufsize);
764 /****************************************************************************
766 ****************************************************************************/
767 int reply_chkpth(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
773 BOOL bad_path = False;
775 cnum = SVAL(inbuf,smb_tid);
777 pstrcpy(name,smb_buf(inbuf) + 1);
778 unix_convert(name,cnum,0,&bad_path);
780 mode = SVAL(inbuf,smb_vwv0);
782 if (check_name(name,cnum))
783 ok = directory_exist(name,NULL);
787 /* We special case this - as when a Windows machine
788 is parsing a path is steps through the components
789 one at a time - if a component fails it expects
790 ERRbadpath, not ERRbadfile.
794 unix_ERR_class = ERRDOS;
795 unix_ERR_code = ERRbadpath;
799 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
800 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
801 (get_remote_arch() == RA_WINNT))
803 unix_ERR_class = ERRDOS;
804 unix_ERR_code = ERRbaddirectory;
808 return(UNIXERROR(ERRDOS,ERRbadpath));
811 outsize = set_message(outbuf,0,0,True);
813 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
819 /****************************************************************************
821 ****************************************************************************/
822 int reply_getatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
832 BOOL bad_path = False;
834 cnum = SVAL(inbuf,smb_tid);
836 pstrcpy(fname,smb_buf(inbuf) + 1);
837 unix_convert(fname,cnum,0,&bad_path);
839 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
840 under WfWg - weird! */
843 mode = aHIDDEN | aDIR;
844 if (!CAN_WRITE(cnum)) mode |= aRONLY;
850 if (check_name(fname,cnum))
852 if (sys_stat(fname,&sbuf) == 0)
854 mode = dos_mode(cnum,fname,&sbuf);
856 mtime = sbuf.st_mtime;
862 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
867 if((errno == ENOENT) && bad_path)
869 unix_ERR_class = ERRDOS;
870 unix_ERR_code = ERRbadpath;
873 return(UNIXERROR(ERRDOS,ERRbadfile));
876 outsize = set_message(outbuf,10,0,True);
878 SSVAL(outbuf,smb_vwv0,mode);
879 if(lp_dos_filetime_resolution(SNUM(cnum)) )
880 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
882 put_dos_date3(outbuf,smb_vwv1,mtime);
883 SIVAL(outbuf,smb_vwv3,size);
885 if (Protocol >= PROTOCOL_NT1) {
886 char *p = strrchr(fname,'/');
887 uint16 flg2 = SVAL(outbuf,smb_flg2);
889 if (!is_8_3(fname, True))
890 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
893 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
899 /****************************************************************************
901 ****************************************************************************/
902 int reply_setatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
910 BOOL bad_path = False;
912 cnum = SVAL(inbuf,smb_tid);
914 pstrcpy(fname,smb_buf(inbuf) + 1);
915 unix_convert(fname,cnum,0,&bad_path);
917 mode = SVAL(inbuf,smb_vwv0);
918 mtime = make_unix_date3(inbuf+smb_vwv1);
920 if (directory_exist(fname,NULL))
922 if (check_name(fname,cnum))
923 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
925 ok = set_filetime(cnum,fname,mtime);
929 if((errno == ENOENT) && bad_path)
931 unix_ERR_class = ERRDOS;
932 unix_ERR_code = ERRbadpath;
935 return(UNIXERROR(ERRDOS,ERRnoaccess));
938 outsize = set_message(outbuf,0,0,True);
940 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
946 /****************************************************************************
948 ****************************************************************************/
949 int reply_dskattr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
953 int dfree,dsize,bsize;
955 cnum = SVAL(inbuf,smb_tid);
957 sys_disk_free(".",&bsize,&dfree,&dsize);
959 outsize = set_message(outbuf,5,0,True);
961 SSVAL(outbuf,smb_vwv0,dsize);
962 SSVAL(outbuf,smb_vwv1,bsize/512);
963 SSVAL(outbuf,smb_vwv2,512);
964 SSVAL(outbuf,smb_vwv3,dfree);
966 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
972 /****************************************************************************
974 Can be called from SMBsearch, SMBffirst or SMBfunique.
975 ****************************************************************************/
976 int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
987 BOOL finished = False;
996 BOOL check_descend = False;
997 BOOL expect_close = False;
998 BOOL can_open = True;
999 BOOL bad_path = False;
1001 *mask = *directory = *fname = 0;
1003 /* If we were called as SMBffirst then we must expect close. */
1004 if(CVAL(inbuf,smb_com) == SMBffirst)
1005 expect_close = True;
1007 cnum = SVAL(inbuf,smb_tid);
1009 outsize = set_message(outbuf,1,3,True);
1010 maxentries = SVAL(inbuf,smb_vwv0);
1011 dirtype = SVAL(inbuf,smb_vwv1);
1012 path = smb_buf(inbuf) + 1;
1013 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1016 /* dirtype &= ~aDIR; */
1018 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1021 if (status_len == 0)
1025 pstrcpy(directory,smb_buf(inbuf)+1);
1026 pstrcpy(dir2,smb_buf(inbuf)+1);
1027 unix_convert(directory,cnum,0,&bad_path);
1030 if (!check_name(directory,cnum))
1033 p = strrchr(dir2,'/');
1045 p = strrchr(directory,'/');
1051 if (strlen(directory) == 0)
1052 pstrcpy(directory,"./");
1054 CVAL(status,0) = dirtype;
1058 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1059 memcpy(mask,status+1,11);
1061 dirtype = CVAL(status,0) & 0x1F;
1062 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
1063 if (!Connections[cnum].dirptr)
1065 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
1066 if (!case_sensitive)
1070 /* turn strings of spaces into a . */
1072 trim_string(mask,NULL," ");
1073 if ((p = strrchr(mask,' ')))
1078 trim_string(mask,NULL," ");
1085 for (p=mask; *p; p++)
1087 if (*p != '?' && *p != '*' && !isdoschar(*p))
1089 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1095 if (!strchr(mask,'.') && strlen(mask)>8)
1098 fstrcpy(tmp,&mask[8]);
1104 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1108 p = smb_buf(outbuf) + 3;
1112 if (status_len == 0)
1114 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
1119 if((errno == ENOENT) && bad_path)
1121 unix_ERR_class = ERRDOS;
1122 unix_ERR_code = ERRbadpath;
1124 return (UNIXERROR(ERRDOS,ERRnofids));
1126 return(ERROR(ERRDOS,ERRnofids));
1130 DEBUG(4,("dptr_num is %d\n",dptr_num));
1134 if ((dirtype&0x1F) == aVOLID)
1136 memcpy(p,status,21);
1137 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
1138 dptr_fill(p+12,dptr_num);
1139 if (dptr_zero(p+12) && (status_len==0))
1143 p += DIR_STRUCT_SIZE;
1147 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
1148 if (in_list(Connections[cnum].dirpath,
1149 lp_dontdescend(SNUM(cnum)),True))
1150 check_descend = True;
1152 for (i=numentries;(i<maxentries) && !finished;i++)
1155 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
1158 memcpy(p,status,21);
1159 make_dir_struct(p,mask,fname,size,mode,date);
1160 dptr_fill(p+12,dptr_num);
1163 p += DIR_STRUCT_SIZE;
1172 if (numentries == 0 || !ok)
1174 CVAL(outbuf,smb_rcls) = ERRDOS;
1175 SSVAL(outbuf,smb_err,ERRnofiles);
1178 /* If we were called as SMBffirst with smb_search_id == NULL
1179 and no entries were found then return error and close dirptr
1182 if(ok && expect_close && numentries == 0 && status_len == 0)
1184 CVAL(outbuf,smb_rcls) = ERRDOS;
1185 SSVAL(outbuf,smb_err,ERRnofiles);
1186 /* Also close the dptr - we know it's gone */
1187 dptr_close(dptr_num);
1190 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1191 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1192 dptr_close(dptr_num);
1194 SSVAL(outbuf,smb_vwv0,numentries);
1195 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1196 CVAL(smb_buf(outbuf),0) = 5;
1197 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1199 if (Protocol >= PROTOCOL_NT1) {
1200 uint16 flg2 = SVAL(outbuf,smb_flg2);
1201 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1204 outsize += DIR_STRUCT_SIZE*numentries;
1205 smb_setlen(outbuf,outsize - 4);
1207 if ((! *directory) && dptr_path(dptr_num))
1208 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1210 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1212 smb_fn_name(CVAL(inbuf,smb_com)),
1213 mask,directory,cnum,dirtype,numentries,maxentries));
1219 /****************************************************************************
1220 reply to a fclose (stop directory search)
1221 ****************************************************************************/
1222 int reply_fclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1231 cnum = SVAL(inbuf,smb_tid);
1233 outsize = set_message(outbuf,1,0,True);
1234 path = smb_buf(inbuf) + 1;
1235 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1238 if (status_len == 0)
1239 return(ERROR(ERRSRV,ERRsrverror));
1241 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1243 if(dptr_fetch(status+12,&dptr_num)) {
1244 /* Close the dptr - we know it's gone */
1245 dptr_close(dptr_num);
1248 SSVAL(outbuf,smb_vwv0,0);
1250 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1256 /****************************************************************************
1258 ****************************************************************************/
1259 int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1272 BOOL bad_path = False;
1274 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1276 cnum = SVAL(inbuf,smb_tid);
1278 share_mode = SVAL(inbuf,smb_vwv0);
1280 pstrcpy(fname,smb_buf(inbuf)+1);
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 Files[fnum].reserved = False;
1295 return(UNIXERROR(ERRDOS,ERRnoaccess));
1298 unixmode = unix_mode(cnum,aARCH);
1300 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1301 oplock_request,&rmode,NULL);
1307 if((errno == ENOENT) && bad_path)
1309 unix_ERR_class = ERRDOS;
1310 unix_ERR_code = ERRbadpath;
1312 Files[fnum].reserved = False;
1313 return(UNIXERROR(ERRDOS,ERRnoaccess));
1316 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1317 close_file(fnum,False);
1318 return(ERROR(ERRDOS,ERRnoaccess));
1321 size = sbuf.st_size;
1322 fmode = dos_mode(cnum,fname,&sbuf);
1323 mtime = sbuf.st_mtime;
1326 DEBUG(3,("attempt to open a directory %s\n",fname));
1327 close_file(fnum,False);
1328 return(ERROR(ERRDOS,ERRnoaccess));
1331 outsize = set_message(outbuf,7,0,True);
1332 SSVAL(outbuf,smb_vwv0,fnum);
1333 SSVAL(outbuf,smb_vwv1,fmode);
1334 if(lp_dos_filetime_resolution(SNUM(cnum)) )
1335 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1337 put_dos_date3(outbuf,smb_vwv2,mtime);
1338 SIVAL(outbuf,smb_vwv4,size);
1339 SSVAL(outbuf,smb_vwv6,rmode);
1341 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1342 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1345 if(fsp->granted_oplock)
1346 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1351 /****************************************************************************
1352 reply to an open and X
1353 ****************************************************************************/
1354 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1357 int cnum = SVAL(inbuf,smb_tid);
1359 int smb_mode = SVAL(inbuf,smb_vwv3);
1360 int smb_attr = SVAL(inbuf,smb_vwv5);
1361 /* Breakout the oplock request bits so we can set the
1362 reply bits separately. */
1363 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1364 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1365 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1367 int open_flags = SVAL(inbuf,smb_vwv2);
1368 int smb_sattr = SVAL(inbuf,smb_vwv4);
1369 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1371 int smb_ofun = SVAL(inbuf,smb_vwv8);
1373 int size=0,fmode=0,mtime=0,rmode=0;
1376 BOOL bad_path = False;
1379 /* If it's an IPC, pass off the pipe handler. */
1381 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1383 /* XXXX we need to handle passed times, sattr and flags */
1385 pstrcpy(fname,smb_buf(inbuf));
1386 unix_convert(fname,cnum,0,&bad_path);
1388 fnum = find_free_file();
1390 return(ERROR(ERRSRV,ERRnofids));
1392 if (!check_name(fname,cnum))
1394 if((errno == ENOENT) && bad_path)
1396 unix_ERR_class = ERRDOS;
1397 unix_ERR_code = ERRbadpath;
1399 Files[fnum].reserved = False;
1400 return(UNIXERROR(ERRDOS,ERRnoaccess));
1403 unixmode = unix_mode(cnum,smb_attr | aARCH);
1405 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1406 oplock_request, &rmode,&smb_action);
1412 if((errno == ENOENT) && bad_path)
1414 unix_ERR_class = ERRDOS;
1415 unix_ERR_code = ERRbadpath;
1417 Files[fnum].reserved = False;
1418 return(UNIXERROR(ERRDOS,ERRnoaccess));
1421 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1422 close_file(fnum,False);
1423 return(ERROR(ERRDOS,ERRnoaccess));
1426 size = sbuf.st_size;
1427 fmode = dos_mode(cnum,fname,&sbuf);
1428 mtime = sbuf.st_mtime;
1430 close_file(fnum,False);
1431 return(ERROR(ERRDOS,ERRnoaccess));
1434 /* If the caller set the extended oplock request bit
1435 and we granted one (by whatever means) - set the
1436 correct bit for extended oplock reply.
1439 if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1440 smb_action |= EXTENDED_OPLOCK_GRANTED;
1443 if(ex_oplock_request && fsp->granted_oplock) {
1444 smb_action |= EXTENDED_OPLOCK_GRANTED;
1447 /* If the caller set the core oplock request bit
1448 and we granted one (by whatever means) - set the
1449 correct bit for core oplock reply.
1452 if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1453 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1456 if(core_oplock_request && fsp->granted_oplock) {
1457 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1460 set_message(outbuf,15,0,True);
1461 SSVAL(outbuf,smb_vwv2,fnum);
1462 SSVAL(outbuf,smb_vwv3,fmode);
1463 if(lp_dos_filetime_resolution(SNUM(cnum)) )
1464 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1466 put_dos_date3(outbuf,smb_vwv4,mtime);
1467 SIVAL(outbuf,smb_vwv6,size);
1468 SSVAL(outbuf,smb_vwv8,rmode);
1469 SSVAL(outbuf,smb_vwv11,smb_action);
1473 return chain_reply(inbuf,outbuf,length,bufsize);
1477 /****************************************************************************
1478 reply to a SMBulogoffX
1479 ****************************************************************************/
1480 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1482 uint16 vuid = SVAL(inbuf,smb_uid);
1483 user_struct *vuser = get_valid_user_struct(vuid);
1486 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1489 /* in user level security we are supposed to close any files
1490 open by this user */
1491 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1493 for (i=0;i<MAX_OPEN_FILES;i++)
1494 if ((Files[i].vuid == vuid) && Files[i].open) {
1495 close_file(i,False);
1499 invalidate_vuid(vuid);
1501 set_message(outbuf,2,0,True);
1503 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1505 return chain_reply(inbuf,outbuf,length,bufsize);
1509 /****************************************************************************
1510 reply to a mknew or a create
1511 ****************************************************************************/
1512 int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1521 BOOL bad_path = False;
1523 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1525 com = SVAL(inbuf,smb_com);
1526 cnum = SVAL(inbuf,smb_tid);
1528 createmode = SVAL(inbuf,smb_vwv0);
1529 pstrcpy(fname,smb_buf(inbuf)+1);
1530 unix_convert(fname,cnum,0,&bad_path);
1532 if (createmode & aVOLID)
1534 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1537 unixmode = unix_mode(cnum,createmode);
1539 fnum = find_free_file();
1541 return(ERROR(ERRSRV,ERRnofids));
1543 if (!check_name(fname,cnum))
1545 if((errno == ENOENT) && bad_path)
1547 unix_ERR_class = ERRDOS;
1548 unix_ERR_code = ERRbadpath;
1550 Files[fnum].reserved = False;
1551 return(UNIXERROR(ERRDOS,ERRnoaccess));
1556 /* We should fail if file exists. */
1561 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1565 /* Open file in dos compatibility share mode. */
1566 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1567 oplock_request, NULL, NULL);
1573 if((errno == ENOENT) && bad_path)
1575 unix_ERR_class = ERRDOS;
1576 unix_ERR_code = ERRbadpath;
1578 Files[fnum].reserved = False;
1579 return(UNIXERROR(ERRDOS,ERRnoaccess));
1582 outsize = set_message(outbuf,1,0,True);
1583 SSVAL(outbuf,smb_vwv0,fnum);
1585 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1586 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1589 if(fsp->granted_oplock)
1590 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1592 DEBUG(2,("new file %s\n",fname));
1593 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));
1599 /****************************************************************************
1600 reply to a create temporary file
1601 ****************************************************************************/
1602 int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1611 BOOL bad_path = False;
1613 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1615 cnum = SVAL(inbuf,smb_tid);
1616 createmode = SVAL(inbuf,smb_vwv0);
1617 pstrcpy(fname,smb_buf(inbuf)+1);
1618 pstrcat(fname,"/TMXXXXXX");
1619 unix_convert(fname,cnum,0,&bad_path);
1621 unixmode = unix_mode(cnum,createmode);
1623 fnum = find_free_file();
1625 return(ERROR(ERRSRV,ERRnofids));
1627 if (!check_name(fname,cnum))
1629 if((errno == ENOENT) && bad_path)
1631 unix_ERR_class = ERRDOS;
1632 unix_ERR_code = ERRbadpath;
1634 Files[fnum].reserved = False;
1635 return(UNIXERROR(ERRDOS,ERRnoaccess));
1638 pstrcpy(fname2,(char *)mktemp(fname));
1640 /* Open file in dos compatibility share mode. */
1641 /* We should fail if file exists. */
1642 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1643 oplock_request, NULL, NULL);
1649 if((errno == ENOENT) && bad_path)
1651 unix_ERR_class = ERRDOS;
1652 unix_ERR_code = ERRbadpath;
1654 Files[fnum].reserved = False;
1655 return(UNIXERROR(ERRDOS,ERRnoaccess));
1658 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1659 SSVAL(outbuf,smb_vwv0,fnum);
1660 CVAL(smb_buf(outbuf),0) = 4;
1661 pstrcpy(smb_buf(outbuf) + 1,fname2);
1663 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1664 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1667 if(fsp->granted_oplock)
1668 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1670 DEBUG(2,("created temp file %s\n",fname2));
1671 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));
1677 /*******************************************************************
1678 check if a user is allowed to delete a file
1679 ********************************************************************/
1680 static BOOL can_delete(char *fname,int cnum,int dirtype)
1685 if (!CAN_WRITE(cnum)) return(False);
1687 if (sys_lstat(fname,&sbuf) != 0) return(False);
1688 fmode = dos_mode(cnum,fname,&sbuf);
1689 if (fmode & aDIR) return(False);
1690 if (!lp_delete_readonly(SNUM(cnum))) {
1691 if (fmode & aRONLY) return(False);
1693 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1695 if (!check_file_sharing(cnum,fname,False)) return(False);
1699 /****************************************************************************
1701 ****************************************************************************/
1702 int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1712 int error = ERRnoaccess;
1715 BOOL bad_path = False;
1717 *directory = *mask = 0;
1719 cnum = SVAL(inbuf,smb_tid);
1720 dirtype = SVAL(inbuf,smb_vwv0);
1722 pstrcpy(name,smb_buf(inbuf) + 1);
1724 DEBUG(3,("reply_unlink : %s\n",name));
1726 unix_convert(name,cnum,0,&bad_path);
1728 p = strrchr(name,'/');
1730 pstrcpy(directory,"./");
1734 pstrcpy(directory,name);
1738 if (is_mangled(mask))
1739 check_mangled_cache( mask );
1741 has_wild = strchr(mask,'*') || strchr(mask,'?');
1744 pstrcat(directory,"/");
1745 pstrcat(directory,mask);
1746 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1747 if (!count) exists = file_exist(directory,NULL);
1749 void *dirptr = NULL;
1752 if (check_name(directory,cnum))
1753 dirptr = OpenDir(cnum, directory, True);
1755 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1756 the pattern matches against the long name, otherwise the short name
1757 We don't implement this yet XXXX
1764 if (strequal(mask,"????????.???"))
1767 while ((dname = ReadDirName(dirptr)))
1770 pstrcpy(fname,dname);
1772 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1774 error = ERRnoaccess;
1775 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1776 if (!can_delete(fname,cnum,dirtype)) continue;
1777 if (!sys_unlink(fname)) count++;
1778 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1786 return(ERROR(ERRDOS,error));
1789 if((errno == ENOENT) && bad_path)
1791 unix_ERR_class = ERRDOS;
1792 unix_ERR_code = ERRbadpath;
1794 return(UNIXERROR(ERRDOS,error));
1798 outsize = set_message(outbuf,0,0,True);
1804 /****************************************************************************
1805 reply to a readbraw (core+ protocol)
1806 ****************************************************************************/
1807 int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1809 int cnum,maxcount,mincount,fnum;
1812 char *header = outbuf;
1818 * Special check if an oplock break has been issued
1819 * and the readraw request croses on the wire, we must
1820 * return a zero length response here.
1823 if(global_oplock_break)
1825 _smb_setlen(header,0);
1826 transfer_file(0,Client,0,header,4,0);
1827 DEBUG(5,("readbraw - oplock break finished\n"));
1831 cnum = SVAL(inbuf,smb_tid);
1832 fnum = GETFNUM(inbuf,smb_vwv0);
1834 startpos = IVAL(inbuf,smb_vwv1);
1835 maxcount = SVAL(inbuf,smb_vwv3);
1836 mincount = SVAL(inbuf,smb_vwv4);
1838 /* ensure we don't overrun the packet size */
1839 maxcount = MIN(65535,maxcount);
1840 maxcount = MAX(mincount,maxcount);
1842 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1844 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1845 _smb_setlen(header,0);
1846 transfer_file(0,Client,0,header,4,0);
1851 fd = Files[fnum].fd_ptr->fd;
1852 fname = Files[fnum].name;
1856 if (!is_locked(fnum,cnum,maxcount,startpos))
1858 int size = Files[fnum].size;
1859 int sizeneeded = startpos + maxcount;
1861 if (size < sizeneeded) {
1863 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1865 if (!Files[fnum].can_write)
1866 Files[fnum].size = size;
1869 nread = MIN(maxcount,(int)(size - startpos));
1872 if (nread < mincount)
1875 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1878 maxcount,mincount,nread));
1883 _smb_setlen(header,nread);
1885 #if USE_READ_PREDICTION
1886 if (!Files[fnum].can_write)
1887 predict = read_predict(fd,startpos,header+4,NULL,nread);
1890 if ((nread-predict) > 0)
1891 seek_file(fnum,startpos + predict);
1893 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1898 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1899 fname,startpos,nread,ret));
1902 ret = read_file(fnum,header+4,startpos,nread);
1903 if (ret < mincount) ret = 0;
1905 _smb_setlen(header,ret);
1906 transfer_file(0,Client,0,header,4+ret,0);
1909 DEBUG(5,("readbraw finished\n"));
1914 /****************************************************************************
1915 reply to a lockread (core+ protocol)
1916 ****************************************************************************/
1917 int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz)
1923 uint32 startpos, numtoread;
1927 cnum = SVAL(inbuf,smb_tid);
1928 fnum = GETFNUM(inbuf,smb_vwv0);
1930 CHECK_FNUM(fnum,cnum);
1934 numtoread = SVAL(inbuf,smb_vwv1);
1935 startpos = IVAL(inbuf,smb_vwv2);
1937 outsize = set_message(outbuf,5,3,True);
1938 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1939 data = smb_buf(outbuf) + 3;
1941 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1942 return (ERROR(eclass,ecode));
1944 nread = read_file(fnum,data,startpos,numtoread);
1947 return(UNIXERROR(ERRDOS,ERRnoaccess));
1950 SSVAL(outbuf,smb_vwv0,nread);
1951 SSVAL(outbuf,smb_vwv5,nread+3);
1952 SSVAL(smb_buf(outbuf),1,nread);
1954 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1960 /****************************************************************************
1962 ****************************************************************************/
1963 int reply_read(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1965 int cnum,numtoread,fnum;
1971 cnum = SVAL(inbuf,smb_tid);
1972 fnum = GETFNUM(inbuf,smb_vwv0);
1974 CHECK_FNUM(fnum,cnum);
1978 numtoread = SVAL(inbuf,smb_vwv1);
1979 startpos = IVAL(inbuf,smb_vwv2);
1981 outsize = set_message(outbuf,5,3,True);
1982 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1983 data = smb_buf(outbuf) + 3;
1985 if (is_locked(fnum,cnum,numtoread,startpos))
1986 return(ERROR(ERRDOS,ERRlock));
1989 nread = read_file(fnum,data,startpos,numtoread);
1992 return(UNIXERROR(ERRDOS,ERRnoaccess));
1995 SSVAL(outbuf,smb_vwv0,nread);
1996 SSVAL(outbuf,smb_vwv5,nread+3);
1997 CVAL(smb_buf(outbuf),0) = 1;
1998 SSVAL(smb_buf(outbuf),1,nread);
2000 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
2006 /****************************************************************************
2007 reply to a read and X
2008 ****************************************************************************/
2009 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2011 int fnum = GETFNUM(inbuf,smb_vwv2);
2012 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2013 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
2014 int smb_mincnt = SVAL(inbuf,smb_vwv6);
2020 cnum = SVAL(inbuf,smb_tid);
2022 /* If it's an IPC, pass off the pipe handler. */
2024 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2026 CHECK_FNUM(fnum,cnum);
2030 set_message(outbuf,12,0,True);
2031 data = smb_buf(outbuf);
2033 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
2034 return(ERROR(ERRDOS,ERRlock));
2035 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
2039 return(UNIXERROR(ERRDOS,ERRnoaccess));
2041 SSVAL(outbuf,smb_vwv5,nread);
2042 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2043 SSVAL(smb_buf(outbuf),-2,nread);
2045 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
2046 timestring(),fnum,cnum,
2047 smb_mincnt,smb_maxcnt,nread));
2051 return chain_reply(inbuf,outbuf,length,bufsize);
2055 /****************************************************************************
2056 reply to a writebraw (core+ or LANMAN1.0 protocol)
2057 ****************************************************************************/
2058 int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2061 int total_written=0;
2070 cnum = SVAL(inbuf,smb_tid);
2071 fnum = GETFNUM(inbuf,smb_vwv0);
2073 CHECK_FNUM(fnum,cnum);
2077 tcount = IVAL(inbuf,smb_vwv1);
2078 startpos = IVAL(inbuf,smb_vwv3);
2079 write_through = BITSETW(inbuf+smb_vwv7,0);
2081 /* We have to deal with slightly different formats depending
2082 on whether we are using the core+ or lanman1.0 protocol */
2083 if(Protocol <= PROTOCOL_COREPLUS) {
2084 numtowrite = SVAL(smb_buf(inbuf),-2);
2085 data = smb_buf(inbuf);
2087 numtowrite = SVAL(inbuf,smb_vwv10);
2088 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2091 /* force the error type */
2092 CVAL(inbuf,smb_com) = SMBwritec;
2093 CVAL(outbuf,smb_com) = SMBwritec;
2095 if (is_locked(fnum,cnum,tcount,startpos))
2096 return(ERROR(ERRDOS,ERRlock));
2098 if (seek_file(fnum,startpos) != startpos)
2099 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
2102 nwritten = write_file(fnum,data,numtowrite);
2104 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
2105 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
2107 if (nwritten < numtowrite)
2108 return(UNIXERROR(ERRHRD,ERRdiskfull));
2110 total_written = nwritten;
2112 /* Return a message to the redirector to tell it
2113 to send more bytes */
2114 CVAL(outbuf,smb_com) = SMBwritebraw;
2115 SSVALS(outbuf,smb_vwv0,-1);
2116 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2117 send_smb(Client,outbuf);
2119 /* Now read the raw data into the buffer and write it */
2120 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2121 exit_server("secondary writebraw failed");
2124 /* Even though this is not an smb message, smb_len
2125 returns the generic length of an smb message */
2126 numtowrite = smb_len(inbuf);
2128 if (tcount > nwritten+numtowrite) {
2129 DEBUG(3,("Client overestimated the write %d %d %d\n",
2130 tcount,nwritten,numtowrite));
2133 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
2135 total_written += nwritten;
2137 /* Set up outbuf to return the correct return */
2138 outsize = set_message(outbuf,1,0,True);
2139 CVAL(outbuf,smb_com) = SMBwritec;
2140 SSVAL(outbuf,smb_vwv0,total_written);
2142 if (nwritten < numtowrite) {
2143 CVAL(outbuf,smb_rcls) = ERRHRD;
2144 SSVAL(outbuf,smb_err,ERRdiskfull);
2147 if (lp_syncalways(SNUM(cnum)) || write_through)
2150 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
2151 timestring(),fnum,cnum,startpos,numtowrite,total_written));
2153 /* we won't return a status if write through is not selected - this
2154 follows what WfWg does */
2155 if (!write_through && total_written==tcount)
2162 /****************************************************************************
2163 reply to a writeunlock (core+)
2164 ****************************************************************************/
2165 int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2171 uint32 numtowrite,startpos;
2175 cnum = SVAL(inbuf,smb_tid);
2176 fnum = GETFNUM(inbuf,smb_vwv0);
2178 CHECK_FNUM(fnum,cnum);
2182 numtowrite = SVAL(inbuf,smb_vwv1);
2183 startpos = IVAL(inbuf,smb_vwv2);
2184 data = smb_buf(inbuf) + 3;
2186 if (is_locked(fnum,cnum,numtowrite,startpos))
2187 return(ERROR(ERRDOS,ERRlock));
2189 seek_file(fnum,startpos);
2191 /* The special X/Open SMB protocol handling of
2192 zero length writes is *NOT* done for
2197 nwritten = write_file(fnum,data,numtowrite);
2199 if (lp_syncalways(SNUM(cnum)))
2202 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2203 return(UNIXERROR(ERRDOS,ERRnoaccess));
2205 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2206 return(ERROR(eclass,ecode));
2208 outsize = set_message(outbuf,1,0,True);
2210 SSVAL(outbuf,smb_vwv0,nwritten);
2212 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2213 timestring(),fnum,cnum,numtowrite,nwritten));
2219 /****************************************************************************
2221 ****************************************************************************/
2222 int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2224 int cnum,numtowrite,fnum;
2230 cnum = SVAL(inbuf,smb_tid);
2231 fnum = GETFNUM(inbuf,smb_vwv0);
2233 CHECK_FNUM(fnum,cnum);
2237 numtowrite = SVAL(inbuf,smb_vwv1);
2238 startpos = IVAL(inbuf,smb_vwv2);
2239 data = smb_buf(inbuf) + 3;
2241 if (is_locked(fnum,cnum,numtowrite,startpos))
2242 return(ERROR(ERRDOS,ERRlock));
2244 seek_file(fnum,startpos);
2246 /* X/Open SMB protocol says that if smb_vwv1 is
2247 zero then the file size should be extended or
2248 truncated to the size given in smb_vwv[2-3] */
2250 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2252 nwritten = write_file(fnum,data,numtowrite);
2254 if (lp_syncalways(SNUM(cnum)))
2257 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2258 return(UNIXERROR(ERRDOS,ERRnoaccess));
2260 outsize = set_message(outbuf,1,0,True);
2262 SSVAL(outbuf,smb_vwv0,nwritten);
2264 if (nwritten < numtowrite) {
2265 CVAL(outbuf,smb_rcls) = ERRHRD;
2266 SSVAL(outbuf,smb_err,ERRdiskfull);
2269 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2275 /****************************************************************************
2276 reply to a write and X
2277 ****************************************************************************/
2278 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2280 int fnum = GETFNUM(inbuf,smb_vwv2);
2281 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2282 int smb_dsize = SVAL(inbuf,smb_vwv10);
2283 int smb_doff = SVAL(inbuf,smb_vwv11);
2284 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2289 cnum = SVAL(inbuf,smb_tid);
2291 CHECK_FNUM(fnum,cnum);
2295 data = smb_base(inbuf) + smb_doff;
2297 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2298 return(ERROR(ERRDOS,ERRlock));
2300 seek_file(fnum,smb_offs);
2302 /* X/Open SMB protocol says that, unlike SMBwrite
2303 if the length is zero then NO truncation is
2304 done, just a write of zero. To truncate a file,
2309 nwritten = write_file(fnum,data,smb_dsize);
2311 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2312 return(UNIXERROR(ERRDOS,ERRnoaccess));
2314 set_message(outbuf,6,0,True);
2316 SSVAL(outbuf,smb_vwv2,nwritten);
2318 if (nwritten < smb_dsize) {
2319 CVAL(outbuf,smb_rcls) = ERRHRD;
2320 SSVAL(outbuf,smb_err,ERRdiskfull);
2323 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2327 if (lp_syncalways(SNUM(cnum)) || write_through)
2330 return chain_reply(inbuf,outbuf,length,bufsize);
2334 /****************************************************************************
2336 ****************************************************************************/
2337 int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2345 cnum = SVAL(inbuf,smb_tid);
2346 fnum = GETFNUM(inbuf,smb_vwv0);
2348 CHECK_FNUM(fnum,cnum);
2351 mode = SVAL(inbuf,smb_vwv1) & 3;
2352 startpos = IVAL(inbuf,smb_vwv2);
2356 case 0: umode = SEEK_SET; break;
2357 case 1: umode = SEEK_CUR; break;
2358 case 2: umode = SEEK_END; break;
2360 umode = SEEK_SET; break;
2363 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2364 Files[fnum].pos = res;
2366 outsize = set_message(outbuf,2,0,True);
2367 SIVALS(outbuf,smb_vwv0,res);
2369 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2375 /****************************************************************************
2377 ****************************************************************************/
2378 int reply_flush(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2381 int outsize = set_message(outbuf,0,0,True);
2383 cnum = SVAL(inbuf,smb_tid);
2384 fnum = GETFNUM(inbuf,smb_vwv0);
2386 if (fnum != 0xFFFF) {
2387 CHECK_FNUM(fnum,cnum);
2394 for (i=0;i<MAX_OPEN_FILES;i++)
2401 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2406 /****************************************************************************
2408 ****************************************************************************/
2409 int reply_exit(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2411 int outsize = set_message(outbuf,0,0,True);
2412 DEBUG(3,("%s exit\n",timestring()));
2418 /****************************************************************************
2420 ****************************************************************************/
2421 int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2426 int32 eclass = 0, err = 0;
2428 outsize = set_message(outbuf,0,0,True);
2430 cnum = SVAL(inbuf,smb_tid);
2432 /* If it's an IPC, pass off to the pipe handler. */
2434 return reply_pipe_close(inbuf,outbuf);
2436 fnum = GETFNUM(inbuf,smb_vwv0);
2438 CHECK_FNUM(fnum,cnum);
2440 if(HAS_CACHED_ERROR(fnum)) {
2441 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2442 err = Files[fnum].wbmpx_ptr->wr_error;
2445 mtime = make_unix_date3(inbuf+smb_vwv1);
2447 /* try and set the date */
2448 set_filetime(cnum, Files[fnum].name,mtime);
2450 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2451 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2452 Connections[cnum].num_files_open));
2454 close_file(fnum,True);
2456 /* We have a cached error */
2458 return(ERROR(eclass,err));
2464 /****************************************************************************
2465 reply to a writeclose (Core+ protocol)
2466 ****************************************************************************/
2467 int reply_writeclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2469 int cnum,numtowrite,fnum;
2476 cnum = SVAL(inbuf,smb_tid);
2477 fnum = GETFNUM(inbuf,smb_vwv0);
2479 CHECK_FNUM(fnum,cnum);
2483 numtowrite = SVAL(inbuf,smb_vwv1);
2484 startpos = IVAL(inbuf,smb_vwv2);
2485 mtime = make_unix_date3(inbuf+smb_vwv4);
2486 data = smb_buf(inbuf) + 1;
2488 if (is_locked(fnum,cnum,numtowrite,startpos))
2489 return(ERROR(ERRDOS,ERRlock));
2491 seek_file(fnum,startpos);
2493 nwritten = write_file(fnum,data,numtowrite);
2495 set_filetime(cnum, Files[fnum].name,mtime);
2497 close_file(fnum,True);
2499 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2500 timestring(),fnum,cnum,numtowrite,nwritten,
2501 Connections[cnum].num_files_open));
2504 return(UNIXERROR(ERRDOS,ERRnoaccess));
2506 outsize = set_message(outbuf,1,0,True);
2508 SSVAL(outbuf,smb_vwv0,nwritten);
2513 /****************************************************************************
2515 ****************************************************************************/
2516 int reply_lock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2519 int outsize = set_message(outbuf,0,0,True);
2520 uint32 count,offset;
2524 cnum = SVAL(inbuf,smb_tid);
2525 fnum = GETFNUM(inbuf,smb_vwv0);
2527 CHECK_FNUM(fnum,cnum);
2530 count = IVAL(inbuf,smb_vwv1);
2531 offset = IVAL(inbuf,smb_vwv3);
2533 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));
2535 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2536 return (ERROR(eclass,ecode));
2542 /****************************************************************************
2544 ****************************************************************************/
2545 int reply_unlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2548 int outsize = set_message(outbuf,0,0,True);
2549 uint32 count,offset;
2553 cnum = SVAL(inbuf,smb_tid);
2554 fnum = GETFNUM(inbuf,smb_vwv0);
2556 CHECK_FNUM(fnum,cnum);
2559 count = IVAL(inbuf,smb_vwv1);
2560 offset = IVAL(inbuf,smb_vwv3);
2562 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2563 return (ERROR(eclass,ecode));
2565 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));
2571 /****************************************************************************
2573 ****************************************************************************/
2574 int reply_tdis(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2577 int outsize = set_message(outbuf,0,0,True);
2580 cnum = SVAL(inbuf,smb_tid);
2581 vuid = SVAL(inbuf,smb_uid);
2583 if (!OPEN_CNUM(cnum)) {
2584 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2585 return(ERROR(ERRSRV,ERRinvnid));
2588 Connections[cnum].used = False;
2590 close_cnum(cnum,vuid);
2592 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2599 /****************************************************************************
2601 ****************************************************************************/
2602 int reply_echo(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2605 int smb_reverb = SVAL(inbuf,smb_vwv0);
2607 int data_len = smb_buflen(inbuf);
2608 int outsize = set_message(outbuf,1,data_len,True);
2610 cnum = SVAL(inbuf,smb_tid);
2612 /* According to the latest CIFS spec we shouldn't
2613 care what the TID is.
2617 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2619 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2620 return(ERROR(ERRSRV,ERRinvnid));
2624 /* copy any incoming data back out */
2626 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2628 if (smb_reverb > 100)
2630 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2634 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2636 SSVAL(outbuf,smb_vwv0,seq_num);
2638 smb_setlen(outbuf,outsize - 4);
2640 send_smb(Client,outbuf);
2643 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2649 /****************************************************************************
2650 reply to a printopen
2651 ****************************************************************************/
2652 int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2660 *fname = *fname2 = 0;
2662 cnum = SVAL(inbuf,smb_tid);
2664 if (!CAN_PRINT(cnum))
2665 return(ERROR(ERRDOS,ERRnoaccess));
2670 pstrcpy(s,smb_buf(inbuf)+1);
2674 if (!(isalnum(*p) || strchr("._-",*p)))
2679 if (strlen(s) > 10) s[10] = 0;
2681 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2684 fnum = find_free_file();
2686 return(ERROR(ERRSRV,ERRnofids));
2688 pstrcpy(fname2,(char *)mktemp(fname));
2690 if (!check_name(fname2,cnum)) {
2691 Files[fnum].reserved = False;
2692 return(ERROR(ERRDOS,ERRnoaccess));
2695 /* Open for exclusive use, write only. */
2696 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2699 if (!Files[fnum].open) {
2700 Files[fnum].reserved = False;
2701 return(UNIXERROR(ERRDOS,ERRnoaccess));
2704 /* force it to be a print file */
2705 Files[fnum].print_file = True;
2707 outsize = set_message(outbuf,1,0,True);
2708 SSVAL(outbuf,smb_vwv0,fnum);
2710 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2716 /****************************************************************************
2717 reply to a printclose
2718 ****************************************************************************/
2719 int reply_printclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2722 int outsize = set_message(outbuf,0,0,True);
2724 cnum = SVAL(inbuf,smb_tid);
2725 fnum = GETFNUM(inbuf,smb_vwv0);
2727 CHECK_FNUM(fnum,cnum);
2730 if (!CAN_PRINT(cnum))
2731 return(ERROR(ERRDOS,ERRnoaccess));
2733 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2735 close_file(fnum,True);
2741 /****************************************************************************
2742 reply to a printqueue
2743 ****************************************************************************/
2744 int reply_printqueue(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2747 int outsize = set_message(outbuf,2,3,True);
2748 int max_count = SVAL(inbuf,smb_vwv0);
2749 int start_index = SVAL(inbuf,smb_vwv1);
2752 cnum = SVAL(inbuf,smb_tid);
2753 vuid = SVAL(inbuf,smb_uid);
2755 /* allow checking the queue for anyone */
2757 if (!CAN_PRINT(cnum))
2758 return(ERROR(ERRDOS,ERRnoaccess));
2761 SSVAL(outbuf,smb_vwv0,0);
2762 SSVAL(outbuf,smb_vwv1,0);
2763 CVAL(smb_buf(outbuf),0) = 1;
2764 SSVAL(smb_buf(outbuf),1,0);
2766 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2767 timestring(),cnum,start_index,max_count));
2769 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2774 for (i=0;i<MAX_CONNECTIONS;i++)
2775 if (CAN_PRINT(i) && Connections[i].printer)
2779 for (i=0;i<MAX_CONNECTIONS;i++)
2783 if (!OPEN_CNUM(cnum))
2784 return(ERROR(ERRSRV,ERRinvnid));
2786 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2789 if (!become_user(&Connections[cnum], cnum, vuid))
2790 return(ERROR(ERRSRV,ERRinvnid));
2793 print_queue_struct *queue = NULL;
2794 char *p = smb_buf(outbuf) + 3;
2795 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2796 int num_to_get = ABS(max_count);
2797 int first = (max_count>0?start_index:start_index+max_count+1);
2803 num_to_get = MIN(num_to_get,count-first);
2806 for (i=first;i<first+num_to_get;i++)
2808 put_dos_date2(p,0,queue[i].time);
2809 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2810 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2811 SIVAL(p,7,queue[i].size);
2813 StrnCpy(p+12,queue[i].user,16);
2819 outsize = set_message(outbuf,2,28*count+3,False);
2820 SSVAL(outbuf,smb_vwv0,count);
2821 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2822 CVAL(smb_buf(outbuf),0) = 1;
2823 SSVAL(smb_buf(outbuf),1,28*count);
2826 if (queue) free(queue);
2828 DEBUG(3,("%d entries returned in queue\n",count));
2835 /****************************************************************************
2836 reply to a printwrite
2837 ****************************************************************************/
2838 int reply_printwrite(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2840 int cnum,numtowrite,fnum;
2841 int outsize = set_message(outbuf,0,0,True);
2844 cnum = SVAL(inbuf,smb_tid);
2846 if (!CAN_PRINT(cnum))
2847 return(ERROR(ERRDOS,ERRnoaccess));
2849 fnum = GETFNUM(inbuf,smb_vwv0);
2851 CHECK_FNUM(fnum,cnum);
2855 numtowrite = SVAL(smb_buf(inbuf),1);
2856 data = smb_buf(inbuf) + 3;
2858 if (write_file(fnum,data,numtowrite) != numtowrite)
2859 return(UNIXERROR(ERRDOS,ERRnoaccess));
2861 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2867 /****************************************************************************
2869 ****************************************************************************/
2870 int reply_mkdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2874 int outsize,ret= -1;
2875 BOOL bad_path = False;
2877 pstrcpy(directory,smb_buf(inbuf) + 1);
2878 cnum = SVAL(inbuf,smb_tid);
2879 unix_convert(directory,cnum,0,&bad_path);
2881 if (check_name(directory,cnum))
2882 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2886 if((errno == ENOENT) && bad_path)
2888 unix_ERR_class = ERRDOS;
2889 unix_ERR_code = ERRbadpath;
2891 return(UNIXERROR(ERRDOS,ERRnoaccess));
2894 outsize = set_message(outbuf,0,0,True);
2896 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2901 /****************************************************************************
2902 Static function used by reply_rmdir to delete an entire directory
2904 ****************************************************************************/
2905 static BOOL recursive_rmdir(char *directory)
2909 void *dirptr = OpenDir(-1, directory, False);
2914 while((dname = ReadDirName(dirptr)))
2919 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2922 /* Construct the full name. */
2923 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2929 pstrcpy(fullname, directory);
2930 pstrcat(fullname, "/");
2931 pstrcat(fullname, dname);
2933 if(sys_lstat(fullname, &st) != 0)
2939 if(st.st_mode & S_IFDIR)
2941 if(recursive_rmdir(fullname)!=0)
2946 if(sys_rmdir(fullname) != 0)
2952 else if(sys_unlink(fullname) != 0)
2962 /****************************************************************************
2964 ****************************************************************************/
2965 int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2971 BOOL bad_path = False;
2973 cnum = SVAL(inbuf,smb_tid);
2974 pstrcpy(directory,smb_buf(inbuf) + 1);
2975 unix_convert(directory,cnum,0,&bad_path);
2977 if (check_name(directory,cnum))
2980 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2981 ok = (sys_rmdir(directory) == 0);
2982 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2984 /* Check to see if the only thing in this directory are
2985 vetoed files/directories. If so then delete them and
2986 retry. If we fail to delete any of them (and we *don't*
2987 do a recursive delete) then fail the rmdir. */
2988 BOOL all_veto_files = True;
2990 void *dirptr = OpenDir(cnum, directory, False);
2994 int dirpos = TellDir(dirptr);
2995 while ((dname = ReadDirName(dirptr)))
2997 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2999 if(!IS_VETO_PATH(cnum, dname))
3001 all_veto_files = False;
3007 SeekDir(dirptr,dirpos);
3008 while ((dname = ReadDirName(dirptr)))
3013 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3016 /* Construct the full name. */
3017 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3022 pstrcpy(fullname, directory);
3023 pstrcat(fullname, "/");
3024 pstrcat(fullname, dname);
3026 if(sys_lstat(fullname, &st) != 0)
3028 if(st.st_mode & S_IFDIR)
3030 if(lp_recursive_veto_delete(SNUM(cnum)))
3032 if(recursive_rmdir(fullname) != 0)
3035 if(sys_rmdir(fullname) != 0)
3038 else if(sys_unlink(fullname) != 0)
3042 /* Retry the rmdir */
3043 ok = (sys_rmdir(directory) == 0);
3053 DEBUG(3,("couldn't remove directory %s : %s\n",
3054 directory,strerror(errno)));
3059 if((errno == ENOENT) && bad_path)
3061 unix_ERR_class = ERRDOS;
3062 unix_ERR_code = ERRbadpath;
3064 return(UNIXERROR(ERRDOS,ERRbadpath));
3067 outsize = set_message(outbuf,0,0,True);
3069 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
3075 /*******************************************************************
3076 resolve wildcards in a filename rename
3077 ********************************************************************/
3078 static BOOL resolve_wildcards(char *name1,char *name2)
3080 fstring root1,root2;
3084 name1 = strrchr(name1,'/');
3085 name2 = strrchr(name2,'/');
3087 if (!name1 || !name2) return(False);
3089 fstrcpy(root1,name1);
3090 fstrcpy(root2,name2);
3091 p = strrchr(root1,'.');
3098 p = strrchr(root2,'.');
3130 pstrcpy(name2,root2);
3133 pstrcat(name2,ext2);
3139 /*******************************************************************
3140 check if a user is allowed to rename a file
3141 ********************************************************************/
3142 static BOOL can_rename(char *fname,int cnum)
3146 if (!CAN_WRITE(cnum)) return(False);
3148 if (sys_lstat(fname,&sbuf) != 0) return(False);
3149 if (!check_file_sharing(cnum,fname,True)) return(False);
3154 /****************************************************************************
3156 ****************************************************************************/
3157 int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3163 pstring mask,newname;
3164 pstring newname_last_component;
3167 int error = ERRnoaccess;
3170 BOOL bad_path1 = False;
3171 BOOL bad_path2 = False;
3173 *directory = *mask = 0;
3175 cnum = SVAL(inbuf,smb_tid);
3177 pstrcpy(name,smb_buf(inbuf) + 1);
3178 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3180 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3182 unix_convert(name,cnum,0,&bad_path1);
3183 unix_convert(newname,cnum,newname_last_component,&bad_path2);
3186 * Split the old name into directory and last component
3187 * strings. Note that unix_convert may have stripped off a
3188 * leading ./ from both name and newname if the rename is
3189 * at the root of the share. We need to make sure either both
3190 * name and newname contain a / character or neither of them do
3191 * as this is checked in resolve_wildcards().
3194 p = strrchr(name,'/');
3196 pstrcpy(directory,".");
3200 pstrcpy(directory,name);
3202 *p = '/'; /* Replace needed for exceptional test below. */
3205 if (is_mangled(mask))
3206 check_mangled_cache( mask );
3208 has_wild = strchr(mask,'*') || strchr(mask,'?');
3211 BOOL is_short_name = is_8_3(name, True);
3213 /* Add a terminating '/' to the directory name. */
3214 pstrcat(directory,"/");
3215 pstrcat(directory,mask);
3217 /* Ensure newname contains a '/' also */
3218 if(strrchr(newname,'/') == 0) {
3221 pstrcpy(tmpstr, "./");
3222 pstrcat(tmpstr, newname);
3223 pstrcpy(newname, tmpstr);
3226 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",
3227 case_sensitive, case_preserve, short_case_preserve, directory,
3228 newname, newname_last_component, is_short_name));
3231 * Check for special case with case preserving and not
3232 * case sensitive, if directory and newname are identical,
3233 * and the old last component differs from the original
3234 * last component only by case, then we should allow
3235 * the rename (user is trying to change the case of the
3238 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3239 ((short_case_preserve == True) && (is_short_name == True))) &&
3240 strcsequal(directory, newname)) {
3241 pstring newname_modified_last_component;
3244 * Get the last component of the modified name.
3245 * Note that we guarantee that newname contains a '/'
3248 p = strrchr(newname,'/');
3249 pstrcpy(newname_modified_last_component,p+1);
3251 if(strcsequal(newname_modified_last_component,
3252 newname_last_component) == False) {
3254 * Replace the modified last component with
3257 pstrcpy(p+1, newname_last_component);
3261 if (resolve_wildcards(directory,newname) &&
3262 can_rename(directory,cnum) &&
3263 !file_exist(newname,NULL) &&
3264 !sys_rename(directory,newname)) count++;
3266 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3267 directory,newname));
3269 if (!count) exists = file_exist(directory,NULL);
3270 if (!count && exists && file_exist(newname,NULL)) {
3275 void *dirptr = NULL;
3279 if (check_name(directory,cnum))
3280 dirptr = OpenDir(cnum, directory, True);
3286 if (strequal(mask,"????????.???"))
3289 while ((dname = ReadDirName(dirptr)))
3292 pstrcpy(fname,dname);
3294 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3296 error = ERRnoaccess;
3297 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3298 if (!can_rename(fname,cnum)) {
3299 DEBUG(6,("rename %s refused\n", fname));
3302 pstrcpy(destname,newname);
3304 if (!resolve_wildcards(fname,destname)) {
3305 DEBUG(6,("resolve_wildcards %s %s failed\n",
3310 if (file_exist(destname,NULL)) {
3311 DEBUG(6,("file_exist %s\n",
3316 if (!sys_rename(fname,destname)) count++;
3317 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3325 return(ERROR(ERRDOS,error));
3328 if((errno == ENOENT) && (bad_path1 || bad_path2))
3330 unix_ERR_class = ERRDOS;
3331 unix_ERR_code = ERRbadpath;
3333 return(UNIXERROR(ERRDOS,error));
3337 outsize = set_message(outbuf,0,0,True);
3342 /*******************************************************************
3343 copy a file as part of a reply_copy
3344 ******************************************************************/
3345 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3346 int count,BOOL target_is_directory)
3354 pstrcpy(dest,dest1);
3355 if (target_is_directory) {
3356 char *p = strrchr(src,'/');
3365 if (!file_exist(src,&st)) return(False);
3367 fnum1 = find_free_file();
3368 if (fnum1<0) return(False);
3369 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3370 1,0,0,&Access,&action);
3372 if (!Files[fnum1].open) {
3373 Files[fnum1].reserved = False;
3377 if (!target_is_directory && count)
3380 fnum2 = find_free_file();
3382 close_file(fnum1,False);
3385 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3386 ofun,st.st_mode,0,&Access,&action);
3388 if (!Files[fnum2].open) {
3389 close_file(fnum1,False);
3390 Files[fnum2].reserved = False;
3394 if ((ofun&3) == 1) {
3395 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3399 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3401 close_file(fnum1,False);
3402 close_file(fnum2,False);
3404 return(ret == st.st_size);
3409 /****************************************************************************
3410 reply to a file copy.
3411 ****************************************************************************/
3412 int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3418 pstring mask,newname;
3421 int error = ERRnoaccess;
3424 int tid2 = SVAL(inbuf,smb_vwv0);
3425 int ofun = SVAL(inbuf,smb_vwv1);
3426 int flags = SVAL(inbuf,smb_vwv2);
3427 BOOL target_is_directory=False;
3428 BOOL bad_path1 = False;
3429 BOOL bad_path2 = False;
3431 *directory = *mask = 0;
3433 cnum = SVAL(inbuf,smb_tid);
3435 pstrcpy(name,smb_buf(inbuf));
3436 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3438 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3441 /* can't currently handle inter share copies XXXX */
3442 DEBUG(3,("Rejecting inter-share copy\n"));
3443 return(ERROR(ERRSRV,ERRinvdevice));
3446 unix_convert(name,cnum,0,&bad_path1);
3447 unix_convert(newname,cnum,0,&bad_path2);
3449 target_is_directory = directory_exist(newname,NULL);
3451 if ((flags&1) && target_is_directory) {
3452 return(ERROR(ERRDOS,ERRbadfile));
3455 if ((flags&2) && !target_is_directory) {
3456 return(ERROR(ERRDOS,ERRbadpath));
3459 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3460 /* wants a tree copy! XXXX */
3461 DEBUG(3,("Rejecting tree copy\n"));
3462 return(ERROR(ERRSRV,ERRerror));
3465 p = strrchr(name,'/');
3467 pstrcpy(directory,"./");
3471 pstrcpy(directory,name);
3475 if (is_mangled(mask))
3476 check_mangled_cache( mask );
3478 has_wild = strchr(mask,'*') || strchr(mask,'?');
3481 pstrcat(directory,"/");
3482 pstrcat(directory,mask);
3483 if (resolve_wildcards(directory,newname) &&
3484 copy_file(directory,newname,cnum,ofun,
3485 count,target_is_directory)) count++;
3486 if (!count) exists = file_exist(directory,NULL);
3488 void *dirptr = NULL;
3492 if (check_name(directory,cnum))
3493 dirptr = OpenDir(cnum, directory, True);
3499 if (strequal(mask,"????????.???"))
3502 while ((dname = ReadDirName(dirptr)))
3505 pstrcpy(fname,dname);
3507 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3509 error = ERRnoaccess;
3510 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3511 pstrcpy(destname,newname);
3512 if (resolve_wildcards(fname,destname) &&
3513 copy_file(directory,newname,cnum,ofun,
3514 count,target_is_directory)) count++;
3515 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3523 return(ERROR(ERRDOS,error));
3526 if((errno == ENOENT) && (bad_path1 || bad_path2))
3528 unix_ERR_class = ERRDOS;
3529 unix_ERR_code = ERRbadpath;
3531 return(UNIXERROR(ERRDOS,error));
3535 outsize = set_message(outbuf,1,0,True);
3536 SSVAL(outbuf,smb_vwv0,count);
3543 /****************************************************************************
3545 ****************************************************************************/
3546 int reply_setdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3553 cnum = SVAL(inbuf,smb_tid);
3555 snum = Connections[cnum].service;
3556 if (!CAN_SETDIR(snum))
3557 return(ERROR(ERRDOS,ERRnoaccess));
3559 pstrcpy(newdir,smb_buf(inbuf) + 1);
3562 if (strlen(newdir) == 0)
3566 ok = directory_exist(newdir,NULL);
3568 string_set(&Connections[cnum].connectpath,newdir);
3572 return(ERROR(ERRDOS,ERRbadpath));
3574 outsize = set_message(outbuf,0,0,True);
3575 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3577 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3583 /****************************************************************************
3584 reply to a lockingX request
3585 ****************************************************************************/
3586 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3588 int fnum = GETFNUM(inbuf,smb_vwv2);
3589 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3591 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3593 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3594 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3595 uint32 count, offset;
3600 uint32 ecode=0, dummy2;
3601 int eclass=0, dummy1;
3603 cnum = SVAL(inbuf,smb_tid);
3605 CHECK_FNUM(fnum,cnum);
3608 data = smb_buf(inbuf);
3610 /* Check if this is an oplock break on a file
3611 we have granted an oplock on.
3613 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3616 files_struct *fsp = &Files[fnum];
3617 uint32 dev = fsp->fd_ptr->dev;
3618 uint32 inode = fsp->fd_ptr->inode;
3620 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3623 * Make sure we have granted an oplock on this file.
3625 if(!fsp->granted_oplock)
3627 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3628 no oplock granted on this file.\n", fnum));
3629 return ERROR(ERRDOS,ERRlock);
3632 /* Remove the oplock flag from the sharemode. */
3633 lock_share_entry(fsp->cnum, dev, inode, &token);
3634 if(remove_share_oplock( fnum, token)==False) {
3635 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3636 dev = %x, inode = %x\n",
3638 unlock_share_entry(fsp->cnum, dev, inode, token);
3640 unlock_share_entry(fsp->cnum, dev, inode, token);
3642 /* Clear the granted flag and return. */
3643 fsp->granted_oplock = False;
3646 /* if this is a pure oplock break request then don't send a reply */
3647 if (num_locks == 0 && num_ulocks == 0)
3649 /* Sanity check - ensure a pure oplock break is not a
3651 if(CVAL(inbuf,smb_vwv0) != 0xff)
3652 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3653 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3658 /* Data now points at the beginning of the list
3659 of smb_unlkrng structs */
3660 for(i = 0; i < (int)num_ulocks; i++) {
3661 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3662 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3663 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3664 return ERROR(eclass,ecode);
3667 /* Now do any requested locks */
3668 data += 10*num_ulocks;
3669 /* Data now points at the beginning of the list
3670 of smb_lkrng structs */
3671 for(i = 0; i < (int)num_locks; i++) {
3672 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3673 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3674 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3678 /* If any of the above locks failed, then we must unlock
3679 all of the previous locks (X/Open spec). */
3680 if(i != num_locks && num_locks != 0) {
3681 for(; i >= 0; i--) {
3682 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3683 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3684 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3686 return ERROR(eclass,ecode);
3689 set_message(outbuf,2,0,True);
3691 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3692 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3696 return chain_reply(inbuf,outbuf,length,bufsize);
3700 /****************************************************************************
3701 reply to a SMBreadbmpx (read block multiplex) request
3702 ****************************************************************************/
3703 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3710 int outsize, mincount, maxcount;
3715 /* this function doesn't seem to work - disable by default */
3717 return(ERROR(ERRSRV,ERRuseSTD));
3719 outsize = set_message(outbuf,8,0,True);
3721 cnum = SVAL(inbuf,smb_tid);
3722 fnum = GETFNUM(inbuf,smb_vwv0);
3724 CHECK_FNUM(fnum,cnum);
3728 startpos = IVAL(inbuf,smb_vwv1);
3729 maxcount = SVAL(inbuf,smb_vwv3);
3730 mincount = SVAL(inbuf,smb_vwv4);
3732 data = smb_buf(outbuf);
3733 pad = ((long)data)%4;
3734 if (pad) pad = 4 - pad;
3737 max_per_packet = bufsize-(outsize+pad);
3741 if (is_locked(fnum,cnum,maxcount,startpos))
3742 return(ERROR(ERRDOS,ERRlock));
3746 int N = MIN(max_per_packet,tcount-total_read);
3748 nread = read_file(fnum,data,startpos,N);
3750 if (nread <= 0) nread = 0;
3753 tcount = total_read + nread;
3755 set_message(outbuf,8,nread,False);
3756 SIVAL(outbuf,smb_vwv0,startpos);
3757 SSVAL(outbuf,smb_vwv2,tcount);
3758 SSVAL(outbuf,smb_vwv6,nread);
3759 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3761 send_smb(Client,outbuf);
3763 total_read += nread;
3766 while (total_read < tcount);
3772 /****************************************************************************
3773 reply to a SMBwritebmpx (write block multiplex primary) request
3774 ****************************************************************************/
3775 int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3777 int cnum,numtowrite,fnum;
3781 int tcount, write_through, smb_doff;
3784 cnum = SVAL(inbuf,smb_tid);
3785 fnum = GETFNUM(inbuf,smb_vwv0);
3787 CHECK_FNUM(fnum,cnum);
3791 tcount = SVAL(inbuf,smb_vwv1);
3792 startpos = IVAL(inbuf,smb_vwv3);
3793 write_through = BITSETW(inbuf+smb_vwv7,0);
3794 numtowrite = SVAL(inbuf,smb_vwv10);
3795 smb_doff = SVAL(inbuf,smb_vwv11);
3797 data = smb_base(inbuf) + smb_doff;
3799 /* If this fails we need to send an SMBwriteC response,
3800 not an SMBwritebmpx - set this up now so we don't forget */
3801 CVAL(outbuf,smb_com) = SMBwritec;
3803 if (is_locked(fnum,cnum,tcount,startpos))
3804 return(ERROR(ERRDOS,ERRlock));
3806 seek_file(fnum,startpos);
3807 nwritten = write_file(fnum,data,numtowrite);
3809 if(lp_syncalways(SNUM(cnum)) || write_through)
3812 if(nwritten < numtowrite)
3813 return(UNIXERROR(ERRHRD,ERRdiskfull));
3815 /* If the maximum to be written to this file
3816 is greater than what we just wrote then set
3817 up a secondary struct to be attached to this
3818 fd, we will use this to cache error messages etc. */
3819 if(tcount > nwritten)
3821 write_bmpx_struct *wbms;
3822 if(Files[fnum].wbmpx_ptr != NULL)
3823 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3825 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3828 DEBUG(0,("Out of memory in reply_readmpx\n"));
3829 return(ERROR(ERRSRV,ERRnoresource));
3831 wbms->wr_mode = write_through;
3832 wbms->wr_discard = False; /* No errors yet */
3833 wbms->wr_total_written = nwritten;
3834 wbms->wr_errclass = 0;
3836 Files[fnum].wbmpx_ptr = wbms;
3839 /* We are returning successfully, set the message type back to
3841 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3843 outsize = set_message(outbuf,1,0,True);
3845 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3847 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3848 timestring(),fnum,cnum,numtowrite,nwritten));
3850 if (write_through && tcount==nwritten) {
3851 /* we need to send both a primary and a secondary response */
3852 smb_setlen(outbuf,outsize - 4);
3853 send_smb(Client,outbuf);
3855 /* now the secondary */
3856 outsize = set_message(outbuf,1,0,True);
3857 CVAL(outbuf,smb_com) = SMBwritec;
3858 SSVAL(outbuf,smb_vwv0,nwritten);
3865 /****************************************************************************
3866 reply to a SMBwritebs (write block multiplex secondary) request
3867 ****************************************************************************/
3868 int reply_writebs(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3870 int cnum,numtowrite,fnum;
3874 int tcount, write_through, smb_doff;
3876 write_bmpx_struct *wbms;
3877 BOOL send_response = False;
3879 cnum = SVAL(inbuf,smb_tid);
3880 fnum = GETFNUM(inbuf,smb_vwv0);
3881 CHECK_FNUM(fnum,cnum);
3884 tcount = SVAL(inbuf,smb_vwv1);
3885 startpos = IVAL(inbuf,smb_vwv2);
3886 numtowrite = SVAL(inbuf,smb_vwv6);
3887 smb_doff = SVAL(inbuf,smb_vwv7);
3889 data = smb_base(inbuf) + smb_doff;
3891 /* We need to send an SMBwriteC response, not an SMBwritebs */
3892 CVAL(outbuf,smb_com) = SMBwritec;
3894 /* This fd should have an auxiliary struct attached,
3895 check that it does */
3896 wbms = Files[fnum].wbmpx_ptr;
3897 if(!wbms) return(-1);
3899 /* If write through is set we can return errors, else we must
3901 write_through = wbms->wr_mode;
3903 /* Check for an earlier error */
3904 if(wbms->wr_discard)
3905 return -1; /* Just discard the packet */
3907 seek_file(fnum,startpos);
3908 nwritten = write_file(fnum,data,numtowrite);
3910 if(lp_syncalways(SNUM(cnum)) || write_through)
3913 if (nwritten < numtowrite)
3916 /* We are returning an error - we can delete the aux struct */
3917 if (wbms) free((char *)wbms);
3918 Files[fnum].wbmpx_ptr = NULL;
3919 return(ERROR(ERRHRD,ERRdiskfull));
3921 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3924 /* Increment the total written, if this matches tcount
3925 we can discard the auxiliary struct (hurrah !) and return a writeC */
3926 wbms->wr_total_written += nwritten;
3927 if(wbms->wr_total_written >= tcount)
3929 if (write_through) {
3930 outsize = set_message(outbuf,1,0,True);
3931 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3932 send_response = True;
3936 Files[fnum].wbmpx_ptr = NULL;
3946 /****************************************************************************
3947 reply to a SMBsetattrE
3948 ****************************************************************************/
3949 int reply_setattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3952 struct utimbuf unix_times;
3955 outsize = set_message(outbuf,0,0,True);
3957 cnum = SVAL(inbuf,smb_tid);
3958 fnum = GETFNUM(inbuf,smb_vwv0);
3960 CHECK_FNUM(fnum,cnum);
3963 /* Convert the DOS times into unix times. Ignore create
3964 time as UNIX can't set this.
3966 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3967 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3970 * Patch from Ray Frush <frush@engr.colostate.edu>
3971 * Sometimes times are sent as zero - ignore them.
3974 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3976 /* Ignore request */
3977 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3978 not setting timestamps of 0\n",
3979 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3982 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3984 /* set modify time = to access time if modify time was 0 */
3985 unix_times.modtime = unix_times.actime;
3988 /* Set the date on this file */
3989 if(file_utime(cnum, Files[fnum].name, &unix_times))
3990 return(ERROR(ERRDOS,ERRnoaccess));
3992 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3993 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3999 /****************************************************************************
4000 reply to a SMBgetattrE
4001 ****************************************************************************/
4002 int reply_getattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4009 outsize = set_message(outbuf,11,0,True);
4011 cnum = SVAL(inbuf,smb_tid);
4012 fnum = GETFNUM(inbuf,smb_vwv0);
4014 CHECK_FNUM(fnum,cnum);
4017 /* Do an fstat on this file */
4018 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
4019 return(UNIXERROR(ERRDOS,ERRnoaccess));
4021 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
4023 /* Convert the times into dos times. Set create
4024 date to be last modify date as UNIX doesn't save
4026 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
4027 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4028 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4031 SIVAL(outbuf,smb_vwv6,0);
4032 SIVAL(outbuf,smb_vwv8,0);
4036 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
4037 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
4039 SSVAL(outbuf,smb_vwv10, mode);
4041 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));