Initial version imported to CVS
[Samba/gbeck.git] / source / smbd / reply.c
blobb7b51775bb8bbcd1141b9a754c16e4b208934291
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
27 #include "includes.h"
28 #include "loadparm.h"
29 #include "trans2.h"
31 /* look in server.c for some explanation of these variables */
32 extern int Protocol;
33 extern int DEBUGLEVEL;
34 extern int chain_size;
35 extern int maxxmit;
36 extern int chain_fnum;
37 extern char magic_char;
38 extern connection_struct Connections[];
39 extern files_struct Files[];
40 extern BOOL case_sensitive;
41 extern pstring sesssetup_user;
42 extern int Client;
44 /* this macro should always be used to extract an fnum (smb_fid) from
45 a packet to ensure chaining works correctly */
46 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
49 /****************************************************************************
50 reply to an special message
51 ****************************************************************************/
52 int reply_special(char *inbuf,char *outbuf)
54 int outsize = 4;
55 int msg_type = CVAL(inbuf,0);
56 int msg_flags = CVAL(inbuf,1);
57 pstring name1,name2;
58 extern fstring remote_machine;
59 extern fstring local_machine;
60 char *p;
62 *name1 = *name2 = 0;
64 smb_setlen(outbuf,0);
66 switch (msg_type)
68 case 0x81: /* session request */
69 CVAL(outbuf,0) = 0x82;
70 CVAL(outbuf,3) = 0;
71 if (name_len(inbuf+4) > 50)
73 DEBUG(0,("Invalid name length in session request\n"));
74 return(0);
76 name_extract(inbuf,4,name1);
77 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
78 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2));
80 strcpy(remote_machine,name2);
81 trim_string(remote_machine," "," ");
82 p = strchr(remote_machine,' ');
83 strlower(remote_machine);
84 if (p) *p = 0;
86 strcpy(local_machine,name1);
87 trim_string(local_machine," "," ");
88 p = strchr(local_machine,' ');
89 strlower(local_machine);
90 if (p) *p = 0;
92 add_session_user(remote_machine);
94 reload_services(True);
95 reopen_logs();
97 break;
98 case 0x85: /* session keepalive */
99 default:
100 return(0);
103 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags));
105 return(outsize);
109 /*******************************************************************
110 work out what error to give to a failed connection
111 ********************************************************************/
112 static int connection_error(char *inbuf,char *outbuf,int connection_num)
114 switch (connection_num)
116 case -8:
117 return(ERROR(ERRSRV,ERRnoresource));
118 case -7:
119 return(ERROR(ERRSRV,ERRbaduid));
120 case -6:
121 return(ERROR(ERRSRV,ERRinvdevice));
122 case -5:
123 return(ERROR(ERRSRV,ERRinvnetname));
124 case -4:
125 return(ERROR(ERRSRV,ERRaccess));
126 case -3:
127 return(ERROR(ERRDOS,ERRnoipc));
128 case -2:
129 return(ERROR(ERRSRV,ERRinvnetname));
131 return(ERROR(ERRSRV,ERRbadpw));
135 /****************************************************************************
136 reply to a tcon
137 ****************************************************************************/
138 int reply_tcon(char *inbuf,char *outbuf)
140 pstring service;
141 pstring user;
142 pstring password;
143 pstring dev;
144 int connection_num;
145 int outsize = 0;
146 int uid = SVAL(inbuf,smb_uid);
147 int vuid;
148 int pwlen;
150 *service = *user = *password = *dev = 0;
152 vuid = valid_uid(uid);
154 parse_connect(inbuf,service,user,password,&pwlen,dev);
156 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
158 if (connection_num < 0)
159 return(connection_error(inbuf,outbuf,connection_num));
161 outsize = set_message(outbuf,2,0,True);
162 SSVAL(outbuf,smb_vwv0,maxxmit);
163 SSVAL(outbuf,smb_vwv1,connection_num);
164 SSVAL(outbuf,smb_tid,connection_num);
166 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
168 return(outsize);
172 /****************************************************************************
173 reply to a tcon and X
174 ****************************************************************************/
175 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
177 pstring service;
178 pstring user;
179 pstring password;
180 pstring devicename;
181 int connection_num;
182 int outsize = 0;
183 int uid = SVAL(inbuf,smb_uid);
184 int vuid;
185 int smb_com2 = SVAL(inbuf,smb_vwv0);
186 int smb_off2 = SVAL(inbuf,smb_vwv1);
187 int passlen = SVAL(inbuf,smb_vwv3);
189 *service = *user = *password = *devicename = 0;
191 /* we might have to close an old one */
192 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
193 close_cnum(SVAL(inbuf,smb_tid),uid);
195 vuid = valid_uid(uid);
198 char *path;
199 char *p;
200 memcpy(password,smb_buf(inbuf),passlen);
201 password[passlen]=0;
202 path = smb_buf(inbuf) + passlen;
203 DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
204 strcpy(service,path+2);
205 p = strchr(service,'\\');
206 if (!p)
207 return(ERROR(ERRSRV,ERRinvnetname));
208 *p = 0;
209 strcpy(service,p+1);
210 p = strchr(service,'%');
211 if (p)
213 *p++ = 0;
214 strcpy(user,p);
216 StrnCpy(devicename,path + strlen(path) + 1,6);
217 DEBUG(4,("Got device type %s\n",devicename));
220 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
222 if (connection_num < 0)
223 return(connection_error(inbuf,outbuf,connection_num));
225 outsize = set_message(outbuf,2,strlen(devicename)+1,True);
227 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
229 /* set the incoming and outgoing tid to the just created one */
230 SSVAL(inbuf,smb_tid,connection_num);
231 SSVAL(outbuf,smb_tid,connection_num);
233 CVAL(outbuf,smb_vwv0) = smb_com2;
234 SSVAL(outbuf,smb_vwv1,(chain_size + outsize)-4);
236 strcpy(smb_buf(outbuf),devicename);
238 if (smb_com2 != 0xFF)
239 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
240 outbuf,outbuf+outsize,
241 length,bufsize);
243 return(outsize);
247 /****************************************************************************
248 reply to an unknown type
249 ****************************************************************************/
250 int reply_unknown(char *inbuf,char *outbuf)
252 int cnum;
253 int type;
254 cnum = SVAL(inbuf,smb_tid);
255 type = CVAL(inbuf,smb_com);
257 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
258 timestring(),
259 smb_fn_name(type),
260 cnum,type,type));
262 return(ERROR(ERRSRV,ERRunknownsmb));
266 /****************************************************************************
267 reply to an ioctl
268 ****************************************************************************/
269 int reply_ioctl(char *inbuf,char *outbuf)
271 DEBUG(3,("ignoring ioctl\n"));
273 return(ERROR(ERRSRV,ERRnosupport));
277 /****************************************************************************
278 reply to a session setup command
279 ****************************************************************************/
280 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
282 int outsize = 0;
283 int sess_uid;
284 int gid;
285 int smb_com2;
286 int smb_off2;
287 int smb_bufsize;
288 int smb_mpxmax;
289 int smb_vc_num;
290 uint32 smb_sesskey;
291 int smb_apasslen;
292 pstring smb_apasswd;
293 int smb_ntpasslen = 0;
294 pstring smb_ntpasswd;
295 BOOL valid_nt_password = False;
296 pstring user;
297 BOOL guest=False;
299 *smb_apasswd = 0;
301 sess_uid = SVAL(inbuf,smb_uid);
302 smb_com2 = CVAL(inbuf,smb_vwv0);
303 smb_off2 = SVAL(inbuf,smb_vwv1);
304 smb_bufsize = SVAL(inbuf,smb_vwv2);
305 smb_mpxmax = SVAL(inbuf,smb_vwv3);
306 smb_vc_num = SVAL(inbuf,smb_vwv4);
307 smb_sesskey = IVAL(inbuf,smb_vwv5);
309 if (Protocol < PROTOCOL_NT1) {
310 smb_apasslen = SVAL(inbuf,smb_vwv7);
311 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
312 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
313 } else {
314 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
315 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
316 BOOL doencrypt = SMBENCRYPT();
317 char *p = smb_buf(inbuf);
318 if (passlen1 > 256) passlen1 = 0;
319 if (passlen2 > 256) passlen2 = 0; /* I don't know why NT gives weird
320 lengths sometimes */
321 if(doencrypt) {
322 /* Save the lanman2 password and the NT md4 password. */
323 smb_apasslen = passlen1;
324 memcpy(smb_apasswd,p,smb_apasslen);
325 smb_ntpasslen = passlen2;
326 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
327 } else {
328 /* for Win95 */
329 if (passlen1 > passlen2) {
330 smb_apasslen = passlen1;
331 StrnCpy(smb_apasswd,p,smb_apasslen);
332 } else {
333 smb_apasslen = passlen2;
334 StrnCpy(smb_apasswd,p + passlen1,smb_apasslen);
337 if (passlen2 == 1) {
338 /* apparently NT sometimes sets passlen2 to 1 when it means 0. This
339 tries to work around that problem */
340 passlen2 = 0;
342 p += passlen1 + passlen2;
343 strcpy(user,p); p = skip_string(p,1);
344 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
345 p,skip_string(p,1),skip_string(p,2)));
349 DEBUG(3,("sesssetupX:name=[%s]\n",user));
351 if (!*user)
352 strcpy(user,lp_guestaccount(-1));
354 strlower(user);
356 strcpy(sesssetup_user,user);
358 reload_services(True);
360 add_session_user(user);
363 if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
364 !check_hosts_equiv(user))
367 if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
368 guest = True;
370 /* now check if it's a valid username/password */
371 /* If an NT password was supplied try and validate with that
372 first. This is superior as the passwords are mixed case 128 length unicode */
373 if(smb_ntpasslen && !guest)
375 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL,True))
376 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
377 else
378 valid_nt_password = True;
380 if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL,False))
382 if (lp_security() >= SEC_USER) {
383 #if (GUEST_SESSSETUP == 0)
384 return(ERROR(ERRSRV,ERRbadpw));
385 #endif
386 #if (GUEST_SESSSETUP == 1)
387 if (Get_Pwnam(user,True))
388 return(ERROR(ERRSRV,ERRbadpw));
389 #endif
391 if (*smb_apasswd || !Get_Pwnam(user,True))
392 strcpy(user,lp_guestaccount(-1));
393 DEBUG(3,("Registered username %s for guest access\n",user));
394 guest = True;
398 if (!Get_Pwnam(user,True)) {
399 DEBUG(3,("No such user %s - using guest account\n",user));
400 strcpy(user,lp_guestaccount(-1));
401 guest = True;
404 if (!strequal(user,lp_guestaccount(-1)) &&
405 lp_servicenumber(user) < 0)
407 int homes = lp_servicenumber(HOMES_NAME);
408 char *home = get_home_dir(user);
409 if (homes >= 0 && home)
410 lp_add_home(user,homes,home);
414 /* it's ok - setup a reply */
415 if (Protocol < PROTOCOL_NT1) {
416 outsize = set_message(outbuf,3,0,True);
417 } else {
418 char *p;
419 outsize = set_message(outbuf,3,3,True);
420 p = smb_buf(outbuf);
421 strcpy(p,"Unix"); p = skip_string(p,1);
422 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
423 strcpy(p,my_workgroup()); p = skip_string(p,1);
424 outsize = set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
425 /* perhaps grab OS version here?? */
428 /* Set the correct uid in the outgoing and incoming packets
429 We will use this on future requests to determine which
430 user we should become.
433 struct passwd *pw = Get_Pwnam(user,False);
434 if (!pw) {
435 DEBUG(1,("Username %s is invalid on this system\n",user));
436 return(ERROR(ERRSRV,ERRbadpw));
438 gid = pw->pw_gid;
439 SSVAL(outbuf,smb_uid,(uint16)pw->pw_uid);
440 SSVAL(inbuf,smb_uid,(uint16)pw->pw_uid);
443 CVAL(outbuf,smb_vwv0) = smb_com2;
444 SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
446 if (guest)
447 SSVAL(outbuf,smb_vwv2,1);
449 /* register the name and uid as being validated, so further connections
450 to a uid can get through without a password, on the same VC */
451 register_uid(SVAL(inbuf,smb_uid),gid,user,guest);
453 maxxmit = MIN(maxxmit,smb_bufsize);
455 if (smb_com2 != 0xFF)
456 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
457 outbuf,outbuf+outsize,
458 length,bufsize);
460 return(outsize);
464 /****************************************************************************
465 reply to a chkpth
466 ****************************************************************************/
467 int reply_chkpth(char *inbuf,char *outbuf)
469 int outsize = 0;
470 int cnum,mode;
471 pstring name;
472 BOOL ok = False;
474 cnum = SVAL(inbuf,smb_tid);
476 strcpy(name,smb_buf(inbuf) + 1);
477 unix_convert(name,cnum);
479 mode = SVAL(inbuf,smb_vwv0);
481 if (check_name(name,cnum))
482 ok = directory_exist(name,NULL);
484 if (!ok)
485 return(ERROR(ERRDOS,ERRbadpath));
487 outsize = set_message(outbuf,0,0,True);
489 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
491 return(outsize);
495 /****************************************************************************
496 reply to a getatr
497 ****************************************************************************/
498 int reply_getatr(char *inbuf,char *outbuf)
500 pstring fname;
501 int cnum;
502 int outsize = 0;
503 struct stat sbuf;
504 BOOL ok = False;
505 int mode=0;
506 uint32 size=0;
507 time_t mtime=0;
509 cnum = SVAL(inbuf,smb_tid);
511 strcpy(fname,smb_buf(inbuf) + 1);
512 unix_convert(fname,cnum);
514 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
515 under WfWg - weird! */
516 if (! (*fname))
518 mode = aHIDDEN | aDIR;
519 if (!CAN_WRITE(cnum)) mode |= aRONLY;
520 size = 0;
521 mtime = 0;
522 ok = True;
524 else
525 if (check_name(fname,cnum))
527 if (sys_stat(fname,&sbuf) == 0)
529 mode = dos_mode(cnum,fname,&sbuf);
530 size = sbuf.st_size;
531 mtime = sbuf.st_mtime;
532 if (mode & aDIR)
533 size = 0;
534 ok = True;
536 else
537 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
540 if (!ok)
541 return(UNIXERROR(ERRDOS,ERRbadfile));
543 outsize = set_message(outbuf,10,0,True);
545 SSVAL(outbuf,smb_vwv0,mode);
546 put_dos_date3(outbuf,smb_vwv1,mtime);
547 SIVAL(outbuf,smb_vwv3,size);
549 if (Protocol >= PROTOCOL_NT1) {
550 char *p = strrchr(fname,'/');
551 uint16 flg2 = SVAL(outbuf,smb_flg2);
552 if (!p) p = fname;
553 if (!is_8_3(fname))
554 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
557 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
559 return(outsize);
563 /****************************************************************************
564 reply to a setatr
565 ****************************************************************************/
566 int reply_setatr(char *inbuf,char *outbuf)
568 pstring fname;
569 int cnum;
570 int outsize = 0;
571 BOOL ok=False;
572 int mode;
573 time_t mtime;
575 cnum = SVAL(inbuf,smb_tid);
577 strcpy(fname,smb_buf(inbuf) + 1);
578 unix_convert(fname,cnum);
580 mode = SVAL(inbuf,smb_vwv0);
581 mtime = make_unix_date3(inbuf+smb_vwv1);
583 if (directory_exist(fname,NULL))
584 mode |= aDIR;
585 if (check_name(fname,cnum))
586 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
587 if (ok)
588 ok = set_filetime(fname,mtime);
590 if (!ok)
591 return(UNIXERROR(ERRDOS,ERRnoaccess));
593 outsize = set_message(outbuf,0,0,True);
595 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
597 return(outsize);
601 /****************************************************************************
602 reply to a dskattr
603 ****************************************************************************/
604 int reply_dskattr(char *inbuf,char *outbuf)
606 int cnum;
607 int outsize = 0;
608 int dfree,dsize,bsize;
610 cnum = SVAL(inbuf,smb_tid);
612 sys_disk_free(".",&bsize,&dfree,&dsize);
614 outsize = set_message(outbuf,5,0,True);
616 SSVAL(outbuf,smb_vwv0,dsize);
617 SSVAL(outbuf,smb_vwv1,bsize/512);
618 SSVAL(outbuf,smb_vwv2,512);
619 SSVAL(outbuf,smb_vwv3,dfree);
621 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
623 return(outsize);
627 /****************************************************************************
628 reply to a search
629 Can be called from SMBsearch, SMBffirst or SMBfunique.
630 ****************************************************************************/
631 int reply_search(char *inbuf,char *outbuf)
633 pstring mask;
634 pstring directory;
635 pstring fname;
636 int size,mode;
637 time_t date;
638 int dirtype;
639 int cnum;
640 int outsize = 0;
641 int numentries = 0;
642 BOOL finished = False;
643 int maxentries;
644 int i;
645 char *p;
646 BOOL ok = False;
647 int status_len;
648 char *path;
649 char status[21];
650 int dptr_num= -1;
651 BOOL check_descend = False;
652 BOOL expect_close = False;
653 BOOL can_open = True;
655 *mask = *directory = *fname = 0;
657 /* If we were called as SMBffirst then we must expect close. */
658 if(CVAL(inbuf,smb_com) == SMBffirst)
659 expect_close = True;
661 cnum = SVAL(inbuf,smb_tid);
663 outsize = set_message(outbuf,1,3,True);
664 maxentries = SVAL(inbuf,smb_vwv0);
665 dirtype = SVAL(inbuf,smb_vwv1);
666 path = smb_buf(inbuf) + 1;
667 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
670 /* dirtype &= ~aDIR; */
672 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
675 if (status_len == 0)
677 pstring dir2;
679 strcpy(directory,smb_buf(inbuf)+1);
680 strcpy(dir2,smb_buf(inbuf)+1);
681 unix_convert(directory,cnum);
682 unix_format(dir2);
684 if (!check_name(directory,cnum))
685 can_open = False;
687 p = strrchr(dir2,'/');
688 if (p == NULL)
689 {strcpy(mask,dir2);*dir2 = 0;}
690 else
691 {*p = 0;strcpy(mask,p+1);}
693 p = strrchr(directory,'/');
694 if (!p)
695 *directory = 0;
696 else
697 *p = 0;
699 if (strlen(directory) == 0)
700 strcpy(directory,"./");
701 bzero(status,21);
702 CVAL(status,0) = dirtype;
704 else
706 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
707 memcpy(mask,status+1,11);
708 mask[11] = 0;
709 dirtype = CVAL(status,0) & 0x1F;
710 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
711 if (!Connections[cnum].dirptr)
712 goto SearchEmpty;
713 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
714 if (!case_sensitive)
715 strnorm(mask);
718 /* turn strings of spaces into a . */
720 trim_string(mask,NULL," ");
721 if ((p = strrchr(mask,' ')))
723 fstring ext;
724 strcpy(ext,p+1);
725 *p = 0;
726 trim_string(mask,NULL," ");
727 strcat(mask,".");
728 strcat(mask,ext);
733 for (p=mask; *p; p++)
735 if (*p != '?' && *p != '*' && !isdoschar(*p))
737 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
738 *p = '?';
743 if (!strchr(mask,'.') && strlen(mask)>8)
745 fstring tmp;
746 strcpy(tmp,&mask[8]);
747 mask[8] = '.';
748 mask[9] = 0;
749 strcat(mask,tmp);
752 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
754 if (can_open)
756 p = smb_buf(outbuf) + 3;
758 ok = True;
760 if (status_len == 0)
762 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
763 if (dptr_num < 0)
764 return(ERROR(ERRDOS,ERRnofids));
767 DEBUG(4,("dptr_num is %d\n",dptr_num));
769 if (ok)
771 if ((dirtype&0x1F) == aVOLID)
773 memcpy(p,status,21);
774 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
775 dptr_fill(p+12,dptr_num);
776 if (dptr_zero(p+12) && (status_len==0))
777 numentries = 1;
778 else
779 numentries = 0;
780 p += DIR_STRUCT_SIZE;
782 else
784 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
785 if (in_list(Connections[cnum].dirpath,
786 lp_dontdescend(SNUM(cnum)),True))
787 check_descend = True;
789 for (i=numentries;(i<maxentries) && !finished;i++)
791 finished =
792 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
793 if (!finished)
795 memcpy(p,status,21);
796 make_dir_struct(p,mask,fname,size,mode,date);
797 dptr_fill(p+12,dptr_num);
798 numentries++;
800 p += DIR_STRUCT_SIZE;
807 SearchEmpty:
809 if (numentries == 0 || !ok)
811 CVAL(outbuf,smb_rcls) = ERRDOS;
812 SSVAL(outbuf,smb_err,ERRnofiles);
815 /* If we were called as SMBffirst with smb_search_id == NULL
816 and no entries were found then return error and close dirptr
817 (X/Open spec) */
819 if(ok && expect_close && numentries == 0 && status_len == 0)
821 CVAL(outbuf,smb_rcls) = ERRDOS;
822 SSVAL(outbuf,smb_err,ERRnofiles);
823 /* Also close the dptr - we know it's gone */
824 dptr_close(dptr_num);
827 /* If we were called as SMBfunique, then we can close the dirptr now ! */
828 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
829 dptr_close(dptr_num);
831 SSVAL(outbuf,smb_vwv0,numentries);
832 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
833 CVAL(smb_buf(outbuf),0) = 5;
834 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
836 if (Protocol >= PROTOCOL_NT1) {
837 uint16 flg2 = SVAL(outbuf,smb_flg2);
838 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
841 outsize += DIR_STRUCT_SIZE*numentries;
842 smb_setlen(outbuf,outsize - 4);
844 if ((! *directory) && dptr_path(dptr_num))
845 sprintf(directory,"(%s)",dptr_path(dptr_num));
847 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
848 timestring(),
849 smb_fn_name(CVAL(inbuf,smb_com)),
850 mask,directory,cnum,dirtype,numentries,maxentries));
852 return(outsize);
856 /****************************************************************************
857 reply to a fclose (stop directory search)
858 ****************************************************************************/
859 int reply_fclose(char *inbuf,char *outbuf)
861 int cnum;
862 int outsize = 0;
863 int status_len;
864 char *path;
865 char status[21];
866 int dptr_num= -1;
868 cnum = SVAL(inbuf,smb_tid);
870 outsize = set_message(outbuf,1,0,True);
871 path = smb_buf(inbuf) + 1;
872 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
875 if (status_len == 0)
876 return(ERROR(ERRSRV,ERRsrverror));
878 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
880 if(dptr_fetch(status+12,&dptr_num)) {
881 /* Close the dptr - we know it's gone */
882 dptr_close(dptr_num);
885 SSVAL(outbuf,smb_vwv0,0);
887 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
889 return(outsize);
893 /****************************************************************************
894 reply to an open
895 ****************************************************************************/
896 int reply_open(char *inbuf,char *outbuf)
898 pstring fname;
899 int cnum;
900 int fnum = -1;
901 int outsize = 0;
902 int fmode=0;
903 int share_mode;
904 int size = 0;
905 time_t mtime=0;
906 int unixmode;
907 int rmode=0;
908 struct stat sbuf;
910 cnum = SVAL(inbuf,smb_tid);
912 share_mode = SVAL(inbuf,smb_vwv0);
914 strcpy(fname,smb_buf(inbuf)+1);
915 unix_convert(fname,cnum);
917 fnum = find_free_file();
918 if (fnum < 0)
919 return(ERROR(ERRSRV,ERRnofids));
921 if (!check_name(fname,cnum))
922 return(UNIXERROR(ERRDOS,ERRnoaccess));
924 unixmode = unix_mode(cnum,aARCH);
926 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
928 if (!Files[fnum].open)
929 return(UNIXERROR(ERRDOS,ERRnoaccess));
931 if (fstat(Files[fnum].fd,&sbuf) != 0) {
932 close_file(fnum);
933 return(ERROR(ERRDOS,ERRnoaccess));
936 size = sbuf.st_size;
937 fmode = dos_mode(cnum,fname,&sbuf);
938 mtime = sbuf.st_mtime;
940 if (fmode & aDIR) {
941 DEBUG(3,("attempt to open a directory %s\n",fname));
942 close_file(fnum);
943 return(ERROR(ERRDOS,ERRnoaccess));
946 outsize = set_message(outbuf,7,0,True);
947 SSVAL(outbuf,smb_vwv0,fnum);
948 SSVAL(outbuf,smb_vwv1,fmode);
949 put_dos_date3(outbuf,smb_vwv2,mtime);
950 SIVAL(outbuf,smb_vwv4,size);
951 SSVAL(outbuf,smb_vwv6,rmode);
953 return(outsize);
957 /****************************************************************************
958 reply to an open and X
959 ****************************************************************************/
960 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
962 pstring fname;
963 int cnum = SVAL(inbuf,smb_tid);
964 int fnum = -1;
965 int outsize = 0;
966 int openmode = 0;
967 int smb_com2 = CVAL(inbuf,smb_vwv0);
968 int smb_off2 = SVAL(inbuf,smb_vwv1);
969 int smb_mode = SVAL(inbuf,smb_vwv3);
970 int smb_attr = SVAL(inbuf,smb_vwv5);
971 #if 0
972 int open_flags = SVAL(inbuf,smb_vwv2);
973 int smb_sattr = SVAL(inbuf,smb_vwv4);
974 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
975 #endif
976 int smb_ofun = SVAL(inbuf,smb_vwv8);
977 int unixmode;
978 int size=0,fmode=0,mtime=0,rmode=0;
979 struct stat sbuf;
980 int smb_action = 0;
982 /* XXXX we need to handle passed times, sattr and flags */
984 strcpy(fname,smb_buf(inbuf));
985 unix_convert(fname,cnum);
987 /* now add create and trunc bits */
988 if (smb_ofun & 0x10)
989 openmode |= O_CREAT;
990 if ((smb_ofun & 0x3) == 2)
991 openmode |= O_TRUNC;
993 fnum = find_free_file();
994 if (fnum < 0)
995 return(ERROR(ERRSRV,ERRnofids));
997 if (!check_name(fname,cnum))
998 return(UNIXERROR(ERRDOS,ERRnoaccess));
1000 unixmode = unix_mode(cnum,smb_attr | aARCH);
1002 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1003 &rmode,&smb_action);
1005 if (!Files[fnum].open)
1006 return(UNIXERROR(ERRDOS,ERRnoaccess));
1008 if (fstat(Files[fnum].fd,&sbuf) != 0) {
1009 close_file(fnum);
1010 return(ERROR(ERRDOS,ERRnoaccess));
1013 size = sbuf.st_size;
1014 fmode = dos_mode(cnum,fname,&sbuf);
1015 mtime = sbuf.st_mtime;
1016 if (fmode & aDIR) {
1017 close_file(fnum);
1018 return(ERROR(ERRDOS,ERRnoaccess));
1021 outsize = set_message(outbuf,15,0,True);
1022 CVAL(outbuf,smb_vwv0) = smb_com2;
1023 SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
1024 SSVAL(outbuf,smb_vwv2,fnum);
1025 SSVAL(outbuf,smb_vwv3,fmode);
1026 put_dos_date3(outbuf,smb_vwv4,mtime);
1027 SIVAL(outbuf,smb_vwv6,size);
1028 SSVAL(outbuf,smb_vwv8,rmode);
1029 SSVAL(outbuf,smb_vwv11,smb_action);
1031 chain_fnum = fnum;
1033 if (smb_com2 != 0xFF)
1034 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
1035 outbuf,outbuf+outsize,
1036 length,bufsize);
1038 chain_fnum = -1;
1040 return(outsize);
1044 /****************************************************************************
1045 reply to a SMBulogoffX
1046 ****************************************************************************/
1047 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1049 int outsize = 0;
1050 int smb_com2 = CVAL(inbuf,smb_vwv0);
1051 int smb_off2 = SVAL(inbuf,smb_vwv1);
1052 int uid = SVAL(inbuf,smb_uid);
1054 invalidate_uid(uid);
1056 outsize = set_message(outbuf,2,0,True);
1057 CVAL(outbuf,smb_vwv0) = smb_com2;
1058 SSVAL(outbuf,smb_vwv1,(chain_size+outsize)-4);
1060 DEBUG(3,("%s ulogoffX uid=%d\n",timestring(),uid));
1062 if (smb_com2 != 0xFF)
1063 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
1064 outbuf,outbuf+outsize,
1065 length,bufsize);
1068 return(outsize);
1072 /****************************************************************************
1073 reply to a mknew
1074 ****************************************************************************/
1075 int reply_mknew(char *inbuf,char *outbuf)
1077 pstring fname;
1078 int cnum,com;
1079 int fnum = -1;
1080 int outsize = 0;
1081 int createmode;
1082 mode_t unixmode;
1084 com = SVAL(inbuf,smb_com);
1085 cnum = SVAL(inbuf,smb_tid);
1087 createmode = SVAL(inbuf,smb_vwv0);
1088 strcpy(fname,smb_buf(inbuf)+1);
1089 unix_convert(fname,cnum);
1091 if (createmode & aVOLID)
1093 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1096 unixmode = unix_mode(cnum,createmode);
1098 if (com == SMBmknew && file_exist(fname,NULL))
1099 return(ERROR(ERRDOS,ERRfilexists));
1101 fnum = find_free_file();
1102 if (fnum < 0)
1103 return(ERROR(ERRSRV,ERRnofids));
1105 if (!check_name(fname,cnum))
1106 return(UNIXERROR(ERRDOS,ERRnoaccess));
1108 open_file(fnum,cnum,fname,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1110 if (!Files[fnum].open)
1111 return(UNIXERROR(ERRDOS,ERRnoaccess));
1113 outsize = set_message(outbuf,1,0,True);
1114 SSVAL(outbuf,smb_vwv0,fnum);
1116 DEBUG(2,("new file %s\n",fname));
1117 DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd,fnum,cnum,createmode,unixmode));
1119 return(outsize);
1123 /****************************************************************************
1124 reply to a create temporary file
1125 ****************************************************************************/
1126 int reply_ctemp(char *inbuf,char *outbuf)
1128 pstring fname;
1129 pstring fname2;
1130 int cnum;
1131 int fnum = -1;
1132 int outsize = 0;
1133 int createmode;
1134 mode_t unixmode;
1136 cnum = SVAL(inbuf,smb_tid);
1137 createmode = SVAL(inbuf,smb_vwv0);
1138 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1139 unix_convert(fname,cnum);
1141 unixmode = unix_mode(cnum,createmode);
1143 fnum = find_free_file();
1144 if (fnum < 0)
1145 return(ERROR(ERRSRV,ERRnofids));
1147 if (!check_name(fname,cnum))
1148 return(UNIXERROR(ERRDOS,ERRnoaccess));
1150 strcpy(fname2,(char *)mktemp(fname));
1152 open_file(fnum,cnum,fname2,O_RDWR | O_CREAT | O_TRUNC,unixmode);
1154 if (!Files[fnum].open)
1155 return(UNIXERROR(ERRDOS,ERRnoaccess));
1157 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1158 SSVAL(outbuf,smb_vwv0,fnum);
1159 CVAL(smb_buf(outbuf),0) = 4;
1160 strcpy(smb_buf(outbuf) + 1,fname2);
1162 DEBUG(2,("created temp file %s\n",fname2));
1163 DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd,fnum,cnum,createmode,unixmode));
1165 return(outsize);
1169 /*******************************************************************
1170 check if a user is allowed to delete a file
1171 ********************************************************************/
1172 static BOOL can_delete(char *fname,int cnum,int dirtype)
1174 struct stat sbuf;
1175 int fmode;
1177 if (!CAN_WRITE(cnum)) return(False);
1179 if (sys_lstat(fname,&sbuf) != 0) return(False);
1180 fmode = dos_mode(cnum,fname,&sbuf);
1181 if (fmode & aDIR) return(False);
1182 if (fmode & aRONLY) return(False);
1183 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1184 return(False);
1185 if (!check_file_sharing(cnum,fname)) return(False);
1186 return(True);
1189 /****************************************************************************
1190 reply to a unlink
1191 ****************************************************************************/
1192 int reply_unlink(char *inbuf,char *outbuf)
1194 int outsize = 0;
1195 pstring name;
1196 int cnum;
1197 int dirtype;
1198 pstring directory;
1199 pstring mask;
1200 char *p;
1201 int count=0;
1202 int error = ERRnoaccess;
1203 BOOL has_wild;
1204 BOOL exists=False;
1206 *directory = *mask = 0;
1208 cnum = SVAL(inbuf,smb_tid);
1209 dirtype = SVAL(inbuf,smb_vwv0);
1211 strcpy(name,smb_buf(inbuf) + 1);
1213 DEBUG(3,("reply_unlink : %s\n",name));
1215 unix_convert(name,cnum);
1217 p = strrchr(name,'/');
1218 if (!p) {
1219 strcpy(directory,"./");
1220 strcpy(mask,name);
1221 } else {
1222 *p = 0;
1223 strcpy(directory,name);
1224 strcpy(mask,p+1);
1227 if (is_mangled(mask))
1228 check_mangled_stack(mask);
1230 has_wild = strchr(mask,'*') || strchr(mask,'?');
1232 if (!has_wild) {
1233 strcat(directory,"/");
1234 strcat(directory,mask);
1235 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1236 if (!count) exists = file_exist(directory,NULL);
1237 } else {
1238 void *dirptr = NULL;
1239 char *dname;
1241 if (check_name(directory,cnum))
1242 dirptr = OpenDir(directory);
1244 if (dirptr)
1246 error = ERRbadfile;
1248 if (strequal(mask,"????????.???"))
1249 strcpy(mask,"*");
1251 while ((dname = ReadDirName(dirptr)))
1253 pstring fname;
1254 strcpy(fname,dname);
1256 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1258 error = ERRnoaccess;
1259 sprintf(fname,"%s/%s",directory,dname);
1260 if (!can_delete(fname,cnum,dirtype)) continue;
1261 if (!sys_unlink(fname)) count++;
1262 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1264 CloseDir(dirptr);
1268 if (count == 0) {
1269 if (exists)
1270 return(ERROR(ERRDOS,error));
1271 else
1272 return(UNIXERROR(ERRDOS,error));
1275 outsize = set_message(outbuf,0,0,True);
1277 return(outsize);
1281 /****************************************************************************
1282 reply to a readbraw (core+ protocol)
1283 ****************************************************************************/
1284 int reply_readbraw(char *inbuf, char *outbuf)
1286 int cnum,maxcount,mincount,fnum;
1287 int nread = 0;
1288 int startpos;
1289 char *header = outbuf;
1290 int ret=0;
1291 int fd;
1292 char *fname;
1294 cnum = SVAL(inbuf,smb_tid);
1295 fnum = GETFNUM(inbuf,smb_vwv0);
1297 startpos = IVAL(inbuf,smb_vwv1);
1298 maxcount = SVAL(inbuf,smb_vwv3);
1299 mincount = SVAL(inbuf,smb_vwv4);
1301 /* ensure we don't overrun the packet size */
1302 maxcount = MIN(65535,maxcount);
1303 maxcount = MAX(mincount,maxcount);
1305 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1307 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1308 _smb_setlen(header,0);
1309 transfer_file(0,Client,0,header,4,0);
1310 return(-1);
1312 else
1314 fd = Files[fnum].fd;
1315 fname = Files[fnum].name;
1319 if (!is_locked(fnum,cnum,maxcount,startpos))
1321 int size = Files[fnum].size;
1322 int sizeneeded = startpos + maxcount;
1324 if (size < sizeneeded) {
1325 struct stat st;
1326 if (fstat(Files[fnum].fd,&st) == 0)
1327 size = st.st_size;
1328 if (!Files[fnum].can_write)
1329 Files[fnum].size = size;
1332 nread = MIN(maxcount,size - startpos);
1335 if (nread < mincount)
1336 nread = 0;
1338 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1339 timestring(),
1340 fnum,cnum,startpos,
1341 maxcount,mincount,nread));
1343 #if UNSAFE_READRAW
1345 int predict=0;
1346 _smb_setlen(header,nread);
1348 if (!Files[fnum].can_write)
1349 predict = read_predict(fd,startpos,header+4,NULL,nread);
1351 if ((nread-predict) > 0)
1352 seek_file(fnum,startpos + predict);
1354 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1355 startpos+predict);
1358 if (ret != nread+4)
1359 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1360 fname,startpos,nread,ret));
1362 #else
1363 ret = read_file(fnum,header+4,startpos,nread,nread,-1,False);
1364 if (ret < mincount) ret = 0;
1366 _smb_setlen(header,ret);
1367 transfer_file(0,Client,0,header,4+ret,0);
1368 #endif
1370 DEBUG(5,("readbraw finished\n"));
1371 return -1;
1375 /****************************************************************************
1376 reply to a lockread (core+ protocol)
1377 ****************************************************************************/
1378 int reply_lockread(char *inbuf,char *outbuf)
1380 int cnum,fnum;
1381 int nread = -1;
1382 char *data;
1383 int outsize = 0;
1384 uint32 startpos, numtoread;
1385 int eclass;
1386 uint32 ecode;
1388 cnum = SVAL(inbuf,smb_tid);
1389 fnum = GETFNUM(inbuf,smb_vwv0);
1391 CHECK_FNUM(fnum,cnum);
1392 CHECK_READ(fnum);
1393 CHECK_ERROR(fnum);
1395 numtoread = SVAL(inbuf,smb_vwv1);
1396 startpos = IVAL(inbuf,smb_vwv2);
1398 outsize = set_message(outbuf,5,3,True);
1399 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1400 data = smb_buf(outbuf) + 3;
1402 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1403 return (ERROR(eclass,ecode));
1405 nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False);
1407 if (nread < 0)
1408 return(UNIXERROR(ERRDOS,ERRnoaccess));
1410 outsize += nread;
1411 SSVAL(outbuf,smb_vwv0,nread);
1412 SSVAL(outbuf,smb_vwv5,nread+3);
1413 SSVAL(smb_buf(outbuf),1,nread);
1415 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1417 return(outsize);
1421 /****************************************************************************
1422 reply to a read
1423 ****************************************************************************/
1424 int reply_read(char *inbuf,char *outbuf)
1426 int cnum,numtoread,fnum;
1427 int nread = 0;
1428 char *data;
1429 int startpos;
1430 int outsize = 0;
1432 cnum = SVAL(inbuf,smb_tid);
1433 fnum = GETFNUM(inbuf,smb_vwv0);
1435 CHECK_FNUM(fnum,cnum);
1436 CHECK_READ(fnum);
1437 CHECK_ERROR(fnum);
1439 numtoread = SVAL(inbuf,smb_vwv1);
1440 startpos = IVAL(inbuf,smb_vwv2);
1442 outsize = set_message(outbuf,5,3,True);
1443 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1444 data = smb_buf(outbuf) + 3;
1446 if (is_locked(fnum,cnum,numtoread,startpos))
1447 return(ERROR(ERRDOS,ERRlock));
1449 if (numtoread > 0)
1450 nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False);
1452 if (nread < 0)
1453 return(UNIXERROR(ERRDOS,ERRnoaccess));
1455 outsize += nread;
1456 SSVAL(outbuf,smb_vwv0,nread);
1457 SSVAL(outbuf,smb_vwv5,nread+3);
1458 CVAL(smb_buf(outbuf),0) = 1;
1459 SSVAL(smb_buf(outbuf),1,nread);
1461 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1463 return(outsize);
1467 /****************************************************************************
1468 reply to a read and X
1469 ****************************************************************************/
1470 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1472 int smb_com2 = CVAL(inbuf,smb_vwv0);
1473 int smb_off2 = SVAL(inbuf,smb_vwv1);
1474 int fnum = GETFNUM(inbuf,smb_vwv2);
1475 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1476 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1477 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1478 int cnum;
1479 int nread = -1;
1480 char *data;
1481 int outsize = 0;
1482 BOOL ok = False;
1484 cnum = SVAL(inbuf,smb_tid);
1486 CHECK_FNUM(fnum,cnum);
1487 CHECK_READ(fnum);
1488 CHECK_ERROR(fnum);
1490 outsize = set_message(outbuf,12,0,True);
1491 data = smb_buf(outbuf);
1493 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1494 return(ERROR(ERRDOS,ERRlock));
1495 nread = read_file(fnum,data,smb_offs,smb_maxcnt,smb_maxcnt,-1,False);
1496 ok = True;
1498 if (nread < 0)
1499 return(UNIXERROR(ERRDOS,ERRnoaccess));
1501 outsize += nread;
1502 CVAL(outbuf,smb_vwv0) = smb_com2;
1503 SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
1504 SSVAL(outbuf,smb_vwv5,nread);
1505 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf) + chain_size);
1506 SSVAL(smb_buf(outbuf),-2,nread);
1508 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d com2=%d off2=%d\n",
1509 timestring(),fnum,cnum,
1510 smb_mincnt,smb_maxcnt,nread,smb_com2,smb_off2));
1512 chain_fnum = fnum;
1514 if (smb_com2 != 0xFF)
1515 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
1516 outbuf,outbuf+outsize,
1517 length,bufsize);
1519 chain_fnum = -1;
1521 return(outsize);
1525 /****************************************************************************
1526 reply to a writebraw (core+ or LANMAN1.0 protocol)
1527 ****************************************************************************/
1528 int reply_writebraw(char *inbuf,char *outbuf)
1530 int nwritten=0;
1531 int total_written=0;
1532 int numtowrite=0;
1533 int cnum,fnum;
1534 int outsize = 0;
1535 long startpos;
1536 char *data=NULL;
1537 BOOL write_through;
1538 int tcount;
1540 cnum = SVAL(inbuf,smb_tid);
1541 fnum = GETFNUM(inbuf,smb_vwv0);
1543 CHECK_FNUM(fnum,cnum);
1544 CHECK_WRITE(fnum);
1545 CHECK_ERROR(fnum);
1547 tcount = IVAL(inbuf,smb_vwv1);
1548 startpos = IVAL(inbuf,smb_vwv3);
1549 write_through = BITSETW(inbuf+smb_vwv7,0);
1551 /* We have to deal with slightly different formats depending
1552 on whether we are using the core+ or lanman1.0 protocol */
1553 if(Protocol <= PROTOCOL_COREPLUS) {
1554 numtowrite = SVAL(smb_buf(inbuf),-2);
1555 data = smb_buf(inbuf);
1556 } else {
1557 numtowrite = SVAL(inbuf,smb_vwv10);
1558 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1561 /* force the error type */
1562 CVAL(inbuf,smb_com) = SMBwritec;
1563 CVAL(outbuf,smb_com) = SMBwritec;
1565 if (is_locked(fnum,cnum,tcount,startpos))
1566 return(ERROR(ERRDOS,ERRlock));
1568 if (seek_file(fnum,startpos) != startpos)
1569 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1571 if (numtowrite>0)
1572 nwritten = write_file(fnum,data,numtowrite);
1574 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1575 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1577 if (nwritten < numtowrite)
1578 return(UNIXERROR(ERRHRD,ERRdiskfull));
1580 total_written = nwritten;
1582 /* Return a message to the redirector to tell it
1583 to send more bytes */
1584 CVAL(outbuf,smb_com) = SMBwritebraw;
1585 SSVALS(outbuf,smb_vwv0,-1);
1586 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1587 send_smb(Client,outbuf);
1589 /* Now read the raw data into the buffer and write it */
1590 if(read_smb_length(Client,inbuf,0) == -1) {
1591 exit_server("secondary writebraw failed");
1594 /* Even though this is not an smb message, smb_len
1595 returns the generic length of an smb message */
1596 numtowrite = smb_len(inbuf);
1598 if (tcount > nwritten+numtowrite) {
1599 DEBUG(3,("Client overestimated the write %d %d %d\n",
1600 tcount,nwritten,numtowrite));
1603 nwritten = transfer_file(Client,Files[fnum].fd,numtowrite,NULL,0,
1604 startpos+nwritten);
1605 total_written += nwritten;
1607 /* Set up outbuf to return the correct return */
1608 outsize = set_message(outbuf,1,0,True);
1609 CVAL(outbuf,smb_com) = SMBwritec;
1610 SSVAL(outbuf,smb_vwv0,total_written);
1612 if (nwritten < numtowrite) {
1613 CVAL(outbuf,smb_rcls) = ERRHRD;
1614 SSVAL(outbuf,smb_err,ERRdiskfull);
1617 if (lp_syncalways(SNUM(cnum)) || write_through)
1618 sync_file(fnum);
1620 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1621 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1623 /* we won't return a status if write through is not selected - this
1624 follows what WfWg does */
1625 if (!write_through && total_written==tcount)
1626 return(-1);
1628 return(outsize);
1632 /****************************************************************************
1633 reply to a writeunlock (core+)
1634 ****************************************************************************/
1635 int reply_writeunlock(char *inbuf,char *outbuf)
1637 int cnum,fnum;
1638 int nwritten = -1;
1639 int outsize = 0;
1640 char *data;
1641 uint32 numtowrite,startpos;
1642 int eclass;
1643 uint32 ecode;
1645 cnum = SVAL(inbuf,smb_tid);
1646 fnum = GETFNUM(inbuf,smb_vwv0);
1648 CHECK_FNUM(fnum,cnum);
1649 CHECK_WRITE(fnum);
1650 CHECK_ERROR(fnum);
1652 numtowrite = SVAL(inbuf,smb_vwv1);
1653 startpos = IVAL(inbuf,smb_vwv2);
1654 data = smb_buf(inbuf) + 3;
1656 if (is_locked(fnum,cnum,numtowrite,startpos))
1657 return(ERROR(ERRDOS,ERRlock));
1659 seek_file(fnum,startpos);
1661 /* The special X/Open SMB protocol handling of
1662 zero length writes is *NOT* done for
1663 this call */
1664 if(numtowrite == 0)
1665 nwritten = 0;
1666 else
1667 nwritten = write_file(fnum,data,numtowrite);
1669 if (lp_syncalways(SNUM(cnum)))
1670 sync_file(fnum);
1672 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1673 return(UNIXERROR(ERRDOS,ERRnoaccess));
1675 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1676 return(ERROR(eclass,ecode));
1678 outsize = set_message(outbuf,1,0,True);
1680 SSVAL(outbuf,smb_vwv0,nwritten);
1682 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1683 timestring(),fnum,cnum,numtowrite,nwritten));
1685 return(outsize);
1689 /****************************************************************************
1690 reply to a write
1691 ****************************************************************************/
1692 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1694 int cnum,numtowrite,fnum;
1695 int nwritten = -1;
1696 int outsize = 0;
1697 int startpos;
1698 char *data;
1700 dum1 = dum2 = 0;
1703 cnum = SVAL(inbuf,smb_tid);
1704 fnum = GETFNUM(inbuf,smb_vwv0);
1706 CHECK_FNUM(fnum,cnum);
1707 CHECK_WRITE(fnum);
1708 CHECK_ERROR(fnum);
1710 numtowrite = SVAL(inbuf,smb_vwv1);
1711 startpos = IVAL(inbuf,smb_vwv2);
1712 data = smb_buf(inbuf) + 3;
1714 if (is_locked(fnum,cnum,numtowrite,startpos))
1715 return(ERROR(ERRDOS,ERRlock));
1717 seek_file(fnum,startpos);
1719 /* X/Open SMB protocol says that if smb_vwv1 is
1720 zero then the file size should be extended or
1721 truncated to the size given in smb_vwv[2-3] */
1722 if(numtowrite == 0)
1723 nwritten = set_filelen(Files[fnum].fd, startpos);
1724 else
1725 nwritten = write_file(fnum,data,numtowrite);
1727 if (lp_syncalways(SNUM(cnum)))
1728 sync_file(fnum);
1730 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1731 return(UNIXERROR(ERRDOS,ERRnoaccess));
1733 outsize = set_message(outbuf,1,0,True);
1735 SSVAL(outbuf,smb_vwv0,nwritten);
1737 if (nwritten < numtowrite) {
1738 CVAL(outbuf,smb_rcls) = ERRHRD;
1739 SSVAL(outbuf,smb_err,ERRdiskfull);
1742 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1744 return(outsize);
1748 /****************************************************************************
1749 reply to a write and X
1750 ****************************************************************************/
1751 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1753 int smb_com2 = CVAL(inbuf,smb_vwv0);
1754 int smb_off2 = SVAL(inbuf,smb_vwv1);
1755 int fnum = GETFNUM(inbuf,smb_vwv2);
1756 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1757 int smb_dsize = SVAL(inbuf,smb_vwv10);
1758 int smb_doff = SVAL(inbuf,smb_vwv11);
1759 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1760 int cnum;
1761 int nwritten = -1;
1762 int outsize = 0;
1763 char *data;
1765 cnum = SVAL(inbuf,smb_tid);
1767 CHECK_FNUM(fnum,cnum);
1768 CHECK_WRITE(fnum);
1769 CHECK_ERROR(fnum);
1771 data = smb_base(inbuf) + smb_doff;
1773 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1774 return(ERROR(ERRDOS,ERRlock));
1776 seek_file(fnum,smb_offs);
1778 /* X/Open SMB protocol says that, unlike SMBwrite
1779 if the length is zero then NO truncation is
1780 done, just a write of zero. To truncate a file,
1781 use SMBwrite. */
1782 if(smb_dsize == 0)
1783 nwritten = 0;
1784 else
1785 nwritten = write_file(fnum,data,smb_dsize);
1787 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1788 return(UNIXERROR(ERRDOS,ERRnoaccess));
1790 outsize = set_message(outbuf,6,0,True);
1792 CVAL(outbuf,smb_vwv0) = smb_com2;
1793 SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
1794 SSVAL(outbuf,smb_vwv2,nwritten);
1796 if (nwritten < smb_dsize) {
1797 CVAL(outbuf,smb_rcls) = ERRHRD;
1798 SSVAL(outbuf,smb_err,ERRdiskfull);
1801 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1803 chain_fnum = fnum;
1805 if (lp_syncalways(SNUM(cnum)) || write_through)
1806 sync_file(fnum);
1808 if (smb_com2 != 0xFF)
1809 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
1810 outbuf,outbuf+outsize,
1811 length,bufsize);
1813 chain_fnum = -1;
1815 return(outsize);
1819 /****************************************************************************
1820 reply to a lseek
1821 ****************************************************************************/
1822 int reply_lseek(char *inbuf,char *outbuf)
1824 int cnum,fnum;
1825 uint32 startpos;
1826 int32 res= -1;
1827 int mode,umode;
1828 int outsize = 0;
1830 cnum = SVAL(inbuf,smb_tid);
1831 fnum = GETFNUM(inbuf,smb_vwv0);
1833 CHECK_FNUM(fnum,cnum);
1834 CHECK_ERROR(fnum);
1836 mode = SVAL(inbuf,smb_vwv1) & 3;
1837 startpos = IVAL(inbuf,smb_vwv2);
1839 switch (mode & 3)
1841 case 0: umode = SEEK_SET; break;
1842 case 1: umode = SEEK_CUR; break;
1843 case 2: umode = SEEK_END; break;
1844 default:
1845 umode = SEEK_SET; break;
1848 res = lseek(Files[fnum].fd,startpos,umode);
1849 Files[fnum].pos = res;
1851 outsize = set_message(outbuf,2,0,True);
1852 SIVALS(outbuf,smb_vwv0,res);
1854 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1856 return(outsize);
1860 /****************************************************************************
1861 reply to a flush
1862 ****************************************************************************/
1863 int reply_flush(char *inbuf,char *outbuf)
1865 int cnum, fnum;
1866 int outsize = set_message(outbuf,0,0,True);
1868 cnum = SVAL(inbuf,smb_tid);
1869 fnum = GETFNUM(inbuf,smb_vwv0);
1871 if (fnum != 0xFFFF) {
1872 CHECK_FNUM(fnum,cnum);
1873 CHECK_ERROR(fnum);
1876 if (fnum == 0xFFFF)
1878 int i;
1879 for (i=0;i<MAX_OPEN_FILES;i++)
1880 if (OPEN_FNUM(i))
1881 sync_file(i);
1883 else
1884 sync_file(fnum);
1886 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1887 return(outsize);
1891 /****************************************************************************
1892 reply to a exit
1893 ****************************************************************************/
1894 int reply_exit(char *inbuf,char *outbuf)
1896 int outsize = set_message(outbuf,0,0,True);
1897 DEBUG(3,("%s exit\n",timestring()));
1899 return(outsize);
1903 /****************************************************************************
1904 reply to a close
1905 ****************************************************************************/
1906 int reply_close(char *inbuf,char *outbuf)
1908 int fnum,cnum;
1909 int outsize = 0;
1910 time_t mtime;
1911 int32 eclass = 0, err = 0;
1913 outsize = set_message(outbuf,0,0,True);
1915 cnum = SVAL(inbuf,smb_tid);
1917 fnum = GETFNUM(inbuf,smb_vwv0);
1918 CHECK_FNUM(fnum,cnum);
1920 if(HAS_CACHED_ERROR(fnum)) {
1921 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1922 err = Files[fnum].wbmpx_ptr->wr_error;
1925 mtime = make_unix_date3(inbuf+smb_vwv1);
1927 close_file(fnum);
1929 /* try and set the date */
1930 set_filetime(Files[fnum].name,mtime);
1932 /* We have a cached error */
1933 if(eclass || err)
1934 return(ERROR(eclass,err));
1936 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
1937 timestring(),Files[fnum].fd,fnum,cnum,
1938 Connections[cnum].num_files_open));
1940 return(outsize);
1944 /****************************************************************************
1945 reply to a writeclose (Core+ protocol)
1946 ****************************************************************************/
1947 int reply_writeclose(char *inbuf,char *outbuf)
1949 int cnum,numtowrite,fnum;
1950 int nwritten = -1;
1951 int outsize = 0;
1952 int startpos;
1953 char *data;
1954 time_t mtime;
1956 cnum = SVAL(inbuf,smb_tid);
1957 fnum = GETFNUM(inbuf,smb_vwv0);
1959 CHECK_FNUM(fnum,cnum);
1960 CHECK_WRITE(fnum);
1961 CHECK_ERROR(fnum);
1963 numtowrite = SVAL(inbuf,smb_vwv1);
1964 startpos = IVAL(inbuf,smb_vwv2);
1965 mtime = make_unix_date3(inbuf+smb_vwv4);
1966 data = smb_buf(inbuf) + 1;
1968 if (is_locked(fnum,cnum,numtowrite,startpos))
1969 return(ERROR(ERRDOS,ERRlock));
1971 seek_file(fnum,startpos);
1973 nwritten = write_file(fnum,data,numtowrite);
1975 close_file(fnum);
1977 set_filetime(Files[fnum].name,mtime);
1979 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
1980 timestring(),fnum,cnum,numtowrite,nwritten,
1981 Connections[cnum].num_files_open));
1983 if (nwritten <= 0)
1984 return(UNIXERROR(ERRDOS,ERRnoaccess));
1986 outsize = set_message(outbuf,1,0,True);
1988 SSVAL(outbuf,smb_vwv0,nwritten);
1989 return(outsize);
1993 /****************************************************************************
1994 reply to a lock
1995 ****************************************************************************/
1996 int reply_lock(char *inbuf,char *outbuf)
1998 int fnum,cnum;
1999 int outsize = set_message(outbuf,0,0,True);
2000 uint32 count,offset;
2001 int eclass;
2002 uint32 ecode;
2004 cnum = SVAL(inbuf,smb_tid);
2005 fnum = GETFNUM(inbuf,smb_vwv0);
2007 CHECK_FNUM(fnum,cnum);
2008 CHECK_ERROR(fnum);
2010 count = IVAL(inbuf,smb_vwv1);
2011 offset = IVAL(inbuf,smb_vwv3);
2013 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2015 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2016 return (ERROR(eclass,ecode));
2018 return(outsize);
2022 /****************************************************************************
2023 reply to a unlock
2024 ****************************************************************************/
2025 int reply_unlock(char *inbuf,char *outbuf)
2027 int fnum,cnum;
2028 int outsize = set_message(outbuf,0,0,True);
2029 uint32 count,offset;
2030 int eclass;
2031 uint32 ecode;
2033 cnum = SVAL(inbuf,smb_tid);
2034 fnum = GETFNUM(inbuf,smb_vwv0);
2036 CHECK_FNUM(fnum,cnum);
2037 CHECK_ERROR(fnum);
2039 count = IVAL(inbuf,smb_vwv1);
2040 offset = IVAL(inbuf,smb_vwv3);
2042 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2043 return (ERROR(eclass,ecode));
2045 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd,fnum,cnum,offset,count));
2047 return(outsize);
2051 /****************************************************************************
2052 reply to a tdis
2053 ****************************************************************************/
2054 int reply_tdis(char *inbuf,char *outbuf)
2056 int cnum, uid;
2057 int outsize = set_message(outbuf,0,0,True);
2059 cnum = SVAL(inbuf,smb_tid);
2060 uid = SVAL(inbuf,smb_uid);
2062 Connections[cnum].used = False;
2064 close_cnum(cnum,uid);
2066 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2068 return outsize;
2073 /****************************************************************************
2074 reply to a echo
2075 ****************************************************************************/
2076 int reply_echo(char *inbuf,char *outbuf)
2078 int cnum;
2079 int smb_reverb = SVAL(inbuf,smb_vwv0);
2080 int seq_num;
2081 int data_len = smb_buflen(inbuf);
2082 int outsize = set_message(outbuf,1,data_len,True);
2084 cnum = SVAL(inbuf,smb_tid);
2086 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2088 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2089 return(ERROR(ERRSRV,ERRinvnid));
2092 /* copy any incoming data back out */
2093 if (data_len > 0)
2094 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2096 if (smb_reverb > 100)
2098 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2099 smb_reverb = 100;
2102 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2104 SSVAL(outbuf,smb_vwv0,seq_num);
2106 smb_setlen(outbuf,outsize - 4);
2108 send_smb(Client,outbuf);
2111 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2113 return -1;
2117 /****************************************************************************
2118 reply to a printopen
2119 ****************************************************************************/
2120 int reply_printopen(char *inbuf,char *outbuf)
2122 pstring fname;
2123 pstring fname2;
2124 int cnum;
2125 int fnum = -1;
2126 int outsize = 0;
2128 *fname = *fname2 = 0;
2130 cnum = SVAL(inbuf,smb_tid);
2132 if (!CAN_PRINT(cnum))
2133 return(ERROR(ERRDOS,ERRnoaccess));
2136 pstring s;
2137 char *p;
2138 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2139 p = s;
2140 while (*p)
2142 if (!(isalnum(*p) || strchr("._-",*p)))
2143 *p = 'X';
2144 p++;
2147 if (strlen(s) > 10) s[10] = 0;
2149 sprintf(fname,"%s.XXXXXX",s);
2152 fnum = find_free_file();
2153 if (fnum < 0)
2154 return(ERROR(ERRSRV,ERRnofids));
2156 strcpy(fname2,(char *)mktemp(fname));
2158 if (!check_name(fname2,cnum))
2159 return(ERROR(ERRDOS,ERRnoaccess));
2161 open_file(fnum,cnum,fname2,O_WRONLY | O_CREAT | O_TRUNC,
2162 unix_mode(cnum,0));
2164 if (!Files[fnum].open)
2165 return(UNIXERROR(ERRDOS,ERRnoaccess));
2167 /* force it to be a print file */
2168 Files[fnum].print_file = True;
2170 outsize = set_message(outbuf,1,0,True);
2171 SSVAL(outbuf,smb_vwv0,fnum);
2173 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd,fnum,cnum));
2175 return(outsize);
2179 /****************************************************************************
2180 reply to a printclose
2181 ****************************************************************************/
2182 int reply_printclose(char *inbuf,char *outbuf)
2184 int fnum,cnum;
2185 int outsize = set_message(outbuf,0,0,True);
2187 cnum = SVAL(inbuf,smb_tid);
2188 fnum = GETFNUM(inbuf,smb_vwv0);
2190 CHECK_FNUM(fnum,cnum);
2191 CHECK_ERROR(fnum);
2193 if (!CAN_PRINT(cnum))
2194 return(ERROR(ERRDOS,ERRnoaccess));
2196 close_file(fnum);
2198 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd,fnum,cnum));
2200 return(outsize);
2204 /****************************************************************************
2205 reply to a printqueue
2206 ****************************************************************************/
2207 int reply_printqueue(char *inbuf,char *outbuf)
2209 int cnum, uid;
2210 int outsize = set_message(outbuf,2,3,True);
2211 int max_count = SVAL(inbuf,smb_vwv0);
2212 int start_index = SVAL(inbuf,smb_vwv1);
2214 cnum = SVAL(inbuf,smb_tid);
2215 uid = SVAL(inbuf,smb_uid);
2217 /* allow checking the queue for anyone */
2218 #if 0
2219 if (!CAN_PRINT(cnum))
2220 return(ERROR(ERRDOS,ERRnoaccess));
2221 #endif
2223 SSVAL(outbuf,smb_vwv0,0);
2224 SSVAL(outbuf,smb_vwv1,0);
2225 CVAL(smb_buf(outbuf),0) = 1;
2226 SSVAL(smb_buf(outbuf),1,0);
2228 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2229 timestring(),cnum,start_index,max_count));
2231 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2233 int i;
2234 cnum = -1;
2236 for (i=0;i<MAX_CONNECTIONS;i++)
2237 if (CAN_PRINT(i) && Connections[i].printer)
2238 cnum = i;
2240 if (cnum == -1)
2241 for (i=0;i<MAX_CONNECTIONS;i++)
2242 if (OPEN_CNUM(i))
2243 cnum = i;
2245 if (!OPEN_CNUM(cnum))
2246 return(ERROR(ERRSRV,ERRinvnid));
2248 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2251 if (!become_user(cnum,uid))
2252 return(ERROR(ERRSRV,ERRinvnid));
2255 print_queue_struct *queue = NULL;
2256 char *p = smb_buf(outbuf) + 3;
2257 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2258 int num_to_get = ABS(max_count);
2259 int first = (max_count>0?start_index:start_index+max_count+1);
2260 int i;
2262 if (first >= count)
2263 num_to_get = 0;
2264 else
2265 num_to_get = MIN(num_to_get,count-first);
2268 for (i=first;i<first+num_to_get;i++)
2270 put_dos_date2(p,0,queue[i].time);
2271 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2272 SSVAL(p,5,queue[i].job);
2273 SIVAL(p,7,queue[i].size);
2274 CVAL(p,11) = 0;
2275 StrnCpy(p+12,queue[i].user,16);
2276 p += 28;
2279 if (count > 0)
2281 outsize = set_message(outbuf,2,28*count+3,False);
2282 SSVAL(outbuf,smb_vwv0,count);
2283 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2284 CVAL(smb_buf(outbuf),0) = 1;
2285 SSVAL(smb_buf(outbuf),1,28*count);
2288 if (queue) free(queue);
2290 DEBUG(3,("%d entries returned in queue\n",count));
2293 return(outsize);
2297 /****************************************************************************
2298 reply to a printwrite
2299 ****************************************************************************/
2300 int reply_printwrite(char *inbuf,char *outbuf)
2302 int cnum,numtowrite,fnum;
2303 int outsize = set_message(outbuf,0,0,True);
2304 char *data;
2306 cnum = SVAL(inbuf,smb_tid);
2308 if (!CAN_PRINT(cnum))
2309 return(ERROR(ERRDOS,ERRnoaccess));
2311 fnum = GETFNUM(inbuf,smb_vwv0);
2313 CHECK_FNUM(fnum,cnum);
2314 CHECK_WRITE(fnum);
2315 CHECK_ERROR(fnum);
2317 numtowrite = SVAL(smb_buf(inbuf),1);
2318 data = smb_buf(inbuf) + 3;
2320 if (write_file(fnum,data,numtowrite) != numtowrite)
2321 return(UNIXERROR(ERRDOS,ERRnoaccess));
2323 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2325 return(outsize);
2329 /****************************************************************************
2330 reply to a mkdir
2331 ****************************************************************************/
2332 int reply_mkdir(char *inbuf,char *outbuf)
2334 pstring directory;
2335 int cnum;
2336 int outsize,ret= -1;
2338 strcpy(directory,smb_buf(inbuf) + 1);
2339 cnum = SVAL(inbuf,smb_tid);
2340 unix_convert(directory,cnum);
2342 if (check_name(directory,cnum))
2343 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2345 if (ret < 0)
2346 return(UNIXERROR(ERRDOS,ERRnoaccess));
2348 outsize = set_message(outbuf,0,0,True);
2350 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2352 return(outsize);
2356 /****************************************************************************
2357 reply to a rmdir
2358 ****************************************************************************/
2359 int reply_rmdir(char *inbuf,char *outbuf)
2361 pstring directory;
2362 int cnum;
2363 int outsize = 0;
2364 BOOL ok = False;
2366 cnum = SVAL(inbuf,smb_tid);
2367 strcpy(directory,smb_buf(inbuf) + 1);
2368 unix_convert(directory,cnum);
2370 if (check_name(directory,cnum))
2372 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2373 ok = (sys_rmdir(directory) == 0);
2374 if (!ok)
2375 DEBUG(3,("couldn't remove directory %s : %s\n",
2376 directory,strerror(errno)));
2379 if (!ok)
2380 return(UNIXERROR(ERRDOS,ERRbadpath));
2382 outsize = set_message(outbuf,0,0,True);
2384 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2386 return(outsize);
2390 /*******************************************************************
2391 resolve wildcards in a filename rename
2392 ********************************************************************/
2393 static BOOL resolve_wildcards(char *name1,char *name2)
2395 fstring root1,root2;
2396 fstring ext1,ext2;
2397 char *p,*p2;
2399 name1 = strrchr(name1,'/');
2400 name2 = strrchr(name2,'/');
2402 if (!name1 || !name2) return(False);
2404 strcpy(root1,name1);
2405 strcpy(root2,name2);
2406 p = strrchr(root1,'.');
2407 if (p) {
2408 *p = 0;
2409 strcpy(ext1,p+1);
2410 } else {
2411 strcpy(ext1,"");
2413 p = strrchr(root2,'.');
2414 if (p) {
2415 *p = 0;
2416 strcpy(ext2,p+1);
2417 } else {
2418 strcpy(ext2,"");
2421 p = root1;
2422 p2 = root2;
2423 while (*p2) {
2424 if (*p2 == '?') {
2425 *p2 = *p;
2426 p2++;
2427 } else {
2428 p2++;
2430 if (*p) p++;
2433 p = ext1;
2434 p2 = ext2;
2435 while (*p2) {
2436 if (*p2 == '?') {
2437 *p2 = *p;
2438 p2++;
2439 } else {
2440 p2++;
2442 if (*p) p++;
2445 strcpy(name2,root2);
2446 if (ext2[0]) {
2447 strcat(name2,".");
2448 strcat(name2,ext2);
2451 return(True);
2454 /*******************************************************************
2455 check if a user is allowed to rename a file
2456 ********************************************************************/
2457 static BOOL can_rename(char *fname,int cnum)
2459 struct stat sbuf;
2461 if (!CAN_WRITE(cnum)) return(False);
2463 if (sys_lstat(fname,&sbuf) != 0) return(False);
2464 if (!check_file_sharing(cnum,fname)) return(False);
2466 return(True);
2469 /****************************************************************************
2470 reply to a mv
2471 ****************************************************************************/
2472 int reply_mv(char *inbuf,char *outbuf)
2474 int outsize = 0;
2475 pstring name;
2476 int cnum;
2477 pstring directory;
2478 pstring mask,newname;
2479 char *p;
2480 int count=0;
2481 int error = ERRnoaccess;
2482 BOOL has_wild;
2483 BOOL exists=False;
2485 *directory = *mask = 0;
2487 cnum = SVAL(inbuf,smb_tid);
2489 strcpy(name,smb_buf(inbuf) + 1);
2490 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2492 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2494 unix_convert(name,cnum);
2495 unix_convert(newname,cnum);
2497 p = strrchr(name,'/');
2498 if (!p) {
2499 strcpy(directory,"./");
2500 strcpy(mask,name);
2501 } else {
2502 *p = 0;
2503 strcpy(directory,name);
2504 strcpy(mask,p+1);
2507 if (is_mangled(mask))
2508 check_mangled_stack(mask);
2510 has_wild = strchr(mask,'*') || strchr(mask,'?');
2512 if (!has_wild) {
2513 strcat(directory,"/");
2514 strcat(directory,mask);
2515 if (resolve_wildcards(directory,newname) &&
2516 can_rename(directory,cnum) &&
2517 !file_exist(newname,NULL) &&
2518 !sys_rename(directory,newname)) count++;
2519 if (!count) exists = file_exist(directory,NULL);
2520 if (!count && exists && file_exist(newname,NULL)) {
2521 exists = True;
2522 error = 183;
2524 } else {
2525 void *dirptr = NULL;
2526 char *dname;
2527 pstring destname;
2529 if (check_name(directory,cnum))
2530 dirptr = OpenDir(directory);
2532 if (dirptr)
2534 error = ERRbadfile;
2536 if (strequal(mask,"????????.???"))
2537 strcpy(mask,"*");
2539 while ((dname = ReadDirName(dirptr)))
2541 pstring fname;
2542 strcpy(fname,dname);
2544 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2546 error = ERRnoaccess;
2547 sprintf(fname,"%s/%s",directory,dname);
2548 if (!can_rename(fname,cnum)) continue;
2549 strcpy(destname,newname);
2551 if (!resolve_wildcards(fname,destname)) continue;
2553 if (file_exist(destname,NULL)) {
2554 error = 183;
2555 continue;
2557 if (!sys_rename(fname,destname)) count++;
2558 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2560 CloseDir(dirptr);
2564 if (count == 0) {
2565 if (exists)
2566 return(ERROR(ERRDOS,error));
2567 else
2568 return(UNIXERROR(ERRDOS,error));
2571 outsize = set_message(outbuf,0,0,True);
2573 return(outsize);
2576 /*******************************************************************
2577 copy a file as part of a reply_copy
2578 ******************************************************************/
2579 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2580 int count,BOOL target_is_directory)
2582 int Access,action;
2583 struct stat st;
2584 int ret=0;
2585 int fnum1,fnum2;
2586 pstring dest;
2588 strcpy(dest,dest1);
2589 if (target_is_directory) {
2590 char *p = strrchr(src,'/');
2591 if (p)
2592 p++;
2593 else
2594 p = src;
2595 strcat(dest,"/");
2596 strcat(dest,p);
2599 if (!file_exist(src,&st)) return(False);
2601 fnum1 = find_free_file();
2602 if (fnum1<0) return(False);
2603 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2604 1,0,&Access,&action);
2606 if (!Files[fnum1].open) return(False);
2608 if (!target_is_directory && count)
2609 ofun = 1;
2611 fnum2 = find_free_file();
2612 if (fnum2<0) {
2613 close_file(fnum1);
2614 return(False);
2616 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2617 ofun,st.st_mode,&Access,&action);
2619 if (!Files[fnum2].open) {
2620 close_file(fnum1);
2621 return(False);
2624 if ((ofun&3) == 1) {
2625 lseek(Files[fnum2].fd,0,SEEK_END);
2628 if (st.st_size)
2629 ret = transfer_file(Files[fnum1].fd,Files[fnum2].fd,st.st_size,NULL,0,0);
2631 close_file(fnum1);
2632 close_file(fnum2);
2634 return(ret == st.st_size);
2639 /****************************************************************************
2640 reply to a file copy.
2641 ****************************************************************************/
2642 int reply_copy(char *inbuf,char *outbuf)
2644 int outsize = 0;
2645 pstring name;
2646 int cnum;
2647 pstring directory;
2648 pstring mask,newname;
2649 char *p;
2650 int count=0;
2651 int error = ERRnoaccess;
2652 BOOL has_wild;
2653 BOOL exists=False;
2654 int tid2 = SVAL(inbuf,smb_vwv0);
2655 int ofun = SVAL(inbuf,smb_vwv1);
2656 int flags = SVAL(inbuf,smb_vwv2);
2657 BOOL target_is_directory=False;
2659 *directory = *mask = 0;
2661 cnum = SVAL(inbuf,smb_tid);
2663 strcpy(name,smb_buf(inbuf));
2664 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2666 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2668 if (tid2 != cnum) {
2669 /* can't currently handle inter share copies XXXX */
2670 DEBUG(3,("Rejecting inter-share copy\n"));
2671 return(ERROR(ERRSRV,ERRinvdevice));
2674 unix_convert(name,cnum);
2675 unix_convert(newname,cnum);
2677 target_is_directory = directory_exist(newname,NULL);
2679 if ((flags&1) && target_is_directory) {
2680 return(ERROR(ERRDOS,ERRbadfile));
2683 if ((flags&2) && !target_is_directory) {
2684 return(ERROR(ERRDOS,ERRbadpath));
2687 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2688 /* wants a tree copy! XXXX */
2689 DEBUG(3,("Rejecting tree copy\n"));
2690 return(ERROR(ERRSRV,ERRerror));
2693 p = strrchr(name,'/');
2694 if (!p) {
2695 strcpy(directory,"./");
2696 strcpy(mask,name);
2697 } else {
2698 *p = 0;
2699 strcpy(directory,name);
2700 strcpy(mask,p+1);
2703 if (is_mangled(mask))
2704 check_mangled_stack(mask);
2706 has_wild = strchr(mask,'*') || strchr(mask,'?');
2708 if (!has_wild) {
2709 strcat(directory,"/");
2710 strcat(directory,mask);
2711 if (resolve_wildcards(directory,newname) &&
2712 copy_file(directory,newname,cnum,ofun,
2713 count,target_is_directory)) count++;
2714 if (!count) exists = file_exist(directory,NULL);
2715 } else {
2716 void *dirptr = NULL;
2717 char *dname;
2718 pstring destname;
2720 if (check_name(directory,cnum))
2721 dirptr = OpenDir(directory);
2723 if (dirptr)
2725 error = ERRbadfile;
2727 if (strequal(mask,"????????.???"))
2728 strcpy(mask,"*");
2730 while ((dname = ReadDirName(dirptr)))
2732 pstring fname;
2733 strcpy(fname,dname);
2735 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2737 error = ERRnoaccess;
2738 sprintf(fname,"%s/%s",directory,dname);
2739 strcpy(destname,newname);
2740 if (resolve_wildcards(fname,destname) &&
2741 copy_file(directory,newname,cnum,ofun,
2742 count,target_is_directory)) count++;
2743 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2745 CloseDir(dirptr);
2749 if (count == 0) {
2750 if (exists)
2751 return(ERROR(ERRDOS,error));
2752 else
2753 return(UNIXERROR(ERRDOS,error));
2756 outsize = set_message(outbuf,1,0,True);
2757 SSVAL(outbuf,smb_vwv0,count);
2759 return(outsize);
2764 /****************************************************************************
2765 reply to a setdir
2766 ****************************************************************************/
2767 int reply_setdir(char *inbuf,char *outbuf)
2769 int cnum,snum;
2770 int outsize = 0;
2771 BOOL ok = False;
2772 pstring newdir;
2774 cnum = SVAL(inbuf,smb_tid);
2776 snum = Connections[cnum].service;
2777 if (!CAN_SETDIR(snum))
2778 return(ERROR(ERRDOS,ERRnoaccess));
2780 strcpy(newdir,smb_buf(inbuf) + 1);
2781 strlower(newdir);
2783 if (strlen(newdir) == 0)
2784 ok = True;
2785 else
2787 ok = directory_exist(newdir,NULL);
2788 if (ok)
2789 string_set(&Connections[cnum].connectpath,newdir);
2792 if (!ok)
2793 return(ERROR(ERRDOS,ERRbadpath));
2795 outsize = set_message(outbuf,0,0,True);
2796 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
2798 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
2800 return(outsize);
2804 /****************************************************************************
2805 reply to a lockingX request
2806 ****************************************************************************/
2807 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
2809 int smb_com2 = CVAL(inbuf,smb_vwv0);
2810 int smb_off2 = SVAL(inbuf,smb_vwv1);
2811 int fnum = GETFNUM(inbuf,smb_vwv2);
2812 uint16 locktype = SVAL(inbuf,smb_vwv3);
2813 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
2814 uint16 num_locks = SVAL(inbuf,smb_vwv7);
2815 uint32 count, offset;
2817 int cnum;
2818 int i;
2819 char *data;
2820 uint32 ecode=0, dummy2;
2821 int outsize, eclass=0, dummy1;
2823 cnum = SVAL(inbuf,smb_tid);
2825 CHECK_FNUM(fnum,cnum);
2826 CHECK_ERROR(fnum);
2828 data = smb_buf(inbuf);
2829 /* Data now points at the beginning of the list
2830 of smb_unlkrng structs */
2831 for(i = 0; i < (int)num_ulocks; i++) {
2832 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2833 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2834 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
2835 return ERROR(eclass,ecode);
2838 /* Now do any requested locks */
2839 data += 10*num_ulocks;
2840 /* Data now points at the beginning of the list
2841 of smb_lkrng structs */
2842 for(i = 0; i < (int)num_locks; i++) {
2843 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2844 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2845 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
2846 break;
2849 /* If any of the above locks failed, then we must unlock
2850 all of the previous locks (X/Open spec). */
2851 if(i != num_locks && num_locks != 0) {
2852 for(; i >= 0; i--) {
2853 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2854 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2855 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
2857 return ERROR(eclass,ecode);
2860 outsize = set_message(outbuf,2,0,True);
2862 CVAL(outbuf,smb_vwv0) = smb_com2;
2863 SSVAL(outbuf,smb_vwv1,(outsize+chain_size)-4);
2865 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
2866 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
2868 chain_fnum = fnum;
2870 if (smb_com2 != 0xFF)
2871 outsize += chain_reply(smb_com2,inbuf,inbuf+smb_off2+4,
2872 outbuf,outbuf+outsize,
2873 length,bufsize);
2875 chain_fnum = -1;
2877 return(outsize);
2881 /****************************************************************************
2882 reply to a SMBreadbmpx (read block multiplex) request
2883 ****************************************************************************/
2884 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
2886 int cnum,fnum;
2887 int nread = -1;
2888 int total_read;
2889 char *data;
2890 int32 startpos;
2891 int outsize, mincount, maxcount;
2892 int max_per_packet;
2893 int tcount;
2894 int pad;
2896 /* this function doesn't seem to work - disable by default */
2897 if (!lp_readbmpx())
2898 return(ERROR(ERRSRV,ERRuseSTD));
2900 outsize = set_message(outbuf,8,0,True);
2902 cnum = SVAL(inbuf,smb_tid);
2903 fnum = GETFNUM(inbuf,smb_vwv0);
2905 CHECK_FNUM(fnum,cnum);
2906 CHECK_READ(fnum);
2907 CHECK_ERROR(fnum);
2909 startpos = IVAL(inbuf,smb_vwv1);
2910 maxcount = SVAL(inbuf,smb_vwv3);
2911 mincount = SVAL(inbuf,smb_vwv4);
2913 data = smb_buf(outbuf);
2914 pad = ((int)data)%4;
2915 if (pad) pad = 4 - pad;
2916 data += pad;
2918 max_per_packet = bufsize-(outsize+pad);
2919 tcount = maxcount;
2920 total_read = 0;
2922 if (is_locked(fnum,cnum,maxcount,startpos))
2923 return(ERROR(ERRDOS,ERRlock));
2927 int N = MIN(max_per_packet,tcount-total_read);
2929 nread = read_file(fnum,data,startpos,N,N,-1,False);
2931 if (nread <= 0) nread = 0;
2933 if (nread < N)
2934 tcount = total_read + nread;
2936 set_message(outbuf,8,nread,False);
2937 SIVAL(outbuf,smb_vwv0,startpos);
2938 SSVAL(outbuf,smb_vwv2,tcount);
2939 SSVAL(outbuf,smb_vwv6,nread);
2940 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
2942 send_smb(Client,outbuf);
2944 total_read += nread;
2945 startpos += nread;
2947 while (total_read < tcount);
2949 return(-1);
2953 /****************************************************************************
2954 reply to a SMBwritebmpx (write block multiplex primary) request
2955 ****************************************************************************/
2956 int reply_writebmpx(char *inbuf,char *outbuf)
2958 int cnum,numtowrite,fnum;
2959 int nwritten = -1;
2960 int outsize = 0;
2961 int32 startpos;
2962 int tcount, write_through, smb_doff;
2963 char *data;
2965 cnum = SVAL(inbuf,smb_tid);
2966 fnum = GETFNUM(inbuf,smb_vwv0);
2968 CHECK_FNUM(fnum,cnum);
2969 CHECK_WRITE(fnum);
2970 CHECK_ERROR(fnum);
2972 tcount = SVAL(inbuf,smb_vwv1);
2973 startpos = IVAL(inbuf,smb_vwv3);
2974 write_through = BITSETW(inbuf+smb_vwv7,0);
2975 numtowrite = SVAL(inbuf,smb_vwv10);
2976 smb_doff = SVAL(inbuf,smb_vwv11);
2978 data = smb_base(inbuf) + smb_doff;
2980 /* If this fails we need to send an SMBwriteC response,
2981 not an SMBwritebmpx - set this up now so we don't forget */
2982 CVAL(outbuf,smb_com) = SMBwritec;
2984 if (is_locked(fnum,cnum,tcount,startpos))
2985 return(ERROR(ERRDOS,ERRlock));
2987 seek_file(fnum,startpos);
2988 nwritten = write_file(fnum,data,numtowrite);
2990 if(lp_syncalways(SNUM(cnum)) || write_through)
2991 sync_file(fnum);
2993 if(nwritten < numtowrite)
2994 return(UNIXERROR(ERRHRD,ERRdiskfull));
2996 /* If the maximum to be written to this file
2997 is greater than what we just wrote then set
2998 up a secondary struct to be attached to this
2999 fd, we will use this to cache error messages etc. */
3000 if(tcount > nwritten)
3002 write_bmpx_struct *wbms;
3003 if(Files[fnum].wbmpx_ptr != NULL)
3004 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3005 else
3006 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3007 if(!wbms)
3009 DEBUG(0,("Out of memory in reply_readmpx\n"));
3010 return(ERROR(ERRSRV,ERRnoresource));
3012 wbms->wr_mode = write_through;
3013 wbms->wr_discard = False; /* No errors yet */
3014 wbms->wr_total_written = nwritten;
3015 wbms->wr_errclass = 0;
3016 wbms->wr_error = 0;
3017 Files[fnum].wbmpx_ptr = wbms;
3020 /* We are returning successfully, set the message type back to
3021 SMBwritebmpx */
3022 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3024 outsize = set_message(outbuf,1,0,True);
3026 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3028 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3029 timestring(),fnum,cnum,numtowrite,nwritten));
3031 if (write_through && tcount==nwritten) {
3032 /* we need to send both a primary and a secondary response */
3033 smb_setlen(outbuf,outsize - 4);
3034 send_smb(Client,outbuf);
3036 /* now the secondary */
3037 outsize = set_message(outbuf,1,0,True);
3038 CVAL(outbuf,smb_com) = SMBwritec;
3039 SSVAL(outbuf,smb_vwv0,nwritten);
3042 return(outsize);
3046 /****************************************************************************
3047 reply to a SMBwritebs (write block multiplex secondary) request
3048 ****************************************************************************/
3049 int reply_writebs(char *inbuf,char *outbuf)
3051 int cnum,numtowrite,fnum;
3052 int nwritten = -1;
3053 int outsize = 0;
3054 int32 startpos;
3055 int tcount, write_through, smb_doff;
3056 char *data;
3057 write_bmpx_struct *wbms;
3058 BOOL send_response = False;
3060 cnum = SVAL(inbuf,smb_tid);
3061 fnum = GETFNUM(inbuf,smb_vwv0);
3062 CHECK_FNUM(fnum,cnum);
3063 CHECK_WRITE(fnum);
3065 tcount = SVAL(inbuf,smb_vwv1);
3066 startpos = IVAL(inbuf,smb_vwv2);
3067 numtowrite = SVAL(inbuf,smb_vwv6);
3068 smb_doff = SVAL(inbuf,smb_vwv7);
3070 data = smb_base(inbuf) + smb_doff;
3072 /* We need to send an SMBwriteC response, not an SMBwritebs */
3073 CVAL(outbuf,smb_com) = SMBwritec;
3075 /* This fd should have an auxiliary struct attached,
3076 check that it does */
3077 wbms = Files[fnum].wbmpx_ptr;
3078 if(!wbms) return(-1);
3080 /* If write through is set we can return errors, else we must
3081 cache them */
3082 write_through = wbms->wr_mode;
3084 /* Check for an earlier error */
3085 if(wbms->wr_discard)
3086 return -1; /* Just discard the packet */
3088 seek_file(fnum,startpos);
3089 nwritten = write_file(fnum,data,numtowrite);
3091 if(lp_syncalways(SNUM(cnum)) || write_through)
3092 sync_file(fnum);
3094 if (nwritten < numtowrite)
3096 if(write_through) {
3097 /* We are returning an error - we can delete the aux struct */
3098 if (wbms) free((char *)wbms);
3099 Files[fnum].wbmpx_ptr = NULL;
3100 return(ERROR(ERRHRD,ERRdiskfull));
3102 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3105 /* Increment the total written, if this matches tcount
3106 we can discard the auxiliary struct (hurrah !) and return a writeC */
3107 wbms->wr_total_written += nwritten;
3108 if(wbms->wr_total_written >= tcount)
3110 if (write_through) {
3111 outsize = set_message(outbuf,1,0,True);
3112 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3113 send_response = True;
3116 free((char *)wbms);
3117 Files[fnum].wbmpx_ptr = NULL;
3120 if(send_response)
3121 return(outsize);
3123 return(-1);
3127 /****************************************************************************
3128 reply to a SMBsetattrE
3129 ****************************************************************************/
3130 int reply_setattrE(char *inbuf,char *outbuf)
3132 int cnum,fnum;
3133 struct utimbuf unix_times;
3134 int outsize = 0;
3136 outsize = set_message(outbuf,0,0,True);
3138 cnum = SVAL(inbuf,smb_tid);
3139 fnum = GETFNUM(inbuf,smb_vwv0);
3141 CHECK_FNUM(fnum,cnum);
3142 CHECK_ERROR(fnum);
3144 /* Convert the DOS times into unix times. Ignore create
3145 time as UNIX can't set this.
3147 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3148 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3150 /* Set the date on this file */
3151 if(sys_utime(Files[fnum].name, &unix_times))
3152 return(ERROR(ERRDOS,ERRnoaccess));
3154 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3156 return(outsize);
3160 /****************************************************************************
3161 reply to a SMBgetattrE
3162 ****************************************************************************/
3163 int reply_getattrE(char *inbuf,char *outbuf)
3165 int cnum,fnum;
3166 struct stat sbuf;
3167 int outsize = 0;
3168 int mode;
3170 outsize = set_message(outbuf,11,0,True);
3172 cnum = SVAL(inbuf,smb_tid);
3173 fnum = GETFNUM(inbuf,smb_vwv0);
3175 CHECK_FNUM(fnum,cnum);
3176 CHECK_ERROR(fnum);
3178 /* Do an fstat on this file */
3179 if(fstat(Files[fnum].fd, &sbuf))
3180 return(UNIXERROR(ERRDOS,ERRnoaccess));
3182 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3184 /* Convert the times into dos times. Set create
3185 date to be last modify date as UNIX doesn't save
3186 this */
3187 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3188 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3189 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3190 if (mode & aDIR)
3192 SIVAL(outbuf,smb_vwv6,0);
3193 SIVAL(outbuf,smb_vwv8,0);
3195 else
3197 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3198 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3200 SSVAL(outbuf,smb_vwv10, mode);
3202 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3204 return(outsize);