This commit was manufactured by cvs2svn to create tag
[Samba/gbeck.git] / source / smbd / reply.c
blob3698787ba462f304bce843b363c3bc6c6a614b59
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
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 maxxmit;
34 extern int chain_fnum;
35 extern char magic_char;
36 extern connection_struct Connections[];
37 extern files_struct Files[];
38 extern BOOL case_sensitive;
39 extern BOOL case_preserve;
40 extern pstring sesssetup_user;
41 extern int Client;
43 /* this macro should always be used to extract an fnum (smb_fid) from
44 a packet to ensure chaining works correctly */
45 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
48 /****************************************************************************
49 reply to an special message
50 ****************************************************************************/
51 int reply_special(char *inbuf,char *outbuf)
53 int outsize = 4;
54 int msg_type = CVAL(inbuf,0);
55 int msg_flags = CVAL(inbuf,1);
56 pstring name1,name2;
57 extern fstring remote_machine;
58 extern fstring local_machine;
59 char *p;
61 *name1 = *name2 = 0;
63 smb_setlen(outbuf,0);
65 switch (msg_type)
67 case 0x81: /* session request */
68 CVAL(outbuf,0) = 0x82;
69 CVAL(outbuf,3) = 0;
70 if (name_len(inbuf+4) > 50)
72 DEBUG(0,("Invalid name length in session request\n"));
73 return(0);
75 name_extract(inbuf,4,name1);
76 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
77 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2));
79 strcpy(remote_machine,name2);
80 trim_string(remote_machine," "," ");
81 p = strchr(remote_machine,' ');
82 strlower(remote_machine);
83 if (p) *p = 0;
85 strcpy(local_machine,name1);
86 trim_string(local_machine," "," ");
87 p = strchr(local_machine,' ');
88 strlower(local_machine);
89 if (p) *p = 0;
91 add_session_user(remote_machine);
93 reload_services(True);
94 reopen_logs();
96 break;
97 case 0x85: /* session keepalive */
98 default:
99 return(0);
102 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags));
104 return(outsize);
108 /*******************************************************************
109 work out what error to give to a failed connection
110 ********************************************************************/
111 static int connection_error(char *inbuf,char *outbuf,int connection_num)
113 switch (connection_num)
115 case -8:
116 return(ERROR(ERRSRV,ERRnoresource));
117 case -7:
118 return(ERROR(ERRSRV,ERRbaduid));
119 case -6:
120 return(ERROR(ERRSRV,ERRinvdevice));
121 case -5:
122 return(ERROR(ERRSRV,ERRinvnetname));
123 case -4:
124 return(ERROR(ERRSRV,ERRaccess));
125 case -3:
126 return(ERROR(ERRDOS,ERRnoipc));
127 case -2:
128 return(ERROR(ERRSRV,ERRinvnetname));
130 return(ERROR(ERRSRV,ERRbadpw));
135 /****************************************************************************
136 parse a share descriptor string
137 ****************************************************************************/
138 static void parse_connect(char *p,char *service,char *user,
139 char *password,int *pwlen,char *dev)
141 char *p2;
143 DEBUG(4,("parsing connect string %s\n",p));
145 p2 = strrchr(p,'\\');
146 if (p2 == NULL)
147 strcpy(service,p);
148 else
149 strcpy(service,p2+1);
151 p += strlen(p) + 2;
153 strcpy(password,p);
154 *pwlen = strlen(password);
156 p += strlen(p) + 2;
158 strcpy(dev,p);
160 *user = 0;
161 p = strchr(service,'%');
162 if (p != NULL)
164 *p = 0;
165 strcpy(user,p+1);
172 /****************************************************************************
173 reply to a tcon
174 ****************************************************************************/
175 int reply_tcon(char *inbuf,char *outbuf)
177 pstring service;
178 pstring user;
179 pstring password;
180 pstring dev;
181 int connection_num;
182 int outsize = 0;
183 uint16 vuid = SVAL(inbuf,smb_uid);
184 int pwlen=0;
186 *service = *user = *password = *dev = 0;
188 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
190 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
192 if (connection_num < 0)
193 return(connection_error(inbuf,outbuf,connection_num));
195 outsize = set_message(outbuf,2,0,True);
196 SSVAL(outbuf,smb_vwv0,maxxmit);
197 SSVAL(outbuf,smb_vwv1,connection_num);
198 SSVAL(outbuf,smb_tid,connection_num);
200 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
202 return(outsize);
206 /****************************************************************************
207 reply to a tcon and X
208 ****************************************************************************/
209 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
211 pstring service;
212 pstring user;
213 pstring password;
214 pstring devicename;
215 int connection_num;
216 uint16 vuid = SVAL(inbuf,smb_uid);
217 int passlen = SVAL(inbuf,smb_vwv3);
218 BOOL doencrypt = SMBENCRYPT();
220 *service = *user = *password = *devicename = 0;
222 /* we might have to close an old one */
223 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
224 close_cnum(SVAL(inbuf,smb_tid),vuid);
227 char *path;
228 char *p;
229 memcpy(password,smb_buf(inbuf),passlen);
230 password[passlen]=0;
231 path = smb_buf(inbuf) + passlen;
233 if (!doencrypt || passlen != 24) {
234 if (strequal(password," "))
235 *password = 0;
236 passlen = strlen(password);
239 DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
240 strcpy(service,path+2);
241 p = strchr(service,'\\');
242 if (!p)
243 return(ERROR(ERRSRV,ERRinvnetname));
244 *p = 0;
245 strcpy(service,p+1);
246 p = strchr(service,'%');
247 if (p)
249 *p++ = 0;
250 strcpy(user,p);
252 StrnCpy(devicename,path + strlen(path) + 1,6);
253 DEBUG(4,("Got device type %s\n",devicename));
256 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
258 if (connection_num < 0)
259 return(connection_error(inbuf,outbuf,connection_num));
261 set_message(outbuf,2,strlen(devicename)+1,True);
263 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
265 /* set the incoming and outgoing tid to the just created one */
266 SSVAL(inbuf,smb_tid,connection_num);
267 SSVAL(outbuf,smb_tid,connection_num);
269 strcpy(smb_buf(outbuf),devicename);
271 return chain_reply(inbuf,outbuf,length,bufsize);
275 /****************************************************************************
276 reply to an unknown type
277 ****************************************************************************/
278 int reply_unknown(char *inbuf,char *outbuf)
280 int cnum;
281 int type;
282 cnum = SVAL(inbuf,smb_tid);
283 type = CVAL(inbuf,smb_com);
285 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
286 timestring(),
287 smb_fn_name(type),
288 cnum,type,type));
290 return(ERROR(ERRSRV,ERRunknownsmb));
294 /****************************************************************************
295 reply to an ioctl
296 ****************************************************************************/
297 int reply_ioctl(char *inbuf,char *outbuf)
299 DEBUG(3,("ignoring ioctl\n"));
300 #if 0
301 /* we just say it succeeds and hope its all OK.
302 some day it would be nice to interpret them individually */
303 return set_message(outbuf,1,0,True);
304 #else
305 return(ERROR(ERRSRV,ERRnosupport));
306 #endif
310 /****************************************************************************
311 reply to a session setup command
312 ****************************************************************************/
313 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
315 uint16 sess_vuid;
316 int gid;
317 int uid;
318 int smb_bufsize;
319 int smb_mpxmax;
320 int smb_vc_num;
321 uint32 smb_sesskey;
322 int smb_apasslen = 0;
323 pstring smb_apasswd;
324 int smb_ntpasslen = 0;
325 pstring smb_ntpasswd;
326 BOOL valid_nt_password = False;
327 pstring user;
328 BOOL guest=False;
329 BOOL computer_id=False;
330 static BOOL done_sesssetup = False;
331 BOOL doencrypt = SMBENCRYPT();
333 *smb_apasswd = 0;
335 smb_bufsize = SVAL(inbuf,smb_vwv2);
336 smb_mpxmax = SVAL(inbuf,smb_vwv3);
337 smb_vc_num = SVAL(inbuf,smb_vwv4);
338 smb_sesskey = IVAL(inbuf,smb_vwv5);
340 if (Protocol < PROTOCOL_NT1) {
341 smb_apasslen = SVAL(inbuf,smb_vwv7);
342 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
343 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
345 if (lp_security() != SEC_SERVER && !doencrypt)
346 smb_apasslen = strlen(smb_apasswd);
347 } else {
348 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
349 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
350 char *p = smb_buf(inbuf);
352 if (passlen1 != 24 && passlen2 != 24)
353 doencrypt = False;
355 if(doencrypt) {
356 /* Save the lanman2 password and the NT md4 password. */
357 smb_apasslen = passlen1;
358 memcpy(smb_apasswd,p,smb_apasslen);
359 smb_ntpasslen = passlen2;
360 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
361 } else {
362 /* both Win95 and WinNT stuff up the password lengths for
363 non-encrypting systems. Uggh.
365 if passlen1==24 its a win95 system, and its setting the
366 password length incorrectly. Luckily it still works with the
367 default code because Win95 will null terminate the password
368 anyway
370 if passlen1>0 and passlen2>0 then maybe its a NT box and its
371 setting passlen2 to some random value which really stuffs
372 things up. we need to fix that one. */
373 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
374 passlen2 != 1) {
375 passlen2 = 0;
377 /* we use the first password that they gave */
378 smb_apasslen = passlen1;
379 StrnCpy(smb_apasswd,p,smb_apasslen);
381 /* trim the password */
382 smb_apasslen = strlen(smb_apasswd);
384 /* wfwg sometimes uses a space instead of a null */
385 if (strequal(smb_apasswd," ")) {
386 smb_apasslen = 0;
387 *smb_apasswd = 0;
391 p += passlen1 + passlen2;
392 strcpy(user,p); p = skip_string(p,1);
393 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
394 p,skip_string(p,1),skip_string(p,2)));
398 DEBUG(3,("sesssetupX:name=[%s]\n",user));
400 /* If name ends in $ then I think it's asking about whether a */
401 /* computer with that name (minus the $) has access. For now */
402 /* say yes to everything ending in $. */
403 if (user[strlen(user) - 1] == '$') {
404 computer_id = True;
405 user[strlen(user) - 1] = '\0';
409 if (!*user)
410 strcpy(user,lp_guestaccount(-1));
412 strlower(user);
414 strcpy(sesssetup_user,user);
416 reload_services(True);
418 add_session_user(user);
421 if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
422 !check_hosts_equiv(user))
425 if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
426 guest = True;
428 /* now check if it's a valid username/password */
429 /* If an NT password was supplied try and validate with that
430 first. This is superior as the passwords are mixed case 128 length unicode */
431 if(smb_ntpasslen && !guest)
433 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
434 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
435 else
436 valid_nt_password = True;
438 if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
440 if (!computer_id && lp_security() >= SEC_USER) {
441 #if (GUEST_SESSSETUP == 0)
442 return(ERROR(ERRSRV,ERRbadpw));
443 #endif
444 #if (GUEST_SESSSETUP == 1)
445 if (Get_Pwnam(user,True))
446 return(ERROR(ERRSRV,ERRbadpw));
447 #endif
449 if (*smb_apasswd || !Get_Pwnam(user,True))
450 strcpy(user,lp_guestaccount(-1));
451 DEBUG(3,("Registered username %s for guest access\n",user));
452 guest = True;
456 if (!Get_Pwnam(user,True)) {
457 DEBUG(3,("No such user %s - using guest account\n",user));
458 strcpy(user,lp_guestaccount(-1));
459 guest = True;
462 if (!strequal(user,lp_guestaccount(-1)) &&
463 lp_servicenumber(user) < 0)
465 int homes = lp_servicenumber(HOMES_NAME);
466 char *home = get_home_dir(user);
467 if (homes >= 0 && home)
468 lp_add_home(user,homes,home);
472 /* it's ok - setup a reply */
473 if (Protocol < PROTOCOL_NT1) {
474 set_message(outbuf,3,0,True);
475 } else {
476 char *p;
477 set_message(outbuf,3,3,True);
478 p = smb_buf(outbuf);
479 strcpy(p,"Unix"); p = skip_string(p,1);
480 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
481 strcpy(p,lp_workgroup()); p = skip_string(p,1);
482 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
483 /* perhaps grab OS version here?? */
486 /* Set the correct uid in the outgoing and incoming packets
487 We will use this on future requests to determine which
488 user we should become.
491 struct passwd *pw = Get_Pwnam(user,False);
492 if (!pw) {
493 DEBUG(1,("Username %s is invalid on this system\n",user));
494 return(ERROR(ERRSRV,ERRbadpw));
496 gid = pw->pw_gid;
497 uid = pw->pw_uid;
500 if (guest && !computer_id)
501 SSVAL(outbuf,smb_vwv2,1);
503 /* register the name and uid as being validated, so further connections
504 to a uid can get through without a password, on the same VC */
505 sess_vuid = register_vuid(uid,gid,user,guest);
507 SSVAL(outbuf,smb_uid,sess_vuid);
508 SSVAL(inbuf,smb_uid,sess_vuid);
510 if (!done_sesssetup)
511 maxxmit = MIN(maxxmit,smb_bufsize);
513 done_sesssetup = True;
515 return chain_reply(inbuf,outbuf,length,bufsize);
519 /****************************************************************************
520 reply to a chkpth
521 ****************************************************************************/
522 int reply_chkpth(char *inbuf,char *outbuf)
524 int outsize = 0;
525 int cnum,mode;
526 pstring name;
527 BOOL ok = False;
529 cnum = SVAL(inbuf,smb_tid);
531 strcpy(name,smb_buf(inbuf) + 1);
532 unix_convert(name,cnum,0);
534 mode = SVAL(inbuf,smb_vwv0);
536 if (check_name(name,cnum))
537 ok = directory_exist(name,NULL);
539 if (!ok)
540 return(ERROR(ERRDOS,ERRbadpath));
542 outsize = set_message(outbuf,0,0,True);
544 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
546 return(outsize);
550 /****************************************************************************
551 reply to a getatr
552 ****************************************************************************/
553 int reply_getatr(char *inbuf,char *outbuf)
555 pstring fname;
556 int cnum;
557 int outsize = 0;
558 struct stat sbuf;
559 BOOL ok = False;
560 int mode=0;
561 uint32 size=0;
562 time_t mtime=0;
564 cnum = SVAL(inbuf,smb_tid);
566 strcpy(fname,smb_buf(inbuf) + 1);
567 unix_convert(fname,cnum,0);
569 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
570 under WfWg - weird! */
571 if (! (*fname))
573 mode = aHIDDEN | aDIR;
574 if (!CAN_WRITE(cnum)) mode |= aRONLY;
575 size = 0;
576 mtime = 0;
577 ok = True;
579 else
580 if (check_name(fname,cnum))
582 if (sys_stat(fname,&sbuf) == 0)
584 mode = dos_mode(cnum,fname,&sbuf);
585 size = sbuf.st_size;
586 mtime = sbuf.st_mtime;
587 if (mode & aDIR)
588 size = 0;
589 ok = True;
591 else
592 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
595 if (!ok)
596 return(UNIXERROR(ERRDOS,ERRbadfile));
598 outsize = set_message(outbuf,10,0,True);
600 SSVAL(outbuf,smb_vwv0,mode);
601 put_dos_date3(outbuf,smb_vwv1,mtime);
602 SIVAL(outbuf,smb_vwv3,size);
604 if (Protocol >= PROTOCOL_NT1) {
605 char *p = strrchr(fname,'/');
606 uint16 flg2 = SVAL(outbuf,smb_flg2);
607 if (!p) p = fname;
608 if (!is_8_3(fname))
609 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
612 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
614 return(outsize);
618 /****************************************************************************
619 reply to a setatr
620 ****************************************************************************/
621 int reply_setatr(char *inbuf,char *outbuf)
623 pstring fname;
624 int cnum;
625 int outsize = 0;
626 BOOL ok=False;
627 int mode;
628 time_t mtime;
630 cnum = SVAL(inbuf,smb_tid);
632 strcpy(fname,smb_buf(inbuf) + 1);
633 unix_convert(fname,cnum,0);
635 mode = SVAL(inbuf,smb_vwv0);
636 mtime = make_unix_date3(inbuf+smb_vwv1);
638 if (directory_exist(fname,NULL))
639 mode |= aDIR;
640 if (check_name(fname,cnum))
641 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
642 if (ok)
643 ok = set_filetime(fname,mtime);
645 if (!ok)
646 return(UNIXERROR(ERRDOS,ERRnoaccess));
648 outsize = set_message(outbuf,0,0,True);
650 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
652 return(outsize);
656 /****************************************************************************
657 reply to a dskattr
658 ****************************************************************************/
659 int reply_dskattr(char *inbuf,char *outbuf)
661 int cnum;
662 int outsize = 0;
663 int dfree,dsize,bsize;
665 cnum = SVAL(inbuf,smb_tid);
667 sys_disk_free(".",&bsize,&dfree,&dsize);
669 outsize = set_message(outbuf,5,0,True);
671 SSVAL(outbuf,smb_vwv0,dsize);
672 SSVAL(outbuf,smb_vwv1,bsize/512);
673 SSVAL(outbuf,smb_vwv2,512);
674 SSVAL(outbuf,smb_vwv3,dfree);
676 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
678 return(outsize);
682 /****************************************************************************
683 reply to a search
684 Can be called from SMBsearch, SMBffirst or SMBfunique.
685 ****************************************************************************/
686 int reply_search(char *inbuf,char *outbuf)
688 pstring mask;
689 pstring directory;
690 pstring fname;
691 int size,mode;
692 time_t date;
693 int dirtype;
694 int cnum;
695 int outsize = 0;
696 int numentries = 0;
697 BOOL finished = False;
698 int maxentries;
699 int i;
700 char *p;
701 BOOL ok = False;
702 int status_len;
703 char *path;
704 char status[21];
705 int dptr_num= -1;
706 BOOL check_descend = False;
707 BOOL expect_close = False;
708 BOOL can_open = True;
710 *mask = *directory = *fname = 0;
712 /* If we were called as SMBffirst then we must expect close. */
713 if(CVAL(inbuf,smb_com) == SMBffirst)
714 expect_close = True;
716 cnum = SVAL(inbuf,smb_tid);
718 outsize = set_message(outbuf,1,3,True);
719 maxentries = SVAL(inbuf,smb_vwv0);
720 dirtype = SVAL(inbuf,smb_vwv1);
721 path = smb_buf(inbuf) + 1;
722 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
725 /* dirtype &= ~aDIR; */
727 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
730 if (status_len == 0)
732 pstring dir2;
734 strcpy(directory,smb_buf(inbuf)+1);
735 strcpy(dir2,smb_buf(inbuf)+1);
736 unix_convert(directory,cnum,0);
737 unix_format(dir2);
739 if (!check_name(directory,cnum))
740 can_open = False;
742 p = strrchr(dir2,'/');
743 if (p == NULL)
744 {strcpy(mask,dir2);*dir2 = 0;}
745 else
746 {*p = 0;strcpy(mask,p+1);}
748 p = strrchr(directory,'/');
749 if (!p)
750 *directory = 0;
751 else
752 *p = 0;
754 if (strlen(directory) == 0)
755 strcpy(directory,"./");
756 bzero(status,21);
757 CVAL(status,0) = dirtype;
759 else
761 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
762 memcpy(mask,status+1,11);
763 mask[11] = 0;
764 dirtype = CVAL(status,0) & 0x1F;
765 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
766 if (!Connections[cnum].dirptr)
767 goto SearchEmpty;
768 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
769 if (!case_sensitive)
770 strnorm(mask);
773 /* turn strings of spaces into a . */
775 trim_string(mask,NULL," ");
776 if ((p = strrchr(mask,' ')))
778 fstring ext;
779 strcpy(ext,p+1);
780 *p = 0;
781 trim_string(mask,NULL," ");
782 strcat(mask,".");
783 strcat(mask,ext);
788 for (p=mask; *p; p++)
790 if (*p != '?' && *p != '*' && !isdoschar(*p))
792 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
793 *p = '?';
798 if (!strchr(mask,'.') && strlen(mask)>8)
800 fstring tmp;
801 strcpy(tmp,&mask[8]);
802 mask[8] = '.';
803 mask[9] = 0;
804 strcat(mask,tmp);
807 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
809 if (can_open)
811 p = smb_buf(outbuf) + 3;
813 ok = True;
815 if (status_len == 0)
817 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
818 if (dptr_num < 0)
819 return(ERROR(ERRDOS,ERRnofids));
822 DEBUG(4,("dptr_num is %d\n",dptr_num));
824 if (ok)
826 if ((dirtype&0x1F) == aVOLID)
828 memcpy(p,status,21);
829 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
830 dptr_fill(p+12,dptr_num);
831 if (dptr_zero(p+12) && (status_len==0))
832 numentries = 1;
833 else
834 numentries = 0;
835 p += DIR_STRUCT_SIZE;
837 else
839 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
840 if (in_list(Connections[cnum].dirpath,
841 lp_dontdescend(SNUM(cnum)),True))
842 check_descend = True;
844 for (i=numentries;(i<maxentries) && !finished;i++)
846 finished =
847 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
848 if (!finished)
850 memcpy(p,status,21);
851 make_dir_struct(p,mask,fname,size,mode,date);
852 dptr_fill(p+12,dptr_num);
853 numentries++;
855 p += DIR_STRUCT_SIZE;
862 SearchEmpty:
864 if (numentries == 0 || !ok)
866 CVAL(outbuf,smb_rcls) = ERRDOS;
867 SSVAL(outbuf,smb_err,ERRnofiles);
870 /* If we were called as SMBffirst with smb_search_id == NULL
871 and no entries were found then return error and close dirptr
872 (X/Open spec) */
874 if(ok && expect_close && numentries == 0 && status_len == 0)
876 CVAL(outbuf,smb_rcls) = ERRDOS;
877 SSVAL(outbuf,smb_err,ERRnofiles);
878 /* Also close the dptr - we know it's gone */
879 dptr_close(dptr_num);
882 /* If we were called as SMBfunique, then we can close the dirptr now ! */
883 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
884 dptr_close(dptr_num);
886 SSVAL(outbuf,smb_vwv0,numentries);
887 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
888 CVAL(smb_buf(outbuf),0) = 5;
889 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
891 if (Protocol >= PROTOCOL_NT1) {
892 uint16 flg2 = SVAL(outbuf,smb_flg2);
893 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
896 outsize += DIR_STRUCT_SIZE*numentries;
897 smb_setlen(outbuf,outsize - 4);
899 if ((! *directory) && dptr_path(dptr_num))
900 sprintf(directory,"(%s)",dptr_path(dptr_num));
902 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
903 timestring(),
904 smb_fn_name(CVAL(inbuf,smb_com)),
905 mask,directory,cnum,dirtype,numentries,maxentries));
907 return(outsize);
911 /****************************************************************************
912 reply to a fclose (stop directory search)
913 ****************************************************************************/
914 int reply_fclose(char *inbuf,char *outbuf)
916 int cnum;
917 int outsize = 0;
918 int status_len;
919 char *path;
920 char status[21];
921 int dptr_num= -1;
923 cnum = SVAL(inbuf,smb_tid);
925 outsize = set_message(outbuf,1,0,True);
926 path = smb_buf(inbuf) + 1;
927 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
930 if (status_len == 0)
931 return(ERROR(ERRSRV,ERRsrverror));
933 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
935 if(dptr_fetch(status+12,&dptr_num)) {
936 /* Close the dptr - we know it's gone */
937 dptr_close(dptr_num);
940 SSVAL(outbuf,smb_vwv0,0);
942 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
944 return(outsize);
948 /****************************************************************************
949 reply to an open
950 ****************************************************************************/
951 int reply_open(char *inbuf,char *outbuf)
953 pstring fname;
954 int cnum;
955 int fnum = -1;
956 int outsize = 0;
957 int fmode=0;
958 int share_mode;
959 int size = 0;
960 time_t mtime=0;
961 int unixmode;
962 int rmode=0;
963 struct stat sbuf;
965 cnum = SVAL(inbuf,smb_tid);
967 share_mode = SVAL(inbuf,smb_vwv0);
969 strcpy(fname,smb_buf(inbuf)+1);
970 unix_convert(fname,cnum,0);
972 fnum = find_free_file();
973 if (fnum < 0)
974 return(ERROR(ERRSRV,ERRnofids));
976 if (!check_name(fname,cnum))
977 return(UNIXERROR(ERRDOS,ERRnoaccess));
979 unixmode = unix_mode(cnum,aARCH);
981 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
983 if (!Files[fnum].open)
984 return(UNIXERROR(ERRDOS,ERRnoaccess));
986 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
987 close_file(fnum);
988 return(ERROR(ERRDOS,ERRnoaccess));
991 size = sbuf.st_size;
992 fmode = dos_mode(cnum,fname,&sbuf);
993 mtime = sbuf.st_mtime;
995 if (fmode & aDIR) {
996 DEBUG(3,("attempt to open a directory %s\n",fname));
997 close_file(fnum);
998 return(ERROR(ERRDOS,ERRnoaccess));
1001 outsize = set_message(outbuf,7,0,True);
1002 SSVAL(outbuf,smb_vwv0,fnum);
1003 SSVAL(outbuf,smb_vwv1,fmode);
1004 put_dos_date3(outbuf,smb_vwv2,mtime);
1005 SIVAL(outbuf,smb_vwv4,size);
1006 SSVAL(outbuf,smb_vwv6,rmode);
1008 if (lp_fake_oplocks(SNUM(cnum))) {
1009 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1012 return(outsize);
1016 /****************************************************************************
1017 reply to an open and X
1018 ****************************************************************************/
1019 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1021 pstring fname;
1022 int cnum = SVAL(inbuf,smb_tid);
1023 int fnum = -1;
1024 int openmode = 0;
1025 int smb_mode = SVAL(inbuf,smb_vwv3);
1026 int smb_attr = SVAL(inbuf,smb_vwv5);
1027 BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
1028 #if 0
1029 int open_flags = SVAL(inbuf,smb_vwv2);
1030 int smb_sattr = SVAL(inbuf,smb_vwv4);
1031 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1032 #endif
1033 int smb_ofun = SVAL(inbuf,smb_vwv8);
1034 int unixmode;
1035 int size=0,fmode=0,mtime=0,rmode=0;
1036 struct stat sbuf;
1037 int smb_action = 0;
1039 /* If it's an IPC, pass off the pipe handler. */
1040 if (IS_IPC(cnum))
1041 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1043 /* XXXX we need to handle passed times, sattr and flags */
1045 strcpy(fname,smb_buf(inbuf));
1046 unix_convert(fname,cnum,0);
1048 /* now add create and trunc bits */
1049 if (smb_ofun & 0x10)
1050 openmode |= O_CREAT;
1051 if ((smb_ofun & 0x3) == 2)
1052 openmode |= O_TRUNC;
1054 fnum = find_free_file();
1055 if (fnum < 0)
1056 return(ERROR(ERRSRV,ERRnofids));
1058 if (!check_name(fname,cnum))
1059 return(UNIXERROR(ERRDOS,ERRnoaccess));
1061 unixmode = unix_mode(cnum,smb_attr | aARCH);
1063 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1064 &rmode,&smb_action);
1066 if (!Files[fnum].open)
1067 return(UNIXERROR(ERRDOS,ERRnoaccess));
1069 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1070 close_file(fnum);
1071 return(ERROR(ERRDOS,ERRnoaccess));
1074 size = sbuf.st_size;
1075 fmode = dos_mode(cnum,fname,&sbuf);
1076 mtime = sbuf.st_mtime;
1077 if (fmode & aDIR) {
1078 close_file(fnum);
1079 return(ERROR(ERRDOS,ERRnoaccess));
1082 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1083 smb_action |= (1<<15);
1086 set_message(outbuf,15,0,True);
1087 SSVAL(outbuf,smb_vwv2,fnum);
1088 SSVAL(outbuf,smb_vwv3,fmode);
1089 put_dos_date3(outbuf,smb_vwv4,mtime);
1090 SIVAL(outbuf,smb_vwv6,size);
1091 SSVAL(outbuf,smb_vwv8,rmode);
1092 SSVAL(outbuf,smb_vwv11,smb_action);
1094 chain_fnum = fnum;
1096 return chain_reply(inbuf,outbuf,length,bufsize);
1100 /****************************************************************************
1101 reply to a SMBulogoffX
1102 ****************************************************************************/
1103 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1105 uint16 vuid = SVAL(inbuf,smb_uid);
1106 user_struct *vuser = get_valid_user_struct(vuid);
1108 if(vuser == 0) {
1109 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1112 /* in user level security we are supposed to close any files
1113 open by this user */
1114 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1115 int i;
1116 for (i=0;i<MAX_OPEN_FILES;i++)
1117 if (Files[i].uid == vuser->uid && Files[i].open) {
1118 close_file(i);
1122 invalidate_vuid(vuid);
1124 set_message(outbuf,2,0,True);
1126 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1128 return chain_reply(inbuf,outbuf,length,bufsize);
1132 /****************************************************************************
1133 reply to a mknew
1134 ****************************************************************************/
1135 int reply_mknew(char *inbuf,char *outbuf)
1137 pstring fname;
1138 int cnum,com;
1139 int fnum = -1;
1140 int outsize = 0;
1141 int createmode;
1142 mode_t unixmode;
1144 com = SVAL(inbuf,smb_com);
1145 cnum = SVAL(inbuf,smb_tid);
1147 createmode = SVAL(inbuf,smb_vwv0);
1148 strcpy(fname,smb_buf(inbuf)+1);
1149 unix_convert(fname,cnum,0);
1151 if (createmode & aVOLID)
1153 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1156 unixmode = unix_mode(cnum,createmode);
1158 if (com == SMBmknew && file_exist(fname,NULL))
1159 return(ERROR(ERRDOS,ERRfilexists));
1161 fnum = find_free_file();
1162 if (fnum < 0)
1163 return(ERROR(ERRSRV,ERRnofids));
1165 if (!check_name(fname,cnum))
1166 return(UNIXERROR(ERRDOS,ERRnoaccess));
1168 open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode, 0);
1170 if (!Files[fnum].open)
1171 return(UNIXERROR(ERRDOS,ERRnoaccess));
1173 outsize = set_message(outbuf,1,0,True);
1174 SSVAL(outbuf,smb_vwv0,fnum);
1176 if (lp_fake_oplocks(SNUM(cnum))) {
1177 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1180 DEBUG(2,("new file %s\n",fname));
1181 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));
1183 return(outsize);
1187 /****************************************************************************
1188 reply to a create temporary file
1189 ****************************************************************************/
1190 int reply_ctemp(char *inbuf,char *outbuf)
1192 pstring fname;
1193 pstring fname2;
1194 int cnum;
1195 int fnum = -1;
1196 int outsize = 0;
1197 int createmode;
1198 mode_t unixmode;
1200 cnum = SVAL(inbuf,smb_tid);
1201 createmode = SVAL(inbuf,smb_vwv0);
1202 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1203 unix_convert(fname,cnum,0);
1205 unixmode = unix_mode(cnum,createmode);
1207 fnum = find_free_file();
1208 if (fnum < 0)
1209 return(ERROR(ERRSRV,ERRnofids));
1211 if (!check_name(fname,cnum))
1212 return(UNIXERROR(ERRDOS,ERRnoaccess));
1214 strcpy(fname2,(char *)mktemp(fname));
1216 open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode, 0);
1218 if (!Files[fnum].open)
1219 return(UNIXERROR(ERRDOS,ERRnoaccess));
1221 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1222 SSVAL(outbuf,smb_vwv0,fnum);
1223 CVAL(smb_buf(outbuf),0) = 4;
1224 strcpy(smb_buf(outbuf) + 1,fname2);
1226 if (lp_fake_oplocks(SNUM(cnum))) {
1227 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1230 DEBUG(2,("created temp file %s\n",fname2));
1231 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));
1233 return(outsize);
1237 /*******************************************************************
1238 check if a user is allowed to delete a file
1239 ********************************************************************/
1240 static BOOL can_delete(char *fname,int cnum,int dirtype)
1242 struct stat sbuf;
1243 int fmode;
1245 if (!CAN_WRITE(cnum)) return(False);
1247 if (sys_lstat(fname,&sbuf) != 0) return(False);
1248 fmode = dos_mode(cnum,fname,&sbuf);
1249 if (fmode & aDIR) return(False);
1250 if (!lp_delete_readonly(SNUM(cnum))) {
1251 if (fmode & aRONLY) return(False);
1253 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1254 return(False);
1255 if (!check_file_sharing(cnum,fname)) return(False);
1256 return(True);
1259 /****************************************************************************
1260 reply to a unlink
1261 ****************************************************************************/
1262 int reply_unlink(char *inbuf,char *outbuf)
1264 int outsize = 0;
1265 pstring name;
1266 int cnum;
1267 int dirtype;
1268 pstring directory;
1269 pstring mask;
1270 char *p;
1271 int count=0;
1272 int error = ERRnoaccess;
1273 BOOL has_wild;
1274 BOOL exists=False;
1276 *directory = *mask = 0;
1278 cnum = SVAL(inbuf,smb_tid);
1279 dirtype = SVAL(inbuf,smb_vwv0);
1281 strcpy(name,smb_buf(inbuf) + 1);
1283 DEBUG(3,("reply_unlink : %s\n",name));
1285 unix_convert(name,cnum,0);
1287 p = strrchr(name,'/');
1288 if (!p) {
1289 strcpy(directory,"./");
1290 strcpy(mask,name);
1291 } else {
1292 *p = 0;
1293 strcpy(directory,name);
1294 strcpy(mask,p+1);
1297 if (is_mangled(mask))
1298 check_mangled_stack(mask);
1300 has_wild = strchr(mask,'*') || strchr(mask,'?');
1302 if (!has_wild) {
1303 strcat(directory,"/");
1304 strcat(directory,mask);
1305 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1306 if (!count) exists = file_exist(directory,NULL);
1307 } else {
1308 void *dirptr = NULL;
1309 char *dname;
1311 if (check_name(directory,cnum))
1312 dirptr = OpenDir(directory);
1314 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1315 the pattern matches against the long name, otherwise the short name
1316 We don't implement this yet XXXX
1319 if (dirptr)
1321 error = ERRbadfile;
1323 if (strequal(mask,"????????.???"))
1324 strcpy(mask,"*");
1326 while ((dname = ReadDirName(dirptr)))
1328 pstring fname;
1329 strcpy(fname,dname);
1331 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1333 error = ERRnoaccess;
1334 sprintf(fname,"%s/%s",directory,dname);
1335 if (!can_delete(fname,cnum,dirtype)) continue;
1336 if (!sys_unlink(fname)) count++;
1337 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1339 CloseDir(dirptr);
1343 if (count == 0) {
1344 if (exists)
1345 return(ERROR(ERRDOS,error));
1346 else
1347 return(UNIXERROR(ERRDOS,error));
1350 outsize = set_message(outbuf,0,0,True);
1352 return(outsize);
1356 /****************************************************************************
1357 reply to a readbraw (core+ protocol)
1358 ****************************************************************************/
1359 int reply_readbraw(char *inbuf, char *outbuf)
1361 int cnum,maxcount,mincount,fnum;
1362 int nread = 0;
1363 int startpos;
1364 char *header = outbuf;
1365 int ret=0;
1366 int fd;
1367 char *fname;
1369 cnum = SVAL(inbuf,smb_tid);
1370 fnum = GETFNUM(inbuf,smb_vwv0);
1372 startpos = IVAL(inbuf,smb_vwv1);
1373 maxcount = SVAL(inbuf,smb_vwv3);
1374 mincount = SVAL(inbuf,smb_vwv4);
1376 /* ensure we don't overrun the packet size */
1377 maxcount = MIN(65535,maxcount);
1378 maxcount = MAX(mincount,maxcount);
1380 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1382 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1383 _smb_setlen(header,0);
1384 transfer_file(0,Client,0,header,4,0);
1385 return(-1);
1387 else
1389 fd = Files[fnum].fd_ptr->fd;
1390 fname = Files[fnum].name;
1394 if (!is_locked(fnum,cnum,maxcount,startpos))
1396 int size = Files[fnum].size;
1397 int sizeneeded = startpos + maxcount;
1399 if (size < sizeneeded) {
1400 struct stat st;
1401 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1402 size = st.st_size;
1403 if (!Files[fnum].can_write)
1404 Files[fnum].size = size;
1407 nread = MIN(maxcount,size - startpos);
1410 if (nread < mincount)
1411 nread = 0;
1413 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1414 timestring(),
1415 fnum,cnum,startpos,
1416 maxcount,mincount,nread));
1418 #if UNSAFE_READRAW
1420 int predict=0;
1421 _smb_setlen(header,nread);
1423 if (!Files[fnum].can_write)
1424 predict = read_predict(fd,startpos,header+4,NULL,nread);
1426 if ((nread-predict) > 0)
1427 seek_file(fnum,startpos + predict);
1429 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1430 startpos+predict);
1433 if (ret != nread+4)
1434 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1435 fname,startpos,nread,ret));
1437 #else
1438 ret = read_file(fnum,header+4,startpos,nread);
1439 if (ret < mincount) ret = 0;
1441 _smb_setlen(header,ret);
1442 transfer_file(0,Client,0,header,4+ret,0);
1443 #endif
1445 DEBUG(5,("readbraw finished\n"));
1446 return -1;
1450 /****************************************************************************
1451 reply to a lockread (core+ protocol)
1452 ****************************************************************************/
1453 int reply_lockread(char *inbuf,char *outbuf)
1455 int cnum,fnum;
1456 int nread = -1;
1457 char *data;
1458 int outsize = 0;
1459 uint32 startpos, numtoread;
1460 int eclass;
1461 uint32 ecode;
1463 cnum = SVAL(inbuf,smb_tid);
1464 fnum = GETFNUM(inbuf,smb_vwv0);
1466 CHECK_FNUM(fnum,cnum);
1467 CHECK_READ(fnum);
1468 CHECK_ERROR(fnum);
1470 numtoread = SVAL(inbuf,smb_vwv1);
1471 startpos = IVAL(inbuf,smb_vwv2);
1473 outsize = set_message(outbuf,5,3,True);
1474 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1475 data = smb_buf(outbuf) + 3;
1477 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1478 return (ERROR(eclass,ecode));
1480 nread = read_file(fnum,data,startpos,numtoread);
1482 if (nread < 0)
1483 return(UNIXERROR(ERRDOS,ERRnoaccess));
1485 outsize += nread;
1486 SSVAL(outbuf,smb_vwv0,nread);
1487 SSVAL(outbuf,smb_vwv5,nread+3);
1488 SSVAL(smb_buf(outbuf),1,nread);
1490 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1492 return(outsize);
1496 /****************************************************************************
1497 reply to a read
1498 ****************************************************************************/
1499 int reply_read(char *inbuf,char *outbuf)
1501 int cnum,numtoread,fnum;
1502 int nread = 0;
1503 char *data;
1504 int startpos;
1505 int outsize = 0;
1507 cnum = SVAL(inbuf,smb_tid);
1508 fnum = GETFNUM(inbuf,smb_vwv0);
1510 CHECK_FNUM(fnum,cnum);
1511 CHECK_READ(fnum);
1512 CHECK_ERROR(fnum);
1514 numtoread = SVAL(inbuf,smb_vwv1);
1515 startpos = IVAL(inbuf,smb_vwv2);
1517 outsize = set_message(outbuf,5,3,True);
1518 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1519 data = smb_buf(outbuf) + 3;
1521 if (is_locked(fnum,cnum,numtoread,startpos))
1522 return(ERROR(ERRDOS,ERRlock));
1524 if (numtoread > 0)
1525 nread = read_file(fnum,data,startpos,numtoread);
1527 if (nread < 0)
1528 return(UNIXERROR(ERRDOS,ERRnoaccess));
1530 outsize += nread;
1531 SSVAL(outbuf,smb_vwv0,nread);
1532 SSVAL(outbuf,smb_vwv5,nread+3);
1533 CVAL(smb_buf(outbuf),0) = 1;
1534 SSVAL(smb_buf(outbuf),1,nread);
1536 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1538 return(outsize);
1542 /****************************************************************************
1543 reply to a read and X
1544 ****************************************************************************/
1545 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1547 int fnum = GETFNUM(inbuf,smb_vwv2);
1548 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1549 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1550 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1551 int cnum;
1552 int nread = -1;
1553 char *data;
1554 BOOL ok = False;
1556 cnum = SVAL(inbuf,smb_tid);
1558 CHECK_FNUM(fnum,cnum);
1559 CHECK_READ(fnum);
1560 CHECK_ERROR(fnum);
1562 set_message(outbuf,12,0,True);
1563 data = smb_buf(outbuf);
1565 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1566 return(ERROR(ERRDOS,ERRlock));
1567 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1568 ok = True;
1570 if (nread < 0)
1571 return(UNIXERROR(ERRDOS,ERRnoaccess));
1573 SSVAL(outbuf,smb_vwv5,nread);
1574 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1575 SSVAL(smb_buf(outbuf),-2,nread);
1577 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1578 timestring(),fnum,cnum,
1579 smb_mincnt,smb_maxcnt,nread));
1581 chain_fnum = fnum;
1583 return chain_reply(inbuf,outbuf,length,bufsize);
1587 /****************************************************************************
1588 reply to a writebraw (core+ or LANMAN1.0 protocol)
1589 ****************************************************************************/
1590 int reply_writebraw(char *inbuf,char *outbuf)
1592 int nwritten=0;
1593 int total_written=0;
1594 int numtowrite=0;
1595 int cnum,fnum;
1596 int outsize = 0;
1597 long startpos;
1598 char *data=NULL;
1599 BOOL write_through;
1600 int tcount;
1602 cnum = SVAL(inbuf,smb_tid);
1603 fnum = GETFNUM(inbuf,smb_vwv0);
1605 CHECK_FNUM(fnum,cnum);
1606 CHECK_WRITE(fnum);
1607 CHECK_ERROR(fnum);
1609 tcount = IVAL(inbuf,smb_vwv1);
1610 startpos = IVAL(inbuf,smb_vwv3);
1611 write_through = BITSETW(inbuf+smb_vwv7,0);
1613 /* We have to deal with slightly different formats depending
1614 on whether we are using the core+ or lanman1.0 protocol */
1615 if(Protocol <= PROTOCOL_COREPLUS) {
1616 numtowrite = SVAL(smb_buf(inbuf),-2);
1617 data = smb_buf(inbuf);
1618 } else {
1619 numtowrite = SVAL(inbuf,smb_vwv10);
1620 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1623 /* force the error type */
1624 CVAL(inbuf,smb_com) = SMBwritec;
1625 CVAL(outbuf,smb_com) = SMBwritec;
1627 if (is_locked(fnum,cnum,tcount,startpos))
1628 return(ERROR(ERRDOS,ERRlock));
1630 if (seek_file(fnum,startpos) != startpos)
1631 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1633 if (numtowrite>0)
1634 nwritten = write_file(fnum,data,numtowrite);
1636 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1637 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1639 if (nwritten < numtowrite)
1640 return(UNIXERROR(ERRHRD,ERRdiskfull));
1642 total_written = nwritten;
1644 /* Return a message to the redirector to tell it
1645 to send more bytes */
1646 CVAL(outbuf,smb_com) = SMBwritebraw;
1647 SSVALS(outbuf,smb_vwv0,-1);
1648 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1649 send_smb(Client,outbuf);
1651 /* Now read the raw data into the buffer and write it */
1652 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1653 exit_server("secondary writebraw failed");
1656 /* Even though this is not an smb message, smb_len
1657 returns the generic length of an smb message */
1658 numtowrite = smb_len(inbuf);
1660 if (tcount > nwritten+numtowrite) {
1661 DEBUG(3,("Client overestimated the write %d %d %d\n",
1662 tcount,nwritten,numtowrite));
1665 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1666 startpos+nwritten);
1667 total_written += nwritten;
1669 /* Set up outbuf to return the correct return */
1670 outsize = set_message(outbuf,1,0,True);
1671 CVAL(outbuf,smb_com) = SMBwritec;
1672 SSVAL(outbuf,smb_vwv0,total_written);
1674 if (nwritten < numtowrite) {
1675 CVAL(outbuf,smb_rcls) = ERRHRD;
1676 SSVAL(outbuf,smb_err,ERRdiskfull);
1679 if (lp_syncalways(SNUM(cnum)) || write_through)
1680 sync_file(fnum);
1682 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1683 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1685 /* we won't return a status if write through is not selected - this
1686 follows what WfWg does */
1687 if (!write_through && total_written==tcount)
1688 return(-1);
1690 return(outsize);
1694 /****************************************************************************
1695 reply to a writeunlock (core+)
1696 ****************************************************************************/
1697 int reply_writeunlock(char *inbuf,char *outbuf)
1699 int cnum,fnum;
1700 int nwritten = -1;
1701 int outsize = 0;
1702 char *data;
1703 uint32 numtowrite,startpos;
1704 int eclass;
1705 uint32 ecode;
1707 cnum = SVAL(inbuf,smb_tid);
1708 fnum = GETFNUM(inbuf,smb_vwv0);
1710 CHECK_FNUM(fnum,cnum);
1711 CHECK_WRITE(fnum);
1712 CHECK_ERROR(fnum);
1714 numtowrite = SVAL(inbuf,smb_vwv1);
1715 startpos = IVAL(inbuf,smb_vwv2);
1716 data = smb_buf(inbuf) + 3;
1718 if (is_locked(fnum,cnum,numtowrite,startpos))
1719 return(ERROR(ERRDOS,ERRlock));
1721 seek_file(fnum,startpos);
1723 /* The special X/Open SMB protocol handling of
1724 zero length writes is *NOT* done for
1725 this call */
1726 if(numtowrite == 0)
1727 nwritten = 0;
1728 else
1729 nwritten = write_file(fnum,data,numtowrite);
1731 if (lp_syncalways(SNUM(cnum)))
1732 sync_file(fnum);
1734 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1735 return(UNIXERROR(ERRDOS,ERRnoaccess));
1737 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1738 return(ERROR(eclass,ecode));
1740 outsize = set_message(outbuf,1,0,True);
1742 SSVAL(outbuf,smb_vwv0,nwritten);
1744 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1745 timestring(),fnum,cnum,numtowrite,nwritten));
1747 return(outsize);
1751 /****************************************************************************
1752 reply to a write
1753 ****************************************************************************/
1754 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1756 int cnum,numtowrite,fnum;
1757 int nwritten = -1;
1758 int outsize = 0;
1759 int startpos;
1760 char *data;
1762 dum1 = dum2 = 0;
1765 cnum = SVAL(inbuf,smb_tid);
1766 fnum = GETFNUM(inbuf,smb_vwv0);
1768 CHECK_FNUM(fnum,cnum);
1769 CHECK_WRITE(fnum);
1770 CHECK_ERROR(fnum);
1772 numtowrite = SVAL(inbuf,smb_vwv1);
1773 startpos = IVAL(inbuf,smb_vwv2);
1774 data = smb_buf(inbuf) + 3;
1776 if (is_locked(fnum,cnum,numtowrite,startpos))
1777 return(ERROR(ERRDOS,ERRlock));
1779 seek_file(fnum,startpos);
1781 /* X/Open SMB protocol says that if smb_vwv1 is
1782 zero then the file size should be extended or
1783 truncated to the size given in smb_vwv[2-3] */
1784 if(numtowrite == 0)
1785 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
1786 else
1787 nwritten = write_file(fnum,data,numtowrite);
1789 if (lp_syncalways(SNUM(cnum)))
1790 sync_file(fnum);
1792 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1793 return(UNIXERROR(ERRDOS,ERRnoaccess));
1795 outsize = set_message(outbuf,1,0,True);
1797 SSVAL(outbuf,smb_vwv0,nwritten);
1799 if (nwritten < numtowrite) {
1800 CVAL(outbuf,smb_rcls) = ERRHRD;
1801 SSVAL(outbuf,smb_err,ERRdiskfull);
1804 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1806 return(outsize);
1810 /****************************************************************************
1811 reply to a write and X
1812 ****************************************************************************/
1813 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1815 int fnum = GETFNUM(inbuf,smb_vwv2);
1816 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1817 int smb_dsize = SVAL(inbuf,smb_vwv10);
1818 int smb_doff = SVAL(inbuf,smb_vwv11);
1819 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1820 int cnum;
1821 int nwritten = -1;
1822 char *data;
1824 cnum = SVAL(inbuf,smb_tid);
1826 CHECK_FNUM(fnum,cnum);
1827 CHECK_WRITE(fnum);
1828 CHECK_ERROR(fnum);
1830 data = smb_base(inbuf) + smb_doff;
1832 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1833 return(ERROR(ERRDOS,ERRlock));
1835 seek_file(fnum,smb_offs);
1837 /* X/Open SMB protocol says that, unlike SMBwrite
1838 if the length is zero then NO truncation is
1839 done, just a write of zero. To truncate a file,
1840 use SMBwrite. */
1841 if(smb_dsize == 0)
1842 nwritten = 0;
1843 else
1844 nwritten = write_file(fnum,data,smb_dsize);
1846 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1847 return(UNIXERROR(ERRDOS,ERRnoaccess));
1849 set_message(outbuf,6,0,True);
1851 SSVAL(outbuf,smb_vwv2,nwritten);
1853 if (nwritten < smb_dsize) {
1854 CVAL(outbuf,smb_rcls) = ERRHRD;
1855 SSVAL(outbuf,smb_err,ERRdiskfull);
1858 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1860 chain_fnum = fnum;
1862 if (lp_syncalways(SNUM(cnum)) || write_through)
1863 sync_file(fnum);
1865 return chain_reply(inbuf,outbuf,length,bufsize);
1869 /****************************************************************************
1870 reply to a lseek
1871 ****************************************************************************/
1872 int reply_lseek(char *inbuf,char *outbuf)
1874 int cnum,fnum;
1875 uint32 startpos;
1876 int32 res= -1;
1877 int mode,umode;
1878 int outsize = 0;
1880 cnum = SVAL(inbuf,smb_tid);
1881 fnum = GETFNUM(inbuf,smb_vwv0);
1883 CHECK_FNUM(fnum,cnum);
1884 CHECK_ERROR(fnum);
1886 mode = SVAL(inbuf,smb_vwv1) & 3;
1887 startpos = IVAL(inbuf,smb_vwv2);
1889 switch (mode & 3)
1891 case 0: umode = SEEK_SET; break;
1892 case 1: umode = SEEK_CUR; break;
1893 case 2: umode = SEEK_END; break;
1894 default:
1895 umode = SEEK_SET; break;
1898 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
1899 Files[fnum].pos = res;
1901 outsize = set_message(outbuf,2,0,True);
1902 SIVALS(outbuf,smb_vwv0,res);
1904 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1906 return(outsize);
1910 /****************************************************************************
1911 reply to a flush
1912 ****************************************************************************/
1913 int reply_flush(char *inbuf,char *outbuf)
1915 int cnum, fnum;
1916 int outsize = set_message(outbuf,0,0,True);
1918 cnum = SVAL(inbuf,smb_tid);
1919 fnum = GETFNUM(inbuf,smb_vwv0);
1921 if (fnum != 0xFFFF) {
1922 CHECK_FNUM(fnum,cnum);
1923 CHECK_ERROR(fnum);
1926 if (fnum == 0xFFFF)
1928 int i;
1929 for (i=0;i<MAX_OPEN_FILES;i++)
1930 if (OPEN_FNUM(i))
1931 sync_file(i);
1933 else
1934 sync_file(fnum);
1936 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1937 return(outsize);
1941 /****************************************************************************
1942 reply to a exit
1943 ****************************************************************************/
1944 int reply_exit(char *inbuf,char *outbuf)
1946 int outsize = set_message(outbuf,0,0,True);
1947 DEBUG(3,("%s exit\n",timestring()));
1949 return(outsize);
1953 /****************************************************************************
1954 reply to a close
1955 ****************************************************************************/
1956 int reply_close(char *inbuf,char *outbuf)
1958 int fnum,cnum;
1959 int outsize = 0;
1960 time_t mtime;
1961 int32 eclass = 0, err = 0;
1963 outsize = set_message(outbuf,0,0,True);
1965 cnum = SVAL(inbuf,smb_tid);
1967 fnum = GETFNUM(inbuf,smb_vwv0);
1968 CHECK_FNUM(fnum,cnum);
1970 if(HAS_CACHED_ERROR(fnum)) {
1971 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1972 err = Files[fnum].wbmpx_ptr->wr_error;
1975 mtime = make_unix_date3(inbuf+smb_vwv1);
1977 /* try and set the date */
1978 set_filetime(Files[fnum].name,mtime);
1980 close_file(fnum);
1982 /* We have a cached error */
1983 if(eclass || err)
1984 return(ERROR(eclass,err));
1986 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
1987 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
1988 Connections[cnum].num_files_open));
1990 return(outsize);
1994 /****************************************************************************
1995 reply to a writeclose (Core+ protocol)
1996 ****************************************************************************/
1997 int reply_writeclose(char *inbuf,char *outbuf)
1999 int cnum,numtowrite,fnum;
2000 int nwritten = -1;
2001 int outsize = 0;
2002 int startpos;
2003 char *data;
2004 time_t mtime;
2006 cnum = SVAL(inbuf,smb_tid);
2007 fnum = GETFNUM(inbuf,smb_vwv0);
2009 CHECK_FNUM(fnum,cnum);
2010 CHECK_WRITE(fnum);
2011 CHECK_ERROR(fnum);
2013 numtowrite = SVAL(inbuf,smb_vwv1);
2014 startpos = IVAL(inbuf,smb_vwv2);
2015 mtime = make_unix_date3(inbuf+smb_vwv4);
2016 data = smb_buf(inbuf) + 1;
2018 if (is_locked(fnum,cnum,numtowrite,startpos))
2019 return(ERROR(ERRDOS,ERRlock));
2021 seek_file(fnum,startpos);
2023 nwritten = write_file(fnum,data,numtowrite);
2025 set_filetime(Files[fnum].name,mtime);
2027 close_file(fnum);
2029 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2030 timestring(),fnum,cnum,numtowrite,nwritten,
2031 Connections[cnum].num_files_open));
2033 if (nwritten <= 0)
2034 return(UNIXERROR(ERRDOS,ERRnoaccess));
2036 outsize = set_message(outbuf,1,0,True);
2038 SSVAL(outbuf,smb_vwv0,nwritten);
2039 return(outsize);
2043 /****************************************************************************
2044 reply to a lock
2045 ****************************************************************************/
2046 int reply_lock(char *inbuf,char *outbuf)
2048 int fnum,cnum;
2049 int outsize = set_message(outbuf,0,0,True);
2050 uint32 count,offset;
2051 int eclass;
2052 uint32 ecode;
2054 cnum = SVAL(inbuf,smb_tid);
2055 fnum = GETFNUM(inbuf,smb_vwv0);
2057 CHECK_FNUM(fnum,cnum);
2058 CHECK_ERROR(fnum);
2060 count = IVAL(inbuf,smb_vwv1);
2061 offset = IVAL(inbuf,smb_vwv3);
2063 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));
2065 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2066 return (ERROR(eclass,ecode));
2068 return(outsize);
2072 /****************************************************************************
2073 reply to a unlock
2074 ****************************************************************************/
2075 int reply_unlock(char *inbuf,char *outbuf)
2077 int fnum,cnum;
2078 int outsize = set_message(outbuf,0,0,True);
2079 uint32 count,offset;
2080 int eclass;
2081 uint32 ecode;
2083 cnum = SVAL(inbuf,smb_tid);
2084 fnum = GETFNUM(inbuf,smb_vwv0);
2086 CHECK_FNUM(fnum,cnum);
2087 CHECK_ERROR(fnum);
2089 count = IVAL(inbuf,smb_vwv1);
2090 offset = IVAL(inbuf,smb_vwv3);
2092 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2093 return (ERROR(eclass,ecode));
2095 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));
2097 return(outsize);
2101 /****************************************************************************
2102 reply to a tdis
2103 ****************************************************************************/
2104 int reply_tdis(char *inbuf,char *outbuf)
2106 int cnum;
2107 int outsize = set_message(outbuf,0,0,True);
2108 uint16 vuid;
2110 cnum = SVAL(inbuf,smb_tid);
2111 vuid = SVAL(inbuf,smb_uid);
2113 if (!OPEN_CNUM(cnum)) {
2114 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2115 return(ERROR(ERRSRV,ERRinvnid));
2118 Connections[cnum].used = False;
2120 close_cnum(cnum,vuid);
2122 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2124 return outsize;
2129 /****************************************************************************
2130 reply to a echo
2131 ****************************************************************************/
2132 int reply_echo(char *inbuf,char *outbuf)
2134 int cnum;
2135 int smb_reverb = SVAL(inbuf,smb_vwv0);
2136 int seq_num;
2137 int data_len = smb_buflen(inbuf);
2138 int outsize = set_message(outbuf,1,data_len,True);
2140 cnum = SVAL(inbuf,smb_tid);
2142 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2144 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2145 return(ERROR(ERRSRV,ERRinvnid));
2148 /* copy any incoming data back out */
2149 if (data_len > 0)
2150 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2152 if (smb_reverb > 100)
2154 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2155 smb_reverb = 100;
2158 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2160 SSVAL(outbuf,smb_vwv0,seq_num);
2162 smb_setlen(outbuf,outsize - 4);
2164 send_smb(Client,outbuf);
2167 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2169 return -1;
2173 /****************************************************************************
2174 reply to a printopen
2175 ****************************************************************************/
2176 int reply_printopen(char *inbuf,char *outbuf)
2178 pstring fname;
2179 pstring fname2;
2180 int cnum;
2181 int fnum = -1;
2182 int outsize = 0;
2184 *fname = *fname2 = 0;
2186 cnum = SVAL(inbuf,smb_tid);
2188 if (!CAN_PRINT(cnum))
2189 return(ERROR(ERRDOS,ERRnoaccess));
2192 pstring s;
2193 char *p;
2194 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2195 p = s;
2196 while (*p)
2198 if (!(isalnum(*p) || strchr("._-",*p)))
2199 *p = 'X';
2200 p++;
2203 if (strlen(s) > 10) s[10] = 0;
2205 sprintf(fname,"%s.XXXXXX",s);
2208 fnum = find_free_file();
2209 if (fnum < 0)
2210 return(ERROR(ERRSRV,ERRnofids));
2212 strcpy(fname2,(char *)mktemp(fname));
2214 if (!check_name(fname2,cnum))
2215 return(ERROR(ERRDOS,ERRnoaccess));
2217 open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC,
2218 unix_mode(cnum,0), 0);
2220 if (!Files[fnum].open)
2221 return(UNIXERROR(ERRDOS,ERRnoaccess));
2223 /* force it to be a print file */
2224 Files[fnum].print_file = True;
2226 outsize = set_message(outbuf,1,0,True);
2227 SSVAL(outbuf,smb_vwv0,fnum);
2229 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2231 return(outsize);
2235 /****************************************************************************
2236 reply to a printclose
2237 ****************************************************************************/
2238 int reply_printclose(char *inbuf,char *outbuf)
2240 int fnum,cnum;
2241 int outsize = set_message(outbuf,0,0,True);
2243 cnum = SVAL(inbuf,smb_tid);
2244 fnum = GETFNUM(inbuf,smb_vwv0);
2246 CHECK_FNUM(fnum,cnum);
2247 CHECK_ERROR(fnum);
2249 if (!CAN_PRINT(cnum))
2250 return(ERROR(ERRDOS,ERRnoaccess));
2252 close_file(fnum);
2254 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2256 return(outsize);
2260 /****************************************************************************
2261 reply to a printqueue
2262 ****************************************************************************/
2263 int reply_printqueue(char *inbuf,char *outbuf)
2265 int cnum;
2266 int outsize = set_message(outbuf,2,3,True);
2267 int max_count = SVAL(inbuf,smb_vwv0);
2268 int start_index = SVAL(inbuf,smb_vwv1);
2269 uint16 vuid;
2271 cnum = SVAL(inbuf,smb_tid);
2272 vuid = SVAL(inbuf,smb_uid);
2274 /* allow checking the queue for anyone */
2275 #if 0
2276 if (!CAN_PRINT(cnum))
2277 return(ERROR(ERRDOS,ERRnoaccess));
2278 #endif
2280 SSVAL(outbuf,smb_vwv0,0);
2281 SSVAL(outbuf,smb_vwv1,0);
2282 CVAL(smb_buf(outbuf),0) = 1;
2283 SSVAL(smb_buf(outbuf),1,0);
2285 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2286 timestring(),cnum,start_index,max_count));
2288 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2290 int i;
2291 cnum = -1;
2293 for (i=0;i<MAX_CONNECTIONS;i++)
2294 if (CAN_PRINT(i) && Connections[i].printer)
2295 cnum = i;
2297 if (cnum == -1)
2298 for (i=0;i<MAX_CONNECTIONS;i++)
2299 if (OPEN_CNUM(i))
2300 cnum = i;
2302 if (!OPEN_CNUM(cnum))
2303 return(ERROR(ERRSRV,ERRinvnid));
2305 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2308 if (!become_user(cnum,vuid))
2309 return(ERROR(ERRSRV,ERRinvnid));
2312 print_queue_struct *queue = NULL;
2313 char *p = smb_buf(outbuf) + 3;
2314 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2315 int num_to_get = ABS(max_count);
2316 int first = (max_count>0?start_index:start_index+max_count+1);
2317 int i;
2319 if (first >= count)
2320 num_to_get = 0;
2321 else
2322 num_to_get = MIN(num_to_get,count-first);
2325 for (i=first;i<first+num_to_get;i++)
2327 put_dos_date2(p,0,queue[i].time);
2328 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2329 SSVAL(p,5,queue[i].job);
2330 SIVAL(p,7,queue[i].size);
2331 CVAL(p,11) = 0;
2332 StrnCpy(p+12,queue[i].user,16);
2333 p += 28;
2336 if (count > 0)
2338 outsize = set_message(outbuf,2,28*count+3,False);
2339 SSVAL(outbuf,smb_vwv0,count);
2340 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2341 CVAL(smb_buf(outbuf),0) = 1;
2342 SSVAL(smb_buf(outbuf),1,28*count);
2345 if (queue) free(queue);
2347 DEBUG(3,("%d entries returned in queue\n",count));
2350 return(outsize);
2354 /****************************************************************************
2355 reply to a printwrite
2356 ****************************************************************************/
2357 int reply_printwrite(char *inbuf,char *outbuf)
2359 int cnum,numtowrite,fnum;
2360 int outsize = set_message(outbuf,0,0,True);
2361 char *data;
2363 cnum = SVAL(inbuf,smb_tid);
2365 if (!CAN_PRINT(cnum))
2366 return(ERROR(ERRDOS,ERRnoaccess));
2368 fnum = GETFNUM(inbuf,smb_vwv0);
2370 CHECK_FNUM(fnum,cnum);
2371 CHECK_WRITE(fnum);
2372 CHECK_ERROR(fnum);
2374 numtowrite = SVAL(smb_buf(inbuf),1);
2375 data = smb_buf(inbuf) + 3;
2377 if (write_file(fnum,data,numtowrite) != numtowrite)
2378 return(UNIXERROR(ERRDOS,ERRnoaccess));
2380 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2382 return(outsize);
2386 /****************************************************************************
2387 reply to a mkdir
2388 ****************************************************************************/
2389 int reply_mkdir(char *inbuf,char *outbuf)
2391 pstring directory;
2392 int cnum;
2393 int outsize,ret= -1;
2395 strcpy(directory,smb_buf(inbuf) + 1);
2396 cnum = SVAL(inbuf,smb_tid);
2397 unix_convert(directory,cnum,0);
2399 if (check_name(directory,cnum))
2400 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2402 if (ret < 0)
2403 return(UNIXERROR(ERRDOS,ERRnoaccess));
2405 outsize = set_message(outbuf,0,0,True);
2407 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2409 return(outsize);
2413 /****************************************************************************
2414 reply to a rmdir
2415 ****************************************************************************/
2416 int reply_rmdir(char *inbuf,char *outbuf)
2418 pstring directory;
2419 int cnum;
2420 int outsize = 0;
2421 BOOL ok = False;
2423 cnum = SVAL(inbuf,smb_tid);
2424 strcpy(directory,smb_buf(inbuf) + 1);
2425 unix_convert(directory,cnum,0);
2427 if (check_name(directory,cnum))
2429 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2430 ok = (sys_rmdir(directory) == 0);
2431 if (!ok)
2432 DEBUG(3,("couldn't remove directory %s : %s\n",
2433 directory,strerror(errno)));
2436 if (!ok)
2437 return(UNIXERROR(ERRDOS,ERRbadpath));
2439 outsize = set_message(outbuf,0,0,True);
2441 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2443 return(outsize);
2447 /*******************************************************************
2448 resolve wildcards in a filename rename
2449 ********************************************************************/
2450 static BOOL resolve_wildcards(char *name1,char *name2)
2452 fstring root1,root2;
2453 fstring ext1,ext2;
2454 char *p,*p2;
2456 name1 = strrchr(name1,'/');
2457 name2 = strrchr(name2,'/');
2459 if (!name1 || !name2) return(False);
2461 strcpy(root1,name1);
2462 strcpy(root2,name2);
2463 p = strrchr(root1,'.');
2464 if (p) {
2465 *p = 0;
2466 strcpy(ext1,p+1);
2467 } else {
2468 strcpy(ext1,"");
2470 p = strrchr(root2,'.');
2471 if (p) {
2472 *p = 0;
2473 strcpy(ext2,p+1);
2474 } else {
2475 strcpy(ext2,"");
2478 p = root1;
2479 p2 = root2;
2480 while (*p2) {
2481 if (*p2 == '?') {
2482 *p2 = *p;
2483 p2++;
2484 } else {
2485 p2++;
2487 if (*p) p++;
2490 p = ext1;
2491 p2 = ext2;
2492 while (*p2) {
2493 if (*p2 == '?') {
2494 *p2 = *p;
2495 p2++;
2496 } else {
2497 p2++;
2499 if (*p) p++;
2502 strcpy(name2,root2);
2503 if (ext2[0]) {
2504 strcat(name2,".");
2505 strcat(name2,ext2);
2508 return(True);
2511 /*******************************************************************
2512 check if a user is allowed to rename a file
2513 ********************************************************************/
2514 static BOOL can_rename(char *fname,int cnum)
2516 struct stat sbuf;
2518 if (!CAN_WRITE(cnum)) return(False);
2520 if (sys_lstat(fname,&sbuf) != 0) return(False);
2521 if (!check_file_sharing(cnum,fname)) return(False);
2523 return(True);
2526 /****************************************************************************
2527 reply to a mv
2528 ****************************************************************************/
2529 int reply_mv(char *inbuf,char *outbuf)
2531 int outsize = 0;
2532 pstring name;
2533 int cnum;
2534 pstring directory;
2535 pstring mask,newname;
2536 pstring newname_last_component;
2537 char *p;
2538 int count=0;
2539 int error = ERRnoaccess;
2540 BOOL has_wild;
2541 BOOL exists=False;
2543 *directory = *mask = 0;
2545 cnum = SVAL(inbuf,smb_tid);
2547 strcpy(name,smb_buf(inbuf) + 1);
2548 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2550 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2552 unix_convert(name,cnum,0);
2553 unix_convert(newname,cnum,newname_last_component);
2555 p = strrchr(name,'/');
2556 if (!p) {
2557 strcpy(directory,"./");
2558 strcpy(mask,name);
2559 } else {
2560 *p = 0;
2561 strcpy(directory,name);
2562 strcpy(mask,p+1);
2563 *p = '/'; /* Replace needed for exceptional test below. */
2566 if (is_mangled(mask))
2567 check_mangled_stack(mask);
2569 has_wild = strchr(mask,'*') || strchr(mask,'?');
2571 if (!has_wild) {
2572 strcat(directory,"/");
2573 strcat(directory,mask);
2575 DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, name = %s, newname = %s, newname_last_component = %s\n", case_sensitive, case_preserve, name, newname, newname_last_component));
2578 * Check for special case with case preserving and not
2579 * case sensitive, if name and newname are identical,
2580 * and the old last component differs from the original
2581 * last component only by case, then we should allow
2582 * the rename (user is trying to change the case of the
2583 * filename).
2585 if((case_sensitive == False) && (case_preserve == True) &&
2586 strcsequal(name, newname)) {
2587 pstring newname_modified_last_component;
2590 * Get the last component of the modified name.
2592 p = strrchr(newname,'/');
2593 if (!p)
2594 strcpy(newname_modified_last_component,name);
2595 else
2596 strcpy(newname_modified_last_component,p+1);
2598 if(strcsequal(newname_modified_last_component,
2599 newname_last_component) == False) {
2601 * Replace the modified last component with
2602 * the original.
2604 if(p)
2605 strcpy(p+1, newname_last_component);
2606 else
2607 strcpy(newname, newname_last_component);
2611 if (resolve_wildcards(directory,newname) &&
2612 can_rename(directory,cnum) &&
2613 !file_exist(newname,NULL) &&
2614 !sys_rename(directory,newname)) count++;
2616 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",directory,newname));
2618 if (!count) exists = file_exist(directory,NULL);
2619 if (!count && exists && file_exist(newname,NULL)) {
2620 exists = True;
2621 error = 183;
2623 } else {
2624 void *dirptr = NULL;
2625 char *dname;
2626 pstring destname;
2628 if (check_name(directory,cnum))
2629 dirptr = OpenDir(directory);
2631 if (dirptr)
2633 error = ERRbadfile;
2635 if (strequal(mask,"????????.???"))
2636 strcpy(mask,"*");
2638 while ((dname = ReadDirName(dirptr)))
2640 pstring fname;
2641 strcpy(fname,dname);
2643 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2645 error = ERRnoaccess;
2646 sprintf(fname,"%s/%s",directory,dname);
2647 if (!can_rename(fname,cnum)) continue;
2648 strcpy(destname,newname);
2650 if (!resolve_wildcards(fname,destname)) continue;
2652 if (file_exist(destname,NULL)) {
2653 error = 183;
2654 continue;
2656 if (!sys_rename(fname,destname)) count++;
2657 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2659 CloseDir(dirptr);
2663 if (count == 0) {
2664 if (exists)
2665 return(ERROR(ERRDOS,error));
2666 else
2667 return(UNIXERROR(ERRDOS,error));
2670 outsize = set_message(outbuf,0,0,True);
2672 return(outsize);
2675 /*******************************************************************
2676 copy a file as part of a reply_copy
2677 ******************************************************************/
2678 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2679 int count,BOOL target_is_directory)
2681 int Access,action;
2682 struct stat st;
2683 int ret=0;
2684 int fnum1,fnum2;
2685 pstring dest;
2687 strcpy(dest,dest1);
2688 if (target_is_directory) {
2689 char *p = strrchr(src,'/');
2690 if (p)
2691 p++;
2692 else
2693 p = src;
2694 strcat(dest,"/");
2695 strcat(dest,p);
2698 if (!file_exist(src,&st)) return(False);
2700 fnum1 = find_free_file();
2701 if (fnum1<0) return(False);
2702 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2703 1,0,&Access,&action);
2705 if (!Files[fnum1].open) return(False);
2707 if (!target_is_directory && count)
2708 ofun = 1;
2710 fnum2 = find_free_file();
2711 if (fnum2<0) {
2712 close_file(fnum1);
2713 return(False);
2715 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2716 ofun,st.st_mode,&Access,&action);
2718 if (!Files[fnum2].open) {
2719 close_file(fnum1);
2720 return(False);
2723 if ((ofun&3) == 1) {
2724 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
2727 if (st.st_size)
2728 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
2730 close_file(fnum1);
2731 close_file(fnum2);
2733 return(ret == st.st_size);
2738 /****************************************************************************
2739 reply to a file copy.
2740 ****************************************************************************/
2741 int reply_copy(char *inbuf,char *outbuf)
2743 int outsize = 0;
2744 pstring name;
2745 int cnum;
2746 pstring directory;
2747 pstring mask,newname;
2748 char *p;
2749 int count=0;
2750 int error = ERRnoaccess;
2751 BOOL has_wild;
2752 BOOL exists=False;
2753 int tid2 = SVAL(inbuf,smb_vwv0);
2754 int ofun = SVAL(inbuf,smb_vwv1);
2755 int flags = SVAL(inbuf,smb_vwv2);
2756 BOOL target_is_directory=False;
2758 *directory = *mask = 0;
2760 cnum = SVAL(inbuf,smb_tid);
2762 strcpy(name,smb_buf(inbuf));
2763 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2765 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2767 if (tid2 != cnum) {
2768 /* can't currently handle inter share copies XXXX */
2769 DEBUG(3,("Rejecting inter-share copy\n"));
2770 return(ERROR(ERRSRV,ERRinvdevice));
2773 unix_convert(name,cnum,0);
2774 unix_convert(newname,cnum,0);
2776 target_is_directory = directory_exist(newname,NULL);
2778 if ((flags&1) && target_is_directory) {
2779 return(ERROR(ERRDOS,ERRbadfile));
2782 if ((flags&2) && !target_is_directory) {
2783 return(ERROR(ERRDOS,ERRbadpath));
2786 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2787 /* wants a tree copy! XXXX */
2788 DEBUG(3,("Rejecting tree copy\n"));
2789 return(ERROR(ERRSRV,ERRerror));
2792 p = strrchr(name,'/');
2793 if (!p) {
2794 strcpy(directory,"./");
2795 strcpy(mask,name);
2796 } else {
2797 *p = 0;
2798 strcpy(directory,name);
2799 strcpy(mask,p+1);
2802 if (is_mangled(mask))
2803 check_mangled_stack(mask);
2805 has_wild = strchr(mask,'*') || strchr(mask,'?');
2807 if (!has_wild) {
2808 strcat(directory,"/");
2809 strcat(directory,mask);
2810 if (resolve_wildcards(directory,newname) &&
2811 copy_file(directory,newname,cnum,ofun,
2812 count,target_is_directory)) count++;
2813 if (!count) exists = file_exist(directory,NULL);
2814 } else {
2815 void *dirptr = NULL;
2816 char *dname;
2817 pstring destname;
2819 if (check_name(directory,cnum))
2820 dirptr = OpenDir(directory);
2822 if (dirptr)
2824 error = ERRbadfile;
2826 if (strequal(mask,"????????.???"))
2827 strcpy(mask,"*");
2829 while ((dname = ReadDirName(dirptr)))
2831 pstring fname;
2832 strcpy(fname,dname);
2834 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2836 error = ERRnoaccess;
2837 sprintf(fname,"%s/%s",directory,dname);
2838 strcpy(destname,newname);
2839 if (resolve_wildcards(fname,destname) &&
2840 copy_file(directory,newname,cnum,ofun,
2841 count,target_is_directory)) count++;
2842 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2844 CloseDir(dirptr);
2848 if (count == 0) {
2849 if (exists)
2850 return(ERROR(ERRDOS,error));
2851 else
2852 return(UNIXERROR(ERRDOS,error));
2855 outsize = set_message(outbuf,1,0,True);
2856 SSVAL(outbuf,smb_vwv0,count);
2858 return(outsize);
2863 /****************************************************************************
2864 reply to a setdir
2865 ****************************************************************************/
2866 int reply_setdir(char *inbuf,char *outbuf)
2868 int cnum,snum;
2869 int outsize = 0;
2870 BOOL ok = False;
2871 pstring newdir;
2873 cnum = SVAL(inbuf,smb_tid);
2875 snum = Connections[cnum].service;
2876 if (!CAN_SETDIR(snum))
2877 return(ERROR(ERRDOS,ERRnoaccess));
2879 strcpy(newdir,smb_buf(inbuf) + 1);
2880 strlower(newdir);
2882 if (strlen(newdir) == 0)
2883 ok = True;
2884 else
2886 ok = directory_exist(newdir,NULL);
2887 if (ok)
2888 string_set(&Connections[cnum].connectpath,newdir);
2891 if (!ok)
2892 return(ERROR(ERRDOS,ERRbadpath));
2894 outsize = set_message(outbuf,0,0,True);
2895 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
2897 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
2899 return(outsize);
2903 /****************************************************************************
2904 reply to a lockingX request
2905 ****************************************************************************/
2906 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
2908 int fnum = GETFNUM(inbuf,smb_vwv2);
2909 uint16 locktype = SVAL(inbuf,smb_vwv3);
2910 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
2911 uint16 num_locks = SVAL(inbuf,smb_vwv7);
2912 uint32 count, offset;
2914 int cnum;
2915 int i;
2916 char *data;
2917 uint32 ecode=0, dummy2;
2918 int eclass=0, dummy1;
2920 cnum = SVAL(inbuf,smb_tid);
2922 CHECK_FNUM(fnum,cnum);
2923 CHECK_ERROR(fnum);
2925 data = smb_buf(inbuf);
2926 /* Data now points at the beginning of the list
2927 of smb_unlkrng structs */
2928 for(i = 0; i < (int)num_ulocks; i++) {
2929 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2930 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2931 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
2932 return ERROR(eclass,ecode);
2935 /* Now do any requested locks */
2936 data += 10*num_ulocks;
2937 /* Data now points at the beginning of the list
2938 of smb_lkrng structs */
2939 for(i = 0; i < (int)num_locks; i++) {
2940 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2941 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2942 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
2943 break;
2946 /* If any of the above locks failed, then we must unlock
2947 all of the previous locks (X/Open spec). */
2948 if(i != num_locks && num_locks != 0) {
2949 for(; i >= 0; i--) {
2950 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2951 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2952 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
2954 return ERROR(eclass,ecode);
2957 set_message(outbuf,2,0,True);
2959 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
2960 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
2962 chain_fnum = fnum;
2964 return chain_reply(inbuf,outbuf,length,bufsize);
2968 /****************************************************************************
2969 reply to a SMBreadbmpx (read block multiplex) request
2970 ****************************************************************************/
2971 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
2973 int cnum,fnum;
2974 int nread = -1;
2975 int total_read;
2976 char *data;
2977 int32 startpos;
2978 int outsize, mincount, maxcount;
2979 int max_per_packet;
2980 int tcount;
2981 int pad;
2983 /* this function doesn't seem to work - disable by default */
2984 if (!lp_readbmpx())
2985 return(ERROR(ERRSRV,ERRuseSTD));
2987 outsize = set_message(outbuf,8,0,True);
2989 cnum = SVAL(inbuf,smb_tid);
2990 fnum = GETFNUM(inbuf,smb_vwv0);
2992 CHECK_FNUM(fnum,cnum);
2993 CHECK_READ(fnum);
2994 CHECK_ERROR(fnum);
2996 startpos = IVAL(inbuf,smb_vwv1);
2997 maxcount = SVAL(inbuf,smb_vwv3);
2998 mincount = SVAL(inbuf,smb_vwv4);
3000 data = smb_buf(outbuf);
3001 pad = ((int)data)%4;
3002 if (pad) pad = 4 - pad;
3003 data += pad;
3005 max_per_packet = bufsize-(outsize+pad);
3006 tcount = maxcount;
3007 total_read = 0;
3009 if (is_locked(fnum,cnum,maxcount,startpos))
3010 return(ERROR(ERRDOS,ERRlock));
3014 int N = MIN(max_per_packet,tcount-total_read);
3016 nread = read_file(fnum,data,startpos,N);
3018 if (nread <= 0) nread = 0;
3020 if (nread < N)
3021 tcount = total_read + nread;
3023 set_message(outbuf,8,nread,False);
3024 SIVAL(outbuf,smb_vwv0,startpos);
3025 SSVAL(outbuf,smb_vwv2,tcount);
3026 SSVAL(outbuf,smb_vwv6,nread);
3027 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3029 send_smb(Client,outbuf);
3031 total_read += nread;
3032 startpos += nread;
3034 while (total_read < tcount);
3036 return(-1);
3040 /****************************************************************************
3041 reply to a SMBwritebmpx (write block multiplex primary) request
3042 ****************************************************************************/
3043 int reply_writebmpx(char *inbuf,char *outbuf)
3045 int cnum,numtowrite,fnum;
3046 int nwritten = -1;
3047 int outsize = 0;
3048 int32 startpos;
3049 int tcount, write_through, smb_doff;
3050 char *data;
3052 cnum = SVAL(inbuf,smb_tid);
3053 fnum = GETFNUM(inbuf,smb_vwv0);
3055 CHECK_FNUM(fnum,cnum);
3056 CHECK_WRITE(fnum);
3057 CHECK_ERROR(fnum);
3059 tcount = SVAL(inbuf,smb_vwv1);
3060 startpos = IVAL(inbuf,smb_vwv3);
3061 write_through = BITSETW(inbuf+smb_vwv7,0);
3062 numtowrite = SVAL(inbuf,smb_vwv10);
3063 smb_doff = SVAL(inbuf,smb_vwv11);
3065 data = smb_base(inbuf) + smb_doff;
3067 /* If this fails we need to send an SMBwriteC response,
3068 not an SMBwritebmpx - set this up now so we don't forget */
3069 CVAL(outbuf,smb_com) = SMBwritec;
3071 if (is_locked(fnum,cnum,tcount,startpos))
3072 return(ERROR(ERRDOS,ERRlock));
3074 seek_file(fnum,startpos);
3075 nwritten = write_file(fnum,data,numtowrite);
3077 if(lp_syncalways(SNUM(cnum)) || write_through)
3078 sync_file(fnum);
3080 if(nwritten < numtowrite)
3081 return(UNIXERROR(ERRHRD,ERRdiskfull));
3083 /* If the maximum to be written to this file
3084 is greater than what we just wrote then set
3085 up a secondary struct to be attached to this
3086 fd, we will use this to cache error messages etc. */
3087 if(tcount > nwritten)
3089 write_bmpx_struct *wbms;
3090 if(Files[fnum].wbmpx_ptr != NULL)
3091 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3092 else
3093 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3094 if(!wbms)
3096 DEBUG(0,("Out of memory in reply_readmpx\n"));
3097 return(ERROR(ERRSRV,ERRnoresource));
3099 wbms->wr_mode = write_through;
3100 wbms->wr_discard = False; /* No errors yet */
3101 wbms->wr_total_written = nwritten;
3102 wbms->wr_errclass = 0;
3103 wbms->wr_error = 0;
3104 Files[fnum].wbmpx_ptr = wbms;
3107 /* We are returning successfully, set the message type back to
3108 SMBwritebmpx */
3109 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3111 outsize = set_message(outbuf,1,0,True);
3113 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3115 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3116 timestring(),fnum,cnum,numtowrite,nwritten));
3118 if (write_through && tcount==nwritten) {
3119 /* we need to send both a primary and a secondary response */
3120 smb_setlen(outbuf,outsize - 4);
3121 send_smb(Client,outbuf);
3123 /* now the secondary */
3124 outsize = set_message(outbuf,1,0,True);
3125 CVAL(outbuf,smb_com) = SMBwritec;
3126 SSVAL(outbuf,smb_vwv0,nwritten);
3129 return(outsize);
3133 /****************************************************************************
3134 reply to a SMBwritebs (write block multiplex secondary) request
3135 ****************************************************************************/
3136 int reply_writebs(char *inbuf,char *outbuf)
3138 int cnum,numtowrite,fnum;
3139 int nwritten = -1;
3140 int outsize = 0;
3141 int32 startpos;
3142 int tcount, write_through, smb_doff;
3143 char *data;
3144 write_bmpx_struct *wbms;
3145 BOOL send_response = False;
3147 cnum = SVAL(inbuf,smb_tid);
3148 fnum = GETFNUM(inbuf,smb_vwv0);
3149 CHECK_FNUM(fnum,cnum);
3150 CHECK_WRITE(fnum);
3152 tcount = SVAL(inbuf,smb_vwv1);
3153 startpos = IVAL(inbuf,smb_vwv2);
3154 numtowrite = SVAL(inbuf,smb_vwv6);
3155 smb_doff = SVAL(inbuf,smb_vwv7);
3157 data = smb_base(inbuf) + smb_doff;
3159 /* We need to send an SMBwriteC response, not an SMBwritebs */
3160 CVAL(outbuf,smb_com) = SMBwritec;
3162 /* This fd should have an auxiliary struct attached,
3163 check that it does */
3164 wbms = Files[fnum].wbmpx_ptr;
3165 if(!wbms) return(-1);
3167 /* If write through is set we can return errors, else we must
3168 cache them */
3169 write_through = wbms->wr_mode;
3171 /* Check for an earlier error */
3172 if(wbms->wr_discard)
3173 return -1; /* Just discard the packet */
3175 seek_file(fnum,startpos);
3176 nwritten = write_file(fnum,data,numtowrite);
3178 if(lp_syncalways(SNUM(cnum)) || write_through)
3179 sync_file(fnum);
3181 if (nwritten < numtowrite)
3183 if(write_through) {
3184 /* We are returning an error - we can delete the aux struct */
3185 if (wbms) free((char *)wbms);
3186 Files[fnum].wbmpx_ptr = NULL;
3187 return(ERROR(ERRHRD,ERRdiskfull));
3189 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3192 /* Increment the total written, if this matches tcount
3193 we can discard the auxiliary struct (hurrah !) and return a writeC */
3194 wbms->wr_total_written += nwritten;
3195 if(wbms->wr_total_written >= tcount)
3197 if (write_through) {
3198 outsize = set_message(outbuf,1,0,True);
3199 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3200 send_response = True;
3203 free((char *)wbms);
3204 Files[fnum].wbmpx_ptr = NULL;
3207 if(send_response)
3208 return(outsize);
3210 return(-1);
3214 /****************************************************************************
3215 reply to a SMBsetattrE
3216 ****************************************************************************/
3217 int reply_setattrE(char *inbuf,char *outbuf)
3219 int cnum,fnum;
3220 struct utimbuf unix_times;
3221 int outsize = 0;
3223 outsize = set_message(outbuf,0,0,True);
3225 cnum = SVAL(inbuf,smb_tid);
3226 fnum = GETFNUM(inbuf,smb_vwv0);
3228 CHECK_FNUM(fnum,cnum);
3229 CHECK_ERROR(fnum);
3231 /* Convert the DOS times into unix times. Ignore create
3232 time as UNIX can't set this.
3234 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3235 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3237 /* Set the date on this file */
3238 if(sys_utime(Files[fnum].name, &unix_times))
3239 return(ERROR(ERRDOS,ERRnoaccess));
3241 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3243 return(outsize);
3247 /****************************************************************************
3248 reply to a SMBgetattrE
3249 ****************************************************************************/
3250 int reply_getattrE(char *inbuf,char *outbuf)
3252 int cnum,fnum;
3253 struct stat sbuf;
3254 int outsize = 0;
3255 int mode;
3257 outsize = set_message(outbuf,11,0,True);
3259 cnum = SVAL(inbuf,smb_tid);
3260 fnum = GETFNUM(inbuf,smb_vwv0);
3262 CHECK_FNUM(fnum,cnum);
3263 CHECK_ERROR(fnum);
3265 /* Do an fstat on this file */
3266 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3267 return(UNIXERROR(ERRDOS,ERRnoaccess));
3269 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3271 /* Convert the times into dos times. Set create
3272 date to be last modify date as UNIX doesn't save
3273 this */
3274 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3275 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3276 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3277 if (mode & aDIR)
3279 SIVAL(outbuf,smb_vwv6,0);
3280 SIVAL(outbuf,smb_vwv8,0);
3282 else
3284 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3285 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3287 SSVAL(outbuf,smb_vwv10, mode);
3289 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3291 return(outsize);