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 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()));
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));
369 /****************************************************************************
370 always return an error: it's just a matter of which one...
371 ****************************************************************************/
372 static int session_trust_account(char *inbuf, char *outbuf, char *user,
373 char *smb_passwd, int smb_passlen,
374 char *smb_nt_passwd, int smb_nt_passlen)
376 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
377 if (lp_security() == SEC_USER)
379 smb_trust_acct = get_smbpwd_entry(user, 0);
383 DEBUG(3,("Trust account %s only supported with security = user\n", user));
384 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
385 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
388 if (smb_trust_acct == NULL)
390 /* lkclXXXX: workstation entry doesn't exist */
391 DEBUG(4,("Trust account %s user doesn't exist\n",user));
392 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
393 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
397 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
399 DEBUG(4,("Trust account %s - password length wrong.\n", user));
400 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
401 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
404 if (!smb_password_ok(smb_trust_acct, smb_passwd, smb_nt_passwd))
406 DEBUG(4,("Trust Account %s - password failed\n", user));
407 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
408 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
411 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
413 DEBUG(4,("Domain trust account %s denied by server\n",user));
414 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
415 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
418 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
420 DEBUG(4,("Server trust account %s denied by server\n",user));
421 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
422 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
424 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
426 DEBUG(4,("Wksta trust account %s denied by server\n", user));
427 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
428 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
432 /* don't know what to do: indicate logon failure */
433 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
434 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
438 /****************************************************************************
439 reply to a session setup command
440 ****************************************************************************/
441 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
450 int smb_apasslen = 0;
452 int smb_ntpasslen = 0;
453 pstring smb_ntpasswd;
454 BOOL valid_nt_password = False;
457 static BOOL done_sesssetup = False;
458 BOOL doencrypt = SMBENCRYPT();
464 smb_bufsize = SVAL(inbuf,smb_vwv2);
465 smb_mpxmax = SVAL(inbuf,smb_vwv3);
466 smb_vc_num = SVAL(inbuf,smb_vwv4);
467 smb_sesskey = IVAL(inbuf,smb_vwv5);
469 if (Protocol < PROTOCOL_NT1) {
470 smb_apasslen = SVAL(inbuf,smb_vwv7);
471 if (smb_apasslen > MAX_PASS_LEN)
473 overflow_attack(smb_apasslen);
476 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
477 smb_apasswd[smb_apasslen] = 0;
478 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
480 if (!doencrypt && (lp_security() != SEC_SERVER)) {
481 smb_apasslen = strlen(smb_apasswd);
484 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
485 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
486 uint32 client_caps = IVAL(inbuf,smb_vwv11);
487 enum remote_arch_types ra_type = get_remote_arch();
489 char *p = smb_buf(inbuf);
491 /* client_caps is used as final determination if client is NT or Win95.
492 This is needed to return the correct error codes in some
496 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
498 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
499 set_remote_arch( RA_WINNT);
501 set_remote_arch( RA_WIN95);
504 if (passlen1 != 24 && passlen2 != 24)
507 if (passlen1 > MAX_PASS_LEN) {
508 overflow_attack(passlen1);
511 passlen1 = MIN(passlen1, MAX_PASS_LEN);
512 passlen2 = MIN(passlen2, MAX_PASS_LEN);
514 if(doencrypt || (lp_security() == SEC_SERVER)) {
515 /* Save the lanman2 password and the NT md4 password. */
516 smb_apasslen = passlen1;
517 memcpy(smb_apasswd,p,smb_apasslen);
518 smb_apasswd[smb_apasslen] = 0;
519 smb_ntpasslen = passlen2;
520 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
521 smb_ntpasswd[smb_ntpasslen] = 0;
523 /* both Win95 and WinNT stuff up the password lengths for
524 non-encrypting systems. Uggh.
526 if passlen1==24 its a win95 system, and its setting the
527 password length incorrectly. Luckily it still works with the
528 default code because Win95 will null terminate the password
531 if passlen1>0 and passlen2>0 then maybe its a NT box and its
532 setting passlen2 to some random value which really stuffs
533 things up. we need to fix that one. */
534 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
538 /* we use the first password that they gave */
539 smb_apasslen = passlen1;
540 StrnCpy(smb_apasswd,p,smb_apasslen);
542 /* trim the password */
543 smb_apasslen = strlen(smb_apasswd);
545 /* wfwg sometimes uses a space instead of a null */
546 if (strequal(smb_apasswd," ")) {
552 p += passlen1 + passlen2;
553 fstrcpy(user,p); p = skip_string(p,1);
556 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
557 domain,skip_string(p,1),skip_string(p,2)));
561 DEBUG(3,("sesssetupX:name=[%s]\n",user));
563 /* If name ends in $ then I think it's asking about whether a */
564 /* computer with that name (minus the $) has access. For now */
565 /* say yes to everything ending in $. */
566 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
568 return session_trust_account(inbuf, outbuf, user,
569 smb_apasswd, smb_apasslen,
570 smb_ntpasswd, smb_ntpasslen);
573 /* If no username is sent use the guest account */
576 strcpy(user,lp_guestaccount(-1));
577 /* If no user and no password then set guest flag. */
578 if( *smb_apasswd == 0)
584 strcpy(sesssetup_user,user);
586 reload_services(True);
588 add_session_user(user);
590 /* Check if the given username was the guest user with no password.
591 We need to do this check after add_session_user() as that
592 call can potentially change the username (via map_user).
595 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
598 if (!guest && !(lp_security() == SEC_SERVER &&
599 server_validate(user, domain,
600 smb_apasswd, smb_apasslen,
601 smb_ntpasswd, smb_ntpasslen)) &&
602 !check_hosts_equiv(user))
605 /* now check if it's a valid username/password */
606 /* If an NT password was supplied try and validate with that
607 first. This is superior as the passwords are mixed case
608 128 length unicode */
611 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
612 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
614 valid_nt_password = True;
616 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
618 if (lp_security() >= SEC_USER) {
619 #if (GUEST_SESSSETUP == 0)
620 return(ERROR(ERRSRV,ERRbadpw));
622 #if (GUEST_SESSSETUP == 1)
623 if (Get_Pwnam(user,True))
624 return(ERROR(ERRSRV,ERRbadpw));
627 if (*smb_apasswd || !Get_Pwnam(user,True))
628 strcpy(user,lp_guestaccount(-1));
629 DEBUG(3,("Registered username %s for guest access\n",user));
634 if (!Get_Pwnam(user,True)) {
635 DEBUG(3,("No such user %s - using guest account\n",user));
636 strcpy(user,lp_guestaccount(-1));
640 if (!strequal(user,lp_guestaccount(-1)) &&
641 lp_servicenumber(user) < 0)
643 int homes = lp_servicenumber(HOMES_NAME);
644 char *home = get_home_dir(user);
645 if (homes >= 0 && home)
646 lp_add_home(user,homes,home);
650 /* it's ok - setup a reply */
651 if (Protocol < PROTOCOL_NT1) {
652 set_message(outbuf,3,0,True);
655 set_message(outbuf,3,3,True);
657 strcpy(p,"Unix"); p = skip_string(p,1);
658 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
659 strcpy(p,myworkgroup); p = skip_string(p,1);
660 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
661 /* perhaps grab OS version here?? */
664 /* Set the correct uid in the outgoing and incoming packets
665 We will use this on future requests to determine which
666 user we should become.
669 struct passwd *pw = Get_Pwnam(user,False);
671 DEBUG(1,("Username %s is invalid on this system\n",user));
672 return(ERROR(ERRSRV,ERRbadpw));
679 SSVAL(outbuf,smb_vwv2,1);
681 /* register the name and uid as being validated, so further connections
682 to a uid can get through without a password, on the same VC */
683 sess_vuid = register_vuid(uid,gid,user,guest);
685 SSVAL(outbuf,smb_uid,sess_vuid);
686 SSVAL(inbuf,smb_uid,sess_vuid);
689 max_send = MIN(max_send,smb_bufsize);
691 DEBUG(6,("Client requested max send size of %d\n", max_send));
693 done_sesssetup = True;
695 return chain_reply(inbuf,outbuf,length,bufsize);
699 /****************************************************************************
701 ****************************************************************************/
702 int reply_chkpth(char *inbuf,char *outbuf)
708 BOOL bad_path = False;
710 cnum = SVAL(inbuf,smb_tid);
712 pstrcpy(name,smb_buf(inbuf) + 1);
713 unix_convert(name,cnum,0,&bad_path);
715 mode = SVAL(inbuf,smb_vwv0);
717 if (check_name(name,cnum))
718 ok = directory_exist(name,NULL);
722 /* We special case this - as when a Windows machine
723 is parsing a path is steps through the components
724 one at a time - if a component fails it expects
725 ERRbadpath, not ERRbadfile.
729 unix_ERR_class = ERRDOS;
730 unix_ERR_code = ERRbadpath;
734 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
735 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
736 (get_remote_arch() == RA_WINNT))
738 unix_ERR_class = ERRDOS;
739 unix_ERR_code = ERRbaddirectory;
743 return(UNIXERROR(ERRDOS,ERRbadpath));
746 outsize = set_message(outbuf,0,0,True);
748 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
754 /****************************************************************************
756 ****************************************************************************/
757 int reply_getatr(char *inbuf,char *outbuf)
767 BOOL bad_path = False;
769 cnum = SVAL(inbuf,smb_tid);
771 pstrcpy(fname,smb_buf(inbuf) + 1);
772 unix_convert(fname,cnum,0,&bad_path);
774 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
775 under WfWg - weird! */
778 mode = aHIDDEN | aDIR;
779 if (!CAN_WRITE(cnum)) mode |= aRONLY;
785 if (check_name(fname,cnum))
787 if (sys_stat(fname,&sbuf) == 0)
789 mode = dos_mode(cnum,fname,&sbuf);
791 mtime = sbuf.st_mtime;
797 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
802 if((errno == ENOENT) && bad_path)
804 unix_ERR_class = ERRDOS;
805 unix_ERR_code = ERRbadpath;
808 return(UNIXERROR(ERRDOS,ERRbadfile));
811 outsize = set_message(outbuf,10,0,True);
813 SSVAL(outbuf,smb_vwv0,mode);
814 if(lp_dos_filetime_resolution(SNUM(cnum)) )
815 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
817 put_dos_date3(outbuf,smb_vwv1,mtime);
818 SIVAL(outbuf,smb_vwv3,size);
820 if (Protocol >= PROTOCOL_NT1) {
821 char *p = strrchr(fname,'/');
822 uint16 flg2 = SVAL(outbuf,smb_flg2);
824 if (!is_8_3(fname, True))
825 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
828 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
834 /****************************************************************************
836 ****************************************************************************/
837 int reply_setatr(char *inbuf,char *outbuf)
845 BOOL bad_path = False;
847 cnum = SVAL(inbuf,smb_tid);
849 pstrcpy(fname,smb_buf(inbuf) + 1);
850 unix_convert(fname,cnum,0,&bad_path);
852 mode = SVAL(inbuf,smb_vwv0);
853 mtime = make_unix_date3(inbuf+smb_vwv1);
855 if (directory_exist(fname,NULL))
857 if (check_name(fname,cnum))
858 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
860 ok = set_filetime(cnum,fname,mtime);
864 if((errno == ENOENT) && bad_path)
866 unix_ERR_class = ERRDOS;
867 unix_ERR_code = ERRbadpath;
870 return(UNIXERROR(ERRDOS,ERRnoaccess));
873 outsize = set_message(outbuf,0,0,True);
875 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
881 /****************************************************************************
883 ****************************************************************************/
884 int reply_dskattr(char *inbuf,char *outbuf)
888 int dfree,dsize,bsize;
890 cnum = SVAL(inbuf,smb_tid);
892 sys_disk_free(".",&bsize,&dfree,&dsize);
894 outsize = set_message(outbuf,5,0,True);
896 SSVAL(outbuf,smb_vwv0,dsize);
897 SSVAL(outbuf,smb_vwv1,bsize/512);
898 SSVAL(outbuf,smb_vwv2,512);
899 SSVAL(outbuf,smb_vwv3,dfree);
901 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
907 /****************************************************************************
909 Can be called from SMBsearch, SMBffirst or SMBfunique.
910 ****************************************************************************/
911 int reply_search(char *inbuf,char *outbuf)
922 BOOL finished = False;
931 BOOL check_descend = False;
932 BOOL expect_close = False;
933 BOOL can_open = True;
934 BOOL bad_path = False;
936 *mask = *directory = *fname = 0;
938 /* If we were called as SMBffirst then we must expect close. */
939 if(CVAL(inbuf,smb_com) == SMBffirst)
942 cnum = SVAL(inbuf,smb_tid);
944 outsize = set_message(outbuf,1,3,True);
945 maxentries = SVAL(inbuf,smb_vwv0);
946 dirtype = SVAL(inbuf,smb_vwv1);
947 path = smb_buf(inbuf) + 1;
948 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
951 /* dirtype &= ~aDIR; */
953 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
960 pstrcpy(directory,smb_buf(inbuf)+1);
961 pstrcpy(dir2,smb_buf(inbuf)+1);
962 unix_convert(directory,cnum,0,&bad_path);
965 if (!check_name(directory,cnum))
968 p = strrchr(dir2,'/');
980 p = strrchr(directory,'/');
986 if (strlen(directory) == 0)
987 strcpy(directory,"./");
989 CVAL(status,0) = dirtype;
993 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
994 memcpy(mask,status+1,11);
996 dirtype = CVAL(status,0) & 0x1F;
997 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
998 if (!Connections[cnum].dirptr)
1000 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
1001 if (!case_sensitive)
1005 /* turn strings of spaces into a . */
1007 trim_string(mask,NULL," ");
1008 if ((p = strrchr(mask,' ')))
1013 trim_string(mask,NULL," ");
1020 for (p=mask; *p; p++)
1022 if (*p != '?' && *p != '*' && !isdoschar(*p))
1024 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1030 if (!strchr(mask,'.') && strlen(mask)>8)
1033 fstrcpy(tmp,&mask[8]);
1039 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1043 p = smb_buf(outbuf) + 3;
1047 if (status_len == 0)
1049 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
1054 if((errno == ENOENT) && bad_path)
1056 unix_ERR_class = ERRDOS;
1057 unix_ERR_code = ERRbadpath;
1059 return (UNIXERROR(ERRDOS,ERRnofids));
1061 return(ERROR(ERRDOS,ERRnofids));
1065 DEBUG(4,("dptr_num is %d\n",dptr_num));
1069 if ((dirtype&0x1F) == aVOLID)
1071 memcpy(p,status,21);
1072 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
1073 dptr_fill(p+12,dptr_num);
1074 if (dptr_zero(p+12) && (status_len==0))
1078 p += DIR_STRUCT_SIZE;
1082 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
1083 if (in_list(Connections[cnum].dirpath,
1084 lp_dontdescend(SNUM(cnum)),True))
1085 check_descend = True;
1087 for (i=numentries;(i<maxentries) && !finished;i++)
1090 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
1093 memcpy(p,status,21);
1094 make_dir_struct(p,mask,fname,size,mode,date);
1095 dptr_fill(p+12,dptr_num);
1098 p += DIR_STRUCT_SIZE;
1107 if (numentries == 0 || !ok)
1109 CVAL(outbuf,smb_rcls) = ERRDOS;
1110 SSVAL(outbuf,smb_err,ERRnofiles);
1113 /* If we were called as SMBffirst with smb_search_id == NULL
1114 and no entries were found then return error and close dirptr
1117 if(ok && expect_close && numentries == 0 && status_len == 0)
1119 CVAL(outbuf,smb_rcls) = ERRDOS;
1120 SSVAL(outbuf,smb_err,ERRnofiles);
1121 /* Also close the dptr - we know it's gone */
1122 dptr_close(dptr_num);
1125 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1126 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1127 dptr_close(dptr_num);
1129 SSVAL(outbuf,smb_vwv0,numentries);
1130 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1131 CVAL(smb_buf(outbuf),0) = 5;
1132 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1134 if (Protocol >= PROTOCOL_NT1) {
1135 uint16 flg2 = SVAL(outbuf,smb_flg2);
1136 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1139 outsize += DIR_STRUCT_SIZE*numentries;
1140 smb_setlen(outbuf,outsize - 4);
1142 if ((! *directory) && dptr_path(dptr_num))
1143 sprintf(directory,"(%s)",dptr_path(dptr_num));
1145 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1147 smb_fn_name(CVAL(inbuf,smb_com)),
1148 mask,directory,cnum,dirtype,numentries,maxentries));
1154 /****************************************************************************
1155 reply to a fclose (stop directory search)
1156 ****************************************************************************/
1157 int reply_fclose(char *inbuf,char *outbuf)
1166 cnum = SVAL(inbuf,smb_tid);
1168 outsize = set_message(outbuf,1,0,True);
1169 path = smb_buf(inbuf) + 1;
1170 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1173 if (status_len == 0)
1174 return(ERROR(ERRSRV,ERRsrverror));
1176 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1178 if(dptr_fetch(status+12,&dptr_num)) {
1179 /* Close the dptr - we know it's gone */
1180 dptr_close(dptr_num);
1183 SSVAL(outbuf,smb_vwv0,0);
1185 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1191 /****************************************************************************
1193 ****************************************************************************/
1194 int reply_open(char *inbuf,char *outbuf)
1207 BOOL bad_path = False;
1209 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1211 cnum = SVAL(inbuf,smb_tid);
1213 share_mode = SVAL(inbuf,smb_vwv0);
1215 pstrcpy(fname,smb_buf(inbuf)+1);
1216 unix_convert(fname,cnum,0,&bad_path);
1218 fnum = find_free_file();
1220 return(ERROR(ERRSRV,ERRnofids));
1222 if (!check_name(fname,cnum))
1224 if((errno == ENOENT) && bad_path)
1226 unix_ERR_class = ERRDOS;
1227 unix_ERR_code = ERRbadpath;
1229 Files[fnum].reserved = False;
1230 return(UNIXERROR(ERRDOS,ERRnoaccess));
1233 unixmode = unix_mode(cnum,aARCH);
1235 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1236 oplock_request,&rmode,NULL);
1242 if((errno == ENOENT) && bad_path)
1244 unix_ERR_class = ERRDOS;
1245 unix_ERR_code = ERRbadpath;
1247 Files[fnum].reserved = False;
1248 return(UNIXERROR(ERRDOS,ERRnoaccess));
1251 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1252 close_file(fnum,False);
1253 return(ERROR(ERRDOS,ERRnoaccess));
1256 size = sbuf.st_size;
1257 fmode = dos_mode(cnum,fname,&sbuf);
1258 mtime = sbuf.st_mtime;
1261 DEBUG(3,("attempt to open a directory %s\n",fname));
1262 close_file(fnum,False);
1263 return(ERROR(ERRDOS,ERRnoaccess));
1266 outsize = set_message(outbuf,7,0,True);
1267 SSVAL(outbuf,smb_vwv0,fnum);
1268 SSVAL(outbuf,smb_vwv1,fmode);
1269 if(lp_dos_filetime_resolution(SNUM(cnum)) )
1270 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1272 put_dos_date3(outbuf,smb_vwv2,mtime);
1273 SIVAL(outbuf,smb_vwv4,size);
1274 SSVAL(outbuf,smb_vwv6,rmode);
1276 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1277 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1280 if(fsp->granted_oplock)
1281 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1286 /****************************************************************************
1287 reply to an open and X
1288 ****************************************************************************/
1289 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1292 int cnum = SVAL(inbuf,smb_tid);
1294 int smb_mode = SVAL(inbuf,smb_vwv3);
1295 int smb_attr = SVAL(inbuf,smb_vwv5);
1296 /* Breakout the oplock request bits so we can set the
1297 reply bits separately. */
1298 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1299 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1300 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1302 int open_flags = SVAL(inbuf,smb_vwv2);
1303 int smb_sattr = SVAL(inbuf,smb_vwv4);
1304 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1306 int smb_ofun = SVAL(inbuf,smb_vwv8);
1308 int size=0,fmode=0,mtime=0,rmode=0;
1311 BOOL bad_path = False;
1314 /* If it's an IPC, pass off the pipe handler. */
1316 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1318 /* XXXX we need to handle passed times, sattr and flags */
1320 pstrcpy(fname,smb_buf(inbuf));
1321 unix_convert(fname,cnum,0,&bad_path);
1323 fnum = find_free_file();
1325 return(ERROR(ERRSRV,ERRnofids));
1327 if (!check_name(fname,cnum))
1329 if((errno == ENOENT) && bad_path)
1331 unix_ERR_class = ERRDOS;
1332 unix_ERR_code = ERRbadpath;
1334 Files[fnum].reserved = False;
1335 return(UNIXERROR(ERRDOS,ERRnoaccess));
1338 unixmode = unix_mode(cnum,smb_attr | aARCH);
1340 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1341 oplock_request, &rmode,&smb_action);
1347 if((errno == ENOENT) && bad_path)
1349 unix_ERR_class = ERRDOS;
1350 unix_ERR_code = ERRbadpath;
1352 Files[fnum].reserved = False;
1353 return(UNIXERROR(ERRDOS,ERRnoaccess));
1356 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1357 close_file(fnum,False);
1358 return(ERROR(ERRDOS,ERRnoaccess));
1361 size = sbuf.st_size;
1362 fmode = dos_mode(cnum,fname,&sbuf);
1363 mtime = sbuf.st_mtime;
1365 close_file(fnum,False);
1366 return(ERROR(ERRDOS,ERRnoaccess));
1369 /* If the caller set the extended oplock request bit
1370 and we granted one (by whatever means) - set the
1371 correct bit for extended oplock reply.
1374 if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1375 smb_action |= EXTENDED_OPLOCK_GRANTED;
1378 if(ex_oplock_request && fsp->granted_oplock) {
1379 smb_action |= EXTENDED_OPLOCK_GRANTED;
1382 /* If the caller set the core oplock request bit
1383 and we granted one (by whatever means) - set the
1384 correct bit for core oplock reply.
1387 if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1388 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1391 if(core_oplock_request && fsp->granted_oplock) {
1392 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1395 set_message(outbuf,15,0,True);
1396 SSVAL(outbuf,smb_vwv2,fnum);
1397 SSVAL(outbuf,smb_vwv3,fmode);
1398 if(lp_dos_filetime_resolution(SNUM(cnum)) )
1399 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1401 put_dos_date3(outbuf,smb_vwv4,mtime);
1402 SIVAL(outbuf,smb_vwv6,size);
1403 SSVAL(outbuf,smb_vwv8,rmode);
1404 SSVAL(outbuf,smb_vwv11,smb_action);
1408 return chain_reply(inbuf,outbuf,length,bufsize);
1412 /****************************************************************************
1413 reply to a SMBulogoffX
1414 ****************************************************************************/
1415 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1417 uint16 vuid = SVAL(inbuf,smb_uid);
1418 user_struct *vuser = get_valid_user_struct(vuid);
1421 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1424 /* in user level security we are supposed to close any files
1425 open by this user */
1426 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1428 for (i=0;i<MAX_OPEN_FILES;i++)
1429 if ((Files[i].vuid == vuid) && Files[i].open) {
1430 close_file(i,False);
1434 invalidate_vuid(vuid);
1436 set_message(outbuf,2,0,True);
1438 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1440 return chain_reply(inbuf,outbuf,length,bufsize);
1444 /****************************************************************************
1445 reply to a mknew or a create
1446 ****************************************************************************/
1447 int reply_mknew(char *inbuf,char *outbuf)
1456 BOOL bad_path = False;
1458 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1460 com = SVAL(inbuf,smb_com);
1461 cnum = SVAL(inbuf,smb_tid);
1463 createmode = SVAL(inbuf,smb_vwv0);
1464 pstrcpy(fname,smb_buf(inbuf)+1);
1465 unix_convert(fname,cnum,0,&bad_path);
1467 if (createmode & aVOLID)
1469 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1472 unixmode = unix_mode(cnum,createmode);
1474 fnum = find_free_file();
1476 return(ERROR(ERRSRV,ERRnofids));
1478 if (!check_name(fname,cnum))
1480 if((errno == ENOENT) && bad_path)
1482 unix_ERR_class = ERRDOS;
1483 unix_ERR_code = ERRbadpath;
1485 Files[fnum].reserved = False;
1486 return(UNIXERROR(ERRDOS,ERRnoaccess));
1491 /* We should fail if file exists. */
1496 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1500 /* Open file in dos compatibility share mode. */
1501 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1502 oplock_request, NULL, NULL);
1508 if((errno == ENOENT) && bad_path)
1510 unix_ERR_class = ERRDOS;
1511 unix_ERR_code = ERRbadpath;
1513 Files[fnum].reserved = False;
1514 return(UNIXERROR(ERRDOS,ERRnoaccess));
1517 outsize = set_message(outbuf,1,0,True);
1518 SSVAL(outbuf,smb_vwv0,fnum);
1520 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1521 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1524 if(fsp->granted_oplock)
1525 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1527 DEBUG(2,("new file %s\n",fname));
1528 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));
1534 /****************************************************************************
1535 reply to a create temporary file
1536 ****************************************************************************/
1537 int reply_ctemp(char *inbuf,char *outbuf)
1546 BOOL bad_path = False;
1548 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1550 cnum = SVAL(inbuf,smb_tid);
1551 createmode = SVAL(inbuf,smb_vwv0);
1552 pstrcpy(fname,smb_buf(inbuf)+1);
1553 strcat(fname,"/TMXXXXXX");
1554 unix_convert(fname,cnum,0,&bad_path);
1556 unixmode = unix_mode(cnum,createmode);
1558 fnum = find_free_file();
1560 return(ERROR(ERRSRV,ERRnofids));
1562 if (!check_name(fname,cnum))
1564 if((errno == ENOENT) && bad_path)
1566 unix_ERR_class = ERRDOS;
1567 unix_ERR_code = ERRbadpath;
1569 Files[fnum].reserved = False;
1570 return(UNIXERROR(ERRDOS,ERRnoaccess));
1573 strcpy(fname2,(char *)mktemp(fname));
1575 /* Open file in dos compatibility share mode. */
1576 /* We should fail if file exists. */
1577 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1578 oplock_request, NULL, NULL);
1584 if((errno == ENOENT) && bad_path)
1586 unix_ERR_class = ERRDOS;
1587 unix_ERR_code = ERRbadpath;
1589 Files[fnum].reserved = False;
1590 return(UNIXERROR(ERRDOS,ERRnoaccess));
1593 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1594 SSVAL(outbuf,smb_vwv0,fnum);
1595 CVAL(smb_buf(outbuf),0) = 4;
1596 strcpy(smb_buf(outbuf) + 1,fname2);
1598 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1599 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1602 if(fsp->granted_oplock)
1603 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1605 DEBUG(2,("created temp file %s\n",fname2));
1606 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));
1612 /*******************************************************************
1613 check if a user is allowed to delete a file
1614 ********************************************************************/
1615 static BOOL can_delete(char *fname,int cnum,int dirtype)
1620 if (!CAN_WRITE(cnum)) return(False);
1622 if (sys_lstat(fname,&sbuf) != 0) return(False);
1623 fmode = dos_mode(cnum,fname,&sbuf);
1624 if (fmode & aDIR) return(False);
1625 if (!lp_delete_readonly(SNUM(cnum))) {
1626 if (fmode & aRONLY) return(False);
1628 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1630 if (!check_file_sharing(cnum,fname,False)) return(False);
1634 /****************************************************************************
1636 ****************************************************************************/
1637 int reply_unlink(char *inbuf,char *outbuf)
1647 int error = ERRnoaccess;
1650 BOOL bad_path = False;
1652 *directory = *mask = 0;
1654 cnum = SVAL(inbuf,smb_tid);
1655 dirtype = SVAL(inbuf,smb_vwv0);
1657 pstrcpy(name,smb_buf(inbuf) + 1);
1659 DEBUG(3,("reply_unlink : %s\n",name));
1661 unix_convert(name,cnum,0,&bad_path);
1663 p = strrchr(name,'/');
1665 strcpy(directory,"./");
1669 strcpy(directory,name);
1673 if (is_mangled(mask))
1674 check_mangled_stack(mask);
1676 has_wild = strchr(mask,'*') || strchr(mask,'?');
1679 strcat(directory,"/");
1680 strcat(directory,mask);
1681 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1682 if (!count) exists = file_exist(directory,NULL);
1684 void *dirptr = NULL;
1687 if (check_name(directory,cnum))
1688 dirptr = OpenDir(cnum, directory, True);
1690 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1691 the pattern matches against the long name, otherwise the short name
1692 We don't implement this yet XXXX
1699 if (strequal(mask,"????????.???"))
1702 while ((dname = ReadDirName(dirptr)))
1705 pstrcpy(fname,dname);
1707 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1709 error = ERRnoaccess;
1710 sprintf(fname,"%s/%s",directory,dname);
1711 if (!can_delete(fname,cnum,dirtype)) continue;
1712 if (!sys_unlink(fname)) count++;
1713 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1721 return(ERROR(ERRDOS,error));
1724 if((errno == ENOENT) && bad_path)
1726 unix_ERR_class = ERRDOS;
1727 unix_ERR_code = ERRbadpath;
1729 return(UNIXERROR(ERRDOS,error));
1733 outsize = set_message(outbuf,0,0,True);
1739 /****************************************************************************
1740 reply to a readbraw (core+ protocol)
1741 ****************************************************************************/
1742 int reply_readbraw(char *inbuf, char *outbuf)
1744 int cnum,maxcount,mincount,fnum;
1747 char *header = outbuf;
1753 * Special check if an oplock break has been issued
1754 * and the readraw request croses on the wire, we must
1755 * return a zero length response here.
1758 if(global_oplock_break)
1760 _smb_setlen(header,0);
1761 transfer_file(0,Client,0,header,4,0);
1762 DEBUG(5,("readbraw - oplock break finished\n"));
1766 cnum = SVAL(inbuf,smb_tid);
1767 fnum = GETFNUM(inbuf,smb_vwv0);
1769 startpos = IVAL(inbuf,smb_vwv1);
1770 maxcount = SVAL(inbuf,smb_vwv3);
1771 mincount = SVAL(inbuf,smb_vwv4);
1773 /* ensure we don't overrun the packet size */
1774 maxcount = MIN(65535,maxcount);
1775 maxcount = MAX(mincount,maxcount);
1777 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1779 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1780 _smb_setlen(header,0);
1781 transfer_file(0,Client,0,header,4,0);
1786 fd = Files[fnum].fd_ptr->fd;
1787 fname = Files[fnum].name;
1791 if (!is_locked(fnum,cnum,maxcount,startpos))
1793 int size = Files[fnum].size;
1794 int sizeneeded = startpos + maxcount;
1796 if (size < sizeneeded) {
1798 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1800 if (!Files[fnum].can_write)
1801 Files[fnum].size = size;
1804 nread = MIN(maxcount,(int)(size - startpos));
1807 if (nread < mincount)
1810 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1813 maxcount,mincount,nread));
1818 _smb_setlen(header,nread);
1820 #if USE_READ_PREDICTION
1821 if (!Files[fnum].can_write)
1822 predict = read_predict(fd,startpos,header+4,NULL,nread);
1825 if ((nread-predict) > 0)
1826 seek_file(fnum,startpos + predict);
1828 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1833 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1834 fname,startpos,nread,ret));
1837 ret = read_file(fnum,header+4,startpos,nread);
1838 if (ret < mincount) ret = 0;
1840 _smb_setlen(header,ret);
1841 transfer_file(0,Client,0,header,4+ret,0);
1844 DEBUG(5,("readbraw finished\n"));
1849 /****************************************************************************
1850 reply to a lockread (core+ protocol)
1851 ****************************************************************************/
1852 int reply_lockread(char *inbuf,char *outbuf)
1858 uint32 startpos, numtoread;
1862 cnum = SVAL(inbuf,smb_tid);
1863 fnum = GETFNUM(inbuf,smb_vwv0);
1865 CHECK_FNUM(fnum,cnum);
1869 numtoread = SVAL(inbuf,smb_vwv1);
1870 startpos = IVAL(inbuf,smb_vwv2);
1872 outsize = set_message(outbuf,5,3,True);
1873 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1874 data = smb_buf(outbuf) + 3;
1876 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1877 return (ERROR(eclass,ecode));
1879 nread = read_file(fnum,data,startpos,numtoread);
1882 return(UNIXERROR(ERRDOS,ERRnoaccess));
1885 SSVAL(outbuf,smb_vwv0,nread);
1886 SSVAL(outbuf,smb_vwv5,nread+3);
1887 SSVAL(smb_buf(outbuf),1,nread);
1889 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1895 /****************************************************************************
1897 ****************************************************************************/
1898 int reply_read(char *inbuf,char *outbuf)
1900 int cnum,numtoread,fnum;
1906 cnum = SVAL(inbuf,smb_tid);
1907 fnum = GETFNUM(inbuf,smb_vwv0);
1909 CHECK_FNUM(fnum,cnum);
1913 numtoread = SVAL(inbuf,smb_vwv1);
1914 startpos = IVAL(inbuf,smb_vwv2);
1916 outsize = set_message(outbuf,5,3,True);
1917 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1918 data = smb_buf(outbuf) + 3;
1920 if (is_locked(fnum,cnum,numtoread,startpos))
1921 return(ERROR(ERRDOS,ERRlock));
1924 nread = read_file(fnum,data,startpos,numtoread);
1927 return(UNIXERROR(ERRDOS,ERRnoaccess));
1930 SSVAL(outbuf,smb_vwv0,nread);
1931 SSVAL(outbuf,smb_vwv5,nread+3);
1932 CVAL(smb_buf(outbuf),0) = 1;
1933 SSVAL(smb_buf(outbuf),1,nread);
1935 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1941 /****************************************************************************
1942 reply to a read and X
1943 ****************************************************************************/
1944 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1946 int fnum = GETFNUM(inbuf,smb_vwv2);
1947 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1948 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1949 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1955 cnum = SVAL(inbuf,smb_tid);
1957 /* If it's an IPC, pass off the pipe handler. */
1959 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1961 CHECK_FNUM(fnum,cnum);
1965 set_message(outbuf,12,0,True);
1966 data = smb_buf(outbuf);
1968 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1969 return(ERROR(ERRDOS,ERRlock));
1970 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1974 return(UNIXERROR(ERRDOS,ERRnoaccess));
1976 SSVAL(outbuf,smb_vwv5,nread);
1977 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1978 SSVAL(smb_buf(outbuf),-2,nread);
1980 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1981 timestring(),fnum,cnum,
1982 smb_mincnt,smb_maxcnt,nread));
1986 return chain_reply(inbuf,outbuf,length,bufsize);
1990 /****************************************************************************
1991 reply to a writebraw (core+ or LANMAN1.0 protocol)
1992 ****************************************************************************/
1993 int reply_writebraw(char *inbuf,char *outbuf)
1996 int total_written=0;
2005 cnum = SVAL(inbuf,smb_tid);
2006 fnum = GETFNUM(inbuf,smb_vwv0);
2008 CHECK_FNUM(fnum,cnum);
2012 tcount = IVAL(inbuf,smb_vwv1);
2013 startpos = IVAL(inbuf,smb_vwv3);
2014 write_through = BITSETW(inbuf+smb_vwv7,0);
2016 /* We have to deal with slightly different formats depending
2017 on whether we are using the core+ or lanman1.0 protocol */
2018 if(Protocol <= PROTOCOL_COREPLUS) {
2019 numtowrite = SVAL(smb_buf(inbuf),-2);
2020 data = smb_buf(inbuf);
2022 numtowrite = SVAL(inbuf,smb_vwv10);
2023 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2026 /* force the error type */
2027 CVAL(inbuf,smb_com) = SMBwritec;
2028 CVAL(outbuf,smb_com) = SMBwritec;
2030 if (is_locked(fnum,cnum,tcount,startpos))
2031 return(ERROR(ERRDOS,ERRlock));
2033 if (seek_file(fnum,startpos) != startpos)
2034 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
2037 nwritten = write_file(fnum,data,numtowrite);
2039 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
2040 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
2042 if (nwritten < numtowrite)
2043 return(UNIXERROR(ERRHRD,ERRdiskfull));
2045 total_written = nwritten;
2047 /* Return a message to the redirector to tell it
2048 to send more bytes */
2049 CVAL(outbuf,smb_com) = SMBwritebraw;
2050 SSVALS(outbuf,smb_vwv0,-1);
2051 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2052 send_smb(Client,outbuf);
2054 /* Now read the raw data into the buffer and write it */
2055 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2056 exit_server("secondary writebraw failed");
2059 /* Even though this is not an smb message, smb_len
2060 returns the generic length of an smb message */
2061 numtowrite = smb_len(inbuf);
2063 if (tcount > nwritten+numtowrite) {
2064 DEBUG(3,("Client overestimated the write %d %d %d\n",
2065 tcount,nwritten,numtowrite));
2068 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
2070 total_written += nwritten;
2072 /* Set up outbuf to return the correct return */
2073 outsize = set_message(outbuf,1,0,True);
2074 CVAL(outbuf,smb_com) = SMBwritec;
2075 SSVAL(outbuf,smb_vwv0,total_written);
2077 if (nwritten < numtowrite) {
2078 CVAL(outbuf,smb_rcls) = ERRHRD;
2079 SSVAL(outbuf,smb_err,ERRdiskfull);
2082 if (lp_syncalways(SNUM(cnum)) || write_through)
2085 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
2086 timestring(),fnum,cnum,startpos,numtowrite,total_written));
2088 /* we won't return a status if write through is not selected - this
2089 follows what WfWg does */
2090 if (!write_through && total_written==tcount)
2097 /****************************************************************************
2098 reply to a writeunlock (core+)
2099 ****************************************************************************/
2100 int reply_writeunlock(char *inbuf,char *outbuf)
2106 uint32 numtowrite,startpos;
2110 cnum = SVAL(inbuf,smb_tid);
2111 fnum = GETFNUM(inbuf,smb_vwv0);
2113 CHECK_FNUM(fnum,cnum);
2117 numtowrite = SVAL(inbuf,smb_vwv1);
2118 startpos = IVAL(inbuf,smb_vwv2);
2119 data = smb_buf(inbuf) + 3;
2121 if (is_locked(fnum,cnum,numtowrite,startpos))
2122 return(ERROR(ERRDOS,ERRlock));
2124 seek_file(fnum,startpos);
2126 /* The special X/Open SMB protocol handling of
2127 zero length writes is *NOT* done for
2132 nwritten = write_file(fnum,data,numtowrite);
2134 if (lp_syncalways(SNUM(cnum)))
2137 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2138 return(UNIXERROR(ERRDOS,ERRnoaccess));
2140 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2141 return(ERROR(eclass,ecode));
2143 outsize = set_message(outbuf,1,0,True);
2145 SSVAL(outbuf,smb_vwv0,nwritten);
2147 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2148 timestring(),fnum,cnum,numtowrite,nwritten));
2154 /****************************************************************************
2156 ****************************************************************************/
2157 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
2159 int cnum,numtowrite,fnum;
2168 cnum = SVAL(inbuf,smb_tid);
2169 fnum = GETFNUM(inbuf,smb_vwv0);
2171 CHECK_FNUM(fnum,cnum);
2175 numtowrite = SVAL(inbuf,smb_vwv1);
2176 startpos = IVAL(inbuf,smb_vwv2);
2177 data = smb_buf(inbuf) + 3;
2179 if (is_locked(fnum,cnum,numtowrite,startpos))
2180 return(ERROR(ERRDOS,ERRlock));
2182 seek_file(fnum,startpos);
2184 /* X/Open SMB protocol says that if smb_vwv1 is
2185 zero then the file size should be extended or
2186 truncated to the size given in smb_vwv[2-3] */
2188 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2190 nwritten = write_file(fnum,data,numtowrite);
2192 if (lp_syncalways(SNUM(cnum)))
2195 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2196 return(UNIXERROR(ERRDOS,ERRnoaccess));
2198 outsize = set_message(outbuf,1,0,True);
2200 SSVAL(outbuf,smb_vwv0,nwritten);
2202 if (nwritten < numtowrite) {
2203 CVAL(outbuf,smb_rcls) = ERRHRD;
2204 SSVAL(outbuf,smb_err,ERRdiskfull);
2207 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2213 /****************************************************************************
2214 reply to a write and X
2215 ****************************************************************************/
2216 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2218 int fnum = GETFNUM(inbuf,smb_vwv2);
2219 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2220 int smb_dsize = SVAL(inbuf,smb_vwv10);
2221 int smb_doff = SVAL(inbuf,smb_vwv11);
2222 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2227 cnum = SVAL(inbuf,smb_tid);
2229 CHECK_FNUM(fnum,cnum);
2233 data = smb_base(inbuf) + smb_doff;
2235 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2236 return(ERROR(ERRDOS,ERRlock));
2238 seek_file(fnum,smb_offs);
2240 /* X/Open SMB protocol says that, unlike SMBwrite
2241 if the length is zero then NO truncation is
2242 done, just a write of zero. To truncate a file,
2247 nwritten = write_file(fnum,data,smb_dsize);
2249 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2250 return(UNIXERROR(ERRDOS,ERRnoaccess));
2252 set_message(outbuf,6,0,True);
2254 SSVAL(outbuf,smb_vwv2,nwritten);
2256 if (nwritten < smb_dsize) {
2257 CVAL(outbuf,smb_rcls) = ERRHRD;
2258 SSVAL(outbuf,smb_err,ERRdiskfull);
2261 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2265 if (lp_syncalways(SNUM(cnum)) || write_through)
2268 return chain_reply(inbuf,outbuf,length,bufsize);
2272 /****************************************************************************
2274 ****************************************************************************/
2275 int reply_lseek(char *inbuf,char *outbuf)
2283 cnum = SVAL(inbuf,smb_tid);
2284 fnum = GETFNUM(inbuf,smb_vwv0);
2286 CHECK_FNUM(fnum,cnum);
2289 mode = SVAL(inbuf,smb_vwv1) & 3;
2290 startpos = IVAL(inbuf,smb_vwv2);
2294 case 0: umode = SEEK_SET; break;
2295 case 1: umode = SEEK_CUR; break;
2296 case 2: umode = SEEK_END; break;
2298 umode = SEEK_SET; break;
2301 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2302 Files[fnum].pos = res;
2304 outsize = set_message(outbuf,2,0,True);
2305 SIVALS(outbuf,smb_vwv0,res);
2307 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2313 /****************************************************************************
2315 ****************************************************************************/
2316 int reply_flush(char *inbuf,char *outbuf)
2319 int outsize = set_message(outbuf,0,0,True);
2321 cnum = SVAL(inbuf,smb_tid);
2322 fnum = GETFNUM(inbuf,smb_vwv0);
2324 if (fnum != 0xFFFF) {
2325 CHECK_FNUM(fnum,cnum);
2332 for (i=0;i<MAX_OPEN_FILES;i++)
2339 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2344 /****************************************************************************
2346 ****************************************************************************/
2347 int reply_exit(char *inbuf,char *outbuf)
2349 int outsize = set_message(outbuf,0,0,True);
2350 DEBUG(3,("%s exit\n",timestring()));
2356 /****************************************************************************
2358 ****************************************************************************/
2359 int reply_close(char *inbuf,char *outbuf)
2364 int32 eclass = 0, err = 0;
2366 outsize = set_message(outbuf,0,0,True);
2368 cnum = SVAL(inbuf,smb_tid);
2370 /* If it's an IPC, pass off to the pipe handler. */
2372 return reply_pipe_close(inbuf,outbuf);
2374 fnum = GETFNUM(inbuf,smb_vwv0);
2376 CHECK_FNUM(fnum,cnum);
2378 if(HAS_CACHED_ERROR(fnum)) {
2379 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2380 err = Files[fnum].wbmpx_ptr->wr_error;
2383 mtime = make_unix_date3(inbuf+smb_vwv1);
2385 /* try and set the date */
2386 set_filetime(cnum, Files[fnum].name,mtime);
2388 close_file(fnum,True);
2390 /* We have a cached error */
2392 return(ERROR(eclass,err));
2394 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2395 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2396 Connections[cnum].num_files_open));
2402 /****************************************************************************
2403 reply to a writeclose (Core+ protocol)
2404 ****************************************************************************/
2405 int reply_writeclose(char *inbuf,char *outbuf)
2407 int cnum,numtowrite,fnum;
2414 cnum = SVAL(inbuf,smb_tid);
2415 fnum = GETFNUM(inbuf,smb_vwv0);
2417 CHECK_FNUM(fnum,cnum);
2421 numtowrite = SVAL(inbuf,smb_vwv1);
2422 startpos = IVAL(inbuf,smb_vwv2);
2423 mtime = make_unix_date3(inbuf+smb_vwv4);
2424 data = smb_buf(inbuf) + 1;
2426 if (is_locked(fnum,cnum,numtowrite,startpos))
2427 return(ERROR(ERRDOS,ERRlock));
2429 seek_file(fnum,startpos);
2431 nwritten = write_file(fnum,data,numtowrite);
2433 set_filetime(cnum, Files[fnum].name,mtime);
2435 close_file(fnum,True);
2437 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2438 timestring(),fnum,cnum,numtowrite,nwritten,
2439 Connections[cnum].num_files_open));
2442 return(UNIXERROR(ERRDOS,ERRnoaccess));
2444 outsize = set_message(outbuf,1,0,True);
2446 SSVAL(outbuf,smb_vwv0,nwritten);
2451 /****************************************************************************
2453 ****************************************************************************/
2454 int reply_lock(char *inbuf,char *outbuf)
2457 int outsize = set_message(outbuf,0,0,True);
2458 uint32 count,offset;
2462 cnum = SVAL(inbuf,smb_tid);
2463 fnum = GETFNUM(inbuf,smb_vwv0);
2465 CHECK_FNUM(fnum,cnum);
2468 count = IVAL(inbuf,smb_vwv1);
2469 offset = IVAL(inbuf,smb_vwv3);
2471 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));
2473 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2474 return (ERROR(eclass,ecode));
2480 /****************************************************************************
2482 ****************************************************************************/
2483 int reply_unlock(char *inbuf,char *outbuf)
2486 int outsize = set_message(outbuf,0,0,True);
2487 uint32 count,offset;
2491 cnum = SVAL(inbuf,smb_tid);
2492 fnum = GETFNUM(inbuf,smb_vwv0);
2494 CHECK_FNUM(fnum,cnum);
2497 count = IVAL(inbuf,smb_vwv1);
2498 offset = IVAL(inbuf,smb_vwv3);
2500 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2501 return (ERROR(eclass,ecode));
2503 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));
2509 /****************************************************************************
2511 ****************************************************************************/
2512 int reply_tdis(char *inbuf,char *outbuf)
2515 int outsize = set_message(outbuf,0,0,True);
2518 cnum = SVAL(inbuf,smb_tid);
2519 vuid = SVAL(inbuf,smb_uid);
2521 if (!OPEN_CNUM(cnum)) {
2522 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2523 return(ERROR(ERRSRV,ERRinvnid));
2526 Connections[cnum].used = False;
2528 close_cnum(cnum,vuid);
2530 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2537 /****************************************************************************
2539 ****************************************************************************/
2540 int reply_echo(char *inbuf,char *outbuf)
2543 int smb_reverb = SVAL(inbuf,smb_vwv0);
2545 int data_len = smb_buflen(inbuf);
2546 int outsize = set_message(outbuf,1,data_len,True);
2548 cnum = SVAL(inbuf,smb_tid);
2550 /* According to the latest CIFS spec we shouldn't
2551 care what the TID is.
2555 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2557 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2558 return(ERROR(ERRSRV,ERRinvnid));
2562 /* copy any incoming data back out */
2564 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2566 if (smb_reverb > 100)
2568 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2572 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2574 SSVAL(outbuf,smb_vwv0,seq_num);
2576 smb_setlen(outbuf,outsize - 4);
2578 send_smb(Client,outbuf);
2581 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2587 /****************************************************************************
2588 reply to a printopen
2589 ****************************************************************************/
2590 int reply_printopen(char *inbuf,char *outbuf)
2598 *fname = *fname2 = 0;
2600 cnum = SVAL(inbuf,smb_tid);
2602 if (!CAN_PRINT(cnum))
2603 return(ERROR(ERRDOS,ERRnoaccess));
2608 pstrcpy(s,smb_buf(inbuf)+1);
2612 if (!(isalnum(*p) || strchr("._-",*p)))
2617 if (strlen(s) > 10) s[10] = 0;
2619 sprintf(fname,"%s.XXXXXX",s);
2622 fnum = find_free_file();
2624 return(ERROR(ERRSRV,ERRnofids));
2626 strcpy(fname2,(char *)mktemp(fname));
2628 if (!check_name(fname2,cnum)) {
2629 Files[fnum].reserved = False;
2630 return(ERROR(ERRDOS,ERRnoaccess));
2633 /* Open for exclusive use, write only. */
2634 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2637 if (!Files[fnum].open) {
2638 Files[fnum].reserved = False;
2639 return(UNIXERROR(ERRDOS,ERRnoaccess));
2642 /* force it to be a print file */
2643 Files[fnum].print_file = True;
2645 outsize = set_message(outbuf,1,0,True);
2646 SSVAL(outbuf,smb_vwv0,fnum);
2648 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2654 /****************************************************************************
2655 reply to a printclose
2656 ****************************************************************************/
2657 int reply_printclose(char *inbuf,char *outbuf)
2660 int outsize = set_message(outbuf,0,0,True);
2662 cnum = SVAL(inbuf,smb_tid);
2663 fnum = GETFNUM(inbuf,smb_vwv0);
2665 CHECK_FNUM(fnum,cnum);
2668 if (!CAN_PRINT(cnum))
2669 return(ERROR(ERRDOS,ERRnoaccess));
2671 close_file(fnum,True);
2673 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2679 /****************************************************************************
2680 reply to a printqueue
2681 ****************************************************************************/
2682 int reply_printqueue(char *inbuf,char *outbuf)
2685 int outsize = set_message(outbuf,2,3,True);
2686 int max_count = SVAL(inbuf,smb_vwv0);
2687 int start_index = SVAL(inbuf,smb_vwv1);
2690 cnum = SVAL(inbuf,smb_tid);
2691 vuid = SVAL(inbuf,smb_uid);
2693 /* allow checking the queue for anyone */
2695 if (!CAN_PRINT(cnum))
2696 return(ERROR(ERRDOS,ERRnoaccess));
2699 SSVAL(outbuf,smb_vwv0,0);
2700 SSVAL(outbuf,smb_vwv1,0);
2701 CVAL(smb_buf(outbuf),0) = 1;
2702 SSVAL(smb_buf(outbuf),1,0);
2704 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2705 timestring(),cnum,start_index,max_count));
2707 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2712 for (i=0;i<MAX_CONNECTIONS;i++)
2713 if (CAN_PRINT(i) && Connections[i].printer)
2717 for (i=0;i<MAX_CONNECTIONS;i++)
2721 if (!OPEN_CNUM(cnum))
2722 return(ERROR(ERRSRV,ERRinvnid));
2724 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2727 if (!become_user(&Connections[cnum], cnum, vuid))
2728 return(ERROR(ERRSRV,ERRinvnid));
2731 print_queue_struct *queue = NULL;
2732 char *p = smb_buf(outbuf) + 3;
2733 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2734 int num_to_get = ABS(max_count);
2735 int first = (max_count>0?start_index:start_index+max_count+1);
2741 num_to_get = MIN(num_to_get,count-first);
2744 for (i=first;i<first+num_to_get;i++)
2746 put_dos_date2(p,0,queue[i].time);
2747 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2748 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2749 SIVAL(p,7,queue[i].size);
2751 StrnCpy(p+12,queue[i].user,16);
2757 outsize = set_message(outbuf,2,28*count+3,False);
2758 SSVAL(outbuf,smb_vwv0,count);
2759 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2760 CVAL(smb_buf(outbuf),0) = 1;
2761 SSVAL(smb_buf(outbuf),1,28*count);
2764 if (queue) free(queue);
2766 DEBUG(3,("%d entries returned in queue\n",count));
2773 /****************************************************************************
2774 reply to a printwrite
2775 ****************************************************************************/
2776 int reply_printwrite(char *inbuf,char *outbuf)
2778 int cnum,numtowrite,fnum;
2779 int outsize = set_message(outbuf,0,0,True);
2782 cnum = SVAL(inbuf,smb_tid);
2784 if (!CAN_PRINT(cnum))
2785 return(ERROR(ERRDOS,ERRnoaccess));
2787 fnum = GETFNUM(inbuf,smb_vwv0);
2789 CHECK_FNUM(fnum,cnum);
2793 numtowrite = SVAL(smb_buf(inbuf),1);
2794 data = smb_buf(inbuf) + 3;
2796 if (write_file(fnum,data,numtowrite) != numtowrite)
2797 return(UNIXERROR(ERRDOS,ERRnoaccess));
2799 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2805 /****************************************************************************
2807 ****************************************************************************/
2808 int reply_mkdir(char *inbuf,char *outbuf)
2812 int outsize,ret= -1;
2813 BOOL bad_path = False;
2815 pstrcpy(directory,smb_buf(inbuf) + 1);
2816 cnum = SVAL(inbuf,smb_tid);
2817 unix_convert(directory,cnum,0,&bad_path);
2819 if (check_name(directory,cnum))
2820 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2824 if((errno == ENOENT) && bad_path)
2826 unix_ERR_class = ERRDOS;
2827 unix_ERR_code = ERRbadpath;
2829 return(UNIXERROR(ERRDOS,ERRnoaccess));
2832 outsize = set_message(outbuf,0,0,True);
2834 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2839 /****************************************************************************
2840 Static function used by reply_rmdir to delete an entire directory
2842 ****************************************************************************/
2843 static BOOL recursive_rmdir(char *directory)
2847 void *dirptr = OpenDir(-1, directory, False);
2852 while((dname = ReadDirName(dirptr)))
2857 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2860 /* Construct the full name. */
2861 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2867 strcpy(fullname, directory);
2868 strcat(fullname, "/");
2869 strcat(fullname, dname);
2871 if(sys_lstat(fullname, &st) != 0)
2877 if(st.st_mode & S_IFDIR)
2879 if(recursive_rmdir(fullname)!=0)
2884 if(sys_rmdir(fullname) != 0)
2890 else if(sys_unlink(fullname) != 0)
2900 /****************************************************************************
2902 ****************************************************************************/
2903 int reply_rmdir(char *inbuf,char *outbuf)
2909 BOOL bad_path = False;
2911 cnum = SVAL(inbuf,smb_tid);
2912 pstrcpy(directory,smb_buf(inbuf) + 1);
2913 unix_convert(directory,cnum,0,&bad_path);
2915 if (check_name(directory,cnum))
2918 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2919 ok = (sys_rmdir(directory) == 0);
2920 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2922 /* Check to see if the only thing in this directory are
2923 vetoed files/directories. If so then delete them and
2924 retry. If we fail to delete any of them (and we *don't*
2925 do a recursive delete) then fail the rmdir. */
2926 BOOL all_veto_files = True;
2928 void *dirptr = OpenDir(cnum, directory, False);
2932 int dirpos = TellDir(dirptr);
2933 while ((dname = ReadDirName(dirptr)))
2935 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2937 if(!IS_VETO_PATH(cnum, dname))
2939 all_veto_files = False;
2945 SeekDir(dirptr,dirpos);
2946 while ((dname = ReadDirName(dirptr)))
2951 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2954 /* Construct the full name. */
2955 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2960 pstrcpy(fullname, directory);
2961 strcat(fullname, "/");
2962 strcat(fullname, dname);
2964 if(sys_lstat(fullname, &st) != 0)
2966 if(st.st_mode & S_IFDIR)
2968 if(lp_recursive_veto_delete(SNUM(cnum)))
2970 if(recursive_rmdir(fullname) != 0)
2973 if(sys_rmdir(fullname) != 0)
2976 else if(sys_unlink(fullname) != 0)
2980 /* Retry the rmdir */
2981 ok = (sys_rmdir(directory) == 0);
2991 DEBUG(3,("couldn't remove directory %s : %s\n",
2992 directory,strerror(errno)));
2997 if((errno == ENOENT) && bad_path)
2999 unix_ERR_class = ERRDOS;
3000 unix_ERR_code = ERRbadpath;
3002 return(UNIXERROR(ERRDOS,ERRbadpath));
3005 outsize = set_message(outbuf,0,0,True);
3007 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
3013 /*******************************************************************
3014 resolve wildcards in a filename rename
3015 ********************************************************************/
3016 static BOOL resolve_wildcards(char *name1,char *name2)
3018 fstring root1,root2;
3022 name1 = strrchr(name1,'/');
3023 name2 = strrchr(name2,'/');
3025 if (!name1 || !name2) return(False);
3027 fstrcpy(root1,name1);
3028 fstrcpy(root2,name2);
3029 p = strrchr(root1,'.');
3036 p = strrchr(root2,'.');
3068 strcpy(name2,root2);
3077 /*******************************************************************
3078 check if a user is allowed to rename a file
3079 ********************************************************************/
3080 static BOOL can_rename(char *fname,int cnum)
3084 if (!CAN_WRITE(cnum)) return(False);
3086 if (sys_lstat(fname,&sbuf) != 0) return(False);
3087 if (!check_file_sharing(cnum,fname,True)) return(False);
3092 /****************************************************************************
3094 ****************************************************************************/
3095 int reply_mv(char *inbuf,char *outbuf)
3101 pstring mask,newname;
3102 pstring newname_last_component;
3105 int error = ERRnoaccess;
3108 BOOL bad_path1 = False;
3109 BOOL bad_path2 = False;
3111 *directory = *mask = 0;
3113 cnum = SVAL(inbuf,smb_tid);
3115 pstrcpy(name,smb_buf(inbuf) + 1);
3116 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3118 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3120 unix_convert(name,cnum,0,&bad_path1);
3121 unix_convert(newname,cnum,newname_last_component,&bad_path2);
3124 * Split the old name into directory and last component
3125 * strings. Note that unix_convert may have stripped off a
3126 * leading ./ from both name and newname if the rename is
3127 * at the root of the share. We need to make sure either both
3128 * name and newname contain a / character or neither of them do
3129 * as this is checked in resolve_wildcards().
3132 p = strrchr(name,'/');
3134 strcpy(directory,".");
3138 strcpy(directory,name);
3140 *p = '/'; /* Replace needed for exceptional test below. */
3143 if (is_mangled(mask))
3144 check_mangled_stack(mask);
3146 has_wild = strchr(mask,'*') || strchr(mask,'?');
3149 BOOL is_short_name = is_8_3(name, True);
3151 /* Add a terminating '/' to the directory name. */
3152 strcat(directory,"/");
3153 strcat(directory,mask);
3155 /* Ensure newname contains a '/' also */
3156 if(strrchr(newname,'/') == 0) {
3159 strcpy(tmpstr, "./");
3160 strcat(tmpstr, newname);
3161 strcpy(newname, tmpstr);
3164 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",
3165 case_sensitive, case_preserve, short_case_preserve, directory,
3166 newname, newname_last_component, is_short_name));
3169 * Check for special case with case preserving and not
3170 * case sensitive, if directory and newname are identical,
3171 * and the old last component differs from the original
3172 * last component only by case, then we should allow
3173 * the rename (user is trying to change the case of the
3176 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3177 ((short_case_preserve == True) && (is_short_name == True))) &&
3178 strcsequal(directory, newname)) {
3179 pstring newname_modified_last_component;
3182 * Get the last component of the modified name.
3183 * Note that we guarantee that newname contains a '/'
3186 p = strrchr(newname,'/');
3187 strcpy(newname_modified_last_component,p+1);
3189 if(strcsequal(newname_modified_last_component,
3190 newname_last_component) == False) {
3192 * Replace the modified last component with
3195 strcpy(p+1, newname_last_component);
3199 if (resolve_wildcards(directory,newname) &&
3200 can_rename(directory,cnum) &&
3201 !file_exist(newname,NULL) &&
3202 !sys_rename(directory,newname)) count++;
3204 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3205 directory,newname));
3207 if (!count) exists = file_exist(directory,NULL);
3208 if (!count && exists && file_exist(newname,NULL)) {
3213 void *dirptr = NULL;
3217 if (check_name(directory,cnum))
3218 dirptr = OpenDir(cnum, directory, True);
3224 if (strequal(mask,"????????.???"))
3227 while ((dname = ReadDirName(dirptr)))
3230 pstrcpy(fname,dname);
3232 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3234 error = ERRnoaccess;
3235 sprintf(fname,"%s/%s",directory,dname);
3236 if (!can_rename(fname,cnum)) {
3237 DEBUG(6,("rename %s refused\n", fname));
3240 pstrcpy(destname,newname);
3242 if (!resolve_wildcards(fname,destname)) {
3243 DEBUG(6,("resolve_wildcards %s %s failed\n",
3248 if (file_exist(destname,NULL)) {
3249 DEBUG(6,("file_exist %s\n",
3254 if (!sys_rename(fname,destname)) count++;
3255 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3263 return(ERROR(ERRDOS,error));
3266 if((errno == ENOENT) && (bad_path1 || bad_path2))
3268 unix_ERR_class = ERRDOS;
3269 unix_ERR_code = ERRbadpath;
3271 return(UNIXERROR(ERRDOS,error));
3275 outsize = set_message(outbuf,0,0,True);
3280 /*******************************************************************
3281 copy a file as part of a reply_copy
3282 ******************************************************************/
3283 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3284 int count,BOOL target_is_directory)
3292 pstrcpy(dest,dest1);
3293 if (target_is_directory) {
3294 char *p = strrchr(src,'/');
3303 if (!file_exist(src,&st)) return(False);
3305 fnum1 = find_free_file();
3306 if (fnum1<0) return(False);
3307 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3308 1,0,0,&Access,&action);
3310 if (!Files[fnum1].open) {
3311 Files[fnum1].reserved = False;
3315 if (!target_is_directory && count)
3318 fnum2 = find_free_file();
3320 close_file(fnum1,False);
3323 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3324 ofun,st.st_mode,0,&Access,&action);
3326 if (!Files[fnum2].open) {
3327 close_file(fnum1,False);
3328 Files[fnum2].reserved = False;
3332 if ((ofun&3) == 1) {
3333 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3337 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3339 close_file(fnum1,False);
3340 close_file(fnum2,False);
3342 return(ret == st.st_size);
3347 /****************************************************************************
3348 reply to a file copy.
3349 ****************************************************************************/
3350 int reply_copy(char *inbuf,char *outbuf)
3356 pstring mask,newname;
3359 int error = ERRnoaccess;
3362 int tid2 = SVAL(inbuf,smb_vwv0);
3363 int ofun = SVAL(inbuf,smb_vwv1);
3364 int flags = SVAL(inbuf,smb_vwv2);
3365 BOOL target_is_directory=False;
3366 BOOL bad_path1 = False;
3367 BOOL bad_path2 = False;
3369 *directory = *mask = 0;
3371 cnum = SVAL(inbuf,smb_tid);
3373 pstrcpy(name,smb_buf(inbuf));
3374 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3376 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3379 /* can't currently handle inter share copies XXXX */
3380 DEBUG(3,("Rejecting inter-share copy\n"));
3381 return(ERROR(ERRSRV,ERRinvdevice));
3384 unix_convert(name,cnum,0,&bad_path1);
3385 unix_convert(newname,cnum,0,&bad_path2);
3387 target_is_directory = directory_exist(newname,NULL);
3389 if ((flags&1) && target_is_directory) {
3390 return(ERROR(ERRDOS,ERRbadfile));
3393 if ((flags&2) && !target_is_directory) {
3394 return(ERROR(ERRDOS,ERRbadpath));
3397 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3398 /* wants a tree copy! XXXX */
3399 DEBUG(3,("Rejecting tree copy\n"));
3400 return(ERROR(ERRSRV,ERRerror));
3403 p = strrchr(name,'/');
3405 strcpy(directory,"./");
3409 strcpy(directory,name);
3413 if (is_mangled(mask))
3414 check_mangled_stack(mask);
3416 has_wild = strchr(mask,'*') || strchr(mask,'?');
3419 strcat(directory,"/");
3420 strcat(directory,mask);
3421 if (resolve_wildcards(directory,newname) &&
3422 copy_file(directory,newname,cnum,ofun,
3423 count,target_is_directory)) count++;
3424 if (!count) exists = file_exist(directory,NULL);
3426 void *dirptr = NULL;
3430 if (check_name(directory,cnum))
3431 dirptr = OpenDir(cnum, directory, True);
3437 if (strequal(mask,"????????.???"))
3440 while ((dname = ReadDirName(dirptr)))
3443 pstrcpy(fname,dname);
3445 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3447 error = ERRnoaccess;
3448 sprintf(fname,"%s/%s",directory,dname);
3449 strcpy(destname,newname);
3450 if (resolve_wildcards(fname,destname) &&
3451 copy_file(directory,newname,cnum,ofun,
3452 count,target_is_directory)) count++;
3453 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3461 return(ERROR(ERRDOS,error));
3464 if((errno == ENOENT) && (bad_path1 || bad_path2))
3466 unix_ERR_class = ERRDOS;
3467 unix_ERR_code = ERRbadpath;
3469 return(UNIXERROR(ERRDOS,error));
3473 outsize = set_message(outbuf,1,0,True);
3474 SSVAL(outbuf,smb_vwv0,count);
3481 /****************************************************************************
3483 ****************************************************************************/
3484 int reply_setdir(char *inbuf,char *outbuf)
3491 cnum = SVAL(inbuf,smb_tid);
3493 snum = Connections[cnum].service;
3494 if (!CAN_SETDIR(snum))
3495 return(ERROR(ERRDOS,ERRnoaccess));
3497 pstrcpy(newdir,smb_buf(inbuf) + 1);
3500 if (strlen(newdir) == 0)
3504 ok = directory_exist(newdir,NULL);
3506 string_set(&Connections[cnum].connectpath,newdir);
3510 return(ERROR(ERRDOS,ERRbadpath));
3512 outsize = set_message(outbuf,0,0,True);
3513 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3515 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3521 /****************************************************************************
3522 reply to a lockingX request
3523 ****************************************************************************/
3524 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3526 int fnum = GETFNUM(inbuf,smb_vwv2);
3527 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3529 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3531 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3532 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3533 uint32 count, offset;
3538 uint32 ecode=0, dummy2;
3539 int eclass=0, dummy1;
3541 cnum = SVAL(inbuf,smb_tid);
3543 CHECK_FNUM(fnum,cnum);
3546 data = smb_buf(inbuf);
3548 /* Check if this is an oplock break on a file
3549 we have granted an oplock on.
3551 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3554 files_struct *fsp = &Files[fnum];
3555 uint32 dev = fsp->fd_ptr->dev;
3556 uint32 inode = fsp->fd_ptr->inode;
3558 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3561 * Make sure we have granted an oplock on this file.
3563 if(!fsp->granted_oplock)
3565 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3566 no oplock granted on this file.\n", fnum));
3567 return ERROR(ERRDOS,ERRlock);
3570 /* Remove the oplock flag from the sharemode. */
3571 lock_share_entry(fsp->cnum, dev, inode, &token);
3572 if(remove_share_oplock( fnum, token)==False) {
3573 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3574 dev = %x, inode = %x\n",
3576 unlock_share_entry(fsp->cnum, dev, inode, token);
3578 unlock_share_entry(fsp->cnum, dev, inode, token);
3580 /* Clear the granted flag and return. */
3581 fsp->granted_oplock = False;
3584 /* if this is a pure oplock break request then don't send a reply */
3585 if (num_locks == 0 && num_ulocks == 0)
3587 /* Sanity check - ensure a pure oplock break is not a
3589 if(CVAL(inbuf,smb_vwv0) != 0xff)
3590 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3591 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3596 /* Data now points at the beginning of the list
3597 of smb_unlkrng structs */
3598 for(i = 0; i < (int)num_ulocks; i++) {
3599 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3600 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3601 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3602 return ERROR(eclass,ecode);
3605 /* Now do any requested locks */
3606 data += 10*num_ulocks;
3607 /* Data now points at the beginning of the list
3608 of smb_lkrng structs */
3609 for(i = 0; i < (int)num_locks; i++) {
3610 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3611 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3612 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3616 /* If any of the above locks failed, then we must unlock
3617 all of the previous locks (X/Open spec). */
3618 if(i != num_locks && num_locks != 0) {
3619 for(; i >= 0; i--) {
3620 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3621 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3622 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3624 return ERROR(eclass,ecode);
3627 set_message(outbuf,2,0,True);
3629 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3630 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3634 return chain_reply(inbuf,outbuf,length,bufsize);
3638 /****************************************************************************
3639 reply to a SMBreadbmpx (read block multiplex) request
3640 ****************************************************************************/
3641 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3648 int outsize, mincount, maxcount;
3653 /* this function doesn't seem to work - disable by default */
3655 return(ERROR(ERRSRV,ERRuseSTD));
3657 outsize = set_message(outbuf,8,0,True);
3659 cnum = SVAL(inbuf,smb_tid);
3660 fnum = GETFNUM(inbuf,smb_vwv0);
3662 CHECK_FNUM(fnum,cnum);
3666 startpos = IVAL(inbuf,smb_vwv1);
3667 maxcount = SVAL(inbuf,smb_vwv3);
3668 mincount = SVAL(inbuf,smb_vwv4);
3670 data = smb_buf(outbuf);
3671 pad = ((long)data)%4;
3672 if (pad) pad = 4 - pad;
3675 max_per_packet = bufsize-(outsize+pad);
3679 if (is_locked(fnum,cnum,maxcount,startpos))
3680 return(ERROR(ERRDOS,ERRlock));
3684 int N = MIN(max_per_packet,tcount-total_read);
3686 nread = read_file(fnum,data,startpos,N);
3688 if (nread <= 0) nread = 0;
3691 tcount = total_read + nread;
3693 set_message(outbuf,8,nread,False);
3694 SIVAL(outbuf,smb_vwv0,startpos);
3695 SSVAL(outbuf,smb_vwv2,tcount);
3696 SSVAL(outbuf,smb_vwv6,nread);
3697 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3699 send_smb(Client,outbuf);
3701 total_read += nread;
3704 while (total_read < tcount);
3710 /****************************************************************************
3711 reply to a SMBwritebmpx (write block multiplex primary) request
3712 ****************************************************************************/
3713 int reply_writebmpx(char *inbuf,char *outbuf)
3715 int cnum,numtowrite,fnum;
3719 int tcount, write_through, smb_doff;
3722 cnum = SVAL(inbuf,smb_tid);
3723 fnum = GETFNUM(inbuf,smb_vwv0);
3725 CHECK_FNUM(fnum,cnum);
3729 tcount = SVAL(inbuf,smb_vwv1);
3730 startpos = IVAL(inbuf,smb_vwv3);
3731 write_through = BITSETW(inbuf+smb_vwv7,0);
3732 numtowrite = SVAL(inbuf,smb_vwv10);
3733 smb_doff = SVAL(inbuf,smb_vwv11);
3735 data = smb_base(inbuf) + smb_doff;
3737 /* If this fails we need to send an SMBwriteC response,
3738 not an SMBwritebmpx - set this up now so we don't forget */
3739 CVAL(outbuf,smb_com) = SMBwritec;
3741 if (is_locked(fnum,cnum,tcount,startpos))
3742 return(ERROR(ERRDOS,ERRlock));
3744 seek_file(fnum,startpos);
3745 nwritten = write_file(fnum,data,numtowrite);
3747 if(lp_syncalways(SNUM(cnum)) || write_through)
3750 if(nwritten < numtowrite)
3751 return(UNIXERROR(ERRHRD,ERRdiskfull));
3753 /* If the maximum to be written to this file
3754 is greater than what we just wrote then set
3755 up a secondary struct to be attached to this
3756 fd, we will use this to cache error messages etc. */
3757 if(tcount > nwritten)
3759 write_bmpx_struct *wbms;
3760 if(Files[fnum].wbmpx_ptr != NULL)
3761 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3763 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3766 DEBUG(0,("Out of memory in reply_readmpx\n"));
3767 return(ERROR(ERRSRV,ERRnoresource));
3769 wbms->wr_mode = write_through;
3770 wbms->wr_discard = False; /* No errors yet */
3771 wbms->wr_total_written = nwritten;
3772 wbms->wr_errclass = 0;
3774 Files[fnum].wbmpx_ptr = wbms;
3777 /* We are returning successfully, set the message type back to
3779 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3781 outsize = set_message(outbuf,1,0,True);
3783 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3785 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3786 timestring(),fnum,cnum,numtowrite,nwritten));
3788 if (write_through && tcount==nwritten) {
3789 /* we need to send both a primary and a secondary response */
3790 smb_setlen(outbuf,outsize - 4);
3791 send_smb(Client,outbuf);
3793 /* now the secondary */
3794 outsize = set_message(outbuf,1,0,True);
3795 CVAL(outbuf,smb_com) = SMBwritec;
3796 SSVAL(outbuf,smb_vwv0,nwritten);
3803 /****************************************************************************
3804 reply to a SMBwritebs (write block multiplex secondary) request
3805 ****************************************************************************/
3806 int reply_writebs(char *inbuf,char *outbuf)
3808 int cnum,numtowrite,fnum;
3812 int tcount, write_through, smb_doff;
3814 write_bmpx_struct *wbms;
3815 BOOL send_response = False;
3817 cnum = SVAL(inbuf,smb_tid);
3818 fnum = GETFNUM(inbuf,smb_vwv0);
3819 CHECK_FNUM(fnum,cnum);
3822 tcount = SVAL(inbuf,smb_vwv1);
3823 startpos = IVAL(inbuf,smb_vwv2);
3824 numtowrite = SVAL(inbuf,smb_vwv6);
3825 smb_doff = SVAL(inbuf,smb_vwv7);
3827 data = smb_base(inbuf) + smb_doff;
3829 /* We need to send an SMBwriteC response, not an SMBwritebs */
3830 CVAL(outbuf,smb_com) = SMBwritec;
3832 /* This fd should have an auxiliary struct attached,
3833 check that it does */
3834 wbms = Files[fnum].wbmpx_ptr;
3835 if(!wbms) return(-1);
3837 /* If write through is set we can return errors, else we must
3839 write_through = wbms->wr_mode;
3841 /* Check for an earlier error */
3842 if(wbms->wr_discard)
3843 return -1; /* Just discard the packet */
3845 seek_file(fnum,startpos);
3846 nwritten = write_file(fnum,data,numtowrite);
3848 if(lp_syncalways(SNUM(cnum)) || write_through)
3851 if (nwritten < numtowrite)
3854 /* We are returning an error - we can delete the aux struct */
3855 if (wbms) free((char *)wbms);
3856 Files[fnum].wbmpx_ptr = NULL;
3857 return(ERROR(ERRHRD,ERRdiskfull));
3859 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3862 /* Increment the total written, if this matches tcount
3863 we can discard the auxiliary struct (hurrah !) and return a writeC */
3864 wbms->wr_total_written += nwritten;
3865 if(wbms->wr_total_written >= tcount)
3867 if (write_through) {
3868 outsize = set_message(outbuf,1,0,True);
3869 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3870 send_response = True;
3874 Files[fnum].wbmpx_ptr = NULL;
3884 /****************************************************************************
3885 reply to a SMBsetattrE
3886 ****************************************************************************/
3887 int reply_setattrE(char *inbuf,char *outbuf)
3890 struct utimbuf unix_times;
3893 outsize = set_message(outbuf,0,0,True);
3895 cnum = SVAL(inbuf,smb_tid);
3896 fnum = GETFNUM(inbuf,smb_vwv0);
3898 CHECK_FNUM(fnum,cnum);
3901 /* Convert the DOS times into unix times. Ignore create
3902 time as UNIX can't set this.
3904 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3905 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3908 * Patch from Ray Frush <frush@engr.colostate.edu>
3909 * Sometimes times are sent as zero - ignore them.
3912 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3914 /* Ignore request */
3915 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3916 not setting timestamps of 0\n",
3917 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3920 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3922 /* set modify time = to access time if modify time was 0 */
3923 unix_times.modtime = unix_times.actime;
3926 /* Set the date on this file */
3927 if(file_utime(cnum, Files[fnum].name, &unix_times))
3928 return(ERROR(ERRDOS,ERRnoaccess));
3930 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3931 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3937 /****************************************************************************
3938 reply to a SMBgetattrE
3939 ****************************************************************************/
3940 int reply_getattrE(char *inbuf,char *outbuf)
3947 outsize = set_message(outbuf,11,0,True);
3949 cnum = SVAL(inbuf,smb_tid);
3950 fnum = GETFNUM(inbuf,smb_vwv0);
3952 CHECK_FNUM(fnum,cnum);
3955 /* Do an fstat on this file */
3956 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3957 return(UNIXERROR(ERRDOS,ERRnoaccess));
3959 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3961 /* Convert the times into dos times. Set create
3962 date to be last modify date as UNIX doesn't save
3964 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf));
3965 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3966 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3969 SIVAL(outbuf,smb_vwv6,0);
3970 SIVAL(outbuf,smb_vwv8,0);
3974 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3975 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3977 SSVAL(outbuf,smb_vwv10, mode);
3979 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));