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
;
46 /* this macro should always be used to extract an fnum (smb_fid) from
47 a packet to ensure chaining works correctly */
48 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
51 /****************************************************************************
52 reply to an special message
53 ****************************************************************************/
54 int reply_special(char *inbuf
,char *outbuf
)
57 int msg_type
= CVAL(inbuf
,0);
58 int msg_flags
= CVAL(inbuf
,1);
60 extern fstring remote_machine
;
61 extern fstring local_machine
;
70 case 0x81: /* session request */
71 CVAL(outbuf
,0) = 0x82;
73 if (name_len(inbuf
+4) > 50)
75 DEBUG(0,("Invalid name length in session request\n"));
78 name_extract(inbuf
,4,name1
);
79 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
80 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1
,name2
));
82 strcpy(remote_machine
,name2
);
83 trim_string(remote_machine
," "," ");
84 p
= strchr(remote_machine
,' ');
85 strlower(remote_machine
);
88 strcpy(local_machine
,name1
);
89 trim_string(local_machine
," "," ");
90 p
= strchr(local_machine
,' ');
91 strlower(local_machine
);
94 add_session_user(remote_machine
);
96 reload_services(True
);
100 case 0x85: /* session keepalive */
105 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type
,msg_flags
));
111 /*******************************************************************
112 work out what error to give to a failed connection
113 ********************************************************************/
114 static int connection_error(char *inbuf
,char *outbuf
,int connection_num
)
116 switch (connection_num
)
119 return(ERROR(ERRSRV
,ERRnoresource
));
121 return(ERROR(ERRSRV
,ERRbaduid
));
123 return(ERROR(ERRSRV
,ERRinvdevice
));
125 return(ERROR(ERRSRV
,ERRinvnetname
));
127 return(ERROR(ERRSRV
,ERRaccess
));
129 return(ERROR(ERRDOS
,ERRnoipc
));
131 return(ERROR(ERRSRV
,ERRinvnetname
));
133 return(ERROR(ERRSRV
,ERRbadpw
));
138 /****************************************************************************
139 parse a share descriptor string
140 ****************************************************************************/
141 static void parse_connect(char *p
,char *service
,char *user
,
142 char *password
,int *pwlen
,char *dev
)
146 DEBUG(4,("parsing connect string %s\n",p
));
148 p2
= strrchr(p
,'\\');
152 strcpy(service
,p2
+1);
157 *pwlen
= strlen(password
);
164 p
= strchr(service
,'%');
175 /****************************************************************************
177 ****************************************************************************/
178 int reply_tcon(char *inbuf
,char *outbuf
)
186 uint16 vuid
= SVAL(inbuf
,smb_uid
);
189 *service
= *user
= *password
= *dev
= 0;
191 parse_connect(smb_buf(inbuf
)+1,service
,user
,password
,&pwlen
,dev
);
193 connection_num
= make_connection(service
,user
,password
,pwlen
,dev
,vuid
);
195 if (connection_num
< 0)
196 return(connection_error(inbuf
,outbuf
,connection_num
));
198 outsize
= set_message(outbuf
,2,0,True
);
199 SSVAL(outbuf
,smb_vwv0
,max_recv
);
200 SSVAL(outbuf
,smb_vwv1
,connection_num
);
201 SSVAL(outbuf
,smb_tid
,connection_num
);
203 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service
,user
,connection_num
));
209 /****************************************************************************
210 reply to a tcon and X
211 ****************************************************************************/
212 int reply_tcon_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
219 uint16 vuid
= SVAL(inbuf
,smb_uid
);
220 int passlen
= SVAL(inbuf
,smb_vwv3
);
221 BOOL doencrypt
= SMBENCRYPT();
223 *service
= *user
= *password
= *devicename
= 0;
225 /* we might have to close an old one */
226 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) != 0)
227 close_cnum(SVAL(inbuf
,smb_tid
),vuid
);
232 memcpy(password
,smb_buf(inbuf
),passlen
);
234 path
= smb_buf(inbuf
) + passlen
;
236 if (!doencrypt
|| passlen
!= 24) {
237 if (strequal(password
," "))
239 passlen
= strlen(password
);
242 DEBUG(4,("parsing net-path %s, passlen=%d\n",path
,passlen
));
243 strcpy(service
,path
+2);
244 p
= strchr(service
,'\\');
246 return(ERROR(ERRSRV
,ERRinvnetname
));
249 p
= strchr(service
,'%');
255 StrnCpy(devicename
,path
+ strlen(path
) + 1,6);
256 DEBUG(4,("Got device type %s\n",devicename
));
259 connection_num
= make_connection(service
,user
,password
,passlen
,devicename
,vuid
);
261 if (connection_num
< 0)
262 return(connection_error(inbuf
,outbuf
,connection_num
));
264 set_message(outbuf
,2,strlen(devicename
)+1,True
);
266 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service
,user
,connection_num
));
268 /* set the incoming and outgoing tid to the just created one */
269 SSVAL(inbuf
,smb_tid
,connection_num
);
270 SSVAL(outbuf
,smb_tid
,connection_num
);
272 strcpy(smb_buf(outbuf
),devicename
);
274 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
278 /****************************************************************************
279 reply to an unknown type
280 ****************************************************************************/
281 int reply_unknown(char *inbuf
,char *outbuf
)
285 cnum
= SVAL(inbuf
,smb_tid
);
286 type
= CVAL(inbuf
,smb_com
);
288 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
293 return(ERROR(ERRSRV
,ERRunknownsmb
));
297 /****************************************************************************
299 ****************************************************************************/
300 int reply_ioctl(char *inbuf
,char *outbuf
)
302 DEBUG(3,("ignoring ioctl\n"));
304 /* we just say it succeeds and hope its all OK.
305 some day it would be nice to interpret them individually */
306 return set_message(outbuf
,1,0,True
);
308 return(ERROR(ERRSRV
,ERRnosupport
));
313 /****************************************************************************
314 reply to a session setup command
315 ****************************************************************************/
316 int reply_sesssetup_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
325 int smb_apasslen
= 0;
327 int smb_ntpasslen
= 0;
328 pstring smb_ntpasswd
;
329 BOOL valid_nt_password
= False
;
332 BOOL computer_id
=False
;
333 static BOOL done_sesssetup
= False
;
334 BOOL doencrypt
= SMBENCRYPT();
338 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
339 smb_mpxmax
= SVAL(inbuf
,smb_vwv3
);
340 smb_vc_num
= SVAL(inbuf
,smb_vwv4
);
341 smb_sesskey
= IVAL(inbuf
,smb_vwv5
);
343 if (Protocol
< PROTOCOL_NT1
) {
344 smb_apasslen
= SVAL(inbuf
,smb_vwv7
);
345 memcpy(smb_apasswd
,smb_buf(inbuf
),smb_apasslen
);
346 StrnCpy(user
,smb_buf(inbuf
)+smb_apasslen
,sizeof(user
)-1);
348 if (lp_security() != SEC_SERVER
&& !doencrypt
)
349 smb_apasslen
= strlen(smb_apasswd
);
351 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
352 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
353 char *p
= smb_buf(inbuf
);
355 if (passlen1
!= 24 && passlen2
!= 24)
359 /* Save the lanman2 password and the NT md4 password. */
360 smb_apasslen
= passlen1
;
361 memcpy(smb_apasswd
,p
,smb_apasslen
);
362 smb_ntpasslen
= passlen2
;
363 memcpy(smb_ntpasswd
,p
+passlen1
,smb_ntpasslen
);
365 /* both Win95 and WinNT stuff up the password lengths for
366 non-encrypting systems. Uggh.
368 if passlen1==24 its a win95 system, and its setting the
369 password length incorrectly. Luckily it still works with the
370 default code because Win95 will null terminate the password
373 if passlen1>0 and passlen2>0 then maybe its a NT box and its
374 setting passlen2 to some random value which really stuffs
375 things up. we need to fix that one. */
376 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
380 /* we use the first password that they gave */
381 smb_apasslen
= passlen1
;
382 StrnCpy(smb_apasswd
,p
,smb_apasslen
);
384 /* trim the password */
385 smb_apasslen
= strlen(smb_apasswd
);
387 /* wfwg sometimes uses a space instead of a null */
388 if (strequal(smb_apasswd
," ")) {
394 p
+= passlen1
+ passlen2
;
395 strcpy(user
,p
); p
= skip_string(p
,1);
396 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
397 p
,skip_string(p
,1),skip_string(p
,2)));
401 DEBUG(3,("sesssetupX:name=[%s]\n",user
));
403 /* If name ends in $ then I think it's asking about whether a */
404 /* computer with that name (minus the $) has access. For now */
405 /* say yes to everything ending in $. */
406 if (user
[strlen(user
) - 1] == '$') {
408 user
[strlen(user
) - 1] = '\0';
413 strcpy(user
,lp_guestaccount(-1));
417 strcpy(sesssetup_user
,user
);
419 reload_services(True
);
421 add_session_user(user
);
424 if (!(lp_security() == SEC_SERVER
&& server_validate(inbuf
)) &&
425 !check_hosts_equiv(user
))
428 if (strequal(user
,lp_guestaccount(-1)) && (*smb_apasswd
== 0))
431 /* now check if it's a valid username/password */
432 /* If an NT password was supplied try and validate with that
433 first. This is superior as the passwords are mixed case 128 length unicode */
434 if(smb_ntpasslen
&& !guest
)
436 if(!password_ok(user
,smb_ntpasswd
,smb_ntpasslen
,NULL
))
437 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
439 valid_nt_password
= True
;
441 if (!valid_nt_password
&& !guest
&& !password_ok(user
,smb_apasswd
,smb_apasslen
,NULL
))
443 if (!computer_id
&& lp_security() >= SEC_USER
) {
444 #if (GUEST_SESSSETUP == 0)
445 return(ERROR(ERRSRV
,ERRbadpw
));
447 #if (GUEST_SESSSETUP == 1)
448 if (Get_Pwnam(user
,True
))
449 return(ERROR(ERRSRV
,ERRbadpw
));
452 if (*smb_apasswd
|| !Get_Pwnam(user
,True
))
453 strcpy(user
,lp_guestaccount(-1));
454 DEBUG(3,("Registered username %s for guest access\n",user
));
459 if (!Get_Pwnam(user
,True
)) {
460 DEBUG(3,("No such user %s - using guest account\n",user
));
461 strcpy(user
,lp_guestaccount(-1));
465 if (!strequal(user
,lp_guestaccount(-1)) &&
466 lp_servicenumber(user
) < 0)
468 int homes
= lp_servicenumber(HOMES_NAME
);
469 char *home
= get_home_dir(user
);
470 if (homes
>= 0 && home
)
471 lp_add_home(user
,homes
,home
);
475 /* it's ok - setup a reply */
476 if (Protocol
< PROTOCOL_NT1
) {
477 set_message(outbuf
,3,0,True
);
480 set_message(outbuf
,3,3,True
);
482 strcpy(p
,"Unix"); p
= skip_string(p
,1);
483 strcpy(p
,"Samba "); strcat(p
,VERSION
); p
= skip_string(p
,1);
484 strcpy(p
,myworkgroup
); p
= skip_string(p
,1);
485 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
486 /* perhaps grab OS version here?? */
489 /* Set the correct uid in the outgoing and incoming packets
490 We will use this on future requests to determine which
491 user we should become.
494 struct passwd
*pw
= Get_Pwnam(user
,False
);
496 DEBUG(1,("Username %s is invalid on this system\n",user
));
497 return(ERROR(ERRSRV
,ERRbadpw
));
503 if (guest
&& !computer_id
)
504 SSVAL(outbuf
,smb_vwv2
,1);
506 /* register the name and uid as being validated, so further connections
507 to a uid can get through without a password, on the same VC */
508 sess_vuid
= register_vuid(uid
,gid
,user
,guest
);
510 SSVAL(outbuf
,smb_uid
,sess_vuid
);
511 SSVAL(inbuf
,smb_uid
,sess_vuid
);
514 max_send
= MIN(max_send
,smb_bufsize
);
516 DEBUG(1,(" Client requested max send size of %d\n", max_send
));
518 done_sesssetup
= True
;
520 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
524 /****************************************************************************
526 ****************************************************************************/
527 int reply_chkpth(char *inbuf
,char *outbuf
)
534 cnum
= SVAL(inbuf
,smb_tid
);
536 strcpy(name
,smb_buf(inbuf
) + 1);
537 unix_convert(name
,cnum
,0);
539 mode
= SVAL(inbuf
,smb_vwv0
);
541 if (check_name(name
,cnum
))
542 ok
= directory_exist(name
,NULL
);
545 return(ERROR(ERRDOS
,ERRbadpath
));
547 outsize
= set_message(outbuf
,0,0,True
);
549 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name
,cnum
,mode
));
555 /****************************************************************************
557 ****************************************************************************/
558 int reply_getatr(char *inbuf
,char *outbuf
)
569 cnum
= SVAL(inbuf
,smb_tid
);
571 strcpy(fname
,smb_buf(inbuf
) + 1);
572 unix_convert(fname
,cnum
,0);
574 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
575 under WfWg - weird! */
578 mode
= aHIDDEN
| aDIR
;
579 if (!CAN_WRITE(cnum
)) mode
|= aRONLY
;
585 if (check_name(fname
,cnum
))
587 if (sys_stat(fname
,&sbuf
) == 0)
589 mode
= dos_mode(cnum
,fname
,&sbuf
);
591 mtime
= sbuf
.st_mtime
;
597 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
601 return(UNIXERROR(ERRDOS
,ERRbadfile
));
603 outsize
= set_message(outbuf
,10,0,True
);
605 SSVAL(outbuf
,smb_vwv0
,mode
);
606 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
607 SIVAL(outbuf
,smb_vwv3
,size
);
609 if (Protocol
>= PROTOCOL_NT1
) {
610 char *p
= strrchr(fname
,'/');
611 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
613 if (!is_8_3(fname
, True
))
614 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
617 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname
,mode
,size
));
623 /****************************************************************************
625 ****************************************************************************/
626 int reply_setatr(char *inbuf
,char *outbuf
)
635 cnum
= SVAL(inbuf
,smb_tid
);
637 strcpy(fname
,smb_buf(inbuf
) + 1);
638 unix_convert(fname
,cnum
,0);
640 mode
= SVAL(inbuf
,smb_vwv0
);
641 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
643 if (directory_exist(fname
,NULL
))
645 if (check_name(fname
,cnum
))
646 ok
= (dos_chmod(cnum
,fname
,mode
,NULL
) == 0);
648 ok
= set_filetime(fname
,mtime
);
651 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
653 outsize
= set_message(outbuf
,0,0,True
);
655 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname
,mode
));
661 /****************************************************************************
663 ****************************************************************************/
664 int reply_dskattr(char *inbuf
,char *outbuf
)
668 int dfree
,dsize
,bsize
;
670 cnum
= SVAL(inbuf
,smb_tid
);
672 sys_disk_free(".",&bsize
,&dfree
,&dsize
);
674 outsize
= set_message(outbuf
,5,0,True
);
676 SSVAL(outbuf
,smb_vwv0
,dsize
);
677 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
678 SSVAL(outbuf
,smb_vwv2
,512);
679 SSVAL(outbuf
,smb_vwv3
,dfree
);
681 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum
,dfree
));
687 /****************************************************************************
689 Can be called from SMBsearch, SMBffirst or SMBfunique.
690 ****************************************************************************/
691 int reply_search(char *inbuf
,char *outbuf
)
702 BOOL finished
= False
;
711 BOOL check_descend
= False
;
712 BOOL expect_close
= False
;
713 BOOL can_open
= True
;
715 *mask
= *directory
= *fname
= 0;
717 /* If we were called as SMBffirst then we must expect close. */
718 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
721 cnum
= SVAL(inbuf
,smb_tid
);
723 outsize
= set_message(outbuf
,1,3,True
);
724 maxentries
= SVAL(inbuf
,smb_vwv0
);
725 dirtype
= SVAL(inbuf
,smb_vwv1
);
726 path
= smb_buf(inbuf
) + 1;
727 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
730 /* dirtype &= ~aDIR; */
732 DEBUG(5,("path=%s status_len=%d\n",path
,status_len
));
739 strcpy(directory
,smb_buf(inbuf
)+1);
740 strcpy(dir2
,smb_buf(inbuf
)+1);
741 unix_convert(directory
,cnum
,0);
744 if (!check_name(directory
,cnum
))
747 p
= strrchr(dir2
,'/');
749 {strcpy(mask
,dir2
);*dir2
= 0;}
751 {*p
= 0;strcpy(mask
,p
+1);}
753 p
= strrchr(directory
,'/');
759 if (strlen(directory
) == 0)
760 strcpy(directory
,"./");
762 CVAL(status
,0) = dirtype
;
766 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
767 memcpy(mask
,status
+1,11);
769 dirtype
= CVAL(status
,0) & 0x1F;
770 Connections
[cnum
].dirptr
= dptr_fetch(SNUM(cnum
), status
+12,&dptr_num
);
771 if (!Connections
[cnum
].dirptr
)
773 string_set(&Connections
[cnum
].dirpath
,dptr_path(dptr_num
));
778 /* turn strings of spaces into a . */
780 trim_string(mask
,NULL
," ");
781 if ((p
= strrchr(mask
,' ')))
786 trim_string(mask
,NULL
," ");
793 for (p
=mask
; *p
; p
++)
795 if (*p
!= '?' && *p
!= '*' && !isdoschar(*p
))
797 DEBUG(5,("Invalid char [%c] in search mask?\n",*p
));
803 if (!strchr(mask
,'.') && strlen(mask
)>8)
806 strcpy(tmp
,&mask
[8]);
812 DEBUG(5,("mask=%s directory=%s\n",mask
,directory
));
816 p
= smb_buf(outbuf
) + 3;
822 dptr_num
= dptr_create(cnum
,directory
,expect_close
,SVAL(inbuf
,smb_pid
));
824 return(ERROR(ERRDOS
,ERRnofids
));
827 DEBUG(4,("dptr_num is %d\n",dptr_num
));
831 if ((dirtype
&0x1F) == aVOLID
)
834 make_dir_struct(p
,"???????????",volume_label(SNUM(cnum
)),0,aVOLID
,0);
835 dptr_fill(SNUM(cnum
), p
+12,dptr_num
);
836 if (dptr_zero(p
+12) && (status_len
==0))
840 p
+= DIR_STRUCT_SIZE
;
844 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections
[cnum
].dirpath
,lp_dontdescend(SNUM(cnum
))));
845 if (in_list(Connections
[cnum
].dirpath
,
846 lp_dontdescend(SNUM(cnum
)),True
))
847 check_descend
= True
;
849 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
852 !get_dir_entry(cnum
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
856 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
857 dptr_fill(SNUM(cnum
), p
+12,dptr_num
);
860 p
+= DIR_STRUCT_SIZE
;
869 if (numentries
== 0 || !ok
)
871 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
872 SSVAL(outbuf
,smb_err
,ERRnofiles
);
875 /* If we were called as SMBffirst with smb_search_id == NULL
876 and no entries were found then return error and close dirptr
879 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
881 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
882 SSVAL(outbuf
,smb_err
,ERRnofiles
);
883 /* Also close the dptr - we know it's gone */
884 dptr_close(dptr_num
);
887 /* If we were called as SMBfunique, then we can close the dirptr now ! */
888 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
889 dptr_close(dptr_num
);
891 SSVAL(outbuf
,smb_vwv0
,numentries
);
892 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
893 CVAL(smb_buf(outbuf
),0) = 5;
894 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
896 if (Protocol
>= PROTOCOL_NT1
) {
897 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
898 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
901 outsize
+= DIR_STRUCT_SIZE
*numentries
;
902 smb_setlen(outbuf
,outsize
- 4);
904 if ((! *directory
) && dptr_path(dptr_num
))
905 sprintf(directory
,"(%s)",dptr_path(dptr_num
));
907 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
909 smb_fn_name(CVAL(inbuf
,smb_com
)),
910 mask
,directory
,cnum
,dirtype
,numentries
,maxentries
));
916 /****************************************************************************
917 reply to a fclose (stop directory search)
918 ****************************************************************************/
919 int reply_fclose(char *inbuf
,char *outbuf
)
928 cnum
= SVAL(inbuf
,smb_tid
);
930 outsize
= set_message(outbuf
,1,0,True
);
931 path
= smb_buf(inbuf
) + 1;
932 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
936 return(ERROR(ERRSRV
,ERRsrverror
));
938 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
940 if(dptr_fetch(SNUM(cnum
), status
+12,&dptr_num
)) {
941 /* Close the dptr - we know it's gone */
942 dptr_close(dptr_num
);
945 SSVAL(outbuf
,smb_vwv0
,0);
947 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum
));
953 /****************************************************************************
955 ****************************************************************************/
956 int reply_open(char *inbuf
,char *outbuf
)
970 cnum
= SVAL(inbuf
,smb_tid
);
972 share_mode
= SVAL(inbuf
,smb_vwv0
);
974 strcpy(fname
,smb_buf(inbuf
)+1);
975 unix_convert(fname
,cnum
,0);
977 fnum
= find_free_file();
979 return(ERROR(ERRSRV
,ERRnofids
));
981 if (!check_name(fname
,cnum
))
982 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
984 unixmode
= unix_mode(cnum
,aARCH
);
986 open_file_shared(fnum
,cnum
,fname
,share_mode
,3,unixmode
,&rmode
,NULL
);
988 if (!Files
[fnum
].open
)
989 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
991 if (fstat(Files
[fnum
].fd_ptr
->fd
,&sbuf
) != 0) {
993 return(ERROR(ERRDOS
,ERRnoaccess
));
997 fmode
= dos_mode(cnum
,fname
,&sbuf
);
998 mtime
= sbuf
.st_mtime
;
1001 DEBUG(3,("attempt to open a directory %s\n",fname
));
1003 return(ERROR(ERRDOS
,ERRnoaccess
));
1006 outsize
= set_message(outbuf
,7,0,True
);
1007 SSVAL(outbuf
,smb_vwv0
,fnum
);
1008 SSVAL(outbuf
,smb_vwv1
,fmode
);
1009 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1010 SIVAL(outbuf
,smb_vwv4
,size
);
1011 SSVAL(outbuf
,smb_vwv6
,rmode
);
1013 if (lp_fake_oplocks(SNUM(cnum
))) {
1014 CVAL(outbuf
,smb_flg
) |= (CVAL(inbuf
,smb_flg
) & (1<<5));
1021 /****************************************************************************
1022 reply to an open and X
1023 ****************************************************************************/
1024 int reply_open_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1027 int cnum
= SVAL(inbuf
,smb_tid
);
1030 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1031 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1032 BOOL oplock_request
= BITSETW(inbuf
+smb_vwv2
,1);
1034 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1035 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1036 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1038 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1040 int size
=0,fmode
=0,mtime
=0,rmode
=0;
1044 /* If it's an IPC, pass off the pipe handler. */
1046 return reply_open_pipe_and_X(inbuf
,outbuf
,length
,bufsize
);
1048 /* XXXX we need to handle passed times, sattr and flags */
1050 strcpy(fname
,smb_buf(inbuf
));
1051 unix_convert(fname
,cnum
,0);
1053 /* now add create and trunc bits */
1054 if (smb_ofun
& 0x10)
1055 openmode
|= O_CREAT
;
1056 if ((smb_ofun
& 0x3) == 2)
1057 openmode
|= O_TRUNC
;
1059 fnum
= find_free_file();
1061 return(ERROR(ERRSRV
,ERRnofids
));
1063 if (!check_name(fname
,cnum
))
1064 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1066 unixmode
= unix_mode(cnum
,smb_attr
| aARCH
);
1068 open_file_shared(fnum
,cnum
,fname
,smb_mode
,smb_ofun
,unixmode
,
1069 &rmode
,&smb_action
);
1071 if (!Files
[fnum
].open
)
1072 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1074 if (fstat(Files
[fnum
].fd_ptr
->fd
,&sbuf
) != 0) {
1076 return(ERROR(ERRDOS
,ERRnoaccess
));
1079 size
= sbuf
.st_size
;
1080 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1081 mtime
= sbuf
.st_mtime
;
1084 return(ERROR(ERRDOS
,ERRnoaccess
));
1087 if (oplock_request
&& lp_fake_oplocks(SNUM(cnum
))) {
1088 smb_action
|= (1<<15);
1091 set_message(outbuf
,15,0,True
);
1092 SSVAL(outbuf
,smb_vwv2
,fnum
);
1093 SSVAL(outbuf
,smb_vwv3
,fmode
);
1094 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1095 SIVAL(outbuf
,smb_vwv6
,size
);
1096 SSVAL(outbuf
,smb_vwv8
,rmode
);
1097 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1101 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1105 /****************************************************************************
1106 reply to a SMBulogoffX
1107 ****************************************************************************/
1108 int reply_ulogoffX(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1110 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1111 user_struct
*vuser
= get_valid_user_struct(vuid
);
1114 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1117 /* in user level security we are supposed to close any files
1118 open by this user */
1119 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1121 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
1122 if (Files
[i
].uid
== vuser
->uid
&& Files
[i
].open
) {
1127 invalidate_vuid(vuid
);
1129 set_message(outbuf
,2,0,True
);
1131 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid
));
1133 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1137 /****************************************************************************
1138 reply to a mknew or a create
1139 ****************************************************************************/
1140 int reply_mknew(char *inbuf
,char *outbuf
)
1150 com
= SVAL(inbuf
,smb_com
);
1151 cnum
= SVAL(inbuf
,smb_tid
);
1153 createmode
= SVAL(inbuf
,smb_vwv0
);
1154 strcpy(fname
,smb_buf(inbuf
)+1);
1155 unix_convert(fname
,cnum
,0);
1157 if (createmode
& aVOLID
)
1159 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1162 unixmode
= unix_mode(cnum
,createmode
);
1164 fnum
= find_free_file();
1166 return(ERROR(ERRSRV
,ERRnofids
));
1168 if (!check_name(fname
,cnum
))
1169 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1173 /* We should fail if file exists. */
1178 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1182 /* Open file in dos compatibility share mode. */
1183 open_file_shared(fnum
,cnum
,fname
,(DENY_FCB
<<4)|0xF, ofun
, unixmode
, NULL
, NULL
);
1185 if (!Files
[fnum
].open
)
1186 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1188 outsize
= set_message(outbuf
,1,0,True
);
1189 SSVAL(outbuf
,smb_vwv0
,fnum
);
1191 if (lp_fake_oplocks(SNUM(cnum
))) {
1192 CVAL(outbuf
,smb_flg
) |= (CVAL(inbuf
,smb_flg
) & (1<<5));
1195 DEBUG(2,("new file %s\n",fname
));
1196 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
));
1202 /****************************************************************************
1203 reply to a create temporary file
1204 ****************************************************************************/
1205 int reply_ctemp(char *inbuf
,char *outbuf
)
1215 cnum
= SVAL(inbuf
,smb_tid
);
1216 createmode
= SVAL(inbuf
,smb_vwv0
);
1217 sprintf(fname
,"%s/TMXXXXXX",smb_buf(inbuf
)+1);
1218 unix_convert(fname
,cnum
,0);
1220 unixmode
= unix_mode(cnum
,createmode
);
1222 fnum
= find_free_file();
1224 return(ERROR(ERRSRV
,ERRnofids
));
1226 if (!check_name(fname
,cnum
))
1227 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1229 strcpy(fname2
,(char *)mktemp(fname
));
1231 /* Open file in dos compatibility share mode. */
1232 /* We should fail if file exists. */
1233 open_file_shared(fnum
,cnum
,fname2
,(DENY_FCB
<<4)|0xF, 0x10, unixmode
, NULL
, NULL
);
1235 if (!Files
[fnum
].open
)
1236 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1238 outsize
= set_message(outbuf
,1,2 + strlen(fname2
),True
);
1239 SSVAL(outbuf
,smb_vwv0
,fnum
);
1240 CVAL(smb_buf(outbuf
),0) = 4;
1241 strcpy(smb_buf(outbuf
) + 1,fname2
);
1243 if (lp_fake_oplocks(SNUM(cnum
))) {
1244 CVAL(outbuf
,smb_flg
) |= (CVAL(inbuf
,smb_flg
) & (1<<5));
1247 DEBUG(2,("created temp file %s\n",fname2
));
1248 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
));
1254 /*******************************************************************
1255 check if a user is allowed to delete a file
1256 ********************************************************************/
1257 static BOOL
can_delete(char *fname
,int cnum
,int dirtype
)
1262 if (!CAN_WRITE(cnum
)) return(False
);
1264 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
1265 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1266 if (fmode
& aDIR
) return(False
);
1267 if (!lp_delete_readonly(SNUM(cnum
))) {
1268 if (fmode
& aRONLY
) return(False
);
1270 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1272 if (!check_file_sharing(cnum
,fname
)) return(False
);
1276 /****************************************************************************
1278 ****************************************************************************/
1279 int reply_unlink(char *inbuf
,char *outbuf
)
1289 int error
= ERRnoaccess
;
1293 *directory
= *mask
= 0;
1295 cnum
= SVAL(inbuf
,smb_tid
);
1296 dirtype
= SVAL(inbuf
,smb_vwv0
);
1298 strcpy(name
,smb_buf(inbuf
) + 1);
1300 DEBUG(3,("reply_unlink : %s\n",name
));
1302 unix_convert(name
,cnum
,0);
1304 p
= strrchr(name
,'/');
1306 strcpy(directory
,"./");
1310 strcpy(directory
,name
);
1314 if (is_mangled(mask
))
1315 check_mangled_stack(mask
);
1317 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
1320 strcat(directory
,"/");
1321 strcat(directory
,mask
);
1322 if (can_delete(directory
,cnum
,dirtype
) && !sys_unlink(directory
)) count
++;
1323 if (!count
) exists
= file_exist(directory
,NULL
);
1325 void *dirptr
= NULL
;
1328 if (check_name(directory
,cnum
))
1329 dirptr
= OpenDir(SNUM(cnum
), directory
, True
);
1331 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1332 the pattern matches against the long name, otherwise the short name
1333 We don't implement this yet XXXX
1340 if (strequal(mask
,"????????.???"))
1343 while ((dname
= ReadDirName(dirptr
)))
1346 strcpy(fname
,dname
);
1348 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
1350 error
= ERRnoaccess
;
1351 sprintf(fname
,"%s/%s",directory
,dname
);
1352 if (!can_delete(fname
,cnum
,dirtype
)) continue;
1353 if (!sys_unlink(fname
)) count
++;
1354 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname
));
1362 return(ERROR(ERRDOS
,error
));
1364 return(UNIXERROR(ERRDOS
,error
));
1367 outsize
= set_message(outbuf
,0,0,True
);
1373 /****************************************************************************
1374 reply to a readbraw (core+ protocol)
1375 ****************************************************************************/
1376 int reply_readbraw(char *inbuf
, char *outbuf
)
1378 int cnum
,maxcount
,mincount
,fnum
;
1381 char *header
= outbuf
;
1386 cnum
= SVAL(inbuf
,smb_tid
);
1387 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1389 startpos
= IVAL(inbuf
,smb_vwv1
);
1390 maxcount
= SVAL(inbuf
,smb_vwv3
);
1391 mincount
= SVAL(inbuf
,smb_vwv4
);
1393 /* ensure we don't overrun the packet size */
1394 maxcount
= MIN(65535,maxcount
);
1395 maxcount
= MAX(mincount
,maxcount
);
1397 if (!FNUM_OK(fnum
,cnum
) || !Files
[fnum
].can_read
)
1399 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum
));
1400 _smb_setlen(header
,0);
1401 transfer_file(0,Client
,0,header
,4,0);
1406 fd
= Files
[fnum
].fd_ptr
->fd
;
1407 fname
= Files
[fnum
].name
;
1411 if (!is_locked(fnum
,cnum
,maxcount
,startpos
))
1413 int size
= Files
[fnum
].size
;
1414 int sizeneeded
= startpos
+ maxcount
;
1416 if (size
< sizeneeded
) {
1418 if (fstat(Files
[fnum
].fd_ptr
->fd
,&st
) == 0)
1420 if (!Files
[fnum
].can_write
)
1421 Files
[fnum
].size
= size
;
1424 nread
= MIN(maxcount
,size
- startpos
);
1427 if (nread
< mincount
)
1430 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1433 maxcount
,mincount
,nread
));
1438 _smb_setlen(header
,nread
);
1440 if (!Files
[fnum
].can_write
)
1441 predict
= read_predict(fd
,startpos
,header
+4,NULL
,nread
);
1443 if ((nread
-predict
) > 0)
1444 seek_file(fnum
,startpos
+ predict
);
1446 ret
= transfer_file(fd
,Client
,nread
-predict
,header
,4+predict
,
1451 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1452 fname
,startpos
,nread
,ret
));
1455 ret
= read_file(fnum
,header
+4,startpos
,nread
);
1456 if (ret
< mincount
) ret
= 0;
1458 _smb_setlen(header
,ret
);
1459 transfer_file(0,Client
,0,header
,4+ret
,0);
1462 DEBUG(5,("readbraw finished\n"));
1467 /****************************************************************************
1468 reply to a lockread (core+ protocol)
1469 ****************************************************************************/
1470 int reply_lockread(char *inbuf
,char *outbuf
)
1476 uint32 startpos
, numtoread
;
1480 cnum
= SVAL(inbuf
,smb_tid
);
1481 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1483 CHECK_FNUM(fnum
,cnum
);
1487 numtoread
= SVAL(inbuf
,smb_vwv1
);
1488 startpos
= IVAL(inbuf
,smb_vwv2
);
1490 outsize
= set_message(outbuf
,5,3,True
);
1491 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1492 data
= smb_buf(outbuf
) + 3;
1494 if(!do_lock( fnum
, cnum
, numtoread
, startpos
, &eclass
, &ecode
))
1495 return (ERROR(eclass
,ecode
));
1497 nread
= read_file(fnum
,data
,startpos
,numtoread
);
1500 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1503 SSVAL(outbuf
,smb_vwv0
,nread
);
1504 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1505 SSVAL(smb_buf(outbuf
),1,nread
);
1507 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum
,cnum
,numtoread
,nread
));
1513 /****************************************************************************
1515 ****************************************************************************/
1516 int reply_read(char *inbuf
,char *outbuf
)
1518 int cnum
,numtoread
,fnum
;
1524 cnum
= SVAL(inbuf
,smb_tid
);
1525 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1527 CHECK_FNUM(fnum
,cnum
);
1531 numtoread
= SVAL(inbuf
,smb_vwv1
);
1532 startpos
= IVAL(inbuf
,smb_vwv2
);
1534 outsize
= set_message(outbuf
,5,3,True
);
1535 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1536 data
= smb_buf(outbuf
) + 3;
1538 if (is_locked(fnum
,cnum
,numtoread
,startpos
))
1539 return(ERROR(ERRDOS
,ERRlock
));
1542 nread
= read_file(fnum
,data
,startpos
,numtoread
);
1545 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1548 SSVAL(outbuf
,smb_vwv0
,nread
);
1549 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1550 CVAL(smb_buf(outbuf
),0) = 1;
1551 SSVAL(smb_buf(outbuf
),1,nread
);
1553 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum
,cnum
,numtoread
,nread
));
1559 /****************************************************************************
1560 reply to a read and X
1561 ****************************************************************************/
1562 int reply_read_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1564 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
1565 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
1566 int smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
1567 int smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
1573 cnum
= SVAL(inbuf
,smb_tid
);
1575 CHECK_FNUM(fnum
,cnum
);
1579 set_message(outbuf
,12,0,True
);
1580 data
= smb_buf(outbuf
);
1582 if (is_locked(fnum
,cnum
,smb_maxcnt
,smb_offs
))
1583 return(ERROR(ERRDOS
,ERRlock
));
1584 nread
= read_file(fnum
,data
,smb_offs
,smb_maxcnt
);
1588 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1590 SSVAL(outbuf
,smb_vwv5
,nread
);
1591 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
1592 SSVAL(smb_buf(outbuf
),-2,nread
);
1594 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1595 timestring(),fnum
,cnum
,
1596 smb_mincnt
,smb_maxcnt
,nread
));
1600 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1604 /****************************************************************************
1605 reply to a writebraw (core+ or LANMAN1.0 protocol)
1606 ****************************************************************************/
1607 int reply_writebraw(char *inbuf
,char *outbuf
)
1610 int total_written
=0;
1619 cnum
= SVAL(inbuf
,smb_tid
);
1620 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1622 CHECK_FNUM(fnum
,cnum
);
1626 tcount
= IVAL(inbuf
,smb_vwv1
);
1627 startpos
= IVAL(inbuf
,smb_vwv3
);
1628 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
1630 /* We have to deal with slightly different formats depending
1631 on whether we are using the core+ or lanman1.0 protocol */
1632 if(Protocol
<= PROTOCOL_COREPLUS
) {
1633 numtowrite
= SVAL(smb_buf(inbuf
),-2);
1634 data
= smb_buf(inbuf
);
1636 numtowrite
= SVAL(inbuf
,smb_vwv10
);
1637 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
1640 /* force the error type */
1641 CVAL(inbuf
,smb_com
) = SMBwritec
;
1642 CVAL(outbuf
,smb_com
) = SMBwritec
;
1644 if (is_locked(fnum
,cnum
,tcount
,startpos
))
1645 return(ERROR(ERRDOS
,ERRlock
));
1647 if (seek_file(fnum
,startpos
) != startpos
)
1648 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos
));
1651 nwritten
= write_file(fnum
,data
,numtowrite
);
1653 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1654 timestring(),fnum
,cnum
,startpos
,numtowrite
,nwritten
,write_through
));
1656 if (nwritten
< numtowrite
)
1657 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
1659 total_written
= nwritten
;
1661 /* Return a message to the redirector to tell it
1662 to send more bytes */
1663 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
1664 SSVALS(outbuf
,smb_vwv0
,-1);
1665 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
1666 send_smb(Client
,outbuf
);
1668 /* Now read the raw data into the buffer and write it */
1669 if (read_smb_length(Client
,inbuf
,SMB_SECONDARY_WAIT
) == -1) {
1670 exit_server("secondary writebraw failed");
1673 /* Even though this is not an smb message, smb_len
1674 returns the generic length of an smb message */
1675 numtowrite
= smb_len(inbuf
);
1677 if (tcount
> nwritten
+numtowrite
) {
1678 DEBUG(3,("Client overestimated the write %d %d %d\n",
1679 tcount
,nwritten
,numtowrite
));
1682 nwritten
= transfer_file(Client
,Files
[fnum
].fd_ptr
->fd
,numtowrite
,NULL
,0,
1684 total_written
+= nwritten
;
1686 /* Set up outbuf to return the correct return */
1687 outsize
= set_message(outbuf
,1,0,True
);
1688 CVAL(outbuf
,smb_com
) = SMBwritec
;
1689 SSVAL(outbuf
,smb_vwv0
,total_written
);
1691 if (nwritten
< numtowrite
) {
1692 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1693 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1696 if (lp_syncalways(SNUM(cnum
)) || write_through
)
1699 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1700 timestring(),fnum
,cnum
,startpos
,numtowrite
,total_written
));
1702 /* we won't return a status if write through is not selected - this
1703 follows what WfWg does */
1704 if (!write_through
&& total_written
==tcount
)
1711 /****************************************************************************
1712 reply to a writeunlock (core+)
1713 ****************************************************************************/
1714 int reply_writeunlock(char *inbuf
,char *outbuf
)
1720 uint32 numtowrite
,startpos
;
1724 cnum
= SVAL(inbuf
,smb_tid
);
1725 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1727 CHECK_FNUM(fnum
,cnum
);
1731 numtowrite
= SVAL(inbuf
,smb_vwv1
);
1732 startpos
= IVAL(inbuf
,smb_vwv2
);
1733 data
= smb_buf(inbuf
) + 3;
1735 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
1736 return(ERROR(ERRDOS
,ERRlock
));
1738 seek_file(fnum
,startpos
);
1740 /* The special X/Open SMB protocol handling of
1741 zero length writes is *NOT* done for
1746 nwritten
= write_file(fnum
,data
,numtowrite
);
1748 if (lp_syncalways(SNUM(cnum
)))
1751 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
1752 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1754 if(!do_unlock(fnum
, cnum
, numtowrite
, startpos
, &eclass
, &ecode
))
1755 return(ERROR(eclass
,ecode
));
1757 outsize
= set_message(outbuf
,1,0,True
);
1759 SSVAL(outbuf
,smb_vwv0
,nwritten
);
1761 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1762 timestring(),fnum
,cnum
,numtowrite
,nwritten
));
1768 /****************************************************************************
1770 ****************************************************************************/
1771 int reply_write(char *inbuf
,char *outbuf
,int dum1
,int dum2
)
1773 int cnum
,numtowrite
,fnum
;
1782 cnum
= SVAL(inbuf
,smb_tid
);
1783 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1785 CHECK_FNUM(fnum
,cnum
);
1789 numtowrite
= SVAL(inbuf
,smb_vwv1
);
1790 startpos
= IVAL(inbuf
,smb_vwv2
);
1791 data
= smb_buf(inbuf
) + 3;
1793 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
1794 return(ERROR(ERRDOS
,ERRlock
));
1796 seek_file(fnum
,startpos
);
1798 /* X/Open SMB protocol says that if smb_vwv1 is
1799 zero then the file size should be extended or
1800 truncated to the size given in smb_vwv[2-3] */
1802 nwritten
= set_filelen(Files
[fnum
].fd_ptr
->fd
, startpos
);
1804 nwritten
= write_file(fnum
,data
,numtowrite
);
1806 if (lp_syncalways(SNUM(cnum
)))
1809 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
1810 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1812 outsize
= set_message(outbuf
,1,0,True
);
1814 SSVAL(outbuf
,smb_vwv0
,nwritten
);
1816 if (nwritten
< numtowrite
) {
1817 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1818 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1821 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum
,cnum
,numtowrite
,nwritten
));
1827 /****************************************************************************
1828 reply to a write and X
1829 ****************************************************************************/
1830 int reply_write_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1832 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
1833 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
1834 int smb_dsize
= SVAL(inbuf
,smb_vwv10
);
1835 int smb_doff
= SVAL(inbuf
,smb_vwv11
);
1836 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
1841 cnum
= SVAL(inbuf
,smb_tid
);
1843 CHECK_FNUM(fnum
,cnum
);
1847 data
= smb_base(inbuf
) + smb_doff
;
1849 if (is_locked(fnum
,cnum
,smb_dsize
,smb_offs
))
1850 return(ERROR(ERRDOS
,ERRlock
));
1852 seek_file(fnum
,smb_offs
);
1854 /* X/Open SMB protocol says that, unlike SMBwrite
1855 if the length is zero then NO truncation is
1856 done, just a write of zero. To truncate a file,
1861 nwritten
= write_file(fnum
,data
,smb_dsize
);
1863 if(((nwritten
== 0) && (smb_dsize
!= 0))||(nwritten
< 0))
1864 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1866 set_message(outbuf
,6,0,True
);
1868 SSVAL(outbuf
,smb_vwv2
,nwritten
);
1870 if (nwritten
< smb_dsize
) {
1871 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1872 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1875 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum
,cnum
,smb_dsize
,nwritten
));
1879 if (lp_syncalways(SNUM(cnum
)) || write_through
)
1882 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1886 /****************************************************************************
1888 ****************************************************************************/
1889 int reply_lseek(char *inbuf
,char *outbuf
)
1897 cnum
= SVAL(inbuf
,smb_tid
);
1898 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1900 CHECK_FNUM(fnum
,cnum
);
1903 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
1904 startpos
= IVAL(inbuf
,smb_vwv2
);
1908 case 0: umode
= SEEK_SET
; break;
1909 case 1: umode
= SEEK_CUR
; break;
1910 case 2: umode
= SEEK_END
; break;
1912 umode
= SEEK_SET
; break;
1915 res
= lseek(Files
[fnum
].fd_ptr
->fd
,startpos
,umode
);
1916 Files
[fnum
].pos
= res
;
1918 outsize
= set_message(outbuf
,2,0,True
);
1919 SIVALS(outbuf
,smb_vwv0
,res
);
1921 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum
,cnum
,startpos
,mode
));
1927 /****************************************************************************
1929 ****************************************************************************/
1930 int reply_flush(char *inbuf
,char *outbuf
)
1933 int outsize
= set_message(outbuf
,0,0,True
);
1935 cnum
= SVAL(inbuf
,smb_tid
);
1936 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1938 if (fnum
!= 0xFFFF) {
1939 CHECK_FNUM(fnum
,cnum
);
1946 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
1953 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum
));
1958 /****************************************************************************
1960 ****************************************************************************/
1961 int reply_exit(char *inbuf
,char *outbuf
)
1963 int outsize
= set_message(outbuf
,0,0,True
);
1964 DEBUG(3,("%s exit\n",timestring()));
1970 /****************************************************************************
1972 ****************************************************************************/
1973 int reply_close(char *inbuf
,char *outbuf
)
1978 int32 eclass
= 0, err
= 0;
1980 outsize
= set_message(outbuf
,0,0,True
);
1982 cnum
= SVAL(inbuf
,smb_tid
);
1984 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1985 CHECK_FNUM(fnum
,cnum
);
1987 if(HAS_CACHED_ERROR(fnum
)) {
1988 eclass
= Files
[fnum
].wbmpx_ptr
->wr_errclass
;
1989 err
= Files
[fnum
].wbmpx_ptr
->wr_error
;
1992 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
1994 /* try and set the date */
1995 set_filetime(Files
[fnum
].name
,mtime
);
1999 /* We have a cached error */
2001 return(ERROR(eclass
,err
));
2003 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2004 timestring(),Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
,
2005 Connections
[cnum
].num_files_open
));
2011 /****************************************************************************
2012 reply to a writeclose (Core+ protocol)
2013 ****************************************************************************/
2014 int reply_writeclose(char *inbuf
,char *outbuf
)
2016 int cnum
,numtowrite
,fnum
;
2023 cnum
= SVAL(inbuf
,smb_tid
);
2024 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2026 CHECK_FNUM(fnum
,cnum
);
2030 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2031 startpos
= IVAL(inbuf
,smb_vwv2
);
2032 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2033 data
= smb_buf(inbuf
) + 1;
2035 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
2036 return(ERROR(ERRDOS
,ERRlock
));
2038 seek_file(fnum
,startpos
);
2040 nwritten
= write_file(fnum
,data
,numtowrite
);
2042 set_filetime(Files
[fnum
].name
,mtime
);
2046 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2047 timestring(),fnum
,cnum
,numtowrite
,nwritten
,
2048 Connections
[cnum
].num_files_open
));
2051 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2053 outsize
= set_message(outbuf
,1,0,True
);
2055 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2060 /****************************************************************************
2062 ****************************************************************************/
2063 int reply_lock(char *inbuf
,char *outbuf
)
2066 int outsize
= set_message(outbuf
,0,0,True
);
2067 uint32 count
,offset
;
2071 cnum
= SVAL(inbuf
,smb_tid
);
2072 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2074 CHECK_FNUM(fnum
,cnum
);
2077 count
= IVAL(inbuf
,smb_vwv1
);
2078 offset
= IVAL(inbuf
,smb_vwv3
);
2080 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
));
2082 if(!do_lock( fnum
, cnum
, count
, offset
, &eclass
, &ecode
))
2083 return (ERROR(eclass
,ecode
));
2089 /****************************************************************************
2091 ****************************************************************************/
2092 int reply_unlock(char *inbuf
,char *outbuf
)
2095 int outsize
= set_message(outbuf
,0,0,True
);
2096 uint32 count
,offset
;
2100 cnum
= SVAL(inbuf
,smb_tid
);
2101 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2103 CHECK_FNUM(fnum
,cnum
);
2106 count
= IVAL(inbuf
,smb_vwv1
);
2107 offset
= IVAL(inbuf
,smb_vwv3
);
2109 if(!do_unlock(fnum
, cnum
, count
, offset
, &eclass
, &ecode
))
2110 return (ERROR(eclass
,ecode
));
2112 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
));
2118 /****************************************************************************
2120 ****************************************************************************/
2121 int reply_tdis(char *inbuf
,char *outbuf
)
2124 int outsize
= set_message(outbuf
,0,0,True
);
2127 cnum
= SVAL(inbuf
,smb_tid
);
2128 vuid
= SVAL(inbuf
,smb_uid
);
2130 if (!OPEN_CNUM(cnum
)) {
2131 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum
));
2132 return(ERROR(ERRSRV
,ERRinvnid
));
2135 Connections
[cnum
].used
= False
;
2137 close_cnum(cnum
,vuid
);
2139 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum
));
2146 /****************************************************************************
2148 ****************************************************************************/
2149 int reply_echo(char *inbuf
,char *outbuf
)
2152 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2154 int data_len
= smb_buflen(inbuf
);
2155 int outsize
= set_message(outbuf
,1,data_len
,True
);
2157 cnum
= SVAL(inbuf
,smb_tid
);
2159 /* According to the latest CIFS spec we shouldn't
2160 care what the TID is.
2164 if (cnum
!= 0xFFFF && !OPEN_CNUM(cnum
))
2166 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum
));
2167 return(ERROR(ERRSRV
,ERRinvnid
));
2171 /* copy any incoming data back out */
2173 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2175 if (smb_reverb
> 100)
2177 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2181 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++)
2183 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2185 smb_setlen(outbuf
,outsize
- 4);
2187 send_smb(Client
,outbuf
);
2190 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb
,cnum
));
2196 /****************************************************************************
2197 reply to a printopen
2198 ****************************************************************************/
2199 int reply_printopen(char *inbuf
,char *outbuf
)
2207 *fname
= *fname2
= 0;
2209 cnum
= SVAL(inbuf
,smb_tid
);
2211 if (!CAN_PRINT(cnum
))
2212 return(ERROR(ERRDOS
,ERRnoaccess
));
2217 StrnCpy(s
,smb_buf(inbuf
)+1,sizeof(pstring
)-1);
2221 if (!(isalnum(*p
) || strchr("._-",*p
)))
2226 if (strlen(s
) > 10) s
[10] = 0;
2228 sprintf(fname
,"%s.XXXXXX",s
);
2231 fnum
= find_free_file();
2233 return(ERROR(ERRSRV
,ERRnofids
));
2235 strcpy(fname2
,(char *)mktemp(fname
));
2237 if (!check_name(fname2
,cnum
))
2238 return(ERROR(ERRDOS
,ERRnoaccess
));
2240 /* Open for exclusive use, write only. */
2241 open_file_shared(fnum
,cnum
,fname2
,(DENY_ALL
<<4)|1, 0x12, unix_mode(cnum
,0), NULL
, NULL
);
2243 if (!Files
[fnum
].open
)
2244 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2246 /* force it to be a print file */
2247 Files
[fnum
].print_file
= True
;
2249 outsize
= set_message(outbuf
,1,0,True
);
2250 SSVAL(outbuf
,smb_vwv0
,fnum
);
2252 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2
,Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
));
2258 /****************************************************************************
2259 reply to a printclose
2260 ****************************************************************************/
2261 int reply_printclose(char *inbuf
,char *outbuf
)
2264 int outsize
= set_message(outbuf
,0,0,True
);
2266 cnum
= SVAL(inbuf
,smb_tid
);
2267 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2269 CHECK_FNUM(fnum
,cnum
);
2272 if (!CAN_PRINT(cnum
))
2273 return(ERROR(ERRDOS
,ERRnoaccess
));
2277 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
));
2283 /****************************************************************************
2284 reply to a printqueue
2285 ****************************************************************************/
2286 int reply_printqueue(char *inbuf
,char *outbuf
)
2289 int outsize
= set_message(outbuf
,2,3,True
);
2290 int max_count
= SVAL(inbuf
,smb_vwv0
);
2291 int start_index
= SVAL(inbuf
,smb_vwv1
);
2294 cnum
= SVAL(inbuf
,smb_tid
);
2295 vuid
= SVAL(inbuf
,smb_uid
);
2297 /* allow checking the queue for anyone */
2299 if (!CAN_PRINT(cnum
))
2300 return(ERROR(ERRDOS
,ERRnoaccess
));
2303 SSVAL(outbuf
,smb_vwv0
,0);
2304 SSVAL(outbuf
,smb_vwv1
,0);
2305 CVAL(smb_buf(outbuf
),0) = 1;
2306 SSVAL(smb_buf(outbuf
),1,0);
2308 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2309 timestring(),cnum
,start_index
,max_count
));
2311 if (!OPEN_CNUM(cnum
) || !Connections
[cnum
].printer
)
2316 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2317 if (CAN_PRINT(i
) && Connections
[i
].printer
)
2321 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2325 if (!OPEN_CNUM(cnum
))
2326 return(ERROR(ERRSRV
,ERRinvnid
));
2328 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum
));
2331 if (!become_user(cnum
,vuid
))
2332 return(ERROR(ERRSRV
,ERRinvnid
));
2335 print_queue_struct
*queue
= NULL
;
2336 char *p
= smb_buf(outbuf
) + 3;
2337 int count
= get_printqueue(SNUM(cnum
),cnum
,&queue
,NULL
);
2338 int num_to_get
= ABS(max_count
);
2339 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
2345 num_to_get
= MIN(num_to_get
,count
-first
);
2348 for (i
=first
;i
<first
+num_to_get
;i
++)
2350 put_dos_date2(p
,0,queue
[i
].time
);
2351 CVAL(p
,4) = (queue
[i
].status
==LPQ_PRINTING
?2:3);
2352 SSVAL(p
,5,queue
[i
].job
);
2353 SIVAL(p
,7,queue
[i
].size
);
2355 StrnCpy(p
+12,queue
[i
].user
,16);
2361 outsize
= set_message(outbuf
,2,28*count
+3,False
);
2362 SSVAL(outbuf
,smb_vwv0
,count
);
2363 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
2364 CVAL(smb_buf(outbuf
),0) = 1;
2365 SSVAL(smb_buf(outbuf
),1,28*count
);
2368 if (queue
) free(queue
);
2370 DEBUG(3,("%d entries returned in queue\n",count
));
2377 /****************************************************************************
2378 reply to a printwrite
2379 ****************************************************************************/
2380 int reply_printwrite(char *inbuf
,char *outbuf
)
2382 int cnum
,numtowrite
,fnum
;
2383 int outsize
= set_message(outbuf
,0,0,True
);
2386 cnum
= SVAL(inbuf
,smb_tid
);
2388 if (!CAN_PRINT(cnum
))
2389 return(ERROR(ERRDOS
,ERRnoaccess
));
2391 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2393 CHECK_FNUM(fnum
,cnum
);
2397 numtowrite
= SVAL(smb_buf(inbuf
),1);
2398 data
= smb_buf(inbuf
) + 3;
2400 if (write_file(fnum
,data
,numtowrite
) != numtowrite
)
2401 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2403 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum
,cnum
,numtowrite
));
2409 /****************************************************************************
2411 ****************************************************************************/
2412 int reply_mkdir(char *inbuf
,char *outbuf
)
2416 int outsize
,ret
= -1;
2418 strcpy(directory
,smb_buf(inbuf
) + 1);
2419 cnum
= SVAL(inbuf
,smb_tid
);
2420 unix_convert(directory
,cnum
,0);
2422 if (check_name(directory
,cnum
))
2423 ret
= sys_mkdir(directory
,unix_mode(cnum
,aDIR
));
2426 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2428 outsize
= set_message(outbuf
,0,0,True
);
2430 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory
,cnum
,ret
));
2436 /****************************************************************************
2438 ****************************************************************************/
2439 int reply_rmdir(char *inbuf
,char *outbuf
)
2446 cnum
= SVAL(inbuf
,smb_tid
);
2447 strcpy(directory
,smb_buf(inbuf
) + 1);
2448 unix_convert(directory
,cnum
,0);
2450 if (check_name(directory
,cnum
))
2453 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
2454 ok
= (sys_rmdir(directory
) == 0);
2455 if(!ok
&& (errno
== ENOTEMPTY
) && lp_veto_files(SNUM(cnum
)))
2457 /* Check to see if the only thing in this directory are
2458 vetoed files/directories. If so then delete them and
2459 retry. If we fail to delete any of them (and we *don't*
2460 do a recursive delete) then fail the rmdir. */
2461 BOOL all_veto_files
= True
;
2463 void *dirptr
= OpenDir(SNUM(cnum
), directory
, False
);
2467 int dirpos
= TellDir(dirptr
);
2468 while ((dname
= ReadDirName(dirptr
)))
2470 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2472 if(!is_vetoed_name(SNUM(cnum
), dname
))
2474 all_veto_files
= False
;
2480 SeekDir(dirptr
,dirpos
);
2481 while ((dname
= ReadDirName(dirptr
)))
2486 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2489 /* Construct the full name. */
2490 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
2495 strcpy(fullname
, directory
);
2496 strcat(fullname
, "/");
2497 strcat(fullname
, dname
);
2499 if(sys_lstat(fullname
, &st
) != 0)
2501 if(st
.st_mode
& S_IFDIR
)
2503 if(sys_rmdir(fullname
) != 0)
2506 else if(sys_unlink(fullname
) != 0)
2510 /* Retry the rmdir */
2511 ok
= (sys_rmdir(directory
) == 0);
2521 DEBUG(3,("couldn't remove directory %s : %s\n",
2522 directory
,strerror(errno
)));
2526 return(UNIXERROR(ERRDOS
,ERRbadpath
));
2528 outsize
= set_message(outbuf
,0,0,True
);
2530 DEBUG(3,("%s rmdir %s\n",timestring(),directory
));
2536 /*******************************************************************
2537 resolve wildcards in a filename rename
2538 ********************************************************************/
2539 static BOOL
resolve_wildcards(char *name1
,char *name2
)
2541 fstring root1
,root2
;
2545 name1
= strrchr(name1
,'/');
2546 name2
= strrchr(name2
,'/');
2548 if (!name1
|| !name2
) return(False
);
2550 strcpy(root1
,name1
);
2551 strcpy(root2
,name2
);
2552 p
= strrchr(root1
,'.');
2559 p
= strrchr(root2
,'.');
2591 strcpy(name2
,root2
);
2600 /*******************************************************************
2601 check if a user is allowed to rename a file
2602 ********************************************************************/
2603 static BOOL
can_rename(char *fname
,int cnum
)
2607 if (!CAN_WRITE(cnum
)) return(False
);
2609 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
2610 if (!check_file_sharing(cnum
,fname
)) return(False
);
2615 /****************************************************************************
2617 ****************************************************************************/
2618 int reply_mv(char *inbuf
,char *outbuf
)
2624 pstring mask
,newname
;
2625 pstring newname_last_component
;
2628 int error
= ERRnoaccess
;
2632 *directory
= *mask
= 0;
2634 cnum
= SVAL(inbuf
,smb_tid
);
2636 strcpy(name
,smb_buf(inbuf
) + 1);
2637 strcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
2639 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
2641 unix_convert(name
,cnum
,0);
2642 unix_convert(newname
,cnum
,newname_last_component
);
2645 * Split the old name into directory and last component
2646 * strings. Note that unix_convert may have stripped off a
2647 * leading ./ from both name and newname if the rename is
2648 * at the root of the share. We need to make sure either both
2649 * name and newname contain a / character or neither of them do
2650 * as this is checked in resolve_wildcards().
2653 p
= strrchr(name
,'/');
2655 strcpy(directory
,".");
2659 strcpy(directory
,name
);
2661 *p
= '/'; /* Replace needed for exceptional test below. */
2664 if (is_mangled(mask
))
2665 check_mangled_stack(mask
);
2667 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
2670 BOOL is_short_name
= is_8_3(name
, True
);
2672 /* Add a terminating '/' to the directory name. */
2673 strcat(directory
,"/");
2674 strcat(directory
,mask
);
2676 /* Ensure newname contains a '/' also */
2677 if(strrchr(newname
,'/') == 0) {
2680 strcpy(tmpstr
, "./");
2681 strcat(tmpstr
, newname
);
2682 strcpy(newname
, tmpstr
);
2685 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",
2686 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
2687 newname
, newname_last_component
, is_short_name
));
2690 * Check for special case with case preserving and not
2691 * case sensitive, if directory and newname are identical,
2692 * and the old last component differs from the original
2693 * last component only by case, then we should allow
2694 * the rename (user is trying to change the case of the
2697 if((case_sensitive
== False
) && ( ((case_preserve
== True
) && (is_short_name
== False
)) ||
2698 ((short_case_preserve
== True
) && (is_short_name
== True
))) &&
2699 strcsequal(directory
, newname
)) {
2700 pstring newname_modified_last_component
;
2703 * Get the last component of the modified name.
2704 * Note that we guarantee that newname contains a '/'
2707 p
= strrchr(newname
,'/');
2708 strcpy(newname_modified_last_component
,p
+1);
2710 if(strcsequal(newname_modified_last_component
,
2711 newname_last_component
) == False
) {
2713 * Replace the modified last component with
2716 strcpy(p
+1, newname_last_component
);
2720 if (resolve_wildcards(directory
,newname
) &&
2721 can_rename(directory
,cnum
) &&
2722 !file_exist(newname
,NULL
) &&
2723 !sys_rename(directory
,newname
)) count
++;
2725 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count
!= 0) ? "succeeded" : "failed",
2726 directory
,newname
));
2728 if (!count
) exists
= file_exist(directory
,NULL
);
2729 if (!count
&& exists
&& file_exist(newname
,NULL
)) {
2734 void *dirptr
= NULL
;
2738 if (check_name(directory
,cnum
))
2739 dirptr
= OpenDir(SNUM(cnum
), directory
, True
);
2745 if (strequal(mask
,"????????.???"))
2748 while ((dname
= ReadDirName(dirptr
)))
2751 strcpy(fname
,dname
);
2753 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
2755 error
= ERRnoaccess
;
2756 sprintf(fname
,"%s/%s",directory
,dname
);
2757 if (!can_rename(fname
,cnum
)) continue;
2758 strcpy(destname
,newname
);
2760 if (!resolve_wildcards(fname
,destname
)) continue;
2762 if (file_exist(destname
,NULL
)) {
2766 if (!sys_rename(fname
,destname
)) count
++;
2767 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname
,destname
));
2775 return(ERROR(ERRDOS
,error
));
2777 return(UNIXERROR(ERRDOS
,error
));
2780 outsize
= set_message(outbuf
,0,0,True
);
2785 /*******************************************************************
2786 copy a file as part of a reply_copy
2787 ******************************************************************/
2788 static BOOL
copy_file(char *src
,char *dest1
,int cnum
,int ofun
,
2789 int count
,BOOL target_is_directory
)
2798 if (target_is_directory
) {
2799 char *p
= strrchr(src
,'/');
2808 if (!file_exist(src
,&st
)) return(False
);
2810 fnum1
= find_free_file();
2811 if (fnum1
<0) return(False
);
2812 open_file_shared(fnum1
,cnum
,src
,(DENY_NONE
<<4),
2813 1,0,&Access
,&action
);
2815 if (!Files
[fnum1
].open
) return(False
);
2817 if (!target_is_directory
&& count
)
2820 fnum2
= find_free_file();
2825 open_file_shared(fnum2
,cnum
,dest
,(DENY_NONE
<<4)|1,
2826 ofun
,st
.st_mode
,&Access
,&action
);
2828 if (!Files
[fnum2
].open
) {
2833 if ((ofun
&3) == 1) {
2834 lseek(Files
[fnum2
].fd_ptr
->fd
,0,SEEK_END
);
2838 ret
= transfer_file(Files
[fnum1
].fd_ptr
->fd
,Files
[fnum2
].fd_ptr
->fd
,st
.st_size
,NULL
,0,0);
2843 return(ret
== st
.st_size
);
2848 /****************************************************************************
2849 reply to a file copy.
2850 ****************************************************************************/
2851 int reply_copy(char *inbuf
,char *outbuf
)
2857 pstring mask
,newname
;
2860 int error
= ERRnoaccess
;
2863 int tid2
= SVAL(inbuf
,smb_vwv0
);
2864 int ofun
= SVAL(inbuf
,smb_vwv1
);
2865 int flags
= SVAL(inbuf
,smb_vwv2
);
2866 BOOL target_is_directory
=False
;
2868 *directory
= *mask
= 0;
2870 cnum
= SVAL(inbuf
,smb_tid
);
2872 strcpy(name
,smb_buf(inbuf
));
2873 strcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
2875 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
2878 /* can't currently handle inter share copies XXXX */
2879 DEBUG(3,("Rejecting inter-share copy\n"));
2880 return(ERROR(ERRSRV
,ERRinvdevice
));
2883 unix_convert(name
,cnum
,0);
2884 unix_convert(newname
,cnum
,0);
2886 target_is_directory
= directory_exist(newname
,NULL
);
2888 if ((flags
&1) && target_is_directory
) {
2889 return(ERROR(ERRDOS
,ERRbadfile
));
2892 if ((flags
&2) && !target_is_directory
) {
2893 return(ERROR(ERRDOS
,ERRbadpath
));
2896 if ((flags
&(1<<5)) && directory_exist(name
,NULL
)) {
2897 /* wants a tree copy! XXXX */
2898 DEBUG(3,("Rejecting tree copy\n"));
2899 return(ERROR(ERRSRV
,ERRerror
));
2902 p
= strrchr(name
,'/');
2904 strcpy(directory
,"./");
2908 strcpy(directory
,name
);
2912 if (is_mangled(mask
))
2913 check_mangled_stack(mask
);
2915 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
2918 strcat(directory
,"/");
2919 strcat(directory
,mask
);
2920 if (resolve_wildcards(directory
,newname
) &&
2921 copy_file(directory
,newname
,cnum
,ofun
,
2922 count
,target_is_directory
)) count
++;
2923 if (!count
) exists
= file_exist(directory
,NULL
);
2925 void *dirptr
= NULL
;
2929 if (check_name(directory
,cnum
))
2930 dirptr
= OpenDir(SNUM(cnum
), directory
, True
);
2936 if (strequal(mask
,"????????.???"))
2939 while ((dname
= ReadDirName(dirptr
)))
2942 strcpy(fname
,dname
);
2944 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
2946 error
= ERRnoaccess
;
2947 sprintf(fname
,"%s/%s",directory
,dname
);
2948 strcpy(destname
,newname
);
2949 if (resolve_wildcards(fname
,destname
) &&
2950 copy_file(directory
,newname
,cnum
,ofun
,
2951 count
,target_is_directory
)) count
++;
2952 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
2960 return(ERROR(ERRDOS
,error
));
2962 return(UNIXERROR(ERRDOS
,error
));
2965 outsize
= set_message(outbuf
,1,0,True
);
2966 SSVAL(outbuf
,smb_vwv0
,count
);
2973 /****************************************************************************
2975 ****************************************************************************/
2976 int reply_setdir(char *inbuf
,char *outbuf
)
2983 cnum
= SVAL(inbuf
,smb_tid
);
2985 snum
= Connections
[cnum
].service
;
2986 if (!CAN_SETDIR(snum
))
2987 return(ERROR(ERRDOS
,ERRnoaccess
));
2989 strcpy(newdir
,smb_buf(inbuf
) + 1);
2992 if (strlen(newdir
) == 0)
2996 ok
= directory_exist(newdir
,NULL
);
2998 string_set(&Connections
[cnum
].connectpath
,newdir
);
3002 return(ERROR(ERRDOS
,ERRbadpath
));
3004 outsize
= set_message(outbuf
,0,0,True
);
3005 CVAL(outbuf
,smb_reh
) = CVAL(inbuf
,smb_reh
);
3007 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir
,cnum
));
3013 /****************************************************************************
3014 reply to a lockingX request
3015 ****************************************************************************/
3016 int reply_lockingX(char *inbuf
,char *outbuf
,int length
,int bufsize
)
3018 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
3019 uint16 locktype
= SVAL(inbuf
,smb_vwv3
);
3020 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
3021 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
3022 uint32 count
, offset
;
3027 uint32 ecode
=0, dummy2
;
3028 int eclass
=0, dummy1
;
3030 cnum
= SVAL(inbuf
,smb_tid
);
3032 CHECK_FNUM(fnum
,cnum
);
3035 data
= smb_buf(inbuf
);
3036 /* Data now points at the beginning of the list
3037 of smb_unlkrng structs */
3038 for(i
= 0; i
< (int)num_ulocks
; i
++) {
3039 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3040 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3041 if(!do_unlock(fnum
,cnum
,count
,offset
,&eclass
, &ecode
))
3042 return ERROR(eclass
,ecode
);
3045 /* Now do any requested locks */
3046 data
+= 10*num_ulocks
;
3047 /* Data now points at the beginning of the list
3048 of smb_lkrng structs */
3049 for(i
= 0; i
< (int)num_locks
; i
++) {
3050 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3051 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3052 if(!do_lock(fnum
,cnum
,count
,offset
, &eclass
, &ecode
))
3056 /* If any of the above locks failed, then we must unlock
3057 all of the previous locks (X/Open spec). */
3058 if(i
!= num_locks
&& num_locks
!= 0) {
3059 for(; i
>= 0; i
--) {
3060 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3061 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3062 do_unlock(fnum
,cnum
,count
,offset
,&dummy1
,&dummy2
);
3064 return ERROR(eclass
,ecode
);
3067 set_message(outbuf
,2,0,True
);
3069 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3070 timestring(),fnum
,cnum
,locktype
,num_locks
,num_ulocks
));
3074 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
3078 /****************************************************************************
3079 reply to a SMBreadbmpx (read block multiplex) request
3080 ****************************************************************************/
3081 int reply_readbmpx(char *inbuf
,char *outbuf
,int length
,int bufsize
)
3088 int outsize
, mincount
, maxcount
;
3093 /* this function doesn't seem to work - disable by default */
3095 return(ERROR(ERRSRV
,ERRuseSTD
));
3097 outsize
= set_message(outbuf
,8,0,True
);
3099 cnum
= SVAL(inbuf
,smb_tid
);
3100 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3102 CHECK_FNUM(fnum
,cnum
);
3106 startpos
= IVAL(inbuf
,smb_vwv1
);
3107 maxcount
= SVAL(inbuf
,smb_vwv3
);
3108 mincount
= SVAL(inbuf
,smb_vwv4
);
3110 data
= smb_buf(outbuf
);
3111 pad
= ((int)data
)%4;
3112 if (pad
) pad
= 4 - pad
;
3115 max_per_packet
= bufsize
-(outsize
+pad
);
3119 if (is_locked(fnum
,cnum
,maxcount
,startpos
))
3120 return(ERROR(ERRDOS
,ERRlock
));
3124 int N
= MIN(max_per_packet
,tcount
-total_read
);
3126 nread
= read_file(fnum
,data
,startpos
,N
);
3128 if (nread
<= 0) nread
= 0;
3131 tcount
= total_read
+ nread
;
3133 set_message(outbuf
,8,nread
,False
);
3134 SIVAL(outbuf
,smb_vwv0
,startpos
);
3135 SSVAL(outbuf
,smb_vwv2
,tcount
);
3136 SSVAL(outbuf
,smb_vwv6
,nread
);
3137 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
3139 send_smb(Client
,outbuf
);
3141 total_read
+= nread
;
3144 while (total_read
< tcount
);
3150 /****************************************************************************
3151 reply to a SMBwritebmpx (write block multiplex primary) request
3152 ****************************************************************************/
3153 int reply_writebmpx(char *inbuf
,char *outbuf
)
3155 int cnum
,numtowrite
,fnum
;
3159 int tcount
, write_through
, smb_doff
;
3162 cnum
= SVAL(inbuf
,smb_tid
);
3163 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3165 CHECK_FNUM(fnum
,cnum
);
3169 tcount
= SVAL(inbuf
,smb_vwv1
);
3170 startpos
= IVAL(inbuf
,smb_vwv3
);
3171 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
3172 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3173 smb_doff
= SVAL(inbuf
,smb_vwv11
);
3175 data
= smb_base(inbuf
) + smb_doff
;
3177 /* If this fails we need to send an SMBwriteC response,
3178 not an SMBwritebmpx - set this up now so we don't forget */
3179 CVAL(outbuf
,smb_com
) = SMBwritec
;
3181 if (is_locked(fnum
,cnum
,tcount
,startpos
))
3182 return(ERROR(ERRDOS
,ERRlock
));
3184 seek_file(fnum
,startpos
);
3185 nwritten
= write_file(fnum
,data
,numtowrite
);
3187 if(lp_syncalways(SNUM(cnum
)) || write_through
)
3190 if(nwritten
< numtowrite
)
3191 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3193 /* If the maximum to be written to this file
3194 is greater than what we just wrote then set
3195 up a secondary struct to be attached to this
3196 fd, we will use this to cache error messages etc. */
3197 if(tcount
> nwritten
)
3199 write_bmpx_struct
*wbms
;
3200 if(Files
[fnum
].wbmpx_ptr
!= NULL
)
3201 wbms
= Files
[fnum
].wbmpx_ptr
; /* Use an existing struct */
3203 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
3206 DEBUG(0,("Out of memory in reply_readmpx\n"));
3207 return(ERROR(ERRSRV
,ERRnoresource
));
3209 wbms
->wr_mode
= write_through
;
3210 wbms
->wr_discard
= False
; /* No errors yet */
3211 wbms
->wr_total_written
= nwritten
;
3212 wbms
->wr_errclass
= 0;
3214 Files
[fnum
].wbmpx_ptr
= wbms
;
3217 /* We are returning successfully, set the message type back to
3219 CVAL(outbuf
,smb_com
) = SMBwriteBmpx
;
3221 outsize
= set_message(outbuf
,1,0,True
);
3223 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
3225 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3226 timestring(),fnum
,cnum
,numtowrite
,nwritten
));
3228 if (write_through
&& tcount
==nwritten
) {
3229 /* we need to send both a primary and a secondary response */
3230 smb_setlen(outbuf
,outsize
- 4);
3231 send_smb(Client
,outbuf
);
3233 /* now the secondary */
3234 outsize
= set_message(outbuf
,1,0,True
);
3235 CVAL(outbuf
,smb_com
) = SMBwritec
;
3236 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3243 /****************************************************************************
3244 reply to a SMBwritebs (write block multiplex secondary) request
3245 ****************************************************************************/
3246 int reply_writebs(char *inbuf
,char *outbuf
)
3248 int cnum
,numtowrite
,fnum
;
3252 int tcount
, write_through
, smb_doff
;
3254 write_bmpx_struct
*wbms
;
3255 BOOL send_response
= False
;
3257 cnum
= SVAL(inbuf
,smb_tid
);
3258 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3259 CHECK_FNUM(fnum
,cnum
);
3262 tcount
= SVAL(inbuf
,smb_vwv1
);
3263 startpos
= IVAL(inbuf
,smb_vwv2
);
3264 numtowrite
= SVAL(inbuf
,smb_vwv6
);
3265 smb_doff
= SVAL(inbuf
,smb_vwv7
);
3267 data
= smb_base(inbuf
) + smb_doff
;
3269 /* We need to send an SMBwriteC response, not an SMBwritebs */
3270 CVAL(outbuf
,smb_com
) = SMBwritec
;
3272 /* This fd should have an auxiliary struct attached,
3273 check that it does */
3274 wbms
= Files
[fnum
].wbmpx_ptr
;
3275 if(!wbms
) return(-1);
3277 /* If write through is set we can return errors, else we must
3279 write_through
= wbms
->wr_mode
;
3281 /* Check for an earlier error */
3282 if(wbms
->wr_discard
)
3283 return -1; /* Just discard the packet */
3285 seek_file(fnum
,startpos
);
3286 nwritten
= write_file(fnum
,data
,numtowrite
);
3288 if(lp_syncalways(SNUM(cnum
)) || write_through
)
3291 if (nwritten
< numtowrite
)
3294 /* We are returning an error - we can delete the aux struct */
3295 if (wbms
) free((char *)wbms
);
3296 Files
[fnum
].wbmpx_ptr
= NULL
;
3297 return(ERROR(ERRHRD
,ERRdiskfull
));
3299 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
3302 /* Increment the total written, if this matches tcount
3303 we can discard the auxiliary struct (hurrah !) and return a writeC */
3304 wbms
->wr_total_written
+= nwritten
;
3305 if(wbms
->wr_total_written
>= tcount
)
3307 if (write_through
) {
3308 outsize
= set_message(outbuf
,1,0,True
);
3309 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
3310 send_response
= True
;
3314 Files
[fnum
].wbmpx_ptr
= NULL
;
3324 /****************************************************************************
3325 reply to a SMBsetattrE
3326 ****************************************************************************/
3327 int reply_setattrE(char *inbuf
,char *outbuf
)
3330 struct utimbuf unix_times
;
3333 outsize
= set_message(outbuf
,0,0,True
);
3335 cnum
= SVAL(inbuf
,smb_tid
);
3336 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3338 CHECK_FNUM(fnum
,cnum
);
3341 /* Convert the DOS times into unix times. Ignore create
3342 time as UNIX can't set this.
3344 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
3345 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
3347 /* Set the date on this file */
3348 if(sys_utime(Files
[fnum
].name
, &unix_times
))
3349 return(ERROR(ERRDOS
,ERRnoaccess
));
3351 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum
,cnum
));
3357 /****************************************************************************
3358 reply to a SMBgetattrE
3359 ****************************************************************************/
3360 int reply_getattrE(char *inbuf
,char *outbuf
)
3367 outsize
= set_message(outbuf
,11,0,True
);
3369 cnum
= SVAL(inbuf
,smb_tid
);
3370 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3372 CHECK_FNUM(fnum
,cnum
);
3375 /* Do an fstat on this file */
3376 if(fstat(Files
[fnum
].fd_ptr
->fd
, &sbuf
))
3377 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3379 mode
= dos_mode(cnum
,Files
[fnum
].name
,&sbuf
);
3381 /* Convert the times into dos times. Set create
3382 date to be last modify date as UNIX doesn't save
3384 put_dos_date2(outbuf
,smb_vwv0
,sbuf
.st_mtime
);
3385 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
3386 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
3389 SIVAL(outbuf
,smb_vwv6
,0);
3390 SIVAL(outbuf
,smb_vwv8
,0);
3394 SIVAL(outbuf
,smb_vwv6
,sbuf
.st_size
);
3395 SIVAL(outbuf
,smb_vwv8
,ROUNDUP(sbuf
.st_size
,1024));
3397 SSVAL(outbuf
,smb_vwv10
, mode
);
3399 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum
,cnum
));