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() && lp_security() != SEC_SHARE)
1408 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1411 /* XXXX we need to handle passed times, sattr and flags */
1413 pstrcpy(fname,smb_buf(inbuf));
1414 unix_convert(fname,conn,0,&bad_path,NULL);
1418 return(ERROR(ERRSRV,ERRnofids));
1420 if (!check_name(fname,conn))
1422 if((errno == ENOENT) && bad_path)
1424 unix_ERR_class = ERRDOS;
1425 unix_ERR_code = ERRbadpath;
1428 return(UNIXERROR(ERRDOS,ERRnoaccess));
1431 unixmode = unix_mode(conn,smb_attr | aARCH);
1433 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1434 oplock_request, &rmode,&smb_action);
1438 if((errno == ENOENT) && bad_path)
1440 unix_ERR_class = ERRDOS;
1441 unix_ERR_code = ERRbadpath;
1444 return(UNIXERROR(ERRDOS,ERRnoaccess));
1447 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1448 close_file(fsp,False);
1449 return(ERROR(ERRDOS,ERRnoaccess));
1452 size = sbuf.st_size;
1453 fmode = dos_mode(conn,fname,&sbuf);
1454 mtime = sbuf.st_mtime;
1456 close_file(fsp,False);
1457 return(ERROR(ERRDOS,ERRnoaccess));
1460 /* If the caller set the extended oplock request bit
1461 and we granted one (by whatever means) - set the
1462 correct bit for extended oplock reply.
1465 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1466 smb_action |= EXTENDED_OPLOCK_GRANTED;
1469 if(ex_oplock_request && fsp->granted_oplock) {
1470 smb_action |= EXTENDED_OPLOCK_GRANTED;
1473 /* If the caller set the core oplock request bit
1474 and we granted one (by whatever means) - set the
1475 correct bit for core oplock reply.
1478 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1479 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1482 if(core_oplock_request && fsp->granted_oplock) {
1483 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1486 set_message(outbuf,15,0,True);
1487 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1488 SSVAL(outbuf,smb_vwv3,fmode);
1489 if(lp_dos_filetime_resolution(SNUM(conn)) )
1490 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1492 put_dos_date3(outbuf,smb_vwv4,mtime);
1493 SIVAL(outbuf,smb_vwv6,(uint32)size);
1494 SSVAL(outbuf,smb_vwv8,rmode);
1495 SSVAL(outbuf,smb_vwv11,smb_action);
1497 return chain_reply(inbuf,outbuf,length,bufsize);
1501 /****************************************************************************
1502 reply to a SMBulogoffX
1503 ****************************************************************************/
1504 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1506 uint16 vuid = SVAL(inbuf,smb_uid);
1507 user_struct *vuser = get_valid_user_struct(vuid);
1510 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1513 /* in user level security we are supposed to close any files
1514 open by this user */
1515 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1516 file_close_user(vuid);
1519 invalidate_vuid(vuid);
1521 set_message(outbuf,2,0,True);
1523 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1525 return chain_reply(inbuf,outbuf,length,bufsize);
1529 /****************************************************************************
1530 reply to a mknew or a create
1531 ****************************************************************************/
1532 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1540 BOOL bad_path = False;
1542 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1544 com = SVAL(inbuf,smb_com);
1546 createmode = SVAL(inbuf,smb_vwv0);
1547 pstrcpy(fname,smb_buf(inbuf)+1);
1548 unix_convert(fname,conn,0,&bad_path,NULL);
1550 if (createmode & aVOLID)
1552 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1555 unixmode = unix_mode(conn,createmode);
1559 return(ERROR(ERRSRV,ERRnofids));
1561 if (!check_name(fname,conn))
1563 if((errno == ENOENT) && bad_path)
1565 unix_ERR_class = ERRDOS;
1566 unix_ERR_code = ERRbadpath;
1569 return(UNIXERROR(ERRDOS,ERRnoaccess));
1574 /* We should fail if file exists. */
1579 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1583 /* Open file in dos compatibility share mode. */
1584 open_file_shared(fsp,conn,fname,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1585 ofun, unixmode, oplock_request, NULL, NULL);
1589 if((errno == ENOENT) && bad_path)
1591 unix_ERR_class = ERRDOS;
1592 unix_ERR_code = ERRbadpath;
1595 return(UNIXERROR(ERRDOS,ERRnoaccess));
1598 outsize = set_message(outbuf,1,0,True);
1599 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1601 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1602 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1605 if(fsp->granted_oplock)
1606 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1608 DEBUG( 2, ( "new file %s\n", fname ) );
1609 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1610 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1616 /****************************************************************************
1617 reply to a create temporary file
1618 ****************************************************************************/
1619 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1626 BOOL bad_path = False;
1628 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1630 createmode = SVAL(inbuf,smb_vwv0);
1631 pstrcpy(fname,smb_buf(inbuf)+1);
1632 pstrcat(fname,"/TMXXXXXX");
1633 unix_convert(fname,conn,0,&bad_path,NULL);
1635 unixmode = unix_mode(conn,createmode);
1639 return(ERROR(ERRSRV,ERRnofids));
1641 if (!check_name(fname,conn))
1643 if((errno == ENOENT) && bad_path)
1645 unix_ERR_class = ERRDOS;
1646 unix_ERR_code = ERRbadpath;
1649 return(UNIXERROR(ERRDOS,ERRnoaccess));
1652 pstrcpy(fname2,(char *)mktemp(fname));
1654 /* Open file in dos compatibility share mode. */
1655 /* We should fail if file exists. */
1656 open_file_shared(fsp,conn,fname2,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1657 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unixmode, oplock_request, NULL, NULL);
1661 if((errno == ENOENT) && bad_path)
1663 unix_ERR_class = ERRDOS;
1664 unix_ERR_code = ERRbadpath;
1667 return(UNIXERROR(ERRDOS,ERRnoaccess));
1670 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1671 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1672 CVAL(smb_buf(outbuf),0) = 4;
1673 pstrcpy(smb_buf(outbuf) + 1,fname2);
1675 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1676 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1679 if(fsp->granted_oplock)
1680 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1682 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1683 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1684 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1690 /*******************************************************************
1691 check if a user is allowed to delete a file
1692 ********************************************************************/
1693 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1695 SMB_STRUCT_STAT sbuf;
1698 if (!CAN_WRITE(conn)) return(False);
1700 if (dos_lstat(fname,&sbuf) != 0) return(False);
1701 fmode = dos_mode(conn,fname,&sbuf);
1702 if (fmode & aDIR) return(False);
1703 if (!lp_delete_readonly(SNUM(conn))) {
1704 if (fmode & aRONLY) return(False);
1706 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1708 if (!check_file_sharing(conn,fname,False)) return(False);
1712 /****************************************************************************
1714 ****************************************************************************/
1715 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1724 int error = ERRnoaccess;
1727 BOOL bad_path = False;
1729 *directory = *mask = 0;
1731 dirtype = SVAL(inbuf,smb_vwv0);
1733 pstrcpy(name,smb_buf(inbuf) + 1);
1735 DEBUG(3,("reply_unlink : %s\n",name));
1737 unix_convert(name,conn,0,&bad_path,NULL);
1739 p = strrchr(name,'/');
1741 pstrcpy(directory,"./");
1745 pstrcpy(directory,name);
1749 if (is_mangled(mask))
1750 check_mangled_cache( mask );
1752 has_wild = strchr(mask,'*') || strchr(mask,'?');
1755 pstrcat(directory,"/");
1756 pstrcat(directory,mask);
1757 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory))
1760 exists = file_exist(directory,NULL);
1762 void *dirptr = NULL;
1765 if (check_name(directory,conn))
1766 dirptr = OpenDir(conn, directory, True);
1768 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1769 the pattern matches against the long name, otherwise the short name
1770 We don't implement this yet XXXX
1777 if (strequal(mask,"????????.???"))
1780 while ((dname = ReadDirName(dirptr)))
1783 pstrcpy(fname,dname);
1785 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1787 error = ERRnoaccess;
1788 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1789 if (!can_delete(fname,conn,dirtype)) continue;
1790 if (!dos_unlink(fname)) count++;
1791 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1799 return(ERROR(ERRDOS,error));
1802 if((errno == ENOENT) && bad_path)
1804 unix_ERR_class = ERRDOS;
1805 unix_ERR_code = ERRbadpath;
1807 return(UNIXERROR(ERRDOS,error));
1811 outsize = set_message(outbuf,0,0,True);
1817 /****************************************************************************
1818 reply to a readbraw (core+ protocol)
1819 ****************************************************************************/
1820 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1822 size_t maxcount,mincount;
1825 char *header = outbuf;
1830 * Special check if an oplock break has been issued
1831 * and the readraw request croses on the wire, we must
1832 * return a zero length response here.
1835 if(global_oplock_break)
1837 _smb_setlen(header,0);
1838 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1839 DEBUG(5,("readbraw - oplock break finished\n"));
1843 fsp = file_fsp(inbuf,smb_vwv0);
1845 startpos = IVAL(inbuf,smb_vwv1);
1846 #ifdef LARGE_SMB_OFF_T
1847 if(CVAL(inbuf,smb_wct) == 10) {
1849 * This is a large offset (64 bit) read.
1851 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1853 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1854 (double)startpos ));
1855 _smb_setlen(header,0);
1856 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1860 #endif /* LARGE_SMB_OFF_T */
1861 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1862 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1864 /* ensure we don't overrun the packet size */
1865 maxcount = MIN(65535,maxcount);
1866 maxcount = MAX(mincount,maxcount);
1868 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1869 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1870 _smb_setlen(header,0);
1871 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1875 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1877 SMB_OFF_T size = fsp->size;
1878 SMB_OFF_T sizeneeded = startpos + maxcount;
1880 if (size < sizeneeded)
1883 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1885 if (!fsp->can_write)
1889 nread = MIN(maxcount,(size - startpos));
1892 if (nread < mincount)
1895 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1896 fsp->fnum, (double)startpos,
1897 maxcount, mincount, nread ) );
1901 BOOL seek_fail = False;
1903 _smb_setlen(header,nread);
1905 #if USE_READ_PREDICTION
1906 if (!fsp->can_write)
1907 predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1908 #endif /* USE_READ_PREDICTION */
1910 if ((nread-predict) > 0) {
1911 if(seek_file(fsp,startpos + predict) == -1) {
1912 DEBUG(0,("reply_readbraw: ERROR: seek_file failed.\n"));
1919 ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,
1920 (SMB_OFF_T)(nread-predict),header,4+predict,
1925 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1926 fsp->fsp_name,startpos,nread,ret));
1928 #else /* UNSAFE_READRAW */
1929 ret = read_file(fsp,header+4,startpos,nread);
1930 if (ret < mincount) ret = 0;
1932 _smb_setlen(header,ret);
1933 transfer_file(0,Client,0,header,4+ret,0);
1934 #endif /* UNSAFE_READRAW */
1936 DEBUG(5,("readbraw finished\n"));
1941 /****************************************************************************
1942 reply to a lockread (core+ protocol)
1943 ****************************************************************************/
1944 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1953 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1955 CHECK_FSP(fsp,conn);
1959 numtoread = SVAL(inbuf,smb_vwv1);
1960 startpos = IVAL(inbuf,smb_vwv2);
1962 outsize = set_message(outbuf,5,3,True);
1963 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1964 data = smb_buf(outbuf) + 3;
1966 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1967 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1969 * A blocking lock was requested. Package up
1970 * this smb into a queued request and push it
1971 * onto the blocking lock queue.
1973 if(push_blocking_lock_request(inbuf, length, -1, 0))
1976 return (ERROR(eclass,ecode));
1979 nread = read_file(fsp,data,startpos,numtoread);
1982 return(UNIXERROR(ERRDOS,ERRnoaccess));
1985 SSVAL(outbuf,smb_vwv0,nread);
1986 SSVAL(outbuf,smb_vwv5,nread+3);
1987 SSVAL(smb_buf(outbuf),1,nread);
1989 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1990 fsp->fnum, numtoread, nread ) );
1996 /****************************************************************************
1998 ****************************************************************************/
1999 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2006 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2008 CHECK_FSP(fsp,conn);
2012 numtoread = SVAL(inbuf,smb_vwv1);
2013 startpos = IVAL(inbuf,smb_vwv2);
2015 outsize = set_message(outbuf,5,3,True);
2016 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2017 data = smb_buf(outbuf) + 3;
2019 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
2020 return(ERROR(ERRDOS,ERRlock));
2023 nread = read_file(fsp,data,startpos,numtoread);
2026 return(UNIXERROR(ERRDOS,ERRnoaccess));
2029 SSVAL(outbuf,smb_vwv0,nread);
2030 SSVAL(outbuf,smb_vwv5,nread+3);
2031 CVAL(smb_buf(outbuf),0) = 1;
2032 SSVAL(smb_buf(outbuf),1,nread);
2034 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2035 fsp->fnum, numtoread, nread ) );
2041 /****************************************************************************
2042 reply to a read and X
2043 ****************************************************************************/
2044 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2046 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2047 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2048 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2049 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2053 /* If it's an IPC, pass off the pipe handler. */
2055 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2057 CHECK_FSP(fsp,conn);
2061 set_message(outbuf,12,0,True);
2062 data = smb_buf(outbuf);
2064 #ifdef LARGE_SMB_OFF_T
2065 if(CVAL(inbuf,smb_wct) == 12) {
2067 * This is a large offset (64 bit) read.
2069 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2071 #endif /* LARGE_SMB_OFF_T */
2073 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2074 return(ERROR(ERRDOS,ERRlock));
2075 nread = read_file(fsp,data,startpos,smb_maxcnt);
2078 return(UNIXERROR(ERRDOS,ERRnoaccess));
2080 SSVAL(outbuf,smb_vwv5,nread);
2081 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2082 SSVAL(smb_buf(outbuf),-2,nread);
2084 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2085 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2087 return chain_reply(inbuf,outbuf,length,bufsize);
2090 /****************************************************************************
2091 reply to a writebraw (core+ or LANMAN1.0 protocol)
2092 ****************************************************************************/
2093 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2096 ssize_t total_written=0;
2097 size_t numtowrite=0;
2102 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2105 CHECK_FSP(fsp,conn);
2109 tcount = IVAL(inbuf,smb_vwv1);
2110 startpos = IVAL(inbuf,smb_vwv3);
2111 write_through = BITSETW(inbuf+smb_vwv7,0);
2113 /* We have to deal with slightly different formats depending
2114 on whether we are using the core+ or lanman1.0 protocol */
2115 if(Protocol <= PROTOCOL_COREPLUS) {
2116 numtowrite = SVAL(smb_buf(inbuf),-2);
2117 data = smb_buf(inbuf);
2119 numtowrite = SVAL(inbuf,smb_vwv10);
2120 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2123 /* force the error type */
2124 CVAL(inbuf,smb_com) = SMBwritec;
2125 CVAL(outbuf,smb_com) = SMBwritec;
2127 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2128 return(ERROR(ERRDOS,ERRlock));
2130 if (seek_file(fsp,startpos) == -1) {
2131 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2132 return(UNIXERROR(ERRDOS,ERRnoaccess));
2136 nwritten = write_file(fsp,data,numtowrite);
2138 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2139 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2141 if (nwritten < numtowrite)
2142 return(UNIXERROR(ERRHRD,ERRdiskfull));
2144 total_written = nwritten;
2146 /* Return a message to the redirector to tell it
2147 to send more bytes */
2148 CVAL(outbuf,smb_com) = SMBwritebraw;
2149 SSVALS(outbuf,smb_vwv0,-1);
2150 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2151 send_smb(Client,outbuf);
2153 /* Now read the raw data into the buffer and write it */
2154 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2155 exit_server("secondary writebraw failed");
2158 /* Even though this is not an smb message, smb_len
2159 returns the generic length of an smb message */
2160 numtowrite = smb_len(inbuf);
2162 if (tcount > nwritten+numtowrite) {
2163 DEBUG(3,("Client overestimated the write %d %d %d\n",
2164 tcount,nwritten,numtowrite));
2167 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2169 total_written += nwritten;
2171 /* Set up outbuf to return the correct return */
2172 outsize = set_message(outbuf,1,0,True);
2173 CVAL(outbuf,smb_com) = SMBwritec;
2174 SSVAL(outbuf,smb_vwv0,total_written);
2176 if (nwritten < (ssize_t)numtowrite) {
2177 CVAL(outbuf,smb_rcls) = ERRHRD;
2178 SSVAL(outbuf,smb_err,ERRdiskfull);
2181 if (lp_syncalways(SNUM(conn)) || write_through)
2182 sync_file(conn,fsp);
2184 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2185 fsp->fnum, (double)startpos, numtowrite, total_written));
2187 /* we won't return a status if write through is not selected - this
2188 follows what WfWg does */
2189 if (!write_through && total_written==tcount)
2195 /****************************************************************************
2196 reply to a writeunlock (core+)
2197 ****************************************************************************/
2198 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2200 ssize_t nwritten = -1;
2206 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2209 CHECK_FSP(fsp,conn);
2213 numtowrite = SVAL(inbuf,smb_vwv1);
2214 startpos = IVAL(inbuf,smb_vwv2);
2215 data = smb_buf(inbuf) + 3;
2217 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2218 return(ERROR(ERRDOS,ERRlock));
2220 if(seek_file(fsp,startpos) == -1)
2221 return(UNIXERROR(ERRDOS,ERRnoaccess));
2223 /* The special X/Open SMB protocol handling of
2224 zero length writes is *NOT* done for
2229 nwritten = write_file(fsp,data,numtowrite);
2231 if (lp_syncalways(SNUM(conn)))
2232 sync_file(conn,fsp);
2234 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2235 return(UNIXERROR(ERRDOS,ERRnoaccess));
2237 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2238 return(ERROR(eclass,ecode));
2240 outsize = set_message(outbuf,1,0,True);
2242 SSVAL(outbuf,smb_vwv0,nwritten);
2244 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2245 fsp->fnum, numtowrite, nwritten ) );
2250 /****************************************************************************
2252 ****************************************************************************/
2253 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2256 ssize_t nwritten = -1;
2259 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2262 CHECK_FSP(fsp,conn);
2266 numtowrite = SVAL(inbuf,smb_vwv1);
2267 startpos = IVAL(inbuf,smb_vwv2);
2268 data = smb_buf(inbuf) + 3;
2270 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2271 return(ERROR(ERRDOS,ERRlock));
2273 if(seek_file(fsp,startpos) == -1)
2274 return(UNIXERROR(ERRDOS,ERRnoaccess));
2276 /* X/Open SMB protocol says that if smb_vwv1 is
2277 zero then the file size should be extended or
2278 truncated to the size given in smb_vwv[2-3] */
2280 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2282 nwritten = write_file(fsp,data,numtowrite);
2284 if (lp_syncalways(SNUM(conn)))
2285 sync_file(conn,fsp);
2287 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2288 return(UNIXERROR(ERRDOS,ERRnoaccess));
2290 outsize = set_message(outbuf,1,0,True);
2292 SSVAL(outbuf,smb_vwv0,nwritten);
2294 if (nwritten < (ssize_t)numtowrite) {
2295 CVAL(outbuf,smb_rcls) = ERRHRD;
2296 SSVAL(outbuf,smb_err,ERRdiskfull);
2299 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2300 fsp->fnum, numtowrite, nwritten));
2306 /****************************************************************************
2307 reply to a write and X
2308 ****************************************************************************/
2309 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2311 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2312 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2313 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2314 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2315 ssize_t nwritten = -1;
2316 int smb_doff = SVAL(inbuf,smb_vwv11);
2319 /* If it's an IPC, pass off the pipe handler. */
2321 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2323 CHECK_FSP(fsp,conn);
2327 data = smb_base(inbuf) + smb_doff;
2329 #ifdef LARGE_SMB_OFF_T
2330 if(CVAL(inbuf,smb_wct) == 14) {
2332 * This is a large offset (64 bit) write.
2334 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2336 #endif /* LARGE_SMB_OFF_T */
2338 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2339 return(ERROR(ERRDOS,ERRlock));
2341 if(seek_file(fsp,startpos) == -1)
2342 return(UNIXERROR(ERRDOS,ERRnoaccess));
2344 /* X/Open SMB protocol says that, unlike SMBwrite
2345 if the length is zero then NO truncation is
2346 done, just a write of zero. To truncate a file,
2351 nwritten = write_file(fsp,data,numtowrite);
2353 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2354 return(UNIXERROR(ERRDOS,ERRnoaccess));
2356 set_message(outbuf,6,0,True);
2358 SSVAL(outbuf,smb_vwv2,nwritten);
2360 if (nwritten < (ssize_t)numtowrite) {
2361 CVAL(outbuf,smb_rcls) = ERRHRD;
2362 SSVAL(outbuf,smb_err,ERRdiskfull);
2365 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2366 fsp->fnum, numtowrite, nwritten));
2368 if (lp_syncalways(SNUM(conn)) || write_through)
2369 sync_file(conn,fsp);
2371 return chain_reply(inbuf,outbuf,length,bufsize);
2375 /****************************************************************************
2377 ****************************************************************************/
2378 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2384 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2386 CHECK_FSP(fsp,conn);
2389 mode = SVAL(inbuf,smb_vwv1) & 3;
2390 startpos = IVAL(inbuf,smb_vwv2);
2394 case 0: umode = SEEK_SET; break;
2395 case 1: umode = SEEK_CUR; break;
2396 case 2: umode = SEEK_END; break;
2398 umode = SEEK_SET; break;
2401 if((res = sys_lseek(fsp->fd_ptr->fd,startpos,umode)) == -1)
2402 return(UNIXERROR(ERRDOS,ERRnoaccess));
2406 outsize = set_message(outbuf,2,0,True);
2407 SIVALS(outbuf,smb_vwv0,res);
2409 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2410 fsp->fnum, (double)startpos, mode));
2415 /****************************************************************************
2417 ****************************************************************************/
2418 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2420 int outsize = set_message(outbuf,0,0,True);
2421 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2424 CHECK_FSP(fsp,conn);
2429 file_sync_all(conn);
2431 sync_file(conn,fsp);
2434 DEBUG(3,("flush\n"));
2439 /****************************************************************************
2441 ****************************************************************************/
2442 int reply_exit(connection_struct *conn,
2443 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2445 int outsize = set_message(outbuf,0,0,True);
2446 DEBUG(3,("exit\n"));
2452 /****************************************************************************
2453 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2454 ****************************************************************************/
2455 int reply_close(connection_struct *conn,
2456 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2460 int32 eclass = 0, err = 0;
2461 files_struct *fsp = NULL;
2463 outsize = set_message(outbuf,0,0,True);
2465 /* If it's an IPC, pass off to the pipe handler. */
2467 return reply_pipe_close(conn, inbuf,outbuf);
2470 fsp = file_fsp(inbuf,smb_vwv0);
2473 * We can only use CHECK_FSP if we know it's not a directory.
2476 if(!fsp || !fsp->open || (fsp->conn != conn))
2477 return(ERROR(ERRDOS,ERRbadfid));
2479 if(HAS_CACHED_ERROR(fsp)) {
2480 eclass = fsp->wbmpx_ptr->wr_errclass;
2481 err = fsp->wbmpx_ptr->wr_error;
2484 if(fsp->is_directory) {
2486 * Special case - close NT SMB directory
2489 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2490 close_directory(fsp);
2493 * Close ordinary file.
2495 mtime = make_unix_date3(inbuf+smb_vwv1);
2497 /* try and set the date */
2498 set_filetime(conn, fsp->fsp_name,mtime);
2500 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2501 fsp->fd_ptr->fd, fsp->fnum,
2502 conn->num_files_open));
2504 close_file(fsp,True);
2507 /* We have a cached error */
2509 return(ERROR(eclass,err));
2515 /****************************************************************************
2516 reply to a writeclose (Core+ protocol)
2517 ****************************************************************************/
2518 int reply_writeclose(connection_struct *conn,
2519 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2522 ssize_t nwritten = -1;
2527 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2529 CHECK_FSP(fsp,conn);
2533 numtowrite = SVAL(inbuf,smb_vwv1);
2534 startpos = IVAL(inbuf,smb_vwv2);
2535 mtime = make_unix_date3(inbuf+smb_vwv4);
2536 data = smb_buf(inbuf) + 1;
2538 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2539 return(ERROR(ERRDOS,ERRlock));
2541 if(seek_file(fsp,startpos) == -1)
2542 return(UNIXERROR(ERRDOS,ERRnoaccess));
2544 nwritten = write_file(fsp,data,numtowrite);
2546 set_filetime(conn, fsp->fsp_name,mtime);
2548 close_file(fsp,True);
2550 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2551 fsp->fnum, numtowrite, nwritten,
2552 conn->num_files_open));
2555 return(UNIXERROR(ERRDOS,ERRnoaccess));
2557 outsize = set_message(outbuf,1,0,True);
2559 SSVAL(outbuf,smb_vwv0,nwritten);
2564 /****************************************************************************
2566 ****************************************************************************/
2567 int reply_lock(connection_struct *conn,
2568 char *inbuf,char *outbuf, int length, int dum_buffsize)
2570 int outsize = set_message(outbuf,0,0,True);
2571 SMB_OFF_T count,offset;
2574 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2576 CHECK_FSP(fsp,conn);
2579 count = IVAL(inbuf,smb_vwv1);
2580 offset = IVAL(inbuf,smb_vwv3);
2582 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2583 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2585 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2586 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2588 * A blocking lock was requested. Package up
2589 * this smb into a queued request and push it
2590 * onto the blocking lock queue.
2592 if(push_blocking_lock_request(inbuf, length, -1, 0))
2595 return (ERROR(eclass,ecode));
2602 /****************************************************************************
2604 ****************************************************************************/
2605 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2607 int outsize = set_message(outbuf,0,0,True);
2608 SMB_OFF_T count,offset;
2611 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2613 CHECK_FSP(fsp,conn);
2616 count = IVAL(inbuf,smb_vwv1);
2617 offset = IVAL(inbuf,smb_vwv3);
2619 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2620 return (ERROR(eclass,ecode));
2622 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2623 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2629 /****************************************************************************
2631 ****************************************************************************/
2632 int reply_tdis(connection_struct *conn,
2633 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2635 int outsize = set_message(outbuf,0,0,True);
2638 vuid = SVAL(inbuf,smb_uid);
2641 DEBUG(4,("Invalid connection in tdis\n"));
2642 return(ERROR(ERRSRV,ERRinvnid));
2647 close_cnum(conn,vuid);
2654 /****************************************************************************
2656 ****************************************************************************/
2657 int reply_echo(connection_struct *conn,
2658 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2660 int smb_reverb = SVAL(inbuf,smb_vwv0);
2662 int data_len = smb_buflen(inbuf);
2663 int outsize = set_message(outbuf,1,data_len,True);
2665 /* copy any incoming data back out */
2667 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2669 if (smb_reverb > 100) {
2670 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2674 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2675 SSVAL(outbuf,smb_vwv0,seq_num);
2677 smb_setlen(outbuf,outsize - 4);
2679 send_smb(Client,outbuf);
2682 DEBUG(3,("echo %d times\n", smb_reverb));
2688 /****************************************************************************
2689 reply to a printopen
2690 ****************************************************************************/
2691 int reply_printopen(connection_struct *conn,
2692 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2699 *fname = *fname2 = 0;
2701 if (!CAN_PRINT(conn))
2702 return(ERROR(ERRDOS,ERRnoaccess));
2707 pstrcpy(s,smb_buf(inbuf)+1);
2710 if (!(isalnum((int)*p) || strchr("._-",*p)))
2715 if (strlen(s) > 10) s[10] = 0;
2717 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2722 return(ERROR(ERRSRV,ERRnofids));
2724 pstrcpy(fname2,(char *)mktemp(fname));
2726 if (!check_name(fname2,conn)) {
2728 return(ERROR(ERRDOS,ERRnoaccess));
2731 /* Open for exclusive use, write only. */
2732 open_file_shared(fsp,conn,fname2, SET_DENY_MODE(DENY_ALL)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
2733 (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL), unix_mode(conn,0), 0, NULL, NULL);
2737 return(UNIXERROR(ERRDOS,ERRnoaccess));
2740 /* force it to be a print file */
2741 fsp->print_file = True;
2743 outsize = set_message(outbuf,1,0,True);
2744 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2746 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2747 fname2, fsp->fd_ptr->fd, fsp->fnum));
2753 /****************************************************************************
2754 reply to a printclose
2755 ****************************************************************************/
2756 int reply_printclose(connection_struct *conn,
2757 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2759 int outsize = set_message(outbuf,0,0,True);
2760 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2762 CHECK_FSP(fsp,conn);
2765 if (!CAN_PRINT(conn))
2766 return(ERROR(ERRDOS,ERRnoaccess));
2768 DEBUG(3,("printclose fd=%d fnum=%d\n",
2769 fsp->fd_ptr->fd,fsp->fnum));
2771 close_file(fsp,True);
2777 /****************************************************************************
2778 reply to a printqueue
2779 ****************************************************************************/
2780 int reply_printqueue(connection_struct *conn,
2781 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2783 int outsize = set_message(outbuf,2,3,True);
2784 int max_count = SVAL(inbuf,smb_vwv0);
2785 int start_index = SVAL(inbuf,smb_vwv1);
2787 /* we used to allow the client to get the cnum wrong, but that
2788 is really quite gross and only worked when there was only
2789 one printer - I think we should now only accept it if they
2790 get it right (tridge) */
2791 if (!CAN_PRINT(conn))
2792 return(ERROR(ERRDOS,ERRnoaccess));
2794 SSVAL(outbuf,smb_vwv0,0);
2795 SSVAL(outbuf,smb_vwv1,0);
2796 CVAL(smb_buf(outbuf),0) = 1;
2797 SSVAL(smb_buf(outbuf),1,0);
2799 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2800 start_index, max_count));
2803 print_queue_struct *queue = NULL;
2804 char *p = smb_buf(outbuf) + 3;
2805 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2806 int num_to_get = ABS(max_count);
2807 int first = (max_count>0?start_index:start_index+max_count+1);
2813 num_to_get = MIN(num_to_get,count-first);
2816 for (i=first;i<first+num_to_get;i++) {
2817 put_dos_date2(p,0,queue[i].time);
2818 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2819 SSVAL(p,5,printjob_encode(SNUM(conn),
2821 SIVAL(p,7,queue[i].size);
2823 StrnCpy(p+12,queue[i].user,16);
2828 outsize = set_message(outbuf,2,28*count+3,False);
2829 SSVAL(outbuf,smb_vwv0,count);
2830 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2831 CVAL(smb_buf(outbuf),0) = 1;
2832 SSVAL(smb_buf(outbuf),1,28*count);
2835 if (queue) free(queue);
2837 DEBUG(3,("%d entries returned in queue\n",count));
2844 /****************************************************************************
2845 reply to a printwrite
2846 ****************************************************************************/
2847 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2850 int outsize = set_message(outbuf,0,0,True);
2852 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2854 if (!CAN_PRINT(conn))
2855 return(ERROR(ERRDOS,ERRnoaccess));
2857 CHECK_FSP(fsp,conn);
2861 numtowrite = SVAL(smb_buf(inbuf),1);
2862 data = smb_buf(inbuf) + 3;
2864 if (write_file(fsp,data,numtowrite) != numtowrite)
2865 return(UNIXERROR(ERRDOS,ERRnoaccess));
2867 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2873 /****************************************************************************
2875 ****************************************************************************/
2876 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2879 int outsize,ret= -1;
2880 BOOL bad_path = False;
2882 pstrcpy(directory,smb_buf(inbuf) + 1);
2883 unix_convert(directory,conn,0,&bad_path,NULL);
2885 if (check_name(directory, conn))
2886 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2890 if((errno == ENOENT) && bad_path)
2892 unix_ERR_class = ERRDOS;
2893 unix_ERR_code = ERRbadpath;
2895 return(UNIXERROR(ERRDOS,ERRnoaccess));
2898 outsize = set_message(outbuf,0,0,True);
2900 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2905 /****************************************************************************
2906 Static function used by reply_rmdir to delete an entire directory
2908 ****************************************************************************/
2909 static BOOL recursive_rmdir(char *directory)
2913 void *dirptr = OpenDir(NULL, directory, False);
2918 while((dname = ReadDirName(dirptr)))
2923 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2926 /* Construct the full name. */
2927 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2933 pstrcpy(fullname, directory);
2934 pstrcat(fullname, "/");
2935 pstrcat(fullname, dname);
2937 if(dos_lstat(fullname, &st) != 0)
2943 if(st.st_mode & S_IFDIR)
2945 if(recursive_rmdir(fullname)!=0)
2950 if(dos_rmdir(fullname) != 0)
2956 else if(dos_unlink(fullname) != 0)
2966 /****************************************************************************
2968 ****************************************************************************/
2969 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2974 BOOL bad_path = False;
2976 pstrcpy(directory,smb_buf(inbuf) + 1);
2977 unix_convert(directory,conn, NULL,&bad_path,NULL);
2979 if (check_name(directory,conn))
2982 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2983 ok = (dos_rmdir(directory) == 0);
2984 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
2986 /* Check to see if the only thing in this directory are
2987 vetoed files/directories. If so then delete them and
2988 retry. If we fail to delete any of them (and we *don't*
2989 do a recursive delete) then fail the rmdir. */
2990 BOOL all_veto_files = True;
2992 void *dirptr = OpenDir(conn, directory, False);
2996 int dirpos = TellDir(dirptr);
2997 while ((dname = ReadDirName(dirptr)))
2999 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3001 if(!IS_VETO_PATH(conn, dname))
3003 all_veto_files = False;
3009 SeekDir(dirptr,dirpos);
3010 while ((dname = ReadDirName(dirptr)))
3015 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3018 /* Construct the full name. */
3019 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3024 pstrcpy(fullname, directory);
3025 pstrcat(fullname, "/");
3026 pstrcat(fullname, dname);
3028 if(dos_lstat(fullname, &st) != 0)
3030 if(st.st_mode & S_IFDIR)
3032 if(lp_recursive_veto_delete(SNUM(conn)))
3034 if(recursive_rmdir(fullname) != 0)
3037 if(dos_rmdir(fullname) != 0)
3040 else if(dos_unlink(fullname) != 0)
3044 /* Retry the rmdir */
3045 ok = (dos_rmdir(directory) == 0);
3055 DEBUG(3,("couldn't remove directory %s : %s\n",
3056 directory,strerror(errno)));
3061 if((errno == ENOENT) && bad_path)
3063 unix_ERR_class = ERRDOS;
3064 unix_ERR_code = ERRbadpath;
3066 return(UNIXERROR(ERRDOS,ERRbadpath));
3069 outsize = set_message(outbuf,0,0,True);
3071 DEBUG( 3, ( "rmdir %s\n", directory ) );
3077 /*******************************************************************
3078 resolve wildcards in a filename rename
3079 ********************************************************************/
3080 static BOOL resolve_wildcards(char *name1,char *name2)
3082 fstring root1,root2;
3086 name1 = strrchr(name1,'/');
3087 name2 = strrchr(name2,'/');
3089 if (!name1 || !name2) return(False);
3091 fstrcpy(root1,name1);
3092 fstrcpy(root2,name2);
3093 p = strrchr(root1,'.');
3100 p = strrchr(root2,'.');
3132 pstrcpy(name2,root2);
3135 pstrcat(name2,ext2);
3141 /*******************************************************************
3142 check if a user is allowed to rename a file
3143 ********************************************************************/
3144 static BOOL can_rename(char *fname,connection_struct *conn)
3146 SMB_STRUCT_STAT sbuf;
3148 if (!CAN_WRITE(conn)) return(False);
3150 if (dos_lstat(fname,&sbuf) != 0) return(False);
3151 if (!check_file_sharing(conn,fname,True)) return(False);
3156 /****************************************************************************
3157 The guts of the rename command, split out so it may be called by the NT SMB
3159 ****************************************************************************/
3160 int rename_internals(connection_struct *conn,
3161 char *inbuf, char *outbuf, char *name,
3162 char *newname, BOOL replace_if_exists)
3166 pstring newname_last_component;
3169 BOOL bad_path1 = False;
3170 BOOL bad_path2 = False;
3172 int error = ERRnoaccess;
3175 *directory = *mask = 0;
3177 unix_convert(name,conn,0,&bad_path1,NULL);
3178 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3181 * Split the old name into directory and last component
3182 * strings. Note that unix_convert may have stripped off a
3183 * leading ./ from both name and newname if the rename is
3184 * at the root of the share. We need to make sure either both
3185 * name and newname contain a / character or neither of them do
3186 * as this is checked in resolve_wildcards().
3189 p = strrchr(name,'/');
3191 pstrcpy(directory,".");
3195 pstrcpy(directory,name);
3197 *p = '/'; /* Replace needed for exceptional test below. */
3200 if (is_mangled(mask))
3201 check_mangled_cache( mask );
3203 has_wild = strchr(mask,'*') || strchr(mask,'?');
3207 * No wildcards - just process the one file.
3209 BOOL is_short_name = is_8_3(name, True);
3211 /* Add a terminating '/' to the directory name. */
3212 pstrcat(directory,"/");
3213 pstrcat(directory,mask);
3215 /* Ensure newname contains a '/' also */
3216 if(strrchr(newname,'/') == 0) {
3219 pstrcpy(tmpstr, "./");
3220 pstrcat(tmpstr, newname);
3221 pstrcpy(newname, tmpstr);
3224 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",
3225 case_sensitive, case_preserve, short_case_preserve, directory,
3226 newname, newname_last_component, is_short_name));
3229 * Check for special case with case preserving and not
3230 * case sensitive, if directory and newname are identical,
3231 * and the old last component differs from the original
3232 * last component only by case, then we should allow
3233 * the rename (user is trying to change the case of the
3236 if((case_sensitive == False) &&
3237 (((case_preserve == True) &&
3238 (is_short_name == False)) ||
3239 ((short_case_preserve == True) &&
3240 (is_short_name == True))) &&
3241 strcsequal(directory, newname)) {
3242 pstring newname_modified_last_component;
3245 * Get the last component of the modified name.
3246 * Note that we guarantee that newname contains a '/'
3249 p = strrchr(newname,'/');
3250 pstrcpy(newname_modified_last_component,p+1);
3252 if(strcsequal(newname_modified_last_component,
3253 newname_last_component) == False) {
3255 * Replace the modified last component with
3258 pstrcpy(p+1, newname_last_component);
3262 if(replace_if_exists) {
3264 * NT SMB specific flag - rename can overwrite
3265 * file with the same name so don't check for
3268 if(resolve_wildcards(directory,newname) &&
3269 can_rename(directory,conn) &&
3270 !dos_rename(directory,newname))
3273 if (resolve_wildcards(directory,newname) &&
3274 can_rename(directory,conn) &&
3275 !file_exist(newname,NULL) &&
3276 !dos_rename(directory,newname))
3280 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3281 directory,newname));
3283 if (!count) exists = file_exist(directory,NULL);
3284 if (!count && exists && file_exist(newname,NULL)) {
3290 * Wildcards - process each file that matches.
3292 void *dirptr = NULL;
3296 if (check_name(directory,conn))
3297 dirptr = OpenDir(conn, directory, True);
3302 if (strequal(mask,"????????.???"))
3305 while ((dname = ReadDirName(dirptr))) {
3307 pstrcpy(fname,dname);
3309 if(!mask_match(fname, mask, case_sensitive, False))
3312 error = ERRnoaccess;
3313 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3314 if (!can_rename(fname,conn)) {
3315 DEBUG(6,("rename %s refused\n", fname));
3318 pstrcpy(destname,newname);
3320 if (!resolve_wildcards(fname,destname)) {
3321 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3325 if (!replace_if_exists && file_exist(destname,NULL)) {
3326 DEBUG(6,("file_exist %s\n", destname));
3331 if (!dos_rename(fname,destname))
3333 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3341 return(ERROR(ERRDOS,error));
3343 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3344 unix_ERR_class = ERRDOS;
3345 unix_ERR_code = ERRbadpath;
3347 return(UNIXERROR(ERRDOS,error));
3354 /****************************************************************************
3356 ****************************************************************************/
3358 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3364 pstrcpy(name,smb_buf(inbuf) + 1);
3365 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3367 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3369 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3371 outsize = set_message(outbuf,0,0,True);
3376 /*******************************************************************
3377 copy a file as part of a reply_copy
3378 ******************************************************************/
3380 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3381 int count,BOOL target_is_directory)
3386 files_struct *fsp1,*fsp2;
3389 pstrcpy(dest,dest1);
3390 if (target_is_directory) {
3391 char *p = strrchr(src,'/');
3400 if (!file_exist(src,&st))
3407 open_file_shared(fsp1,conn,src,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3408 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3415 if (!target_is_directory && count)
3420 close_file(fsp1,False);
3423 open_file_shared(fsp2,conn,dest,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3424 ofun,st.st_mode,0,&Access,&action);
3427 close_file(fsp1,False);
3432 if ((ofun&3) == 1) {
3433 if(sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END) == -1) {
3434 DEBUG(0,("copy_file: error - sys_lseek returned error %s\n",
3437 * Stop the copy from occurring.
3445 ret = transfer_file(fsp1->fd_ptr->fd,
3446 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3448 close_file(fsp1,False);
3449 close_file(fsp2,False);
3451 return(ret == st.st_size);
3456 /****************************************************************************
3457 reply to a file copy.
3458 ****************************************************************************/
3459 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3464 pstring mask,newname;
3467 int error = ERRnoaccess;
3470 int tid2 = SVAL(inbuf,smb_vwv0);
3471 int ofun = SVAL(inbuf,smb_vwv1);
3472 int flags = SVAL(inbuf,smb_vwv2);
3473 BOOL target_is_directory=False;
3474 BOOL bad_path1 = False;
3475 BOOL bad_path2 = False;
3477 *directory = *mask = 0;
3479 pstrcpy(name,smb_buf(inbuf));
3480 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3482 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3484 if (tid2 != conn->cnum) {
3485 /* can't currently handle inter share copies XXXX */
3486 DEBUG(3,("Rejecting inter-share copy\n"));
3487 return(ERROR(ERRSRV,ERRinvdevice));
3490 unix_convert(name,conn,0,&bad_path1,NULL);
3491 unix_convert(newname,conn,0,&bad_path2,NULL);
3493 target_is_directory = directory_exist(newname,NULL);
3495 if ((flags&1) && target_is_directory) {
3496 return(ERROR(ERRDOS,ERRbadfile));
3499 if ((flags&2) && !target_is_directory) {
3500 return(ERROR(ERRDOS,ERRbadpath));
3503 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3504 /* wants a tree copy! XXXX */
3505 DEBUG(3,("Rejecting tree copy\n"));
3506 return(ERROR(ERRSRV,ERRerror));
3509 p = strrchr(name,'/');
3511 pstrcpy(directory,"./");
3515 pstrcpy(directory,name);
3519 if (is_mangled(mask))
3520 check_mangled_cache( mask );
3522 has_wild = strchr(mask,'*') || strchr(mask,'?');
3525 pstrcat(directory,"/");
3526 pstrcat(directory,mask);
3527 if (resolve_wildcards(directory,newname) &&
3528 copy_file(directory,newname,conn,ofun,
3529 count,target_is_directory)) count++;
3530 if (!count) exists = file_exist(directory,NULL);
3532 void *dirptr = NULL;
3536 if (check_name(directory,conn))
3537 dirptr = OpenDir(conn, directory, True);
3543 if (strequal(mask,"????????.???"))
3546 while ((dname = ReadDirName(dirptr)))
3549 pstrcpy(fname,dname);
3551 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3553 error = ERRnoaccess;
3554 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3555 pstrcpy(destname,newname);
3556 if (resolve_wildcards(fname,destname) &&
3557 copy_file(directory,newname,conn,ofun,
3558 count,target_is_directory)) count++;
3559 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3567 return(ERROR(ERRDOS,error));
3570 if((errno == ENOENT) && (bad_path1 || bad_path2))
3572 unix_ERR_class = ERRDOS;
3573 unix_ERR_code = ERRbadpath;
3575 return(UNIXERROR(ERRDOS,error));
3579 outsize = set_message(outbuf,1,0,True);
3580 SSVAL(outbuf,smb_vwv0,count);
3585 /****************************************************************************
3587 ****************************************************************************/
3588 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3596 if (!CAN_SETDIR(snum))
3597 return(ERROR(ERRDOS,ERRnoaccess));
3599 pstrcpy(newdir,smb_buf(inbuf) + 1);
3602 if (strlen(newdir) == 0) {
3605 ok = directory_exist(newdir,NULL);
3607 string_set(&conn->connectpath,newdir);
3612 return(ERROR(ERRDOS,ERRbadpath));
3614 outsize = set_message(outbuf,0,0,True);
3615 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3617 DEBUG(3,("setdir %s\n", newdir));
3622 /****************************************************************************
3623 reply to a lockingX request
3624 ****************************************************************************/
3625 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3627 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3628 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3630 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3632 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3633 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3634 SMB_OFF_T count = 0, offset = 0;
3635 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3638 uint32 ecode=0, dummy2;
3639 int eclass=0, dummy1;
3640 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3641 CHECK_FSP(fsp,conn);
3644 data = smb_buf(inbuf);
3646 /* Check if this is an oplock break on a file
3647 we have granted an oplock on.
3649 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3652 SMB_DEV_T dev = fsp->fd_ptr->dev;
3653 SMB_INO_T inode = fsp->fd_ptr->inode;
3655 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3658 * Make sure we have granted an oplock on this file.
3660 if(!fsp->granted_oplock)
3662 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3663 no oplock granted on this file.\n", fsp->fnum));
3664 return ERROR(ERRDOS,ERRlock);
3667 /* Remove the oplock flag from the sharemode. */
3668 lock_share_entry(fsp->conn, dev, inode, &token);
3669 if(remove_share_oplock(token, fsp)==False) {
3671 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3672 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3674 unlock_share_entry(fsp->conn, dev, inode, token);
3676 unlock_share_entry(fsp->conn, dev, inode, token);
3678 /* Clear the granted flag and return. */
3679 fsp->granted_oplock = False;
3682 /* if this is a pure oplock break request then don't send a reply */
3683 if (num_locks == 0 && num_ulocks == 0)
3685 /* Sanity check - ensure a pure oplock break is not a
3687 if(CVAL(inbuf,smb_vwv0) != 0xff)
3688 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3689 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3694 /* Data now points at the beginning of the list
3695 of smb_unlkrng structs */
3696 for(i = 0; i < (int)num_ulocks; i++) {
3697 if(!large_file_format) {
3698 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3699 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3701 #ifdef LARGE_SMB_OFF_T
3703 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3704 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3705 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3706 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3708 #endif /* LARGE_SMB_OFF_T */
3710 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3711 (double)offset, (double)count, fsp->fsp_name ));
3713 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3714 return ERROR(eclass,ecode);
3717 /* Setup the timeout in seconds. */
3718 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3720 /* Now do any requested locks */
3721 data += ((large_file_format ? 20 : 10)*num_ulocks);
3723 /* Data now points at the beginning of the list
3724 of smb_lkrng structs */
3726 for(i = 0; i < (int)num_locks; i++) {
3727 if(!large_file_format) {
3728 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3729 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3731 #ifdef LARGE_SMB_OFF_T
3733 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3734 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3735 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3736 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3738 #endif /* LARGE_SMB_OFF_T */
3740 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3741 (double)offset, (double)count, fsp->fsp_name ));
3743 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3745 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3747 * A blocking lock was requested. Package up
3748 * this smb into a queued request and push it
3749 * onto the blocking lock queue.
3751 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3758 /* If any of the above locks failed, then we must unlock
3759 all of the previous locks (X/Open spec). */
3760 if(i != num_locks && num_locks != 0) {
3761 for(; i >= 0; i--) {
3762 if(!large_file_format) {
3763 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3764 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3766 #ifdef LARGE_SMB_OFF_T
3768 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3769 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3770 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3771 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3773 #endif /* LARGE_SMB_OFF_T */
3775 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3777 return ERROR(eclass,ecode);
3780 set_message(outbuf,2,0,True);
3782 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3783 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3785 return chain_reply(inbuf,outbuf,length,bufsize);
3789 /****************************************************************************
3790 reply to a SMBreadbmpx (read block multiplex) request
3791 ****************************************************************************/
3792 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3803 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3805 /* this function doesn't seem to work - disable by default */
3807 return(ERROR(ERRSRV,ERRuseSTD));
3809 outsize = set_message(outbuf,8,0,True);
3811 CHECK_FSP(fsp,conn);
3815 startpos = IVAL(inbuf,smb_vwv1);
3816 maxcount = SVAL(inbuf,smb_vwv3);
3818 data = smb_buf(outbuf);
3819 pad = ((long)data)%4;
3820 if (pad) pad = 4 - pad;
3823 max_per_packet = bufsize-(outsize+pad);
3827 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3828 return(ERROR(ERRDOS,ERRlock));
3832 size_t N = MIN(max_per_packet,tcount-total_read);
3834 nread = read_file(fsp,data,startpos,N);
3836 if (nread <= 0) nread = 0;
3838 if (nread < (ssize_t)N)
3839 tcount = total_read + nread;
3841 set_message(outbuf,8,nread,False);
3842 SIVAL(outbuf,smb_vwv0,startpos);
3843 SSVAL(outbuf,smb_vwv2,tcount);
3844 SSVAL(outbuf,smb_vwv6,nread);
3845 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3847 send_smb(Client,outbuf);
3849 total_read += nread;
3852 while (total_read < (ssize_t)tcount);
3857 /****************************************************************************
3858 reply to a SMBwritebmpx (write block multiplex primary) request
3859 ****************************************************************************/
3860 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3863 ssize_t nwritten = -1;
3870 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3872 CHECK_FSP(fsp,conn);
3876 tcount = SVAL(inbuf,smb_vwv1);
3877 startpos = IVAL(inbuf,smb_vwv3);
3878 write_through = BITSETW(inbuf+smb_vwv7,0);
3879 numtowrite = SVAL(inbuf,smb_vwv10);
3880 smb_doff = SVAL(inbuf,smb_vwv11);
3882 data = smb_base(inbuf) + smb_doff;
3884 /* If this fails we need to send an SMBwriteC response,
3885 not an SMBwritebmpx - set this up now so we don't forget */
3886 CVAL(outbuf,smb_com) = SMBwritec;
3888 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3889 return(ERROR(ERRDOS,ERRlock));
3891 if(seek_file(fsp,startpos) == -1)
3892 return(UNIXERROR(ERRDOS,ERRnoaccess));
3894 nwritten = write_file(fsp,data,numtowrite);
3896 if(lp_syncalways(SNUM(conn)) || write_through)
3897 sync_file(conn,fsp);
3899 if(nwritten < (ssize_t)numtowrite)
3900 return(UNIXERROR(ERRHRD,ERRdiskfull));
3902 /* If the maximum to be written to this file
3903 is greater than what we just wrote then set
3904 up a secondary struct to be attached to this
3905 fd, we will use this to cache error messages etc. */
3906 if((ssize_t)tcount > nwritten)
3908 write_bmpx_struct *wbms;
3909 if(fsp->wbmpx_ptr != NULL)
3910 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3912 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3915 DEBUG(0,("Out of memory in reply_readmpx\n"));
3916 return(ERROR(ERRSRV,ERRnoresource));
3918 wbms->wr_mode = write_through;
3919 wbms->wr_discard = False; /* No errors yet */
3920 wbms->wr_total_written = nwritten;
3921 wbms->wr_errclass = 0;
3923 fsp->wbmpx_ptr = wbms;
3926 /* We are returning successfully, set the message type back to
3928 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3930 outsize = set_message(outbuf,1,0,True);
3932 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3934 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3935 fsp->fnum, numtowrite, nwritten ) );
3937 if (write_through && tcount==nwritten) {
3938 /* we need to send both a primary and a secondary response */
3939 smb_setlen(outbuf,outsize - 4);
3940 send_smb(Client,outbuf);
3942 /* now the secondary */
3943 outsize = set_message(outbuf,1,0,True);
3944 CVAL(outbuf,smb_com) = SMBwritec;
3945 SSVAL(outbuf,smb_vwv0,nwritten);
3952 /****************************************************************************
3953 reply to a SMBwritebs (write block multiplex secondary) request
3954 ****************************************************************************/
3955 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3958 ssize_t nwritten = -1;
3965 write_bmpx_struct *wbms;
3966 BOOL send_response = False;
3967 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3969 CHECK_FSP(fsp,conn);
3972 tcount = SVAL(inbuf,smb_vwv1);
3973 startpos = IVAL(inbuf,smb_vwv2);
3974 numtowrite = SVAL(inbuf,smb_vwv6);
3975 smb_doff = SVAL(inbuf,smb_vwv7);
3977 data = smb_base(inbuf) + smb_doff;
3979 /* We need to send an SMBwriteC response, not an SMBwritebs */
3980 CVAL(outbuf,smb_com) = SMBwritec;
3982 /* This fd should have an auxiliary struct attached,
3983 check that it does */
3984 wbms = fsp->wbmpx_ptr;
3985 if(!wbms) return(-1);
3987 /* If write through is set we can return errors, else we must
3989 write_through = wbms->wr_mode;
3991 /* Check for an earlier error */
3992 if(wbms->wr_discard)
3993 return -1; /* Just discard the packet */
3995 if(seek_file(fsp,startpos) == -1)
3999 /* We are returning an error - we can delete the aux struct */
4000 if (wbms) free((char *)wbms);
4001 fsp->wbmpx_ptr = NULL;
4002 return(UNIXERROR(ERRDOS,ERRnoaccess));
4004 return(CACHE_ERROR(wbms,ERRDOS,ERRnoaccess));
4007 nwritten = write_file(fsp,data,numtowrite);
4009 if(lp_syncalways(SNUM(conn)) || write_through)
4010 sync_file(conn,fsp);
4012 if (nwritten < (ssize_t)numtowrite)
4016 /* We are returning an error - we can delete the aux struct */
4017 if (wbms) free((char *)wbms);
4018 fsp->wbmpx_ptr = NULL;
4019 return(ERROR(ERRHRD,ERRdiskfull));
4021 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4024 /* Increment the total written, if this matches tcount
4025 we can discard the auxiliary struct (hurrah !) and return a writeC */
4026 wbms->wr_total_written += nwritten;
4027 if(wbms->wr_total_written >= tcount)
4031 outsize = set_message(outbuf,1,0,True);
4032 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4033 send_response = True;
4037 fsp->wbmpx_ptr = NULL;
4047 /****************************************************************************
4048 reply to a SMBsetattrE
4049 ****************************************************************************/
4050 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4052 struct utimbuf unix_times;
4054 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4056 outsize = set_message(outbuf,0,0,True);
4058 CHECK_FSP(fsp,conn);
4061 /* Convert the DOS times into unix times. Ignore create
4062 time as UNIX can't set this.
4064 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4065 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4068 * Patch from Ray Frush <frush@engr.colostate.edu>
4069 * Sometimes times are sent as zero - ignore them.
4072 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4074 /* Ignore request */
4077 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4078 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4082 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4084 /* set modify time = to access time if modify time was 0 */
4085 unix_times.modtime = unix_times.actime;
4088 /* Set the date on this file */
4089 if(file_utime(conn, fsp->fsp_name, &unix_times))
4090 return(ERROR(ERRDOS,ERRnoaccess));
4092 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4093 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4099 /****************************************************************************
4100 reply to a SMBgetattrE
4101 ****************************************************************************/
4102 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4104 SMB_STRUCT_STAT sbuf;
4107 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4109 outsize = set_message(outbuf,11,0,True);
4111 CHECK_FSP(fsp,conn);
4114 /* Do an fstat on this file */
4115 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4116 return(UNIXERROR(ERRDOS,ERRnoaccess));
4118 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4120 /* Convert the times into dos times. Set create
4121 date to be last modify date as UNIX doesn't save
4123 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4124 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4125 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4128 SIVAL(outbuf,smb_vwv6,0);
4129 SIVAL(outbuf,smb_vwv8,0);
4133 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4134 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4136 SSVAL(outbuf,smb_vwv10, mode);
4138 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));