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;
44 uint32 global_client_caps = 0;
47 /****************************************************************************
48 report a possible attack via the password buffer overflow bug
49 ****************************************************************************/
50 static void overflow_attack(int len)
54 dbgtext( "ERROR: Invalid password length %d.\n", len );
55 dbgtext( "Your machine may be under attack by someone " );
56 dbgtext( "attempting to exploit an old bug.\n" );
57 dbgtext( "Attack was from IP = %s.\n", client_addr(Client) );
59 exit_server("possible attack");
63 /****************************************************************************
64 reply to an special message
65 ****************************************************************************/
66 int reply_special(char *inbuf,char *outbuf)
69 int msg_type = CVAL(inbuf,0);
70 int msg_flags = CVAL(inbuf,1);
72 extern fstring remote_machine;
73 extern fstring local_machine;
79 bzero(outbuf,smb_size);
84 case 0x81: /* session request */
85 CVAL(outbuf,0) = 0x82;
87 if (name_len(inbuf+4) > 50 ||
88 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
89 DEBUG(0,("Invalid name length in session request\n"));
92 name_extract(inbuf,4,name1);
93 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
94 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
97 fstrcpy(remote_machine,name2);
98 remote_machine[15] = 0;
99 trim_string(remote_machine," "," ");
100 strlower(remote_machine);
102 fstrcpy(local_machine,name1);
103 len = strlen(local_machine);
105 name_type = local_machine[15];
106 local_machine[15] = 0;
108 trim_string(local_machine," "," ");
109 strlower(local_machine);
111 if (name_type == 'R') {
112 /* We are being asked for a pathworks session ---
114 CVAL(outbuf, 0) = 0x83;
118 add_session_user(remote_machine);
120 reload_services(True);
124 claim_connection(NULL,"STATUS.",MAXSTATUS,True);
129 case 0x89: /* session keepalive request
130 (some old clients produce this?) */
131 CVAL(outbuf,0) = 0x85;
135 case 0x82: /* positive session response */
136 case 0x83: /* negative session response */
137 case 0x84: /* retarget session response */
138 DEBUG(0,("Unexpected session response\n"));
141 case 0x85: /* session keepalive */
146 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
147 msg_type, msg_flags));
153 /*******************************************************************
154 work out what error to give to a failed connection
155 ********************************************************************/
156 static int connection_error(char *inbuf,char *outbuf,int ecode)
158 if (ecode == ERRnoipc) {
159 return(ERROR(ERRDOS,ERRnoipc));
162 return(ERROR(ERRSRV,ecode));
167 /****************************************************************************
168 parse a share descriptor string
169 ****************************************************************************/
170 static void parse_connect(char *p,char *service,char *user,
171 char *password,int *pwlen,char *dev)
175 DEBUG(4,("parsing connect string %s\n",p));
177 p2 = strrchr(p,'\\');
181 fstrcpy(service,p2+1);
186 *pwlen = strlen(password);
193 p = strchr(service,'%');
204 /****************************************************************************
206 ****************************************************************************/
207 int reply_tcon(connection_struct *conn,
208 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
215 uint16 vuid = SVAL(inbuf,smb_uid);
219 *service = *user = *password = *dev = 0;
221 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
224 * Pass the user through the NT -> unix user mapping
228 (void)map_username(user);
231 * Do any UNIX username case mangling.
233 (void)Get_Pwnam( user, True);
235 conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
238 return(connection_error(inbuf,outbuf,ecode));
241 outsize = set_message(outbuf,2,0,True);
242 SSVAL(outbuf,smb_vwv0,max_recv);
243 SSVAL(outbuf,smb_vwv1,conn->cnum);
244 SSVAL(outbuf,smb_tid,conn->cnum);
246 DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
247 service, user, conn->cnum));
253 /****************************************************************************
254 reply to a tcon and X
255 ****************************************************************************/
256 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
263 uint16 vuid = SVAL(inbuf,smb_uid);
264 int passlen = SVAL(inbuf,smb_vwv3);
268 *service = *user = *password = *devicename = 0;
270 /* we might have to close an old one */
271 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
272 close_cnum(conn,vuid);
275 if (passlen > MAX_PASS_LEN) {
276 overflow_attack(passlen);
279 memcpy(password,smb_buf(inbuf),passlen);
281 path = smb_buf(inbuf) + passlen;
284 if (strequal(password," "))
286 passlen = strlen(password);
289 fstrcpy(service,path+2);
290 p = strchr(service,'\\');
292 return(ERROR(ERRSRV,ERRinvnetname));
294 fstrcpy(service,p+1);
295 p = strchr(service,'%');
300 StrnCpy(devicename,path + strlen(path) + 1,6);
301 DEBUG(4,("Got device type %s\n",devicename));
304 * Pass the user through the NT -> unix user mapping
308 (void)map_username(user);
311 * Do any UNIX username case mangling.
313 (void)Get_Pwnam(user, True);
315 conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
318 return(connection_error(inbuf,outbuf,ecode));
320 if (Protocol < PROTOCOL_NT1) {
321 set_message(outbuf,2,strlen(devicename)+1,True);
322 pstrcpy(smb_buf(outbuf),devicename);
324 char *fsname = lp_fstype(SNUM(conn));
326 set_message(outbuf,3,3,True);
329 pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
330 pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
332 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
334 /* what does setting this bit do? It is set by NT4 and
335 may affect the ability to autorun mounted cdroms */
336 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
339 DEBUG(3,("tconX service=%s user=%s\n",
342 /* set the incoming and outgoing tid to the just created one */
343 SSVAL(inbuf,smb_tid,conn->cnum);
344 SSVAL(outbuf,smb_tid,conn->cnum);
346 return chain_reply(inbuf,outbuf,length,bufsize);
350 /****************************************************************************
351 reply to an unknown type
352 ****************************************************************************/
353 int reply_unknown(char *inbuf,char *outbuf)
356 type = CVAL(inbuf,smb_com);
358 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
359 smb_fn_name(type), type, type));
361 return(ERROR(ERRSRV,ERRunknownsmb));
365 /****************************************************************************
367 ****************************************************************************/
368 int reply_ioctl(connection_struct *conn,
369 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
371 DEBUG(3,("ignoring ioctl\n"));
373 /* we just say it succeeds and hope its all OK.
374 some day it would be nice to interpret them individually */
375 return set_message(outbuf,1,0,True);
377 return(ERROR(ERRSRV,ERRnosupport));
381 /****************************************************************************
382 always return an error: it's just a matter of which one...
383 ****************************************************************************/
384 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
385 char *smb_passwd, int smb_passlen,
386 char *smb_nt_passwd, int smb_nt_passlen)
388 struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
389 if (lp_security() == SEC_USER)
391 smb_trust_acct = getsmbpwnam(user);
395 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
396 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
397 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
400 if (smb_trust_acct == NULL)
402 /* lkclXXXX: workstation entry doesn't exist */
403 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
404 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
405 return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
409 if ((smb_passlen != 24) || (smb_nt_passlen != 24))
411 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
412 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
413 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
416 if (!smb_password_ok(smb_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd))
418 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
419 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
420 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
423 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
425 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
426 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
427 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
430 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
432 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
433 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
434 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
437 if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
439 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
440 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
441 return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
445 /* don't know what to do: indicate logon failure */
446 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
447 return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
450 /****************************************************************************
451 Check for a valid username and password in security=server mode.
452 ****************************************************************************/
454 static BOOL check_server_security(char *orig_user, char *domain,
455 char *smb_apasswd, int smb_apasslen,
456 char *smb_ntpasswd, int smb_ntpasslen)
458 if(lp_security() != SEC_SERVER)
461 return server_validate(orig_user, domain,
462 smb_apasswd, smb_apasslen,
463 smb_ntpasswd, smb_ntpasslen);
466 /****************************************************************************
467 Check for a valid username and password in security=domain mode.
468 ****************************************************************************/
470 static BOOL check_domain_security(char *orig_user, char *domain,
471 char *smb_apasswd, int smb_apasslen,
472 char *smb_ntpasswd, int smb_ntpasslen)
474 if(lp_security() != SEC_DOMAIN)
477 return domain_client_validate(orig_user, domain,
478 smb_apasswd, smb_apasslen,
479 smb_ntpasswd, smb_ntpasslen);
482 /****************************************************************************
483 reply to a session setup command
484 ****************************************************************************/
486 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
492 int smb_apasslen = 0;
494 int smb_ntpasslen = 0;
495 pstring smb_ntpasswd;
496 BOOL valid_nt_password = False;
500 static BOOL done_sesssetup = False;
501 BOOL doencrypt = SMBENCRYPT();
507 smb_bufsize = SVAL(inbuf,smb_vwv2);
509 if (Protocol < PROTOCOL_NT1) {
510 smb_apasslen = SVAL(inbuf,smb_vwv7);
511 if (smb_apasslen > MAX_PASS_LEN)
513 overflow_attack(smb_apasslen);
516 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
517 smb_apasswd[smb_apasslen] = 0;
518 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
520 if (!doencrypt && (lp_security() != SEC_SERVER)) {
521 smb_apasslen = strlen(smb_apasswd);
524 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
525 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
526 enum remote_arch_types ra_type = get_remote_arch();
527 char *p = smb_buf(inbuf);
529 global_client_caps = IVAL(inbuf,smb_vwv11);
531 /* client_caps is used as final determination if client is NT or Win95.
532 This is needed to return the correct error codes in some
536 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
538 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
539 set_remote_arch( RA_WINNT);
541 set_remote_arch( RA_WIN95);
544 if (passlen1 != 24 && passlen2 != 24)
547 if (passlen1 > MAX_PASS_LEN) {
548 overflow_attack(passlen1);
551 passlen1 = MIN(passlen1, MAX_PASS_LEN);
552 passlen2 = MIN(passlen2, MAX_PASS_LEN);
555 /* both Win95 and WinNT stuff up the password lengths for
556 non-encrypting systems. Uggh.
558 if passlen1==24 its a win95 system, and its setting the
559 password length incorrectly. Luckily it still works with the
560 default code because Win95 will null terminate the password
563 if passlen1>0 and passlen2>0 then maybe its a NT box and its
564 setting passlen2 to some random value which really stuffs
565 things up. we need to fix that one. */
567 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
571 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
572 /* Save the lanman2 password and the NT md4 password. */
573 smb_apasslen = passlen1;
574 memcpy(smb_apasswd,p,smb_apasslen);
575 smb_apasswd[smb_apasslen] = 0;
576 smb_ntpasslen = passlen2;
577 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
578 smb_ntpasswd[smb_ntpasslen] = 0;
580 /* we use the first password that they gave */
581 smb_apasslen = passlen1;
582 StrnCpy(smb_apasswd,p,smb_apasslen);
584 /* trim the password */
585 smb_apasslen = strlen(smb_apasswd);
587 /* wfwg sometimes uses a space instead of a null */
588 if (strequal(smb_apasswd," ")) {
594 p += passlen1 + passlen2;
595 fstrcpy(user,p); p = skip_string(p,1);
598 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
599 domain,skip_string(p,1),skip_string(p,2)));
603 DEBUG(3,("sesssetupX:name=[%s]\n",user));
605 /* If name ends in $ then I think it's asking about whether a */
606 /* computer with that name (minus the $) has access. For now */
607 /* say yes to everything ending in $. */
608 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
610 return session_trust_account(conn, inbuf, outbuf, user,
611 smb_apasswd, smb_apasslen,
612 smb_ntpasswd, smb_ntpasslen);
615 /* If no username is sent use the guest account */
618 pstrcpy(user,lp_guestaccount(-1));
619 /* If no user and no password then set guest flag. */
620 if( *smb_apasswd == 0)
627 * In share level security, only overwrite sesssetup_use if
628 * it's a non null-session share. Helps keep %U and %G
632 if((lp_security() != SEC_SHARE) || (*user && !guest))
633 pstrcpy(sesssetup_user,user);
635 reload_services(True);
638 * Save the username before mapping. We will use
639 * the original username sent to us for security=server
640 * and security=domain checking.
643 pstrcpy( orig_user, user);
646 * Pass the user through the NT -> unix user mapping
650 (void)map_username(user);
653 * Do any UNIX username case mangling.
655 (void)Get_Pwnam( user, True);
657 add_session_user(user);
660 * Check if the given username was the guest user with no password.
663 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
667 * Check with orig_user for security=server and
672 !check_server_security(orig_user, domain,
673 smb_apasswd, smb_apasslen,
674 smb_ntpasswd, smb_ntpasslen) &&
675 !check_domain_security(orig_user, domain,
676 smb_apasswd, smb_apasslen,
677 smb_ntpasswd, smb_ntpasslen) &&
678 !check_hosts_equiv(user)
683 * If we get here then the user wasn't guest and the remote
684 * authentication methods failed. Check the authentication
685 * methods on this local server.
687 * If an NT password was supplied try and validate with that
688 * first. This is superior as the passwords are mixed case
689 * 128 length unicode.
694 if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
695 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
697 valid_nt_password = True;
700 if (!valid_nt_password && !password_ok(user, smb_apasswd,smb_apasslen,NULL))
702 if (lp_security() >= SEC_USER)
704 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
705 return(ERROR(ERRSRV,ERRbadpw));
707 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
709 if (Get_Pwnam(user,True))
710 return(ERROR(ERRSRV,ERRbadpw));
714 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
715 * Then always map to guest account - as done below.
719 if (*smb_apasswd || !Get_Pwnam(user,True))
720 pstrcpy(user,lp_guestaccount(-1));
721 DEBUG(3,("Registered username %s for guest access\n",user));
726 if (!Get_Pwnam(user,True)) {
727 DEBUG(3,("No such user %s - using guest account\n",user));
728 pstrcpy(user,lp_guestaccount(-1));
732 if (!strequal(user,lp_guestaccount(-1)) &&
733 lp_servicenumber(user) < 0)
735 int homes = lp_servicenumber(HOMES_NAME);
736 char *home = get_home_dir(user);
737 if (homes >= 0 && home)
738 lp_add_home(user,homes,home);
742 /* it's ok - setup a reply */
743 if (Protocol < PROTOCOL_NT1) {
744 set_message(outbuf,3,0,True);
747 set_message(outbuf,3,3,True);
749 pstrcpy(p,"Unix"); p = skip_string(p,1);
750 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
751 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
752 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
753 /* perhaps grab OS version here?? */
756 /* Set the correct uid in the outgoing and incoming packets
757 We will use this on future requests to determine which
758 user we should become.
761 struct passwd *pw = Get_Pwnam(user,False);
763 DEBUG(1,("Username %s is invalid on this system\n",user));
764 return(ERROR(ERRSRV,ERRbadpw));
771 SSVAL(outbuf,smb_vwv2,1);
773 /* register the name and uid as being validated, so further connections
774 to a uid can get through without a password, on the same VC */
775 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
777 SSVAL(outbuf,smb_uid,sess_vuid);
778 SSVAL(inbuf,smb_uid,sess_vuid);
781 max_send = MIN(max_send,smb_bufsize);
783 DEBUG(6,("Client requested max send size of %d\n", max_send));
785 done_sesssetup = True;
787 return chain_reply(inbuf,outbuf,length,bufsize);
791 /****************************************************************************
793 ****************************************************************************/
794 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
800 BOOL bad_path = False;
803 pstrcpy(name,smb_buf(inbuf) + 1);
804 unix_convert(name,conn,0,&bad_path,&st);
806 mode = SVAL(inbuf,smb_vwv0);
808 if (check_name(name,conn)) {
810 ok = S_ISDIR(st.st_mode);
812 ok = directory_exist(name,NULL);
817 /* We special case this - as when a Windows machine
818 is parsing a path is steps through the components
819 one at a time - if a component fails it expects
820 ERRbadpath, not ERRbadfile.
824 unix_ERR_class = ERRDOS;
825 unix_ERR_code = ERRbadpath;
829 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
830 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
831 (get_remote_arch() == RA_WINNT))
833 unix_ERR_class = ERRDOS;
834 unix_ERR_code = ERRbaddirectory;
838 return(UNIXERROR(ERRDOS,ERRbadpath));
841 outsize = set_message(outbuf,0,0,True);
843 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
849 /****************************************************************************
851 ****************************************************************************/
852 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
856 SMB_STRUCT_STAT sbuf;
861 BOOL bad_path = False;
863 pstrcpy(fname,smb_buf(inbuf) + 1);
865 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
866 under WfWg - weird! */
869 mode = aHIDDEN | aDIR;
870 if (!CAN_WRITE(conn)) mode |= aRONLY;
877 unix_convert(fname,conn,0,&bad_path,&sbuf);
878 if (check_name(fname,conn))
880 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
882 mode = dos_mode(conn,fname,&sbuf);
884 mtime = sbuf.st_mtime;
890 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
896 if((errno == ENOENT) && bad_path)
898 unix_ERR_class = ERRDOS;
899 unix_ERR_code = ERRbadpath;
902 return(UNIXERROR(ERRDOS,ERRbadfile));
905 outsize = set_message(outbuf,10,0,True);
907 SSVAL(outbuf,smb_vwv0,mode);
908 if(lp_dos_filetime_resolution(SNUM(conn)) )
909 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
911 put_dos_date3(outbuf,smb_vwv1,mtime);
912 SIVAL(outbuf,smb_vwv3,(uint32)size);
914 if (Protocol >= PROTOCOL_NT1) {
915 char *p = strrchr(fname,'/');
916 uint16 flg2 = SVAL(outbuf,smb_flg2);
918 if (!is_8_3(fname, True))
919 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
922 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
928 /****************************************************************************
930 ****************************************************************************/
931 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
939 BOOL bad_path = False;
941 pstrcpy(fname,smb_buf(inbuf) + 1);
942 unix_convert(fname,conn,0,&bad_path,&st);
944 mode = SVAL(inbuf,smb_vwv0);
945 mtime = make_unix_date3(inbuf+smb_vwv1);
947 if (VALID_STAT_OF_DIR(st) || directory_exist(fname,NULL))
949 if (check_name(fname,conn))
950 ok = (file_chmod(conn,fname,mode,NULL) == 0);
952 ok = set_filetime(conn,fname,mtime);
956 if((errno == ENOENT) && bad_path)
958 unix_ERR_class = ERRDOS;
959 unix_ERR_code = ERRbadpath;
962 return(UNIXERROR(ERRDOS,ERRnoaccess));
965 outsize = set_message(outbuf,0,0,True);
967 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
973 /****************************************************************************
975 ****************************************************************************/
976 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
979 SMB_BIG_UINT dfree,dsize,bsize;
981 sys_disk_free(".",&bsize,&dfree,&dsize);
983 outsize = set_message(outbuf,5,0,True);
985 SSVAL(outbuf,smb_vwv0,dsize);
986 SSVAL(outbuf,smb_vwv1,bsize/512);
987 SSVAL(outbuf,smb_vwv2,512);
988 SSVAL(outbuf,smb_vwv3,dfree);
990 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
996 /****************************************************************************
998 Can be called from SMBsearch, SMBffirst or SMBfunique.
999 ****************************************************************************/
1000 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1011 BOOL finished = False;
1020 BOOL check_descend = False;
1021 BOOL expect_close = False;
1022 BOOL can_open = True;
1023 BOOL bad_path = False;
1025 *mask = *directory = *fname = 0;
1027 /* If we were called as SMBffirst then we must expect close. */
1028 if(CVAL(inbuf,smb_com) == SMBffirst)
1029 expect_close = True;
1031 outsize = set_message(outbuf,1,3,True);
1032 maxentries = SVAL(inbuf,smb_vwv0);
1033 dirtype = SVAL(inbuf,smb_vwv1);
1034 path = smb_buf(inbuf) + 1;
1035 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1038 /* dirtype &= ~aDIR; */
1040 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
1043 if (status_len == 0)
1047 pstrcpy(directory,smb_buf(inbuf)+1);
1048 pstrcpy(dir2,smb_buf(inbuf)+1);
1049 unix_convert(directory,conn,0,&bad_path,NULL);
1052 if (!check_name(directory,conn))
1055 p = strrchr(dir2,'/');
1067 p = strrchr(directory,'/');
1073 if (strlen(directory) == 0)
1074 pstrcpy(directory,"./");
1076 CVAL(status,0) = dirtype;
1080 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1081 memcpy(mask,status+1,11);
1083 dirtype = CVAL(status,0) & 0x1F;
1084 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1087 string_set(&conn->dirpath,dptr_path(dptr_num));
1088 if (!case_sensitive)
1092 /* turn strings of spaces into a . */
1094 trim_string(mask,NULL," ");
1095 if ((p = strrchr(mask,' ')))
1100 trim_string(mask,NULL," ");
1106 /* Convert the formatted mask. (This code lives in trans2.c) */
1114 if((skip = skip_multibyte_char( *p )) != 0 )
1120 if (*p != '?' && *p != '*' && !isdoschar(*p))
1122 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1130 if (!strchr(mask,'.') && strlen(mask)>8)
1133 fstrcpy(tmp,&mask[8]);
1139 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1143 p = smb_buf(outbuf) + 3;
1147 if (status_len == 0)
1149 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1154 if((errno == ENOENT) && bad_path)
1156 unix_ERR_class = ERRDOS;
1157 unix_ERR_code = ERRbadpath;
1159 return (UNIXERROR(ERRDOS,ERRnofids));
1161 return(ERROR(ERRDOS,ERRnofids));
1165 DEBUG(4,("dptr_num is %d\n",dptr_num));
1169 if ((dirtype&0x1F) == aVOLID)
1171 memcpy(p,status,21);
1172 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1173 dptr_fill(p+12,dptr_num);
1174 if (dptr_zero(p+12) && (status_len==0))
1178 p += DIR_STRUCT_SIZE;
1182 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1183 conn->dirpath,lp_dontdescend(SNUM(conn))));
1184 if (in_list(conn->dirpath,
1185 lp_dontdescend(SNUM(conn)),True))
1186 check_descend = True;
1188 for (i=numentries;(i<maxentries) && !finished;i++)
1191 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1194 memcpy(p,status,21);
1195 make_dir_struct(p,mask,fname,size,mode,date);
1196 dptr_fill(p+12,dptr_num);
1199 p += DIR_STRUCT_SIZE;
1208 if (numentries == 0 || !ok)
1210 CVAL(outbuf,smb_rcls) = ERRDOS;
1211 SSVAL(outbuf,smb_err,ERRnofiles);
1214 /* If we were called as SMBffirst with smb_search_id == NULL
1215 and no entries were found then return error and close dirptr
1218 if(ok && expect_close && numentries == 0 && status_len == 0)
1220 CVAL(outbuf,smb_rcls) = ERRDOS;
1221 SSVAL(outbuf,smb_err,ERRnofiles);
1222 /* Also close the dptr - we know it's gone */
1223 dptr_close(dptr_num);
1226 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1227 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1228 dptr_close(dptr_num);
1230 SSVAL(outbuf,smb_vwv0,numentries);
1231 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1232 CVAL(smb_buf(outbuf),0) = 5;
1233 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1235 if (Protocol >= PROTOCOL_NT1) {
1236 uint16 flg2 = SVAL(outbuf,smb_flg2);
1237 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1240 outsize += DIR_STRUCT_SIZE*numentries;
1241 smb_setlen(outbuf,outsize - 4);
1243 if ((! *directory) && dptr_path(dptr_num))
1244 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1246 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1247 smb_fn_name(CVAL(inbuf,smb_com)),
1248 mask, directory, dirtype, numentries, maxentries ) );
1254 /****************************************************************************
1255 reply to a fclose (stop directory search)
1256 ****************************************************************************/
1257 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1265 outsize = set_message(outbuf,1,0,True);
1266 path = smb_buf(inbuf) + 1;
1267 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1270 if (status_len == 0)
1271 return(ERROR(ERRSRV,ERRsrverror));
1273 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1275 if(dptr_fetch(status+12,&dptr_num)) {
1276 /* Close the dptr - we know it's gone */
1277 dptr_close(dptr_num);
1280 SSVAL(outbuf,smb_vwv0,0);
1282 DEBUG(3,("search close\n"));
1288 /****************************************************************************
1290 ****************************************************************************/
1292 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1302 SMB_STRUCT_STAT sbuf;
1303 BOOL bad_path = False;
1305 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1307 share_mode = SVAL(inbuf,smb_vwv0);
1309 pstrcpy(fname,smb_buf(inbuf)+1);
1310 unix_convert(fname,conn,0,&bad_path,NULL);
1314 return(ERROR(ERRSRV,ERRnofids));
1316 if (!check_name(fname,conn))
1318 if((errno == ENOENT) && bad_path)
1320 unix_ERR_class = ERRDOS;
1321 unix_ERR_code = ERRbadpath;
1324 return(UNIXERROR(ERRDOS,ERRnoaccess));
1327 unixmode = unix_mode(conn,aARCH);
1329 open_file_shared(fsp,conn,fname,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1330 unixmode, oplock_request,&rmode,NULL);
1334 if((errno == ENOENT) && bad_path)
1336 unix_ERR_class = ERRDOS;
1337 unix_ERR_code = ERRbadpath;
1340 return(UNIXERROR(ERRDOS,ERRnoaccess));
1343 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1344 close_file(fsp,False);
1345 return(ERROR(ERRDOS,ERRnoaccess));
1348 size = sbuf.st_size;
1349 fmode = dos_mode(conn,fname,&sbuf);
1350 mtime = sbuf.st_mtime;
1353 DEBUG(3,("attempt to open a directory %s\n",fname));
1354 close_file(fsp,False);
1355 return(ERROR(ERRDOS,ERRnoaccess));
1358 outsize = set_message(outbuf,7,0,True);
1359 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1360 SSVAL(outbuf,smb_vwv1,fmode);
1361 if(lp_dos_filetime_resolution(SNUM(conn)) )
1362 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1364 put_dos_date3(outbuf,smb_vwv2,mtime);
1365 SIVAL(outbuf,smb_vwv4,(uint32)size);
1366 SSVAL(outbuf,smb_vwv6,rmode);
1368 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1369 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1372 if(fsp->granted_oplock)
1373 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1378 /****************************************************************************
1379 reply to an open and X
1380 ****************************************************************************/
1381 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1384 int smb_mode = SVAL(inbuf,smb_vwv3);
1385 int smb_attr = SVAL(inbuf,smb_vwv5);
1386 /* Breakout the oplock request bits so we can set the
1387 reply bits separately. */
1388 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1389 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1390 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1392 int open_flags = SVAL(inbuf,smb_vwv2);
1393 int smb_sattr = SVAL(inbuf,smb_vwv4);
1394 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1396 int smb_ofun = SVAL(inbuf,smb_vwv8);
1399 int fmode=0,mtime=0,rmode=0;
1400 SMB_STRUCT_STAT sbuf;
1402 BOOL bad_path = False;
1405 /* If it's an IPC, pass off the pipe handler. */
1406 if (IS_IPC(conn) && lp_nt_pipe_support())
1407 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1409 /* XXXX we need to handle passed times, sattr and flags */
1411 pstrcpy(fname,smb_buf(inbuf));
1412 unix_convert(fname,conn,0,&bad_path,NULL);
1416 return(ERROR(ERRSRV,ERRnofids));
1418 if (!check_name(fname,conn))
1420 if((errno == ENOENT) && bad_path)
1422 unix_ERR_class = ERRDOS;
1423 unix_ERR_code = ERRbadpath;
1426 return(UNIXERROR(ERRDOS,ERRnoaccess));
1429 unixmode = unix_mode(conn,smb_attr | aARCH);
1431 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1432 oplock_request, &rmode,&smb_action);
1436 if((errno == ENOENT) && bad_path)
1438 unix_ERR_class = ERRDOS;
1439 unix_ERR_code = ERRbadpath;
1442 return(UNIXERROR(ERRDOS,ERRnoaccess));
1445 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1446 close_file(fsp,False);
1447 return(ERROR(ERRDOS,ERRnoaccess));
1450 size = sbuf.st_size;
1451 fmode = dos_mode(conn,fname,&sbuf);
1452 mtime = sbuf.st_mtime;
1454 close_file(fsp,False);
1455 return(ERROR(ERRDOS,ERRnoaccess));
1458 /* If the caller set the extended oplock request bit
1459 and we granted one (by whatever means) - set the
1460 correct bit for extended oplock reply.
1463 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1464 smb_action |= EXTENDED_OPLOCK_GRANTED;
1467 if(ex_oplock_request && fsp->granted_oplock) {
1468 smb_action |= EXTENDED_OPLOCK_GRANTED;
1471 /* If the caller set the core oplock request bit
1472 and we granted one (by whatever means) - set the
1473 correct bit for core oplock reply.
1476 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1477 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1480 if(core_oplock_request && fsp->granted_oplock) {
1481 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1484 set_message(outbuf,15,0,True);
1485 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1486 SSVAL(outbuf,smb_vwv3,fmode);
1487 if(lp_dos_filetime_resolution(SNUM(conn)) )
1488 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1490 put_dos_date3(outbuf,smb_vwv4,mtime);
1491 SIVAL(outbuf,smb_vwv6,(uint32)size);
1492 SSVAL(outbuf,smb_vwv8,rmode);
1493 SSVAL(outbuf,smb_vwv11,smb_action);
1495 return chain_reply(inbuf,outbuf,length,bufsize);
1499 /****************************************************************************
1500 reply to a SMBulogoffX
1501 ****************************************************************************/
1502 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1504 uint16 vuid = SVAL(inbuf,smb_uid);
1505 user_struct *vuser = get_valid_user_struct(vuid);
1508 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1511 /* in user level security we are supposed to close any files
1512 open by this user */
1513 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1514 file_close_user(vuid);
1517 invalidate_vuid(vuid);
1519 set_message(outbuf,2,0,True);
1521 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1523 return chain_reply(inbuf,outbuf,length,bufsize);
1527 /****************************************************************************
1528 reply to a mknew or a create
1529 ****************************************************************************/
1530 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1538 BOOL bad_path = False;
1540 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1542 com = SVAL(inbuf,smb_com);
1544 createmode = SVAL(inbuf,smb_vwv0);
1545 pstrcpy(fname,smb_buf(inbuf)+1);
1546 unix_convert(fname,conn,0,&bad_path,NULL);
1548 if (createmode & aVOLID)
1550 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1553 unixmode = unix_mode(conn,createmode);
1557 return(ERROR(ERRSRV,ERRnofids));
1559 if (!check_name(fname,conn))
1561 if((errno == ENOENT) && bad_path)
1563 unix_ERR_class = ERRDOS;
1564 unix_ERR_code = ERRbadpath;
1567 return(UNIXERROR(ERRDOS,ERRnoaccess));
1572 /* We should fail if file exists. */
1577 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1581 /* Open file in dos compatibility share mode. */
1582 open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1583 ofun, unixmode, oplock_request, NULL, NULL);
1587 if((errno == ENOENT) && bad_path)
1589 unix_ERR_class = ERRDOS;
1590 unix_ERR_code = ERRbadpath;
1593 return(UNIXERROR(ERRDOS,ERRnoaccess));
1596 outsize = set_message(outbuf,1,0,True);
1597 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1599 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1600 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1603 if(fsp->granted_oplock)
1604 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1606 DEBUG( 2, ( "new file %s\n", fname ) );
1607 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1608 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1614 /****************************************************************************
1615 reply to a create temporary file
1616 ****************************************************************************/
1617 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1624 BOOL bad_path = False;
1626 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1628 createmode = SVAL(inbuf,smb_vwv0);
1629 pstrcpy(fname,smb_buf(inbuf)+1);
1630 pstrcat(fname,"/TMXXXXXX");
1631 unix_convert(fname,conn,0,&bad_path,NULL);
1633 unixmode = unix_mode(conn,createmode);
1637 return(ERROR(ERRSRV,ERRnofids));
1639 if (!check_name(fname,conn))
1641 if((errno == ENOENT) && bad_path)
1643 unix_ERR_class = ERRDOS;
1644 unix_ERR_code = ERRbadpath;
1647 return(UNIXERROR(ERRDOS,ERRnoaccess));
1650 pstrcpy(fname2,(char *)mktemp(fname));
1652 /* Open file in dos compatibility share mode. */
1653 /* We should fail if file exists. */
1654 open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1655 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1659 if((errno == ENOENT) && bad_path)
1661 unix_ERR_class = ERRDOS;
1662 unix_ERR_code = ERRbadpath;
1665 return(UNIXERROR(ERRDOS,ERRnoaccess));
1668 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1669 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1670 CVAL(smb_buf(outbuf),0) = 4;
1671 pstrcpy(smb_buf(outbuf) + 1,fname2);
1673 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1674 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1677 if(fsp->granted_oplock)
1678 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1680 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1681 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1682 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1688 /*******************************************************************
1689 check if a user is allowed to delete a file
1690 ********************************************************************/
1691 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1693 SMB_STRUCT_STAT sbuf;
1696 if (!CAN_WRITE(conn)) return(False);
1698 if (dos_lstat(fname,&sbuf) != 0) return(False);
1699 fmode = dos_mode(conn,fname,&sbuf);
1700 if (fmode & aDIR) return(False);
1701 if (!lp_delete_readonly(SNUM(conn))) {
1702 if (fmode & aRONLY) return(False);
1704 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1706 if (!check_file_sharing(conn,fname,False)) return(False);
1710 /****************************************************************************
1712 ****************************************************************************/
1713 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1722 int error = ERRnoaccess;
1725 BOOL bad_path = False;
1727 *directory = *mask = 0;
1729 dirtype = SVAL(inbuf,smb_vwv0);
1731 pstrcpy(name,smb_buf(inbuf) + 1);
1733 DEBUG(3,("reply_unlink : %s\n",name));
1735 unix_convert(name,conn,0,&bad_path,NULL);
1737 p = strrchr(name,'/');
1739 pstrcpy(directory,"./");
1743 pstrcpy(directory,name);
1747 if (is_mangled(mask))
1748 check_mangled_cache( mask );
1750 has_wild = strchr(mask,'*') || strchr(mask,'?');
1753 pstrcat(directory,"/");
1754 pstrcat(directory,mask);
1755 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
1758 exists = file_exist(directory,NULL);
1760 void *dirptr = NULL;
1763 if (check_name(directory,conn))
1764 dirptr = OpenDir(conn, directory, True);
1766 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1767 the pattern matches against the long name, otherwise the short name
1768 We don't implement this yet XXXX
1775 if (strequal(mask,"????????.???"))
1778 while ((dname = ReadDirName(dirptr)))
1781 pstrcpy(fname,dname);
1783 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1785 error = ERRnoaccess;
1786 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1787 if (!can_delete(fname,conn,dirtype)) continue;
1788 if (!dos_unlink(fname)) count++;
1789 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1797 return(ERROR(ERRDOS,error));
1800 if((errno == ENOENT) && bad_path)
1802 unix_ERR_class = ERRDOS;
1803 unix_ERR_code = ERRbadpath;
1805 return(UNIXERROR(ERRDOS,error));
1809 outsize = set_message(outbuf,0,0,True);
1815 /****************************************************************************
1816 reply to a readbraw (core+ protocol)
1817 ****************************************************************************/
1818 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1820 size_t maxcount,mincount;
1823 char *header = outbuf;
1828 * Special check if an oplock break has been issued
1829 * and the readraw request croses on the wire, we must
1830 * return a zero length response here.
1833 if(global_oplock_break)
1835 _smb_setlen(header,0);
1836 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1837 DEBUG(5,("readbraw - oplock break finished\n"));
1841 fsp = file_fsp(inbuf,smb_vwv0);
1843 startpos = IVAL(inbuf,smb_vwv1);
1844 #ifdef LARGE_SMB_OFF_T
1845 if(CVAL(inbuf,smb_wct) == 10) {
1847 * This is a large offset (64 bit) read.
1849 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1851 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1852 (double)startpos ));
1853 _smb_setlen(header,0);
1854 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1858 #endif /* LARGE_SMB_OFF_T */
1859 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1860 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1862 /* ensure we don't overrun the packet size */
1863 maxcount = MIN(65535,maxcount);
1864 maxcount = MAX(mincount,maxcount);
1866 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1867 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1868 _smb_setlen(header,0);
1869 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1873 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1875 SMB_OFF_T size = fsp->size;
1876 SMB_OFF_T sizeneeded = startpos + maxcount;
1878 if (size < sizeneeded)
1881 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1883 if (!fsp->can_write)
1887 nread = MIN(maxcount,(size - startpos));
1890 if (nread < mincount)
1893 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1894 fsp->fnum, (double)startpos,
1895 maxcount, mincount, nread ) );
1899 BOOL seek_fail = False;
1901 _smb_setlen(header,nread);
1903 #if USE_READ_PREDICTION
1904 if (!fsp->can_write)
1905 predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1906 #endif /* USE_READ_PREDICTION */
1908 if ((nread-predict) > 0) {
1909 if(seek_file(fsp,startpos + predict) == -1) {
1910 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1917 ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,
1918 (SMB_OFF_T)(nread-predict),header,4+predict,
1923 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1924 fsp->fsp_name,startpos,nread,ret));
1926 #else /* UNSAFE_READRAW */
1927 ret = read_file(fsp,header+4,startpos,nread);
1928 if (ret < mincount) ret = 0;
1930 _smb_setlen(header,ret);
1931 transfer_file(0,Client,0,header,4+ret,0);
1932 #endif /* UNSAFE_READRAW */
1934 DEBUG(5,("readbraw finished\n"));
1939 /****************************************************************************
1940 reply to a lockread (core+ protocol)
1941 ****************************************************************************/
1942 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1951 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1953 CHECK_FSP(fsp,conn);
1957 numtoread = SVAL(inbuf,smb_vwv1);
1958 startpos = IVAL(inbuf,smb_vwv2);
1960 outsize = set_message(outbuf,5,3,True);
1961 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1962 data = smb_buf(outbuf) + 3;
1964 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1965 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1967 * A blocking lock was requested. Package up
1968 * this smb into a queued request and push it
1969 * onto the blocking lock queue.
1971 if(push_blocking_lock_request(inbuf, length, -1, 0))
1974 return (ERROR(eclass,ecode));
1977 nread = read_file(fsp,data,startpos,numtoread);
1980 return(UNIXERROR(ERRDOS,ERRnoaccess));
1983 SSVAL(outbuf,smb_vwv0,nread);
1984 SSVAL(outbuf,smb_vwv5,nread+3);
1985 SSVAL(smb_buf(outbuf),1,nread);
1987 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1988 fsp->fnum, numtoread, nread ) );
1994 /****************************************************************************
1996 ****************************************************************************/
1997 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2004 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2006 CHECK_FSP(fsp,conn);
2010 numtoread = SVAL(inbuf,smb_vwv1);
2011 startpos = IVAL(inbuf,smb_vwv2);
2013 outsize = set_message(outbuf,5,3,True);
2014 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2015 data = smb_buf(outbuf) + 3;
2017 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2018 return(ERROR(ERRDOS,ERRlock));
2021 nread = read_file(fsp,data,startpos,numtoread);
2024 return(UNIXERROR(ERRDOS,ERRnoaccess));
2027 SSVAL(outbuf,smb_vwv0,nread);
2028 SSVAL(outbuf,smb_vwv5,nread+3);
2029 CVAL(smb_buf(outbuf),0) = 1;
2030 SSVAL(smb_buf(outbuf),1,nread);
2032 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2033 fsp->fnum, numtoread, nread ) );
2039 /****************************************************************************
2040 reply to a read and X
2041 ****************************************************************************/
2042 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2044 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2045 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2046 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2047 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2051 /* If it's an IPC, pass off the pipe handler. */
2053 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2055 CHECK_FSP(fsp,conn);
2059 set_message(outbuf,12,0,True);
2060 data = smb_buf(outbuf);
2062 #ifdef LARGE_SMB_OFF_T
2063 if(CVAL(inbuf,smb_wct) == 12) {
2065 * This is a large offset (64 bit) read.
2067 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2069 #endif /* LARGE_SMB_OFF_T */
2071 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2072 return(ERROR(ERRDOS,ERRlock));
2073 nread = read_file(fsp,data,startpos,smb_maxcnt);
2076 return(UNIXERROR(ERRDOS,ERRnoaccess));
2078 SSVAL(outbuf,smb_vwv5,nread);
2079 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2080 SSVAL(smb_buf(outbuf),-2,nread);
2082 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2083 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2085 return chain_reply(inbuf,outbuf,length,bufsize);
2088 /****************************************************************************
2089 reply to a writebraw (core+ or LANMAN1.0 protocol)
2090 ****************************************************************************/
2091 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2094 ssize_t total_written=0;
2095 size_t numtowrite=0;
2100 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2103 CHECK_FSP(fsp,conn);
2107 tcount = IVAL(inbuf,smb_vwv1);
2108 startpos = IVAL(inbuf,smb_vwv3);
2109 write_through = BITSETW(inbuf+smb_vwv7,0);
2111 /* We have to deal with slightly different formats depending
2112 on whether we are using the core+ or lanman1.0 protocol */
2113 if(Protocol <= PROTOCOL_COREPLUS) {
2114 numtowrite = SVAL(smb_buf(inbuf),-2);
2115 data = smb_buf(inbuf);
2117 numtowrite = SVAL(inbuf,smb_vwv10);
2118 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2121 /* force the error type */
2122 CVAL(inbuf,smb_com) = SMBwritec;
2123 CVAL(outbuf,smb_com) = SMBwritec;
2125 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2126 return(ERROR(ERRDOS,ERRlock));
2128 if (seek_file(fsp,startpos) == -1) {
2129 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2130 return(UNIXERROR(ERRDOS,ERRnoaccess));
2134 nwritten = write_file(fsp,data,numtowrite);
2136 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2137 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2139 if (nwritten < numtowrite)
2140 return(UNIXERROR(ERRHRD,ERRdiskfull));
2142 total_written = nwritten;
2144 /* Return a message to the redirector to tell it
2145 to send more bytes */
2146 CVAL(outbuf,smb_com) = SMBwritebraw;
2147 SSVALS(outbuf,smb_vwv0,-1);
2148 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2149 send_smb(Client,outbuf);
2151 /* Now read the raw data into the buffer and write it */
2152 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2153 exit_server("secondary writebraw failed");
2156 /* Even though this is not an smb message, smb_len
2157 returns the generic length of an smb message */
2158 numtowrite = smb_len(inbuf);
2160 if (tcount > nwritten+numtowrite) {
2161 DEBUG(3,("Client overestimated the write %d %d %d\n",
2162 tcount,nwritten,numtowrite));
2165 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2167 total_written += nwritten;
2169 /* Set up outbuf to return the correct return */
2170 outsize = set_message(outbuf,1,0,True);
2171 CVAL(outbuf,smb_com) = SMBwritec;
2172 SSVAL(outbuf,smb_vwv0,total_written);
2174 if (nwritten < (ssize_t)numtowrite) {
2175 CVAL(outbuf,smb_rcls) = ERRHRD;
2176 SSVAL(outbuf,smb_err,ERRdiskfull);
2179 if (lp_syncalways(SNUM(conn)) || write_through)
2180 sync_file(conn,fsp);
2182 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2183 fsp->fnum, (double)startpos, numtowrite, total_written));
2185 /* we won't return a status if write through is not selected - this
2186 follows what WfWg does */
2187 if (!write_through && total_written==tcount)
2193 /****************************************************************************
2194 reply to a writeunlock (core+)
2195 ****************************************************************************/
2196 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2198 ssize_t nwritten = -1;
2204 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2207 CHECK_FSP(fsp,conn);
2211 numtowrite = SVAL(inbuf,smb_vwv1);
2212 startpos = IVAL(inbuf,smb_vwv2);
2213 data = smb_buf(inbuf) + 3;
2215 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2216 return(ERROR(ERRDOS,ERRlock));
2218 if(seek_file(fsp,startpos) == -1)
2219 return(UNIXERROR(ERRDOS,ERRnoaccess));
2221 /* The special X/Open SMB protocol handling of
2222 zero length writes is *NOT* done for
2227 nwritten = write_file(fsp,data,numtowrite);
2229 if (lp_syncalways(SNUM(conn)))
2230 sync_file(conn,fsp);
2232 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2233 return(UNIXERROR(ERRDOS,ERRnoaccess));
2235 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2236 return(ERROR(eclass,ecode));
2238 outsize = set_message(outbuf,1,0,True);
2240 SSVAL(outbuf,smb_vwv0,nwritten);
2242 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2243 fsp->fnum, numtowrite, nwritten ) );
2248 /****************************************************************************
2250 ****************************************************************************/
2251 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2254 ssize_t nwritten = -1;
2257 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2260 CHECK_FSP(fsp,conn);
2264 numtowrite = SVAL(inbuf,smb_vwv1);
2265 startpos = IVAL(inbuf,smb_vwv2);
2266 data = smb_buf(inbuf) + 3;
2268 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2269 return(ERROR(ERRDOS,ERRlock));
2271 if(seek_file(fsp,startpos) == -1)
2272 return(UNIXERROR(ERRDOS,ERRnoaccess));
2274 /* X/Open SMB protocol says that if smb_vwv1 is
2275 zero then the file size should be extended or
2276 truncated to the size given in smb_vwv[2-3] */
2278 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2280 nwritten = write_file(fsp,data,numtowrite);
2282 if (lp_syncalways(SNUM(conn)))
2283 sync_file(conn,fsp);
2285 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2286 return(UNIXERROR(ERRDOS,ERRnoaccess));
2288 outsize = set_message(outbuf,1,0,True);
2290 SSVAL(outbuf,smb_vwv0,nwritten);
2292 if (nwritten < (ssize_t)numtowrite) {
2293 CVAL(outbuf,smb_rcls) = ERRHRD;
2294 SSVAL(outbuf,smb_err,ERRdiskfull);
2297 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2298 fsp->fnum, numtowrite, nwritten));
2304 /****************************************************************************
2305 reply to a write and X
2306 ****************************************************************************/
2307 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2309 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2310 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2311 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2312 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2313 ssize_t nwritten = -1;
2314 int smb_doff = SVAL(inbuf,smb_vwv11);
2317 /* If it's an IPC, pass off the pipe handler. */
2319 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2321 CHECK_FSP(fsp,conn);
2325 data = smb_base(inbuf) + smb_doff;
2327 #ifdef LARGE_SMB_OFF_T
2328 if(CVAL(inbuf,smb_wct) == 14) {
2330 * This is a large offset (64 bit) write.
2332 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2334 #endif /* LARGE_SMB_OFF_T */
2336 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2337 return(ERROR(ERRDOS,ERRlock));
2339 if(seek_file(fsp,startpos) == -1)
2340 return(UNIXERROR(ERRDOS,ERRnoaccess));
2342 /* X/Open SMB protocol says that, unlike SMBwrite
2343 if the length is zero then NO truncation is
2344 done, just a write of zero. To truncate a file,
2349 nwritten = write_file(fsp,data,numtowrite);
2351 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2352 return(UNIXERROR(ERRDOS,ERRnoaccess));
2354 set_message(outbuf,6,0,True);
2356 SSVAL(outbuf,smb_vwv2,nwritten);
2358 if (nwritten < (ssize_t)numtowrite) {
2359 CVAL(outbuf,smb_rcls) = ERRHRD;
2360 SSVAL(outbuf,smb_err,ERRdiskfull);
2363 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2364 fsp->fnum, numtowrite, nwritten));
2366 if (lp_syncalways(SNUM(conn)) || write_through)
2367 sync_file(conn,fsp);
2369 return chain_reply(inbuf,outbuf,length,bufsize);
2373 /****************************************************************************
2375 ****************************************************************************/
2376 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2382 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2384 CHECK_FSP(fsp,conn);
2387 mode = SVAL(inbuf,smb_vwv1) & 3;
2388 startpos = IVAL(inbuf,smb_vwv2);
2392 case 0: umode = SEEK_SET; break;
2393 case 1: umode = SEEK_CUR; break;
2394 case 2: umode = SEEK_END; break;
2396 umode = SEEK_SET; break;
2399 if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2400 return(UNIXERROR(ERRDOS,ERRnoaccess));
2404 outsize = set_message(outbuf,2,0,True);
2405 SIVALS(outbuf,smb_vwv0,res);
2407 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2408 fsp->fnum, (double)startpos, mode));
2413 /****************************************************************************
2415 ****************************************************************************/
2416 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2418 int outsize = set_message(outbuf,0,0,True);
2419 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2422 CHECK_FSP(fsp,conn);
2427 file_sync_all(conn);
2429 sync_file(conn,fsp);
2432 DEBUG(3,("flush\n"));
2437 /****************************************************************************
2439 ****************************************************************************/
2440 int reply_exit(connection_struct *conn,
2441 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2443 int outsize = set_message(outbuf,0,0,True);
2444 DEBUG(3,("exit\n"));
2450 /****************************************************************************
2451 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2452 ****************************************************************************/
2453 int reply_close(connection_struct *conn,
2454 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2458 int32 eclass = 0, err = 0;
2459 files_struct *fsp = NULL;
2461 outsize = set_message(outbuf,0,0,True);
2463 /* If it's an IPC, pass off to the pipe handler. */
2465 return reply_pipe_close(conn, inbuf,outbuf);
2468 fsp = file_fsp(inbuf,smb_vwv0);
2471 * We can only use CHECK_FSP if we know it's not a directory.
2474 if(!fsp || !fsp->open || (fsp->conn != conn))
2475 return(ERROR(ERRDOS,ERRbadfid));
2477 if(HAS_CACHED_ERROR(fsp)) {
2478 eclass = fsp->wbmpx_ptr->wr_errclass;
2479 err = fsp->wbmpx_ptr->wr_error;
2482 if(fsp->is_directory) {
2484 * Special case - close NT SMB directory
2487 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2488 close_directory(fsp);
2491 * Close ordinary file.
2493 mtime = make_unix_date3(inbuf+smb_vwv1);
2495 /* try and set the date */
2496 set_filetime(conn, fsp->fsp_name,mtime);
2498 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2499 fsp->fd_ptr->fd, fsp->fnum,
2500 conn->num_files_open));
2502 close_file(fsp,True);
2505 /* We have a cached error */
2507 return(ERROR(eclass,err));
2513 /****************************************************************************
2514 reply to a writeclose (Core+ protocol)
2515 ****************************************************************************/
2516 int reply_writeclose(connection_struct *conn,
2517 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2520 ssize_t nwritten = -1;
2525 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2527 CHECK_FSP(fsp,conn);
2531 numtowrite = SVAL(inbuf,smb_vwv1);
2532 startpos = IVAL(inbuf,smb_vwv2);
2533 mtime = make_unix_date3(inbuf+smb_vwv4);
2534 data = smb_buf(inbuf) + 1;
2536 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2537 return(ERROR(ERRDOS,ERRlock));
2539 if(seek_file(fsp,startpos) == -1)
2540 return(UNIXERROR(ERRDOS,ERRnoaccess));
2542 nwritten = write_file(fsp,data,numtowrite);
2544 set_filetime(conn, fsp->fsp_name,mtime);
2546 close_file(fsp,True);
2548 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2549 fsp->fnum, numtowrite, nwritten,
2550 conn->num_files_open));
2553 return(UNIXERROR(ERRDOS,ERRnoaccess));
2555 outsize = set_message(outbuf,1,0,True);
2557 SSVAL(outbuf,smb_vwv0,nwritten);
2562 /****************************************************************************
2564 ****************************************************************************/
2565 int reply_lock(connection_struct *conn,
2566 char *inbuf,char *outbuf, int length, int dum_buffsize)
2568 int outsize = set_message(outbuf,0,0,True);
2569 SMB_OFF_T count,offset;
2572 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2574 CHECK_FSP(fsp,conn);
2577 count = IVAL(inbuf,smb_vwv1);
2578 offset = IVAL(inbuf,smb_vwv3);
2580 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2581 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2583 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2584 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2586 * A blocking lock was requested. Package up
2587 * this smb into a queued request and push it
2588 * onto the blocking lock queue.
2590 if(push_blocking_lock_request(inbuf, length, -1, 0))
2593 return (ERROR(eclass,ecode));
2600 /****************************************************************************
2602 ****************************************************************************/
2603 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2605 int outsize = set_message(outbuf,0,0,True);
2606 SMB_OFF_T count,offset;
2609 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2611 CHECK_FSP(fsp,conn);
2614 count = IVAL(inbuf,smb_vwv1);
2615 offset = IVAL(inbuf,smb_vwv3);
2617 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2618 return (ERROR(eclass,ecode));
2620 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2621 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2627 /****************************************************************************
2629 ****************************************************************************/
2630 int reply_tdis(connection_struct *conn,
2631 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2633 int outsize = set_message(outbuf,0,0,True);
2636 vuid = SVAL(inbuf,smb_uid);
2639 DEBUG(4,("Invalid connection in tdis\n"));
2640 return(ERROR(ERRSRV,ERRinvnid));
2645 close_cnum(conn,vuid);
2652 /****************************************************************************
2654 ****************************************************************************/
2655 int reply_echo(connection_struct *conn,
2656 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2658 int smb_reverb = SVAL(inbuf,smb_vwv0);
2660 int data_len = smb_buflen(inbuf);
2661 int outsize = set_message(outbuf,1,data_len,True);
2663 /* copy any incoming data back out */
2665 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2667 if (smb_reverb > 100) {
2668 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2672 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2673 SSVAL(outbuf,smb_vwv0,seq_num);
2675 smb_setlen(outbuf,outsize - 4);
2677 send_smb(Client,outbuf);
2680 DEBUG(3,("echo %d times\n", smb_reverb));
2686 /****************************************************************************
2687 reply to a printopen
2688 ****************************************************************************/
2689 int reply_printopen(connection_struct *conn,
2690 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2697 *fname = *fname2 = 0;
2699 if (!CAN_PRINT(conn))
2700 return(ERROR(ERRDOS,ERRnoaccess));
2705 pstrcpy(s,smb_buf(inbuf)+1);
2708 if (!(isalnum((int)*p) || strchr("._-",*p)))
2713 if (strlen(s) > 10) s[10] = 0;
2715 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2720 return(ERROR(ERRSRV,ERRnofids));
2722 pstrcpy(fname2,(char *)mktemp(fname));
2724 if (!check_name(fname2,conn)) {
2726 return(ERROR(ERRDOS,ERRnoaccess));
2729 /* Open for exclusive use, write only. */
2730 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2731 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2735 return(UNIXERROR(ERRDOS,ERRnoaccess));
2738 /* force it to be a print file */
2739 fsp->print_file = True;
2741 outsize = set_message(outbuf,1,0,True);
2742 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2744 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2745 fname2, fsp->fd_ptr->fd, fsp->fnum));
2751 /****************************************************************************
2752 reply to a printclose
2753 ****************************************************************************/
2754 int reply_printclose(connection_struct *conn,
2755 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2757 int outsize = set_message(outbuf,0,0,True);
2758 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2760 CHECK_FSP(fsp,conn);
2763 if (!CAN_PRINT(conn))
2764 return(ERROR(ERRDOS,ERRnoaccess));
2766 DEBUG(3,("printclose fd=%d fnum=%d\n",
2767 fsp->fd_ptr->fd,fsp->fnum));
2769 close_file(fsp,True);
2775 /****************************************************************************
2776 reply to a printqueue
2777 ****************************************************************************/
2778 int reply_printqueue(connection_struct *conn,
2779 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2781 int outsize = set_message(outbuf,2,3,True);
2782 int max_count = SVAL(inbuf,smb_vwv0);
2783 int start_index = SVAL(inbuf,smb_vwv1);
2785 /* we used to allow the client to get the cnum wrong, but that
2786 is really quite gross and only worked when there was only
2787 one printer - I think we should now only accept it if they
2788 get it right (tridge) */
2789 if (!CAN_PRINT(conn))
2790 return(ERROR(ERRDOS,ERRnoaccess));
2792 SSVAL(outbuf,smb_vwv0,0);
2793 SSVAL(outbuf,smb_vwv1,0);
2794 CVAL(smb_buf(outbuf),0) = 1;
2795 SSVAL(smb_buf(outbuf),1,0);
2797 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2798 start_index, max_count));
2801 print_queue_struct *queue = NULL;
2802 char *p = smb_buf(outbuf) + 3;
2803 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2804 int num_to_get = ABS(max_count);
2805 int first = (max_count>0?start_index:start_index+max_count+1);
2811 num_to_get = MIN(num_to_get,count-first);
2814 for (i=first;i<first+num_to_get;i++) {
2815 put_dos_date2(p,0,queue[i].time);
2816 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2817 SSVAL(p,5,printjob_encode(SNUM(conn),
2819 SIVAL(p,7,queue[i].size);
2821 StrnCpy(p+12,queue[i].user,16);
2826 outsize = set_message(outbuf,2,28*count+3,False);
2827 SSVAL(outbuf,smb_vwv0,count);
2828 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2829 CVAL(smb_buf(outbuf),0) = 1;
2830 SSVAL(smb_buf(outbuf),1,28*count);
2833 if (queue) free(queue);
2835 DEBUG(3,("%d entries returned in queue\n",count));
2842 /****************************************************************************
2843 reply to a printwrite
2844 ****************************************************************************/
2845 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2848 int outsize = set_message(outbuf,0,0,True);
2850 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2852 if (!CAN_PRINT(conn))
2853 return(ERROR(ERRDOS,ERRnoaccess));
2855 CHECK_FSP(fsp,conn);
2859 numtowrite = SVAL(smb_buf(inbuf),1);
2860 data = smb_buf(inbuf) + 3;
2862 if (write_file(fsp,data,numtowrite) != numtowrite)
2863 return(UNIXERROR(ERRDOS,ERRnoaccess));
2865 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2871 /****************************************************************************
2873 ****************************************************************************/
2874 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2877 int outsize,ret= -1;
2878 BOOL bad_path = False;
2880 pstrcpy(directory,smb_buf(inbuf) + 1);
2881 unix_convert(directory,conn,0,&bad_path,NULL);
2883 if (check_name(directory, conn))
2884 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2888 if((errno == ENOENT) && bad_path)
2890 unix_ERR_class = ERRDOS;
2891 unix_ERR_code = ERRbadpath;
2893 return(UNIXERROR(ERRDOS,ERRnoaccess));
2896 outsize = set_message(outbuf,0,0,True);
2898 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2903 /****************************************************************************
2904 Static function used by reply_rmdir to delete an entire directory
2906 ****************************************************************************/
2907 static BOOL recursive_rmdir(char *directory)
2911 void *dirptr = OpenDir(NULL, directory, False);
2916 while((dname = ReadDirName(dirptr)))
2921 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2924 /* Construct the full name. */
2925 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2931 pstrcpy(fullname, directory);
2932 pstrcat(fullname, "/");
2933 pstrcat(fullname, dname);
2935 if(dos_lstat(fullname, &st) != 0)
2941 if(st.st_mode & S_IFDIR)
2943 if(recursive_rmdir(fullname)!=0)
2948 if(dos_rmdir(fullname) != 0)
2954 else if(dos_unlink(fullname) != 0)
2964 /****************************************************************************
2966 ****************************************************************************/
2967 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2972 BOOL bad_path = False;
2974 pstrcpy(directory,smb_buf(inbuf) + 1);
2975 unix_convert(directory,conn, NULL,&bad_path,NULL);
2977 if (check_name(directory,conn))
2980 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2981 ok = (dos_rmdir(directory) == 0);
2982 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
2984 /* Check to see if the only thing in this directory are
2985 vetoed files/directories. If so then delete them and
2986 retry. If we fail to delete any of them (and we *don't*
2987 do a recursive delete) then fail the rmdir. */
2988 BOOL all_veto_files = True;
2990 void *dirptr = OpenDir(conn, directory, False);
2994 int dirpos = TellDir(dirptr);
2995 while ((dname = ReadDirName(dirptr)))
2997 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2999 if(!IS_VETO_PATH(conn, dname))
3001 all_veto_files = False;
3007 SeekDir(dirptr,dirpos);
3008 while ((dname = ReadDirName(dirptr)))
3013 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3016 /* Construct the full name. */
3017 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3022 pstrcpy(fullname, directory);
3023 pstrcat(fullname, "/");
3024 pstrcat(fullname, dname);
3026 if(dos_lstat(fullname, &st) != 0)
3028 if(st.st_mode & S_IFDIR)
3030 if(lp_recursive_veto_delete(SNUM(conn)))
3032 if(recursive_rmdir(fullname) != 0)
3035 if(dos_rmdir(fullname) != 0)
3038 else if(dos_unlink(fullname) != 0)
3042 /* Retry the rmdir */
3043 ok = (dos_rmdir(directory) == 0);
3053 DEBUG(3,("couldn't remove directory %s : %s\n",
3054 directory,strerror(errno)));
3059 if((errno == ENOENT) && bad_path)
3061 unix_ERR_class = ERRDOS;
3062 unix_ERR_code = ERRbadpath;
3064 return(UNIXERROR(ERRDOS,ERRbadpath));
3067 outsize = set_message(outbuf,0,0,True);
3069 DEBUG( 3, ( "rmdir %s\n", directory ) );
3075 /*******************************************************************
3076 resolve wildcards in a filename rename
3077 ********************************************************************/
3078 static BOOL resolve_wildcards(char *name1,char *name2)
3080 fstring root1,root2;
3084 name1 = strrchr(name1,'/');
3085 name2 = strrchr(name2,'/');
3087 if (!name1 || !name2) return(False);
3089 fstrcpy(root1,name1);
3090 fstrcpy(root2,name2);
3091 p = strrchr(root1,'.');
3098 p = strrchr(root2,'.');
3130 pstrcpy(name2,root2);
3133 pstrcat(name2,ext2);
3139 /*******************************************************************
3140 check if a user is allowed to rename a file
3141 ********************************************************************/
3142 static BOOL can_rename(char *fname,connection_struct *conn)
3144 SMB_STRUCT_STAT sbuf;
3146 if (!CAN_WRITE(conn)) return(False);
3148 if (dos_lstat(fname,&sbuf) != 0) return(False);
3149 if (!check_file_sharing(conn,fname,True)) return(False);
3154 /****************************************************************************
3155 The guts of the rename command, split out so it may be called by the NT SMB
3157 ****************************************************************************/
3158 int rename_internals(connection_struct *conn,
3159 char *inbuf, char *outbuf, char *name,
3160 char *newname, BOOL replace_if_exists)
3164 pstring newname_last_component;
3167 BOOL bad_path1 = False;
3168 BOOL bad_path2 = False;
3170 int error = ERRnoaccess;
3173 *directory = *mask = 0;
3175 unix_convert(name,conn,0,&bad_path1,NULL);
3176 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3179 * Split the old name into directory and last component
3180 * strings. Note that unix_convert may have stripped off a
3181 * leading ./ from both name and newname if the rename is
3182 * at the root of the share. We need to make sure either both
3183 * name and newname contain a / character or neither of them do
3184 * as this is checked in resolve_wildcards().
3187 p = strrchr(name,'/');
3189 pstrcpy(directory,".");
3193 pstrcpy(directory,name);
3195 *p = '/'; /* Replace needed for exceptional test below. */
3198 if (is_mangled(mask))
3199 check_mangled_cache( mask );
3201 has_wild = strchr(mask,'*') || strchr(mask,'?');
3205 * No wildcards - just process the one file.
3207 BOOL is_short_name = is_8_3(name, True);
3209 /* Add a terminating '/' to the directory name. */
3210 pstrcat(directory,"/");
3211 pstrcat(directory,mask);
3213 /* Ensure newname contains a '/' also */
3214 if(strrchr(newname,'/') == 0) {
3217 pstrcpy(tmpstr, "./");
3218 pstrcat(tmpstr, newname);
3219 pstrcpy(newname, tmpstr);
3222 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",
3223 case_sensitive, case_preserve, short_case_preserve, directory,
3224 newname, newname_last_component, is_short_name));
3227 * Check for special case with case preserving and not
3228 * case sensitive, if directory and newname are identical,
3229 * and the old last component differs from the original
3230 * last component only by case, then we should allow
3231 * the rename (user is trying to change the case of the
3234 if((case_sensitive == False) &&
3235 (((case_preserve == True) &&
3236 (is_short_name == False)) ||
3237 ((short_case_preserve == True) &&
3238 (is_short_name == True))) &&
3239 strcsequal(directory, newname)) {
3240 pstring newname_modified_last_component;
3243 * Get the last component of the modified name.
3244 * Note that we guarantee that newname contains a '/'
3247 p = strrchr(newname,'/');
3248 pstrcpy(newname_modified_last_component,p+1);
3250 if(strcsequal(newname_modified_last_component,
3251 newname_last_component) == False) {
3253 * Replace the modified last component with
3256 pstrcpy(p+1, newname_last_component);
3260 if(replace_if_exists) {
3262 * NT SMB specific flag - rename can overwrite
3263 * file with the same name so don't check for
3266 if(resolve_wildcards(directory,newname) &&
3267 can_rename(directory,conn) &&
3268 !dos_rename(directory,newname))
3271 if (resolve_wildcards(directory,newname) &&
3272 can_rename(directory,conn) &&
3273 !file_exist(newname,NULL) &&
3274 !dos_rename(directory,newname))
3278 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3279 directory,newname));
3281 if (!count) exists = file_exist(directory,NULL);
3282 if (!count && exists && file_exist(newname,NULL)) {
3288 * Wildcards - process each file that matches.
3290 void *dirptr = NULL;
3294 if (check_name(directory,conn))
3295 dirptr = OpenDir(conn, directory, True);
3300 if (strequal(mask,"????????.???"))
3303 while ((dname = ReadDirName(dirptr))) {
3305 pstrcpy(fname,dname);
3307 if(!mask_match(fname, mask, case_sensitive, False))
3310 error = ERRnoaccess;
3311 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3312 if (!can_rename(fname,conn)) {
3313 DEBUG(6,("rename %s refused\n", fname));
3316 pstrcpy(destname,newname);
3318 if (!resolve_wildcards(fname,destname)) {
3319 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3323 if (!replace_if_exists && file_exist(destname,NULL)) {
3324 DEBUG(6,("file_exist %s\n", destname));
3329 if (!dos_rename(fname,destname))
3331 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3339 return(ERROR(ERRDOS,error));
3341 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3342 unix_ERR_class = ERRDOS;
3343 unix_ERR_code = ERRbadpath;
3345 return(UNIXERROR(ERRDOS,error));
3352 /****************************************************************************
3354 ****************************************************************************/
3356 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3362 pstrcpy(name,smb_buf(inbuf) + 1);
3363 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3365 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3367 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3369 outsize = set_message(outbuf,0,0,True);
3374 /*******************************************************************
3375 copy a file as part of a reply_copy
3376 ******************************************************************/
3378 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3379 int count,BOOL target_is_directory)
3384 files_struct *fsp1,*fsp2;
3387 pstrcpy(dest,dest1);
3388 if (target_is_directory) {
3389 char *p = strrchr(src,'/');
3398 if (!file_exist(src,&st))
3405 open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3406 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3413 if (!target_is_directory && count)
3418 close_file(fsp1,False);
3421 open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3422 ofun,st.st_mode,0,&Access,&action);
3425 close_file(fsp1,False);
3430 if ((ofun&3) == 1) {
3431 if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3432 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3435 * Stop the copy from occurring.
3443 ret = transfer_file(fsp1->fd_ptr->fd,
3444 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3446 close_file(fsp1,False);
3447 close_file(fsp2,False);
3449 return(ret == st.st_size);
3454 /****************************************************************************
3455 reply to a file copy.
3456 ****************************************************************************/
3457 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3462 pstring mask,newname;
3465 int error = ERRnoaccess;
3468 int tid2 = SVAL(inbuf,smb_vwv0);
3469 int ofun = SVAL(inbuf,smb_vwv1);
3470 int flags = SVAL(inbuf,smb_vwv2);
3471 BOOL target_is_directory=False;
3472 BOOL bad_path1 = False;
3473 BOOL bad_path2 = False;
3475 *directory = *mask = 0;
3477 pstrcpy(name,smb_buf(inbuf));
3478 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3480 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3482 if (tid2 != conn->cnum) {
3483 /* can't currently handle inter share copies XXXX */
3484 DEBUG(3,("Rejecting inter-share copy\n"));
3485 return(ERROR(ERRSRV,ERRinvdevice));
3488 unix_convert(name,conn,0,&bad_path1,NULL);
3489 unix_convert(newname,conn,0,&bad_path2,NULL);
3491 target_is_directory = directory_exist(newname,NULL);
3493 if ((flags&1) && target_is_directory) {
3494 return(ERROR(ERRDOS,ERRbadfile));
3497 if ((flags&2) && !target_is_directory) {
3498 return(ERROR(ERRDOS,ERRbadpath));
3501 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3502 /* wants a tree copy! XXXX */
3503 DEBUG(3,("Rejecting tree copy\n"));
3504 return(ERROR(ERRSRV,ERRerror));
3507 p = strrchr(name,'/');
3509 pstrcpy(directory,"./");
3513 pstrcpy(directory,name);
3517 if (is_mangled(mask))
3518 check_mangled_cache( mask );
3520 has_wild = strchr(mask,'*') || strchr(mask,'?');
3523 pstrcat(directory,"/");
3524 pstrcat(directory,mask);
3525 if (resolve_wildcards(directory,newname) &&
3526 copy_file(directory,newname,conn,ofun,
3527 count,target_is_directory)) count++;
3528 if (!count) exists = file_exist(directory,NULL);
3530 void *dirptr = NULL;
3534 if (check_name(directory,conn))
3535 dirptr = OpenDir(conn, directory, True);
3541 if (strequal(mask,"????????.???"))
3544 while ((dname = ReadDirName(dirptr)))
3547 pstrcpy(fname,dname);
3549 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3551 error = ERRnoaccess;
3552 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3553 pstrcpy(destname,newname);
3554 if (resolve_wildcards(fname,destname) &&
3555 copy_file(directory,newname,conn,ofun,
3556 count,target_is_directory)) count++;
3557 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3565 return(ERROR(ERRDOS,error));
3568 if((errno == ENOENT) && (bad_path1 || bad_path2))
3570 unix_ERR_class = ERRDOS;
3571 unix_ERR_code = ERRbadpath;
3573 return(UNIXERROR(ERRDOS,error));
3577 outsize = set_message(outbuf,1,0,True);
3578 SSVAL(outbuf,smb_vwv0,count);
3583 /****************************************************************************
3585 ****************************************************************************/
3586 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3594 if (!CAN_SETDIR(snum))
3595 return(ERROR(ERRDOS,ERRnoaccess));
3597 pstrcpy(newdir,smb_buf(inbuf) + 1);
3600 if (strlen(newdir) == 0) {
3603 ok = directory_exist(newdir,NULL);
3605 string_set(&conn->connectpath,newdir);
3610 return(ERROR(ERRDOS,ERRbadpath));
3612 outsize = set_message(outbuf,0,0,True);
3613 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3615 DEBUG(3,("setdir %s\n", newdir));
3620 /****************************************************************************
3621 reply to a lockingX request
3622 ****************************************************************************/
3623 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3625 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3626 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3628 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3630 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3631 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3632 SMB_OFF_T count = 0, offset = 0;
3633 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3636 uint32 ecode=0, dummy2;
3637 int eclass=0, dummy1;
3638 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3639 CHECK_FSP(fsp,conn);
3642 data = smb_buf(inbuf);
3644 /* Check if this is an oplock break on a file
3645 we have granted an oplock on.
3647 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3650 SMB_DEV_T dev = fsp->fd_ptr->dev;
3651 SMB_INO_T inode = fsp->fd_ptr->inode;
3653 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3656 * Make sure we have granted an oplock on this file.
3658 if(!fsp->granted_oplock)
3660 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3661 no oplock granted on this file.\n", fsp->fnum));
3662 return ERROR(ERRDOS,ERRlock);
3665 /* Remove the oplock flag from the sharemode. */
3666 lock_share_entry(fsp->conn, dev, inode, &token);
3667 if(remove_share_oplock(token, fsp)==False) {
3669 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3670 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3672 unlock_share_entry(fsp->conn, dev, inode, token);
3674 unlock_share_entry(fsp->conn, dev, inode, token);
3676 /* Clear the granted flag and return. */
3677 fsp->granted_oplock = False;
3680 /* if this is a pure oplock break request then don't send a reply */
3681 if (num_locks == 0 && num_ulocks == 0)
3683 /* Sanity check - ensure a pure oplock break is not a
3685 if(CVAL(inbuf,smb_vwv0) != 0xff)
3686 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3687 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3692 /* Data now points at the beginning of the list
3693 of smb_unlkrng structs */
3694 for(i = 0; i < (int)num_ulocks; i++) {
3695 if(!large_file_format) {
3696 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3697 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3699 #ifdef LARGE_SMB_OFF_T
3701 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3702 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3703 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3704 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3706 #endif /* LARGE_SMB_OFF_T */
3708 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3709 (double)offset, (double)count, fsp->fsp_name ));
3711 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3712 return ERROR(eclass,ecode);
3715 /* Setup the timeout in seconds. */
3716 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3718 /* Now do any requested locks */
3719 data += ((large_file_format ? 20 : 10)*num_ulocks);
3721 /* Data now points at the beginning of the list
3722 of smb_lkrng structs */
3724 for(i = 0; i < (int)num_locks; i++) {
3725 if(!large_file_format) {
3726 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3727 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3729 #ifdef LARGE_SMB_OFF_T
3731 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3732 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3733 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3734 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3736 #endif /* LARGE_SMB_OFF_T */
3738 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3739 (double)offset, (double)count, fsp->fsp_name ));
3741 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3743 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3745 * A blocking lock was requested. Package up
3746 * this smb into a queued request and push it
3747 * onto the blocking lock queue.
3749 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3756 /* If any of the above locks failed, then we must unlock
3757 all of the previous locks (X/Open spec). */
3758 if(i != num_locks && num_locks != 0) {
3759 for(; i >= 0; i--) {
3760 if(!large_file_format) {
3761 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3762 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3764 #ifdef LARGE_SMB_OFF_T
3766 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3767 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3768 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3769 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3771 #endif /* LARGE_SMB_OFF_T */
3773 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3775 return ERROR(eclass,ecode);
3778 set_message(outbuf,2,0,True);
3780 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3781 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3783 return chain_reply(inbuf,outbuf,length,bufsize);
3787 /****************************************************************************
3788 reply to a SMBreadbmpx (read block multiplex) request
3789 ****************************************************************************/
3790 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3801 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3803 /* this function doesn't seem to work - disable by default */
3805 return(ERROR(ERRSRV,ERRuseSTD));
3807 outsize = set_message(outbuf,8,0,True);
3809 CHECK_FSP(fsp,conn);
3813 startpos = IVAL(inbuf,smb_vwv1);
3814 maxcount = SVAL(inbuf,smb_vwv3);
3816 data = smb_buf(outbuf);
3817 pad = ((long)data)%4;
3818 if (pad) pad = 4 - pad;
3821 max_per_packet = bufsize-(outsize+pad);
3825 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3826 return(ERROR(ERRDOS,ERRlock));
3830 size_t N = MIN(max_per_packet,tcount-total_read);
3832 nread = read_file(fsp,data,startpos,N);
3834 if (nread <= 0) nread = 0;
3836 if (nread < (ssize_t)N)
3837 tcount = total_read + nread;
3839 set_message(outbuf,8,nread,False);
3840 SIVAL(outbuf,smb_vwv0,startpos);
3841 SSVAL(outbuf,smb_vwv2,tcount);
3842 SSVAL(outbuf,smb_vwv6,nread);
3843 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3845 send_smb(Client,outbuf);
3847 total_read += nread;
3850 while (total_read < (ssize_t)tcount);
3855 /****************************************************************************
3856 reply to a SMBwritebmpx (write block multiplex primary) request
3857 ****************************************************************************/
3858 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3861 ssize_t nwritten = -1;
3868 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3870 CHECK_FSP(fsp,conn);
3874 tcount = SVAL(inbuf,smb_vwv1);
3875 startpos = IVAL(inbuf,smb_vwv3);
3876 write_through = BITSETW(inbuf+smb_vwv7,0);
3877 numtowrite = SVAL(inbuf,smb_vwv10);
3878 smb_doff = SVAL(inbuf,smb_vwv11);
3880 data = smb_base(inbuf) + smb_doff;
3882 /* If this fails we need to send an SMBwriteC response,
3883 not an SMBwritebmpx - set this up now so we don't forget */
3884 CVAL(outbuf,smb_com) = SMBwritec;
3886 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3887 return(ERROR(ERRDOS,ERRlock));
3889 if(seek_file(fsp,startpos) == -1)
3890 return(UNIXERROR(ERRDOS,ERRnoaccess));
3892 nwritten = write_file(fsp,data,numtowrite);
3894 if(lp_syncalways(SNUM(conn)) || write_through)
3895 sync_file(conn,fsp);
3897 if(nwritten < (ssize_t)numtowrite)
3898 return(UNIXERROR(ERRHRD,ERRdiskfull));
3900 /* If the maximum to be written to this file
3901 is greater than what we just wrote then set
3902 up a secondary struct to be attached to this
3903 fd, we will use this to cache error messages etc. */
3904 if((ssize_t)tcount > nwritten)
3906 write_bmpx_struct *wbms;
3907 if(fsp->wbmpx_ptr != NULL)
3908 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3910 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3913 DEBUG(0,("Out of memory in reply_readmpx\n"));
3914 return(ERROR(ERRSRV,ERRnoresource));
3916 wbms->wr_mode = write_through;
3917 wbms->wr_discard = False; /* No errors yet */
3918 wbms->wr_total_written = nwritten;
3919 wbms->wr_errclass = 0;
3921 fsp->wbmpx_ptr = wbms;
3924 /* We are returning successfully, set the message type back to
3926 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3928 outsize = set_message(outbuf,1,0,True);
3930 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3932 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3933 fsp->fnum, numtowrite, nwritten ) );
3935 if (write_through && tcount==nwritten) {
3936 /* we need to send both a primary and a secondary response */
3937 smb_setlen(outbuf,outsize - 4);
3938 send_smb(Client,outbuf);
3940 /* now the secondary */
3941 outsize = set_message(outbuf,1,0,True);
3942 CVAL(outbuf,smb_com) = SMBwritec;
3943 SSVAL(outbuf,smb_vwv0,nwritten);
3950 /****************************************************************************
3951 reply to a SMBwritebs (write block multiplex secondary) request
3952 ****************************************************************************/
3953 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3956 ssize_t nwritten = -1;
3963 write_bmpx_struct *wbms;
3964 BOOL send_response = False;
3965 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3967 CHECK_FSP(fsp,conn);
3970 tcount = SVAL(inbuf,smb_vwv1);
3971 startpos = IVAL(inbuf,smb_vwv2);
3972 numtowrite = SVAL(inbuf,smb_vwv6);
3973 smb_doff = SVAL(inbuf,smb_vwv7);
3975 data = smb_base(inbuf) + smb_doff;
3977 /* We need to send an SMBwriteC response, not an SMBwritebs */
3978 CVAL(outbuf,smb_com) = SMBwritec;
3980 /* This fd should have an auxiliary struct attached,
3981 check that it does */
3982 wbms = fsp->wbmpx_ptr;
3983 if(!wbms) return(-1);
3985 /* If write through is set we can return errors, else we must
3987 write_through = wbms->wr_mode;
3989 /* Check for an earlier error */
3990 if(wbms->wr_discard)
3991 return -1; /* Just discard the packet */
3993 if(seek_file(fsp,startpos) == -1)
3997 /* We are returning an error - we can delete the aux struct */
3998 if (wbms) free((char *)wbms);
3999 fsp->wbmpx_ptr = NULL;
4000 return(UNIXERROR(ERRDOS,ERRnoaccess));
4002 return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
4005 nwritten = write_file(fsp,data,numtowrite);
4007 if(lp_syncalways(SNUM(conn)) || write_through)
4008 sync_file(conn,fsp);
4010 if (nwritten < (ssize_t)numtowrite)
4014 /* We are returning an error - we can delete the aux struct */
4015 if (wbms) free((char *)wbms);
4016 fsp->wbmpx_ptr = NULL;
4017 return(ERROR(ERRHRD,ERRdiskfull));
4019 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4022 /* Increment the total written, if this matches tcount
4023 we can discard the auxiliary struct (hurrah !) and return a writeC */
4024 wbms->wr_total_written += nwritten;
4025 if(wbms->wr_total_written >= tcount)
4029 outsize = set_message(outbuf,1,0,True);
4030 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4031 send_response = True;
4035 fsp->wbmpx_ptr = NULL;
4045 /****************************************************************************
4046 reply to a SMBsetattrE
4047 ****************************************************************************/
4048 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4050 struct utimbuf unix_times;
4052 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4054 outsize = set_message(outbuf,0,0,True);
4056 CHECK_FSP(fsp,conn);
4059 /* Convert the DOS times into unix times. Ignore create
4060 time as UNIX can't set this.
4062 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4063 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4066 * Patch from Ray Frush <frush@engr.colostate.edu>
4067 * Sometimes times are sent as zero - ignore them.
4070 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4072 /* Ignore request */
4075 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4076 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4080 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4082 /* set modify time = to access time if modify time was 0 */
4083 unix_times.modtime = unix_times.actime;
4086 /* Set the date on this file */
4087 if(file_utime(conn, fsp->fsp_name, &unix_times))
4088 return(ERROR(ERRDOS,ERRnoaccess));
4090 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4091 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4097 /****************************************************************************
4098 reply to a SMBgetattrE
4099 ****************************************************************************/
4100 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4102 SMB_STRUCT_STAT sbuf;
4105 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4107 outsize = set_message(outbuf,11,0,True);
4109 CHECK_FSP(fsp,conn);
4112 /* Do an fstat on this file */
4113 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4114 return(UNIXERROR(ERRDOS,ERRnoaccess));
4116 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4118 /* Convert the times into dos times. Set create
4119 date to be last modify date as UNIX doesn't save
4121 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4122 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4123 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4126 SIVAL(outbuf,smb_vwv6,0);
4127 SIVAL(outbuf,smb_vwv8,0);
4131 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4132 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4134 SSVAL(outbuf,smb_vwv10, mode);
4136 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));