2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1995
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
;
34 extern int chain_fnum
;
35 extern char magic_char
;
36 extern connection_struct Connections
[];
37 extern files_struct Files
[];
38 extern BOOL case_sensitive
;
39 extern BOOL case_preserve
;
40 extern pstring sesssetup_user
;
43 /* this macro should always be used to extract an fnum (smb_fid) from
44 a packet to ensure chaining works correctly */
45 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
48 /****************************************************************************
49 reply to an special message
50 ****************************************************************************/
51 int reply_special(char *inbuf
,char *outbuf
)
54 int msg_type
= CVAL(inbuf
,0);
55 int msg_flags
= CVAL(inbuf
,1);
57 extern fstring remote_machine
;
58 extern fstring local_machine
;
67 case 0x81: /* session request */
68 CVAL(outbuf
,0) = 0x82;
70 if (name_len(inbuf
+4) > 50)
72 DEBUG(0,("Invalid name length in session request\n"));
75 name_extract(inbuf
,4,name1
);
76 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
77 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1
,name2
));
79 strcpy(remote_machine
,name2
);
80 trim_string(remote_machine
," "," ");
81 p
= strchr(remote_machine
,' ');
82 strlower(remote_machine
);
85 strcpy(local_machine
,name1
);
86 trim_string(local_machine
," "," ");
87 p
= strchr(local_machine
,' ');
88 strlower(local_machine
);
91 add_session_user(remote_machine
);
93 reload_services(True
);
97 case 0x85: /* session keepalive */
102 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type
,msg_flags
));
108 /*******************************************************************
109 work out what error to give to a failed connection
110 ********************************************************************/
111 static int connection_error(char *inbuf
,char *outbuf
,int connection_num
)
113 switch (connection_num
)
116 return(ERROR(ERRSRV
,ERRnoresource
));
118 return(ERROR(ERRSRV
,ERRbaduid
));
120 return(ERROR(ERRSRV
,ERRinvdevice
));
122 return(ERROR(ERRSRV
,ERRinvnetname
));
124 return(ERROR(ERRSRV
,ERRaccess
));
126 return(ERROR(ERRDOS
,ERRnoipc
));
128 return(ERROR(ERRSRV
,ERRinvnetname
));
130 return(ERROR(ERRSRV
,ERRbadpw
));
135 /****************************************************************************
136 parse a share descriptor string
137 ****************************************************************************/
138 static void parse_connect(char *p
,char *service
,char *user
,
139 char *password
,int *pwlen
,char *dev
)
143 DEBUG(4,("parsing connect string %s\n",p
));
145 p2
= strrchr(p
,'\\');
149 strcpy(service
,p2
+1);
154 *pwlen
= strlen(password
);
161 p
= strchr(service
,'%');
172 /****************************************************************************
174 ****************************************************************************/
175 int reply_tcon(char *inbuf
,char *outbuf
)
183 uint16 vuid
= SVAL(inbuf
,smb_uid
);
186 *service
= *user
= *password
= *dev
= 0;
188 parse_connect(smb_buf(inbuf
)+1,service
,user
,password
,&pwlen
,dev
);
190 connection_num
= make_connection(service
,user
,password
,pwlen
,dev
,vuid
);
192 if (connection_num
< 0)
193 return(connection_error(inbuf
,outbuf
,connection_num
));
195 outsize
= set_message(outbuf
,2,0,True
);
196 SSVAL(outbuf
,smb_vwv0
,maxxmit
);
197 SSVAL(outbuf
,smb_vwv1
,connection_num
);
198 SSVAL(outbuf
,smb_tid
,connection_num
);
200 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service
,user
,connection_num
));
206 /****************************************************************************
207 reply to a tcon and X
208 ****************************************************************************/
209 int reply_tcon_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
216 uint16 vuid
= SVAL(inbuf
,smb_uid
);
217 int passlen
= SVAL(inbuf
,smb_vwv3
);
218 BOOL doencrypt
= SMBENCRYPT();
220 *service
= *user
= *password
= *devicename
= 0;
222 /* we might have to close an old one */
223 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) != 0)
224 close_cnum(SVAL(inbuf
,smb_tid
),vuid
);
229 memcpy(password
,smb_buf(inbuf
),passlen
);
231 path
= smb_buf(inbuf
) + passlen
;
233 if (!doencrypt
|| passlen
!= 24) {
234 if (strequal(password
," "))
236 passlen
= strlen(password
);
239 DEBUG(4,("parsing net-path %s, passlen=%d\n",path
,passlen
));
240 strcpy(service
,path
+2);
241 p
= strchr(service
,'\\');
243 return(ERROR(ERRSRV
,ERRinvnetname
));
246 p
= strchr(service
,'%');
252 StrnCpy(devicename
,path
+ strlen(path
) + 1,6);
253 DEBUG(4,("Got device type %s\n",devicename
));
256 connection_num
= make_connection(service
,user
,password
,passlen
,devicename
,vuid
);
258 if (connection_num
< 0)
259 return(connection_error(inbuf
,outbuf
,connection_num
));
261 set_message(outbuf
,2,strlen(devicename
)+1,True
);
263 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service
,user
,connection_num
));
265 /* set the incoming and outgoing tid to the just created one */
266 SSVAL(inbuf
,smb_tid
,connection_num
);
267 SSVAL(outbuf
,smb_tid
,connection_num
);
269 strcpy(smb_buf(outbuf
),devicename
);
271 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
275 /****************************************************************************
276 reply to an unknown type
277 ****************************************************************************/
278 int reply_unknown(char *inbuf
,char *outbuf
)
282 cnum
= SVAL(inbuf
,smb_tid
);
283 type
= CVAL(inbuf
,smb_com
);
285 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
290 return(ERROR(ERRSRV
,ERRunknownsmb
));
294 /****************************************************************************
296 ****************************************************************************/
297 int reply_ioctl(char *inbuf
,char *outbuf
)
299 DEBUG(3,("ignoring ioctl\n"));
301 /* we just say it succeeds and hope its all OK.
302 some day it would be nice to interpret them individually */
303 return set_message(outbuf
,1,0,True
);
305 return(ERROR(ERRSRV
,ERRnosupport
));
310 /****************************************************************************
311 reply to a session setup command
312 ****************************************************************************/
313 int reply_sesssetup_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
322 int smb_apasslen
= 0;
324 int smb_ntpasslen
= 0;
325 pstring smb_ntpasswd
;
326 BOOL valid_nt_password
= False
;
329 BOOL computer_id
=False
;
330 static BOOL done_sesssetup
= False
;
331 BOOL doencrypt
= SMBENCRYPT();
335 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
336 smb_mpxmax
= SVAL(inbuf
,smb_vwv3
);
337 smb_vc_num
= SVAL(inbuf
,smb_vwv4
);
338 smb_sesskey
= IVAL(inbuf
,smb_vwv5
);
340 if (Protocol
< PROTOCOL_NT1
) {
341 smb_apasslen
= SVAL(inbuf
,smb_vwv7
);
342 memcpy(smb_apasswd
,smb_buf(inbuf
),smb_apasslen
);
343 StrnCpy(user
,smb_buf(inbuf
)+smb_apasslen
,sizeof(user
)-1);
345 if (lp_security() != SEC_SERVER
&& !doencrypt
)
346 smb_apasslen
= strlen(smb_apasswd
);
348 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
349 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
350 char *p
= smb_buf(inbuf
);
352 if (passlen1
!= 24 && passlen2
!= 24)
356 /* Save the lanman2 password and the NT md4 password. */
357 smb_apasslen
= passlen1
;
358 memcpy(smb_apasswd
,p
,smb_apasslen
);
359 smb_ntpasslen
= passlen2
;
360 memcpy(smb_ntpasswd
,p
+passlen1
,smb_ntpasslen
);
362 /* both Win95 and WinNT stuff up the password lengths for
363 non-encrypting systems. Uggh.
365 if passlen1==24 its a win95 system, and its setting the
366 password length incorrectly. Luckily it still works with the
367 default code because Win95 will null terminate the password
370 if passlen1>0 and passlen2>0 then maybe its a NT box and its
371 setting passlen2 to some random value which really stuffs
372 things up. we need to fix that one. */
373 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
377 /* we use the first password that they gave */
378 smb_apasslen
= passlen1
;
379 StrnCpy(smb_apasswd
,p
,smb_apasslen
);
381 /* trim the password */
382 smb_apasslen
= strlen(smb_apasswd
);
384 /* wfwg sometimes uses a space instead of a null */
385 if (strequal(smb_apasswd
," ")) {
391 p
+= passlen1
+ passlen2
;
392 strcpy(user
,p
); p
= skip_string(p
,1);
393 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
394 p
,skip_string(p
,1),skip_string(p
,2)));
398 DEBUG(3,("sesssetupX:name=[%s]\n",user
));
400 /* If name ends in $ then I think it's asking about whether a */
401 /* computer with that name (minus the $) has access. For now */
402 /* say yes to everything ending in $. */
403 if (user
[strlen(user
) - 1] == '$') {
405 user
[strlen(user
) - 1] = '\0';
410 strcpy(user
,lp_guestaccount(-1));
414 strcpy(sesssetup_user
,user
);
416 reload_services(True
);
418 add_session_user(user
);
421 if (!(lp_security() == SEC_SERVER
&& server_validate(inbuf
)) &&
422 !check_hosts_equiv(user
))
425 if (strequal(user
,lp_guestaccount(-1)) && (*smb_apasswd
== 0))
428 /* now check if it's a valid username/password */
429 /* If an NT password was supplied try and validate with that
430 first. This is superior as the passwords are mixed case 128 length unicode */
431 if(smb_ntpasslen
&& !guest
)
433 if(!password_ok(user
,smb_ntpasswd
,smb_ntpasslen
,NULL
))
434 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
436 valid_nt_password
= True
;
438 if (!valid_nt_password
&& !guest
&& !password_ok(user
,smb_apasswd
,smb_apasslen
,NULL
))
440 if (!computer_id
&& lp_security() >= SEC_USER
) {
441 #if (GUEST_SESSSETUP == 0)
442 return(ERROR(ERRSRV
,ERRbadpw
));
444 #if (GUEST_SESSSETUP == 1)
445 if (Get_Pwnam(user
,True
))
446 return(ERROR(ERRSRV
,ERRbadpw
));
449 if (*smb_apasswd
|| !Get_Pwnam(user
,True
))
450 strcpy(user
,lp_guestaccount(-1));
451 DEBUG(3,("Registered username %s for guest access\n",user
));
456 if (!Get_Pwnam(user
,True
)) {
457 DEBUG(3,("No such user %s - using guest account\n",user
));
458 strcpy(user
,lp_guestaccount(-1));
462 if (!strequal(user
,lp_guestaccount(-1)) &&
463 lp_servicenumber(user
) < 0)
465 int homes
= lp_servicenumber(HOMES_NAME
);
466 char *home
= get_home_dir(user
);
467 if (homes
>= 0 && home
)
468 lp_add_home(user
,homes
,home
);
472 /* it's ok - setup a reply */
473 if (Protocol
< PROTOCOL_NT1
) {
474 set_message(outbuf
,3,0,True
);
477 set_message(outbuf
,3,3,True
);
479 strcpy(p
,"Unix"); p
= skip_string(p
,1);
480 strcpy(p
,"Samba "); strcat(p
,VERSION
); p
= skip_string(p
,1);
481 strcpy(p
,lp_workgroup()); p
= skip_string(p
,1);
482 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
483 /* perhaps grab OS version here?? */
486 /* Set the correct uid in the outgoing and incoming packets
487 We will use this on future requests to determine which
488 user we should become.
491 struct passwd
*pw
= Get_Pwnam(user
,False
);
493 DEBUG(1,("Username %s is invalid on this system\n",user
));
494 return(ERROR(ERRSRV
,ERRbadpw
));
500 if (guest
&& !computer_id
)
501 SSVAL(outbuf
,smb_vwv2
,1);
503 /* register the name and uid as being validated, so further connections
504 to a uid can get through without a password, on the same VC */
505 sess_vuid
= register_vuid(uid
,gid
,user
,guest
);
507 SSVAL(outbuf
,smb_uid
,sess_vuid
);
508 SSVAL(inbuf
,smb_uid
,sess_vuid
);
511 maxxmit
= MIN(maxxmit
,smb_bufsize
);
513 done_sesssetup
= True
;
515 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
519 /****************************************************************************
521 ****************************************************************************/
522 int reply_chkpth(char *inbuf
,char *outbuf
)
529 cnum
= SVAL(inbuf
,smb_tid
);
531 strcpy(name
,smb_buf(inbuf
) + 1);
532 unix_convert(name
,cnum
,0);
534 mode
= SVAL(inbuf
,smb_vwv0
);
536 if (check_name(name
,cnum
))
537 ok
= directory_exist(name
,NULL
);
540 return(ERROR(ERRDOS
,ERRbadpath
));
542 outsize
= set_message(outbuf
,0,0,True
);
544 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name
,cnum
,mode
));
550 /****************************************************************************
552 ****************************************************************************/
553 int reply_getatr(char *inbuf
,char *outbuf
)
564 cnum
= SVAL(inbuf
,smb_tid
);
566 strcpy(fname
,smb_buf(inbuf
) + 1);
567 unix_convert(fname
,cnum
,0);
569 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
570 under WfWg - weird! */
573 mode
= aHIDDEN
| aDIR
;
574 if (!CAN_WRITE(cnum
)) mode
|= aRONLY
;
580 if (check_name(fname
,cnum
))
582 if (sys_stat(fname
,&sbuf
) == 0)
584 mode
= dos_mode(cnum
,fname
,&sbuf
);
586 mtime
= sbuf
.st_mtime
;
592 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
596 return(UNIXERROR(ERRDOS
,ERRbadfile
));
598 outsize
= set_message(outbuf
,10,0,True
);
600 SSVAL(outbuf
,smb_vwv0
,mode
);
601 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
602 SIVAL(outbuf
,smb_vwv3
,size
);
604 if (Protocol
>= PROTOCOL_NT1
) {
605 char *p
= strrchr(fname
,'/');
606 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
609 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
612 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname
,mode
,size
));
618 /****************************************************************************
620 ****************************************************************************/
621 int reply_setatr(char *inbuf
,char *outbuf
)
630 cnum
= SVAL(inbuf
,smb_tid
);
632 strcpy(fname
,smb_buf(inbuf
) + 1);
633 unix_convert(fname
,cnum
,0);
635 mode
= SVAL(inbuf
,smb_vwv0
);
636 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
638 if (directory_exist(fname
,NULL
))
640 if (check_name(fname
,cnum
))
641 ok
= (dos_chmod(cnum
,fname
,mode
,NULL
) == 0);
643 ok
= set_filetime(fname
,mtime
);
646 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
648 outsize
= set_message(outbuf
,0,0,True
);
650 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname
,mode
));
656 /****************************************************************************
658 ****************************************************************************/
659 int reply_dskattr(char *inbuf
,char *outbuf
)
663 int dfree
,dsize
,bsize
;
665 cnum
= SVAL(inbuf
,smb_tid
);
667 sys_disk_free(".",&bsize
,&dfree
,&dsize
);
669 outsize
= set_message(outbuf
,5,0,True
);
671 SSVAL(outbuf
,smb_vwv0
,dsize
);
672 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
673 SSVAL(outbuf
,smb_vwv2
,512);
674 SSVAL(outbuf
,smb_vwv3
,dfree
);
676 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum
,dfree
));
682 /****************************************************************************
684 Can be called from SMBsearch, SMBffirst or SMBfunique.
685 ****************************************************************************/
686 int reply_search(char *inbuf
,char *outbuf
)
697 BOOL finished
= False
;
706 BOOL check_descend
= False
;
707 BOOL expect_close
= False
;
708 BOOL can_open
= True
;
710 *mask
= *directory
= *fname
= 0;
712 /* If we were called as SMBffirst then we must expect close. */
713 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
716 cnum
= SVAL(inbuf
,smb_tid
);
718 outsize
= set_message(outbuf
,1,3,True
);
719 maxentries
= SVAL(inbuf
,smb_vwv0
);
720 dirtype
= SVAL(inbuf
,smb_vwv1
);
721 path
= smb_buf(inbuf
) + 1;
722 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
725 /* dirtype &= ~aDIR; */
727 DEBUG(5,("path=%s status_len=%d\n",path
,status_len
));
734 strcpy(directory
,smb_buf(inbuf
)+1);
735 strcpy(dir2
,smb_buf(inbuf
)+1);
736 unix_convert(directory
,cnum
,0);
739 if (!check_name(directory
,cnum
))
742 p
= strrchr(dir2
,'/');
744 {strcpy(mask
,dir2
);*dir2
= 0;}
746 {*p
= 0;strcpy(mask
,p
+1);}
748 p
= strrchr(directory
,'/');
754 if (strlen(directory
) == 0)
755 strcpy(directory
,"./");
757 CVAL(status
,0) = dirtype
;
761 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
762 memcpy(mask
,status
+1,11);
764 dirtype
= CVAL(status
,0) & 0x1F;
765 Connections
[cnum
].dirptr
= dptr_fetch(status
+12,&dptr_num
);
766 if (!Connections
[cnum
].dirptr
)
768 string_set(&Connections
[cnum
].dirpath
,dptr_path(dptr_num
));
773 /* turn strings of spaces into a . */
775 trim_string(mask
,NULL
," ");
776 if ((p
= strrchr(mask
,' ')))
781 trim_string(mask
,NULL
," ");
788 for (p
=mask
; *p
; p
++)
790 if (*p
!= '?' && *p
!= '*' && !isdoschar(*p
))
792 DEBUG(5,("Invalid char [%c] in search mask?\n",*p
));
798 if (!strchr(mask
,'.') && strlen(mask
)>8)
801 strcpy(tmp
,&mask
[8]);
807 DEBUG(5,("mask=%s directory=%s\n",mask
,directory
));
811 p
= smb_buf(outbuf
) + 3;
817 dptr_num
= dptr_create(cnum
,directory
,expect_close
,SVAL(inbuf
,smb_pid
));
819 return(ERROR(ERRDOS
,ERRnofids
));
822 DEBUG(4,("dptr_num is %d\n",dptr_num
));
826 if ((dirtype
&0x1F) == aVOLID
)
829 make_dir_struct(p
,"???????????",volume_label(SNUM(cnum
)),0,aVOLID
,0);
830 dptr_fill(p
+12,dptr_num
);
831 if (dptr_zero(p
+12) && (status_len
==0))
835 p
+= DIR_STRUCT_SIZE
;
839 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections
[cnum
].dirpath
,lp_dontdescend(SNUM(cnum
))));
840 if (in_list(Connections
[cnum
].dirpath
,
841 lp_dontdescend(SNUM(cnum
)),True
))
842 check_descend
= True
;
844 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
847 !get_dir_entry(cnum
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
851 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
852 dptr_fill(p
+12,dptr_num
);
855 p
+= DIR_STRUCT_SIZE
;
864 if (numentries
== 0 || !ok
)
866 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
867 SSVAL(outbuf
,smb_err
,ERRnofiles
);
870 /* If we were called as SMBffirst with smb_search_id == NULL
871 and no entries were found then return error and close dirptr
874 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
876 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
877 SSVAL(outbuf
,smb_err
,ERRnofiles
);
878 /* Also close the dptr - we know it's gone */
879 dptr_close(dptr_num
);
882 /* If we were called as SMBfunique, then we can close the dirptr now ! */
883 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
884 dptr_close(dptr_num
);
886 SSVAL(outbuf
,smb_vwv0
,numentries
);
887 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
888 CVAL(smb_buf(outbuf
),0) = 5;
889 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
891 if (Protocol
>= PROTOCOL_NT1
) {
892 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
893 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
896 outsize
+= DIR_STRUCT_SIZE
*numentries
;
897 smb_setlen(outbuf
,outsize
- 4);
899 if ((! *directory
) && dptr_path(dptr_num
))
900 sprintf(directory
,"(%s)",dptr_path(dptr_num
));
902 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
904 smb_fn_name(CVAL(inbuf
,smb_com
)),
905 mask
,directory
,cnum
,dirtype
,numentries
,maxentries
));
911 /****************************************************************************
912 reply to a fclose (stop directory search)
913 ****************************************************************************/
914 int reply_fclose(char *inbuf
,char *outbuf
)
923 cnum
= SVAL(inbuf
,smb_tid
);
925 outsize
= set_message(outbuf
,1,0,True
);
926 path
= smb_buf(inbuf
) + 1;
927 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
931 return(ERROR(ERRSRV
,ERRsrverror
));
933 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
935 if(dptr_fetch(status
+12,&dptr_num
)) {
936 /* Close the dptr - we know it's gone */
937 dptr_close(dptr_num
);
940 SSVAL(outbuf
,smb_vwv0
,0);
942 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum
));
948 /****************************************************************************
950 ****************************************************************************/
951 int reply_open(char *inbuf
,char *outbuf
)
965 cnum
= SVAL(inbuf
,smb_tid
);
967 share_mode
= SVAL(inbuf
,smb_vwv0
);
969 strcpy(fname
,smb_buf(inbuf
)+1);
970 unix_convert(fname
,cnum
,0);
972 fnum
= find_free_file();
974 return(ERROR(ERRSRV
,ERRnofids
));
976 if (!check_name(fname
,cnum
))
977 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
979 unixmode
= unix_mode(cnum
,aARCH
);
981 open_file_shared(fnum
,cnum
,fname
,share_mode
,3,unixmode
,&rmode
,NULL
);
983 if (!Files
[fnum
].open
)
984 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
986 if (fstat(Files
[fnum
].fd_ptr
->fd
,&sbuf
) != 0) {
988 return(ERROR(ERRDOS
,ERRnoaccess
));
992 fmode
= dos_mode(cnum
,fname
,&sbuf
);
993 mtime
= sbuf
.st_mtime
;
996 DEBUG(3,("attempt to open a directory %s\n",fname
));
998 return(ERROR(ERRDOS
,ERRnoaccess
));
1001 outsize
= set_message(outbuf
,7,0,True
);
1002 SSVAL(outbuf
,smb_vwv0
,fnum
);
1003 SSVAL(outbuf
,smb_vwv1
,fmode
);
1004 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1005 SIVAL(outbuf
,smb_vwv4
,size
);
1006 SSVAL(outbuf
,smb_vwv6
,rmode
);
1008 if (lp_fake_oplocks(SNUM(cnum
))) {
1009 CVAL(outbuf
,smb_flg
) |= (CVAL(inbuf
,smb_flg
) & (1<<5));
1016 /****************************************************************************
1017 reply to an open and X
1018 ****************************************************************************/
1019 int reply_open_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1022 int cnum
= SVAL(inbuf
,smb_tid
);
1025 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1026 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1027 BOOL oplock_request
= BITSETW(inbuf
+smb_vwv2
,1);
1029 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1030 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1031 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1033 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1035 int size
=0,fmode
=0,mtime
=0,rmode
=0;
1039 /* If it's an IPC, pass off the pipe handler. */
1041 return reply_open_pipe_and_X(inbuf
,outbuf
,length
,bufsize
);
1043 /* XXXX we need to handle passed times, sattr and flags */
1045 strcpy(fname
,smb_buf(inbuf
));
1046 unix_convert(fname
,cnum
,0);
1048 /* now add create and trunc bits */
1049 if (smb_ofun
& 0x10)
1050 openmode
|= O_CREAT
;
1051 if ((smb_ofun
& 0x3) == 2)
1052 openmode
|= O_TRUNC
;
1054 fnum
= find_free_file();
1056 return(ERROR(ERRSRV
,ERRnofids
));
1058 if (!check_name(fname
,cnum
))
1059 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1061 unixmode
= unix_mode(cnum
,smb_attr
| aARCH
);
1063 open_file_shared(fnum
,cnum
,fname
,smb_mode
,smb_ofun
,unixmode
,
1064 &rmode
,&smb_action
);
1066 if (!Files
[fnum
].open
)
1067 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1069 if (fstat(Files
[fnum
].fd_ptr
->fd
,&sbuf
) != 0) {
1071 return(ERROR(ERRDOS
,ERRnoaccess
));
1074 size
= sbuf
.st_size
;
1075 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1076 mtime
= sbuf
.st_mtime
;
1079 return(ERROR(ERRDOS
,ERRnoaccess
));
1082 if (oplock_request
&& lp_fake_oplocks(SNUM(cnum
))) {
1083 smb_action
|= (1<<15);
1086 set_message(outbuf
,15,0,True
);
1087 SSVAL(outbuf
,smb_vwv2
,fnum
);
1088 SSVAL(outbuf
,smb_vwv3
,fmode
);
1089 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1090 SIVAL(outbuf
,smb_vwv6
,size
);
1091 SSVAL(outbuf
,smb_vwv8
,rmode
);
1092 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1096 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1100 /****************************************************************************
1101 reply to a SMBulogoffX
1102 ****************************************************************************/
1103 int reply_ulogoffX(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1105 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1106 user_struct
*vuser
= get_valid_user_struct(vuid
);
1109 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1112 /* in user level security we are supposed to close any files
1113 open by this user */
1114 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1116 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
1117 if (Files
[i
].uid
== vuser
->uid
&& Files
[i
].open
) {
1122 invalidate_vuid(vuid
);
1124 set_message(outbuf
,2,0,True
);
1126 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid
));
1128 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1132 /****************************************************************************
1134 ****************************************************************************/
1135 int reply_mknew(char *inbuf
,char *outbuf
)
1144 com
= SVAL(inbuf
,smb_com
);
1145 cnum
= SVAL(inbuf
,smb_tid
);
1147 createmode
= SVAL(inbuf
,smb_vwv0
);
1148 strcpy(fname
,smb_buf(inbuf
)+1);
1149 unix_convert(fname
,cnum
,0);
1151 if (createmode
& aVOLID
)
1153 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1156 unixmode
= unix_mode(cnum
,createmode
);
1158 if (com
== SMBmknew
&& file_exist(fname
,NULL
))
1159 return(ERROR(ERRDOS
,ERRfilexists
));
1161 fnum
= find_free_file();
1163 return(ERROR(ERRSRV
,ERRnofids
));
1165 if (!check_name(fname
,cnum
))
1166 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1168 open_file(fnum
,cnum
,fname
,O_RDWR
| O_CREAT
| O_TRUNC
,unixmode
, 0);
1170 if (!Files
[fnum
].open
)
1171 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1173 outsize
= set_message(outbuf
,1,0,True
);
1174 SSVAL(outbuf
,smb_vwv0
,fnum
);
1176 if (lp_fake_oplocks(SNUM(cnum
))) {
1177 CVAL(outbuf
,smb_flg
) |= (CVAL(inbuf
,smb_flg
) & (1<<5));
1180 DEBUG(2,("new file %s\n",fname
));
1181 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
));
1187 /****************************************************************************
1188 reply to a create temporary file
1189 ****************************************************************************/
1190 int reply_ctemp(char *inbuf
,char *outbuf
)
1200 cnum
= SVAL(inbuf
,smb_tid
);
1201 createmode
= SVAL(inbuf
,smb_vwv0
);
1202 sprintf(fname
,"%s/TMXXXXXX",smb_buf(inbuf
)+1);
1203 unix_convert(fname
,cnum
,0);
1205 unixmode
= unix_mode(cnum
,createmode
);
1207 fnum
= find_free_file();
1209 return(ERROR(ERRSRV
,ERRnofids
));
1211 if (!check_name(fname
,cnum
))
1212 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1214 strcpy(fname2
,(char *)mktemp(fname
));
1216 open_file(fnum
,cnum
,fname2
,O_RDWR
| O_CREAT
| O_TRUNC
,unixmode
, 0);
1218 if (!Files
[fnum
].open
)
1219 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1221 outsize
= set_message(outbuf
,1,2 + strlen(fname2
),True
);
1222 SSVAL(outbuf
,smb_vwv0
,fnum
);
1223 CVAL(smb_buf(outbuf
),0) = 4;
1224 strcpy(smb_buf(outbuf
) + 1,fname2
);
1226 if (lp_fake_oplocks(SNUM(cnum
))) {
1227 CVAL(outbuf
,smb_flg
) |= (CVAL(inbuf
,smb_flg
) & (1<<5));
1230 DEBUG(2,("created temp file %s\n",fname2
));
1231 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
));
1237 /*******************************************************************
1238 check if a user is allowed to delete a file
1239 ********************************************************************/
1240 static BOOL
can_delete(char *fname
,int cnum
,int dirtype
)
1245 if (!CAN_WRITE(cnum
)) return(False
);
1247 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
1248 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1249 if (fmode
& aDIR
) return(False
);
1250 if (!lp_delete_readonly(SNUM(cnum
))) {
1251 if (fmode
& aRONLY
) return(False
);
1253 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1255 if (!check_file_sharing(cnum
,fname
)) return(False
);
1259 /****************************************************************************
1261 ****************************************************************************/
1262 int reply_unlink(char *inbuf
,char *outbuf
)
1272 int error
= ERRnoaccess
;
1276 *directory
= *mask
= 0;
1278 cnum
= SVAL(inbuf
,smb_tid
);
1279 dirtype
= SVAL(inbuf
,smb_vwv0
);
1281 strcpy(name
,smb_buf(inbuf
) + 1);
1283 DEBUG(3,("reply_unlink : %s\n",name
));
1285 unix_convert(name
,cnum
,0);
1287 p
= strrchr(name
,'/');
1289 strcpy(directory
,"./");
1293 strcpy(directory
,name
);
1297 if (is_mangled(mask
))
1298 check_mangled_stack(mask
);
1300 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
1303 strcat(directory
,"/");
1304 strcat(directory
,mask
);
1305 if (can_delete(directory
,cnum
,dirtype
) && !sys_unlink(directory
)) count
++;
1306 if (!count
) exists
= file_exist(directory
,NULL
);
1308 void *dirptr
= NULL
;
1311 if (check_name(directory
,cnum
))
1312 dirptr
= OpenDir(directory
);
1314 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1315 the pattern matches against the long name, otherwise the short name
1316 We don't implement this yet XXXX
1323 if (strequal(mask
,"????????.???"))
1326 while ((dname
= ReadDirName(dirptr
)))
1329 strcpy(fname
,dname
);
1331 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
1333 error
= ERRnoaccess
;
1334 sprintf(fname
,"%s/%s",directory
,dname
);
1335 if (!can_delete(fname
,cnum
,dirtype
)) continue;
1336 if (!sys_unlink(fname
)) count
++;
1337 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname
));
1345 return(ERROR(ERRDOS
,error
));
1347 return(UNIXERROR(ERRDOS
,error
));
1350 outsize
= set_message(outbuf
,0,0,True
);
1356 /****************************************************************************
1357 reply to a readbraw (core+ protocol)
1358 ****************************************************************************/
1359 int reply_readbraw(char *inbuf
, char *outbuf
)
1361 int cnum
,maxcount
,mincount
,fnum
;
1364 char *header
= outbuf
;
1369 cnum
= SVAL(inbuf
,smb_tid
);
1370 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1372 startpos
= IVAL(inbuf
,smb_vwv1
);
1373 maxcount
= SVAL(inbuf
,smb_vwv3
);
1374 mincount
= SVAL(inbuf
,smb_vwv4
);
1376 /* ensure we don't overrun the packet size */
1377 maxcount
= MIN(65535,maxcount
);
1378 maxcount
= MAX(mincount
,maxcount
);
1380 if (!FNUM_OK(fnum
,cnum
) || !Files
[fnum
].can_read
)
1382 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum
));
1383 _smb_setlen(header
,0);
1384 transfer_file(0,Client
,0,header
,4,0);
1389 fd
= Files
[fnum
].fd_ptr
->fd
;
1390 fname
= Files
[fnum
].name
;
1394 if (!is_locked(fnum
,cnum
,maxcount
,startpos
))
1396 int size
= Files
[fnum
].size
;
1397 int sizeneeded
= startpos
+ maxcount
;
1399 if (size
< sizeneeded
) {
1401 if (fstat(Files
[fnum
].fd_ptr
->fd
,&st
) == 0)
1403 if (!Files
[fnum
].can_write
)
1404 Files
[fnum
].size
= size
;
1407 nread
= MIN(maxcount
,size
- startpos
);
1410 if (nread
< mincount
)
1413 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1416 maxcount
,mincount
,nread
));
1421 _smb_setlen(header
,nread
);
1423 if (!Files
[fnum
].can_write
)
1424 predict
= read_predict(fd
,startpos
,header
+4,NULL
,nread
);
1426 if ((nread
-predict
) > 0)
1427 seek_file(fnum
,startpos
+ predict
);
1429 ret
= transfer_file(fd
,Client
,nread
-predict
,header
,4+predict
,
1434 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1435 fname
,startpos
,nread
,ret
));
1438 ret
= read_file(fnum
,header
+4,startpos
,nread
);
1439 if (ret
< mincount
) ret
= 0;
1441 _smb_setlen(header
,ret
);
1442 transfer_file(0,Client
,0,header
,4+ret
,0);
1445 DEBUG(5,("readbraw finished\n"));
1450 /****************************************************************************
1451 reply to a lockread (core+ protocol)
1452 ****************************************************************************/
1453 int reply_lockread(char *inbuf
,char *outbuf
)
1459 uint32 startpos
, numtoread
;
1463 cnum
= SVAL(inbuf
,smb_tid
);
1464 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1466 CHECK_FNUM(fnum
,cnum
);
1470 numtoread
= SVAL(inbuf
,smb_vwv1
);
1471 startpos
= IVAL(inbuf
,smb_vwv2
);
1473 outsize
= set_message(outbuf
,5,3,True
);
1474 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1475 data
= smb_buf(outbuf
) + 3;
1477 if(!do_lock( fnum
, cnum
, numtoread
, startpos
, &eclass
, &ecode
))
1478 return (ERROR(eclass
,ecode
));
1480 nread
= read_file(fnum
,data
,startpos
,numtoread
);
1483 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1486 SSVAL(outbuf
,smb_vwv0
,nread
);
1487 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1488 SSVAL(smb_buf(outbuf
),1,nread
);
1490 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum
,cnum
,numtoread
,nread
));
1496 /****************************************************************************
1498 ****************************************************************************/
1499 int reply_read(char *inbuf
,char *outbuf
)
1501 int cnum
,numtoread
,fnum
;
1507 cnum
= SVAL(inbuf
,smb_tid
);
1508 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1510 CHECK_FNUM(fnum
,cnum
);
1514 numtoread
= SVAL(inbuf
,smb_vwv1
);
1515 startpos
= IVAL(inbuf
,smb_vwv2
);
1517 outsize
= set_message(outbuf
,5,3,True
);
1518 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1519 data
= smb_buf(outbuf
) + 3;
1521 if (is_locked(fnum
,cnum
,numtoread
,startpos
))
1522 return(ERROR(ERRDOS
,ERRlock
));
1525 nread
= read_file(fnum
,data
,startpos
,numtoread
);
1528 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1531 SSVAL(outbuf
,smb_vwv0
,nread
);
1532 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1533 CVAL(smb_buf(outbuf
),0) = 1;
1534 SSVAL(smb_buf(outbuf
),1,nread
);
1536 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum
,cnum
,numtoread
,nread
));
1542 /****************************************************************************
1543 reply to a read and X
1544 ****************************************************************************/
1545 int reply_read_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1547 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
1548 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
1549 int smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
1550 int smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
1556 cnum
= SVAL(inbuf
,smb_tid
);
1558 CHECK_FNUM(fnum
,cnum
);
1562 set_message(outbuf
,12,0,True
);
1563 data
= smb_buf(outbuf
);
1565 if (is_locked(fnum
,cnum
,smb_maxcnt
,smb_offs
))
1566 return(ERROR(ERRDOS
,ERRlock
));
1567 nread
= read_file(fnum
,data
,smb_offs
,smb_maxcnt
);
1571 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1573 SSVAL(outbuf
,smb_vwv5
,nread
);
1574 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
1575 SSVAL(smb_buf(outbuf
),-2,nread
);
1577 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1578 timestring(),fnum
,cnum
,
1579 smb_mincnt
,smb_maxcnt
,nread
));
1583 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1587 /****************************************************************************
1588 reply to a writebraw (core+ or LANMAN1.0 protocol)
1589 ****************************************************************************/
1590 int reply_writebraw(char *inbuf
,char *outbuf
)
1593 int total_written
=0;
1602 cnum
= SVAL(inbuf
,smb_tid
);
1603 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1605 CHECK_FNUM(fnum
,cnum
);
1609 tcount
= IVAL(inbuf
,smb_vwv1
);
1610 startpos
= IVAL(inbuf
,smb_vwv3
);
1611 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
1613 /* We have to deal with slightly different formats depending
1614 on whether we are using the core+ or lanman1.0 protocol */
1615 if(Protocol
<= PROTOCOL_COREPLUS
) {
1616 numtowrite
= SVAL(smb_buf(inbuf
),-2);
1617 data
= smb_buf(inbuf
);
1619 numtowrite
= SVAL(inbuf
,smb_vwv10
);
1620 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
1623 /* force the error type */
1624 CVAL(inbuf
,smb_com
) = SMBwritec
;
1625 CVAL(outbuf
,smb_com
) = SMBwritec
;
1627 if (is_locked(fnum
,cnum
,tcount
,startpos
))
1628 return(ERROR(ERRDOS
,ERRlock
));
1630 if (seek_file(fnum
,startpos
) != startpos
)
1631 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos
));
1634 nwritten
= write_file(fnum
,data
,numtowrite
);
1636 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1637 timestring(),fnum
,cnum
,startpos
,numtowrite
,nwritten
,write_through
));
1639 if (nwritten
< numtowrite
)
1640 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
1642 total_written
= nwritten
;
1644 /* Return a message to the redirector to tell it
1645 to send more bytes */
1646 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
1647 SSVALS(outbuf
,smb_vwv0
,-1);
1648 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
1649 send_smb(Client
,outbuf
);
1651 /* Now read the raw data into the buffer and write it */
1652 if (read_smb_length(Client
,inbuf
,SMB_SECONDARY_WAIT
) == -1) {
1653 exit_server("secondary writebraw failed");
1656 /* Even though this is not an smb message, smb_len
1657 returns the generic length of an smb message */
1658 numtowrite
= smb_len(inbuf
);
1660 if (tcount
> nwritten
+numtowrite
) {
1661 DEBUG(3,("Client overestimated the write %d %d %d\n",
1662 tcount
,nwritten
,numtowrite
));
1665 nwritten
= transfer_file(Client
,Files
[fnum
].fd_ptr
->fd
,numtowrite
,NULL
,0,
1667 total_written
+= nwritten
;
1669 /* Set up outbuf to return the correct return */
1670 outsize
= set_message(outbuf
,1,0,True
);
1671 CVAL(outbuf
,smb_com
) = SMBwritec
;
1672 SSVAL(outbuf
,smb_vwv0
,total_written
);
1674 if (nwritten
< numtowrite
) {
1675 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1676 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1679 if (lp_syncalways(SNUM(cnum
)) || write_through
)
1682 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1683 timestring(),fnum
,cnum
,startpos
,numtowrite
,total_written
));
1685 /* we won't return a status if write through is not selected - this
1686 follows what WfWg does */
1687 if (!write_through
&& total_written
==tcount
)
1694 /****************************************************************************
1695 reply to a writeunlock (core+)
1696 ****************************************************************************/
1697 int reply_writeunlock(char *inbuf
,char *outbuf
)
1703 uint32 numtowrite
,startpos
;
1707 cnum
= SVAL(inbuf
,smb_tid
);
1708 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1710 CHECK_FNUM(fnum
,cnum
);
1714 numtowrite
= SVAL(inbuf
,smb_vwv1
);
1715 startpos
= IVAL(inbuf
,smb_vwv2
);
1716 data
= smb_buf(inbuf
) + 3;
1718 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
1719 return(ERROR(ERRDOS
,ERRlock
));
1721 seek_file(fnum
,startpos
);
1723 /* The special X/Open SMB protocol handling of
1724 zero length writes is *NOT* done for
1729 nwritten
= write_file(fnum
,data
,numtowrite
);
1731 if (lp_syncalways(SNUM(cnum
)))
1734 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
1735 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1737 if(!do_unlock(fnum
, cnum
, numtowrite
, startpos
, &eclass
, &ecode
))
1738 return(ERROR(eclass
,ecode
));
1740 outsize
= set_message(outbuf
,1,0,True
);
1742 SSVAL(outbuf
,smb_vwv0
,nwritten
);
1744 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1745 timestring(),fnum
,cnum
,numtowrite
,nwritten
));
1751 /****************************************************************************
1753 ****************************************************************************/
1754 int reply_write(char *inbuf
,char *outbuf
,int dum1
,int dum2
)
1756 int cnum
,numtowrite
,fnum
;
1765 cnum
= SVAL(inbuf
,smb_tid
);
1766 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1768 CHECK_FNUM(fnum
,cnum
);
1772 numtowrite
= SVAL(inbuf
,smb_vwv1
);
1773 startpos
= IVAL(inbuf
,smb_vwv2
);
1774 data
= smb_buf(inbuf
) + 3;
1776 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
1777 return(ERROR(ERRDOS
,ERRlock
));
1779 seek_file(fnum
,startpos
);
1781 /* X/Open SMB protocol says that if smb_vwv1 is
1782 zero then the file size should be extended or
1783 truncated to the size given in smb_vwv[2-3] */
1785 nwritten
= set_filelen(Files
[fnum
].fd_ptr
->fd
, startpos
);
1787 nwritten
= write_file(fnum
,data
,numtowrite
);
1789 if (lp_syncalways(SNUM(cnum
)))
1792 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
1793 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1795 outsize
= set_message(outbuf
,1,0,True
);
1797 SSVAL(outbuf
,smb_vwv0
,nwritten
);
1799 if (nwritten
< numtowrite
) {
1800 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1801 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1804 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum
,cnum
,numtowrite
,nwritten
));
1810 /****************************************************************************
1811 reply to a write and X
1812 ****************************************************************************/
1813 int reply_write_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1815 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
1816 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
1817 int smb_dsize
= SVAL(inbuf
,smb_vwv10
);
1818 int smb_doff
= SVAL(inbuf
,smb_vwv11
);
1819 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
1824 cnum
= SVAL(inbuf
,smb_tid
);
1826 CHECK_FNUM(fnum
,cnum
);
1830 data
= smb_base(inbuf
) + smb_doff
;
1832 if (is_locked(fnum
,cnum
,smb_dsize
,smb_offs
))
1833 return(ERROR(ERRDOS
,ERRlock
));
1835 seek_file(fnum
,smb_offs
);
1837 /* X/Open SMB protocol says that, unlike SMBwrite
1838 if the length is zero then NO truncation is
1839 done, just a write of zero. To truncate a file,
1844 nwritten
= write_file(fnum
,data
,smb_dsize
);
1846 if(((nwritten
== 0) && (smb_dsize
!= 0))||(nwritten
< 0))
1847 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1849 set_message(outbuf
,6,0,True
);
1851 SSVAL(outbuf
,smb_vwv2
,nwritten
);
1853 if (nwritten
< smb_dsize
) {
1854 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1855 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1858 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum
,cnum
,smb_dsize
,nwritten
));
1862 if (lp_syncalways(SNUM(cnum
)) || write_through
)
1865 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1869 /****************************************************************************
1871 ****************************************************************************/
1872 int reply_lseek(char *inbuf
,char *outbuf
)
1880 cnum
= SVAL(inbuf
,smb_tid
);
1881 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1883 CHECK_FNUM(fnum
,cnum
);
1886 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
1887 startpos
= IVAL(inbuf
,smb_vwv2
);
1891 case 0: umode
= SEEK_SET
; break;
1892 case 1: umode
= SEEK_CUR
; break;
1893 case 2: umode
= SEEK_END
; break;
1895 umode
= SEEK_SET
; break;
1898 res
= lseek(Files
[fnum
].fd_ptr
->fd
,startpos
,umode
);
1899 Files
[fnum
].pos
= res
;
1901 outsize
= set_message(outbuf
,2,0,True
);
1902 SIVALS(outbuf
,smb_vwv0
,res
);
1904 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum
,cnum
,startpos
,mode
));
1910 /****************************************************************************
1912 ****************************************************************************/
1913 int reply_flush(char *inbuf
,char *outbuf
)
1916 int outsize
= set_message(outbuf
,0,0,True
);
1918 cnum
= SVAL(inbuf
,smb_tid
);
1919 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1921 if (fnum
!= 0xFFFF) {
1922 CHECK_FNUM(fnum
,cnum
);
1929 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
1936 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum
));
1941 /****************************************************************************
1943 ****************************************************************************/
1944 int reply_exit(char *inbuf
,char *outbuf
)
1946 int outsize
= set_message(outbuf
,0,0,True
);
1947 DEBUG(3,("%s exit\n",timestring()));
1953 /****************************************************************************
1955 ****************************************************************************/
1956 int reply_close(char *inbuf
,char *outbuf
)
1961 int32 eclass
= 0, err
= 0;
1963 outsize
= set_message(outbuf
,0,0,True
);
1965 cnum
= SVAL(inbuf
,smb_tid
);
1967 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1968 CHECK_FNUM(fnum
,cnum
);
1970 if(HAS_CACHED_ERROR(fnum
)) {
1971 eclass
= Files
[fnum
].wbmpx_ptr
->wr_errclass
;
1972 err
= Files
[fnum
].wbmpx_ptr
->wr_error
;
1975 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
1977 /* try and set the date */
1978 set_filetime(Files
[fnum
].name
,mtime
);
1982 /* We have a cached error */
1984 return(ERROR(eclass
,err
));
1986 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
1987 timestring(),Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
,
1988 Connections
[cnum
].num_files_open
));
1994 /****************************************************************************
1995 reply to a writeclose (Core+ protocol)
1996 ****************************************************************************/
1997 int reply_writeclose(char *inbuf
,char *outbuf
)
1999 int cnum
,numtowrite
,fnum
;
2006 cnum
= SVAL(inbuf
,smb_tid
);
2007 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2009 CHECK_FNUM(fnum
,cnum
);
2013 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2014 startpos
= IVAL(inbuf
,smb_vwv2
);
2015 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2016 data
= smb_buf(inbuf
) + 1;
2018 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
2019 return(ERROR(ERRDOS
,ERRlock
));
2021 seek_file(fnum
,startpos
);
2023 nwritten
= write_file(fnum
,data
,numtowrite
);
2025 set_filetime(Files
[fnum
].name
,mtime
);
2029 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2030 timestring(),fnum
,cnum
,numtowrite
,nwritten
,
2031 Connections
[cnum
].num_files_open
));
2034 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2036 outsize
= set_message(outbuf
,1,0,True
);
2038 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2043 /****************************************************************************
2045 ****************************************************************************/
2046 int reply_lock(char *inbuf
,char *outbuf
)
2049 int outsize
= set_message(outbuf
,0,0,True
);
2050 uint32 count
,offset
;
2054 cnum
= SVAL(inbuf
,smb_tid
);
2055 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2057 CHECK_FNUM(fnum
,cnum
);
2060 count
= IVAL(inbuf
,smb_vwv1
);
2061 offset
= IVAL(inbuf
,smb_vwv3
);
2063 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
));
2065 if(!do_lock( fnum
, cnum
, count
, offset
, &eclass
, &ecode
))
2066 return (ERROR(eclass
,ecode
));
2072 /****************************************************************************
2074 ****************************************************************************/
2075 int reply_unlock(char *inbuf
,char *outbuf
)
2078 int outsize
= set_message(outbuf
,0,0,True
);
2079 uint32 count
,offset
;
2083 cnum
= SVAL(inbuf
,smb_tid
);
2084 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2086 CHECK_FNUM(fnum
,cnum
);
2089 count
= IVAL(inbuf
,smb_vwv1
);
2090 offset
= IVAL(inbuf
,smb_vwv3
);
2092 if(!do_unlock(fnum
, cnum
, count
, offset
, &eclass
, &ecode
))
2093 return (ERROR(eclass
,ecode
));
2095 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
));
2101 /****************************************************************************
2103 ****************************************************************************/
2104 int reply_tdis(char *inbuf
,char *outbuf
)
2107 int outsize
= set_message(outbuf
,0,0,True
);
2110 cnum
= SVAL(inbuf
,smb_tid
);
2111 vuid
= SVAL(inbuf
,smb_uid
);
2113 if (!OPEN_CNUM(cnum
)) {
2114 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum
));
2115 return(ERROR(ERRSRV
,ERRinvnid
));
2118 Connections
[cnum
].used
= False
;
2120 close_cnum(cnum
,vuid
);
2122 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum
));
2129 /****************************************************************************
2131 ****************************************************************************/
2132 int reply_echo(char *inbuf
,char *outbuf
)
2135 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2137 int data_len
= smb_buflen(inbuf
);
2138 int outsize
= set_message(outbuf
,1,data_len
,True
);
2140 cnum
= SVAL(inbuf
,smb_tid
);
2142 if (cnum
!= 0xFFFF && !OPEN_CNUM(cnum
))
2144 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum
));
2145 return(ERROR(ERRSRV
,ERRinvnid
));
2148 /* copy any incoming data back out */
2150 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2152 if (smb_reverb
> 100)
2154 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2158 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++)
2160 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2162 smb_setlen(outbuf
,outsize
- 4);
2164 send_smb(Client
,outbuf
);
2167 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb
,cnum
));
2173 /****************************************************************************
2174 reply to a printopen
2175 ****************************************************************************/
2176 int reply_printopen(char *inbuf
,char *outbuf
)
2184 *fname
= *fname2
= 0;
2186 cnum
= SVAL(inbuf
,smb_tid
);
2188 if (!CAN_PRINT(cnum
))
2189 return(ERROR(ERRDOS
,ERRnoaccess
));
2194 StrnCpy(s
,smb_buf(inbuf
)+1,sizeof(pstring
)-1);
2198 if (!(isalnum(*p
) || strchr("._-",*p
)))
2203 if (strlen(s
) > 10) s
[10] = 0;
2205 sprintf(fname
,"%s.XXXXXX",s
);
2208 fnum
= find_free_file();
2210 return(ERROR(ERRSRV
,ERRnofids
));
2212 strcpy(fname2
,(char *)mktemp(fname
));
2214 if (!check_name(fname2
,cnum
))
2215 return(ERROR(ERRDOS
,ERRnoaccess
));
2217 open_file(fnum
,cnum
,fname2
,O_WRONLY
| O_CREAT
| O_TRUNC
,
2218 unix_mode(cnum
,0), 0);
2220 if (!Files
[fnum
].open
)
2221 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2223 /* force it to be a print file */
2224 Files
[fnum
].print_file
= True
;
2226 outsize
= set_message(outbuf
,1,0,True
);
2227 SSVAL(outbuf
,smb_vwv0
,fnum
);
2229 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2
,Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
));
2235 /****************************************************************************
2236 reply to a printclose
2237 ****************************************************************************/
2238 int reply_printclose(char *inbuf
,char *outbuf
)
2241 int outsize
= set_message(outbuf
,0,0,True
);
2243 cnum
= SVAL(inbuf
,smb_tid
);
2244 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2246 CHECK_FNUM(fnum
,cnum
);
2249 if (!CAN_PRINT(cnum
))
2250 return(ERROR(ERRDOS
,ERRnoaccess
));
2254 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
));
2260 /****************************************************************************
2261 reply to a printqueue
2262 ****************************************************************************/
2263 int reply_printqueue(char *inbuf
,char *outbuf
)
2266 int outsize
= set_message(outbuf
,2,3,True
);
2267 int max_count
= SVAL(inbuf
,smb_vwv0
);
2268 int start_index
= SVAL(inbuf
,smb_vwv1
);
2271 cnum
= SVAL(inbuf
,smb_tid
);
2272 vuid
= SVAL(inbuf
,smb_uid
);
2274 /* allow checking the queue for anyone */
2276 if (!CAN_PRINT(cnum
))
2277 return(ERROR(ERRDOS
,ERRnoaccess
));
2280 SSVAL(outbuf
,smb_vwv0
,0);
2281 SSVAL(outbuf
,smb_vwv1
,0);
2282 CVAL(smb_buf(outbuf
),0) = 1;
2283 SSVAL(smb_buf(outbuf
),1,0);
2285 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2286 timestring(),cnum
,start_index
,max_count
));
2288 if (!OPEN_CNUM(cnum
) || !Connections
[cnum
].printer
)
2293 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2294 if (CAN_PRINT(i
) && Connections
[i
].printer
)
2298 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2302 if (!OPEN_CNUM(cnum
))
2303 return(ERROR(ERRSRV
,ERRinvnid
));
2305 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum
));
2308 if (!become_user(cnum
,vuid
))
2309 return(ERROR(ERRSRV
,ERRinvnid
));
2312 print_queue_struct
*queue
= NULL
;
2313 char *p
= smb_buf(outbuf
) + 3;
2314 int count
= get_printqueue(SNUM(cnum
),cnum
,&queue
,NULL
);
2315 int num_to_get
= ABS(max_count
);
2316 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
2322 num_to_get
= MIN(num_to_get
,count
-first
);
2325 for (i
=first
;i
<first
+num_to_get
;i
++)
2327 put_dos_date2(p
,0,queue
[i
].time
);
2328 CVAL(p
,4) = (queue
[i
].status
==LPQ_PRINTING
?2:3);
2329 SSVAL(p
,5,queue
[i
].job
);
2330 SIVAL(p
,7,queue
[i
].size
);
2332 StrnCpy(p
+12,queue
[i
].user
,16);
2338 outsize
= set_message(outbuf
,2,28*count
+3,False
);
2339 SSVAL(outbuf
,smb_vwv0
,count
);
2340 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
2341 CVAL(smb_buf(outbuf
),0) = 1;
2342 SSVAL(smb_buf(outbuf
),1,28*count
);
2345 if (queue
) free(queue
);
2347 DEBUG(3,("%d entries returned in queue\n",count
));
2354 /****************************************************************************
2355 reply to a printwrite
2356 ****************************************************************************/
2357 int reply_printwrite(char *inbuf
,char *outbuf
)
2359 int cnum
,numtowrite
,fnum
;
2360 int outsize
= set_message(outbuf
,0,0,True
);
2363 cnum
= SVAL(inbuf
,smb_tid
);
2365 if (!CAN_PRINT(cnum
))
2366 return(ERROR(ERRDOS
,ERRnoaccess
));
2368 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2370 CHECK_FNUM(fnum
,cnum
);
2374 numtowrite
= SVAL(smb_buf(inbuf
),1);
2375 data
= smb_buf(inbuf
) + 3;
2377 if (write_file(fnum
,data
,numtowrite
) != numtowrite
)
2378 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2380 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum
,cnum
,numtowrite
));
2386 /****************************************************************************
2388 ****************************************************************************/
2389 int reply_mkdir(char *inbuf
,char *outbuf
)
2393 int outsize
,ret
= -1;
2395 strcpy(directory
,smb_buf(inbuf
) + 1);
2396 cnum
= SVAL(inbuf
,smb_tid
);
2397 unix_convert(directory
,cnum
,0);
2399 if (check_name(directory
,cnum
))
2400 ret
= sys_mkdir(directory
,unix_mode(cnum
,aDIR
));
2403 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2405 outsize
= set_message(outbuf
,0,0,True
);
2407 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory
,cnum
,ret
));
2413 /****************************************************************************
2415 ****************************************************************************/
2416 int reply_rmdir(char *inbuf
,char *outbuf
)
2423 cnum
= SVAL(inbuf
,smb_tid
);
2424 strcpy(directory
,smb_buf(inbuf
) + 1);
2425 unix_convert(directory
,cnum
,0);
2427 if (check_name(directory
,cnum
))
2429 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
2430 ok
= (sys_rmdir(directory
) == 0);
2432 DEBUG(3,("couldn't remove directory %s : %s\n",
2433 directory
,strerror(errno
)));
2437 return(UNIXERROR(ERRDOS
,ERRbadpath
));
2439 outsize
= set_message(outbuf
,0,0,True
);
2441 DEBUG(3,("%s rmdir %s\n",timestring(),directory
));
2447 /*******************************************************************
2448 resolve wildcards in a filename rename
2449 ********************************************************************/
2450 static BOOL
resolve_wildcards(char *name1
,char *name2
)
2452 fstring root1
,root2
;
2456 name1
= strrchr(name1
,'/');
2457 name2
= strrchr(name2
,'/');
2459 if (!name1
|| !name2
) return(False
);
2461 strcpy(root1
,name1
);
2462 strcpy(root2
,name2
);
2463 p
= strrchr(root1
,'.');
2470 p
= strrchr(root2
,'.');
2502 strcpy(name2
,root2
);
2511 /*******************************************************************
2512 check if a user is allowed to rename a file
2513 ********************************************************************/
2514 static BOOL
can_rename(char *fname
,int cnum
)
2518 if (!CAN_WRITE(cnum
)) return(False
);
2520 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
2521 if (!check_file_sharing(cnum
,fname
)) return(False
);
2526 /****************************************************************************
2528 ****************************************************************************/
2529 int reply_mv(char *inbuf
,char *outbuf
)
2535 pstring mask
,newname
;
2536 pstring newname_last_component
;
2539 int error
= ERRnoaccess
;
2543 *directory
= *mask
= 0;
2545 cnum
= SVAL(inbuf
,smb_tid
);
2547 strcpy(name
,smb_buf(inbuf
) + 1);
2548 strcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
2550 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
2552 unix_convert(name
,cnum
,0);
2553 unix_convert(newname
,cnum
,newname_last_component
);
2555 p
= strrchr(name
,'/');
2557 strcpy(directory
,"./");
2561 strcpy(directory
,name
);
2563 *p
= '/'; /* Replace needed for exceptional test below. */
2566 if (is_mangled(mask
))
2567 check_mangled_stack(mask
);
2569 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
2572 strcat(directory
,"/");
2573 strcat(directory
,mask
);
2575 DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, name = %s, newname = %s, newname_last_component = %s\n", case_sensitive
, case_preserve
, name
, newname
, newname_last_component
));
2578 * Check for special case with case preserving and not
2579 * case sensitive, if name and newname are identical,
2580 * and the old last component differs from the original
2581 * last component only by case, then we should allow
2582 * the rename (user is trying to change the case of the
2585 if((case_sensitive
== False
) && (case_preserve
== True
) &&
2586 strcsequal(name
, newname
)) {
2587 pstring newname_modified_last_component
;
2590 * Get the last component of the modified name.
2592 p
= strrchr(newname
,'/');
2594 strcpy(newname_modified_last_component
,name
);
2596 strcpy(newname_modified_last_component
,p
+1);
2598 if(strcsequal(newname_modified_last_component
,
2599 newname_last_component
) == False
) {
2601 * Replace the modified last component with
2605 strcpy(p
+1, newname_last_component
);
2607 strcpy(newname
, newname_last_component
);
2611 if (resolve_wildcards(directory
,newname
) &&
2612 can_rename(directory
,cnum
) &&
2613 !file_exist(newname
,NULL
) &&
2614 !sys_rename(directory
,newname
)) count
++;
2616 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",directory
,newname
));
2618 if (!count
) exists
= file_exist(directory
,NULL
);
2619 if (!count
&& exists
&& file_exist(newname
,NULL
)) {
2624 void *dirptr
= NULL
;
2628 if (check_name(directory
,cnum
))
2629 dirptr
= OpenDir(directory
);
2635 if (strequal(mask
,"????????.???"))
2638 while ((dname
= ReadDirName(dirptr
)))
2641 strcpy(fname
,dname
);
2643 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
2645 error
= ERRnoaccess
;
2646 sprintf(fname
,"%s/%s",directory
,dname
);
2647 if (!can_rename(fname
,cnum
)) continue;
2648 strcpy(destname
,newname
);
2650 if (!resolve_wildcards(fname
,destname
)) continue;
2652 if (file_exist(destname
,NULL
)) {
2656 if (!sys_rename(fname
,destname
)) count
++;
2657 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname
,destname
));
2665 return(ERROR(ERRDOS
,error
));
2667 return(UNIXERROR(ERRDOS
,error
));
2670 outsize
= set_message(outbuf
,0,0,True
);
2675 /*******************************************************************
2676 copy a file as part of a reply_copy
2677 ******************************************************************/
2678 static BOOL
copy_file(char *src
,char *dest1
,int cnum
,int ofun
,
2679 int count
,BOOL target_is_directory
)
2688 if (target_is_directory
) {
2689 char *p
= strrchr(src
,'/');
2698 if (!file_exist(src
,&st
)) return(False
);
2700 fnum1
= find_free_file();
2701 if (fnum1
<0) return(False
);
2702 open_file_shared(fnum1
,cnum
,src
,(DENY_NONE
<<4),
2703 1,0,&Access
,&action
);
2705 if (!Files
[fnum1
].open
) return(False
);
2707 if (!target_is_directory
&& count
)
2710 fnum2
= find_free_file();
2715 open_file_shared(fnum2
,cnum
,dest
,(DENY_NONE
<<4)|1,
2716 ofun
,st
.st_mode
,&Access
,&action
);
2718 if (!Files
[fnum2
].open
) {
2723 if ((ofun
&3) == 1) {
2724 lseek(Files
[fnum2
].fd_ptr
->fd
,0,SEEK_END
);
2728 ret
= transfer_file(Files
[fnum1
].fd_ptr
->fd
,Files
[fnum2
].fd_ptr
->fd
,st
.st_size
,NULL
,0,0);
2733 return(ret
== st
.st_size
);
2738 /****************************************************************************
2739 reply to a file copy.
2740 ****************************************************************************/
2741 int reply_copy(char *inbuf
,char *outbuf
)
2747 pstring mask
,newname
;
2750 int error
= ERRnoaccess
;
2753 int tid2
= SVAL(inbuf
,smb_vwv0
);
2754 int ofun
= SVAL(inbuf
,smb_vwv1
);
2755 int flags
= SVAL(inbuf
,smb_vwv2
);
2756 BOOL target_is_directory
=False
;
2758 *directory
= *mask
= 0;
2760 cnum
= SVAL(inbuf
,smb_tid
);
2762 strcpy(name
,smb_buf(inbuf
));
2763 strcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
2765 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
2768 /* can't currently handle inter share copies XXXX */
2769 DEBUG(3,("Rejecting inter-share copy\n"));
2770 return(ERROR(ERRSRV
,ERRinvdevice
));
2773 unix_convert(name
,cnum
,0);
2774 unix_convert(newname
,cnum
,0);
2776 target_is_directory
= directory_exist(newname
,NULL
);
2778 if ((flags
&1) && target_is_directory
) {
2779 return(ERROR(ERRDOS
,ERRbadfile
));
2782 if ((flags
&2) && !target_is_directory
) {
2783 return(ERROR(ERRDOS
,ERRbadpath
));
2786 if ((flags
&(1<<5)) && directory_exist(name
,NULL
)) {
2787 /* wants a tree copy! XXXX */
2788 DEBUG(3,("Rejecting tree copy\n"));
2789 return(ERROR(ERRSRV
,ERRerror
));
2792 p
= strrchr(name
,'/');
2794 strcpy(directory
,"./");
2798 strcpy(directory
,name
);
2802 if (is_mangled(mask
))
2803 check_mangled_stack(mask
);
2805 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
2808 strcat(directory
,"/");
2809 strcat(directory
,mask
);
2810 if (resolve_wildcards(directory
,newname
) &&
2811 copy_file(directory
,newname
,cnum
,ofun
,
2812 count
,target_is_directory
)) count
++;
2813 if (!count
) exists
= file_exist(directory
,NULL
);
2815 void *dirptr
= NULL
;
2819 if (check_name(directory
,cnum
))
2820 dirptr
= OpenDir(directory
);
2826 if (strequal(mask
,"????????.???"))
2829 while ((dname
= ReadDirName(dirptr
)))
2832 strcpy(fname
,dname
);
2834 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
2836 error
= ERRnoaccess
;
2837 sprintf(fname
,"%s/%s",directory
,dname
);
2838 strcpy(destname
,newname
);
2839 if (resolve_wildcards(fname
,destname
) &&
2840 copy_file(directory
,newname
,cnum
,ofun
,
2841 count
,target_is_directory
)) count
++;
2842 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
2850 return(ERROR(ERRDOS
,error
));
2852 return(UNIXERROR(ERRDOS
,error
));
2855 outsize
= set_message(outbuf
,1,0,True
);
2856 SSVAL(outbuf
,smb_vwv0
,count
);
2863 /****************************************************************************
2865 ****************************************************************************/
2866 int reply_setdir(char *inbuf
,char *outbuf
)
2873 cnum
= SVAL(inbuf
,smb_tid
);
2875 snum
= Connections
[cnum
].service
;
2876 if (!CAN_SETDIR(snum
))
2877 return(ERROR(ERRDOS
,ERRnoaccess
));
2879 strcpy(newdir
,smb_buf(inbuf
) + 1);
2882 if (strlen(newdir
) == 0)
2886 ok
= directory_exist(newdir
,NULL
);
2888 string_set(&Connections
[cnum
].connectpath
,newdir
);
2892 return(ERROR(ERRDOS
,ERRbadpath
));
2894 outsize
= set_message(outbuf
,0,0,True
);
2895 CVAL(outbuf
,smb_reh
) = CVAL(inbuf
,smb_reh
);
2897 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir
,cnum
));
2903 /****************************************************************************
2904 reply to a lockingX request
2905 ****************************************************************************/
2906 int reply_lockingX(char *inbuf
,char *outbuf
,int length
,int bufsize
)
2908 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
2909 uint16 locktype
= SVAL(inbuf
,smb_vwv3
);
2910 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
2911 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
2912 uint32 count
, offset
;
2917 uint32 ecode
=0, dummy2
;
2918 int eclass
=0, dummy1
;
2920 cnum
= SVAL(inbuf
,smb_tid
);
2922 CHECK_FNUM(fnum
,cnum
);
2925 data
= smb_buf(inbuf
);
2926 /* Data now points at the beginning of the list
2927 of smb_unlkrng structs */
2928 for(i
= 0; i
< (int)num_ulocks
; i
++) {
2929 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
2930 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
2931 if(!do_unlock(fnum
,cnum
,count
,offset
,&eclass
, &ecode
))
2932 return ERROR(eclass
,ecode
);
2935 /* Now do any requested locks */
2936 data
+= 10*num_ulocks
;
2937 /* Data now points at the beginning of the list
2938 of smb_lkrng structs */
2939 for(i
= 0; i
< (int)num_locks
; i
++) {
2940 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
2941 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
2942 if(!do_lock(fnum
,cnum
,count
,offset
, &eclass
, &ecode
))
2946 /* If any of the above locks failed, then we must unlock
2947 all of the previous locks (X/Open spec). */
2948 if(i
!= num_locks
&& num_locks
!= 0) {
2949 for(; i
>= 0; i
--) {
2950 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
2951 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
2952 do_unlock(fnum
,cnum
,count
,offset
,&dummy1
,&dummy2
);
2954 return ERROR(eclass
,ecode
);
2957 set_message(outbuf
,2,0,True
);
2959 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
2960 timestring(),fnum
,cnum
,locktype
,num_locks
,num_ulocks
));
2964 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2968 /****************************************************************************
2969 reply to a SMBreadbmpx (read block multiplex) request
2970 ****************************************************************************/
2971 int reply_readbmpx(char *inbuf
,char *outbuf
,int length
,int bufsize
)
2978 int outsize
, mincount
, maxcount
;
2983 /* this function doesn't seem to work - disable by default */
2985 return(ERROR(ERRSRV
,ERRuseSTD
));
2987 outsize
= set_message(outbuf
,8,0,True
);
2989 cnum
= SVAL(inbuf
,smb_tid
);
2990 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2992 CHECK_FNUM(fnum
,cnum
);
2996 startpos
= IVAL(inbuf
,smb_vwv1
);
2997 maxcount
= SVAL(inbuf
,smb_vwv3
);
2998 mincount
= SVAL(inbuf
,smb_vwv4
);
3000 data
= smb_buf(outbuf
);
3001 pad
= ((int)data
)%4;
3002 if (pad
) pad
= 4 - pad
;
3005 max_per_packet
= bufsize
-(outsize
+pad
);
3009 if (is_locked(fnum
,cnum
,maxcount
,startpos
))
3010 return(ERROR(ERRDOS
,ERRlock
));
3014 int N
= MIN(max_per_packet
,tcount
-total_read
);
3016 nread
= read_file(fnum
,data
,startpos
,N
);
3018 if (nread
<= 0) nread
= 0;
3021 tcount
= total_read
+ nread
;
3023 set_message(outbuf
,8,nread
,False
);
3024 SIVAL(outbuf
,smb_vwv0
,startpos
);
3025 SSVAL(outbuf
,smb_vwv2
,tcount
);
3026 SSVAL(outbuf
,smb_vwv6
,nread
);
3027 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
3029 send_smb(Client
,outbuf
);
3031 total_read
+= nread
;
3034 while (total_read
< tcount
);
3040 /****************************************************************************
3041 reply to a SMBwritebmpx (write block multiplex primary) request
3042 ****************************************************************************/
3043 int reply_writebmpx(char *inbuf
,char *outbuf
)
3045 int cnum
,numtowrite
,fnum
;
3049 int tcount
, write_through
, smb_doff
;
3052 cnum
= SVAL(inbuf
,smb_tid
);
3053 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3055 CHECK_FNUM(fnum
,cnum
);
3059 tcount
= SVAL(inbuf
,smb_vwv1
);
3060 startpos
= IVAL(inbuf
,smb_vwv3
);
3061 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
3062 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3063 smb_doff
= SVAL(inbuf
,smb_vwv11
);
3065 data
= smb_base(inbuf
) + smb_doff
;
3067 /* If this fails we need to send an SMBwriteC response,
3068 not an SMBwritebmpx - set this up now so we don't forget */
3069 CVAL(outbuf
,smb_com
) = SMBwritec
;
3071 if (is_locked(fnum
,cnum
,tcount
,startpos
))
3072 return(ERROR(ERRDOS
,ERRlock
));
3074 seek_file(fnum
,startpos
);
3075 nwritten
= write_file(fnum
,data
,numtowrite
);
3077 if(lp_syncalways(SNUM(cnum
)) || write_through
)
3080 if(nwritten
< numtowrite
)
3081 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3083 /* If the maximum to be written to this file
3084 is greater than what we just wrote then set
3085 up a secondary struct to be attached to this
3086 fd, we will use this to cache error messages etc. */
3087 if(tcount
> nwritten
)
3089 write_bmpx_struct
*wbms
;
3090 if(Files
[fnum
].wbmpx_ptr
!= NULL
)
3091 wbms
= Files
[fnum
].wbmpx_ptr
; /* Use an existing struct */
3093 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
3096 DEBUG(0,("Out of memory in reply_readmpx\n"));
3097 return(ERROR(ERRSRV
,ERRnoresource
));
3099 wbms
->wr_mode
= write_through
;
3100 wbms
->wr_discard
= False
; /* No errors yet */
3101 wbms
->wr_total_written
= nwritten
;
3102 wbms
->wr_errclass
= 0;
3104 Files
[fnum
].wbmpx_ptr
= wbms
;
3107 /* We are returning successfully, set the message type back to
3109 CVAL(outbuf
,smb_com
) = SMBwriteBmpx
;
3111 outsize
= set_message(outbuf
,1,0,True
);
3113 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
3115 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3116 timestring(),fnum
,cnum
,numtowrite
,nwritten
));
3118 if (write_through
&& tcount
==nwritten
) {
3119 /* we need to send both a primary and a secondary response */
3120 smb_setlen(outbuf
,outsize
- 4);
3121 send_smb(Client
,outbuf
);
3123 /* now the secondary */
3124 outsize
= set_message(outbuf
,1,0,True
);
3125 CVAL(outbuf
,smb_com
) = SMBwritec
;
3126 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3133 /****************************************************************************
3134 reply to a SMBwritebs (write block multiplex secondary) request
3135 ****************************************************************************/
3136 int reply_writebs(char *inbuf
,char *outbuf
)
3138 int cnum
,numtowrite
,fnum
;
3142 int tcount
, write_through
, smb_doff
;
3144 write_bmpx_struct
*wbms
;
3145 BOOL send_response
= False
;
3147 cnum
= SVAL(inbuf
,smb_tid
);
3148 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3149 CHECK_FNUM(fnum
,cnum
);
3152 tcount
= SVAL(inbuf
,smb_vwv1
);
3153 startpos
= IVAL(inbuf
,smb_vwv2
);
3154 numtowrite
= SVAL(inbuf
,smb_vwv6
);
3155 smb_doff
= SVAL(inbuf
,smb_vwv7
);
3157 data
= smb_base(inbuf
) + smb_doff
;
3159 /* We need to send an SMBwriteC response, not an SMBwritebs */
3160 CVAL(outbuf
,smb_com
) = SMBwritec
;
3162 /* This fd should have an auxiliary struct attached,
3163 check that it does */
3164 wbms
= Files
[fnum
].wbmpx_ptr
;
3165 if(!wbms
) return(-1);
3167 /* If write through is set we can return errors, else we must
3169 write_through
= wbms
->wr_mode
;
3171 /* Check for an earlier error */
3172 if(wbms
->wr_discard
)
3173 return -1; /* Just discard the packet */
3175 seek_file(fnum
,startpos
);
3176 nwritten
= write_file(fnum
,data
,numtowrite
);
3178 if(lp_syncalways(SNUM(cnum
)) || write_through
)
3181 if (nwritten
< numtowrite
)
3184 /* We are returning an error - we can delete the aux struct */
3185 if (wbms
) free((char *)wbms
);
3186 Files
[fnum
].wbmpx_ptr
= NULL
;
3187 return(ERROR(ERRHRD
,ERRdiskfull
));
3189 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
3192 /* Increment the total written, if this matches tcount
3193 we can discard the auxiliary struct (hurrah !) and return a writeC */
3194 wbms
->wr_total_written
+= nwritten
;
3195 if(wbms
->wr_total_written
>= tcount
)
3197 if (write_through
) {
3198 outsize
= set_message(outbuf
,1,0,True
);
3199 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
3200 send_response
= True
;
3204 Files
[fnum
].wbmpx_ptr
= NULL
;
3214 /****************************************************************************
3215 reply to a SMBsetattrE
3216 ****************************************************************************/
3217 int reply_setattrE(char *inbuf
,char *outbuf
)
3220 struct utimbuf unix_times
;
3223 outsize
= set_message(outbuf
,0,0,True
);
3225 cnum
= SVAL(inbuf
,smb_tid
);
3226 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3228 CHECK_FNUM(fnum
,cnum
);
3231 /* Convert the DOS times into unix times. Ignore create
3232 time as UNIX can't set this.
3234 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
3235 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
3237 /* Set the date on this file */
3238 if(sys_utime(Files
[fnum
].name
, &unix_times
))
3239 return(ERROR(ERRDOS
,ERRnoaccess
));
3241 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum
,cnum
));
3247 /****************************************************************************
3248 reply to a SMBgetattrE
3249 ****************************************************************************/
3250 int reply_getattrE(char *inbuf
,char *outbuf
)
3257 outsize
= set_message(outbuf
,11,0,True
);
3259 cnum
= SVAL(inbuf
,smb_tid
);
3260 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3262 CHECK_FNUM(fnum
,cnum
);
3265 /* Do an fstat on this file */
3266 if(fstat(Files
[fnum
].fd_ptr
->fd
, &sbuf
))
3267 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3269 mode
= dos_mode(cnum
,Files
[fnum
].name
,&sbuf
);
3271 /* Convert the times into dos times. Set create
3272 date to be last modify date as UNIX doesn't save
3274 put_dos_date2(outbuf
,smb_vwv0
,sbuf
.st_mtime
);
3275 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
3276 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
3279 SIVAL(outbuf
,smb_vwv6
,0);
3280 SIVAL(outbuf
,smb_vwv8
,0);
3284 SIVAL(outbuf
,smb_vwv6
,sbuf
.st_size
);
3285 SIVAL(outbuf
,smb_vwv8
,ROUNDUP(sbuf
.st_size
,1024));
3287 SSVAL(outbuf
,smb_vwv10
, mode
);
3289 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum
,cnum
));