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(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(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(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(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(directory
);
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
))
2452 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
2453 ok
= (sys_rmdir(directory
) == 0);
2455 DEBUG(3,("couldn't remove directory %s : %s\n",
2456 directory
,strerror(errno
)));
2460 return(UNIXERROR(ERRDOS
,ERRbadpath
));
2462 outsize
= set_message(outbuf
,0,0,True
);
2464 DEBUG(3,("%s rmdir %s\n",timestring(),directory
));
2470 /*******************************************************************
2471 resolve wildcards in a filename rename
2472 ********************************************************************/
2473 static BOOL
resolve_wildcards(char *name1
,char *name2
)
2475 fstring root1
,root2
;
2479 name1
= strrchr(name1
,'/');
2480 name2
= strrchr(name2
,'/');
2482 if (!name1
|| !name2
) return(False
);
2484 strcpy(root1
,name1
);
2485 strcpy(root2
,name2
);
2486 p
= strrchr(root1
,'.');
2493 p
= strrchr(root2
,'.');
2525 strcpy(name2
,root2
);
2534 /*******************************************************************
2535 check if a user is allowed to rename a file
2536 ********************************************************************/
2537 static BOOL
can_rename(char *fname
,int cnum
)
2541 if (!CAN_WRITE(cnum
)) return(False
);
2543 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
2544 if (!check_file_sharing(cnum
,fname
)) return(False
);
2549 /****************************************************************************
2551 ****************************************************************************/
2552 int reply_mv(char *inbuf
,char *outbuf
)
2558 pstring mask
,newname
;
2559 pstring newname_last_component
;
2562 int error
= ERRnoaccess
;
2566 *directory
= *mask
= 0;
2568 cnum
= SVAL(inbuf
,smb_tid
);
2570 strcpy(name
,smb_buf(inbuf
) + 1);
2571 strcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
2573 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
2575 unix_convert(name
,cnum
,0);
2576 unix_convert(newname
,cnum
,newname_last_component
);
2579 * Split the old name into directory and last component
2580 * strings. Note that unix_convert may have stripped off a
2581 * leading ./ from both name and newname if the rename is
2582 * at the root of the share. We need to make sure either both
2583 * name and newname contain a / character or neither of them do
2584 * as this is checked in resolve_wildcards().
2587 p
= strrchr(name
,'/');
2589 strcpy(directory
,".");
2593 strcpy(directory
,name
);
2595 *p
= '/'; /* Replace needed for exceptional test below. */
2598 if (is_mangled(mask
))
2599 check_mangled_stack(mask
);
2601 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
2604 BOOL is_short_name
= is_8_3(name
, True
);
2606 /* Add a terminating '/' to the directory name. */
2607 strcat(directory
,"/");
2608 strcat(directory
,mask
);
2610 /* Ensure newname contains a '/' also */
2611 if(strrchr(newname
,'/') == 0) {
2614 strcpy(tmpstr
, "./");
2615 strcat(tmpstr
, newname
);
2616 strcpy(newname
, tmpstr
);
2619 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",
2620 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
2621 newname
, newname_last_component
, is_short_name
));
2624 * Check for special case with case preserving and not
2625 * case sensitive, if directory and newname are identical,
2626 * and the old last component differs from the original
2627 * last component only by case, then we should allow
2628 * the rename (user is trying to change the case of the
2631 if((case_sensitive
== False
) && ( ((case_preserve
== True
) && (is_short_name
== False
)) ||
2632 ((short_case_preserve
== True
) && (is_short_name
== True
))) &&
2633 strcsequal(directory
, newname
)) {
2634 pstring newname_modified_last_component
;
2637 * Get the last component of the modified name.
2638 * Note that we guarantee that newname contains a '/'
2641 p
= strrchr(newname
,'/');
2642 strcpy(newname_modified_last_component
,p
+1);
2644 if(strcsequal(newname_modified_last_component
,
2645 newname_last_component
) == False
) {
2647 * Replace the modified last component with
2650 strcpy(p
+1, newname_last_component
);
2654 if (resolve_wildcards(directory
,newname
) &&
2655 can_rename(directory
,cnum
) &&
2656 !file_exist(newname
,NULL
) &&
2657 !sys_rename(directory
,newname
)) count
++;
2659 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count
!= 0) ? "succeeded" : "failed",
2660 directory
,newname
));
2662 if (!count
) exists
= file_exist(directory
,NULL
);
2663 if (!count
&& exists
&& file_exist(newname
,NULL
)) {
2668 void *dirptr
= NULL
;
2672 if (check_name(directory
,cnum
))
2673 dirptr
= OpenDir(directory
);
2679 if (strequal(mask
,"????????.???"))
2682 while ((dname
= ReadDirName(dirptr
)))
2685 strcpy(fname
,dname
);
2687 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
2689 error
= ERRnoaccess
;
2690 sprintf(fname
,"%s/%s",directory
,dname
);
2691 if (!can_rename(fname
,cnum
)) continue;
2692 strcpy(destname
,newname
);
2694 if (!resolve_wildcards(fname
,destname
)) continue;
2696 if (file_exist(destname
,NULL
)) {
2700 if (!sys_rename(fname
,destname
)) count
++;
2701 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname
,destname
));
2709 return(ERROR(ERRDOS
,error
));
2711 return(UNIXERROR(ERRDOS
,error
));
2714 outsize
= set_message(outbuf
,0,0,True
);
2719 /*******************************************************************
2720 copy a file as part of a reply_copy
2721 ******************************************************************/
2722 static BOOL
copy_file(char *src
,char *dest1
,int cnum
,int ofun
,
2723 int count
,BOOL target_is_directory
)
2732 if (target_is_directory
) {
2733 char *p
= strrchr(src
,'/');
2742 if (!file_exist(src
,&st
)) return(False
);
2744 fnum1
= find_free_file();
2745 if (fnum1
<0) return(False
);
2746 open_file_shared(fnum1
,cnum
,src
,(DENY_NONE
<<4),
2747 1,0,&Access
,&action
);
2749 if (!Files
[fnum1
].open
) return(False
);
2751 if (!target_is_directory
&& count
)
2754 fnum2
= find_free_file();
2759 open_file_shared(fnum2
,cnum
,dest
,(DENY_NONE
<<4)|1,
2760 ofun
,st
.st_mode
,&Access
,&action
);
2762 if (!Files
[fnum2
].open
) {
2767 if ((ofun
&3) == 1) {
2768 lseek(Files
[fnum2
].fd_ptr
->fd
,0,SEEK_END
);
2772 ret
= transfer_file(Files
[fnum1
].fd_ptr
->fd
,Files
[fnum2
].fd_ptr
->fd
,st
.st_size
,NULL
,0,0);
2777 return(ret
== st
.st_size
);
2782 /****************************************************************************
2783 reply to a file copy.
2784 ****************************************************************************/
2785 int reply_copy(char *inbuf
,char *outbuf
)
2791 pstring mask
,newname
;
2794 int error
= ERRnoaccess
;
2797 int tid2
= SVAL(inbuf
,smb_vwv0
);
2798 int ofun
= SVAL(inbuf
,smb_vwv1
);
2799 int flags
= SVAL(inbuf
,smb_vwv2
);
2800 BOOL target_is_directory
=False
;
2802 *directory
= *mask
= 0;
2804 cnum
= SVAL(inbuf
,smb_tid
);
2806 strcpy(name
,smb_buf(inbuf
));
2807 strcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
2809 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
2812 /* can't currently handle inter share copies XXXX */
2813 DEBUG(3,("Rejecting inter-share copy\n"));
2814 return(ERROR(ERRSRV
,ERRinvdevice
));
2817 unix_convert(name
,cnum
,0);
2818 unix_convert(newname
,cnum
,0);
2820 target_is_directory
= directory_exist(newname
,NULL
);
2822 if ((flags
&1) && target_is_directory
) {
2823 return(ERROR(ERRDOS
,ERRbadfile
));
2826 if ((flags
&2) && !target_is_directory
) {
2827 return(ERROR(ERRDOS
,ERRbadpath
));
2830 if ((flags
&(1<<5)) && directory_exist(name
,NULL
)) {
2831 /* wants a tree copy! XXXX */
2832 DEBUG(3,("Rejecting tree copy\n"));
2833 return(ERROR(ERRSRV
,ERRerror
));
2836 p
= strrchr(name
,'/');
2838 strcpy(directory
,"./");
2842 strcpy(directory
,name
);
2846 if (is_mangled(mask
))
2847 check_mangled_stack(mask
);
2849 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
2852 strcat(directory
,"/");
2853 strcat(directory
,mask
);
2854 if (resolve_wildcards(directory
,newname
) &&
2855 copy_file(directory
,newname
,cnum
,ofun
,
2856 count
,target_is_directory
)) count
++;
2857 if (!count
) exists
= file_exist(directory
,NULL
);
2859 void *dirptr
= NULL
;
2863 if (check_name(directory
,cnum
))
2864 dirptr
= OpenDir(directory
);
2870 if (strequal(mask
,"????????.???"))
2873 while ((dname
= ReadDirName(dirptr
)))
2876 strcpy(fname
,dname
);
2878 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
2880 error
= ERRnoaccess
;
2881 sprintf(fname
,"%s/%s",directory
,dname
);
2882 strcpy(destname
,newname
);
2883 if (resolve_wildcards(fname
,destname
) &&
2884 copy_file(directory
,newname
,cnum
,ofun
,
2885 count
,target_is_directory
)) count
++;
2886 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
2894 return(ERROR(ERRDOS
,error
));
2896 return(UNIXERROR(ERRDOS
,error
));
2899 outsize
= set_message(outbuf
,1,0,True
);
2900 SSVAL(outbuf
,smb_vwv0
,count
);
2907 /****************************************************************************
2909 ****************************************************************************/
2910 int reply_setdir(char *inbuf
,char *outbuf
)
2917 cnum
= SVAL(inbuf
,smb_tid
);
2919 snum
= Connections
[cnum
].service
;
2920 if (!CAN_SETDIR(snum
))
2921 return(ERROR(ERRDOS
,ERRnoaccess
));
2923 strcpy(newdir
,smb_buf(inbuf
) + 1);
2926 if (strlen(newdir
) == 0)
2930 ok
= directory_exist(newdir
,NULL
);
2932 string_set(&Connections
[cnum
].connectpath
,newdir
);
2936 return(ERROR(ERRDOS
,ERRbadpath
));
2938 outsize
= set_message(outbuf
,0,0,True
);
2939 CVAL(outbuf
,smb_reh
) = CVAL(inbuf
,smb_reh
);
2941 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir
,cnum
));
2947 /****************************************************************************
2948 reply to a lockingX request
2949 ****************************************************************************/
2950 int reply_lockingX(char *inbuf
,char *outbuf
,int length
,int bufsize
)
2952 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
2953 uint16 locktype
= SVAL(inbuf
,smb_vwv3
);
2954 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
2955 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
2956 uint32 count
, offset
;
2961 uint32 ecode
=0, dummy2
;
2962 int eclass
=0, dummy1
;
2964 cnum
= SVAL(inbuf
,smb_tid
);
2966 CHECK_FNUM(fnum
,cnum
);
2969 data
= smb_buf(inbuf
);
2970 /* Data now points at the beginning of the list
2971 of smb_unlkrng structs */
2972 for(i
= 0; i
< (int)num_ulocks
; i
++) {
2973 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
2974 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
2975 if(!do_unlock(fnum
,cnum
,count
,offset
,&eclass
, &ecode
))
2976 return ERROR(eclass
,ecode
);
2979 /* Now do any requested locks */
2980 data
+= 10*num_ulocks
;
2981 /* Data now points at the beginning of the list
2982 of smb_lkrng structs */
2983 for(i
= 0; i
< (int)num_locks
; i
++) {
2984 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
2985 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
2986 if(!do_lock(fnum
,cnum
,count
,offset
, &eclass
, &ecode
))
2990 /* If any of the above locks failed, then we must unlock
2991 all of the previous locks (X/Open spec). */
2992 if(i
!= num_locks
&& num_locks
!= 0) {
2993 for(; i
>= 0; i
--) {
2994 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
2995 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
2996 do_unlock(fnum
,cnum
,count
,offset
,&dummy1
,&dummy2
);
2998 return ERROR(eclass
,ecode
);
3001 set_message(outbuf
,2,0,True
);
3003 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3004 timestring(),fnum
,cnum
,locktype
,num_locks
,num_ulocks
));
3008 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
3012 /****************************************************************************
3013 reply to a SMBreadbmpx (read block multiplex) request
3014 ****************************************************************************/
3015 int reply_readbmpx(char *inbuf
,char *outbuf
,int length
,int bufsize
)
3022 int outsize
, mincount
, maxcount
;
3027 /* this function doesn't seem to work - disable by default */
3029 return(ERROR(ERRSRV
,ERRuseSTD
));
3031 outsize
= set_message(outbuf
,8,0,True
);
3033 cnum
= SVAL(inbuf
,smb_tid
);
3034 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3036 CHECK_FNUM(fnum
,cnum
);
3040 startpos
= IVAL(inbuf
,smb_vwv1
);
3041 maxcount
= SVAL(inbuf
,smb_vwv3
);
3042 mincount
= SVAL(inbuf
,smb_vwv4
);
3044 data
= smb_buf(outbuf
);
3045 pad
= ((int)data
)%4;
3046 if (pad
) pad
= 4 - pad
;
3049 max_per_packet
= bufsize
-(outsize
+pad
);
3053 if (is_locked(fnum
,cnum
,maxcount
,startpos
))
3054 return(ERROR(ERRDOS
,ERRlock
));
3058 int N
= MIN(max_per_packet
,tcount
-total_read
);
3060 nread
= read_file(fnum
,data
,startpos
,N
);
3062 if (nread
<= 0) nread
= 0;
3065 tcount
= total_read
+ nread
;
3067 set_message(outbuf
,8,nread
,False
);
3068 SIVAL(outbuf
,smb_vwv0
,startpos
);
3069 SSVAL(outbuf
,smb_vwv2
,tcount
);
3070 SSVAL(outbuf
,smb_vwv6
,nread
);
3071 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
3073 send_smb(Client
,outbuf
);
3075 total_read
+= nread
;
3078 while (total_read
< tcount
);
3084 /****************************************************************************
3085 reply to a SMBwritebmpx (write block multiplex primary) request
3086 ****************************************************************************/
3087 int reply_writebmpx(char *inbuf
,char *outbuf
)
3089 int cnum
,numtowrite
,fnum
;
3093 int tcount
, write_through
, smb_doff
;
3096 cnum
= SVAL(inbuf
,smb_tid
);
3097 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3099 CHECK_FNUM(fnum
,cnum
);
3103 tcount
= SVAL(inbuf
,smb_vwv1
);
3104 startpos
= IVAL(inbuf
,smb_vwv3
);
3105 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
3106 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3107 smb_doff
= SVAL(inbuf
,smb_vwv11
);
3109 data
= smb_base(inbuf
) + smb_doff
;
3111 /* If this fails we need to send an SMBwriteC response,
3112 not an SMBwritebmpx - set this up now so we don't forget */
3113 CVAL(outbuf
,smb_com
) = SMBwritec
;
3115 if (is_locked(fnum
,cnum
,tcount
,startpos
))
3116 return(ERROR(ERRDOS
,ERRlock
));
3118 seek_file(fnum
,startpos
);
3119 nwritten
= write_file(fnum
,data
,numtowrite
);
3121 if(lp_syncalways(SNUM(cnum
)) || write_through
)
3124 if(nwritten
< numtowrite
)
3125 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3127 /* If the maximum to be written to this file
3128 is greater than what we just wrote then set
3129 up a secondary struct to be attached to this
3130 fd, we will use this to cache error messages etc. */
3131 if(tcount
> nwritten
)
3133 write_bmpx_struct
*wbms
;
3134 if(Files
[fnum
].wbmpx_ptr
!= NULL
)
3135 wbms
= Files
[fnum
].wbmpx_ptr
; /* Use an existing struct */
3137 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
3140 DEBUG(0,("Out of memory in reply_readmpx\n"));
3141 return(ERROR(ERRSRV
,ERRnoresource
));
3143 wbms
->wr_mode
= write_through
;
3144 wbms
->wr_discard
= False
; /* No errors yet */
3145 wbms
->wr_total_written
= nwritten
;
3146 wbms
->wr_errclass
= 0;
3148 Files
[fnum
].wbmpx_ptr
= wbms
;
3151 /* We are returning successfully, set the message type back to
3153 CVAL(outbuf
,smb_com
) = SMBwriteBmpx
;
3155 outsize
= set_message(outbuf
,1,0,True
);
3157 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
3159 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3160 timestring(),fnum
,cnum
,numtowrite
,nwritten
));
3162 if (write_through
&& tcount
==nwritten
) {
3163 /* we need to send both a primary and a secondary response */
3164 smb_setlen(outbuf
,outsize
- 4);
3165 send_smb(Client
,outbuf
);
3167 /* now the secondary */
3168 outsize
= set_message(outbuf
,1,0,True
);
3169 CVAL(outbuf
,smb_com
) = SMBwritec
;
3170 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3177 /****************************************************************************
3178 reply to a SMBwritebs (write block multiplex secondary) request
3179 ****************************************************************************/
3180 int reply_writebs(char *inbuf
,char *outbuf
)
3182 int cnum
,numtowrite
,fnum
;
3186 int tcount
, write_through
, smb_doff
;
3188 write_bmpx_struct
*wbms
;
3189 BOOL send_response
= False
;
3191 cnum
= SVAL(inbuf
,smb_tid
);
3192 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3193 CHECK_FNUM(fnum
,cnum
);
3196 tcount
= SVAL(inbuf
,smb_vwv1
);
3197 startpos
= IVAL(inbuf
,smb_vwv2
);
3198 numtowrite
= SVAL(inbuf
,smb_vwv6
);
3199 smb_doff
= SVAL(inbuf
,smb_vwv7
);
3201 data
= smb_base(inbuf
) + smb_doff
;
3203 /* We need to send an SMBwriteC response, not an SMBwritebs */
3204 CVAL(outbuf
,smb_com
) = SMBwritec
;
3206 /* This fd should have an auxiliary struct attached,
3207 check that it does */
3208 wbms
= Files
[fnum
].wbmpx_ptr
;
3209 if(!wbms
) return(-1);
3211 /* If write through is set we can return errors, else we must
3213 write_through
= wbms
->wr_mode
;
3215 /* Check for an earlier error */
3216 if(wbms
->wr_discard
)
3217 return -1; /* Just discard the packet */
3219 seek_file(fnum
,startpos
);
3220 nwritten
= write_file(fnum
,data
,numtowrite
);
3222 if(lp_syncalways(SNUM(cnum
)) || write_through
)
3225 if (nwritten
< numtowrite
)
3228 /* We are returning an error - we can delete the aux struct */
3229 if (wbms
) free((char *)wbms
);
3230 Files
[fnum
].wbmpx_ptr
= NULL
;
3231 return(ERROR(ERRHRD
,ERRdiskfull
));
3233 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
3236 /* Increment the total written, if this matches tcount
3237 we can discard the auxiliary struct (hurrah !) and return a writeC */
3238 wbms
->wr_total_written
+= nwritten
;
3239 if(wbms
->wr_total_written
>= tcount
)
3241 if (write_through
) {
3242 outsize
= set_message(outbuf
,1,0,True
);
3243 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
3244 send_response
= True
;
3248 Files
[fnum
].wbmpx_ptr
= NULL
;
3258 /****************************************************************************
3259 reply to a SMBsetattrE
3260 ****************************************************************************/
3261 int reply_setattrE(char *inbuf
,char *outbuf
)
3264 struct utimbuf unix_times
;
3267 outsize
= set_message(outbuf
,0,0,True
);
3269 cnum
= SVAL(inbuf
,smb_tid
);
3270 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3272 CHECK_FNUM(fnum
,cnum
);
3275 /* Convert the DOS times into unix times. Ignore create
3276 time as UNIX can't set this.
3278 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
3279 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
3281 /* Set the date on this file */
3282 if(sys_utime(Files
[fnum
].name
, &unix_times
))
3283 return(ERROR(ERRDOS
,ERRnoaccess
));
3285 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum
,cnum
));
3291 /****************************************************************************
3292 reply to a SMBgetattrE
3293 ****************************************************************************/
3294 int reply_getattrE(char *inbuf
,char *outbuf
)
3301 outsize
= set_message(outbuf
,11,0,True
);
3303 cnum
= SVAL(inbuf
,smb_tid
);
3304 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3306 CHECK_FNUM(fnum
,cnum
);
3309 /* Do an fstat on this file */
3310 if(fstat(Files
[fnum
].fd_ptr
->fd
, &sbuf
))
3311 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3313 mode
= dos_mode(cnum
,Files
[fnum
].name
,&sbuf
);
3315 /* Convert the times into dos times. Set create
3316 date to be last modify date as UNIX doesn't save
3318 put_dos_date2(outbuf
,smb_vwv0
,sbuf
.st_mtime
);
3319 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
3320 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
3323 SIVAL(outbuf
,smb_vwv6
,0);
3324 SIVAL(outbuf
,smb_vwv8
,0);
3328 SIVAL(outbuf
,smb_vwv6
,sbuf
.st_size
);
3329 SIVAL(outbuf
,smb_vwv8
,ROUNDUP(sbuf
.st_size
,1024));
3331 SSVAL(outbuf
,smb_vwv10
, mode
);
3333 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum
,cnum
));