This is the ubiqx binary tree and linked list library.
[Samba.git] / source / smbd / reply.c
blobbaccb76291146b9714eb1d8bab6ca6c46b8f5c7a
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
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
27 #include "includes.h"
28 #include "trans2.h"
30 /* look in server.c for some explanation of these variables */
31 extern int Protocol;
32 extern int DEBUGLEVEL;
33 extern int max_send;
34 extern int max_recv;
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;
44 extern int Client;
45 extern int global_oplock_break;
47 /* this macro should always be used to extract an fnum (smb_fid) from
48 a packet to ensure chaining works correctly */
49 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
52 /****************************************************************************
53 report a possible attack via the password buffer overflow bug
54 ****************************************************************************/
55 static void overflow_attack(int len)
57 DEBUG(0,("ERROR: Invalid password length %d\n", len));
58 DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n"));
59 DEBUG(0,("Attack was from IP=%s\n", client_addr()));
60 exit_server("possible attack");
64 /****************************************************************************
65 reply to an special message
66 ****************************************************************************/
67 int reply_special(char *inbuf,char *outbuf)
69 int outsize = 4;
70 int msg_type = CVAL(inbuf,0);
71 int msg_flags = CVAL(inbuf,1);
72 pstring name1,name2;
73 extern fstring remote_machine;
74 extern fstring local_machine;
75 char *p;
77 *name1 = *name2 = 0;
79 smb_setlen(outbuf,0);
81 switch (msg_type) {
82 case 0x81: /* session request */
83 CVAL(outbuf,0) = 0x82;
84 CVAL(outbuf,3) = 0;
85 if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
86 DEBUG(0,("Invalid name length in session request\n"));
87 return(0);
89 name_extract(inbuf,4,name1);
90 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
91 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
92 name1,name2));
94 fstrcpy(remote_machine,name2);
95 trim_string(remote_machine," "," ");
96 p = strchr(remote_machine,' ');
97 strlower(remote_machine);
98 if (p) *p = 0;
100 fstrcpy(local_machine,name1);
101 trim_string(local_machine," "," ");
102 p = strchr(local_machine,' ');
103 strlower(local_machine);
104 if (p) *p = 0;
106 add_session_user(remote_machine);
108 reload_services(True);
109 reopen_logs();
111 break;
113 case 0x89: /* session keepalive request
114 (some old clients produce this?) */
115 CVAL(outbuf,0) = 0x85;
116 CVAL(outbuf,3) = 0;
117 break;
119 case 0x82: /* positive session response */
120 case 0x83: /* negative session response */
121 case 0x84: /* retarget session response */
122 DEBUG(0,("Unexpected session response\n"));
123 break;
125 case 0x85: /* session keepalive */
126 default:
127 return(0);
130 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",
131 timestring(),msg_type,msg_flags));
133 return(outsize);
137 /*******************************************************************
138 work out what error to give to a failed connection
139 ********************************************************************/
140 static int connection_error(char *inbuf,char *outbuf,int connection_num)
142 switch (connection_num)
144 case -8:
145 return(ERROR(ERRSRV,ERRnoresource));
146 case -7:
147 return(ERROR(ERRSRV,ERRbaduid));
148 case -6:
149 return(ERROR(ERRSRV,ERRinvdevice));
150 case -5:
151 return(ERROR(ERRSRV,ERRinvnetname));
152 case -4:
153 return(ERROR(ERRSRV,ERRaccess));
154 case -3:
155 return(ERROR(ERRDOS,ERRnoipc));
156 case -2:
157 return(ERROR(ERRSRV,ERRinvnetname));
159 return(ERROR(ERRSRV,ERRbadpw));
164 /****************************************************************************
165 parse a share descriptor string
166 ****************************************************************************/
167 static void parse_connect(char *p,char *service,char *user,
168 char *password,int *pwlen,char *dev)
170 char *p2;
172 DEBUG(4,("parsing connect string %s\n",p));
174 p2 = strrchr(p,'\\');
175 if (p2 == NULL)
176 fstrcpy(service,p);
177 else
178 fstrcpy(service,p2+1);
180 p += strlen(p) + 2;
182 fstrcpy(password,p);
183 *pwlen = strlen(password);
185 p += strlen(p) + 2;
187 fstrcpy(dev,p);
189 *user = 0;
190 p = strchr(service,'%');
191 if (p != NULL)
193 *p = 0;
194 fstrcpy(user,p+1);
201 /****************************************************************************
202 reply to a tcon
203 ****************************************************************************/
204 int reply_tcon(char *inbuf,char *outbuf)
206 pstring service;
207 pstring user;
208 pstring password;
209 pstring dev;
210 int connection_num;
211 int outsize = 0;
212 uint16 vuid = SVAL(inbuf,smb_uid);
213 int pwlen=0;
215 *service = *user = *password = *dev = 0;
217 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
219 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
221 if (connection_num < 0)
222 return(connection_error(inbuf,outbuf,connection_num));
224 outsize = set_message(outbuf,2,0,True);
225 SSVAL(outbuf,smb_vwv0,max_recv);
226 SSVAL(outbuf,smb_vwv1,connection_num);
227 SSVAL(outbuf,smb_tid,connection_num);
229 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
231 return(outsize);
235 /****************************************************************************
236 reply to a tcon and X
237 ****************************************************************************/
238 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
240 pstring service;
241 pstring user;
242 pstring password;
243 pstring devicename;
244 int connection_num;
245 uint16 vuid = SVAL(inbuf,smb_uid);
246 int passlen = SVAL(inbuf,smb_vwv3);
247 BOOL doencrypt = SMBENCRYPT();
249 *service = *user = *password = *devicename = 0;
251 /* we might have to close an old one */
252 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
253 close_cnum(SVAL(inbuf,smb_tid),vuid);
255 if (passlen > MAX_PASS_LEN) {
256 overflow_attack(passlen);
260 char *path;
261 char *p;
262 memcpy(password,smb_buf(inbuf),passlen);
263 password[passlen]=0;
264 path = smb_buf(inbuf) + passlen;
266 if (!doencrypt || passlen != 24) {
267 if (strequal(password," "))
268 *password = 0;
269 passlen = strlen(password);
272 fstrcpy(service,path+2);
273 p = strchr(service,'\\');
274 if (!p)
275 return(ERROR(ERRSRV,ERRinvnetname));
276 *p = 0;
277 fstrcpy(service,p+1);
278 p = strchr(service,'%');
279 if (p)
281 *p++ = 0;
282 fstrcpy(user,p);
284 StrnCpy(devicename,path + strlen(path) + 1,6);
285 DEBUG(4,("Got device type %s\n",devicename));
288 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
290 if (connection_num < 0)
291 return(connection_error(inbuf,outbuf,connection_num));
293 if (Protocol < PROTOCOL_NT1)
295 set_message(outbuf,2,strlen(devicename)+1,True);
296 strcpy(smb_buf(outbuf),devicename);
298 else
300 char *fsname = "SAMBA";
301 char *p;
303 set_message(outbuf,3,3,True);
305 p = smb_buf(outbuf);
306 strcpy(p,devicename); p = skip_string(p,1); /* device name */
307 strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
309 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
311 SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
314 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
316 /* set the incoming and outgoing tid to the just created one */
317 SSVAL(inbuf,smb_tid,connection_num);
318 SSVAL(outbuf,smb_tid,connection_num);
320 return chain_reply(inbuf,outbuf,length,bufsize);
324 /****************************************************************************
325 reply to an unknown type
326 ****************************************************************************/
327 int reply_unknown(char *inbuf,char *outbuf)
329 int cnum;
330 int type;
331 cnum = SVAL(inbuf,smb_tid);
332 type = CVAL(inbuf,smb_com);
334 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
335 timestring(),
336 smb_fn_name(type),
337 cnum,type,type));
339 return(ERROR(ERRSRV,ERRunknownsmb));
343 /****************************************************************************
344 reply to an ioctl
345 ****************************************************************************/
346 int reply_ioctl(char *inbuf,char *outbuf)
348 DEBUG(3,("ignoring ioctl\n"));
349 #if 0
350 /* we just say it succeeds and hope its all OK.
351 some day it would be nice to interpret them individually */
352 return set_message(outbuf,1,0,True);
353 #else
354 return(ERROR(ERRSRV,ERRnosupport));
355 #endif
359 /****************************************************************************
360 reply to a session setup command
361 ****************************************************************************/
362 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
364 uint16 sess_vuid;
365 int gid;
366 int uid;
367 int smb_bufsize;
368 int smb_mpxmax;
369 int smb_vc_num;
370 uint32 smb_sesskey;
371 int smb_apasslen = 0;
372 pstring smb_apasswd;
373 int smb_ntpasslen = 0;
374 pstring smb_ntpasswd;
375 BOOL valid_nt_password = False;
376 pstring user;
377 BOOL guest=False;
378 BOOL computer_id=False;
379 static BOOL done_sesssetup = False;
380 BOOL doencrypt = SMBENCRYPT();
382 *smb_apasswd = 0;
384 smb_bufsize = SVAL(inbuf,smb_vwv2);
385 smb_mpxmax = SVAL(inbuf,smb_vwv3);
386 smb_vc_num = SVAL(inbuf,smb_vwv4);
387 smb_sesskey = IVAL(inbuf,smb_vwv5);
389 if (Protocol < PROTOCOL_NT1) {
390 smb_apasslen = SVAL(inbuf,smb_vwv7);
391 if (smb_apasslen > MAX_PASS_LEN)
393 overflow_attack(smb_apasslen);
396 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
397 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
399 if (lp_security() != SEC_SERVER && !doencrypt) {
400 smb_apasslen = strlen(smb_apasswd);
402 } else {
403 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
404 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
405 uint32 client_caps = IVAL(inbuf,smb_vwv11);
406 enum remote_arch_types ra_type = get_remote_arch();
408 char *p = smb_buf(inbuf);
410 /* client_caps is used as final determination if client is NT or Win95.
411 This is needed to return the correct error codes in some
412 circumstances.
415 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
417 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
418 set_remote_arch( RA_WINNT);
419 else
420 set_remote_arch( RA_WIN95);
423 if (passlen1 != 24 && passlen2 != 24)
424 doencrypt = False;
426 if (passlen1 > MAX_PASS_LEN) {
427 overflow_attack(passlen1);
430 passlen1 = MIN(passlen1, MAX_PASS_LEN);
431 passlen2 = MIN(passlen2, MAX_PASS_LEN);
433 if(doencrypt) {
434 /* Save the lanman2 password and the NT md4 password. */
435 smb_apasslen = passlen1;
436 memcpy(smb_apasswd,p,smb_apasslen);
437 smb_ntpasslen = passlen2;
438 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
439 } else {
440 /* both Win95 and WinNT stuff up the password lengths for
441 non-encrypting systems. Uggh.
443 if passlen1==24 its a win95 system, and its setting the
444 password length incorrectly. Luckily it still works with the
445 default code because Win95 will null terminate the password
446 anyway
448 if passlen1>0 and passlen2>0 then maybe its a NT box and its
449 setting passlen2 to some random value which really stuffs
450 things up. we need to fix that one. */
451 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
452 passlen2 != 1) {
453 passlen2 = 0;
455 /* we use the first password that they gave */
456 smb_apasslen = passlen1;
457 StrnCpy(smb_apasswd,p,smb_apasslen);
459 /* trim the password */
460 smb_apasslen = strlen(smb_apasswd);
462 /* wfwg sometimes uses a space instead of a null */
463 if (strequal(smb_apasswd," ")) {
464 smb_apasslen = 0;
465 *smb_apasswd = 0;
469 p += passlen1 + passlen2;
470 fstrcpy(user,p); p = skip_string(p,1);
471 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
472 p,skip_string(p,1),skip_string(p,2)));
476 DEBUG(3,("sesssetupX:name=[%s]\n",user));
478 /* If name ends in $ then I think it's asking about whether a */
479 /* computer with that name (minus the $) has access. For now */
480 /* say yes to everything ending in $. */
481 if (user[strlen(user) - 1] == '$') {
482 computer_id = True;
483 user[strlen(user) - 1] = '\0';
487 /* If no username is sent use the guest account */
488 if (!*user)
490 strcpy(user,lp_guestaccount(-1));
491 /* If no user and no password then set guest flag. */
492 if( *smb_apasswd == 0)
493 guest = True;
496 strlower(user);
498 strcpy(sesssetup_user,user);
500 reload_services(True);
502 add_session_user(user);
504 /* Check if the given username was the guest user with no password.
505 We need to do this check after add_session_user() as that
506 call can potentially change the username (via map_user).
509 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
510 guest = True;
512 if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
513 !check_hosts_equiv(user))
516 /* now check if it's a valid username/password */
517 /* If an NT password was supplied try and validate with that
518 first. This is superior as the passwords are mixed case
519 128 length unicode */
520 if(smb_ntpasslen)
522 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
523 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
524 else
525 valid_nt_password = True;
527 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
529 if (!computer_id && lp_security() >= SEC_USER) {
530 #if (GUEST_SESSSETUP == 0)
531 return(ERROR(ERRSRV,ERRbadpw));
532 #endif
533 #if (GUEST_SESSSETUP == 1)
534 if (Get_Pwnam(user,True))
535 return(ERROR(ERRSRV,ERRbadpw));
536 #endif
538 if (*smb_apasswd || !Get_Pwnam(user,True))
539 strcpy(user,lp_guestaccount(-1));
540 DEBUG(3,("Registered username %s for guest access\n",user));
541 guest = True;
545 if (!Get_Pwnam(user,True)) {
546 DEBUG(3,("No such user %s - using guest account\n",user));
547 strcpy(user,lp_guestaccount(-1));
548 guest = True;
551 if (!strequal(user,lp_guestaccount(-1)) &&
552 lp_servicenumber(user) < 0)
554 int homes = lp_servicenumber(HOMES_NAME);
555 char *home = get_home_dir(user);
556 if (homes >= 0 && home)
557 lp_add_home(user,homes,home);
561 /* it's ok - setup a reply */
562 if (Protocol < PROTOCOL_NT1) {
563 set_message(outbuf,3,0,True);
564 } else {
565 char *p;
566 set_message(outbuf,3,3,True);
567 p = smb_buf(outbuf);
568 strcpy(p,"Unix"); p = skip_string(p,1);
569 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
570 strcpy(p,myworkgroup); p = skip_string(p,1);
571 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
572 /* perhaps grab OS version here?? */
575 /* Set the correct uid in the outgoing and incoming packets
576 We will use this on future requests to determine which
577 user we should become.
580 struct passwd *pw = Get_Pwnam(user,False);
581 if (!pw) {
582 DEBUG(1,("Username %s is invalid on this system\n",user));
583 return(ERROR(ERRSRV,ERRbadpw));
585 gid = pw->pw_gid;
586 uid = pw->pw_uid;
589 if (guest && !computer_id)
590 SSVAL(outbuf,smb_vwv2,1);
592 /* register the name and uid as being validated, so further connections
593 to a uid can get through without a password, on the same VC */
594 sess_vuid = register_vuid(uid,gid,user,guest);
596 SSVAL(outbuf,smb_uid,sess_vuid);
597 SSVAL(inbuf,smb_uid,sess_vuid);
599 if (!done_sesssetup)
600 max_send = MIN(max_send,smb_bufsize);
602 DEBUG(6,("Client requested max send size of %d\n", max_send));
604 done_sesssetup = True;
606 return chain_reply(inbuf,outbuf,length,bufsize);
610 /****************************************************************************
611 reply to a chkpth
612 ****************************************************************************/
613 int reply_chkpth(char *inbuf,char *outbuf)
615 int outsize = 0;
616 int cnum,mode;
617 pstring name;
618 BOOL ok = False;
619 BOOL bad_path = False;
621 cnum = SVAL(inbuf,smb_tid);
623 pstrcpy(name,smb_buf(inbuf) + 1);
624 unix_convert(name,cnum,0,&bad_path);
626 mode = SVAL(inbuf,smb_vwv0);
628 if (check_name(name,cnum))
629 ok = directory_exist(name,NULL);
631 if (!ok)
633 /* We special case this - as when a Windows machine
634 is parsing a path is steps through the components
635 one at a time - if a component fails it expects
636 ERRbadpath, not ERRbadfile.
638 if(errno == ENOENT)
640 unix_ERR_class = ERRDOS;
641 unix_ERR_code = ERRbadpath;
644 #if 0
645 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
646 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
647 (get_remote_arch() == RA_WINNT))
649 unix_ERR_class = ERRDOS;
650 unix_ERR_code = ERRbaddirectory;
652 #endif
654 return(UNIXERROR(ERRDOS,ERRbadpath));
657 outsize = set_message(outbuf,0,0,True);
659 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
661 return(outsize);
665 /****************************************************************************
666 reply to a getatr
667 ****************************************************************************/
668 int reply_getatr(char *inbuf,char *outbuf)
670 pstring fname;
671 int cnum;
672 int outsize = 0;
673 struct stat sbuf;
674 BOOL ok = False;
675 int mode=0;
676 uint32 size=0;
677 time_t mtime=0;
678 BOOL bad_path = False;
680 cnum = SVAL(inbuf,smb_tid);
682 pstrcpy(fname,smb_buf(inbuf) + 1);
683 unix_convert(fname,cnum,0,&bad_path);
685 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
686 under WfWg - weird! */
687 if (! (*fname))
689 mode = aHIDDEN | aDIR;
690 if (!CAN_WRITE(cnum)) mode |= aRONLY;
691 size = 0;
692 mtime = 0;
693 ok = True;
695 else
696 if (check_name(fname,cnum))
698 if (sys_stat(fname,&sbuf) == 0)
700 mode = dos_mode(cnum,fname,&sbuf);
701 size = sbuf.st_size;
702 mtime = sbuf.st_mtime;
703 if (mode & aDIR)
704 size = 0;
705 ok = True;
707 else
708 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
711 if (!ok)
713 if((errno == ENOENT) && bad_path)
715 unix_ERR_class = ERRDOS;
716 unix_ERR_code = ERRbadpath;
719 return(UNIXERROR(ERRDOS,ERRbadfile));
722 outsize = set_message(outbuf,10,0,True);
724 SSVAL(outbuf,smb_vwv0,mode);
725 put_dos_date3(outbuf,smb_vwv1,mtime);
726 SIVAL(outbuf,smb_vwv3,size);
728 if (Protocol >= PROTOCOL_NT1) {
729 char *p = strrchr(fname,'/');
730 uint16 flg2 = SVAL(outbuf,smb_flg2);
731 if (!p) p = fname;
732 if (!is_8_3(fname, True))
733 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
736 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
738 return(outsize);
742 /****************************************************************************
743 reply to a setatr
744 ****************************************************************************/
745 int reply_setatr(char *inbuf,char *outbuf)
747 pstring fname;
748 int cnum;
749 int outsize = 0;
750 BOOL ok=False;
751 int mode;
752 time_t mtime;
753 BOOL bad_path = False;
755 cnum = SVAL(inbuf,smb_tid);
757 pstrcpy(fname,smb_buf(inbuf) + 1);
758 unix_convert(fname,cnum,0,&bad_path);
760 mode = SVAL(inbuf,smb_vwv0);
761 mtime = make_unix_date3(inbuf+smb_vwv1);
763 if (directory_exist(fname,NULL))
764 mode |= aDIR;
765 if (check_name(fname,cnum))
766 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
767 if (ok)
768 ok = set_filetime(fname,mtime);
770 if (!ok)
772 if((errno == ENOENT) && bad_path)
774 unix_ERR_class = ERRDOS;
775 unix_ERR_code = ERRbadpath;
778 return(UNIXERROR(ERRDOS,ERRnoaccess));
781 outsize = set_message(outbuf,0,0,True);
783 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
785 return(outsize);
789 /****************************************************************************
790 reply to a dskattr
791 ****************************************************************************/
792 int reply_dskattr(char *inbuf,char *outbuf)
794 int cnum;
795 int outsize = 0;
796 int dfree,dsize,bsize;
798 cnum = SVAL(inbuf,smb_tid);
800 sys_disk_free(".",&bsize,&dfree,&dsize);
802 outsize = set_message(outbuf,5,0,True);
804 SSVAL(outbuf,smb_vwv0,dsize);
805 SSVAL(outbuf,smb_vwv1,bsize/512);
806 SSVAL(outbuf,smb_vwv2,512);
807 SSVAL(outbuf,smb_vwv3,dfree);
809 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
811 return(outsize);
815 /****************************************************************************
816 reply to a search
817 Can be called from SMBsearch, SMBffirst or SMBfunique.
818 ****************************************************************************/
819 int reply_search(char *inbuf,char *outbuf)
821 pstring mask;
822 pstring directory;
823 pstring fname;
824 int size,mode;
825 time_t date;
826 int dirtype;
827 int cnum;
828 int outsize = 0;
829 int numentries = 0;
830 BOOL finished = False;
831 int maxentries;
832 int i;
833 char *p;
834 BOOL ok = False;
835 int status_len;
836 char *path;
837 char status[21];
838 int dptr_num= -1;
839 BOOL check_descend = False;
840 BOOL expect_close = False;
841 BOOL can_open = True;
842 BOOL bad_path = False;
844 *mask = *directory = *fname = 0;
846 /* If we were called as SMBffirst then we must expect close. */
847 if(CVAL(inbuf,smb_com) == SMBffirst)
848 expect_close = True;
850 cnum = SVAL(inbuf,smb_tid);
852 outsize = set_message(outbuf,1,3,True);
853 maxentries = SVAL(inbuf,smb_vwv0);
854 dirtype = SVAL(inbuf,smb_vwv1);
855 path = smb_buf(inbuf) + 1;
856 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
859 /* dirtype &= ~aDIR; */
861 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
864 if (status_len == 0)
866 pstring dir2;
868 pstrcpy(directory,smb_buf(inbuf)+1);
869 pstrcpy(dir2,smb_buf(inbuf)+1);
870 unix_convert(directory,cnum,0,&bad_path);
871 unix_format(dir2);
873 if (!check_name(directory,cnum))
874 can_open = False;
876 p = strrchr(dir2,'/');
877 if (p == NULL)
879 strcpy(mask,dir2);
880 *dir2 = 0;
882 else
884 *p = 0;
885 pstrcpy(mask,p+1);
888 p = strrchr(directory,'/');
889 if (!p)
890 *directory = 0;
891 else
892 *p = 0;
894 if (strlen(directory) == 0)
895 strcpy(directory,"./");
896 bzero(status,21);
897 CVAL(status,0) = dirtype;
899 else
901 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
902 memcpy(mask,status+1,11);
903 mask[11] = 0;
904 dirtype = CVAL(status,0) & 0x1F;
905 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
906 if (!Connections[cnum].dirptr)
907 goto SearchEmpty;
908 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
909 if (!case_sensitive)
910 strnorm(mask);
913 /* turn strings of spaces into a . */
915 trim_string(mask,NULL," ");
916 if ((p = strrchr(mask,' ')))
918 fstring ext;
919 fstrcpy(ext,p+1);
920 *p = 0;
921 trim_string(mask,NULL," ");
922 strcat(mask,".");
923 strcat(mask,ext);
928 for (p=mask; *p; p++)
930 if (*p != '?' && *p != '*' && !isdoschar(*p))
932 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
933 *p = '?';
938 if (!strchr(mask,'.') && strlen(mask)>8)
940 fstring tmp;
941 fstrcpy(tmp,&mask[8]);
942 mask[8] = '.';
943 mask[9] = 0;
944 strcat(mask,tmp);
947 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
949 if (can_open)
951 p = smb_buf(outbuf) + 3;
953 ok = True;
955 if (status_len == 0)
957 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
958 if (dptr_num < 0)
960 if(dptr_num == -2)
962 if((errno == ENOENT) && bad_path)
964 unix_ERR_class = ERRDOS;
965 unix_ERR_code = ERRbadpath;
967 return (UNIXERROR(ERRDOS,ERRnofids));
969 return(ERROR(ERRDOS,ERRnofids));
973 DEBUG(4,("dptr_num is %d\n",dptr_num));
975 if (ok)
977 if ((dirtype&0x1F) == aVOLID)
979 memcpy(p,status,21);
980 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
981 dptr_fill(p+12,dptr_num);
982 if (dptr_zero(p+12) && (status_len==0))
983 numentries = 1;
984 else
985 numentries = 0;
986 p += DIR_STRUCT_SIZE;
988 else
990 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
991 if (in_list(Connections[cnum].dirpath,
992 lp_dontdescend(SNUM(cnum)),True))
993 check_descend = True;
995 for (i=numentries;(i<maxentries) && !finished;i++)
997 finished =
998 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
999 if (!finished)
1001 memcpy(p,status,21);
1002 make_dir_struct(p,mask,fname,size,mode,date);
1003 dptr_fill(p+12,dptr_num);
1004 numentries++;
1006 p += DIR_STRUCT_SIZE;
1013 SearchEmpty:
1015 if (numentries == 0 || !ok)
1017 CVAL(outbuf,smb_rcls) = ERRDOS;
1018 SSVAL(outbuf,smb_err,ERRnofiles);
1021 /* If we were called as SMBffirst with smb_search_id == NULL
1022 and no entries were found then return error and close dirptr
1023 (X/Open spec) */
1025 if(ok && expect_close && numentries == 0 && status_len == 0)
1027 CVAL(outbuf,smb_rcls) = ERRDOS;
1028 SSVAL(outbuf,smb_err,ERRnofiles);
1029 /* Also close the dptr - we know it's gone */
1030 dptr_close(dptr_num);
1033 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1034 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1035 dptr_close(dptr_num);
1037 SSVAL(outbuf,smb_vwv0,numentries);
1038 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1039 CVAL(smb_buf(outbuf),0) = 5;
1040 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1042 if (Protocol >= PROTOCOL_NT1) {
1043 uint16 flg2 = SVAL(outbuf,smb_flg2);
1044 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1047 outsize += DIR_STRUCT_SIZE*numentries;
1048 smb_setlen(outbuf,outsize - 4);
1050 if ((! *directory) && dptr_path(dptr_num))
1051 sprintf(directory,"(%s)",dptr_path(dptr_num));
1053 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1054 timestring(),
1055 smb_fn_name(CVAL(inbuf,smb_com)),
1056 mask,directory,cnum,dirtype,numentries,maxentries));
1058 return(outsize);
1062 /****************************************************************************
1063 reply to a fclose (stop directory search)
1064 ****************************************************************************/
1065 int reply_fclose(char *inbuf,char *outbuf)
1067 int cnum;
1068 int outsize = 0;
1069 int status_len;
1070 char *path;
1071 char status[21];
1072 int dptr_num= -1;
1074 cnum = SVAL(inbuf,smb_tid);
1076 outsize = set_message(outbuf,1,0,True);
1077 path = smb_buf(inbuf) + 1;
1078 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1081 if (status_len == 0)
1082 return(ERROR(ERRSRV,ERRsrverror));
1084 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1086 if(dptr_fetch(status+12,&dptr_num)) {
1087 /* Close the dptr - we know it's gone */
1088 dptr_close(dptr_num);
1091 SSVAL(outbuf,smb_vwv0,0);
1093 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1095 return(outsize);
1099 /****************************************************************************
1100 reply to an open
1101 ****************************************************************************/
1102 int reply_open(char *inbuf,char *outbuf)
1104 pstring fname;
1105 int cnum;
1106 int fnum = -1;
1107 int outsize = 0;
1108 int fmode=0;
1109 int share_mode;
1110 int size = 0;
1111 time_t mtime=0;
1112 int unixmode;
1113 int rmode=0;
1114 struct stat sbuf;
1115 BOOL bad_path = False;
1116 files_struct *fsp;
1117 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1119 cnum = SVAL(inbuf,smb_tid);
1121 share_mode = SVAL(inbuf,smb_vwv0);
1123 pstrcpy(fname,smb_buf(inbuf)+1);
1124 unix_convert(fname,cnum,0,&bad_path);
1126 fnum = find_free_file();
1127 if (fnum < 0)
1128 return(ERROR(ERRSRV,ERRnofids));
1130 if (!check_name(fname,cnum))
1132 if((errno == ENOENT) && bad_path)
1134 unix_ERR_class = ERRDOS;
1135 unix_ERR_code = ERRbadpath;
1137 return(UNIXERROR(ERRDOS,ERRnoaccess));
1140 unixmode = unix_mode(cnum,aARCH);
1142 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1143 oplock_request,&rmode,NULL);
1145 fsp = &Files[fnum];
1147 if (!fsp->open)
1149 if((errno == ENOENT) && bad_path)
1151 unix_ERR_class = ERRDOS;
1152 unix_ERR_code = ERRbadpath;
1154 return(UNIXERROR(ERRDOS,ERRnoaccess));
1157 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1158 close_file(fnum);
1159 return(ERROR(ERRDOS,ERRnoaccess));
1162 size = sbuf.st_size;
1163 fmode = dos_mode(cnum,fname,&sbuf);
1164 mtime = sbuf.st_mtime;
1166 if (fmode & aDIR) {
1167 DEBUG(3,("attempt to open a directory %s\n",fname));
1168 close_file(fnum);
1169 return(ERROR(ERRDOS,ERRnoaccess));
1172 outsize = set_message(outbuf,7,0,True);
1173 SSVAL(outbuf,smb_vwv0,fnum);
1174 SSVAL(outbuf,smb_vwv1,fmode);
1175 put_dos_date3(outbuf,smb_vwv2,mtime);
1176 SIVAL(outbuf,smb_vwv4,size);
1177 SSVAL(outbuf,smb_vwv6,rmode);
1179 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1180 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1183 if(fsp->granted_oplock)
1184 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1185 return(outsize);
1189 /****************************************************************************
1190 reply to an open and X
1191 ****************************************************************************/
1192 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1194 pstring fname;
1195 int cnum = SVAL(inbuf,smb_tid);
1196 int fnum = -1;
1197 int smb_mode = SVAL(inbuf,smb_vwv3);
1198 int smb_attr = SVAL(inbuf,smb_vwv5);
1199 BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1200 #if 0
1201 int open_flags = SVAL(inbuf,smb_vwv2);
1202 int smb_sattr = SVAL(inbuf,smb_vwv4);
1203 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1204 #endif
1205 int smb_ofun = SVAL(inbuf,smb_vwv8);
1206 int unixmode;
1207 int size=0,fmode=0,mtime=0,rmode=0;
1208 struct stat sbuf;
1209 int smb_action = 0;
1210 BOOL bad_path = False;
1211 files_struct *fsp;
1213 /* If it's an IPC, pass off the pipe handler. */
1214 if (IS_IPC(cnum))
1215 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1217 /* XXXX we need to handle passed times, sattr and flags */
1219 pstrcpy(fname,smb_buf(inbuf));
1220 unix_convert(fname,cnum,0,&bad_path);
1222 fnum = find_free_file();
1223 if (fnum < 0)
1224 return(ERROR(ERRSRV,ERRnofids));
1226 if (!check_name(fname,cnum))
1228 if((errno == ENOENT) && bad_path)
1230 unix_ERR_class = ERRDOS;
1231 unix_ERR_code = ERRbadpath;
1233 return(UNIXERROR(ERRDOS,ERRnoaccess));
1236 unixmode = unix_mode(cnum,smb_attr | aARCH);
1238 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1239 oplock_request, &rmode,&smb_action);
1241 fsp = &Files[fnum];
1243 if (!fsp->open)
1245 if((errno == ENOENT) && bad_path)
1247 unix_ERR_class = ERRDOS;
1248 unix_ERR_code = ERRbadpath;
1250 return(UNIXERROR(ERRDOS,ERRnoaccess));
1253 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1254 close_file(fnum);
1255 return(ERROR(ERRDOS,ERRnoaccess));
1258 size = sbuf.st_size;
1259 fmode = dos_mode(cnum,fname,&sbuf);
1260 mtime = sbuf.st_mtime;
1261 if (fmode & aDIR) {
1262 close_file(fnum);
1263 return(ERROR(ERRDOS,ERRnoaccess));
1266 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1267 smb_action |= EXTENDED_OPLOCK_GRANTED;
1268 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1271 if(fsp->granted_oplock) {
1272 smb_action |= EXTENDED_OPLOCK_GRANTED;
1273 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1276 set_message(outbuf,15,0,True);
1277 SSVAL(outbuf,smb_vwv2,fnum);
1278 SSVAL(outbuf,smb_vwv3,fmode);
1279 put_dos_date3(outbuf,smb_vwv4,mtime);
1280 SIVAL(outbuf,smb_vwv6,size);
1281 SSVAL(outbuf,smb_vwv8,rmode);
1282 SSVAL(outbuf,smb_vwv11,smb_action);
1284 chain_fnum = fnum;
1286 return chain_reply(inbuf,outbuf,length,bufsize);
1290 /****************************************************************************
1291 reply to a SMBulogoffX
1292 ****************************************************************************/
1293 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1295 uint16 vuid = SVAL(inbuf,smb_uid);
1296 user_struct *vuser = get_valid_user_struct(vuid);
1298 if(vuser == 0) {
1299 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1302 /* in user level security we are supposed to close any files
1303 open by this user */
1304 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1305 int i;
1306 for (i=0;i<MAX_OPEN_FILES;i++)
1307 if (Files[i].uid == vuser->uid && Files[i].open) {
1308 close_file(i);
1312 invalidate_vuid(vuid);
1314 set_message(outbuf,2,0,True);
1316 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1318 return chain_reply(inbuf,outbuf,length,bufsize);
1322 /****************************************************************************
1323 reply to a mknew or a create
1324 ****************************************************************************/
1325 int reply_mknew(char *inbuf,char *outbuf)
1327 pstring fname;
1328 int cnum,com;
1329 int fnum = -1;
1330 int outsize = 0;
1331 int createmode;
1332 mode_t unixmode;
1333 int ofun = 0;
1334 BOOL bad_path = False;
1335 files_struct *fsp;
1336 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1338 com = SVAL(inbuf,smb_com);
1339 cnum = SVAL(inbuf,smb_tid);
1341 createmode = SVAL(inbuf,smb_vwv0);
1342 pstrcpy(fname,smb_buf(inbuf)+1);
1343 unix_convert(fname,cnum,0,&bad_path);
1345 if (createmode & aVOLID)
1347 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1350 unixmode = unix_mode(cnum,createmode);
1352 fnum = find_free_file();
1353 if (fnum < 0)
1354 return(ERROR(ERRSRV,ERRnofids));
1356 if (!check_name(fname,cnum))
1358 if((errno == ENOENT) && bad_path)
1360 unix_ERR_class = ERRDOS;
1361 unix_ERR_code = ERRbadpath;
1363 return(UNIXERROR(ERRDOS,ERRnoaccess));
1366 if(com == SMBmknew)
1368 /* We should fail if file exists. */
1369 ofun = 0x10;
1371 else
1373 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1374 ofun = 0x12;
1377 /* Open file in dos compatibility share mode. */
1378 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1379 oplock_request, NULL, NULL);
1381 fsp = &Files[fnum];
1383 if (!fsp->open)
1385 if((errno == ENOENT) && bad_path)
1387 unix_ERR_class = ERRDOS;
1388 unix_ERR_code = ERRbadpath;
1390 return(UNIXERROR(ERRDOS,ERRnoaccess));
1393 outsize = set_message(outbuf,1,0,True);
1394 SSVAL(outbuf,smb_vwv0,fnum);
1396 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1397 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1400 if(fsp->granted_oplock)
1401 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1403 DEBUG(2,("new file %s\n",fname));
1404 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));
1406 return(outsize);
1410 /****************************************************************************
1411 reply to a create temporary file
1412 ****************************************************************************/
1413 int reply_ctemp(char *inbuf,char *outbuf)
1415 pstring fname;
1416 pstring fname2;
1417 int cnum;
1418 int fnum = -1;
1419 int outsize = 0;
1420 int createmode;
1421 mode_t unixmode;
1422 BOOL bad_path = False;
1423 files_struct *fsp;
1424 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1426 cnum = SVAL(inbuf,smb_tid);
1427 createmode = SVAL(inbuf,smb_vwv0);
1428 pstrcpy(fname,smb_buf(inbuf)+1);
1429 strcat(fname,"/TMXXXXXX");
1430 unix_convert(fname,cnum,0,&bad_path);
1432 unixmode = unix_mode(cnum,createmode);
1434 fnum = find_free_file();
1435 if (fnum < 0)
1436 return(ERROR(ERRSRV,ERRnofids));
1438 if (!check_name(fname,cnum))
1440 if((errno == ENOENT) && bad_path)
1442 unix_ERR_class = ERRDOS;
1443 unix_ERR_code = ERRbadpath;
1445 return(UNIXERROR(ERRDOS,ERRnoaccess));
1448 strcpy(fname2,(char *)mktemp(fname));
1450 /* Open file in dos compatibility share mode. */
1451 /* We should fail if file exists. */
1452 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1453 oplock_request, NULL, NULL);
1455 fsp = &Files[fnum];
1457 if (!fsp->open)
1459 if((errno == ENOENT) && bad_path)
1461 unix_ERR_class = ERRDOS;
1462 unix_ERR_code = ERRbadpath;
1464 return(UNIXERROR(ERRDOS,ERRnoaccess));
1467 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1468 SSVAL(outbuf,smb_vwv0,fnum);
1469 CVAL(smb_buf(outbuf),0) = 4;
1470 strcpy(smb_buf(outbuf) + 1,fname2);
1472 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1473 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1476 if(fsp->granted_oplock)
1477 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1479 DEBUG(2,("created temp file %s\n",fname2));
1480 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));
1482 return(outsize);
1486 /*******************************************************************
1487 check if a user is allowed to delete a file
1488 ********************************************************************/
1489 static BOOL can_delete(char *fname,int cnum,int dirtype)
1491 struct stat sbuf;
1492 int fmode;
1494 if (!CAN_WRITE(cnum)) return(False);
1496 if (sys_lstat(fname,&sbuf) != 0) return(False);
1497 fmode = dos_mode(cnum,fname,&sbuf);
1498 if (fmode & aDIR) return(False);
1499 if (!lp_delete_readonly(SNUM(cnum))) {
1500 if (fmode & aRONLY) return(False);
1502 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1503 return(False);
1504 if (!check_file_sharing(cnum,fname)) return(False);
1505 return(True);
1508 /****************************************************************************
1509 reply to a unlink
1510 ****************************************************************************/
1511 int reply_unlink(char *inbuf,char *outbuf)
1513 int outsize = 0;
1514 pstring name;
1515 int cnum;
1516 int dirtype;
1517 pstring directory;
1518 pstring mask;
1519 char *p;
1520 int count=0;
1521 int error = ERRnoaccess;
1522 BOOL has_wild;
1523 BOOL exists=False;
1524 BOOL bad_path = False;
1526 *directory = *mask = 0;
1528 cnum = SVAL(inbuf,smb_tid);
1529 dirtype = SVAL(inbuf,smb_vwv0);
1531 pstrcpy(name,smb_buf(inbuf) + 1);
1533 DEBUG(3,("reply_unlink : %s\n",name));
1535 unix_convert(name,cnum,0,&bad_path);
1537 p = strrchr(name,'/');
1538 if (!p) {
1539 strcpy(directory,"./");
1540 strcpy(mask,name);
1541 } else {
1542 *p = 0;
1543 strcpy(directory,name);
1544 strcpy(mask,p+1);
1547 if (is_mangled(mask))
1548 check_mangled_stack(mask);
1550 has_wild = strchr(mask,'*') || strchr(mask,'?');
1552 if (!has_wild) {
1553 strcat(directory,"/");
1554 strcat(directory,mask);
1555 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1556 if (!count) exists = file_exist(directory,NULL);
1557 } else {
1558 void *dirptr = NULL;
1559 char *dname;
1561 if (check_name(directory,cnum))
1562 dirptr = OpenDir(cnum, directory, True);
1564 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1565 the pattern matches against the long name, otherwise the short name
1566 We don't implement this yet XXXX
1569 if (dirptr)
1571 error = ERRbadfile;
1573 if (strequal(mask,"????????.???"))
1574 strcpy(mask,"*");
1576 while ((dname = ReadDirName(dirptr)))
1578 pstring fname;
1579 pstrcpy(fname,dname);
1581 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1583 error = ERRnoaccess;
1584 sprintf(fname,"%s/%s",directory,dname);
1585 if (!can_delete(fname,cnum,dirtype)) continue;
1586 if (!sys_unlink(fname)) count++;
1587 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1589 CloseDir(dirptr);
1593 if (count == 0) {
1594 if (exists)
1595 return(ERROR(ERRDOS,error));
1596 else
1598 if((errno == ENOENT) && bad_path)
1600 unix_ERR_class = ERRDOS;
1601 unix_ERR_code = ERRbadpath;
1603 return(UNIXERROR(ERRDOS,error));
1607 outsize = set_message(outbuf,0,0,True);
1609 return(outsize);
1613 /****************************************************************************
1614 reply to a readbraw (core+ protocol)
1615 ****************************************************************************/
1616 int reply_readbraw(char *inbuf, char *outbuf)
1618 int cnum,maxcount,mincount,fnum;
1619 int nread = 0;
1620 uint32 startpos;
1621 char *header = outbuf;
1622 int ret=0;
1623 int fd;
1624 char *fname;
1627 * Special check if an oplock break has been issued
1628 * and the readraw request croses on the wire, we must
1629 * return a zero length response here.
1632 if(global_oplock_break)
1634 _smb_setlen(header,0);
1635 transfer_file(0,Client,0,header,4,0);
1636 DEBUG(5,("readbraw - oplock break finished\n"));
1637 return -1;
1640 cnum = SVAL(inbuf,smb_tid);
1641 fnum = GETFNUM(inbuf,smb_vwv0);
1643 startpos = IVAL(inbuf,smb_vwv1);
1644 maxcount = SVAL(inbuf,smb_vwv3);
1645 mincount = SVAL(inbuf,smb_vwv4);
1647 /* ensure we don't overrun the packet size */
1648 maxcount = MIN(65535,maxcount);
1649 maxcount = MAX(mincount,maxcount);
1651 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1653 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1654 _smb_setlen(header,0);
1655 transfer_file(0,Client,0,header,4,0);
1656 return(-1);
1658 else
1660 fd = Files[fnum].fd_ptr->fd;
1661 fname = Files[fnum].name;
1665 if (!is_locked(fnum,cnum,maxcount,startpos))
1667 int size = Files[fnum].size;
1668 int sizeneeded = startpos + maxcount;
1670 if (size < sizeneeded) {
1671 struct stat st;
1672 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1673 size = st.st_size;
1674 if (!Files[fnum].can_write)
1675 Files[fnum].size = size;
1678 nread = MIN(maxcount,(int)(size - startpos));
1681 if (nread < mincount)
1682 nread = 0;
1684 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1685 timestring(),
1686 fnum,cnum,startpos,
1687 maxcount,mincount,nread));
1689 #if UNSAFE_READRAW
1691 int predict=0;
1692 _smb_setlen(header,nread);
1694 if (!Files[fnum].can_write)
1695 predict = read_predict(fd,startpos,header+4,NULL,nread);
1697 if ((nread-predict) > 0)
1698 seek_file(fnum,startpos + predict);
1700 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1701 startpos+predict);
1704 if (ret != nread+4)
1705 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1706 fname,startpos,nread,ret));
1708 #else
1709 ret = read_file(fnum,header+4,startpos,nread);
1710 if (ret < mincount) ret = 0;
1712 _smb_setlen(header,ret);
1713 transfer_file(0,Client,0,header,4+ret,0);
1714 #endif
1716 DEBUG(5,("readbraw finished\n"));
1717 return -1;
1721 /****************************************************************************
1722 reply to a lockread (core+ protocol)
1723 ****************************************************************************/
1724 int reply_lockread(char *inbuf,char *outbuf)
1726 int cnum,fnum;
1727 int nread = -1;
1728 char *data;
1729 int outsize = 0;
1730 uint32 startpos, numtoread;
1731 int eclass;
1732 uint32 ecode;
1734 cnum = SVAL(inbuf,smb_tid);
1735 fnum = GETFNUM(inbuf,smb_vwv0);
1737 CHECK_FNUM(fnum,cnum);
1738 CHECK_READ(fnum);
1739 CHECK_ERROR(fnum);
1741 numtoread = SVAL(inbuf,smb_vwv1);
1742 startpos = IVAL(inbuf,smb_vwv2);
1744 outsize = set_message(outbuf,5,3,True);
1745 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1746 data = smb_buf(outbuf) + 3;
1748 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1749 return (ERROR(eclass,ecode));
1751 nread = read_file(fnum,data,startpos,numtoread);
1753 if (nread < 0)
1754 return(UNIXERROR(ERRDOS,ERRnoaccess));
1756 outsize += nread;
1757 SSVAL(outbuf,smb_vwv0,nread);
1758 SSVAL(outbuf,smb_vwv5,nread+3);
1759 SSVAL(smb_buf(outbuf),1,nread);
1761 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1763 return(outsize);
1767 /****************************************************************************
1768 reply to a read
1769 ****************************************************************************/
1770 int reply_read(char *inbuf,char *outbuf)
1772 int cnum,numtoread,fnum;
1773 int nread = 0;
1774 char *data;
1775 uint32 startpos;
1776 int outsize = 0;
1778 cnum = SVAL(inbuf,smb_tid);
1779 fnum = GETFNUM(inbuf,smb_vwv0);
1781 CHECK_FNUM(fnum,cnum);
1782 CHECK_READ(fnum);
1783 CHECK_ERROR(fnum);
1785 numtoread = SVAL(inbuf,smb_vwv1);
1786 startpos = IVAL(inbuf,smb_vwv2);
1788 outsize = set_message(outbuf,5,3,True);
1789 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1790 data = smb_buf(outbuf) + 3;
1792 if (is_locked(fnum,cnum,numtoread,startpos))
1793 return(ERROR(ERRDOS,ERRlock));
1795 if (numtoread > 0)
1796 nread = read_file(fnum,data,startpos,numtoread);
1798 if (nread < 0)
1799 return(UNIXERROR(ERRDOS,ERRnoaccess));
1801 outsize += nread;
1802 SSVAL(outbuf,smb_vwv0,nread);
1803 SSVAL(outbuf,smb_vwv5,nread+3);
1804 CVAL(smb_buf(outbuf),0) = 1;
1805 SSVAL(smb_buf(outbuf),1,nread);
1807 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1809 return(outsize);
1813 /****************************************************************************
1814 reply to a read and X
1815 ****************************************************************************/
1816 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1818 int fnum = GETFNUM(inbuf,smb_vwv2);
1819 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1820 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1821 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1822 int cnum;
1823 int nread = -1;
1824 char *data;
1825 BOOL ok = False;
1827 cnum = SVAL(inbuf,smb_tid);
1829 CHECK_FNUM(fnum,cnum);
1830 CHECK_READ(fnum);
1831 CHECK_ERROR(fnum);
1833 set_message(outbuf,12,0,True);
1834 data = smb_buf(outbuf);
1836 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1837 return(ERROR(ERRDOS,ERRlock));
1838 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1839 ok = True;
1841 if (nread < 0)
1842 return(UNIXERROR(ERRDOS,ERRnoaccess));
1844 SSVAL(outbuf,smb_vwv5,nread);
1845 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1846 SSVAL(smb_buf(outbuf),-2,nread);
1848 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1849 timestring(),fnum,cnum,
1850 smb_mincnt,smb_maxcnt,nread));
1852 chain_fnum = fnum;
1854 return chain_reply(inbuf,outbuf,length,bufsize);
1858 /****************************************************************************
1859 reply to a writebraw (core+ or LANMAN1.0 protocol)
1860 ****************************************************************************/
1861 int reply_writebraw(char *inbuf,char *outbuf)
1863 int nwritten=0;
1864 int total_written=0;
1865 int numtowrite=0;
1866 int cnum,fnum;
1867 int outsize = 0;
1868 long startpos;
1869 char *data=NULL;
1870 BOOL write_through;
1871 int tcount;
1873 cnum = SVAL(inbuf,smb_tid);
1874 fnum = GETFNUM(inbuf,smb_vwv0);
1876 CHECK_FNUM(fnum,cnum);
1877 CHECK_WRITE(fnum);
1878 CHECK_ERROR(fnum);
1880 tcount = IVAL(inbuf,smb_vwv1);
1881 startpos = IVAL(inbuf,smb_vwv3);
1882 write_through = BITSETW(inbuf+smb_vwv7,0);
1884 /* We have to deal with slightly different formats depending
1885 on whether we are using the core+ or lanman1.0 protocol */
1886 if(Protocol <= PROTOCOL_COREPLUS) {
1887 numtowrite = SVAL(smb_buf(inbuf),-2);
1888 data = smb_buf(inbuf);
1889 } else {
1890 numtowrite = SVAL(inbuf,smb_vwv10);
1891 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1894 /* force the error type */
1895 CVAL(inbuf,smb_com) = SMBwritec;
1896 CVAL(outbuf,smb_com) = SMBwritec;
1898 if (is_locked(fnum,cnum,tcount,startpos))
1899 return(ERROR(ERRDOS,ERRlock));
1901 if (seek_file(fnum,startpos) != startpos)
1902 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1904 if (numtowrite>0)
1905 nwritten = write_file(fnum,data,numtowrite);
1907 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1908 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1910 if (nwritten < numtowrite)
1911 return(UNIXERROR(ERRHRD,ERRdiskfull));
1913 total_written = nwritten;
1915 /* Return a message to the redirector to tell it
1916 to send more bytes */
1917 CVAL(outbuf,smb_com) = SMBwritebraw;
1918 SSVALS(outbuf,smb_vwv0,-1);
1919 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1920 send_smb(Client,outbuf);
1922 /* Now read the raw data into the buffer and write it */
1923 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1924 exit_server("secondary writebraw failed");
1927 /* Even though this is not an smb message, smb_len
1928 returns the generic length of an smb message */
1929 numtowrite = smb_len(inbuf);
1931 if (tcount > nwritten+numtowrite) {
1932 DEBUG(3,("Client overestimated the write %d %d %d\n",
1933 tcount,nwritten,numtowrite));
1936 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1937 startpos+nwritten);
1938 total_written += nwritten;
1940 /* Set up outbuf to return the correct return */
1941 outsize = set_message(outbuf,1,0,True);
1942 CVAL(outbuf,smb_com) = SMBwritec;
1943 SSVAL(outbuf,smb_vwv0,total_written);
1945 if (nwritten < numtowrite) {
1946 CVAL(outbuf,smb_rcls) = ERRHRD;
1947 SSVAL(outbuf,smb_err,ERRdiskfull);
1950 if (lp_syncalways(SNUM(cnum)) || write_through)
1951 sync_file(fnum);
1953 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1954 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1956 /* we won't return a status if write through is not selected - this
1957 follows what WfWg does */
1958 if (!write_through && total_written==tcount)
1959 return(-1);
1961 return(outsize);
1965 /****************************************************************************
1966 reply to a writeunlock (core+)
1967 ****************************************************************************/
1968 int reply_writeunlock(char *inbuf,char *outbuf)
1970 int cnum,fnum;
1971 int nwritten = -1;
1972 int outsize = 0;
1973 char *data;
1974 uint32 numtowrite,startpos;
1975 int eclass;
1976 uint32 ecode;
1978 cnum = SVAL(inbuf,smb_tid);
1979 fnum = GETFNUM(inbuf,smb_vwv0);
1981 CHECK_FNUM(fnum,cnum);
1982 CHECK_WRITE(fnum);
1983 CHECK_ERROR(fnum);
1985 numtowrite = SVAL(inbuf,smb_vwv1);
1986 startpos = IVAL(inbuf,smb_vwv2);
1987 data = smb_buf(inbuf) + 3;
1989 if (is_locked(fnum,cnum,numtowrite,startpos))
1990 return(ERROR(ERRDOS,ERRlock));
1992 seek_file(fnum,startpos);
1994 /* The special X/Open SMB protocol handling of
1995 zero length writes is *NOT* done for
1996 this call */
1997 if(numtowrite == 0)
1998 nwritten = 0;
1999 else
2000 nwritten = write_file(fnum,data,numtowrite);
2002 if (lp_syncalways(SNUM(cnum)))
2003 sync_file(fnum);
2005 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2006 return(UNIXERROR(ERRDOS,ERRnoaccess));
2008 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2009 return(ERROR(eclass,ecode));
2011 outsize = set_message(outbuf,1,0,True);
2013 SSVAL(outbuf,smb_vwv0,nwritten);
2015 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2016 timestring(),fnum,cnum,numtowrite,nwritten));
2018 return(outsize);
2022 /****************************************************************************
2023 reply to a write
2024 ****************************************************************************/
2025 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
2027 int cnum,numtowrite,fnum;
2028 int nwritten = -1;
2029 int outsize = 0;
2030 int startpos;
2031 char *data;
2033 dum1 = dum2 = 0;
2036 cnum = SVAL(inbuf,smb_tid);
2037 fnum = GETFNUM(inbuf,smb_vwv0);
2039 CHECK_FNUM(fnum,cnum);
2040 CHECK_WRITE(fnum);
2041 CHECK_ERROR(fnum);
2043 numtowrite = SVAL(inbuf,smb_vwv1);
2044 startpos = IVAL(inbuf,smb_vwv2);
2045 data = smb_buf(inbuf) + 3;
2047 if (is_locked(fnum,cnum,numtowrite,startpos))
2048 return(ERROR(ERRDOS,ERRlock));
2050 seek_file(fnum,startpos);
2052 /* X/Open SMB protocol says that if smb_vwv1 is
2053 zero then the file size should be extended or
2054 truncated to the size given in smb_vwv[2-3] */
2055 if(numtowrite == 0)
2056 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2057 else
2058 nwritten = write_file(fnum,data,numtowrite);
2060 if (lp_syncalways(SNUM(cnum)))
2061 sync_file(fnum);
2063 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2064 return(UNIXERROR(ERRDOS,ERRnoaccess));
2066 outsize = set_message(outbuf,1,0,True);
2068 SSVAL(outbuf,smb_vwv0,nwritten);
2070 if (nwritten < numtowrite) {
2071 CVAL(outbuf,smb_rcls) = ERRHRD;
2072 SSVAL(outbuf,smb_err,ERRdiskfull);
2075 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2077 return(outsize);
2081 /****************************************************************************
2082 reply to a write and X
2083 ****************************************************************************/
2084 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2086 int fnum = GETFNUM(inbuf,smb_vwv2);
2087 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2088 int smb_dsize = SVAL(inbuf,smb_vwv10);
2089 int smb_doff = SVAL(inbuf,smb_vwv11);
2090 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2091 int cnum;
2092 int nwritten = -1;
2093 char *data;
2095 cnum = SVAL(inbuf,smb_tid);
2097 CHECK_FNUM(fnum,cnum);
2098 CHECK_WRITE(fnum);
2099 CHECK_ERROR(fnum);
2101 data = smb_base(inbuf) + smb_doff;
2103 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2104 return(ERROR(ERRDOS,ERRlock));
2106 seek_file(fnum,smb_offs);
2108 /* X/Open SMB protocol says that, unlike SMBwrite
2109 if the length is zero then NO truncation is
2110 done, just a write of zero. To truncate a file,
2111 use SMBwrite. */
2112 if(smb_dsize == 0)
2113 nwritten = 0;
2114 else
2115 nwritten = write_file(fnum,data,smb_dsize);
2117 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2118 return(UNIXERROR(ERRDOS,ERRnoaccess));
2120 set_message(outbuf,6,0,True);
2122 SSVAL(outbuf,smb_vwv2,nwritten);
2124 if (nwritten < smb_dsize) {
2125 CVAL(outbuf,smb_rcls) = ERRHRD;
2126 SSVAL(outbuf,smb_err,ERRdiskfull);
2129 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2131 chain_fnum = fnum;
2133 if (lp_syncalways(SNUM(cnum)) || write_through)
2134 sync_file(fnum);
2136 return chain_reply(inbuf,outbuf,length,bufsize);
2140 /****************************************************************************
2141 reply to a lseek
2142 ****************************************************************************/
2143 int reply_lseek(char *inbuf,char *outbuf)
2145 int cnum,fnum;
2146 uint32 startpos;
2147 int32 res= -1;
2148 int mode,umode;
2149 int outsize = 0;
2151 cnum = SVAL(inbuf,smb_tid);
2152 fnum = GETFNUM(inbuf,smb_vwv0);
2154 CHECK_FNUM(fnum,cnum);
2155 CHECK_ERROR(fnum);
2157 mode = SVAL(inbuf,smb_vwv1) & 3;
2158 startpos = IVAL(inbuf,smb_vwv2);
2160 switch (mode & 3)
2162 case 0: umode = SEEK_SET; break;
2163 case 1: umode = SEEK_CUR; break;
2164 case 2: umode = SEEK_END; break;
2165 default:
2166 umode = SEEK_SET; break;
2169 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2170 Files[fnum].pos = res;
2172 outsize = set_message(outbuf,2,0,True);
2173 SIVALS(outbuf,smb_vwv0,res);
2175 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2177 return(outsize);
2181 /****************************************************************************
2182 reply to a flush
2183 ****************************************************************************/
2184 int reply_flush(char *inbuf,char *outbuf)
2186 int cnum, fnum;
2187 int outsize = set_message(outbuf,0,0,True);
2189 cnum = SVAL(inbuf,smb_tid);
2190 fnum = GETFNUM(inbuf,smb_vwv0);
2192 if (fnum != 0xFFFF) {
2193 CHECK_FNUM(fnum,cnum);
2194 CHECK_ERROR(fnum);
2197 if (fnum == 0xFFFF)
2199 int i;
2200 for (i=0;i<MAX_OPEN_FILES;i++)
2201 if (OPEN_FNUM(i))
2202 sync_file(i);
2204 else
2205 sync_file(fnum);
2207 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2208 return(outsize);
2212 /****************************************************************************
2213 reply to a exit
2214 ****************************************************************************/
2215 int reply_exit(char *inbuf,char *outbuf)
2217 int outsize = set_message(outbuf,0,0,True);
2218 DEBUG(3,("%s exit\n",timestring()));
2220 return(outsize);
2224 /****************************************************************************
2225 reply to a close
2226 ****************************************************************************/
2227 int reply_close(char *inbuf,char *outbuf)
2229 int fnum,cnum;
2230 int outsize = 0;
2231 time_t mtime;
2232 int32 eclass = 0, err = 0;
2234 outsize = set_message(outbuf,0,0,True);
2236 cnum = SVAL(inbuf,smb_tid);
2238 fnum = GETFNUM(inbuf,smb_vwv0);
2239 CHECK_FNUM(fnum,cnum);
2241 if(HAS_CACHED_ERROR(fnum)) {
2242 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2243 err = Files[fnum].wbmpx_ptr->wr_error;
2246 mtime = make_unix_date3(inbuf+smb_vwv1);
2248 /* try and set the date */
2249 set_filetime(Files[fnum].name,mtime);
2251 close_file(fnum);
2253 /* We have a cached error */
2254 if(eclass || err)
2255 return(ERROR(eclass,err));
2257 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2258 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2259 Connections[cnum].num_files_open));
2261 return(outsize);
2265 /****************************************************************************
2266 reply to a writeclose (Core+ protocol)
2267 ****************************************************************************/
2268 int reply_writeclose(char *inbuf,char *outbuf)
2270 int cnum,numtowrite,fnum;
2271 int nwritten = -1;
2272 int outsize = 0;
2273 int startpos;
2274 char *data;
2275 time_t mtime;
2277 cnum = SVAL(inbuf,smb_tid);
2278 fnum = GETFNUM(inbuf,smb_vwv0);
2280 CHECK_FNUM(fnum,cnum);
2281 CHECK_WRITE(fnum);
2282 CHECK_ERROR(fnum);
2284 numtowrite = SVAL(inbuf,smb_vwv1);
2285 startpos = IVAL(inbuf,smb_vwv2);
2286 mtime = make_unix_date3(inbuf+smb_vwv4);
2287 data = smb_buf(inbuf) + 1;
2289 if (is_locked(fnum,cnum,numtowrite,startpos))
2290 return(ERROR(ERRDOS,ERRlock));
2292 seek_file(fnum,startpos);
2294 nwritten = write_file(fnum,data,numtowrite);
2296 set_filetime(Files[fnum].name,mtime);
2298 close_file(fnum);
2300 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2301 timestring(),fnum,cnum,numtowrite,nwritten,
2302 Connections[cnum].num_files_open));
2304 if (nwritten <= 0)
2305 return(UNIXERROR(ERRDOS,ERRnoaccess));
2307 outsize = set_message(outbuf,1,0,True);
2309 SSVAL(outbuf,smb_vwv0,nwritten);
2310 return(outsize);
2314 /****************************************************************************
2315 reply to a lock
2316 ****************************************************************************/
2317 int reply_lock(char *inbuf,char *outbuf)
2319 int fnum,cnum;
2320 int outsize = set_message(outbuf,0,0,True);
2321 uint32 count,offset;
2322 int eclass;
2323 uint32 ecode;
2325 cnum = SVAL(inbuf,smb_tid);
2326 fnum = GETFNUM(inbuf,smb_vwv0);
2328 CHECK_FNUM(fnum,cnum);
2329 CHECK_ERROR(fnum);
2331 count = IVAL(inbuf,smb_vwv1);
2332 offset = IVAL(inbuf,smb_vwv3);
2334 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));
2336 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2337 return (ERROR(eclass,ecode));
2339 return(outsize);
2343 /****************************************************************************
2344 reply to a unlock
2345 ****************************************************************************/
2346 int reply_unlock(char *inbuf,char *outbuf)
2348 int fnum,cnum;
2349 int outsize = set_message(outbuf,0,0,True);
2350 uint32 count,offset;
2351 int eclass;
2352 uint32 ecode;
2354 cnum = SVAL(inbuf,smb_tid);
2355 fnum = GETFNUM(inbuf,smb_vwv0);
2357 CHECK_FNUM(fnum,cnum);
2358 CHECK_ERROR(fnum);
2360 count = IVAL(inbuf,smb_vwv1);
2361 offset = IVAL(inbuf,smb_vwv3);
2363 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2364 return (ERROR(eclass,ecode));
2366 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));
2368 return(outsize);
2372 /****************************************************************************
2373 reply to a tdis
2374 ****************************************************************************/
2375 int reply_tdis(char *inbuf,char *outbuf)
2377 int cnum;
2378 int outsize = set_message(outbuf,0,0,True);
2379 uint16 vuid;
2381 cnum = SVAL(inbuf,smb_tid);
2382 vuid = SVAL(inbuf,smb_uid);
2384 if (!OPEN_CNUM(cnum)) {
2385 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2386 return(ERROR(ERRSRV,ERRinvnid));
2389 Connections[cnum].used = False;
2391 close_cnum(cnum,vuid);
2393 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2395 return outsize;
2400 /****************************************************************************
2401 reply to a echo
2402 ****************************************************************************/
2403 int reply_echo(char *inbuf,char *outbuf)
2405 int cnum;
2406 int smb_reverb = SVAL(inbuf,smb_vwv0);
2407 int seq_num;
2408 int data_len = smb_buflen(inbuf);
2409 int outsize = set_message(outbuf,1,data_len,True);
2411 cnum = SVAL(inbuf,smb_tid);
2413 /* According to the latest CIFS spec we shouldn't
2414 care what the TID is.
2417 #if 0
2418 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2420 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2421 return(ERROR(ERRSRV,ERRinvnid));
2423 #endif
2425 /* copy any incoming data back out */
2426 if (data_len > 0)
2427 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2429 if (smb_reverb > 100)
2431 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2432 smb_reverb = 100;
2435 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2437 SSVAL(outbuf,smb_vwv0,seq_num);
2439 smb_setlen(outbuf,outsize - 4);
2441 send_smb(Client,outbuf);
2444 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2446 return -1;
2450 /****************************************************************************
2451 reply to a printopen
2452 ****************************************************************************/
2453 int reply_printopen(char *inbuf,char *outbuf)
2455 pstring fname;
2456 pstring fname2;
2457 int cnum;
2458 int fnum = -1;
2459 int outsize = 0;
2461 *fname = *fname2 = 0;
2463 cnum = SVAL(inbuf,smb_tid);
2465 if (!CAN_PRINT(cnum))
2466 return(ERROR(ERRDOS,ERRnoaccess));
2469 pstring s;
2470 char *p;
2471 pstrcpy(s,smb_buf(inbuf)+1);
2472 p = s;
2473 while (*p)
2475 if (!(isalnum(*p) || strchr("._-",*p)))
2476 *p = 'X';
2477 p++;
2480 if (strlen(s) > 10) s[10] = 0;
2482 sprintf(fname,"%s.XXXXXX",s);
2485 fnum = find_free_file();
2486 if (fnum < 0)
2487 return(ERROR(ERRSRV,ERRnofids));
2489 strcpy(fname2,(char *)mktemp(fname));
2491 if (!check_name(fname2,cnum))
2492 return(ERROR(ERRDOS,ERRnoaccess));
2494 /* Open for exclusive use, write only. */
2495 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2496 0, NULL, NULL);
2498 if (!Files[fnum].open)
2499 return(UNIXERROR(ERRDOS,ERRnoaccess));
2501 /* force it to be a print file */
2502 Files[fnum].print_file = True;
2504 outsize = set_message(outbuf,1,0,True);
2505 SSVAL(outbuf,smb_vwv0,fnum);
2507 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2509 return(outsize);
2513 /****************************************************************************
2514 reply to a printclose
2515 ****************************************************************************/
2516 int reply_printclose(char *inbuf,char *outbuf)
2518 int fnum,cnum;
2519 int outsize = set_message(outbuf,0,0,True);
2521 cnum = SVAL(inbuf,smb_tid);
2522 fnum = GETFNUM(inbuf,smb_vwv0);
2524 CHECK_FNUM(fnum,cnum);
2525 CHECK_ERROR(fnum);
2527 if (!CAN_PRINT(cnum))
2528 return(ERROR(ERRDOS,ERRnoaccess));
2530 close_file(fnum);
2532 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2534 return(outsize);
2538 /****************************************************************************
2539 reply to a printqueue
2540 ****************************************************************************/
2541 int reply_printqueue(char *inbuf,char *outbuf)
2543 int cnum;
2544 int outsize = set_message(outbuf,2,3,True);
2545 int max_count = SVAL(inbuf,smb_vwv0);
2546 int start_index = SVAL(inbuf,smb_vwv1);
2547 uint16 vuid;
2549 cnum = SVAL(inbuf,smb_tid);
2550 vuid = SVAL(inbuf,smb_uid);
2552 /* allow checking the queue for anyone */
2553 #if 0
2554 if (!CAN_PRINT(cnum))
2555 return(ERROR(ERRDOS,ERRnoaccess));
2556 #endif
2558 SSVAL(outbuf,smb_vwv0,0);
2559 SSVAL(outbuf,smb_vwv1,0);
2560 CVAL(smb_buf(outbuf),0) = 1;
2561 SSVAL(smb_buf(outbuf),1,0);
2563 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2564 timestring(),cnum,start_index,max_count));
2566 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2568 int i;
2569 cnum = -1;
2571 for (i=0;i<MAX_CONNECTIONS;i++)
2572 if (CAN_PRINT(i) && Connections[i].printer)
2573 cnum = i;
2575 if (cnum == -1)
2576 for (i=0;i<MAX_CONNECTIONS;i++)
2577 if (OPEN_CNUM(i))
2578 cnum = i;
2580 if (!OPEN_CNUM(cnum))
2581 return(ERROR(ERRSRV,ERRinvnid));
2583 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2586 if (!become_user(cnum,vuid))
2587 return(ERROR(ERRSRV,ERRinvnid));
2590 print_queue_struct *queue = NULL;
2591 char *p = smb_buf(outbuf) + 3;
2592 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2593 int num_to_get = ABS(max_count);
2594 int first = (max_count>0?start_index:start_index+max_count+1);
2595 int i;
2597 if (first >= count)
2598 num_to_get = 0;
2599 else
2600 num_to_get = MIN(num_to_get,count-first);
2603 for (i=first;i<first+num_to_get;i++)
2605 put_dos_date2(p,0,queue[i].time);
2606 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2607 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2608 SIVAL(p,7,queue[i].size);
2609 CVAL(p,11) = 0;
2610 StrnCpy(p+12,queue[i].user,16);
2611 p += 28;
2614 if (count > 0)
2616 outsize = set_message(outbuf,2,28*count+3,False);
2617 SSVAL(outbuf,smb_vwv0,count);
2618 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2619 CVAL(smb_buf(outbuf),0) = 1;
2620 SSVAL(smb_buf(outbuf),1,28*count);
2623 if (queue) free(queue);
2625 DEBUG(3,("%d entries returned in queue\n",count));
2628 return(outsize);
2632 /****************************************************************************
2633 reply to a printwrite
2634 ****************************************************************************/
2635 int reply_printwrite(char *inbuf,char *outbuf)
2637 int cnum,numtowrite,fnum;
2638 int outsize = set_message(outbuf,0,0,True);
2639 char *data;
2641 cnum = SVAL(inbuf,smb_tid);
2643 if (!CAN_PRINT(cnum))
2644 return(ERROR(ERRDOS,ERRnoaccess));
2646 fnum = GETFNUM(inbuf,smb_vwv0);
2648 CHECK_FNUM(fnum,cnum);
2649 CHECK_WRITE(fnum);
2650 CHECK_ERROR(fnum);
2652 numtowrite = SVAL(smb_buf(inbuf),1);
2653 data = smb_buf(inbuf) + 3;
2655 if (write_file(fnum,data,numtowrite) != numtowrite)
2656 return(UNIXERROR(ERRDOS,ERRnoaccess));
2658 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2660 return(outsize);
2664 /****************************************************************************
2665 reply to a mkdir
2666 ****************************************************************************/
2667 int reply_mkdir(char *inbuf,char *outbuf)
2669 pstring directory;
2670 int cnum;
2671 int outsize,ret= -1;
2672 BOOL bad_path = False;
2674 pstrcpy(directory,smb_buf(inbuf) + 1);
2675 cnum = SVAL(inbuf,smb_tid);
2676 unix_convert(directory,cnum,0,&bad_path);
2678 if (check_name(directory,cnum))
2679 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2681 if (ret < 0)
2683 if((errno == ENOENT) && bad_path)
2685 unix_ERR_class = ERRDOS;
2686 unix_ERR_code = ERRbadpath;
2688 return(UNIXERROR(ERRDOS,ERRnoaccess));
2691 outsize = set_message(outbuf,0,0,True);
2693 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2695 return(outsize);
2698 /****************************************************************************
2699 Static function used by reply_rmdir to delete an entire directory
2700 tree recursively.
2701 ****************************************************************************/
2702 static BOOL recursive_rmdir(char *directory)
2704 char *dname = NULL;
2705 BOOL ret = False;
2706 void *dirptr = OpenDir(-1, directory, False);
2708 if(dirptr == NULL)
2709 return True;
2711 while((dname = ReadDirName(dirptr)))
2713 pstring fullname;
2714 struct stat st;
2716 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2717 continue;
2719 /* Construct the full name. */
2720 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2722 errno = ENOMEM;
2723 ret = True;
2724 break;
2726 strcpy(fullname, directory);
2727 strcat(fullname, "/");
2728 strcat(fullname, dname);
2730 if(sys_lstat(fullname, &st) != 0)
2732 ret = True;
2733 break;
2736 if(st.st_mode & S_IFDIR)
2738 if(recursive_rmdir(fullname)!=0)
2740 ret = True;
2741 break;
2743 if(sys_rmdir(fullname) != 0)
2745 ret = True;
2746 break;
2749 else if(sys_unlink(fullname) != 0)
2751 ret = True;
2752 break;
2755 CloseDir(dirptr);
2756 return ret;
2759 /****************************************************************************
2760 reply to a rmdir
2761 ****************************************************************************/
2762 int reply_rmdir(char *inbuf,char *outbuf)
2764 pstring directory;
2765 int cnum;
2766 int outsize = 0;
2767 BOOL ok = False;
2768 BOOL bad_path = False;
2770 cnum = SVAL(inbuf,smb_tid);
2771 pstrcpy(directory,smb_buf(inbuf) + 1);
2772 unix_convert(directory,cnum,0,&bad_path);
2774 if (check_name(directory,cnum))
2777 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2778 ok = (sys_rmdir(directory) == 0);
2779 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2781 /* Check to see if the only thing in this directory are
2782 vetoed files/directories. If so then delete them and
2783 retry. If we fail to delete any of them (and we *don't*
2784 do a recursive delete) then fail the rmdir. */
2785 BOOL all_veto_files = True;
2786 char *dname;
2787 void *dirptr = OpenDir(cnum, directory, False);
2789 if(dirptr != NULL)
2791 int dirpos = TellDir(dirptr);
2792 while ((dname = ReadDirName(dirptr)))
2794 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2795 continue;
2796 if(!IS_VETO_PATH(cnum, dname))
2798 all_veto_files = False;
2799 break;
2802 if(all_veto_files)
2804 SeekDir(dirptr,dirpos);
2805 while ((dname = ReadDirName(dirptr)))
2807 pstring fullname;
2808 struct stat st;
2810 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2811 continue;
2813 /* Construct the full name. */
2814 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2816 errno = ENOMEM;
2817 break;
2819 pstrcpy(fullname, directory);
2820 strcat(fullname, "/");
2821 strcat(fullname, dname);
2823 if(sys_lstat(fullname, &st) != 0)
2824 break;
2825 if(st.st_mode & S_IFDIR)
2827 if(lp_recursive_veto_delete(SNUM(cnum)))
2829 if(recursive_rmdir(fullname) != 0)
2830 break;
2832 if(sys_rmdir(fullname) != 0)
2833 break;
2835 else if(sys_unlink(fullname) != 0)
2836 break;
2838 CloseDir(dirptr);
2839 /* Retry the rmdir */
2840 ok = (sys_rmdir(directory) == 0);
2842 else
2843 CloseDir(dirptr);
2845 else
2846 errno = ENOTEMPTY;
2849 if (!ok)
2850 DEBUG(3,("couldn't remove directory %s : %s\n",
2851 directory,strerror(errno)));
2854 if (!ok)
2856 if((errno == ENOENT) && bad_path)
2858 unix_ERR_class = ERRDOS;
2859 unix_ERR_code = ERRbadpath;
2861 return(UNIXERROR(ERRDOS,ERRbadpath));
2864 outsize = set_message(outbuf,0,0,True);
2866 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2868 return(outsize);
2872 /*******************************************************************
2873 resolve wildcards in a filename rename
2874 ********************************************************************/
2875 static BOOL resolve_wildcards(char *name1,char *name2)
2877 fstring root1,root2;
2878 fstring ext1,ext2;
2879 char *p,*p2;
2881 name1 = strrchr(name1,'/');
2882 name2 = strrchr(name2,'/');
2884 if (!name1 || !name2) return(False);
2886 fstrcpy(root1,name1);
2887 fstrcpy(root2,name2);
2888 p = strrchr(root1,'.');
2889 if (p) {
2890 *p = 0;
2891 fstrcpy(ext1,p+1);
2892 } else {
2893 fstrcpy(ext1,"");
2895 p = strrchr(root2,'.');
2896 if (p) {
2897 *p = 0;
2898 fstrcpy(ext2,p+1);
2899 } else {
2900 fstrcpy(ext2,"");
2903 p = root1;
2904 p2 = root2;
2905 while (*p2) {
2906 if (*p2 == '?') {
2907 *p2 = *p;
2908 p2++;
2909 } else {
2910 p2++;
2912 if (*p) p++;
2915 p = ext1;
2916 p2 = ext2;
2917 while (*p2) {
2918 if (*p2 == '?') {
2919 *p2 = *p;
2920 p2++;
2921 } else {
2922 p2++;
2924 if (*p) p++;
2927 strcpy(name2,root2);
2928 if (ext2[0]) {
2929 strcat(name2,".");
2930 strcat(name2,ext2);
2933 return(True);
2936 /*******************************************************************
2937 check if a user is allowed to rename a file
2938 ********************************************************************/
2939 static BOOL can_rename(char *fname,int cnum)
2941 struct stat sbuf;
2943 if (!CAN_WRITE(cnum)) return(False);
2945 if (sys_lstat(fname,&sbuf) != 0) return(False);
2946 if (!check_file_sharing(cnum,fname)) return(False);
2948 return(True);
2951 /****************************************************************************
2952 reply to a mv
2953 ****************************************************************************/
2954 int reply_mv(char *inbuf,char *outbuf)
2956 int outsize = 0;
2957 pstring name;
2958 int cnum;
2959 pstring directory;
2960 pstring mask,newname;
2961 pstring newname_last_component;
2962 char *p;
2963 int count=0;
2964 int error = ERRnoaccess;
2965 BOOL has_wild;
2966 BOOL exists=False;
2967 BOOL bad_path1 = False;
2968 BOOL bad_path2 = False;
2970 *directory = *mask = 0;
2972 cnum = SVAL(inbuf,smb_tid);
2974 pstrcpy(name,smb_buf(inbuf) + 1);
2975 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2977 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2979 unix_convert(name,cnum,0,&bad_path1);
2980 unix_convert(newname,cnum,newname_last_component,&bad_path2);
2983 * Split the old name into directory and last component
2984 * strings. Note that unix_convert may have stripped off a
2985 * leading ./ from both name and newname if the rename is
2986 * at the root of the share. We need to make sure either both
2987 * name and newname contain a / character or neither of them do
2988 * as this is checked in resolve_wildcards().
2991 p = strrchr(name,'/');
2992 if (!p) {
2993 strcpy(directory,".");
2994 strcpy(mask,name);
2995 } else {
2996 *p = 0;
2997 strcpy(directory,name);
2998 strcpy(mask,p+1);
2999 *p = '/'; /* Replace needed for exceptional test below. */
3002 if (is_mangled(mask))
3003 check_mangled_stack(mask);
3005 has_wild = strchr(mask,'*') || strchr(mask,'?');
3007 if (!has_wild) {
3008 BOOL is_short_name = is_8_3(name, True);
3010 /* Add a terminating '/' to the directory name. */
3011 strcat(directory,"/");
3012 strcat(directory,mask);
3014 /* Ensure newname contains a '/' also */
3015 if(strrchr(newname,'/') == 0) {
3016 pstring tmpstr;
3018 strcpy(tmpstr, "./");
3019 strcat(tmpstr, newname);
3020 strcpy(newname, tmpstr);
3023 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",
3024 case_sensitive, case_preserve, short_case_preserve, directory,
3025 newname, newname_last_component, is_short_name));
3028 * Check for special case with case preserving and not
3029 * case sensitive, if directory and newname are identical,
3030 * and the old last component differs from the original
3031 * last component only by case, then we should allow
3032 * the rename (user is trying to change the case of the
3033 * filename).
3035 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3036 ((short_case_preserve == True) && (is_short_name == True))) &&
3037 strcsequal(directory, newname)) {
3038 pstring newname_modified_last_component;
3041 * Get the last component of the modified name.
3042 * Note that we guarantee that newname contains a '/'
3043 * character above.
3045 p = strrchr(newname,'/');
3046 strcpy(newname_modified_last_component,p+1);
3048 if(strcsequal(newname_modified_last_component,
3049 newname_last_component) == False) {
3051 * Replace the modified last component with
3052 * the original.
3054 strcpy(p+1, newname_last_component);
3058 if (resolve_wildcards(directory,newname) &&
3059 can_rename(directory,cnum) &&
3060 !file_exist(newname,NULL) &&
3061 !sys_rename(directory,newname)) count++;
3063 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3064 directory,newname));
3066 if (!count) exists = file_exist(directory,NULL);
3067 if (!count && exists && file_exist(newname,NULL)) {
3068 exists = True;
3069 error = 183;
3071 } else {
3072 void *dirptr = NULL;
3073 char *dname;
3074 pstring destname;
3076 if (check_name(directory,cnum))
3077 dirptr = OpenDir(cnum, directory, True);
3079 if (dirptr)
3081 error = ERRbadfile;
3083 if (strequal(mask,"????????.???"))
3084 strcpy(mask,"*");
3086 while ((dname = ReadDirName(dirptr)))
3088 pstring fname;
3089 pstrcpy(fname,dname);
3091 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3093 error = ERRnoaccess;
3094 sprintf(fname,"%s/%s",directory,dname);
3095 if (!can_rename(fname,cnum)) continue;
3096 pstrcpy(destname,newname);
3098 if (!resolve_wildcards(fname,destname)) continue;
3100 if (file_exist(destname,NULL)) {
3101 error = 183;
3102 continue;
3104 if (!sys_rename(fname,destname)) count++;
3105 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3107 CloseDir(dirptr);
3111 if (count == 0) {
3112 if (exists)
3113 return(ERROR(ERRDOS,error));
3114 else
3116 if((errno == ENOENT) && (bad_path1 || bad_path2))
3118 unix_ERR_class = ERRDOS;
3119 unix_ERR_code = ERRbadpath;
3121 return(UNIXERROR(ERRDOS,error));
3125 outsize = set_message(outbuf,0,0,True);
3127 return(outsize);
3130 /*******************************************************************
3131 copy a file as part of a reply_copy
3132 ******************************************************************/
3133 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3134 int count,BOOL target_is_directory)
3136 int Access,action;
3137 struct stat st;
3138 int ret=0;
3139 int fnum1,fnum2;
3140 pstring dest;
3142 pstrcpy(dest,dest1);
3143 if (target_is_directory) {
3144 char *p = strrchr(src,'/');
3145 if (p)
3146 p++;
3147 else
3148 p = src;
3149 strcat(dest,"/");
3150 strcat(dest,p);
3153 if (!file_exist(src,&st)) return(False);
3155 fnum1 = find_free_file();
3156 if (fnum1<0) return(False);
3157 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3158 1,0,0,&Access,&action);
3160 if (!Files[fnum1].open) return(False);
3162 if (!target_is_directory && count)
3163 ofun = 1;
3165 fnum2 = find_free_file();
3166 if (fnum2<0) {
3167 close_file(fnum1);
3168 return(False);
3170 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3171 ofun,st.st_mode,0,&Access,&action);
3173 if (!Files[fnum2].open) {
3174 close_file(fnum1);
3175 return(False);
3178 if ((ofun&3) == 1) {
3179 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3182 if (st.st_size)
3183 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3185 close_file(fnum1);
3186 close_file(fnum2);
3188 return(ret == st.st_size);
3193 /****************************************************************************
3194 reply to a file copy.
3195 ****************************************************************************/
3196 int reply_copy(char *inbuf,char *outbuf)
3198 int outsize = 0;
3199 pstring name;
3200 int cnum;
3201 pstring directory;
3202 pstring mask,newname;
3203 char *p;
3204 int count=0;
3205 int error = ERRnoaccess;
3206 BOOL has_wild;
3207 BOOL exists=False;
3208 int tid2 = SVAL(inbuf,smb_vwv0);
3209 int ofun = SVAL(inbuf,smb_vwv1);
3210 int flags = SVAL(inbuf,smb_vwv2);
3211 BOOL target_is_directory=False;
3212 BOOL bad_path1 = False;
3213 BOOL bad_path2 = False;
3215 *directory = *mask = 0;
3217 cnum = SVAL(inbuf,smb_tid);
3219 pstrcpy(name,smb_buf(inbuf));
3220 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3222 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3224 if (tid2 != cnum) {
3225 /* can't currently handle inter share copies XXXX */
3226 DEBUG(3,("Rejecting inter-share copy\n"));
3227 return(ERROR(ERRSRV,ERRinvdevice));
3230 unix_convert(name,cnum,0,&bad_path1);
3231 unix_convert(newname,cnum,0,&bad_path2);
3233 target_is_directory = directory_exist(newname,NULL);
3235 if ((flags&1) && target_is_directory) {
3236 return(ERROR(ERRDOS,ERRbadfile));
3239 if ((flags&2) && !target_is_directory) {
3240 return(ERROR(ERRDOS,ERRbadpath));
3243 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3244 /* wants a tree copy! XXXX */
3245 DEBUG(3,("Rejecting tree copy\n"));
3246 return(ERROR(ERRSRV,ERRerror));
3249 p = strrchr(name,'/');
3250 if (!p) {
3251 strcpy(directory,"./");
3252 strcpy(mask,name);
3253 } else {
3254 *p = 0;
3255 strcpy(directory,name);
3256 strcpy(mask,p+1);
3259 if (is_mangled(mask))
3260 check_mangled_stack(mask);
3262 has_wild = strchr(mask,'*') || strchr(mask,'?');
3264 if (!has_wild) {
3265 strcat(directory,"/");
3266 strcat(directory,mask);
3267 if (resolve_wildcards(directory,newname) &&
3268 copy_file(directory,newname,cnum,ofun,
3269 count,target_is_directory)) count++;
3270 if (!count) exists = file_exist(directory,NULL);
3271 } else {
3272 void *dirptr = NULL;
3273 char *dname;
3274 pstring destname;
3276 if (check_name(directory,cnum))
3277 dirptr = OpenDir(cnum, directory, True);
3279 if (dirptr)
3281 error = ERRbadfile;
3283 if (strequal(mask,"????????.???"))
3284 strcpy(mask,"*");
3286 while ((dname = ReadDirName(dirptr)))
3288 pstring fname;
3289 pstrcpy(fname,dname);
3291 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3293 error = ERRnoaccess;
3294 sprintf(fname,"%s/%s",directory,dname);
3295 strcpy(destname,newname);
3296 if (resolve_wildcards(fname,destname) &&
3297 copy_file(directory,newname,cnum,ofun,
3298 count,target_is_directory)) count++;
3299 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3301 CloseDir(dirptr);
3305 if (count == 0) {
3306 if (exists)
3307 return(ERROR(ERRDOS,error));
3308 else
3310 if((errno == ENOENT) && (bad_path1 || bad_path2))
3312 unix_ERR_class = ERRDOS;
3313 unix_ERR_code = ERRbadpath;
3315 return(UNIXERROR(ERRDOS,error));
3319 outsize = set_message(outbuf,1,0,True);
3320 SSVAL(outbuf,smb_vwv0,count);
3322 return(outsize);
3327 /****************************************************************************
3328 reply to a setdir
3329 ****************************************************************************/
3330 int reply_setdir(char *inbuf,char *outbuf)
3332 int cnum,snum;
3333 int outsize = 0;
3334 BOOL ok = False;
3335 pstring newdir;
3337 cnum = SVAL(inbuf,smb_tid);
3339 snum = Connections[cnum].service;
3340 if (!CAN_SETDIR(snum))
3341 return(ERROR(ERRDOS,ERRnoaccess));
3343 pstrcpy(newdir,smb_buf(inbuf) + 1);
3344 strlower(newdir);
3346 if (strlen(newdir) == 0)
3347 ok = True;
3348 else
3350 ok = directory_exist(newdir,NULL);
3351 if (ok)
3352 string_set(&Connections[cnum].connectpath,newdir);
3355 if (!ok)
3356 return(ERROR(ERRDOS,ERRbadpath));
3358 outsize = set_message(outbuf,0,0,True);
3359 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3361 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3363 return(outsize);
3367 /****************************************************************************
3368 reply to a lockingX request
3369 ****************************************************************************/
3370 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3372 int fnum = GETFNUM(inbuf,smb_vwv2);
3373 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3374 #if 0
3375 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3376 #endif
3377 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3378 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3379 uint32 count, offset;
3381 int cnum;
3382 int i;
3383 char *data;
3384 uint32 ecode=0, dummy2;
3385 int eclass=0, dummy1;
3387 cnum = SVAL(inbuf,smb_tid);
3389 CHECK_FNUM(fnum,cnum);
3390 CHECK_ERROR(fnum);
3392 data = smb_buf(inbuf);
3394 /* Check if this is an oplock break on a file
3395 we have granted an oplock on.
3397 if((locktype == LOCKING_ANDX_OPLOCK_RELEASE) &&
3398 (num_ulocks == 0) && (num_locks == 0) &&
3399 (CVAL(inbuf,smb_vwv0) == 0xFF))
3401 share_lock_token token;
3402 files_struct *fsp = &Files[fnum];
3403 uint32 dev = fsp->fd_ptr->dev;
3404 uint32 inode = fsp->fd_ptr->inode;
3406 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3407 fnum));
3409 * Make sure we have granted an oplock on this file.
3411 if(!fsp->granted_oplock)
3413 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3414 no oplock granted on this file.\n", fnum));
3415 return ERROR(ERRDOS,ERRlock);
3418 /* Remove the oplock flag from the sharemode. */
3419 lock_share_entry(fsp->cnum, dev, inode, &token);
3420 if(remove_share_oplock( fnum, token)==False)
3422 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3423 dev = %x, inode = %x\n", fnum, dev, inode));
3424 unlock_share_entry(fsp->cnum, dev, inode, token);
3425 return -1;
3427 unlock_share_entry(fsp->cnum, dev, inode, token);
3429 /* Clear the granted flag and return. */
3431 fsp->granted_oplock = False;
3432 return -1;
3435 /* Data now points at the beginning of the list
3436 of smb_unlkrng structs */
3437 for(i = 0; i < (int)num_ulocks; i++) {
3438 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3439 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3440 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3441 return ERROR(eclass,ecode);
3444 /* Now do any requested locks */
3445 data += 10*num_ulocks;
3446 /* Data now points at the beginning of the list
3447 of smb_lkrng structs */
3448 for(i = 0; i < (int)num_locks; i++) {
3449 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3450 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3451 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3452 break;
3455 /* If any of the above locks failed, then we must unlock
3456 all of the previous locks (X/Open spec). */
3457 if(i != num_locks && num_locks != 0) {
3458 for(; i >= 0; i--) {
3459 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3460 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3461 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3463 return ERROR(eclass,ecode);
3466 set_message(outbuf,2,0,True);
3468 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3469 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3471 chain_fnum = fnum;
3473 return chain_reply(inbuf,outbuf,length,bufsize);
3477 /****************************************************************************
3478 reply to a SMBreadbmpx (read block multiplex) request
3479 ****************************************************************************/
3480 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3482 int cnum,fnum;
3483 int nread = -1;
3484 int total_read;
3485 char *data;
3486 uint32 startpos;
3487 int outsize, mincount, maxcount;
3488 int max_per_packet;
3489 int tcount;
3490 int pad;
3492 /* this function doesn't seem to work - disable by default */
3493 if (!lp_readbmpx())
3494 return(ERROR(ERRSRV,ERRuseSTD));
3496 outsize = set_message(outbuf,8,0,True);
3498 cnum = SVAL(inbuf,smb_tid);
3499 fnum = GETFNUM(inbuf,smb_vwv0);
3501 CHECK_FNUM(fnum,cnum);
3502 CHECK_READ(fnum);
3503 CHECK_ERROR(fnum);
3505 startpos = IVAL(inbuf,smb_vwv1);
3506 maxcount = SVAL(inbuf,smb_vwv3);
3507 mincount = SVAL(inbuf,smb_vwv4);
3509 data = smb_buf(outbuf);
3510 pad = ((long)data)%4;
3511 if (pad) pad = 4 - pad;
3512 data += pad;
3514 max_per_packet = bufsize-(outsize+pad);
3515 tcount = maxcount;
3516 total_read = 0;
3518 if (is_locked(fnum,cnum,maxcount,startpos))
3519 return(ERROR(ERRDOS,ERRlock));
3523 int N = MIN(max_per_packet,tcount-total_read);
3525 nread = read_file(fnum,data,startpos,N);
3527 if (nread <= 0) nread = 0;
3529 if (nread < N)
3530 tcount = total_read + nread;
3532 set_message(outbuf,8,nread,False);
3533 SIVAL(outbuf,smb_vwv0,startpos);
3534 SSVAL(outbuf,smb_vwv2,tcount);
3535 SSVAL(outbuf,smb_vwv6,nread);
3536 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3538 send_smb(Client,outbuf);
3540 total_read += nread;
3541 startpos += nread;
3543 while (total_read < tcount);
3545 return(-1);
3549 /****************************************************************************
3550 reply to a SMBwritebmpx (write block multiplex primary) request
3551 ****************************************************************************/
3552 int reply_writebmpx(char *inbuf,char *outbuf)
3554 int cnum,numtowrite,fnum;
3555 int nwritten = -1;
3556 int outsize = 0;
3557 uint32 startpos;
3558 int tcount, write_through, smb_doff;
3559 char *data;
3561 cnum = SVAL(inbuf,smb_tid);
3562 fnum = GETFNUM(inbuf,smb_vwv0);
3564 CHECK_FNUM(fnum,cnum);
3565 CHECK_WRITE(fnum);
3566 CHECK_ERROR(fnum);
3568 tcount = SVAL(inbuf,smb_vwv1);
3569 startpos = IVAL(inbuf,smb_vwv3);
3570 write_through = BITSETW(inbuf+smb_vwv7,0);
3571 numtowrite = SVAL(inbuf,smb_vwv10);
3572 smb_doff = SVAL(inbuf,smb_vwv11);
3574 data = smb_base(inbuf) + smb_doff;
3576 /* If this fails we need to send an SMBwriteC response,
3577 not an SMBwritebmpx - set this up now so we don't forget */
3578 CVAL(outbuf,smb_com) = SMBwritec;
3580 if (is_locked(fnum,cnum,tcount,startpos))
3581 return(ERROR(ERRDOS,ERRlock));
3583 seek_file(fnum,startpos);
3584 nwritten = write_file(fnum,data,numtowrite);
3586 if(lp_syncalways(SNUM(cnum)) || write_through)
3587 sync_file(fnum);
3589 if(nwritten < numtowrite)
3590 return(UNIXERROR(ERRHRD,ERRdiskfull));
3592 /* If the maximum to be written to this file
3593 is greater than what we just wrote then set
3594 up a secondary struct to be attached to this
3595 fd, we will use this to cache error messages etc. */
3596 if(tcount > nwritten)
3598 write_bmpx_struct *wbms;
3599 if(Files[fnum].wbmpx_ptr != NULL)
3600 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3601 else
3602 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3603 if(!wbms)
3605 DEBUG(0,("Out of memory in reply_readmpx\n"));
3606 return(ERROR(ERRSRV,ERRnoresource));
3608 wbms->wr_mode = write_through;
3609 wbms->wr_discard = False; /* No errors yet */
3610 wbms->wr_total_written = nwritten;
3611 wbms->wr_errclass = 0;
3612 wbms->wr_error = 0;
3613 Files[fnum].wbmpx_ptr = wbms;
3616 /* We are returning successfully, set the message type back to
3617 SMBwritebmpx */
3618 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3620 outsize = set_message(outbuf,1,0,True);
3622 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3624 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3625 timestring(),fnum,cnum,numtowrite,nwritten));
3627 if (write_through && tcount==nwritten) {
3628 /* we need to send both a primary and a secondary response */
3629 smb_setlen(outbuf,outsize - 4);
3630 send_smb(Client,outbuf);
3632 /* now the secondary */
3633 outsize = set_message(outbuf,1,0,True);
3634 CVAL(outbuf,smb_com) = SMBwritec;
3635 SSVAL(outbuf,smb_vwv0,nwritten);
3638 return(outsize);
3642 /****************************************************************************
3643 reply to a SMBwritebs (write block multiplex secondary) request
3644 ****************************************************************************/
3645 int reply_writebs(char *inbuf,char *outbuf)
3647 int cnum,numtowrite,fnum;
3648 int nwritten = -1;
3649 int outsize = 0;
3650 int32 startpos;
3651 int tcount, write_through, smb_doff;
3652 char *data;
3653 write_bmpx_struct *wbms;
3654 BOOL send_response = False;
3656 cnum = SVAL(inbuf,smb_tid);
3657 fnum = GETFNUM(inbuf,smb_vwv0);
3658 CHECK_FNUM(fnum,cnum);
3659 CHECK_WRITE(fnum);
3661 tcount = SVAL(inbuf,smb_vwv1);
3662 startpos = IVAL(inbuf,smb_vwv2);
3663 numtowrite = SVAL(inbuf,smb_vwv6);
3664 smb_doff = SVAL(inbuf,smb_vwv7);
3666 data = smb_base(inbuf) + smb_doff;
3668 /* We need to send an SMBwriteC response, not an SMBwritebs */
3669 CVAL(outbuf,smb_com) = SMBwritec;
3671 /* This fd should have an auxiliary struct attached,
3672 check that it does */
3673 wbms = Files[fnum].wbmpx_ptr;
3674 if(!wbms) return(-1);
3676 /* If write through is set we can return errors, else we must
3677 cache them */
3678 write_through = wbms->wr_mode;
3680 /* Check for an earlier error */
3681 if(wbms->wr_discard)
3682 return -1; /* Just discard the packet */
3684 seek_file(fnum,startpos);
3685 nwritten = write_file(fnum,data,numtowrite);
3687 if(lp_syncalways(SNUM(cnum)) || write_through)
3688 sync_file(fnum);
3690 if (nwritten < numtowrite)
3692 if(write_through) {
3693 /* We are returning an error - we can delete the aux struct */
3694 if (wbms) free((char *)wbms);
3695 Files[fnum].wbmpx_ptr = NULL;
3696 return(ERROR(ERRHRD,ERRdiskfull));
3698 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3701 /* Increment the total written, if this matches tcount
3702 we can discard the auxiliary struct (hurrah !) and return a writeC */
3703 wbms->wr_total_written += nwritten;
3704 if(wbms->wr_total_written >= tcount)
3706 if (write_through) {
3707 outsize = set_message(outbuf,1,0,True);
3708 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3709 send_response = True;
3712 free((char *)wbms);
3713 Files[fnum].wbmpx_ptr = NULL;
3716 if(send_response)
3717 return(outsize);
3719 return(-1);
3723 /****************************************************************************
3724 reply to a SMBsetattrE
3725 ****************************************************************************/
3726 int reply_setattrE(char *inbuf,char *outbuf)
3728 int cnum,fnum;
3729 struct utimbuf unix_times;
3730 int outsize = 0;
3732 outsize = set_message(outbuf,0,0,True);
3734 cnum = SVAL(inbuf,smb_tid);
3735 fnum = GETFNUM(inbuf,smb_vwv0);
3737 CHECK_FNUM(fnum,cnum);
3738 CHECK_ERROR(fnum);
3740 /* Convert the DOS times into unix times. Ignore create
3741 time as UNIX can't set this.
3743 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3744 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3747 * Patch from Ray Frush <frush@engr.colostate.edu>
3748 * Sometimes times are sent as zero - ignore them.
3751 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3753 /* Ignore request */
3754 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3755 not setting timestamps of 0\n",
3756 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3757 return(outsize);
3759 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3761 /* set modify time = to access time if modify time was 0 */
3762 unix_times.modtime = unix_times.actime;
3765 /* Set the date on this file */
3766 if(sys_utime(Files[fnum].name, &unix_times))
3767 return(ERROR(ERRDOS,ERRnoaccess));
3769 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3770 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3772 return(outsize);
3776 /****************************************************************************
3777 reply to a SMBgetattrE
3778 ****************************************************************************/
3779 int reply_getattrE(char *inbuf,char *outbuf)
3781 int cnum,fnum;
3782 struct stat sbuf;
3783 int outsize = 0;
3784 int mode;
3786 outsize = set_message(outbuf,11,0,True);
3788 cnum = SVAL(inbuf,smb_tid);
3789 fnum = GETFNUM(inbuf,smb_vwv0);
3791 CHECK_FNUM(fnum,cnum);
3792 CHECK_ERROR(fnum);
3794 /* Do an fstat on this file */
3795 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3796 return(UNIXERROR(ERRDOS,ERRnoaccess));
3798 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3800 /* Convert the times into dos times. Set create
3801 date to be last modify date as UNIX doesn't save
3802 this */
3803 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3804 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3805 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3806 if (mode & aDIR)
3808 SIVAL(outbuf,smb_vwv6,0);
3809 SIVAL(outbuf,smb_vwv8,0);
3811 else
3813 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3814 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3816 SSVAL(outbuf,smb_vwv10, mode);
3818 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3820 return(outsize);