Changes to allow Samba to return the same error code as Windows NT.
[Samba.git] / source / smbd / reply.c
blobcadd63e045728766a9630f80583f3204d6be18a2
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1997
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
27 #include "includes.h"
28 #include "trans2.h"
30 /* look in server.c for some explanation of these variables */
31 extern int Protocol;
32 extern int DEBUGLEVEL;
33 extern int max_send;
34 extern int max_recv;
35 extern int chain_fnum;
36 extern char magic_char;
37 extern connection_struct Connections[];
38 extern files_struct Files[];
39 extern BOOL case_sensitive;
40 extern BOOL case_preserve;
41 extern BOOL short_case_preserve;
42 extern pstring sesssetup_user;
43 extern fstring myworkgroup;
44 extern int Client;
46 /* this macro should always be used to extract an fnum (smb_fid) from
47 a packet to ensure chaining works correctly */
48 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
51 /****************************************************************************
52 reply to an special message
53 ****************************************************************************/
54 int reply_special(char *inbuf,char *outbuf)
56 int outsize = 4;
57 int msg_type = CVAL(inbuf,0);
58 int msg_flags = CVAL(inbuf,1);
59 pstring name1,name2;
60 extern fstring remote_machine;
61 extern fstring local_machine;
62 char *p;
64 *name1 = *name2 = 0;
66 smb_setlen(outbuf,0);
68 switch (msg_type)
70 case 0x81: /* session request */
71 CVAL(outbuf,0) = 0x82;
72 CVAL(outbuf,3) = 0;
73 if (name_len(inbuf+4) > 50)
75 DEBUG(0,("Invalid name length in session request\n"));
76 return(0);
78 name_extract(inbuf,4,name1);
79 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
80 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2));
82 strcpy(remote_machine,name2);
83 trim_string(remote_machine," "," ");
84 p = strchr(remote_machine,' ');
85 strlower(remote_machine);
86 if (p) *p = 0;
88 strcpy(local_machine,name1);
89 trim_string(local_machine," "," ");
90 p = strchr(local_machine,' ');
91 strlower(local_machine);
92 if (p) *p = 0;
94 add_session_user(remote_machine);
96 reload_services(True);
97 reopen_logs();
99 break;
100 case 0x85: /* session keepalive */
101 default:
102 return(0);
105 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags));
107 return(outsize);
111 /*******************************************************************
112 work out what error to give to a failed connection
113 ********************************************************************/
114 static int connection_error(char *inbuf,char *outbuf,int connection_num)
116 switch (connection_num)
118 case -8:
119 return(ERROR(ERRSRV,ERRnoresource));
120 case -7:
121 return(ERROR(ERRSRV,ERRbaduid));
122 case -6:
123 return(ERROR(ERRSRV,ERRinvdevice));
124 case -5:
125 return(ERROR(ERRSRV,ERRinvnetname));
126 case -4:
127 return(ERROR(ERRSRV,ERRaccess));
128 case -3:
129 return(ERROR(ERRDOS,ERRnoipc));
130 case -2:
131 return(ERROR(ERRSRV,ERRinvnetname));
133 return(ERROR(ERRSRV,ERRbadpw));
138 /****************************************************************************
139 parse a share descriptor string
140 ****************************************************************************/
141 static void parse_connect(char *p,char *service,char *user,
142 char *password,int *pwlen,char *dev)
144 char *p2;
146 DEBUG(4,("parsing connect string %s\n",p));
148 p2 = strrchr(p,'\\');
149 if (p2 == NULL)
150 strcpy(service,p);
151 else
152 strcpy(service,p2+1);
154 p += strlen(p) + 2;
156 strcpy(password,p);
157 *pwlen = strlen(password);
159 p += strlen(p) + 2;
161 strcpy(dev,p);
163 *user = 0;
164 p = strchr(service,'%');
165 if (p != NULL)
167 *p = 0;
168 strcpy(user,p+1);
175 /****************************************************************************
176 reply to a tcon
177 ****************************************************************************/
178 int reply_tcon(char *inbuf,char *outbuf)
180 pstring service;
181 pstring user;
182 pstring password;
183 pstring dev;
184 int connection_num;
185 int outsize = 0;
186 uint16 vuid = SVAL(inbuf,smb_uid);
187 int pwlen=0;
189 *service = *user = *password = *dev = 0;
191 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
193 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
195 if (connection_num < 0)
196 return(connection_error(inbuf,outbuf,connection_num));
198 outsize = set_message(outbuf,2,0,True);
199 SSVAL(outbuf,smb_vwv0,max_recv);
200 SSVAL(outbuf,smb_vwv1,connection_num);
201 SSVAL(outbuf,smb_tid,connection_num);
203 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
205 return(outsize);
209 /****************************************************************************
210 reply to a tcon and X
211 ****************************************************************************/
212 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
214 pstring service;
215 pstring user;
216 pstring password;
217 pstring devicename;
218 int connection_num;
219 uint16 vuid = SVAL(inbuf,smb_uid);
220 int passlen = SVAL(inbuf,smb_vwv3);
221 BOOL doencrypt = SMBENCRYPT();
223 *service = *user = *password = *devicename = 0;
225 /* we might have to close an old one */
226 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
227 close_cnum(SVAL(inbuf,smb_tid),vuid);
230 char *path;
231 char *p;
232 memcpy(password,smb_buf(inbuf),passlen);
233 password[passlen]=0;
234 path = smb_buf(inbuf) + passlen;
236 if (!doencrypt || passlen != 24) {
237 if (strequal(password," "))
238 *password = 0;
239 passlen = strlen(password);
242 DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
243 strcpy(service,path+2);
244 p = strchr(service,'\\');
245 if (!p)
246 return(ERROR(ERRSRV,ERRinvnetname));
247 *p = 0;
248 strcpy(service,p+1);
249 p = strchr(service,'%');
250 if (p)
252 *p++ = 0;
253 strcpy(user,p);
255 StrnCpy(devicename,path + strlen(path) + 1,6);
256 DEBUG(4,("Got device type %s\n",devicename));
259 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
261 if (connection_num < 0)
262 return(connection_error(inbuf,outbuf,connection_num));
264 set_message(outbuf,2,strlen(devicename)+1,True);
266 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
268 /* set the incoming and outgoing tid to the just created one */
269 SSVAL(inbuf,smb_tid,connection_num);
270 SSVAL(outbuf,smb_tid,connection_num);
272 strcpy(smb_buf(outbuf),devicename);
274 return chain_reply(inbuf,outbuf,length,bufsize);
278 /****************************************************************************
279 reply to an unknown type
280 ****************************************************************************/
281 int reply_unknown(char *inbuf,char *outbuf)
283 int cnum;
284 int type;
285 cnum = SVAL(inbuf,smb_tid);
286 type = CVAL(inbuf,smb_com);
288 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
289 timestring(),
290 smb_fn_name(type),
291 cnum,type,type));
293 return(ERROR(ERRSRV,ERRunknownsmb));
297 /****************************************************************************
298 reply to an ioctl
299 ****************************************************************************/
300 int reply_ioctl(char *inbuf,char *outbuf)
302 DEBUG(3,("ignoring ioctl\n"));
303 #if 0
304 /* we just say it succeeds and hope its all OK.
305 some day it would be nice to interpret them individually */
306 return set_message(outbuf,1,0,True);
307 #else
308 return(ERROR(ERRSRV,ERRnosupport));
309 #endif
313 /****************************************************************************
314 reply to a session setup command
315 ****************************************************************************/
316 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
318 uint16 sess_vuid;
319 int gid;
320 int uid;
321 int smb_bufsize;
322 int smb_mpxmax;
323 int smb_vc_num;
324 uint32 smb_sesskey;
325 int smb_apasslen = 0;
326 pstring smb_apasswd;
327 int smb_ntpasslen = 0;
328 pstring smb_ntpasswd;
329 BOOL valid_nt_password = False;
330 pstring user;
331 BOOL guest=False;
332 BOOL computer_id=False;
333 static BOOL done_sesssetup = False;
334 BOOL doencrypt = SMBENCRYPT();
336 *smb_apasswd = 0;
338 smb_bufsize = SVAL(inbuf,smb_vwv2);
339 smb_mpxmax = SVAL(inbuf,smb_vwv3);
340 smb_vc_num = SVAL(inbuf,smb_vwv4);
341 smb_sesskey = IVAL(inbuf,smb_vwv5);
343 if (Protocol < PROTOCOL_NT1) {
344 smb_apasslen = SVAL(inbuf,smb_vwv7);
345 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
346 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
348 if (lp_security() != SEC_SERVER && !doencrypt)
349 smb_apasslen = strlen(smb_apasswd);
350 } else {
351 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
352 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
353 char *p = smb_buf(inbuf);
355 if (passlen1 != 24 && passlen2 != 24)
356 doencrypt = False;
358 if(doencrypt) {
359 /* Save the lanman2 password and the NT md4 password. */
360 smb_apasslen = passlen1;
361 memcpy(smb_apasswd,p,smb_apasslen);
362 smb_ntpasslen = passlen2;
363 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
364 } else {
365 /* both Win95 and WinNT stuff up the password lengths for
366 non-encrypting systems. Uggh.
368 if passlen1==24 its a win95 system, and its setting the
369 password length incorrectly. Luckily it still works with the
370 default code because Win95 will null terminate the password
371 anyway
373 if passlen1>0 and passlen2>0 then maybe its a NT box and its
374 setting passlen2 to some random value which really stuffs
375 things up. we need to fix that one. */
376 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
377 passlen2 != 1) {
378 passlen2 = 0;
380 /* we use the first password that they gave */
381 smb_apasslen = passlen1;
382 StrnCpy(smb_apasswd,p,smb_apasslen);
384 /* trim the password */
385 smb_apasslen = strlen(smb_apasswd);
387 /* wfwg sometimes uses a space instead of a null */
388 if (strequal(smb_apasswd," ")) {
389 smb_apasslen = 0;
390 *smb_apasswd = 0;
394 p += passlen1 + passlen2;
395 strcpy(user,p); p = skip_string(p,1);
396 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
397 p,skip_string(p,1),skip_string(p,2)));
401 DEBUG(3,("sesssetupX:name=[%s]\n",user));
403 /* If name ends in $ then I think it's asking about whether a */
404 /* computer with that name (minus the $) has access. For now */
405 /* say yes to everything ending in $. */
406 if (user[strlen(user) - 1] == '$') {
407 computer_id = True;
408 user[strlen(user) - 1] = '\0';
412 /* If no username is sent use the guest account */
413 if (!*user)
415 strcpy(user,lp_guestaccount(-1));
416 /* If no user and no password then set guest flag. */
417 if( *smb_apasswd == 0)
418 guest = True;
421 strlower(user);
423 strcpy(sesssetup_user,user);
425 reload_services(True);
427 add_session_user(user);
430 if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
431 !check_hosts_equiv(user))
434 /* now check if it's a valid username/password */
435 /* If an NT password was supplied try and validate with that
436 first. This is superior as the passwords are mixed case
437 128 length unicode */
438 if(smb_ntpasslen)
440 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
441 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
442 else
443 valid_nt_password = True;
445 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
447 if (!computer_id && lp_security() >= SEC_USER) {
448 #if (GUEST_SESSSETUP == 0)
449 return(ERROR(ERRSRV,ERRbadpw));
450 #endif
451 #if (GUEST_SESSSETUP == 1)
452 if (Get_Pwnam(user,True))
453 return(ERROR(ERRSRV,ERRbadpw));
454 #endif
456 if (*smb_apasswd || !Get_Pwnam(user,True))
457 strcpy(user,lp_guestaccount(-1));
458 DEBUG(3,("Registered username %s for guest access\n",user));
459 guest = True;
463 if (!Get_Pwnam(user,True)) {
464 DEBUG(3,("No such user %s - using guest account\n",user));
465 strcpy(user,lp_guestaccount(-1));
466 guest = True;
469 if (!strequal(user,lp_guestaccount(-1)) &&
470 lp_servicenumber(user) < 0)
472 int homes = lp_servicenumber(HOMES_NAME);
473 char *home = get_home_dir(user);
474 if (homes >= 0 && home)
475 lp_add_home(user,homes,home);
479 /* it's ok - setup a reply */
480 if (Protocol < PROTOCOL_NT1) {
481 set_message(outbuf,3,0,True);
482 } else {
483 char *p;
484 set_message(outbuf,3,3,True);
485 p = smb_buf(outbuf);
486 strcpy(p,"Unix"); p = skip_string(p,1);
487 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
488 strcpy(p,myworkgroup); p = skip_string(p,1);
489 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
490 /* perhaps grab OS version here?? */
493 /* Set the correct uid in the outgoing and incoming packets
494 We will use this on future requests to determine which
495 user we should become.
498 struct passwd *pw = Get_Pwnam(user,False);
499 if (!pw) {
500 DEBUG(1,("Username %s is invalid on this system\n",user));
501 return(ERROR(ERRSRV,ERRbadpw));
503 gid = pw->pw_gid;
504 uid = pw->pw_uid;
507 if (guest && !computer_id)
508 SSVAL(outbuf,smb_vwv2,1);
510 /* register the name and uid as being validated, so further connections
511 to a uid can get through without a password, on the same VC */
512 sess_vuid = register_vuid(uid,gid,user,guest);
514 SSVAL(outbuf,smb_uid,sess_vuid);
515 SSVAL(inbuf,smb_uid,sess_vuid);
517 if (!done_sesssetup)
518 max_send = MIN(max_send,smb_bufsize);
520 DEBUG(1,(" Client requested max send size of %d\n", max_send));
522 done_sesssetup = True;
524 return chain_reply(inbuf,outbuf,length,bufsize);
528 /****************************************************************************
529 reply to a chkpth
530 ****************************************************************************/
531 int reply_chkpth(char *inbuf,char *outbuf)
533 int outsize = 0;
534 int cnum,mode;
535 pstring name;
536 BOOL ok = False;
537 BOOL bad_path = False;
539 cnum = SVAL(inbuf,smb_tid);
541 strcpy(name,smb_buf(inbuf) + 1);
542 unix_convert(name,cnum,0,&bad_path);
544 mode = SVAL(inbuf,smb_vwv0);
546 if (check_name(name,cnum))
547 ok = directory_exist(name,NULL);
549 if (!ok)
551 /* We special case this - as when a Windows machine
552 is parsing a path is steps through the components
553 one at a time - if a component fails it expects
554 ERRbadpath, not ERRbadfile.
556 if(errno == ENOENT)
558 unix_ERR_class = ERRDOS;
559 unix_ERR_code = ERRbadpath;
561 return(UNIXERROR(ERRDOS,ERRbadpath));
564 outsize = set_message(outbuf,0,0,True);
566 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
568 return(outsize);
572 /****************************************************************************
573 reply to a getatr
574 ****************************************************************************/
575 int reply_getatr(char *inbuf,char *outbuf)
577 pstring fname;
578 int cnum;
579 int outsize = 0;
580 struct stat sbuf;
581 BOOL ok = False;
582 int mode=0;
583 uint32 size=0;
584 time_t mtime=0;
585 BOOL bad_path = False;
587 cnum = SVAL(inbuf,smb_tid);
589 strcpy(fname,smb_buf(inbuf) + 1);
590 unix_convert(fname,cnum,0,&bad_path);
592 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
593 under WfWg - weird! */
594 if (! (*fname))
596 mode = aHIDDEN | aDIR;
597 if (!CAN_WRITE(cnum)) mode |= aRONLY;
598 size = 0;
599 mtime = 0;
600 ok = True;
602 else
603 if (check_name(fname,cnum))
605 if (sys_stat(fname,&sbuf) == 0)
607 mode = dos_mode(cnum,fname,&sbuf);
608 size = sbuf.st_size;
609 mtime = sbuf.st_mtime;
610 if (mode & aDIR)
611 size = 0;
612 ok = True;
614 else
615 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
618 if (!ok)
620 if((errno == ENOENT) && bad_path)
622 unix_ERR_class = ERRDOS;
623 unix_ERR_code = ERRbadpath;
626 return(UNIXERROR(ERRDOS,ERRbadfile));
629 outsize = set_message(outbuf,10,0,True);
631 SSVAL(outbuf,smb_vwv0,mode);
632 put_dos_date3(outbuf,smb_vwv1,mtime);
633 SIVAL(outbuf,smb_vwv3,size);
635 if (Protocol >= PROTOCOL_NT1) {
636 char *p = strrchr(fname,'/');
637 uint16 flg2 = SVAL(outbuf,smb_flg2);
638 if (!p) p = fname;
639 if (!is_8_3(fname, True))
640 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
643 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
645 return(outsize);
649 /****************************************************************************
650 reply to a setatr
651 ****************************************************************************/
652 int reply_setatr(char *inbuf,char *outbuf)
654 pstring fname;
655 int cnum;
656 int outsize = 0;
657 BOOL ok=False;
658 int mode;
659 time_t mtime;
660 BOOL bad_path = False;
662 cnum = SVAL(inbuf,smb_tid);
664 strcpy(fname,smb_buf(inbuf) + 1);
665 unix_convert(fname,cnum,0,&bad_path);
667 mode = SVAL(inbuf,smb_vwv0);
668 mtime = make_unix_date3(inbuf+smb_vwv1);
670 if (directory_exist(fname,NULL))
671 mode |= aDIR;
672 if (check_name(fname,cnum))
673 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
674 if (ok)
675 ok = set_filetime(fname,mtime);
677 if (!ok)
679 if((errno == ENOENT) && bad_path)
681 unix_ERR_class = ERRDOS;
682 unix_ERR_code = ERRbadpath;
685 return(UNIXERROR(ERRDOS,ERRnoaccess));
688 outsize = set_message(outbuf,0,0,True);
690 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
692 return(outsize);
696 /****************************************************************************
697 reply to a dskattr
698 ****************************************************************************/
699 int reply_dskattr(char *inbuf,char *outbuf)
701 int cnum;
702 int outsize = 0;
703 int dfree,dsize,bsize;
705 cnum = SVAL(inbuf,smb_tid);
707 sys_disk_free(".",&bsize,&dfree,&dsize);
709 outsize = set_message(outbuf,5,0,True);
711 SSVAL(outbuf,smb_vwv0,dsize);
712 SSVAL(outbuf,smb_vwv1,bsize/512);
713 SSVAL(outbuf,smb_vwv2,512);
714 SSVAL(outbuf,smb_vwv3,dfree);
716 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
718 return(outsize);
722 /****************************************************************************
723 reply to a search
724 Can be called from SMBsearch, SMBffirst or SMBfunique.
725 ****************************************************************************/
726 int reply_search(char *inbuf,char *outbuf)
728 pstring mask;
729 pstring directory;
730 pstring fname;
731 int size,mode;
732 time_t date;
733 int dirtype;
734 int cnum;
735 int outsize = 0;
736 int numentries = 0;
737 BOOL finished = False;
738 int maxentries;
739 int i;
740 char *p;
741 BOOL ok = False;
742 int status_len;
743 char *path;
744 char status[21];
745 int dptr_num= -1;
746 BOOL check_descend = False;
747 BOOL expect_close = False;
748 BOOL can_open = True;
749 BOOL bad_path = False;
751 *mask = *directory = *fname = 0;
753 /* If we were called as SMBffirst then we must expect close. */
754 if(CVAL(inbuf,smb_com) == SMBffirst)
755 expect_close = True;
757 cnum = SVAL(inbuf,smb_tid);
759 outsize = set_message(outbuf,1,3,True);
760 maxentries = SVAL(inbuf,smb_vwv0);
761 dirtype = SVAL(inbuf,smb_vwv1);
762 path = smb_buf(inbuf) + 1;
763 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
766 /* dirtype &= ~aDIR; */
768 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
771 if (status_len == 0)
773 pstring dir2;
775 strcpy(directory,smb_buf(inbuf)+1);
776 strcpy(dir2,smb_buf(inbuf)+1);
777 unix_convert(directory,cnum,0,&bad_path);
778 unix_format(dir2);
780 if (!check_name(directory,cnum))
781 can_open = False;
783 p = strrchr(dir2,'/');
784 if (p == NULL)
786 strcpy(mask,dir2);
787 *dir2 = 0;
789 else
791 *p = 0;
792 strcpy(mask,p+1);
795 p = strrchr(directory,'/');
796 if (!p)
797 *directory = 0;
798 else
799 *p = 0;
801 if (strlen(directory) == 0)
802 strcpy(directory,"./");
803 bzero(status,21);
804 CVAL(status,0) = dirtype;
806 else
808 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
809 memcpy(mask,status+1,11);
810 mask[11] = 0;
811 dirtype = CVAL(status,0) & 0x1F;
812 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
813 if (!Connections[cnum].dirptr)
814 goto SearchEmpty;
815 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
816 if (!case_sensitive)
817 strnorm(mask);
820 /* turn strings of spaces into a . */
822 trim_string(mask,NULL," ");
823 if ((p = strrchr(mask,' ')))
825 fstring ext;
826 strcpy(ext,p+1);
827 *p = 0;
828 trim_string(mask,NULL," ");
829 strcat(mask,".");
830 strcat(mask,ext);
835 for (p=mask; *p; p++)
837 if (*p != '?' && *p != '*' && !isdoschar(*p))
839 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
840 *p = '?';
845 if (!strchr(mask,'.') && strlen(mask)>8)
847 fstring tmp;
848 strcpy(tmp,&mask[8]);
849 mask[8] = '.';
850 mask[9] = 0;
851 strcat(mask,tmp);
854 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
856 if (can_open)
858 p = smb_buf(outbuf) + 3;
860 ok = True;
862 if (status_len == 0)
864 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
865 if (dptr_num < 0)
867 if(dptr_num == -2)
869 if((errno == ENOENT) && bad_path)
871 unix_ERR_class = ERRDOS;
872 unix_ERR_code = ERRbadpath;
874 return (UNIXERROR(ERRDOS,ERRnofids));
876 return(ERROR(ERRDOS,ERRnofids));
880 DEBUG(4,("dptr_num is %d\n",dptr_num));
882 if (ok)
884 if ((dirtype&0x1F) == aVOLID)
886 memcpy(p,status,21);
887 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
888 dptr_fill(p+12,dptr_num);
889 if (dptr_zero(p+12) && (status_len==0))
890 numentries = 1;
891 else
892 numentries = 0;
893 p += DIR_STRUCT_SIZE;
895 else
897 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
898 if (in_list(Connections[cnum].dirpath,
899 lp_dontdescend(SNUM(cnum)),True))
900 check_descend = True;
902 for (i=numentries;(i<maxentries) && !finished;i++)
904 finished =
905 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
906 if (!finished)
908 memcpy(p,status,21);
909 make_dir_struct(p,mask,fname,size,mode,date);
910 dptr_fill(p+12,dptr_num);
911 numentries++;
913 p += DIR_STRUCT_SIZE;
920 SearchEmpty:
922 if (numentries == 0 || !ok)
924 CVAL(outbuf,smb_rcls) = ERRDOS;
925 SSVAL(outbuf,smb_err,ERRnofiles);
928 /* If we were called as SMBffirst with smb_search_id == NULL
929 and no entries were found then return error and close dirptr
930 (X/Open spec) */
932 if(ok && expect_close && numentries == 0 && status_len == 0)
934 CVAL(outbuf,smb_rcls) = ERRDOS;
935 SSVAL(outbuf,smb_err,ERRnofiles);
936 /* Also close the dptr - we know it's gone */
937 dptr_close(dptr_num);
940 /* If we were called as SMBfunique, then we can close the dirptr now ! */
941 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
942 dptr_close(dptr_num);
944 SSVAL(outbuf,smb_vwv0,numentries);
945 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
946 CVAL(smb_buf(outbuf),0) = 5;
947 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
949 if (Protocol >= PROTOCOL_NT1) {
950 uint16 flg2 = SVAL(outbuf,smb_flg2);
951 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
954 outsize += DIR_STRUCT_SIZE*numentries;
955 smb_setlen(outbuf,outsize - 4);
957 if ((! *directory) && dptr_path(dptr_num))
958 sprintf(directory,"(%s)",dptr_path(dptr_num));
960 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
961 timestring(),
962 smb_fn_name(CVAL(inbuf,smb_com)),
963 mask,directory,cnum,dirtype,numentries,maxentries));
965 return(outsize);
969 /****************************************************************************
970 reply to a fclose (stop directory search)
971 ****************************************************************************/
972 int reply_fclose(char *inbuf,char *outbuf)
974 int cnum;
975 int outsize = 0;
976 int status_len;
977 char *path;
978 char status[21];
979 int dptr_num= -1;
981 cnum = SVAL(inbuf,smb_tid);
983 outsize = set_message(outbuf,1,0,True);
984 path = smb_buf(inbuf) + 1;
985 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
988 if (status_len == 0)
989 return(ERROR(ERRSRV,ERRsrverror));
991 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
993 if(dptr_fetch(status+12,&dptr_num)) {
994 /* Close the dptr - we know it's gone */
995 dptr_close(dptr_num);
998 SSVAL(outbuf,smb_vwv0,0);
1000 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
1002 return(outsize);
1006 /****************************************************************************
1007 reply to an open
1008 ****************************************************************************/
1009 int reply_open(char *inbuf,char *outbuf)
1011 pstring fname;
1012 int cnum;
1013 int fnum = -1;
1014 int outsize = 0;
1015 int fmode=0;
1016 int share_mode;
1017 int size = 0;
1018 time_t mtime=0;
1019 int unixmode;
1020 int rmode=0;
1021 struct stat sbuf;
1022 BOOL bad_path = False;
1024 cnum = SVAL(inbuf,smb_tid);
1026 share_mode = SVAL(inbuf,smb_vwv0);
1028 strcpy(fname,smb_buf(inbuf)+1);
1029 unix_convert(fname,cnum,0,&bad_path);
1031 fnum = find_free_file();
1032 if (fnum < 0)
1033 return(ERROR(ERRSRV,ERRnofids));
1035 if (!check_name(fname,cnum))
1037 if((errno == ENOENT) && bad_path)
1039 unix_ERR_class = ERRDOS;
1040 unix_ERR_code = ERRbadpath;
1042 return(UNIXERROR(ERRDOS,ERRnoaccess));
1045 unixmode = unix_mode(cnum,aARCH);
1047 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
1049 if (!Files[fnum].open)
1051 if((errno == ENOENT) && bad_path)
1053 unix_ERR_class = ERRDOS;
1054 unix_ERR_code = ERRbadpath;
1056 return(UNIXERROR(ERRDOS,ERRnoaccess));
1059 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1060 close_file(fnum);
1061 return(ERROR(ERRDOS,ERRnoaccess));
1064 size = sbuf.st_size;
1065 fmode = dos_mode(cnum,fname,&sbuf);
1066 mtime = sbuf.st_mtime;
1068 if (fmode & aDIR) {
1069 DEBUG(3,("attempt to open a directory %s\n",fname));
1070 close_file(fnum);
1071 return(ERROR(ERRDOS,ERRnoaccess));
1074 outsize = set_message(outbuf,7,0,True);
1075 SSVAL(outbuf,smb_vwv0,fnum);
1076 SSVAL(outbuf,smb_vwv1,fmode);
1077 put_dos_date3(outbuf,smb_vwv2,mtime);
1078 SIVAL(outbuf,smb_vwv4,size);
1079 SSVAL(outbuf,smb_vwv6,rmode);
1081 if (lp_fake_oplocks(SNUM(cnum))) {
1082 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1085 return(outsize);
1089 /****************************************************************************
1090 reply to an open and X
1091 ****************************************************************************/
1092 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1094 pstring fname;
1095 int cnum = SVAL(inbuf,smb_tid);
1096 int fnum = -1;
1097 int smb_mode = SVAL(inbuf,smb_vwv3);
1098 int smb_attr = SVAL(inbuf,smb_vwv5);
1099 BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
1100 #if 0
1101 int open_flags = SVAL(inbuf,smb_vwv2);
1102 int smb_sattr = SVAL(inbuf,smb_vwv4);
1103 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1104 #endif
1105 int smb_ofun = SVAL(inbuf,smb_vwv8);
1106 int unixmode;
1107 int size=0,fmode=0,mtime=0,rmode=0;
1108 struct stat sbuf;
1109 int smb_action = 0;
1110 BOOL bad_path = False;
1112 /* If it's an IPC, pass off the pipe handler. */
1113 if (IS_IPC(cnum))
1114 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1116 /* XXXX we need to handle passed times, sattr and flags */
1118 strcpy(fname,smb_buf(inbuf));
1119 unix_convert(fname,cnum,0,&bad_path);
1121 fnum = find_free_file();
1122 if (fnum < 0)
1123 return(ERROR(ERRSRV,ERRnofids));
1125 if (!check_name(fname,cnum))
1127 if((errno == ENOENT) && bad_path)
1129 unix_ERR_class = ERRDOS;
1130 unix_ERR_code = ERRbadpath;
1132 return(UNIXERROR(ERRDOS,ERRnoaccess));
1135 unixmode = unix_mode(cnum,smb_attr | aARCH);
1137 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1138 &rmode,&smb_action);
1140 if (!Files[fnum].open)
1142 if((errno == ENOENT) && bad_path)
1144 unix_ERR_class = ERRDOS;
1145 unix_ERR_code = ERRbadpath;
1147 return(UNIXERROR(ERRDOS,ERRnoaccess));
1150 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1151 close_file(fnum);
1152 return(ERROR(ERRDOS,ERRnoaccess));
1155 size = sbuf.st_size;
1156 fmode = dos_mode(cnum,fname,&sbuf);
1157 mtime = sbuf.st_mtime;
1158 if (fmode & aDIR) {
1159 close_file(fnum);
1160 return(ERROR(ERRDOS,ERRnoaccess));
1163 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1164 smb_action |= (1<<15);
1167 set_message(outbuf,15,0,True);
1168 SSVAL(outbuf,smb_vwv2,fnum);
1169 SSVAL(outbuf,smb_vwv3,fmode);
1170 put_dos_date3(outbuf,smb_vwv4,mtime);
1171 SIVAL(outbuf,smb_vwv6,size);
1172 SSVAL(outbuf,smb_vwv8,rmode);
1173 SSVAL(outbuf,smb_vwv11,smb_action);
1175 chain_fnum = fnum;
1177 return chain_reply(inbuf,outbuf,length,bufsize);
1181 /****************************************************************************
1182 reply to a SMBulogoffX
1183 ****************************************************************************/
1184 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1186 uint16 vuid = SVAL(inbuf,smb_uid);
1187 user_struct *vuser = get_valid_user_struct(vuid);
1189 if(vuser == 0) {
1190 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1193 /* in user level security we are supposed to close any files
1194 open by this user */
1195 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1196 int i;
1197 for (i=0;i<MAX_OPEN_FILES;i++)
1198 if (Files[i].uid == vuser->uid && Files[i].open) {
1199 close_file(i);
1203 invalidate_vuid(vuid);
1205 set_message(outbuf,2,0,True);
1207 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1209 return chain_reply(inbuf,outbuf,length,bufsize);
1213 /****************************************************************************
1214 reply to a mknew or a create
1215 ****************************************************************************/
1216 int reply_mknew(char *inbuf,char *outbuf)
1218 pstring fname;
1219 int cnum,com;
1220 int fnum = -1;
1221 int outsize = 0;
1222 int createmode;
1223 mode_t unixmode;
1224 int ofun = 0;
1225 BOOL bad_path = False;
1227 com = SVAL(inbuf,smb_com);
1228 cnum = SVAL(inbuf,smb_tid);
1230 createmode = SVAL(inbuf,smb_vwv0);
1231 strcpy(fname,smb_buf(inbuf)+1);
1232 unix_convert(fname,cnum,0,&bad_path);
1234 if (createmode & aVOLID)
1236 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1239 unixmode = unix_mode(cnum,createmode);
1241 fnum = find_free_file();
1242 if (fnum < 0)
1243 return(ERROR(ERRSRV,ERRnofids));
1245 if (!check_name(fname,cnum))
1247 if((errno == ENOENT) && bad_path)
1249 unix_ERR_class = ERRDOS;
1250 unix_ERR_code = ERRbadpath;
1252 return(UNIXERROR(ERRDOS,ERRnoaccess));
1255 if(com == SMBmknew)
1257 /* We should fail if file exists. */
1258 ofun = 0x10;
1260 else
1262 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1263 ofun = 0x12;
1266 /* Open file in dos compatibility share mode. */
1267 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL);
1269 if (!Files[fnum].open)
1271 if((errno == ENOENT) && bad_path)
1273 unix_ERR_class = ERRDOS;
1274 unix_ERR_code = ERRbadpath;
1276 return(UNIXERROR(ERRDOS,ERRnoaccess));
1279 outsize = set_message(outbuf,1,0,True);
1280 SSVAL(outbuf,smb_vwv0,fnum);
1282 if (lp_fake_oplocks(SNUM(cnum))) {
1283 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1286 DEBUG(2,("new file %s\n",fname));
1287 DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
1289 return(outsize);
1293 /****************************************************************************
1294 reply to a create temporary file
1295 ****************************************************************************/
1296 int reply_ctemp(char *inbuf,char *outbuf)
1298 pstring fname;
1299 pstring fname2;
1300 int cnum;
1301 int fnum = -1;
1302 int outsize = 0;
1303 int createmode;
1304 mode_t unixmode;
1305 BOOL bad_path = False;
1307 cnum = SVAL(inbuf,smb_tid);
1308 createmode = SVAL(inbuf,smb_vwv0);
1309 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1310 unix_convert(fname,cnum,0,&bad_path);
1312 unixmode = unix_mode(cnum,createmode);
1314 fnum = find_free_file();
1315 if (fnum < 0)
1316 return(ERROR(ERRSRV,ERRnofids));
1318 if (!check_name(fname,cnum))
1320 if((errno == ENOENT) && bad_path)
1322 unix_ERR_class = ERRDOS;
1323 unix_ERR_code = ERRbadpath;
1325 return(UNIXERROR(ERRDOS,ERRnoaccess));
1328 strcpy(fname2,(char *)mktemp(fname));
1330 /* Open file in dos compatibility share mode. */
1331 /* We should fail if file exists. */
1332 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL);
1334 if (!Files[fnum].open)
1336 if((errno == ENOENT) && bad_path)
1338 unix_ERR_class = ERRDOS;
1339 unix_ERR_code = ERRbadpath;
1341 return(UNIXERROR(ERRDOS,ERRnoaccess));
1344 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1345 SSVAL(outbuf,smb_vwv0,fnum);
1346 CVAL(smb_buf(outbuf),0) = 4;
1347 strcpy(smb_buf(outbuf) + 1,fname2);
1349 if (lp_fake_oplocks(SNUM(cnum))) {
1350 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1353 DEBUG(2,("created temp file %s\n",fname2));
1354 DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
1356 return(outsize);
1360 /*******************************************************************
1361 check if a user is allowed to delete a file
1362 ********************************************************************/
1363 static BOOL can_delete(char *fname,int cnum,int dirtype)
1365 struct stat sbuf;
1366 int fmode;
1368 if (!CAN_WRITE(cnum)) return(False);
1370 if (sys_lstat(fname,&sbuf) != 0) return(False);
1371 fmode = dos_mode(cnum,fname,&sbuf);
1372 if (fmode & aDIR) return(False);
1373 if (!lp_delete_readonly(SNUM(cnum))) {
1374 if (fmode & aRONLY) return(False);
1376 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1377 return(False);
1378 if (!check_file_sharing(cnum,fname)) return(False);
1379 return(True);
1382 /****************************************************************************
1383 reply to a unlink
1384 ****************************************************************************/
1385 int reply_unlink(char *inbuf,char *outbuf)
1387 int outsize = 0;
1388 pstring name;
1389 int cnum;
1390 int dirtype;
1391 pstring directory;
1392 pstring mask;
1393 char *p;
1394 int count=0;
1395 int error = ERRnoaccess;
1396 BOOL has_wild;
1397 BOOL exists=False;
1398 BOOL bad_path = False;
1400 *directory = *mask = 0;
1402 cnum = SVAL(inbuf,smb_tid);
1403 dirtype = SVAL(inbuf,smb_vwv0);
1405 strcpy(name,smb_buf(inbuf) + 1);
1407 DEBUG(3,("reply_unlink : %s\n",name));
1409 unix_convert(name,cnum,0,&bad_path);
1411 p = strrchr(name,'/');
1412 if (!p) {
1413 strcpy(directory,"./");
1414 strcpy(mask,name);
1415 } else {
1416 *p = 0;
1417 strcpy(directory,name);
1418 strcpy(mask,p+1);
1421 if (is_mangled(mask))
1422 check_mangled_stack(mask);
1424 has_wild = strchr(mask,'*') || strchr(mask,'?');
1426 if (!has_wild) {
1427 strcat(directory,"/");
1428 strcat(directory,mask);
1429 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1430 if (!count) exists = file_exist(directory,NULL);
1431 } else {
1432 void *dirptr = NULL;
1433 char *dname;
1435 if (check_name(directory,cnum))
1436 dirptr = OpenDir(cnum, directory, True);
1438 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1439 the pattern matches against the long name, otherwise the short name
1440 We don't implement this yet XXXX
1443 if (dirptr)
1445 error = ERRbadfile;
1447 if (strequal(mask,"????????.???"))
1448 strcpy(mask,"*");
1450 while ((dname = ReadDirName(dirptr)))
1452 pstring fname;
1453 strcpy(fname,dname);
1455 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1457 error = ERRnoaccess;
1458 sprintf(fname,"%s/%s",directory,dname);
1459 if (!can_delete(fname,cnum,dirtype)) continue;
1460 if (!sys_unlink(fname)) count++;
1461 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1463 CloseDir(dirptr);
1467 if (count == 0) {
1468 if (exists)
1469 return(ERROR(ERRDOS,error));
1470 else
1472 if((errno == ENOENT) && bad_path)
1474 unix_ERR_class = ERRDOS;
1475 unix_ERR_code = ERRbadpath;
1477 return(UNIXERROR(ERRDOS,error));
1481 outsize = set_message(outbuf,0,0,True);
1483 return(outsize);
1487 /****************************************************************************
1488 reply to a readbraw (core+ protocol)
1489 ****************************************************************************/
1490 int reply_readbraw(char *inbuf, char *outbuf)
1492 int cnum,maxcount,mincount,fnum;
1493 int nread = 0;
1494 uint32 startpos;
1495 char *header = outbuf;
1496 int ret=0;
1497 int fd;
1498 char *fname;
1500 cnum = SVAL(inbuf,smb_tid);
1501 fnum = GETFNUM(inbuf,smb_vwv0);
1503 startpos = IVAL(inbuf,smb_vwv1);
1504 maxcount = SVAL(inbuf,smb_vwv3);
1505 mincount = SVAL(inbuf,smb_vwv4);
1507 /* ensure we don't overrun the packet size */
1508 maxcount = MIN(65535,maxcount);
1509 maxcount = MAX(mincount,maxcount);
1511 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1513 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1514 _smb_setlen(header,0);
1515 transfer_file(0,Client,0,header,4,0);
1516 return(-1);
1518 else
1520 fd = Files[fnum].fd_ptr->fd;
1521 fname = Files[fnum].name;
1525 if (!is_locked(fnum,cnum,maxcount,startpos))
1527 int size = Files[fnum].size;
1528 int sizeneeded = startpos + maxcount;
1530 if (size < sizeneeded) {
1531 struct stat st;
1532 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1533 size = st.st_size;
1534 if (!Files[fnum].can_write)
1535 Files[fnum].size = size;
1538 nread = MIN(maxcount,(int)(size - startpos));
1541 if (nread < mincount)
1542 nread = 0;
1544 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1545 timestring(),
1546 fnum,cnum,startpos,
1547 maxcount,mincount,nread));
1549 #if UNSAFE_READRAW
1551 int predict=0;
1552 _smb_setlen(header,nread);
1554 if (!Files[fnum].can_write)
1555 predict = read_predict(fd,startpos,header+4,NULL,nread);
1557 if ((nread-predict) > 0)
1558 seek_file(fnum,startpos + predict);
1560 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1561 startpos+predict);
1564 if (ret != nread+4)
1565 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1566 fname,startpos,nread,ret));
1568 #else
1569 ret = read_file(fnum,header+4,startpos,nread);
1570 if (ret < mincount) ret = 0;
1572 _smb_setlen(header,ret);
1573 transfer_file(0,Client,0,header,4+ret,0);
1574 #endif
1576 DEBUG(5,("readbraw finished\n"));
1577 return -1;
1581 /****************************************************************************
1582 reply to a lockread (core+ protocol)
1583 ****************************************************************************/
1584 int reply_lockread(char *inbuf,char *outbuf)
1586 int cnum,fnum;
1587 int nread = -1;
1588 char *data;
1589 int outsize = 0;
1590 uint32 startpos, numtoread;
1591 int eclass;
1592 uint32 ecode;
1594 cnum = SVAL(inbuf,smb_tid);
1595 fnum = GETFNUM(inbuf,smb_vwv0);
1597 CHECK_FNUM(fnum,cnum);
1598 CHECK_READ(fnum);
1599 CHECK_ERROR(fnum);
1601 numtoread = SVAL(inbuf,smb_vwv1);
1602 startpos = IVAL(inbuf,smb_vwv2);
1604 outsize = set_message(outbuf,5,3,True);
1605 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1606 data = smb_buf(outbuf) + 3;
1608 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1609 return (ERROR(eclass,ecode));
1611 nread = read_file(fnum,data,startpos,numtoread);
1613 if (nread < 0)
1614 return(UNIXERROR(ERRDOS,ERRnoaccess));
1616 outsize += nread;
1617 SSVAL(outbuf,smb_vwv0,nread);
1618 SSVAL(outbuf,smb_vwv5,nread+3);
1619 SSVAL(smb_buf(outbuf),1,nread);
1621 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1623 return(outsize);
1627 /****************************************************************************
1628 reply to a read
1629 ****************************************************************************/
1630 int reply_read(char *inbuf,char *outbuf)
1632 int cnum,numtoread,fnum;
1633 int nread = 0;
1634 char *data;
1635 uint32 startpos;
1636 int outsize = 0;
1638 cnum = SVAL(inbuf,smb_tid);
1639 fnum = GETFNUM(inbuf,smb_vwv0);
1641 CHECK_FNUM(fnum,cnum);
1642 CHECK_READ(fnum);
1643 CHECK_ERROR(fnum);
1645 numtoread = SVAL(inbuf,smb_vwv1);
1646 startpos = IVAL(inbuf,smb_vwv2);
1648 outsize = set_message(outbuf,5,3,True);
1649 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1650 data = smb_buf(outbuf) + 3;
1652 if (is_locked(fnum,cnum,numtoread,startpos))
1653 return(ERROR(ERRDOS,ERRlock));
1655 if (numtoread > 0)
1656 nread = read_file(fnum,data,startpos,numtoread);
1658 if (nread < 0)
1659 return(UNIXERROR(ERRDOS,ERRnoaccess));
1661 outsize += nread;
1662 SSVAL(outbuf,smb_vwv0,nread);
1663 SSVAL(outbuf,smb_vwv5,nread+3);
1664 CVAL(smb_buf(outbuf),0) = 1;
1665 SSVAL(smb_buf(outbuf),1,nread);
1667 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1669 return(outsize);
1673 /****************************************************************************
1674 reply to a read and X
1675 ****************************************************************************/
1676 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1678 int fnum = GETFNUM(inbuf,smb_vwv2);
1679 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1680 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1681 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1682 int cnum;
1683 int nread = -1;
1684 char *data;
1685 BOOL ok = False;
1687 cnum = SVAL(inbuf,smb_tid);
1689 CHECK_FNUM(fnum,cnum);
1690 CHECK_READ(fnum);
1691 CHECK_ERROR(fnum);
1693 set_message(outbuf,12,0,True);
1694 data = smb_buf(outbuf);
1696 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1697 return(ERROR(ERRDOS,ERRlock));
1698 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1699 ok = True;
1701 if (nread < 0)
1702 return(UNIXERROR(ERRDOS,ERRnoaccess));
1704 SSVAL(outbuf,smb_vwv5,nread);
1705 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1706 SSVAL(smb_buf(outbuf),-2,nread);
1708 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1709 timestring(),fnum,cnum,
1710 smb_mincnt,smb_maxcnt,nread));
1712 chain_fnum = fnum;
1714 return chain_reply(inbuf,outbuf,length,bufsize);
1718 /****************************************************************************
1719 reply to a writebraw (core+ or LANMAN1.0 protocol)
1720 ****************************************************************************/
1721 int reply_writebraw(char *inbuf,char *outbuf)
1723 int nwritten=0;
1724 int total_written=0;
1725 int numtowrite=0;
1726 int cnum,fnum;
1727 int outsize = 0;
1728 long startpos;
1729 char *data=NULL;
1730 BOOL write_through;
1731 int tcount;
1733 cnum = SVAL(inbuf,smb_tid);
1734 fnum = GETFNUM(inbuf,smb_vwv0);
1736 CHECK_FNUM(fnum,cnum);
1737 CHECK_WRITE(fnum);
1738 CHECK_ERROR(fnum);
1740 tcount = IVAL(inbuf,smb_vwv1);
1741 startpos = IVAL(inbuf,smb_vwv3);
1742 write_through = BITSETW(inbuf+smb_vwv7,0);
1744 /* We have to deal with slightly different formats depending
1745 on whether we are using the core+ or lanman1.0 protocol */
1746 if(Protocol <= PROTOCOL_COREPLUS) {
1747 numtowrite = SVAL(smb_buf(inbuf),-2);
1748 data = smb_buf(inbuf);
1749 } else {
1750 numtowrite = SVAL(inbuf,smb_vwv10);
1751 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1754 /* force the error type */
1755 CVAL(inbuf,smb_com) = SMBwritec;
1756 CVAL(outbuf,smb_com) = SMBwritec;
1758 if (is_locked(fnum,cnum,tcount,startpos))
1759 return(ERROR(ERRDOS,ERRlock));
1761 if (seek_file(fnum,startpos) != startpos)
1762 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1764 if (numtowrite>0)
1765 nwritten = write_file(fnum,data,numtowrite);
1767 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1768 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1770 if (nwritten < numtowrite)
1771 return(UNIXERROR(ERRHRD,ERRdiskfull));
1773 total_written = nwritten;
1775 /* Return a message to the redirector to tell it
1776 to send more bytes */
1777 CVAL(outbuf,smb_com) = SMBwritebraw;
1778 SSVALS(outbuf,smb_vwv0,-1);
1779 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1780 send_smb(Client,outbuf);
1782 /* Now read the raw data into the buffer and write it */
1783 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1784 exit_server("secondary writebraw failed");
1787 /* Even though this is not an smb message, smb_len
1788 returns the generic length of an smb message */
1789 numtowrite = smb_len(inbuf);
1791 if (tcount > nwritten+numtowrite) {
1792 DEBUG(3,("Client overestimated the write %d %d %d\n",
1793 tcount,nwritten,numtowrite));
1796 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1797 startpos+nwritten);
1798 total_written += nwritten;
1800 /* Set up outbuf to return the correct return */
1801 outsize = set_message(outbuf,1,0,True);
1802 CVAL(outbuf,smb_com) = SMBwritec;
1803 SSVAL(outbuf,smb_vwv0,total_written);
1805 if (nwritten < numtowrite) {
1806 CVAL(outbuf,smb_rcls) = ERRHRD;
1807 SSVAL(outbuf,smb_err,ERRdiskfull);
1810 if (lp_syncalways(SNUM(cnum)) || write_through)
1811 sync_file(fnum);
1813 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1814 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1816 /* we won't return a status if write through is not selected - this
1817 follows what WfWg does */
1818 if (!write_through && total_written==tcount)
1819 return(-1);
1821 return(outsize);
1825 /****************************************************************************
1826 reply to a writeunlock (core+)
1827 ****************************************************************************/
1828 int reply_writeunlock(char *inbuf,char *outbuf)
1830 int cnum,fnum;
1831 int nwritten = -1;
1832 int outsize = 0;
1833 char *data;
1834 uint32 numtowrite,startpos;
1835 int eclass;
1836 uint32 ecode;
1838 cnum = SVAL(inbuf,smb_tid);
1839 fnum = GETFNUM(inbuf,smb_vwv0);
1841 CHECK_FNUM(fnum,cnum);
1842 CHECK_WRITE(fnum);
1843 CHECK_ERROR(fnum);
1845 numtowrite = SVAL(inbuf,smb_vwv1);
1846 startpos = IVAL(inbuf,smb_vwv2);
1847 data = smb_buf(inbuf) + 3;
1849 if (is_locked(fnum,cnum,numtowrite,startpos))
1850 return(ERROR(ERRDOS,ERRlock));
1852 seek_file(fnum,startpos);
1854 /* The special X/Open SMB protocol handling of
1855 zero length writes is *NOT* done for
1856 this call */
1857 if(numtowrite == 0)
1858 nwritten = 0;
1859 else
1860 nwritten = write_file(fnum,data,numtowrite);
1862 if (lp_syncalways(SNUM(cnum)))
1863 sync_file(fnum);
1865 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1866 return(UNIXERROR(ERRDOS,ERRnoaccess));
1868 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1869 return(ERROR(eclass,ecode));
1871 outsize = set_message(outbuf,1,0,True);
1873 SSVAL(outbuf,smb_vwv0,nwritten);
1875 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1876 timestring(),fnum,cnum,numtowrite,nwritten));
1878 return(outsize);
1882 /****************************************************************************
1883 reply to a write
1884 ****************************************************************************/
1885 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1887 int cnum,numtowrite,fnum;
1888 int nwritten = -1;
1889 int outsize = 0;
1890 int startpos;
1891 char *data;
1893 dum1 = dum2 = 0;
1896 cnum = SVAL(inbuf,smb_tid);
1897 fnum = GETFNUM(inbuf,smb_vwv0);
1899 CHECK_FNUM(fnum,cnum);
1900 CHECK_WRITE(fnum);
1901 CHECK_ERROR(fnum);
1903 numtowrite = SVAL(inbuf,smb_vwv1);
1904 startpos = IVAL(inbuf,smb_vwv2);
1905 data = smb_buf(inbuf) + 3;
1907 if (is_locked(fnum,cnum,numtowrite,startpos))
1908 return(ERROR(ERRDOS,ERRlock));
1910 seek_file(fnum,startpos);
1912 /* X/Open SMB protocol says that if smb_vwv1 is
1913 zero then the file size should be extended or
1914 truncated to the size given in smb_vwv[2-3] */
1915 if(numtowrite == 0)
1916 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
1917 else
1918 nwritten = write_file(fnum,data,numtowrite);
1920 if (lp_syncalways(SNUM(cnum)))
1921 sync_file(fnum);
1923 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1924 return(UNIXERROR(ERRDOS,ERRnoaccess));
1926 outsize = set_message(outbuf,1,0,True);
1928 SSVAL(outbuf,smb_vwv0,nwritten);
1930 if (nwritten < numtowrite) {
1931 CVAL(outbuf,smb_rcls) = ERRHRD;
1932 SSVAL(outbuf,smb_err,ERRdiskfull);
1935 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1937 return(outsize);
1941 /****************************************************************************
1942 reply to a write and X
1943 ****************************************************************************/
1944 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1946 int fnum = GETFNUM(inbuf,smb_vwv2);
1947 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1948 int smb_dsize = SVAL(inbuf,smb_vwv10);
1949 int smb_doff = SVAL(inbuf,smb_vwv11);
1950 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1951 int cnum;
1952 int nwritten = -1;
1953 char *data;
1955 cnum = SVAL(inbuf,smb_tid);
1957 CHECK_FNUM(fnum,cnum);
1958 CHECK_WRITE(fnum);
1959 CHECK_ERROR(fnum);
1961 data = smb_base(inbuf) + smb_doff;
1963 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1964 return(ERROR(ERRDOS,ERRlock));
1966 seek_file(fnum,smb_offs);
1968 /* X/Open SMB protocol says that, unlike SMBwrite
1969 if the length is zero then NO truncation is
1970 done, just a write of zero. To truncate a file,
1971 use SMBwrite. */
1972 if(smb_dsize == 0)
1973 nwritten = 0;
1974 else
1975 nwritten = write_file(fnum,data,smb_dsize);
1977 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1978 return(UNIXERROR(ERRDOS,ERRnoaccess));
1980 set_message(outbuf,6,0,True);
1982 SSVAL(outbuf,smb_vwv2,nwritten);
1984 if (nwritten < smb_dsize) {
1985 CVAL(outbuf,smb_rcls) = ERRHRD;
1986 SSVAL(outbuf,smb_err,ERRdiskfull);
1989 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1991 chain_fnum = fnum;
1993 if (lp_syncalways(SNUM(cnum)) || write_through)
1994 sync_file(fnum);
1996 return chain_reply(inbuf,outbuf,length,bufsize);
2000 /****************************************************************************
2001 reply to a lseek
2002 ****************************************************************************/
2003 int reply_lseek(char *inbuf,char *outbuf)
2005 int cnum,fnum;
2006 uint32 startpos;
2007 int32 res= -1;
2008 int mode,umode;
2009 int outsize = 0;
2011 cnum = SVAL(inbuf,smb_tid);
2012 fnum = GETFNUM(inbuf,smb_vwv0);
2014 CHECK_FNUM(fnum,cnum);
2015 CHECK_ERROR(fnum);
2017 mode = SVAL(inbuf,smb_vwv1) & 3;
2018 startpos = IVAL(inbuf,smb_vwv2);
2020 switch (mode & 3)
2022 case 0: umode = SEEK_SET; break;
2023 case 1: umode = SEEK_CUR; break;
2024 case 2: umode = SEEK_END; break;
2025 default:
2026 umode = SEEK_SET; break;
2029 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
2030 Files[fnum].pos = res;
2032 outsize = set_message(outbuf,2,0,True);
2033 SIVALS(outbuf,smb_vwv0,res);
2035 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
2037 return(outsize);
2041 /****************************************************************************
2042 reply to a flush
2043 ****************************************************************************/
2044 int reply_flush(char *inbuf,char *outbuf)
2046 int cnum, fnum;
2047 int outsize = set_message(outbuf,0,0,True);
2049 cnum = SVAL(inbuf,smb_tid);
2050 fnum = GETFNUM(inbuf,smb_vwv0);
2052 if (fnum != 0xFFFF) {
2053 CHECK_FNUM(fnum,cnum);
2054 CHECK_ERROR(fnum);
2057 if (fnum == 0xFFFF)
2059 int i;
2060 for (i=0;i<MAX_OPEN_FILES;i++)
2061 if (OPEN_FNUM(i))
2062 sync_file(i);
2064 else
2065 sync_file(fnum);
2067 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
2068 return(outsize);
2072 /****************************************************************************
2073 reply to a exit
2074 ****************************************************************************/
2075 int reply_exit(char *inbuf,char *outbuf)
2077 int outsize = set_message(outbuf,0,0,True);
2078 DEBUG(3,("%s exit\n",timestring()));
2080 return(outsize);
2084 /****************************************************************************
2085 reply to a close
2086 ****************************************************************************/
2087 int reply_close(char *inbuf,char *outbuf)
2089 int fnum,cnum;
2090 int outsize = 0;
2091 time_t mtime;
2092 int32 eclass = 0, err = 0;
2094 outsize = set_message(outbuf,0,0,True);
2096 cnum = SVAL(inbuf,smb_tid);
2098 fnum = GETFNUM(inbuf,smb_vwv0);
2099 CHECK_FNUM(fnum,cnum);
2101 if(HAS_CACHED_ERROR(fnum)) {
2102 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
2103 err = Files[fnum].wbmpx_ptr->wr_error;
2106 mtime = make_unix_date3(inbuf+smb_vwv1);
2108 /* try and set the date */
2109 set_filetime(Files[fnum].name,mtime);
2111 close_file(fnum);
2113 /* We have a cached error */
2114 if(eclass || err)
2115 return(ERROR(eclass,err));
2117 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2118 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2119 Connections[cnum].num_files_open));
2121 return(outsize);
2125 /****************************************************************************
2126 reply to a writeclose (Core+ protocol)
2127 ****************************************************************************/
2128 int reply_writeclose(char *inbuf,char *outbuf)
2130 int cnum,numtowrite,fnum;
2131 int nwritten = -1;
2132 int outsize = 0;
2133 int startpos;
2134 char *data;
2135 time_t mtime;
2137 cnum = SVAL(inbuf,smb_tid);
2138 fnum = GETFNUM(inbuf,smb_vwv0);
2140 CHECK_FNUM(fnum,cnum);
2141 CHECK_WRITE(fnum);
2142 CHECK_ERROR(fnum);
2144 numtowrite = SVAL(inbuf,smb_vwv1);
2145 startpos = IVAL(inbuf,smb_vwv2);
2146 mtime = make_unix_date3(inbuf+smb_vwv4);
2147 data = smb_buf(inbuf) + 1;
2149 if (is_locked(fnum,cnum,numtowrite,startpos))
2150 return(ERROR(ERRDOS,ERRlock));
2152 seek_file(fnum,startpos);
2154 nwritten = write_file(fnum,data,numtowrite);
2156 set_filetime(Files[fnum].name,mtime);
2158 close_file(fnum);
2160 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2161 timestring(),fnum,cnum,numtowrite,nwritten,
2162 Connections[cnum].num_files_open));
2164 if (nwritten <= 0)
2165 return(UNIXERROR(ERRDOS,ERRnoaccess));
2167 outsize = set_message(outbuf,1,0,True);
2169 SSVAL(outbuf,smb_vwv0,nwritten);
2170 return(outsize);
2174 /****************************************************************************
2175 reply to a lock
2176 ****************************************************************************/
2177 int reply_lock(char *inbuf,char *outbuf)
2179 int fnum,cnum;
2180 int outsize = set_message(outbuf,0,0,True);
2181 uint32 count,offset;
2182 int eclass;
2183 uint32 ecode;
2185 cnum = SVAL(inbuf,smb_tid);
2186 fnum = GETFNUM(inbuf,smb_vwv0);
2188 CHECK_FNUM(fnum,cnum);
2189 CHECK_ERROR(fnum);
2191 count = IVAL(inbuf,smb_vwv1);
2192 offset = IVAL(inbuf,smb_vwv3);
2194 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count));
2196 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2197 return (ERROR(eclass,ecode));
2199 return(outsize);
2203 /****************************************************************************
2204 reply to a unlock
2205 ****************************************************************************/
2206 int reply_unlock(char *inbuf,char *outbuf)
2208 int fnum,cnum;
2209 int outsize = set_message(outbuf,0,0,True);
2210 uint32 count,offset;
2211 int eclass;
2212 uint32 ecode;
2214 cnum = SVAL(inbuf,smb_tid);
2215 fnum = GETFNUM(inbuf,smb_vwv0);
2217 CHECK_FNUM(fnum,cnum);
2218 CHECK_ERROR(fnum);
2220 count = IVAL(inbuf,smb_vwv1);
2221 offset = IVAL(inbuf,smb_vwv3);
2223 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2224 return (ERROR(eclass,ecode));
2226 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count));
2228 return(outsize);
2232 /****************************************************************************
2233 reply to a tdis
2234 ****************************************************************************/
2235 int reply_tdis(char *inbuf,char *outbuf)
2237 int cnum;
2238 int outsize = set_message(outbuf,0,0,True);
2239 uint16 vuid;
2241 cnum = SVAL(inbuf,smb_tid);
2242 vuid = SVAL(inbuf,smb_uid);
2244 if (!OPEN_CNUM(cnum)) {
2245 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2246 return(ERROR(ERRSRV,ERRinvnid));
2249 Connections[cnum].used = False;
2251 close_cnum(cnum,vuid);
2253 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2255 return outsize;
2260 /****************************************************************************
2261 reply to a echo
2262 ****************************************************************************/
2263 int reply_echo(char *inbuf,char *outbuf)
2265 int cnum;
2266 int smb_reverb = SVAL(inbuf,smb_vwv0);
2267 int seq_num;
2268 int data_len = smb_buflen(inbuf);
2269 int outsize = set_message(outbuf,1,data_len,True);
2271 cnum = SVAL(inbuf,smb_tid);
2273 /* According to the latest CIFS spec we shouldn't
2274 care what the TID is.
2277 #if 0
2278 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2280 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2281 return(ERROR(ERRSRV,ERRinvnid));
2283 #endif
2285 /* copy any incoming data back out */
2286 if (data_len > 0)
2287 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2289 if (smb_reverb > 100)
2291 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2292 smb_reverb = 100;
2295 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2297 SSVAL(outbuf,smb_vwv0,seq_num);
2299 smb_setlen(outbuf,outsize - 4);
2301 send_smb(Client,outbuf);
2304 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2306 return -1;
2310 /****************************************************************************
2311 reply to a printopen
2312 ****************************************************************************/
2313 int reply_printopen(char *inbuf,char *outbuf)
2315 pstring fname;
2316 pstring fname2;
2317 int cnum;
2318 int fnum = -1;
2319 int outsize = 0;
2321 *fname = *fname2 = 0;
2323 cnum = SVAL(inbuf,smb_tid);
2325 if (!CAN_PRINT(cnum))
2326 return(ERROR(ERRDOS,ERRnoaccess));
2329 pstring s;
2330 char *p;
2331 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2332 p = s;
2333 while (*p)
2335 if (!(isalnum(*p) || strchr("._-",*p)))
2336 *p = 'X';
2337 p++;
2340 if (strlen(s) > 10) s[10] = 0;
2342 sprintf(fname,"%s.XXXXXX",s);
2345 fnum = find_free_file();
2346 if (fnum < 0)
2347 return(ERROR(ERRSRV,ERRnofids));
2349 strcpy(fname2,(char *)mktemp(fname));
2351 if (!check_name(fname2,cnum))
2352 return(ERROR(ERRDOS,ERRnoaccess));
2354 /* Open for exclusive use, write only. */
2355 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL);
2357 if (!Files[fnum].open)
2358 return(UNIXERROR(ERRDOS,ERRnoaccess));
2360 /* force it to be a print file */
2361 Files[fnum].print_file = True;
2363 outsize = set_message(outbuf,1,0,True);
2364 SSVAL(outbuf,smb_vwv0,fnum);
2366 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2368 return(outsize);
2372 /****************************************************************************
2373 reply to a printclose
2374 ****************************************************************************/
2375 int reply_printclose(char *inbuf,char *outbuf)
2377 int fnum,cnum;
2378 int outsize = set_message(outbuf,0,0,True);
2380 cnum = SVAL(inbuf,smb_tid);
2381 fnum = GETFNUM(inbuf,smb_vwv0);
2383 CHECK_FNUM(fnum,cnum);
2384 CHECK_ERROR(fnum);
2386 if (!CAN_PRINT(cnum))
2387 return(ERROR(ERRDOS,ERRnoaccess));
2389 close_file(fnum);
2391 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2393 return(outsize);
2397 /****************************************************************************
2398 reply to a printqueue
2399 ****************************************************************************/
2400 int reply_printqueue(char *inbuf,char *outbuf)
2402 int cnum;
2403 int outsize = set_message(outbuf,2,3,True);
2404 int max_count = SVAL(inbuf,smb_vwv0);
2405 int start_index = SVAL(inbuf,smb_vwv1);
2406 uint16 vuid;
2408 cnum = SVAL(inbuf,smb_tid);
2409 vuid = SVAL(inbuf,smb_uid);
2411 /* allow checking the queue for anyone */
2412 #if 0
2413 if (!CAN_PRINT(cnum))
2414 return(ERROR(ERRDOS,ERRnoaccess));
2415 #endif
2417 SSVAL(outbuf,smb_vwv0,0);
2418 SSVAL(outbuf,smb_vwv1,0);
2419 CVAL(smb_buf(outbuf),0) = 1;
2420 SSVAL(smb_buf(outbuf),1,0);
2422 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2423 timestring(),cnum,start_index,max_count));
2425 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2427 int i;
2428 cnum = -1;
2430 for (i=0;i<MAX_CONNECTIONS;i++)
2431 if (CAN_PRINT(i) && Connections[i].printer)
2432 cnum = i;
2434 if (cnum == -1)
2435 for (i=0;i<MAX_CONNECTIONS;i++)
2436 if (OPEN_CNUM(i))
2437 cnum = i;
2439 if (!OPEN_CNUM(cnum))
2440 return(ERROR(ERRSRV,ERRinvnid));
2442 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2445 if (!become_user(cnum,vuid))
2446 return(ERROR(ERRSRV,ERRinvnid));
2449 print_queue_struct *queue = NULL;
2450 char *p = smb_buf(outbuf) + 3;
2451 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2452 int num_to_get = ABS(max_count);
2453 int first = (max_count>0?start_index:start_index+max_count+1);
2454 int i;
2456 if (first >= count)
2457 num_to_get = 0;
2458 else
2459 num_to_get = MIN(num_to_get,count-first);
2462 for (i=first;i<first+num_to_get;i++)
2464 put_dos_date2(p,0,queue[i].time);
2465 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2466 SSVAL(p,5,queue[i].job);
2467 SIVAL(p,7,queue[i].size);
2468 CVAL(p,11) = 0;
2469 StrnCpy(p+12,queue[i].user,16);
2470 p += 28;
2473 if (count > 0)
2475 outsize = set_message(outbuf,2,28*count+3,False);
2476 SSVAL(outbuf,smb_vwv0,count);
2477 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2478 CVAL(smb_buf(outbuf),0) = 1;
2479 SSVAL(smb_buf(outbuf),1,28*count);
2482 if (queue) free(queue);
2484 DEBUG(3,("%d entries returned in queue\n",count));
2487 return(outsize);
2491 /****************************************************************************
2492 reply to a printwrite
2493 ****************************************************************************/
2494 int reply_printwrite(char *inbuf,char *outbuf)
2496 int cnum,numtowrite,fnum;
2497 int outsize = set_message(outbuf,0,0,True);
2498 char *data;
2500 cnum = SVAL(inbuf,smb_tid);
2502 if (!CAN_PRINT(cnum))
2503 return(ERROR(ERRDOS,ERRnoaccess));
2505 fnum = GETFNUM(inbuf,smb_vwv0);
2507 CHECK_FNUM(fnum,cnum);
2508 CHECK_WRITE(fnum);
2509 CHECK_ERROR(fnum);
2511 numtowrite = SVAL(smb_buf(inbuf),1);
2512 data = smb_buf(inbuf) + 3;
2514 if (write_file(fnum,data,numtowrite) != numtowrite)
2515 return(UNIXERROR(ERRDOS,ERRnoaccess));
2517 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2519 return(outsize);
2523 /****************************************************************************
2524 reply to a mkdir
2525 ****************************************************************************/
2526 int reply_mkdir(char *inbuf,char *outbuf)
2528 pstring directory;
2529 int cnum;
2530 int outsize,ret= -1;
2531 BOOL bad_path = False;
2533 strcpy(directory,smb_buf(inbuf) + 1);
2534 cnum = SVAL(inbuf,smb_tid);
2535 unix_convert(directory,cnum,0,&bad_path);
2537 if (check_name(directory,cnum))
2538 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2540 if (ret < 0)
2542 if((errno == ENOENT) && bad_path)
2544 unix_ERR_class = ERRDOS;
2545 unix_ERR_code = ERRbadpath;
2547 return(UNIXERROR(ERRDOS,ERRnoaccess));
2550 outsize = set_message(outbuf,0,0,True);
2552 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2554 return(outsize);
2558 /****************************************************************************
2559 reply to a rmdir
2560 ****************************************************************************/
2561 int reply_rmdir(char *inbuf,char *outbuf)
2563 pstring directory;
2564 int cnum;
2565 int outsize = 0;
2566 BOOL ok = False;
2567 BOOL bad_path = False;
2569 cnum = SVAL(inbuf,smb_tid);
2570 strcpy(directory,smb_buf(inbuf) + 1);
2571 unix_convert(directory,cnum,0,&bad_path);
2573 if (check_name(directory,cnum))
2576 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2577 ok = (sys_rmdir(directory) == 0);
2578 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2580 /* Check to see if the only thing in this directory are
2581 vetoed files/directories. If so then delete them and
2582 retry. If we fail to delete any of them (and we *don't*
2583 do a recursive delete) then fail the rmdir. */
2584 BOOL all_veto_files = True;
2585 char *dname;
2586 void *dirptr = OpenDir(cnum, directory, False);
2588 if(dirptr != NULL)
2590 int dirpos = TellDir(dirptr);
2591 while ((dname = ReadDirName(dirptr)))
2593 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2594 continue;
2595 if(!IS_VETO_PATH(cnum, dname))
2597 all_veto_files = False;
2598 break;
2601 if(all_veto_files)
2603 SeekDir(dirptr,dirpos);
2604 while ((dname = ReadDirName(dirptr)))
2606 pstring fullname;
2607 struct stat st;
2609 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2610 continue;
2612 /* Construct the full name. */
2613 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2615 errno = ENOMEM;
2616 break;
2618 strcpy(fullname, directory);
2619 strcat(fullname, "/");
2620 strcat(fullname, dname);
2622 if(sys_lstat(fullname, &st) != 0)
2623 break;
2624 if(st.st_mode & S_IFDIR)
2626 if(sys_rmdir(fullname) != 0)
2627 break;
2629 else if(sys_unlink(fullname) != 0)
2630 break;
2632 CloseDir(dirptr);
2633 /* Retry the rmdir */
2634 ok = (sys_rmdir(directory) == 0);
2636 else
2637 CloseDir(dirptr);
2639 else
2640 errno = ENOTEMPTY;
2643 if (!ok)
2644 DEBUG(3,("couldn't remove directory %s : %s\n",
2645 directory,strerror(errno)));
2648 if (!ok)
2650 if((errno == ENOENT) && bad_path)
2652 unix_ERR_class = ERRDOS;
2653 unix_ERR_code = ERRbadpath;
2655 return(UNIXERROR(ERRDOS,ERRbadpath));
2658 outsize = set_message(outbuf,0,0,True);
2660 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2662 return(outsize);
2666 /*******************************************************************
2667 resolve wildcards in a filename rename
2668 ********************************************************************/
2669 static BOOL resolve_wildcards(char *name1,char *name2)
2671 fstring root1,root2;
2672 fstring ext1,ext2;
2673 char *p,*p2;
2675 name1 = strrchr(name1,'/');
2676 name2 = strrchr(name2,'/');
2678 if (!name1 || !name2) return(False);
2680 strcpy(root1,name1);
2681 strcpy(root2,name2);
2682 p = strrchr(root1,'.');
2683 if (p) {
2684 *p = 0;
2685 strcpy(ext1,p+1);
2686 } else {
2687 strcpy(ext1,"");
2689 p = strrchr(root2,'.');
2690 if (p) {
2691 *p = 0;
2692 strcpy(ext2,p+1);
2693 } else {
2694 strcpy(ext2,"");
2697 p = root1;
2698 p2 = root2;
2699 while (*p2) {
2700 if (*p2 == '?') {
2701 *p2 = *p;
2702 p2++;
2703 } else {
2704 p2++;
2706 if (*p) p++;
2709 p = ext1;
2710 p2 = ext2;
2711 while (*p2) {
2712 if (*p2 == '?') {
2713 *p2 = *p;
2714 p2++;
2715 } else {
2716 p2++;
2718 if (*p) p++;
2721 strcpy(name2,root2);
2722 if (ext2[0]) {
2723 strcat(name2,".");
2724 strcat(name2,ext2);
2727 return(True);
2730 /*******************************************************************
2731 check if a user is allowed to rename a file
2732 ********************************************************************/
2733 static BOOL can_rename(char *fname,int cnum)
2735 struct stat sbuf;
2737 if (!CAN_WRITE(cnum)) return(False);
2739 if (sys_lstat(fname,&sbuf) != 0) return(False);
2740 if (!check_file_sharing(cnum,fname)) return(False);
2742 return(True);
2745 /****************************************************************************
2746 reply to a mv
2747 ****************************************************************************/
2748 int reply_mv(char *inbuf,char *outbuf)
2750 int outsize = 0;
2751 pstring name;
2752 int cnum;
2753 pstring directory;
2754 pstring mask,newname;
2755 pstring newname_last_component;
2756 char *p;
2757 int count=0;
2758 int error = ERRnoaccess;
2759 BOOL has_wild;
2760 BOOL exists=False;
2761 BOOL bad_path1 = False;
2762 BOOL bad_path2 = False;
2764 *directory = *mask = 0;
2766 cnum = SVAL(inbuf,smb_tid);
2768 strcpy(name,smb_buf(inbuf) + 1);
2769 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2771 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2773 unix_convert(name,cnum,0,&bad_path1);
2774 unix_convert(newname,cnum,newname_last_component,&bad_path2);
2777 * Split the old name into directory and last component
2778 * strings. Note that unix_convert may have stripped off a
2779 * leading ./ from both name and newname if the rename is
2780 * at the root of the share. We need to make sure either both
2781 * name and newname contain a / character or neither of them do
2782 * as this is checked in resolve_wildcards().
2785 p = strrchr(name,'/');
2786 if (!p) {
2787 strcpy(directory,".");
2788 strcpy(mask,name);
2789 } else {
2790 *p = 0;
2791 strcpy(directory,name);
2792 strcpy(mask,p+1);
2793 *p = '/'; /* Replace needed for exceptional test below. */
2796 if (is_mangled(mask))
2797 check_mangled_stack(mask);
2799 has_wild = strchr(mask,'*') || strchr(mask,'?');
2801 if (!has_wild) {
2802 BOOL is_short_name = is_8_3(name, True);
2804 /* Add a terminating '/' to the directory name. */
2805 strcat(directory,"/");
2806 strcat(directory,mask);
2808 /* Ensure newname contains a '/' also */
2809 if(strrchr(newname,'/') == 0) {
2810 pstring tmpstr;
2812 strcpy(tmpstr, "./");
2813 strcat(tmpstr, newname);
2814 strcpy(newname, tmpstr);
2817 DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
2818 case_sensitive, case_preserve, short_case_preserve, directory,
2819 newname, newname_last_component, is_short_name));
2822 * Check for special case with case preserving and not
2823 * case sensitive, if directory and newname are identical,
2824 * and the old last component differs from the original
2825 * last component only by case, then we should allow
2826 * the rename (user is trying to change the case of the
2827 * filename).
2829 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
2830 ((short_case_preserve == True) && (is_short_name == True))) &&
2831 strcsequal(directory, newname)) {
2832 pstring newname_modified_last_component;
2835 * Get the last component of the modified name.
2836 * Note that we guarantee that newname contains a '/'
2837 * character above.
2839 p = strrchr(newname,'/');
2840 strcpy(newname_modified_last_component,p+1);
2842 if(strcsequal(newname_modified_last_component,
2843 newname_last_component) == False) {
2845 * Replace the modified last component with
2846 * the original.
2848 strcpy(p+1, newname_last_component);
2852 if (resolve_wildcards(directory,newname) &&
2853 can_rename(directory,cnum) &&
2854 !file_exist(newname,NULL) &&
2855 !sys_rename(directory,newname)) count++;
2857 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
2858 directory,newname));
2860 if (!count) exists = file_exist(directory,NULL);
2861 if (!count && exists && file_exist(newname,NULL)) {
2862 exists = True;
2863 error = 183;
2865 } else {
2866 void *dirptr = NULL;
2867 char *dname;
2868 pstring destname;
2870 if (check_name(directory,cnum))
2871 dirptr = OpenDir(cnum, directory, True);
2873 if (dirptr)
2875 error = ERRbadfile;
2877 if (strequal(mask,"????????.???"))
2878 strcpy(mask,"*");
2880 while ((dname = ReadDirName(dirptr)))
2882 pstring fname;
2883 strcpy(fname,dname);
2885 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2887 error = ERRnoaccess;
2888 sprintf(fname,"%s/%s",directory,dname);
2889 if (!can_rename(fname,cnum)) continue;
2890 strcpy(destname,newname);
2892 if (!resolve_wildcards(fname,destname)) continue;
2894 if (file_exist(destname,NULL)) {
2895 error = 183;
2896 continue;
2898 if (!sys_rename(fname,destname)) count++;
2899 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2901 CloseDir(dirptr);
2905 if (count == 0) {
2906 if (exists)
2907 return(ERROR(ERRDOS,error));
2908 else
2910 if((errno == ENOENT) && (bad_path1 || bad_path2))
2912 unix_ERR_class = ERRDOS;
2913 unix_ERR_code = ERRbadpath;
2915 return(UNIXERROR(ERRDOS,error));
2919 outsize = set_message(outbuf,0,0,True);
2921 return(outsize);
2924 /*******************************************************************
2925 copy a file as part of a reply_copy
2926 ******************************************************************/
2927 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2928 int count,BOOL target_is_directory)
2930 int Access,action;
2931 struct stat st;
2932 int ret=0;
2933 int fnum1,fnum2;
2934 pstring dest;
2936 strcpy(dest,dest1);
2937 if (target_is_directory) {
2938 char *p = strrchr(src,'/');
2939 if (p)
2940 p++;
2941 else
2942 p = src;
2943 strcat(dest,"/");
2944 strcat(dest,p);
2947 if (!file_exist(src,&st)) return(False);
2949 fnum1 = find_free_file();
2950 if (fnum1<0) return(False);
2951 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2952 1,0,&Access,&action);
2954 if (!Files[fnum1].open) return(False);
2956 if (!target_is_directory && count)
2957 ofun = 1;
2959 fnum2 = find_free_file();
2960 if (fnum2<0) {
2961 close_file(fnum1);
2962 return(False);
2964 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2965 ofun,st.st_mode,&Access,&action);
2967 if (!Files[fnum2].open) {
2968 close_file(fnum1);
2969 return(False);
2972 if ((ofun&3) == 1) {
2973 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
2976 if (st.st_size)
2977 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
2979 close_file(fnum1);
2980 close_file(fnum2);
2982 return(ret == st.st_size);
2987 /****************************************************************************
2988 reply to a file copy.
2989 ****************************************************************************/
2990 int reply_copy(char *inbuf,char *outbuf)
2992 int outsize = 0;
2993 pstring name;
2994 int cnum;
2995 pstring directory;
2996 pstring mask,newname;
2997 char *p;
2998 int count=0;
2999 int error = ERRnoaccess;
3000 BOOL has_wild;
3001 BOOL exists=False;
3002 int tid2 = SVAL(inbuf,smb_vwv0);
3003 int ofun = SVAL(inbuf,smb_vwv1);
3004 int flags = SVAL(inbuf,smb_vwv2);
3005 BOOL target_is_directory=False;
3006 BOOL bad_path1 = False;
3007 BOOL bad_path2 = False;
3009 *directory = *mask = 0;
3011 cnum = SVAL(inbuf,smb_tid);
3013 strcpy(name,smb_buf(inbuf));
3014 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
3016 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3018 if (tid2 != cnum) {
3019 /* can't currently handle inter share copies XXXX */
3020 DEBUG(3,("Rejecting inter-share copy\n"));
3021 return(ERROR(ERRSRV,ERRinvdevice));
3024 unix_convert(name,cnum,0,&bad_path1);
3025 unix_convert(newname,cnum,0,&bad_path2);
3027 target_is_directory = directory_exist(newname,NULL);
3029 if ((flags&1) && target_is_directory) {
3030 return(ERROR(ERRDOS,ERRbadfile));
3033 if ((flags&2) && !target_is_directory) {
3034 return(ERROR(ERRDOS,ERRbadpath));
3037 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
3038 /* wants a tree copy! XXXX */
3039 DEBUG(3,("Rejecting tree copy\n"));
3040 return(ERROR(ERRSRV,ERRerror));
3043 p = strrchr(name,'/');
3044 if (!p) {
3045 strcpy(directory,"./");
3046 strcpy(mask,name);
3047 } else {
3048 *p = 0;
3049 strcpy(directory,name);
3050 strcpy(mask,p+1);
3053 if (is_mangled(mask))
3054 check_mangled_stack(mask);
3056 has_wild = strchr(mask,'*') || strchr(mask,'?');
3058 if (!has_wild) {
3059 strcat(directory,"/");
3060 strcat(directory,mask);
3061 if (resolve_wildcards(directory,newname) &&
3062 copy_file(directory,newname,cnum,ofun,
3063 count,target_is_directory)) count++;
3064 if (!count) exists = file_exist(directory,NULL);
3065 } else {
3066 void *dirptr = NULL;
3067 char *dname;
3068 pstring destname;
3070 if (check_name(directory,cnum))
3071 dirptr = OpenDir(cnum, directory, True);
3073 if (dirptr)
3075 error = ERRbadfile;
3077 if (strequal(mask,"????????.???"))
3078 strcpy(mask,"*");
3080 while ((dname = ReadDirName(dirptr)))
3082 pstring fname;
3083 strcpy(fname,dname);
3085 if(!mask_match(fname, mask, case_sensitive, False)) continue;
3087 error = ERRnoaccess;
3088 sprintf(fname,"%s/%s",directory,dname);
3089 strcpy(destname,newname);
3090 if (resolve_wildcards(fname,destname) &&
3091 copy_file(directory,newname,cnum,ofun,
3092 count,target_is_directory)) count++;
3093 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3095 CloseDir(dirptr);
3099 if (count == 0) {
3100 if (exists)
3101 return(ERROR(ERRDOS,error));
3102 else
3104 if((errno == ENOENT) && (bad_path1 || bad_path2))
3106 unix_ERR_class = ERRDOS;
3107 unix_ERR_code = ERRbadpath;
3109 return(UNIXERROR(ERRDOS,error));
3113 outsize = set_message(outbuf,1,0,True);
3114 SSVAL(outbuf,smb_vwv0,count);
3116 return(outsize);
3121 /****************************************************************************
3122 reply to a setdir
3123 ****************************************************************************/
3124 int reply_setdir(char *inbuf,char *outbuf)
3126 int cnum,snum;
3127 int outsize = 0;
3128 BOOL ok = False;
3129 pstring newdir;
3131 cnum = SVAL(inbuf,smb_tid);
3133 snum = Connections[cnum].service;
3134 if (!CAN_SETDIR(snum))
3135 return(ERROR(ERRDOS,ERRnoaccess));
3137 strcpy(newdir,smb_buf(inbuf) + 1);
3138 strlower(newdir);
3140 if (strlen(newdir) == 0)
3141 ok = True;
3142 else
3144 ok = directory_exist(newdir,NULL);
3145 if (ok)
3146 string_set(&Connections[cnum].connectpath,newdir);
3149 if (!ok)
3150 return(ERROR(ERRDOS,ERRbadpath));
3152 outsize = set_message(outbuf,0,0,True);
3153 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3155 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3157 return(outsize);
3161 /****************************************************************************
3162 reply to a lockingX request
3163 ****************************************************************************/
3164 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3166 int fnum = GETFNUM(inbuf,smb_vwv2);
3167 uint16 locktype = SVAL(inbuf,smb_vwv3);
3168 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3169 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3170 uint32 count, offset;
3172 int cnum;
3173 int i;
3174 char *data;
3175 uint32 ecode=0, dummy2;
3176 int eclass=0, dummy1;
3178 cnum = SVAL(inbuf,smb_tid);
3180 CHECK_FNUM(fnum,cnum);
3181 CHECK_ERROR(fnum);
3183 data = smb_buf(inbuf);
3184 /* Data now points at the beginning of the list
3185 of smb_unlkrng structs */
3186 for(i = 0; i < (int)num_ulocks; i++) {
3187 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3188 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3189 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3190 return ERROR(eclass,ecode);
3193 /* Now do any requested locks */
3194 data += 10*num_ulocks;
3195 /* Data now points at the beginning of the list
3196 of smb_lkrng structs */
3197 for(i = 0; i < (int)num_locks; i++) {
3198 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3199 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3200 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3201 break;
3204 /* If any of the above locks failed, then we must unlock
3205 all of the previous locks (X/Open spec). */
3206 if(i != num_locks && num_locks != 0) {
3207 for(; i >= 0; i--) {
3208 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3209 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3210 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3212 return ERROR(eclass,ecode);
3215 set_message(outbuf,2,0,True);
3217 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3218 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
3220 chain_fnum = fnum;
3222 return chain_reply(inbuf,outbuf,length,bufsize);
3226 /****************************************************************************
3227 reply to a SMBreadbmpx (read block multiplex) request
3228 ****************************************************************************/
3229 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3231 int cnum,fnum;
3232 int nread = -1;
3233 int total_read;
3234 char *data;
3235 uint32 startpos;
3236 int outsize, mincount, maxcount;
3237 int max_per_packet;
3238 int tcount;
3239 int pad;
3241 /* this function doesn't seem to work - disable by default */
3242 if (!lp_readbmpx())
3243 return(ERROR(ERRSRV,ERRuseSTD));
3245 outsize = set_message(outbuf,8,0,True);
3247 cnum = SVAL(inbuf,smb_tid);
3248 fnum = GETFNUM(inbuf,smb_vwv0);
3250 CHECK_FNUM(fnum,cnum);
3251 CHECK_READ(fnum);
3252 CHECK_ERROR(fnum);
3254 startpos = IVAL(inbuf,smb_vwv1);
3255 maxcount = SVAL(inbuf,smb_vwv3);
3256 mincount = SVAL(inbuf,smb_vwv4);
3258 data = smb_buf(outbuf);
3259 pad = ((long)data)%4;
3260 if (pad) pad = 4 - pad;
3261 data += pad;
3263 max_per_packet = bufsize-(outsize+pad);
3264 tcount = maxcount;
3265 total_read = 0;
3267 if (is_locked(fnum,cnum,maxcount,startpos))
3268 return(ERROR(ERRDOS,ERRlock));
3272 int N = MIN(max_per_packet,tcount-total_read);
3274 nread = read_file(fnum,data,startpos,N);
3276 if (nread <= 0) nread = 0;
3278 if (nread < N)
3279 tcount = total_read + nread;
3281 set_message(outbuf,8,nread,False);
3282 SIVAL(outbuf,smb_vwv0,startpos);
3283 SSVAL(outbuf,smb_vwv2,tcount);
3284 SSVAL(outbuf,smb_vwv6,nread);
3285 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3287 send_smb(Client,outbuf);
3289 total_read += nread;
3290 startpos += nread;
3292 while (total_read < tcount);
3294 return(-1);
3298 /****************************************************************************
3299 reply to a SMBwritebmpx (write block multiplex primary) request
3300 ****************************************************************************/
3301 int reply_writebmpx(char *inbuf,char *outbuf)
3303 int cnum,numtowrite,fnum;
3304 int nwritten = -1;
3305 int outsize = 0;
3306 uint32 startpos;
3307 int tcount, write_through, smb_doff;
3308 char *data;
3310 cnum = SVAL(inbuf,smb_tid);
3311 fnum = GETFNUM(inbuf,smb_vwv0);
3313 CHECK_FNUM(fnum,cnum);
3314 CHECK_WRITE(fnum);
3315 CHECK_ERROR(fnum);
3317 tcount = SVAL(inbuf,smb_vwv1);
3318 startpos = IVAL(inbuf,smb_vwv3);
3319 write_through = BITSETW(inbuf+smb_vwv7,0);
3320 numtowrite = SVAL(inbuf,smb_vwv10);
3321 smb_doff = SVAL(inbuf,smb_vwv11);
3323 data = smb_base(inbuf) + smb_doff;
3325 /* If this fails we need to send an SMBwriteC response,
3326 not an SMBwritebmpx - set this up now so we don't forget */
3327 CVAL(outbuf,smb_com) = SMBwritec;
3329 if (is_locked(fnum,cnum,tcount,startpos))
3330 return(ERROR(ERRDOS,ERRlock));
3332 seek_file(fnum,startpos);
3333 nwritten = write_file(fnum,data,numtowrite);
3335 if(lp_syncalways(SNUM(cnum)) || write_through)
3336 sync_file(fnum);
3338 if(nwritten < numtowrite)
3339 return(UNIXERROR(ERRHRD,ERRdiskfull));
3341 /* If the maximum to be written to this file
3342 is greater than what we just wrote then set
3343 up a secondary struct to be attached to this
3344 fd, we will use this to cache error messages etc. */
3345 if(tcount > nwritten)
3347 write_bmpx_struct *wbms;
3348 if(Files[fnum].wbmpx_ptr != NULL)
3349 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3350 else
3351 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3352 if(!wbms)
3354 DEBUG(0,("Out of memory in reply_readmpx\n"));
3355 return(ERROR(ERRSRV,ERRnoresource));
3357 wbms->wr_mode = write_through;
3358 wbms->wr_discard = False; /* No errors yet */
3359 wbms->wr_total_written = nwritten;
3360 wbms->wr_errclass = 0;
3361 wbms->wr_error = 0;
3362 Files[fnum].wbmpx_ptr = wbms;
3365 /* We are returning successfully, set the message type back to
3366 SMBwritebmpx */
3367 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3369 outsize = set_message(outbuf,1,0,True);
3371 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3373 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3374 timestring(),fnum,cnum,numtowrite,nwritten));
3376 if (write_through && tcount==nwritten) {
3377 /* we need to send both a primary and a secondary response */
3378 smb_setlen(outbuf,outsize - 4);
3379 send_smb(Client,outbuf);
3381 /* now the secondary */
3382 outsize = set_message(outbuf,1,0,True);
3383 CVAL(outbuf,smb_com) = SMBwritec;
3384 SSVAL(outbuf,smb_vwv0,nwritten);
3387 return(outsize);
3391 /****************************************************************************
3392 reply to a SMBwritebs (write block multiplex secondary) request
3393 ****************************************************************************/
3394 int reply_writebs(char *inbuf,char *outbuf)
3396 int cnum,numtowrite,fnum;
3397 int nwritten = -1;
3398 int outsize = 0;
3399 int32 startpos;
3400 int tcount, write_through, smb_doff;
3401 char *data;
3402 write_bmpx_struct *wbms;
3403 BOOL send_response = False;
3405 cnum = SVAL(inbuf,smb_tid);
3406 fnum = GETFNUM(inbuf,smb_vwv0);
3407 CHECK_FNUM(fnum,cnum);
3408 CHECK_WRITE(fnum);
3410 tcount = SVAL(inbuf,smb_vwv1);
3411 startpos = IVAL(inbuf,smb_vwv2);
3412 numtowrite = SVAL(inbuf,smb_vwv6);
3413 smb_doff = SVAL(inbuf,smb_vwv7);
3415 data = smb_base(inbuf) + smb_doff;
3417 /* We need to send an SMBwriteC response, not an SMBwritebs */
3418 CVAL(outbuf,smb_com) = SMBwritec;
3420 /* This fd should have an auxiliary struct attached,
3421 check that it does */
3422 wbms = Files[fnum].wbmpx_ptr;
3423 if(!wbms) return(-1);
3425 /* If write through is set we can return errors, else we must
3426 cache them */
3427 write_through = wbms->wr_mode;
3429 /* Check for an earlier error */
3430 if(wbms->wr_discard)
3431 return -1; /* Just discard the packet */
3433 seek_file(fnum,startpos);
3434 nwritten = write_file(fnum,data,numtowrite);
3436 if(lp_syncalways(SNUM(cnum)) || write_through)
3437 sync_file(fnum);
3439 if (nwritten < numtowrite)
3441 if(write_through) {
3442 /* We are returning an error - we can delete the aux struct */
3443 if (wbms) free((char *)wbms);
3444 Files[fnum].wbmpx_ptr = NULL;
3445 return(ERROR(ERRHRD,ERRdiskfull));
3447 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3450 /* Increment the total written, if this matches tcount
3451 we can discard the auxiliary struct (hurrah !) and return a writeC */
3452 wbms->wr_total_written += nwritten;
3453 if(wbms->wr_total_written >= tcount)
3455 if (write_through) {
3456 outsize = set_message(outbuf,1,0,True);
3457 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3458 send_response = True;
3461 free((char *)wbms);
3462 Files[fnum].wbmpx_ptr = NULL;
3465 if(send_response)
3466 return(outsize);
3468 return(-1);
3472 /****************************************************************************
3473 reply to a SMBsetattrE
3474 ****************************************************************************/
3475 int reply_setattrE(char *inbuf,char *outbuf)
3477 int cnum,fnum;
3478 struct utimbuf unix_times;
3479 int outsize = 0;
3481 outsize = set_message(outbuf,0,0,True);
3483 cnum = SVAL(inbuf,smb_tid);
3484 fnum = GETFNUM(inbuf,smb_vwv0);
3486 CHECK_FNUM(fnum,cnum);
3487 CHECK_ERROR(fnum);
3489 /* Convert the DOS times into unix times. Ignore create
3490 time as UNIX can't set this.
3492 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3493 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3495 /* Set the date on this file */
3496 if(sys_utime(Files[fnum].name, &unix_times))
3497 return(ERROR(ERRDOS,ERRnoaccess));
3499 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3501 return(outsize);
3505 /****************************************************************************
3506 reply to a SMBgetattrE
3507 ****************************************************************************/
3508 int reply_getattrE(char *inbuf,char *outbuf)
3510 int cnum,fnum;
3511 struct stat sbuf;
3512 int outsize = 0;
3513 int mode;
3515 outsize = set_message(outbuf,11,0,True);
3517 cnum = SVAL(inbuf,smb_tid);
3518 fnum = GETFNUM(inbuf,smb_vwv0);
3520 CHECK_FNUM(fnum,cnum);
3521 CHECK_ERROR(fnum);
3523 /* Do an fstat on this file */
3524 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3525 return(UNIXERROR(ERRDOS,ERRnoaccess));
3527 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3529 /* Convert the times into dos times. Set create
3530 date to be last modify date as UNIX doesn't save
3531 this */
3532 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3533 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3534 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3535 if (mode & aDIR)
3537 SIVAL(outbuf,smb_vwv6,0);
3538 SIVAL(outbuf,smb_vwv8,0);
3540 else
3542 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3543 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3545 SSVAL(outbuf,smb_vwv10, mode);
3547 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3549 return(outsize);