2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1997
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
30 /* look in server.c for some explanation of these variables */
32 extern int DEBUGLEVEL
;
35 extern int chain_fnum
;
36 extern char magic_char
;
37 extern connection_struct Connections
[];
38 extern files_struct Files
[];
39 extern BOOL case_sensitive
;
40 extern BOOL case_preserve
;
41 extern BOOL short_case_preserve
;
42 extern pstring sesssetup_user
;
43 extern fstring myworkgroup
;
45 extern int global_oplock_break
;
47 /* this macro should always be used to extract an fnum (smb_fid) from
48 a packet to ensure chaining works correctly */
49 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
52 /****************************************************************************
53 report a possible attack via the password buffer overflow bug
54 ****************************************************************************/
55 static void overflow_attack(int len
)
57 DEBUG(0,("ERROR: Invalid password length %d\n", len
));
58 DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n"));
59 DEBUG(0,("Attack was from IP=%s\n", client_addr()));
60 exit_server("possible attack");
64 /****************************************************************************
65 reply to an special message
66 ****************************************************************************/
67 int reply_special(char *inbuf
,char *outbuf
)
70 int msg_type
= CVAL(inbuf
,0);
71 int msg_flags
= CVAL(inbuf
,1);
73 extern fstring remote_machine
;
74 extern fstring local_machine
;
82 case 0x81: /* session request */
83 CVAL(outbuf
,0) = 0x82;
85 if (name_len(inbuf
+4) > 50 || name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
86 DEBUG(0,("Invalid name length in session request\n"));
89 name_extract(inbuf
,4,name1
);
90 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
91 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
94 fstrcpy(remote_machine
,name2
);
95 trim_string(remote_machine
," "," ");
96 p
= strchr(remote_machine
,' ');
97 strlower(remote_machine
);
100 fstrcpy(local_machine
,name1
);
101 trim_string(local_machine
," "," ");
102 p
= strchr(local_machine
,' ');
103 strlower(local_machine
);
106 add_session_user(remote_machine
);
108 reload_services(True
);
113 case 0x89: /* session keepalive request
114 (some old clients produce this?) */
115 CVAL(outbuf
,0) = 0x85;
119 case 0x82: /* positive session response */
120 case 0x83: /* negative session response */
121 case 0x84: /* retarget session response */
122 DEBUG(0,("Unexpected session response\n"));
125 case 0x85: /* session keepalive */
130 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",
131 timestring(),msg_type
,msg_flags
));
137 /*******************************************************************
138 work out what error to give to a failed connection
139 ********************************************************************/
140 static int connection_error(char *inbuf
,char *outbuf
,int connection_num
)
142 switch (connection_num
)
145 return(ERROR(ERRSRV
,ERRnoresource
));
147 return(ERROR(ERRSRV
,ERRbaduid
));
149 return(ERROR(ERRSRV
,ERRinvdevice
));
151 return(ERROR(ERRSRV
,ERRinvnetname
));
153 return(ERROR(ERRSRV
,ERRaccess
));
155 return(ERROR(ERRDOS
,ERRnoipc
));
157 return(ERROR(ERRSRV
,ERRinvnetname
));
159 return(ERROR(ERRSRV
,ERRbadpw
));
164 /****************************************************************************
165 parse a share descriptor string
166 ****************************************************************************/
167 static void parse_connect(char *p
,char *service
,char *user
,
168 char *password
,int *pwlen
,char *dev
)
172 DEBUG(4,("parsing connect string %s\n",p
));
174 p2
= strrchr(p
,'\\');
178 fstrcpy(service
,p2
+1);
183 *pwlen
= strlen(password
);
190 p
= strchr(service
,'%');
201 /****************************************************************************
203 ****************************************************************************/
204 int reply_tcon(char *inbuf
,char *outbuf
)
212 uint16 vuid
= SVAL(inbuf
,smb_uid
);
215 *service
= *user
= *password
= *dev
= 0;
217 parse_connect(smb_buf(inbuf
)+1,service
,user
,password
,&pwlen
,dev
);
219 connection_num
= make_connection(service
,user
,password
,pwlen
,dev
,vuid
);
221 if (connection_num
< 0)
222 return(connection_error(inbuf
,outbuf
,connection_num
));
224 outsize
= set_message(outbuf
,2,0,True
);
225 SSVAL(outbuf
,smb_vwv0
,max_recv
);
226 SSVAL(outbuf
,smb_vwv1
,connection_num
);
227 SSVAL(outbuf
,smb_tid
,connection_num
);
229 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service
,user
,connection_num
));
235 /****************************************************************************
236 reply to a tcon and X
237 ****************************************************************************/
238 int reply_tcon_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
245 uint16 vuid
= SVAL(inbuf
,smb_uid
);
246 int passlen
= SVAL(inbuf
,smb_vwv3
);
247 BOOL doencrypt
= SMBENCRYPT();
249 *service
= *user
= *password
= *devicename
= 0;
251 /* we might have to close an old one */
252 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) != 0)
253 close_cnum(SVAL(inbuf
,smb_tid
),vuid
);
255 if (passlen
> MAX_PASS_LEN
) {
256 overflow_attack(passlen
);
262 memcpy(password
,smb_buf(inbuf
),passlen
);
264 path
= smb_buf(inbuf
) + passlen
;
266 if (!doencrypt
|| passlen
!= 24) {
267 if (strequal(password
," "))
269 passlen
= strlen(password
);
272 fstrcpy(service
,path
+2);
273 p
= strchr(service
,'\\');
275 return(ERROR(ERRSRV
,ERRinvnetname
));
277 fstrcpy(service
,p
+1);
278 p
= strchr(service
,'%');
284 StrnCpy(devicename
,path
+ strlen(path
) + 1,6);
285 DEBUG(4,("Got device type %s\n",devicename
));
288 connection_num
= make_connection(service
,user
,password
,passlen
,devicename
,vuid
);
290 if (connection_num
< 0)
291 return(connection_error(inbuf
,outbuf
,connection_num
));
293 if (Protocol
< PROTOCOL_NT1
)
295 set_message(outbuf
,2,strlen(devicename
)+1,True
);
296 strcpy(smb_buf(outbuf
),devicename
);
300 char *fsname
= "SAMBA";
303 set_message(outbuf
,3,3,True
);
306 strcpy(p
,devicename
); p
= skip_string(p
,1); /* device name */
307 strcpy(p
,fsname
); p
= skip_string(p
,1); /* filesystem type e.g NTFS */
309 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
311 SSVAL(outbuf
, smb_vwv2
, 0x0); /* optional support */
314 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service
,user
,connection_num
));
316 /* set the incoming and outgoing tid to the just created one */
317 SSVAL(inbuf
,smb_tid
,connection_num
);
318 SSVAL(outbuf
,smb_tid
,connection_num
);
320 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
324 /****************************************************************************
325 reply to an unknown type
326 ****************************************************************************/
327 int reply_unknown(char *inbuf
,char *outbuf
)
331 cnum
= SVAL(inbuf
,smb_tid
);
332 type
= CVAL(inbuf
,smb_com
);
334 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
339 return(ERROR(ERRSRV
,ERRunknownsmb
));
343 /****************************************************************************
345 ****************************************************************************/
346 int reply_ioctl(char *inbuf
,char *outbuf
)
348 DEBUG(3,("ignoring ioctl\n"));
350 /* we just say it succeeds and hope its all OK.
351 some day it would be nice to interpret them individually */
352 return set_message(outbuf
,1,0,True
);
354 return(ERROR(ERRSRV
,ERRnosupport
));
359 /****************************************************************************
360 reply to a session setup command
361 ****************************************************************************/
362 int reply_sesssetup_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
371 int smb_apasslen
= 0;
373 int smb_ntpasslen
= 0;
374 pstring smb_ntpasswd
;
375 BOOL valid_nt_password
= False
;
378 BOOL computer_id
=False
;
379 static BOOL done_sesssetup
= False
;
380 BOOL doencrypt
= SMBENCRYPT();
384 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
385 smb_mpxmax
= SVAL(inbuf
,smb_vwv3
);
386 smb_vc_num
= SVAL(inbuf
,smb_vwv4
);
387 smb_sesskey
= IVAL(inbuf
,smb_vwv5
);
389 if (Protocol
< PROTOCOL_NT1
) {
390 smb_apasslen
= SVAL(inbuf
,smb_vwv7
);
391 if (smb_apasslen
> MAX_PASS_LEN
)
393 overflow_attack(smb_apasslen
);
396 memcpy(smb_apasswd
,smb_buf(inbuf
),smb_apasslen
);
397 pstrcpy(user
,smb_buf(inbuf
)+smb_apasslen
);
399 if (lp_security() != SEC_SERVER
&& !doencrypt
) {
400 smb_apasslen
= strlen(smb_apasswd
);
403 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
404 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
405 uint32 client_caps
= IVAL(inbuf
,smb_vwv11
);
406 enum remote_arch_types ra_type
= get_remote_arch();
408 char *p
= smb_buf(inbuf
);
410 /* client_caps is used as final determination if client is NT or Win95.
411 This is needed to return the correct error codes in some
415 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN95
)
417 if(client_caps
& (CAP_NT_SMBS
| CAP_STATUS32
))
418 set_remote_arch( RA_WINNT
);
420 set_remote_arch( RA_WIN95
);
423 if (passlen1
!= 24 && passlen2
!= 24)
426 if (passlen1
> MAX_PASS_LEN
) {
427 overflow_attack(passlen1
);
430 passlen1
= MIN(passlen1
, MAX_PASS_LEN
);
431 passlen2
= MIN(passlen2
, MAX_PASS_LEN
);
434 /* Save the lanman2 password and the NT md4 password. */
435 smb_apasslen
= passlen1
;
436 memcpy(smb_apasswd
,p
,smb_apasslen
);
437 smb_ntpasslen
= passlen2
;
438 memcpy(smb_ntpasswd
,p
+passlen1
,smb_ntpasslen
);
440 /* both Win95 and WinNT stuff up the password lengths for
441 non-encrypting systems. Uggh.
443 if passlen1==24 its a win95 system, and its setting the
444 password length incorrectly. Luckily it still works with the
445 default code because Win95 will null terminate the password
448 if passlen1>0 and passlen2>0 then maybe its a NT box and its
449 setting passlen2 to some random value which really stuffs
450 things up. we need to fix that one. */
451 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
455 /* we use the first password that they gave */
456 smb_apasslen
= passlen1
;
457 StrnCpy(smb_apasswd
,p
,smb_apasslen
);
459 /* trim the password */
460 smb_apasslen
= strlen(smb_apasswd
);
462 /* wfwg sometimes uses a space instead of a null */
463 if (strequal(smb_apasswd
," ")) {
469 p
+= passlen1
+ passlen2
;
470 fstrcpy(user
,p
); p
= skip_string(p
,1);
471 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
472 p
,skip_string(p
,1),skip_string(p
,2)));
476 DEBUG(3,("sesssetupX:name=[%s]\n",user
));
478 /* If name ends in $ then I think it's asking about whether a */
479 /* computer with that name (minus the $) has access. For now */
480 /* say yes to everything ending in $. */
481 if (user
[strlen(user
) - 1] == '$') {
483 user
[strlen(user
) - 1] = '\0';
487 /* If no username is sent use the guest account */
490 strcpy(user
,lp_guestaccount(-1));
491 /* If no user and no password then set guest flag. */
492 if( *smb_apasswd
== 0)
498 strcpy(sesssetup_user
,user
);
500 reload_services(True
);
502 add_session_user(user
);
504 /* Check if the given username was the guest user with no password.
505 We need to do this check after add_session_user() as that
506 call can potentially change the username (via map_user).
509 if(!guest
&& strequal(user
,lp_guestaccount(-1)) && (*smb_apasswd
== 0))
512 if (!guest
&& !(lp_security() == SEC_SERVER
&& server_validate(inbuf
)) &&
513 !check_hosts_equiv(user
))
516 /* now check if it's a valid username/password */
517 /* If an NT password was supplied try and validate with that
518 first. This is superior as the passwords are mixed case
519 128 length unicode */
522 if(!password_ok(user
,smb_ntpasswd
,smb_ntpasslen
,NULL
))
523 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
525 valid_nt_password
= True
;
527 if (!valid_nt_password
&& !password_ok(user
,smb_apasswd
,smb_apasslen
,NULL
))
529 if (!computer_id
&& lp_security() >= SEC_USER
) {
530 #if (GUEST_SESSSETUP == 0)
531 return(ERROR(ERRSRV
,ERRbadpw
));
533 #if (GUEST_SESSSETUP == 1)
534 if (Get_Pwnam(user
,True
))
535 return(ERROR(ERRSRV
,ERRbadpw
));
538 if (*smb_apasswd
|| !Get_Pwnam(user
,True
))
539 strcpy(user
,lp_guestaccount(-1));
540 DEBUG(3,("Registered username %s for guest access\n",user
));
545 if (!Get_Pwnam(user
,True
)) {
546 DEBUG(3,("No such user %s - using guest account\n",user
));
547 strcpy(user
,lp_guestaccount(-1));
551 if (!strequal(user
,lp_guestaccount(-1)) &&
552 lp_servicenumber(user
) < 0)
554 int homes
= lp_servicenumber(HOMES_NAME
);
555 char *home
= get_home_dir(user
);
556 if (homes
>= 0 && home
)
557 lp_add_home(user
,homes
,home
);
561 /* it's ok - setup a reply */
562 if (Protocol
< PROTOCOL_NT1
) {
563 set_message(outbuf
,3,0,True
);
566 set_message(outbuf
,3,3,True
);
568 strcpy(p
,"Unix"); p
= skip_string(p
,1);
569 strcpy(p
,"Samba "); strcat(p
,VERSION
); p
= skip_string(p
,1);
570 strcpy(p
,myworkgroup
); p
= skip_string(p
,1);
571 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
572 /* perhaps grab OS version here?? */
575 /* Set the correct uid in the outgoing and incoming packets
576 We will use this on future requests to determine which
577 user we should become.
580 struct passwd
*pw
= Get_Pwnam(user
,False
);
582 DEBUG(1,("Username %s is invalid on this system\n",user
));
583 return(ERROR(ERRSRV
,ERRbadpw
));
589 if (guest
&& !computer_id
)
590 SSVAL(outbuf
,smb_vwv2
,1);
592 /* register the name and uid as being validated, so further connections
593 to a uid can get through without a password, on the same VC */
594 sess_vuid
= register_vuid(uid
,gid
,user
,guest
);
596 SSVAL(outbuf
,smb_uid
,sess_vuid
);
597 SSVAL(inbuf
,smb_uid
,sess_vuid
);
600 max_send
= MIN(max_send
,smb_bufsize
);
602 DEBUG(6,("Client requested max send size of %d\n", max_send
));
604 done_sesssetup
= True
;
606 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
610 /****************************************************************************
612 ****************************************************************************/
613 int reply_chkpth(char *inbuf
,char *outbuf
)
619 BOOL bad_path
= False
;
621 cnum
= SVAL(inbuf
,smb_tid
);
623 pstrcpy(name
,smb_buf(inbuf
) + 1);
624 unix_convert(name
,cnum
,0,&bad_path
);
626 mode
= SVAL(inbuf
,smb_vwv0
);
628 if (check_name(name
,cnum
))
629 ok
= directory_exist(name
,NULL
);
633 /* We special case this - as when a Windows machine
634 is parsing a path is steps through the components
635 one at a time - if a component fails it expects
636 ERRbadpath, not ERRbadfile.
640 unix_ERR_class
= ERRDOS
;
641 unix_ERR_code
= ERRbadpath
;
645 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
646 if((errno
== ENOTDIR
) && (Protocol
>= PROTOCOL_NT1
) &&
647 (get_remote_arch() == RA_WINNT
))
649 unix_ERR_class
= ERRDOS
;
650 unix_ERR_code
= ERRbaddirectory
;
654 return(UNIXERROR(ERRDOS
,ERRbadpath
));
657 outsize
= set_message(outbuf
,0,0,True
);
659 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name
,cnum
,mode
));
665 /****************************************************************************
667 ****************************************************************************/
668 int reply_getatr(char *inbuf
,char *outbuf
)
678 BOOL bad_path
= False
;
680 cnum
= SVAL(inbuf
,smb_tid
);
682 pstrcpy(fname
,smb_buf(inbuf
) + 1);
683 unix_convert(fname
,cnum
,0,&bad_path
);
685 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
686 under WfWg - weird! */
689 mode
= aHIDDEN
| aDIR
;
690 if (!CAN_WRITE(cnum
)) mode
|= aRONLY
;
696 if (check_name(fname
,cnum
))
698 if (sys_stat(fname
,&sbuf
) == 0)
700 mode
= dos_mode(cnum
,fname
,&sbuf
);
702 mtime
= sbuf
.st_mtime
;
708 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
713 if((errno
== ENOENT
) && bad_path
)
715 unix_ERR_class
= ERRDOS
;
716 unix_ERR_code
= ERRbadpath
;
719 return(UNIXERROR(ERRDOS
,ERRbadfile
));
722 outsize
= set_message(outbuf
,10,0,True
);
724 SSVAL(outbuf
,smb_vwv0
,mode
);
725 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
726 SIVAL(outbuf
,smb_vwv3
,size
);
728 if (Protocol
>= PROTOCOL_NT1
) {
729 char *p
= strrchr(fname
,'/');
730 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
732 if (!is_8_3(fname
, True
))
733 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
736 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname
,mode
,size
));
742 /****************************************************************************
744 ****************************************************************************/
745 int reply_setatr(char *inbuf
,char *outbuf
)
753 BOOL bad_path
= False
;
755 cnum
= SVAL(inbuf
,smb_tid
);
757 pstrcpy(fname
,smb_buf(inbuf
) + 1);
758 unix_convert(fname
,cnum
,0,&bad_path
);
760 mode
= SVAL(inbuf
,smb_vwv0
);
761 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
763 if (directory_exist(fname
,NULL
))
765 if (check_name(fname
,cnum
))
766 ok
= (dos_chmod(cnum
,fname
,mode
,NULL
) == 0);
768 ok
= set_filetime(fname
,mtime
);
772 if((errno
== ENOENT
) && bad_path
)
774 unix_ERR_class
= ERRDOS
;
775 unix_ERR_code
= ERRbadpath
;
778 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
781 outsize
= set_message(outbuf
,0,0,True
);
783 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname
,mode
));
789 /****************************************************************************
791 ****************************************************************************/
792 int reply_dskattr(char *inbuf
,char *outbuf
)
796 int dfree
,dsize
,bsize
;
798 cnum
= SVAL(inbuf
,smb_tid
);
800 sys_disk_free(".",&bsize
,&dfree
,&dsize
);
802 outsize
= set_message(outbuf
,5,0,True
);
804 SSVAL(outbuf
,smb_vwv0
,dsize
);
805 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
806 SSVAL(outbuf
,smb_vwv2
,512);
807 SSVAL(outbuf
,smb_vwv3
,dfree
);
809 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum
,dfree
));
815 /****************************************************************************
817 Can be called from SMBsearch, SMBffirst or SMBfunique.
818 ****************************************************************************/
819 int reply_search(char *inbuf
,char *outbuf
)
830 BOOL finished
= False
;
839 BOOL check_descend
= False
;
840 BOOL expect_close
= False
;
841 BOOL can_open
= True
;
842 BOOL bad_path
= False
;
844 *mask
= *directory
= *fname
= 0;
846 /* If we were called as SMBffirst then we must expect close. */
847 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
850 cnum
= SVAL(inbuf
,smb_tid
);
852 outsize
= set_message(outbuf
,1,3,True
);
853 maxentries
= SVAL(inbuf
,smb_vwv0
);
854 dirtype
= SVAL(inbuf
,smb_vwv1
);
855 path
= smb_buf(inbuf
) + 1;
856 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
859 /* dirtype &= ~aDIR; */
861 DEBUG(5,("path=%s status_len=%d\n",path
,status_len
));
868 pstrcpy(directory
,smb_buf(inbuf
)+1);
869 pstrcpy(dir2
,smb_buf(inbuf
)+1);
870 unix_convert(directory
,cnum
,0,&bad_path
);
873 if (!check_name(directory
,cnum
))
876 p
= strrchr(dir2
,'/');
888 p
= strrchr(directory
,'/');
894 if (strlen(directory
) == 0)
895 strcpy(directory
,"./");
897 CVAL(status
,0) = dirtype
;
901 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
902 memcpy(mask
,status
+1,11);
904 dirtype
= CVAL(status
,0) & 0x1F;
905 Connections
[cnum
].dirptr
= dptr_fetch(status
+12,&dptr_num
);
906 if (!Connections
[cnum
].dirptr
)
908 string_set(&Connections
[cnum
].dirpath
,dptr_path(dptr_num
));
913 /* turn strings of spaces into a . */
915 trim_string(mask
,NULL
," ");
916 if ((p
= strrchr(mask
,' ')))
921 trim_string(mask
,NULL
," ");
928 for (p
=mask
; *p
; p
++)
930 if (*p
!= '?' && *p
!= '*' && !isdoschar(*p
))
932 DEBUG(5,("Invalid char [%c] in search mask?\n",*p
));
938 if (!strchr(mask
,'.') && strlen(mask
)>8)
941 fstrcpy(tmp
,&mask
[8]);
947 DEBUG(5,("mask=%s directory=%s\n",mask
,directory
));
951 p
= smb_buf(outbuf
) + 3;
957 dptr_num
= dptr_create(cnum
,directory
,expect_close
,SVAL(inbuf
,smb_pid
));
962 if((errno
== ENOENT
) && bad_path
)
964 unix_ERR_class
= ERRDOS
;
965 unix_ERR_code
= ERRbadpath
;
967 return (UNIXERROR(ERRDOS
,ERRnofids
));
969 return(ERROR(ERRDOS
,ERRnofids
));
973 DEBUG(4,("dptr_num is %d\n",dptr_num
));
977 if ((dirtype
&0x1F) == aVOLID
)
980 make_dir_struct(p
,"???????????",volume_label(SNUM(cnum
)),0,aVOLID
,0);
981 dptr_fill(p
+12,dptr_num
);
982 if (dptr_zero(p
+12) && (status_len
==0))
986 p
+= DIR_STRUCT_SIZE
;
990 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections
[cnum
].dirpath
,lp_dontdescend(SNUM(cnum
))));
991 if (in_list(Connections
[cnum
].dirpath
,
992 lp_dontdescend(SNUM(cnum
)),True
))
993 check_descend
= True
;
995 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
998 !get_dir_entry(cnum
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
1001 memcpy(p
,status
,21);
1002 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
1003 dptr_fill(p
+12,dptr_num
);
1006 p
+= DIR_STRUCT_SIZE
;
1015 if (numentries
== 0 || !ok
)
1017 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1018 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1021 /* If we were called as SMBffirst with smb_search_id == NULL
1022 and no entries were found then return error and close dirptr
1025 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
1027 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
1028 SSVAL(outbuf
,smb_err
,ERRnofiles
);
1029 /* Also close the dptr - we know it's gone */
1030 dptr_close(dptr_num
);
1033 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1034 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
1035 dptr_close(dptr_num
);
1037 SSVAL(outbuf
,smb_vwv0
,numentries
);
1038 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1039 CVAL(smb_buf(outbuf
),0) = 5;
1040 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1042 if (Protocol
>= PROTOCOL_NT1
) {
1043 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
1044 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
1047 outsize
+= DIR_STRUCT_SIZE
*numentries
;
1048 smb_setlen(outbuf
,outsize
- 4);
1050 if ((! *directory
) && dptr_path(dptr_num
))
1051 sprintf(directory
,"(%s)",dptr_path(dptr_num
));
1053 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1055 smb_fn_name(CVAL(inbuf
,smb_com
)),
1056 mask
,directory
,cnum
,dirtype
,numentries
,maxentries
));
1062 /****************************************************************************
1063 reply to a fclose (stop directory search)
1064 ****************************************************************************/
1065 int reply_fclose(char *inbuf
,char *outbuf
)
1074 cnum
= SVAL(inbuf
,smb_tid
);
1076 outsize
= set_message(outbuf
,1,0,True
);
1077 path
= smb_buf(inbuf
) + 1;
1078 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
1081 if (status_len
== 0)
1082 return(ERROR(ERRSRV
,ERRsrverror
));
1084 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
1086 if(dptr_fetch(status
+12,&dptr_num
)) {
1087 /* Close the dptr - we know it's gone */
1088 dptr_close(dptr_num
);
1091 SSVAL(outbuf
,smb_vwv0
,0);
1093 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum
));
1099 /****************************************************************************
1101 ****************************************************************************/
1102 int reply_open(char *inbuf
,char *outbuf
)
1115 BOOL bad_path
= False
;
1117 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1119 cnum
= SVAL(inbuf
,smb_tid
);
1121 share_mode
= SVAL(inbuf
,smb_vwv0
);
1123 pstrcpy(fname
,smb_buf(inbuf
)+1);
1124 unix_convert(fname
,cnum
,0,&bad_path
);
1126 fnum
= find_free_file();
1128 return(ERROR(ERRSRV
,ERRnofids
));
1130 if (!check_name(fname
,cnum
))
1132 if((errno
== ENOENT
) && bad_path
)
1134 unix_ERR_class
= ERRDOS
;
1135 unix_ERR_code
= ERRbadpath
;
1137 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1140 unixmode
= unix_mode(cnum
,aARCH
);
1142 open_file_shared(fnum
,cnum
,fname
,share_mode
,3,unixmode
,
1143 oplock_request
,&rmode
,NULL
);
1149 if((errno
== ENOENT
) && bad_path
)
1151 unix_ERR_class
= ERRDOS
;
1152 unix_ERR_code
= ERRbadpath
;
1154 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1157 if (fstat(fsp
->fd_ptr
->fd
,&sbuf
) != 0) {
1159 return(ERROR(ERRDOS
,ERRnoaccess
));
1162 size
= sbuf
.st_size
;
1163 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1164 mtime
= sbuf
.st_mtime
;
1167 DEBUG(3,("attempt to open a directory %s\n",fname
));
1169 return(ERROR(ERRDOS
,ERRnoaccess
));
1172 outsize
= set_message(outbuf
,7,0,True
);
1173 SSVAL(outbuf
,smb_vwv0
,fnum
);
1174 SSVAL(outbuf
,smb_vwv1
,fmode
);
1175 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1176 SIVAL(outbuf
,smb_vwv4
,size
);
1177 SSVAL(outbuf
,smb_vwv6
,rmode
);
1179 if (oplock_request
&& lp_fake_oplocks(SNUM(cnum
))) {
1180 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1183 if(fsp
->granted_oplock
)
1184 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1189 /****************************************************************************
1190 reply to an open and X
1191 ****************************************************************************/
1192 int reply_open_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1195 int cnum
= SVAL(inbuf
,smb_tid
);
1197 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1198 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1199 BOOL oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
1201 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1202 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1203 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1205 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1207 int size
=0,fmode
=0,mtime
=0,rmode
=0;
1210 BOOL bad_path
= False
;
1213 /* If it's an IPC, pass off the pipe handler. */
1215 return reply_open_pipe_and_X(inbuf
,outbuf
,length
,bufsize
);
1217 /* XXXX we need to handle passed times, sattr and flags */
1219 pstrcpy(fname
,smb_buf(inbuf
));
1220 unix_convert(fname
,cnum
,0,&bad_path
);
1222 fnum
= find_free_file();
1224 return(ERROR(ERRSRV
,ERRnofids
));
1226 if (!check_name(fname
,cnum
))
1228 if((errno
== ENOENT
) && bad_path
)
1230 unix_ERR_class
= ERRDOS
;
1231 unix_ERR_code
= ERRbadpath
;
1233 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1236 unixmode
= unix_mode(cnum
,smb_attr
| aARCH
);
1238 open_file_shared(fnum
,cnum
,fname
,smb_mode
,smb_ofun
,unixmode
,
1239 oplock_request
, &rmode
,&smb_action
);
1245 if((errno
== ENOENT
) && bad_path
)
1247 unix_ERR_class
= ERRDOS
;
1248 unix_ERR_code
= ERRbadpath
;
1250 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1253 if (fstat(fsp
->fd_ptr
->fd
,&sbuf
) != 0) {
1255 return(ERROR(ERRDOS
,ERRnoaccess
));
1258 size
= sbuf
.st_size
;
1259 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1260 mtime
= sbuf
.st_mtime
;
1263 return(ERROR(ERRDOS
,ERRnoaccess
));
1266 if (oplock_request
&& lp_fake_oplocks(SNUM(cnum
))) {
1267 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1268 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1271 if(fsp
->granted_oplock
) {
1272 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1273 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1276 set_message(outbuf
,15,0,True
);
1277 SSVAL(outbuf
,smb_vwv2
,fnum
);
1278 SSVAL(outbuf
,smb_vwv3
,fmode
);
1279 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1280 SIVAL(outbuf
,smb_vwv6
,size
);
1281 SSVAL(outbuf
,smb_vwv8
,rmode
);
1282 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1286 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1290 /****************************************************************************
1291 reply to a SMBulogoffX
1292 ****************************************************************************/
1293 int reply_ulogoffX(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1295 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1296 user_struct
*vuser
= get_valid_user_struct(vuid
);
1299 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1302 /* in user level security we are supposed to close any files
1303 open by this user */
1304 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1306 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
1307 if (Files
[i
].uid
== vuser
->uid
&& Files
[i
].open
) {
1312 invalidate_vuid(vuid
);
1314 set_message(outbuf
,2,0,True
);
1316 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid
));
1318 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1322 /****************************************************************************
1323 reply to a mknew or a create
1324 ****************************************************************************/
1325 int reply_mknew(char *inbuf
,char *outbuf
)
1334 BOOL bad_path
= False
;
1336 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1338 com
= SVAL(inbuf
,smb_com
);
1339 cnum
= SVAL(inbuf
,smb_tid
);
1341 createmode
= SVAL(inbuf
,smb_vwv0
);
1342 pstrcpy(fname
,smb_buf(inbuf
)+1);
1343 unix_convert(fname
,cnum
,0,&bad_path
);
1345 if (createmode
& aVOLID
)
1347 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1350 unixmode
= unix_mode(cnum
,createmode
);
1352 fnum
= find_free_file();
1354 return(ERROR(ERRSRV
,ERRnofids
));
1356 if (!check_name(fname
,cnum
))
1358 if((errno
== ENOENT
) && bad_path
)
1360 unix_ERR_class
= ERRDOS
;
1361 unix_ERR_code
= ERRbadpath
;
1363 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1368 /* We should fail if file exists. */
1373 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1377 /* Open file in dos compatibility share mode. */
1378 open_file_shared(fnum
,cnum
,fname
,(DENY_FCB
<<4)|0xF, ofun
, unixmode
,
1379 oplock_request
, NULL
, NULL
);
1385 if((errno
== ENOENT
) && bad_path
)
1387 unix_ERR_class
= ERRDOS
;
1388 unix_ERR_code
= ERRbadpath
;
1390 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1393 outsize
= set_message(outbuf
,1,0,True
);
1394 SSVAL(outbuf
,smb_vwv0
,fnum
);
1396 if (oplock_request
&& lp_fake_oplocks(SNUM(cnum
))) {
1397 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1400 if(fsp
->granted_oplock
)
1401 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1403 DEBUG(2,("new file %s\n",fname
));
1404 DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname
,Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
,createmode
,unixmode
));
1410 /****************************************************************************
1411 reply to a create temporary file
1412 ****************************************************************************/
1413 int reply_ctemp(char *inbuf
,char *outbuf
)
1422 BOOL bad_path
= False
;
1424 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1426 cnum
= SVAL(inbuf
,smb_tid
);
1427 createmode
= SVAL(inbuf
,smb_vwv0
);
1428 pstrcpy(fname
,smb_buf(inbuf
)+1);
1429 strcat(fname
,"/TMXXXXXX");
1430 unix_convert(fname
,cnum
,0,&bad_path
);
1432 unixmode
= unix_mode(cnum
,createmode
);
1434 fnum
= find_free_file();
1436 return(ERROR(ERRSRV
,ERRnofids
));
1438 if (!check_name(fname
,cnum
))
1440 if((errno
== ENOENT
) && bad_path
)
1442 unix_ERR_class
= ERRDOS
;
1443 unix_ERR_code
= ERRbadpath
;
1445 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1448 strcpy(fname2
,(char *)mktemp(fname
));
1450 /* Open file in dos compatibility share mode. */
1451 /* We should fail if file exists. */
1452 open_file_shared(fnum
,cnum
,fname2
,(DENY_FCB
<<4)|0xF, 0x10, unixmode
,
1453 oplock_request
, NULL
, NULL
);
1459 if((errno
== ENOENT
) && bad_path
)
1461 unix_ERR_class
= ERRDOS
;
1462 unix_ERR_code
= ERRbadpath
;
1464 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1467 outsize
= set_message(outbuf
,1,2 + strlen(fname2
),True
);
1468 SSVAL(outbuf
,smb_vwv0
,fnum
);
1469 CVAL(smb_buf(outbuf
),0) = 4;
1470 strcpy(smb_buf(outbuf
) + 1,fname2
);
1472 if (oplock_request
&& lp_fake_oplocks(SNUM(cnum
))) {
1473 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1476 if(fsp
->granted_oplock
)
1477 CVAL(outbuf
,smb_flg
) |= CORE_OPLOCK_GRANTED
;
1479 DEBUG(2,("created temp file %s\n",fname2
));
1480 DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2
,Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
,createmode
,unixmode
));
1486 /*******************************************************************
1487 check if a user is allowed to delete a file
1488 ********************************************************************/
1489 static BOOL
can_delete(char *fname
,int cnum
,int dirtype
)
1494 if (!CAN_WRITE(cnum
)) return(False
);
1496 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
1497 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1498 if (fmode
& aDIR
) return(False
);
1499 if (!lp_delete_readonly(SNUM(cnum
))) {
1500 if (fmode
& aRONLY
) return(False
);
1502 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1504 if (!check_file_sharing(cnum
,fname
)) return(False
);
1508 /****************************************************************************
1510 ****************************************************************************/
1511 int reply_unlink(char *inbuf
,char *outbuf
)
1521 int error
= ERRnoaccess
;
1524 BOOL bad_path
= False
;
1526 *directory
= *mask
= 0;
1528 cnum
= SVAL(inbuf
,smb_tid
);
1529 dirtype
= SVAL(inbuf
,smb_vwv0
);
1531 pstrcpy(name
,smb_buf(inbuf
) + 1);
1533 DEBUG(3,("reply_unlink : %s\n",name
));
1535 unix_convert(name
,cnum
,0,&bad_path
);
1537 p
= strrchr(name
,'/');
1539 strcpy(directory
,"./");
1543 strcpy(directory
,name
);
1547 if (is_mangled(mask
))
1548 check_mangled_stack(mask
);
1550 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
1553 strcat(directory
,"/");
1554 strcat(directory
,mask
);
1555 if (can_delete(directory
,cnum
,dirtype
) && !sys_unlink(directory
)) count
++;
1556 if (!count
) exists
= file_exist(directory
,NULL
);
1558 void *dirptr
= NULL
;
1561 if (check_name(directory
,cnum
))
1562 dirptr
= OpenDir(cnum
, directory
, True
);
1564 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1565 the pattern matches against the long name, otherwise the short name
1566 We don't implement this yet XXXX
1573 if (strequal(mask
,"????????.???"))
1576 while ((dname
= ReadDirName(dirptr
)))
1579 pstrcpy(fname
,dname
);
1581 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
1583 error
= ERRnoaccess
;
1584 sprintf(fname
,"%s/%s",directory
,dname
);
1585 if (!can_delete(fname
,cnum
,dirtype
)) continue;
1586 if (!sys_unlink(fname
)) count
++;
1587 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname
));
1595 return(ERROR(ERRDOS
,error
));
1598 if((errno
== ENOENT
) && bad_path
)
1600 unix_ERR_class
= ERRDOS
;
1601 unix_ERR_code
= ERRbadpath
;
1603 return(UNIXERROR(ERRDOS
,error
));
1607 outsize
= set_message(outbuf
,0,0,True
);
1613 /****************************************************************************
1614 reply to a readbraw (core+ protocol)
1615 ****************************************************************************/
1616 int reply_readbraw(char *inbuf
, char *outbuf
)
1618 int cnum
,maxcount
,mincount
,fnum
;
1621 char *header
= outbuf
;
1627 * Special check if an oplock break has been issued
1628 * and the readraw request croses on the wire, we must
1629 * return a zero length response here.
1632 if(global_oplock_break
)
1634 _smb_setlen(header
,0);
1635 transfer_file(0,Client
,0,header
,4,0);
1636 DEBUG(5,("readbraw - oplock break finished\n"));
1640 cnum
= SVAL(inbuf
,smb_tid
);
1641 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1643 startpos
= IVAL(inbuf
,smb_vwv1
);
1644 maxcount
= SVAL(inbuf
,smb_vwv3
);
1645 mincount
= SVAL(inbuf
,smb_vwv4
);
1647 /* ensure we don't overrun the packet size */
1648 maxcount
= MIN(65535,maxcount
);
1649 maxcount
= MAX(mincount
,maxcount
);
1651 if (!FNUM_OK(fnum
,cnum
) || !Files
[fnum
].can_read
)
1653 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum
));
1654 _smb_setlen(header
,0);
1655 transfer_file(0,Client
,0,header
,4,0);
1660 fd
= Files
[fnum
].fd_ptr
->fd
;
1661 fname
= Files
[fnum
].name
;
1665 if (!is_locked(fnum
,cnum
,maxcount
,startpos
))
1667 int size
= Files
[fnum
].size
;
1668 int sizeneeded
= startpos
+ maxcount
;
1670 if (size
< sizeneeded
) {
1672 if (fstat(Files
[fnum
].fd_ptr
->fd
,&st
) == 0)
1674 if (!Files
[fnum
].can_write
)
1675 Files
[fnum
].size
= size
;
1678 nread
= MIN(maxcount
,(int)(size
- startpos
));
1681 if (nread
< mincount
)
1684 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1687 maxcount
,mincount
,nread
));
1692 _smb_setlen(header
,nread
);
1694 if (!Files
[fnum
].can_write
)
1695 predict
= read_predict(fd
,startpos
,header
+4,NULL
,nread
);
1697 if ((nread
-predict
) > 0)
1698 seek_file(fnum
,startpos
+ predict
);
1700 ret
= transfer_file(fd
,Client
,nread
-predict
,header
,4+predict
,
1705 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1706 fname
,startpos
,nread
,ret
));
1709 ret
= read_file(fnum
,header
+4,startpos
,nread
);
1710 if (ret
< mincount
) ret
= 0;
1712 _smb_setlen(header
,ret
);
1713 transfer_file(0,Client
,0,header
,4+ret
,0);
1716 DEBUG(5,("readbraw finished\n"));
1721 /****************************************************************************
1722 reply to a lockread (core+ protocol)
1723 ****************************************************************************/
1724 int reply_lockread(char *inbuf
,char *outbuf
)
1730 uint32 startpos
, numtoread
;
1734 cnum
= SVAL(inbuf
,smb_tid
);
1735 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1737 CHECK_FNUM(fnum
,cnum
);
1741 numtoread
= SVAL(inbuf
,smb_vwv1
);
1742 startpos
= IVAL(inbuf
,smb_vwv2
);
1744 outsize
= set_message(outbuf
,5,3,True
);
1745 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1746 data
= smb_buf(outbuf
) + 3;
1748 if(!do_lock( fnum
, cnum
, numtoread
, startpos
, &eclass
, &ecode
))
1749 return (ERROR(eclass
,ecode
));
1751 nread
= read_file(fnum
,data
,startpos
,numtoread
);
1754 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1757 SSVAL(outbuf
,smb_vwv0
,nread
);
1758 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1759 SSVAL(smb_buf(outbuf
),1,nread
);
1761 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum
,cnum
,numtoread
,nread
));
1767 /****************************************************************************
1769 ****************************************************************************/
1770 int reply_read(char *inbuf
,char *outbuf
)
1772 int cnum
,numtoread
,fnum
;
1778 cnum
= SVAL(inbuf
,smb_tid
);
1779 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1781 CHECK_FNUM(fnum
,cnum
);
1785 numtoread
= SVAL(inbuf
,smb_vwv1
);
1786 startpos
= IVAL(inbuf
,smb_vwv2
);
1788 outsize
= set_message(outbuf
,5,3,True
);
1789 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1790 data
= smb_buf(outbuf
) + 3;
1792 if (is_locked(fnum
,cnum
,numtoread
,startpos
))
1793 return(ERROR(ERRDOS
,ERRlock
));
1796 nread
= read_file(fnum
,data
,startpos
,numtoread
);
1799 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1802 SSVAL(outbuf
,smb_vwv0
,nread
);
1803 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1804 CVAL(smb_buf(outbuf
),0) = 1;
1805 SSVAL(smb_buf(outbuf
),1,nread
);
1807 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum
,cnum
,numtoread
,nread
));
1813 /****************************************************************************
1814 reply to a read and X
1815 ****************************************************************************/
1816 int reply_read_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1818 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
1819 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
1820 int smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
1821 int smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
1827 cnum
= SVAL(inbuf
,smb_tid
);
1829 CHECK_FNUM(fnum
,cnum
);
1833 set_message(outbuf
,12,0,True
);
1834 data
= smb_buf(outbuf
);
1836 if (is_locked(fnum
,cnum
,smb_maxcnt
,smb_offs
))
1837 return(ERROR(ERRDOS
,ERRlock
));
1838 nread
= read_file(fnum
,data
,smb_offs
,smb_maxcnt
);
1842 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1844 SSVAL(outbuf
,smb_vwv5
,nread
);
1845 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
1846 SSVAL(smb_buf(outbuf
),-2,nread
);
1848 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1849 timestring(),fnum
,cnum
,
1850 smb_mincnt
,smb_maxcnt
,nread
));
1854 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1858 /****************************************************************************
1859 reply to a writebraw (core+ or LANMAN1.0 protocol)
1860 ****************************************************************************/
1861 int reply_writebraw(char *inbuf
,char *outbuf
)
1864 int total_written
=0;
1873 cnum
= SVAL(inbuf
,smb_tid
);
1874 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1876 CHECK_FNUM(fnum
,cnum
);
1880 tcount
= IVAL(inbuf
,smb_vwv1
);
1881 startpos
= IVAL(inbuf
,smb_vwv3
);
1882 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
1884 /* We have to deal with slightly different formats depending
1885 on whether we are using the core+ or lanman1.0 protocol */
1886 if(Protocol
<= PROTOCOL_COREPLUS
) {
1887 numtowrite
= SVAL(smb_buf(inbuf
),-2);
1888 data
= smb_buf(inbuf
);
1890 numtowrite
= SVAL(inbuf
,smb_vwv10
);
1891 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
1894 /* force the error type */
1895 CVAL(inbuf
,smb_com
) = SMBwritec
;
1896 CVAL(outbuf
,smb_com
) = SMBwritec
;
1898 if (is_locked(fnum
,cnum
,tcount
,startpos
))
1899 return(ERROR(ERRDOS
,ERRlock
));
1901 if (seek_file(fnum
,startpos
) != startpos
)
1902 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos
));
1905 nwritten
= write_file(fnum
,data
,numtowrite
);
1907 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1908 timestring(),fnum
,cnum
,startpos
,numtowrite
,nwritten
,write_through
));
1910 if (nwritten
< numtowrite
)
1911 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
1913 total_written
= nwritten
;
1915 /* Return a message to the redirector to tell it
1916 to send more bytes */
1917 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
1918 SSVALS(outbuf
,smb_vwv0
,-1);
1919 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
1920 send_smb(Client
,outbuf
);
1922 /* Now read the raw data into the buffer and write it */
1923 if (read_smb_length(Client
,inbuf
,SMB_SECONDARY_WAIT
) == -1) {
1924 exit_server("secondary writebraw failed");
1927 /* Even though this is not an smb message, smb_len
1928 returns the generic length of an smb message */
1929 numtowrite
= smb_len(inbuf
);
1931 if (tcount
> nwritten
+numtowrite
) {
1932 DEBUG(3,("Client overestimated the write %d %d %d\n",
1933 tcount
,nwritten
,numtowrite
));
1936 nwritten
= transfer_file(Client
,Files
[fnum
].fd_ptr
->fd
,numtowrite
,NULL
,0,
1938 total_written
+= nwritten
;
1940 /* Set up outbuf to return the correct return */
1941 outsize
= set_message(outbuf
,1,0,True
);
1942 CVAL(outbuf
,smb_com
) = SMBwritec
;
1943 SSVAL(outbuf
,smb_vwv0
,total_written
);
1945 if (nwritten
< numtowrite
) {
1946 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1947 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1950 if (lp_syncalways(SNUM(cnum
)) || write_through
)
1953 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1954 timestring(),fnum
,cnum
,startpos
,numtowrite
,total_written
));
1956 /* we won't return a status if write through is not selected - this
1957 follows what WfWg does */
1958 if (!write_through
&& total_written
==tcount
)
1965 /****************************************************************************
1966 reply to a writeunlock (core+)
1967 ****************************************************************************/
1968 int reply_writeunlock(char *inbuf
,char *outbuf
)
1974 uint32 numtowrite
,startpos
;
1978 cnum
= SVAL(inbuf
,smb_tid
);
1979 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1981 CHECK_FNUM(fnum
,cnum
);
1985 numtowrite
= SVAL(inbuf
,smb_vwv1
);
1986 startpos
= IVAL(inbuf
,smb_vwv2
);
1987 data
= smb_buf(inbuf
) + 3;
1989 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
1990 return(ERROR(ERRDOS
,ERRlock
));
1992 seek_file(fnum
,startpos
);
1994 /* The special X/Open SMB protocol handling of
1995 zero length writes is *NOT* done for
2000 nwritten
= write_file(fnum
,data
,numtowrite
);
2002 if (lp_syncalways(SNUM(cnum
)))
2005 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
2006 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2008 if(!do_unlock(fnum
, cnum
, numtowrite
, startpos
, &eclass
, &ecode
))
2009 return(ERROR(eclass
,ecode
));
2011 outsize
= set_message(outbuf
,1,0,True
);
2013 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2015 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2016 timestring(),fnum
,cnum
,numtowrite
,nwritten
));
2022 /****************************************************************************
2024 ****************************************************************************/
2025 int reply_write(char *inbuf
,char *outbuf
,int dum1
,int dum2
)
2027 int cnum
,numtowrite
,fnum
;
2036 cnum
= SVAL(inbuf
,smb_tid
);
2037 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2039 CHECK_FNUM(fnum
,cnum
);
2043 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2044 startpos
= IVAL(inbuf
,smb_vwv2
);
2045 data
= smb_buf(inbuf
) + 3;
2047 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
2048 return(ERROR(ERRDOS
,ERRlock
));
2050 seek_file(fnum
,startpos
);
2052 /* X/Open SMB protocol says that if smb_vwv1 is
2053 zero then the file size should be extended or
2054 truncated to the size given in smb_vwv[2-3] */
2056 nwritten
= set_filelen(Files
[fnum
].fd_ptr
->fd
, startpos
);
2058 nwritten
= write_file(fnum
,data
,numtowrite
);
2060 if (lp_syncalways(SNUM(cnum
)))
2063 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
2064 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2066 outsize
= set_message(outbuf
,1,0,True
);
2068 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2070 if (nwritten
< numtowrite
) {
2071 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2072 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2075 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum
,cnum
,numtowrite
,nwritten
));
2081 /****************************************************************************
2082 reply to a write and X
2083 ****************************************************************************/
2084 int reply_write_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
2086 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
2087 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
2088 int smb_dsize
= SVAL(inbuf
,smb_vwv10
);
2089 int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2090 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2095 cnum
= SVAL(inbuf
,smb_tid
);
2097 CHECK_FNUM(fnum
,cnum
);
2101 data
= smb_base(inbuf
) + smb_doff
;
2103 if (is_locked(fnum
,cnum
,smb_dsize
,smb_offs
))
2104 return(ERROR(ERRDOS
,ERRlock
));
2106 seek_file(fnum
,smb_offs
);
2108 /* X/Open SMB protocol says that, unlike SMBwrite
2109 if the length is zero then NO truncation is
2110 done, just a write of zero. To truncate a file,
2115 nwritten
= write_file(fnum
,data
,smb_dsize
);
2117 if(((nwritten
== 0) && (smb_dsize
!= 0))||(nwritten
< 0))
2118 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2120 set_message(outbuf
,6,0,True
);
2122 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2124 if (nwritten
< smb_dsize
) {
2125 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
2126 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2129 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum
,cnum
,smb_dsize
,nwritten
));
2133 if (lp_syncalways(SNUM(cnum
)) || write_through
)
2136 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2140 /****************************************************************************
2142 ****************************************************************************/
2143 int reply_lseek(char *inbuf
,char *outbuf
)
2151 cnum
= SVAL(inbuf
,smb_tid
);
2152 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2154 CHECK_FNUM(fnum
,cnum
);
2157 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2158 startpos
= IVAL(inbuf
,smb_vwv2
);
2162 case 0: umode
= SEEK_SET
; break;
2163 case 1: umode
= SEEK_CUR
; break;
2164 case 2: umode
= SEEK_END
; break;
2166 umode
= SEEK_SET
; break;
2169 res
= lseek(Files
[fnum
].fd_ptr
->fd
,startpos
,umode
);
2170 Files
[fnum
].pos
= res
;
2172 outsize
= set_message(outbuf
,2,0,True
);
2173 SIVALS(outbuf
,smb_vwv0
,res
);
2175 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum
,cnum
,startpos
,mode
));
2181 /****************************************************************************
2183 ****************************************************************************/
2184 int reply_flush(char *inbuf
,char *outbuf
)
2187 int outsize
= set_message(outbuf
,0,0,True
);
2189 cnum
= SVAL(inbuf
,smb_tid
);
2190 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2192 if (fnum
!= 0xFFFF) {
2193 CHECK_FNUM(fnum
,cnum
);
2200 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
2207 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum
));
2212 /****************************************************************************
2214 ****************************************************************************/
2215 int reply_exit(char *inbuf
,char *outbuf
)
2217 int outsize
= set_message(outbuf
,0,0,True
);
2218 DEBUG(3,("%s exit\n",timestring()));
2224 /****************************************************************************
2226 ****************************************************************************/
2227 int reply_close(char *inbuf
,char *outbuf
)
2232 int32 eclass
= 0, err
= 0;
2234 outsize
= set_message(outbuf
,0,0,True
);
2236 cnum
= SVAL(inbuf
,smb_tid
);
2238 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2239 CHECK_FNUM(fnum
,cnum
);
2241 if(HAS_CACHED_ERROR(fnum
)) {
2242 eclass
= Files
[fnum
].wbmpx_ptr
->wr_errclass
;
2243 err
= Files
[fnum
].wbmpx_ptr
->wr_error
;
2246 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2248 /* try and set the date */
2249 set_filetime(Files
[fnum
].name
,mtime
);
2253 /* We have a cached error */
2255 return(ERROR(eclass
,err
));
2257 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2258 timestring(),Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
,
2259 Connections
[cnum
].num_files_open
));
2265 /****************************************************************************
2266 reply to a writeclose (Core+ protocol)
2267 ****************************************************************************/
2268 int reply_writeclose(char *inbuf
,char *outbuf
)
2270 int cnum
,numtowrite
,fnum
;
2277 cnum
= SVAL(inbuf
,smb_tid
);
2278 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2280 CHECK_FNUM(fnum
,cnum
);
2284 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2285 startpos
= IVAL(inbuf
,smb_vwv2
);
2286 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2287 data
= smb_buf(inbuf
) + 1;
2289 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
2290 return(ERROR(ERRDOS
,ERRlock
));
2292 seek_file(fnum
,startpos
);
2294 nwritten
= write_file(fnum
,data
,numtowrite
);
2296 set_filetime(Files
[fnum
].name
,mtime
);
2300 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2301 timestring(),fnum
,cnum
,numtowrite
,nwritten
,
2302 Connections
[cnum
].num_files_open
));
2305 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2307 outsize
= set_message(outbuf
,1,0,True
);
2309 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2314 /****************************************************************************
2316 ****************************************************************************/
2317 int reply_lock(char *inbuf
,char *outbuf
)
2320 int outsize
= set_message(outbuf
,0,0,True
);
2321 uint32 count
,offset
;
2325 cnum
= SVAL(inbuf
,smb_tid
);
2326 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2328 CHECK_FNUM(fnum
,cnum
);
2331 count
= IVAL(inbuf
,smb_vwv1
);
2332 offset
= IVAL(inbuf
,smb_vwv3
);
2334 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
,offset
,count
));
2336 if(!do_lock( fnum
, cnum
, count
, offset
, &eclass
, &ecode
))
2337 return (ERROR(eclass
,ecode
));
2343 /****************************************************************************
2345 ****************************************************************************/
2346 int reply_unlock(char *inbuf
,char *outbuf
)
2349 int outsize
= set_message(outbuf
,0,0,True
);
2350 uint32 count
,offset
;
2354 cnum
= SVAL(inbuf
,smb_tid
);
2355 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2357 CHECK_FNUM(fnum
,cnum
);
2360 count
= IVAL(inbuf
,smb_vwv1
);
2361 offset
= IVAL(inbuf
,smb_vwv3
);
2363 if(!do_unlock(fnum
, cnum
, count
, offset
, &eclass
, &ecode
))
2364 return (ERROR(eclass
,ecode
));
2366 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
,offset
,count
));
2372 /****************************************************************************
2374 ****************************************************************************/
2375 int reply_tdis(char *inbuf
,char *outbuf
)
2378 int outsize
= set_message(outbuf
,0,0,True
);
2381 cnum
= SVAL(inbuf
,smb_tid
);
2382 vuid
= SVAL(inbuf
,smb_uid
);
2384 if (!OPEN_CNUM(cnum
)) {
2385 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum
));
2386 return(ERROR(ERRSRV
,ERRinvnid
));
2389 Connections
[cnum
].used
= False
;
2391 close_cnum(cnum
,vuid
);
2393 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum
));
2400 /****************************************************************************
2402 ****************************************************************************/
2403 int reply_echo(char *inbuf
,char *outbuf
)
2406 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2408 int data_len
= smb_buflen(inbuf
);
2409 int outsize
= set_message(outbuf
,1,data_len
,True
);
2411 cnum
= SVAL(inbuf
,smb_tid
);
2413 /* According to the latest CIFS spec we shouldn't
2414 care what the TID is.
2418 if (cnum
!= 0xFFFF && !OPEN_CNUM(cnum
))
2420 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum
));
2421 return(ERROR(ERRSRV
,ERRinvnid
));
2425 /* copy any incoming data back out */
2427 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2429 if (smb_reverb
> 100)
2431 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2435 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++)
2437 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2439 smb_setlen(outbuf
,outsize
- 4);
2441 send_smb(Client
,outbuf
);
2444 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb
,cnum
));
2450 /****************************************************************************
2451 reply to a printopen
2452 ****************************************************************************/
2453 int reply_printopen(char *inbuf
,char *outbuf
)
2461 *fname
= *fname2
= 0;
2463 cnum
= SVAL(inbuf
,smb_tid
);
2465 if (!CAN_PRINT(cnum
))
2466 return(ERROR(ERRDOS
,ERRnoaccess
));
2471 pstrcpy(s
,smb_buf(inbuf
)+1);
2475 if (!(isalnum(*p
) || strchr("._-",*p
)))
2480 if (strlen(s
) > 10) s
[10] = 0;
2482 sprintf(fname
,"%s.XXXXXX",s
);
2485 fnum
= find_free_file();
2487 return(ERROR(ERRSRV
,ERRnofids
));
2489 strcpy(fname2
,(char *)mktemp(fname
));
2491 if (!check_name(fname2
,cnum
))
2492 return(ERROR(ERRDOS
,ERRnoaccess
));
2494 /* Open for exclusive use, write only. */
2495 open_file_shared(fnum
,cnum
,fname2
,(DENY_ALL
<<4)|1, 0x12, unix_mode(cnum
,0),
2498 if (!Files
[fnum
].open
)
2499 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2501 /* force it to be a print file */
2502 Files
[fnum
].print_file
= True
;
2504 outsize
= set_message(outbuf
,1,0,True
);
2505 SSVAL(outbuf
,smb_vwv0
,fnum
);
2507 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2
,Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
));
2513 /****************************************************************************
2514 reply to a printclose
2515 ****************************************************************************/
2516 int reply_printclose(char *inbuf
,char *outbuf
)
2519 int outsize
= set_message(outbuf
,0,0,True
);
2521 cnum
= SVAL(inbuf
,smb_tid
);
2522 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2524 CHECK_FNUM(fnum
,cnum
);
2527 if (!CAN_PRINT(cnum
))
2528 return(ERROR(ERRDOS
,ERRnoaccess
));
2532 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
));
2538 /****************************************************************************
2539 reply to a printqueue
2540 ****************************************************************************/
2541 int reply_printqueue(char *inbuf
,char *outbuf
)
2544 int outsize
= set_message(outbuf
,2,3,True
);
2545 int max_count
= SVAL(inbuf
,smb_vwv0
);
2546 int start_index
= SVAL(inbuf
,smb_vwv1
);
2549 cnum
= SVAL(inbuf
,smb_tid
);
2550 vuid
= SVAL(inbuf
,smb_uid
);
2552 /* allow checking the queue for anyone */
2554 if (!CAN_PRINT(cnum
))
2555 return(ERROR(ERRDOS
,ERRnoaccess
));
2558 SSVAL(outbuf
,smb_vwv0
,0);
2559 SSVAL(outbuf
,smb_vwv1
,0);
2560 CVAL(smb_buf(outbuf
),0) = 1;
2561 SSVAL(smb_buf(outbuf
),1,0);
2563 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2564 timestring(),cnum
,start_index
,max_count
));
2566 if (!OPEN_CNUM(cnum
) || !Connections
[cnum
].printer
)
2571 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2572 if (CAN_PRINT(i
) && Connections
[i
].printer
)
2576 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2580 if (!OPEN_CNUM(cnum
))
2581 return(ERROR(ERRSRV
,ERRinvnid
));
2583 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum
));
2586 if (!become_user(cnum
,vuid
))
2587 return(ERROR(ERRSRV
,ERRinvnid
));
2590 print_queue_struct
*queue
= NULL
;
2591 char *p
= smb_buf(outbuf
) + 3;
2592 int count
= get_printqueue(SNUM(cnum
),cnum
,&queue
,NULL
);
2593 int num_to_get
= ABS(max_count
);
2594 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
2600 num_to_get
= MIN(num_to_get
,count
-first
);
2603 for (i
=first
;i
<first
+num_to_get
;i
++)
2605 put_dos_date2(p
,0,queue
[i
].time
);
2606 CVAL(p
,4) = (queue
[i
].status
==LPQ_PRINTING
?2:3);
2607 SSVAL(p
,5,printjob_encode(SNUM(cnum
), queue
[i
].job
));
2608 SIVAL(p
,7,queue
[i
].size
);
2610 StrnCpy(p
+12,queue
[i
].user
,16);
2616 outsize
= set_message(outbuf
,2,28*count
+3,False
);
2617 SSVAL(outbuf
,smb_vwv0
,count
);
2618 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
2619 CVAL(smb_buf(outbuf
),0) = 1;
2620 SSVAL(smb_buf(outbuf
),1,28*count
);
2623 if (queue
) free(queue
);
2625 DEBUG(3,("%d entries returned in queue\n",count
));
2632 /****************************************************************************
2633 reply to a printwrite
2634 ****************************************************************************/
2635 int reply_printwrite(char *inbuf
,char *outbuf
)
2637 int cnum
,numtowrite
,fnum
;
2638 int outsize
= set_message(outbuf
,0,0,True
);
2641 cnum
= SVAL(inbuf
,smb_tid
);
2643 if (!CAN_PRINT(cnum
))
2644 return(ERROR(ERRDOS
,ERRnoaccess
));
2646 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2648 CHECK_FNUM(fnum
,cnum
);
2652 numtowrite
= SVAL(smb_buf(inbuf
),1);
2653 data
= smb_buf(inbuf
) + 3;
2655 if (write_file(fnum
,data
,numtowrite
) != numtowrite
)
2656 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2658 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum
,cnum
,numtowrite
));
2664 /****************************************************************************
2666 ****************************************************************************/
2667 int reply_mkdir(char *inbuf
,char *outbuf
)
2671 int outsize
,ret
= -1;
2672 BOOL bad_path
= False
;
2674 pstrcpy(directory
,smb_buf(inbuf
) + 1);
2675 cnum
= SVAL(inbuf
,smb_tid
);
2676 unix_convert(directory
,cnum
,0,&bad_path
);
2678 if (check_name(directory
,cnum
))
2679 ret
= sys_mkdir(directory
,unix_mode(cnum
,aDIR
));
2683 if((errno
== ENOENT
) && bad_path
)
2685 unix_ERR_class
= ERRDOS
;
2686 unix_ERR_code
= ERRbadpath
;
2688 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2691 outsize
= set_message(outbuf
,0,0,True
);
2693 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory
,cnum
,ret
));
2698 /****************************************************************************
2699 Static function used by reply_rmdir to delete an entire directory
2701 ****************************************************************************/
2702 static BOOL
recursive_rmdir(char *directory
)
2706 void *dirptr
= OpenDir(-1, directory
, False
);
2711 while((dname
= ReadDirName(dirptr
)))
2716 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2719 /* Construct the full name. */
2720 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
2726 strcpy(fullname
, directory
);
2727 strcat(fullname
, "/");
2728 strcat(fullname
, dname
);
2730 if(sys_lstat(fullname
, &st
) != 0)
2736 if(st
.st_mode
& S_IFDIR
)
2738 if(recursive_rmdir(fullname
)!=0)
2743 if(sys_rmdir(fullname
) != 0)
2749 else if(sys_unlink(fullname
) != 0)
2759 /****************************************************************************
2761 ****************************************************************************/
2762 int reply_rmdir(char *inbuf
,char *outbuf
)
2768 BOOL bad_path
= False
;
2770 cnum
= SVAL(inbuf
,smb_tid
);
2771 pstrcpy(directory
,smb_buf(inbuf
) + 1);
2772 unix_convert(directory
,cnum
,0,&bad_path
);
2774 if (check_name(directory
,cnum
))
2777 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
2778 ok
= (sys_rmdir(directory
) == 0);
2779 if(!ok
&& (errno
== ENOTEMPTY
) && lp_veto_files(SNUM(cnum
)))
2781 /* Check to see if the only thing in this directory are
2782 vetoed files/directories. If so then delete them and
2783 retry. If we fail to delete any of them (and we *don't*
2784 do a recursive delete) then fail the rmdir. */
2785 BOOL all_veto_files
= True
;
2787 void *dirptr
= OpenDir(cnum
, directory
, False
);
2791 int dirpos
= TellDir(dirptr
);
2792 while ((dname
= ReadDirName(dirptr
)))
2794 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2796 if(!IS_VETO_PATH(cnum
, dname
))
2798 all_veto_files
= False
;
2804 SeekDir(dirptr
,dirpos
);
2805 while ((dname
= ReadDirName(dirptr
)))
2810 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2813 /* Construct the full name. */
2814 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
2819 pstrcpy(fullname
, directory
);
2820 strcat(fullname
, "/");
2821 strcat(fullname
, dname
);
2823 if(sys_lstat(fullname
, &st
) != 0)
2825 if(st
.st_mode
& S_IFDIR
)
2827 if(lp_recursive_veto_delete(SNUM(cnum
)))
2829 if(recursive_rmdir(fullname
) != 0)
2832 if(sys_rmdir(fullname
) != 0)
2835 else if(sys_unlink(fullname
) != 0)
2839 /* Retry the rmdir */
2840 ok
= (sys_rmdir(directory
) == 0);
2850 DEBUG(3,("couldn't remove directory %s : %s\n",
2851 directory
,strerror(errno
)));
2856 if((errno
== ENOENT
) && bad_path
)
2858 unix_ERR_class
= ERRDOS
;
2859 unix_ERR_code
= ERRbadpath
;
2861 return(UNIXERROR(ERRDOS
,ERRbadpath
));
2864 outsize
= set_message(outbuf
,0,0,True
);
2866 DEBUG(3,("%s rmdir %s\n",timestring(),directory
));
2872 /*******************************************************************
2873 resolve wildcards in a filename rename
2874 ********************************************************************/
2875 static BOOL
resolve_wildcards(char *name1
,char *name2
)
2877 fstring root1
,root2
;
2881 name1
= strrchr(name1
,'/');
2882 name2
= strrchr(name2
,'/');
2884 if (!name1
|| !name2
) return(False
);
2886 fstrcpy(root1
,name1
);
2887 fstrcpy(root2
,name2
);
2888 p
= strrchr(root1
,'.');
2895 p
= strrchr(root2
,'.');
2927 strcpy(name2
,root2
);
2936 /*******************************************************************
2937 check if a user is allowed to rename a file
2938 ********************************************************************/
2939 static BOOL
can_rename(char *fname
,int cnum
)
2943 if (!CAN_WRITE(cnum
)) return(False
);
2945 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
2946 if (!check_file_sharing(cnum
,fname
)) return(False
);
2951 /****************************************************************************
2953 ****************************************************************************/
2954 int reply_mv(char *inbuf
,char *outbuf
)
2960 pstring mask
,newname
;
2961 pstring newname_last_component
;
2964 int error
= ERRnoaccess
;
2967 BOOL bad_path1
= False
;
2968 BOOL bad_path2
= False
;
2970 *directory
= *mask
= 0;
2972 cnum
= SVAL(inbuf
,smb_tid
);
2974 pstrcpy(name
,smb_buf(inbuf
) + 1);
2975 pstrcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
2977 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
2979 unix_convert(name
,cnum
,0,&bad_path1
);
2980 unix_convert(newname
,cnum
,newname_last_component
,&bad_path2
);
2983 * Split the old name into directory and last component
2984 * strings. Note that unix_convert may have stripped off a
2985 * leading ./ from both name and newname if the rename is
2986 * at the root of the share. We need to make sure either both
2987 * name and newname contain a / character or neither of them do
2988 * as this is checked in resolve_wildcards().
2991 p
= strrchr(name
,'/');
2993 strcpy(directory
,".");
2997 strcpy(directory
,name
);
2999 *p
= '/'; /* Replace needed for exceptional test below. */
3002 if (is_mangled(mask
))
3003 check_mangled_stack(mask
);
3005 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
3008 BOOL is_short_name
= is_8_3(name
, True
);
3010 /* Add a terminating '/' to the directory name. */
3011 strcat(directory
,"/");
3012 strcat(directory
,mask
);
3014 /* Ensure newname contains a '/' also */
3015 if(strrchr(newname
,'/') == 0) {
3018 strcpy(tmpstr
, "./");
3019 strcat(tmpstr
, newname
);
3020 strcpy(newname
, tmpstr
);
3023 DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3024 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3025 newname
, newname_last_component
, is_short_name
));
3028 * Check for special case with case preserving and not
3029 * case sensitive, if directory and newname are identical,
3030 * and the old last component differs from the original
3031 * last component only by case, then we should allow
3032 * the rename (user is trying to change the case of the
3035 if((case_sensitive
== False
) && ( ((case_preserve
== True
) && (is_short_name
== False
)) ||
3036 ((short_case_preserve
== True
) && (is_short_name
== True
))) &&
3037 strcsequal(directory
, newname
)) {
3038 pstring newname_modified_last_component
;
3041 * Get the last component of the modified name.
3042 * Note that we guarantee that newname contains a '/'
3045 p
= strrchr(newname
,'/');
3046 strcpy(newname_modified_last_component
,p
+1);
3048 if(strcsequal(newname_modified_last_component
,
3049 newname_last_component
) == False
) {
3051 * Replace the modified last component with
3054 strcpy(p
+1, newname_last_component
);
3058 if (resolve_wildcards(directory
,newname
) &&
3059 can_rename(directory
,cnum
) &&
3060 !file_exist(newname
,NULL
) &&
3061 !sys_rename(directory
,newname
)) count
++;
3063 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count
!= 0) ? "succeeded" : "failed",
3064 directory
,newname
));
3066 if (!count
) exists
= file_exist(directory
,NULL
);
3067 if (!count
&& exists
&& file_exist(newname
,NULL
)) {
3072 void *dirptr
= NULL
;
3076 if (check_name(directory
,cnum
))
3077 dirptr
= OpenDir(cnum
, directory
, True
);
3083 if (strequal(mask
,"????????.???"))
3086 while ((dname
= ReadDirName(dirptr
)))
3089 pstrcpy(fname
,dname
);
3091 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
3093 error
= ERRnoaccess
;
3094 sprintf(fname
,"%s/%s",directory
,dname
);
3095 if (!can_rename(fname
,cnum
)) continue;
3096 pstrcpy(destname
,newname
);
3098 if (!resolve_wildcards(fname
,destname
)) continue;
3100 if (file_exist(destname
,NULL
)) {
3104 if (!sys_rename(fname
,destname
)) count
++;
3105 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname
,destname
));
3113 return(ERROR(ERRDOS
,error
));
3116 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
3118 unix_ERR_class
= ERRDOS
;
3119 unix_ERR_code
= ERRbadpath
;
3121 return(UNIXERROR(ERRDOS
,error
));
3125 outsize
= set_message(outbuf
,0,0,True
);
3130 /*******************************************************************
3131 copy a file as part of a reply_copy
3132 ******************************************************************/
3133 static BOOL
copy_file(char *src
,char *dest1
,int cnum
,int ofun
,
3134 int count
,BOOL target_is_directory
)
3142 pstrcpy(dest
,dest1
);
3143 if (target_is_directory
) {
3144 char *p
= strrchr(src
,'/');
3153 if (!file_exist(src
,&st
)) return(False
);
3155 fnum1
= find_free_file();
3156 if (fnum1
<0) return(False
);
3157 open_file_shared(fnum1
,cnum
,src
,(DENY_NONE
<<4),
3158 1,0,0,&Access
,&action
);
3160 if (!Files
[fnum1
].open
) return(False
);
3162 if (!target_is_directory
&& count
)
3165 fnum2
= find_free_file();
3170 open_file_shared(fnum2
,cnum
,dest
,(DENY_NONE
<<4)|1,
3171 ofun
,st
.st_mode
,0,&Access
,&action
);
3173 if (!Files
[fnum2
].open
) {
3178 if ((ofun
&3) == 1) {
3179 lseek(Files
[fnum2
].fd_ptr
->fd
,0,SEEK_END
);
3183 ret
= transfer_file(Files
[fnum1
].fd_ptr
->fd
,Files
[fnum2
].fd_ptr
->fd
,st
.st_size
,NULL
,0,0);
3188 return(ret
== st
.st_size
);
3193 /****************************************************************************
3194 reply to a file copy.
3195 ****************************************************************************/
3196 int reply_copy(char *inbuf
,char *outbuf
)
3202 pstring mask
,newname
;
3205 int error
= ERRnoaccess
;
3208 int tid2
= SVAL(inbuf
,smb_vwv0
);
3209 int ofun
= SVAL(inbuf
,smb_vwv1
);
3210 int flags
= SVAL(inbuf
,smb_vwv2
);
3211 BOOL target_is_directory
=False
;
3212 BOOL bad_path1
= False
;
3213 BOOL bad_path2
= False
;
3215 *directory
= *mask
= 0;
3217 cnum
= SVAL(inbuf
,smb_tid
);
3219 pstrcpy(name
,smb_buf(inbuf
));
3220 pstrcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
3222 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
3225 /* can't currently handle inter share copies XXXX */
3226 DEBUG(3,("Rejecting inter-share copy\n"));
3227 return(ERROR(ERRSRV
,ERRinvdevice
));
3230 unix_convert(name
,cnum
,0,&bad_path1
);
3231 unix_convert(newname
,cnum
,0,&bad_path2
);
3233 target_is_directory
= directory_exist(newname
,NULL
);
3235 if ((flags
&1) && target_is_directory
) {
3236 return(ERROR(ERRDOS
,ERRbadfile
));
3239 if ((flags
&2) && !target_is_directory
) {
3240 return(ERROR(ERRDOS
,ERRbadpath
));
3243 if ((flags
&(1<<5)) && directory_exist(name
,NULL
)) {
3244 /* wants a tree copy! XXXX */
3245 DEBUG(3,("Rejecting tree copy\n"));
3246 return(ERROR(ERRSRV
,ERRerror
));
3249 p
= strrchr(name
,'/');
3251 strcpy(directory
,"./");
3255 strcpy(directory
,name
);
3259 if (is_mangled(mask
))
3260 check_mangled_stack(mask
);
3262 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
3265 strcat(directory
,"/");
3266 strcat(directory
,mask
);
3267 if (resolve_wildcards(directory
,newname
) &&
3268 copy_file(directory
,newname
,cnum
,ofun
,
3269 count
,target_is_directory
)) count
++;
3270 if (!count
) exists
= file_exist(directory
,NULL
);
3272 void *dirptr
= NULL
;
3276 if (check_name(directory
,cnum
))
3277 dirptr
= OpenDir(cnum
, directory
, True
);
3283 if (strequal(mask
,"????????.???"))
3286 while ((dname
= ReadDirName(dirptr
)))
3289 pstrcpy(fname
,dname
);
3291 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
3293 error
= ERRnoaccess
;
3294 sprintf(fname
,"%s/%s",directory
,dname
);
3295 strcpy(destname
,newname
);
3296 if (resolve_wildcards(fname
,destname
) &&
3297 copy_file(directory
,newname
,cnum
,ofun
,
3298 count
,target_is_directory
)) count
++;
3299 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
3307 return(ERROR(ERRDOS
,error
));
3310 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
3312 unix_ERR_class
= ERRDOS
;
3313 unix_ERR_code
= ERRbadpath
;
3315 return(UNIXERROR(ERRDOS
,error
));
3319 outsize
= set_message(outbuf
,1,0,True
);
3320 SSVAL(outbuf
,smb_vwv0
,count
);
3327 /****************************************************************************
3329 ****************************************************************************/
3330 int reply_setdir(char *inbuf
,char *outbuf
)
3337 cnum
= SVAL(inbuf
,smb_tid
);
3339 snum
= Connections
[cnum
].service
;
3340 if (!CAN_SETDIR(snum
))
3341 return(ERROR(ERRDOS
,ERRnoaccess
));
3343 pstrcpy(newdir
,smb_buf(inbuf
) + 1);
3346 if (strlen(newdir
) == 0)
3350 ok
= directory_exist(newdir
,NULL
);
3352 string_set(&Connections
[cnum
].connectpath
,newdir
);
3356 return(ERROR(ERRDOS
,ERRbadpath
));
3358 outsize
= set_message(outbuf
,0,0,True
);
3359 CVAL(outbuf
,smb_reh
) = CVAL(inbuf
,smb_reh
);
3361 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir
,cnum
));
3367 /****************************************************************************
3368 reply to a lockingX request
3369 ****************************************************************************/
3370 int reply_lockingX(char *inbuf
,char *outbuf
,int length
,int bufsize
)
3372 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
3373 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
3375 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
3377 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
3378 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
3379 uint32 count
, offset
;
3384 uint32 ecode
=0, dummy2
;
3385 int eclass
=0, dummy1
;
3387 cnum
= SVAL(inbuf
,smb_tid
);
3389 CHECK_FNUM(fnum
,cnum
);
3392 data
= smb_buf(inbuf
);
3394 /* Check if this is an oplock break on a file
3395 we have granted an oplock on.
3397 if((locktype
== LOCKING_ANDX_OPLOCK_RELEASE
) &&
3398 (num_ulocks
== 0) && (num_locks
== 0) &&
3399 (CVAL(inbuf
,smb_vwv0
) == 0xFF))
3401 share_lock_token token
;
3402 files_struct
*fsp
= &Files
[fnum
];
3403 uint32 dev
= fsp
->fd_ptr
->dev
;
3404 uint32 inode
= fsp
->fd_ptr
->inode
;
3406 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3409 * Make sure we have granted an oplock on this file.
3411 if(!fsp
->granted_oplock
)
3413 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3414 no oplock granted on this file.\n", fnum
));
3415 return ERROR(ERRDOS
,ERRlock
);
3418 /* Remove the oplock flag from the sharemode. */
3419 lock_share_entry(fsp
->cnum
, dev
, inode
, &token
);
3420 if(remove_share_oplock( fnum
, token
)==False
)
3422 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3423 dev = %x, inode = %x\n", fnum
, dev
, inode
));
3424 unlock_share_entry(fsp
->cnum
, dev
, inode
, token
);
3427 unlock_share_entry(fsp
->cnum
, dev
, inode
, token
);
3429 /* Clear the granted flag and return. */
3431 fsp
->granted_oplock
= False
;
3435 /* Data now points at the beginning of the list
3436 of smb_unlkrng structs */
3437 for(i
= 0; i
< (int)num_ulocks
; i
++) {
3438 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3439 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3440 if(!do_unlock(fnum
,cnum
,count
,offset
,&eclass
, &ecode
))
3441 return ERROR(eclass
,ecode
);
3444 /* Now do any requested locks */
3445 data
+= 10*num_ulocks
;
3446 /* Data now points at the beginning of the list
3447 of smb_lkrng structs */
3448 for(i
= 0; i
< (int)num_locks
; i
++) {
3449 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3450 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3451 if(!do_lock(fnum
,cnum
,count
,offset
, &eclass
, &ecode
))
3455 /* If any of the above locks failed, then we must unlock
3456 all of the previous locks (X/Open spec). */
3457 if(i
!= num_locks
&& num_locks
!= 0) {
3458 for(; i
>= 0; i
--) {
3459 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3460 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3461 do_unlock(fnum
,cnum
,count
,offset
,&dummy1
,&dummy2
);
3463 return ERROR(eclass
,ecode
);
3466 set_message(outbuf
,2,0,True
);
3468 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3469 timestring(),fnum
,cnum
,(unsigned int)locktype
,num_locks
,num_ulocks
));
3473 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
3477 /****************************************************************************
3478 reply to a SMBreadbmpx (read block multiplex) request
3479 ****************************************************************************/
3480 int reply_readbmpx(char *inbuf
,char *outbuf
,int length
,int bufsize
)
3487 int outsize
, mincount
, maxcount
;
3492 /* this function doesn't seem to work - disable by default */
3494 return(ERROR(ERRSRV
,ERRuseSTD
));
3496 outsize
= set_message(outbuf
,8,0,True
);
3498 cnum
= SVAL(inbuf
,smb_tid
);
3499 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3501 CHECK_FNUM(fnum
,cnum
);
3505 startpos
= IVAL(inbuf
,smb_vwv1
);
3506 maxcount
= SVAL(inbuf
,smb_vwv3
);
3507 mincount
= SVAL(inbuf
,smb_vwv4
);
3509 data
= smb_buf(outbuf
);
3510 pad
= ((long)data
)%4;
3511 if (pad
) pad
= 4 - pad
;
3514 max_per_packet
= bufsize
-(outsize
+pad
);
3518 if (is_locked(fnum
,cnum
,maxcount
,startpos
))
3519 return(ERROR(ERRDOS
,ERRlock
));
3523 int N
= MIN(max_per_packet
,tcount
-total_read
);
3525 nread
= read_file(fnum
,data
,startpos
,N
);
3527 if (nread
<= 0) nread
= 0;
3530 tcount
= total_read
+ nread
;
3532 set_message(outbuf
,8,nread
,False
);
3533 SIVAL(outbuf
,smb_vwv0
,startpos
);
3534 SSVAL(outbuf
,smb_vwv2
,tcount
);
3535 SSVAL(outbuf
,smb_vwv6
,nread
);
3536 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
3538 send_smb(Client
,outbuf
);
3540 total_read
+= nread
;
3543 while (total_read
< tcount
);
3549 /****************************************************************************
3550 reply to a SMBwritebmpx (write block multiplex primary) request
3551 ****************************************************************************/
3552 int reply_writebmpx(char *inbuf
,char *outbuf
)
3554 int cnum
,numtowrite
,fnum
;
3558 int tcount
, write_through
, smb_doff
;
3561 cnum
= SVAL(inbuf
,smb_tid
);
3562 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3564 CHECK_FNUM(fnum
,cnum
);
3568 tcount
= SVAL(inbuf
,smb_vwv1
);
3569 startpos
= IVAL(inbuf
,smb_vwv3
);
3570 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
3571 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3572 smb_doff
= SVAL(inbuf
,smb_vwv11
);
3574 data
= smb_base(inbuf
) + smb_doff
;
3576 /* If this fails we need to send an SMBwriteC response,
3577 not an SMBwritebmpx - set this up now so we don't forget */
3578 CVAL(outbuf
,smb_com
) = SMBwritec
;
3580 if (is_locked(fnum
,cnum
,tcount
,startpos
))
3581 return(ERROR(ERRDOS
,ERRlock
));
3583 seek_file(fnum
,startpos
);
3584 nwritten
= write_file(fnum
,data
,numtowrite
);
3586 if(lp_syncalways(SNUM(cnum
)) || write_through
)
3589 if(nwritten
< numtowrite
)
3590 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3592 /* If the maximum to be written to this file
3593 is greater than what we just wrote then set
3594 up a secondary struct to be attached to this
3595 fd, we will use this to cache error messages etc. */
3596 if(tcount
> nwritten
)
3598 write_bmpx_struct
*wbms
;
3599 if(Files
[fnum
].wbmpx_ptr
!= NULL
)
3600 wbms
= Files
[fnum
].wbmpx_ptr
; /* Use an existing struct */
3602 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
3605 DEBUG(0,("Out of memory in reply_readmpx\n"));
3606 return(ERROR(ERRSRV
,ERRnoresource
));
3608 wbms
->wr_mode
= write_through
;
3609 wbms
->wr_discard
= False
; /* No errors yet */
3610 wbms
->wr_total_written
= nwritten
;
3611 wbms
->wr_errclass
= 0;
3613 Files
[fnum
].wbmpx_ptr
= wbms
;
3616 /* We are returning successfully, set the message type back to
3618 CVAL(outbuf
,smb_com
) = SMBwriteBmpx
;
3620 outsize
= set_message(outbuf
,1,0,True
);
3622 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
3624 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3625 timestring(),fnum
,cnum
,numtowrite
,nwritten
));
3627 if (write_through
&& tcount
==nwritten
) {
3628 /* we need to send both a primary and a secondary response */
3629 smb_setlen(outbuf
,outsize
- 4);
3630 send_smb(Client
,outbuf
);
3632 /* now the secondary */
3633 outsize
= set_message(outbuf
,1,0,True
);
3634 CVAL(outbuf
,smb_com
) = SMBwritec
;
3635 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3642 /****************************************************************************
3643 reply to a SMBwritebs (write block multiplex secondary) request
3644 ****************************************************************************/
3645 int reply_writebs(char *inbuf
,char *outbuf
)
3647 int cnum
,numtowrite
,fnum
;
3651 int tcount
, write_through
, smb_doff
;
3653 write_bmpx_struct
*wbms
;
3654 BOOL send_response
= False
;
3656 cnum
= SVAL(inbuf
,smb_tid
);
3657 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3658 CHECK_FNUM(fnum
,cnum
);
3661 tcount
= SVAL(inbuf
,smb_vwv1
);
3662 startpos
= IVAL(inbuf
,smb_vwv2
);
3663 numtowrite
= SVAL(inbuf
,smb_vwv6
);
3664 smb_doff
= SVAL(inbuf
,smb_vwv7
);
3666 data
= smb_base(inbuf
) + smb_doff
;
3668 /* We need to send an SMBwriteC response, not an SMBwritebs */
3669 CVAL(outbuf
,smb_com
) = SMBwritec
;
3671 /* This fd should have an auxiliary struct attached,
3672 check that it does */
3673 wbms
= Files
[fnum
].wbmpx_ptr
;
3674 if(!wbms
) return(-1);
3676 /* If write through is set we can return errors, else we must
3678 write_through
= wbms
->wr_mode
;
3680 /* Check for an earlier error */
3681 if(wbms
->wr_discard
)
3682 return -1; /* Just discard the packet */
3684 seek_file(fnum
,startpos
);
3685 nwritten
= write_file(fnum
,data
,numtowrite
);
3687 if(lp_syncalways(SNUM(cnum
)) || write_through
)
3690 if (nwritten
< numtowrite
)
3693 /* We are returning an error - we can delete the aux struct */
3694 if (wbms
) free((char *)wbms
);
3695 Files
[fnum
].wbmpx_ptr
= NULL
;
3696 return(ERROR(ERRHRD
,ERRdiskfull
));
3698 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
3701 /* Increment the total written, if this matches tcount
3702 we can discard the auxiliary struct (hurrah !) and return a writeC */
3703 wbms
->wr_total_written
+= nwritten
;
3704 if(wbms
->wr_total_written
>= tcount
)
3706 if (write_through
) {
3707 outsize
= set_message(outbuf
,1,0,True
);
3708 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
3709 send_response
= True
;
3713 Files
[fnum
].wbmpx_ptr
= NULL
;
3723 /****************************************************************************
3724 reply to a SMBsetattrE
3725 ****************************************************************************/
3726 int reply_setattrE(char *inbuf
,char *outbuf
)
3729 struct utimbuf unix_times
;
3732 outsize
= set_message(outbuf
,0,0,True
);
3734 cnum
= SVAL(inbuf
,smb_tid
);
3735 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3737 CHECK_FNUM(fnum
,cnum
);
3740 /* Convert the DOS times into unix times. Ignore create
3741 time as UNIX can't set this.
3743 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
3744 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
3747 * Patch from Ray Frush <frush@engr.colostate.edu>
3748 * Sometimes times are sent as zero - ignore them.
3751 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0))
3753 /* Ignore request */
3754 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3755 not setting timestamps of 0\n",
3756 timestring(), fnum
,cnum
,unix_times
.actime
,unix_times
.modtime
));
3759 else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0))
3761 /* set modify time = to access time if modify time was 0 */
3762 unix_times
.modtime
= unix_times
.actime
;
3765 /* Set the date on this file */
3766 if(sys_utime(Files
[fnum
].name
, &unix_times
))
3767 return(ERROR(ERRDOS
,ERRnoaccess
));
3769 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3770 timestring(), fnum
,cnum
,unix_times
.actime
,unix_times
.modtime
));
3776 /****************************************************************************
3777 reply to a SMBgetattrE
3778 ****************************************************************************/
3779 int reply_getattrE(char *inbuf
,char *outbuf
)
3786 outsize
= set_message(outbuf
,11,0,True
);
3788 cnum
= SVAL(inbuf
,smb_tid
);
3789 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3791 CHECK_FNUM(fnum
,cnum
);
3794 /* Do an fstat on this file */
3795 if(fstat(Files
[fnum
].fd_ptr
->fd
, &sbuf
))
3796 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3798 mode
= dos_mode(cnum
,Files
[fnum
].name
,&sbuf
);
3800 /* Convert the times into dos times. Set create
3801 date to be last modify date as UNIX doesn't save
3803 put_dos_date2(outbuf
,smb_vwv0
,sbuf
.st_mtime
);
3804 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
3805 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
3808 SIVAL(outbuf
,smb_vwv6
,0);
3809 SIVAL(outbuf
,smb_vwv8
,0);
3813 SIVAL(outbuf
,smb_vwv6
,sbuf
.st_size
);
3814 SIVAL(outbuf
,smb_vwv8
,ROUNDUP(sbuf
.st_size
,1024));
3816 SSVAL(outbuf
,smb_vwv10
, mode
);
3818 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum
,cnum
));