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
31 /* look in server.c for some explanation of these variables */
33 extern int DEBUGLEVEL
;
34 extern int chain_size
;
36 extern int chain_fnum
;
37 extern char magic_char
;
38 extern connection_struct Connections
[];
39 extern files_struct Files
[];
40 extern BOOL case_sensitive
;
41 extern pstring sesssetup_user
;
44 /* this macro should always be used to extract an fnum (smb_fid) from
45 a packet to ensure chaining works correctly */
46 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
49 /****************************************************************************
50 reply to an special message
51 ****************************************************************************/
52 int reply_special(char *inbuf
,char *outbuf
)
55 int msg_type
= CVAL(inbuf
,0);
56 int msg_flags
= CVAL(inbuf
,1);
58 extern fstring remote_machine
;
59 extern fstring local_machine
;
68 case 0x81: /* session request */
69 CVAL(outbuf
,0) = 0x82;
71 if (name_len(inbuf
+4) > 50)
73 DEBUG(0,("Invalid name length in session request\n"));
76 name_extract(inbuf
,4,name1
);
77 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
78 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1
,name2
));
80 strcpy(remote_machine
,name2
);
81 trim_string(remote_machine
," "," ");
82 p
= strchr(remote_machine
,' ');
83 strlower(remote_machine
);
86 strcpy(local_machine
,name1
);
87 trim_string(local_machine
," "," ");
88 p
= strchr(local_machine
,' ');
89 strlower(local_machine
);
92 add_session_user(remote_machine
);
94 reload_services(True
);
98 case 0x85: /* session keepalive */
103 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type
,msg_flags
));
109 /*******************************************************************
110 work out what error to give to a failed connection
111 ********************************************************************/
112 static int connection_error(char *inbuf
,char *outbuf
,int connection_num
)
114 switch (connection_num
)
117 return(ERROR(ERRSRV
,ERRnoresource
));
119 return(ERROR(ERRSRV
,ERRbaduid
));
121 return(ERROR(ERRSRV
,ERRinvdevice
));
123 return(ERROR(ERRSRV
,ERRinvnetname
));
125 return(ERROR(ERRSRV
,ERRaccess
));
127 return(ERROR(ERRDOS
,ERRnoipc
));
129 return(ERROR(ERRSRV
,ERRinvnetname
));
131 return(ERROR(ERRSRV
,ERRbadpw
));
135 /****************************************************************************
137 ****************************************************************************/
138 int reply_tcon(char *inbuf
,char *outbuf
)
146 int uid
= SVAL(inbuf
,smb_uid
);
150 *service
= *user
= *password
= *dev
= 0;
152 vuid
= valid_uid(uid
);
154 parse_connect(inbuf
,service
,user
,password
,&pwlen
,dev
);
156 connection_num
= make_connection(service
,user
,password
,pwlen
,dev
,vuid
);
158 if (connection_num
< 0)
159 return(connection_error(inbuf
,outbuf
,connection_num
));
161 outsize
= set_message(outbuf
,2,0,True
);
162 SSVAL(outbuf
,smb_vwv0
,maxxmit
);
163 SSVAL(outbuf
,smb_vwv1
,connection_num
);
164 SSVAL(outbuf
,smb_tid
,connection_num
);
166 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service
,user
,connection_num
));
172 /****************************************************************************
173 reply to a tcon and X
174 ****************************************************************************/
175 int reply_tcon_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
183 int uid
= SVAL(inbuf
,smb_uid
);
185 int smb_com2
= SVAL(inbuf
,smb_vwv0
);
186 int smb_off2
= SVAL(inbuf
,smb_vwv1
);
187 int passlen
= SVAL(inbuf
,smb_vwv3
);
189 *service
= *user
= *password
= *devicename
= 0;
191 /* we might have to close an old one */
192 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) != 0)
193 close_cnum(SVAL(inbuf
,smb_tid
),uid
);
195 vuid
= valid_uid(uid
);
200 memcpy(password
,smb_buf(inbuf
),passlen
);
202 path
= smb_buf(inbuf
) + passlen
;
203 DEBUG(4,("parsing net-path %s, passlen=%d\n",path
,passlen
));
204 strcpy(service
,path
+2);
205 p
= strchr(service
,'\\');
207 return(ERROR(ERRSRV
,ERRinvnetname
));
210 p
= strchr(service
,'%');
216 StrnCpy(devicename
,path
+ strlen(path
) + 1,6);
217 DEBUG(4,("Got device type %s\n",devicename
));
220 connection_num
= make_connection(service
,user
,password
,passlen
,devicename
,vuid
);
222 if (connection_num
< 0)
223 return(connection_error(inbuf
,outbuf
,connection_num
));
225 outsize
= set_message(outbuf
,2,strlen(devicename
)+1,True
);
227 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service
,user
,connection_num
));
229 /* set the incoming and outgoing tid to the just created one */
230 SSVAL(inbuf
,smb_tid
,connection_num
);
231 SSVAL(outbuf
,smb_tid
,connection_num
);
233 CVAL(outbuf
,smb_vwv0
) = smb_com2
;
234 SSVAL(outbuf
,smb_vwv1
,(chain_size
+ outsize
)-4);
236 strcpy(smb_buf(outbuf
),devicename
);
238 if (smb_com2
!= 0xFF)
239 outsize
+= chain_reply(smb_com2
,inbuf
,inbuf
+smb_off2
+4,
240 outbuf
,outbuf
+outsize
,
247 /****************************************************************************
248 reply to an unknown type
249 ****************************************************************************/
250 int reply_unknown(char *inbuf
,char *outbuf
)
254 cnum
= SVAL(inbuf
,smb_tid
);
255 type
= CVAL(inbuf
,smb_com
);
257 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
262 return(ERROR(ERRSRV
,ERRunknownsmb
));
266 /****************************************************************************
268 ****************************************************************************/
269 int reply_ioctl(char *inbuf
,char *outbuf
)
271 DEBUG(3,("ignoring ioctl\n"));
273 return(ERROR(ERRSRV
,ERRnosupport
));
277 /****************************************************************************
278 reply to a session setup command
279 ****************************************************************************/
280 int reply_sesssetup_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
293 int smb_ntpasslen
= 0;
294 pstring smb_ntpasswd
;
295 BOOL valid_nt_password
= False
;
301 sess_uid
= SVAL(inbuf
,smb_uid
);
302 smb_com2
= CVAL(inbuf
,smb_vwv0
);
303 smb_off2
= SVAL(inbuf
,smb_vwv1
);
304 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
305 smb_mpxmax
= SVAL(inbuf
,smb_vwv3
);
306 smb_vc_num
= SVAL(inbuf
,smb_vwv4
);
307 smb_sesskey
= IVAL(inbuf
,smb_vwv5
);
309 if (Protocol
< PROTOCOL_NT1
) {
310 smb_apasslen
= SVAL(inbuf
,smb_vwv7
);
311 memcpy(smb_apasswd
,smb_buf(inbuf
),smb_apasslen
);
312 StrnCpy(user
,smb_buf(inbuf
)+smb_apasslen
,sizeof(user
)-1);
314 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
315 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
316 BOOL doencrypt
= SMBENCRYPT();
317 char *p
= smb_buf(inbuf
);
318 if (passlen1
> 256) passlen1
= 0;
319 if (passlen2
> 256) passlen2
= 0; /* I don't know why NT gives weird
322 /* Save the lanman2 password and the NT md4 password. */
323 smb_apasslen
= passlen1
;
324 memcpy(smb_apasswd
,p
,smb_apasslen
);
325 smb_ntpasslen
= passlen2
;
326 memcpy(smb_ntpasswd
,p
+passlen1
,smb_ntpasslen
);
329 if (passlen1
> passlen2
) {
330 smb_apasslen
= passlen1
;
331 StrnCpy(smb_apasswd
,p
,smb_apasslen
);
333 smb_apasslen
= passlen2
;
334 StrnCpy(smb_apasswd
,p
+ passlen1
,smb_apasslen
);
338 /* apparently NT sometimes sets passlen2 to 1 when it means 0. This
339 tries to work around that problem */
342 p
+= passlen1
+ passlen2
;
343 strcpy(user
,p
); p
= skip_string(p
,1);
344 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
345 p
,skip_string(p
,1),skip_string(p
,2)));
349 DEBUG(3,("sesssetupX:name=[%s]\n",user
));
352 strcpy(user
,lp_guestaccount(-1));
356 strcpy(sesssetup_user
,user
);
358 reload_services(True
);
360 add_session_user(user
);
363 if (!(lp_security() == SEC_SERVER
&& server_validate(inbuf
)) &&
364 !check_hosts_equiv(user
))
367 if (strequal(user
,lp_guestaccount(-1)) && (*smb_apasswd
== 0))
370 /* now check if it's a valid username/password */
371 /* If an NT password was supplied try and validate with that
372 first. This is superior as the passwords are mixed case 128 length unicode */
373 if(smb_ntpasslen
&& !guest
)
375 if(!password_ok(user
,smb_ntpasswd
,smb_ntpasslen
,NULL
,True
))
376 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
378 valid_nt_password
= True
;
380 if (!valid_nt_password
&& !guest
&& !password_ok(user
,smb_apasswd
,smb_apasslen
,NULL
,False
))
382 if (lp_security() >= SEC_USER
) {
383 #if (GUEST_SESSSETUP == 0)
384 return(ERROR(ERRSRV
,ERRbadpw
));
386 #if (GUEST_SESSSETUP == 1)
387 if (Get_Pwnam(user
,True
))
388 return(ERROR(ERRSRV
,ERRbadpw
));
391 if (*smb_apasswd
|| !Get_Pwnam(user
,True
))
392 strcpy(user
,lp_guestaccount(-1));
393 DEBUG(3,("Registered username %s for guest access\n",user
));
398 if (!Get_Pwnam(user
,True
)) {
399 DEBUG(3,("No such user %s - using guest account\n",user
));
400 strcpy(user
,lp_guestaccount(-1));
404 if (!strequal(user
,lp_guestaccount(-1)) &&
405 lp_servicenumber(user
) < 0)
407 int homes
= lp_servicenumber(HOMES_NAME
);
408 char *home
= get_home_dir(user
);
409 if (homes
>= 0 && home
)
410 lp_add_home(user
,homes
,home
);
414 /* it's ok - setup a reply */
415 if (Protocol
< PROTOCOL_NT1
) {
416 outsize
= set_message(outbuf
,3,0,True
);
419 outsize
= set_message(outbuf
,3,3,True
);
421 strcpy(p
,"Unix"); p
= skip_string(p
,1);
422 strcpy(p
,"Samba "); strcat(p
,VERSION
); p
= skip_string(p
,1);
423 strcpy(p
,my_workgroup()); p
= skip_string(p
,1);
424 outsize
= set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
425 /* perhaps grab OS version here?? */
428 /* Set the correct uid in the outgoing and incoming packets
429 We will use this on future requests to determine which
430 user we should become.
433 struct passwd
*pw
= Get_Pwnam(user
,False
);
435 DEBUG(1,("Username %s is invalid on this system\n",user
));
436 return(ERROR(ERRSRV
,ERRbadpw
));
439 SSVAL(outbuf
,smb_uid
,(uint16
)pw
->pw_uid
);
440 SSVAL(inbuf
,smb_uid
,(uint16
)pw
->pw_uid
);
443 CVAL(outbuf
,smb_vwv0
) = smb_com2
;
444 SSVAL(outbuf
,smb_vwv1
,(chain_size
+outsize
)-4);
447 SSVAL(outbuf
,smb_vwv2
,1);
449 /* register the name and uid as being validated, so further connections
450 to a uid can get through without a password, on the same VC */
451 register_uid(SVAL(inbuf
,smb_uid
),gid
,user
,guest
);
453 maxxmit
= MIN(maxxmit
,smb_bufsize
);
455 if (smb_com2
!= 0xFF)
456 outsize
+= chain_reply(smb_com2
,inbuf
,inbuf
+smb_off2
+4,
457 outbuf
,outbuf
+outsize
,
464 /****************************************************************************
466 ****************************************************************************/
467 int reply_chkpth(char *inbuf
,char *outbuf
)
474 cnum
= SVAL(inbuf
,smb_tid
);
476 strcpy(name
,smb_buf(inbuf
) + 1);
477 unix_convert(name
,cnum
);
479 mode
= SVAL(inbuf
,smb_vwv0
);
481 if (check_name(name
,cnum
))
482 ok
= directory_exist(name
,NULL
);
485 return(ERROR(ERRDOS
,ERRbadpath
));
487 outsize
= set_message(outbuf
,0,0,True
);
489 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name
,cnum
,mode
));
495 /****************************************************************************
497 ****************************************************************************/
498 int reply_getatr(char *inbuf
,char *outbuf
)
509 cnum
= SVAL(inbuf
,smb_tid
);
511 strcpy(fname
,smb_buf(inbuf
) + 1);
512 unix_convert(fname
,cnum
);
514 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
515 under WfWg - weird! */
518 mode
= aHIDDEN
| aDIR
;
519 if (!CAN_WRITE(cnum
)) mode
|= aRONLY
;
525 if (check_name(fname
,cnum
))
527 if (sys_stat(fname
,&sbuf
) == 0)
529 mode
= dos_mode(cnum
,fname
,&sbuf
);
531 mtime
= sbuf
.st_mtime
;
537 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
541 return(UNIXERROR(ERRDOS
,ERRbadfile
));
543 outsize
= set_message(outbuf
,10,0,True
);
545 SSVAL(outbuf
,smb_vwv0
,mode
);
546 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
547 SIVAL(outbuf
,smb_vwv3
,size
);
549 if (Protocol
>= PROTOCOL_NT1
) {
550 char *p
= strrchr(fname
,'/');
551 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
554 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
557 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname
,mode
,size
));
563 /****************************************************************************
565 ****************************************************************************/
566 int reply_setatr(char *inbuf
,char *outbuf
)
575 cnum
= SVAL(inbuf
,smb_tid
);
577 strcpy(fname
,smb_buf(inbuf
) + 1);
578 unix_convert(fname
,cnum
);
580 mode
= SVAL(inbuf
,smb_vwv0
);
581 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
583 if (directory_exist(fname
,NULL
))
585 if (check_name(fname
,cnum
))
586 ok
= (dos_chmod(cnum
,fname
,mode
,NULL
) == 0);
588 ok
= set_filetime(fname
,mtime
);
591 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
593 outsize
= set_message(outbuf
,0,0,True
);
595 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname
,mode
));
601 /****************************************************************************
603 ****************************************************************************/
604 int reply_dskattr(char *inbuf
,char *outbuf
)
608 int dfree
,dsize
,bsize
;
610 cnum
= SVAL(inbuf
,smb_tid
);
612 sys_disk_free(".",&bsize
,&dfree
,&dsize
);
614 outsize
= set_message(outbuf
,5,0,True
);
616 SSVAL(outbuf
,smb_vwv0
,dsize
);
617 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
618 SSVAL(outbuf
,smb_vwv2
,512);
619 SSVAL(outbuf
,smb_vwv3
,dfree
);
621 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum
,dfree
));
627 /****************************************************************************
629 Can be called from SMBsearch, SMBffirst or SMBfunique.
630 ****************************************************************************/
631 int reply_search(char *inbuf
,char *outbuf
)
642 BOOL finished
= False
;
651 BOOL check_descend
= False
;
652 BOOL expect_close
= False
;
653 BOOL can_open
= True
;
655 *mask
= *directory
= *fname
= 0;
657 /* If we were called as SMBffirst then we must expect close. */
658 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
661 cnum
= SVAL(inbuf
,smb_tid
);
663 outsize
= set_message(outbuf
,1,3,True
);
664 maxentries
= SVAL(inbuf
,smb_vwv0
);
665 dirtype
= SVAL(inbuf
,smb_vwv1
);
666 path
= smb_buf(inbuf
) + 1;
667 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
670 /* dirtype &= ~aDIR; */
672 DEBUG(5,("path=%s status_len=%d\n",path
,status_len
));
679 strcpy(directory
,smb_buf(inbuf
)+1);
680 strcpy(dir2
,smb_buf(inbuf
)+1);
681 unix_convert(directory
,cnum
);
684 if (!check_name(directory
,cnum
))
687 p
= strrchr(dir2
,'/');
689 {strcpy(mask
,dir2
);*dir2
= 0;}
691 {*p
= 0;strcpy(mask
,p
+1);}
693 p
= strrchr(directory
,'/');
699 if (strlen(directory
) == 0)
700 strcpy(directory
,"./");
702 CVAL(status
,0) = dirtype
;
706 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
707 memcpy(mask
,status
+1,11);
709 dirtype
= CVAL(status
,0) & 0x1F;
710 Connections
[cnum
].dirptr
= dptr_fetch(status
+12,&dptr_num
);
711 if (!Connections
[cnum
].dirptr
)
713 string_set(&Connections
[cnum
].dirpath
,dptr_path(dptr_num
));
718 /* turn strings of spaces into a . */
720 trim_string(mask
,NULL
," ");
721 if ((p
= strrchr(mask
,' ')))
726 trim_string(mask
,NULL
," ");
733 for (p
=mask
; *p
; p
++)
735 if (*p
!= '?' && *p
!= '*' && !isdoschar(*p
))
737 DEBUG(5,("Invalid char [%c] in search mask?\n",*p
));
743 if (!strchr(mask
,'.') && strlen(mask
)>8)
746 strcpy(tmp
,&mask
[8]);
752 DEBUG(5,("mask=%s directory=%s\n",mask
,directory
));
756 p
= smb_buf(outbuf
) + 3;
762 dptr_num
= dptr_create(cnum
,directory
,expect_close
,SVAL(inbuf
,smb_pid
));
764 return(ERROR(ERRDOS
,ERRnofids
));
767 DEBUG(4,("dptr_num is %d\n",dptr_num
));
771 if ((dirtype
&0x1F) == aVOLID
)
774 make_dir_struct(p
,"???????????",volume_label(SNUM(cnum
)),0,aVOLID
,0);
775 dptr_fill(p
+12,dptr_num
);
776 if (dptr_zero(p
+12) && (status_len
==0))
780 p
+= DIR_STRUCT_SIZE
;
784 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections
[cnum
].dirpath
,lp_dontdescend(SNUM(cnum
))));
785 if (in_list(Connections
[cnum
].dirpath
,
786 lp_dontdescend(SNUM(cnum
)),True
))
787 check_descend
= True
;
789 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
792 !get_dir_entry(cnum
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
796 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
797 dptr_fill(p
+12,dptr_num
);
800 p
+= DIR_STRUCT_SIZE
;
809 if (numentries
== 0 || !ok
)
811 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
812 SSVAL(outbuf
,smb_err
,ERRnofiles
);
815 /* If we were called as SMBffirst with smb_search_id == NULL
816 and no entries were found then return error and close dirptr
819 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
821 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
822 SSVAL(outbuf
,smb_err
,ERRnofiles
);
823 /* Also close the dptr - we know it's gone */
824 dptr_close(dptr_num
);
827 /* If we were called as SMBfunique, then we can close the dirptr now ! */
828 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
829 dptr_close(dptr_num
);
831 SSVAL(outbuf
,smb_vwv0
,numentries
);
832 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
833 CVAL(smb_buf(outbuf
),0) = 5;
834 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
836 if (Protocol
>= PROTOCOL_NT1
) {
837 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
838 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
841 outsize
+= DIR_STRUCT_SIZE
*numentries
;
842 smb_setlen(outbuf
,outsize
- 4);
844 if ((! *directory
) && dptr_path(dptr_num
))
845 sprintf(directory
,"(%s)",dptr_path(dptr_num
));
847 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
849 smb_fn_name(CVAL(inbuf
,smb_com
)),
850 mask
,directory
,cnum
,dirtype
,numentries
,maxentries
));
856 /****************************************************************************
857 reply to a fclose (stop directory search)
858 ****************************************************************************/
859 int reply_fclose(char *inbuf
,char *outbuf
)
868 cnum
= SVAL(inbuf
,smb_tid
);
870 outsize
= set_message(outbuf
,1,0,True
);
871 path
= smb_buf(inbuf
) + 1;
872 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
876 return(ERROR(ERRSRV
,ERRsrverror
));
878 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
880 if(dptr_fetch(status
+12,&dptr_num
)) {
881 /* Close the dptr - we know it's gone */
882 dptr_close(dptr_num
);
885 SSVAL(outbuf
,smb_vwv0
,0);
887 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum
));
893 /****************************************************************************
895 ****************************************************************************/
896 int reply_open(char *inbuf
,char *outbuf
)
910 cnum
= SVAL(inbuf
,smb_tid
);
912 share_mode
= SVAL(inbuf
,smb_vwv0
);
914 strcpy(fname
,smb_buf(inbuf
)+1);
915 unix_convert(fname
,cnum
);
917 fnum
= find_free_file();
919 return(ERROR(ERRSRV
,ERRnofids
));
921 if (!check_name(fname
,cnum
))
922 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
924 unixmode
= unix_mode(cnum
,aARCH
);
926 open_file_shared(fnum
,cnum
,fname
,share_mode
,3,unixmode
,&rmode
,NULL
);
928 if (!Files
[fnum
].open
)
929 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
931 if (fstat(Files
[fnum
].fd
,&sbuf
) != 0) {
933 return(ERROR(ERRDOS
,ERRnoaccess
));
937 fmode
= dos_mode(cnum
,fname
,&sbuf
);
938 mtime
= sbuf
.st_mtime
;
941 DEBUG(3,("attempt to open a directory %s\n",fname
));
943 return(ERROR(ERRDOS
,ERRnoaccess
));
946 outsize
= set_message(outbuf
,7,0,True
);
947 SSVAL(outbuf
,smb_vwv0
,fnum
);
948 SSVAL(outbuf
,smb_vwv1
,fmode
);
949 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
950 SIVAL(outbuf
,smb_vwv4
,size
);
951 SSVAL(outbuf
,smb_vwv6
,rmode
);
957 /****************************************************************************
958 reply to an open and X
959 ****************************************************************************/
960 int reply_open_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
963 int cnum
= SVAL(inbuf
,smb_tid
);
967 int smb_com2
= CVAL(inbuf
,smb_vwv0
);
968 int smb_off2
= SVAL(inbuf
,smb_vwv1
);
969 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
970 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
972 int open_flags
= SVAL(inbuf
,smb_vwv2
);
973 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
974 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
976 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
978 int size
=0,fmode
=0,mtime
=0,rmode
=0;
982 /* XXXX we need to handle passed times, sattr and flags */
984 strcpy(fname
,smb_buf(inbuf
));
985 unix_convert(fname
,cnum
);
987 /* now add create and trunc bits */
990 if ((smb_ofun
& 0x3) == 2)
993 fnum
= find_free_file();
995 return(ERROR(ERRSRV
,ERRnofids
));
997 if (!check_name(fname
,cnum
))
998 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1000 unixmode
= unix_mode(cnum
,smb_attr
| aARCH
);
1002 open_file_shared(fnum
,cnum
,fname
,smb_mode
,smb_ofun
,unixmode
,
1003 &rmode
,&smb_action
);
1005 if (!Files
[fnum
].open
)
1006 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1008 if (fstat(Files
[fnum
].fd
,&sbuf
) != 0) {
1010 return(ERROR(ERRDOS
,ERRnoaccess
));
1013 size
= sbuf
.st_size
;
1014 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1015 mtime
= sbuf
.st_mtime
;
1018 return(ERROR(ERRDOS
,ERRnoaccess
));
1021 outsize
= set_message(outbuf
,15,0,True
);
1022 CVAL(outbuf
,smb_vwv0
) = smb_com2
;
1023 SSVAL(outbuf
,smb_vwv1
,(chain_size
+outsize
)-4);
1024 SSVAL(outbuf
,smb_vwv2
,fnum
);
1025 SSVAL(outbuf
,smb_vwv3
,fmode
);
1026 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1027 SIVAL(outbuf
,smb_vwv6
,size
);
1028 SSVAL(outbuf
,smb_vwv8
,rmode
);
1029 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1033 if (smb_com2
!= 0xFF)
1034 outsize
+= chain_reply(smb_com2
,inbuf
,inbuf
+smb_off2
+4,
1035 outbuf
,outbuf
+outsize
,
1044 /****************************************************************************
1045 reply to a SMBulogoffX
1046 ****************************************************************************/
1047 int reply_ulogoffX(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1050 int smb_com2
= CVAL(inbuf
,smb_vwv0
);
1051 int smb_off2
= SVAL(inbuf
,smb_vwv1
);
1052 int uid
= SVAL(inbuf
,smb_uid
);
1054 invalidate_uid(uid
);
1056 outsize
= set_message(outbuf
,2,0,True
);
1057 CVAL(outbuf
,smb_vwv0
) = smb_com2
;
1058 SSVAL(outbuf
,smb_vwv1
,(chain_size
+outsize
)-4);
1060 DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid
));
1062 if (smb_com2
!= 0xFF)
1063 outsize
+= chain_reply(smb_com2
,inbuf
,inbuf
+smb_off2
+4,
1064 outbuf
,outbuf
+outsize
,
1072 /****************************************************************************
1074 ****************************************************************************/
1075 int reply_mknew(char *inbuf
,char *outbuf
)
1084 com
= SVAL(inbuf
,smb_com
);
1085 cnum
= SVAL(inbuf
,smb_tid
);
1087 createmode
= SVAL(inbuf
,smb_vwv0
);
1088 strcpy(fname
,smb_buf(inbuf
)+1);
1089 unix_convert(fname
,cnum
);
1091 if (createmode
& aVOLID
)
1093 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1096 unixmode
= unix_mode(cnum
,createmode
);
1098 if (com
== SMBmknew
&& file_exist(fname
,NULL
))
1099 return(ERROR(ERRDOS
,ERRfilexists
));
1101 fnum
= find_free_file();
1103 return(ERROR(ERRSRV
,ERRnofids
));
1105 if (!check_name(fname
,cnum
))
1106 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1108 open_file(fnum
,cnum
,fname
,O_RDWR
| O_CREAT
| O_TRUNC
,unixmode
);
1110 if (!Files
[fnum
].open
)
1111 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1113 outsize
= set_message(outbuf
,1,0,True
);
1114 SSVAL(outbuf
,smb_vwv0
,fnum
);
1116 DEBUG(2,("new file %s\n",fname
));
1117 DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname
,Files
[fnum
].fd
,fnum
,cnum
,createmode
,unixmode
));
1123 /****************************************************************************
1124 reply to a create temporary file
1125 ****************************************************************************/
1126 int reply_ctemp(char *inbuf
,char *outbuf
)
1136 cnum
= SVAL(inbuf
,smb_tid
);
1137 createmode
= SVAL(inbuf
,smb_vwv0
);
1138 sprintf(fname
,"%s/TMXXXXXX",smb_buf(inbuf
)+1);
1139 unix_convert(fname
,cnum
);
1141 unixmode
= unix_mode(cnum
,createmode
);
1143 fnum
= find_free_file();
1145 return(ERROR(ERRSRV
,ERRnofids
));
1147 if (!check_name(fname
,cnum
))
1148 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1150 strcpy(fname2
,(char *)mktemp(fname
));
1152 open_file(fnum
,cnum
,fname2
,O_RDWR
| O_CREAT
| O_TRUNC
,unixmode
);
1154 if (!Files
[fnum
].open
)
1155 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1157 outsize
= set_message(outbuf
,1,2 + strlen(fname2
),True
);
1158 SSVAL(outbuf
,smb_vwv0
,fnum
);
1159 CVAL(smb_buf(outbuf
),0) = 4;
1160 strcpy(smb_buf(outbuf
) + 1,fname2
);
1162 DEBUG(2,("created temp file %s\n",fname2
));
1163 DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2
,Files
[fnum
].fd
,fnum
,cnum
,createmode
,unixmode
));
1169 /*******************************************************************
1170 check if a user is allowed to delete a file
1171 ********************************************************************/
1172 static BOOL
can_delete(char *fname
,int cnum
,int dirtype
)
1177 if (!CAN_WRITE(cnum
)) return(False
);
1179 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
1180 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1181 if (fmode
& aDIR
) return(False
);
1182 if (fmode
& aRONLY
) return(False
);
1183 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1185 if (!check_file_sharing(cnum
,fname
)) return(False
);
1189 /****************************************************************************
1191 ****************************************************************************/
1192 int reply_unlink(char *inbuf
,char *outbuf
)
1202 int error
= ERRnoaccess
;
1206 *directory
= *mask
= 0;
1208 cnum
= SVAL(inbuf
,smb_tid
);
1209 dirtype
= SVAL(inbuf
,smb_vwv0
);
1211 strcpy(name
,smb_buf(inbuf
) + 1);
1213 DEBUG(3,("reply_unlink : %s\n",name
));
1215 unix_convert(name
,cnum
);
1217 p
= strrchr(name
,'/');
1219 strcpy(directory
,"./");
1223 strcpy(directory
,name
);
1227 if (is_mangled(mask
))
1228 check_mangled_stack(mask
);
1230 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
1233 strcat(directory
,"/");
1234 strcat(directory
,mask
);
1235 if (can_delete(directory
,cnum
,dirtype
) && !sys_unlink(directory
)) count
++;
1236 if (!count
) exists
= file_exist(directory
,NULL
);
1238 void *dirptr
= NULL
;
1241 if (check_name(directory
,cnum
))
1242 dirptr
= OpenDir(directory
);
1248 if (strequal(mask
,"????????.???"))
1251 while ((dname
= ReadDirName(dirptr
)))
1254 strcpy(fname
,dname
);
1256 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
1258 error
= ERRnoaccess
;
1259 sprintf(fname
,"%s/%s",directory
,dname
);
1260 if (!can_delete(fname
,cnum
,dirtype
)) continue;
1261 if (!sys_unlink(fname
)) count
++;
1262 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname
));
1270 return(ERROR(ERRDOS
,error
));
1272 return(UNIXERROR(ERRDOS
,error
));
1275 outsize
= set_message(outbuf
,0,0,True
);
1281 /****************************************************************************
1282 reply to a readbraw (core+ protocol)
1283 ****************************************************************************/
1284 int reply_readbraw(char *inbuf
, char *outbuf
)
1286 int cnum
,maxcount
,mincount
,fnum
;
1289 char *header
= outbuf
;
1294 cnum
= SVAL(inbuf
,smb_tid
);
1295 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1297 startpos
= IVAL(inbuf
,smb_vwv1
);
1298 maxcount
= SVAL(inbuf
,smb_vwv3
);
1299 mincount
= SVAL(inbuf
,smb_vwv4
);
1301 /* ensure we don't overrun the packet size */
1302 maxcount
= MIN(65535,maxcount
);
1303 maxcount
= MAX(mincount
,maxcount
);
1305 if (!FNUM_OK(fnum
,cnum
) || !Files
[fnum
].can_read
)
1307 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum
));
1308 _smb_setlen(header
,0);
1309 transfer_file(0,Client
,0,header
,4,0);
1314 fd
= Files
[fnum
].fd
;
1315 fname
= Files
[fnum
].name
;
1319 if (!is_locked(fnum
,cnum
,maxcount
,startpos
))
1321 int size
= Files
[fnum
].size
;
1322 int sizeneeded
= startpos
+ maxcount
;
1324 if (size
< sizeneeded
) {
1326 if (fstat(Files
[fnum
].fd
,&st
) == 0)
1328 if (!Files
[fnum
].can_write
)
1329 Files
[fnum
].size
= size
;
1332 nread
= MIN(maxcount
,size
- startpos
);
1335 if (nread
< mincount
)
1338 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1341 maxcount
,mincount
,nread
));
1346 _smb_setlen(header
,nread
);
1348 if (!Files
[fnum
].can_write
)
1349 predict
= read_predict(fd
,startpos
,header
+4,NULL
,nread
);
1351 if ((nread
-predict
) > 0)
1352 seek_file(fnum
,startpos
+ predict
);
1354 ret
= transfer_file(fd
,Client
,nread
-predict
,header
,4+predict
,
1359 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1360 fname
,startpos
,nread
,ret
));
1363 ret
= read_file(fnum
,header
+4,startpos
,nread
,nread
,-1,False
);
1364 if (ret
< mincount
) ret
= 0;
1366 _smb_setlen(header
,ret
);
1367 transfer_file(0,Client
,0,header
,4+ret
,0);
1370 DEBUG(5,("readbraw finished\n"));
1375 /****************************************************************************
1376 reply to a lockread (core+ protocol)
1377 ****************************************************************************/
1378 int reply_lockread(char *inbuf
,char *outbuf
)
1384 uint32 startpos
, numtoread
;
1388 cnum
= SVAL(inbuf
,smb_tid
);
1389 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1391 CHECK_FNUM(fnum
,cnum
);
1395 numtoread
= SVAL(inbuf
,smb_vwv1
);
1396 startpos
= IVAL(inbuf
,smb_vwv2
);
1398 outsize
= set_message(outbuf
,5,3,True
);
1399 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1400 data
= smb_buf(outbuf
) + 3;
1402 if(!do_lock( fnum
, cnum
, numtoread
, startpos
, &eclass
, &ecode
))
1403 return (ERROR(eclass
,ecode
));
1405 nread
= read_file(fnum
,data
,startpos
,numtoread
,numtoread
,-1,False
);
1408 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1411 SSVAL(outbuf
,smb_vwv0
,nread
);
1412 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1413 SSVAL(smb_buf(outbuf
),1,nread
);
1415 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum
,cnum
,numtoread
,nread
));
1421 /****************************************************************************
1423 ****************************************************************************/
1424 int reply_read(char *inbuf
,char *outbuf
)
1426 int cnum
,numtoread
,fnum
;
1432 cnum
= SVAL(inbuf
,smb_tid
);
1433 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1435 CHECK_FNUM(fnum
,cnum
);
1439 numtoread
= SVAL(inbuf
,smb_vwv1
);
1440 startpos
= IVAL(inbuf
,smb_vwv2
);
1442 outsize
= set_message(outbuf
,5,3,True
);
1443 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1444 data
= smb_buf(outbuf
) + 3;
1446 if (is_locked(fnum
,cnum
,numtoread
,startpos
))
1447 return(ERROR(ERRDOS
,ERRlock
));
1450 nread
= read_file(fnum
,data
,startpos
,numtoread
,numtoread
,-1,False
);
1453 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1456 SSVAL(outbuf
,smb_vwv0
,nread
);
1457 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1458 CVAL(smb_buf(outbuf
),0) = 1;
1459 SSVAL(smb_buf(outbuf
),1,nread
);
1461 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum
,cnum
,numtoread
,nread
));
1467 /****************************************************************************
1468 reply to a read and X
1469 ****************************************************************************/
1470 int reply_read_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1472 int smb_com2
= CVAL(inbuf
,smb_vwv0
);
1473 int smb_off2
= SVAL(inbuf
,smb_vwv1
);
1474 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
1475 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
1476 int smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
1477 int smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
1484 cnum
= SVAL(inbuf
,smb_tid
);
1486 CHECK_FNUM(fnum
,cnum
);
1490 outsize
= set_message(outbuf
,12,0,True
);
1491 data
= smb_buf(outbuf
);
1493 if (is_locked(fnum
,cnum
,smb_maxcnt
,smb_offs
))
1494 return(ERROR(ERRDOS
,ERRlock
));
1495 nread
= read_file(fnum
,data
,smb_offs
,smb_maxcnt
,smb_maxcnt
,-1,False
);
1499 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1502 CVAL(outbuf
,smb_vwv0
) = smb_com2
;
1503 SSVAL(outbuf
,smb_vwv1
,(outsize
+chain_size
)-4);
1504 SSVAL(outbuf
,smb_vwv5
,nread
);
1505 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
) + chain_size
);
1506 SSVAL(smb_buf(outbuf
),-2,nread
);
1508 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d com2=%d off2=%d\n",
1509 timestring(),fnum
,cnum
,
1510 smb_mincnt
,smb_maxcnt
,nread
,smb_com2
,smb_off2
));
1514 if (smb_com2
!= 0xFF)
1515 outsize
+= chain_reply(smb_com2
,inbuf
,inbuf
+smb_off2
+4,
1516 outbuf
,outbuf
+outsize
,
1525 /****************************************************************************
1526 reply to a writebraw (core+ or LANMAN1.0 protocol)
1527 ****************************************************************************/
1528 int reply_writebraw(char *inbuf
,char *outbuf
)
1531 int total_written
=0;
1540 cnum
= SVAL(inbuf
,smb_tid
);
1541 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1543 CHECK_FNUM(fnum
,cnum
);
1547 tcount
= IVAL(inbuf
,smb_vwv1
);
1548 startpos
= IVAL(inbuf
,smb_vwv3
);
1549 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
1551 /* We have to deal with slightly different formats depending
1552 on whether we are using the core+ or lanman1.0 protocol */
1553 if(Protocol
<= PROTOCOL_COREPLUS
) {
1554 numtowrite
= SVAL(smb_buf(inbuf
),-2);
1555 data
= smb_buf(inbuf
);
1557 numtowrite
= SVAL(inbuf
,smb_vwv10
);
1558 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
1561 /* force the error type */
1562 CVAL(inbuf
,smb_com
) = SMBwritec
;
1563 CVAL(outbuf
,smb_com
) = SMBwritec
;
1565 if (is_locked(fnum
,cnum
,tcount
,startpos
))
1566 return(ERROR(ERRDOS
,ERRlock
));
1568 if (seek_file(fnum
,startpos
) != startpos
)
1569 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos
));
1572 nwritten
= write_file(fnum
,data
,numtowrite
);
1574 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1575 timestring(),fnum
,cnum
,startpos
,numtowrite
,nwritten
,write_through
));
1577 if (nwritten
< numtowrite
)
1578 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
1580 total_written
= nwritten
;
1582 /* Return a message to the redirector to tell it
1583 to send more bytes */
1584 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
1585 SSVALS(outbuf
,smb_vwv0
,-1);
1586 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
1587 send_smb(Client
,outbuf
);
1589 /* Now read the raw data into the buffer and write it */
1590 if(read_smb_length(Client
,inbuf
,0) == -1) {
1591 exit_server("secondary writebraw failed");
1594 /* Even though this is not an smb message, smb_len
1595 returns the generic length of an smb message */
1596 numtowrite
= smb_len(inbuf
);
1598 if (tcount
> nwritten
+numtowrite
) {
1599 DEBUG(3,("Client overestimated the write %d %d %d\n",
1600 tcount
,nwritten
,numtowrite
));
1603 nwritten
= transfer_file(Client
,Files
[fnum
].fd
,numtowrite
,NULL
,0,
1605 total_written
+= nwritten
;
1607 /* Set up outbuf to return the correct return */
1608 outsize
= set_message(outbuf
,1,0,True
);
1609 CVAL(outbuf
,smb_com
) = SMBwritec
;
1610 SSVAL(outbuf
,smb_vwv0
,total_written
);
1612 if (nwritten
< numtowrite
) {
1613 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1614 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1617 if (lp_syncalways(SNUM(cnum
)) || write_through
)
1620 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1621 timestring(),fnum
,cnum
,startpos
,numtowrite
,total_written
));
1623 /* we won't return a status if write through is not selected - this
1624 follows what WfWg does */
1625 if (!write_through
&& total_written
==tcount
)
1632 /****************************************************************************
1633 reply to a writeunlock (core+)
1634 ****************************************************************************/
1635 int reply_writeunlock(char *inbuf
,char *outbuf
)
1641 uint32 numtowrite
,startpos
;
1645 cnum
= SVAL(inbuf
,smb_tid
);
1646 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1648 CHECK_FNUM(fnum
,cnum
);
1652 numtowrite
= SVAL(inbuf
,smb_vwv1
);
1653 startpos
= IVAL(inbuf
,smb_vwv2
);
1654 data
= smb_buf(inbuf
) + 3;
1656 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
1657 return(ERROR(ERRDOS
,ERRlock
));
1659 seek_file(fnum
,startpos
);
1661 /* The special X/Open SMB protocol handling of
1662 zero length writes is *NOT* done for
1667 nwritten
= write_file(fnum
,data
,numtowrite
);
1669 if (lp_syncalways(SNUM(cnum
)))
1672 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
1673 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1675 if(!do_unlock(fnum
, cnum
, numtowrite
, startpos
, &eclass
, &ecode
))
1676 return(ERROR(eclass
,ecode
));
1678 outsize
= set_message(outbuf
,1,0,True
);
1680 SSVAL(outbuf
,smb_vwv0
,nwritten
);
1682 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1683 timestring(),fnum
,cnum
,numtowrite
,nwritten
));
1689 /****************************************************************************
1691 ****************************************************************************/
1692 int reply_write(char *inbuf
,char *outbuf
,int dum1
,int dum2
)
1694 int cnum
,numtowrite
,fnum
;
1703 cnum
= SVAL(inbuf
,smb_tid
);
1704 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1706 CHECK_FNUM(fnum
,cnum
);
1710 numtowrite
= SVAL(inbuf
,smb_vwv1
);
1711 startpos
= IVAL(inbuf
,smb_vwv2
);
1712 data
= smb_buf(inbuf
) + 3;
1714 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
1715 return(ERROR(ERRDOS
,ERRlock
));
1717 seek_file(fnum
,startpos
);
1719 /* X/Open SMB protocol says that if smb_vwv1 is
1720 zero then the file size should be extended or
1721 truncated to the size given in smb_vwv[2-3] */
1723 nwritten
= set_filelen(Files
[fnum
].fd
, startpos
);
1725 nwritten
= write_file(fnum
,data
,numtowrite
);
1727 if (lp_syncalways(SNUM(cnum
)))
1730 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
1731 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1733 outsize
= set_message(outbuf
,1,0,True
);
1735 SSVAL(outbuf
,smb_vwv0
,nwritten
);
1737 if (nwritten
< numtowrite
) {
1738 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1739 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1742 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum
,cnum
,numtowrite
,nwritten
));
1748 /****************************************************************************
1749 reply to a write and X
1750 ****************************************************************************/
1751 int reply_write_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1753 int smb_com2
= CVAL(inbuf
,smb_vwv0
);
1754 int smb_off2
= SVAL(inbuf
,smb_vwv1
);
1755 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
1756 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
1757 int smb_dsize
= SVAL(inbuf
,smb_vwv10
);
1758 int smb_doff
= SVAL(inbuf
,smb_vwv11
);
1759 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
1765 cnum
= SVAL(inbuf
,smb_tid
);
1767 CHECK_FNUM(fnum
,cnum
);
1771 data
= smb_base(inbuf
) + smb_doff
;
1773 if (is_locked(fnum
,cnum
,smb_dsize
,smb_offs
))
1774 return(ERROR(ERRDOS
,ERRlock
));
1776 seek_file(fnum
,smb_offs
);
1778 /* X/Open SMB protocol says that, unlike SMBwrite
1779 if the length is zero then NO truncation is
1780 done, just a write of zero. To truncate a file,
1785 nwritten
= write_file(fnum
,data
,smb_dsize
);
1787 if(((nwritten
== 0) && (smb_dsize
!= 0))||(nwritten
< 0))
1788 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1790 outsize
= set_message(outbuf
,6,0,True
);
1792 CVAL(outbuf
,smb_vwv0
) = smb_com2
;
1793 SSVAL(outbuf
,smb_vwv1
,(outsize
+chain_size
)-4);
1794 SSVAL(outbuf
,smb_vwv2
,nwritten
);
1796 if (nwritten
< smb_dsize
) {
1797 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1798 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1801 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum
,cnum
,smb_dsize
,nwritten
));
1805 if (lp_syncalways(SNUM(cnum
)) || write_through
)
1808 if (smb_com2
!= 0xFF)
1809 outsize
+= chain_reply(smb_com2
,inbuf
,inbuf
+smb_off2
+4,
1810 outbuf
,outbuf
+outsize
,
1819 /****************************************************************************
1821 ****************************************************************************/
1822 int reply_lseek(char *inbuf
,char *outbuf
)
1830 cnum
= SVAL(inbuf
,smb_tid
);
1831 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1833 CHECK_FNUM(fnum
,cnum
);
1836 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
1837 startpos
= IVAL(inbuf
,smb_vwv2
);
1841 case 0: umode
= SEEK_SET
; break;
1842 case 1: umode
= SEEK_CUR
; break;
1843 case 2: umode
= SEEK_END
; break;
1845 umode
= SEEK_SET
; break;
1848 res
= lseek(Files
[fnum
].fd
,startpos
,umode
);
1849 Files
[fnum
].pos
= res
;
1851 outsize
= set_message(outbuf
,2,0,True
);
1852 SIVALS(outbuf
,smb_vwv0
,res
);
1854 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum
,cnum
,startpos
,mode
));
1860 /****************************************************************************
1862 ****************************************************************************/
1863 int reply_flush(char *inbuf
,char *outbuf
)
1866 int outsize
= set_message(outbuf
,0,0,True
);
1868 cnum
= SVAL(inbuf
,smb_tid
);
1869 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1871 if (fnum
!= 0xFFFF) {
1872 CHECK_FNUM(fnum
,cnum
);
1879 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
1886 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum
));
1891 /****************************************************************************
1893 ****************************************************************************/
1894 int reply_exit(char *inbuf
,char *outbuf
)
1896 int outsize
= set_message(outbuf
,0,0,True
);
1897 DEBUG(3,("%s exit\n",timestring()));
1903 /****************************************************************************
1905 ****************************************************************************/
1906 int reply_close(char *inbuf
,char *outbuf
)
1911 int32 eclass
= 0, err
= 0;
1913 outsize
= set_message(outbuf
,0,0,True
);
1915 cnum
= SVAL(inbuf
,smb_tid
);
1917 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1918 CHECK_FNUM(fnum
,cnum
);
1920 if(HAS_CACHED_ERROR(fnum
)) {
1921 eclass
= Files
[fnum
].wbmpx_ptr
->wr_errclass
;
1922 err
= Files
[fnum
].wbmpx_ptr
->wr_error
;
1925 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
1929 /* try and set the date */
1930 set_filetime(Files
[fnum
].name
,mtime
);
1932 /* We have a cached error */
1934 return(ERROR(eclass
,err
));
1936 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
1937 timestring(),Files
[fnum
].fd
,fnum
,cnum
,
1938 Connections
[cnum
].num_files_open
));
1944 /****************************************************************************
1945 reply to a writeclose (Core+ protocol)
1946 ****************************************************************************/
1947 int reply_writeclose(char *inbuf
,char *outbuf
)
1949 int cnum
,numtowrite
,fnum
;
1956 cnum
= SVAL(inbuf
,smb_tid
);
1957 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1959 CHECK_FNUM(fnum
,cnum
);
1963 numtowrite
= SVAL(inbuf
,smb_vwv1
);
1964 startpos
= IVAL(inbuf
,smb_vwv2
);
1965 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
1966 data
= smb_buf(inbuf
) + 1;
1968 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
1969 return(ERROR(ERRDOS
,ERRlock
));
1971 seek_file(fnum
,startpos
);
1973 nwritten
= write_file(fnum
,data
,numtowrite
);
1977 set_filetime(Files
[fnum
].name
,mtime
);
1979 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
1980 timestring(),fnum
,cnum
,numtowrite
,nwritten
,
1981 Connections
[cnum
].num_files_open
));
1984 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1986 outsize
= set_message(outbuf
,1,0,True
);
1988 SSVAL(outbuf
,smb_vwv0
,nwritten
);
1993 /****************************************************************************
1995 ****************************************************************************/
1996 int reply_lock(char *inbuf
,char *outbuf
)
1999 int outsize
= set_message(outbuf
,0,0,True
);
2000 uint32 count
,offset
;
2004 cnum
= SVAL(inbuf
,smb_tid
);
2005 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2007 CHECK_FNUM(fnum
,cnum
);
2010 count
= IVAL(inbuf
,smb_vwv1
);
2011 offset
= IVAL(inbuf
,smb_vwv3
);
2013 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files
[fnum
].fd
,fnum
,cnum
,offset
,count
));
2015 if(!do_lock( fnum
, cnum
, count
, offset
, &eclass
, &ecode
))
2016 return (ERROR(eclass
,ecode
));
2022 /****************************************************************************
2024 ****************************************************************************/
2025 int reply_unlock(char *inbuf
,char *outbuf
)
2028 int outsize
= set_message(outbuf
,0,0,True
);
2029 uint32 count
,offset
;
2033 cnum
= SVAL(inbuf
,smb_tid
);
2034 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2036 CHECK_FNUM(fnum
,cnum
);
2039 count
= IVAL(inbuf
,smb_vwv1
);
2040 offset
= IVAL(inbuf
,smb_vwv3
);
2042 if(!do_unlock(fnum
, cnum
, count
, offset
, &eclass
, &ecode
))
2043 return (ERROR(eclass
,ecode
));
2045 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files
[fnum
].fd
,fnum
,cnum
,offset
,count
));
2051 /****************************************************************************
2053 ****************************************************************************/
2054 int reply_tdis(char *inbuf
,char *outbuf
)
2057 int outsize
= set_message(outbuf
,0,0,True
);
2059 cnum
= SVAL(inbuf
,smb_tid
);
2060 uid
= SVAL(inbuf
,smb_uid
);
2062 Connections
[cnum
].used
= False
;
2064 close_cnum(cnum
,uid
);
2066 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum
));
2073 /****************************************************************************
2075 ****************************************************************************/
2076 int reply_echo(char *inbuf
,char *outbuf
)
2079 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2081 int data_len
= smb_buflen(inbuf
);
2082 int outsize
= set_message(outbuf
,1,data_len
,True
);
2084 cnum
= SVAL(inbuf
,smb_tid
);
2086 if (cnum
!= 0xFFFF && !OPEN_CNUM(cnum
))
2088 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum
));
2089 return(ERROR(ERRSRV
,ERRinvnid
));
2092 /* copy any incoming data back out */
2094 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2096 if (smb_reverb
> 100)
2098 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2102 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++)
2104 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2106 smb_setlen(outbuf
,outsize
- 4);
2108 send_smb(Client
,outbuf
);
2111 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb
,cnum
));
2117 /****************************************************************************
2118 reply to a printopen
2119 ****************************************************************************/
2120 int reply_printopen(char *inbuf
,char *outbuf
)
2128 *fname
= *fname2
= 0;
2130 cnum
= SVAL(inbuf
,smb_tid
);
2132 if (!CAN_PRINT(cnum
))
2133 return(ERROR(ERRDOS
,ERRnoaccess
));
2138 StrnCpy(s
,smb_buf(inbuf
)+1,sizeof(pstring
)-1);
2142 if (!(isalnum(*p
) || strchr("._-",*p
)))
2147 if (strlen(s
) > 10) s
[10] = 0;
2149 sprintf(fname
,"%s.XXXXXX",s
);
2152 fnum
= find_free_file();
2154 return(ERROR(ERRSRV
,ERRnofids
));
2156 strcpy(fname2
,(char *)mktemp(fname
));
2158 if (!check_name(fname2
,cnum
))
2159 return(ERROR(ERRDOS
,ERRnoaccess
));
2161 open_file(fnum
,cnum
,fname2
,O_WRONLY
| O_CREAT
| O_TRUNC
,
2164 if (!Files
[fnum
].open
)
2165 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2167 /* force it to be a print file */
2168 Files
[fnum
].print_file
= True
;
2170 outsize
= set_message(outbuf
,1,0,True
);
2171 SSVAL(outbuf
,smb_vwv0
,fnum
);
2173 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2
,Files
[fnum
].fd
,fnum
,cnum
));
2179 /****************************************************************************
2180 reply to a printclose
2181 ****************************************************************************/
2182 int reply_printclose(char *inbuf
,char *outbuf
)
2185 int outsize
= set_message(outbuf
,0,0,True
);
2187 cnum
= SVAL(inbuf
,smb_tid
);
2188 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2190 CHECK_FNUM(fnum
,cnum
);
2193 if (!CAN_PRINT(cnum
))
2194 return(ERROR(ERRDOS
,ERRnoaccess
));
2198 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files
[fnum
].fd
,fnum
,cnum
));
2204 /****************************************************************************
2205 reply to a printqueue
2206 ****************************************************************************/
2207 int reply_printqueue(char *inbuf
,char *outbuf
)
2210 int outsize
= set_message(outbuf
,2,3,True
);
2211 int max_count
= SVAL(inbuf
,smb_vwv0
);
2212 int start_index
= SVAL(inbuf
,smb_vwv1
);
2214 cnum
= SVAL(inbuf
,smb_tid
);
2215 uid
= SVAL(inbuf
,smb_uid
);
2217 /* allow checking the queue for anyone */
2219 if (!CAN_PRINT(cnum
))
2220 return(ERROR(ERRDOS
,ERRnoaccess
));
2223 SSVAL(outbuf
,smb_vwv0
,0);
2224 SSVAL(outbuf
,smb_vwv1
,0);
2225 CVAL(smb_buf(outbuf
),0) = 1;
2226 SSVAL(smb_buf(outbuf
),1,0);
2228 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2229 timestring(),cnum
,start_index
,max_count
));
2231 if (!OPEN_CNUM(cnum
) || !Connections
[cnum
].printer
)
2236 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2237 if (CAN_PRINT(i
) && Connections
[i
].printer
)
2241 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2245 if (!OPEN_CNUM(cnum
))
2246 return(ERROR(ERRSRV
,ERRinvnid
));
2248 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum
));
2251 if (!become_user(cnum
,uid
))
2252 return(ERROR(ERRSRV
,ERRinvnid
));
2255 print_queue_struct
*queue
= NULL
;
2256 char *p
= smb_buf(outbuf
) + 3;
2257 int count
= get_printqueue(SNUM(cnum
),cnum
,&queue
,NULL
);
2258 int num_to_get
= ABS(max_count
);
2259 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
2265 num_to_get
= MIN(num_to_get
,count
-first
);
2268 for (i
=first
;i
<first
+num_to_get
;i
++)
2270 put_dos_date2(p
,0,queue
[i
].time
);
2271 CVAL(p
,4) = (queue
[i
].status
==LPQ_PRINTING
?2:3);
2272 SSVAL(p
,5,queue
[i
].job
);
2273 SIVAL(p
,7,queue
[i
].size
);
2275 StrnCpy(p
+12,queue
[i
].user
,16);
2281 outsize
= set_message(outbuf
,2,28*count
+3,False
);
2282 SSVAL(outbuf
,smb_vwv0
,count
);
2283 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
2284 CVAL(smb_buf(outbuf
),0) = 1;
2285 SSVAL(smb_buf(outbuf
),1,28*count
);
2288 if (queue
) free(queue
);
2290 DEBUG(3,("%d entries returned in queue\n",count
));
2297 /****************************************************************************
2298 reply to a printwrite
2299 ****************************************************************************/
2300 int reply_printwrite(char *inbuf
,char *outbuf
)
2302 int cnum
,numtowrite
,fnum
;
2303 int outsize
= set_message(outbuf
,0,0,True
);
2306 cnum
= SVAL(inbuf
,smb_tid
);
2308 if (!CAN_PRINT(cnum
))
2309 return(ERROR(ERRDOS
,ERRnoaccess
));
2311 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2313 CHECK_FNUM(fnum
,cnum
);
2317 numtowrite
= SVAL(smb_buf(inbuf
),1);
2318 data
= smb_buf(inbuf
) + 3;
2320 if (write_file(fnum
,data
,numtowrite
) != numtowrite
)
2321 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2323 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum
,cnum
,numtowrite
));
2329 /****************************************************************************
2331 ****************************************************************************/
2332 int reply_mkdir(char *inbuf
,char *outbuf
)
2336 int outsize
,ret
= -1;
2338 strcpy(directory
,smb_buf(inbuf
) + 1);
2339 cnum
= SVAL(inbuf
,smb_tid
);
2340 unix_convert(directory
,cnum
);
2342 if (check_name(directory
,cnum
))
2343 ret
= sys_mkdir(directory
,unix_mode(cnum
,aDIR
));
2346 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2348 outsize
= set_message(outbuf
,0,0,True
);
2350 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory
,cnum
,ret
));
2356 /****************************************************************************
2358 ****************************************************************************/
2359 int reply_rmdir(char *inbuf
,char *outbuf
)
2366 cnum
= SVAL(inbuf
,smb_tid
);
2367 strcpy(directory
,smb_buf(inbuf
) + 1);
2368 unix_convert(directory
,cnum
);
2370 if (check_name(directory
,cnum
))
2372 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
2373 ok
= (sys_rmdir(directory
) == 0);
2375 DEBUG(3,("couldn't remove directory %s : %s\n",
2376 directory
,strerror(errno
)));
2380 return(UNIXERROR(ERRDOS
,ERRbadpath
));
2382 outsize
= set_message(outbuf
,0,0,True
);
2384 DEBUG(3,("%s rmdir %s\n",timestring(),directory
));
2390 /*******************************************************************
2391 resolve wildcards in a filename rename
2392 ********************************************************************/
2393 static BOOL
resolve_wildcards(char *name1
,char *name2
)
2395 fstring root1
,root2
;
2399 name1
= strrchr(name1
,'/');
2400 name2
= strrchr(name2
,'/');
2402 if (!name1
|| !name2
) return(False
);
2404 strcpy(root1
,name1
);
2405 strcpy(root2
,name2
);
2406 p
= strrchr(root1
,'.');
2413 p
= strrchr(root2
,'.');
2445 strcpy(name2
,root2
);
2454 /*******************************************************************
2455 check if a user is allowed to rename a file
2456 ********************************************************************/
2457 static BOOL
can_rename(char *fname
,int cnum
)
2461 if (!CAN_WRITE(cnum
)) return(False
);
2463 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
2464 if (!check_file_sharing(cnum
,fname
)) return(False
);
2469 /****************************************************************************
2471 ****************************************************************************/
2472 int reply_mv(char *inbuf
,char *outbuf
)
2478 pstring mask
,newname
;
2481 int error
= ERRnoaccess
;
2485 *directory
= *mask
= 0;
2487 cnum
= SVAL(inbuf
,smb_tid
);
2489 strcpy(name
,smb_buf(inbuf
) + 1);
2490 strcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
2492 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
2494 unix_convert(name
,cnum
);
2495 unix_convert(newname
,cnum
);
2497 p
= strrchr(name
,'/');
2499 strcpy(directory
,"./");
2503 strcpy(directory
,name
);
2507 if (is_mangled(mask
))
2508 check_mangled_stack(mask
);
2510 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
2513 strcat(directory
,"/");
2514 strcat(directory
,mask
);
2515 if (resolve_wildcards(directory
,newname
) &&
2516 can_rename(directory
,cnum
) &&
2517 !file_exist(newname
,NULL
) &&
2518 !sys_rename(directory
,newname
)) count
++;
2519 if (!count
) exists
= file_exist(directory
,NULL
);
2520 if (!count
&& exists
&& file_exist(newname
,NULL
)) {
2525 void *dirptr
= NULL
;
2529 if (check_name(directory
,cnum
))
2530 dirptr
= OpenDir(directory
);
2536 if (strequal(mask
,"????????.???"))
2539 while ((dname
= ReadDirName(dirptr
)))
2542 strcpy(fname
,dname
);
2544 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
2546 error
= ERRnoaccess
;
2547 sprintf(fname
,"%s/%s",directory
,dname
);
2548 if (!can_rename(fname
,cnum
)) continue;
2549 strcpy(destname
,newname
);
2551 if (!resolve_wildcards(fname
,destname
)) continue;
2553 if (file_exist(destname
,NULL
)) {
2557 if (!sys_rename(fname
,destname
)) count
++;
2558 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname
,destname
));
2566 return(ERROR(ERRDOS
,error
));
2568 return(UNIXERROR(ERRDOS
,error
));
2571 outsize
= set_message(outbuf
,0,0,True
);
2576 /*******************************************************************
2577 copy a file as part of a reply_copy
2578 ******************************************************************/
2579 static BOOL
copy_file(char *src
,char *dest1
,int cnum
,int ofun
,
2580 int count
,BOOL target_is_directory
)
2589 if (target_is_directory
) {
2590 char *p
= strrchr(src
,'/');
2599 if (!file_exist(src
,&st
)) return(False
);
2601 fnum1
= find_free_file();
2602 if (fnum1
<0) return(False
);
2603 open_file_shared(fnum1
,cnum
,src
,(DENY_NONE
<<4),
2604 1,0,&Access
,&action
);
2606 if (!Files
[fnum1
].open
) return(False
);
2608 if (!target_is_directory
&& count
)
2611 fnum2
= find_free_file();
2616 open_file_shared(fnum2
,cnum
,dest
,(DENY_NONE
<<4)|1,
2617 ofun
,st
.st_mode
,&Access
,&action
);
2619 if (!Files
[fnum2
].open
) {
2624 if ((ofun
&3) == 1) {
2625 lseek(Files
[fnum2
].fd
,0,SEEK_END
);
2629 ret
= transfer_file(Files
[fnum1
].fd
,Files
[fnum2
].fd
,st
.st_size
,NULL
,0,0);
2634 return(ret
== st
.st_size
);
2639 /****************************************************************************
2640 reply to a file copy.
2641 ****************************************************************************/
2642 int reply_copy(char *inbuf
,char *outbuf
)
2648 pstring mask
,newname
;
2651 int error
= ERRnoaccess
;
2654 int tid2
= SVAL(inbuf
,smb_vwv0
);
2655 int ofun
= SVAL(inbuf
,smb_vwv1
);
2656 int flags
= SVAL(inbuf
,smb_vwv2
);
2657 BOOL target_is_directory
=False
;
2659 *directory
= *mask
= 0;
2661 cnum
= SVAL(inbuf
,smb_tid
);
2663 strcpy(name
,smb_buf(inbuf
));
2664 strcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
2666 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
2669 /* can't currently handle inter share copies XXXX */
2670 DEBUG(3,("Rejecting inter-share copy\n"));
2671 return(ERROR(ERRSRV
,ERRinvdevice
));
2674 unix_convert(name
,cnum
);
2675 unix_convert(newname
,cnum
);
2677 target_is_directory
= directory_exist(newname
,NULL
);
2679 if ((flags
&1) && target_is_directory
) {
2680 return(ERROR(ERRDOS
,ERRbadfile
));
2683 if ((flags
&2) && !target_is_directory
) {
2684 return(ERROR(ERRDOS
,ERRbadpath
));
2687 if ((flags
&(1<<5)) && directory_exist(name
,NULL
)) {
2688 /* wants a tree copy! XXXX */
2689 DEBUG(3,("Rejecting tree copy\n"));
2690 return(ERROR(ERRSRV
,ERRerror
));
2693 p
= strrchr(name
,'/');
2695 strcpy(directory
,"./");
2699 strcpy(directory
,name
);
2703 if (is_mangled(mask
))
2704 check_mangled_stack(mask
);
2706 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
2709 strcat(directory
,"/");
2710 strcat(directory
,mask
);
2711 if (resolve_wildcards(directory
,newname
) &&
2712 copy_file(directory
,newname
,cnum
,ofun
,
2713 count
,target_is_directory
)) count
++;
2714 if (!count
) exists
= file_exist(directory
,NULL
);
2716 void *dirptr
= NULL
;
2720 if (check_name(directory
,cnum
))
2721 dirptr
= OpenDir(directory
);
2727 if (strequal(mask
,"????????.???"))
2730 while ((dname
= ReadDirName(dirptr
)))
2733 strcpy(fname
,dname
);
2735 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
2737 error
= ERRnoaccess
;
2738 sprintf(fname
,"%s/%s",directory
,dname
);
2739 strcpy(destname
,newname
);
2740 if (resolve_wildcards(fname
,destname
) &&
2741 copy_file(directory
,newname
,cnum
,ofun
,
2742 count
,target_is_directory
)) count
++;
2743 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
2751 return(ERROR(ERRDOS
,error
));
2753 return(UNIXERROR(ERRDOS
,error
));
2756 outsize
= set_message(outbuf
,1,0,True
);
2757 SSVAL(outbuf
,smb_vwv0
,count
);
2764 /****************************************************************************
2766 ****************************************************************************/
2767 int reply_setdir(char *inbuf
,char *outbuf
)
2774 cnum
= SVAL(inbuf
,smb_tid
);
2776 snum
= Connections
[cnum
].service
;
2777 if (!CAN_SETDIR(snum
))
2778 return(ERROR(ERRDOS
,ERRnoaccess
));
2780 strcpy(newdir
,smb_buf(inbuf
) + 1);
2783 if (strlen(newdir
) == 0)
2787 ok
= directory_exist(newdir
,NULL
);
2789 string_set(&Connections
[cnum
].connectpath
,newdir
);
2793 return(ERROR(ERRDOS
,ERRbadpath
));
2795 outsize
= set_message(outbuf
,0,0,True
);
2796 CVAL(outbuf
,smb_reh
) = CVAL(inbuf
,smb_reh
);
2798 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir
,cnum
));
2804 /****************************************************************************
2805 reply to a lockingX request
2806 ****************************************************************************/
2807 int reply_lockingX(char *inbuf
,char *outbuf
,int length
,int bufsize
)
2809 int smb_com2
= CVAL(inbuf
,smb_vwv0
);
2810 int smb_off2
= SVAL(inbuf
,smb_vwv1
);
2811 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
2812 uint16 locktype
= SVAL(inbuf
,smb_vwv3
);
2813 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
2814 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
2815 uint32 count
, offset
;
2820 uint32 ecode
=0, dummy2
;
2821 int outsize
, eclass
=0, dummy1
;
2823 cnum
= SVAL(inbuf
,smb_tid
);
2825 CHECK_FNUM(fnum
,cnum
);
2828 data
= smb_buf(inbuf
);
2829 /* Data now points at the beginning of the list
2830 of smb_unlkrng structs */
2831 for(i
= 0; i
< (int)num_ulocks
; i
++) {
2832 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
2833 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
2834 if(!do_unlock(fnum
,cnum
,count
,offset
,&eclass
, &ecode
))
2835 return ERROR(eclass
,ecode
);
2838 /* Now do any requested locks */
2839 data
+= 10*num_ulocks
;
2840 /* Data now points at the beginning of the list
2841 of smb_lkrng structs */
2842 for(i
= 0; i
< (int)num_locks
; i
++) {
2843 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
2844 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
2845 if(!do_lock(fnum
,cnum
,count
,offset
, &eclass
, &ecode
))
2849 /* If any of the above locks failed, then we must unlock
2850 all of the previous locks (X/Open spec). */
2851 if(i
!= num_locks
&& num_locks
!= 0) {
2852 for(; i
>= 0; i
--) {
2853 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
2854 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
2855 do_unlock(fnum
,cnum
,count
,offset
,&dummy1
,&dummy2
);
2857 return ERROR(eclass
,ecode
);
2860 outsize
= set_message(outbuf
,2,0,True
);
2862 CVAL(outbuf
,smb_vwv0
) = smb_com2
;
2863 SSVAL(outbuf
,smb_vwv1
,(outsize
+chain_size
)-4);
2865 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
2866 timestring(),fnum
,cnum
,locktype
,num_locks
,num_ulocks
));
2870 if (smb_com2
!= 0xFF)
2871 outsize
+= chain_reply(smb_com2
,inbuf
,inbuf
+smb_off2
+4,
2872 outbuf
,outbuf
+outsize
,
2881 /****************************************************************************
2882 reply to a SMBreadbmpx (read block multiplex) request
2883 ****************************************************************************/
2884 int reply_readbmpx(char *inbuf
,char *outbuf
,int length
,int bufsize
)
2891 int outsize
, mincount
, maxcount
;
2896 /* this function doesn't seem to work - disable by default */
2898 return(ERROR(ERRSRV
,ERRuseSTD
));
2900 outsize
= set_message(outbuf
,8,0,True
);
2902 cnum
= SVAL(inbuf
,smb_tid
);
2903 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2905 CHECK_FNUM(fnum
,cnum
);
2909 startpos
= IVAL(inbuf
,smb_vwv1
);
2910 maxcount
= SVAL(inbuf
,smb_vwv3
);
2911 mincount
= SVAL(inbuf
,smb_vwv4
);
2913 data
= smb_buf(outbuf
);
2914 pad
= ((int)data
)%4;
2915 if (pad
) pad
= 4 - pad
;
2918 max_per_packet
= bufsize
-(outsize
+pad
);
2922 if (is_locked(fnum
,cnum
,maxcount
,startpos
))
2923 return(ERROR(ERRDOS
,ERRlock
));
2927 int N
= MIN(max_per_packet
,tcount
-total_read
);
2929 nread
= read_file(fnum
,data
,startpos
,N
,N
,-1,False
);
2931 if (nread
<= 0) nread
= 0;
2934 tcount
= total_read
+ nread
;
2936 set_message(outbuf
,8,nread
,False
);
2937 SIVAL(outbuf
,smb_vwv0
,startpos
);
2938 SSVAL(outbuf
,smb_vwv2
,tcount
);
2939 SSVAL(outbuf
,smb_vwv6
,nread
);
2940 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
2942 send_smb(Client
,outbuf
);
2944 total_read
+= nread
;
2947 while (total_read
< tcount
);
2953 /****************************************************************************
2954 reply to a SMBwritebmpx (write block multiplex primary) request
2955 ****************************************************************************/
2956 int reply_writebmpx(char *inbuf
,char *outbuf
)
2958 int cnum
,numtowrite
,fnum
;
2962 int tcount
, write_through
, smb_doff
;
2965 cnum
= SVAL(inbuf
,smb_tid
);
2966 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2968 CHECK_FNUM(fnum
,cnum
);
2972 tcount
= SVAL(inbuf
,smb_vwv1
);
2973 startpos
= IVAL(inbuf
,smb_vwv3
);
2974 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2975 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2976 smb_doff
= SVAL(inbuf
,smb_vwv11
);
2978 data
= smb_base(inbuf
) + smb_doff
;
2980 /* If this fails we need to send an SMBwriteC response,
2981 not an SMBwritebmpx - set this up now so we don't forget */
2982 CVAL(outbuf
,smb_com
) = SMBwritec
;
2984 if (is_locked(fnum
,cnum
,tcount
,startpos
))
2985 return(ERROR(ERRDOS
,ERRlock
));
2987 seek_file(fnum
,startpos
);
2988 nwritten
= write_file(fnum
,data
,numtowrite
);
2990 if(lp_syncalways(SNUM(cnum
)) || write_through
)
2993 if(nwritten
< numtowrite
)
2994 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2996 /* If the maximum to be written to this file
2997 is greater than what we just wrote then set
2998 up a secondary struct to be attached to this
2999 fd, we will use this to cache error messages etc. */
3000 if(tcount
> nwritten
)
3002 write_bmpx_struct
*wbms
;
3003 if(Files
[fnum
].wbmpx_ptr
!= NULL
)
3004 wbms
= Files
[fnum
].wbmpx_ptr
; /* Use an existing struct */
3006 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
3009 DEBUG(0,("Out of memory in reply_readmpx\n"));
3010 return(ERROR(ERRSRV
,ERRnoresource
));
3012 wbms
->wr_mode
= write_through
;
3013 wbms
->wr_discard
= False
; /* No errors yet */
3014 wbms
->wr_total_written
= nwritten
;
3015 wbms
->wr_errclass
= 0;
3017 Files
[fnum
].wbmpx_ptr
= wbms
;
3020 /* We are returning successfully, set the message type back to
3022 CVAL(outbuf
,smb_com
) = SMBwriteBmpx
;
3024 outsize
= set_message(outbuf
,1,0,True
);
3026 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
3028 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3029 timestring(),fnum
,cnum
,numtowrite
,nwritten
));
3031 if (write_through
&& tcount
==nwritten
) {
3032 /* we need to send both a primary and a secondary response */
3033 smb_setlen(outbuf
,outsize
- 4);
3034 send_smb(Client
,outbuf
);
3036 /* now the secondary */
3037 outsize
= set_message(outbuf
,1,0,True
);
3038 CVAL(outbuf
,smb_com
) = SMBwritec
;
3039 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3046 /****************************************************************************
3047 reply to a SMBwritebs (write block multiplex secondary) request
3048 ****************************************************************************/
3049 int reply_writebs(char *inbuf
,char *outbuf
)
3051 int cnum
,numtowrite
,fnum
;
3055 int tcount
, write_through
, smb_doff
;
3057 write_bmpx_struct
*wbms
;
3058 BOOL send_response
= False
;
3060 cnum
= SVAL(inbuf
,smb_tid
);
3061 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3062 CHECK_FNUM(fnum
,cnum
);
3065 tcount
= SVAL(inbuf
,smb_vwv1
);
3066 startpos
= IVAL(inbuf
,smb_vwv2
);
3067 numtowrite
= SVAL(inbuf
,smb_vwv6
);
3068 smb_doff
= SVAL(inbuf
,smb_vwv7
);
3070 data
= smb_base(inbuf
) + smb_doff
;
3072 /* We need to send an SMBwriteC response, not an SMBwritebs */
3073 CVAL(outbuf
,smb_com
) = SMBwritec
;
3075 /* This fd should have an auxiliary struct attached,
3076 check that it does */
3077 wbms
= Files
[fnum
].wbmpx_ptr
;
3078 if(!wbms
) return(-1);
3080 /* If write through is set we can return errors, else we must
3082 write_through
= wbms
->wr_mode
;
3084 /* Check for an earlier error */
3085 if(wbms
->wr_discard
)
3086 return -1; /* Just discard the packet */
3088 seek_file(fnum
,startpos
);
3089 nwritten
= write_file(fnum
,data
,numtowrite
);
3091 if(lp_syncalways(SNUM(cnum
)) || write_through
)
3094 if (nwritten
< numtowrite
)
3097 /* We are returning an error - we can delete the aux struct */
3098 if (wbms
) free((char *)wbms
);
3099 Files
[fnum
].wbmpx_ptr
= NULL
;
3100 return(ERROR(ERRHRD
,ERRdiskfull
));
3102 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
3105 /* Increment the total written, if this matches tcount
3106 we can discard the auxiliary struct (hurrah !) and return a writeC */
3107 wbms
->wr_total_written
+= nwritten
;
3108 if(wbms
->wr_total_written
>= tcount
)
3110 if (write_through
) {
3111 outsize
= set_message(outbuf
,1,0,True
);
3112 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
3113 send_response
= True
;
3117 Files
[fnum
].wbmpx_ptr
= NULL
;
3127 /****************************************************************************
3128 reply to a SMBsetattrE
3129 ****************************************************************************/
3130 int reply_setattrE(char *inbuf
,char *outbuf
)
3133 struct utimbuf unix_times
;
3136 outsize
= set_message(outbuf
,0,0,True
);
3138 cnum
= SVAL(inbuf
,smb_tid
);
3139 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3141 CHECK_FNUM(fnum
,cnum
);
3144 /* Convert the DOS times into unix times. Ignore create
3145 time as UNIX can't set this.
3147 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
3148 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
3150 /* Set the date on this file */
3151 if(sys_utime(Files
[fnum
].name
, &unix_times
))
3152 return(ERROR(ERRDOS
,ERRnoaccess
));
3154 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum
,cnum
));
3160 /****************************************************************************
3161 reply to a SMBgetattrE
3162 ****************************************************************************/
3163 int reply_getattrE(char *inbuf
,char *outbuf
)
3170 outsize
= set_message(outbuf
,11,0,True
);
3172 cnum
= SVAL(inbuf
,smb_tid
);
3173 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3175 CHECK_FNUM(fnum
,cnum
);
3178 /* Do an fstat on this file */
3179 if(fstat(Files
[fnum
].fd
, &sbuf
))
3180 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3182 mode
= dos_mode(cnum
,Files
[fnum
].name
,&sbuf
);
3184 /* Convert the times into dos times. Set create
3185 date to be last modify date as UNIX doesn't save
3187 put_dos_date2(outbuf
,smb_vwv0
,sbuf
.st_mtime
);
3188 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
3189 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
3192 SIVAL(outbuf
,smb_vwv6
,0);
3193 SIVAL(outbuf
,smb_vwv8
,0);
3197 SIVAL(outbuf
,smb_vwv6
,sbuf
.st_size
);
3198 SIVAL(outbuf
,smb_vwv8
,ROUNDUP(sbuf
.st_size
,1024));
3200 SSVAL(outbuf
,smb_vwv10
, mode
);
3202 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum
,cnum
));