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, (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));
451 /****************************************************************************
452 reply to a session setup command
453 ****************************************************************************/
454 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
460 int smb_apasslen = 0;
462 int smb_ntpasslen = 0;
463 pstring smb_ntpasswd;
464 BOOL valid_nt_password = False;
468 static BOOL done_sesssetup = False;
469 BOOL doencrypt = SMBENCRYPT();
475 smb_bufsize = SVAL(inbuf,smb_vwv2);
477 if (Protocol < PROTOCOL_NT1) {
478 smb_apasslen = SVAL(inbuf,smb_vwv7);
479 if (smb_apasslen > MAX_PASS_LEN)
481 overflow_attack(smb_apasslen);
484 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
485 smb_apasswd[smb_apasslen] = 0;
486 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
488 if (!doencrypt && (lp_security() != SEC_SERVER)) {
489 smb_apasslen = strlen(smb_apasswd);
492 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
493 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
494 enum remote_arch_types ra_type = get_remote_arch();
495 char *p = smb_buf(inbuf);
497 global_client_caps = IVAL(inbuf,smb_vwv11);
499 /* client_caps is used as final determination if client is NT or Win95.
500 This is needed to return the correct error codes in some
504 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
506 if(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))
507 set_remote_arch( RA_WINNT);
509 set_remote_arch( RA_WIN95);
512 if (passlen1 != 24 && passlen2 != 24)
515 if (passlen1 > MAX_PASS_LEN) {
516 overflow_attack(passlen1);
519 passlen1 = MIN(passlen1, MAX_PASS_LEN);
520 passlen2 = MIN(passlen2, MAX_PASS_LEN);
523 /* both Win95 and WinNT stuff up the password lengths for
524 non-encrypting systems. Uggh.
526 if passlen1==24 its a win95 system, and its setting the
527 password length incorrectly. Luckily it still works with the
528 default code because Win95 will null terminate the password
531 if passlen1>0 and passlen2>0 then maybe its a NT box and its
532 setting passlen2 to some random value which really stuffs
533 things up. we need to fix that one. */
535 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
539 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
540 /* Save the lanman2 password and the NT md4 password. */
541 smb_apasslen = passlen1;
542 memcpy(smb_apasswd,p,smb_apasslen);
543 smb_apasswd[smb_apasslen] = 0;
544 smb_ntpasslen = passlen2;
545 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
546 smb_ntpasswd[smb_ntpasslen] = 0;
548 /* we use the first password that they gave */
549 smb_apasslen = passlen1;
550 StrnCpy(smb_apasswd,p,smb_apasslen);
552 /* trim the password */
553 smb_apasslen = strlen(smb_apasswd);
555 /* wfwg sometimes uses a space instead of a null */
556 if (strequal(smb_apasswd," ")) {
562 p += passlen1 + passlen2;
563 fstrcpy(user,p); p = skip_string(p,1);
566 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
567 domain,skip_string(p,1),skip_string(p,2)));
571 DEBUG(3,("sesssetupX:name=[%s]\n",user));
573 /* If name ends in $ then I think it's asking about whether a */
574 /* computer with that name (minus the $) has access. For now */
575 /* say yes to everything ending in $. */
576 if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
578 return session_trust_account(conn, inbuf, outbuf, user,
579 smb_apasswd, smb_apasslen,
580 smb_ntpasswd, smb_ntpasslen);
583 /* If no username is sent use the guest account */
586 pstrcpy(user,lp_guestaccount(-1));
587 /* If no user and no password then set guest flag. */
588 if( *smb_apasswd == 0)
595 * In share level security, only overwrite sesssetup_use if
596 * it's a non null-session share. Helps keep %U and %G
600 if((lp_security() != SEC_SHARE) || *user)
601 pstrcpy(sesssetup_user,user);
603 reload_services(True);
606 * Save the username before mapping. We will use
607 * the original username sent to us for security=server
608 * and security=domain checking.
611 pstrcpy( orig_user, user);
614 * Pass the user through the NT -> unix user mapping
618 (void)map_username(user);
621 * Do any UNIX username case mangling.
623 (void)Get_Pwnam( user, True);
625 add_session_user(user);
628 * Check if the given username was the guest user with no password.
631 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
634 if (!guest && !(lp_security() == SEC_SERVER &&
635 /* Check with orig_user for security=server and
637 server_validate(orig_user, domain,
638 smb_apasswd, smb_apasslen,
639 smb_ntpasswd, smb_ntpasslen)) &&
640 !(lp_security() == SEC_DOMAIN &&
641 domain_client_validate(orig_user, domain,
642 smb_apasswd, smb_apasslen,
643 smb_ntpasswd, smb_ntpasslen)) &&
644 !check_hosts_equiv(user)
648 /* now check if it's a valid username/password */
649 /* If an NT password was supplied try and validate with that
650 first. This is superior as the passwords are mixed case
651 128 length unicode */
654 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
655 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
657 valid_nt_password = True;
659 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
661 if (lp_security() >= SEC_USER) {
662 #if (GUEST_SESSSETUP == 0)
663 return(ERROR(ERRSRV,ERRbadpw));
665 #if (GUEST_SESSSETUP == 1)
666 if (Get_Pwnam(user,True))
667 return(ERROR(ERRSRV,ERRbadpw));
670 if (*smb_apasswd || !Get_Pwnam(user,True))
671 pstrcpy(user,lp_guestaccount(-1));
672 DEBUG(3,("Registered username %s for guest access\n",user));
677 if (!Get_Pwnam(user,True)) {
678 DEBUG(3,("No such user %s - using guest account\n",user));
679 pstrcpy(user,lp_guestaccount(-1));
683 if (!strequal(user,lp_guestaccount(-1)) &&
684 lp_servicenumber(user) < 0)
686 int homes = lp_servicenumber(HOMES_NAME);
687 char *home = get_home_dir(user);
688 if (homes >= 0 && home)
689 lp_add_home(user,homes,home);
693 /* it's ok - setup a reply */
694 if (Protocol < PROTOCOL_NT1) {
695 set_message(outbuf,3,0,True);
698 set_message(outbuf,3,3,True);
700 pstrcpy(p,"Unix"); p = skip_string(p,1);
701 pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
702 pstrcpy(p,global_myworkgroup); p = skip_string(p,1);
703 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
704 /* perhaps grab OS version here?? */
707 /* Set the correct uid in the outgoing and incoming packets
708 We will use this on future requests to determine which
709 user we should become.
712 struct passwd *pw = Get_Pwnam(user,False);
714 DEBUG(1,("Username %s is invalid on this system\n",user));
715 return(ERROR(ERRSRV,ERRbadpw));
722 SSVAL(outbuf,smb_vwv2,1);
724 /* register the name and uid as being validated, so further connections
725 to a uid can get through without a password, on the same VC */
726 sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest);
728 SSVAL(outbuf,smb_uid,sess_vuid);
729 SSVAL(inbuf,smb_uid,sess_vuid);
732 max_send = MIN(max_send,smb_bufsize);
734 DEBUG(6,("Client requested max send size of %d\n", max_send));
736 done_sesssetup = True;
738 return chain_reply(inbuf,outbuf,length,bufsize);
742 /****************************************************************************
744 ****************************************************************************/
745 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
751 BOOL bad_path = False;
754 pstrcpy(name,smb_buf(inbuf) + 1);
755 unix_convert(name,conn,0,&bad_path,&st);
757 mode = SVAL(inbuf,smb_vwv0);
759 if (check_name(name,conn)) {
761 ok = S_ISDIR(st.st_mode);
763 ok = directory_exist(name,NULL);
768 /* We special case this - as when a Windows machine
769 is parsing a path is steps through the components
770 one at a time - if a component fails it expects
771 ERRbadpath, not ERRbadfile.
775 unix_ERR_class = ERRDOS;
776 unix_ERR_code = ERRbadpath;
780 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
781 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
782 (get_remote_arch() == RA_WINNT))
784 unix_ERR_class = ERRDOS;
785 unix_ERR_code = ERRbaddirectory;
789 return(UNIXERROR(ERRDOS,ERRbadpath));
792 outsize = set_message(outbuf,0,0,True);
794 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
800 /****************************************************************************
802 ****************************************************************************/
803 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
807 SMB_STRUCT_STAT sbuf;
812 BOOL bad_path = False;
814 pstrcpy(fname,smb_buf(inbuf) + 1);
815 unix_convert(fname,conn,0,&bad_path,&sbuf);
817 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
818 under WfWg - weird! */
821 mode = aHIDDEN | aDIR;
822 if (!CAN_WRITE(conn)) mode |= aRONLY;
828 if (check_name(fname,conn))
830 if (VALID_STAT(sbuf) || dos_stat(fname,&sbuf) == 0)
832 mode = dos_mode(conn,fname,&sbuf);
834 mtime = sbuf.st_mtime;
840 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
845 if((errno == ENOENT) && bad_path)
847 unix_ERR_class = ERRDOS;
848 unix_ERR_code = ERRbadpath;
851 return(UNIXERROR(ERRDOS,ERRbadfile));
854 outsize = set_message(outbuf,10,0,True);
856 SSVAL(outbuf,smb_vwv0,mode);
857 if(lp_dos_filetime_resolution(SNUM(conn)) )
858 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
860 put_dos_date3(outbuf,smb_vwv1,mtime);
861 SIVAL(outbuf,smb_vwv3,(uint32)size);
863 if (Protocol >= PROTOCOL_NT1) {
864 char *p = strrchr(fname,'/');
865 uint16 flg2 = SVAL(outbuf,smb_flg2);
867 if (!is_8_3(fname, True))
868 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
871 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
877 /****************************************************************************
879 ****************************************************************************/
880 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
888 BOOL bad_path = False;
890 pstrcpy(fname,smb_buf(inbuf) + 1);
891 unix_convert(fname,conn,0,&bad_path,&st);
893 mode = SVAL(inbuf,smb_vwv0);
894 mtime = make_unix_date3(inbuf+smb_vwv1);
896 if (VALID_STAT_OF_DIR(st) || directory_exist(fname,NULL))
898 if (check_name(fname,conn))
899 ok = (file_chmod(conn,fname,mode,NULL) == 0);
901 ok = set_filetime(conn,fname,mtime);
905 if((errno == ENOENT) && bad_path)
907 unix_ERR_class = ERRDOS;
908 unix_ERR_code = ERRbadpath;
911 return(UNIXERROR(ERRDOS,ERRnoaccess));
914 outsize = set_message(outbuf,0,0,True);
916 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
922 /****************************************************************************
924 ****************************************************************************/
925 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
928 SMB_BIG_UINT dfree,dsize,bsize;
930 sys_disk_free(".",&bsize,&dfree,&dsize);
932 outsize = set_message(outbuf,5,0,True);
934 SSVAL(outbuf,smb_vwv0,dsize);
935 SSVAL(outbuf,smb_vwv1,bsize/512);
936 SSVAL(outbuf,smb_vwv2,512);
937 SSVAL(outbuf,smb_vwv3,dfree);
939 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
945 /****************************************************************************
947 Can be called from SMBsearch, SMBffirst or SMBfunique.
948 ****************************************************************************/
949 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
960 BOOL finished = False;
969 BOOL check_descend = False;
970 BOOL expect_close = False;
971 BOOL can_open = True;
972 BOOL bad_path = False;
974 *mask = *directory = *fname = 0;
976 /* If we were called as SMBffirst then we must expect close. */
977 if(CVAL(inbuf,smb_com) == SMBffirst)
980 outsize = set_message(outbuf,1,3,True);
981 maxentries = SVAL(inbuf,smb_vwv0);
982 dirtype = SVAL(inbuf,smb_vwv1);
983 path = smb_buf(inbuf) + 1;
984 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
987 /* dirtype &= ~aDIR; */
989 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
996 pstrcpy(directory,smb_buf(inbuf)+1);
997 pstrcpy(dir2,smb_buf(inbuf)+1);
998 unix_convert(directory,conn,0,&bad_path,NULL);
1001 if (!check_name(directory,conn))
1004 p = strrchr(dir2,'/');
1016 p = strrchr(directory,'/');
1022 if (strlen(directory) == 0)
1023 pstrcpy(directory,"./");
1025 CVAL(status,0) = dirtype;
1029 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1030 memcpy(mask,status+1,11);
1032 dirtype = CVAL(status,0) & 0x1F;
1033 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1036 string_set(&conn->dirpath,dptr_path(dptr_num));
1037 if (!case_sensitive)
1041 /* turn strings of spaces into a . */
1043 trim_string(mask,NULL," ");
1044 if ((p = strrchr(mask,' ')))
1049 trim_string(mask,NULL," ");
1055 /* Convert the formatted mask. (This code lives in trans2.c) */
1063 if((skip = skip_multibyte_char( *p )) != 0 )
1069 if (*p != '?' && *p != '*' && !isdoschar(*p))
1071 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
1079 if (!strchr(mask,'.') && strlen(mask)>8)
1082 fstrcpy(tmp,&mask[8]);
1088 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
1092 p = smb_buf(outbuf) + 3;
1096 if (status_len == 0)
1098 dptr_num = dptr_create(conn,directory,expect_close,SVAL(inbuf,smb_pid));
1103 if((errno == ENOENT) && bad_path)
1105 unix_ERR_class = ERRDOS;
1106 unix_ERR_code = ERRbadpath;
1108 return (UNIXERROR(ERRDOS,ERRnofids));
1110 return(ERROR(ERRDOS,ERRnofids));
1114 DEBUG(4,("dptr_num is %d\n",dptr_num));
1118 if ((dirtype&0x1F) == aVOLID)
1120 memcpy(p,status,21);
1121 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1122 dptr_fill(p+12,dptr_num);
1123 if (dptr_zero(p+12) && (status_len==0))
1127 p += DIR_STRUCT_SIZE;
1131 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1132 conn->dirpath,lp_dontdescend(SNUM(conn))));
1133 if (in_list(conn->dirpath,
1134 lp_dontdescend(SNUM(conn)),True))
1135 check_descend = True;
1137 for (i=numentries;(i<maxentries) && !finished;i++)
1140 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1143 memcpy(p,status,21);
1144 make_dir_struct(p,mask,fname,size,mode,date);
1145 dptr_fill(p+12,dptr_num);
1148 p += DIR_STRUCT_SIZE;
1157 if (numentries == 0 || !ok)
1159 CVAL(outbuf,smb_rcls) = ERRDOS;
1160 SSVAL(outbuf,smb_err,ERRnofiles);
1163 /* If we were called as SMBffirst with smb_search_id == NULL
1164 and no entries were found then return error and close dirptr
1167 if(ok && expect_close && numentries == 0 && status_len == 0)
1169 CVAL(outbuf,smb_rcls) = ERRDOS;
1170 SSVAL(outbuf,smb_err,ERRnofiles);
1171 /* Also close the dptr - we know it's gone */
1172 dptr_close(dptr_num);
1175 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1176 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1177 dptr_close(dptr_num);
1179 SSVAL(outbuf,smb_vwv0,numentries);
1180 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1181 CVAL(smb_buf(outbuf),0) = 5;
1182 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1184 if (Protocol >= PROTOCOL_NT1) {
1185 uint16 flg2 = SVAL(outbuf,smb_flg2);
1186 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1189 outsize += DIR_STRUCT_SIZE*numentries;
1190 smb_setlen(outbuf,outsize - 4);
1192 if ((! *directory) && dptr_path(dptr_num))
1193 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1195 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1196 smb_fn_name(CVAL(inbuf,smb_com)),
1197 mask, directory, dirtype, numentries, maxentries ) );
1203 /****************************************************************************
1204 reply to a fclose (stop directory search)
1205 ****************************************************************************/
1206 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1214 outsize = set_message(outbuf,1,0,True);
1215 path = smb_buf(inbuf) + 1;
1216 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1219 if (status_len == 0)
1220 return(ERROR(ERRSRV,ERRsrverror));
1222 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1224 if(dptr_fetch(status+12,&dptr_num)) {
1225 /* Close the dptr - we know it's gone */
1226 dptr_close(dptr_num);
1229 SSVAL(outbuf,smb_vwv0,0);
1231 DEBUG(3,("search close\n"));
1237 /****************************************************************************
1239 ****************************************************************************/
1240 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1250 SMB_STRUCT_STAT sbuf;
1251 BOOL bad_path = False;
1253 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1255 share_mode = SVAL(inbuf,smb_vwv0);
1257 pstrcpy(fname,smb_buf(inbuf)+1);
1258 unix_convert(fname,conn,0,&bad_path,NULL);
1262 return(ERROR(ERRSRV,ERRnofids));
1264 if (!check_name(fname,conn))
1266 if((errno == ENOENT) && bad_path)
1268 unix_ERR_class = ERRDOS;
1269 unix_ERR_code = ERRbadpath;
1272 return(UNIXERROR(ERRDOS,ERRnoaccess));
1275 unixmode = unix_mode(conn,aARCH);
1277 open_file_shared(fsp,conn,fname,share_mode,3,unixmode,
1278 oplock_request,&rmode,NULL);
1282 if((errno == ENOENT) && bad_path)
1284 unix_ERR_class = ERRDOS;
1285 unix_ERR_code = ERRbadpath;
1288 return(UNIXERROR(ERRDOS,ERRnoaccess));
1291 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1292 close_file(fsp,False);
1293 return(ERROR(ERRDOS,ERRnoaccess));
1296 size = sbuf.st_size;
1297 fmode = dos_mode(conn,fname,&sbuf);
1298 mtime = sbuf.st_mtime;
1301 DEBUG(3,("attempt to open a directory %s\n",fname));
1302 close_file(fsp,False);
1303 return(ERROR(ERRDOS,ERRnoaccess));
1306 outsize = set_message(outbuf,7,0,True);
1307 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1308 SSVAL(outbuf,smb_vwv1,fmode);
1309 if(lp_dos_filetime_resolution(SNUM(conn)) )
1310 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1312 put_dos_date3(outbuf,smb_vwv2,mtime);
1313 SIVAL(outbuf,smb_vwv4,(uint32)size);
1314 SSVAL(outbuf,smb_vwv6,rmode);
1316 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1317 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1320 if(fsp->granted_oplock)
1321 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1326 /****************************************************************************
1327 reply to an open and X
1328 ****************************************************************************/
1329 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1332 int smb_mode = SVAL(inbuf,smb_vwv3);
1333 int smb_attr = SVAL(inbuf,smb_vwv5);
1334 /* Breakout the oplock request bits so we can set the
1335 reply bits separately. */
1336 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1337 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1338 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1340 int open_flags = SVAL(inbuf,smb_vwv2);
1341 int smb_sattr = SVAL(inbuf,smb_vwv4);
1342 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1344 int smb_ofun = SVAL(inbuf,smb_vwv8);
1347 int fmode=0,mtime=0,rmode=0;
1348 SMB_STRUCT_STAT sbuf;
1350 BOOL bad_path = False;
1353 /* If it's an IPC, pass off the pipe handler. */
1355 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1357 /* XXXX we need to handle passed times, sattr and flags */
1359 pstrcpy(fname,smb_buf(inbuf));
1360 unix_convert(fname,conn,0,&bad_path,NULL);
1364 return(ERROR(ERRSRV,ERRnofids));
1366 if (!check_name(fname,conn))
1368 if((errno == ENOENT) && bad_path)
1370 unix_ERR_class = ERRDOS;
1371 unix_ERR_code = ERRbadpath;
1374 return(UNIXERROR(ERRDOS,ERRnoaccess));
1377 unixmode = unix_mode(conn,smb_attr | aARCH);
1379 open_file_shared(fsp,conn,fname,smb_mode,smb_ofun,unixmode,
1380 oplock_request, &rmode,&smb_action);
1384 if((errno == ENOENT) && bad_path)
1386 unix_ERR_class = ERRDOS;
1387 unix_ERR_code = ERRbadpath;
1390 return(UNIXERROR(ERRDOS,ERRnoaccess));
1393 if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1394 close_file(fsp,False);
1395 return(ERROR(ERRDOS,ERRnoaccess));
1398 size = sbuf.st_size;
1399 fmode = dos_mode(conn,fname,&sbuf);
1400 mtime = sbuf.st_mtime;
1402 close_file(fsp,False);
1403 return(ERROR(ERRDOS,ERRnoaccess));
1406 /* If the caller set the extended oplock request bit
1407 and we granted one (by whatever means) - set the
1408 correct bit for extended oplock reply.
1411 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1412 smb_action |= EXTENDED_OPLOCK_GRANTED;
1415 if(ex_oplock_request && fsp->granted_oplock) {
1416 smb_action |= EXTENDED_OPLOCK_GRANTED;
1419 /* If the caller set the core oplock request bit
1420 and we granted one (by whatever means) - set the
1421 correct bit for core oplock reply.
1424 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1425 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1428 if(core_oplock_request && fsp->granted_oplock) {
1429 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1432 set_message(outbuf,15,0,True);
1433 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1434 SSVAL(outbuf,smb_vwv3,fmode);
1435 if(lp_dos_filetime_resolution(SNUM(conn)) )
1436 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1438 put_dos_date3(outbuf,smb_vwv4,mtime);
1439 SIVAL(outbuf,smb_vwv6,(uint32)size);
1440 SSVAL(outbuf,smb_vwv8,rmode);
1441 SSVAL(outbuf,smb_vwv11,smb_action);
1443 return chain_reply(inbuf,outbuf,length,bufsize);
1447 /****************************************************************************
1448 reply to a SMBulogoffX
1449 ****************************************************************************/
1450 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1452 uint16 vuid = SVAL(inbuf,smb_uid);
1453 user_struct *vuser = get_valid_user_struct(vuid);
1456 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1459 /* in user level security we are supposed to close any files
1460 open by this user */
1461 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1462 file_close_user(vuid);
1465 invalidate_vuid(vuid);
1467 set_message(outbuf,2,0,True);
1469 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1471 return chain_reply(inbuf,outbuf,length,bufsize);
1475 /****************************************************************************
1476 reply to a mknew or a create
1477 ****************************************************************************/
1478 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1486 BOOL bad_path = False;
1488 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1490 com = SVAL(inbuf,smb_com);
1492 createmode = SVAL(inbuf,smb_vwv0);
1493 pstrcpy(fname,smb_buf(inbuf)+1);
1494 unix_convert(fname,conn,0,&bad_path,NULL);
1496 if (createmode & aVOLID)
1498 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1501 unixmode = unix_mode(conn,createmode);
1505 return(ERROR(ERRSRV,ERRnofids));
1507 if (!check_name(fname,conn))
1509 if((errno == ENOENT) && bad_path)
1511 unix_ERR_class = ERRDOS;
1512 unix_ERR_code = ERRbadpath;
1515 return(UNIXERROR(ERRDOS,ERRnoaccess));
1520 /* We should fail if file exists. */
1525 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1529 /* Open file in dos compatibility share mode. */
1530 open_file_shared(fsp,conn,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1531 oplock_request, NULL, NULL);
1535 if((errno == ENOENT) && bad_path)
1537 unix_ERR_class = ERRDOS;
1538 unix_ERR_code = ERRbadpath;
1541 return(UNIXERROR(ERRDOS,ERRnoaccess));
1544 outsize = set_message(outbuf,1,0,True);
1545 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1547 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1548 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1551 if(fsp->granted_oplock)
1552 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1554 DEBUG( 2, ( "new file %s\n", fname ) );
1555 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1556 fname, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1562 /****************************************************************************
1563 reply to a create temporary file
1564 ****************************************************************************/
1565 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1572 BOOL bad_path = False;
1574 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1576 createmode = SVAL(inbuf,smb_vwv0);
1577 pstrcpy(fname,smb_buf(inbuf)+1);
1578 pstrcat(fname,"/TMXXXXXX");
1579 unix_convert(fname,conn,0,&bad_path,NULL);
1581 unixmode = unix_mode(conn,createmode);
1585 return(ERROR(ERRSRV,ERRnofids));
1587 if (!check_name(fname,conn))
1589 if((errno == ENOENT) && bad_path)
1591 unix_ERR_class = ERRDOS;
1592 unix_ERR_code = ERRbadpath;
1595 return(UNIXERROR(ERRDOS,ERRnoaccess));
1598 pstrcpy(fname2,(char *)mktemp(fname));
1600 /* Open file in dos compatibility share mode. */
1601 /* We should fail if file exists. */
1602 open_file_shared(fsp,conn,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1603 oplock_request, NULL, NULL);
1607 if((errno == ENOENT) && bad_path)
1609 unix_ERR_class = ERRDOS;
1610 unix_ERR_code = ERRbadpath;
1613 return(UNIXERROR(ERRDOS,ERRnoaccess));
1616 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1617 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1618 CVAL(smb_buf(outbuf),0) = 4;
1619 pstrcpy(smb_buf(outbuf) + 1,fname2);
1621 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1622 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1625 if(fsp->granted_oplock)
1626 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1628 DEBUG( 2, ( "created temp file %s\n", fname2 ) );
1629 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1630 fname2, fsp->fd_ptr->fd, createmode, (int)unixmode ) );
1636 /*******************************************************************
1637 check if a user is allowed to delete a file
1638 ********************************************************************/
1639 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1641 SMB_STRUCT_STAT sbuf;
1644 if (!CAN_WRITE(conn)) return(False);
1646 if (dos_lstat(fname,&sbuf) != 0) return(False);
1647 fmode = dos_mode(conn,fname,&sbuf);
1648 if (fmode & aDIR) return(False);
1649 if (!lp_delete_readonly(SNUM(conn))) {
1650 if (fmode & aRONLY) return(False);
1652 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1654 if (!check_file_sharing(conn,fname,False)) return(False);
1658 /****************************************************************************
1660 ****************************************************************************/
1661 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1670 int error = ERRnoaccess;
1673 BOOL bad_path = False;
1675 *directory = *mask = 0;
1677 dirtype = SVAL(inbuf,smb_vwv0);
1679 pstrcpy(name,smb_buf(inbuf) + 1);
1681 DEBUG(3,("reply_unlink : %s\n",name));
1683 unix_convert(name,conn,0,&bad_path,NULL);
1685 p = strrchr(name,'/');
1687 pstrcpy(directory,"./");
1691 pstrcpy(directory,name);
1695 if (is_mangled(mask))
1696 check_mangled_cache( mask );
1698 has_wild = strchr(mask,'*') || strchr(mask,'?');
1701 pstrcat(directory,"/");
1702 pstrcat(directory,mask);
1703 if (can_delete(directory,conn,dirtype) && !dos_unlink(directory)) count++;
1704 if (!count) exists = file_exist(directory,NULL);
1706 void *dirptr = NULL;
1709 if (check_name(directory,conn))
1710 dirptr = OpenDir(conn, directory, True);
1712 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1713 the pattern matches against the long name, otherwise the short name
1714 We don't implement this yet XXXX
1721 if (strequal(mask,"????????.???"))
1724 while ((dname = ReadDirName(dirptr)))
1727 pstrcpy(fname,dname);
1729 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1731 error = ERRnoaccess;
1732 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1733 if (!can_delete(fname,conn,dirtype)) continue;
1734 if (!dos_unlink(fname)) count++;
1735 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1743 return(ERROR(ERRDOS,error));
1746 if((errno == ENOENT) && bad_path)
1748 unix_ERR_class = ERRDOS;
1749 unix_ERR_code = ERRbadpath;
1751 return(UNIXERROR(ERRDOS,error));
1755 outsize = set_message(outbuf,0,0,True);
1761 /****************************************************************************
1762 reply to a readbraw (core+ protocol)
1763 ****************************************************************************/
1764 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1766 size_t maxcount,mincount;
1769 char *header = outbuf;
1774 * Special check if an oplock break has been issued
1775 * and the readraw request croses on the wire, we must
1776 * return a zero length response here.
1779 if(global_oplock_break)
1781 _smb_setlen(header,0);
1782 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1783 DEBUG(5,("readbraw - oplock break finished\n"));
1787 fsp = file_fsp(inbuf,smb_vwv0);
1789 startpos = IVAL(inbuf,smb_vwv1);
1790 #ifdef LARGE_SMB_OFF_T
1791 if(CVAL(inbuf,smb_wct) == 10) {
1793 * This is a large offset (64 bit) read.
1795 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1797 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n",
1798 (double)startpos ));
1799 _smb_setlen(header,0);
1800 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1804 #endif /* LARGE_SMB_OFF_T */
1805 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1806 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1808 /* ensure we don't overrun the packet size */
1809 maxcount = MIN(65535,maxcount);
1810 maxcount = MAX(mincount,maxcount);
1812 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1813 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fsp->fnum));
1814 _smb_setlen(header,0);
1815 transfer_file(0,Client,(SMB_OFF_T)0,header,4,0);
1819 if (!is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
1821 SMB_OFF_T size = fsp->size;
1822 SMB_OFF_T sizeneeded = startpos + maxcount;
1824 if (size < sizeneeded)
1827 if (sys_fstat(fsp->fd_ptr->fd,&st) == 0)
1829 if (!fsp->can_write)
1833 nread = MIN(maxcount,(size - startpos));
1836 if (nread < mincount)
1839 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
1840 fsp->fnum, (double)startpos,
1841 maxcount, mincount, nread ) );
1846 _smb_setlen(header,nread);
1848 #if USE_READ_PREDICTION
1849 if (!fsp->can_write)
1850 predict = read_predict(fsp->fd_ptr->fd,startpos,header+4,NULL,nread);
1851 #endif /* USE_READ_PREDICTION */
1853 if ((nread-predict) > 0)
1854 seek_file(fsp,startpos + predict);
1856 ret = (ssize_t)transfer_file(fsp->fd_ptr->fd,Client,(SMB_OFF_T)(nread-predict),header,4+predict,
1861 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1862 fsp->fsp_name,startpos,nread,ret));
1864 #else /* UNSAFE_READRAW */
1865 ret = read_file(fsp,header+4,startpos,nread);
1866 if (ret < mincount) ret = 0;
1868 _smb_setlen(header,ret);
1869 transfer_file(0,Client,0,header,4+ret,0);
1870 #endif /* UNSAFE_READRAW */
1872 DEBUG(5,("readbraw finished\n"));
1877 /****************************************************************************
1878 reply to a lockread (core+ protocol)
1879 ****************************************************************************/
1880 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1889 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1891 CHECK_FSP(fsp,conn);
1895 numtoread = SVAL(inbuf,smb_vwv1);
1896 startpos = IVAL(inbuf,smb_vwv2);
1898 outsize = set_message(outbuf,5,3,True);
1899 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1900 data = smb_buf(outbuf) + 3;
1902 if(!do_lock( fsp, conn, numtoread, startpos, F_RDLCK, &eclass, &ecode)) {
1903 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
1905 * A blocking lock was requested. Package up
1906 * this smb into a queued request and push it
1907 * onto the blocking lock queue.
1909 if(push_blocking_lock_request(inbuf, length, -1, 0))
1912 return (ERROR(eclass,ecode));
1915 nread = read_file(fsp,data,startpos,numtoread);
1918 return(UNIXERROR(ERRDOS,ERRnoaccess));
1921 SSVAL(outbuf,smb_vwv0,nread);
1922 SSVAL(outbuf,smb_vwv5,nread+3);
1923 SSVAL(smb_buf(outbuf),1,nread);
1925 DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
1926 fsp->fnum, numtoread, nread ) );
1932 /****************************************************************************
1934 ****************************************************************************/
1935 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1942 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1944 CHECK_FSP(fsp,conn);
1948 numtoread = SVAL(inbuf,smb_vwv1);
1949 startpos = IVAL(inbuf,smb_vwv2);
1951 outsize = set_message(outbuf,5,3,True);
1952 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1953 data = smb_buf(outbuf) + 3;
1955 if (is_locked(fsp,conn,numtoread,startpos, F_RDLCK))
1956 return(ERROR(ERRDOS,ERRlock));
1959 nread = read_file(fsp,data,startpos,numtoread);
1962 return(UNIXERROR(ERRDOS,ERRnoaccess));
1965 SSVAL(outbuf,smb_vwv0,nread);
1966 SSVAL(outbuf,smb_vwv5,nread+3);
1967 CVAL(smb_buf(outbuf),0) = 1;
1968 SSVAL(smb_buf(outbuf),1,nread);
1970 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1971 fsp->fnum, numtoread, nread ) );
1977 /****************************************************************************
1978 reply to a read and X
1979 ****************************************************************************/
1980 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1982 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1983 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1984 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1985 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1989 /* If it's an IPC, pass off the pipe handler. */
1991 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1993 CHECK_FSP(fsp,conn);
1997 set_message(outbuf,12,0,True);
1998 data = smb_buf(outbuf);
2000 #ifdef LARGE_SMB_OFF_T
2001 if(CVAL(inbuf,smb_wct) == 12) {
2003 * This is a large offset (64 bit) read.
2005 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2007 #endif /* LARGE_SMB_OFF_T */
2009 if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK))
2010 return(ERROR(ERRDOS,ERRlock));
2011 nread = read_file(fsp,data,startpos,smb_maxcnt);
2014 return(UNIXERROR(ERRDOS,ERRnoaccess));
2016 SSVAL(outbuf,smb_vwv5,nread);
2017 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2018 SSVAL(smb_buf(outbuf),-2,nread);
2020 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2021 fsp->fnum, smb_mincnt, smb_maxcnt, nread ) );
2023 return chain_reply(inbuf,outbuf,length,bufsize);
2026 /****************************************************************************
2027 reply to a writebraw (core+ or LANMAN1.0 protocol)
2028 ****************************************************************************/
2029 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2032 ssize_t total_written=0;
2033 size_t numtowrite=0;
2038 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2041 CHECK_FSP(fsp,conn);
2045 tcount = IVAL(inbuf,smb_vwv1);
2046 startpos = IVAL(inbuf,smb_vwv3);
2047 write_through = BITSETW(inbuf+smb_vwv7,0);
2049 /* We have to deal with slightly different formats depending
2050 on whether we are using the core+ or lanman1.0 protocol */
2051 if(Protocol <= PROTOCOL_COREPLUS) {
2052 numtowrite = SVAL(smb_buf(inbuf),-2);
2053 data = smb_buf(inbuf);
2055 numtowrite = SVAL(inbuf,smb_vwv10);
2056 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2059 /* force the error type */
2060 CVAL(inbuf,smb_com) = SMBwritec;
2061 CVAL(outbuf,smb_com) = SMBwritec;
2063 if (is_locked(fsp,conn,tcount,startpos, F_WRLCK))
2064 return(ERROR(ERRDOS,ERRlock));
2066 if (seek_file(fsp,startpos) != startpos)
2067 DEBUG(0,("couldn't seek to %.0f in writebraw\n",(double)startpos));
2070 nwritten = write_file(fsp,data,numtowrite);
2072 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2073 fsp->fnum, (double)startpos, numtowrite, nwritten, write_through));
2075 if (nwritten < numtowrite)
2076 return(UNIXERROR(ERRHRD,ERRdiskfull));
2078 total_written = nwritten;
2080 /* Return a message to the redirector to tell it
2081 to send more bytes */
2082 CVAL(outbuf,smb_com) = SMBwritebraw;
2083 SSVALS(outbuf,smb_vwv0,-1);
2084 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2085 send_smb(Client,outbuf);
2087 /* Now read the raw data into the buffer and write it */
2088 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
2089 exit_server("secondary writebraw failed");
2092 /* Even though this is not an smb message, smb_len
2093 returns the generic length of an smb message */
2094 numtowrite = smb_len(inbuf);
2096 if (tcount > nwritten+numtowrite) {
2097 DEBUG(3,("Client overestimated the write %d %d %d\n",
2098 tcount,nwritten,numtowrite));
2101 nwritten = transfer_file(Client,fsp->fd_ptr->fd,(SMB_OFF_T)numtowrite,NULL,0,
2103 total_written += nwritten;
2105 /* Set up outbuf to return the correct return */
2106 outsize = set_message(outbuf,1,0,True);
2107 CVAL(outbuf,smb_com) = SMBwritec;
2108 SSVAL(outbuf,smb_vwv0,total_written);
2110 if (nwritten < (ssize_t)numtowrite) {
2111 CVAL(outbuf,smb_rcls) = ERRHRD;
2112 SSVAL(outbuf,smb_err,ERRdiskfull);
2115 if (lp_syncalways(SNUM(conn)) || write_through)
2116 sync_file(conn,fsp);
2118 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2119 fsp->fnum, (double)startpos, numtowrite, total_written));
2121 /* we won't return a status if write through is not selected - this
2122 follows what WfWg does */
2123 if (!write_through && total_written==tcount)
2129 /****************************************************************************
2130 reply to a writeunlock (core+)
2131 ****************************************************************************/
2132 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2134 ssize_t nwritten = -1;
2140 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2143 CHECK_FSP(fsp,conn);
2147 numtowrite = SVAL(inbuf,smb_vwv1);
2148 startpos = IVAL(inbuf,smb_vwv2);
2149 data = smb_buf(inbuf) + 3;
2151 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2152 return(ERROR(ERRDOS,ERRlock));
2154 seek_file(fsp,startpos);
2156 /* The special X/Open SMB protocol handling of
2157 zero length writes is *NOT* done for
2162 nwritten = write_file(fsp,data,numtowrite);
2164 if (lp_syncalways(SNUM(conn)))
2165 sync_file(conn,fsp);
2167 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2168 return(UNIXERROR(ERRDOS,ERRnoaccess));
2170 if(!do_unlock(fsp, conn, numtowrite, startpos, &eclass, &ecode))
2171 return(ERROR(eclass,ecode));
2173 outsize = set_message(outbuf,1,0,True);
2175 SSVAL(outbuf,smb_vwv0,nwritten);
2177 DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
2178 fsp->fnum, numtowrite, nwritten ) );
2183 /****************************************************************************
2185 ****************************************************************************/
2186 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
2189 ssize_t nwritten = -1;
2192 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2195 CHECK_FSP(fsp,conn);
2199 numtowrite = SVAL(inbuf,smb_vwv1);
2200 startpos = IVAL(inbuf,smb_vwv2);
2201 data = smb_buf(inbuf) + 3;
2203 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2204 return(ERROR(ERRDOS,ERRlock));
2206 seek_file(fsp,startpos);
2208 /* X/Open SMB protocol says that if smb_vwv1 is
2209 zero then the file size should be extended or
2210 truncated to the size given in smb_vwv[2-3] */
2212 nwritten = set_filelen(fsp->fd_ptr->fd, (SMB_OFF_T)startpos);
2214 nwritten = write_file(fsp,data,numtowrite);
2216 if (lp_syncalways(SNUM(conn)))
2217 sync_file(conn,fsp);
2219 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2220 return(UNIXERROR(ERRDOS,ERRnoaccess));
2222 outsize = set_message(outbuf,1,0,True);
2224 SSVAL(outbuf,smb_vwv0,nwritten);
2226 if (nwritten < (ssize_t)numtowrite) {
2227 CVAL(outbuf,smb_rcls) = ERRHRD;
2228 SSVAL(outbuf,smb_err,ERRdiskfull);
2231 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2232 fsp->fnum, numtowrite, nwritten));
2238 /****************************************************************************
2239 reply to a write and X
2240 ****************************************************************************/
2241 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2243 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2244 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2245 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2246 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2247 ssize_t nwritten = -1;
2248 int smb_doff = SVAL(inbuf,smb_vwv11);
2251 CHECK_FSP(fsp,conn);
2255 data = smb_base(inbuf) + smb_doff;
2257 #ifdef LARGE_SMB_OFF_T
2258 if(CVAL(inbuf,smb_wct) == 14) {
2260 * This is a large offset (64 bit) write.
2262 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2264 #endif /* LARGE_SMB_OFF_T */
2266 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2267 return(ERROR(ERRDOS,ERRlock));
2269 seek_file(fsp,startpos);
2271 /* X/Open SMB protocol says that, unlike SMBwrite
2272 if the length is zero then NO truncation is
2273 done, just a write of zero. To truncate a file,
2278 nwritten = write_file(fsp,data,numtowrite);
2280 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2281 return(UNIXERROR(ERRDOS,ERRnoaccess));
2283 set_message(outbuf,6,0,True);
2285 SSVAL(outbuf,smb_vwv2,nwritten);
2287 if (nwritten < (ssize_t)numtowrite) {
2288 CVAL(outbuf,smb_rcls) = ERRHRD;
2289 SSVAL(outbuf,smb_err,ERRdiskfull);
2292 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2293 fsp->fnum, numtowrite, nwritten));
2295 if (lp_syncalways(SNUM(conn)) || write_through)
2296 sync_file(conn,fsp);
2298 return chain_reply(inbuf,outbuf,length,bufsize);
2302 /****************************************************************************
2304 ****************************************************************************/
2305 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2311 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2313 CHECK_FSP(fsp,conn);
2316 mode = SVAL(inbuf,smb_vwv1) & 3;
2317 startpos = IVAL(inbuf,smb_vwv2);
2321 case 0: umode = SEEK_SET; break;
2322 case 1: umode = SEEK_CUR; break;
2323 case 2: umode = SEEK_END; break;
2325 umode = SEEK_SET; break;
2328 res = sys_lseek(fsp->fd_ptr->fd,startpos,umode);
2331 outsize = set_message(outbuf,2,0,True);
2332 SIVALS(outbuf,smb_vwv0,res);
2334 DEBUG(3,("lseek fnum=%d ofs=%.0f mode=%d\n",
2335 fsp->fnum, (double)startpos, mode));
2340 /****************************************************************************
2342 ****************************************************************************/
2343 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2345 int outsize = set_message(outbuf,0,0,True);
2346 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2349 CHECK_FSP(fsp,conn);
2354 file_sync_all(conn);
2356 sync_file(conn,fsp);
2359 DEBUG(3,("flush\n"));
2364 /****************************************************************************
2366 ****************************************************************************/
2367 int reply_exit(connection_struct *conn,
2368 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2370 int outsize = set_message(outbuf,0,0,True);
2371 DEBUG(3,("exit\n"));
2377 /****************************************************************************
2378 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2379 ****************************************************************************/
2380 int reply_close(connection_struct *conn,
2381 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2385 int32 eclass = 0, err = 0;
2386 files_struct *fsp = NULL;
2388 outsize = set_message(outbuf,0,0,True);
2390 /* If it's an IPC, pass off to the pipe handler. */
2392 return reply_pipe_close(conn, inbuf,outbuf);
2395 fsp = file_fsp(inbuf,smb_vwv0);
2398 * We can only use CHECK_FSP if we know it's not a directory.
2401 if(!fsp || !fsp->open || (fsp->conn != conn))
2402 return(ERROR(ERRDOS,ERRbadfid));
2404 if(HAS_CACHED_ERROR(fsp)) {
2405 eclass = fsp->wbmpx_ptr->wr_errclass;
2406 err = fsp->wbmpx_ptr->wr_error;
2409 if(fsp->is_directory) {
2411 * Special case - close NT SMB directory
2414 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
2415 close_directory(fsp);
2418 * Close ordinary file.
2420 mtime = make_unix_date3(inbuf+smb_vwv1);
2422 /* try and set the date */
2423 set_filetime(conn, fsp->fsp_name,mtime);
2425 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2426 fsp->fd_ptr->fd, fsp->fnum,
2427 conn->num_files_open));
2429 close_file(fsp,True);
2432 /* We have a cached error */
2434 return(ERROR(eclass,err));
2440 /****************************************************************************
2441 reply to a writeclose (Core+ protocol)
2442 ****************************************************************************/
2443 int reply_writeclose(connection_struct *conn,
2444 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2447 ssize_t nwritten = -1;
2452 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2454 CHECK_FSP(fsp,conn);
2458 numtowrite = SVAL(inbuf,smb_vwv1);
2459 startpos = IVAL(inbuf,smb_vwv2);
2460 mtime = make_unix_date3(inbuf+smb_vwv4);
2461 data = smb_buf(inbuf) + 1;
2463 if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK))
2464 return(ERROR(ERRDOS,ERRlock));
2466 seek_file(fsp,startpos);
2468 nwritten = write_file(fsp,data,numtowrite);
2470 set_filetime(conn, fsp->fsp_name,mtime);
2472 close_file(fsp,True);
2474 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2475 fsp->fnum, numtowrite, nwritten,
2476 conn->num_files_open));
2479 return(UNIXERROR(ERRDOS,ERRnoaccess));
2481 outsize = set_message(outbuf,1,0,True);
2483 SSVAL(outbuf,smb_vwv0,nwritten);
2488 /****************************************************************************
2490 ****************************************************************************/
2491 int reply_lock(connection_struct *conn,
2492 char *inbuf,char *outbuf, int length, int dum_buffsize)
2494 int outsize = set_message(outbuf,0,0,True);
2495 SMB_OFF_T count,offset;
2498 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2500 CHECK_FSP(fsp,conn);
2503 count = IVAL(inbuf,smb_vwv1);
2504 offset = IVAL(inbuf,smb_vwv3);
2506 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2507 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count));
2509 if (!do_lock(fsp, conn, count, offset, F_WRLCK, &eclass, &ecode)) {
2510 if((ecode == ERRlock) && lp_blocking_locks(SNUM(conn))) {
2512 * A blocking lock was requested. Package up
2513 * this smb into a queued request and push it
2514 * onto the blocking lock queue.
2516 if(push_blocking_lock_request(inbuf, length, -1, 0))
2519 return (ERROR(eclass,ecode));
2526 /****************************************************************************
2528 ****************************************************************************/
2529 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2531 int outsize = set_message(outbuf,0,0,True);
2532 SMB_OFF_T count,offset;
2535 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2537 CHECK_FSP(fsp,conn);
2540 count = IVAL(inbuf,smb_vwv1);
2541 offset = IVAL(inbuf,smb_vwv3);
2543 if(!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
2544 return (ERROR(eclass,ecode));
2546 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2547 fsp->fd_ptr->fd, fsp->fnum, (double)offset, (double)count ) );
2553 /****************************************************************************
2555 ****************************************************************************/
2556 int reply_tdis(connection_struct *conn,
2557 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2559 int outsize = set_message(outbuf,0,0,True);
2562 vuid = SVAL(inbuf,smb_uid);
2565 DEBUG(4,("Invalid connection in tdis\n"));
2566 return(ERROR(ERRSRV,ERRinvnid));
2571 close_cnum(conn,vuid);
2578 /****************************************************************************
2580 ****************************************************************************/
2581 int reply_echo(connection_struct *conn,
2582 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2584 int smb_reverb = SVAL(inbuf,smb_vwv0);
2586 int data_len = smb_buflen(inbuf);
2587 int outsize = set_message(outbuf,1,data_len,True);
2589 /* copy any incoming data back out */
2591 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2593 if (smb_reverb > 100) {
2594 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2598 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2599 SSVAL(outbuf,smb_vwv0,seq_num);
2601 smb_setlen(outbuf,outsize - 4);
2603 send_smb(Client,outbuf);
2606 DEBUG(3,("echo %d times\n", smb_reverb));
2612 /****************************************************************************
2613 reply to a printopen
2614 ****************************************************************************/
2615 int reply_printopen(connection_struct *conn,
2616 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2623 *fname = *fname2 = 0;
2625 if (!CAN_PRINT(conn))
2626 return(ERROR(ERRDOS,ERRnoaccess));
2631 pstrcpy(s,smb_buf(inbuf)+1);
2634 if (!(isalnum((int)*p) || strchr("._-",*p)))
2639 if (strlen(s) > 10) s[10] = 0;
2641 slprintf(fname,sizeof(fname)-1, "%s.XXXXXX",s);
2646 return(ERROR(ERRSRV,ERRnofids));
2648 pstrcpy(fname2,(char *)mktemp(fname));
2650 if (!check_name(fname2,conn)) {
2652 return(ERROR(ERRDOS,ERRnoaccess));
2655 /* Open for exclusive use, write only. */
2656 open_file_shared(fsp,conn,fname2,
2657 (DENY_ALL<<4)|1, 0x12, unix_mode(conn,0),
2662 return(UNIXERROR(ERRDOS,ERRnoaccess));
2665 /* force it to be a print file */
2666 fsp->print_file = True;
2668 outsize = set_message(outbuf,1,0,True);
2669 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2671 DEBUG(3,("openprint %s fd=%d fnum=%d\n",
2672 fname2, fsp->fd_ptr->fd, fsp->fnum));
2678 /****************************************************************************
2679 reply to a printclose
2680 ****************************************************************************/
2681 int reply_printclose(connection_struct *conn,
2682 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2684 int outsize = set_message(outbuf,0,0,True);
2685 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2687 CHECK_FSP(fsp,conn);
2690 if (!CAN_PRINT(conn))
2691 return(ERROR(ERRDOS,ERRnoaccess));
2693 DEBUG(3,("printclose fd=%d fnum=%d\n",
2694 fsp->fd_ptr->fd,fsp->fnum));
2696 close_file(fsp,True);
2702 /****************************************************************************
2703 reply to a printqueue
2704 ****************************************************************************/
2705 int reply_printqueue(connection_struct *conn,
2706 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2708 int outsize = set_message(outbuf,2,3,True);
2709 int max_count = SVAL(inbuf,smb_vwv0);
2710 int start_index = SVAL(inbuf,smb_vwv1);
2712 /* we used to allow the client to get the cnum wrong, but that
2713 is really quite gross and only worked when there was only
2714 one printer - I think we should now only accept it if they
2715 get it right (tridge) */
2716 if (!CAN_PRINT(conn))
2717 return(ERROR(ERRDOS,ERRnoaccess));
2719 SSVAL(outbuf,smb_vwv0,0);
2720 SSVAL(outbuf,smb_vwv1,0);
2721 CVAL(smb_buf(outbuf),0) = 1;
2722 SSVAL(smb_buf(outbuf),1,0);
2724 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2725 start_index, max_count));
2728 print_queue_struct *queue = NULL;
2729 char *p = smb_buf(outbuf) + 3;
2730 int count = get_printqueue(SNUM(conn), conn,&queue,NULL);
2731 int num_to_get = ABS(max_count);
2732 int first = (max_count>0?start_index:start_index+max_count+1);
2738 num_to_get = MIN(num_to_get,count-first);
2741 for (i=first;i<first+num_to_get;i++) {
2742 put_dos_date2(p,0,queue[i].time);
2743 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2744 SSVAL(p,5,printjob_encode(SNUM(conn),
2746 SIVAL(p,7,queue[i].size);
2748 StrnCpy(p+12,queue[i].user,16);
2753 outsize = set_message(outbuf,2,28*count+3,False);
2754 SSVAL(outbuf,smb_vwv0,count);
2755 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2756 CVAL(smb_buf(outbuf),0) = 1;
2757 SSVAL(smb_buf(outbuf),1,28*count);
2760 if (queue) free(queue);
2762 DEBUG(3,("%d entries returned in queue\n",count));
2769 /****************************************************************************
2770 reply to a printwrite
2771 ****************************************************************************/
2772 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2775 int outsize = set_message(outbuf,0,0,True);
2777 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2779 if (!CAN_PRINT(conn))
2780 return(ERROR(ERRDOS,ERRnoaccess));
2782 CHECK_FSP(fsp,conn);
2786 numtowrite = SVAL(smb_buf(inbuf),1);
2787 data = smb_buf(inbuf) + 3;
2789 if (write_file(fsp,data,numtowrite) != numtowrite)
2790 return(UNIXERROR(ERRDOS,ERRnoaccess));
2792 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2798 /****************************************************************************
2800 ****************************************************************************/
2801 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2804 int outsize,ret= -1;
2805 BOOL bad_path = False;
2807 pstrcpy(directory,smb_buf(inbuf) + 1);
2808 unix_convert(directory,conn,0,&bad_path,NULL);
2810 if (check_name(directory, conn))
2811 ret = dos_mkdir(directory,unix_mode(conn,aDIR));
2815 if((errno == ENOENT) && bad_path)
2817 unix_ERR_class = ERRDOS;
2818 unix_ERR_code = ERRbadpath;
2820 return(UNIXERROR(ERRDOS,ERRnoaccess));
2823 outsize = set_message(outbuf,0,0,True);
2825 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, ret ) );
2830 /****************************************************************************
2831 Static function used by reply_rmdir to delete an entire directory
2833 ****************************************************************************/
2834 static BOOL recursive_rmdir(char *directory)
2838 void *dirptr = OpenDir(NULL, directory, False);
2843 while((dname = ReadDirName(dirptr)))
2848 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2851 /* Construct the full name. */
2852 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2858 pstrcpy(fullname, directory);
2859 pstrcat(fullname, "/");
2860 pstrcat(fullname, dname);
2862 if(dos_lstat(fullname, &st) != 0)
2868 if(st.st_mode & S_IFDIR)
2870 if(recursive_rmdir(fullname)!=0)
2875 if(dos_rmdir(fullname) != 0)
2881 else if(dos_unlink(fullname) != 0)
2891 /****************************************************************************
2893 ****************************************************************************/
2894 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2899 BOOL bad_path = False;
2901 pstrcpy(directory,smb_buf(inbuf) + 1);
2902 unix_convert(directory,conn, NULL,&bad_path,NULL);
2904 if (check_name(directory,conn))
2907 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2908 ok = (dos_rmdir(directory) == 0);
2909 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(conn)))
2911 /* Check to see if the only thing in this directory are
2912 vetoed files/directories. If so then delete them and
2913 retry. If we fail to delete any of them (and we *don't*
2914 do a recursive delete) then fail the rmdir. */
2915 BOOL all_veto_files = True;
2917 void *dirptr = OpenDir(conn, directory, False);
2921 int dirpos = TellDir(dirptr);
2922 while ((dname = ReadDirName(dirptr)))
2924 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2926 if(!IS_VETO_PATH(conn, dname))
2928 all_veto_files = False;
2934 SeekDir(dirptr,dirpos);
2935 while ((dname = ReadDirName(dirptr)))
2940 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2943 /* Construct the full name. */
2944 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2949 pstrcpy(fullname, directory);
2950 pstrcat(fullname, "/");
2951 pstrcat(fullname, dname);
2953 if(dos_lstat(fullname, &st) != 0)
2955 if(st.st_mode & S_IFDIR)
2957 if(lp_recursive_veto_delete(SNUM(conn)))
2959 if(recursive_rmdir(fullname) != 0)
2962 if(dos_rmdir(fullname) != 0)
2965 else if(dos_unlink(fullname) != 0)
2969 /* Retry the rmdir */
2970 ok = (dos_rmdir(directory) == 0);
2980 DEBUG(3,("couldn't remove directory %s : %s\n",
2981 directory,strerror(errno)));
2986 if((errno == ENOENT) && bad_path)
2988 unix_ERR_class = ERRDOS;
2989 unix_ERR_code = ERRbadpath;
2991 return(UNIXERROR(ERRDOS,ERRbadpath));
2994 outsize = set_message(outbuf,0,0,True);
2996 DEBUG( 3, ( "rmdir %s\n", directory ) );
3002 /*******************************************************************
3003 resolve wildcards in a filename rename
3004 ********************************************************************/
3005 static BOOL resolve_wildcards(char *name1,char *name2)
3007 fstring root1,root2;
3011 name1 = strrchr(name1,'/');
3012 name2 = strrchr(name2,'/');
3014 if (!name1 || !name2) return(False);
3016 fstrcpy(root1,name1);
3017 fstrcpy(root2,name2);
3018 p = strrchr(root1,'.');
3025 p = strrchr(root2,'.');
3057 pstrcpy(name2,root2);
3060 pstrcat(name2,ext2);
3066 /*******************************************************************
3067 check if a user is allowed to rename a file
3068 ********************************************************************/
3069 static BOOL can_rename(char *fname,connection_struct *conn)
3071 SMB_STRUCT_STAT sbuf;
3073 if (!CAN_WRITE(conn)) return(False);
3075 if (dos_lstat(fname,&sbuf) != 0) return(False);
3076 if (!check_file_sharing(conn,fname,True)) return(False);
3081 /****************************************************************************
3082 The guts of the rename command, split out so it may be called by the NT SMB
3084 ****************************************************************************/
3085 int rename_internals(connection_struct *conn,
3086 char *inbuf, char *outbuf, char *name,
3087 char *newname, BOOL replace_if_exists)
3091 pstring newname_last_component;
3094 BOOL bad_path1 = False;
3095 BOOL bad_path2 = False;
3097 int error = ERRnoaccess;
3100 *directory = *mask = 0;
3102 unix_convert(name,conn,0,&bad_path1,NULL);
3103 unix_convert(newname,conn,newname_last_component,&bad_path2,NULL);
3106 * Split the old name into directory and last component
3107 * strings. Note that unix_convert may have stripped off a
3108 * leading ./ from both name and newname if the rename is
3109 * at the root of the share. We need to make sure either both
3110 * name and newname contain a / character or neither of them do
3111 * as this is checked in resolve_wildcards().
3114 p = strrchr(name,'/');
3116 pstrcpy(directory,".");
3120 pstrcpy(directory,name);
3122 *p = '/'; /* Replace needed for exceptional test below. */
3125 if (is_mangled(mask))
3126 check_mangled_cache( mask );
3128 has_wild = strchr(mask,'*') || strchr(mask,'?');
3132 * No wildcards - just process the one file.
3134 BOOL is_short_name = is_8_3(name, True);
3136 /* Add a terminating '/' to the directory name. */
3137 pstrcat(directory,"/");
3138 pstrcat(directory,mask);
3140 /* Ensure newname contains a '/' also */
3141 if(strrchr(newname,'/') == 0) {
3144 pstrcpy(tmpstr, "./");
3145 pstrcat(tmpstr, newname);
3146 pstrcpy(newname, tmpstr);
3149 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",
3150 case_sensitive, case_preserve, short_case_preserve, directory,
3151 newname, newname_last_component, is_short_name));
3154 * Check for special case with case preserving and not
3155 * case sensitive, if directory and newname are identical,
3156 * and the old last component differs from the original
3157 * last component only by case, then we should allow
3158 * the rename (user is trying to change the case of the
3161 if((case_sensitive == False) &&
3162 (((case_preserve == True) &&
3163 (is_short_name == False)) ||
3164 ((short_case_preserve == True) &&
3165 (is_short_name == True))) &&
3166 strcsequal(directory, newname)) {
3167 pstring newname_modified_last_component;
3170 * Get the last component of the modified name.
3171 * Note that we guarantee that newname contains a '/'
3174 p = strrchr(newname,'/');
3175 pstrcpy(newname_modified_last_component,p+1);
3177 if(strcsequal(newname_modified_last_component,
3178 newname_last_component) == False) {
3180 * Replace the modified last component with
3183 pstrcpy(p+1, newname_last_component);
3187 if(replace_if_exists) {
3189 * NT SMB specific flag - rename can overwrite
3190 * file with the same name so don't check for
3193 if(resolve_wildcards(directory,newname) &&
3194 can_rename(directory,conn) &&
3195 !dos_rename(directory,newname))
3198 if (resolve_wildcards(directory,newname) &&
3199 can_rename(directory,conn) &&
3200 !file_exist(newname,NULL) &&
3201 !dos_rename(directory,newname))
3205 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3206 directory,newname));
3208 if (!count) exists = file_exist(directory,NULL);
3209 if (!count && exists && file_exist(newname,NULL)) {
3215 * Wildcards - process each file that matches.
3217 void *dirptr = NULL;
3221 if (check_name(directory,conn))
3222 dirptr = OpenDir(conn, directory, True);
3227 if (strequal(mask,"????????.???"))
3230 while ((dname = ReadDirName(dirptr))) {
3232 pstrcpy(fname,dname);
3234 if(!mask_match(fname, mask, case_sensitive, False))
3237 error = ERRnoaccess;
3238 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3239 if (!can_rename(fname,conn)) {
3240 DEBUG(6,("rename %s refused\n", fname));
3243 pstrcpy(destname,newname);
3245 if (!resolve_wildcards(fname,destname)) {
3246 DEBUG(6,("resolve_wildcards %s %s failed\n", fname, destname));
3250 if (!replace_if_exists && file_exist(destname,NULL)) {
3251 DEBUG(6,("file_exist %s\n", destname));
3256 if (!dos_rename(fname,destname))
3258 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3266 return(ERROR(ERRDOS,error));
3268 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3269 unix_ERR_class = ERRDOS;
3270 unix_ERR_code = ERRbadpath;
3272 return(UNIXERROR(ERRDOS,error));
3279 /****************************************************************************
3281 ****************************************************************************/
3283 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3289 pstrcpy(name,smb_buf(inbuf) + 1);
3290 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3292 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3294 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3296 outsize = set_message(outbuf,0,0,True);
3301 /*******************************************************************
3302 copy a file as part of a reply_copy
3303 ******************************************************************/
3304 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3305 int count,BOOL target_is_directory)
3310 files_struct *fsp1,*fsp2;
3313 pstrcpy(dest,dest1);
3314 if (target_is_directory) {
3315 char *p = strrchr(src,'/');
3324 if (!file_exist(src,&st)) return(False);
3327 if (!fsp1) return(False);
3328 open_file_shared(fsp1,conn,src,(DENY_NONE<<4),
3329 1,0,0,&Access,&action);
3336 if (!target_is_directory && count)
3341 close_file(fsp1,False);
3344 open_file_shared(fsp2,conn,dest,(DENY_NONE<<4)|1,
3345 ofun,st.st_mode,0,&Access,&action);
3348 close_file(fsp1,False);
3353 if ((ofun&3) == 1) {
3354 sys_lseek(fsp2->fd_ptr->fd,0,SEEK_END);
3358 ret = transfer_file(fsp1->fd_ptr->fd,
3359 fsp2->fd_ptr->fd,st.st_size,NULL,0,0);
3361 close_file(fsp1,False);
3362 close_file(fsp2,False);
3364 return(ret == st.st_size);
3369 /****************************************************************************
3370 reply to a file copy.
3371 ****************************************************************************/
3372 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3377 pstring mask,newname;
3380 int error = ERRnoaccess;
3383 int tid2 = SVAL(inbuf,smb_vwv0);
3384 int ofun = SVAL(inbuf,smb_vwv1);
3385 int flags = SVAL(inbuf,smb_vwv2);
3386 BOOL target_is_directory=False;
3387 BOOL bad_path1 = False;
3388 BOOL bad_path2 = False;
3390 *directory = *mask = 0;
3392 pstrcpy(name,smb_buf(inbuf));
3393 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3395 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3397 if (tid2 != conn->cnum) {
3398 /* can't currently handle inter share copies XXXX */
3399 DEBUG(3,("Rejecting inter-share copy\n"));
3400 return(ERROR(ERRSRV,ERRinvdevice));
3403 unix_convert(name,conn,0,&bad_path1,NULL);
3404 unix_convert(newname,conn,0,&bad_path2,NULL);
3406 target_is_directory = directory_exist(newname,NULL);
3408 if ((flags&1) && target_is_directory) {
3409 return(ERROR(ERRDOS,ERRbadfile));
3412 if ((flags&2) && !target_is_directory) {
3413 return(ERROR(ERRDOS,ERRbadpath));
3416 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3417 /* wants a tree copy! XXXX */
3418 DEBUG(3,("Rejecting tree copy\n"));
3419 return(ERROR(ERRSRV,ERRerror));
3422 p = strrchr(name,'/');
3424 pstrcpy(directory,"./");
3428 pstrcpy(directory,name);
3432 if (is_mangled(mask))
3433 check_mangled_cache( mask );
3435 has_wild = strchr(mask,'*') || strchr(mask,'?');
3438 pstrcat(directory,"/");
3439 pstrcat(directory,mask);
3440 if (resolve_wildcards(directory,newname) &&
3441 copy_file(directory,newname,conn,ofun,
3442 count,target_is_directory)) count++;
3443 if (!count) exists = file_exist(directory,NULL);
3445 void *dirptr = NULL;
3449 if (check_name(directory,conn))
3450 dirptr = OpenDir(conn, directory, True);
3456 if (strequal(mask,"????????.???"))
3459 while ((dname = ReadDirName(dirptr)))
3462 pstrcpy(fname,dname);
3464 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3466 error = ERRnoaccess;
3467 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3468 pstrcpy(destname,newname);
3469 if (resolve_wildcards(fname,destname) &&
3470 copy_file(directory,newname,conn,ofun,
3471 count,target_is_directory)) count++;
3472 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3480 return(ERROR(ERRDOS,error));
3483 if((errno == ENOENT) && (bad_path1 || bad_path2))
3485 unix_ERR_class = ERRDOS;
3486 unix_ERR_code = ERRbadpath;
3488 return(UNIXERROR(ERRDOS,error));
3492 outsize = set_message(outbuf,1,0,True);
3493 SSVAL(outbuf,smb_vwv0,count);
3498 /****************************************************************************
3500 ****************************************************************************/
3501 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3509 if (!CAN_SETDIR(snum))
3510 return(ERROR(ERRDOS,ERRnoaccess));
3512 pstrcpy(newdir,smb_buf(inbuf) + 1);
3515 if (strlen(newdir) == 0) {
3518 ok = directory_exist(newdir,NULL);
3520 string_set(&conn->connectpath,newdir);
3525 return(ERROR(ERRDOS,ERRbadpath));
3527 outsize = set_message(outbuf,0,0,True);
3528 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3530 DEBUG(3,("setdir %s\n", newdir));
3535 /****************************************************************************
3536 reply to a lockingX request
3537 ****************************************************************************/
3538 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3540 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3541 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3543 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3545 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3546 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3547 SMB_OFF_T count, offset;
3548 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3551 uint32 ecode=0, dummy2;
3552 int eclass=0, dummy1;
3553 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
3554 CHECK_FSP(fsp,conn);
3557 data = smb_buf(inbuf);
3559 /* Check if this is an oplock break on a file
3560 we have granted an oplock on.
3562 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
3565 SMB_DEV_T dev = fsp->fd_ptr->dev;
3566 SMB_INO_T inode = fsp->fd_ptr->inode;
3568 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3571 * Make sure we have granted an oplock on this file.
3573 if(!fsp->granted_oplock)
3575 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3576 no oplock granted on this file.\n", fsp->fnum));
3577 return ERROR(ERRDOS,ERRlock);
3580 /* Remove the oplock flag from the sharemode. */
3581 lock_share_entry(fsp->conn, dev, inode, &token);
3582 if(remove_share_oplock(fsp, token)==False) {
3584 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3585 dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode));
3587 unlock_share_entry(fsp->conn, dev, inode, token);
3589 unlock_share_entry(fsp->conn, dev, inode, token);
3591 /* Clear the granted flag and return. */
3592 fsp->granted_oplock = False;
3595 /* if this is a pure oplock break request then don't send a reply */
3596 if (num_locks == 0 && num_ulocks == 0)
3598 /* Sanity check - ensure a pure oplock break is not a
3600 if(CVAL(inbuf,smb_vwv0) != 0xff)
3601 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3602 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3607 /* Data now points at the beginning of the list
3608 of smb_unlkrng structs */
3609 for(i = 0; i < (int)num_ulocks; i++) {
3610 if(!large_file_format) {
3611 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3612 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3614 #ifdef LARGE_SMB_OFF_T
3616 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3617 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3618 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3619 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3621 #endif /* LARGE_SMB_OFF_T */
3623 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
3624 (double)offset, (double)count, fsp->fsp_name ));
3626 if(!do_unlock(fsp,conn,count,offset,&eclass, &ecode))
3627 return ERROR(eclass,ecode);
3630 /* Setup the timeout in seconds. */
3631 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3633 /* Now do any requested locks */
3634 data += ((large_file_format ? 20 : 10)*num_ulocks);
3636 /* Data now points at the beginning of the list
3637 of smb_lkrng structs */
3639 for(i = 0; i < (int)num_locks; i++) {
3640 if(!large_file_format) {
3641 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3642 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3644 #ifdef LARGE_SMB_OFF_T
3646 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3647 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3648 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3649 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3651 #endif /* LARGE_SMB_OFF_T */
3653 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
3654 (double)offset, (double)count, fsp->fsp_name ));
3656 if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
3658 if((ecode == ERRlock) && (lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3660 * A blocking lock was requested. Package up
3661 * this smb into a queued request and push it
3662 * onto the blocking lock queue.
3664 if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
3671 /* If any of the above locks failed, then we must unlock
3672 all of the previous locks (X/Open spec). */
3673 if(i != num_locks && num_locks != 0) {
3674 for(; i >= 0; i--) {
3675 if(!large_file_format) {
3676 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3677 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3679 #ifdef LARGE_SMB_OFF_T
3681 count = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(i))) << 32) |
3682 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(i)));
3683 offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) |
3684 ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i)));
3686 #endif /* LARGE_SMB_OFF_T */
3688 do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
3690 return ERROR(eclass,ecode);
3693 set_message(outbuf,2,0,True);
3695 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3696 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3698 return chain_reply(inbuf,outbuf,length,bufsize);
3702 /****************************************************************************
3703 reply to a SMBreadbmpx (read block multiplex) request
3704 ****************************************************************************/
3705 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3716 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3718 /* this function doesn't seem to work - disable by default */
3720 return(ERROR(ERRSRV,ERRuseSTD));
3722 outsize = set_message(outbuf,8,0,True);
3724 CHECK_FSP(fsp,conn);
3728 startpos = IVAL(inbuf,smb_vwv1);
3729 maxcount = SVAL(inbuf,smb_vwv3);
3731 data = smb_buf(outbuf);
3732 pad = ((long)data)%4;
3733 if (pad) pad = 4 - pad;
3736 max_per_packet = bufsize-(outsize+pad);
3740 if (is_locked(fsp,conn,maxcount,startpos, F_RDLCK))
3741 return(ERROR(ERRDOS,ERRlock));
3745 size_t N = MIN(max_per_packet,tcount-total_read);
3747 nread = read_file(fsp,data,startpos,N);
3749 if (nread <= 0) nread = 0;
3751 if (nread < (ssize_t)N)
3752 tcount = total_read + nread;
3754 set_message(outbuf,8,nread,False);
3755 SIVAL(outbuf,smb_vwv0,startpos);
3756 SSVAL(outbuf,smb_vwv2,tcount);
3757 SSVAL(outbuf,smb_vwv6,nread);
3758 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3760 send_smb(Client,outbuf);
3762 total_read += nread;
3765 while (total_read < (ssize_t)tcount);
3770 /****************************************************************************
3771 reply to a SMBwritebmpx (write block multiplex primary) request
3772 ****************************************************************************/
3773 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3776 ssize_t nwritten = -1;
3783 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3785 CHECK_FSP(fsp,conn);
3789 tcount = SVAL(inbuf,smb_vwv1);
3790 startpos = IVAL(inbuf,smb_vwv3);
3791 write_through = BITSETW(inbuf+smb_vwv7,0);
3792 numtowrite = SVAL(inbuf,smb_vwv10);
3793 smb_doff = SVAL(inbuf,smb_vwv11);
3795 data = smb_base(inbuf) + smb_doff;
3797 /* If this fails we need to send an SMBwriteC response,
3798 not an SMBwritebmpx - set this up now so we don't forget */
3799 CVAL(outbuf,smb_com) = SMBwritec;
3801 if (is_locked(fsp,conn,tcount,startpos,F_WRLCK))
3802 return(ERROR(ERRDOS,ERRlock));
3804 seek_file(fsp,startpos);
3805 nwritten = write_file(fsp,data,numtowrite);
3807 if(lp_syncalways(SNUM(conn)) || write_through)
3808 sync_file(conn,fsp);
3810 if(nwritten < (ssize_t)numtowrite)
3811 return(UNIXERROR(ERRHRD,ERRdiskfull));
3813 /* If the maximum to be written to this file
3814 is greater than what we just wrote then set
3815 up a secondary struct to be attached to this
3816 fd, we will use this to cache error messages etc. */
3817 if((ssize_t)tcount > nwritten)
3819 write_bmpx_struct *wbms;
3820 if(fsp->wbmpx_ptr != NULL)
3821 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
3823 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3826 DEBUG(0,("Out of memory in reply_readmpx\n"));
3827 return(ERROR(ERRSRV,ERRnoresource));
3829 wbms->wr_mode = write_through;
3830 wbms->wr_discard = False; /* No errors yet */
3831 wbms->wr_total_written = nwritten;
3832 wbms->wr_errclass = 0;
3834 fsp->wbmpx_ptr = wbms;
3837 /* We are returning successfully, set the message type back to
3839 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3841 outsize = set_message(outbuf,1,0,True);
3843 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3845 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
3846 fsp->fnum, numtowrite, nwritten ) );
3848 if (write_through && tcount==nwritten) {
3849 /* we need to send both a primary and a secondary response */
3850 smb_setlen(outbuf,outsize - 4);
3851 send_smb(Client,outbuf);
3853 /* now the secondary */
3854 outsize = set_message(outbuf,1,0,True);
3855 CVAL(outbuf,smb_com) = SMBwritec;
3856 SSVAL(outbuf,smb_vwv0,nwritten);
3863 /****************************************************************************
3864 reply to a SMBwritebs (write block multiplex secondary) request
3865 ****************************************************************************/
3866 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3869 ssize_t nwritten = -1;
3876 write_bmpx_struct *wbms;
3877 BOOL send_response = False;
3878 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3880 CHECK_FSP(fsp,conn);
3883 tcount = SVAL(inbuf,smb_vwv1);
3884 startpos = IVAL(inbuf,smb_vwv2);
3885 numtowrite = SVAL(inbuf,smb_vwv6);
3886 smb_doff = SVAL(inbuf,smb_vwv7);
3888 data = smb_base(inbuf) + smb_doff;
3890 /* We need to send an SMBwriteC response, not an SMBwritebs */
3891 CVAL(outbuf,smb_com) = SMBwritec;
3893 /* This fd should have an auxiliary struct attached,
3894 check that it does */
3895 wbms = fsp->wbmpx_ptr;
3896 if(!wbms) return(-1);
3898 /* If write through is set we can return errors, else we must
3900 write_through = wbms->wr_mode;
3902 /* Check for an earlier error */
3903 if(wbms->wr_discard)
3904 return -1; /* Just discard the packet */
3906 seek_file(fsp,startpos);
3907 nwritten = write_file(fsp,data,numtowrite);
3909 if(lp_syncalways(SNUM(conn)) || write_through)
3910 sync_file(conn,fsp);
3912 if (nwritten < (ssize_t)numtowrite)
3916 /* We are returning an error - we can delete the aux struct */
3917 if (wbms) free((char *)wbms);
3918 fsp->wbmpx_ptr = NULL;
3919 return(ERROR(ERRHRD,ERRdiskfull));
3921 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3924 /* Increment the total written, if this matches tcount
3925 we can discard the auxiliary struct (hurrah !) and return a writeC */
3926 wbms->wr_total_written += nwritten;
3927 if(wbms->wr_total_written >= tcount)
3931 outsize = set_message(outbuf,1,0,True);
3932 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3933 send_response = True;
3937 fsp->wbmpx_ptr = NULL;
3947 /****************************************************************************
3948 reply to a SMBsetattrE
3949 ****************************************************************************/
3950 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3952 struct utimbuf unix_times;
3954 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3956 outsize = set_message(outbuf,0,0,True);
3958 CHECK_FSP(fsp,conn);
3961 /* Convert the DOS times into unix times. Ignore create
3962 time as UNIX can't set this.
3964 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3965 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3968 * Patch from Ray Frush <frush@engr.colostate.edu>
3969 * Sometimes times are sent as zero - ignore them.
3972 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3974 /* Ignore request */
3977 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
3978 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
3982 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3984 /* set modify time = to access time if modify time was 0 */
3985 unix_times.modtime = unix_times.actime;
3988 /* Set the date on this file */
3989 if(file_utime(conn, fsp->fsp_name, &unix_times))
3990 return(ERROR(ERRDOS,ERRnoaccess));
3992 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
3993 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
3999 /****************************************************************************
4000 reply to a SMBgetattrE
4001 ****************************************************************************/
4002 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4004 SMB_STRUCT_STAT sbuf;
4007 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4009 outsize = set_message(outbuf,11,0,True);
4011 CHECK_FSP(fsp,conn);
4014 /* Do an fstat on this file */
4015 if(sys_fstat(fsp->fd_ptr->fd, &sbuf))
4016 return(UNIXERROR(ERRDOS,ERRnoaccess));
4018 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4020 /* Convert the times into dos times. Set create
4021 date to be last modify date as UNIX doesn't save
4023 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4024 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4025 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4028 SIVAL(outbuf,smb_vwv6,0);
4029 SIVAL(outbuf,smb_vwv8,0);
4033 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4034 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
4036 SSVAL(outbuf,smb_vwv10, mode);
4038 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));