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 char magic_char;
37 extern BOOL case_sensitive;
38 extern BOOL case_preserve;
39 extern BOOL short_case_preserve;
40 extern pstring sesssetup_user;
41 extern fstring global_myworkgroup;
43 extern int global_oplock_break;
45 /****************************************************************************
46 report a possible attack via the password buffer overflow bug
47 ****************************************************************************/
48 static void overflow_attack(int len)
52 dbgtext( "ERROR: Invalid password length %d.\n", len );
53 dbgtext( "Your machine may be under attack by someone " );
54 dbgtext( "attempting to exploit an old bug.\n" );
55 dbgtext( "Attack was from IP = %s.\n", client_addr(Client) );
57 exit_server("possible attack");
61 /****************************************************************************
62 reply to an special message
63 ****************************************************************************/
64 int reply_special(char *inbuf,char *outbuf)
67 int msg_type = CVAL(inbuf,0);
68 int msg_flags = CVAL(inbuf,1);
70 extern fstring remote_machine;
71 extern fstring local_machine;
77 bzero(outbuf,smb_size);
82 case 0x81: /* session request */
83 CVAL(outbuf,0) = 0x82;
85 if (name_len(inbuf+4) > 50 ||
86 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
87 DEBUG(0,("Invalid name length in session request\n"));
90 name_extract(inbuf,4,name1);
91 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
92 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
95 fstrcpy(remote_machine,name2);
96 remote_machine[15] = 0;
97 trim_string(remote_machine," "," ");
98 strlower(remote_machine);
100 fstrcpy(local_machine,name1);
101 len = strlen(local_machine);
103 name_type = local_machine[15];
104 local_machine[15] = 0;
106 trim_string(local_machine," "," ");
107 strlower(local_machine);
109 if (name_type == 'R') {
110 /* We are being asked for a pathworks session ---
112 CVAL(outbuf, 0) = 0x83;
116 add_session_user(remote_machine);
118 reload_services(True);
122 claim_connection(NULL,"STATUS.",MAXSTATUS,True);
127 case 0x89: /* session keepalive request
128 (some old clients produce this?) */
129 CVAL(outbuf,0) = 0x85;
133 case 0x82: /* positive session response */
134 case 0x83: /* negative session response */
135 case 0x84: /* retarget session response */
136 DEBUG(0,("Unexpected session response\n"));
139 case 0x85: /* session keepalive */
144 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
145 msg_type, msg_flags));
151 /*******************************************************************
152 work out what error to give to a failed connection
153 ********************************************************************/
154 static int connection_error(char *inbuf,char *outbuf,int ecode)
156 if (ecode == ERRnoipc) {
157 return(ERROR(ERRDOS,ERRnoipc));
160 return(ERROR(ERRSRV,ecode));
165 /****************************************************************************
166 parse a share descriptor string
167 ****************************************************************************/
168 static void parse_connect(char *p,char *service,char *user,
169 char *password,int *pwlen,char *dev)
173 DEBUG(4,("parsing connect string %s\n",p));
175 p2 = strrchr(p,'\\');
179 fstrcpy(service,p2+1);
184 *pwlen = strlen(password);
191 p = strchr(service,'%');
202 /****************************************************************************
204 ****************************************************************************/
205 int reply_tcon(connection_struct *conn,
206 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
213 uint16 vuid = SVAL(inbuf,smb_uid);
217 *service = *user = *password = *dev = 0;
219 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
222 * Pass the user through the NT -> unix user mapping
226 (void)map_username(user);
229 * Do any UNIX username case mangling.
231 (void)Get_Pwnam( user, True);
233 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
236 return(connection_error(inbuf,outbuf,ecode));
239 outsize = set_message(outbuf,2,0,True);
240 SSVAL(outbuf,smb_vwv0,max_recv);
241 SSVAL(outbuf,smb_vwv1,conn->cnum);
242 SSVAL(outbuf,smb_tid,conn->cnum);
244 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
245 service, user, conn->cnum));
251 /****************************************************************************
252 reply to a tcon and X
253 ****************************************************************************/
254 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
261 uint16 vuid = SVAL(inbuf,smb_uid);
262 int passlen = SVAL(inbuf,smb_vwv3);
266 *service = *user = *password = *devicename = 0;
268 /* we might have to close an old one */
269 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
270 close_cnum(conn,vuid);
273 if (passlen > MAX_PASS_LEN) {
274 overflow_attack(passlen);
277 memcpy(password,smb_buf(inbuf),passlen);
279 path = smb_buf(inbuf) + passlen;
282 if (strequal(password," "))
284 passlen = strlen(password);
287 fstrcpy(service,path+2);
288 p = strchr(service,'\\');
290 return(ERROR(ERRSRV,ERRinvnetname));
292 fstrcpy(service,p+1);
293 p = strchr(service,'%');
298 StrnCpy(devicename,path + strlen(path) + 1,6);
299 DEBUG(4,("Got device type %s\n",devicename));
302 * Pass the user through the NT -> unix user mapping
306 (void)map_username(user);
309 * Do any UNIX username case mangling.
311 (void)Get_Pwnam(user, True);
313 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
316 return(connection_error(inbuf,outbuf,ecode));
318 if (Protocol < PROTOCOL_NT1) {
319 set_message(outbuf,2,strlen(devicename)+1,True);
320 pstrcpy(smb_buf(outbuf),devicename);
322 char *fsname = FSTYPE_STRING;
324 set_message(outbuf,3,3,True);
327 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
328 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
330 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
332 SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
335 DEBUG(3,("tconX service=%s user=%s\n",
338 /* set the incoming and outgoing tid to the just created one */
339 SSVAL(inbuf,smb_tid,conn->cnum);
340 SSVAL(outbuf,smb_tid,conn->cnum);
342 return chain_reply(inbuf,outbuf,length,bufsize);
346 /****************************************************************************
347 reply to an unknown type
348 ****************************************************************************/
349 int reply_unknown(char *inbuf,char *outbuf)
352 type = CVAL(inbuf,smb_com);
354 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
355 smb_fn_name(type), type, type));
357 return(ERROR(ERRSRV,ERRunknownsmb));
361 /****************************************************************************
363 ****************************************************************************/
364 int reply_ioctl(connection_struct *conn,
365 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
367 DEBUG(3,("ignoring ioctl\n"));
369 /* we just say it succeeds and hope its all OK.
370 some day it would be nice to interpret them individually */
371 return set_message(outbuf,1,0,True);
373 return(ERROR(ERRSRV,ERRnosupport));
377 /****************************************************************************
378 always return an error: it's just a matter of which one...
379 ****************************************************************************/
380 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
381 char *smb_passwd, int smb_passlen,
382 char *smb_nt_passwd, int smb_nt_passlen)
384 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
385 if (lp_security() == SEC_USER)
387 smb_trust_acct = getsmbpwnam(user);
391 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
392 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
393 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
396 if (smb_trust_acct == NULL)
398 /* lkclXXXX: workstation entry doesn't exist */
399 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
400 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
401 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
405 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
407 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
408 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
409 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
412 if (!smb_password_ok(smb_trust_acct, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
414 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
415 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
416 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
419 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
421 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
422 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
423 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
426 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
428 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
429 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
430 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
433 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
435 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
436 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
437 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
441 /* don't know what to do: indicate logon failure */
442 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
443 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
447 /****************************************************************************
448 reply to a session setup command
449 ****************************************************************************/
450 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
459 int smb_apasslen = 0;
461 int smb_ntpasslen = 0;
462 pstring smb_ntpasswd;
463 BOOL valid_nt_password = False;
467 static BOOL done_sesssetup = False;
468 BOOL doencrypt = SMBENCRYPT();
474 smb_bufsize = SVAL(inbuf,smb_vwv2);
475 smb_mpxmax = SVAL(inbuf,smb_vwv3);
476 smb_vc_num = SVAL(inbuf,smb_vwv4);
477 smb_sesskey = IVAL(inbuf,smb_vwv5);
479 if (Protocol < PROTOCOL_NT1) {
480 smb_apasslen = SVAL(inbuf,smb_vwv7);
481 if (smb_apasslen > MAX_PASS_LEN)
483 overflow_attack(smb_apasslen);
486 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
487 smb_apasswd[smb_apasslen] = 0;
488 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
490 if (!doencrypt && (lp_security() != SEC_SERVER)) {
491 smb_apasslen = strlen(smb_apasswd);
494 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
495 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
496 uint32 client_caps = IVAL(inbuf,smb_vwv11);
497 enum remote_arch_types ra_type = get_remote_arch();
499 char *p = smb_buf(inbuf);
501 /* client_caps is used as final determination if client is NT or Win95.
502 This is needed to return the correct error codes in some
506 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
508 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
509 set_remote_arch( RA_WINNT);
511 set_remote_arch( RA_WIN95);
514 if (passlen1 != 24 && passlen2 != 24)
517 if (passlen1 > MAX_PASS_LEN) {
518 overflow_attack(passlen1);
521 passlen1 = MIN(passlen1, MAX_PASS_LEN);
522 passlen2 = MIN(passlen2, MAX_PASS_LEN);
525 /* both Win95 and WinNT stuff up the password lengths for
526 non-encrypting systems. Uggh.
528 if passlen1==24 its a win95 system, and its setting the
529 password length incorrectly. Luckily it still works with the
530 default code because Win95 will null terminate the password
533 if passlen1>0 and passlen2>0 then maybe its a NT box and its
534 setting passlen2 to some random value which really stuffs
535 things up. we need to fix that one. */
537 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
541 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
542 /* Save the lanman2 password and the NT md4 password. */
543 smb_apasslen = passlen1;
544 memcpy(smb_apasswd,p,smb_apasslen);
545 smb_apasswd[smb_apasslen] = 0;
546 smb_ntpasslen = passlen2;
547 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
548 smb_ntpasswd[smb_ntpasslen] = 0;
550 /* we use the first password that they gave */
551 smb_apasslen = passlen1;
552 StrnCpy(smb_apasswd,p,smb_apasslen);
554 /* trim the password */
555 smb_apasslen = strlen(smb_apasswd);
557 /* wfwg sometimes uses a space instead of a null */
558 if (strequal(smb_apasswd," ")) {
564 p += passlen1 + passlen2;
565 fstrcpy(user,p); p = skip_string(p,1);
568 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
569 domain,skip_string(p,1),skip_string(p,2)));
573 DEBUG(3,("sesssetupX:name=[%s]\n",user));
575 /* If name ends in $ then I think it's asking about whether a */
576 /* computer with that name (minus the $) has access. For now */
577 /* say yes to everything ending in $. */
578 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
580 return session_trust_account(conn, inbuf, outbuf, user,
581 smb_apasswd, smb_apasslen,
582 smb_ntpasswd, smb_ntpasslen);
585 /* If no username is sent use the guest account */
588 pstrcpy(user,lp_guestaccount(-1));
589 /* If no user and no password then set guest flag. */
590 if( *smb_apasswd == 0)
597 * In share level security, only overwrite sesssetup_use if
598 * it's a non null-session share. Helps keep %U and %G
602 if((lp_security() != SEC_SHARE) || *user)
603 pstrcpy(sesssetup_user,user);
605 reload_services(True);
608 * Save the username before mapping. We will use
609 * the original username sent to us for security=server
610 * and security=domain checking.
613 pstrcpy( orig_user, user);
616 * Pass the user through the NT -> unix user mapping
620 (void)map_username(user);
623 * Do any UNIX username case mangling.
625 (void)Get_Pwnam( user, True);
627 add_session_user(user);
630 * Check if the given username was the guest user with no password.
633 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
636 if (!guest && !(lp_security() == SEC_SERVER &&
637 /* Check with orig_user for security=server and
639 server_validate(orig_user, domain,
640 smb_apasswd, smb_apasslen,
641 smb_ntpasswd, smb_ntpasslen)) &&
642 !(lp_security() == SEC_DOMAIN &&
643 domain_client_validate(orig_user, domain,
644 smb_apasswd, smb_apasslen,
645 smb_ntpasswd, smb_ntpasslen)) &&
646 !check_hosts_equiv(user)
650 /* now check if it's a valid username/password */
651 /* If an NT password was supplied try and validate with that
652 first. This is superior as the passwords are mixed case
653 128 length unicode */
656 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
657 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
659 valid_nt_password = True;
661 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
663 if (lp_security() >= SEC_USER) {
664 #if (GUEST_SESSSETUP == 0)
665 return(ERROR(ERRSRV,ERRbadpw));
667 #if (GUEST_SESSSETUP == 1)
668 if (Get_Pwnam(user,True))
669 return(ERROR(ERRSRV,ERRbadpw));
672 if (*smb_apasswd || !Get_Pwnam(user,True))
673 pstrcpy(user,lp_guestaccount(-1));
674 DEBUG(3,("Registered username %s for guest access\n",user));
679 if (!Get_Pwnam(user,True)) {
680 DEBUG(3,("No such user %s - using guest account\n",user));
681 pstrcpy(user,lp_guestaccount(-1));
685 if (!strequal(user,lp_guestaccount(-1)) &&
686 lp_servicenumber(user) < 0)
688 int homes = lp_servicenumber(HOMES_NAME);
689 char *home = get_home_dir(user);
690 if (homes >= 0 && home)
691 lp_add_home(user,homes,home);
695 /* it's ok - setup a reply */
696 if (Protocol < PROTOCOL_NT1) {
697 set_message(outbuf,3,0,True);
700 set_message(outbuf,3,3,True);
702 pstrcpy(p,"Unix"); p = skip_string(p,1);
703 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
704 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
705 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
706 /* perhaps grab OS version here?? */
709 /* Set the correct uid in the outgoing and incoming packets
710 We will use this on future requests to determine which
711 user we should become.
714 struct passwd *pw = Get_Pwnam(user,False);
716 DEBUG(1,("Username %s is invalid on this system\n",user));
717 return(ERROR(ERRSRV,ERRbadpw));
724 SSVAL(outbuf,smb_vwv2,1);
726 /* register the name and uid as being validated, so further connections
727 to a uid can get through without a password, on the same VC */
728 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
730 SSVAL(outbuf,smb_uid,sess_vuid);
731 SSVAL(inbuf,smb_uid,sess_vuid);
734 max_send = MIN(max_send,smb_bufsize);
736 DEBUG(6,("Client requested max send size of %d\n", max_send));
738 done_sesssetup = True;
740 return chain_reply(inbuf,outbuf,length,bufsize);
744 /****************************************************************************
746 ****************************************************************************/
747 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
753 BOOL bad_path = False;
756 pstrcpy(name,smb_buf(inbuf) + 1);
757 unix_convert(name,conn,0,&bad_path,&st);
759 mode = SVAL(inbuf,smb_vwv0);
761 if (check_name(name,conn)) {
763 ok = S_ISDIR(st.st_mode);
765 ok = directory_exist(name,NULL);
770 /* We special case this - as when a Windows machine
771 is parsing a path is steps through the components
772 one at a time - if a component fails it expects
773 ERRbadpath, not ERRbadfile.
777 unix_ERR_class = ERRDOS;
778 unix_ERR_code = ERRbadpath;
782 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
783 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
784 (get_remote_arch() == RA_WINNT))
786 unix_ERR_class = ERRDOS;
787 unix_ERR_code = ERRbaddirectory;
791 return(UNIXERROR(ERRDOS,ERRbadpath));
794 outsize = set_message(outbuf,0,0,True);
796 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
802 /****************************************************************************
804 ****************************************************************************/
805 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
809 SMB_STRUCT_STAT sbuf;
814 BOOL bad_path = False;
816 pstrcpy(fname,smb_buf(inbuf) + 1);
817 unix_convert(fname,conn,0,&bad_path,&sbuf);
819 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
820 under WfWg - weird! */
823 mode = aHIDDEN | aDIR;
824 if (!CAN_WRITE(conn)) mode |= aRONLY;
830 if (check_name(fname,conn))
832 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
834 mode = dos_mode(conn,fname,&sbuf);
836 mtime = sbuf.st_mtime;
842 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
847 if((errno == ENOENT) && bad_path)
849 unix_ERR_class = ERRDOS;
850 unix_ERR_code = ERRbadpath;
853 return(UNIXERROR(ERRDOS,ERRbadfile));
856 outsize = set_message(outbuf,10,0,True);
858 SSVAL(outbuf,smb_vwv0,mode);
859 if(lp_dos_filetime_resolution(SNUM(conn)) )
860 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
862 put_dos_date3(outbuf,smb_vwv1,mtime);
863 SIVAL(outbuf,smb_vwv3,(uint32)size);
865 if (Protocol >= PROTOCOL_NT1) {
866 char *p = strrchr(fname,'/');
867 uint16 flg2 = SVAL(outbuf,smb_flg2);
869 if (!is_8_3(fname, True))
870 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
873 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
879 /****************************************************************************
881 ****************************************************************************/
882 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
890 BOOL bad_path = False;
892 pstrcpy(fname,smb_buf(inbuf) + 1);
893 unix_convert(fname,conn,0,&bad_path,&st);
895 mode = SVAL(inbuf,smb_vwv0);
896 mtime = make_unix_date3(inbuf+smb_vwv1);
898 if (VALID_STAT_OF_DIR(st) || directory_exist(fname,NULL))
900 if (check_name(fname,conn))
901 ok = (file_chmod(conn,fname,mode,NULL) == 0);
903 ok = set_filetime(conn,fname,mtime);
907 if((errno == ENOENT) && bad_path)
909 unix_ERR_class = ERRDOS;
910 unix_ERR_code = ERRbadpath;
913 return(UNIXERROR(ERRDOS,ERRnoaccess));
916 outsize = set_message(outbuf,0,0,True);
918 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
924 /****************************************************************************
926 ****************************************************************************/
927 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
930 int dfree,dsize,bsize;
932 sys_disk_free(".",&bsize,&dfree,&dsize);
934 outsize = set_message(outbuf,5,0,True);
936 SSVAL(outbuf,smb_vwv0,dsize);
937 SSVAL(outbuf,smb_vwv1,bsize/512);
938 SSVAL(outbuf,smb_vwv2,512);
939 SSVAL(outbuf,smb_vwv3,dfree);
941 DEBUG(3,("dskattr dfree=%d\n", dfree));
947 /****************************************************************************
949 Can be called from SMBsearch, SMBffirst or SMBfunique.
950 ****************************************************************************/
951 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
962 BOOL finished = False;
971 BOOL check_descend = False;
972 BOOL expect_close = False;
973 BOOL can_open = True;
974 BOOL bad_path = False;
976 *mask = *directory = *fname = 0;
978 /* If we were called as SMBffirst then we must expect close. */
979 if(CVAL(inbuf,smb_com) == SMBffirst)
982 outsize = set_message(outbuf,1,3,True);
983 maxentries = SVAL(inbuf,smb_vwv0);
984 dirtype = SVAL(inbuf,smb_vwv1);
985 path = smb_buf(inbuf) + 1;
986 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
989 /* dirtype &= ~aDIR; */
991 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
998 pstrcpy(directory,smb_buf(inbuf)+1);
999 pstrcpy(dir2,smb_buf(inbuf)+1);
1000 unix_convert(directory,conn,0,&bad_path,NULL);
1003 if (!check_name(directory,conn))
1006 p = strrchr(dir2,'/');
1018 p = strrchr(directory,'/');
1024 if (strlen(directory) == 0)
1025 pstrcpy(directory,"./");
1027 CVAL(status,0) = dirtype;
1031 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1032 memcpy(mask,status+1,11);
1034 dirtype = CVAL(status,0) & 0x1F;
1035 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1038 string_set(&conn->dirpath,dptr_path(dptr_num));
1039 if (!case_sensitive)
1043 /* turn strings of spaces into a . */
1045 trim_string(mask,NULL," ");
1046 if ((p = strrchr(mask,' ')))
1051 trim_string(mask,NULL," ");
1057 /* Convert the formatted mask. (This code lives in trans2.c) */
1065 if((skip = skip_multibyte_char( *p )) != 0 )
1071 if (*p != '?' && *p != '*' && !isdoschar(*p))
1073 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1081 if (!strchr(mask,'.') && strlen(mask)>8)
1084 fstrcpy(tmp,&mask[8]);
1090 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1094 p = smb_buf(outbuf) + 3;
1098 if (status_len == 0)
1100 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1105 if((errno == ENOENT) && bad_path)
1107 unix_ERR_class = ERRDOS;
1108 unix_ERR_code = ERRbadpath;
1110 return (UNIXERROR(ERRDOS,ERRnofids));
1112 return(ERROR(ERRDOS,ERRnofids));
1116 DEBUG(4,("dptr_num is %d\n",dptr_num));
1120 if ((dirtype&0x1F) == aVOLID)
1122 memcpy(p,status,21);
1123 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1124 dptr_fill(p+12,dptr_num);
1125 if (dptr_zero(p+12) && (status_len==0))
1129 p += DIR_STRUCT_SIZE;
1133 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1134 conn->dirpath,lp_dontdescend(SNUM(conn))));
1135 if (in_list(conn->dirpath,
1136 lp_dontdescend(SNUM(conn)),True))
1137 check_descend = True;
1139 for (i=numentries;(i<maxentries) && !finished;i++)
1142 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1145 memcpy(p,status,21);
1146 make_dir_struct(p,mask,fname,size,mode,date);
1147 dptr_fill(p+12,dptr_num);
1150 p += DIR_STRUCT_SIZE;
1159 if (numentries == 0 || !ok)
1161 CVAL(outbuf,smb_rcls) = ERRDOS;
1162 SSVAL(outbuf,smb_err,ERRnofiles);
1165 /* If we were called as SMBffirst with smb_search_id == NULL
1166 and no entries were found then return error and close dirptr
1169 if(ok && expect_close && numentries == 0 && status_len == 0)
1171 CVAL(outbuf,smb_rcls) = ERRDOS;
1172 SSVAL(outbuf,smb_err,ERRnofiles);
1173 /* Also close the dptr - we know it's gone */
1174 dptr_close(dptr_num);
1177 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1178 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1179 dptr_close(dptr_num);
1181 SSVAL(outbuf,smb_vwv0,numentries);
1182 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1183 CVAL(smb_buf(outbuf),0) = 5;
1184 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1186 if (Protocol >= PROTOCOL_NT1) {
1187 uint16 flg2 = SVAL(outbuf,smb_flg2);
1188 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1191 outsize += DIR_STRUCT_SIZE*numentries;
1192 smb_setlen(outbuf,outsize - 4);
1194 if ((! *directory) && dptr_path(dptr_num))
1195 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1197 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1198 smb_fn_name(CVAL(inbuf,smb_com)),
1199 mask, directory, dirtype, numentries, maxentries ) );
1205 /****************************************************************************
1206 reply to a fclose (stop directory search)
1207 ****************************************************************************/
1208 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1216 outsize = set_message(outbuf,1,0,True);
1217 path = smb_buf(inbuf) + 1;
1218 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1221 if (status_len == 0)
1222 return(ERROR(ERRSRV,ERRsrverror));
1224 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1226 if(dptr_fetch(status+12,&dptr_num)) {
1227 /* Close the dptr - we know it's gone */
1228 dptr_close(dptr_num);
1231 SSVAL(outbuf,smb_vwv0,0);
1233 DEBUG(3,("search close\n"));
1239 /****************************************************************************
1241 ****************************************************************************/
1242 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1252 SMB_STRUCT_STAT sbuf;
1253 BOOL bad_path = False;
1255 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1257 share_mode = SVAL(inbuf,smb_vwv0);
1259 pstrcpy(fname,smb_buf(inbuf)+1);
1260 unix_convert(fname,conn,0,&bad_path,NULL);
1264 return(ERROR(ERRSRV,ERRnofids));
1266 if (!check_name(fname,conn))
1268 if((errno == ENOENT) && bad_path)
1270 unix_ERR_class = ERRDOS;
1271 unix_ERR_code = ERRbadpath;
1274 return(UNIXERROR(ERRDOS,ERRnoaccess));
1277 unixmode = unix_mode(conn,aARCH);
1279 open_file_shared(fsp,conn,fname,share_mode,3,unixmode,
1280 oplock_request,&rmode,NULL);
1284 if((errno == ENOENT) && bad_path)
1286 unix_ERR_class = ERRDOS;
1287 unix_ERR_code = ERRbadpath;
1290 return(UNIXERROR(ERRDOS,ERRnoaccess));
1293 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1294 close_file(fsp,False);
1295 return(ERROR(ERRDOS,ERRnoaccess));
1298 size = sbuf.st_size;
1299 fmode = dos_mode(conn,fname,&sbuf);
1300 mtime = sbuf.st_mtime;
1303 DEBUG(3,("attempt to open a directory %s\n",fname));
1304 close_file(fsp,False);
1305 return(ERROR(ERRDOS,ERRnoaccess));
1308 outsize = set_message(outbuf,7,0,True);
1309 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1310 SSVAL(outbuf,smb_vwv1,fmode);
1311 if(lp_dos_filetime_resolution(SNUM(conn)) )
1312 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1314 put_dos_date3(outbuf,smb_vwv2,mtime);
1315 SIVAL(outbuf,smb_vwv4,(uint32)size);
1316 SSVAL(outbuf,smb_vwv6,rmode);
1318 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1319 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1322 if(fsp->granted_oplock)
1323 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1328 /****************************************************************************
1329 reply to an open and X
1330 ****************************************************************************/
1331 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1334 int smb_mode = SVAL(inbuf,smb_vwv3);
1335 int smb_attr = SVAL(inbuf,smb_vwv5);
1336 /* Breakout the oplock request bits so we can set the
1337 reply bits separately. */
1338 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1339 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1340 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1342 int open_flags = SVAL(inbuf,smb_vwv2);
1343 int smb_sattr = SVAL(inbuf,smb_vwv4);
1344 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1346 int smb_ofun = SVAL(inbuf,smb_vwv8);
1349 int fmode=0,mtime=0,rmode=0;
1350 SMB_STRUCT_STAT sbuf;
1352 BOOL bad_path = False;
1355 /* If it's an IPC, pass off the pipe handler. */
1357 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1359 /* XXXX we need to handle passed times, sattr and flags */
1361 pstrcpy(fname,smb_buf(inbuf));
1362 unix_convert(fname,conn,0,&bad_path,NULL);
1366 return(ERROR(ERRSRV,ERRnofids));
1368 if (!check_name(fname,conn))
1370 if((errno == ENOENT) && bad_path)
1372 unix_ERR_class = ERRDOS;
1373 unix_ERR_code = ERRbadpath;
1376 return(UNIXERROR(ERRDOS,ERRnoaccess));
1379 unixmode = unix_mode(conn,smb_attr | aARCH);
1381 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1382 oplock_request, &rmode,&smb_action);
1386 if((errno == ENOENT) && bad_path)
1388 unix_ERR_class = ERRDOS;
1389 unix_ERR_code = ERRbadpath;
1392 return(UNIXERROR(ERRDOS,ERRnoaccess));
1395 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1396 close_file(fsp,False);
1397 return(ERROR(ERRDOS,ERRnoaccess));
1400 size = sbuf.st_size;
1401 fmode = dos_mode(conn,fname,&sbuf);
1402 mtime = sbuf.st_mtime;
1404 close_file(fsp,False);
1405 return(ERROR(ERRDOS,ERRnoaccess));
1408 /* If the caller set the extended oplock request bit
1409 and we granted one (by whatever means) - set the
1410 correct bit for extended oplock reply.
1413 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1414 smb_action |= EXTENDED_OPLOCK_GRANTED;
1417 if(ex_oplock_request && fsp->granted_oplock) {
1418 smb_action |= EXTENDED_OPLOCK_GRANTED;
1421 /* If the caller set the core oplock request bit
1422 and we granted one (by whatever means) - set the
1423 correct bit for core oplock reply.
1426 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1427 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1430 if(core_oplock_request && fsp->granted_oplock) {
1431 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1434 set_message(outbuf,15,0,True);
1435 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1436 SSVAL(outbuf,smb_vwv3,fmode);
1437 if(lp_dos_filetime_resolution(SNUM(conn)) )
1438 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1440 put_dos_date3(outbuf,smb_vwv4,mtime);
1441 SIVAL(outbuf,smb_vwv6,(uint32)size);
1442 SSVAL(outbuf,smb_vwv8,rmode);
1443 SSVAL(outbuf,smb_vwv11,smb_action);
1445 return chain_reply(inbuf,outbuf,length,bufsize);
1449 /****************************************************************************
1450 reply to a SMBulogoffX
1451 ****************************************************************************/
1452 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1454 uint16 vuid = SVAL(inbuf,smb_uid);
1455 user_struct *vuser = get_valid_user_struct(vuid);
1458 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1461 /* in user level security we are supposed to close any files
1462 open by this user */
1463 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1464 file_close_user(vuid);
1467 invalidate_vuid(vuid);
1469 set_message(outbuf,2,0,True);
1471 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1473 return chain_reply(inbuf,outbuf,length,bufsize);
1477 /****************************************************************************
1478 reply to a mknew or a create
1479 ****************************************************************************/
1480 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1488 BOOL bad_path = False;
1490 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1492 com = SVAL(inbuf,smb_com);
1494 createmode = SVAL(inbuf,smb_vwv0);
1495 pstrcpy(fname,smb_buf(inbuf)+1);
1496 unix_convert(fname,conn,0,&bad_path,NULL);
1498 if (createmode & aVOLID)
1500 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1503 unixmode = unix_mode(conn,createmode);
1507 return(ERROR(ERRSRV,ERRnofids));
1509 if (!check_name(fname,conn))
1511 if((errno == ENOENT) && bad_path)
1513 unix_ERR_class = ERRDOS;
1514 unix_ERR_code = ERRbadpath;
1517 return(UNIXERROR(ERRDOS,ERRnoaccess));
1522 /* We should fail if file exists. */
1527 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1531 /* Open file in dos compatibility share mode. */
1532 open_file_shared(fsp,conn,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1533 oplock_request, NULL, NULL);
1537 if((errno == ENOENT) && bad_path)
1539 unix_ERR_class = ERRDOS;
1540 unix_ERR_code = ERRbadpath;
1543 return(UNIXERROR(ERRDOS,ERRnoaccess));
1546 outsize = set_message(outbuf,1,0,True);
1547 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1549 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1550 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1553 if(fsp->granted_oplock)
1554 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1556 DEBUG( 2, ( "new file %s\n", fname ) );
1557 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1558 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1564 /****************************************************************************
1565 reply to a create temporary file
1566 ****************************************************************************/
1567 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1574 BOOL bad_path = False;
1576 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1578 createmode = SVAL(inbuf,smb_vwv0);
1579 pstrcpy(fname,smb_buf(inbuf)+1);
1580 pstrcat(fname,"/TMXXXXXX");
1581 unix_convert(fname,conn,0,&bad_path,NULL);
1583 unixmode = unix_mode(conn,createmode);
1587 return(ERROR(ERRSRV,ERRnofids));
1589 if (!check_name(fname,conn))
1591 if((errno == ENOENT) && bad_path)
1593 unix_ERR_class = ERRDOS;
1594 unix_ERR_code = ERRbadpath;
1597 return(UNIXERROR(ERRDOS,ERRnoaccess));
1600 pstrcpy(fname2,(char *)mktemp(fname));
1602 /* Open file in dos compatibility share mode. */
1603 /* We should fail if file exists. */
1604 open_file_shared(fsp,conn,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1605 oplock_request, NULL, NULL);
1609 if((errno == ENOENT) && bad_path)
1611 unix_ERR_class = ERRDOS;
1612 unix_ERR_code = ERRbadpath;
1615 return(UNIXERROR(ERRDOS,ERRnoaccess));
1618 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1619 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1620 CVAL(smb_buf(outbuf),0) = 4;
1621 pstrcpy(smb_buf(outbuf) + 1,fname2);
1623 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1624 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1627 if(fsp->granted_oplock)
1628 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1630 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1631 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1632 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1638 /*******************************************************************
1639 check if a user is allowed to delete a file
1640 ********************************************************************/
1641 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1643 SMB_STRUCT_STAT sbuf;
1646 if (!CAN_WRITE(conn)) return(False);
1648 if (dos_lstat(fname,&sbuf) != 0) return(False);
1649 fmode = dos_mode(conn,fname,&sbuf);
1650 if (fmode & aDIR) return(False);
1651 if (!lp_delete_readonly(SNUM(conn))) {
1652 if (fmode & aRONLY) return(False);
1654 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1656 if (!check_file_sharing(conn,fname,False)) return(False);
1660 /****************************************************************************
1662 ****************************************************************************/
1663 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1672 int error = ERRnoaccess;
1675 BOOL bad_path = False;
1677 *directory = *mask = 0;
1679 dirtype = SVAL(inbuf,smb_vwv0);
1681 pstrcpy(name,smb_buf(inbuf) + 1);
1683 DEBUG(3,("reply_unlink : %s\n",name));
1685 unix_convert(name,conn,0,&bad_path,NULL);
1687 p = strrchr(name,'/');
1689 pstrcpy(directory,"./");
1693 pstrcpy(directory,name);
1697 if (is_mangled(mask))
1698 check_mangled_cache( mask );
1700 has_wild = strchr(mask,'*') || strchr(mask,'?');
1703 pstrcat(directory,"/");
1704 pstrcat(directory,mask);
1705 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) count++;
1706 if (!count) exists = file_exist(directory,NULL);
1708 void *dirptr = NULL;
1711 if (check_name(directory,conn))
1712 dirptr = OpenDir(conn, directory, True);
1714 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1715 the pattern matches against the long name, otherwise the short name
1716 We don't implement this yet XXXX
1723 if (strequal(mask,"????????.???"))
1726 while ((dname = ReadDirName(dirptr)))
1729 pstrcpy(fname,dname);
1731 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1733 error = ERRnoaccess;
1734 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1735 if (!can_delete(fname,conn,dirtype)) continue;
1736 if (!dos_unlink(fname)) count++;
1737 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1745 return(ERROR(ERRDOS,error));
1748 if((errno == ENOENT) && bad_path)
1750 unix_ERR_class = ERRDOS;
1751 unix_ERR_code = ERRbadpath;
1753 return(UNIXERROR(ERRDOS,error));
1757 outsize = set_message(outbuf,0,0,True);
1763 /****************************************************************************
1764 reply to a readbraw (core+ protocol)
1765 ****************************************************************************/
1766 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1768 size_t maxcount,mincount;
1771 char *header = outbuf;
1778 * Special check if an oplock break has been issued
1779 * and the readraw request croses on the wire, we must
1780 * return a zero length response here.
1783 if(global_oplock_break)
1785 _smb_setlen(header,0);
1786 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1787 DEBUG(5,("readbraw - oplock break finished\n"));
1791 fsp = file_fsp(inbuf,smb_vwv0);
1793 startpos = IVAL(inbuf,smb_vwv1);
1794 #ifdef LARGE_SMB_OFF_T
1795 if(SVAL(inbuf,smb_wct) == 10) {
1797 * This is a large offset (64 bit) read.
1799 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1801 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1802 (double)startpos ));
1803 _smb_setlen(header,0);
1804 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1808 #endif /* LARGE_SMB_OFF_T */
1809 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1810 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1812 /* ensure we don't overrun the packet size */
1813 maxcount = MIN(65535,maxcount);
1814 maxcount = MAX(mincount,maxcount);
1816 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1817 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1818 _smb_setlen(header,0);
1819 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1822 fd = fsp->fd_ptr->fd;
1823 fname = fsp->fsp_name;
1827 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1829 SMB_OFF_T size = fsp->size;
1830 SMB_OFF_T sizeneeded = startpos + maxcount;
1832 if (size < sizeneeded)
1835 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1837 if (!fsp->can_write)
1841 nread = MIN(maxcount,(size - startpos));
1844 if (nread < mincount)
1847 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1848 fsp->fnum, (double)startpos,
1849 maxcount, mincount, nread ) );
1854 _smb_setlen(header,nread);
1856 #if USE_READ_PREDICTION
1857 if (!fsp->can_write)
1858 predict = read_predict(fd,startpos,header+4,NULL,nread);
1859 #endif /* USE_READ_PREDICTION */
1861 if ((nread-predict) > 0)
1862 seek_file(fsp,startpos + predict);
1864 ret = (ssize_t)transfer_file(fd,Client,(SMB_OFF_T)(nread-predict),header,4+predict,
1869 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1870 fname,startpos,nread,ret));
1872 #else /* UNSAFE_READRAW */
1873 ret = read_file(fsp,header+4,startpos,nread);
1874 if (ret < mincount) ret = 0;
1876 _smb_setlen(header,ret);
1877 transfer_file(0,Client,0,header,4+ret,0);
1878 #endif /* UNSAFE_READRAW */
1880 DEBUG(5,("readbraw finished\n"));
1885 /****************************************************************************
1886 reply to a lockread (core+ protocol)
1887 ****************************************************************************/
1888 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1897 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1899 CHECK_FSP(fsp,conn);
1903 numtoread = SVAL(inbuf,smb_vwv1);
1904 startpos = IVAL(inbuf,smb_vwv2);
1906 outsize = set_message(outbuf,5,3,True);
1907 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1908 data = smb_buf(outbuf) + 3;
1910 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1911 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1913 * A blocking lock was requested. Package up
1914 * this smb into a queued request and push it
1915 * onto the blocking lock queue.
1917 if(push_blocking_lock_request(inbuf, length, -1, 0))
1920 return (ERROR(eclass,ecode));
1923 nread = read_file(fsp,data,startpos,numtoread);
1926 return(UNIXERROR(ERRDOS,ERRnoaccess));
1929 SSVAL(outbuf,smb_vwv0,nread);
1930 SSVAL(outbuf,smb_vwv5,nread+3);
1931 SSVAL(smb_buf(outbuf),1,nread);
1933 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1934 fsp->fnum, numtoread, nread ) );
1940 /****************************************************************************
1942 ****************************************************************************/
1943 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1950 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1952 CHECK_FSP(fsp,conn);
1956 numtoread = SVAL(inbuf,smb_vwv1);
1957 startpos = IVAL(inbuf,smb_vwv2);
1959 outsize = set_message(outbuf,5,3,True);
1960 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1961 data = smb_buf(outbuf) + 3;
1963 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
1964 return(ERROR(ERRDOS,ERRlock));
1967 nread = read_file(fsp,data,startpos,numtoread);
1970 return(UNIXERROR(ERRDOS,ERRnoaccess));
1973 SSVAL(outbuf,smb_vwv0,nread);
1974 SSVAL(outbuf,smb_vwv5,nread+3);
1975 CVAL(smb_buf(outbuf),0) = 1;
1976 SSVAL(smb_buf(outbuf),1,nread);
1978 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1979 fsp->fnum, numtoread, nread ) );
1985 /****************************************************************************
1986 reply to a read and X
1987 ****************************************************************************/
1988 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1990 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1991 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1992 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1993 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1998 /* If it's an IPC, pass off the pipe handler. */
2000 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2002 CHECK_FSP(fsp,conn);
2006 set_message(outbuf,12,0,True);
2007 data = smb_buf(outbuf);
2009 #ifdef LARGE_SMB_OFF_T
2010 if(SVAL(inbuf,smb_wct) == 12) {
2012 * This is a large offset (64 bit) read.
2014 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2016 #endif /* LARGE_SMB_OFF_T */
2018 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2019 return(ERROR(ERRDOS,ERRlock));
2020 nread = read_file(fsp,data,startpos,smb_maxcnt);
2024 return(UNIXERROR(ERRDOS,ERRnoaccess));
2026 SSVAL(outbuf,smb_vwv5,nread);
2027 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2028 SSVAL(smb_buf(outbuf),-2,nread);
2030 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2031 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2033 return chain_reply(inbuf,outbuf,length,bufsize);
2036 /****************************************************************************
2037 reply to a writebraw (core+ or LANMAN1.0 protocol)
2038 ****************************************************************************/
2039 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2042 ssize_t total_written=0;
2043 size_t numtowrite=0;
2048 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2051 CHECK_FSP(fsp,conn);
2055 tcount = IVAL(inbuf,smb_vwv1);
2056 startpos = IVAL(inbuf,smb_vwv3);
2057 write_through = BITSETW(inbuf+smb_vwv7,0);
2059 /* We have to deal with slightly different formats depending
2060 on whether we are using the core+ or lanman1.0 protocol */
2061 if(Protocol <= PROTOCOL_COREPLUS) {
2062 numtowrite = SVAL(smb_buf(inbuf),-2);
2063 data = smb_buf(inbuf);
2065 numtowrite = SVAL(inbuf,smb_vwv10);
2066 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2069 /* force the error type */
2070 CVAL(inbuf,smb_com) = SMBwritec;
2071 CVAL(outbuf,smb_com) = SMBwritec;
2073 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2074 return(ERROR(ERRDOS,ERRlock));
2076 if (seek_file(fsp,startpos) != startpos)
2077 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2080 nwritten = write_file(fsp,data,numtowrite);
2082 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2083 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2085 if (nwritten < numtowrite)
2086 return(UNIXERROR(ERRHRD,ERRdiskfull));
2088 total_written = nwritten;
2090 /* Return a message to the redirector to tell it
2091 to send more bytes */
2092 CVAL(outbuf,smb_com) = SMBwritebraw;
2093 SSVALS(outbuf,smb_vwv0,-1);
2094 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2095 send_smb(Client,outbuf);
2097 /* Now read the raw data into the buffer and write it */
2098 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2099 exit_server("secondary writebraw failed");
2102 /* Even though this is not an smb message, smb_len
2103 returns the generic length of an smb message */
2104 numtowrite = smb_len(inbuf);
2106 if (tcount > nwritten+numtowrite) {
2107 DEBUG(3,("Client overestimated the write %d %d %d\n",
2108 tcount,nwritten,numtowrite));
2111 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2113 total_written += nwritten;
2115 /* Set up outbuf to return the correct return */
2116 outsize = set_message(outbuf,1,0,True);
2117 CVAL(outbuf,smb_com) = SMBwritec;
2118 SSVAL(outbuf,smb_vwv0,total_written);
2120 if (nwritten < (ssize_t)numtowrite) {
2121 CVAL(outbuf,smb_rcls) = ERRHRD;
2122 SSVAL(outbuf,smb_err,ERRdiskfull);
2125 if (lp_syncalways(SNUM(conn)) || write_through)
2126 sync_file(conn,fsp);
2128 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2129 fsp->fnum, (double)startpos, numtowrite, total_written));
2131 /* we won't return a status if write through is not selected - this
2132 follows what WfWg does */
2133 if (!write_through && total_written==tcount)
2139 /****************************************************************************
2140 reply to a writeunlock (core+)
2141 ****************************************************************************/
2142 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2144 ssize_t nwritten = -1;
2150 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2153 CHECK_FSP(fsp,conn);
2157 numtowrite = SVAL(inbuf,smb_vwv1);
2158 startpos = IVAL(inbuf,smb_vwv2);
2159 data = smb_buf(inbuf) + 3;
2161 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2162 return(ERROR(ERRDOS,ERRlock));
2164 seek_file(fsp,startpos);
2166 /* The special X/Open SMB protocol handling of
2167 zero length writes is *NOT* done for
2172 nwritten = write_file(fsp,data,numtowrite);
2174 if (lp_syncalways(SNUM(conn)))
2175 sync_file(conn,fsp);
2177 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2178 return(UNIXERROR(ERRDOS,ERRnoaccess));
2180 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2181 return(ERROR(eclass,ecode));
2183 outsize = set_message(outbuf,1,0,True);
2185 SSVAL(outbuf,smb_vwv0,nwritten);
2187 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2188 fsp->fnum, numtowrite, nwritten ) );
2193 /****************************************************************************
2195 ****************************************************************************/
2196 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2199 ssize_t nwritten = -1;
2202 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2205 CHECK_FSP(fsp,conn);
2209 numtowrite = SVAL(inbuf,smb_vwv1);
2210 startpos = IVAL(inbuf,smb_vwv2);
2211 data = smb_buf(inbuf) + 3;
2213 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2214 return(ERROR(ERRDOS,ERRlock));
2216 seek_file(fsp,startpos);
2218 /* X/Open SMB protocol says that if smb_vwv1 is
2219 zero then the file size should be extended or
2220 truncated to the size given in smb_vwv[2-3] */
2222 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2224 nwritten = write_file(fsp,data,numtowrite);
2226 if (lp_syncalways(SNUM(conn)))
2227 sync_file(conn,fsp);
2229 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2230 return(UNIXERROR(ERRDOS,ERRnoaccess));
2232 outsize = set_message(outbuf,1,0,True);
2234 SSVAL(outbuf,smb_vwv0,nwritten);
2236 if (nwritten < (ssize_t)numtowrite) {
2237 CVAL(outbuf,smb_rcls) = ERRHRD;
2238 SSVAL(outbuf,smb_err,ERRdiskfull);
2241 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2242 fsp->fnum, numtowrite, nwritten));
2248 /****************************************************************************
2249 reply to a write and X
2250 ****************************************************************************/
2251 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2253 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2254 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2255 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2256 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2257 ssize_t nwritten = -1;
2258 int smb_doff = SVAL(inbuf,smb_vwv11);
2261 CHECK_FSP(fsp,conn);
2265 data = smb_base(inbuf) + smb_doff;
2267 #ifdef LLARGE_SMB_OFF_T
2268 if(SVAL(inbuf,smb_wct) == 14) {
2270 * This is a large offset (64 bit) write.
2272 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2274 #endif /* LARGE_SMB_OFF_T */
2276 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2277 return(ERROR(ERRDOS,ERRlock));
2279 seek_file(fsp,startpos);
2281 /* X/Open SMB protocol says that, unlike SMBwrite
2282 if the length is zero then NO truncation is
2283 done, just a write of zero. To truncate a file,
2288 nwritten = write_file(fsp,data,numtowrite);
2290 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2291 return(UNIXERROR(ERRDOS,ERRnoaccess));
2293 set_message(outbuf,6,0,True);
2295 SSVAL(outbuf,smb_vwv2,nwritten);
2297 if (nwritten < (ssize_t)numtowrite) {
2298 CVAL(outbuf,smb_rcls) = ERRHRD;
2299 SSVAL(outbuf,smb_err,ERRdiskfull);
2302 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2303 fsp->fnum, numtowrite, nwritten));
2305 if (lp_syncalways(SNUM(conn)) || write_through)
2306 sync_file(conn,fsp);
2308 return chain_reply(inbuf,outbuf,length,bufsize);
2312 /****************************************************************************
2314 ****************************************************************************/
2315 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2321 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2323 CHECK_FSP(fsp,conn);
2326 mode = SVAL(inbuf,smb_vwv1) & 3;
2327 startpos = IVAL(inbuf,smb_vwv2);
2331 case 0: umode = SEEK_SET; break;
2332 case 1: umode = SEEK_CUR; break;
2333 case 2: umode = SEEK_END; break;
2335 umode = SEEK_SET; break;
2338 res = sys_lseek(fsp->fd_ptr->fd,startpos,umode);
2341 outsize = set_message(outbuf,2,0,True);
2342 SIVALS(outbuf,smb_vwv0,res);
2344 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2345 fsp->fnum, (double)startpos, mode));
2350 /****************************************************************************
2352 ****************************************************************************/
2353 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2355 int outsize = set_message(outbuf,0,0,True);
2356 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2359 CHECK_FSP(fsp,conn);
2364 file_sync_all(conn);
2366 sync_file(conn,fsp);
2369 DEBUG(3,("flush\n"));
2374 /****************************************************************************
2376 ****************************************************************************/
2377 int reply_exit(connection_struct *conn,
2378 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2380 int outsize = set_message(outbuf,0,0,True);
2381 DEBUG(3,("exit\n"));
2387 /****************************************************************************
2388 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2389 ****************************************************************************/
2390 int reply_close(connection_struct *conn,
2391 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2395 int32 eclass = 0, err = 0;
2396 files_struct *fsp = NULL;
2398 outsize = set_message(outbuf,0,0,True);
2400 /* If it's an IPC, pass off to the pipe handler. */
2402 return reply_pipe_close(conn, inbuf,outbuf);
2405 fsp = file_fsp(inbuf,smb_vwv0);
2408 * We can only use CHECK_FSP if we know it's not a directory.
2411 if(!fsp || !fsp->open || (fsp->conn != conn))
2412 return(ERROR(ERRDOS,ERRbadfid));
2414 if(HAS_CACHED_ERROR(fsp)) {
2415 eclass = fsp->wbmpx_ptr->wr_errclass;
2416 err = fsp->wbmpx_ptr->wr_error;
2419 if(fsp->is_directory) {
2421 * Special case - close NT SMB directory
2424 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2425 close_directory(fsp);
2428 * Close ordinary file.
2430 mtime = make_unix_date3(inbuf+smb_vwv1);
2432 /* try and set the date */
2433 set_filetime(conn, fsp->fsp_name,mtime);
2435 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2436 fsp->fd_ptr->fd, fsp->fnum,
2437 conn->num_files_open));
2439 close_file(fsp,True);
2442 /* We have a cached error */
2444 return(ERROR(eclass,err));
2450 /****************************************************************************
2451 reply to a writeclose (Core+ protocol)
2452 ****************************************************************************/
2453 int reply_writeclose(connection_struct *conn,
2454 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2457 ssize_t nwritten = -1;
2462 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2464 CHECK_FSP(fsp,conn);
2468 numtowrite = SVAL(inbuf,smb_vwv1);
2469 startpos = IVAL(inbuf,smb_vwv2);
2470 mtime = make_unix_date3(inbuf+smb_vwv4);
2471 data = smb_buf(inbuf) + 1;
2473 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2474 return(ERROR(ERRDOS,ERRlock));
2476 seek_file(fsp,startpos);
2478 nwritten = write_file(fsp,data,numtowrite);
2480 set_filetime(conn, fsp->fsp_name,mtime);
2482 close_file(fsp,True);
2484 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2485 fsp->fnum, numtowrite, nwritten,
2486 conn->num_files_open));
2489 return(UNIXERROR(ERRDOS,ERRnoaccess));
2491 outsize = set_message(outbuf,1,0,True);
2493 SSVAL(outbuf,smb_vwv0,nwritten);
2498 /****************************************************************************
2500 ****************************************************************************/
2501 int reply_lock(connection_struct *conn,
2502 char *inbuf,char *outbuf, int length, int dum_buffsize)
2504 int outsize = set_message(outbuf,0,0,True);
2505 SMB_OFF_T count,offset;
2508 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2510 CHECK_FSP(fsp,conn);
2513 count = IVAL(inbuf,smb_vwv1);
2514 offset = IVAL(inbuf,smb_vwv3);
2516 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2517 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2519 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2520 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2522 * A blocking lock was requested. Package up
2523 * this smb into a queued request and push it
2524 * onto the blocking lock queue.
2526 if(push_blocking_lock_request(inbuf, length, -1, 0))
2529 return (ERROR(eclass,ecode));
2536 /****************************************************************************
2538 ****************************************************************************/
2539 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2541 int outsize = set_message(outbuf,0,0,True);
2542 SMB_OFF_T count,offset;
2545 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2547 CHECK_FSP(fsp,conn);
2550 count = IVAL(inbuf,smb_vwv1);
2551 offset = IVAL(inbuf,smb_vwv3);
2553 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2554 return (ERROR(eclass,ecode));
2556 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2557 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2563 /****************************************************************************
2565 ****************************************************************************/
2566 int reply_tdis(connection_struct *conn,
2567 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2569 int outsize = set_message(outbuf,0,0,True);
2572 vuid = SVAL(inbuf,smb_uid);
2575 DEBUG(4,("Invalid connection in tdis\n"));
2576 return(ERROR(ERRSRV,ERRinvnid));
2581 close_cnum(conn,vuid);
2588 /****************************************************************************
2590 ****************************************************************************/
2591 int reply_echo(connection_struct *conn,
2592 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2594 int smb_reverb = SVAL(inbuf,smb_vwv0);
2596 int data_len = smb_buflen(inbuf);
2597 int outsize = set_message(outbuf,1,data_len,True);
2599 /* copy any incoming data back out */
2601 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2603 if (smb_reverb > 100) {
2604 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2608 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2609 SSVAL(outbuf,smb_vwv0,seq_num);
2611 smb_setlen(outbuf,outsize - 4);
2613 send_smb(Client,outbuf);
2616 DEBUG(3,("echo %d times\n", smb_reverb));
2622 /****************************************************************************
2623 reply to a printopen
2624 ****************************************************************************/
2625 int reply_printopen(connection_struct *conn,
2626 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2633 *fname = *fname2 = 0;
2635 if (!CAN_PRINT(conn))
2636 return(ERROR(ERRDOS,ERRnoaccess));
2641 pstrcpy(s,smb_buf(inbuf)+1);
2644 if (!(isalnum((int)*p) || strchr("._-",*p)))
2649 if (strlen(s) > 10) s[10] = 0;
2651 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2656 return(ERROR(ERRSRV,ERRnofids));
2658 pstrcpy(fname2,(char *)mktemp(fname));
2660 if (!check_name(fname2,conn)) {
2662 return(ERROR(ERRDOS,ERRnoaccess));
2665 /* Open for exclusive use, write only. */
2666 open_file_shared(fsp,conn,fname2,
2667 (DENY_ALL<<4)|1, 0x12, unix_mode(conn,0),
2672 return(UNIXERROR(ERRDOS,ERRnoaccess));
2675 /* force it to be a print file */
2676 fsp->print_file = True;
2678 outsize = set_message(outbuf,1,0,True);
2679 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2681 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2682 fname2, fsp->fd_ptr->fd, fsp->fnum));
2688 /****************************************************************************
2689 reply to a printclose
2690 ****************************************************************************/
2691 int reply_printclose(connection_struct *conn,
2692 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2694 int outsize = set_message(outbuf,0,0,True);
2695 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2697 CHECK_FSP(fsp,conn);
2700 if (!CAN_PRINT(conn))
2701 return(ERROR(ERRDOS,ERRnoaccess));
2703 DEBUG(3,("printclose fd=%d fnum=%d\n",
2704 fsp->fd_ptr->fd,fsp->fnum));
2706 close_file(fsp,True);
2712 /****************************************************************************
2713 reply to a printqueue
2714 ****************************************************************************/
2715 int reply_printqueue(connection_struct *conn,
2716 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2718 int outsize = set_message(outbuf,2,3,True);
2719 int max_count = SVAL(inbuf,smb_vwv0);
2720 int start_index = SVAL(inbuf,smb_vwv1);
2723 vuid = SVAL(inbuf,smb_uid);
2725 /* we used to allow the client to get the cnum wrong, but that
2726 is really quite gross and only worked when there was only
2727 one printer - I think we should now only accept it if they
2728 get it right (tridge) */
2729 if (!CAN_PRINT(conn))
2730 return(ERROR(ERRDOS,ERRnoaccess));
2732 SSVAL(outbuf,smb_vwv0,0);
2733 SSVAL(outbuf,smb_vwv1,0);
2734 CVAL(smb_buf(outbuf),0) = 1;
2735 SSVAL(smb_buf(outbuf),1,0);
2737 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2738 start_index, max_count));
2741 print_queue_struct *queue = NULL;
2742 char *p = smb_buf(outbuf) + 3;
2743 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2744 int num_to_get = ABS(max_count);
2745 int first = (max_count>0?start_index:start_index+max_count+1);
2751 num_to_get = MIN(num_to_get,count-first);
2754 for (i=first;i<first+num_to_get;i++) {
2755 put_dos_date2(p,0,queue[i].time);
2756 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2757 SSVAL(p,5,printjob_encode(SNUM(conn),
2759 SIVAL(p,7,queue[i].size);
2761 StrnCpy(p+12,queue[i].user,16);
2766 outsize = set_message(outbuf,2,28*count+3,False);
2767 SSVAL(outbuf,smb_vwv0,count);
2768 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2769 CVAL(smb_buf(outbuf),0) = 1;
2770 SSVAL(smb_buf(outbuf),1,28*count);
2773 if (queue) free(queue);
2775 DEBUG(3,("%d entries returned in queue\n",count));
2782 /****************************************************************************
2783 reply to a printwrite
2784 ****************************************************************************/
2785 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2788 int outsize = set_message(outbuf,0,0,True);
2790 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2792 if (!CAN_PRINT(conn))
2793 return(ERROR(ERRDOS,ERRnoaccess));
2795 CHECK_FSP(fsp,conn);
2799 numtowrite = SVAL(smb_buf(inbuf),1);
2800 data = smb_buf(inbuf) + 3;
2802 if (write_file(fsp,data,numtowrite) != numtowrite)
2803 return(UNIXERROR(ERRDOS,ERRnoaccess));
2805 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2811 /****************************************************************************
2813 ****************************************************************************/
2814 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2817 int outsize,ret= -1;
2818 BOOL bad_path = False;
2820 pstrcpy(directory,smb_buf(inbuf) + 1);
2821 unix_convert(directory,conn,0,&bad_path,NULL);
2823 if (check_name(directory, conn))
2824 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2828 if((errno == ENOENT) && bad_path)
2830 unix_ERR_class = ERRDOS;
2831 unix_ERR_code = ERRbadpath;
2833 return(UNIXERROR(ERRDOS,ERRnoaccess));
2836 outsize = set_message(outbuf,0,0,True);
2838 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2843 /****************************************************************************
2844 Static function used by reply_rmdir to delete an entire directory
2846 ****************************************************************************/
2847 static BOOL recursive_rmdir(char *directory)
2851 void *dirptr = OpenDir(NULL, directory, False);
2856 while((dname = ReadDirName(dirptr)))
2861 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2864 /* Construct the full name. */
2865 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2871 pstrcpy(fullname, directory);
2872 pstrcat(fullname, "/");
2873 pstrcat(fullname, dname);
2875 if(dos_lstat(fullname, &st) != 0)
2881 if(st.st_mode & S_IFDIR)
2883 if(recursive_rmdir(fullname)!=0)
2888 if(dos_rmdir(fullname) != 0)
2894 else if(dos_unlink(fullname) != 0)
2904 /****************************************************************************
2906 ****************************************************************************/
2907 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2912 BOOL bad_path = False;
2914 pstrcpy(directory,smb_buf(inbuf) + 1);
2915 unix_convert(directory,conn, NULL,&bad_path,NULL);
2917 if (check_name(directory,conn))
2920 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2921 ok = (dos_rmdir(directory) == 0);
2922 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
2924 /* Check to see if the only thing in this directory are
2925 vetoed files/directories. If so then delete them and
2926 retry. If we fail to delete any of them (and we *don't*
2927 do a recursive delete) then fail the rmdir. */
2928 BOOL all_veto_files = True;
2930 void *dirptr = OpenDir(conn, directory, False);
2934 int dirpos = TellDir(dirptr);
2935 while ((dname = ReadDirName(dirptr)))
2937 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2939 if(!IS_VETO_PATH(conn, dname))
2941 all_veto_files = False;
2947 SeekDir(dirptr,dirpos);
2948 while ((dname = ReadDirName(dirptr)))
2953 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2956 /* Construct the full name. */
2957 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2962 pstrcpy(fullname, directory);
2963 pstrcat(fullname, "/");
2964 pstrcat(fullname, dname);
2966 if(dos_lstat(fullname, &st) != 0)
2968 if(st.st_mode & S_IFDIR)
2970 if(lp_recursive_veto_delete(SNUM(conn)))
2972 if(recursive_rmdir(fullname) != 0)
2975 if(dos_rmdir(fullname) != 0)
2978 else if(dos_unlink(fullname) != 0)
2982 /* Retry the rmdir */
2983 ok = (dos_rmdir(directory) == 0);
2993 DEBUG(3,("couldn't remove directory %s : %s\n",
2994 directory,strerror(errno)));
2999 if((errno == ENOENT) && bad_path)
3001 unix_ERR_class = ERRDOS;
3002 unix_ERR_code = ERRbadpath;
3004 return(UNIXERROR(ERRDOS,ERRbadpath));
3007 outsize = set_message(outbuf,0,0,True);
3009 DEBUG( 3, ( "rmdir %s\n", directory ) );
3015 /*******************************************************************
3016 resolve wildcards in a filename rename
3017 ********************************************************************/
3018 static BOOL resolve_wildcards(char *name1,char *name2)
3020 fstring root1,root2;
3024 name1 = strrchr(name1,'/');
3025 name2 = strrchr(name2,'/');
3027 if (!name1 || !name2) return(False);
3029 fstrcpy(root1,name1);
3030 fstrcpy(root2,name2);
3031 p = strrchr(root1,'.');
3038 p = strrchr(root2,'.');
3070 pstrcpy(name2,root2);
3073 pstrcat(name2,ext2);
3079 /*******************************************************************
3080 check if a user is allowed to rename a file
3081 ********************************************************************/
3082 static BOOL can_rename(char *fname,connection_struct *conn)
3084 SMB_STRUCT_STAT sbuf;
3086 if (!CAN_WRITE(conn)) return(False);
3088 if (dos_lstat(fname,&sbuf) != 0) return(False);
3089 if (!check_file_sharing(conn,fname,True)) return(False);
3094 /****************************************************************************
3095 The guts of the rename command, split out so it may be called by the NT SMB
3097 ****************************************************************************/
3098 int rename_internals(connection_struct *conn,
3099 char *inbuf, char *outbuf, char *name,
3100 char *newname, BOOL replace_if_exists)
3104 pstring newname_last_component;
3107 BOOL bad_path1 = False;
3108 BOOL bad_path2 = False;
3110 int error = ERRnoaccess;
3113 *directory = *mask = 0;
3115 unix_convert(name,conn,0,&bad_path1,NULL);
3116 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3119 * Split the old name into directory and last component
3120 * strings. Note that unix_convert may have stripped off a
3121 * leading ./ from both name and newname if the rename is
3122 * at the root of the share. We need to make sure either both
3123 * name and newname contain a / character or neither of them do
3124 * as this is checked in resolve_wildcards().
3127 p = strrchr(name,'/');
3129 pstrcpy(directory,".");
3133 pstrcpy(directory,name);
3135 *p = '/'; /* Replace needed for exceptional test below. */
3138 if (is_mangled(mask))
3139 check_mangled_cache( mask );
3141 has_wild = strchr(mask,'*') || strchr(mask,'?');
3145 * No wildcards - just process the one file.
3147 BOOL is_short_name = is_8_3(name, True);
3149 /* Add a terminating '/' to the directory name. */
3150 pstrcat(directory,"/");
3151 pstrcat(directory,mask);
3153 /* Ensure newname contains a '/' also */
3154 if(strrchr(newname,'/') == 0) {
3157 pstrcpy(tmpstr, "./");
3158 pstrcat(tmpstr, newname);
3159 pstrcpy(newname, tmpstr);
3162 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3163 case_sensitive, case_preserve, short_case_preserve, directory,
3164 newname, newname_last_component, is_short_name));
3167 * Check for special case with case preserving and not
3168 * case sensitive, if directory and newname are identical,
3169 * and the old last component differs from the original
3170 * last component only by case, then we should allow
3171 * the rename (user is trying to change the case of the
3174 if((case_sensitive == False) &&
3175 (((case_preserve == True) &&
3176 (is_short_name == False)) ||
3177 ((short_case_preserve == True) &&
3178 (is_short_name == True))) &&
3179 strcsequal(directory, newname)) {
3180 pstring newname_modified_last_component;
3183 * Get the last component of the modified name.
3184 * Note that we guarantee that newname contains a '/'
3187 p = strrchr(newname,'/');
3188 pstrcpy(newname_modified_last_component,p+1);
3190 if(strcsequal(newname_modified_last_component,
3191 newname_last_component) == False) {
3193 * Replace the modified last component with
3196 pstrcpy(p+1, newname_last_component);
3200 if(replace_if_exists) {
3202 * NT SMB specific flag - rename can overwrite
3203 * file with the same name so don't check for
3206 if(resolve_wildcards(directory,newname) &&
3207 can_rename(directory,conn) &&
3208 !dos_rename(directory,newname))
3211 if (resolve_wildcards(directory,newname) &&
3212 can_rename(directory,conn) &&
3213 !file_exist(newname,NULL) &&
3214 !dos_rename(directory,newname))
3218 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3219 directory,newname));
3221 if (!count) exists = file_exist(directory,NULL);
3222 if (!count && exists && file_exist(newname,NULL)) {
3228 * Wildcards - process each file that matches.
3230 void *dirptr = NULL;
3234 if (check_name(directory,conn))
3235 dirptr = OpenDir(conn, directory, True);
3240 if (strequal(mask,"????????.???"))
3243 while ((dname = ReadDirName(dirptr))) {
3245 pstrcpy(fname,dname);
3247 if(!mask_match(fname, mask, case_sensitive, False))
3250 error = ERRnoaccess;
3251 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3252 if (!can_rename(fname,conn)) {
3253 DEBUG(6,("rename %s refused\n", fname));
3256 pstrcpy(destname,newname);
3258 if (!resolve_wildcards(fname,destname)) {
3259 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3263 if (!replace_if_exists && file_exist(destname,NULL)) {
3264 DEBUG(6,("file_exist %s\n", destname));
3269 if (!dos_rename(fname,destname))
3271 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3279 return(ERROR(ERRDOS,error));
3281 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3282 unix_ERR_class = ERRDOS;
3283 unix_ERR_code = ERRbadpath;
3285 return(UNIXERROR(ERRDOS,error));
3292 /****************************************************************************
3294 ****************************************************************************/
3296 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3302 pstrcpy(name,smb_buf(inbuf) + 1);
3303 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3305 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3307 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3309 outsize = set_message(outbuf,0,0,True);
3314 /*******************************************************************
3315 copy a file as part of a reply_copy
3316 ******************************************************************/
3317 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3318 int count,BOOL target_is_directory)
3323 files_struct *fsp1,*fsp2;
3326 pstrcpy(dest,dest1);
3327 if (target_is_directory) {
3328 char *p = strrchr(src,'/');
3337 if (!file_exist(src,&st)) return(False);
3340 if (!fsp1) return(False);
3341 open_file_shared(fsp1,conn,src,(DENY_NONE<<4),
3342 1,0,0,&Access,&action);
3349 if (!target_is_directory && count)
3354 close_file(fsp1,False);
3357 open_file_shared(fsp2,conn,dest,(DENY_NONE<<4)|1,
3358 ofun,st.st_mode,0,&Access,&action);
3361 close_file(fsp1,False);
3366 if ((ofun&3) == 1) {
3367 sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END);
3371 ret = transfer_file(fsp1->fd_ptr->fd,
3372 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3374 close_file(fsp1,False);
3375 close_file(fsp2,False);
3377 return(ret == st.st_size);
3382 /****************************************************************************
3383 reply to a file copy.
3384 ****************************************************************************/
3385 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3390 pstring mask,newname;
3393 int error = ERRnoaccess;
3396 int tid2 = SVAL(inbuf,smb_vwv0);
3397 int ofun = SVAL(inbuf,smb_vwv1);
3398 int flags = SVAL(inbuf,smb_vwv2);
3399 BOOL target_is_directory=False;
3400 BOOL bad_path1 = False;
3401 BOOL bad_path2 = False;
3403 *directory = *mask = 0;
3405 pstrcpy(name,smb_buf(inbuf));
3406 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3408 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3410 if (tid2 != conn->cnum) {
3411 /* can't currently handle inter share copies XXXX */
3412 DEBUG(3,("Rejecting inter-share copy\n"));
3413 return(ERROR(ERRSRV,ERRinvdevice));
3416 unix_convert(name,conn,0,&bad_path1,NULL);
3417 unix_convert(newname,conn,0,&bad_path2,NULL);
3419 target_is_directory = directory_exist(newname,NULL);
3421 if ((flags&1) && target_is_directory) {
3422 return(ERROR(ERRDOS,ERRbadfile));
3425 if ((flags&2) && !target_is_directory) {
3426 return(ERROR(ERRDOS,ERRbadpath));
3429 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3430 /* wants a tree copy! XXXX */
3431 DEBUG(3,("Rejecting tree copy\n"));
3432 return(ERROR(ERRSRV,ERRerror));
3435 p = strrchr(name,'/');
3437 pstrcpy(directory,"./");
3441 pstrcpy(directory,name);
3445 if (is_mangled(mask))
3446 check_mangled_cache( mask );
3448 has_wild = strchr(mask,'*') || strchr(mask,'?');
3451 pstrcat(directory,"/");
3452 pstrcat(directory,mask);
3453 if (resolve_wildcards(directory,newname) &&
3454 copy_file(directory,newname,conn,ofun,
3455 count,target_is_directory)) count++;
3456 if (!count) exists = file_exist(directory,NULL);
3458 void *dirptr = NULL;
3462 if (check_name(directory,conn))
3463 dirptr = OpenDir(conn, directory, True);
3469 if (strequal(mask,"????????.???"))
3472 while ((dname = ReadDirName(dirptr)))
3475 pstrcpy(fname,dname);
3477 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3479 error = ERRnoaccess;
3480 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3481 pstrcpy(destname,newname);
3482 if (resolve_wildcards(fname,destname) &&
3483 copy_file(directory,newname,conn,ofun,
3484 count,target_is_directory)) count++;
3485 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3493 return(ERROR(ERRDOS,error));
3496 if((errno == ENOENT) && (bad_path1 || bad_path2))
3498 unix_ERR_class = ERRDOS;
3499 unix_ERR_code = ERRbadpath;
3501 return(UNIXERROR(ERRDOS,error));
3505 outsize = set_message(outbuf,1,0,True);
3506 SSVAL(outbuf,smb_vwv0,count);
3511 /****************************************************************************
3513 ****************************************************************************/
3514 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3522 if (!CAN_SETDIR(snum))
3523 return(ERROR(ERRDOS,ERRnoaccess));
3525 pstrcpy(newdir,smb_buf(inbuf) + 1);
3528 if (strlen(newdir) == 0) {
3531 ok = directory_exist(newdir,NULL);
3533 string_set(&conn->connectpath,newdir);
3538 return(ERROR(ERRDOS,ERRbadpath));
3540 outsize = set_message(outbuf,0,0,True);
3541 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3543 DEBUG(3,("setdir %s\n", newdir));
3548 /****************************************************************************
3549 reply to a lockingX request
3550 ****************************************************************************/
3551 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3553 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3554 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3556 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3558 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3559 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3560 SMB_OFF_T count, offset;
3561 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3564 uint32 ecode=0, dummy2;
3565 int eclass=0, dummy1;
3566 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3567 CHECK_FSP(fsp,conn);
3570 data = smb_buf(inbuf);
3572 /* Check if this is an oplock break on a file
3573 we have granted an oplock on.
3575 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3578 SMB_DEV_T dev = fsp->fd_ptr->dev;
3579 SMB_INO_T inode = fsp->fd_ptr->inode;
3581 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3584 * Make sure we have granted an oplock on this file.
3586 if(!fsp->granted_oplock)
3588 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3589 no oplock granted on this file.\n", fsp->fnum));
3590 return ERROR(ERRDOS,ERRlock);
3593 /* Remove the oplock flag from the sharemode. */
3594 lock_share_entry(fsp->conn, dev, inode, &token);
3595 if(remove_share_oplock(fsp, token)==False) {
3597 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3598 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3600 unlock_share_entry(fsp->conn, dev, inode, token);
3602 unlock_share_entry(fsp->conn, dev, inode, token);
3604 /* Clear the granted flag and return. */
3605 fsp->granted_oplock = False;
3608 /* if this is a pure oplock break request then don't send a reply */
3609 if (num_locks == 0 && num_ulocks == 0)
3611 /* Sanity check - ensure a pure oplock break is not a
3613 if(CVAL(inbuf,smb_vwv0) != 0xff)
3614 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3615 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3620 /* Data now points at the beginning of the list
3621 of smb_unlkrng structs */
3622 for(i = 0; i < (int)num_ulocks; i++) {
3623 if(!large_file_format) {
3624 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3625 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3627 #ifdef LARGE_SMB_OFF_T
3629 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3630 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3631 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3632 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3634 #endif /* LARGE_SMB_OFF_T */
3636 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3637 (double)offset, (double)count, fsp->fsp_name ));
3639 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3640 return ERROR(eclass,ecode);
3643 /* Setup the timeout in seconds. */
3644 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3646 /* Now do any requested locks */
3647 data += ((large_file_format ? 20 : 10)*num_ulocks);
3649 /* Data now points at the beginning of the list
3650 of smb_lkrng structs */
3652 for(i = 0; i < (int)num_locks; i++) {
3653 if(!large_file_format) {
3654 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3655 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3657 #ifdef LARGE_SMB_OFF_T
3659 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3660 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3661 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3662 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3664 #endif /* LARGE_SMB_OFF_T */
3666 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3667 (double)offset, (double)count, fsp->fsp_name ));
3669 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3671 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3673 * A blocking lock was requested. Package up
3674 * this smb into a queued request and push it
3675 * onto the blocking lock queue.
3677 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3684 /* If any of the above locks failed, then we must unlock
3685 all of the previous locks (X/Open spec). */
3686 if(i != num_locks && num_locks != 0) {
3687 for(; i >= 0; i--) {
3688 if(!large_file_format) {
3689 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3690 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3692 #ifdef LARGE_SMB_OFF_T
3694 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3695 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3696 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3697 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3699 #endif /* LARGE_SMB_OFF_T */
3701 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3703 return ERROR(eclass,ecode);
3706 set_message(outbuf,2,0,True);
3708 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3709 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3711 return chain_reply(inbuf,outbuf,length,bufsize);
3715 /****************************************************************************
3716 reply to a SMBreadbmpx (read block multiplex) request
3717 ****************************************************************************/
3718 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3725 size_t mincount, maxcount;
3729 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3731 /* this function doesn't seem to work - disable by default */
3733 return(ERROR(ERRSRV,ERRuseSTD));
3735 outsize = set_message(outbuf,8,0,True);
3737 CHECK_FSP(fsp,conn);
3741 startpos = IVAL(inbuf,smb_vwv1);
3742 maxcount = SVAL(inbuf,smb_vwv3);
3743 mincount = SVAL(inbuf,smb_vwv4);
3745 data = smb_buf(outbuf);
3746 pad = ((long)data)%4;
3747 if (pad) pad = 4 - pad;
3750 max_per_packet = bufsize-(outsize+pad);
3754 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3755 return(ERROR(ERRDOS,ERRlock));
3759 size_t N = MIN(max_per_packet,tcount-total_read);
3761 nread = read_file(fsp,data,startpos,N);
3763 if (nread <= 0) nread = 0;
3765 if (nread < (ssize_t)N)
3766 tcount = total_read + nread;
3768 set_message(outbuf,8,nread,False);
3769 SIVAL(outbuf,smb_vwv0,startpos);
3770 SSVAL(outbuf,smb_vwv2,tcount);
3771 SSVAL(outbuf,smb_vwv6,nread);
3772 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3774 send_smb(Client,outbuf);
3776 total_read += nread;
3779 while (total_read < (ssize_t)tcount);
3784 /****************************************************************************
3785 reply to a SMBwritebmpx (write block multiplex primary) request
3786 ****************************************************************************/
3787 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3790 ssize_t nwritten = -1;
3797 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3799 CHECK_FSP(fsp,conn);
3803 tcount = SVAL(inbuf,smb_vwv1);
3804 startpos = IVAL(inbuf,smb_vwv3);
3805 write_through = BITSETW(inbuf+smb_vwv7,0);
3806 numtowrite = SVAL(inbuf,smb_vwv10);
3807 smb_doff = SVAL(inbuf,smb_vwv11);
3809 data = smb_base(inbuf) + smb_doff;
3811 /* If this fails we need to send an SMBwriteC response,
3812 not an SMBwritebmpx - set this up now so we don't forget */
3813 CVAL(outbuf,smb_com) = SMBwritec;
3815 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3816 return(ERROR(ERRDOS,ERRlock));
3818 seek_file(fsp,startpos);
3819 nwritten = write_file(fsp,data,numtowrite);
3821 if(lp_syncalways(SNUM(conn)) || write_through)
3822 sync_file(conn,fsp);
3824 if(nwritten < (ssize_t)numtowrite)
3825 return(UNIXERROR(ERRHRD,ERRdiskfull));
3827 /* If the maximum to be written to this file
3828 is greater than what we just wrote then set
3829 up a secondary struct to be attached to this
3830 fd, we will use this to cache error messages etc. */
3831 if((ssize_t)tcount > nwritten)
3833 write_bmpx_struct *wbms;
3834 if(fsp->wbmpx_ptr != NULL)
3835 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3837 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3840 DEBUG(0,("Out of memory in reply_readmpx\n"));
3841 return(ERROR(ERRSRV,ERRnoresource));
3843 wbms->wr_mode = write_through;
3844 wbms->wr_discard = False; /* No errors yet */
3845 wbms->wr_total_written = nwritten;
3846 wbms->wr_errclass = 0;
3848 fsp->wbmpx_ptr = wbms;
3851 /* We are returning successfully, set the message type back to
3853 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3855 outsize = set_message(outbuf,1,0,True);
3857 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3859 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3860 fsp->fnum, numtowrite, nwritten ) );
3862 if (write_through && tcount==nwritten) {
3863 /* we need to send both a primary and a secondary response */
3864 smb_setlen(outbuf,outsize - 4);
3865 send_smb(Client,outbuf);
3867 /* now the secondary */
3868 outsize = set_message(outbuf,1,0,True);
3869 CVAL(outbuf,smb_com) = SMBwritec;
3870 SSVAL(outbuf,smb_vwv0,nwritten);
3877 /****************************************************************************
3878 reply to a SMBwritebs (write block multiplex secondary) request
3879 ****************************************************************************/
3880 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3883 ssize_t nwritten = -1;
3890 write_bmpx_struct *wbms;
3891 BOOL send_response = False;
3892 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3894 CHECK_FSP(fsp,conn);
3897 tcount = SVAL(inbuf,smb_vwv1);
3898 startpos = IVAL(inbuf,smb_vwv2);
3899 numtowrite = SVAL(inbuf,smb_vwv6);
3900 smb_doff = SVAL(inbuf,smb_vwv7);
3902 data = smb_base(inbuf) + smb_doff;
3904 /* We need to send an SMBwriteC response, not an SMBwritebs */
3905 CVAL(outbuf,smb_com) = SMBwritec;
3907 /* This fd should have an auxiliary struct attached,
3908 check that it does */
3909 wbms = fsp->wbmpx_ptr;
3910 if(!wbms) return(-1);
3912 /* If write through is set we can return errors, else we must
3914 write_through = wbms->wr_mode;
3916 /* Check for an earlier error */
3917 if(wbms->wr_discard)
3918 return -1; /* Just discard the packet */
3920 seek_file(fsp,startpos);
3921 nwritten = write_file(fsp,data,numtowrite);
3923 if(lp_syncalways(SNUM(conn)) || write_through)
3924 sync_file(conn,fsp);
3926 if (nwritten < (ssize_t)numtowrite)
3930 /* We are returning an error - we can delete the aux struct */
3931 if (wbms) free((char *)wbms);
3932 fsp->wbmpx_ptr = NULL;
3933 return(ERROR(ERRHRD,ERRdiskfull));
3935 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3938 /* Increment the total written, if this matches tcount
3939 we can discard the auxiliary struct (hurrah !) and return a writeC */
3940 wbms->wr_total_written += nwritten;
3941 if(wbms->wr_total_written >= tcount)
3945 outsize = set_message(outbuf,1,0,True);
3946 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3947 send_response = True;
3951 fsp->wbmpx_ptr = NULL;
3961 /****************************************************************************
3962 reply to a SMBsetattrE
3963 ****************************************************************************/
3964 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3966 struct utimbuf unix_times;
3968 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3970 outsize = set_message(outbuf,0,0,True);
3972 CHECK_FSP(fsp,conn);
3975 /* Convert the DOS times into unix times. Ignore create
3976 time as UNIX can't set this.
3978 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3979 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3982 * Patch from Ray Frush <frush@engr.colostate.edu>
3983 * Sometimes times are sent as zero - ignore them.
3986 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3988 /* Ignore request */
3991 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
3992 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
3996 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3998 /* set modify time = to access time if modify time was 0 */
3999 unix_times.modtime = unix_times.actime;
4002 /* Set the date on this file */
4003 if(file_utime(conn, fsp->fsp_name, &unix_times))
4004 return(ERROR(ERRDOS,ERRnoaccess));
4006 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4007 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4013 /****************************************************************************
4014 reply to a SMBgetattrE
4015 ****************************************************************************/
4016 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4018 SMB_STRUCT_STAT sbuf;
4021 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4023 outsize = set_message(outbuf,11,0,True);
4025 CHECK_FSP(fsp,conn);
4028 /* Do an fstat on this file */
4029 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4030 return(UNIXERROR(ERRDOS,ERRnoaccess));
4032 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4034 /* Convert the times into dos times. Set create
4035 date to be last modify date as UNIX doesn't save
4037 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4038 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4039 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4042 SIVAL(outbuf,smb_vwv6,0);
4043 SIVAL(outbuf,smb_vwv8,0);
4047 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4048 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
4050 SSVAL(outbuf,smb_vwv10, mode);
4052 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));