2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1997
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
30 /* look in server.c for some explanation of these variables */
32 extern int DEBUGLEVEL
;
35 extern int chain_fnum
;
36 extern char magic_char
;
37 extern connection_struct Connections
[];
38 extern files_struct Files
[];
39 extern BOOL case_sensitive
;
40 extern BOOL case_preserve
;
41 extern BOOL short_case_preserve
;
42 extern pstring sesssetup_user
;
43 extern fstring myworkgroup
;
46 /* this macro should always be used to extract an fnum (smb_fid) from
47 a packet to ensure chaining works correctly */
48 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
51 /****************************************************************************
52 reply to an special message
53 ****************************************************************************/
54 int reply_special(char *inbuf
,char *outbuf
)
57 int msg_type
= CVAL(inbuf
,0);
58 int msg_flags
= CVAL(inbuf
,1);
60 extern fstring remote_machine
;
61 extern fstring local_machine
;
70 case 0x81: /* session request */
71 CVAL(outbuf
,0) = 0x82;
73 if (name_len(inbuf
+4) > 50)
75 DEBUG(0,("Invalid name length in session request\n"));
78 name_extract(inbuf
,4,name1
);
79 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
80 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1
,name2
));
82 strcpy(remote_machine
,name2
);
83 trim_string(remote_machine
," "," ");
84 p
= strchr(remote_machine
,' ');
85 strlower(remote_machine
);
88 strcpy(local_machine
,name1
);
89 trim_string(local_machine
," "," ");
90 p
= strchr(local_machine
,' ');
91 strlower(local_machine
);
94 add_session_user(remote_machine
);
96 reload_services(True
);
100 case 0x85: /* session keepalive */
105 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type
,msg_flags
));
111 /*******************************************************************
112 work out what error to give to a failed connection
113 ********************************************************************/
114 static int connection_error(char *inbuf
,char *outbuf
,int connection_num
)
116 switch (connection_num
)
119 return(ERROR(ERRSRV
,ERRnoresource
));
121 return(ERROR(ERRSRV
,ERRbaduid
));
123 return(ERROR(ERRSRV
,ERRinvdevice
));
125 return(ERROR(ERRSRV
,ERRinvnetname
));
127 return(ERROR(ERRSRV
,ERRaccess
));
129 return(ERROR(ERRDOS
,ERRnoipc
));
131 return(ERROR(ERRSRV
,ERRinvnetname
));
133 return(ERROR(ERRSRV
,ERRbadpw
));
138 /****************************************************************************
139 parse a share descriptor string
140 ****************************************************************************/
141 static void parse_connect(char *p
,char *service
,char *user
,
142 char *password
,int *pwlen
,char *dev
)
146 DEBUG(4,("parsing connect string %s\n",p
));
148 p2
= strrchr(p
,'\\');
152 strcpy(service
,p2
+1);
157 *pwlen
= strlen(password
);
164 p
= strchr(service
,'%');
175 /****************************************************************************
177 ****************************************************************************/
178 int reply_tcon(char *inbuf
,char *outbuf
)
186 uint16 vuid
= SVAL(inbuf
,smb_uid
);
189 *service
= *user
= *password
= *dev
= 0;
191 parse_connect(smb_buf(inbuf
)+1,service
,user
,password
,&pwlen
,dev
);
193 connection_num
= make_connection(service
,user
,password
,pwlen
,dev
,vuid
);
195 if (connection_num
< 0)
196 return(connection_error(inbuf
,outbuf
,connection_num
));
198 outsize
= set_message(outbuf
,2,0,True
);
199 SSVAL(outbuf
,smb_vwv0
,max_recv
);
200 SSVAL(outbuf
,smb_vwv1
,connection_num
);
201 SSVAL(outbuf
,smb_tid
,connection_num
);
203 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service
,user
,connection_num
));
209 /****************************************************************************
210 reply to a tcon and X
211 ****************************************************************************/
212 int reply_tcon_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
219 uint16 vuid
= SVAL(inbuf
,smb_uid
);
220 int passlen
= SVAL(inbuf
,smb_vwv3
);
221 BOOL doencrypt
= SMBENCRYPT();
223 *service
= *user
= *password
= *devicename
= 0;
225 /* we might have to close an old one */
226 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) != 0)
227 close_cnum(SVAL(inbuf
,smb_tid
),vuid
);
232 memcpy(password
,smb_buf(inbuf
),passlen
);
234 path
= smb_buf(inbuf
) + passlen
;
236 if (!doencrypt
|| passlen
!= 24) {
237 if (strequal(password
," "))
239 passlen
= strlen(password
);
242 DEBUG(4,("parsing net-path %s, passlen=%d\n",path
,passlen
));
243 strcpy(service
,path
+2);
244 p
= strchr(service
,'\\');
246 return(ERROR(ERRSRV
,ERRinvnetname
));
249 p
= strchr(service
,'%');
255 StrnCpy(devicename
,path
+ strlen(path
) + 1,6);
256 DEBUG(4,("Got device type %s\n",devicename
));
259 connection_num
= make_connection(service
,user
,password
,passlen
,devicename
,vuid
);
261 if (connection_num
< 0)
262 return(connection_error(inbuf
,outbuf
,connection_num
));
264 set_message(outbuf
,2,strlen(devicename
)+1,True
);
266 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service
,user
,connection_num
));
268 /* set the incoming and outgoing tid to the just created one */
269 SSVAL(inbuf
,smb_tid
,connection_num
);
270 SSVAL(outbuf
,smb_tid
,connection_num
);
272 strcpy(smb_buf(outbuf
),devicename
);
274 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
278 /****************************************************************************
279 reply to an unknown type
280 ****************************************************************************/
281 int reply_unknown(char *inbuf
,char *outbuf
)
285 cnum
= SVAL(inbuf
,smb_tid
);
286 type
= CVAL(inbuf
,smb_com
);
288 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
293 return(ERROR(ERRSRV
,ERRunknownsmb
));
297 /****************************************************************************
299 ****************************************************************************/
300 int reply_ioctl(char *inbuf
,char *outbuf
)
302 DEBUG(3,("ignoring ioctl\n"));
304 /* we just say it succeeds and hope its all OK.
305 some day it would be nice to interpret them individually */
306 return set_message(outbuf
,1,0,True
);
308 return(ERROR(ERRSRV
,ERRnosupport
));
313 /****************************************************************************
314 reply to a session setup command
315 ****************************************************************************/
316 int reply_sesssetup_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
325 int smb_apasslen
= 0;
327 int smb_ntpasslen
= 0;
328 pstring smb_ntpasswd
;
329 BOOL valid_nt_password
= False
;
332 BOOL computer_id
=False
;
333 static BOOL done_sesssetup
= False
;
334 BOOL doencrypt
= SMBENCRYPT();
338 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
339 smb_mpxmax
= SVAL(inbuf
,smb_vwv3
);
340 smb_vc_num
= SVAL(inbuf
,smb_vwv4
);
341 smb_sesskey
= IVAL(inbuf
,smb_vwv5
);
343 if (Protocol
< PROTOCOL_NT1
) {
344 smb_apasslen
= SVAL(inbuf
,smb_vwv7
);
345 memcpy(smb_apasswd
,smb_buf(inbuf
),smb_apasslen
);
346 StrnCpy(user
,smb_buf(inbuf
)+smb_apasslen
,sizeof(user
)-1);
348 if (lp_security() != SEC_SERVER
&& !doencrypt
)
349 smb_apasslen
= strlen(smb_apasswd
);
351 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
352 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
353 char *p
= smb_buf(inbuf
);
355 if (passlen1
!= 24 && passlen2
!= 24)
359 /* Save the lanman2 password and the NT md4 password. */
360 smb_apasslen
= passlen1
;
361 memcpy(smb_apasswd
,p
,smb_apasslen
);
362 smb_ntpasslen
= passlen2
;
363 memcpy(smb_ntpasswd
,p
+passlen1
,smb_ntpasslen
);
365 /* both Win95 and WinNT stuff up the password lengths for
366 non-encrypting systems. Uggh.
368 if passlen1==24 its a win95 system, and its setting the
369 password length incorrectly. Luckily it still works with the
370 default code because Win95 will null terminate the password
373 if passlen1>0 and passlen2>0 then maybe its a NT box and its
374 setting passlen2 to some random value which really stuffs
375 things up. we need to fix that one. */
376 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
380 /* we use the first password that they gave */
381 smb_apasslen
= passlen1
;
382 StrnCpy(smb_apasswd
,p
,smb_apasslen
);
384 /* trim the password */
385 smb_apasslen
= strlen(smb_apasswd
);
387 /* wfwg sometimes uses a space instead of a null */
388 if (strequal(smb_apasswd
," ")) {
394 p
+= passlen1
+ passlen2
;
395 strcpy(user
,p
); p
= skip_string(p
,1);
396 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
397 p
,skip_string(p
,1),skip_string(p
,2)));
401 DEBUG(3,("sesssetupX:name=[%s]\n",user
));
403 /* If name ends in $ then I think it's asking about whether a */
404 /* computer with that name (minus the $) has access. For now */
405 /* say yes to everything ending in $. */
406 if (user
[strlen(user
) - 1] == '$') {
408 user
[strlen(user
) - 1] = '\0';
412 /* If no username is sent use the guest account */
415 strcpy(user
,lp_guestaccount(-1));
416 /* If no user and no password then set guest flag. */
417 if( *smb_apasswd
== 0)
423 strcpy(sesssetup_user
,user
);
425 reload_services(True
);
427 add_session_user(user
);
430 if (!guest
&& !(lp_security() == SEC_SERVER
&& server_validate(inbuf
)) &&
431 !check_hosts_equiv(user
))
434 /* now check if it's a valid username/password */
435 /* If an NT password was supplied try and validate with that
436 first. This is superior as the passwords are mixed case
437 128 length unicode */
440 if(!password_ok(user
,smb_ntpasswd
,smb_ntpasslen
,NULL
))
441 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
443 valid_nt_password
= True
;
445 if (!valid_nt_password
&& !password_ok(user
,smb_apasswd
,smb_apasslen
,NULL
))
447 if (!computer_id
&& lp_security() >= SEC_USER
) {
448 #if (GUEST_SESSSETUP == 0)
449 return(ERROR(ERRSRV
,ERRbadpw
));
451 #if (GUEST_SESSSETUP == 1)
452 if (Get_Pwnam(user
,True
))
453 return(ERROR(ERRSRV
,ERRbadpw
));
456 if (*smb_apasswd
|| !Get_Pwnam(user
,True
))
457 strcpy(user
,lp_guestaccount(-1));
458 DEBUG(3,("Registered username %s for guest access\n",user
));
463 if (!Get_Pwnam(user
,True
)) {
464 DEBUG(3,("No such user %s - using guest account\n",user
));
465 strcpy(user
,lp_guestaccount(-1));
469 if (!strequal(user
,lp_guestaccount(-1)) &&
470 lp_servicenumber(user
) < 0)
472 int homes
= lp_servicenumber(HOMES_NAME
);
473 char *home
= get_home_dir(user
);
474 if (homes
>= 0 && home
)
475 lp_add_home(user
,homes
,home
);
479 /* it's ok - setup a reply */
480 if (Protocol
< PROTOCOL_NT1
) {
481 set_message(outbuf
,3,0,True
);
484 set_message(outbuf
,3,3,True
);
486 strcpy(p
,"Unix"); p
= skip_string(p
,1);
487 strcpy(p
,"Samba "); strcat(p
,VERSION
); p
= skip_string(p
,1);
488 strcpy(p
,myworkgroup
); p
= skip_string(p
,1);
489 set_message(outbuf
,3,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
490 /* perhaps grab OS version here?? */
493 /* Set the correct uid in the outgoing and incoming packets
494 We will use this on future requests to determine which
495 user we should become.
498 struct passwd
*pw
= Get_Pwnam(user
,False
);
500 DEBUG(1,("Username %s is invalid on this system\n",user
));
501 return(ERROR(ERRSRV
,ERRbadpw
));
507 if (guest
&& !computer_id
)
508 SSVAL(outbuf
,smb_vwv2
,1);
510 /* register the name and uid as being validated, so further connections
511 to a uid can get through without a password, on the same VC */
512 sess_vuid
= register_vuid(uid
,gid
,user
,guest
);
514 SSVAL(outbuf
,smb_uid
,sess_vuid
);
515 SSVAL(inbuf
,smb_uid
,sess_vuid
);
518 max_send
= MIN(max_send
,smb_bufsize
);
520 DEBUG(1,(" Client requested max send size of %d\n", max_send
));
522 done_sesssetup
= True
;
524 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
528 /****************************************************************************
530 ****************************************************************************/
531 int reply_chkpth(char *inbuf
,char *outbuf
)
537 BOOL bad_path
= False
;
539 cnum
= SVAL(inbuf
,smb_tid
);
541 strcpy(name
,smb_buf(inbuf
) + 1);
542 unix_convert(name
,cnum
,0,&bad_path
);
544 mode
= SVAL(inbuf
,smb_vwv0
);
546 if (check_name(name
,cnum
))
547 ok
= directory_exist(name
,NULL
);
551 /* We special case this - as when a Windows machine
552 is parsing a path is steps through the components
553 one at a time - if a component fails it expects
554 ERRbadpath, not ERRbadfile.
558 unix_ERR_class
= ERRDOS
;
559 unix_ERR_code
= ERRbadpath
;
561 return(UNIXERROR(ERRDOS
,ERRbadpath
));
564 outsize
= set_message(outbuf
,0,0,True
);
566 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name
,cnum
,mode
));
572 /****************************************************************************
574 ****************************************************************************/
575 int reply_getatr(char *inbuf
,char *outbuf
)
585 BOOL bad_path
= False
;
587 cnum
= SVAL(inbuf
,smb_tid
);
589 strcpy(fname
,smb_buf(inbuf
) + 1);
590 unix_convert(fname
,cnum
,0,&bad_path
);
592 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
593 under WfWg - weird! */
596 mode
= aHIDDEN
| aDIR
;
597 if (!CAN_WRITE(cnum
)) mode
|= aRONLY
;
603 if (check_name(fname
,cnum
))
605 if (sys_stat(fname
,&sbuf
) == 0)
607 mode
= dos_mode(cnum
,fname
,&sbuf
);
609 mtime
= sbuf
.st_mtime
;
615 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
620 if((errno
== ENOENT
) && bad_path
)
622 unix_ERR_class
= ERRDOS
;
623 unix_ERR_code
= ERRbadpath
;
626 return(UNIXERROR(ERRDOS
,ERRbadfile
));
629 outsize
= set_message(outbuf
,10,0,True
);
631 SSVAL(outbuf
,smb_vwv0
,mode
);
632 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
633 SIVAL(outbuf
,smb_vwv3
,size
);
635 if (Protocol
>= PROTOCOL_NT1
) {
636 char *p
= strrchr(fname
,'/');
637 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
639 if (!is_8_3(fname
, True
))
640 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
643 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname
,mode
,size
));
649 /****************************************************************************
651 ****************************************************************************/
652 int reply_setatr(char *inbuf
,char *outbuf
)
660 BOOL bad_path
= False
;
662 cnum
= SVAL(inbuf
,smb_tid
);
664 strcpy(fname
,smb_buf(inbuf
) + 1);
665 unix_convert(fname
,cnum
,0,&bad_path
);
667 mode
= SVAL(inbuf
,smb_vwv0
);
668 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
670 if (directory_exist(fname
,NULL
))
672 if (check_name(fname
,cnum
))
673 ok
= (dos_chmod(cnum
,fname
,mode
,NULL
) == 0);
675 ok
= set_filetime(fname
,mtime
);
679 if((errno
== ENOENT
) && bad_path
)
681 unix_ERR_class
= ERRDOS
;
682 unix_ERR_code
= ERRbadpath
;
685 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
688 outsize
= set_message(outbuf
,0,0,True
);
690 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname
,mode
));
696 /****************************************************************************
698 ****************************************************************************/
699 int reply_dskattr(char *inbuf
,char *outbuf
)
703 int dfree
,dsize
,bsize
;
705 cnum
= SVAL(inbuf
,smb_tid
);
707 sys_disk_free(".",&bsize
,&dfree
,&dsize
);
709 outsize
= set_message(outbuf
,5,0,True
);
711 SSVAL(outbuf
,smb_vwv0
,dsize
);
712 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
713 SSVAL(outbuf
,smb_vwv2
,512);
714 SSVAL(outbuf
,smb_vwv3
,dfree
);
716 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum
,dfree
));
722 /****************************************************************************
724 Can be called from SMBsearch, SMBffirst or SMBfunique.
725 ****************************************************************************/
726 int reply_search(char *inbuf
,char *outbuf
)
737 BOOL finished
= False
;
746 BOOL check_descend
= False
;
747 BOOL expect_close
= False
;
748 BOOL can_open
= True
;
749 BOOL bad_path
= False
;
751 *mask
= *directory
= *fname
= 0;
753 /* If we were called as SMBffirst then we must expect close. */
754 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
757 cnum
= SVAL(inbuf
,smb_tid
);
759 outsize
= set_message(outbuf
,1,3,True
);
760 maxentries
= SVAL(inbuf
,smb_vwv0
);
761 dirtype
= SVAL(inbuf
,smb_vwv1
);
762 path
= smb_buf(inbuf
) + 1;
763 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
766 /* dirtype &= ~aDIR; */
768 DEBUG(5,("path=%s status_len=%d\n",path
,status_len
));
775 strcpy(directory
,smb_buf(inbuf
)+1);
776 strcpy(dir2
,smb_buf(inbuf
)+1);
777 unix_convert(directory
,cnum
,0,&bad_path
);
780 if (!check_name(directory
,cnum
))
783 p
= strrchr(dir2
,'/');
795 p
= strrchr(directory
,'/');
801 if (strlen(directory
) == 0)
802 strcpy(directory
,"./");
804 CVAL(status
,0) = dirtype
;
808 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
809 memcpy(mask
,status
+1,11);
811 dirtype
= CVAL(status
,0) & 0x1F;
812 Connections
[cnum
].dirptr
= dptr_fetch(status
+12,&dptr_num
);
813 if (!Connections
[cnum
].dirptr
)
815 string_set(&Connections
[cnum
].dirpath
,dptr_path(dptr_num
));
820 /* turn strings of spaces into a . */
822 trim_string(mask
,NULL
," ");
823 if ((p
= strrchr(mask
,' ')))
828 trim_string(mask
,NULL
," ");
835 for (p
=mask
; *p
; p
++)
837 if (*p
!= '?' && *p
!= '*' && !isdoschar(*p
))
839 DEBUG(5,("Invalid char [%c] in search mask?\n",*p
));
845 if (!strchr(mask
,'.') && strlen(mask
)>8)
848 strcpy(tmp
,&mask
[8]);
854 DEBUG(5,("mask=%s directory=%s\n",mask
,directory
));
858 p
= smb_buf(outbuf
) + 3;
864 dptr_num
= dptr_create(cnum
,directory
,expect_close
,SVAL(inbuf
,smb_pid
));
869 if((errno
== ENOENT
) && bad_path
)
871 unix_ERR_class
= ERRDOS
;
872 unix_ERR_code
= ERRbadpath
;
874 return (UNIXERROR(ERRDOS
,ERRnofids
));
876 return(ERROR(ERRDOS
,ERRnofids
));
880 DEBUG(4,("dptr_num is %d\n",dptr_num
));
884 if ((dirtype
&0x1F) == aVOLID
)
887 make_dir_struct(p
,"???????????",volume_label(SNUM(cnum
)),0,aVOLID
,0);
888 dptr_fill(p
+12,dptr_num
);
889 if (dptr_zero(p
+12) && (status_len
==0))
893 p
+= DIR_STRUCT_SIZE
;
897 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections
[cnum
].dirpath
,lp_dontdescend(SNUM(cnum
))));
898 if (in_list(Connections
[cnum
].dirpath
,
899 lp_dontdescend(SNUM(cnum
)),True
))
900 check_descend
= True
;
902 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
905 !get_dir_entry(cnum
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
909 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
910 dptr_fill(p
+12,dptr_num
);
913 p
+= DIR_STRUCT_SIZE
;
922 if (numentries
== 0 || !ok
)
924 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
925 SSVAL(outbuf
,smb_err
,ERRnofiles
);
928 /* If we were called as SMBffirst with smb_search_id == NULL
929 and no entries were found then return error and close dirptr
932 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
934 CVAL(outbuf
,smb_rcls
) = ERRDOS
;
935 SSVAL(outbuf
,smb_err
,ERRnofiles
);
936 /* Also close the dptr - we know it's gone */
937 dptr_close(dptr_num
);
940 /* If we were called as SMBfunique, then we can close the dirptr now ! */
941 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
942 dptr_close(dptr_num
);
944 SSVAL(outbuf
,smb_vwv0
,numentries
);
945 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
946 CVAL(smb_buf(outbuf
),0) = 5;
947 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
949 if (Protocol
>= PROTOCOL_NT1
) {
950 uint16 flg2
= SVAL(outbuf
,smb_flg2
);
951 SSVAL(outbuf
,smb_flg2
,flg2
| 0x40); /* IS_LONG_NAME */
954 outsize
+= DIR_STRUCT_SIZE
*numentries
;
955 smb_setlen(outbuf
,outsize
- 4);
957 if ((! *directory
) && dptr_path(dptr_num
))
958 sprintf(directory
,"(%s)",dptr_path(dptr_num
));
960 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
962 smb_fn_name(CVAL(inbuf
,smb_com
)),
963 mask
,directory
,cnum
,dirtype
,numentries
,maxentries
));
969 /****************************************************************************
970 reply to a fclose (stop directory search)
971 ****************************************************************************/
972 int reply_fclose(char *inbuf
,char *outbuf
)
981 cnum
= SVAL(inbuf
,smb_tid
);
983 outsize
= set_message(outbuf
,1,0,True
);
984 path
= smb_buf(inbuf
) + 1;
985 status_len
= SVAL(smb_buf(inbuf
),3 + strlen(path
));
989 return(ERROR(ERRSRV
,ERRsrverror
));
991 memcpy(status
,smb_buf(inbuf
) + 1 + strlen(path
) + 4,21);
993 if(dptr_fetch(status
+12,&dptr_num
)) {
994 /* Close the dptr - we know it's gone */
995 dptr_close(dptr_num
);
998 SSVAL(outbuf
,smb_vwv0
,0);
1000 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum
));
1006 /****************************************************************************
1008 ****************************************************************************/
1009 int reply_open(char *inbuf
,char *outbuf
)
1022 BOOL bad_path
= False
;
1024 cnum
= SVAL(inbuf
,smb_tid
);
1026 share_mode
= SVAL(inbuf
,smb_vwv0
);
1028 strcpy(fname
,smb_buf(inbuf
)+1);
1029 unix_convert(fname
,cnum
,0,&bad_path
);
1031 fnum
= find_free_file();
1033 return(ERROR(ERRSRV
,ERRnofids
));
1035 if (!check_name(fname
,cnum
))
1037 if((errno
== ENOENT
) && bad_path
)
1039 unix_ERR_class
= ERRDOS
;
1040 unix_ERR_code
= ERRbadpath
;
1042 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1045 unixmode
= unix_mode(cnum
,aARCH
);
1047 open_file_shared(fnum
,cnum
,fname
,share_mode
,3,unixmode
,&rmode
,NULL
);
1049 if (!Files
[fnum
].open
)
1051 if((errno
== ENOENT
) && bad_path
)
1053 unix_ERR_class
= ERRDOS
;
1054 unix_ERR_code
= ERRbadpath
;
1056 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1059 if (fstat(Files
[fnum
].fd_ptr
->fd
,&sbuf
) != 0) {
1061 return(ERROR(ERRDOS
,ERRnoaccess
));
1064 size
= sbuf
.st_size
;
1065 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1066 mtime
= sbuf
.st_mtime
;
1069 DEBUG(3,("attempt to open a directory %s\n",fname
));
1071 return(ERROR(ERRDOS
,ERRnoaccess
));
1074 outsize
= set_message(outbuf
,7,0,True
);
1075 SSVAL(outbuf
,smb_vwv0
,fnum
);
1076 SSVAL(outbuf
,smb_vwv1
,fmode
);
1077 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
1078 SIVAL(outbuf
,smb_vwv4
,size
);
1079 SSVAL(outbuf
,smb_vwv6
,rmode
);
1081 if (lp_fake_oplocks(SNUM(cnum
))) {
1082 CVAL(outbuf
,smb_flg
) |= (CVAL(inbuf
,smb_flg
) & (1<<5));
1089 /****************************************************************************
1090 reply to an open and X
1091 ****************************************************************************/
1092 int reply_open_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1095 int cnum
= SVAL(inbuf
,smb_tid
);
1097 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
1098 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
1099 BOOL oplock_request
= BITSETW(inbuf
+smb_vwv2
,1);
1101 int open_flags
= SVAL(inbuf
,smb_vwv2
);
1102 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
1103 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
1105 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
1107 int size
=0,fmode
=0,mtime
=0,rmode
=0;
1110 BOOL bad_path
= False
;
1112 /* If it's an IPC, pass off the pipe handler. */
1114 return reply_open_pipe_and_X(inbuf
,outbuf
,length
,bufsize
);
1116 /* XXXX we need to handle passed times, sattr and flags */
1118 strcpy(fname
,smb_buf(inbuf
));
1119 unix_convert(fname
,cnum
,0,&bad_path
);
1121 fnum
= find_free_file();
1123 return(ERROR(ERRSRV
,ERRnofids
));
1125 if (!check_name(fname
,cnum
))
1127 if((errno
== ENOENT
) && bad_path
)
1129 unix_ERR_class
= ERRDOS
;
1130 unix_ERR_code
= ERRbadpath
;
1132 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1135 unixmode
= unix_mode(cnum
,smb_attr
| aARCH
);
1137 open_file_shared(fnum
,cnum
,fname
,smb_mode
,smb_ofun
,unixmode
,
1138 &rmode
,&smb_action
);
1140 if (!Files
[fnum
].open
)
1142 if((errno
== ENOENT
) && bad_path
)
1144 unix_ERR_class
= ERRDOS
;
1145 unix_ERR_code
= ERRbadpath
;
1147 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1150 if (fstat(Files
[fnum
].fd_ptr
->fd
,&sbuf
) != 0) {
1152 return(ERROR(ERRDOS
,ERRnoaccess
));
1155 size
= sbuf
.st_size
;
1156 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1157 mtime
= sbuf
.st_mtime
;
1160 return(ERROR(ERRDOS
,ERRnoaccess
));
1163 if (oplock_request
&& lp_fake_oplocks(SNUM(cnum
))) {
1164 smb_action
|= (1<<15);
1167 set_message(outbuf
,15,0,True
);
1168 SSVAL(outbuf
,smb_vwv2
,fnum
);
1169 SSVAL(outbuf
,smb_vwv3
,fmode
);
1170 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1171 SIVAL(outbuf
,smb_vwv6
,size
);
1172 SSVAL(outbuf
,smb_vwv8
,rmode
);
1173 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1177 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1181 /****************************************************************************
1182 reply to a SMBulogoffX
1183 ****************************************************************************/
1184 int reply_ulogoffX(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1186 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1187 user_struct
*vuser
= get_valid_user_struct(vuid
);
1190 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1193 /* in user level security we are supposed to close any files
1194 open by this user */
1195 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1197 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
1198 if (Files
[i
].uid
== vuser
->uid
&& Files
[i
].open
) {
1203 invalidate_vuid(vuid
);
1205 set_message(outbuf
,2,0,True
);
1207 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid
));
1209 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1213 /****************************************************************************
1214 reply to a mknew or a create
1215 ****************************************************************************/
1216 int reply_mknew(char *inbuf
,char *outbuf
)
1225 BOOL bad_path
= False
;
1227 com
= SVAL(inbuf
,smb_com
);
1228 cnum
= SVAL(inbuf
,smb_tid
);
1230 createmode
= SVAL(inbuf
,smb_vwv0
);
1231 strcpy(fname
,smb_buf(inbuf
)+1);
1232 unix_convert(fname
,cnum
,0,&bad_path
);
1234 if (createmode
& aVOLID
)
1236 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1239 unixmode
= unix_mode(cnum
,createmode
);
1241 fnum
= find_free_file();
1243 return(ERROR(ERRSRV
,ERRnofids
));
1245 if (!check_name(fname
,cnum
))
1247 if((errno
== ENOENT
) && bad_path
)
1249 unix_ERR_class
= ERRDOS
;
1250 unix_ERR_code
= ERRbadpath
;
1252 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1257 /* We should fail if file exists. */
1262 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1266 /* Open file in dos compatibility share mode. */
1267 open_file_shared(fnum
,cnum
,fname
,(DENY_FCB
<<4)|0xF, ofun
, unixmode
, NULL
, NULL
);
1269 if (!Files
[fnum
].open
)
1271 if((errno
== ENOENT
) && bad_path
)
1273 unix_ERR_class
= ERRDOS
;
1274 unix_ERR_code
= ERRbadpath
;
1276 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1279 outsize
= set_message(outbuf
,1,0,True
);
1280 SSVAL(outbuf
,smb_vwv0
,fnum
);
1282 if (lp_fake_oplocks(SNUM(cnum
))) {
1283 CVAL(outbuf
,smb_flg
) |= (CVAL(inbuf
,smb_flg
) & (1<<5));
1286 DEBUG(2,("new file %s\n",fname
));
1287 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
));
1293 /****************************************************************************
1294 reply to a create temporary file
1295 ****************************************************************************/
1296 int reply_ctemp(char *inbuf
,char *outbuf
)
1305 BOOL bad_path
= False
;
1307 cnum
= SVAL(inbuf
,smb_tid
);
1308 createmode
= SVAL(inbuf
,smb_vwv0
);
1309 sprintf(fname
,"%s/TMXXXXXX",smb_buf(inbuf
)+1);
1310 unix_convert(fname
,cnum
,0,&bad_path
);
1312 unixmode
= unix_mode(cnum
,createmode
);
1314 fnum
= find_free_file();
1316 return(ERROR(ERRSRV
,ERRnofids
));
1318 if (!check_name(fname
,cnum
))
1320 if((errno
== ENOENT
) && bad_path
)
1322 unix_ERR_class
= ERRDOS
;
1323 unix_ERR_code
= ERRbadpath
;
1325 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1328 strcpy(fname2
,(char *)mktemp(fname
));
1330 /* Open file in dos compatibility share mode. */
1331 /* We should fail if file exists. */
1332 open_file_shared(fnum
,cnum
,fname2
,(DENY_FCB
<<4)|0xF, 0x10, unixmode
, NULL
, NULL
);
1334 if (!Files
[fnum
].open
)
1336 if((errno
== ENOENT
) && bad_path
)
1338 unix_ERR_class
= ERRDOS
;
1339 unix_ERR_code
= ERRbadpath
;
1341 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1344 outsize
= set_message(outbuf
,1,2 + strlen(fname2
),True
);
1345 SSVAL(outbuf
,smb_vwv0
,fnum
);
1346 CVAL(smb_buf(outbuf
),0) = 4;
1347 strcpy(smb_buf(outbuf
) + 1,fname2
);
1349 if (lp_fake_oplocks(SNUM(cnum
))) {
1350 CVAL(outbuf
,smb_flg
) |= (CVAL(inbuf
,smb_flg
) & (1<<5));
1353 DEBUG(2,("created temp file %s\n",fname2
));
1354 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
));
1360 /*******************************************************************
1361 check if a user is allowed to delete a file
1362 ********************************************************************/
1363 static BOOL
can_delete(char *fname
,int cnum
,int dirtype
)
1368 if (!CAN_WRITE(cnum
)) return(False
);
1370 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
1371 fmode
= dos_mode(cnum
,fname
,&sbuf
);
1372 if (fmode
& aDIR
) return(False
);
1373 if (!lp_delete_readonly(SNUM(cnum
))) {
1374 if (fmode
& aRONLY
) return(False
);
1376 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1378 if (!check_file_sharing(cnum
,fname
)) return(False
);
1382 /****************************************************************************
1384 ****************************************************************************/
1385 int reply_unlink(char *inbuf
,char *outbuf
)
1395 int error
= ERRnoaccess
;
1398 BOOL bad_path
= False
;
1400 *directory
= *mask
= 0;
1402 cnum
= SVAL(inbuf
,smb_tid
);
1403 dirtype
= SVAL(inbuf
,smb_vwv0
);
1405 strcpy(name
,smb_buf(inbuf
) + 1);
1407 DEBUG(3,("reply_unlink : %s\n",name
));
1409 unix_convert(name
,cnum
,0,&bad_path
);
1411 p
= strrchr(name
,'/');
1413 strcpy(directory
,"./");
1417 strcpy(directory
,name
);
1421 if (is_mangled(mask
))
1422 check_mangled_stack(mask
);
1424 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
1427 strcat(directory
,"/");
1428 strcat(directory
,mask
);
1429 if (can_delete(directory
,cnum
,dirtype
) && !sys_unlink(directory
)) count
++;
1430 if (!count
) exists
= file_exist(directory
,NULL
);
1432 void *dirptr
= NULL
;
1435 if (check_name(directory
,cnum
))
1436 dirptr
= OpenDir(cnum
, directory
, True
);
1438 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1439 the pattern matches against the long name, otherwise the short name
1440 We don't implement this yet XXXX
1447 if (strequal(mask
,"????????.???"))
1450 while ((dname
= ReadDirName(dirptr
)))
1453 strcpy(fname
,dname
);
1455 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
1457 error
= ERRnoaccess
;
1458 sprintf(fname
,"%s/%s",directory
,dname
);
1459 if (!can_delete(fname
,cnum
,dirtype
)) continue;
1460 if (!sys_unlink(fname
)) count
++;
1461 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname
));
1469 return(ERROR(ERRDOS
,error
));
1472 if((errno
== ENOENT
) && bad_path
)
1474 unix_ERR_class
= ERRDOS
;
1475 unix_ERR_code
= ERRbadpath
;
1477 return(UNIXERROR(ERRDOS
,error
));
1481 outsize
= set_message(outbuf
,0,0,True
);
1487 /****************************************************************************
1488 reply to a readbraw (core+ protocol)
1489 ****************************************************************************/
1490 int reply_readbraw(char *inbuf
, char *outbuf
)
1492 int cnum
,maxcount
,mincount
,fnum
;
1495 char *header
= outbuf
;
1500 cnum
= SVAL(inbuf
,smb_tid
);
1501 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1503 startpos
= IVAL(inbuf
,smb_vwv1
);
1504 maxcount
= SVAL(inbuf
,smb_vwv3
);
1505 mincount
= SVAL(inbuf
,smb_vwv4
);
1507 /* ensure we don't overrun the packet size */
1508 maxcount
= MIN(65535,maxcount
);
1509 maxcount
= MAX(mincount
,maxcount
);
1511 if (!FNUM_OK(fnum
,cnum
) || !Files
[fnum
].can_read
)
1513 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum
));
1514 _smb_setlen(header
,0);
1515 transfer_file(0,Client
,0,header
,4,0);
1520 fd
= Files
[fnum
].fd_ptr
->fd
;
1521 fname
= Files
[fnum
].name
;
1525 if (!is_locked(fnum
,cnum
,maxcount
,startpos
))
1527 int size
= Files
[fnum
].size
;
1528 int sizeneeded
= startpos
+ maxcount
;
1530 if (size
< sizeneeded
) {
1532 if (fstat(Files
[fnum
].fd_ptr
->fd
,&st
) == 0)
1534 if (!Files
[fnum
].can_write
)
1535 Files
[fnum
].size
= size
;
1538 nread
= MIN(maxcount
,(int)(size
- startpos
));
1541 if (nread
< mincount
)
1544 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1547 maxcount
,mincount
,nread
));
1552 _smb_setlen(header
,nread
);
1554 if (!Files
[fnum
].can_write
)
1555 predict
= read_predict(fd
,startpos
,header
+4,NULL
,nread
);
1557 if ((nread
-predict
) > 0)
1558 seek_file(fnum
,startpos
+ predict
);
1560 ret
= transfer_file(fd
,Client
,nread
-predict
,header
,4+predict
,
1565 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1566 fname
,startpos
,nread
,ret
));
1569 ret
= read_file(fnum
,header
+4,startpos
,nread
);
1570 if (ret
< mincount
) ret
= 0;
1572 _smb_setlen(header
,ret
);
1573 transfer_file(0,Client
,0,header
,4+ret
,0);
1576 DEBUG(5,("readbraw finished\n"));
1581 /****************************************************************************
1582 reply to a lockread (core+ protocol)
1583 ****************************************************************************/
1584 int reply_lockread(char *inbuf
,char *outbuf
)
1590 uint32 startpos
, numtoread
;
1594 cnum
= SVAL(inbuf
,smb_tid
);
1595 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1597 CHECK_FNUM(fnum
,cnum
);
1601 numtoread
= SVAL(inbuf
,smb_vwv1
);
1602 startpos
= IVAL(inbuf
,smb_vwv2
);
1604 outsize
= set_message(outbuf
,5,3,True
);
1605 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1606 data
= smb_buf(outbuf
) + 3;
1608 if(!do_lock( fnum
, cnum
, numtoread
, startpos
, &eclass
, &ecode
))
1609 return (ERROR(eclass
,ecode
));
1611 nread
= read_file(fnum
,data
,startpos
,numtoread
);
1614 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1617 SSVAL(outbuf
,smb_vwv0
,nread
);
1618 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1619 SSVAL(smb_buf(outbuf
),1,nread
);
1621 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum
,cnum
,numtoread
,nread
));
1627 /****************************************************************************
1629 ****************************************************************************/
1630 int reply_read(char *inbuf
,char *outbuf
)
1632 int cnum
,numtoread
,fnum
;
1638 cnum
= SVAL(inbuf
,smb_tid
);
1639 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1641 CHECK_FNUM(fnum
,cnum
);
1645 numtoread
= SVAL(inbuf
,smb_vwv1
);
1646 startpos
= IVAL(inbuf
,smb_vwv2
);
1648 outsize
= set_message(outbuf
,5,3,True
);
1649 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1650 data
= smb_buf(outbuf
) + 3;
1652 if (is_locked(fnum
,cnum
,numtoread
,startpos
))
1653 return(ERROR(ERRDOS
,ERRlock
));
1656 nread
= read_file(fnum
,data
,startpos
,numtoread
);
1659 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1662 SSVAL(outbuf
,smb_vwv0
,nread
);
1663 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1664 CVAL(smb_buf(outbuf
),0) = 1;
1665 SSVAL(smb_buf(outbuf
),1,nread
);
1667 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum
,cnum
,numtoread
,nread
));
1673 /****************************************************************************
1674 reply to a read and X
1675 ****************************************************************************/
1676 int reply_read_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1678 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
1679 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
1680 int smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
1681 int smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
1687 cnum
= SVAL(inbuf
,smb_tid
);
1689 CHECK_FNUM(fnum
,cnum
);
1693 set_message(outbuf
,12,0,True
);
1694 data
= smb_buf(outbuf
);
1696 if (is_locked(fnum
,cnum
,smb_maxcnt
,smb_offs
))
1697 return(ERROR(ERRDOS
,ERRlock
));
1698 nread
= read_file(fnum
,data
,smb_offs
,smb_maxcnt
);
1702 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1704 SSVAL(outbuf
,smb_vwv5
,nread
);
1705 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
1706 SSVAL(smb_buf(outbuf
),-2,nread
);
1708 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1709 timestring(),fnum
,cnum
,
1710 smb_mincnt
,smb_maxcnt
,nread
));
1714 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1718 /****************************************************************************
1719 reply to a writebraw (core+ or LANMAN1.0 protocol)
1720 ****************************************************************************/
1721 int reply_writebraw(char *inbuf
,char *outbuf
)
1724 int total_written
=0;
1733 cnum
= SVAL(inbuf
,smb_tid
);
1734 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1736 CHECK_FNUM(fnum
,cnum
);
1740 tcount
= IVAL(inbuf
,smb_vwv1
);
1741 startpos
= IVAL(inbuf
,smb_vwv3
);
1742 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
1744 /* We have to deal with slightly different formats depending
1745 on whether we are using the core+ or lanman1.0 protocol */
1746 if(Protocol
<= PROTOCOL_COREPLUS
) {
1747 numtowrite
= SVAL(smb_buf(inbuf
),-2);
1748 data
= smb_buf(inbuf
);
1750 numtowrite
= SVAL(inbuf
,smb_vwv10
);
1751 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
1754 /* force the error type */
1755 CVAL(inbuf
,smb_com
) = SMBwritec
;
1756 CVAL(outbuf
,smb_com
) = SMBwritec
;
1758 if (is_locked(fnum
,cnum
,tcount
,startpos
))
1759 return(ERROR(ERRDOS
,ERRlock
));
1761 if (seek_file(fnum
,startpos
) != startpos
)
1762 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos
));
1765 nwritten
= write_file(fnum
,data
,numtowrite
);
1767 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1768 timestring(),fnum
,cnum
,startpos
,numtowrite
,nwritten
,write_through
));
1770 if (nwritten
< numtowrite
)
1771 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
1773 total_written
= nwritten
;
1775 /* Return a message to the redirector to tell it
1776 to send more bytes */
1777 CVAL(outbuf
,smb_com
) = SMBwritebraw
;
1778 SSVALS(outbuf
,smb_vwv0
,-1);
1779 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
1780 send_smb(Client
,outbuf
);
1782 /* Now read the raw data into the buffer and write it */
1783 if (read_smb_length(Client
,inbuf
,SMB_SECONDARY_WAIT
) == -1) {
1784 exit_server("secondary writebraw failed");
1787 /* Even though this is not an smb message, smb_len
1788 returns the generic length of an smb message */
1789 numtowrite
= smb_len(inbuf
);
1791 if (tcount
> nwritten
+numtowrite
) {
1792 DEBUG(3,("Client overestimated the write %d %d %d\n",
1793 tcount
,nwritten
,numtowrite
));
1796 nwritten
= transfer_file(Client
,Files
[fnum
].fd_ptr
->fd
,numtowrite
,NULL
,0,
1798 total_written
+= nwritten
;
1800 /* Set up outbuf to return the correct return */
1801 outsize
= set_message(outbuf
,1,0,True
);
1802 CVAL(outbuf
,smb_com
) = SMBwritec
;
1803 SSVAL(outbuf
,smb_vwv0
,total_written
);
1805 if (nwritten
< numtowrite
) {
1806 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1807 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1810 if (lp_syncalways(SNUM(cnum
)) || write_through
)
1813 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1814 timestring(),fnum
,cnum
,startpos
,numtowrite
,total_written
));
1816 /* we won't return a status if write through is not selected - this
1817 follows what WfWg does */
1818 if (!write_through
&& total_written
==tcount
)
1825 /****************************************************************************
1826 reply to a writeunlock (core+)
1827 ****************************************************************************/
1828 int reply_writeunlock(char *inbuf
,char *outbuf
)
1834 uint32 numtowrite
,startpos
;
1838 cnum
= SVAL(inbuf
,smb_tid
);
1839 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1841 CHECK_FNUM(fnum
,cnum
);
1845 numtowrite
= SVAL(inbuf
,smb_vwv1
);
1846 startpos
= IVAL(inbuf
,smb_vwv2
);
1847 data
= smb_buf(inbuf
) + 3;
1849 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
1850 return(ERROR(ERRDOS
,ERRlock
));
1852 seek_file(fnum
,startpos
);
1854 /* The special X/Open SMB protocol handling of
1855 zero length writes is *NOT* done for
1860 nwritten
= write_file(fnum
,data
,numtowrite
);
1862 if (lp_syncalways(SNUM(cnum
)))
1865 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
1866 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1868 if(!do_unlock(fnum
, cnum
, numtowrite
, startpos
, &eclass
, &ecode
))
1869 return(ERROR(eclass
,ecode
));
1871 outsize
= set_message(outbuf
,1,0,True
);
1873 SSVAL(outbuf
,smb_vwv0
,nwritten
);
1875 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1876 timestring(),fnum
,cnum
,numtowrite
,nwritten
));
1882 /****************************************************************************
1884 ****************************************************************************/
1885 int reply_write(char *inbuf
,char *outbuf
,int dum1
,int dum2
)
1887 int cnum
,numtowrite
,fnum
;
1896 cnum
= SVAL(inbuf
,smb_tid
);
1897 fnum
= GETFNUM(inbuf
,smb_vwv0
);
1899 CHECK_FNUM(fnum
,cnum
);
1903 numtowrite
= SVAL(inbuf
,smb_vwv1
);
1904 startpos
= IVAL(inbuf
,smb_vwv2
);
1905 data
= smb_buf(inbuf
) + 3;
1907 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
1908 return(ERROR(ERRDOS
,ERRlock
));
1910 seek_file(fnum
,startpos
);
1912 /* X/Open SMB protocol says that if smb_vwv1 is
1913 zero then the file size should be extended or
1914 truncated to the size given in smb_vwv[2-3] */
1916 nwritten
= set_filelen(Files
[fnum
].fd_ptr
->fd
, startpos
);
1918 nwritten
= write_file(fnum
,data
,numtowrite
);
1920 if (lp_syncalways(SNUM(cnum
)))
1923 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0))
1924 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1926 outsize
= set_message(outbuf
,1,0,True
);
1928 SSVAL(outbuf
,smb_vwv0
,nwritten
);
1930 if (nwritten
< numtowrite
) {
1931 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1932 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1935 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum
,cnum
,numtowrite
,nwritten
));
1941 /****************************************************************************
1942 reply to a write and X
1943 ****************************************************************************/
1944 int reply_write_and_X(char *inbuf
,char *outbuf
,int length
,int bufsize
)
1946 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
1947 uint32 smb_offs
= IVAL(inbuf
,smb_vwv3
);
1948 int smb_dsize
= SVAL(inbuf
,smb_vwv10
);
1949 int smb_doff
= SVAL(inbuf
,smb_vwv11
);
1950 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
1955 cnum
= SVAL(inbuf
,smb_tid
);
1957 CHECK_FNUM(fnum
,cnum
);
1961 data
= smb_base(inbuf
) + smb_doff
;
1963 if (is_locked(fnum
,cnum
,smb_dsize
,smb_offs
))
1964 return(ERROR(ERRDOS
,ERRlock
));
1966 seek_file(fnum
,smb_offs
);
1968 /* X/Open SMB protocol says that, unlike SMBwrite
1969 if the length is zero then NO truncation is
1970 done, just a write of zero. To truncate a file,
1975 nwritten
= write_file(fnum
,data
,smb_dsize
);
1977 if(((nwritten
== 0) && (smb_dsize
!= 0))||(nwritten
< 0))
1978 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1980 set_message(outbuf
,6,0,True
);
1982 SSVAL(outbuf
,smb_vwv2
,nwritten
);
1984 if (nwritten
< smb_dsize
) {
1985 CVAL(outbuf
,smb_rcls
) = ERRHRD
;
1986 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1989 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum
,cnum
,smb_dsize
,nwritten
));
1993 if (lp_syncalways(SNUM(cnum
)) || write_through
)
1996 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2000 /****************************************************************************
2002 ****************************************************************************/
2003 int reply_lseek(char *inbuf
,char *outbuf
)
2011 cnum
= SVAL(inbuf
,smb_tid
);
2012 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2014 CHECK_FNUM(fnum
,cnum
);
2017 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2018 startpos
= IVAL(inbuf
,smb_vwv2
);
2022 case 0: umode
= SEEK_SET
; break;
2023 case 1: umode
= SEEK_CUR
; break;
2024 case 2: umode
= SEEK_END
; break;
2026 umode
= SEEK_SET
; break;
2029 res
= lseek(Files
[fnum
].fd_ptr
->fd
,startpos
,umode
);
2030 Files
[fnum
].pos
= res
;
2032 outsize
= set_message(outbuf
,2,0,True
);
2033 SIVALS(outbuf
,smb_vwv0
,res
);
2035 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum
,cnum
,startpos
,mode
));
2041 /****************************************************************************
2043 ****************************************************************************/
2044 int reply_flush(char *inbuf
,char *outbuf
)
2047 int outsize
= set_message(outbuf
,0,0,True
);
2049 cnum
= SVAL(inbuf
,smb_tid
);
2050 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2052 if (fnum
!= 0xFFFF) {
2053 CHECK_FNUM(fnum
,cnum
);
2060 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
2067 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum
));
2072 /****************************************************************************
2074 ****************************************************************************/
2075 int reply_exit(char *inbuf
,char *outbuf
)
2077 int outsize
= set_message(outbuf
,0,0,True
);
2078 DEBUG(3,("%s exit\n",timestring()));
2084 /****************************************************************************
2086 ****************************************************************************/
2087 int reply_close(char *inbuf
,char *outbuf
)
2092 int32 eclass
= 0, err
= 0;
2094 outsize
= set_message(outbuf
,0,0,True
);
2096 cnum
= SVAL(inbuf
,smb_tid
);
2098 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2099 CHECK_FNUM(fnum
,cnum
);
2101 if(HAS_CACHED_ERROR(fnum
)) {
2102 eclass
= Files
[fnum
].wbmpx_ptr
->wr_errclass
;
2103 err
= Files
[fnum
].wbmpx_ptr
->wr_error
;
2106 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2108 /* try and set the date */
2109 set_filetime(Files
[fnum
].name
,mtime
);
2113 /* We have a cached error */
2115 return(ERROR(eclass
,err
));
2117 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2118 timestring(),Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
,
2119 Connections
[cnum
].num_files_open
));
2125 /****************************************************************************
2126 reply to a writeclose (Core+ protocol)
2127 ****************************************************************************/
2128 int reply_writeclose(char *inbuf
,char *outbuf
)
2130 int cnum
,numtowrite
,fnum
;
2137 cnum
= SVAL(inbuf
,smb_tid
);
2138 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2140 CHECK_FNUM(fnum
,cnum
);
2144 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2145 startpos
= IVAL(inbuf
,smb_vwv2
);
2146 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2147 data
= smb_buf(inbuf
) + 1;
2149 if (is_locked(fnum
,cnum
,numtowrite
,startpos
))
2150 return(ERROR(ERRDOS
,ERRlock
));
2152 seek_file(fnum
,startpos
);
2154 nwritten
= write_file(fnum
,data
,numtowrite
);
2156 set_filetime(Files
[fnum
].name
,mtime
);
2160 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2161 timestring(),fnum
,cnum
,numtowrite
,nwritten
,
2162 Connections
[cnum
].num_files_open
));
2165 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2167 outsize
= set_message(outbuf
,1,0,True
);
2169 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2174 /****************************************************************************
2176 ****************************************************************************/
2177 int reply_lock(char *inbuf
,char *outbuf
)
2180 int outsize
= set_message(outbuf
,0,0,True
);
2181 uint32 count
,offset
;
2185 cnum
= SVAL(inbuf
,smb_tid
);
2186 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2188 CHECK_FNUM(fnum
,cnum
);
2191 count
= IVAL(inbuf
,smb_vwv1
);
2192 offset
= IVAL(inbuf
,smb_vwv3
);
2194 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
));
2196 if(!do_lock( fnum
, cnum
, count
, offset
, &eclass
, &ecode
))
2197 return (ERROR(eclass
,ecode
));
2203 /****************************************************************************
2205 ****************************************************************************/
2206 int reply_unlock(char *inbuf
,char *outbuf
)
2209 int outsize
= set_message(outbuf
,0,0,True
);
2210 uint32 count
,offset
;
2214 cnum
= SVAL(inbuf
,smb_tid
);
2215 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2217 CHECK_FNUM(fnum
,cnum
);
2220 count
= IVAL(inbuf
,smb_vwv1
);
2221 offset
= IVAL(inbuf
,smb_vwv3
);
2223 if(!do_unlock(fnum
, cnum
, count
, offset
, &eclass
, &ecode
))
2224 return (ERROR(eclass
,ecode
));
2226 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
));
2232 /****************************************************************************
2234 ****************************************************************************/
2235 int reply_tdis(char *inbuf
,char *outbuf
)
2238 int outsize
= set_message(outbuf
,0,0,True
);
2241 cnum
= SVAL(inbuf
,smb_tid
);
2242 vuid
= SVAL(inbuf
,smb_uid
);
2244 if (!OPEN_CNUM(cnum
)) {
2245 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum
));
2246 return(ERROR(ERRSRV
,ERRinvnid
));
2249 Connections
[cnum
].used
= False
;
2251 close_cnum(cnum
,vuid
);
2253 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum
));
2260 /****************************************************************************
2262 ****************************************************************************/
2263 int reply_echo(char *inbuf
,char *outbuf
)
2266 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2268 int data_len
= smb_buflen(inbuf
);
2269 int outsize
= set_message(outbuf
,1,data_len
,True
);
2271 cnum
= SVAL(inbuf
,smb_tid
);
2273 /* According to the latest CIFS spec we shouldn't
2274 care what the TID is.
2278 if (cnum
!= 0xFFFF && !OPEN_CNUM(cnum
))
2280 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum
));
2281 return(ERROR(ERRSRV
,ERRinvnid
));
2285 /* copy any incoming data back out */
2287 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2289 if (smb_reverb
> 100)
2291 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2295 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++)
2297 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2299 smb_setlen(outbuf
,outsize
- 4);
2301 send_smb(Client
,outbuf
);
2304 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb
,cnum
));
2310 /****************************************************************************
2311 reply to a printopen
2312 ****************************************************************************/
2313 int reply_printopen(char *inbuf
,char *outbuf
)
2321 *fname
= *fname2
= 0;
2323 cnum
= SVAL(inbuf
,smb_tid
);
2325 if (!CAN_PRINT(cnum
))
2326 return(ERROR(ERRDOS
,ERRnoaccess
));
2331 StrnCpy(s
,smb_buf(inbuf
)+1,sizeof(pstring
)-1);
2335 if (!(isalnum(*p
) || strchr("._-",*p
)))
2340 if (strlen(s
) > 10) s
[10] = 0;
2342 sprintf(fname
,"%s.XXXXXX",s
);
2345 fnum
= find_free_file();
2347 return(ERROR(ERRSRV
,ERRnofids
));
2349 strcpy(fname2
,(char *)mktemp(fname
));
2351 if (!check_name(fname2
,cnum
))
2352 return(ERROR(ERRDOS
,ERRnoaccess
));
2354 /* Open for exclusive use, write only. */
2355 open_file_shared(fnum
,cnum
,fname2
,(DENY_ALL
<<4)|1, 0x12, unix_mode(cnum
,0), NULL
, NULL
);
2357 if (!Files
[fnum
].open
)
2358 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2360 /* force it to be a print file */
2361 Files
[fnum
].print_file
= True
;
2363 outsize
= set_message(outbuf
,1,0,True
);
2364 SSVAL(outbuf
,smb_vwv0
,fnum
);
2366 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2
,Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
));
2372 /****************************************************************************
2373 reply to a printclose
2374 ****************************************************************************/
2375 int reply_printclose(char *inbuf
,char *outbuf
)
2378 int outsize
= set_message(outbuf
,0,0,True
);
2380 cnum
= SVAL(inbuf
,smb_tid
);
2381 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2383 CHECK_FNUM(fnum
,cnum
);
2386 if (!CAN_PRINT(cnum
))
2387 return(ERROR(ERRDOS
,ERRnoaccess
));
2391 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files
[fnum
].fd_ptr
->fd
,fnum
,cnum
));
2397 /****************************************************************************
2398 reply to a printqueue
2399 ****************************************************************************/
2400 int reply_printqueue(char *inbuf
,char *outbuf
)
2403 int outsize
= set_message(outbuf
,2,3,True
);
2404 int max_count
= SVAL(inbuf
,smb_vwv0
);
2405 int start_index
= SVAL(inbuf
,smb_vwv1
);
2408 cnum
= SVAL(inbuf
,smb_tid
);
2409 vuid
= SVAL(inbuf
,smb_uid
);
2411 /* allow checking the queue for anyone */
2413 if (!CAN_PRINT(cnum
))
2414 return(ERROR(ERRDOS
,ERRnoaccess
));
2417 SSVAL(outbuf
,smb_vwv0
,0);
2418 SSVAL(outbuf
,smb_vwv1
,0);
2419 CVAL(smb_buf(outbuf
),0) = 1;
2420 SSVAL(smb_buf(outbuf
),1,0);
2422 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2423 timestring(),cnum
,start_index
,max_count
));
2425 if (!OPEN_CNUM(cnum
) || !Connections
[cnum
].printer
)
2430 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2431 if (CAN_PRINT(i
) && Connections
[i
].printer
)
2435 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2439 if (!OPEN_CNUM(cnum
))
2440 return(ERROR(ERRSRV
,ERRinvnid
));
2442 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum
));
2445 if (!become_user(cnum
,vuid
))
2446 return(ERROR(ERRSRV
,ERRinvnid
));
2449 print_queue_struct
*queue
= NULL
;
2450 char *p
= smb_buf(outbuf
) + 3;
2451 int count
= get_printqueue(SNUM(cnum
),cnum
,&queue
,NULL
);
2452 int num_to_get
= ABS(max_count
);
2453 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
2459 num_to_get
= MIN(num_to_get
,count
-first
);
2462 for (i
=first
;i
<first
+num_to_get
;i
++)
2464 put_dos_date2(p
,0,queue
[i
].time
);
2465 CVAL(p
,4) = (queue
[i
].status
==LPQ_PRINTING
?2:3);
2466 SSVAL(p
,5,queue
[i
].job
);
2467 SIVAL(p
,7,queue
[i
].size
);
2469 StrnCpy(p
+12,queue
[i
].user
,16);
2475 outsize
= set_message(outbuf
,2,28*count
+3,False
);
2476 SSVAL(outbuf
,smb_vwv0
,count
);
2477 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
2478 CVAL(smb_buf(outbuf
),0) = 1;
2479 SSVAL(smb_buf(outbuf
),1,28*count
);
2482 if (queue
) free(queue
);
2484 DEBUG(3,("%d entries returned in queue\n",count
));
2491 /****************************************************************************
2492 reply to a printwrite
2493 ****************************************************************************/
2494 int reply_printwrite(char *inbuf
,char *outbuf
)
2496 int cnum
,numtowrite
,fnum
;
2497 int outsize
= set_message(outbuf
,0,0,True
);
2500 cnum
= SVAL(inbuf
,smb_tid
);
2502 if (!CAN_PRINT(cnum
))
2503 return(ERROR(ERRDOS
,ERRnoaccess
));
2505 fnum
= GETFNUM(inbuf
,smb_vwv0
);
2507 CHECK_FNUM(fnum
,cnum
);
2511 numtowrite
= SVAL(smb_buf(inbuf
),1);
2512 data
= smb_buf(inbuf
) + 3;
2514 if (write_file(fnum
,data
,numtowrite
) != numtowrite
)
2515 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2517 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum
,cnum
,numtowrite
));
2523 /****************************************************************************
2525 ****************************************************************************/
2526 int reply_mkdir(char *inbuf
,char *outbuf
)
2530 int outsize
,ret
= -1;
2531 BOOL bad_path
= False
;
2533 strcpy(directory
,smb_buf(inbuf
) + 1);
2534 cnum
= SVAL(inbuf
,smb_tid
);
2535 unix_convert(directory
,cnum
,0,&bad_path
);
2537 if (check_name(directory
,cnum
))
2538 ret
= sys_mkdir(directory
,unix_mode(cnum
,aDIR
));
2542 if((errno
== ENOENT
) && bad_path
)
2544 unix_ERR_class
= ERRDOS
;
2545 unix_ERR_code
= ERRbadpath
;
2547 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2550 outsize
= set_message(outbuf
,0,0,True
);
2552 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory
,cnum
,ret
));
2558 /****************************************************************************
2560 ****************************************************************************/
2561 int reply_rmdir(char *inbuf
,char *outbuf
)
2567 BOOL bad_path
= False
;
2569 cnum
= SVAL(inbuf
,smb_tid
);
2570 strcpy(directory
,smb_buf(inbuf
) + 1);
2571 unix_convert(directory
,cnum
,0,&bad_path
);
2573 if (check_name(directory
,cnum
))
2576 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
2577 ok
= (sys_rmdir(directory
) == 0);
2578 if(!ok
&& (errno
== ENOTEMPTY
) && lp_veto_files(SNUM(cnum
)))
2580 /* Check to see if the only thing in this directory are
2581 vetoed files/directories. If so then delete them and
2582 retry. If we fail to delete any of them (and we *don't*
2583 do a recursive delete) then fail the rmdir. */
2584 BOOL all_veto_files
= True
;
2586 void *dirptr
= OpenDir(cnum
, directory
, False
);
2590 int dirpos
= TellDir(dirptr
);
2591 while ((dname
= ReadDirName(dirptr
)))
2593 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2595 if(!IS_VETO_PATH(cnum
, dname
))
2597 all_veto_files
= False
;
2603 SeekDir(dirptr
,dirpos
);
2604 while ((dname
= ReadDirName(dirptr
)))
2609 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2612 /* Construct the full name. */
2613 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
))
2618 strcpy(fullname
, directory
);
2619 strcat(fullname
, "/");
2620 strcat(fullname
, dname
);
2622 if(sys_lstat(fullname
, &st
) != 0)
2624 if(st
.st_mode
& S_IFDIR
)
2626 if(sys_rmdir(fullname
) != 0)
2629 else if(sys_unlink(fullname
) != 0)
2633 /* Retry the rmdir */
2634 ok
= (sys_rmdir(directory
) == 0);
2644 DEBUG(3,("couldn't remove directory %s : %s\n",
2645 directory
,strerror(errno
)));
2650 if((errno
== ENOENT
) && bad_path
)
2652 unix_ERR_class
= ERRDOS
;
2653 unix_ERR_code
= ERRbadpath
;
2655 return(UNIXERROR(ERRDOS
,ERRbadpath
));
2658 outsize
= set_message(outbuf
,0,0,True
);
2660 DEBUG(3,("%s rmdir %s\n",timestring(),directory
));
2666 /*******************************************************************
2667 resolve wildcards in a filename rename
2668 ********************************************************************/
2669 static BOOL
resolve_wildcards(char *name1
,char *name2
)
2671 fstring root1
,root2
;
2675 name1
= strrchr(name1
,'/');
2676 name2
= strrchr(name2
,'/');
2678 if (!name1
|| !name2
) return(False
);
2680 strcpy(root1
,name1
);
2681 strcpy(root2
,name2
);
2682 p
= strrchr(root1
,'.');
2689 p
= strrchr(root2
,'.');
2721 strcpy(name2
,root2
);
2730 /*******************************************************************
2731 check if a user is allowed to rename a file
2732 ********************************************************************/
2733 static BOOL
can_rename(char *fname
,int cnum
)
2737 if (!CAN_WRITE(cnum
)) return(False
);
2739 if (sys_lstat(fname
,&sbuf
) != 0) return(False
);
2740 if (!check_file_sharing(cnum
,fname
)) return(False
);
2745 /****************************************************************************
2747 ****************************************************************************/
2748 int reply_mv(char *inbuf
,char *outbuf
)
2754 pstring mask
,newname
;
2755 pstring newname_last_component
;
2758 int error
= ERRnoaccess
;
2761 BOOL bad_path1
= False
;
2762 BOOL bad_path2
= False
;
2764 *directory
= *mask
= 0;
2766 cnum
= SVAL(inbuf
,smb_tid
);
2768 strcpy(name
,smb_buf(inbuf
) + 1);
2769 strcpy(newname
,smb_buf(inbuf
) + 3 + strlen(name
));
2771 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
2773 unix_convert(name
,cnum
,0,&bad_path1
);
2774 unix_convert(newname
,cnum
,newname_last_component
,&bad_path2
);
2777 * Split the old name into directory and last component
2778 * strings. Note that unix_convert may have stripped off a
2779 * leading ./ from both name and newname if the rename is
2780 * at the root of the share. We need to make sure either both
2781 * name and newname contain a / character or neither of them do
2782 * as this is checked in resolve_wildcards().
2785 p
= strrchr(name
,'/');
2787 strcpy(directory
,".");
2791 strcpy(directory
,name
);
2793 *p
= '/'; /* Replace needed for exceptional test below. */
2796 if (is_mangled(mask
))
2797 check_mangled_stack(mask
);
2799 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
2802 BOOL is_short_name
= is_8_3(name
, True
);
2804 /* Add a terminating '/' to the directory name. */
2805 strcat(directory
,"/");
2806 strcat(directory
,mask
);
2808 /* Ensure newname contains a '/' also */
2809 if(strrchr(newname
,'/') == 0) {
2812 strcpy(tmpstr
, "./");
2813 strcat(tmpstr
, newname
);
2814 strcpy(newname
, tmpstr
);
2817 DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
2818 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
2819 newname
, newname_last_component
, is_short_name
));
2822 * Check for special case with case preserving and not
2823 * case sensitive, if directory and newname are identical,
2824 * and the old last component differs from the original
2825 * last component only by case, then we should allow
2826 * the rename (user is trying to change the case of the
2829 if((case_sensitive
== False
) && ( ((case_preserve
== True
) && (is_short_name
== False
)) ||
2830 ((short_case_preserve
== True
) && (is_short_name
== True
))) &&
2831 strcsequal(directory
, newname
)) {
2832 pstring newname_modified_last_component
;
2835 * Get the last component of the modified name.
2836 * Note that we guarantee that newname contains a '/'
2839 p
= strrchr(newname
,'/');
2840 strcpy(newname_modified_last_component
,p
+1);
2842 if(strcsequal(newname_modified_last_component
,
2843 newname_last_component
) == False
) {
2845 * Replace the modified last component with
2848 strcpy(p
+1, newname_last_component
);
2852 if (resolve_wildcards(directory
,newname
) &&
2853 can_rename(directory
,cnum
) &&
2854 !file_exist(newname
,NULL
) &&
2855 !sys_rename(directory
,newname
)) count
++;
2857 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count
!= 0) ? "succeeded" : "failed",
2858 directory
,newname
));
2860 if (!count
) exists
= file_exist(directory
,NULL
);
2861 if (!count
&& exists
&& file_exist(newname
,NULL
)) {
2866 void *dirptr
= NULL
;
2870 if (check_name(directory
,cnum
))
2871 dirptr
= OpenDir(cnum
, directory
, True
);
2877 if (strequal(mask
,"????????.???"))
2880 while ((dname
= ReadDirName(dirptr
)))
2883 strcpy(fname
,dname
);
2885 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
2887 error
= ERRnoaccess
;
2888 sprintf(fname
,"%s/%s",directory
,dname
);
2889 if (!can_rename(fname
,cnum
)) continue;
2890 strcpy(destname
,newname
);
2892 if (!resolve_wildcards(fname
,destname
)) continue;
2894 if (file_exist(destname
,NULL
)) {
2898 if (!sys_rename(fname
,destname
)) count
++;
2899 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname
,destname
));
2907 return(ERROR(ERRDOS
,error
));
2910 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
2912 unix_ERR_class
= ERRDOS
;
2913 unix_ERR_code
= ERRbadpath
;
2915 return(UNIXERROR(ERRDOS
,error
));
2919 outsize
= set_message(outbuf
,0,0,True
);
2924 /*******************************************************************
2925 copy a file as part of a reply_copy
2926 ******************************************************************/
2927 static BOOL
copy_file(char *src
,char *dest1
,int cnum
,int ofun
,
2928 int count
,BOOL target_is_directory
)
2937 if (target_is_directory
) {
2938 char *p
= strrchr(src
,'/');
2947 if (!file_exist(src
,&st
)) return(False
);
2949 fnum1
= find_free_file();
2950 if (fnum1
<0) return(False
);
2951 open_file_shared(fnum1
,cnum
,src
,(DENY_NONE
<<4),
2952 1,0,&Access
,&action
);
2954 if (!Files
[fnum1
].open
) return(False
);
2956 if (!target_is_directory
&& count
)
2959 fnum2
= find_free_file();
2964 open_file_shared(fnum2
,cnum
,dest
,(DENY_NONE
<<4)|1,
2965 ofun
,st
.st_mode
,&Access
,&action
);
2967 if (!Files
[fnum2
].open
) {
2972 if ((ofun
&3) == 1) {
2973 lseek(Files
[fnum2
].fd_ptr
->fd
,0,SEEK_END
);
2977 ret
= transfer_file(Files
[fnum1
].fd_ptr
->fd
,Files
[fnum2
].fd_ptr
->fd
,st
.st_size
,NULL
,0,0);
2982 return(ret
== st
.st_size
);
2987 /****************************************************************************
2988 reply to a file copy.
2989 ****************************************************************************/
2990 int reply_copy(char *inbuf
,char *outbuf
)
2996 pstring mask
,newname
;
2999 int error
= ERRnoaccess
;
3002 int tid2
= SVAL(inbuf
,smb_vwv0
);
3003 int ofun
= SVAL(inbuf
,smb_vwv1
);
3004 int flags
= SVAL(inbuf
,smb_vwv2
);
3005 BOOL target_is_directory
=False
;
3006 BOOL bad_path1
= False
;
3007 BOOL bad_path2
= False
;
3009 *directory
= *mask
= 0;
3011 cnum
= SVAL(inbuf
,smb_tid
);
3013 strcpy(name
,smb_buf(inbuf
));
3014 strcpy(newname
,smb_buf(inbuf
) + 1 + strlen(name
));
3016 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
3019 /* can't currently handle inter share copies XXXX */
3020 DEBUG(3,("Rejecting inter-share copy\n"));
3021 return(ERROR(ERRSRV
,ERRinvdevice
));
3024 unix_convert(name
,cnum
,0,&bad_path1
);
3025 unix_convert(newname
,cnum
,0,&bad_path2
);
3027 target_is_directory
= directory_exist(newname
,NULL
);
3029 if ((flags
&1) && target_is_directory
) {
3030 return(ERROR(ERRDOS
,ERRbadfile
));
3033 if ((flags
&2) && !target_is_directory
) {
3034 return(ERROR(ERRDOS
,ERRbadpath
));
3037 if ((flags
&(1<<5)) && directory_exist(name
,NULL
)) {
3038 /* wants a tree copy! XXXX */
3039 DEBUG(3,("Rejecting tree copy\n"));
3040 return(ERROR(ERRSRV
,ERRerror
));
3043 p
= strrchr(name
,'/');
3045 strcpy(directory
,"./");
3049 strcpy(directory
,name
);
3053 if (is_mangled(mask
))
3054 check_mangled_stack(mask
);
3056 has_wild
= strchr(mask
,'*') || strchr(mask
,'?');
3059 strcat(directory
,"/");
3060 strcat(directory
,mask
);
3061 if (resolve_wildcards(directory
,newname
) &&
3062 copy_file(directory
,newname
,cnum
,ofun
,
3063 count
,target_is_directory
)) count
++;
3064 if (!count
) exists
= file_exist(directory
,NULL
);
3066 void *dirptr
= NULL
;
3070 if (check_name(directory
,cnum
))
3071 dirptr
= OpenDir(cnum
, directory
, True
);
3077 if (strequal(mask
,"????????.???"))
3080 while ((dname
= ReadDirName(dirptr
)))
3083 strcpy(fname
,dname
);
3085 if(!mask_match(fname
, mask
, case_sensitive
, False
)) continue;
3087 error
= ERRnoaccess
;
3088 sprintf(fname
,"%s/%s",directory
,dname
);
3089 strcpy(destname
,newname
);
3090 if (resolve_wildcards(fname
,destname
) &&
3091 copy_file(directory
,newname
,cnum
,ofun
,
3092 count
,target_is_directory
)) count
++;
3093 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
3101 return(ERROR(ERRDOS
,error
));
3104 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
3106 unix_ERR_class
= ERRDOS
;
3107 unix_ERR_code
= ERRbadpath
;
3109 return(UNIXERROR(ERRDOS
,error
));
3113 outsize
= set_message(outbuf
,1,0,True
);
3114 SSVAL(outbuf
,smb_vwv0
,count
);
3121 /****************************************************************************
3123 ****************************************************************************/
3124 int reply_setdir(char *inbuf
,char *outbuf
)
3131 cnum
= SVAL(inbuf
,smb_tid
);
3133 snum
= Connections
[cnum
].service
;
3134 if (!CAN_SETDIR(snum
))
3135 return(ERROR(ERRDOS
,ERRnoaccess
));
3137 strcpy(newdir
,smb_buf(inbuf
) + 1);
3140 if (strlen(newdir
) == 0)
3144 ok
= directory_exist(newdir
,NULL
);
3146 string_set(&Connections
[cnum
].connectpath
,newdir
);
3150 return(ERROR(ERRDOS
,ERRbadpath
));
3152 outsize
= set_message(outbuf
,0,0,True
);
3153 CVAL(outbuf
,smb_reh
) = CVAL(inbuf
,smb_reh
);
3155 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir
,cnum
));
3161 /****************************************************************************
3162 reply to a lockingX request
3163 ****************************************************************************/
3164 int reply_lockingX(char *inbuf
,char *outbuf
,int length
,int bufsize
)
3166 int fnum
= GETFNUM(inbuf
,smb_vwv2
);
3167 uint16 locktype
= SVAL(inbuf
,smb_vwv3
);
3168 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
3169 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
3170 uint32 count
, offset
;
3175 uint32 ecode
=0, dummy2
;
3176 int eclass
=0, dummy1
;
3178 cnum
= SVAL(inbuf
,smb_tid
);
3180 CHECK_FNUM(fnum
,cnum
);
3183 data
= smb_buf(inbuf
);
3184 /* Data now points at the beginning of the list
3185 of smb_unlkrng structs */
3186 for(i
= 0; i
< (int)num_ulocks
; i
++) {
3187 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3188 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3189 if(!do_unlock(fnum
,cnum
,count
,offset
,&eclass
, &ecode
))
3190 return ERROR(eclass
,ecode
);
3193 /* Now do any requested locks */
3194 data
+= 10*num_ulocks
;
3195 /* Data now points at the beginning of the list
3196 of smb_lkrng structs */
3197 for(i
= 0; i
< (int)num_locks
; i
++) {
3198 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3199 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3200 if(!do_lock(fnum
,cnum
,count
,offset
, &eclass
, &ecode
))
3204 /* If any of the above locks failed, then we must unlock
3205 all of the previous locks (X/Open spec). */
3206 if(i
!= num_locks
&& num_locks
!= 0) {
3207 for(; i
>= 0; i
--) {
3208 count
= IVAL(data
,SMB_LKLEN_OFFSET(i
));
3209 offset
= IVAL(data
,SMB_LKOFF_OFFSET(i
));
3210 do_unlock(fnum
,cnum
,count
,offset
,&dummy1
,&dummy2
);
3212 return ERROR(eclass
,ecode
);
3215 set_message(outbuf
,2,0,True
);
3217 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3218 timestring(),fnum
,cnum
,locktype
,num_locks
,num_ulocks
));
3222 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
3226 /****************************************************************************
3227 reply to a SMBreadbmpx (read block multiplex) request
3228 ****************************************************************************/
3229 int reply_readbmpx(char *inbuf
,char *outbuf
,int length
,int bufsize
)
3236 int outsize
, mincount
, maxcount
;
3241 /* this function doesn't seem to work - disable by default */
3243 return(ERROR(ERRSRV
,ERRuseSTD
));
3245 outsize
= set_message(outbuf
,8,0,True
);
3247 cnum
= SVAL(inbuf
,smb_tid
);
3248 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3250 CHECK_FNUM(fnum
,cnum
);
3254 startpos
= IVAL(inbuf
,smb_vwv1
);
3255 maxcount
= SVAL(inbuf
,smb_vwv3
);
3256 mincount
= SVAL(inbuf
,smb_vwv4
);
3258 data
= smb_buf(outbuf
);
3259 pad
= ((long)data
)%4;
3260 if (pad
) pad
= 4 - pad
;
3263 max_per_packet
= bufsize
-(outsize
+pad
);
3267 if (is_locked(fnum
,cnum
,maxcount
,startpos
))
3268 return(ERROR(ERRDOS
,ERRlock
));
3272 int N
= MIN(max_per_packet
,tcount
-total_read
);
3274 nread
= read_file(fnum
,data
,startpos
,N
);
3276 if (nread
<= 0) nread
= 0;
3279 tcount
= total_read
+ nread
;
3281 set_message(outbuf
,8,nread
,False
);
3282 SIVAL(outbuf
,smb_vwv0
,startpos
);
3283 SSVAL(outbuf
,smb_vwv2
,tcount
);
3284 SSVAL(outbuf
,smb_vwv6
,nread
);
3285 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
3287 send_smb(Client
,outbuf
);
3289 total_read
+= nread
;
3292 while (total_read
< tcount
);
3298 /****************************************************************************
3299 reply to a SMBwritebmpx (write block multiplex primary) request
3300 ****************************************************************************/
3301 int reply_writebmpx(char *inbuf
,char *outbuf
)
3303 int cnum
,numtowrite
,fnum
;
3307 int tcount
, write_through
, smb_doff
;
3310 cnum
= SVAL(inbuf
,smb_tid
);
3311 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3313 CHECK_FNUM(fnum
,cnum
);
3317 tcount
= SVAL(inbuf
,smb_vwv1
);
3318 startpos
= IVAL(inbuf
,smb_vwv3
);
3319 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
3320 numtowrite
= SVAL(inbuf
,smb_vwv10
);
3321 smb_doff
= SVAL(inbuf
,smb_vwv11
);
3323 data
= smb_base(inbuf
) + smb_doff
;
3325 /* If this fails we need to send an SMBwriteC response,
3326 not an SMBwritebmpx - set this up now so we don't forget */
3327 CVAL(outbuf
,smb_com
) = SMBwritec
;
3329 if (is_locked(fnum
,cnum
,tcount
,startpos
))
3330 return(ERROR(ERRDOS
,ERRlock
));
3332 seek_file(fnum
,startpos
);
3333 nwritten
= write_file(fnum
,data
,numtowrite
);
3335 if(lp_syncalways(SNUM(cnum
)) || write_through
)
3338 if(nwritten
< numtowrite
)
3339 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
3341 /* If the maximum to be written to this file
3342 is greater than what we just wrote then set
3343 up a secondary struct to be attached to this
3344 fd, we will use this to cache error messages etc. */
3345 if(tcount
> nwritten
)
3347 write_bmpx_struct
*wbms
;
3348 if(Files
[fnum
].wbmpx_ptr
!= NULL
)
3349 wbms
= Files
[fnum
].wbmpx_ptr
; /* Use an existing struct */
3351 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
3354 DEBUG(0,("Out of memory in reply_readmpx\n"));
3355 return(ERROR(ERRSRV
,ERRnoresource
));
3357 wbms
->wr_mode
= write_through
;
3358 wbms
->wr_discard
= False
; /* No errors yet */
3359 wbms
->wr_total_written
= nwritten
;
3360 wbms
->wr_errclass
= 0;
3362 Files
[fnum
].wbmpx_ptr
= wbms
;
3365 /* We are returning successfully, set the message type back to
3367 CVAL(outbuf
,smb_com
) = SMBwriteBmpx
;
3369 outsize
= set_message(outbuf
,1,0,True
);
3371 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
3373 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3374 timestring(),fnum
,cnum
,numtowrite
,nwritten
));
3376 if (write_through
&& tcount
==nwritten
) {
3377 /* we need to send both a primary and a secondary response */
3378 smb_setlen(outbuf
,outsize
- 4);
3379 send_smb(Client
,outbuf
);
3381 /* now the secondary */
3382 outsize
= set_message(outbuf
,1,0,True
);
3383 CVAL(outbuf
,smb_com
) = SMBwritec
;
3384 SSVAL(outbuf
,smb_vwv0
,nwritten
);
3391 /****************************************************************************
3392 reply to a SMBwritebs (write block multiplex secondary) request
3393 ****************************************************************************/
3394 int reply_writebs(char *inbuf
,char *outbuf
)
3396 int cnum
,numtowrite
,fnum
;
3400 int tcount
, write_through
, smb_doff
;
3402 write_bmpx_struct
*wbms
;
3403 BOOL send_response
= False
;
3405 cnum
= SVAL(inbuf
,smb_tid
);
3406 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3407 CHECK_FNUM(fnum
,cnum
);
3410 tcount
= SVAL(inbuf
,smb_vwv1
);
3411 startpos
= IVAL(inbuf
,smb_vwv2
);
3412 numtowrite
= SVAL(inbuf
,smb_vwv6
);
3413 smb_doff
= SVAL(inbuf
,smb_vwv7
);
3415 data
= smb_base(inbuf
) + smb_doff
;
3417 /* We need to send an SMBwriteC response, not an SMBwritebs */
3418 CVAL(outbuf
,smb_com
) = SMBwritec
;
3420 /* This fd should have an auxiliary struct attached,
3421 check that it does */
3422 wbms
= Files
[fnum
].wbmpx_ptr
;
3423 if(!wbms
) return(-1);
3425 /* If write through is set we can return errors, else we must
3427 write_through
= wbms
->wr_mode
;
3429 /* Check for an earlier error */
3430 if(wbms
->wr_discard
)
3431 return -1; /* Just discard the packet */
3433 seek_file(fnum
,startpos
);
3434 nwritten
= write_file(fnum
,data
,numtowrite
);
3436 if(lp_syncalways(SNUM(cnum
)) || write_through
)
3439 if (nwritten
< numtowrite
)
3442 /* We are returning an error - we can delete the aux struct */
3443 if (wbms
) free((char *)wbms
);
3444 Files
[fnum
].wbmpx_ptr
= NULL
;
3445 return(ERROR(ERRHRD
,ERRdiskfull
));
3447 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
3450 /* Increment the total written, if this matches tcount
3451 we can discard the auxiliary struct (hurrah !) and return a writeC */
3452 wbms
->wr_total_written
+= nwritten
;
3453 if(wbms
->wr_total_written
>= tcount
)
3455 if (write_through
) {
3456 outsize
= set_message(outbuf
,1,0,True
);
3457 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
3458 send_response
= True
;
3462 Files
[fnum
].wbmpx_ptr
= NULL
;
3472 /****************************************************************************
3473 reply to a SMBsetattrE
3474 ****************************************************************************/
3475 int reply_setattrE(char *inbuf
,char *outbuf
)
3478 struct utimbuf unix_times
;
3481 outsize
= set_message(outbuf
,0,0,True
);
3483 cnum
= SVAL(inbuf
,smb_tid
);
3484 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3486 CHECK_FNUM(fnum
,cnum
);
3489 /* Convert the DOS times into unix times. Ignore create
3490 time as UNIX can't set this.
3492 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
3493 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
3495 /* Set the date on this file */
3496 if(sys_utime(Files
[fnum
].name
, &unix_times
))
3497 return(ERROR(ERRDOS
,ERRnoaccess
));
3499 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum
,cnum
));
3505 /****************************************************************************
3506 reply to a SMBgetattrE
3507 ****************************************************************************/
3508 int reply_getattrE(char *inbuf
,char *outbuf
)
3515 outsize
= set_message(outbuf
,11,0,True
);
3517 cnum
= SVAL(inbuf
,smb_tid
);
3518 fnum
= GETFNUM(inbuf
,smb_vwv0
);
3520 CHECK_FNUM(fnum
,cnum
);
3523 /* Do an fstat on this file */
3524 if(fstat(Files
[fnum
].fd_ptr
->fd
, &sbuf
))
3525 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
3527 mode
= dos_mode(cnum
,Files
[fnum
].name
,&sbuf
);
3529 /* Convert the times into dos times. Set create
3530 date to be last modify date as UNIX doesn't save
3532 put_dos_date2(outbuf
,smb_vwv0
,sbuf
.st_mtime
);
3533 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
3534 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
3537 SIVAL(outbuf
,smb_vwv6
,0);
3538 SIVAL(outbuf
,smb_vwv8
,0);
3542 SIVAL(outbuf
,smb_vwv6
,sbuf
.st_size
);
3543 SIVAL(outbuf
,smb_vwv8
,ROUNDUP(sbuf
.st_size
,1024));
3545 SSVAL(outbuf
,smb_vwv10
, mode
);
3547 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum
,cnum
));