local.h: Removed ununsed SHARE_MODES_XXX defines. Upped SMBD_RELOAD_CHECK
[Samba.git] / source / smbd / reply.c
blob8f650cb994e612a85b20d749abf4a413c2e37bd6
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 (!*user)
413 strcpy(user,lp_guestaccount(-1));
415 strlower(user);
417 strcpy(sesssetup_user,user);
419 reload_services(True);
421 add_session_user(user);
424 if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
425 !check_hosts_equiv(user))
428 if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
429 guest = True;
431 /* now check if it's a valid username/password */
432 /* If an NT password was supplied try and validate with that
433 first. This is superior as the passwords are mixed case 128 length unicode */
434 if(smb_ntpasslen && !guest)
436 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
437 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
438 else
439 valid_nt_password = True;
441 if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
443 if (!computer_id && lp_security() >= SEC_USER) {
444 #if (GUEST_SESSSETUP == 0)
445 return(ERROR(ERRSRV,ERRbadpw));
446 #endif
447 #if (GUEST_SESSSETUP == 1)
448 if (Get_Pwnam(user,True))
449 return(ERROR(ERRSRV,ERRbadpw));
450 #endif
452 if (*smb_apasswd || !Get_Pwnam(user,True))
453 strcpy(user,lp_guestaccount(-1));
454 DEBUG(3,("Registered username %s for guest access\n",user));
455 guest = True;
459 if (!Get_Pwnam(user,True)) {
460 DEBUG(3,("No such user %s - using guest account\n",user));
461 strcpy(user,lp_guestaccount(-1));
462 guest = True;
465 if (!strequal(user,lp_guestaccount(-1)) &&
466 lp_servicenumber(user) < 0)
468 int homes = lp_servicenumber(HOMES_NAME);
469 char *home = get_home_dir(user);
470 if (homes >= 0 && home)
471 lp_add_home(user,homes,home);
475 /* it's ok - setup a reply */
476 if (Protocol < PROTOCOL_NT1) {
477 set_message(outbuf,3,0,True);
478 } else {
479 char *p;
480 set_message(outbuf,3,3,True);
481 p = smb_buf(outbuf);
482 strcpy(p,"Unix"); p = skip_string(p,1);
483 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
484 strcpy(p,myworkgroup); p = skip_string(p,1);
485 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
486 /* perhaps grab OS version here?? */
489 /* Set the correct uid in the outgoing and incoming packets
490 We will use this on future requests to determine which
491 user we should become.
494 struct passwd *pw = Get_Pwnam(user,False);
495 if (!pw) {
496 DEBUG(1,("Username %s is invalid on this system\n",user));
497 return(ERROR(ERRSRV,ERRbadpw));
499 gid = pw->pw_gid;
500 uid = pw->pw_uid;
503 if (guest && !computer_id)
504 SSVAL(outbuf,smb_vwv2,1);
506 /* register the name and uid as being validated, so further connections
507 to a uid can get through without a password, on the same VC */
508 sess_vuid = register_vuid(uid,gid,user,guest);
510 SSVAL(outbuf,smb_uid,sess_vuid);
511 SSVAL(inbuf,smb_uid,sess_vuid);
513 if (!done_sesssetup)
514 max_send = MIN(max_send,smb_bufsize);
516 DEBUG(1,(" Client requested max send size of %d\n", max_send));
518 done_sesssetup = True;
520 return chain_reply(inbuf,outbuf,length,bufsize);
524 /****************************************************************************
525 reply to a chkpth
526 ****************************************************************************/
527 int reply_chkpth(char *inbuf,char *outbuf)
529 int outsize = 0;
530 int cnum,mode;
531 pstring name;
532 BOOL ok = False;
534 cnum = SVAL(inbuf,smb_tid);
536 strcpy(name,smb_buf(inbuf) + 1);
537 unix_convert(name,cnum,0);
539 mode = SVAL(inbuf,smb_vwv0);
541 if (check_name(name,cnum))
542 ok = directory_exist(name,NULL);
544 if (!ok)
545 return(ERROR(ERRDOS,ERRbadpath));
547 outsize = set_message(outbuf,0,0,True);
549 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
551 return(outsize);
555 /****************************************************************************
556 reply to a getatr
557 ****************************************************************************/
558 int reply_getatr(char *inbuf,char *outbuf)
560 pstring fname;
561 int cnum;
562 int outsize = 0;
563 struct stat sbuf;
564 BOOL ok = False;
565 int mode=0;
566 uint32 size=0;
567 time_t mtime=0;
569 cnum = SVAL(inbuf,smb_tid);
571 strcpy(fname,smb_buf(inbuf) + 1);
572 unix_convert(fname,cnum,0);
574 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
575 under WfWg - weird! */
576 if (! (*fname))
578 mode = aHIDDEN | aDIR;
579 if (!CAN_WRITE(cnum)) mode |= aRONLY;
580 size = 0;
581 mtime = 0;
582 ok = True;
584 else
585 if (check_name(fname,cnum))
587 if (sys_stat(fname,&sbuf) == 0)
589 mode = dos_mode(cnum,fname,&sbuf);
590 size = sbuf.st_size;
591 mtime = sbuf.st_mtime;
592 if (mode & aDIR)
593 size = 0;
594 ok = True;
596 else
597 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
600 if (!ok)
601 return(UNIXERROR(ERRDOS,ERRbadfile));
603 outsize = set_message(outbuf,10,0,True);
605 SSVAL(outbuf,smb_vwv0,mode);
606 put_dos_date3(outbuf,smb_vwv1,mtime);
607 SIVAL(outbuf,smb_vwv3,size);
609 if (Protocol >= PROTOCOL_NT1) {
610 char *p = strrchr(fname,'/');
611 uint16 flg2 = SVAL(outbuf,smb_flg2);
612 if (!p) p = fname;
613 if (!is_8_3(fname, True))
614 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
617 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
619 return(outsize);
623 /****************************************************************************
624 reply to a setatr
625 ****************************************************************************/
626 int reply_setatr(char *inbuf,char *outbuf)
628 pstring fname;
629 int cnum;
630 int outsize = 0;
631 BOOL ok=False;
632 int mode;
633 time_t mtime;
635 cnum = SVAL(inbuf,smb_tid);
637 strcpy(fname,smb_buf(inbuf) + 1);
638 unix_convert(fname,cnum,0);
640 mode = SVAL(inbuf,smb_vwv0);
641 mtime = make_unix_date3(inbuf+smb_vwv1);
643 if (directory_exist(fname,NULL))
644 mode |= aDIR;
645 if (check_name(fname,cnum))
646 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
647 if (ok)
648 ok = set_filetime(fname,mtime);
650 if (!ok)
651 return(UNIXERROR(ERRDOS,ERRnoaccess));
653 outsize = set_message(outbuf,0,0,True);
655 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
657 return(outsize);
661 /****************************************************************************
662 reply to a dskattr
663 ****************************************************************************/
664 int reply_dskattr(char *inbuf,char *outbuf)
666 int cnum;
667 int outsize = 0;
668 int dfree,dsize,bsize;
670 cnum = SVAL(inbuf,smb_tid);
672 sys_disk_free(".",&bsize,&dfree,&dsize);
674 outsize = set_message(outbuf,5,0,True);
676 SSVAL(outbuf,smb_vwv0,dsize);
677 SSVAL(outbuf,smb_vwv1,bsize/512);
678 SSVAL(outbuf,smb_vwv2,512);
679 SSVAL(outbuf,smb_vwv3,dfree);
681 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
683 return(outsize);
687 /****************************************************************************
688 reply to a search
689 Can be called from SMBsearch, SMBffirst or SMBfunique.
690 ****************************************************************************/
691 int reply_search(char *inbuf,char *outbuf)
693 pstring mask;
694 pstring directory;
695 pstring fname;
696 int size,mode;
697 time_t date;
698 int dirtype;
699 int cnum;
700 int outsize = 0;
701 int numentries = 0;
702 BOOL finished = False;
703 int maxentries;
704 int i;
705 char *p;
706 BOOL ok = False;
707 int status_len;
708 char *path;
709 char status[21];
710 int dptr_num= -1;
711 BOOL check_descend = False;
712 BOOL expect_close = False;
713 BOOL can_open = True;
715 *mask = *directory = *fname = 0;
717 /* If we were called as SMBffirst then we must expect close. */
718 if(CVAL(inbuf,smb_com) == SMBffirst)
719 expect_close = True;
721 cnum = SVAL(inbuf,smb_tid);
723 outsize = set_message(outbuf,1,3,True);
724 maxentries = SVAL(inbuf,smb_vwv0);
725 dirtype = SVAL(inbuf,smb_vwv1);
726 path = smb_buf(inbuf) + 1;
727 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
730 /* dirtype &= ~aDIR; */
732 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
735 if (status_len == 0)
737 pstring dir2;
739 strcpy(directory,smb_buf(inbuf)+1);
740 strcpy(dir2,smb_buf(inbuf)+1);
741 unix_convert(directory,cnum,0);
742 unix_format(dir2);
744 if (!check_name(directory,cnum))
745 can_open = False;
747 p = strrchr(dir2,'/');
748 if (p == NULL)
749 {strcpy(mask,dir2);*dir2 = 0;}
750 else
751 {*p = 0;strcpy(mask,p+1);}
753 p = strrchr(directory,'/');
754 if (!p)
755 *directory = 0;
756 else
757 *p = 0;
759 if (strlen(directory) == 0)
760 strcpy(directory,"./");
761 bzero(status,21);
762 CVAL(status,0) = dirtype;
764 else
766 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
767 memcpy(mask,status+1,11);
768 mask[11] = 0;
769 dirtype = CVAL(status,0) & 0x1F;
770 Connections[cnum].dirptr = dptr_fetch(SNUM(cnum), status+12,&dptr_num);
771 if (!Connections[cnum].dirptr)
772 goto SearchEmpty;
773 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
774 if (!case_sensitive)
775 strnorm(mask);
778 /* turn strings of spaces into a . */
780 trim_string(mask,NULL," ");
781 if ((p = strrchr(mask,' ')))
783 fstring ext;
784 strcpy(ext,p+1);
785 *p = 0;
786 trim_string(mask,NULL," ");
787 strcat(mask,".");
788 strcat(mask,ext);
793 for (p=mask; *p; p++)
795 if (*p != '?' && *p != '*' && !isdoschar(*p))
797 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
798 *p = '?';
803 if (!strchr(mask,'.') && strlen(mask)>8)
805 fstring tmp;
806 strcpy(tmp,&mask[8]);
807 mask[8] = '.';
808 mask[9] = 0;
809 strcat(mask,tmp);
812 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
814 if (can_open)
816 p = smb_buf(outbuf) + 3;
818 ok = True;
820 if (status_len == 0)
822 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
823 if (dptr_num < 0)
824 return(ERROR(ERRDOS,ERRnofids));
827 DEBUG(4,("dptr_num is %d\n",dptr_num));
829 if (ok)
831 if ((dirtype&0x1F) == aVOLID)
833 memcpy(p,status,21);
834 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
835 dptr_fill(SNUM(cnum), p+12,dptr_num);
836 if (dptr_zero(p+12) && (status_len==0))
837 numentries = 1;
838 else
839 numentries = 0;
840 p += DIR_STRUCT_SIZE;
842 else
844 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
845 if (in_list(Connections[cnum].dirpath,
846 lp_dontdescend(SNUM(cnum)),True))
847 check_descend = True;
849 for (i=numentries;(i<maxentries) && !finished;i++)
851 finished =
852 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
853 if (!finished)
855 memcpy(p,status,21);
856 make_dir_struct(p,mask,fname,size,mode,date);
857 dptr_fill(SNUM(cnum), p+12,dptr_num);
858 numentries++;
860 p += DIR_STRUCT_SIZE;
867 SearchEmpty:
869 if (numentries == 0 || !ok)
871 CVAL(outbuf,smb_rcls) = ERRDOS;
872 SSVAL(outbuf,smb_err,ERRnofiles);
875 /* If we were called as SMBffirst with smb_search_id == NULL
876 and no entries were found then return error and close dirptr
877 (X/Open spec) */
879 if(ok && expect_close && numentries == 0 && status_len == 0)
881 CVAL(outbuf,smb_rcls) = ERRDOS;
882 SSVAL(outbuf,smb_err,ERRnofiles);
883 /* Also close the dptr - we know it's gone */
884 dptr_close(dptr_num);
887 /* If we were called as SMBfunique, then we can close the dirptr now ! */
888 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
889 dptr_close(dptr_num);
891 SSVAL(outbuf,smb_vwv0,numentries);
892 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
893 CVAL(smb_buf(outbuf),0) = 5;
894 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
896 if (Protocol >= PROTOCOL_NT1) {
897 uint16 flg2 = SVAL(outbuf,smb_flg2);
898 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
901 outsize += DIR_STRUCT_SIZE*numentries;
902 smb_setlen(outbuf,outsize - 4);
904 if ((! *directory) && dptr_path(dptr_num))
905 sprintf(directory,"(%s)",dptr_path(dptr_num));
907 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
908 timestring(),
909 smb_fn_name(CVAL(inbuf,smb_com)),
910 mask,directory,cnum,dirtype,numentries,maxentries));
912 return(outsize);
916 /****************************************************************************
917 reply to a fclose (stop directory search)
918 ****************************************************************************/
919 int reply_fclose(char *inbuf,char *outbuf)
921 int cnum;
922 int outsize = 0;
923 int status_len;
924 char *path;
925 char status[21];
926 int dptr_num= -1;
928 cnum = SVAL(inbuf,smb_tid);
930 outsize = set_message(outbuf,1,0,True);
931 path = smb_buf(inbuf) + 1;
932 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
935 if (status_len == 0)
936 return(ERROR(ERRSRV,ERRsrverror));
938 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
940 if(dptr_fetch(SNUM(cnum), status+12,&dptr_num)) {
941 /* Close the dptr - we know it's gone */
942 dptr_close(dptr_num);
945 SSVAL(outbuf,smb_vwv0,0);
947 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
949 return(outsize);
953 /****************************************************************************
954 reply to an open
955 ****************************************************************************/
956 int reply_open(char *inbuf,char *outbuf)
958 pstring fname;
959 int cnum;
960 int fnum = -1;
961 int outsize = 0;
962 int fmode=0;
963 int share_mode;
964 int size = 0;
965 time_t mtime=0;
966 int unixmode;
967 int rmode=0;
968 struct stat sbuf;
970 cnum = SVAL(inbuf,smb_tid);
972 share_mode = SVAL(inbuf,smb_vwv0);
974 strcpy(fname,smb_buf(inbuf)+1);
975 unix_convert(fname,cnum,0);
977 fnum = find_free_file();
978 if (fnum < 0)
979 return(ERROR(ERRSRV,ERRnofids));
981 if (!check_name(fname,cnum))
982 return(UNIXERROR(ERRDOS,ERRnoaccess));
984 unixmode = unix_mode(cnum,aARCH);
986 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
988 if (!Files[fnum].open)
989 return(UNIXERROR(ERRDOS,ERRnoaccess));
991 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
992 close_file(fnum);
993 return(ERROR(ERRDOS,ERRnoaccess));
996 size = sbuf.st_size;
997 fmode = dos_mode(cnum,fname,&sbuf);
998 mtime = sbuf.st_mtime;
1000 if (fmode & aDIR) {
1001 DEBUG(3,("attempt to open a directory %s\n",fname));
1002 close_file(fnum);
1003 return(ERROR(ERRDOS,ERRnoaccess));
1006 outsize = set_message(outbuf,7,0,True);
1007 SSVAL(outbuf,smb_vwv0,fnum);
1008 SSVAL(outbuf,smb_vwv1,fmode);
1009 put_dos_date3(outbuf,smb_vwv2,mtime);
1010 SIVAL(outbuf,smb_vwv4,size);
1011 SSVAL(outbuf,smb_vwv6,rmode);
1013 if (lp_fake_oplocks(SNUM(cnum))) {
1014 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1017 return(outsize);
1021 /****************************************************************************
1022 reply to an open and X
1023 ****************************************************************************/
1024 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1026 pstring fname;
1027 int cnum = SVAL(inbuf,smb_tid);
1028 int fnum = -1;
1029 int openmode = 0;
1030 int smb_mode = SVAL(inbuf,smb_vwv3);
1031 int smb_attr = SVAL(inbuf,smb_vwv5);
1032 BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
1033 #if 0
1034 int open_flags = SVAL(inbuf,smb_vwv2);
1035 int smb_sattr = SVAL(inbuf,smb_vwv4);
1036 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1037 #endif
1038 int smb_ofun = SVAL(inbuf,smb_vwv8);
1039 int unixmode;
1040 int size=0,fmode=0,mtime=0,rmode=0;
1041 struct stat sbuf;
1042 int smb_action = 0;
1044 /* If it's an IPC, pass off the pipe handler. */
1045 if (IS_IPC(cnum))
1046 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1048 /* XXXX we need to handle passed times, sattr and flags */
1050 strcpy(fname,smb_buf(inbuf));
1051 unix_convert(fname,cnum,0);
1053 /* now add create and trunc bits */
1054 if (smb_ofun & 0x10)
1055 openmode |= O_CREAT;
1056 if ((smb_ofun & 0x3) == 2)
1057 openmode |= O_TRUNC;
1059 fnum = find_free_file();
1060 if (fnum < 0)
1061 return(ERROR(ERRSRV,ERRnofids));
1063 if (!check_name(fname,cnum))
1064 return(UNIXERROR(ERRDOS,ERRnoaccess));
1066 unixmode = unix_mode(cnum,smb_attr | aARCH);
1068 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1069 &rmode,&smb_action);
1071 if (!Files[fnum].open)
1072 return(UNIXERROR(ERRDOS,ERRnoaccess));
1074 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1075 close_file(fnum);
1076 return(ERROR(ERRDOS,ERRnoaccess));
1079 size = sbuf.st_size;
1080 fmode = dos_mode(cnum,fname,&sbuf);
1081 mtime = sbuf.st_mtime;
1082 if (fmode & aDIR) {
1083 close_file(fnum);
1084 return(ERROR(ERRDOS,ERRnoaccess));
1087 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1088 smb_action |= (1<<15);
1091 set_message(outbuf,15,0,True);
1092 SSVAL(outbuf,smb_vwv2,fnum);
1093 SSVAL(outbuf,smb_vwv3,fmode);
1094 put_dos_date3(outbuf,smb_vwv4,mtime);
1095 SIVAL(outbuf,smb_vwv6,size);
1096 SSVAL(outbuf,smb_vwv8,rmode);
1097 SSVAL(outbuf,smb_vwv11,smb_action);
1099 chain_fnum = fnum;
1101 return chain_reply(inbuf,outbuf,length,bufsize);
1105 /****************************************************************************
1106 reply to a SMBulogoffX
1107 ****************************************************************************/
1108 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1110 uint16 vuid = SVAL(inbuf,smb_uid);
1111 user_struct *vuser = get_valid_user_struct(vuid);
1113 if(vuser == 0) {
1114 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1117 /* in user level security we are supposed to close any files
1118 open by this user */
1119 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1120 int i;
1121 for (i=0;i<MAX_OPEN_FILES;i++)
1122 if (Files[i].uid == vuser->uid && Files[i].open) {
1123 close_file(i);
1127 invalidate_vuid(vuid);
1129 set_message(outbuf,2,0,True);
1131 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1133 return chain_reply(inbuf,outbuf,length,bufsize);
1137 /****************************************************************************
1138 reply to a mknew or a create
1139 ****************************************************************************/
1140 int reply_mknew(char *inbuf,char *outbuf)
1142 pstring fname;
1143 int cnum,com;
1144 int fnum = -1;
1145 int outsize = 0;
1146 int createmode;
1147 mode_t unixmode;
1148 int ofun = 0;
1150 com = SVAL(inbuf,smb_com);
1151 cnum = SVAL(inbuf,smb_tid);
1153 createmode = SVAL(inbuf,smb_vwv0);
1154 strcpy(fname,smb_buf(inbuf)+1);
1155 unix_convert(fname,cnum,0);
1157 if (createmode & aVOLID)
1159 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1162 unixmode = unix_mode(cnum,createmode);
1164 fnum = find_free_file();
1165 if (fnum < 0)
1166 return(ERROR(ERRSRV,ERRnofids));
1168 if (!check_name(fname,cnum))
1169 return(UNIXERROR(ERRDOS,ERRnoaccess));
1171 if(com == SMBmknew)
1173 /* We should fail if file exists. */
1174 ofun = 0x10;
1176 else
1178 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1179 ofun = 0x12;
1182 /* Open file in dos compatibility share mode. */
1183 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL);
1185 if (!Files[fnum].open)
1186 return(UNIXERROR(ERRDOS,ERRnoaccess));
1188 outsize = set_message(outbuf,1,0,True);
1189 SSVAL(outbuf,smb_vwv0,fnum);
1191 if (lp_fake_oplocks(SNUM(cnum))) {
1192 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1195 DEBUG(2,("new file %s\n",fname));
1196 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));
1198 return(outsize);
1202 /****************************************************************************
1203 reply to a create temporary file
1204 ****************************************************************************/
1205 int reply_ctemp(char *inbuf,char *outbuf)
1207 pstring fname;
1208 pstring fname2;
1209 int cnum;
1210 int fnum = -1;
1211 int outsize = 0;
1212 int createmode;
1213 mode_t unixmode;
1215 cnum = SVAL(inbuf,smb_tid);
1216 createmode = SVAL(inbuf,smb_vwv0);
1217 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1218 unix_convert(fname,cnum,0);
1220 unixmode = unix_mode(cnum,createmode);
1222 fnum = find_free_file();
1223 if (fnum < 0)
1224 return(ERROR(ERRSRV,ERRnofids));
1226 if (!check_name(fname,cnum))
1227 return(UNIXERROR(ERRDOS,ERRnoaccess));
1229 strcpy(fname2,(char *)mktemp(fname));
1231 /* Open file in dos compatibility share mode. */
1232 /* We should fail if file exists. */
1233 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL);
1235 if (!Files[fnum].open)
1236 return(UNIXERROR(ERRDOS,ERRnoaccess));
1238 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1239 SSVAL(outbuf,smb_vwv0,fnum);
1240 CVAL(smb_buf(outbuf),0) = 4;
1241 strcpy(smb_buf(outbuf) + 1,fname2);
1243 if (lp_fake_oplocks(SNUM(cnum))) {
1244 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1247 DEBUG(2,("created temp file %s\n",fname2));
1248 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));
1250 return(outsize);
1254 /*******************************************************************
1255 check if a user is allowed to delete a file
1256 ********************************************************************/
1257 static BOOL can_delete(char *fname,int cnum,int dirtype)
1259 struct stat sbuf;
1260 int fmode;
1262 if (!CAN_WRITE(cnum)) return(False);
1264 if (sys_lstat(fname,&sbuf) != 0) return(False);
1265 fmode = dos_mode(cnum,fname,&sbuf);
1266 if (fmode & aDIR) return(False);
1267 if (!lp_delete_readonly(SNUM(cnum))) {
1268 if (fmode & aRONLY) return(False);
1270 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1271 return(False);
1272 if (!check_file_sharing(cnum,fname)) return(False);
1273 return(True);
1276 /****************************************************************************
1277 reply to a unlink
1278 ****************************************************************************/
1279 int reply_unlink(char *inbuf,char *outbuf)
1281 int outsize = 0;
1282 pstring name;
1283 int cnum;
1284 int dirtype;
1285 pstring directory;
1286 pstring mask;
1287 char *p;
1288 int count=0;
1289 int error = ERRnoaccess;
1290 BOOL has_wild;
1291 BOOL exists=False;
1293 *directory = *mask = 0;
1295 cnum = SVAL(inbuf,smb_tid);
1296 dirtype = SVAL(inbuf,smb_vwv0);
1298 strcpy(name,smb_buf(inbuf) + 1);
1300 DEBUG(3,("reply_unlink : %s\n",name));
1302 unix_convert(name,cnum,0);
1304 p = strrchr(name,'/');
1305 if (!p) {
1306 strcpy(directory,"./");
1307 strcpy(mask,name);
1308 } else {
1309 *p = 0;
1310 strcpy(directory,name);
1311 strcpy(mask,p+1);
1314 if (is_mangled(mask))
1315 check_mangled_stack(mask);
1317 has_wild = strchr(mask,'*') || strchr(mask,'?');
1319 if (!has_wild) {
1320 strcat(directory,"/");
1321 strcat(directory,mask);
1322 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1323 if (!count) exists = file_exist(directory,NULL);
1324 } else {
1325 void *dirptr = NULL;
1326 char *dname;
1328 if (check_name(directory,cnum))
1329 dirptr = OpenDir(SNUM(cnum), directory, True);
1331 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1332 the pattern matches against the long name, otherwise the short name
1333 We don't implement this yet XXXX
1336 if (dirptr)
1338 error = ERRbadfile;
1340 if (strequal(mask,"????????.???"))
1341 strcpy(mask,"*");
1343 while ((dname = ReadDirName(dirptr)))
1345 pstring fname;
1346 strcpy(fname,dname);
1348 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1350 error = ERRnoaccess;
1351 sprintf(fname,"%s/%s",directory,dname);
1352 if (!can_delete(fname,cnum,dirtype)) continue;
1353 if (!sys_unlink(fname)) count++;
1354 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1356 CloseDir(dirptr);
1360 if (count == 0) {
1361 if (exists)
1362 return(ERROR(ERRDOS,error));
1363 else
1364 return(UNIXERROR(ERRDOS,error));
1367 outsize = set_message(outbuf,0,0,True);
1369 return(outsize);
1373 /****************************************************************************
1374 reply to a readbraw (core+ protocol)
1375 ****************************************************************************/
1376 int reply_readbraw(char *inbuf, char *outbuf)
1378 int cnum,maxcount,mincount,fnum;
1379 int nread = 0;
1380 int startpos;
1381 char *header = outbuf;
1382 int ret=0;
1383 int fd;
1384 char *fname;
1386 cnum = SVAL(inbuf,smb_tid);
1387 fnum = GETFNUM(inbuf,smb_vwv0);
1389 startpos = IVAL(inbuf,smb_vwv1);
1390 maxcount = SVAL(inbuf,smb_vwv3);
1391 mincount = SVAL(inbuf,smb_vwv4);
1393 /* ensure we don't overrun the packet size */
1394 maxcount = MIN(65535,maxcount);
1395 maxcount = MAX(mincount,maxcount);
1397 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1399 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1400 _smb_setlen(header,0);
1401 transfer_file(0,Client,0,header,4,0);
1402 return(-1);
1404 else
1406 fd = Files[fnum].fd_ptr->fd;
1407 fname = Files[fnum].name;
1411 if (!is_locked(fnum,cnum,maxcount,startpos))
1413 int size = Files[fnum].size;
1414 int sizeneeded = startpos + maxcount;
1416 if (size < sizeneeded) {
1417 struct stat st;
1418 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1419 size = st.st_size;
1420 if (!Files[fnum].can_write)
1421 Files[fnum].size = size;
1424 nread = MIN(maxcount,size - startpos);
1427 if (nread < mincount)
1428 nread = 0;
1430 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1431 timestring(),
1432 fnum,cnum,startpos,
1433 maxcount,mincount,nread));
1435 #if UNSAFE_READRAW
1437 int predict=0;
1438 _smb_setlen(header,nread);
1440 if (!Files[fnum].can_write)
1441 predict = read_predict(fd,startpos,header+4,NULL,nread);
1443 if ((nread-predict) > 0)
1444 seek_file(fnum,startpos + predict);
1446 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1447 startpos+predict);
1450 if (ret != nread+4)
1451 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1452 fname,startpos,nread,ret));
1454 #else
1455 ret = read_file(fnum,header+4,startpos,nread);
1456 if (ret < mincount) ret = 0;
1458 _smb_setlen(header,ret);
1459 transfer_file(0,Client,0,header,4+ret,0);
1460 #endif
1462 DEBUG(5,("readbraw finished\n"));
1463 return -1;
1467 /****************************************************************************
1468 reply to a lockread (core+ protocol)
1469 ****************************************************************************/
1470 int reply_lockread(char *inbuf,char *outbuf)
1472 int cnum,fnum;
1473 int nread = -1;
1474 char *data;
1475 int outsize = 0;
1476 uint32 startpos, numtoread;
1477 int eclass;
1478 uint32 ecode;
1480 cnum = SVAL(inbuf,smb_tid);
1481 fnum = GETFNUM(inbuf,smb_vwv0);
1483 CHECK_FNUM(fnum,cnum);
1484 CHECK_READ(fnum);
1485 CHECK_ERROR(fnum);
1487 numtoread = SVAL(inbuf,smb_vwv1);
1488 startpos = IVAL(inbuf,smb_vwv2);
1490 outsize = set_message(outbuf,5,3,True);
1491 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1492 data = smb_buf(outbuf) + 3;
1494 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1495 return (ERROR(eclass,ecode));
1497 nread = read_file(fnum,data,startpos,numtoread);
1499 if (nread < 0)
1500 return(UNIXERROR(ERRDOS,ERRnoaccess));
1502 outsize += nread;
1503 SSVAL(outbuf,smb_vwv0,nread);
1504 SSVAL(outbuf,smb_vwv5,nread+3);
1505 SSVAL(smb_buf(outbuf),1,nread);
1507 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1509 return(outsize);
1513 /****************************************************************************
1514 reply to a read
1515 ****************************************************************************/
1516 int reply_read(char *inbuf,char *outbuf)
1518 int cnum,numtoread,fnum;
1519 int nread = 0;
1520 char *data;
1521 int startpos;
1522 int outsize = 0;
1524 cnum = SVAL(inbuf,smb_tid);
1525 fnum = GETFNUM(inbuf,smb_vwv0);
1527 CHECK_FNUM(fnum,cnum);
1528 CHECK_READ(fnum);
1529 CHECK_ERROR(fnum);
1531 numtoread = SVAL(inbuf,smb_vwv1);
1532 startpos = IVAL(inbuf,smb_vwv2);
1534 outsize = set_message(outbuf,5,3,True);
1535 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1536 data = smb_buf(outbuf) + 3;
1538 if (is_locked(fnum,cnum,numtoread,startpos))
1539 return(ERROR(ERRDOS,ERRlock));
1541 if (numtoread > 0)
1542 nread = read_file(fnum,data,startpos,numtoread);
1544 if (nread < 0)
1545 return(UNIXERROR(ERRDOS,ERRnoaccess));
1547 outsize += nread;
1548 SSVAL(outbuf,smb_vwv0,nread);
1549 SSVAL(outbuf,smb_vwv5,nread+3);
1550 CVAL(smb_buf(outbuf),0) = 1;
1551 SSVAL(smb_buf(outbuf),1,nread);
1553 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1555 return(outsize);
1559 /****************************************************************************
1560 reply to a read and X
1561 ****************************************************************************/
1562 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1564 int fnum = GETFNUM(inbuf,smb_vwv2);
1565 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1566 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1567 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1568 int cnum;
1569 int nread = -1;
1570 char *data;
1571 BOOL ok = False;
1573 cnum = SVAL(inbuf,smb_tid);
1575 CHECK_FNUM(fnum,cnum);
1576 CHECK_READ(fnum);
1577 CHECK_ERROR(fnum);
1579 set_message(outbuf,12,0,True);
1580 data = smb_buf(outbuf);
1582 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1583 return(ERROR(ERRDOS,ERRlock));
1584 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1585 ok = True;
1587 if (nread < 0)
1588 return(UNIXERROR(ERRDOS,ERRnoaccess));
1590 SSVAL(outbuf,smb_vwv5,nread);
1591 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1592 SSVAL(smb_buf(outbuf),-2,nread);
1594 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1595 timestring(),fnum,cnum,
1596 smb_mincnt,smb_maxcnt,nread));
1598 chain_fnum = fnum;
1600 return chain_reply(inbuf,outbuf,length,bufsize);
1604 /****************************************************************************
1605 reply to a writebraw (core+ or LANMAN1.0 protocol)
1606 ****************************************************************************/
1607 int reply_writebraw(char *inbuf,char *outbuf)
1609 int nwritten=0;
1610 int total_written=0;
1611 int numtowrite=0;
1612 int cnum,fnum;
1613 int outsize = 0;
1614 long startpos;
1615 char *data=NULL;
1616 BOOL write_through;
1617 int tcount;
1619 cnum = SVAL(inbuf,smb_tid);
1620 fnum = GETFNUM(inbuf,smb_vwv0);
1622 CHECK_FNUM(fnum,cnum);
1623 CHECK_WRITE(fnum);
1624 CHECK_ERROR(fnum);
1626 tcount = IVAL(inbuf,smb_vwv1);
1627 startpos = IVAL(inbuf,smb_vwv3);
1628 write_through = BITSETW(inbuf+smb_vwv7,0);
1630 /* We have to deal with slightly different formats depending
1631 on whether we are using the core+ or lanman1.0 protocol */
1632 if(Protocol <= PROTOCOL_COREPLUS) {
1633 numtowrite = SVAL(smb_buf(inbuf),-2);
1634 data = smb_buf(inbuf);
1635 } else {
1636 numtowrite = SVAL(inbuf,smb_vwv10);
1637 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1640 /* force the error type */
1641 CVAL(inbuf,smb_com) = SMBwritec;
1642 CVAL(outbuf,smb_com) = SMBwritec;
1644 if (is_locked(fnum,cnum,tcount,startpos))
1645 return(ERROR(ERRDOS,ERRlock));
1647 if (seek_file(fnum,startpos) != startpos)
1648 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1650 if (numtowrite>0)
1651 nwritten = write_file(fnum,data,numtowrite);
1653 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1654 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1656 if (nwritten < numtowrite)
1657 return(UNIXERROR(ERRHRD,ERRdiskfull));
1659 total_written = nwritten;
1661 /* Return a message to the redirector to tell it
1662 to send more bytes */
1663 CVAL(outbuf,smb_com) = SMBwritebraw;
1664 SSVALS(outbuf,smb_vwv0,-1);
1665 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1666 send_smb(Client,outbuf);
1668 /* Now read the raw data into the buffer and write it */
1669 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1670 exit_server("secondary writebraw failed");
1673 /* Even though this is not an smb message, smb_len
1674 returns the generic length of an smb message */
1675 numtowrite = smb_len(inbuf);
1677 if (tcount > nwritten+numtowrite) {
1678 DEBUG(3,("Client overestimated the write %d %d %d\n",
1679 tcount,nwritten,numtowrite));
1682 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1683 startpos+nwritten);
1684 total_written += nwritten;
1686 /* Set up outbuf to return the correct return */
1687 outsize = set_message(outbuf,1,0,True);
1688 CVAL(outbuf,smb_com) = SMBwritec;
1689 SSVAL(outbuf,smb_vwv0,total_written);
1691 if (nwritten < numtowrite) {
1692 CVAL(outbuf,smb_rcls) = ERRHRD;
1693 SSVAL(outbuf,smb_err,ERRdiskfull);
1696 if (lp_syncalways(SNUM(cnum)) || write_through)
1697 sync_file(fnum);
1699 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1700 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1702 /* we won't return a status if write through is not selected - this
1703 follows what WfWg does */
1704 if (!write_through && total_written==tcount)
1705 return(-1);
1707 return(outsize);
1711 /****************************************************************************
1712 reply to a writeunlock (core+)
1713 ****************************************************************************/
1714 int reply_writeunlock(char *inbuf,char *outbuf)
1716 int cnum,fnum;
1717 int nwritten = -1;
1718 int outsize = 0;
1719 char *data;
1720 uint32 numtowrite,startpos;
1721 int eclass;
1722 uint32 ecode;
1724 cnum = SVAL(inbuf,smb_tid);
1725 fnum = GETFNUM(inbuf,smb_vwv0);
1727 CHECK_FNUM(fnum,cnum);
1728 CHECK_WRITE(fnum);
1729 CHECK_ERROR(fnum);
1731 numtowrite = SVAL(inbuf,smb_vwv1);
1732 startpos = IVAL(inbuf,smb_vwv2);
1733 data = smb_buf(inbuf) + 3;
1735 if (is_locked(fnum,cnum,numtowrite,startpos))
1736 return(ERROR(ERRDOS,ERRlock));
1738 seek_file(fnum,startpos);
1740 /* The special X/Open SMB protocol handling of
1741 zero length writes is *NOT* done for
1742 this call */
1743 if(numtowrite == 0)
1744 nwritten = 0;
1745 else
1746 nwritten = write_file(fnum,data,numtowrite);
1748 if (lp_syncalways(SNUM(cnum)))
1749 sync_file(fnum);
1751 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1752 return(UNIXERROR(ERRDOS,ERRnoaccess));
1754 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1755 return(ERROR(eclass,ecode));
1757 outsize = set_message(outbuf,1,0,True);
1759 SSVAL(outbuf,smb_vwv0,nwritten);
1761 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1762 timestring(),fnum,cnum,numtowrite,nwritten));
1764 return(outsize);
1768 /****************************************************************************
1769 reply to a write
1770 ****************************************************************************/
1771 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1773 int cnum,numtowrite,fnum;
1774 int nwritten = -1;
1775 int outsize = 0;
1776 int startpos;
1777 char *data;
1779 dum1 = dum2 = 0;
1782 cnum = SVAL(inbuf,smb_tid);
1783 fnum = GETFNUM(inbuf,smb_vwv0);
1785 CHECK_FNUM(fnum,cnum);
1786 CHECK_WRITE(fnum);
1787 CHECK_ERROR(fnum);
1789 numtowrite = SVAL(inbuf,smb_vwv1);
1790 startpos = IVAL(inbuf,smb_vwv2);
1791 data = smb_buf(inbuf) + 3;
1793 if (is_locked(fnum,cnum,numtowrite,startpos))
1794 return(ERROR(ERRDOS,ERRlock));
1796 seek_file(fnum,startpos);
1798 /* X/Open SMB protocol says that if smb_vwv1 is
1799 zero then the file size should be extended or
1800 truncated to the size given in smb_vwv[2-3] */
1801 if(numtowrite == 0)
1802 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
1803 else
1804 nwritten = write_file(fnum,data,numtowrite);
1806 if (lp_syncalways(SNUM(cnum)))
1807 sync_file(fnum);
1809 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1810 return(UNIXERROR(ERRDOS,ERRnoaccess));
1812 outsize = set_message(outbuf,1,0,True);
1814 SSVAL(outbuf,smb_vwv0,nwritten);
1816 if (nwritten < numtowrite) {
1817 CVAL(outbuf,smb_rcls) = ERRHRD;
1818 SSVAL(outbuf,smb_err,ERRdiskfull);
1821 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1823 return(outsize);
1827 /****************************************************************************
1828 reply to a write and X
1829 ****************************************************************************/
1830 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1832 int fnum = GETFNUM(inbuf,smb_vwv2);
1833 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1834 int smb_dsize = SVAL(inbuf,smb_vwv10);
1835 int smb_doff = SVAL(inbuf,smb_vwv11);
1836 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1837 int cnum;
1838 int nwritten = -1;
1839 char *data;
1841 cnum = SVAL(inbuf,smb_tid);
1843 CHECK_FNUM(fnum,cnum);
1844 CHECK_WRITE(fnum);
1845 CHECK_ERROR(fnum);
1847 data = smb_base(inbuf) + smb_doff;
1849 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1850 return(ERROR(ERRDOS,ERRlock));
1852 seek_file(fnum,smb_offs);
1854 /* X/Open SMB protocol says that, unlike SMBwrite
1855 if the length is zero then NO truncation is
1856 done, just a write of zero. To truncate a file,
1857 use SMBwrite. */
1858 if(smb_dsize == 0)
1859 nwritten = 0;
1860 else
1861 nwritten = write_file(fnum,data,smb_dsize);
1863 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1864 return(UNIXERROR(ERRDOS,ERRnoaccess));
1866 set_message(outbuf,6,0,True);
1868 SSVAL(outbuf,smb_vwv2,nwritten);
1870 if (nwritten < smb_dsize) {
1871 CVAL(outbuf,smb_rcls) = ERRHRD;
1872 SSVAL(outbuf,smb_err,ERRdiskfull);
1875 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1877 chain_fnum = fnum;
1879 if (lp_syncalways(SNUM(cnum)) || write_through)
1880 sync_file(fnum);
1882 return chain_reply(inbuf,outbuf,length,bufsize);
1886 /****************************************************************************
1887 reply to a lseek
1888 ****************************************************************************/
1889 int reply_lseek(char *inbuf,char *outbuf)
1891 int cnum,fnum;
1892 uint32 startpos;
1893 int32 res= -1;
1894 int mode,umode;
1895 int outsize = 0;
1897 cnum = SVAL(inbuf,smb_tid);
1898 fnum = GETFNUM(inbuf,smb_vwv0);
1900 CHECK_FNUM(fnum,cnum);
1901 CHECK_ERROR(fnum);
1903 mode = SVAL(inbuf,smb_vwv1) & 3;
1904 startpos = IVAL(inbuf,smb_vwv2);
1906 switch (mode & 3)
1908 case 0: umode = SEEK_SET; break;
1909 case 1: umode = SEEK_CUR; break;
1910 case 2: umode = SEEK_END; break;
1911 default:
1912 umode = SEEK_SET; break;
1915 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
1916 Files[fnum].pos = res;
1918 outsize = set_message(outbuf,2,0,True);
1919 SIVALS(outbuf,smb_vwv0,res);
1921 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1923 return(outsize);
1927 /****************************************************************************
1928 reply to a flush
1929 ****************************************************************************/
1930 int reply_flush(char *inbuf,char *outbuf)
1932 int cnum, fnum;
1933 int outsize = set_message(outbuf,0,0,True);
1935 cnum = SVAL(inbuf,smb_tid);
1936 fnum = GETFNUM(inbuf,smb_vwv0);
1938 if (fnum != 0xFFFF) {
1939 CHECK_FNUM(fnum,cnum);
1940 CHECK_ERROR(fnum);
1943 if (fnum == 0xFFFF)
1945 int i;
1946 for (i=0;i<MAX_OPEN_FILES;i++)
1947 if (OPEN_FNUM(i))
1948 sync_file(i);
1950 else
1951 sync_file(fnum);
1953 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1954 return(outsize);
1958 /****************************************************************************
1959 reply to a exit
1960 ****************************************************************************/
1961 int reply_exit(char *inbuf,char *outbuf)
1963 int outsize = set_message(outbuf,0,0,True);
1964 DEBUG(3,("%s exit\n",timestring()));
1966 return(outsize);
1970 /****************************************************************************
1971 reply to a close
1972 ****************************************************************************/
1973 int reply_close(char *inbuf,char *outbuf)
1975 int fnum,cnum;
1976 int outsize = 0;
1977 time_t mtime;
1978 int32 eclass = 0, err = 0;
1980 outsize = set_message(outbuf,0,0,True);
1982 cnum = SVAL(inbuf,smb_tid);
1984 fnum = GETFNUM(inbuf,smb_vwv0);
1985 CHECK_FNUM(fnum,cnum);
1987 if(HAS_CACHED_ERROR(fnum)) {
1988 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1989 err = Files[fnum].wbmpx_ptr->wr_error;
1992 mtime = make_unix_date3(inbuf+smb_vwv1);
1994 /* try and set the date */
1995 set_filetime(Files[fnum].name,mtime);
1997 close_file(fnum);
1999 /* We have a cached error */
2000 if(eclass || err)
2001 return(ERROR(eclass,err));
2003 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2004 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2005 Connections[cnum].num_files_open));
2007 return(outsize);
2011 /****************************************************************************
2012 reply to a writeclose (Core+ protocol)
2013 ****************************************************************************/
2014 int reply_writeclose(char *inbuf,char *outbuf)
2016 int cnum,numtowrite,fnum;
2017 int nwritten = -1;
2018 int outsize = 0;
2019 int startpos;
2020 char *data;
2021 time_t mtime;
2023 cnum = SVAL(inbuf,smb_tid);
2024 fnum = GETFNUM(inbuf,smb_vwv0);
2026 CHECK_FNUM(fnum,cnum);
2027 CHECK_WRITE(fnum);
2028 CHECK_ERROR(fnum);
2030 numtowrite = SVAL(inbuf,smb_vwv1);
2031 startpos = IVAL(inbuf,smb_vwv2);
2032 mtime = make_unix_date3(inbuf+smb_vwv4);
2033 data = smb_buf(inbuf) + 1;
2035 if (is_locked(fnum,cnum,numtowrite,startpos))
2036 return(ERROR(ERRDOS,ERRlock));
2038 seek_file(fnum,startpos);
2040 nwritten = write_file(fnum,data,numtowrite);
2042 set_filetime(Files[fnum].name,mtime);
2044 close_file(fnum);
2046 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2047 timestring(),fnum,cnum,numtowrite,nwritten,
2048 Connections[cnum].num_files_open));
2050 if (nwritten <= 0)
2051 return(UNIXERROR(ERRDOS,ERRnoaccess));
2053 outsize = set_message(outbuf,1,0,True);
2055 SSVAL(outbuf,smb_vwv0,nwritten);
2056 return(outsize);
2060 /****************************************************************************
2061 reply to a lock
2062 ****************************************************************************/
2063 int reply_lock(char *inbuf,char *outbuf)
2065 int fnum,cnum;
2066 int outsize = set_message(outbuf,0,0,True);
2067 uint32 count,offset;
2068 int eclass;
2069 uint32 ecode;
2071 cnum = SVAL(inbuf,smb_tid);
2072 fnum = GETFNUM(inbuf,smb_vwv0);
2074 CHECK_FNUM(fnum,cnum);
2075 CHECK_ERROR(fnum);
2077 count = IVAL(inbuf,smb_vwv1);
2078 offset = IVAL(inbuf,smb_vwv3);
2080 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));
2082 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2083 return (ERROR(eclass,ecode));
2085 return(outsize);
2089 /****************************************************************************
2090 reply to a unlock
2091 ****************************************************************************/
2092 int reply_unlock(char *inbuf,char *outbuf)
2094 int fnum,cnum;
2095 int outsize = set_message(outbuf,0,0,True);
2096 uint32 count,offset;
2097 int eclass;
2098 uint32 ecode;
2100 cnum = SVAL(inbuf,smb_tid);
2101 fnum = GETFNUM(inbuf,smb_vwv0);
2103 CHECK_FNUM(fnum,cnum);
2104 CHECK_ERROR(fnum);
2106 count = IVAL(inbuf,smb_vwv1);
2107 offset = IVAL(inbuf,smb_vwv3);
2109 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2110 return (ERROR(eclass,ecode));
2112 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));
2114 return(outsize);
2118 /****************************************************************************
2119 reply to a tdis
2120 ****************************************************************************/
2121 int reply_tdis(char *inbuf,char *outbuf)
2123 int cnum;
2124 int outsize = set_message(outbuf,0,0,True);
2125 uint16 vuid;
2127 cnum = SVAL(inbuf,smb_tid);
2128 vuid = SVAL(inbuf,smb_uid);
2130 if (!OPEN_CNUM(cnum)) {
2131 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2132 return(ERROR(ERRSRV,ERRinvnid));
2135 Connections[cnum].used = False;
2137 close_cnum(cnum,vuid);
2139 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2141 return outsize;
2146 /****************************************************************************
2147 reply to a echo
2148 ****************************************************************************/
2149 int reply_echo(char *inbuf,char *outbuf)
2151 int cnum;
2152 int smb_reverb = SVAL(inbuf,smb_vwv0);
2153 int seq_num;
2154 int data_len = smb_buflen(inbuf);
2155 int outsize = set_message(outbuf,1,data_len,True);
2157 cnum = SVAL(inbuf,smb_tid);
2159 /* According to the latest CIFS spec we shouldn't
2160 care what the TID is.
2163 #if 0
2164 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2166 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2167 return(ERROR(ERRSRV,ERRinvnid));
2169 #endif
2171 /* copy any incoming data back out */
2172 if (data_len > 0)
2173 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2175 if (smb_reverb > 100)
2177 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2178 smb_reverb = 100;
2181 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2183 SSVAL(outbuf,smb_vwv0,seq_num);
2185 smb_setlen(outbuf,outsize - 4);
2187 send_smb(Client,outbuf);
2190 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2192 return -1;
2196 /****************************************************************************
2197 reply to a printopen
2198 ****************************************************************************/
2199 int reply_printopen(char *inbuf,char *outbuf)
2201 pstring fname;
2202 pstring fname2;
2203 int cnum;
2204 int fnum = -1;
2205 int outsize = 0;
2207 *fname = *fname2 = 0;
2209 cnum = SVAL(inbuf,smb_tid);
2211 if (!CAN_PRINT(cnum))
2212 return(ERROR(ERRDOS,ERRnoaccess));
2215 pstring s;
2216 char *p;
2217 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2218 p = s;
2219 while (*p)
2221 if (!(isalnum(*p) || strchr("._-",*p)))
2222 *p = 'X';
2223 p++;
2226 if (strlen(s) > 10) s[10] = 0;
2228 sprintf(fname,"%s.XXXXXX",s);
2231 fnum = find_free_file();
2232 if (fnum < 0)
2233 return(ERROR(ERRSRV,ERRnofids));
2235 strcpy(fname2,(char *)mktemp(fname));
2237 if (!check_name(fname2,cnum))
2238 return(ERROR(ERRDOS,ERRnoaccess));
2240 /* Open for exclusive use, write only. */
2241 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL);
2243 if (!Files[fnum].open)
2244 return(UNIXERROR(ERRDOS,ERRnoaccess));
2246 /* force it to be a print file */
2247 Files[fnum].print_file = True;
2249 outsize = set_message(outbuf,1,0,True);
2250 SSVAL(outbuf,smb_vwv0,fnum);
2252 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2254 return(outsize);
2258 /****************************************************************************
2259 reply to a printclose
2260 ****************************************************************************/
2261 int reply_printclose(char *inbuf,char *outbuf)
2263 int fnum,cnum;
2264 int outsize = set_message(outbuf,0,0,True);
2266 cnum = SVAL(inbuf,smb_tid);
2267 fnum = GETFNUM(inbuf,smb_vwv0);
2269 CHECK_FNUM(fnum,cnum);
2270 CHECK_ERROR(fnum);
2272 if (!CAN_PRINT(cnum))
2273 return(ERROR(ERRDOS,ERRnoaccess));
2275 close_file(fnum);
2277 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2279 return(outsize);
2283 /****************************************************************************
2284 reply to a printqueue
2285 ****************************************************************************/
2286 int reply_printqueue(char *inbuf,char *outbuf)
2288 int cnum;
2289 int outsize = set_message(outbuf,2,3,True);
2290 int max_count = SVAL(inbuf,smb_vwv0);
2291 int start_index = SVAL(inbuf,smb_vwv1);
2292 uint16 vuid;
2294 cnum = SVAL(inbuf,smb_tid);
2295 vuid = SVAL(inbuf,smb_uid);
2297 /* allow checking the queue for anyone */
2298 #if 0
2299 if (!CAN_PRINT(cnum))
2300 return(ERROR(ERRDOS,ERRnoaccess));
2301 #endif
2303 SSVAL(outbuf,smb_vwv0,0);
2304 SSVAL(outbuf,smb_vwv1,0);
2305 CVAL(smb_buf(outbuf),0) = 1;
2306 SSVAL(smb_buf(outbuf),1,0);
2308 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2309 timestring(),cnum,start_index,max_count));
2311 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2313 int i;
2314 cnum = -1;
2316 for (i=0;i<MAX_CONNECTIONS;i++)
2317 if (CAN_PRINT(i) && Connections[i].printer)
2318 cnum = i;
2320 if (cnum == -1)
2321 for (i=0;i<MAX_CONNECTIONS;i++)
2322 if (OPEN_CNUM(i))
2323 cnum = i;
2325 if (!OPEN_CNUM(cnum))
2326 return(ERROR(ERRSRV,ERRinvnid));
2328 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2331 if (!become_user(cnum,vuid))
2332 return(ERROR(ERRSRV,ERRinvnid));
2335 print_queue_struct *queue = NULL;
2336 char *p = smb_buf(outbuf) + 3;
2337 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2338 int num_to_get = ABS(max_count);
2339 int first = (max_count>0?start_index:start_index+max_count+1);
2340 int i;
2342 if (first >= count)
2343 num_to_get = 0;
2344 else
2345 num_to_get = MIN(num_to_get,count-first);
2348 for (i=first;i<first+num_to_get;i++)
2350 put_dos_date2(p,0,queue[i].time);
2351 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2352 SSVAL(p,5,queue[i].job);
2353 SIVAL(p,7,queue[i].size);
2354 CVAL(p,11) = 0;
2355 StrnCpy(p+12,queue[i].user,16);
2356 p += 28;
2359 if (count > 0)
2361 outsize = set_message(outbuf,2,28*count+3,False);
2362 SSVAL(outbuf,smb_vwv0,count);
2363 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2364 CVAL(smb_buf(outbuf),0) = 1;
2365 SSVAL(smb_buf(outbuf),1,28*count);
2368 if (queue) free(queue);
2370 DEBUG(3,("%d entries returned in queue\n",count));
2373 return(outsize);
2377 /****************************************************************************
2378 reply to a printwrite
2379 ****************************************************************************/
2380 int reply_printwrite(char *inbuf,char *outbuf)
2382 int cnum,numtowrite,fnum;
2383 int outsize = set_message(outbuf,0,0,True);
2384 char *data;
2386 cnum = SVAL(inbuf,smb_tid);
2388 if (!CAN_PRINT(cnum))
2389 return(ERROR(ERRDOS,ERRnoaccess));
2391 fnum = GETFNUM(inbuf,smb_vwv0);
2393 CHECK_FNUM(fnum,cnum);
2394 CHECK_WRITE(fnum);
2395 CHECK_ERROR(fnum);
2397 numtowrite = SVAL(smb_buf(inbuf),1);
2398 data = smb_buf(inbuf) + 3;
2400 if (write_file(fnum,data,numtowrite) != numtowrite)
2401 return(UNIXERROR(ERRDOS,ERRnoaccess));
2403 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2405 return(outsize);
2409 /****************************************************************************
2410 reply to a mkdir
2411 ****************************************************************************/
2412 int reply_mkdir(char *inbuf,char *outbuf)
2414 pstring directory;
2415 int cnum;
2416 int outsize,ret= -1;
2418 strcpy(directory,smb_buf(inbuf) + 1);
2419 cnum = SVAL(inbuf,smb_tid);
2420 unix_convert(directory,cnum,0);
2422 if (check_name(directory,cnum))
2423 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2425 if (ret < 0)
2426 return(UNIXERROR(ERRDOS,ERRnoaccess));
2428 outsize = set_message(outbuf,0,0,True);
2430 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2432 return(outsize);
2436 /****************************************************************************
2437 reply to a rmdir
2438 ****************************************************************************/
2439 int reply_rmdir(char *inbuf,char *outbuf)
2441 pstring directory;
2442 int cnum;
2443 int outsize = 0;
2444 BOOL ok = False;
2446 cnum = SVAL(inbuf,smb_tid);
2447 strcpy(directory,smb_buf(inbuf) + 1);
2448 unix_convert(directory,cnum,0);
2450 if (check_name(directory,cnum))
2453 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2454 ok = (sys_rmdir(directory) == 0);
2455 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2457 /* Check to see if the only thing in this directory are
2458 vetoed files/directories. If so then delete them and
2459 retry. If we fail to delete any of them (and we *don't*
2460 do a recursive delete) then fail the rmdir. */
2461 BOOL all_veto_files = True;
2462 char *dname;
2463 void *dirptr = OpenDir(SNUM(cnum), directory, False);
2465 if(dirptr != NULL)
2467 int dirpos = TellDir(dirptr);
2468 while ((dname = ReadDirName(dirptr)))
2470 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2471 continue;
2472 if(!is_vetoed_name(SNUM(cnum), dname))
2474 all_veto_files = False;
2475 break;
2478 if(all_veto_files)
2480 SeekDir(dirptr,dirpos);
2481 while ((dname = ReadDirName(dirptr)))
2483 pstring fullname;
2484 struct stat st;
2486 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2487 continue;
2489 /* Construct the full name. */
2490 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2492 errno = ENOMEM;
2493 break;
2495 strcpy(fullname, directory);
2496 strcat(fullname, "/");
2497 strcat(fullname, dname);
2499 if(sys_lstat(fullname, &st) != 0)
2500 break;
2501 if(st.st_mode & S_IFDIR)
2503 if(sys_rmdir(fullname) != 0)
2504 break;
2506 else if(sys_unlink(fullname) != 0)
2507 break;
2509 CloseDir(dirptr);
2510 /* Retry the rmdir */
2511 ok = (sys_rmdir(directory) == 0);
2513 else
2514 CloseDir(dirptr);
2516 else
2517 errno = ENOTEMPTY;
2520 if (!ok)
2521 DEBUG(3,("couldn't remove directory %s : %s\n",
2522 directory,strerror(errno)));
2525 if (!ok)
2526 return(UNIXERROR(ERRDOS,ERRbadpath));
2528 outsize = set_message(outbuf,0,0,True);
2530 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2532 return(outsize);
2536 /*******************************************************************
2537 resolve wildcards in a filename rename
2538 ********************************************************************/
2539 static BOOL resolve_wildcards(char *name1,char *name2)
2541 fstring root1,root2;
2542 fstring ext1,ext2;
2543 char *p,*p2;
2545 name1 = strrchr(name1,'/');
2546 name2 = strrchr(name2,'/');
2548 if (!name1 || !name2) return(False);
2550 strcpy(root1,name1);
2551 strcpy(root2,name2);
2552 p = strrchr(root1,'.');
2553 if (p) {
2554 *p = 0;
2555 strcpy(ext1,p+1);
2556 } else {
2557 strcpy(ext1,"");
2559 p = strrchr(root2,'.');
2560 if (p) {
2561 *p = 0;
2562 strcpy(ext2,p+1);
2563 } else {
2564 strcpy(ext2,"");
2567 p = root1;
2568 p2 = root2;
2569 while (*p2) {
2570 if (*p2 == '?') {
2571 *p2 = *p;
2572 p2++;
2573 } else {
2574 p2++;
2576 if (*p) p++;
2579 p = ext1;
2580 p2 = ext2;
2581 while (*p2) {
2582 if (*p2 == '?') {
2583 *p2 = *p;
2584 p2++;
2585 } else {
2586 p2++;
2588 if (*p) p++;
2591 strcpy(name2,root2);
2592 if (ext2[0]) {
2593 strcat(name2,".");
2594 strcat(name2,ext2);
2597 return(True);
2600 /*******************************************************************
2601 check if a user is allowed to rename a file
2602 ********************************************************************/
2603 static BOOL can_rename(char *fname,int cnum)
2605 struct stat sbuf;
2607 if (!CAN_WRITE(cnum)) return(False);
2609 if (sys_lstat(fname,&sbuf) != 0) return(False);
2610 if (!check_file_sharing(cnum,fname)) return(False);
2612 return(True);
2615 /****************************************************************************
2616 reply to a mv
2617 ****************************************************************************/
2618 int reply_mv(char *inbuf,char *outbuf)
2620 int outsize = 0;
2621 pstring name;
2622 int cnum;
2623 pstring directory;
2624 pstring mask,newname;
2625 pstring newname_last_component;
2626 char *p;
2627 int count=0;
2628 int error = ERRnoaccess;
2629 BOOL has_wild;
2630 BOOL exists=False;
2632 *directory = *mask = 0;
2634 cnum = SVAL(inbuf,smb_tid);
2636 strcpy(name,smb_buf(inbuf) + 1);
2637 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2639 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2641 unix_convert(name,cnum,0);
2642 unix_convert(newname,cnum,newname_last_component);
2645 * Split the old name into directory and last component
2646 * strings. Note that unix_convert may have stripped off a
2647 * leading ./ from both name and newname if the rename is
2648 * at the root of the share. We need to make sure either both
2649 * name and newname contain a / character or neither of them do
2650 * as this is checked in resolve_wildcards().
2653 p = strrchr(name,'/');
2654 if (!p) {
2655 strcpy(directory,".");
2656 strcpy(mask,name);
2657 } else {
2658 *p = 0;
2659 strcpy(directory,name);
2660 strcpy(mask,p+1);
2661 *p = '/'; /* Replace needed for exceptional test below. */
2664 if (is_mangled(mask))
2665 check_mangled_stack(mask);
2667 has_wild = strchr(mask,'*') || strchr(mask,'?');
2669 if (!has_wild) {
2670 BOOL is_short_name = is_8_3(name, True);
2672 /* Add a terminating '/' to the directory name. */
2673 strcat(directory,"/");
2674 strcat(directory,mask);
2676 /* Ensure newname contains a '/' also */
2677 if(strrchr(newname,'/') == 0) {
2678 pstring tmpstr;
2680 strcpy(tmpstr, "./");
2681 strcat(tmpstr, newname);
2682 strcpy(newname, tmpstr);
2685 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",
2686 case_sensitive, case_preserve, short_case_preserve, directory,
2687 newname, newname_last_component, is_short_name));
2690 * Check for special case with case preserving and not
2691 * case sensitive, if directory and newname are identical,
2692 * and the old last component differs from the original
2693 * last component only by case, then we should allow
2694 * the rename (user is trying to change the case of the
2695 * filename).
2697 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
2698 ((short_case_preserve == True) && (is_short_name == True))) &&
2699 strcsequal(directory, newname)) {
2700 pstring newname_modified_last_component;
2703 * Get the last component of the modified name.
2704 * Note that we guarantee that newname contains a '/'
2705 * character above.
2707 p = strrchr(newname,'/');
2708 strcpy(newname_modified_last_component,p+1);
2710 if(strcsequal(newname_modified_last_component,
2711 newname_last_component) == False) {
2713 * Replace the modified last component with
2714 * the original.
2716 strcpy(p+1, newname_last_component);
2720 if (resolve_wildcards(directory,newname) &&
2721 can_rename(directory,cnum) &&
2722 !file_exist(newname,NULL) &&
2723 !sys_rename(directory,newname)) count++;
2725 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
2726 directory,newname));
2728 if (!count) exists = file_exist(directory,NULL);
2729 if (!count && exists && file_exist(newname,NULL)) {
2730 exists = True;
2731 error = 183;
2733 } else {
2734 void *dirptr = NULL;
2735 char *dname;
2736 pstring destname;
2738 if (check_name(directory,cnum))
2739 dirptr = OpenDir(SNUM(cnum), directory, True);
2741 if (dirptr)
2743 error = ERRbadfile;
2745 if (strequal(mask,"????????.???"))
2746 strcpy(mask,"*");
2748 while ((dname = ReadDirName(dirptr)))
2750 pstring fname;
2751 strcpy(fname,dname);
2753 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2755 error = ERRnoaccess;
2756 sprintf(fname,"%s/%s",directory,dname);
2757 if (!can_rename(fname,cnum)) continue;
2758 strcpy(destname,newname);
2760 if (!resolve_wildcards(fname,destname)) continue;
2762 if (file_exist(destname,NULL)) {
2763 error = 183;
2764 continue;
2766 if (!sys_rename(fname,destname)) count++;
2767 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2769 CloseDir(dirptr);
2773 if (count == 0) {
2774 if (exists)
2775 return(ERROR(ERRDOS,error));
2776 else
2777 return(UNIXERROR(ERRDOS,error));
2780 outsize = set_message(outbuf,0,0,True);
2782 return(outsize);
2785 /*******************************************************************
2786 copy a file as part of a reply_copy
2787 ******************************************************************/
2788 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2789 int count,BOOL target_is_directory)
2791 int Access,action;
2792 struct stat st;
2793 int ret=0;
2794 int fnum1,fnum2;
2795 pstring dest;
2797 strcpy(dest,dest1);
2798 if (target_is_directory) {
2799 char *p = strrchr(src,'/');
2800 if (p)
2801 p++;
2802 else
2803 p = src;
2804 strcat(dest,"/");
2805 strcat(dest,p);
2808 if (!file_exist(src,&st)) return(False);
2810 fnum1 = find_free_file();
2811 if (fnum1<0) return(False);
2812 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2813 1,0,&Access,&action);
2815 if (!Files[fnum1].open) return(False);
2817 if (!target_is_directory && count)
2818 ofun = 1;
2820 fnum2 = find_free_file();
2821 if (fnum2<0) {
2822 close_file(fnum1);
2823 return(False);
2825 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2826 ofun,st.st_mode,&Access,&action);
2828 if (!Files[fnum2].open) {
2829 close_file(fnum1);
2830 return(False);
2833 if ((ofun&3) == 1) {
2834 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
2837 if (st.st_size)
2838 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
2840 close_file(fnum1);
2841 close_file(fnum2);
2843 return(ret == st.st_size);
2848 /****************************************************************************
2849 reply to a file copy.
2850 ****************************************************************************/
2851 int reply_copy(char *inbuf,char *outbuf)
2853 int outsize = 0;
2854 pstring name;
2855 int cnum;
2856 pstring directory;
2857 pstring mask,newname;
2858 char *p;
2859 int count=0;
2860 int error = ERRnoaccess;
2861 BOOL has_wild;
2862 BOOL exists=False;
2863 int tid2 = SVAL(inbuf,smb_vwv0);
2864 int ofun = SVAL(inbuf,smb_vwv1);
2865 int flags = SVAL(inbuf,smb_vwv2);
2866 BOOL target_is_directory=False;
2868 *directory = *mask = 0;
2870 cnum = SVAL(inbuf,smb_tid);
2872 strcpy(name,smb_buf(inbuf));
2873 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2875 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2877 if (tid2 != cnum) {
2878 /* can't currently handle inter share copies XXXX */
2879 DEBUG(3,("Rejecting inter-share copy\n"));
2880 return(ERROR(ERRSRV,ERRinvdevice));
2883 unix_convert(name,cnum,0);
2884 unix_convert(newname,cnum,0);
2886 target_is_directory = directory_exist(newname,NULL);
2888 if ((flags&1) && target_is_directory) {
2889 return(ERROR(ERRDOS,ERRbadfile));
2892 if ((flags&2) && !target_is_directory) {
2893 return(ERROR(ERRDOS,ERRbadpath));
2896 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2897 /* wants a tree copy! XXXX */
2898 DEBUG(3,("Rejecting tree copy\n"));
2899 return(ERROR(ERRSRV,ERRerror));
2902 p = strrchr(name,'/');
2903 if (!p) {
2904 strcpy(directory,"./");
2905 strcpy(mask,name);
2906 } else {
2907 *p = 0;
2908 strcpy(directory,name);
2909 strcpy(mask,p+1);
2912 if (is_mangled(mask))
2913 check_mangled_stack(mask);
2915 has_wild = strchr(mask,'*') || strchr(mask,'?');
2917 if (!has_wild) {
2918 strcat(directory,"/");
2919 strcat(directory,mask);
2920 if (resolve_wildcards(directory,newname) &&
2921 copy_file(directory,newname,cnum,ofun,
2922 count,target_is_directory)) count++;
2923 if (!count) exists = file_exist(directory,NULL);
2924 } else {
2925 void *dirptr = NULL;
2926 char *dname;
2927 pstring destname;
2929 if (check_name(directory,cnum))
2930 dirptr = OpenDir(SNUM(cnum), directory, True);
2932 if (dirptr)
2934 error = ERRbadfile;
2936 if (strequal(mask,"????????.???"))
2937 strcpy(mask,"*");
2939 while ((dname = ReadDirName(dirptr)))
2941 pstring fname;
2942 strcpy(fname,dname);
2944 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2946 error = ERRnoaccess;
2947 sprintf(fname,"%s/%s",directory,dname);
2948 strcpy(destname,newname);
2949 if (resolve_wildcards(fname,destname) &&
2950 copy_file(directory,newname,cnum,ofun,
2951 count,target_is_directory)) count++;
2952 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2954 CloseDir(dirptr);
2958 if (count == 0) {
2959 if (exists)
2960 return(ERROR(ERRDOS,error));
2961 else
2962 return(UNIXERROR(ERRDOS,error));
2965 outsize = set_message(outbuf,1,0,True);
2966 SSVAL(outbuf,smb_vwv0,count);
2968 return(outsize);
2973 /****************************************************************************
2974 reply to a setdir
2975 ****************************************************************************/
2976 int reply_setdir(char *inbuf,char *outbuf)
2978 int cnum,snum;
2979 int outsize = 0;
2980 BOOL ok = False;
2981 pstring newdir;
2983 cnum = SVAL(inbuf,smb_tid);
2985 snum = Connections[cnum].service;
2986 if (!CAN_SETDIR(snum))
2987 return(ERROR(ERRDOS,ERRnoaccess));
2989 strcpy(newdir,smb_buf(inbuf) + 1);
2990 strlower(newdir);
2992 if (strlen(newdir) == 0)
2993 ok = True;
2994 else
2996 ok = directory_exist(newdir,NULL);
2997 if (ok)
2998 string_set(&Connections[cnum].connectpath,newdir);
3001 if (!ok)
3002 return(ERROR(ERRDOS,ERRbadpath));
3004 outsize = set_message(outbuf,0,0,True);
3005 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3007 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3009 return(outsize);
3013 /****************************************************************************
3014 reply to a lockingX request
3015 ****************************************************************************/
3016 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3018 int fnum = GETFNUM(inbuf,smb_vwv2);
3019 uint16 locktype = SVAL(inbuf,smb_vwv3);
3020 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3021 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3022 uint32 count, offset;
3024 int cnum;
3025 int i;
3026 char *data;
3027 uint32 ecode=0, dummy2;
3028 int eclass=0, dummy1;
3030 cnum = SVAL(inbuf,smb_tid);
3032 CHECK_FNUM(fnum,cnum);
3033 CHECK_ERROR(fnum);
3035 data = smb_buf(inbuf);
3036 /* Data now points at the beginning of the list
3037 of smb_unlkrng structs */
3038 for(i = 0; i < (int)num_ulocks; i++) {
3039 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3040 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3041 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3042 return ERROR(eclass,ecode);
3045 /* Now do any requested locks */
3046 data += 10*num_ulocks;
3047 /* Data now points at the beginning of the list
3048 of smb_lkrng structs */
3049 for(i = 0; i < (int)num_locks; i++) {
3050 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3051 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3052 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3053 break;
3056 /* If any of the above locks failed, then we must unlock
3057 all of the previous locks (X/Open spec). */
3058 if(i != num_locks && num_locks != 0) {
3059 for(; i >= 0; i--) {
3060 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3061 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3062 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3064 return ERROR(eclass,ecode);
3067 set_message(outbuf,2,0,True);
3069 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3070 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
3072 chain_fnum = fnum;
3074 return chain_reply(inbuf,outbuf,length,bufsize);
3078 /****************************************************************************
3079 reply to a SMBreadbmpx (read block multiplex) request
3080 ****************************************************************************/
3081 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3083 int cnum,fnum;
3084 int nread = -1;
3085 int total_read;
3086 char *data;
3087 int32 startpos;
3088 int outsize, mincount, maxcount;
3089 int max_per_packet;
3090 int tcount;
3091 int pad;
3093 /* this function doesn't seem to work - disable by default */
3094 if (!lp_readbmpx())
3095 return(ERROR(ERRSRV,ERRuseSTD));
3097 outsize = set_message(outbuf,8,0,True);
3099 cnum = SVAL(inbuf,smb_tid);
3100 fnum = GETFNUM(inbuf,smb_vwv0);
3102 CHECK_FNUM(fnum,cnum);
3103 CHECK_READ(fnum);
3104 CHECK_ERROR(fnum);
3106 startpos = IVAL(inbuf,smb_vwv1);
3107 maxcount = SVAL(inbuf,smb_vwv3);
3108 mincount = SVAL(inbuf,smb_vwv4);
3110 data = smb_buf(outbuf);
3111 pad = ((int)data)%4;
3112 if (pad) pad = 4 - pad;
3113 data += pad;
3115 max_per_packet = bufsize-(outsize+pad);
3116 tcount = maxcount;
3117 total_read = 0;
3119 if (is_locked(fnum,cnum,maxcount,startpos))
3120 return(ERROR(ERRDOS,ERRlock));
3124 int N = MIN(max_per_packet,tcount-total_read);
3126 nread = read_file(fnum,data,startpos,N);
3128 if (nread <= 0) nread = 0;
3130 if (nread < N)
3131 tcount = total_read + nread;
3133 set_message(outbuf,8,nread,False);
3134 SIVAL(outbuf,smb_vwv0,startpos);
3135 SSVAL(outbuf,smb_vwv2,tcount);
3136 SSVAL(outbuf,smb_vwv6,nread);
3137 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3139 send_smb(Client,outbuf);
3141 total_read += nread;
3142 startpos += nread;
3144 while (total_read < tcount);
3146 return(-1);
3150 /****************************************************************************
3151 reply to a SMBwritebmpx (write block multiplex primary) request
3152 ****************************************************************************/
3153 int reply_writebmpx(char *inbuf,char *outbuf)
3155 int cnum,numtowrite,fnum;
3156 int nwritten = -1;
3157 int outsize = 0;
3158 int32 startpos;
3159 int tcount, write_through, smb_doff;
3160 char *data;
3162 cnum = SVAL(inbuf,smb_tid);
3163 fnum = GETFNUM(inbuf,smb_vwv0);
3165 CHECK_FNUM(fnum,cnum);
3166 CHECK_WRITE(fnum);
3167 CHECK_ERROR(fnum);
3169 tcount = SVAL(inbuf,smb_vwv1);
3170 startpos = IVAL(inbuf,smb_vwv3);
3171 write_through = BITSETW(inbuf+smb_vwv7,0);
3172 numtowrite = SVAL(inbuf,smb_vwv10);
3173 smb_doff = SVAL(inbuf,smb_vwv11);
3175 data = smb_base(inbuf) + smb_doff;
3177 /* If this fails we need to send an SMBwriteC response,
3178 not an SMBwritebmpx - set this up now so we don't forget */
3179 CVAL(outbuf,smb_com) = SMBwritec;
3181 if (is_locked(fnum,cnum,tcount,startpos))
3182 return(ERROR(ERRDOS,ERRlock));
3184 seek_file(fnum,startpos);
3185 nwritten = write_file(fnum,data,numtowrite);
3187 if(lp_syncalways(SNUM(cnum)) || write_through)
3188 sync_file(fnum);
3190 if(nwritten < numtowrite)
3191 return(UNIXERROR(ERRHRD,ERRdiskfull));
3193 /* If the maximum to be written to this file
3194 is greater than what we just wrote then set
3195 up a secondary struct to be attached to this
3196 fd, we will use this to cache error messages etc. */
3197 if(tcount > nwritten)
3199 write_bmpx_struct *wbms;
3200 if(Files[fnum].wbmpx_ptr != NULL)
3201 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3202 else
3203 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3204 if(!wbms)
3206 DEBUG(0,("Out of memory in reply_readmpx\n"));
3207 return(ERROR(ERRSRV,ERRnoresource));
3209 wbms->wr_mode = write_through;
3210 wbms->wr_discard = False; /* No errors yet */
3211 wbms->wr_total_written = nwritten;
3212 wbms->wr_errclass = 0;
3213 wbms->wr_error = 0;
3214 Files[fnum].wbmpx_ptr = wbms;
3217 /* We are returning successfully, set the message type back to
3218 SMBwritebmpx */
3219 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3221 outsize = set_message(outbuf,1,0,True);
3223 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3225 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3226 timestring(),fnum,cnum,numtowrite,nwritten));
3228 if (write_through && tcount==nwritten) {
3229 /* we need to send both a primary and a secondary response */
3230 smb_setlen(outbuf,outsize - 4);
3231 send_smb(Client,outbuf);
3233 /* now the secondary */
3234 outsize = set_message(outbuf,1,0,True);
3235 CVAL(outbuf,smb_com) = SMBwritec;
3236 SSVAL(outbuf,smb_vwv0,nwritten);
3239 return(outsize);
3243 /****************************************************************************
3244 reply to a SMBwritebs (write block multiplex secondary) request
3245 ****************************************************************************/
3246 int reply_writebs(char *inbuf,char *outbuf)
3248 int cnum,numtowrite,fnum;
3249 int nwritten = -1;
3250 int outsize = 0;
3251 int32 startpos;
3252 int tcount, write_through, smb_doff;
3253 char *data;
3254 write_bmpx_struct *wbms;
3255 BOOL send_response = False;
3257 cnum = SVAL(inbuf,smb_tid);
3258 fnum = GETFNUM(inbuf,smb_vwv0);
3259 CHECK_FNUM(fnum,cnum);
3260 CHECK_WRITE(fnum);
3262 tcount = SVAL(inbuf,smb_vwv1);
3263 startpos = IVAL(inbuf,smb_vwv2);
3264 numtowrite = SVAL(inbuf,smb_vwv6);
3265 smb_doff = SVAL(inbuf,smb_vwv7);
3267 data = smb_base(inbuf) + smb_doff;
3269 /* We need to send an SMBwriteC response, not an SMBwritebs */
3270 CVAL(outbuf,smb_com) = SMBwritec;
3272 /* This fd should have an auxiliary struct attached,
3273 check that it does */
3274 wbms = Files[fnum].wbmpx_ptr;
3275 if(!wbms) return(-1);
3277 /* If write through is set we can return errors, else we must
3278 cache them */
3279 write_through = wbms->wr_mode;
3281 /* Check for an earlier error */
3282 if(wbms->wr_discard)
3283 return -1; /* Just discard the packet */
3285 seek_file(fnum,startpos);
3286 nwritten = write_file(fnum,data,numtowrite);
3288 if(lp_syncalways(SNUM(cnum)) || write_through)
3289 sync_file(fnum);
3291 if (nwritten < numtowrite)
3293 if(write_through) {
3294 /* We are returning an error - we can delete the aux struct */
3295 if (wbms) free((char *)wbms);
3296 Files[fnum].wbmpx_ptr = NULL;
3297 return(ERROR(ERRHRD,ERRdiskfull));
3299 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3302 /* Increment the total written, if this matches tcount
3303 we can discard the auxiliary struct (hurrah !) and return a writeC */
3304 wbms->wr_total_written += nwritten;
3305 if(wbms->wr_total_written >= tcount)
3307 if (write_through) {
3308 outsize = set_message(outbuf,1,0,True);
3309 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3310 send_response = True;
3313 free((char *)wbms);
3314 Files[fnum].wbmpx_ptr = NULL;
3317 if(send_response)
3318 return(outsize);
3320 return(-1);
3324 /****************************************************************************
3325 reply to a SMBsetattrE
3326 ****************************************************************************/
3327 int reply_setattrE(char *inbuf,char *outbuf)
3329 int cnum,fnum;
3330 struct utimbuf unix_times;
3331 int outsize = 0;
3333 outsize = set_message(outbuf,0,0,True);
3335 cnum = SVAL(inbuf,smb_tid);
3336 fnum = GETFNUM(inbuf,smb_vwv0);
3338 CHECK_FNUM(fnum,cnum);
3339 CHECK_ERROR(fnum);
3341 /* Convert the DOS times into unix times. Ignore create
3342 time as UNIX can't set this.
3344 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3345 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3347 /* Set the date on this file */
3348 if(sys_utime(Files[fnum].name, &unix_times))
3349 return(ERROR(ERRDOS,ERRnoaccess));
3351 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3353 return(outsize);
3357 /****************************************************************************
3358 reply to a SMBgetattrE
3359 ****************************************************************************/
3360 int reply_getattrE(char *inbuf,char *outbuf)
3362 int cnum,fnum;
3363 struct stat sbuf;
3364 int outsize = 0;
3365 int mode;
3367 outsize = set_message(outbuf,11,0,True);
3369 cnum = SVAL(inbuf,smb_tid);
3370 fnum = GETFNUM(inbuf,smb_vwv0);
3372 CHECK_FNUM(fnum,cnum);
3373 CHECK_ERROR(fnum);
3375 /* Do an fstat on this file */
3376 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3377 return(UNIXERROR(ERRDOS,ERRnoaccess));
3379 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3381 /* Convert the times into dos times. Set create
3382 date to be last modify date as UNIX doesn't save
3383 this */
3384 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3385 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3386 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3387 if (mode & aDIR)
3389 SIVAL(outbuf,smb_vwv6,0);
3390 SIVAL(outbuf,smb_vwv8,0);
3392 else
3394 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3395 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3397 SSVAL(outbuf,smb_vwv10, mode);
3399 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3401 return(outsize);