Makefile: Changed for HPUX10 tidyup.
[Samba.git] / source / smbd / reply.c
blob0216b58c34afea10af93e8ba85397c93b07ea325
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1997
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
27 #include "includes.h"
28 #include "trans2.h"
30 /* look in server.c for some explanation of these variables */
31 extern int Protocol;
32 extern int DEBUGLEVEL;
33 extern int max_send;
34 extern int max_recv;
35 extern int chain_fnum;
36 extern char magic_char;
37 extern connection_struct Connections[];
38 extern files_struct Files[];
39 extern BOOL case_sensitive;
40 extern BOOL case_preserve;
41 extern BOOL short_case_preserve;
42 extern pstring sesssetup_user;
43 extern fstring myworkgroup;
44 extern int Client;
46 /* this macro should always be used to extract an fnum (smb_fid) from
47 a packet to ensure chaining works correctly */
48 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
51 /****************************************************************************
52 reply to an special message
53 ****************************************************************************/
54 int reply_special(char *inbuf,char *outbuf)
56 int outsize = 4;
57 int msg_type = CVAL(inbuf,0);
58 int msg_flags = CVAL(inbuf,1);
59 pstring name1,name2;
60 extern fstring remote_machine;
61 extern fstring local_machine;
62 char *p;
64 *name1 = *name2 = 0;
66 smb_setlen(outbuf,0);
68 switch (msg_type)
70 case 0x81: /* session request */
71 CVAL(outbuf,0) = 0x82;
72 CVAL(outbuf,3) = 0;
73 if (name_len(inbuf+4) > 50)
75 DEBUG(0,("Invalid name length in session request\n"));
76 return(0);
78 name_extract(inbuf,4,name1);
79 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
80 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2));
82 strcpy(remote_machine,name2);
83 trim_string(remote_machine," "," ");
84 p = strchr(remote_machine,' ');
85 strlower(remote_machine);
86 if (p) *p = 0;
88 strcpy(local_machine,name1);
89 trim_string(local_machine," "," ");
90 p = strchr(local_machine,' ');
91 strlower(local_machine);
92 if (p) *p = 0;
94 add_session_user(remote_machine);
96 reload_services(True);
97 reopen_logs();
99 break;
100 case 0x85: /* session keepalive */
101 default:
102 return(0);
105 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags));
107 return(outsize);
111 /*******************************************************************
112 work out what error to give to a failed connection
113 ********************************************************************/
114 static int connection_error(char *inbuf,char *outbuf,int connection_num)
116 switch (connection_num)
118 case -8:
119 return(ERROR(ERRSRV,ERRnoresource));
120 case -7:
121 return(ERROR(ERRSRV,ERRbaduid));
122 case -6:
123 return(ERROR(ERRSRV,ERRinvdevice));
124 case -5:
125 return(ERROR(ERRSRV,ERRinvnetname));
126 case -4:
127 return(ERROR(ERRSRV,ERRaccess));
128 case -3:
129 return(ERROR(ERRDOS,ERRnoipc));
130 case -2:
131 return(ERROR(ERRSRV,ERRinvnetname));
133 return(ERROR(ERRSRV,ERRbadpw));
138 /****************************************************************************
139 parse a share descriptor string
140 ****************************************************************************/
141 static void parse_connect(char *p,char *service,char *user,
142 char *password,int *pwlen,char *dev)
144 char *p2;
146 DEBUG(4,("parsing connect string %s\n",p));
148 p2 = strrchr(p,'\\');
149 if (p2 == NULL)
150 strcpy(service,p);
151 else
152 strcpy(service,p2+1);
154 p += strlen(p) + 2;
156 strcpy(password,p);
157 *pwlen = strlen(password);
159 p += strlen(p) + 2;
161 strcpy(dev,p);
163 *user = 0;
164 p = strchr(service,'%');
165 if (p != NULL)
167 *p = 0;
168 strcpy(user,p+1);
175 /****************************************************************************
176 reply to a tcon
177 ****************************************************************************/
178 int reply_tcon(char *inbuf,char *outbuf)
180 pstring service;
181 pstring user;
182 pstring password;
183 pstring dev;
184 int connection_num;
185 int outsize = 0;
186 uint16 vuid = SVAL(inbuf,smb_uid);
187 int pwlen=0;
189 *service = *user = *password = *dev = 0;
191 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
193 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
195 if (connection_num < 0)
196 return(connection_error(inbuf,outbuf,connection_num));
198 outsize = set_message(outbuf,2,0,True);
199 SSVAL(outbuf,smb_vwv0,max_recv);
200 SSVAL(outbuf,smb_vwv1,connection_num);
201 SSVAL(outbuf,smb_tid,connection_num);
203 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
205 return(outsize);
209 /****************************************************************************
210 reply to a tcon and X
211 ****************************************************************************/
212 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
214 pstring service;
215 pstring user;
216 pstring password;
217 pstring devicename;
218 int connection_num;
219 uint16 vuid = SVAL(inbuf,smb_uid);
220 int passlen = SVAL(inbuf,smb_vwv3);
221 BOOL doencrypt = SMBENCRYPT();
223 *service = *user = *password = *devicename = 0;
225 /* we might have to close an old one */
226 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
227 close_cnum(SVAL(inbuf,smb_tid),vuid);
230 char *path;
231 char *p;
232 memcpy(password,smb_buf(inbuf),passlen);
233 password[passlen]=0;
234 path = smb_buf(inbuf) + passlen;
236 if (!doencrypt || passlen != 24) {
237 if (strequal(password," "))
238 *password = 0;
239 passlen = strlen(password);
242 DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
243 strcpy(service,path+2);
244 p = strchr(service,'\\');
245 if (!p)
246 return(ERROR(ERRSRV,ERRinvnetname));
247 *p = 0;
248 strcpy(service,p+1);
249 p = strchr(service,'%');
250 if (p)
252 *p++ = 0;
253 strcpy(user,p);
255 StrnCpy(devicename,path + strlen(path) + 1,6);
256 DEBUG(4,("Got device type %s\n",devicename));
259 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
261 if (connection_num < 0)
262 return(connection_error(inbuf,outbuf,connection_num));
264 set_message(outbuf,2,strlen(devicename)+1,True);
266 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
268 /* set the incoming and outgoing tid to the just created one */
269 SSVAL(inbuf,smb_tid,connection_num);
270 SSVAL(outbuf,smb_tid,connection_num);
272 strcpy(smb_buf(outbuf),devicename);
274 return chain_reply(inbuf,outbuf,length,bufsize);
278 /****************************************************************************
279 reply to an unknown type
280 ****************************************************************************/
281 int reply_unknown(char *inbuf,char *outbuf)
283 int cnum;
284 int type;
285 cnum = SVAL(inbuf,smb_tid);
286 type = CVAL(inbuf,smb_com);
288 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
289 timestring(),
290 smb_fn_name(type),
291 cnum,type,type));
293 return(ERROR(ERRSRV,ERRunknownsmb));
297 /****************************************************************************
298 reply to an ioctl
299 ****************************************************************************/
300 int reply_ioctl(char *inbuf,char *outbuf)
302 DEBUG(3,("ignoring ioctl\n"));
303 #if 0
304 /* we just say it succeeds and hope its all OK.
305 some day it would be nice to interpret them individually */
306 return set_message(outbuf,1,0,True);
307 #else
308 return(ERROR(ERRSRV,ERRnosupport));
309 #endif
313 /****************************************************************************
314 reply to a session setup command
315 ****************************************************************************/
316 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
318 uint16 sess_vuid;
319 int gid;
320 int uid;
321 int smb_bufsize;
322 int smb_mpxmax;
323 int smb_vc_num;
324 uint32 smb_sesskey;
325 int smb_apasslen = 0;
326 pstring smb_apasswd;
327 int smb_ntpasslen = 0;
328 pstring smb_ntpasswd;
329 BOOL valid_nt_password = False;
330 pstring user;
331 BOOL guest=False;
332 BOOL computer_id=False;
333 static BOOL done_sesssetup = False;
334 BOOL doencrypt = SMBENCRYPT();
336 *smb_apasswd = 0;
338 smb_bufsize = SVAL(inbuf,smb_vwv2);
339 smb_mpxmax = SVAL(inbuf,smb_vwv3);
340 smb_vc_num = SVAL(inbuf,smb_vwv4);
341 smb_sesskey = IVAL(inbuf,smb_vwv5);
343 if (Protocol < PROTOCOL_NT1) {
344 smb_apasslen = SVAL(inbuf,smb_vwv7);
345 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
346 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
348 if (lp_security() != SEC_SERVER && !doencrypt)
349 smb_apasslen = strlen(smb_apasswd);
350 } else {
351 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
352 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
353 char *p = smb_buf(inbuf);
355 if (passlen1 != 24 && passlen2 != 24)
356 doencrypt = False;
358 if(doencrypt) {
359 /* Save the lanman2 password and the NT md4 password. */
360 smb_apasslen = passlen1;
361 memcpy(smb_apasswd,p,smb_apasslen);
362 smb_ntpasslen = passlen2;
363 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
364 } else {
365 /* both Win95 and WinNT stuff up the password lengths for
366 non-encrypting systems. Uggh.
368 if passlen1==24 its a win95 system, and its setting the
369 password length incorrectly. Luckily it still works with the
370 default code because Win95 will null terminate the password
371 anyway
373 if passlen1>0 and passlen2>0 then maybe its a NT box and its
374 setting passlen2 to some random value which really stuffs
375 things up. we need to fix that one. */
376 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
377 passlen2 != 1) {
378 passlen2 = 0;
380 /* we use the first password that they gave */
381 smb_apasslen = passlen1;
382 StrnCpy(smb_apasswd,p,smb_apasslen);
384 /* trim the password */
385 smb_apasslen = strlen(smb_apasswd);
387 /* wfwg sometimes uses a space instead of a null */
388 if (strequal(smb_apasswd," ")) {
389 smb_apasslen = 0;
390 *smb_apasswd = 0;
394 p += passlen1 + passlen2;
395 strcpy(user,p); p = skip_string(p,1);
396 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
397 p,skip_string(p,1),skip_string(p,2)));
401 DEBUG(3,("sesssetupX:name=[%s]\n",user));
403 /* If name ends in $ then I think it's asking about whether a */
404 /* computer with that name (minus the $) has access. For now */
405 /* say yes to everything ending in $. */
406 if (user[strlen(user) - 1] == '$') {
407 computer_id = True;
408 user[strlen(user) - 1] = '\0';
412 /* If no username is sent use the guest account */
413 if (!*user)
415 strcpy(user,lp_guestaccount(-1));
416 /* If no user and no password then set guest flag. */
417 if( *smb_apasswd == 0)
418 guest = True;
421 strlower(user);
423 strcpy(sesssetup_user,user);
425 reload_services(True);
427 add_session_user(user);
430 if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
431 !check_hosts_equiv(user))
434 /* now check if it's a valid username/password */
435 /* If an NT password was supplied try and validate with that
436 first. This is superior as the passwords are mixed case
437 128 length unicode */
438 if(smb_ntpasslen)
440 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
441 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
442 else
443 valid_nt_password = True;
445 if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
447 if (!computer_id && lp_security() >= SEC_USER) {
448 #if (GUEST_SESSSETUP == 0)
449 return(ERROR(ERRSRV,ERRbadpw));
450 #endif
451 #if (GUEST_SESSSETUP == 1)
452 if (Get_Pwnam(user,True))
453 return(ERROR(ERRSRV,ERRbadpw));
454 #endif
456 if (*smb_apasswd || !Get_Pwnam(user,True))
457 strcpy(user,lp_guestaccount(-1));
458 DEBUG(3,("Registered username %s for guest access\n",user));
459 guest = True;
463 if (!Get_Pwnam(user,True)) {
464 DEBUG(3,("No such user %s - using guest account\n",user));
465 strcpy(user,lp_guestaccount(-1));
466 guest = True;
469 if (!strequal(user,lp_guestaccount(-1)) &&
470 lp_servicenumber(user) < 0)
472 int homes = lp_servicenumber(HOMES_NAME);
473 char *home = get_home_dir(user);
474 if (homes >= 0 && home)
475 lp_add_home(user,homes,home);
479 /* it's ok - setup a reply */
480 if (Protocol < PROTOCOL_NT1) {
481 set_message(outbuf,3,0,True);
482 } else {
483 char *p;
484 set_message(outbuf,3,3,True);
485 p = smb_buf(outbuf);
486 strcpy(p,"Unix"); p = skip_string(p,1);
487 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
488 strcpy(p,myworkgroup); p = skip_string(p,1);
489 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
490 /* perhaps grab OS version here?? */
493 /* Set the correct uid in the outgoing and incoming packets
494 We will use this on future requests to determine which
495 user we should become.
498 struct passwd *pw = Get_Pwnam(user,False);
499 if (!pw) {
500 DEBUG(1,("Username %s is invalid on this system\n",user));
501 return(ERROR(ERRSRV,ERRbadpw));
503 gid = pw->pw_gid;
504 uid = pw->pw_uid;
507 if (guest && !computer_id)
508 SSVAL(outbuf,smb_vwv2,1);
510 /* register the name and uid as being validated, so further connections
511 to a uid can get through without a password, on the same VC */
512 sess_vuid = register_vuid(uid,gid,user,guest);
514 SSVAL(outbuf,smb_uid,sess_vuid);
515 SSVAL(inbuf,smb_uid,sess_vuid);
517 if (!done_sesssetup)
518 max_send = MIN(max_send,smb_bufsize);
520 DEBUG(1,(" Client requested max send size of %d\n", max_send));
522 done_sesssetup = True;
524 return chain_reply(inbuf,outbuf,length,bufsize);
528 /****************************************************************************
529 reply to a chkpth
530 ****************************************************************************/
531 int reply_chkpth(char *inbuf,char *outbuf)
533 int outsize = 0;
534 int cnum,mode;
535 pstring name;
536 BOOL ok = False;
538 cnum = SVAL(inbuf,smb_tid);
540 strcpy(name,smb_buf(inbuf) + 1);
541 unix_convert(name,cnum,0);
543 mode = SVAL(inbuf,smb_vwv0);
545 if (check_name(name,cnum))
546 ok = directory_exist(name,NULL);
548 if (!ok)
549 return(ERROR(ERRDOS,ERRbadpath));
551 outsize = set_message(outbuf,0,0,True);
553 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
555 return(outsize);
559 /****************************************************************************
560 reply to a getatr
561 ****************************************************************************/
562 int reply_getatr(char *inbuf,char *outbuf)
564 pstring fname;
565 int cnum;
566 int outsize = 0;
567 struct stat sbuf;
568 BOOL ok = False;
569 int mode=0;
570 uint32 size=0;
571 time_t mtime=0;
573 cnum = SVAL(inbuf,smb_tid);
575 strcpy(fname,smb_buf(inbuf) + 1);
576 unix_convert(fname,cnum,0);
578 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
579 under WfWg - weird! */
580 if (! (*fname))
582 mode = aHIDDEN | aDIR;
583 if (!CAN_WRITE(cnum)) mode |= aRONLY;
584 size = 0;
585 mtime = 0;
586 ok = True;
588 else
589 if (check_name(fname,cnum))
591 if (sys_stat(fname,&sbuf) == 0)
593 mode = dos_mode(cnum,fname,&sbuf);
594 size = sbuf.st_size;
595 mtime = sbuf.st_mtime;
596 if (mode & aDIR)
597 size = 0;
598 ok = True;
600 else
601 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
604 if (!ok)
605 return(UNIXERROR(ERRDOS,ERRbadfile));
607 outsize = set_message(outbuf,10,0,True);
609 SSVAL(outbuf,smb_vwv0,mode);
610 put_dos_date3(outbuf,smb_vwv1,mtime);
611 SIVAL(outbuf,smb_vwv3,size);
613 if (Protocol >= PROTOCOL_NT1) {
614 char *p = strrchr(fname,'/');
615 uint16 flg2 = SVAL(outbuf,smb_flg2);
616 if (!p) p = fname;
617 if (!is_8_3(fname, True))
618 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
621 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
623 return(outsize);
627 /****************************************************************************
628 reply to a setatr
629 ****************************************************************************/
630 int reply_setatr(char *inbuf,char *outbuf)
632 pstring fname;
633 int cnum;
634 int outsize = 0;
635 BOOL ok=False;
636 int mode;
637 time_t mtime;
639 cnum = SVAL(inbuf,smb_tid);
641 strcpy(fname,smb_buf(inbuf) + 1);
642 unix_convert(fname,cnum,0);
644 mode = SVAL(inbuf,smb_vwv0);
645 mtime = make_unix_date3(inbuf+smb_vwv1);
647 if (directory_exist(fname,NULL))
648 mode |= aDIR;
649 if (check_name(fname,cnum))
650 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
651 if (ok)
652 ok = set_filetime(fname,mtime);
654 if (!ok)
655 return(UNIXERROR(ERRDOS,ERRnoaccess));
657 outsize = set_message(outbuf,0,0,True);
659 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
661 return(outsize);
665 /****************************************************************************
666 reply to a dskattr
667 ****************************************************************************/
668 int reply_dskattr(char *inbuf,char *outbuf)
670 int cnum;
671 int outsize = 0;
672 int dfree,dsize,bsize;
674 cnum = SVAL(inbuf,smb_tid);
676 sys_disk_free(".",&bsize,&dfree,&dsize);
678 outsize = set_message(outbuf,5,0,True);
680 SSVAL(outbuf,smb_vwv0,dsize);
681 SSVAL(outbuf,smb_vwv1,bsize/512);
682 SSVAL(outbuf,smb_vwv2,512);
683 SSVAL(outbuf,smb_vwv3,dfree);
685 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
687 return(outsize);
691 /****************************************************************************
692 reply to a search
693 Can be called from SMBsearch, SMBffirst or SMBfunique.
694 ****************************************************************************/
695 int reply_search(char *inbuf,char *outbuf)
697 pstring mask;
698 pstring directory;
699 pstring fname;
700 int size,mode;
701 time_t date;
702 int dirtype;
703 int cnum;
704 int outsize = 0;
705 int numentries = 0;
706 BOOL finished = False;
707 int maxentries;
708 int i;
709 char *p;
710 BOOL ok = False;
711 int status_len;
712 char *path;
713 char status[21];
714 int dptr_num= -1;
715 BOOL check_descend = False;
716 BOOL expect_close = False;
717 BOOL can_open = True;
719 *mask = *directory = *fname = 0;
721 /* If we were called as SMBffirst then we must expect close. */
722 if(CVAL(inbuf,smb_com) == SMBffirst)
723 expect_close = True;
725 cnum = SVAL(inbuf,smb_tid);
727 outsize = set_message(outbuf,1,3,True);
728 maxentries = SVAL(inbuf,smb_vwv0);
729 dirtype = SVAL(inbuf,smb_vwv1);
730 path = smb_buf(inbuf) + 1;
731 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
734 /* dirtype &= ~aDIR; */
736 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
739 if (status_len == 0)
741 pstring dir2;
743 strcpy(directory,smb_buf(inbuf)+1);
744 strcpy(dir2,smb_buf(inbuf)+1);
745 unix_convert(directory,cnum,0);
746 unix_format(dir2);
748 if (!check_name(directory,cnum))
749 can_open = False;
751 p = strrchr(dir2,'/');
752 if (p == NULL)
753 {strcpy(mask,dir2);*dir2 = 0;}
754 else
755 {*p = 0;strcpy(mask,p+1);}
757 p = strrchr(directory,'/');
758 if (!p)
759 *directory = 0;
760 else
761 *p = 0;
763 if (strlen(directory) == 0)
764 strcpy(directory,"./");
765 bzero(status,21);
766 CVAL(status,0) = dirtype;
768 else
770 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
771 memcpy(mask,status+1,11);
772 mask[11] = 0;
773 dirtype = CVAL(status,0) & 0x1F;
774 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
775 if (!Connections[cnum].dirptr)
776 goto SearchEmpty;
777 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
778 if (!case_sensitive)
779 strnorm(mask);
782 /* turn strings of spaces into a . */
784 trim_string(mask,NULL," ");
785 if ((p = strrchr(mask,' ')))
787 fstring ext;
788 strcpy(ext,p+1);
789 *p = 0;
790 trim_string(mask,NULL," ");
791 strcat(mask,".");
792 strcat(mask,ext);
797 for (p=mask; *p; p++)
799 if (*p != '?' && *p != '*' && !isdoschar(*p))
801 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
802 *p = '?';
807 if (!strchr(mask,'.') && strlen(mask)>8)
809 fstring tmp;
810 strcpy(tmp,&mask[8]);
811 mask[8] = '.';
812 mask[9] = 0;
813 strcat(mask,tmp);
816 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
818 if (can_open)
820 p = smb_buf(outbuf) + 3;
822 ok = True;
824 if (status_len == 0)
826 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
827 if (dptr_num < 0)
828 return(ERROR(ERRDOS,ERRnofids));
831 DEBUG(4,("dptr_num is %d\n",dptr_num));
833 if (ok)
835 if ((dirtype&0x1F) == aVOLID)
837 memcpy(p,status,21);
838 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
839 dptr_fill(p+12,dptr_num);
840 if (dptr_zero(p+12) && (status_len==0))
841 numentries = 1;
842 else
843 numentries = 0;
844 p += DIR_STRUCT_SIZE;
846 else
848 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
849 if (in_list(Connections[cnum].dirpath,
850 lp_dontdescend(SNUM(cnum)),True))
851 check_descend = True;
853 for (i=numentries;(i<maxentries) && !finished;i++)
855 finished =
856 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
857 if (!finished)
859 memcpy(p,status,21);
860 make_dir_struct(p,mask,fname,size,mode,date);
861 dptr_fill(p+12,dptr_num);
862 numentries++;
864 p += DIR_STRUCT_SIZE;
871 SearchEmpty:
873 if (numentries == 0 || !ok)
875 CVAL(outbuf,smb_rcls) = ERRDOS;
876 SSVAL(outbuf,smb_err,ERRnofiles);
879 /* If we were called as SMBffirst with smb_search_id == NULL
880 and no entries were found then return error and close dirptr
881 (X/Open spec) */
883 if(ok && expect_close && numentries == 0 && status_len == 0)
885 CVAL(outbuf,smb_rcls) = ERRDOS;
886 SSVAL(outbuf,smb_err,ERRnofiles);
887 /* Also close the dptr - we know it's gone */
888 dptr_close(dptr_num);
891 /* If we were called as SMBfunique, then we can close the dirptr now ! */
892 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
893 dptr_close(dptr_num);
895 SSVAL(outbuf,smb_vwv0,numentries);
896 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
897 CVAL(smb_buf(outbuf),0) = 5;
898 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
900 if (Protocol >= PROTOCOL_NT1) {
901 uint16 flg2 = SVAL(outbuf,smb_flg2);
902 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
905 outsize += DIR_STRUCT_SIZE*numentries;
906 smb_setlen(outbuf,outsize - 4);
908 if ((! *directory) && dptr_path(dptr_num))
909 sprintf(directory,"(%s)",dptr_path(dptr_num));
911 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
912 timestring(),
913 smb_fn_name(CVAL(inbuf,smb_com)),
914 mask,directory,cnum,dirtype,numentries,maxentries));
916 return(outsize);
920 /****************************************************************************
921 reply to a fclose (stop directory search)
922 ****************************************************************************/
923 int reply_fclose(char *inbuf,char *outbuf)
925 int cnum;
926 int outsize = 0;
927 int status_len;
928 char *path;
929 char status[21];
930 int dptr_num= -1;
932 cnum = SVAL(inbuf,smb_tid);
934 outsize = set_message(outbuf,1,0,True);
935 path = smb_buf(inbuf) + 1;
936 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
939 if (status_len == 0)
940 return(ERROR(ERRSRV,ERRsrverror));
942 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
944 if(dptr_fetch(status+12,&dptr_num)) {
945 /* Close the dptr - we know it's gone */
946 dptr_close(dptr_num);
949 SSVAL(outbuf,smb_vwv0,0);
951 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
953 return(outsize);
957 /****************************************************************************
958 reply to an open
959 ****************************************************************************/
960 int reply_open(char *inbuf,char *outbuf)
962 pstring fname;
963 int cnum;
964 int fnum = -1;
965 int outsize = 0;
966 int fmode=0;
967 int share_mode;
968 int size = 0;
969 time_t mtime=0;
970 int unixmode;
971 int rmode=0;
972 struct stat sbuf;
974 cnum = SVAL(inbuf,smb_tid);
976 share_mode = SVAL(inbuf,smb_vwv0);
978 strcpy(fname,smb_buf(inbuf)+1);
979 unix_convert(fname,cnum,0);
981 fnum = find_free_file();
982 if (fnum < 0)
983 return(ERROR(ERRSRV,ERRnofids));
985 if (!check_name(fname,cnum))
986 return(UNIXERROR(ERRDOS,ERRnoaccess));
988 unixmode = unix_mode(cnum,aARCH);
990 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
992 if (!Files[fnum].open)
993 return(UNIXERROR(ERRDOS,ERRnoaccess));
995 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
996 close_file(fnum);
997 return(ERROR(ERRDOS,ERRnoaccess));
1000 size = sbuf.st_size;
1001 fmode = dos_mode(cnum,fname,&sbuf);
1002 mtime = sbuf.st_mtime;
1004 if (fmode & aDIR) {
1005 DEBUG(3,("attempt to open a directory %s\n",fname));
1006 close_file(fnum);
1007 return(ERROR(ERRDOS,ERRnoaccess));
1010 outsize = set_message(outbuf,7,0,True);
1011 SSVAL(outbuf,smb_vwv0,fnum);
1012 SSVAL(outbuf,smb_vwv1,fmode);
1013 put_dos_date3(outbuf,smb_vwv2,mtime);
1014 SIVAL(outbuf,smb_vwv4,size);
1015 SSVAL(outbuf,smb_vwv6,rmode);
1017 if (lp_fake_oplocks(SNUM(cnum))) {
1018 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1021 return(outsize);
1025 /****************************************************************************
1026 reply to an open and X
1027 ****************************************************************************/
1028 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1030 pstring fname;
1031 int cnum = SVAL(inbuf,smb_tid);
1032 int fnum = -1;
1033 int smb_mode = SVAL(inbuf,smb_vwv3);
1034 int smb_attr = SVAL(inbuf,smb_vwv5);
1035 BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
1036 #if 0
1037 int open_flags = SVAL(inbuf,smb_vwv2);
1038 int smb_sattr = SVAL(inbuf,smb_vwv4);
1039 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1040 #endif
1041 int smb_ofun = SVAL(inbuf,smb_vwv8);
1042 int unixmode;
1043 int size=0,fmode=0,mtime=0,rmode=0;
1044 struct stat sbuf;
1045 int smb_action = 0;
1047 /* If it's an IPC, pass off the pipe handler. */
1048 if (IS_IPC(cnum))
1049 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1051 /* XXXX we need to handle passed times, sattr and flags */
1053 strcpy(fname,smb_buf(inbuf));
1054 unix_convert(fname,cnum,0);
1056 fnum = find_free_file();
1057 if (fnum < 0)
1058 return(ERROR(ERRSRV,ERRnofids));
1060 if (!check_name(fname,cnum))
1061 return(UNIXERROR(ERRDOS,ERRnoaccess));
1063 unixmode = unix_mode(cnum,smb_attr | aARCH);
1065 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1066 &rmode,&smb_action);
1068 if (!Files[fnum].open)
1069 return(UNIXERROR(ERRDOS,ERRnoaccess));
1071 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1072 close_file(fnum);
1073 return(ERROR(ERRDOS,ERRnoaccess));
1076 size = sbuf.st_size;
1077 fmode = dos_mode(cnum,fname,&sbuf);
1078 mtime = sbuf.st_mtime;
1079 if (fmode & aDIR) {
1080 close_file(fnum);
1081 return(ERROR(ERRDOS,ERRnoaccess));
1084 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1085 smb_action |= (1<<15);
1088 set_message(outbuf,15,0,True);
1089 SSVAL(outbuf,smb_vwv2,fnum);
1090 SSVAL(outbuf,smb_vwv3,fmode);
1091 put_dos_date3(outbuf,smb_vwv4,mtime);
1092 SIVAL(outbuf,smb_vwv6,size);
1093 SSVAL(outbuf,smb_vwv8,rmode);
1094 SSVAL(outbuf,smb_vwv11,smb_action);
1096 chain_fnum = fnum;
1098 return chain_reply(inbuf,outbuf,length,bufsize);
1102 /****************************************************************************
1103 reply to a SMBulogoffX
1104 ****************************************************************************/
1105 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1107 uint16 vuid = SVAL(inbuf,smb_uid);
1108 user_struct *vuser = get_valid_user_struct(vuid);
1110 if(vuser == 0) {
1111 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1114 /* in user level security we are supposed to close any files
1115 open by this user */
1116 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1117 int i;
1118 for (i=0;i<MAX_OPEN_FILES;i++)
1119 if (Files[i].uid == vuser->uid && Files[i].open) {
1120 close_file(i);
1124 invalidate_vuid(vuid);
1126 set_message(outbuf,2,0,True);
1128 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1130 return chain_reply(inbuf,outbuf,length,bufsize);
1134 /****************************************************************************
1135 reply to a mknew or a create
1136 ****************************************************************************/
1137 int reply_mknew(char *inbuf,char *outbuf)
1139 pstring fname;
1140 int cnum,com;
1141 int fnum = -1;
1142 int outsize = 0;
1143 int createmode;
1144 mode_t unixmode;
1145 int ofun = 0;
1147 com = SVAL(inbuf,smb_com);
1148 cnum = SVAL(inbuf,smb_tid);
1150 createmode = SVAL(inbuf,smb_vwv0);
1151 strcpy(fname,smb_buf(inbuf)+1);
1152 unix_convert(fname,cnum,0);
1154 if (createmode & aVOLID)
1156 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1159 unixmode = unix_mode(cnum,createmode);
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 if(com == SMBmknew)
1170 /* We should fail if file exists. */
1171 ofun = 0x10;
1173 else
1175 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1176 ofun = 0x12;
1179 /* Open file in dos compatibility share mode. */
1180 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL);
1182 if (!Files[fnum].open)
1183 return(UNIXERROR(ERRDOS,ERRnoaccess));
1185 outsize = set_message(outbuf,1,0,True);
1186 SSVAL(outbuf,smb_vwv0,fnum);
1188 if (lp_fake_oplocks(SNUM(cnum))) {
1189 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1192 DEBUG(2,("new file %s\n",fname));
1193 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));
1195 return(outsize);
1199 /****************************************************************************
1200 reply to a create temporary file
1201 ****************************************************************************/
1202 int reply_ctemp(char *inbuf,char *outbuf)
1204 pstring fname;
1205 pstring fname2;
1206 int cnum;
1207 int fnum = -1;
1208 int outsize = 0;
1209 int createmode;
1210 mode_t unixmode;
1212 cnum = SVAL(inbuf,smb_tid);
1213 createmode = SVAL(inbuf,smb_vwv0);
1214 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1215 unix_convert(fname,cnum,0);
1217 unixmode = unix_mode(cnum,createmode);
1219 fnum = find_free_file();
1220 if (fnum < 0)
1221 return(ERROR(ERRSRV,ERRnofids));
1223 if (!check_name(fname,cnum))
1224 return(UNIXERROR(ERRDOS,ERRnoaccess));
1226 strcpy(fname2,(char *)mktemp(fname));
1228 /* Open file in dos compatibility share mode. */
1229 /* We should fail if file exists. */
1230 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL);
1232 if (!Files[fnum].open)
1233 return(UNIXERROR(ERRDOS,ERRnoaccess));
1235 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1236 SSVAL(outbuf,smb_vwv0,fnum);
1237 CVAL(smb_buf(outbuf),0) = 4;
1238 strcpy(smb_buf(outbuf) + 1,fname2);
1240 if (lp_fake_oplocks(SNUM(cnum))) {
1241 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1244 DEBUG(2,("created temp file %s\n",fname2));
1245 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));
1247 return(outsize);
1251 /*******************************************************************
1252 check if a user is allowed to delete a file
1253 ********************************************************************/
1254 static BOOL can_delete(char *fname,int cnum,int dirtype)
1256 struct stat sbuf;
1257 int fmode;
1259 if (!CAN_WRITE(cnum)) return(False);
1261 if (sys_lstat(fname,&sbuf) != 0) return(False);
1262 fmode = dos_mode(cnum,fname,&sbuf);
1263 if (fmode & aDIR) return(False);
1264 if (!lp_delete_readonly(SNUM(cnum))) {
1265 if (fmode & aRONLY) return(False);
1267 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1268 return(False);
1269 if (!check_file_sharing(cnum,fname)) return(False);
1270 return(True);
1273 /****************************************************************************
1274 reply to a unlink
1275 ****************************************************************************/
1276 int reply_unlink(char *inbuf,char *outbuf)
1278 int outsize = 0;
1279 pstring name;
1280 int cnum;
1281 int dirtype;
1282 pstring directory;
1283 pstring mask;
1284 char *p;
1285 int count=0;
1286 int error = ERRnoaccess;
1287 BOOL has_wild;
1288 BOOL exists=False;
1290 *directory = *mask = 0;
1292 cnum = SVAL(inbuf,smb_tid);
1293 dirtype = SVAL(inbuf,smb_vwv0);
1295 strcpy(name,smb_buf(inbuf) + 1);
1297 DEBUG(3,("reply_unlink : %s\n",name));
1299 unix_convert(name,cnum,0);
1301 p = strrchr(name,'/');
1302 if (!p) {
1303 strcpy(directory,"./");
1304 strcpy(mask,name);
1305 } else {
1306 *p = 0;
1307 strcpy(directory,name);
1308 strcpy(mask,p+1);
1311 if (is_mangled(mask))
1312 check_mangled_stack(mask);
1314 has_wild = strchr(mask,'*') || strchr(mask,'?');
1316 if (!has_wild) {
1317 strcat(directory,"/");
1318 strcat(directory,mask);
1319 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1320 if (!count) exists = file_exist(directory,NULL);
1321 } else {
1322 void *dirptr = NULL;
1323 char *dname;
1325 if (check_name(directory,cnum))
1326 dirptr = OpenDir(cnum, directory, True);
1328 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1329 the pattern matches against the long name, otherwise the short name
1330 We don't implement this yet XXXX
1333 if (dirptr)
1335 error = ERRbadfile;
1337 if (strequal(mask,"????????.???"))
1338 strcpy(mask,"*");
1340 while ((dname = ReadDirName(dirptr)))
1342 pstring fname;
1343 strcpy(fname,dname);
1345 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1347 error = ERRnoaccess;
1348 sprintf(fname,"%s/%s",directory,dname);
1349 if (!can_delete(fname,cnum,dirtype)) continue;
1350 if (!sys_unlink(fname)) count++;
1351 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1353 CloseDir(dirptr);
1357 if (count == 0) {
1358 if (exists)
1359 return(ERROR(ERRDOS,error));
1360 else
1361 return(UNIXERROR(ERRDOS,error));
1364 outsize = set_message(outbuf,0,0,True);
1366 return(outsize);
1370 /****************************************************************************
1371 reply to a readbraw (core+ protocol)
1372 ****************************************************************************/
1373 int reply_readbraw(char *inbuf, char *outbuf)
1375 int cnum,maxcount,mincount,fnum;
1376 int nread = 0;
1377 uint32 startpos;
1378 char *header = outbuf;
1379 int ret=0;
1380 int fd;
1381 char *fname;
1383 cnum = SVAL(inbuf,smb_tid);
1384 fnum = GETFNUM(inbuf,smb_vwv0);
1386 startpos = IVAL(inbuf,smb_vwv1);
1387 maxcount = SVAL(inbuf,smb_vwv3);
1388 mincount = SVAL(inbuf,smb_vwv4);
1390 /* ensure we don't overrun the packet size */
1391 maxcount = MIN(65535,maxcount);
1392 maxcount = MAX(mincount,maxcount);
1394 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1396 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1397 _smb_setlen(header,0);
1398 transfer_file(0,Client,0,header,4,0);
1399 return(-1);
1401 else
1403 fd = Files[fnum].fd_ptr->fd;
1404 fname = Files[fnum].name;
1408 if (!is_locked(fnum,cnum,maxcount,startpos))
1410 int size = Files[fnum].size;
1411 int sizeneeded = startpos + maxcount;
1413 if (size < sizeneeded) {
1414 struct stat st;
1415 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1416 size = st.st_size;
1417 if (!Files[fnum].can_write)
1418 Files[fnum].size = size;
1421 nread = MIN(maxcount,(int)(size - startpos));
1424 if (nread < mincount)
1425 nread = 0;
1427 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1428 timestring(),
1429 fnum,cnum,startpos,
1430 maxcount,mincount,nread));
1432 #if UNSAFE_READRAW
1434 int predict=0;
1435 _smb_setlen(header,nread);
1437 if (!Files[fnum].can_write)
1438 predict = read_predict(fd,startpos,header+4,NULL,nread);
1440 if ((nread-predict) > 0)
1441 seek_file(fnum,startpos + predict);
1443 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1444 startpos+predict);
1447 if (ret != nread+4)
1448 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1449 fname,startpos,nread,ret));
1451 #else
1452 ret = read_file(fnum,header+4,startpos,nread);
1453 if (ret < mincount) ret = 0;
1455 _smb_setlen(header,ret);
1456 transfer_file(0,Client,0,header,4+ret,0);
1457 #endif
1459 DEBUG(5,("readbraw finished\n"));
1460 return -1;
1464 /****************************************************************************
1465 reply to a lockread (core+ protocol)
1466 ****************************************************************************/
1467 int reply_lockread(char *inbuf,char *outbuf)
1469 int cnum,fnum;
1470 int nread = -1;
1471 char *data;
1472 int outsize = 0;
1473 uint32 startpos, numtoread;
1474 int eclass;
1475 uint32 ecode;
1477 cnum = SVAL(inbuf,smb_tid);
1478 fnum = GETFNUM(inbuf,smb_vwv0);
1480 CHECK_FNUM(fnum,cnum);
1481 CHECK_READ(fnum);
1482 CHECK_ERROR(fnum);
1484 numtoread = SVAL(inbuf,smb_vwv1);
1485 startpos = IVAL(inbuf,smb_vwv2);
1487 outsize = set_message(outbuf,5,3,True);
1488 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1489 data = smb_buf(outbuf) + 3;
1491 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1492 return (ERROR(eclass,ecode));
1494 nread = read_file(fnum,data,startpos,numtoread);
1496 if (nread < 0)
1497 return(UNIXERROR(ERRDOS,ERRnoaccess));
1499 outsize += nread;
1500 SSVAL(outbuf,smb_vwv0,nread);
1501 SSVAL(outbuf,smb_vwv5,nread+3);
1502 SSVAL(smb_buf(outbuf),1,nread);
1504 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1506 return(outsize);
1510 /****************************************************************************
1511 reply to a read
1512 ****************************************************************************/
1513 int reply_read(char *inbuf,char *outbuf)
1515 int cnum,numtoread,fnum;
1516 int nread = 0;
1517 char *data;
1518 uint32 startpos;
1519 int outsize = 0;
1521 cnum = SVAL(inbuf,smb_tid);
1522 fnum = GETFNUM(inbuf,smb_vwv0);
1524 CHECK_FNUM(fnum,cnum);
1525 CHECK_READ(fnum);
1526 CHECK_ERROR(fnum);
1528 numtoread = SVAL(inbuf,smb_vwv1);
1529 startpos = IVAL(inbuf,smb_vwv2);
1531 outsize = set_message(outbuf,5,3,True);
1532 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1533 data = smb_buf(outbuf) + 3;
1535 if (is_locked(fnum,cnum,numtoread,startpos))
1536 return(ERROR(ERRDOS,ERRlock));
1538 if (numtoread > 0)
1539 nread = read_file(fnum,data,startpos,numtoread);
1541 if (nread < 0)
1542 return(UNIXERROR(ERRDOS,ERRnoaccess));
1544 outsize += nread;
1545 SSVAL(outbuf,smb_vwv0,nread);
1546 SSVAL(outbuf,smb_vwv5,nread+3);
1547 CVAL(smb_buf(outbuf),0) = 1;
1548 SSVAL(smb_buf(outbuf),1,nread);
1550 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1552 return(outsize);
1556 /****************************************************************************
1557 reply to a read and X
1558 ****************************************************************************/
1559 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1561 int fnum = GETFNUM(inbuf,smb_vwv2);
1562 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1563 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1564 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1565 int cnum;
1566 int nread = -1;
1567 char *data;
1568 BOOL ok = False;
1570 cnum = SVAL(inbuf,smb_tid);
1572 CHECK_FNUM(fnum,cnum);
1573 CHECK_READ(fnum);
1574 CHECK_ERROR(fnum);
1576 set_message(outbuf,12,0,True);
1577 data = smb_buf(outbuf);
1579 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1580 return(ERROR(ERRDOS,ERRlock));
1581 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1582 ok = True;
1584 if (nread < 0)
1585 return(UNIXERROR(ERRDOS,ERRnoaccess));
1587 SSVAL(outbuf,smb_vwv5,nread);
1588 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1589 SSVAL(smb_buf(outbuf),-2,nread);
1591 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1592 timestring(),fnum,cnum,
1593 smb_mincnt,smb_maxcnt,nread));
1595 chain_fnum = fnum;
1597 return chain_reply(inbuf,outbuf,length,bufsize);
1601 /****************************************************************************
1602 reply to a writebraw (core+ or LANMAN1.0 protocol)
1603 ****************************************************************************/
1604 int reply_writebraw(char *inbuf,char *outbuf)
1606 int nwritten=0;
1607 int total_written=0;
1608 int numtowrite=0;
1609 int cnum,fnum;
1610 int outsize = 0;
1611 long startpos;
1612 char *data=NULL;
1613 BOOL write_through;
1614 int tcount;
1616 cnum = SVAL(inbuf,smb_tid);
1617 fnum = GETFNUM(inbuf,smb_vwv0);
1619 CHECK_FNUM(fnum,cnum);
1620 CHECK_WRITE(fnum);
1621 CHECK_ERROR(fnum);
1623 tcount = IVAL(inbuf,smb_vwv1);
1624 startpos = IVAL(inbuf,smb_vwv3);
1625 write_through = BITSETW(inbuf+smb_vwv7,0);
1627 /* We have to deal with slightly different formats depending
1628 on whether we are using the core+ or lanman1.0 protocol */
1629 if(Protocol <= PROTOCOL_COREPLUS) {
1630 numtowrite = SVAL(smb_buf(inbuf),-2);
1631 data = smb_buf(inbuf);
1632 } else {
1633 numtowrite = SVAL(inbuf,smb_vwv10);
1634 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1637 /* force the error type */
1638 CVAL(inbuf,smb_com) = SMBwritec;
1639 CVAL(outbuf,smb_com) = SMBwritec;
1641 if (is_locked(fnum,cnum,tcount,startpos))
1642 return(ERROR(ERRDOS,ERRlock));
1644 if (seek_file(fnum,startpos) != startpos)
1645 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1647 if (numtowrite>0)
1648 nwritten = write_file(fnum,data,numtowrite);
1650 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1651 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1653 if (nwritten < numtowrite)
1654 return(UNIXERROR(ERRHRD,ERRdiskfull));
1656 total_written = nwritten;
1658 /* Return a message to the redirector to tell it
1659 to send more bytes */
1660 CVAL(outbuf,smb_com) = SMBwritebraw;
1661 SSVALS(outbuf,smb_vwv0,-1);
1662 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1663 send_smb(Client,outbuf);
1665 /* Now read the raw data into the buffer and write it */
1666 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1667 exit_server("secondary writebraw failed");
1670 /* Even though this is not an smb message, smb_len
1671 returns the generic length of an smb message */
1672 numtowrite = smb_len(inbuf);
1674 if (tcount > nwritten+numtowrite) {
1675 DEBUG(3,("Client overestimated the write %d %d %d\n",
1676 tcount,nwritten,numtowrite));
1679 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1680 startpos+nwritten);
1681 total_written += nwritten;
1683 /* Set up outbuf to return the correct return */
1684 outsize = set_message(outbuf,1,0,True);
1685 CVAL(outbuf,smb_com) = SMBwritec;
1686 SSVAL(outbuf,smb_vwv0,total_written);
1688 if (nwritten < numtowrite) {
1689 CVAL(outbuf,smb_rcls) = ERRHRD;
1690 SSVAL(outbuf,smb_err,ERRdiskfull);
1693 if (lp_syncalways(SNUM(cnum)) || write_through)
1694 sync_file(fnum);
1696 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1697 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1699 /* we won't return a status if write through is not selected - this
1700 follows what WfWg does */
1701 if (!write_through && total_written==tcount)
1702 return(-1);
1704 return(outsize);
1708 /****************************************************************************
1709 reply to a writeunlock (core+)
1710 ****************************************************************************/
1711 int reply_writeunlock(char *inbuf,char *outbuf)
1713 int cnum,fnum;
1714 int nwritten = -1;
1715 int outsize = 0;
1716 char *data;
1717 uint32 numtowrite,startpos;
1718 int eclass;
1719 uint32 ecode;
1721 cnum = SVAL(inbuf,smb_tid);
1722 fnum = GETFNUM(inbuf,smb_vwv0);
1724 CHECK_FNUM(fnum,cnum);
1725 CHECK_WRITE(fnum);
1726 CHECK_ERROR(fnum);
1728 numtowrite = SVAL(inbuf,smb_vwv1);
1729 startpos = IVAL(inbuf,smb_vwv2);
1730 data = smb_buf(inbuf) + 3;
1732 if (is_locked(fnum,cnum,numtowrite,startpos))
1733 return(ERROR(ERRDOS,ERRlock));
1735 seek_file(fnum,startpos);
1737 /* The special X/Open SMB protocol handling of
1738 zero length writes is *NOT* done for
1739 this call */
1740 if(numtowrite == 0)
1741 nwritten = 0;
1742 else
1743 nwritten = write_file(fnum,data,numtowrite);
1745 if (lp_syncalways(SNUM(cnum)))
1746 sync_file(fnum);
1748 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1749 return(UNIXERROR(ERRDOS,ERRnoaccess));
1751 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1752 return(ERROR(eclass,ecode));
1754 outsize = set_message(outbuf,1,0,True);
1756 SSVAL(outbuf,smb_vwv0,nwritten);
1758 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1759 timestring(),fnum,cnum,numtowrite,nwritten));
1761 return(outsize);
1765 /****************************************************************************
1766 reply to a write
1767 ****************************************************************************/
1768 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1770 int cnum,numtowrite,fnum;
1771 int nwritten = -1;
1772 int outsize = 0;
1773 int startpos;
1774 char *data;
1776 dum1 = dum2 = 0;
1779 cnum = SVAL(inbuf,smb_tid);
1780 fnum = GETFNUM(inbuf,smb_vwv0);
1782 CHECK_FNUM(fnum,cnum);
1783 CHECK_WRITE(fnum);
1784 CHECK_ERROR(fnum);
1786 numtowrite = SVAL(inbuf,smb_vwv1);
1787 startpos = IVAL(inbuf,smb_vwv2);
1788 data = smb_buf(inbuf) + 3;
1790 if (is_locked(fnum,cnum,numtowrite,startpos))
1791 return(ERROR(ERRDOS,ERRlock));
1793 seek_file(fnum,startpos);
1795 /* X/Open SMB protocol says that if smb_vwv1 is
1796 zero then the file size should be extended or
1797 truncated to the size given in smb_vwv[2-3] */
1798 if(numtowrite == 0)
1799 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
1800 else
1801 nwritten = write_file(fnum,data,numtowrite);
1803 if (lp_syncalways(SNUM(cnum)))
1804 sync_file(fnum);
1806 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1807 return(UNIXERROR(ERRDOS,ERRnoaccess));
1809 outsize = set_message(outbuf,1,0,True);
1811 SSVAL(outbuf,smb_vwv0,nwritten);
1813 if (nwritten < numtowrite) {
1814 CVAL(outbuf,smb_rcls) = ERRHRD;
1815 SSVAL(outbuf,smb_err,ERRdiskfull);
1818 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1820 return(outsize);
1824 /****************************************************************************
1825 reply to a write and X
1826 ****************************************************************************/
1827 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1829 int fnum = GETFNUM(inbuf,smb_vwv2);
1830 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1831 int smb_dsize = SVAL(inbuf,smb_vwv10);
1832 int smb_doff = SVAL(inbuf,smb_vwv11);
1833 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1834 int cnum;
1835 int nwritten = -1;
1836 char *data;
1838 cnum = SVAL(inbuf,smb_tid);
1840 CHECK_FNUM(fnum,cnum);
1841 CHECK_WRITE(fnum);
1842 CHECK_ERROR(fnum);
1844 data = smb_base(inbuf) + smb_doff;
1846 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1847 return(ERROR(ERRDOS,ERRlock));
1849 seek_file(fnum,smb_offs);
1851 /* X/Open SMB protocol says that, unlike SMBwrite
1852 if the length is zero then NO truncation is
1853 done, just a write of zero. To truncate a file,
1854 use SMBwrite. */
1855 if(smb_dsize == 0)
1856 nwritten = 0;
1857 else
1858 nwritten = write_file(fnum,data,smb_dsize);
1860 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1861 return(UNIXERROR(ERRDOS,ERRnoaccess));
1863 set_message(outbuf,6,0,True);
1865 SSVAL(outbuf,smb_vwv2,nwritten);
1867 if (nwritten < smb_dsize) {
1868 CVAL(outbuf,smb_rcls) = ERRHRD;
1869 SSVAL(outbuf,smb_err,ERRdiskfull);
1872 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1874 chain_fnum = fnum;
1876 if (lp_syncalways(SNUM(cnum)) || write_through)
1877 sync_file(fnum);
1879 return chain_reply(inbuf,outbuf,length,bufsize);
1883 /****************************************************************************
1884 reply to a lseek
1885 ****************************************************************************/
1886 int reply_lseek(char *inbuf,char *outbuf)
1888 int cnum,fnum;
1889 uint32 startpos;
1890 int32 res= -1;
1891 int mode,umode;
1892 int outsize = 0;
1894 cnum = SVAL(inbuf,smb_tid);
1895 fnum = GETFNUM(inbuf,smb_vwv0);
1897 CHECK_FNUM(fnum,cnum);
1898 CHECK_ERROR(fnum);
1900 mode = SVAL(inbuf,smb_vwv1) & 3;
1901 startpos = IVAL(inbuf,smb_vwv2);
1903 switch (mode & 3)
1905 case 0: umode = SEEK_SET; break;
1906 case 1: umode = SEEK_CUR; break;
1907 case 2: umode = SEEK_END; break;
1908 default:
1909 umode = SEEK_SET; break;
1912 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
1913 Files[fnum].pos = res;
1915 outsize = set_message(outbuf,2,0,True);
1916 SIVALS(outbuf,smb_vwv0,res);
1918 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1920 return(outsize);
1924 /****************************************************************************
1925 reply to a flush
1926 ****************************************************************************/
1927 int reply_flush(char *inbuf,char *outbuf)
1929 int cnum, fnum;
1930 int outsize = set_message(outbuf,0,0,True);
1932 cnum = SVAL(inbuf,smb_tid);
1933 fnum = GETFNUM(inbuf,smb_vwv0);
1935 if (fnum != 0xFFFF) {
1936 CHECK_FNUM(fnum,cnum);
1937 CHECK_ERROR(fnum);
1940 if (fnum == 0xFFFF)
1942 int i;
1943 for (i=0;i<MAX_OPEN_FILES;i++)
1944 if (OPEN_FNUM(i))
1945 sync_file(i);
1947 else
1948 sync_file(fnum);
1950 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1951 return(outsize);
1955 /****************************************************************************
1956 reply to a exit
1957 ****************************************************************************/
1958 int reply_exit(char *inbuf,char *outbuf)
1960 int outsize = set_message(outbuf,0,0,True);
1961 DEBUG(3,("%s exit\n",timestring()));
1963 return(outsize);
1967 /****************************************************************************
1968 reply to a close
1969 ****************************************************************************/
1970 int reply_close(char *inbuf,char *outbuf)
1972 int fnum,cnum;
1973 int outsize = 0;
1974 time_t mtime;
1975 int32 eclass = 0, err = 0;
1977 outsize = set_message(outbuf,0,0,True);
1979 cnum = SVAL(inbuf,smb_tid);
1981 fnum = GETFNUM(inbuf,smb_vwv0);
1982 CHECK_FNUM(fnum,cnum);
1984 if(HAS_CACHED_ERROR(fnum)) {
1985 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1986 err = Files[fnum].wbmpx_ptr->wr_error;
1989 mtime = make_unix_date3(inbuf+smb_vwv1);
1991 /* try and set the date */
1992 set_filetime(Files[fnum].name,mtime);
1994 close_file(fnum);
1996 /* We have a cached error */
1997 if(eclass || err)
1998 return(ERROR(eclass,err));
2000 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2001 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2002 Connections[cnum].num_files_open));
2004 return(outsize);
2008 /****************************************************************************
2009 reply to a writeclose (Core+ protocol)
2010 ****************************************************************************/
2011 int reply_writeclose(char *inbuf,char *outbuf)
2013 int cnum,numtowrite,fnum;
2014 int nwritten = -1;
2015 int outsize = 0;
2016 int startpos;
2017 char *data;
2018 time_t mtime;
2020 cnum = SVAL(inbuf,smb_tid);
2021 fnum = GETFNUM(inbuf,smb_vwv0);
2023 CHECK_FNUM(fnum,cnum);
2024 CHECK_WRITE(fnum);
2025 CHECK_ERROR(fnum);
2027 numtowrite = SVAL(inbuf,smb_vwv1);
2028 startpos = IVAL(inbuf,smb_vwv2);
2029 mtime = make_unix_date3(inbuf+smb_vwv4);
2030 data = smb_buf(inbuf) + 1;
2032 if (is_locked(fnum,cnum,numtowrite,startpos))
2033 return(ERROR(ERRDOS,ERRlock));
2035 seek_file(fnum,startpos);
2037 nwritten = write_file(fnum,data,numtowrite);
2039 set_filetime(Files[fnum].name,mtime);
2041 close_file(fnum);
2043 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2044 timestring(),fnum,cnum,numtowrite,nwritten,
2045 Connections[cnum].num_files_open));
2047 if (nwritten <= 0)
2048 return(UNIXERROR(ERRDOS,ERRnoaccess));
2050 outsize = set_message(outbuf,1,0,True);
2052 SSVAL(outbuf,smb_vwv0,nwritten);
2053 return(outsize);
2057 /****************************************************************************
2058 reply to a lock
2059 ****************************************************************************/
2060 int reply_lock(char *inbuf,char *outbuf)
2062 int fnum,cnum;
2063 int outsize = set_message(outbuf,0,0,True);
2064 uint32 count,offset;
2065 int eclass;
2066 uint32 ecode;
2068 cnum = SVAL(inbuf,smb_tid);
2069 fnum = GETFNUM(inbuf,smb_vwv0);
2071 CHECK_FNUM(fnum,cnum);
2072 CHECK_ERROR(fnum);
2074 count = IVAL(inbuf,smb_vwv1);
2075 offset = IVAL(inbuf,smb_vwv3);
2077 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));
2079 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2080 return (ERROR(eclass,ecode));
2082 return(outsize);
2086 /****************************************************************************
2087 reply to a unlock
2088 ****************************************************************************/
2089 int reply_unlock(char *inbuf,char *outbuf)
2091 int fnum,cnum;
2092 int outsize = set_message(outbuf,0,0,True);
2093 uint32 count,offset;
2094 int eclass;
2095 uint32 ecode;
2097 cnum = SVAL(inbuf,smb_tid);
2098 fnum = GETFNUM(inbuf,smb_vwv0);
2100 CHECK_FNUM(fnum,cnum);
2101 CHECK_ERROR(fnum);
2103 count = IVAL(inbuf,smb_vwv1);
2104 offset = IVAL(inbuf,smb_vwv3);
2106 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2107 return (ERROR(eclass,ecode));
2109 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));
2111 return(outsize);
2115 /****************************************************************************
2116 reply to a tdis
2117 ****************************************************************************/
2118 int reply_tdis(char *inbuf,char *outbuf)
2120 int cnum;
2121 int outsize = set_message(outbuf,0,0,True);
2122 uint16 vuid;
2124 cnum = SVAL(inbuf,smb_tid);
2125 vuid = SVAL(inbuf,smb_uid);
2127 if (!OPEN_CNUM(cnum)) {
2128 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2129 return(ERROR(ERRSRV,ERRinvnid));
2132 Connections[cnum].used = False;
2134 close_cnum(cnum,vuid);
2136 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2138 return outsize;
2143 /****************************************************************************
2144 reply to a echo
2145 ****************************************************************************/
2146 int reply_echo(char *inbuf,char *outbuf)
2148 int cnum;
2149 int smb_reverb = SVAL(inbuf,smb_vwv0);
2150 int seq_num;
2151 int data_len = smb_buflen(inbuf);
2152 int outsize = set_message(outbuf,1,data_len,True);
2154 cnum = SVAL(inbuf,smb_tid);
2156 /* According to the latest CIFS spec we shouldn't
2157 care what the TID is.
2160 #if 0
2161 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2163 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2164 return(ERROR(ERRSRV,ERRinvnid));
2166 #endif
2168 /* copy any incoming data back out */
2169 if (data_len > 0)
2170 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2172 if (smb_reverb > 100)
2174 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2175 smb_reverb = 100;
2178 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2180 SSVAL(outbuf,smb_vwv0,seq_num);
2182 smb_setlen(outbuf,outsize - 4);
2184 send_smb(Client,outbuf);
2187 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2189 return -1;
2193 /****************************************************************************
2194 reply to a printopen
2195 ****************************************************************************/
2196 int reply_printopen(char *inbuf,char *outbuf)
2198 pstring fname;
2199 pstring fname2;
2200 int cnum;
2201 int fnum = -1;
2202 int outsize = 0;
2204 *fname = *fname2 = 0;
2206 cnum = SVAL(inbuf,smb_tid);
2208 if (!CAN_PRINT(cnum))
2209 return(ERROR(ERRDOS,ERRnoaccess));
2212 pstring s;
2213 char *p;
2214 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2215 p = s;
2216 while (*p)
2218 if (!(isalnum(*p) || strchr("._-",*p)))
2219 *p = 'X';
2220 p++;
2223 if (strlen(s) > 10) s[10] = 0;
2225 sprintf(fname,"%s.XXXXXX",s);
2228 fnum = find_free_file();
2229 if (fnum < 0)
2230 return(ERROR(ERRSRV,ERRnofids));
2232 strcpy(fname2,(char *)mktemp(fname));
2234 if (!check_name(fname2,cnum))
2235 return(ERROR(ERRDOS,ERRnoaccess));
2237 /* Open for exclusive use, write only. */
2238 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL);
2240 if (!Files[fnum].open)
2241 return(UNIXERROR(ERRDOS,ERRnoaccess));
2243 /* force it to be a print file */
2244 Files[fnum].print_file = True;
2246 outsize = set_message(outbuf,1,0,True);
2247 SSVAL(outbuf,smb_vwv0,fnum);
2249 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2251 return(outsize);
2255 /****************************************************************************
2256 reply to a printclose
2257 ****************************************************************************/
2258 int reply_printclose(char *inbuf,char *outbuf)
2260 int fnum,cnum;
2261 int outsize = set_message(outbuf,0,0,True);
2263 cnum = SVAL(inbuf,smb_tid);
2264 fnum = GETFNUM(inbuf,smb_vwv0);
2266 CHECK_FNUM(fnum,cnum);
2267 CHECK_ERROR(fnum);
2269 if (!CAN_PRINT(cnum))
2270 return(ERROR(ERRDOS,ERRnoaccess));
2272 close_file(fnum);
2274 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2276 return(outsize);
2280 /****************************************************************************
2281 reply to a printqueue
2282 ****************************************************************************/
2283 int reply_printqueue(char *inbuf,char *outbuf)
2285 int cnum;
2286 int outsize = set_message(outbuf,2,3,True);
2287 int max_count = SVAL(inbuf,smb_vwv0);
2288 int start_index = SVAL(inbuf,smb_vwv1);
2289 uint16 vuid;
2291 cnum = SVAL(inbuf,smb_tid);
2292 vuid = SVAL(inbuf,smb_uid);
2294 /* allow checking the queue for anyone */
2295 #if 0
2296 if (!CAN_PRINT(cnum))
2297 return(ERROR(ERRDOS,ERRnoaccess));
2298 #endif
2300 SSVAL(outbuf,smb_vwv0,0);
2301 SSVAL(outbuf,smb_vwv1,0);
2302 CVAL(smb_buf(outbuf),0) = 1;
2303 SSVAL(smb_buf(outbuf),1,0);
2305 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2306 timestring(),cnum,start_index,max_count));
2308 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2310 int i;
2311 cnum = -1;
2313 for (i=0;i<MAX_CONNECTIONS;i++)
2314 if (CAN_PRINT(i) && Connections[i].printer)
2315 cnum = i;
2317 if (cnum == -1)
2318 for (i=0;i<MAX_CONNECTIONS;i++)
2319 if (OPEN_CNUM(i))
2320 cnum = i;
2322 if (!OPEN_CNUM(cnum))
2323 return(ERROR(ERRSRV,ERRinvnid));
2325 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2328 if (!become_user(cnum,vuid))
2329 return(ERROR(ERRSRV,ERRinvnid));
2332 print_queue_struct *queue = NULL;
2333 char *p = smb_buf(outbuf) + 3;
2334 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2335 int num_to_get = ABS(max_count);
2336 int first = (max_count>0?start_index:start_index+max_count+1);
2337 int i;
2339 if (first >= count)
2340 num_to_get = 0;
2341 else
2342 num_to_get = MIN(num_to_get,count-first);
2345 for (i=first;i<first+num_to_get;i++)
2347 put_dos_date2(p,0,queue[i].time);
2348 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2349 SSVAL(p,5,queue[i].job);
2350 SIVAL(p,7,queue[i].size);
2351 CVAL(p,11) = 0;
2352 StrnCpy(p+12,queue[i].user,16);
2353 p += 28;
2356 if (count > 0)
2358 outsize = set_message(outbuf,2,28*count+3,False);
2359 SSVAL(outbuf,smb_vwv0,count);
2360 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2361 CVAL(smb_buf(outbuf),0) = 1;
2362 SSVAL(smb_buf(outbuf),1,28*count);
2365 if (queue) free(queue);
2367 DEBUG(3,("%d entries returned in queue\n",count));
2370 return(outsize);
2374 /****************************************************************************
2375 reply to a printwrite
2376 ****************************************************************************/
2377 int reply_printwrite(char *inbuf,char *outbuf)
2379 int cnum,numtowrite,fnum;
2380 int outsize = set_message(outbuf,0,0,True);
2381 char *data;
2383 cnum = SVAL(inbuf,smb_tid);
2385 if (!CAN_PRINT(cnum))
2386 return(ERROR(ERRDOS,ERRnoaccess));
2388 fnum = GETFNUM(inbuf,smb_vwv0);
2390 CHECK_FNUM(fnum,cnum);
2391 CHECK_WRITE(fnum);
2392 CHECK_ERROR(fnum);
2394 numtowrite = SVAL(smb_buf(inbuf),1);
2395 data = smb_buf(inbuf) + 3;
2397 if (write_file(fnum,data,numtowrite) != numtowrite)
2398 return(UNIXERROR(ERRDOS,ERRnoaccess));
2400 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2402 return(outsize);
2406 /****************************************************************************
2407 reply to a mkdir
2408 ****************************************************************************/
2409 int reply_mkdir(char *inbuf,char *outbuf)
2411 pstring directory;
2412 int cnum;
2413 int outsize,ret= -1;
2415 strcpy(directory,smb_buf(inbuf) + 1);
2416 cnum = SVAL(inbuf,smb_tid);
2417 unix_convert(directory,cnum,0);
2419 if (check_name(directory,cnum))
2420 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2422 if (ret < 0)
2423 return(UNIXERROR(ERRDOS,ERRnoaccess));
2425 outsize = set_message(outbuf,0,0,True);
2427 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2429 return(outsize);
2433 /****************************************************************************
2434 reply to a rmdir
2435 ****************************************************************************/
2436 int reply_rmdir(char *inbuf,char *outbuf)
2438 pstring directory;
2439 int cnum;
2440 int outsize = 0;
2441 BOOL ok = False;
2443 cnum = SVAL(inbuf,smb_tid);
2444 strcpy(directory,smb_buf(inbuf) + 1);
2445 unix_convert(directory,cnum,0);
2447 if (check_name(directory,cnum))
2450 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2451 ok = (sys_rmdir(directory) == 0);
2452 if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum)))
2454 /* Check to see if the only thing in this directory are
2455 vetoed files/directories. If so then delete them and
2456 retry. If we fail to delete any of them (and we *don't*
2457 do a recursive delete) then fail the rmdir. */
2458 BOOL all_veto_files = True;
2459 char *dname;
2460 void *dirptr = OpenDir(cnum, directory, False);
2462 if(dirptr != NULL)
2464 int dirpos = TellDir(dirptr);
2465 while ((dname = ReadDirName(dirptr)))
2467 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2468 continue;
2469 if(!IS_VETO_PATH(cnum, dname))
2471 all_veto_files = False;
2472 break;
2475 if(all_veto_files)
2477 SeekDir(dirptr,dirpos);
2478 while ((dname = ReadDirName(dirptr)))
2480 pstring fullname;
2481 struct stat st;
2483 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2484 continue;
2486 /* Construct the full name. */
2487 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
2489 errno = ENOMEM;
2490 break;
2492 strcpy(fullname, directory);
2493 strcat(fullname, "/");
2494 strcat(fullname, dname);
2496 if(sys_lstat(fullname, &st) != 0)
2497 break;
2498 if(st.st_mode & S_IFDIR)
2500 if(sys_rmdir(fullname) != 0)
2501 break;
2503 else if(sys_unlink(fullname) != 0)
2504 break;
2506 CloseDir(dirptr);
2507 /* Retry the rmdir */
2508 ok = (sys_rmdir(directory) == 0);
2510 else
2511 CloseDir(dirptr);
2513 else
2514 errno = ENOTEMPTY;
2517 if (!ok)
2518 DEBUG(3,("couldn't remove directory %s : %s\n",
2519 directory,strerror(errno)));
2522 if (!ok)
2523 return(UNIXERROR(ERRDOS,ERRbadpath));
2525 outsize = set_message(outbuf,0,0,True);
2527 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2529 return(outsize);
2533 /*******************************************************************
2534 resolve wildcards in a filename rename
2535 ********************************************************************/
2536 static BOOL resolve_wildcards(char *name1,char *name2)
2538 fstring root1,root2;
2539 fstring ext1,ext2;
2540 char *p,*p2;
2542 name1 = strrchr(name1,'/');
2543 name2 = strrchr(name2,'/');
2545 if (!name1 || !name2) return(False);
2547 strcpy(root1,name1);
2548 strcpy(root2,name2);
2549 p = strrchr(root1,'.');
2550 if (p) {
2551 *p = 0;
2552 strcpy(ext1,p+1);
2553 } else {
2554 strcpy(ext1,"");
2556 p = strrchr(root2,'.');
2557 if (p) {
2558 *p = 0;
2559 strcpy(ext2,p+1);
2560 } else {
2561 strcpy(ext2,"");
2564 p = root1;
2565 p2 = root2;
2566 while (*p2) {
2567 if (*p2 == '?') {
2568 *p2 = *p;
2569 p2++;
2570 } else {
2571 p2++;
2573 if (*p) p++;
2576 p = ext1;
2577 p2 = ext2;
2578 while (*p2) {
2579 if (*p2 == '?') {
2580 *p2 = *p;
2581 p2++;
2582 } else {
2583 p2++;
2585 if (*p) p++;
2588 strcpy(name2,root2);
2589 if (ext2[0]) {
2590 strcat(name2,".");
2591 strcat(name2,ext2);
2594 return(True);
2597 /*******************************************************************
2598 check if a user is allowed to rename a file
2599 ********************************************************************/
2600 static BOOL can_rename(char *fname,int cnum)
2602 struct stat sbuf;
2604 if (!CAN_WRITE(cnum)) return(False);
2606 if (sys_lstat(fname,&sbuf) != 0) return(False);
2607 if (!check_file_sharing(cnum,fname)) return(False);
2609 return(True);
2612 /****************************************************************************
2613 reply to a mv
2614 ****************************************************************************/
2615 int reply_mv(char *inbuf,char *outbuf)
2617 int outsize = 0;
2618 pstring name;
2619 int cnum;
2620 pstring directory;
2621 pstring mask,newname;
2622 pstring newname_last_component;
2623 char *p;
2624 int count=0;
2625 int error = ERRnoaccess;
2626 BOOL has_wild;
2627 BOOL exists=False;
2629 *directory = *mask = 0;
2631 cnum = SVAL(inbuf,smb_tid);
2633 strcpy(name,smb_buf(inbuf) + 1);
2634 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2636 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2638 unix_convert(name,cnum,0);
2639 unix_convert(newname,cnum,newname_last_component);
2642 * Split the old name into directory and last component
2643 * strings. Note that unix_convert may have stripped off a
2644 * leading ./ from both name and newname if the rename is
2645 * at the root of the share. We need to make sure either both
2646 * name and newname contain a / character or neither of them do
2647 * as this is checked in resolve_wildcards().
2650 p = strrchr(name,'/');
2651 if (!p) {
2652 strcpy(directory,".");
2653 strcpy(mask,name);
2654 } else {
2655 *p = 0;
2656 strcpy(directory,name);
2657 strcpy(mask,p+1);
2658 *p = '/'; /* Replace needed for exceptional test below. */
2661 if (is_mangled(mask))
2662 check_mangled_stack(mask);
2664 has_wild = strchr(mask,'*') || strchr(mask,'?');
2666 if (!has_wild) {
2667 BOOL is_short_name = is_8_3(name, True);
2669 /* Add a terminating '/' to the directory name. */
2670 strcat(directory,"/");
2671 strcat(directory,mask);
2673 /* Ensure newname contains a '/' also */
2674 if(strrchr(newname,'/') == 0) {
2675 pstring tmpstr;
2677 strcpy(tmpstr, "./");
2678 strcat(tmpstr, newname);
2679 strcpy(newname, tmpstr);
2682 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",
2683 case_sensitive, case_preserve, short_case_preserve, directory,
2684 newname, newname_last_component, is_short_name));
2687 * Check for special case with case preserving and not
2688 * case sensitive, if directory and newname are identical,
2689 * and the old last component differs from the original
2690 * last component only by case, then we should allow
2691 * the rename (user is trying to change the case of the
2692 * filename).
2694 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
2695 ((short_case_preserve == True) && (is_short_name == True))) &&
2696 strcsequal(directory, newname)) {
2697 pstring newname_modified_last_component;
2700 * Get the last component of the modified name.
2701 * Note that we guarantee that newname contains a '/'
2702 * character above.
2704 p = strrchr(newname,'/');
2705 strcpy(newname_modified_last_component,p+1);
2707 if(strcsequal(newname_modified_last_component,
2708 newname_last_component) == False) {
2710 * Replace the modified last component with
2711 * the original.
2713 strcpy(p+1, newname_last_component);
2717 if (resolve_wildcards(directory,newname) &&
2718 can_rename(directory,cnum) &&
2719 !file_exist(newname,NULL) &&
2720 !sys_rename(directory,newname)) count++;
2722 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
2723 directory,newname));
2725 if (!count) exists = file_exist(directory,NULL);
2726 if (!count && exists && file_exist(newname,NULL)) {
2727 exists = True;
2728 error = 183;
2730 } else {
2731 void *dirptr = NULL;
2732 char *dname;
2733 pstring destname;
2735 if (check_name(directory,cnum))
2736 dirptr = OpenDir(cnum, directory, True);
2738 if (dirptr)
2740 error = ERRbadfile;
2742 if (strequal(mask,"????????.???"))
2743 strcpy(mask,"*");
2745 while ((dname = ReadDirName(dirptr)))
2747 pstring fname;
2748 strcpy(fname,dname);
2750 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2752 error = ERRnoaccess;
2753 sprintf(fname,"%s/%s",directory,dname);
2754 if (!can_rename(fname,cnum)) continue;
2755 strcpy(destname,newname);
2757 if (!resolve_wildcards(fname,destname)) continue;
2759 if (file_exist(destname,NULL)) {
2760 error = 183;
2761 continue;
2763 if (!sys_rename(fname,destname)) count++;
2764 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2766 CloseDir(dirptr);
2770 if (count == 0) {
2771 if (exists)
2772 return(ERROR(ERRDOS,error));
2773 else
2774 return(UNIXERROR(ERRDOS,error));
2777 outsize = set_message(outbuf,0,0,True);
2779 return(outsize);
2782 /*******************************************************************
2783 copy a file as part of a reply_copy
2784 ******************************************************************/
2785 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2786 int count,BOOL target_is_directory)
2788 int Access,action;
2789 struct stat st;
2790 int ret=0;
2791 int fnum1,fnum2;
2792 pstring dest;
2794 strcpy(dest,dest1);
2795 if (target_is_directory) {
2796 char *p = strrchr(src,'/');
2797 if (p)
2798 p++;
2799 else
2800 p = src;
2801 strcat(dest,"/");
2802 strcat(dest,p);
2805 if (!file_exist(src,&st)) return(False);
2807 fnum1 = find_free_file();
2808 if (fnum1<0) return(False);
2809 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2810 1,0,&Access,&action);
2812 if (!Files[fnum1].open) return(False);
2814 if (!target_is_directory && count)
2815 ofun = 1;
2817 fnum2 = find_free_file();
2818 if (fnum2<0) {
2819 close_file(fnum1);
2820 return(False);
2822 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2823 ofun,st.st_mode,&Access,&action);
2825 if (!Files[fnum2].open) {
2826 close_file(fnum1);
2827 return(False);
2830 if ((ofun&3) == 1) {
2831 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
2834 if (st.st_size)
2835 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
2837 close_file(fnum1);
2838 close_file(fnum2);
2840 return(ret == st.st_size);
2845 /****************************************************************************
2846 reply to a file copy.
2847 ****************************************************************************/
2848 int reply_copy(char *inbuf,char *outbuf)
2850 int outsize = 0;
2851 pstring name;
2852 int cnum;
2853 pstring directory;
2854 pstring mask,newname;
2855 char *p;
2856 int count=0;
2857 int error = ERRnoaccess;
2858 BOOL has_wild;
2859 BOOL exists=False;
2860 int tid2 = SVAL(inbuf,smb_vwv0);
2861 int ofun = SVAL(inbuf,smb_vwv1);
2862 int flags = SVAL(inbuf,smb_vwv2);
2863 BOOL target_is_directory=False;
2865 *directory = *mask = 0;
2867 cnum = SVAL(inbuf,smb_tid);
2869 strcpy(name,smb_buf(inbuf));
2870 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2872 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2874 if (tid2 != cnum) {
2875 /* can't currently handle inter share copies XXXX */
2876 DEBUG(3,("Rejecting inter-share copy\n"));
2877 return(ERROR(ERRSRV,ERRinvdevice));
2880 unix_convert(name,cnum,0);
2881 unix_convert(newname,cnum,0);
2883 target_is_directory = directory_exist(newname,NULL);
2885 if ((flags&1) && target_is_directory) {
2886 return(ERROR(ERRDOS,ERRbadfile));
2889 if ((flags&2) && !target_is_directory) {
2890 return(ERROR(ERRDOS,ERRbadpath));
2893 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2894 /* wants a tree copy! XXXX */
2895 DEBUG(3,("Rejecting tree copy\n"));
2896 return(ERROR(ERRSRV,ERRerror));
2899 p = strrchr(name,'/');
2900 if (!p) {
2901 strcpy(directory,"./");
2902 strcpy(mask,name);
2903 } else {
2904 *p = 0;
2905 strcpy(directory,name);
2906 strcpy(mask,p+1);
2909 if (is_mangled(mask))
2910 check_mangled_stack(mask);
2912 has_wild = strchr(mask,'*') || strchr(mask,'?');
2914 if (!has_wild) {
2915 strcat(directory,"/");
2916 strcat(directory,mask);
2917 if (resolve_wildcards(directory,newname) &&
2918 copy_file(directory,newname,cnum,ofun,
2919 count,target_is_directory)) count++;
2920 if (!count) exists = file_exist(directory,NULL);
2921 } else {
2922 void *dirptr = NULL;
2923 char *dname;
2924 pstring destname;
2926 if (check_name(directory,cnum))
2927 dirptr = OpenDir(cnum, directory, True);
2929 if (dirptr)
2931 error = ERRbadfile;
2933 if (strequal(mask,"????????.???"))
2934 strcpy(mask,"*");
2936 while ((dname = ReadDirName(dirptr)))
2938 pstring fname;
2939 strcpy(fname,dname);
2941 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2943 error = ERRnoaccess;
2944 sprintf(fname,"%s/%s",directory,dname);
2945 strcpy(destname,newname);
2946 if (resolve_wildcards(fname,destname) &&
2947 copy_file(directory,newname,cnum,ofun,
2948 count,target_is_directory)) count++;
2949 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2951 CloseDir(dirptr);
2955 if (count == 0) {
2956 if (exists)
2957 return(ERROR(ERRDOS,error));
2958 else
2959 return(UNIXERROR(ERRDOS,error));
2962 outsize = set_message(outbuf,1,0,True);
2963 SSVAL(outbuf,smb_vwv0,count);
2965 return(outsize);
2970 /****************************************************************************
2971 reply to a setdir
2972 ****************************************************************************/
2973 int reply_setdir(char *inbuf,char *outbuf)
2975 int cnum,snum;
2976 int outsize = 0;
2977 BOOL ok = False;
2978 pstring newdir;
2980 cnum = SVAL(inbuf,smb_tid);
2982 snum = Connections[cnum].service;
2983 if (!CAN_SETDIR(snum))
2984 return(ERROR(ERRDOS,ERRnoaccess));
2986 strcpy(newdir,smb_buf(inbuf) + 1);
2987 strlower(newdir);
2989 if (strlen(newdir) == 0)
2990 ok = True;
2991 else
2993 ok = directory_exist(newdir,NULL);
2994 if (ok)
2995 string_set(&Connections[cnum].connectpath,newdir);
2998 if (!ok)
2999 return(ERROR(ERRDOS,ERRbadpath));
3001 outsize = set_message(outbuf,0,0,True);
3002 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3004 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
3006 return(outsize);
3010 /****************************************************************************
3011 reply to a lockingX request
3012 ****************************************************************************/
3013 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
3015 int fnum = GETFNUM(inbuf,smb_vwv2);
3016 uint16 locktype = SVAL(inbuf,smb_vwv3);
3017 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3018 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3019 uint32 count, offset;
3021 int cnum;
3022 int i;
3023 char *data;
3024 uint32 ecode=0, dummy2;
3025 int eclass=0, dummy1;
3027 cnum = SVAL(inbuf,smb_tid);
3029 CHECK_FNUM(fnum,cnum);
3030 CHECK_ERROR(fnum);
3032 data = smb_buf(inbuf);
3033 /* Data now points at the beginning of the list
3034 of smb_unlkrng structs */
3035 for(i = 0; i < (int)num_ulocks; i++) {
3036 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3037 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3038 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
3039 return ERROR(eclass,ecode);
3042 /* Now do any requested locks */
3043 data += 10*num_ulocks;
3044 /* Data now points at the beginning of the list
3045 of smb_lkrng structs */
3046 for(i = 0; i < (int)num_locks; i++) {
3047 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3048 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3049 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
3050 break;
3053 /* If any of the above locks failed, then we must unlock
3054 all of the previous locks (X/Open spec). */
3055 if(i != num_locks && num_locks != 0) {
3056 for(; i >= 0; i--) {
3057 count = IVAL(data,SMB_LKLEN_OFFSET(i));
3058 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
3059 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
3061 return ERROR(eclass,ecode);
3064 set_message(outbuf,2,0,True);
3066 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3067 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
3069 chain_fnum = fnum;
3071 return chain_reply(inbuf,outbuf,length,bufsize);
3075 /****************************************************************************
3076 reply to a SMBreadbmpx (read block multiplex) request
3077 ****************************************************************************/
3078 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3080 int cnum,fnum;
3081 int nread = -1;
3082 int total_read;
3083 char *data;
3084 uint32 startpos;
3085 int outsize, mincount, maxcount;
3086 int max_per_packet;
3087 int tcount;
3088 int pad;
3090 /* this function doesn't seem to work - disable by default */
3091 if (!lp_readbmpx())
3092 return(ERROR(ERRSRV,ERRuseSTD));
3094 outsize = set_message(outbuf,8,0,True);
3096 cnum = SVAL(inbuf,smb_tid);
3097 fnum = GETFNUM(inbuf,smb_vwv0);
3099 CHECK_FNUM(fnum,cnum);
3100 CHECK_READ(fnum);
3101 CHECK_ERROR(fnum);
3103 startpos = IVAL(inbuf,smb_vwv1);
3104 maxcount = SVAL(inbuf,smb_vwv3);
3105 mincount = SVAL(inbuf,smb_vwv4);
3107 data = smb_buf(outbuf);
3108 pad = ((long)data)%4;
3109 if (pad) pad = 4 - pad;
3110 data += pad;
3112 max_per_packet = bufsize-(outsize+pad);
3113 tcount = maxcount;
3114 total_read = 0;
3116 if (is_locked(fnum,cnum,maxcount,startpos))
3117 return(ERROR(ERRDOS,ERRlock));
3121 int N = MIN(max_per_packet,tcount-total_read);
3123 nread = read_file(fnum,data,startpos,N);
3125 if (nread <= 0) nread = 0;
3127 if (nread < N)
3128 tcount = total_read + nread;
3130 set_message(outbuf,8,nread,False);
3131 SIVAL(outbuf,smb_vwv0,startpos);
3132 SSVAL(outbuf,smb_vwv2,tcount);
3133 SSVAL(outbuf,smb_vwv6,nread);
3134 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3136 send_smb(Client,outbuf);
3138 total_read += nread;
3139 startpos += nread;
3141 while (total_read < tcount);
3143 return(-1);
3147 /****************************************************************************
3148 reply to a SMBwritebmpx (write block multiplex primary) request
3149 ****************************************************************************/
3150 int reply_writebmpx(char *inbuf,char *outbuf)
3152 int cnum,numtowrite,fnum;
3153 int nwritten = -1;
3154 int outsize = 0;
3155 uint32 startpos;
3156 int tcount, write_through, smb_doff;
3157 char *data;
3159 cnum = SVAL(inbuf,smb_tid);
3160 fnum = GETFNUM(inbuf,smb_vwv0);
3162 CHECK_FNUM(fnum,cnum);
3163 CHECK_WRITE(fnum);
3164 CHECK_ERROR(fnum);
3166 tcount = SVAL(inbuf,smb_vwv1);
3167 startpos = IVAL(inbuf,smb_vwv3);
3168 write_through = BITSETW(inbuf+smb_vwv7,0);
3169 numtowrite = SVAL(inbuf,smb_vwv10);
3170 smb_doff = SVAL(inbuf,smb_vwv11);
3172 data = smb_base(inbuf) + smb_doff;
3174 /* If this fails we need to send an SMBwriteC response,
3175 not an SMBwritebmpx - set this up now so we don't forget */
3176 CVAL(outbuf,smb_com) = SMBwritec;
3178 if (is_locked(fnum,cnum,tcount,startpos))
3179 return(ERROR(ERRDOS,ERRlock));
3181 seek_file(fnum,startpos);
3182 nwritten = write_file(fnum,data,numtowrite);
3184 if(lp_syncalways(SNUM(cnum)) || write_through)
3185 sync_file(fnum);
3187 if(nwritten < numtowrite)
3188 return(UNIXERROR(ERRHRD,ERRdiskfull));
3190 /* If the maximum to be written to this file
3191 is greater than what we just wrote then set
3192 up a secondary struct to be attached to this
3193 fd, we will use this to cache error messages etc. */
3194 if(tcount > nwritten)
3196 write_bmpx_struct *wbms;
3197 if(Files[fnum].wbmpx_ptr != NULL)
3198 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3199 else
3200 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3201 if(!wbms)
3203 DEBUG(0,("Out of memory in reply_readmpx\n"));
3204 return(ERROR(ERRSRV,ERRnoresource));
3206 wbms->wr_mode = write_through;
3207 wbms->wr_discard = False; /* No errors yet */
3208 wbms->wr_total_written = nwritten;
3209 wbms->wr_errclass = 0;
3210 wbms->wr_error = 0;
3211 Files[fnum].wbmpx_ptr = wbms;
3214 /* We are returning successfully, set the message type back to
3215 SMBwritebmpx */
3216 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3218 outsize = set_message(outbuf,1,0,True);
3220 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3222 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3223 timestring(),fnum,cnum,numtowrite,nwritten));
3225 if (write_through && tcount==nwritten) {
3226 /* we need to send both a primary and a secondary response */
3227 smb_setlen(outbuf,outsize - 4);
3228 send_smb(Client,outbuf);
3230 /* now the secondary */
3231 outsize = set_message(outbuf,1,0,True);
3232 CVAL(outbuf,smb_com) = SMBwritec;
3233 SSVAL(outbuf,smb_vwv0,nwritten);
3236 return(outsize);
3240 /****************************************************************************
3241 reply to a SMBwritebs (write block multiplex secondary) request
3242 ****************************************************************************/
3243 int reply_writebs(char *inbuf,char *outbuf)
3245 int cnum,numtowrite,fnum;
3246 int nwritten = -1;
3247 int outsize = 0;
3248 int32 startpos;
3249 int tcount, write_through, smb_doff;
3250 char *data;
3251 write_bmpx_struct *wbms;
3252 BOOL send_response = False;
3254 cnum = SVAL(inbuf,smb_tid);
3255 fnum = GETFNUM(inbuf,smb_vwv0);
3256 CHECK_FNUM(fnum,cnum);
3257 CHECK_WRITE(fnum);
3259 tcount = SVAL(inbuf,smb_vwv1);
3260 startpos = IVAL(inbuf,smb_vwv2);
3261 numtowrite = SVAL(inbuf,smb_vwv6);
3262 smb_doff = SVAL(inbuf,smb_vwv7);
3264 data = smb_base(inbuf) + smb_doff;
3266 /* We need to send an SMBwriteC response, not an SMBwritebs */
3267 CVAL(outbuf,smb_com) = SMBwritec;
3269 /* This fd should have an auxiliary struct attached,
3270 check that it does */
3271 wbms = Files[fnum].wbmpx_ptr;
3272 if(!wbms) return(-1);
3274 /* If write through is set we can return errors, else we must
3275 cache them */
3276 write_through = wbms->wr_mode;
3278 /* Check for an earlier error */
3279 if(wbms->wr_discard)
3280 return -1; /* Just discard the packet */
3282 seek_file(fnum,startpos);
3283 nwritten = write_file(fnum,data,numtowrite);
3285 if(lp_syncalways(SNUM(cnum)) || write_through)
3286 sync_file(fnum);
3288 if (nwritten < numtowrite)
3290 if(write_through) {
3291 /* We are returning an error - we can delete the aux struct */
3292 if (wbms) free((char *)wbms);
3293 Files[fnum].wbmpx_ptr = NULL;
3294 return(ERROR(ERRHRD,ERRdiskfull));
3296 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3299 /* Increment the total written, if this matches tcount
3300 we can discard the auxiliary struct (hurrah !) and return a writeC */
3301 wbms->wr_total_written += nwritten;
3302 if(wbms->wr_total_written >= tcount)
3304 if (write_through) {
3305 outsize = set_message(outbuf,1,0,True);
3306 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3307 send_response = True;
3310 free((char *)wbms);
3311 Files[fnum].wbmpx_ptr = NULL;
3314 if(send_response)
3315 return(outsize);
3317 return(-1);
3321 /****************************************************************************
3322 reply to a SMBsetattrE
3323 ****************************************************************************/
3324 int reply_setattrE(char *inbuf,char *outbuf)
3326 int cnum,fnum;
3327 struct utimbuf unix_times;
3328 int outsize = 0;
3330 outsize = set_message(outbuf,0,0,True);
3332 cnum = SVAL(inbuf,smb_tid);
3333 fnum = GETFNUM(inbuf,smb_vwv0);
3335 CHECK_FNUM(fnum,cnum);
3336 CHECK_ERROR(fnum);
3338 /* Convert the DOS times into unix times. Ignore create
3339 time as UNIX can't set this.
3341 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3342 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3344 /* Set the date on this file */
3345 if(sys_utime(Files[fnum].name, &unix_times))
3346 return(ERROR(ERRDOS,ERRnoaccess));
3348 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3350 return(outsize);
3354 /****************************************************************************
3355 reply to a SMBgetattrE
3356 ****************************************************************************/
3357 int reply_getattrE(char *inbuf,char *outbuf)
3359 int cnum,fnum;
3360 struct stat sbuf;
3361 int outsize = 0;
3362 int mode;
3364 outsize = set_message(outbuf,11,0,True);
3366 cnum = SVAL(inbuf,smb_tid);
3367 fnum = GETFNUM(inbuf,smb_vwv0);
3369 CHECK_FNUM(fnum,cnum);
3370 CHECK_ERROR(fnum);
3372 /* Do an fstat on this file */
3373 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3374 return(UNIXERROR(ERRDOS,ERRnoaccess));
3376 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3378 /* Convert the times into dos times. Set create
3379 date to be last modify date as UNIX doesn't save
3380 this */
3381 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3382 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3383 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3384 if (mode & aDIR)
3386 SIVAL(outbuf,smb_vwv6,0);
3387 SIVAL(outbuf,smb_vwv8,0);
3389 else
3391 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3392 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3394 SSVAL(outbuf,smb_vwv10, mode);
3396 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3398 return(outsize);