rewrote the password server code using the new clientgen.c client
[Samba.git] / source / smbd / reply.c
blob3643b6eed0d015cf4a235f88cd0e569e33d2b445
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"
29 #include "nterr.h"
31 /* look in server.c for some explanation of these variables */
32 extern int Protocol;
33 extern int DEBUGLEVEL;
34 extern int max_send;
35 extern int max_recv;
36 extern int chain_fnum;
37 extern char magic_char;
38 extern connection_struct Connections[];
39 extern files_struct Files[];
40 extern BOOL case_sensitive;
41 extern BOOL case_preserve;
42 extern BOOL short_case_preserve;
43 extern pstring sesssetup_user;
44 extern fstring myworkgroup;
45 extern int Client;
46 extern int global_oplock_break;
48 /* this macro should always be used to extract an fnum (smb_fid) from
49 a packet to ensure chaining works correctly */
50 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
53 /****************************************************************************
54 report a possible attack via the password buffer overflow bug
55 ****************************************************************************/
56 static void overflow_attack(int len)
58 DEBUG(0,("ERROR: Invalid password length %d\n", len));
59 DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n"));
60 DEBUG(0,("Attack was from IP=%s\n", client_addr()));
61 exit_server("possible attack");
65 /****************************************************************************
66 reply to an special message
67 ****************************************************************************/
68 int reply_special(char *inbuf,char *outbuf)
70 int outsize = 4;
71 int msg_type = CVAL(inbuf,0);
72 int msg_flags = CVAL(inbuf,1);
73 pstring name1,name2;
74 extern fstring remote_machine;
75 extern fstring local_machine;
76 char *p;
78 *name1 = *name2 = 0;
80 smb_setlen(outbuf,0);
82 switch (msg_type) {
83 case 0x81: /* session request */
84 CVAL(outbuf,0) = 0x82;
85 CVAL(outbuf,3) = 0;
86 if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
87 DEBUG(0,("Invalid name length in session request\n"));
88 return(0);
90 name_extract(inbuf,4,name1);
91 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
92 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
93 name1,name2));
95 fstrcpy(remote_machine,name2);
96 trim_string(remote_machine," "," ");
97 p = strchr(remote_machine,' ');
98 strlower(remote_machine);
99 if (p) *p = 0;
101 fstrcpy(local_machine,name1);
102 trim_string(local_machine," "," ");
103 p = strchr(local_machine,' ');
104 strlower(local_machine);
105 if (p) *p = 0;
107 add_session_user(remote_machine);
109 reload_services(True);
110 reopen_logs();
112 break;
114 case 0x89: /* session keepalive request
115 (some old clients produce this?) */
116 CVAL(outbuf,0) = 0x85;
117 CVAL(outbuf,3) = 0;
118 break;
120 case 0x82: /* positive session response */
121 case 0x83: /* negative session response */
122 case 0x84: /* retarget session response */
123 DEBUG(0,("Unexpected session response\n"));
124 break;
126 case 0x85: /* session keepalive */
127 default:
128 return(0);
131 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",
132 timestring(),msg_type,msg_flags));
134 return(outsize);
138 /*******************************************************************
139 work out what error to give to a failed connection
140 ********************************************************************/
141 static int connection_error(char *inbuf,char *outbuf,int connection_num)
143 switch (connection_num)
145 case -8:
146 return(ERROR(ERRSRV,ERRnoresource));
147 case -7:
148 return(ERROR(ERRSRV,ERRbaduid));
149 case -6:
150 return(ERROR(ERRSRV,ERRinvdevice));
151 case -5:
152 return(ERROR(ERRSRV,ERRinvnetname));
153 case -4:
154 return(ERROR(ERRSRV,ERRaccess));
155 case -3:
156 return(ERROR(ERRDOS,ERRnoipc));
157 case -2:
158 return(ERROR(ERRSRV,ERRinvnetname));
160 return(ERROR(ERRSRV,ERRbadpw));
165 /****************************************************************************
166 parse a share descriptor string
167 ****************************************************************************/
168 static void parse_connect(char *p,char *service,char *user,
169 char *password,int *pwlen,char *dev)
171 char *p2;
173 DEBUG(4,("parsing connect string %s\n",p));
175 p2 = strrchr(p,'\\');
176 if (p2 == NULL)
177 fstrcpy(service,p);
178 else
179 fstrcpy(service,p2+1);
181 p += strlen(p) + 2;
183 fstrcpy(password,p);
184 *pwlen = strlen(password);
186 p += strlen(p) + 2;
188 fstrcpy(dev,p);
190 *user = 0;
191 p = strchr(service,'%');
192 if (p != NULL)
194 *p = 0;
195 fstrcpy(user,p+1);
202 /****************************************************************************
203 reply to a tcon
204 ****************************************************************************/
205 int reply_tcon(char *inbuf,char *outbuf)
207 pstring service;
208 pstring user;
209 pstring password;
210 pstring dev;
211 int connection_num;
212 int outsize = 0;
213 uint16 vuid = SVAL(inbuf,smb_uid);
214 int pwlen=0;
216 *service = *user = *password = *dev = 0;
218 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
220 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
222 if (connection_num < 0)
223 return(connection_error(inbuf,outbuf,connection_num));
225 outsize = set_message(outbuf,2,0,True);
226 SSVAL(outbuf,smb_vwv0,max_recv);
227 SSVAL(outbuf,smb_vwv1,connection_num);
228 SSVAL(outbuf,smb_tid,connection_num);
230 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
232 return(outsize);
236 /****************************************************************************
237 reply to a tcon and X
238 ****************************************************************************/
239 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
241 pstring service;
242 pstring user;
243 pstring password;
244 pstring devicename;
245 int connection_num;
246 uint16 vuid = SVAL(inbuf,smb_uid);
247 int passlen = SVAL(inbuf,smb_vwv3);
248 BOOL doencrypt = SMBENCRYPT();
250 *service = *user = *password = *devicename = 0;
252 /* we might have to close an old one */
253 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
254 close_cnum(SVAL(inbuf,smb_tid),vuid);
256 if (passlen > MAX_PASS_LEN) {
257 overflow_attack(passlen);
261 char *path;
262 char *p;
263 memcpy(password,smb_buf(inbuf),passlen);
264 password[passlen]=0;
265 path = smb_buf(inbuf) + passlen;
267 if (!doencrypt || passlen != 24) {
268 if (strequal(password," "))
269 *password = 0;
270 passlen = strlen(password);
273 fstrcpy(service,path+2);
274 p = strchr(service,'\\');
275 if (!p)
276 return(ERROR(ERRSRV,ERRinvnetname));
277 *p = 0;
278 fstrcpy(service,p+1);
279 p = strchr(service,'%');
280 if (p)
282 *p++ = 0;
283 fstrcpy(user,p);
285 StrnCpy(devicename,path + strlen(path) + 1,6);
286 DEBUG(4,("Got device type %s\n",devicename));
289 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
291 if (connection_num < 0)
292 return(connection_error(inbuf,outbuf,connection_num));
294 if (Protocol < PROTOCOL_NT1)
296 set_message(outbuf,2,strlen(devicename)+1,True);
297 strcpy(smb_buf(outbuf),devicename);
299 else
301 char *fsname = "SAMBA";
302 char *p;
304 set_message(outbuf,3,3,True);
306 p = smb_buf(outbuf);
307 strcpy(p,devicename); p = skip_string(p,1); /* device name */
308 strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
310 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
312 SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */
315 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
317 /* set the incoming and outgoing tid to the just created one */
318 SSVAL(inbuf,smb_tid,connection_num);
319 SSVAL(outbuf,smb_tid,connection_num);
321 return chain_reply(inbuf,outbuf,length,bufsize);
325 /****************************************************************************
326 reply to an unknown type
327 ****************************************************************************/
328 int reply_unknown(char *inbuf,char *outbuf)
330 int cnum;
331 int type;
332 cnum = SVAL(inbuf,smb_tid);
333 type = CVAL(inbuf,smb_com);
335 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
336 timestring(),
337 smb_fn_name(type),
338 cnum,type,type));
340 return(ERROR(ERRSRV,ERRunknownsmb));
344 /****************************************************************************
345 reply to an ioctl
346 ****************************************************************************/
347 int reply_ioctl(char *inbuf,char *outbuf)
349 DEBUG(3,("ignoring ioctl\n"));
350 #if 0
351 /* we just say it succeeds and hope its all OK.
352 some day it would be nice to interpret them individually */
353 return set_message(outbuf,1,0,True);
354 #else
355 return(ERROR(ERRSRV,ERRnosupport));
356 #endif
360 /****************************************************************************
361 reply to a session setup command
362 ****************************************************************************/
363 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
365 uint16 sess_vuid;
366 int gid;
367 int uid;
368 int smb_bufsize;
369 int smb_mpxmax;
370 int smb_vc_num;
371 uint32 smb_sesskey;
372 int smb_apasslen = 0;
373 pstring smb_apasswd;
374 int smb_ntpasslen = 0;
375 pstring smb_ntpasswd;
376 BOOL valid_nt_password = False;
377 pstring user;
378 BOOL guest=False;
379 BOOL computer_id=False;
380 static BOOL done_sesssetup = False;
381 BOOL doencrypt = SMBENCRYPT();
382 char *domain = "";
384 *smb_apasswd = 0;
385 *smb_ntpasswd = 0;
387 smb_bufsize = SVAL(inbuf,smb_vwv2);
388 smb_mpxmax = SVAL(inbuf,smb_vwv3);
389 smb_vc_num = SVAL(inbuf,smb_vwv4);
390 smb_sesskey = IVAL(inbuf,smb_vwv5);
392 if (Protocol < PROTOCOL_NT1) {
393 smb_apasslen = SVAL(inbuf,smb_vwv7);
394 if (smb_apasslen > MAX_PASS_LEN)
396 overflow_attack(smb_apasslen);
399 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
400 pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
402 if (lp_security() != SEC_SERVER && !doencrypt) {
403 smb_apasslen = strlen(smb_apasswd);
405 } else {
406 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
407 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
408 uint32 client_caps = IVAL(inbuf,smb_vwv11);
409 enum remote_arch_types ra_type = get_remote_arch();
411 char *p = smb_buf(inbuf);
413 /* client_caps is used as final determination if client is NT or Win95.
414 This is needed to return the correct error codes in some
415 circumstances.
418 if(ra_type == RA_WINNT || ra_type == RA_WIN95)
420 if(client_caps & (CAP_NT_SMBS | CAP_STATUS32))
421 set_remote_arch( RA_WINNT);
422 else
423 set_remote_arch( RA_WIN95);
426 if (passlen1 != 24 && passlen2 != 24)
427 doencrypt = False;
429 if (passlen1 > MAX_PASS_LEN) {
430 overflow_attack(passlen1);
433 passlen1 = MIN(passlen1, MAX_PASS_LEN);
434 passlen2 = MIN(passlen2, MAX_PASS_LEN);
436 if(doencrypt) {
437 /* Save the lanman2 password and the NT md4 password. */
438 smb_apasslen = passlen1;
439 memcpy(smb_apasswd,p,smb_apasslen);
440 smb_ntpasslen = passlen2;
441 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
442 } else {
443 /* both Win95 and WinNT stuff up the password lengths for
444 non-encrypting systems. Uggh.
446 if passlen1==24 its a win95 system, and its setting the
447 password length incorrectly. Luckily it still works with the
448 default code because Win95 will null terminate the password
449 anyway
451 if passlen1>0 and passlen2>0 then maybe its a NT box and its
452 setting passlen2 to some random value which really stuffs
453 things up. we need to fix that one. */
454 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
455 passlen2 != 1) {
456 passlen2 = 0;
458 /* we use the first password that they gave */
459 smb_apasslen = passlen1;
460 StrnCpy(smb_apasswd,p,smb_apasslen);
462 /* trim the password */
463 smb_apasslen = strlen(smb_apasswd);
465 /* wfwg sometimes uses a space instead of a null */
466 if (strequal(smb_apasswd," ")) {
467 smb_apasslen = 0;
468 *smb_apasswd = 0;
472 p += passlen1 + passlen2;
473 fstrcpy(user,p); p = skip_string(p,1);
474 domain = p;
476 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
477 domain,skip_string(p,1),skip_string(p,2)));
481 DEBUG(3,("sesssetupX:name=[%s]\n",user));
483 /* If name ends in $ then I think it's asking about whether a */
484 /* computer with that name (minus the $) has access. For now */
485 /* say yes to everything ending in $. */
486 if (user[strlen(user) - 1] == '$') {
487 #ifdef NTDOMAIN
488 struct smb_passwd *smb_pass; /* To check if machine account exists */
490 PAXX: Ack. We don't want to do this. The workstation trust account
491 with a $ on the end should exist in the local password database
492 or be mapped to something generic, but not modified. For NT
493 domain support we must reject this used in certain circumstances
494 with a code to indicate to the client that it is an invalid use
495 of a workstation trust account. NTWKS needs this error to join
496 a domain. This may be the source of future bugs if we cannot
497 be sure whether to reject this or not.
499 smb_pass = get_smbpwnam(user);
500 if(smb_pass)
502 /* PAXX: This is the NO LOGON workstation trust account stuff */
503 DEBUG(4,("Rejecting workstation trust account %s",user));
504 SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
505 CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
506 return(ERROR(NT_STATUS_ALLOTTED_SPACE_EXCEEDED, 0xc000)); /* 0x99 NT error, 0xc00 */
508 computer_id = True;
509 #else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */
510 user[strlen(user) - 1] = '\0';
511 #endif
515 /* If no username is sent use the guest account */
516 if (!*user)
518 strcpy(user,lp_guestaccount(-1));
519 /* If no user and no password then set guest flag. */
520 if( *smb_apasswd == 0)
521 guest = True;
524 strlower(user);
526 strcpy(sesssetup_user,user);
528 reload_services(True);
530 add_session_user(user);
532 /* Check if the given username was the guest user with no password.
533 We need to do this check after add_session_user() as that
534 call can potentially change the username (via map_user).
537 if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
538 guest = True;
540 if (!guest && !(lp_security() == SEC_SERVER &&
541 server_validate(user, domain,
542 smb_apasswd, smb_apasslen,
543 smb_ntpasswd, smb_ntpasslen)) &&
544 !check_hosts_equiv(user))
547 /* now check if it's a valid username/password */
548 /* If an NT password was supplied try and validate with that
549 first. This is superior as the passwords are mixed case
550 128 length unicode */
551 if(smb_ntpasslen)
553 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
554 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
555 else
556 valid_nt_password = True;
558 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
560 if (!computer_id && lp_security() >= SEC_USER) {
561 #if (GUEST_SESSSETUP == 0)
562 return(ERROR(ERRSRV,ERRbadpw));
563 #endif
564 #if (GUEST_SESSSETUP == 1)
565 if (Get_Pwnam(user,True))
566 return(ERROR(ERRSRV,ERRbadpw));
567 #endif
569 if (*smb_apasswd || !Get_Pwnam(user,True))
570 strcpy(user,lp_guestaccount(-1));
571 DEBUG(3,("Registered username %s for guest access\n",user));
572 guest = True;
576 if (!Get_Pwnam(user,True)) {
577 DEBUG(3,("No such user %s - using guest account\n",user));
578 strcpy(user,lp_guestaccount(-1));
579 guest = True;
582 if (!strequal(user,lp_guestaccount(-1)) &&
583 lp_servicenumber(user) < 0)
585 int homes = lp_servicenumber(HOMES_NAME);
586 char *home = get_home_dir(user);
587 if (homes >= 0 && home)
588 lp_add_home(user,homes,home);
592 /* it's ok - setup a reply */
593 if (Protocol < PROTOCOL_NT1) {
594 set_message(outbuf,3,0,True);
595 } else {
596 char *p;
597 set_message(outbuf,3,3,True);
598 p = smb_buf(outbuf);
599 strcpy(p,"Unix"); p = skip_string(p,1);
600 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
601 strcpy(p,myworkgroup); p = skip_string(p,1);
602 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
603 /* perhaps grab OS version here?? */
606 /* Set the correct uid in the outgoing and incoming packets
607 We will use this on future requests to determine which
608 user we should become.
611 struct passwd *pw = Get_Pwnam(user,False);
612 if (!pw) {
613 DEBUG(1,("Username %s is invalid on this system\n",user));
614 return(ERROR(ERRSRV,ERRbadpw));
616 gid = pw->pw_gid;
617 uid = pw->pw_uid;
620 if (guest && !computer_id)
621 SSVAL(outbuf,smb_vwv2,1);
623 /* register the name and uid as being validated, so further connections
624 to a uid can get through without a password, on the same VC */
625 sess_vuid = register_vuid(uid,gid,user,guest);
627 SSVAL(outbuf,smb_uid,sess_vuid);
628 SSVAL(inbuf,smb_uid,sess_vuid);
630 if (!done_sesssetup)
631 max_send = MIN(max_send,smb_bufsize);
633 DEBUG(6,("Client requested max send size of %d\n", max_send));
635 done_sesssetup = True;
637 return chain_reply(inbuf,outbuf,length,bufsize);
641 /****************************************************************************
642 reply to a chkpth
643 ****************************************************************************/
644 int reply_chkpth(char *inbuf,char *outbuf)
646 int outsize = 0;
647 int cnum,mode;
648 pstring name;
649 BOOL ok = False;
650 BOOL bad_path = False;
652 cnum = SVAL(inbuf,smb_tid);
654 pstrcpy(name,smb_buf(inbuf) + 1);
655 unix_convert(name,cnum,0,&bad_path);
657 mode = SVAL(inbuf,smb_vwv0);
659 if (check_name(name,cnum))
660 ok = directory_exist(name,NULL);
662 if (!ok)
664 /* We special case this - as when a Windows machine
665 is parsing a path is steps through the components
666 one at a time - if a component fails it expects
667 ERRbadpath, not ERRbadfile.
669 if(errno == ENOENT)
671 unix_ERR_class = ERRDOS;
672 unix_ERR_code = ERRbadpath;
675 #if 0
676 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
677 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
678 (get_remote_arch() == RA_WINNT))
680 unix_ERR_class = ERRDOS;
681 unix_ERR_code = ERRbaddirectory;
683 #endif
685 return(UNIXERROR(ERRDOS,ERRbadpath));
688 outsize = set_message(outbuf,0,0,True);
690 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
692 return(outsize);
696 /****************************************************************************
697 reply to a getatr
698 ****************************************************************************/
699 int reply_getatr(char *inbuf,char *outbuf)
701 pstring fname;
702 int cnum;
703 int outsize = 0;
704 struct stat sbuf;
705 BOOL ok = False;
706 int mode=0;
707 uint32 size=0;
708 time_t mtime=0;
709 BOOL bad_path = False;
711 cnum = SVAL(inbuf,smb_tid);
713 pstrcpy(fname,smb_buf(inbuf) + 1);
714 unix_convert(fname,cnum,0,&bad_path);
716 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
717 under WfWg - weird! */
718 if (! (*fname))
720 mode = aHIDDEN | aDIR;
721 if (!CAN_WRITE(cnum)) mode |= aRONLY;
722 size = 0;
723 mtime = 0;
724 ok = True;
726 else
727 if (check_name(fname,cnum))
729 if (sys_stat(fname,&sbuf) == 0)
731 mode = dos_mode(cnum,fname,&sbuf);
732 size = sbuf.st_size;
733 mtime = sbuf.st_mtime;
734 if (mode & aDIR)
735 size = 0;
736 ok = True;
738 else
739 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
742 if (!ok)
744 if((errno == ENOENT) && bad_path)
746 unix_ERR_class = ERRDOS;
747 unix_ERR_code = ERRbadpath;
750 return(UNIXERROR(ERRDOS,ERRbadfile));
753 outsize = set_message(outbuf,10,0,True);
755 SSVAL(outbuf,smb_vwv0,mode);
756 put_dos_date3(outbuf,smb_vwv1,mtime);
757 SIVAL(outbuf,smb_vwv3,size);
759 if (Protocol >= PROTOCOL_NT1) {
760 char *p = strrchr(fname,'/');
761 uint16 flg2 = SVAL(outbuf,smb_flg2);
762 if (!p) p = fname;
763 if (!is_8_3(fname, True))
764 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
767 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
769 return(outsize);
773 /****************************************************************************
774 reply to a setatr
775 ****************************************************************************/
776 int reply_setatr(char *inbuf,char *outbuf)
778 pstring fname;
779 int cnum;
780 int outsize = 0;
781 BOOL ok=False;
782 int mode;
783 time_t mtime;
784 BOOL bad_path = False;
786 cnum = SVAL(inbuf,smb_tid);
788 pstrcpy(fname,smb_buf(inbuf) + 1);
789 unix_convert(fname,cnum,0,&bad_path);
791 mode = SVAL(inbuf,smb_vwv0);
792 mtime = make_unix_date3(inbuf+smb_vwv1);
794 if (directory_exist(fname,NULL))
795 mode |= aDIR;
796 if (check_name(fname,cnum))
797 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
798 if (ok)
799 ok = set_filetime(cnum,fname,mtime);
801 if (!ok)
803 if((errno == ENOENT) && bad_path)
805 unix_ERR_class = ERRDOS;
806 unix_ERR_code = ERRbadpath;
809 return(UNIXERROR(ERRDOS,ERRnoaccess));
812 outsize = set_message(outbuf,0,0,True);
814 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
816 return(outsize);
820 /****************************************************************************
821 reply to a dskattr
822 ****************************************************************************/
823 int reply_dskattr(char *inbuf,char *outbuf)
825 int cnum;
826 int outsize = 0;
827 int dfree,dsize,bsize;
829 cnum = SVAL(inbuf,smb_tid);
831 sys_disk_free(".",&bsize,&dfree,&dsize);
833 outsize = set_message(outbuf,5,0,True);
835 SSVAL(outbuf,smb_vwv0,dsize);
836 SSVAL(outbuf,smb_vwv1,bsize/512);
837 SSVAL(outbuf,smb_vwv2,512);
838 SSVAL(outbuf,smb_vwv3,dfree);
840 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
842 return(outsize);
846 /****************************************************************************
847 reply to a search
848 Can be called from SMBsearch, SMBffirst or SMBfunique.
849 ****************************************************************************/
850 int reply_search(char *inbuf,char *outbuf)
852 pstring mask;
853 pstring directory;
854 pstring fname;
855 int size,mode;
856 time_t date;
857 int dirtype;
858 int cnum;
859 int outsize = 0;
860 int numentries = 0;
861 BOOL finished = False;
862 int maxentries;
863 int i;
864 char *p;
865 BOOL ok = False;
866 int status_len;
867 char *path;
868 char status[21];
869 int dptr_num= -1;
870 BOOL check_descend = False;
871 BOOL expect_close = False;
872 BOOL can_open = True;
873 BOOL bad_path = False;
875 *mask = *directory = *fname = 0;
877 /* If we were called as SMBffirst then we must expect close. */
878 if(CVAL(inbuf,smb_com) == SMBffirst)
879 expect_close = True;
881 cnum = SVAL(inbuf,smb_tid);
883 outsize = set_message(outbuf,1,3,True);
884 maxentries = SVAL(inbuf,smb_vwv0);
885 dirtype = SVAL(inbuf,smb_vwv1);
886 path = smb_buf(inbuf) + 1;
887 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
890 /* dirtype &= ~aDIR; */
892 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
895 if (status_len == 0)
897 pstring dir2;
899 pstrcpy(directory,smb_buf(inbuf)+1);
900 pstrcpy(dir2,smb_buf(inbuf)+1);
901 unix_convert(directory,cnum,0,&bad_path);
902 unix_format(dir2);
904 if (!check_name(directory,cnum))
905 can_open = False;
907 p = strrchr(dir2,'/');
908 if (p == NULL)
910 strcpy(mask,dir2);
911 *dir2 = 0;
913 else
915 *p = 0;
916 pstrcpy(mask,p+1);
919 p = strrchr(directory,'/');
920 if (!p)
921 *directory = 0;
922 else
923 *p = 0;
925 if (strlen(directory) == 0)
926 strcpy(directory,"./");
927 bzero(status,21);
928 CVAL(status,0) = dirtype;
930 else
932 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
933 memcpy(mask,status+1,11);
934 mask[11] = 0;
935 dirtype = CVAL(status,0) & 0x1F;
936 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
937 if (!Connections[cnum].dirptr)
938 goto SearchEmpty;
939 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
940 if (!case_sensitive)
941 strnorm(mask);
944 /* turn strings of spaces into a . */
946 trim_string(mask,NULL," ");
947 if ((p = strrchr(mask,' ')))
949 fstring ext;
950 fstrcpy(ext,p+1);
951 *p = 0;
952 trim_string(mask,NULL," ");
953 strcat(mask,".");
954 strcat(mask,ext);
959 for (p=mask; *p; p++)
961 if (*p != '?' && *p != '*' && !isdoschar(*p))
963 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
964 *p = '?';
969 if (!strchr(mask,'.') && strlen(mask)>8)
971 fstring tmp;
972 fstrcpy(tmp,&mask[8]);
973 mask[8] = '.';
974 mask[9] = 0;
975 strcat(mask,tmp);
978 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
980 if (can_open)
982 p = smb_buf(outbuf) + 3;
984 ok = True;
986 if (status_len == 0)
988 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
989 if (dptr_num < 0)
991 if(dptr_num == -2)
993 if((errno == ENOENT) && bad_path)
995 unix_ERR_class = ERRDOS;
996 unix_ERR_code = ERRbadpath;
998 return (UNIXERROR(ERRDOS,ERRnofids));
1000 return(ERROR(ERRDOS,ERRnofids));
1004 DEBUG(4,("dptr_num is %d\n",dptr_num));
1006 if (ok)
1008 if ((dirtype&0x1F) == aVOLID)
1010 memcpy(p,status,21);
1011 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
1012 dptr_fill(p+12,dptr_num);
1013 if (dptr_zero(p+12) && (status_len==0))
1014 numentries = 1;
1015 else
1016 numentries = 0;
1017 p += DIR_STRUCT_SIZE;
1019 else
1021 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
1022 if (in_list(Connections[cnum].dirpath,
1023 lp_dontdescend(SNUM(cnum)),True))
1024 check_descend = True;
1026 for (i=numentries;(i<maxentries) && !finished;i++)
1028 finished =
1029 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
1030 if (!finished)
1032 memcpy(p,status,21);
1033 make_dir_struct(p,mask,fname,size,mode,date);
1034 dptr_fill(p+12,dptr_num);
1035 numentries++;
1037 p += DIR_STRUCT_SIZE;
1044 SearchEmpty:
1046 if (numentries == 0 || !ok)
1048 CVAL(outbuf,smb_rcls) = ERRDOS;
1049 SSVAL(outbuf,smb_err,ERRnofiles);
1052 /* If we were called as SMBffirst with smb_search_id == NULL
1053 and no entries were found then return error and close dirptr
1054 (X/Open spec) */
1056 if(ok && expect_close && numentries == 0 && status_len == 0)
1058 CVAL(outbuf,smb_rcls) = ERRDOS;
1059 SSVAL(outbuf,smb_err,ERRnofiles);
1060 /* Also close the dptr - we know it's gone */
1061 dptr_close(dptr_num);
1064 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1065 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1066 dptr_close(dptr_num);
1068 SSVAL(outbuf,smb_vwv0,numentries);
1069 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1070 CVAL(smb_buf(outbuf),0) = 5;
1071 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1073 if (Protocol >= PROTOCOL_NT1) {
1074 uint16 flg2 = SVAL(outbuf,smb_flg2);
1075 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1078 outsize += DIR_STRUCT_SIZE*numentries;
1079 smb_setlen(outbuf,outsize - 4);
1081 if ((! *directory) && dptr_path(dptr_num))
1082 sprintf(directory,"(%s)",dptr_path(dptr_num));
1084 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
1085 timestring(),
1086 smb_fn_name(CVAL(inbuf,smb_com)),
1087 mask,directory,cnum,dirtype,numentries,maxentries));
1089 return(outsize);
1093 /****************************************************************************
1094 reply to a fclose (stop directory search)
1095 ****************************************************************************/
1096 int reply_fclose(char *inbuf,char *outbuf)
1098 int cnum;
1099 int outsize = 0;
1100 int status_len;
1101 char *path;
1102 char status[21];
1103 int dptr_num= -1;
1105 cnum = SVAL(inbuf,smb_tid);
1107 outsize = set_message(outbuf,1,0,True);
1108 path = smb_buf(inbuf) + 1;
1109 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
1112 if (status_len == 0)
1113 return(ERROR(ERRSRV,ERRsrverror));
1115 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
1117 if(dptr_fetch(status+12,&dptr_num)) {
1118 /* Close the dptr - we know it's gone */
1119 dptr_close(dptr_num);
1122 SSVAL(outbuf,smb_vwv0,0);
1124 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1126 return(outsize);
1130 /****************************************************************************
1131 reply to an open
1132 ****************************************************************************/
1133 int reply_open(char *inbuf,char *outbuf)
1135 pstring fname;
1136 int cnum;
1137 int fnum = -1;
1138 int outsize = 0;
1139 int fmode=0;
1140 int share_mode;
1141 int size = 0;
1142 time_t mtime=0;
1143 int unixmode;
1144 int rmode=0;
1145 struct stat sbuf;
1146 BOOL bad_path = False;
1147 files_struct *fsp;
1148 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1150 cnum = SVAL(inbuf,smb_tid);
1152 share_mode = SVAL(inbuf,smb_vwv0);
1154 pstrcpy(fname,smb_buf(inbuf)+1);
1155 unix_convert(fname,cnum,0,&bad_path);
1157 fnum = find_free_file();
1158 if (fnum < 0)
1159 return(ERROR(ERRSRV,ERRnofids));
1161 if (!check_name(fname,cnum))
1163 if((errno == ENOENT) && bad_path)
1165 unix_ERR_class = ERRDOS;
1166 unix_ERR_code = ERRbadpath;
1168 return(UNIXERROR(ERRDOS,ERRnoaccess));
1171 unixmode = unix_mode(cnum,aARCH);
1173 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
1174 oplock_request,&rmode,NULL);
1176 fsp = &Files[fnum];
1178 if (!fsp->open)
1180 if((errno == ENOENT) && bad_path)
1182 unix_ERR_class = ERRDOS;
1183 unix_ERR_code = ERRbadpath;
1185 return(UNIXERROR(ERRDOS,ERRnoaccess));
1188 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1189 close_file(fnum,False);
1190 return(ERROR(ERRDOS,ERRnoaccess));
1193 size = sbuf.st_size;
1194 fmode = dos_mode(cnum,fname,&sbuf);
1195 mtime = sbuf.st_mtime;
1197 if (fmode & aDIR) {
1198 DEBUG(3,("attempt to open a directory %s\n",fname));
1199 close_file(fnum,False);
1200 return(ERROR(ERRDOS,ERRnoaccess));
1203 outsize = set_message(outbuf,7,0,True);
1204 SSVAL(outbuf,smb_vwv0,fnum);
1205 SSVAL(outbuf,smb_vwv1,fmode);
1206 put_dos_date3(outbuf,smb_vwv2,mtime);
1207 SIVAL(outbuf,smb_vwv4,size);
1208 SSVAL(outbuf,smb_vwv6,rmode);
1210 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1211 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1214 if(fsp->granted_oplock)
1215 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1216 return(outsize);
1220 /****************************************************************************
1221 reply to an open and X
1222 ****************************************************************************/
1223 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1225 pstring fname;
1226 int cnum = SVAL(inbuf,smb_tid);
1227 int fnum = -1;
1228 int smb_mode = SVAL(inbuf,smb_vwv3);
1229 int smb_attr = SVAL(inbuf,smb_vwv5);
1230 BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1231 #if 0
1232 int open_flags = SVAL(inbuf,smb_vwv2);
1233 int smb_sattr = SVAL(inbuf,smb_vwv4);
1234 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1235 #endif
1236 int smb_ofun = SVAL(inbuf,smb_vwv8);
1237 int unixmode;
1238 int size=0,fmode=0,mtime=0,rmode=0;
1239 struct stat sbuf;
1240 int smb_action = 0;
1241 BOOL bad_path = False;
1242 files_struct *fsp;
1244 /* If it's an IPC, pass off the pipe handler. */
1245 if (IS_IPC(cnum))
1246 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1248 /* XXXX we need to handle passed times, sattr and flags */
1250 pstrcpy(fname,smb_buf(inbuf));
1251 unix_convert(fname,cnum,0,&bad_path);
1253 fnum = find_free_file();
1254 if (fnum < 0)
1255 return(ERROR(ERRSRV,ERRnofids));
1257 if (!check_name(fname,cnum))
1259 if((errno == ENOENT) && bad_path)
1261 unix_ERR_class = ERRDOS;
1262 unix_ERR_code = ERRbadpath;
1264 return(UNIXERROR(ERRDOS,ERRnoaccess));
1267 unixmode = unix_mode(cnum,smb_attr | aARCH);
1269 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1270 oplock_request, &rmode,&smb_action);
1272 fsp = &Files[fnum];
1274 if (!fsp->open)
1276 if((errno == ENOENT) && bad_path)
1278 unix_ERR_class = ERRDOS;
1279 unix_ERR_code = ERRbadpath;
1281 return(UNIXERROR(ERRDOS,ERRnoaccess));
1284 if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1285 close_file(fnum,False);
1286 return(ERROR(ERRDOS,ERRnoaccess));
1289 size = sbuf.st_size;
1290 fmode = dos_mode(cnum,fname,&sbuf);
1291 mtime = sbuf.st_mtime;
1292 if (fmode & aDIR) {
1293 close_file(fnum,False);
1294 return(ERROR(ERRDOS,ERRnoaccess));
1297 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1298 smb_action |= EXTENDED_OPLOCK_GRANTED;
1299 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1302 if(fsp->granted_oplock) {
1303 smb_action |= EXTENDED_OPLOCK_GRANTED;
1304 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1307 set_message(outbuf,15,0,True);
1308 SSVAL(outbuf,smb_vwv2,fnum);
1309 SSVAL(outbuf,smb_vwv3,fmode);
1310 put_dos_date3(outbuf,smb_vwv4,mtime);
1311 SIVAL(outbuf,smb_vwv6,size);
1312 SSVAL(outbuf,smb_vwv8,rmode);
1313 SSVAL(outbuf,smb_vwv11,smb_action);
1315 chain_fnum = fnum;
1317 return chain_reply(inbuf,outbuf,length,bufsize);
1321 /****************************************************************************
1322 reply to a SMBulogoffX
1323 ****************************************************************************/
1324 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1326 uint16 vuid = SVAL(inbuf,smb_uid);
1327 user_struct *vuser = get_valid_user_struct(vuid);
1329 if(vuser == 0) {
1330 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1333 /* in user level security we are supposed to close any files
1334 open by this user */
1335 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1336 int i;
1337 for (i=0;i<MAX_OPEN_FILES;i++)
1338 if (Files[i].uid == vuser->uid && Files[i].open) {
1339 close_file(i,False);
1343 invalidate_vuid(vuid);
1345 set_message(outbuf,2,0,True);
1347 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1349 return chain_reply(inbuf,outbuf,length,bufsize);
1353 /****************************************************************************
1354 reply to a mknew or a create
1355 ****************************************************************************/
1356 int reply_mknew(char *inbuf,char *outbuf)
1358 pstring fname;
1359 int cnum,com;
1360 int fnum = -1;
1361 int outsize = 0;
1362 int createmode;
1363 mode_t unixmode;
1364 int ofun = 0;
1365 BOOL bad_path = False;
1366 files_struct *fsp;
1367 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1369 com = SVAL(inbuf,smb_com);
1370 cnum = SVAL(inbuf,smb_tid);
1372 createmode = SVAL(inbuf,smb_vwv0);
1373 pstrcpy(fname,smb_buf(inbuf)+1);
1374 unix_convert(fname,cnum,0,&bad_path);
1376 if (createmode & aVOLID)
1378 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1381 unixmode = unix_mode(cnum,createmode);
1383 fnum = find_free_file();
1384 if (fnum < 0)
1385 return(ERROR(ERRSRV,ERRnofids));
1387 if (!check_name(fname,cnum))
1389 if((errno == ENOENT) && bad_path)
1391 unix_ERR_class = ERRDOS;
1392 unix_ERR_code = ERRbadpath;
1394 return(UNIXERROR(ERRDOS,ERRnoaccess));
1397 if(com == SMBmknew)
1399 /* We should fail if file exists. */
1400 ofun = 0x10;
1402 else
1404 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1405 ofun = 0x12;
1408 /* Open file in dos compatibility share mode. */
1409 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
1410 oplock_request, NULL, NULL);
1412 fsp = &Files[fnum];
1414 if (!fsp->open)
1416 if((errno == ENOENT) && bad_path)
1418 unix_ERR_class = ERRDOS;
1419 unix_ERR_code = ERRbadpath;
1421 return(UNIXERROR(ERRDOS,ERRnoaccess));
1424 outsize = set_message(outbuf,1,0,True);
1425 SSVAL(outbuf,smb_vwv0,fnum);
1427 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1428 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1431 if(fsp->granted_oplock)
1432 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1434 DEBUG(2,("new file %s\n",fname));
1435 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));
1437 return(outsize);
1441 /****************************************************************************
1442 reply to a create temporary file
1443 ****************************************************************************/
1444 int reply_ctemp(char *inbuf,char *outbuf)
1446 pstring fname;
1447 pstring fname2;
1448 int cnum;
1449 int fnum = -1;
1450 int outsize = 0;
1451 int createmode;
1452 mode_t unixmode;
1453 BOOL bad_path = False;
1454 files_struct *fsp;
1455 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1457 cnum = SVAL(inbuf,smb_tid);
1458 createmode = SVAL(inbuf,smb_vwv0);
1459 pstrcpy(fname,smb_buf(inbuf)+1);
1460 strcat(fname,"/TMXXXXXX");
1461 unix_convert(fname,cnum,0,&bad_path);
1463 unixmode = unix_mode(cnum,createmode);
1465 fnum = find_free_file();
1466 if (fnum < 0)
1467 return(ERROR(ERRSRV,ERRnofids));
1469 if (!check_name(fname,cnum))
1471 if((errno == ENOENT) && bad_path)
1473 unix_ERR_class = ERRDOS;
1474 unix_ERR_code = ERRbadpath;
1476 return(UNIXERROR(ERRDOS,ERRnoaccess));
1479 strcpy(fname2,(char *)mktemp(fname));
1481 /* Open file in dos compatibility share mode. */
1482 /* We should fail if file exists. */
1483 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
1484 oplock_request, NULL, NULL);
1486 fsp = &Files[fnum];
1488 if (!fsp->open)
1490 if((errno == ENOENT) && bad_path)
1492 unix_ERR_class = ERRDOS;
1493 unix_ERR_code = ERRbadpath;
1495 return(UNIXERROR(ERRDOS,ERRnoaccess));
1498 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1499 SSVAL(outbuf,smb_vwv0,fnum);
1500 CVAL(smb_buf(outbuf),0) = 4;
1501 strcpy(smb_buf(outbuf) + 1,fname2);
1503 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1504 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1507 if(fsp->granted_oplock)
1508 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1510 DEBUG(2,("created temp file %s\n",fname2));
1511 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));
1513 return(outsize);
1517 /*******************************************************************
1518 check if a user is allowed to delete a file
1519 ********************************************************************/
1520 static BOOL can_delete(char *fname,int cnum,int dirtype)
1522 struct stat sbuf;
1523 int fmode;
1525 if (!CAN_WRITE(cnum)) return(False);
1527 if (sys_lstat(fname,&sbuf) != 0) return(False);
1528 fmode = dos_mode(cnum,fname,&sbuf);
1529 if (fmode & aDIR) return(False);
1530 if (!lp_delete_readonly(SNUM(cnum))) {
1531 if (fmode & aRONLY) return(False);
1533 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1534 return(False);
1535 if (!check_file_sharing(cnum,fname)) return(False);
1536 return(True);
1539 /****************************************************************************
1540 reply to a unlink
1541 ****************************************************************************/
1542 int reply_unlink(char *inbuf,char *outbuf)
1544 int outsize = 0;
1545 pstring name;
1546 int cnum;
1547 int dirtype;
1548 pstring directory;
1549 pstring mask;
1550 char *p;
1551 int count=0;
1552 int error = ERRnoaccess;
1553 BOOL has_wild;
1554 BOOL exists=False;
1555 BOOL bad_path = False;
1557 *directory = *mask = 0;
1559 cnum = SVAL(inbuf,smb_tid);
1560 dirtype = SVAL(inbuf,smb_vwv0);
1562 pstrcpy(name,smb_buf(inbuf) + 1);
1564 DEBUG(3,("reply_unlink : %s\n",name));
1566 unix_convert(name,cnum,0,&bad_path);
1568 p = strrchr(name,'/');
1569 if (!p) {
1570 strcpy(directory,"./");
1571 strcpy(mask,name);
1572 } else {
1573 *p = 0;
1574 strcpy(directory,name);
1575 strcpy(mask,p+1);
1578 if (is_mangled(mask))
1579 check_mangled_stack(mask);
1581 has_wild = strchr(mask,'*') || strchr(mask,'?');
1583 if (!has_wild) {
1584 strcat(directory,"/");
1585 strcat(directory,mask);
1586 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1587 if (!count) exists = file_exist(directory,NULL);
1588 } else {
1589 void *dirptr = NULL;
1590 char *dname;
1592 if (check_name(directory,cnum))
1593 dirptr = OpenDir(cnum, directory, True);
1595 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1596 the pattern matches against the long name, otherwise the short name
1597 We don't implement this yet XXXX
1600 if (dirptr)
1602 error = ERRbadfile;
1604 if (strequal(mask,"????????.???"))
1605 strcpy(mask,"*");
1607 while ((dname = ReadDirName(dirptr)))
1609 pstring fname;
1610 pstrcpy(fname,dname);
1612 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1614 error = ERRnoaccess;
1615 sprintf(fname,"%s/%s",directory,dname);
1616 if (!can_delete(fname,cnum,dirtype)) continue;
1617 if (!sys_unlink(fname)) count++;
1618 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1620 CloseDir(dirptr);
1624 if (count == 0) {
1625 if (exists)
1626 return(ERROR(ERRDOS,error));
1627 else
1629 if((errno == ENOENT) && bad_path)
1631 unix_ERR_class = ERRDOS;
1632 unix_ERR_code = ERRbadpath;
1634 return(UNIXERROR(ERRDOS,error));
1638 outsize = set_message(outbuf,0,0,True);
1640 return(outsize);
1644 /****************************************************************************
1645 reply to a readbraw (core+ protocol)
1646 ****************************************************************************/
1647 int reply_readbraw(char *inbuf, char *outbuf)
1649 int cnum,maxcount,mincount,fnum;
1650 int nread = 0;
1651 uint32 startpos;
1652 char *header = outbuf;
1653 int ret=0;
1654 int fd;
1655 char *fname;
1658 * Special check if an oplock break has been issued
1659 * and the readraw request croses on the wire, we must
1660 * return a zero length response here.
1663 if(global_oplock_break)
1665 _smb_setlen(header,0);
1666 transfer_file(0,Client,0,header,4,0);
1667 DEBUG(5,("readbraw - oplock break finished\n"));
1668 return -1;
1671 cnum = SVAL(inbuf,smb_tid);
1672 fnum = GETFNUM(inbuf,smb_vwv0);
1674 startpos = IVAL(inbuf,smb_vwv1);
1675 maxcount = SVAL(inbuf,smb_vwv3);
1676 mincount = SVAL(inbuf,smb_vwv4);
1678 /* ensure we don't overrun the packet size */
1679 maxcount = MIN(65535,maxcount);
1680 maxcount = MAX(mincount,maxcount);
1682 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1684 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1685 _smb_setlen(header,0);
1686 transfer_file(0,Client,0,header,4,0);
1687 return(-1);
1689 else
1691 fd = Files[fnum].fd_ptr->fd;
1692 fname = Files[fnum].name;
1696 if (!is_locked(fnum,cnum,maxcount,startpos))
1698 int size = Files[fnum].size;
1699 int sizeneeded = startpos + maxcount;
1701 if (size < sizeneeded) {
1702 struct stat st;
1703 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1704 size = st.st_size;
1705 if (!Files[fnum].can_write)
1706 Files[fnum].size = size;
1709 nread = MIN(maxcount,(int)(size - startpos));
1712 if (nread < mincount)
1713 nread = 0;
1715 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1716 timestring(),
1717 fnum,cnum,startpos,
1718 maxcount,mincount,nread));
1720 #if UNSAFE_READRAW
1722 int predict=0;
1723 _smb_setlen(header,nread);
1725 if (!Files[fnum].can_write)
1726 predict = read_predict(fd,startpos,header+4,NULL,nread);
1728 if ((nread-predict) > 0)
1729 seek_file(fnum,startpos + predict);
1731 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1732 startpos+predict);
1735 if (ret != nread+4)
1736 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1737 fname,startpos,nread,ret));
1739 #else
1740 ret = read_file(fnum,header+4,startpos,nread);
1741 if (ret < mincount) ret = 0;
1743 _smb_setlen(header,ret);
1744 transfer_file(0,Client,0,header,4+ret,0);
1745 #endif
1747 DEBUG(5,("readbraw finished\n"));
1748 return -1;
1752 /****************************************************************************
1753 reply to a lockread (core+ protocol)
1754 ****************************************************************************/
1755 int reply_lockread(char *inbuf,char *outbuf)
1757 int cnum,fnum;
1758 int nread = -1;
1759 char *data;
1760 int outsize = 0;
1761 uint32 startpos, numtoread;
1762 int eclass;
1763 uint32 ecode;
1765 cnum = SVAL(inbuf,smb_tid);
1766 fnum = GETFNUM(inbuf,smb_vwv0);
1768 CHECK_FNUM(fnum,cnum);
1769 CHECK_READ(fnum);
1770 CHECK_ERROR(fnum);
1772 numtoread = SVAL(inbuf,smb_vwv1);
1773 startpos = IVAL(inbuf,smb_vwv2);
1775 outsize = set_message(outbuf,5,3,True);
1776 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1777 data = smb_buf(outbuf) + 3;
1779 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1780 return (ERROR(eclass,ecode));
1782 nread = read_file(fnum,data,startpos,numtoread);
1784 if (nread < 0)
1785 return(UNIXERROR(ERRDOS,ERRnoaccess));
1787 outsize += nread;
1788 SSVAL(outbuf,smb_vwv0,nread);
1789 SSVAL(outbuf,smb_vwv5,nread+3);
1790 SSVAL(smb_buf(outbuf),1,nread);
1792 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1794 return(outsize);
1798 /****************************************************************************
1799 reply to a read
1800 ****************************************************************************/
1801 int reply_read(char *inbuf,char *outbuf)
1803 int cnum,numtoread,fnum;
1804 int nread = 0;
1805 char *data;
1806 uint32 startpos;
1807 int outsize = 0;
1809 cnum = SVAL(inbuf,smb_tid);
1810 fnum = GETFNUM(inbuf,smb_vwv0);
1812 CHECK_FNUM(fnum,cnum);
1813 CHECK_READ(fnum);
1814 CHECK_ERROR(fnum);
1816 numtoread = SVAL(inbuf,smb_vwv1);
1817 startpos = IVAL(inbuf,smb_vwv2);
1819 outsize = set_message(outbuf,5,3,True);
1820 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1821 data = smb_buf(outbuf) + 3;
1823 if (is_locked(fnum,cnum,numtoread,startpos))
1824 return(ERROR(ERRDOS,ERRlock));
1826 if (numtoread > 0)
1827 nread = read_file(fnum,data,startpos,numtoread);
1829 if (nread < 0)
1830 return(UNIXERROR(ERRDOS,ERRnoaccess));
1832 outsize += nread;
1833 SSVAL(outbuf,smb_vwv0,nread);
1834 SSVAL(outbuf,smb_vwv5,nread+3);
1835 CVAL(smb_buf(outbuf),0) = 1;
1836 SSVAL(smb_buf(outbuf),1,nread);
1838 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1840 return(outsize);
1844 /****************************************************************************
1845 reply to a read and X
1846 ****************************************************************************/
1847 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1849 int fnum = GETFNUM(inbuf,smb_vwv2);
1850 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1851 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1852 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1853 int cnum;
1854 int nread = -1;
1855 char *data;
1856 BOOL ok = False;
1858 cnum = SVAL(inbuf,smb_tid);
1860 CHECK_FNUM(fnum,cnum);
1861 CHECK_READ(fnum);
1862 CHECK_ERROR(fnum);
1864 set_message(outbuf,12,0,True);
1865 data = smb_buf(outbuf);
1867 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1868 return(ERROR(ERRDOS,ERRlock));
1869 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1870 ok = True;
1872 if (nread < 0)
1873 return(UNIXERROR(ERRDOS,ERRnoaccess));
1875 SSVAL(outbuf,smb_vwv5,nread);
1876 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1877 SSVAL(smb_buf(outbuf),-2,nread);
1879 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1880 timestring(),fnum,cnum,
1881 smb_mincnt,smb_maxcnt,nread));
1883 chain_fnum = fnum;
1885 return chain_reply(inbuf,outbuf,length,bufsize);
1889 /****************************************************************************
1890 reply to a writebraw (core+ or LANMAN1.0 protocol)
1891 ****************************************************************************/
1892 int reply_writebraw(char *inbuf,char *outbuf)
1894 int nwritten=0;
1895 int total_written=0;
1896 int numtowrite=0;
1897 int cnum,fnum;
1898 int outsize = 0;
1899 long startpos;
1900 char *data=NULL;
1901 BOOL write_through;
1902 int tcount;
1904 cnum = SVAL(inbuf,smb_tid);
1905 fnum = GETFNUM(inbuf,smb_vwv0);
1907 CHECK_FNUM(fnum,cnum);
1908 CHECK_WRITE(fnum);
1909 CHECK_ERROR(fnum);
1911 tcount = IVAL(inbuf,smb_vwv1);
1912 startpos = IVAL(inbuf,smb_vwv3);
1913 write_through = BITSETW(inbuf+smb_vwv7,0);
1915 /* We have to deal with slightly different formats depending
1916 on whether we are using the core+ or lanman1.0 protocol */
1917 if(Protocol <= PROTOCOL_COREPLUS) {
1918 numtowrite = SVAL(smb_buf(inbuf),-2);
1919 data = smb_buf(inbuf);
1920 } else {
1921 numtowrite = SVAL(inbuf,smb_vwv10);
1922 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1925 /* force the error type */
1926 CVAL(inbuf,smb_com) = SMBwritec;
1927 CVAL(outbuf,smb_com) = SMBwritec;
1929 if (is_locked(fnum,cnum,tcount,startpos))
1930 return(ERROR(ERRDOS,ERRlock));
1932 if (seek_file(fnum,startpos) != startpos)
1933 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1935 if (numtowrite>0)
1936 nwritten = write_file(fnum,data,numtowrite);
1938 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1939 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1941 if (nwritten < numtowrite)
1942 return(UNIXERROR(ERRHRD,ERRdiskfull));
1944 total_written = nwritten;
1946 /* Return a message to the redirector to tell it
1947 to send more bytes */
1948 CVAL(outbuf,smb_com) = SMBwritebraw;
1949 SSVALS(outbuf,smb_vwv0,-1);
1950 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1951 send_smb(Client,outbuf);
1953 /* Now read the raw data into the buffer and write it */
1954 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1955 exit_server("secondary writebraw failed");
1958 /* Even though this is not an smb message, smb_len
1959 returns the generic length of an smb message */
1960 numtowrite = smb_len(inbuf);
1962 if (tcount > nwritten+numtowrite) {
1963 DEBUG(3,("Client overestimated the write %d %d %d\n",
1964 tcount,nwritten,numtowrite));
1967 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1968 startpos+nwritten);
1969 total_written += nwritten;
1971 /* Set up outbuf to return the correct return */
1972 outsize = set_message(outbuf,1,0,True);
1973 CVAL(outbuf,smb_com) = SMBwritec;
1974 SSVAL(outbuf,smb_vwv0,total_written);
1976 if (nwritten < numtowrite) {
1977 CVAL(outbuf,smb_rcls) = ERRHRD;
1978 SSVAL(outbuf,smb_err,ERRdiskfull);
1981 if (lp_syncalways(SNUM(cnum)) || write_through)
1982 sync_file(fnum);
1984 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1985 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1987 /* we won't return a status if write through is not selected - this
1988 follows what WfWg does */
1989 if (!write_through && total_written==tcount)
1990 return(-1);
1992 return(outsize);
1996 /****************************************************************************
1997 reply to a writeunlock (core+)
1998 ****************************************************************************/
1999 int reply_writeunlock(char *inbuf,char *outbuf)
2001 int cnum,fnum;
2002 int nwritten = -1;
2003 int outsize = 0;
2004 char *data;
2005 uint32 numtowrite,startpos;
2006 int eclass;
2007 uint32 ecode;
2009 cnum = SVAL(inbuf,smb_tid);
2010 fnum = GETFNUM(inbuf,smb_vwv0);
2012 CHECK_FNUM(fnum,cnum);
2013 CHECK_WRITE(fnum);
2014 CHECK_ERROR(fnum);
2016 numtowrite = SVAL(inbuf,smb_vwv1);
2017 startpos = IVAL(inbuf,smb_vwv2);
2018 data = smb_buf(inbuf) + 3;
2020 if (is_locked(fnum,cnum,numtowrite,startpos))
2021 return(ERROR(ERRDOS,ERRlock));
2023 seek_file(fnum,startpos);
2025 /* The special X/Open SMB protocol handling of
2026 zero length writes is *NOT* done for
2027 this call */
2028 if(numtowrite == 0)
2029 nwritten = 0;
2030 else
2031 nwritten = write_file(fnum,data,numtowrite);
2033 if (lp_syncalways(SNUM(cnum)))
2034 sync_file(fnum);
2036 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2037 return(UNIXERROR(ERRDOS,ERRnoaccess));
2039 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
2040 return(ERROR(eclass,ecode));
2042 outsize = set_message(outbuf,1,0,True);
2044 SSVAL(outbuf,smb_vwv0,nwritten);
2046 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
2047 timestring(),fnum,cnum,numtowrite,nwritten));
2049 return(outsize);
2053 /****************************************************************************
2054 reply to a write
2055 ****************************************************************************/
2056 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
2058 int cnum,numtowrite,fnum;
2059 int nwritten = -1;
2060 int outsize = 0;
2061 int startpos;
2062 char *data;
2064 dum1 = dum2 = 0;
2067 cnum = SVAL(inbuf,smb_tid);
2068 fnum = GETFNUM(inbuf,smb_vwv0);
2070 CHECK_FNUM(fnum,cnum);
2071 CHECK_WRITE(fnum);
2072 CHECK_ERROR(fnum);
2074 numtowrite = SVAL(inbuf,smb_vwv1);
2075 startpos = IVAL(inbuf,smb_vwv2);
2076 data = smb_buf(inbuf) + 3;
2078 if (is_locked(fnum,cnum,numtowrite,startpos))
2079 return(ERROR(ERRDOS,ERRlock));
2081 seek_file(fnum,startpos);
2083 /* X/Open SMB protocol says that if smb_vwv1 is
2084 zero then the file size should be extended or
2085 truncated to the size given in smb_vwv[2-3] */
2086 if(numtowrite == 0)
2087 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
2088 else
2089 nwritten = write_file(fnum,data,numtowrite);
2091 if (lp_syncalways(SNUM(cnum)))
2092 sync_file(fnum);
2094 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
2095 return(UNIXERROR(ERRDOS,ERRnoaccess));
2097 outsize = set_message(outbuf,1,0,True);
2099 SSVAL(outbuf,smb_vwv0,nwritten);
2101 if (nwritten < numtowrite) {
2102 CVAL(outbuf,smb_rcls) = ERRHRD;
2103 SSVAL(outbuf,smb_err,ERRdiskfull);
2106 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
2108 return(outsize);
2112 /****************************************************************************
2113 reply to a write and X
2114 ****************************************************************************/
2115 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
2117 int fnum = GETFNUM(inbuf,smb_vwv2);
2118 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
2119 int smb_dsize = SVAL(inbuf,smb_vwv10);
2120 int smb_doff = SVAL(inbuf,smb_vwv11);
2121 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2122 int cnum;
2123 int nwritten = -1;
2124 char *data;
2126 cnum = SVAL(inbuf,smb_tid);
2128 CHECK_FNUM(fnum,cnum);
2129 CHECK_WRITE(fnum);
2130 CHECK_ERROR(fnum);
2132 data = smb_base(inbuf) + smb_doff;
2134 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
2135 return(ERROR(ERRDOS,ERRlock));
2137 seek_file(fnum,smb_offs);
2139 /* X/Open SMB protocol says that, unlike SMBwrite
2140 if the length is zero then NO truncation is
2141 done, just a write of zero. To truncate a file,
2142 use SMBwrite. */
2143 if(smb_dsize == 0)
2144 nwritten = 0;
2145 else
2146 nwritten = write_file(fnum,data,smb_dsize);
2148 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
2149 return(UNIXERROR(ERRDOS,ERRnoaccess));
2151 set_message(outbuf,6,0,True);
2153 SSVAL(outbuf,smb_vwv2,nwritten);
2155 if (nwritten < smb_dsize) {
2156 CVAL(outbuf,smb_rcls) = ERRHRD;
2157 SSVAL(outbuf,smb_err,ERRdiskfull);
2160 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
2162 chain_fnum = fnum;
2164 if (lp_syncalways(SNUM(cnum)) || write_through)
2165 sync_file(fnum);
2167 return chain_reply(inbuf,outbuf,length,bufsize);
2171 /****************************************************************************
2172 reply to a lseek
2173 ****************************************************************************/
2174 int reply_lseek(char *inbuf,char *outbuf)
2176 int cnum,fnum;
2177 uint32 startpos;
2178 int32 res= -1;
2179 int mode,umode;
2180 int outsize = 0;
2182 cnum = SVAL(inbuf,smb_tid);
2183 fnum = GETFNUM(inbuf,smb_vwv0);
2185 CHECK_FNUM(fnum,cnum);
2186 CHECK_ERROR(fnum);
2188 mode = SVAL(inbuf,smb_vwv1) & 3;
2189 startpos = IVAL(inbuf,smb_vwv2);
2191 switch (mode & 3)
2193 case 0: umode = SEEK_SET; break;
2194 case 1: umode = SEEK_CUR; break;
2195 case 2: umode = SEEK_END; break;
2196 default:
2197 umode = SEEK_SET; break;
2200 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2201 Files[fnum].pos = res;
2203 outsize = set_message(outbuf,2,0,True);
2204 SIVALS(outbuf,smb_vwv0,res);
2206 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2208 return(outsize);
2212 /****************************************************************************
2213 reply to a flush
2214 ****************************************************************************/
2215 int reply_flush(char *inbuf,char *outbuf)
2217 int cnum, fnum;
2218 int outsize = set_message(outbuf,0,0,True);
2220 cnum = SVAL(inbuf,smb_tid);
2221 fnum = GETFNUM(inbuf,smb_vwv0);
2223 if (fnum != 0xFFFF) {
2224 CHECK_FNUM(fnum,cnum);
2225 CHECK_ERROR(fnum);
2228 if (fnum == 0xFFFF)
2230 int i;
2231 for (i=0;i<MAX_OPEN_FILES;i++)
2232 if (OPEN_FNUM(i))
2233 sync_file(i);
2235 else
2236 sync_file(fnum);
2238 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2239 return(outsize);
2243 /****************************************************************************
2244 reply to a exit
2245 ****************************************************************************/
2246 int reply_exit(char *inbuf,char *outbuf)
2248 int outsize = set_message(outbuf,0,0,True);
2249 DEBUG(3,("%s exit\n",timestring()));
2251 return(outsize);
2255 /****************************************************************************
2256 reply to a close
2257 ****************************************************************************/
2258 int reply_close(char *inbuf,char *outbuf)
2260 int fnum,cnum;
2261 int outsize = 0;
2262 time_t mtime;
2263 int32 eclass = 0, err = 0;
2265 outsize = set_message(outbuf,0,0,True);
2267 cnum = SVAL(inbuf,smb_tid);
2269 fnum = GETFNUM(inbuf,smb_vwv0);
2270 CHECK_FNUM(fnum,cnum);
2272 if(HAS_CACHED_ERROR(fnum)) {
2273 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2274 err = Files[fnum].wbmpx_ptr->wr_error;
2277 mtime = make_unix_date3(inbuf+smb_vwv1);
2279 /* try and set the date */
2280 set_filetime(cnum, Files[fnum].name,mtime);
2282 close_file(fnum,True);
2284 /* We have a cached error */
2285 if(eclass || err)
2286 return(ERROR(eclass,err));
2288 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2289 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2290 Connections[cnum].num_files_open));
2292 return(outsize);
2296 /****************************************************************************
2297 reply to a writeclose (Core+ protocol)
2298 ****************************************************************************/
2299 int reply_writeclose(char *inbuf,char *outbuf)
2301 int cnum,numtowrite,fnum;
2302 int nwritten = -1;
2303 int outsize = 0;
2304 int startpos;
2305 char *data;
2306 time_t mtime;
2308 cnum = SVAL(inbuf,smb_tid);
2309 fnum = GETFNUM(inbuf,smb_vwv0);
2311 CHECK_FNUM(fnum,cnum);
2312 CHECK_WRITE(fnum);
2313 CHECK_ERROR(fnum);
2315 numtowrite = SVAL(inbuf,smb_vwv1);
2316 startpos = IVAL(inbuf,smb_vwv2);
2317 mtime = make_unix_date3(inbuf+smb_vwv4);
2318 data = smb_buf(inbuf) + 1;
2320 if (is_locked(fnum,cnum,numtowrite,startpos))
2321 return(ERROR(ERRDOS,ERRlock));
2323 seek_file(fnum,startpos);
2325 nwritten = write_file(fnum,data,numtowrite);
2327 set_filetime(cnum, Files[fnum].name,mtime);
2329 close_file(fnum,True);
2331 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2332 timestring(),fnum,cnum,numtowrite,nwritten,
2333 Connections[cnum].num_files_open));
2335 if (nwritten <= 0)
2336 return(UNIXERROR(ERRDOS,ERRnoaccess));
2338 outsize = set_message(outbuf,1,0,True);
2340 SSVAL(outbuf,smb_vwv0,nwritten);
2341 return(outsize);
2345 /****************************************************************************
2346 reply to a lock
2347 ****************************************************************************/
2348 int reply_lock(char *inbuf,char *outbuf)
2350 int fnum,cnum;
2351 int outsize = set_message(outbuf,0,0,True);
2352 uint32 count,offset;
2353 int eclass;
2354 uint32 ecode;
2356 cnum = SVAL(inbuf,smb_tid);
2357 fnum = GETFNUM(inbuf,smb_vwv0);
2359 CHECK_FNUM(fnum,cnum);
2360 CHECK_ERROR(fnum);
2362 count = IVAL(inbuf,smb_vwv1);
2363 offset = IVAL(inbuf,smb_vwv3);
2365 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));
2367 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2368 return (ERROR(eclass,ecode));
2370 return(outsize);
2374 /****************************************************************************
2375 reply to a unlock
2376 ****************************************************************************/
2377 int reply_unlock(char *inbuf,char *outbuf)
2379 int fnum,cnum;
2380 int outsize = set_message(outbuf,0,0,True);
2381 uint32 count,offset;
2382 int eclass;
2383 uint32 ecode;
2385 cnum = SVAL(inbuf,smb_tid);
2386 fnum = GETFNUM(inbuf,smb_vwv0);
2388 CHECK_FNUM(fnum,cnum);
2389 CHECK_ERROR(fnum);
2391 count = IVAL(inbuf,smb_vwv1);
2392 offset = IVAL(inbuf,smb_vwv3);
2394 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2395 return (ERROR(eclass,ecode));
2397 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));
2399 return(outsize);
2403 /****************************************************************************
2404 reply to a tdis
2405 ****************************************************************************/
2406 int reply_tdis(char *inbuf,char *outbuf)
2408 int cnum;
2409 int outsize = set_message(outbuf,0,0,True);
2410 uint16 vuid;
2412 cnum = SVAL(inbuf,smb_tid);
2413 vuid = SVAL(inbuf,smb_uid);
2415 if (!OPEN_CNUM(cnum)) {
2416 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2417 return(ERROR(ERRSRV,ERRinvnid));
2420 Connections[cnum].used = False;
2422 close_cnum(cnum,vuid);
2424 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2426 return outsize;
2431 /****************************************************************************
2432 reply to a echo
2433 ****************************************************************************/
2434 int reply_echo(char *inbuf,char *outbuf)
2436 int cnum;
2437 int smb_reverb = SVAL(inbuf,smb_vwv0);
2438 int seq_num;
2439 int data_len = smb_buflen(inbuf);
2440 int outsize = set_message(outbuf,1,data_len,True);
2442 cnum = SVAL(inbuf,smb_tid);
2444 /* According to the latest CIFS spec we shouldn't
2445 care what the TID is.
2448 #if 0
2449 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2451 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2452 return(ERROR(ERRSRV,ERRinvnid));
2454 #endif
2456 /* copy any incoming data back out */
2457 if (data_len > 0)
2458 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2460 if (smb_reverb > 100)
2462 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2463 smb_reverb = 100;
2466 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2468 SSVAL(outbuf,smb_vwv0,seq_num);
2470 smb_setlen(outbuf,outsize - 4);
2472 send_smb(Client,outbuf);
2475 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2477 return -1;
2481 /****************************************************************************
2482 reply to a printopen
2483 ****************************************************************************/
2484 int reply_printopen(char *inbuf,char *outbuf)
2486 pstring fname;
2487 pstring fname2;
2488 int cnum;
2489 int fnum = -1;
2490 int outsize = 0;
2492 *fname = *fname2 = 0;
2494 cnum = SVAL(inbuf,smb_tid);
2496 if (!CAN_PRINT(cnum))
2497 return(ERROR(ERRDOS,ERRnoaccess));
2500 pstring s;
2501 char *p;
2502 pstrcpy(s,smb_buf(inbuf)+1);
2503 p = s;
2504 while (*p)
2506 if (!(isalnum(*p) || strchr("._-",*p)))
2507 *p = 'X';
2508 p++;
2511 if (strlen(s) > 10) s[10] = 0;
2513 sprintf(fname,"%s.XXXXXX",s);
2516 fnum = find_free_file();
2517 if (fnum < 0)
2518 return(ERROR(ERRSRV,ERRnofids));
2520 strcpy(fname2,(char *)mktemp(fname));
2522 if (!check_name(fname2,cnum))
2523 return(ERROR(ERRDOS,ERRnoaccess));
2525 /* Open for exclusive use, write only. */
2526 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
2527 0, NULL, NULL);
2529 if (!Files[fnum].open)
2530 return(UNIXERROR(ERRDOS,ERRnoaccess));
2532 /* force it to be a print file */
2533 Files[fnum].print_file = True;
2535 outsize = set_message(outbuf,1,0,True);
2536 SSVAL(outbuf,smb_vwv0,fnum);
2538 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2540 return(outsize);
2544 /****************************************************************************
2545 reply to a printclose
2546 ****************************************************************************/
2547 int reply_printclose(char *inbuf,char *outbuf)
2549 int fnum,cnum;
2550 int outsize = set_message(outbuf,0,0,True);
2552 cnum = SVAL(inbuf,smb_tid);
2553 fnum = GETFNUM(inbuf,smb_vwv0);
2555 CHECK_FNUM(fnum,cnum);
2556 CHECK_ERROR(fnum);
2558 if (!CAN_PRINT(cnum))
2559 return(ERROR(ERRDOS,ERRnoaccess));
2561 close_file(fnum,True);
2563 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2565 return(outsize);
2569 /****************************************************************************
2570 reply to a printqueue
2571 ****************************************************************************/
2572 int reply_printqueue(char *inbuf,char *outbuf)
2574 int cnum;
2575 int outsize = set_message(outbuf,2,3,True);
2576 int max_count = SVAL(inbuf,smb_vwv0);
2577 int start_index = SVAL(inbuf,smb_vwv1);
2578 uint16 vuid;
2580 cnum = SVAL(inbuf,smb_tid);
2581 vuid = SVAL(inbuf,smb_uid);
2583 /* allow checking the queue for anyone */
2584 #if 0
2585 if (!CAN_PRINT(cnum))
2586 return(ERROR(ERRDOS,ERRnoaccess));
2587 #endif
2589 SSVAL(outbuf,smb_vwv0,0);
2590 SSVAL(outbuf,smb_vwv1,0);
2591 CVAL(smb_buf(outbuf),0) = 1;
2592 SSVAL(smb_buf(outbuf),1,0);
2594 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2595 timestring(),cnum,start_index,max_count));
2597 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2599 int i;
2600 cnum = -1;
2602 for (i=0;i<MAX_CONNECTIONS;i++)
2603 if (CAN_PRINT(i) && Connections[i].printer)
2604 cnum = i;
2606 if (cnum == -1)
2607 for (i=0;i<MAX_CONNECTIONS;i++)
2608 if (OPEN_CNUM(i))
2609 cnum = i;
2611 if (!OPEN_CNUM(cnum))
2612 return(ERROR(ERRSRV,ERRinvnid));
2614 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2617 if (!become_user(cnum,vuid))
2618 return(ERROR(ERRSRV,ERRinvnid));
2621 print_queue_struct *queue = NULL;
2622 char *p = smb_buf(outbuf) + 3;
2623 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2624 int num_to_get = ABS(max_count);
2625 int first = (max_count>0?start_index:start_index+max_count+1);
2626 int i;
2628 if (first >= count)
2629 num_to_get = 0;
2630 else
2631 num_to_get = MIN(num_to_get,count-first);
2634 for (i=first;i<first+num_to_get;i++)
2636 put_dos_date2(p,0,queue[i].time);
2637 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2638 SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job));
2639 SIVAL(p,7,queue[i].size);
2640 CVAL(p,11) = 0;
2641 StrnCpy(p+12,queue[i].user,16);
2642 p += 28;
2645 if (count > 0)
2647 outsize = set_message(outbuf,2,28*count+3,False);
2648 SSVAL(outbuf,smb_vwv0,count);
2649 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2650 CVAL(smb_buf(outbuf),0) = 1;
2651 SSVAL(smb_buf(outbuf),1,28*count);
2654 if (queue) free(queue);
2656 DEBUG(3,("%d entries returned in queue\n",count));
2659 return(outsize);
2663 /****************************************************************************
2664 reply to a printwrite
2665 ****************************************************************************/
2666 int reply_printwrite(char *inbuf,char *outbuf)
2668 int cnum,numtowrite,fnum;
2669 int outsize = set_message(outbuf,0,0,True);
2670 char *data;
2672 cnum = SVAL(inbuf,smb_tid);
2674 if (!CAN_PRINT(cnum))
2675 return(ERROR(ERRDOS,ERRnoaccess));
2677 fnum = GETFNUM(inbuf,smb_vwv0);
2679 CHECK_FNUM(fnum,cnum);
2680 CHECK_WRITE(fnum);
2681 CHECK_ERROR(fnum);
2683 numtowrite = SVAL(smb_buf(inbuf),1);
2684 data = smb_buf(inbuf) + 3;
2686 if (write_file(fnum,data,numtowrite) != numtowrite)
2687 return(UNIXERROR(ERRDOS,ERRnoaccess));
2689 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2691 return(outsize);
2695 /****************************************************************************
2696 reply to a mkdir
2697 ****************************************************************************/
2698 int reply_mkdir(char *inbuf,char *outbuf)
2700 pstring directory;
2701 int cnum;
2702 int outsize,ret= -1;
2703 BOOL bad_path = False;
2705 pstrcpy(directory,smb_buf(inbuf) + 1);
2706 cnum = SVAL(inbuf,smb_tid);
2707 unix_convert(directory,cnum,0,&bad_path);
2709 if (check_name(directory,cnum))
2710 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2712 if (ret < 0)
2714 if((errno == ENOENT) && bad_path)
2716 unix_ERR_class = ERRDOS;
2717 unix_ERR_code = ERRbadpath;
2719 return(UNIXERROR(ERRDOS,ERRnoaccess));
2722 outsize = set_message(outbuf,0,0,True);
2724 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2726 return(outsize);
2729 /****************************************************************************
2730 Static function used by reply_rmdir to delete an entire directory
2731 tree recursively.
2732 ****************************************************************************/
2733 static BOOL recursive_rmdir(char *directory)
2735 char *dname = NULL;
2736 BOOL ret = False;
2737 void *dirptr = OpenDir(-1, directory, False);
2739 if(dirptr == NULL)
2740 return True;
2742 while((dname = ReadDirName(dirptr)))
2744 pstring fullname;
2745 struct stat st;
2747 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2748 continue;
2750 /* Construct the full name. */
2751 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2753 errno = ENOMEM;
2754 ret = True;
2755 break;
2757 strcpy(fullname, directory);
2758 strcat(fullname, "/");
2759 strcat(fullname, dname);
2761 if(sys_lstat(fullname, &st) != 0)
2763 ret = True;
2764 break;
2767 if(st.st_mode & S_IFDIR)
2769 if(recursive_rmdir(fullname)!=0)
2771 ret = True;
2772 break;
2774 if(sys_rmdir(fullname) != 0)
2776 ret = True;
2777 break;
2780 else if(sys_unlink(fullname) != 0)
2782 ret = True;
2783 break;
2786 CloseDir(dirptr);
2787 return ret;
2790 /****************************************************************************
2791 reply to a rmdir
2792 ****************************************************************************/
2793 int reply_rmdir(char *inbuf,char *outbuf)
2795 pstring directory;
2796 int cnum;
2797 int outsize = 0;
2798 BOOL ok = False;
2799 BOOL bad_path = False;
2801 cnum = SVAL(inbuf,smb_tid);
2802 pstrcpy(directory,smb_buf(inbuf) + 1);
2803 unix_convert(directory,cnum,0,&bad_path);
2805 if (check_name(directory,cnum))
2808 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2809 ok = (sys_rmdir(directory) == 0);
2810 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2812 /* Check to see if the only thing in this directory are
2813 vetoed files/directories. If so then delete them and
2814 retry. If we fail to delete any of them (and we *don't*
2815 do a recursive delete) then fail the rmdir. */
2816 BOOL all_veto_files = True;
2817 char *dname;
2818 void *dirptr = OpenDir(cnum, directory, False);
2820 if(dirptr != NULL)
2822 int dirpos = TellDir(dirptr);
2823 while ((dname = ReadDirName(dirptr)))
2825 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2826 continue;
2827 if(!IS_VETO_PATH(cnum, dname))
2829 all_veto_files = False;
2830 break;
2833 if(all_veto_files)
2835 SeekDir(dirptr,dirpos);
2836 while ((dname = ReadDirName(dirptr)))
2838 pstring fullname;
2839 struct stat st;
2841 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2842 continue;
2844 /* Construct the full name. */
2845 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2847 errno = ENOMEM;
2848 break;
2850 pstrcpy(fullname, directory);
2851 strcat(fullname, "/");
2852 strcat(fullname, dname);
2854 if(sys_lstat(fullname, &st) != 0)
2855 break;
2856 if(st.st_mode & S_IFDIR)
2858 if(lp_recursive_veto_delete(SNUM(cnum)))
2860 if(recursive_rmdir(fullname) != 0)
2861 break;
2863 if(sys_rmdir(fullname) != 0)
2864 break;
2866 else if(sys_unlink(fullname) != 0)
2867 break;
2869 CloseDir(dirptr);
2870 /* Retry the rmdir */
2871 ok = (sys_rmdir(directory) == 0);
2873 else
2874 CloseDir(dirptr);
2876 else
2877 errno = ENOTEMPTY;
2880 if (!ok)
2881 DEBUG(3,("couldn't remove directory %s : %s\n",
2882 directory,strerror(errno)));
2885 if (!ok)
2887 if((errno == ENOENT) && bad_path)
2889 unix_ERR_class = ERRDOS;
2890 unix_ERR_code = ERRbadpath;
2892 return(UNIXERROR(ERRDOS,ERRbadpath));
2895 outsize = set_message(outbuf,0,0,True);
2897 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2899 return(outsize);
2903 /*******************************************************************
2904 resolve wildcards in a filename rename
2905 ********************************************************************/
2906 static BOOL resolve_wildcards(char *name1,char *name2)
2908 fstring root1,root2;
2909 fstring ext1,ext2;
2910 char *p,*p2;
2912 name1 = strrchr(name1,'/');
2913 name2 = strrchr(name2,'/');
2915 if (!name1 || !name2) return(False);
2917 fstrcpy(root1,name1);
2918 fstrcpy(root2,name2);
2919 p = strrchr(root1,'.');
2920 if (p) {
2921 *p = 0;
2922 fstrcpy(ext1,p+1);
2923 } else {
2924 fstrcpy(ext1,"");
2926 p = strrchr(root2,'.');
2927 if (p) {
2928 *p = 0;
2929 fstrcpy(ext2,p+1);
2930 } else {
2931 fstrcpy(ext2,"");
2934 p = root1;
2935 p2 = root2;
2936 while (*p2) {
2937 if (*p2 == '?') {
2938 *p2 = *p;
2939 p2++;
2940 } else {
2941 p2++;
2943 if (*p) p++;
2946 p = ext1;
2947 p2 = ext2;
2948 while (*p2) {
2949 if (*p2 == '?') {
2950 *p2 = *p;
2951 p2++;
2952 } else {
2953 p2++;
2955 if (*p) p++;
2958 strcpy(name2,root2);
2959 if (ext2[0]) {
2960 strcat(name2,".");
2961 strcat(name2,ext2);
2964 return(True);
2967 /*******************************************************************
2968 check if a user is allowed to rename a file
2969 ********************************************************************/
2970 static BOOL can_rename(char *fname,int cnum)
2972 struct stat sbuf;
2974 if (!CAN_WRITE(cnum)) return(False);
2976 if (sys_lstat(fname,&sbuf) != 0) return(False);
2977 if (!check_file_sharing(cnum,fname)) return(False);
2979 return(True);
2982 /****************************************************************************
2983 reply to a mv
2984 ****************************************************************************/
2985 int reply_mv(char *inbuf,char *outbuf)
2987 int outsize = 0;
2988 pstring name;
2989 int cnum;
2990 pstring directory;
2991 pstring mask,newname;
2992 pstring newname_last_component;
2993 char *p;
2994 int count=0;
2995 int error = ERRnoaccess;
2996 BOOL has_wild;
2997 BOOL exists=False;
2998 BOOL bad_path1 = False;
2999 BOOL bad_path2 = False;
3001 *directory = *mask = 0;
3003 cnum = SVAL(inbuf,smb_tid);
3005 pstrcpy(name,smb_buf(inbuf) + 1);
3006 pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
3008 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3010 unix_convert(name,cnum,0,&bad_path1);
3011 unix_convert(newname,cnum,newname_last_component,&bad_path2);
3014 * Split the old name into directory and last component
3015 * strings. Note that unix_convert may have stripped off a
3016 * leading ./ from both name and newname if the rename is
3017 * at the root of the share. We need to make sure either both
3018 * name and newname contain a / character or neither of them do
3019 * as this is checked in resolve_wildcards().
3022 p = strrchr(name,'/');
3023 if (!p) {
3024 strcpy(directory,".");
3025 strcpy(mask,name);
3026 } else {
3027 *p = 0;
3028 strcpy(directory,name);
3029 strcpy(mask,p+1);
3030 *p = '/'; /* Replace needed for exceptional test below. */
3033 if (is_mangled(mask))
3034 check_mangled_stack(mask);
3036 has_wild = strchr(mask,'*') || strchr(mask,'?');
3038 if (!has_wild) {
3039 BOOL is_short_name = is_8_3(name, True);
3041 /* Add a terminating '/' to the directory name. */
3042 strcat(directory,"/");
3043 strcat(directory,mask);
3045 /* Ensure newname contains a '/' also */
3046 if(strrchr(newname,'/') == 0) {
3047 pstring tmpstr;
3049 strcpy(tmpstr, "./");
3050 strcat(tmpstr, newname);
3051 strcpy(newname, tmpstr);
3054 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",
3055 case_sensitive, case_preserve, short_case_preserve, directory,
3056 newname, newname_last_component, is_short_name));
3059 * Check for special case with case preserving and not
3060 * case sensitive, if directory and newname are identical,
3061 * and the old last component differs from the original
3062 * last component only by case, then we should allow
3063 * the rename (user is trying to change the case of the
3064 * filename).
3066 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
3067 ((short_case_preserve == True) && (is_short_name == True))) &&
3068 strcsequal(directory, newname)) {
3069 pstring newname_modified_last_component;
3072 * Get the last component of the modified name.
3073 * Note that we guarantee that newname contains a '/'
3074 * character above.
3076 p = strrchr(newname,'/');
3077 strcpy(newname_modified_last_component,p+1);
3079 if(strcsequal(newname_modified_last_component,
3080 newname_last_component) == False) {
3082 * Replace the modified last component with
3083 * the original.
3085 strcpy(p+1, newname_last_component);
3089 if (resolve_wildcards(directory,newname) &&
3090 can_rename(directory,cnum) &&
3091 !file_exist(newname,NULL) &&
3092 !sys_rename(directory,newname)) count++;
3094 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3095 directory,newname));
3097 if (!count) exists = file_exist(directory,NULL);
3098 if (!count && exists && file_exist(newname,NULL)) {
3099 exists = True;
3100 error = 183;
3102 } else {
3103 void *dirptr = NULL;
3104 char *dname;
3105 pstring destname;
3107 if (check_name(directory,cnum))
3108 dirptr = OpenDir(cnum, directory, True);
3110 if (dirptr)
3112 error = ERRbadfile;
3114 if (strequal(mask,"????????.???"))
3115 strcpy(mask,"*");
3117 while ((dname = ReadDirName(dirptr)))
3119 pstring fname;
3120 pstrcpy(fname,dname);
3122 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3124 error = ERRnoaccess;
3125 sprintf(fname,"%s/%s",directory,dname);
3126 if (!can_rename(fname,cnum)) continue;
3127 pstrcpy(destname,newname);
3129 if (!resolve_wildcards(fname,destname)) continue;
3131 if (file_exist(destname,NULL)) {
3132 error = 183;
3133 continue;
3135 if (!sys_rename(fname,destname)) count++;
3136 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
3138 CloseDir(dirptr);
3142 if (count == 0) {
3143 if (exists)
3144 return(ERROR(ERRDOS,error));
3145 else
3147 if((errno == ENOENT) && (bad_path1 || bad_path2))
3149 unix_ERR_class = ERRDOS;
3150 unix_ERR_code = ERRbadpath;
3152 return(UNIXERROR(ERRDOS,error));
3156 outsize = set_message(outbuf,0,0,True);
3158 return(outsize);
3161 /*******************************************************************
3162 copy a file as part of a reply_copy
3163 ******************************************************************/
3164 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
3165 int count,BOOL target_is_directory)
3167 int Access,action;
3168 struct stat st;
3169 int ret=0;
3170 int fnum1,fnum2;
3171 pstring dest;
3173 pstrcpy(dest,dest1);
3174 if (target_is_directory) {
3175 char *p = strrchr(src,'/');
3176 if (p)
3177 p++;
3178 else
3179 p = src;
3180 strcat(dest,"/");
3181 strcat(dest,p);
3184 if (!file_exist(src,&st)) return(False);
3186 fnum1 = find_free_file();
3187 if (fnum1<0) return(False);
3188 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
3189 1,0,0,&Access,&action);
3191 if (!Files[fnum1].open) return(False);
3193 if (!target_is_directory && count)
3194 ofun = 1;
3196 fnum2 = find_free_file();
3197 if (fnum2<0) {
3198 close_file(fnum1,False);
3199 return(False);
3201 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
3202 ofun,st.st_mode,0,&Access,&action);
3204 if (!Files[fnum2].open) {
3205 close_file(fnum1,False);
3206 return(False);
3209 if ((ofun&3) == 1) {
3210 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
3213 if (st.st_size)
3214 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
3216 close_file(fnum1,False);
3217 close_file(fnum2,False);
3219 return(ret == st.st_size);
3224 /****************************************************************************
3225 reply to a file copy.
3226 ****************************************************************************/
3227 int reply_copy(char *inbuf,char *outbuf)
3229 int outsize = 0;
3230 pstring name;
3231 int cnum;
3232 pstring directory;
3233 pstring mask,newname;
3234 char *p;
3235 int count=0;
3236 int error = ERRnoaccess;
3237 BOOL has_wild;
3238 BOOL exists=False;
3239 int tid2 = SVAL(inbuf,smb_vwv0);
3240 int ofun = SVAL(inbuf,smb_vwv1);
3241 int flags = SVAL(inbuf,smb_vwv2);
3242 BOOL target_is_directory=False;
3243 BOOL bad_path1 = False;
3244 BOOL bad_path2 = False;
3246 *directory = *mask = 0;
3248 cnum = SVAL(inbuf,smb_tid);
3250 pstrcpy(name,smb_buf(inbuf));
3251 pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3253 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3255 if (tid2 != cnum) {
3256 /* can't currently handle inter share copies XXXX */
3257 DEBUG(3,("Rejecting inter-share copy\n"));
3258 return(ERROR(ERRSRV,ERRinvdevice));
3261 unix_convert(name,cnum,0,&bad_path1);
3262 unix_convert(newname,cnum,0,&bad_path2);
3264 target_is_directory = directory_exist(newname,NULL);
3266 if ((flags&1) && target_is_directory) {
3267 return(ERROR(ERRDOS,ERRbadfile));
3270 if ((flags&2) && !target_is_directory) {
3271 return(ERROR(ERRDOS,ERRbadpath));
3274 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3275 /* wants a tree copy! XXXX */
3276 DEBUG(3,("Rejecting tree copy\n"));
3277 return(ERROR(ERRSRV,ERRerror));
3280 p = strrchr(name,'/');
3281 if (!p) {
3282 strcpy(directory,"./");
3283 strcpy(mask,name);
3284 } else {
3285 *p = 0;
3286 strcpy(directory,name);
3287 strcpy(mask,p+1);
3290 if (is_mangled(mask))
3291 check_mangled_stack(mask);
3293 has_wild = strchr(mask,'*') || strchr(mask,'?');
3295 if (!has_wild) {
3296 strcat(directory,"/");
3297 strcat(directory,mask);
3298 if (resolve_wildcards(directory,newname) &&
3299 copy_file(directory,newname,cnum,ofun,
3300 count,target_is_directory)) count++;
3301 if (!count) exists = file_exist(directory,NULL);
3302 } else {
3303 void *dirptr = NULL;
3304 char *dname;
3305 pstring destname;
3307 if (check_name(directory,cnum))
3308 dirptr = OpenDir(cnum, directory, True);
3310 if (dirptr)
3312 error = ERRbadfile;
3314 if (strequal(mask,"????????.???"))
3315 strcpy(mask,"*");
3317 while ((dname = ReadDirName(dirptr)))
3319 pstring fname;
3320 pstrcpy(fname,dname);
3322 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3324 error = ERRnoaccess;
3325 sprintf(fname,"%s/%s",directory,dname);
3326 strcpy(destname,newname);
3327 if (resolve_wildcards(fname,destname) &&
3328 copy_file(directory,newname,cnum,ofun,
3329 count,target_is_directory)) count++;
3330 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3332 CloseDir(dirptr);
3336 if (count == 0) {
3337 if (exists)
3338 return(ERROR(ERRDOS,error));
3339 else
3341 if((errno == ENOENT) && (bad_path1 || bad_path2))
3343 unix_ERR_class = ERRDOS;
3344 unix_ERR_code = ERRbadpath;
3346 return(UNIXERROR(ERRDOS,error));
3350 outsize = set_message(outbuf,1,0,True);
3351 SSVAL(outbuf,smb_vwv0,count);
3353 return(outsize);
3358 /****************************************************************************
3359 reply to a setdir
3360 ****************************************************************************/
3361 int reply_setdir(char *inbuf,char *outbuf)
3363 int cnum,snum;
3364 int outsize = 0;
3365 BOOL ok = False;
3366 pstring newdir;
3368 cnum = SVAL(inbuf,smb_tid);
3370 snum = Connections[cnum].service;
3371 if (!CAN_SETDIR(snum))
3372 return(ERROR(ERRDOS,ERRnoaccess));
3374 pstrcpy(newdir,smb_buf(inbuf) + 1);
3375 strlower(newdir);
3377 if (strlen(newdir) == 0)
3378 ok = True;
3379 else
3381 ok = directory_exist(newdir,NULL);
3382 if (ok)
3383 string_set(&Connections[cnum].connectpath,newdir);
3386 if (!ok)
3387 return(ERROR(ERRDOS,ERRbadpath));
3389 outsize = set_message(outbuf,0,0,True);
3390 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3392 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3394 return(outsize);
3398 /****************************************************************************
3399 reply to a lockingX request
3400 ****************************************************************************/
3401 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3403 int fnum = GETFNUM(inbuf,smb_vwv2);
3404 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3405 #if 0
3406 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3407 #endif
3408 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3409 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3410 uint32 count, offset;
3412 int cnum;
3413 int i;
3414 char *data;
3415 uint32 ecode=0, dummy2;
3416 int eclass=0, dummy1;
3418 cnum = SVAL(inbuf,smb_tid);
3420 CHECK_FNUM(fnum,cnum);
3421 CHECK_ERROR(fnum);
3423 data = smb_buf(inbuf);
3425 /* Check if this is an oplock break on a file
3426 we have granted an oplock on.
3428 if((locktype == LOCKING_ANDX_OPLOCK_RELEASE) &&
3429 (num_ulocks == 0) && (num_locks == 0) &&
3430 (CVAL(inbuf,smb_vwv0) == 0xFF))
3432 int token;
3433 files_struct *fsp = &Files[fnum];
3434 uint32 dev = fsp->fd_ptr->dev;
3435 uint32 inode = fsp->fd_ptr->inode;
3437 DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
3438 fnum));
3440 * Make sure we have granted an oplock on this file.
3442 if(!fsp->granted_oplock)
3444 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3445 no oplock granted on this file.\n", fnum));
3446 return ERROR(ERRDOS,ERRlock);
3449 /* Remove the oplock flag from the sharemode. */
3450 lock_share_entry(fsp->cnum, dev, inode, &token);
3451 if(remove_share_oplock( fnum, token)==False)
3453 DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
3454 dev = %x, inode = %x\n", fnum, dev, inode));
3455 unlock_share_entry(fsp->cnum, dev, inode, token);
3456 return -1;
3458 unlock_share_entry(fsp->cnum, dev, inode, token);
3460 /* Clear the granted flag and return. */
3462 fsp->granted_oplock = False;
3463 return -1;
3466 /* Data now points at the beginning of the list
3467 of smb_unlkrng structs */
3468 for(i = 0; i < (int)num_ulocks; i++) {
3469 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3470 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3471 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3472 return ERROR(eclass,ecode);
3475 /* Now do any requested locks */
3476 data += 10*num_ulocks;
3477 /* Data now points at the beginning of the list
3478 of smb_lkrng structs */
3479 for(i = 0; i < (int)num_locks; i++) {
3480 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3481 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3482 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3483 break;
3486 /* If any of the above locks failed, then we must unlock
3487 all of the previous locks (X/Open spec). */
3488 if(i != num_locks && num_locks != 0) {
3489 for(; i >= 0; i--) {
3490 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3491 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3492 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3494 return ERROR(eclass,ecode);
3497 set_message(outbuf,2,0,True);
3499 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3500 timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
3502 chain_fnum = fnum;
3504 return chain_reply(inbuf,outbuf,length,bufsize);
3508 /****************************************************************************
3509 reply to a SMBreadbmpx (read block multiplex) request
3510 ****************************************************************************/
3511 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3513 int cnum,fnum;
3514 int nread = -1;
3515 int total_read;
3516 char *data;
3517 uint32 startpos;
3518 int outsize, mincount, maxcount;
3519 int max_per_packet;
3520 int tcount;
3521 int pad;
3523 /* this function doesn't seem to work - disable by default */
3524 if (!lp_readbmpx())
3525 return(ERROR(ERRSRV,ERRuseSTD));
3527 outsize = set_message(outbuf,8,0,True);
3529 cnum = SVAL(inbuf,smb_tid);
3530 fnum = GETFNUM(inbuf,smb_vwv0);
3532 CHECK_FNUM(fnum,cnum);
3533 CHECK_READ(fnum);
3534 CHECK_ERROR(fnum);
3536 startpos = IVAL(inbuf,smb_vwv1);
3537 maxcount = SVAL(inbuf,smb_vwv3);
3538 mincount = SVAL(inbuf,smb_vwv4);
3540 data = smb_buf(outbuf);
3541 pad = ((long)data)%4;
3542 if (pad) pad = 4 - pad;
3543 data += pad;
3545 max_per_packet = bufsize-(outsize+pad);
3546 tcount = maxcount;
3547 total_read = 0;
3549 if (is_locked(fnum,cnum,maxcount,startpos))
3550 return(ERROR(ERRDOS,ERRlock));
3554 int N = MIN(max_per_packet,tcount-total_read);
3556 nread = read_file(fnum,data,startpos,N);
3558 if (nread <= 0) nread = 0;
3560 if (nread < N)
3561 tcount = total_read + nread;
3563 set_message(outbuf,8,nread,False);
3564 SIVAL(outbuf,smb_vwv0,startpos);
3565 SSVAL(outbuf,smb_vwv2,tcount);
3566 SSVAL(outbuf,smb_vwv6,nread);
3567 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3569 send_smb(Client,outbuf);
3571 total_read += nread;
3572 startpos += nread;
3574 while (total_read < tcount);
3576 return(-1);
3580 /****************************************************************************
3581 reply to a SMBwritebmpx (write block multiplex primary) request
3582 ****************************************************************************/
3583 int reply_writebmpx(char *inbuf,char *outbuf)
3585 int cnum,numtowrite,fnum;
3586 int nwritten = -1;
3587 int outsize = 0;
3588 uint32 startpos;
3589 int tcount, write_through, smb_doff;
3590 char *data;
3592 cnum = SVAL(inbuf,smb_tid);
3593 fnum = GETFNUM(inbuf,smb_vwv0);
3595 CHECK_FNUM(fnum,cnum);
3596 CHECK_WRITE(fnum);
3597 CHECK_ERROR(fnum);
3599 tcount = SVAL(inbuf,smb_vwv1);
3600 startpos = IVAL(inbuf,smb_vwv3);
3601 write_through = BITSETW(inbuf+smb_vwv7,0);
3602 numtowrite = SVAL(inbuf,smb_vwv10);
3603 smb_doff = SVAL(inbuf,smb_vwv11);
3605 data = smb_base(inbuf) + smb_doff;
3607 /* If this fails we need to send an SMBwriteC response,
3608 not an SMBwritebmpx - set this up now so we don't forget */
3609 CVAL(outbuf,smb_com) = SMBwritec;
3611 if (is_locked(fnum,cnum,tcount,startpos))
3612 return(ERROR(ERRDOS,ERRlock));
3614 seek_file(fnum,startpos);
3615 nwritten = write_file(fnum,data,numtowrite);
3617 if(lp_syncalways(SNUM(cnum)) || write_through)
3618 sync_file(fnum);
3620 if(nwritten < numtowrite)
3621 return(UNIXERROR(ERRHRD,ERRdiskfull));
3623 /* If the maximum to be written to this file
3624 is greater than what we just wrote then set
3625 up a secondary struct to be attached to this
3626 fd, we will use this to cache error messages etc. */
3627 if(tcount > nwritten)
3629 write_bmpx_struct *wbms;
3630 if(Files[fnum].wbmpx_ptr != NULL)
3631 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3632 else
3633 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3634 if(!wbms)
3636 DEBUG(0,("Out of memory in reply_readmpx\n"));
3637 return(ERROR(ERRSRV,ERRnoresource));
3639 wbms->wr_mode = write_through;
3640 wbms->wr_discard = False; /* No errors yet */
3641 wbms->wr_total_written = nwritten;
3642 wbms->wr_errclass = 0;
3643 wbms->wr_error = 0;
3644 Files[fnum].wbmpx_ptr = wbms;
3647 /* We are returning successfully, set the message type back to
3648 SMBwritebmpx */
3649 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3651 outsize = set_message(outbuf,1,0,True);
3653 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3655 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3656 timestring(),fnum,cnum,numtowrite,nwritten));
3658 if (write_through && tcount==nwritten) {
3659 /* we need to send both a primary and a secondary response */
3660 smb_setlen(outbuf,outsize - 4);
3661 send_smb(Client,outbuf);
3663 /* now the secondary */
3664 outsize = set_message(outbuf,1,0,True);
3665 CVAL(outbuf,smb_com) = SMBwritec;
3666 SSVAL(outbuf,smb_vwv0,nwritten);
3669 return(outsize);
3673 /****************************************************************************
3674 reply to a SMBwritebs (write block multiplex secondary) request
3675 ****************************************************************************/
3676 int reply_writebs(char *inbuf,char *outbuf)
3678 int cnum,numtowrite,fnum;
3679 int nwritten = -1;
3680 int outsize = 0;
3681 int32 startpos;
3682 int tcount, write_through, smb_doff;
3683 char *data;
3684 write_bmpx_struct *wbms;
3685 BOOL send_response = False;
3687 cnum = SVAL(inbuf,smb_tid);
3688 fnum = GETFNUM(inbuf,smb_vwv0);
3689 CHECK_FNUM(fnum,cnum);
3690 CHECK_WRITE(fnum);
3692 tcount = SVAL(inbuf,smb_vwv1);
3693 startpos = IVAL(inbuf,smb_vwv2);
3694 numtowrite = SVAL(inbuf,smb_vwv6);
3695 smb_doff = SVAL(inbuf,smb_vwv7);
3697 data = smb_base(inbuf) + smb_doff;
3699 /* We need to send an SMBwriteC response, not an SMBwritebs */
3700 CVAL(outbuf,smb_com) = SMBwritec;
3702 /* This fd should have an auxiliary struct attached,
3703 check that it does */
3704 wbms = Files[fnum].wbmpx_ptr;
3705 if(!wbms) return(-1);
3707 /* If write through is set we can return errors, else we must
3708 cache them */
3709 write_through = wbms->wr_mode;
3711 /* Check for an earlier error */
3712 if(wbms->wr_discard)
3713 return -1; /* Just discard the packet */
3715 seek_file(fnum,startpos);
3716 nwritten = write_file(fnum,data,numtowrite);
3718 if(lp_syncalways(SNUM(cnum)) || write_through)
3719 sync_file(fnum);
3721 if (nwritten < numtowrite)
3723 if(write_through) {
3724 /* We are returning an error - we can delete the aux struct */
3725 if (wbms) free((char *)wbms);
3726 Files[fnum].wbmpx_ptr = NULL;
3727 return(ERROR(ERRHRD,ERRdiskfull));
3729 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3732 /* Increment the total written, if this matches tcount
3733 we can discard the auxiliary struct (hurrah !) and return a writeC */
3734 wbms->wr_total_written += nwritten;
3735 if(wbms->wr_total_written >= tcount)
3737 if (write_through) {
3738 outsize = set_message(outbuf,1,0,True);
3739 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3740 send_response = True;
3743 free((char *)wbms);
3744 Files[fnum].wbmpx_ptr = NULL;
3747 if(send_response)
3748 return(outsize);
3750 return(-1);
3754 /****************************************************************************
3755 reply to a SMBsetattrE
3756 ****************************************************************************/
3757 int reply_setattrE(char *inbuf,char *outbuf)
3759 int cnum,fnum;
3760 struct utimbuf unix_times;
3761 int outsize = 0;
3763 outsize = set_message(outbuf,0,0,True);
3765 cnum = SVAL(inbuf,smb_tid);
3766 fnum = GETFNUM(inbuf,smb_vwv0);
3768 CHECK_FNUM(fnum,cnum);
3769 CHECK_ERROR(fnum);
3771 /* Convert the DOS times into unix times. Ignore create
3772 time as UNIX can't set this.
3774 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3775 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3778 * Patch from Ray Frush <frush@engr.colostate.edu>
3779 * Sometimes times are sent as zero - ignore them.
3782 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3784 /* Ignore request */
3785 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \
3786 not setting timestamps of 0\n",
3787 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3788 return(outsize);
3790 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3792 /* set modify time = to access time if modify time was 0 */
3793 unix_times.modtime = unix_times.actime;
3796 /* Set the date on this file */
3797 if(file_utime(cnum, Files[fnum].name, &unix_times))
3798 return(ERROR(ERRDOS,ERRnoaccess));
3800 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
3801 timestring(), fnum,cnum,unix_times.actime,unix_times.modtime));
3803 return(outsize);
3807 /****************************************************************************
3808 reply to a SMBgetattrE
3809 ****************************************************************************/
3810 int reply_getattrE(char *inbuf,char *outbuf)
3812 int cnum,fnum;
3813 struct stat sbuf;
3814 int outsize = 0;
3815 int mode;
3817 outsize = set_message(outbuf,11,0,True);
3819 cnum = SVAL(inbuf,smb_tid);
3820 fnum = GETFNUM(inbuf,smb_vwv0);
3822 CHECK_FNUM(fnum,cnum);
3823 CHECK_ERROR(fnum);
3825 /* Do an fstat on this file */
3826 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3827 return(UNIXERROR(ERRDOS,ERRnoaccess));
3829 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3831 /* Convert the times into dos times. Set create
3832 date to be last modify date as UNIX doesn't save
3833 this */
3834 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3835 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3836 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3837 if (mode & aDIR)
3839 SIVAL(outbuf,smb_vwv6,0);
3840 SIVAL(outbuf,smb_vwv8,0);
3842 else
3844 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3845 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3847 SSVAL(outbuf,smb_vwv10, mode);
3849 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3851 return(outsize);