Makefile: Added quoata changes for Linux from Thorvald Natvig
[Samba/gbeck.git] / source / smbd / reply.c
blob8af4536c1959ccbc67d9809d8bde5535a78a1f77
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1997
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
27 #include "includes.h"
28 #include "trans2.h"
30 /* look in server.c for some explanation of these variables */
31 extern int Protocol;
32 extern int DEBUGLEVEL;
33 extern int max_send;
34 extern int max_recv;
35 extern int chain_fnum;
36 extern char magic_char;
37 extern connection_struct Connections[];
38 extern files_struct Files[];
39 extern BOOL case_sensitive;
40 extern BOOL case_preserve;
41 extern BOOL short_case_preserve;
42 extern pstring sesssetup_user;
43 extern fstring myworkgroup;
44 extern int Client;
46 /* this macro should always be used to extract an fnum (smb_fid) from
47 a packet to ensure chaining works correctly */
48 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
51 /****************************************************************************
52 reply to an special message
53 ****************************************************************************/
54 int reply_special(char *inbuf,char *outbuf)
56 int outsize = 4;
57 int msg_type = CVAL(inbuf,0);
58 int msg_flags = CVAL(inbuf,1);
59 pstring name1,name2;
60 extern fstring remote_machine;
61 extern fstring local_machine;
62 char *p;
64 *name1 = *name2 = 0;
66 smb_setlen(outbuf,0);
68 switch (msg_type)
70 case 0x81: /* session request */
71 CVAL(outbuf,0) = 0x82;
72 CVAL(outbuf,3) = 0;
73 if (name_len(inbuf+4) > 50)
75 DEBUG(0,("Invalid name length in session request\n"));
76 return(0);
78 name_extract(inbuf,4,name1);
79 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
80 DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2));
82 strcpy(remote_machine,name2);
83 trim_string(remote_machine," "," ");
84 p = strchr(remote_machine,' ');
85 strlower(remote_machine);
86 if (p) *p = 0;
88 strcpy(local_machine,name1);
89 trim_string(local_machine," "," ");
90 p = strchr(local_machine,' ');
91 strlower(local_machine);
92 if (p) *p = 0;
94 add_session_user(remote_machine);
96 reload_services(True);
97 reopen_logs();
99 break;
100 case 0x85: /* session keepalive */
101 default:
102 return(0);
105 DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags));
107 return(outsize);
111 /*******************************************************************
112 work out what error to give to a failed connection
113 ********************************************************************/
114 static int connection_error(char *inbuf,char *outbuf,int connection_num)
116 switch (connection_num)
118 case -8:
119 return(ERROR(ERRSRV,ERRnoresource));
120 case -7:
121 return(ERROR(ERRSRV,ERRbaduid));
122 case -6:
123 return(ERROR(ERRSRV,ERRinvdevice));
124 case -5:
125 return(ERROR(ERRSRV,ERRinvnetname));
126 case -4:
127 return(ERROR(ERRSRV,ERRaccess));
128 case -3:
129 return(ERROR(ERRDOS,ERRnoipc));
130 case -2:
131 return(ERROR(ERRSRV,ERRinvnetname));
133 return(ERROR(ERRSRV,ERRbadpw));
138 /****************************************************************************
139 parse a share descriptor string
140 ****************************************************************************/
141 static void parse_connect(char *p,char *service,char *user,
142 char *password,int *pwlen,char *dev)
144 char *p2;
146 DEBUG(4,("parsing connect string %s\n",p));
148 p2 = strrchr(p,'\\');
149 if (p2 == NULL)
150 strcpy(service,p);
151 else
152 strcpy(service,p2+1);
154 p += strlen(p) + 2;
156 strcpy(password,p);
157 *pwlen = strlen(password);
159 p += strlen(p) + 2;
161 strcpy(dev,p);
163 *user = 0;
164 p = strchr(service,'%');
165 if (p != NULL)
167 *p = 0;
168 strcpy(user,p+1);
175 /****************************************************************************
176 reply to a tcon
177 ****************************************************************************/
178 int reply_tcon(char *inbuf,char *outbuf)
180 pstring service;
181 pstring user;
182 pstring password;
183 pstring dev;
184 int connection_num;
185 int outsize = 0;
186 uint16 vuid = SVAL(inbuf,smb_uid);
187 int pwlen=0;
189 *service = *user = *password = *dev = 0;
191 parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
193 connection_num = make_connection(service,user,password,pwlen,dev,vuid);
195 if (connection_num < 0)
196 return(connection_error(inbuf,outbuf,connection_num));
198 outsize = set_message(outbuf,2,0,True);
199 SSVAL(outbuf,smb_vwv0,max_recv);
200 SSVAL(outbuf,smb_vwv1,connection_num);
201 SSVAL(outbuf,smb_tid,connection_num);
203 DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
205 return(outsize);
209 /****************************************************************************
210 reply to a tcon and X
211 ****************************************************************************/
212 int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
214 pstring service;
215 pstring user;
216 pstring password;
217 pstring devicename;
218 int connection_num;
219 uint16 vuid = SVAL(inbuf,smb_uid);
220 int passlen = SVAL(inbuf,smb_vwv3);
221 BOOL doencrypt = SMBENCRYPT();
223 *service = *user = *password = *devicename = 0;
225 /* we might have to close an old one */
226 if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0)
227 close_cnum(SVAL(inbuf,smb_tid),vuid);
230 char *path;
231 char *p;
232 memcpy(password,smb_buf(inbuf),passlen);
233 password[passlen]=0;
234 path = smb_buf(inbuf) + passlen;
236 if (!doencrypt || passlen != 24) {
237 if (strequal(password," "))
238 *password = 0;
239 passlen = strlen(password);
242 DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen));
243 strcpy(service,path+2);
244 p = strchr(service,'\\');
245 if (!p)
246 return(ERROR(ERRSRV,ERRinvnetname));
247 *p = 0;
248 strcpy(service,p+1);
249 p = strchr(service,'%');
250 if (p)
252 *p++ = 0;
253 strcpy(user,p);
255 StrnCpy(devicename,path + strlen(path) + 1,6);
256 DEBUG(4,("Got device type %s\n",devicename));
259 connection_num = make_connection(service,user,password,passlen,devicename,vuid);
261 if (connection_num < 0)
262 return(connection_error(inbuf,outbuf,connection_num));
264 set_message(outbuf,2,strlen(devicename)+1,True);
266 DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num));
268 /* set the incoming and outgoing tid to the just created one */
269 SSVAL(inbuf,smb_tid,connection_num);
270 SSVAL(outbuf,smb_tid,connection_num);
272 strcpy(smb_buf(outbuf),devicename);
274 return chain_reply(inbuf,outbuf,length,bufsize);
278 /****************************************************************************
279 reply to an unknown type
280 ****************************************************************************/
281 int reply_unknown(char *inbuf,char *outbuf)
283 int cnum;
284 int type;
285 cnum = SVAL(inbuf,smb_tid);
286 type = CVAL(inbuf,smb_com);
288 DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n",
289 timestring(),
290 smb_fn_name(type),
291 cnum,type,type));
293 return(ERROR(ERRSRV,ERRunknownsmb));
297 /****************************************************************************
298 reply to an ioctl
299 ****************************************************************************/
300 int reply_ioctl(char *inbuf,char *outbuf)
302 DEBUG(3,("ignoring ioctl\n"));
303 #if 0
304 /* we just say it succeeds and hope its all OK.
305 some day it would be nice to interpret them individually */
306 return set_message(outbuf,1,0,True);
307 #else
308 return(ERROR(ERRSRV,ERRnosupport));
309 #endif
313 /****************************************************************************
314 reply to a session setup command
315 ****************************************************************************/
316 int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
318 uint16 sess_vuid;
319 int gid;
320 int uid;
321 int smb_bufsize;
322 int smb_mpxmax;
323 int smb_vc_num;
324 uint32 smb_sesskey;
325 int smb_apasslen = 0;
326 pstring smb_apasswd;
327 int smb_ntpasslen = 0;
328 pstring smb_ntpasswd;
329 BOOL valid_nt_password = False;
330 pstring user;
331 BOOL guest=False;
332 BOOL computer_id=False;
333 static BOOL done_sesssetup = False;
334 BOOL doencrypt = SMBENCRYPT();
336 *smb_apasswd = 0;
338 smb_bufsize = SVAL(inbuf,smb_vwv2);
339 smb_mpxmax = SVAL(inbuf,smb_vwv3);
340 smb_vc_num = SVAL(inbuf,smb_vwv4);
341 smb_sesskey = IVAL(inbuf,smb_vwv5);
343 if (Protocol < PROTOCOL_NT1) {
344 smb_apasslen = SVAL(inbuf,smb_vwv7);
345 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
346 StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1);
348 if (lp_security() != SEC_SERVER && !doencrypt)
349 smb_apasslen = strlen(smb_apasswd);
350 } else {
351 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
352 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
353 char *p = smb_buf(inbuf);
355 if (passlen1 != 24 && passlen2 != 24)
356 doencrypt = False;
358 if(doencrypt) {
359 /* Save the lanman2 password and the NT md4 password. */
360 smb_apasslen = passlen1;
361 memcpy(smb_apasswd,p,smb_apasslen);
362 smb_ntpasslen = passlen2;
363 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
364 } else {
365 /* both Win95 and WinNT stuff up the password lengths for
366 non-encrypting systems. Uggh.
368 if passlen1==24 its a win95 system, and its setting the
369 password length incorrectly. Luckily it still works with the
370 default code because Win95 will null terminate the password
371 anyway
373 if passlen1>0 and passlen2>0 then maybe its a NT box and its
374 setting passlen2 to some random value which really stuffs
375 things up. we need to fix that one. */
376 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
377 passlen2 != 1) {
378 passlen2 = 0;
380 /* we use the first password that they gave */
381 smb_apasslen = passlen1;
382 StrnCpy(smb_apasswd,p,smb_apasslen);
384 /* trim the password */
385 smb_apasslen = strlen(smb_apasswd);
387 /* wfwg sometimes uses a space instead of a null */
388 if (strequal(smb_apasswd," ")) {
389 smb_apasslen = 0;
390 *smb_apasswd = 0;
394 p += passlen1 + passlen2;
395 strcpy(user,p); p = skip_string(p,1);
396 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
397 p,skip_string(p,1),skip_string(p,2)));
401 DEBUG(3,("sesssetupX:name=[%s]\n",user));
403 /* If name ends in $ then I think it's asking about whether a */
404 /* computer with that name (minus the $) has access. For now */
405 /* say yes to everything ending in $. */
406 if (user[strlen(user) - 1] == '$') {
407 computer_id = True;
408 user[strlen(user) - 1] = '\0';
412 if (!*user)
413 strcpy(user,lp_guestaccount(-1));
415 strlower(user);
417 strcpy(sesssetup_user,user);
419 reload_services(True);
421 add_session_user(user);
424 if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
425 !check_hosts_equiv(user))
428 if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
429 guest = True;
431 /* now check if it's a valid username/password */
432 /* If an NT password was supplied try and validate with that
433 first. This is superior as the passwords are mixed case 128 length unicode */
434 if(smb_ntpasslen && !guest)
436 if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
437 DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
438 else
439 valid_nt_password = True;
441 if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
443 if (!computer_id && lp_security() >= SEC_USER) {
444 #if (GUEST_SESSSETUP == 0)
445 return(ERROR(ERRSRV,ERRbadpw));
446 #endif
447 #if (GUEST_SESSSETUP == 1)
448 if (Get_Pwnam(user,True))
449 return(ERROR(ERRSRV,ERRbadpw));
450 #endif
452 if (*smb_apasswd || !Get_Pwnam(user,True))
453 strcpy(user,lp_guestaccount(-1));
454 DEBUG(3,("Registered username %s for guest access\n",user));
455 guest = True;
459 if (!Get_Pwnam(user,True)) {
460 DEBUG(3,("No such user %s - using guest account\n",user));
461 strcpy(user,lp_guestaccount(-1));
462 guest = True;
465 if (!strequal(user,lp_guestaccount(-1)) &&
466 lp_servicenumber(user) < 0)
468 int homes = lp_servicenumber(HOMES_NAME);
469 char *home = get_home_dir(user);
470 if (homes >= 0 && home)
471 lp_add_home(user,homes,home);
475 /* it's ok - setup a reply */
476 if (Protocol < PROTOCOL_NT1) {
477 set_message(outbuf,3,0,True);
478 } else {
479 char *p;
480 set_message(outbuf,3,3,True);
481 p = smb_buf(outbuf);
482 strcpy(p,"Unix"); p = skip_string(p,1);
483 strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
484 strcpy(p,myworkgroup); p = skip_string(p,1);
485 set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
486 /* perhaps grab OS version here?? */
489 /* Set the correct uid in the outgoing and incoming packets
490 We will use this on future requests to determine which
491 user we should become.
494 struct passwd *pw = Get_Pwnam(user,False);
495 if (!pw) {
496 DEBUG(1,("Username %s is invalid on this system\n",user));
497 return(ERROR(ERRSRV,ERRbadpw));
499 gid = pw->pw_gid;
500 uid = pw->pw_uid;
503 if (guest && !computer_id)
504 SSVAL(outbuf,smb_vwv2,1);
506 /* register the name and uid as being validated, so further connections
507 to a uid can get through without a password, on the same VC */
508 sess_vuid = register_vuid(uid,gid,user,guest);
510 SSVAL(outbuf,smb_uid,sess_vuid);
511 SSVAL(inbuf,smb_uid,sess_vuid);
513 if (!done_sesssetup)
514 max_send = MIN(max_send,smb_bufsize);
516 DEBUG(1,(" Client requested max send size of %d\n", max_send));
518 done_sesssetup = True;
520 return chain_reply(inbuf,outbuf,length,bufsize);
524 /****************************************************************************
525 reply to a chkpth
526 ****************************************************************************/
527 int reply_chkpth(char *inbuf,char *outbuf)
529 int outsize = 0;
530 int cnum,mode;
531 pstring name;
532 BOOL ok = False;
534 cnum = SVAL(inbuf,smb_tid);
536 strcpy(name,smb_buf(inbuf) + 1);
537 unix_convert(name,cnum,0);
539 mode = SVAL(inbuf,smb_vwv0);
541 if (check_name(name,cnum))
542 ok = directory_exist(name,NULL);
544 if (!ok)
545 return(ERROR(ERRDOS,ERRbadpath));
547 outsize = set_message(outbuf,0,0,True);
549 DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode));
551 return(outsize);
555 /****************************************************************************
556 reply to a getatr
557 ****************************************************************************/
558 int reply_getatr(char *inbuf,char *outbuf)
560 pstring fname;
561 int cnum;
562 int outsize = 0;
563 struct stat sbuf;
564 BOOL ok = False;
565 int mode=0;
566 uint32 size=0;
567 time_t mtime=0;
569 cnum = SVAL(inbuf,smb_tid);
571 strcpy(fname,smb_buf(inbuf) + 1);
572 unix_convert(fname,cnum,0);
574 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
575 under WfWg - weird! */
576 if (! (*fname))
578 mode = aHIDDEN | aDIR;
579 if (!CAN_WRITE(cnum)) mode |= aRONLY;
580 size = 0;
581 mtime = 0;
582 ok = True;
584 else
585 if (check_name(fname,cnum))
587 if (sys_stat(fname,&sbuf) == 0)
589 mode = dos_mode(cnum,fname,&sbuf);
590 size = sbuf.st_size;
591 mtime = sbuf.st_mtime;
592 if (mode & aDIR)
593 size = 0;
594 ok = True;
596 else
597 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
600 if (!ok)
601 return(UNIXERROR(ERRDOS,ERRbadfile));
603 outsize = set_message(outbuf,10,0,True);
605 SSVAL(outbuf,smb_vwv0,mode);
606 put_dos_date3(outbuf,smb_vwv1,mtime);
607 SIVAL(outbuf,smb_vwv3,size);
609 if (Protocol >= PROTOCOL_NT1) {
610 char *p = strrchr(fname,'/');
611 uint16 flg2 = SVAL(outbuf,smb_flg2);
612 if (!p) p = fname;
613 if (!is_8_3(fname, True))
614 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
617 DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size));
619 return(outsize);
623 /****************************************************************************
624 reply to a setatr
625 ****************************************************************************/
626 int reply_setatr(char *inbuf,char *outbuf)
628 pstring fname;
629 int cnum;
630 int outsize = 0;
631 BOOL ok=False;
632 int mode;
633 time_t mtime;
635 cnum = SVAL(inbuf,smb_tid);
637 strcpy(fname,smb_buf(inbuf) + 1);
638 unix_convert(fname,cnum,0);
640 mode = SVAL(inbuf,smb_vwv0);
641 mtime = make_unix_date3(inbuf+smb_vwv1);
643 if (directory_exist(fname,NULL))
644 mode |= aDIR;
645 if (check_name(fname,cnum))
646 ok = (dos_chmod(cnum,fname,mode,NULL) == 0);
647 if (ok)
648 ok = set_filetime(fname,mtime);
650 if (!ok)
651 return(UNIXERROR(ERRDOS,ERRnoaccess));
653 outsize = set_message(outbuf,0,0,True);
655 DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode));
657 return(outsize);
661 /****************************************************************************
662 reply to a dskattr
663 ****************************************************************************/
664 int reply_dskattr(char *inbuf,char *outbuf)
666 int cnum;
667 int outsize = 0;
668 int dfree,dsize,bsize;
670 cnum = SVAL(inbuf,smb_tid);
672 sys_disk_free(".",&bsize,&dfree,&dsize);
674 outsize = set_message(outbuf,5,0,True);
676 SSVAL(outbuf,smb_vwv0,dsize);
677 SSVAL(outbuf,smb_vwv1,bsize/512);
678 SSVAL(outbuf,smb_vwv2,512);
679 SSVAL(outbuf,smb_vwv3,dfree);
681 DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree));
683 return(outsize);
687 /****************************************************************************
688 reply to a search
689 Can be called from SMBsearch, SMBffirst or SMBfunique.
690 ****************************************************************************/
691 int reply_search(char *inbuf,char *outbuf)
693 pstring mask;
694 pstring directory;
695 pstring fname;
696 int size,mode;
697 time_t date;
698 int dirtype;
699 int cnum;
700 int outsize = 0;
701 int numentries = 0;
702 BOOL finished = False;
703 int maxentries;
704 int i;
705 char *p;
706 BOOL ok = False;
707 int status_len;
708 char *path;
709 char status[21];
710 int dptr_num= -1;
711 BOOL check_descend = False;
712 BOOL expect_close = False;
713 BOOL can_open = True;
715 *mask = *directory = *fname = 0;
717 /* If we were called as SMBffirst then we must expect close. */
718 if(CVAL(inbuf,smb_com) == SMBffirst)
719 expect_close = True;
721 cnum = SVAL(inbuf,smb_tid);
723 outsize = set_message(outbuf,1,3,True);
724 maxentries = SVAL(inbuf,smb_vwv0);
725 dirtype = SVAL(inbuf,smb_vwv1);
726 path = smb_buf(inbuf) + 1;
727 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
730 /* dirtype &= ~aDIR; */
732 DEBUG(5,("path=%s status_len=%d\n",path,status_len));
735 if (status_len == 0)
737 pstring dir2;
739 strcpy(directory,smb_buf(inbuf)+1);
740 strcpy(dir2,smb_buf(inbuf)+1);
741 unix_convert(directory,cnum,0);
742 unix_format(dir2);
744 if (!check_name(directory,cnum))
745 can_open = False;
747 p = strrchr(dir2,'/');
748 if (p == NULL)
749 {strcpy(mask,dir2);*dir2 = 0;}
750 else
751 {*p = 0;strcpy(mask,p+1);}
753 p = strrchr(directory,'/');
754 if (!p)
755 *directory = 0;
756 else
757 *p = 0;
759 if (strlen(directory) == 0)
760 strcpy(directory,"./");
761 bzero(status,21);
762 CVAL(status,0) = dirtype;
764 else
766 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
767 memcpy(mask,status+1,11);
768 mask[11] = 0;
769 dirtype = CVAL(status,0) & 0x1F;
770 Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num);
771 if (!Connections[cnum].dirptr)
772 goto SearchEmpty;
773 string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
774 if (!case_sensitive)
775 strnorm(mask);
778 /* turn strings of spaces into a . */
780 trim_string(mask,NULL," ");
781 if ((p = strrchr(mask,' ')))
783 fstring ext;
784 strcpy(ext,p+1);
785 *p = 0;
786 trim_string(mask,NULL," ");
787 strcat(mask,".");
788 strcat(mask,ext);
793 for (p=mask; *p; p++)
795 if (*p != '?' && *p != '*' && !isdoschar(*p))
797 DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
798 *p = '?';
803 if (!strchr(mask,'.') && strlen(mask)>8)
805 fstring tmp;
806 strcpy(tmp,&mask[8]);
807 mask[8] = '.';
808 mask[9] = 0;
809 strcat(mask,tmp);
812 DEBUG(5,("mask=%s directory=%s\n",mask,directory));
814 if (can_open)
816 p = smb_buf(outbuf) + 3;
818 ok = True;
820 if (status_len == 0)
822 dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid));
823 if (dptr_num < 0)
824 return(ERROR(ERRDOS,ERRnofids));
827 DEBUG(4,("dptr_num is %d\n",dptr_num));
829 if (ok)
831 if ((dirtype&0x1F) == aVOLID)
833 memcpy(p,status,21);
834 make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
835 dptr_fill(p+12,dptr_num);
836 if (dptr_zero(p+12) && (status_len==0))
837 numentries = 1;
838 else
839 numentries = 0;
840 p += DIR_STRUCT_SIZE;
842 else
844 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum))));
845 if (in_list(Connections[cnum].dirpath,
846 lp_dontdescend(SNUM(cnum)),True))
847 check_descend = True;
849 for (i=numentries;(i<maxentries) && !finished;i++)
851 finished =
852 !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend);
853 if (!finished)
855 memcpy(p,status,21);
856 make_dir_struct(p,mask,fname,size,mode,date);
857 dptr_fill(p+12,dptr_num);
858 numentries++;
860 p += DIR_STRUCT_SIZE;
867 SearchEmpty:
869 if (numentries == 0 || !ok)
871 CVAL(outbuf,smb_rcls) = ERRDOS;
872 SSVAL(outbuf,smb_err,ERRnofiles);
875 /* If we were called as SMBffirst with smb_search_id == NULL
876 and no entries were found then return error and close dirptr
877 (X/Open spec) */
879 if(ok && expect_close && numentries == 0 && status_len == 0)
881 CVAL(outbuf,smb_rcls) = ERRDOS;
882 SSVAL(outbuf,smb_err,ERRnofiles);
883 /* Also close the dptr - we know it's gone */
884 dptr_close(dptr_num);
887 /* If we were called as SMBfunique, then we can close the dirptr now ! */
888 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
889 dptr_close(dptr_num);
891 SSVAL(outbuf,smb_vwv0,numentries);
892 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
893 CVAL(smb_buf(outbuf),0) = 5;
894 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
896 if (Protocol >= PROTOCOL_NT1) {
897 uint16 flg2 = SVAL(outbuf,smb_flg2);
898 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
901 outsize += DIR_STRUCT_SIZE*numentries;
902 smb_setlen(outbuf,outsize - 4);
904 if ((! *directory) && dptr_path(dptr_num))
905 sprintf(directory,"(%s)",dptr_path(dptr_num));
907 DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n",
908 timestring(),
909 smb_fn_name(CVAL(inbuf,smb_com)),
910 mask,directory,cnum,dirtype,numentries,maxentries));
912 return(outsize);
916 /****************************************************************************
917 reply to a fclose (stop directory search)
918 ****************************************************************************/
919 int reply_fclose(char *inbuf,char *outbuf)
921 int cnum;
922 int outsize = 0;
923 int status_len;
924 char *path;
925 char status[21];
926 int dptr_num= -1;
928 cnum = SVAL(inbuf,smb_tid);
930 outsize = set_message(outbuf,1,0,True);
931 path = smb_buf(inbuf) + 1;
932 status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
935 if (status_len == 0)
936 return(ERROR(ERRSRV,ERRsrverror));
938 memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
940 if(dptr_fetch(status+12,&dptr_num)) {
941 /* Close the dptr - we know it's gone */
942 dptr_close(dptr_num);
945 SSVAL(outbuf,smb_vwv0,0);
947 DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum));
949 return(outsize);
953 /****************************************************************************
954 reply to an open
955 ****************************************************************************/
956 int reply_open(char *inbuf,char *outbuf)
958 pstring fname;
959 int cnum;
960 int fnum = -1;
961 int outsize = 0;
962 int fmode=0;
963 int share_mode;
964 int size = 0;
965 time_t mtime=0;
966 int unixmode;
967 int rmode=0;
968 struct stat sbuf;
970 cnum = SVAL(inbuf,smb_tid);
972 share_mode = SVAL(inbuf,smb_vwv0);
974 strcpy(fname,smb_buf(inbuf)+1);
975 unix_convert(fname,cnum,0);
977 fnum = find_free_file();
978 if (fnum < 0)
979 return(ERROR(ERRSRV,ERRnofids));
981 if (!check_name(fname,cnum))
982 return(UNIXERROR(ERRDOS,ERRnoaccess));
984 unixmode = unix_mode(cnum,aARCH);
986 open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
988 if (!Files[fnum].open)
989 return(UNIXERROR(ERRDOS,ERRnoaccess));
991 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
992 close_file(fnum);
993 return(ERROR(ERRDOS,ERRnoaccess));
996 size = sbuf.st_size;
997 fmode = dos_mode(cnum,fname,&sbuf);
998 mtime = sbuf.st_mtime;
1000 if (fmode & aDIR) {
1001 DEBUG(3,("attempt to open a directory %s\n",fname));
1002 close_file(fnum);
1003 return(ERROR(ERRDOS,ERRnoaccess));
1006 outsize = set_message(outbuf,7,0,True);
1007 SSVAL(outbuf,smb_vwv0,fnum);
1008 SSVAL(outbuf,smb_vwv1,fmode);
1009 put_dos_date3(outbuf,smb_vwv2,mtime);
1010 SIVAL(outbuf,smb_vwv4,size);
1011 SSVAL(outbuf,smb_vwv6,rmode);
1013 if (lp_fake_oplocks(SNUM(cnum))) {
1014 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1017 return(outsize);
1021 /****************************************************************************
1022 reply to an open and X
1023 ****************************************************************************/
1024 int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1026 pstring fname;
1027 int cnum = SVAL(inbuf,smb_tid);
1028 int fnum = -1;
1029 int openmode = 0;
1030 int smb_mode = SVAL(inbuf,smb_vwv3);
1031 int smb_attr = SVAL(inbuf,smb_vwv5);
1032 BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
1033 #if 0
1034 int open_flags = SVAL(inbuf,smb_vwv2);
1035 int smb_sattr = SVAL(inbuf,smb_vwv4);
1036 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1037 #endif
1038 int smb_ofun = SVAL(inbuf,smb_vwv8);
1039 int unixmode;
1040 int size=0,fmode=0,mtime=0,rmode=0;
1041 struct stat sbuf;
1042 int smb_action = 0;
1044 /* If it's an IPC, pass off the pipe handler. */
1045 if (IS_IPC(cnum))
1046 return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize);
1048 /* XXXX we need to handle passed times, sattr and flags */
1050 strcpy(fname,smb_buf(inbuf));
1051 unix_convert(fname,cnum,0);
1053 /* now add create and trunc bits */
1054 if (smb_ofun & 0x10)
1055 openmode |= O_CREAT;
1056 if ((smb_ofun & 0x3) == 2)
1057 openmode |= O_TRUNC;
1059 fnum = find_free_file();
1060 if (fnum < 0)
1061 return(ERROR(ERRSRV,ERRnofids));
1063 if (!check_name(fname,cnum))
1064 return(UNIXERROR(ERRDOS,ERRnoaccess));
1066 unixmode = unix_mode(cnum,smb_attr | aARCH);
1068 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
1069 &rmode,&smb_action);
1071 if (!Files[fnum].open)
1072 return(UNIXERROR(ERRDOS,ERRnoaccess));
1074 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1075 close_file(fnum);
1076 return(ERROR(ERRDOS,ERRnoaccess));
1079 size = sbuf.st_size;
1080 fmode = dos_mode(cnum,fname,&sbuf);
1081 mtime = sbuf.st_mtime;
1082 if (fmode & aDIR) {
1083 close_file(fnum);
1084 return(ERROR(ERRDOS,ERRnoaccess));
1087 if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
1088 smb_action |= (1<<15);
1091 set_message(outbuf,15,0,True);
1092 SSVAL(outbuf,smb_vwv2,fnum);
1093 SSVAL(outbuf,smb_vwv3,fmode);
1094 put_dos_date3(outbuf,smb_vwv4,mtime);
1095 SIVAL(outbuf,smb_vwv6,size);
1096 SSVAL(outbuf,smb_vwv8,rmode);
1097 SSVAL(outbuf,smb_vwv11,smb_action);
1099 chain_fnum = fnum;
1101 return chain_reply(inbuf,outbuf,length,bufsize);
1105 /****************************************************************************
1106 reply to a SMBulogoffX
1107 ****************************************************************************/
1108 int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
1110 uint16 vuid = SVAL(inbuf,smb_uid);
1111 user_struct *vuser = get_valid_user_struct(vuid);
1113 if(vuser == 0) {
1114 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1117 /* in user level security we are supposed to close any files
1118 open by this user */
1119 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1120 int i;
1121 for (i=0;i<MAX_OPEN_FILES;i++)
1122 if (Files[i].uid == vuser->uid && Files[i].open) {
1123 close_file(i);
1127 invalidate_vuid(vuid);
1129 set_message(outbuf,2,0,True);
1131 DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid));
1133 return chain_reply(inbuf,outbuf,length,bufsize);
1137 /****************************************************************************
1138 reply to a mknew or a create
1139 ****************************************************************************/
1140 int reply_mknew(char *inbuf,char *outbuf)
1142 pstring fname;
1143 int cnum,com;
1144 int fnum = -1;
1145 int outsize = 0;
1146 int createmode;
1147 mode_t unixmode;
1148 int ofun = 0;
1150 com = SVAL(inbuf,smb_com);
1151 cnum = SVAL(inbuf,smb_tid);
1153 createmode = SVAL(inbuf,smb_vwv0);
1154 strcpy(fname,smb_buf(inbuf)+1);
1155 unix_convert(fname,cnum,0);
1157 if (createmode & aVOLID)
1159 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1162 unixmode = unix_mode(cnum,createmode);
1164 fnum = find_free_file();
1165 if (fnum < 0)
1166 return(ERROR(ERRSRV,ERRnofids));
1168 if (!check_name(fname,cnum))
1169 return(UNIXERROR(ERRDOS,ERRnoaccess));
1171 if(com == SMBmknew)
1173 /* We should fail if file exists. */
1174 ofun = 0x10;
1176 else
1178 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1179 ofun = 0x12;
1182 /* Open file in dos compatibility share mode. */
1183 open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL);
1185 if (!Files[fnum].open)
1186 return(UNIXERROR(ERRDOS,ERRnoaccess));
1188 outsize = set_message(outbuf,1,0,True);
1189 SSVAL(outbuf,smb_vwv0,fnum);
1191 if (lp_fake_oplocks(SNUM(cnum))) {
1192 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1195 DEBUG(2,("new file %s\n",fname));
1196 DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
1198 return(outsize);
1202 /****************************************************************************
1203 reply to a create temporary file
1204 ****************************************************************************/
1205 int reply_ctemp(char *inbuf,char *outbuf)
1207 pstring fname;
1208 pstring fname2;
1209 int cnum;
1210 int fnum = -1;
1211 int outsize = 0;
1212 int createmode;
1213 mode_t unixmode;
1215 cnum = SVAL(inbuf,smb_tid);
1216 createmode = SVAL(inbuf,smb_vwv0);
1217 sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
1218 unix_convert(fname,cnum,0);
1220 unixmode = unix_mode(cnum,createmode);
1222 fnum = find_free_file();
1223 if (fnum < 0)
1224 return(ERROR(ERRSRV,ERRnofids));
1226 if (!check_name(fname,cnum))
1227 return(UNIXERROR(ERRDOS,ERRnoaccess));
1229 strcpy(fname2,(char *)mktemp(fname));
1231 /* Open file in dos compatibility share mode. */
1232 /* We should fail if file exists. */
1233 open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL);
1235 if (!Files[fnum].open)
1236 return(UNIXERROR(ERRDOS,ERRnoaccess));
1238 outsize = set_message(outbuf,1,2 + strlen(fname2),True);
1239 SSVAL(outbuf,smb_vwv0,fnum);
1240 CVAL(smb_buf(outbuf),0) = 4;
1241 strcpy(smb_buf(outbuf) + 1,fname2);
1243 if (lp_fake_oplocks(SNUM(cnum))) {
1244 CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
1247 DEBUG(2,("created temp file %s\n",fname2));
1248 DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
1250 return(outsize);
1254 /*******************************************************************
1255 check if a user is allowed to delete a file
1256 ********************************************************************/
1257 static BOOL can_delete(char *fname,int cnum,int dirtype)
1259 struct stat sbuf;
1260 int fmode;
1262 if (!CAN_WRITE(cnum)) return(False);
1264 if (sys_lstat(fname,&sbuf) != 0) return(False);
1265 fmode = dos_mode(cnum,fname,&sbuf);
1266 if (fmode & aDIR) return(False);
1267 if (!lp_delete_readonly(SNUM(cnum))) {
1268 if (fmode & aRONLY) return(False);
1270 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1271 return(False);
1272 if (!check_file_sharing(cnum,fname)) return(False);
1273 return(True);
1276 /****************************************************************************
1277 reply to a unlink
1278 ****************************************************************************/
1279 int reply_unlink(char *inbuf,char *outbuf)
1281 int outsize = 0;
1282 pstring name;
1283 int cnum;
1284 int dirtype;
1285 pstring directory;
1286 pstring mask;
1287 char *p;
1288 int count=0;
1289 int error = ERRnoaccess;
1290 BOOL has_wild;
1291 BOOL exists=False;
1293 *directory = *mask = 0;
1295 cnum = SVAL(inbuf,smb_tid);
1296 dirtype = SVAL(inbuf,smb_vwv0);
1298 strcpy(name,smb_buf(inbuf) + 1);
1300 DEBUG(3,("reply_unlink : %s\n",name));
1302 unix_convert(name,cnum,0);
1304 p = strrchr(name,'/');
1305 if (!p) {
1306 strcpy(directory,"./");
1307 strcpy(mask,name);
1308 } else {
1309 *p = 0;
1310 strcpy(directory,name);
1311 strcpy(mask,p+1);
1314 if (is_mangled(mask))
1315 check_mangled_stack(mask);
1317 has_wild = strchr(mask,'*') || strchr(mask,'?');
1319 if (!has_wild) {
1320 strcat(directory,"/");
1321 strcat(directory,mask);
1322 if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++;
1323 if (!count) exists = file_exist(directory,NULL);
1324 } else {
1325 void *dirptr = NULL;
1326 char *dname;
1328 if (check_name(directory,cnum))
1329 dirptr = OpenDir(directory);
1331 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1332 the pattern matches against the long name, otherwise the short name
1333 We don't implement this yet XXXX
1336 if (dirptr)
1338 error = ERRbadfile;
1340 if (strequal(mask,"????????.???"))
1341 strcpy(mask,"*");
1343 while ((dname = ReadDirName(dirptr)))
1345 pstring fname;
1346 strcpy(fname,dname);
1348 if(!mask_match(fname, mask, case_sensitive, False)) continue;
1350 error = ERRnoaccess;
1351 sprintf(fname,"%s/%s",directory,dname);
1352 if (!can_delete(fname,cnum,dirtype)) continue;
1353 if (!sys_unlink(fname)) count++;
1354 DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
1356 CloseDir(dirptr);
1360 if (count == 0) {
1361 if (exists)
1362 return(ERROR(ERRDOS,error));
1363 else
1364 return(UNIXERROR(ERRDOS,error));
1367 outsize = set_message(outbuf,0,0,True);
1369 return(outsize);
1373 /****************************************************************************
1374 reply to a readbraw (core+ protocol)
1375 ****************************************************************************/
1376 int reply_readbraw(char *inbuf, char *outbuf)
1378 int cnum,maxcount,mincount,fnum;
1379 int nread = 0;
1380 int startpos;
1381 char *header = outbuf;
1382 int ret=0;
1383 int fd;
1384 char *fname;
1386 cnum = SVAL(inbuf,smb_tid);
1387 fnum = GETFNUM(inbuf,smb_vwv0);
1389 startpos = IVAL(inbuf,smb_vwv1);
1390 maxcount = SVAL(inbuf,smb_vwv3);
1391 mincount = SVAL(inbuf,smb_vwv4);
1393 /* ensure we don't overrun the packet size */
1394 maxcount = MIN(65535,maxcount);
1395 maxcount = MAX(mincount,maxcount);
1397 if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read)
1399 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum));
1400 _smb_setlen(header,0);
1401 transfer_file(0,Client,0,header,4,0);
1402 return(-1);
1404 else
1406 fd = Files[fnum].fd_ptr->fd;
1407 fname = Files[fnum].name;
1411 if (!is_locked(fnum,cnum,maxcount,startpos))
1413 int size = Files[fnum].size;
1414 int sizeneeded = startpos + maxcount;
1416 if (size < sizeneeded) {
1417 struct stat st;
1418 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0)
1419 size = st.st_size;
1420 if (!Files[fnum].can_write)
1421 Files[fnum].size = size;
1424 nread = MIN(maxcount,size - startpos);
1427 if (nread < mincount)
1428 nread = 0;
1430 DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n",
1431 timestring(),
1432 fnum,cnum,startpos,
1433 maxcount,mincount,nread));
1435 #if UNSAFE_READRAW
1437 int predict=0;
1438 _smb_setlen(header,nread);
1440 if (!Files[fnum].can_write)
1441 predict = read_predict(fd,startpos,header+4,NULL,nread);
1443 if ((nread-predict) > 0)
1444 seek_file(fnum,startpos + predict);
1446 ret = transfer_file(fd,Client,nread-predict,header,4+predict,
1447 startpos+predict);
1450 if (ret != nread+4)
1451 DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
1452 fname,startpos,nread,ret));
1454 #else
1455 ret = read_file(fnum,header+4,startpos,nread);
1456 if (ret < mincount) ret = 0;
1458 _smb_setlen(header,ret);
1459 transfer_file(0,Client,0,header,4+ret,0);
1460 #endif
1462 DEBUG(5,("readbraw finished\n"));
1463 return -1;
1467 /****************************************************************************
1468 reply to a lockread (core+ protocol)
1469 ****************************************************************************/
1470 int reply_lockread(char *inbuf,char *outbuf)
1472 int cnum,fnum;
1473 int nread = -1;
1474 char *data;
1475 int outsize = 0;
1476 uint32 startpos, numtoread;
1477 int eclass;
1478 uint32 ecode;
1480 cnum = SVAL(inbuf,smb_tid);
1481 fnum = GETFNUM(inbuf,smb_vwv0);
1483 CHECK_FNUM(fnum,cnum);
1484 CHECK_READ(fnum);
1485 CHECK_ERROR(fnum);
1487 numtoread = SVAL(inbuf,smb_vwv1);
1488 startpos = IVAL(inbuf,smb_vwv2);
1490 outsize = set_message(outbuf,5,3,True);
1491 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1492 data = smb_buf(outbuf) + 3;
1494 if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
1495 return (ERROR(eclass,ecode));
1497 nread = read_file(fnum,data,startpos,numtoread);
1499 if (nread < 0)
1500 return(UNIXERROR(ERRDOS,ERRnoaccess));
1502 outsize += nread;
1503 SSVAL(outbuf,smb_vwv0,nread);
1504 SSVAL(outbuf,smb_vwv5,nread+3);
1505 SSVAL(smb_buf(outbuf),1,nread);
1507 DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1509 return(outsize);
1513 /****************************************************************************
1514 reply to a read
1515 ****************************************************************************/
1516 int reply_read(char *inbuf,char *outbuf)
1518 int cnum,numtoread,fnum;
1519 int nread = 0;
1520 char *data;
1521 int startpos;
1522 int outsize = 0;
1524 cnum = SVAL(inbuf,smb_tid);
1525 fnum = GETFNUM(inbuf,smb_vwv0);
1527 CHECK_FNUM(fnum,cnum);
1528 CHECK_READ(fnum);
1529 CHECK_ERROR(fnum);
1531 numtoread = SVAL(inbuf,smb_vwv1);
1532 startpos = IVAL(inbuf,smb_vwv2);
1534 outsize = set_message(outbuf,5,3,True);
1535 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1536 data = smb_buf(outbuf) + 3;
1538 if (is_locked(fnum,cnum,numtoread,startpos))
1539 return(ERROR(ERRDOS,ERRlock));
1541 if (numtoread > 0)
1542 nread = read_file(fnum,data,startpos,numtoread);
1544 if (nread < 0)
1545 return(UNIXERROR(ERRDOS,ERRnoaccess));
1547 outsize += nread;
1548 SSVAL(outbuf,smb_vwv0,nread);
1549 SSVAL(outbuf,smb_vwv5,nread+3);
1550 CVAL(smb_buf(outbuf),0) = 1;
1551 SSVAL(smb_buf(outbuf),1,nread);
1553 DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread));
1555 return(outsize);
1559 /****************************************************************************
1560 reply to a read and X
1561 ****************************************************************************/
1562 int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1564 int fnum = GETFNUM(inbuf,smb_vwv2);
1565 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1566 int smb_maxcnt = SVAL(inbuf,smb_vwv5);
1567 int smb_mincnt = SVAL(inbuf,smb_vwv6);
1568 int cnum;
1569 int nread = -1;
1570 char *data;
1571 BOOL ok = False;
1573 cnum = SVAL(inbuf,smb_tid);
1575 CHECK_FNUM(fnum,cnum);
1576 CHECK_READ(fnum);
1577 CHECK_ERROR(fnum);
1579 set_message(outbuf,12,0,True);
1580 data = smb_buf(outbuf);
1582 if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
1583 return(ERROR(ERRDOS,ERRlock));
1584 nread = read_file(fnum,data,smb_offs,smb_maxcnt);
1585 ok = True;
1587 if (nread < 0)
1588 return(UNIXERROR(ERRDOS,ERRnoaccess));
1590 SSVAL(outbuf,smb_vwv5,nread);
1591 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1592 SSVAL(smb_buf(outbuf),-2,nread);
1594 DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n",
1595 timestring(),fnum,cnum,
1596 smb_mincnt,smb_maxcnt,nread));
1598 chain_fnum = fnum;
1600 return chain_reply(inbuf,outbuf,length,bufsize);
1604 /****************************************************************************
1605 reply to a writebraw (core+ or LANMAN1.0 protocol)
1606 ****************************************************************************/
1607 int reply_writebraw(char *inbuf,char *outbuf)
1609 int nwritten=0;
1610 int total_written=0;
1611 int numtowrite=0;
1612 int cnum,fnum;
1613 int outsize = 0;
1614 long startpos;
1615 char *data=NULL;
1616 BOOL write_through;
1617 int tcount;
1619 cnum = SVAL(inbuf,smb_tid);
1620 fnum = GETFNUM(inbuf,smb_vwv0);
1622 CHECK_FNUM(fnum,cnum);
1623 CHECK_WRITE(fnum);
1624 CHECK_ERROR(fnum);
1626 tcount = IVAL(inbuf,smb_vwv1);
1627 startpos = IVAL(inbuf,smb_vwv3);
1628 write_through = BITSETW(inbuf+smb_vwv7,0);
1630 /* We have to deal with slightly different formats depending
1631 on whether we are using the core+ or lanman1.0 protocol */
1632 if(Protocol <= PROTOCOL_COREPLUS) {
1633 numtowrite = SVAL(smb_buf(inbuf),-2);
1634 data = smb_buf(inbuf);
1635 } else {
1636 numtowrite = SVAL(inbuf,smb_vwv10);
1637 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1640 /* force the error type */
1641 CVAL(inbuf,smb_com) = SMBwritec;
1642 CVAL(outbuf,smb_com) = SMBwritec;
1644 if (is_locked(fnum,cnum,tcount,startpos))
1645 return(ERROR(ERRDOS,ERRlock));
1647 if (seek_file(fnum,startpos) != startpos)
1648 DEBUG(0,("couldn't seek to %d in writebraw\n",startpos));
1650 if (numtowrite>0)
1651 nwritten = write_file(fnum,data,numtowrite);
1653 DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n",
1654 timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through));
1656 if (nwritten < numtowrite)
1657 return(UNIXERROR(ERRHRD,ERRdiskfull));
1659 total_written = nwritten;
1661 /* Return a message to the redirector to tell it
1662 to send more bytes */
1663 CVAL(outbuf,smb_com) = SMBwritebraw;
1664 SSVALS(outbuf,smb_vwv0,-1);
1665 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1666 send_smb(Client,outbuf);
1668 /* Now read the raw data into the buffer and write it */
1669 if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
1670 exit_server("secondary writebraw failed");
1673 /* Even though this is not an smb message, smb_len
1674 returns the generic length of an smb message */
1675 numtowrite = smb_len(inbuf);
1677 if (tcount > nwritten+numtowrite) {
1678 DEBUG(3,("Client overestimated the write %d %d %d\n",
1679 tcount,nwritten,numtowrite));
1682 nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0,
1683 startpos+nwritten);
1684 total_written += nwritten;
1686 /* Set up outbuf to return the correct return */
1687 outsize = set_message(outbuf,1,0,True);
1688 CVAL(outbuf,smb_com) = SMBwritec;
1689 SSVAL(outbuf,smb_vwv0,total_written);
1691 if (nwritten < numtowrite) {
1692 CVAL(outbuf,smb_rcls) = ERRHRD;
1693 SSVAL(outbuf,smb_err,ERRdiskfull);
1696 if (lp_syncalways(SNUM(cnum)) || write_through)
1697 sync_file(fnum);
1699 DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n",
1700 timestring(),fnum,cnum,startpos,numtowrite,total_written));
1702 /* we won't return a status if write through is not selected - this
1703 follows what WfWg does */
1704 if (!write_through && total_written==tcount)
1705 return(-1);
1707 return(outsize);
1711 /****************************************************************************
1712 reply to a writeunlock (core+)
1713 ****************************************************************************/
1714 int reply_writeunlock(char *inbuf,char *outbuf)
1716 int cnum,fnum;
1717 int nwritten = -1;
1718 int outsize = 0;
1719 char *data;
1720 uint32 numtowrite,startpos;
1721 int eclass;
1722 uint32 ecode;
1724 cnum = SVAL(inbuf,smb_tid);
1725 fnum = GETFNUM(inbuf,smb_vwv0);
1727 CHECK_FNUM(fnum,cnum);
1728 CHECK_WRITE(fnum);
1729 CHECK_ERROR(fnum);
1731 numtowrite = SVAL(inbuf,smb_vwv1);
1732 startpos = IVAL(inbuf,smb_vwv2);
1733 data = smb_buf(inbuf) + 3;
1735 if (is_locked(fnum,cnum,numtowrite,startpos))
1736 return(ERROR(ERRDOS,ERRlock));
1738 seek_file(fnum,startpos);
1740 /* The special X/Open SMB protocol handling of
1741 zero length writes is *NOT* done for
1742 this call */
1743 if(numtowrite == 0)
1744 nwritten = 0;
1745 else
1746 nwritten = write_file(fnum,data,numtowrite);
1748 if (lp_syncalways(SNUM(cnum)))
1749 sync_file(fnum);
1751 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1752 return(UNIXERROR(ERRDOS,ERRnoaccess));
1754 if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode))
1755 return(ERROR(eclass,ecode));
1757 outsize = set_message(outbuf,1,0,True);
1759 SSVAL(outbuf,smb_vwv0,nwritten);
1761 DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n",
1762 timestring(),fnum,cnum,numtowrite,nwritten));
1764 return(outsize);
1768 /****************************************************************************
1769 reply to a write
1770 ****************************************************************************/
1771 int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
1773 int cnum,numtowrite,fnum;
1774 int nwritten = -1;
1775 int outsize = 0;
1776 int startpos;
1777 char *data;
1779 dum1 = dum2 = 0;
1782 cnum = SVAL(inbuf,smb_tid);
1783 fnum = GETFNUM(inbuf,smb_vwv0);
1785 CHECK_FNUM(fnum,cnum);
1786 CHECK_WRITE(fnum);
1787 CHECK_ERROR(fnum);
1789 numtowrite = SVAL(inbuf,smb_vwv1);
1790 startpos = IVAL(inbuf,smb_vwv2);
1791 data = smb_buf(inbuf) + 3;
1793 if (is_locked(fnum,cnum,numtowrite,startpos))
1794 return(ERROR(ERRDOS,ERRlock));
1796 seek_file(fnum,startpos);
1798 /* X/Open SMB protocol says that if smb_vwv1 is
1799 zero then the file size should be extended or
1800 truncated to the size given in smb_vwv[2-3] */
1801 if(numtowrite == 0)
1802 nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos);
1803 else
1804 nwritten = write_file(fnum,data,numtowrite);
1806 if (lp_syncalways(SNUM(cnum)))
1807 sync_file(fnum);
1809 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0))
1810 return(UNIXERROR(ERRDOS,ERRnoaccess));
1812 outsize = set_message(outbuf,1,0,True);
1814 SSVAL(outbuf,smb_vwv0,nwritten);
1816 if (nwritten < numtowrite) {
1817 CVAL(outbuf,smb_rcls) = ERRHRD;
1818 SSVAL(outbuf,smb_err,ERRdiskfull);
1821 DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten));
1823 return(outsize);
1827 /****************************************************************************
1828 reply to a write and X
1829 ****************************************************************************/
1830 int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
1832 int fnum = GETFNUM(inbuf,smb_vwv2);
1833 uint32 smb_offs = IVAL(inbuf,smb_vwv3);
1834 int smb_dsize = SVAL(inbuf,smb_vwv10);
1835 int smb_doff = SVAL(inbuf,smb_vwv11);
1836 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1837 int cnum;
1838 int nwritten = -1;
1839 char *data;
1841 cnum = SVAL(inbuf,smb_tid);
1843 CHECK_FNUM(fnum,cnum);
1844 CHECK_WRITE(fnum);
1845 CHECK_ERROR(fnum);
1847 data = smb_base(inbuf) + smb_doff;
1849 if (is_locked(fnum,cnum,smb_dsize,smb_offs))
1850 return(ERROR(ERRDOS,ERRlock));
1852 seek_file(fnum,smb_offs);
1854 /* X/Open SMB protocol says that, unlike SMBwrite
1855 if the length is zero then NO truncation is
1856 done, just a write of zero. To truncate a file,
1857 use SMBwrite. */
1858 if(smb_dsize == 0)
1859 nwritten = 0;
1860 else
1861 nwritten = write_file(fnum,data,smb_dsize);
1863 if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0))
1864 return(UNIXERROR(ERRDOS,ERRnoaccess));
1866 set_message(outbuf,6,0,True);
1868 SSVAL(outbuf,smb_vwv2,nwritten);
1870 if (nwritten < smb_dsize) {
1871 CVAL(outbuf,smb_rcls) = ERRHRD;
1872 SSVAL(outbuf,smb_err,ERRdiskfull);
1875 DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten));
1877 chain_fnum = fnum;
1879 if (lp_syncalways(SNUM(cnum)) || write_through)
1880 sync_file(fnum);
1882 return chain_reply(inbuf,outbuf,length,bufsize);
1886 /****************************************************************************
1887 reply to a lseek
1888 ****************************************************************************/
1889 int reply_lseek(char *inbuf,char *outbuf)
1891 int cnum,fnum;
1892 uint32 startpos;
1893 int32 res= -1;
1894 int mode,umode;
1895 int outsize = 0;
1897 cnum = SVAL(inbuf,smb_tid);
1898 fnum = GETFNUM(inbuf,smb_vwv0);
1900 CHECK_FNUM(fnum,cnum);
1901 CHECK_ERROR(fnum);
1903 mode = SVAL(inbuf,smb_vwv1) & 3;
1904 startpos = IVAL(inbuf,smb_vwv2);
1906 switch (mode & 3)
1908 case 0: umode = SEEK_SET; break;
1909 case 1: umode = SEEK_CUR; break;
1910 case 2: umode = SEEK_END; break;
1911 default:
1912 umode = SEEK_SET; break;
1915 res = lseek(Files[fnum].fd_ptr->fd,startpos,umode);
1916 Files[fnum].pos = res;
1918 outsize = set_message(outbuf,2,0,True);
1919 SIVALS(outbuf,smb_vwv0,res);
1921 DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode));
1923 return(outsize);
1927 /****************************************************************************
1928 reply to a flush
1929 ****************************************************************************/
1930 int reply_flush(char *inbuf,char *outbuf)
1932 int cnum, fnum;
1933 int outsize = set_message(outbuf,0,0,True);
1935 cnum = SVAL(inbuf,smb_tid);
1936 fnum = GETFNUM(inbuf,smb_vwv0);
1938 if (fnum != 0xFFFF) {
1939 CHECK_FNUM(fnum,cnum);
1940 CHECK_ERROR(fnum);
1943 if (fnum == 0xFFFF)
1945 int i;
1946 for (i=0;i<MAX_OPEN_FILES;i++)
1947 if (OPEN_FNUM(i))
1948 sync_file(i);
1950 else
1951 sync_file(fnum);
1953 DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum));
1954 return(outsize);
1958 /****************************************************************************
1959 reply to a exit
1960 ****************************************************************************/
1961 int reply_exit(char *inbuf,char *outbuf)
1963 int outsize = set_message(outbuf,0,0,True);
1964 DEBUG(3,("%s exit\n",timestring()));
1966 return(outsize);
1970 /****************************************************************************
1971 reply to a close
1972 ****************************************************************************/
1973 int reply_close(char *inbuf,char *outbuf)
1975 int fnum,cnum;
1976 int outsize = 0;
1977 time_t mtime;
1978 int32 eclass = 0, err = 0;
1980 outsize = set_message(outbuf,0,0,True);
1982 cnum = SVAL(inbuf,smb_tid);
1984 fnum = GETFNUM(inbuf,smb_vwv0);
1985 CHECK_FNUM(fnum,cnum);
1987 if(HAS_CACHED_ERROR(fnum)) {
1988 eclass = Files[fnum].wbmpx_ptr->wr_errclass;
1989 err = Files[fnum].wbmpx_ptr->wr_error;
1992 mtime = make_unix_date3(inbuf+smb_vwv1);
1994 /* try and set the date */
1995 set_filetime(Files[fnum].name,mtime);
1997 close_file(fnum);
1999 /* We have a cached error */
2000 if(eclass || err)
2001 return(ERROR(eclass,err));
2003 DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
2004 timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
2005 Connections[cnum].num_files_open));
2007 return(outsize);
2011 /****************************************************************************
2012 reply to a writeclose (Core+ protocol)
2013 ****************************************************************************/
2014 int reply_writeclose(char *inbuf,char *outbuf)
2016 int cnum,numtowrite,fnum;
2017 int nwritten = -1;
2018 int outsize = 0;
2019 int startpos;
2020 char *data;
2021 time_t mtime;
2023 cnum = SVAL(inbuf,smb_tid);
2024 fnum = GETFNUM(inbuf,smb_vwv0);
2026 CHECK_FNUM(fnum,cnum);
2027 CHECK_WRITE(fnum);
2028 CHECK_ERROR(fnum);
2030 numtowrite = SVAL(inbuf,smb_vwv1);
2031 startpos = IVAL(inbuf,smb_vwv2);
2032 mtime = make_unix_date3(inbuf+smb_vwv4);
2033 data = smb_buf(inbuf) + 1;
2035 if (is_locked(fnum,cnum,numtowrite,startpos))
2036 return(ERROR(ERRDOS,ERRlock));
2038 seek_file(fnum,startpos);
2040 nwritten = write_file(fnum,data,numtowrite);
2042 set_filetime(Files[fnum].name,mtime);
2044 close_file(fnum);
2046 DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
2047 timestring(),fnum,cnum,numtowrite,nwritten,
2048 Connections[cnum].num_files_open));
2050 if (nwritten <= 0)
2051 return(UNIXERROR(ERRDOS,ERRnoaccess));
2053 outsize = set_message(outbuf,1,0,True);
2055 SSVAL(outbuf,smb_vwv0,nwritten);
2056 return(outsize);
2060 /****************************************************************************
2061 reply to a lock
2062 ****************************************************************************/
2063 int reply_lock(char *inbuf,char *outbuf)
2065 int fnum,cnum;
2066 int outsize = set_message(outbuf,0,0,True);
2067 uint32 count,offset;
2068 int eclass;
2069 uint32 ecode;
2071 cnum = SVAL(inbuf,smb_tid);
2072 fnum = GETFNUM(inbuf,smb_vwv0);
2074 CHECK_FNUM(fnum,cnum);
2075 CHECK_ERROR(fnum);
2077 count = IVAL(inbuf,smb_vwv1);
2078 offset = IVAL(inbuf,smb_vwv3);
2080 DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count));
2082 if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode))
2083 return (ERROR(eclass,ecode));
2085 return(outsize);
2089 /****************************************************************************
2090 reply to a unlock
2091 ****************************************************************************/
2092 int reply_unlock(char *inbuf,char *outbuf)
2094 int fnum,cnum;
2095 int outsize = set_message(outbuf,0,0,True);
2096 uint32 count,offset;
2097 int eclass;
2098 uint32 ecode;
2100 cnum = SVAL(inbuf,smb_tid);
2101 fnum = GETFNUM(inbuf,smb_vwv0);
2103 CHECK_FNUM(fnum,cnum);
2104 CHECK_ERROR(fnum);
2106 count = IVAL(inbuf,smb_vwv1);
2107 offset = IVAL(inbuf,smb_vwv3);
2109 if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode))
2110 return (ERROR(eclass,ecode));
2112 DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count));
2114 return(outsize);
2118 /****************************************************************************
2119 reply to a tdis
2120 ****************************************************************************/
2121 int reply_tdis(char *inbuf,char *outbuf)
2123 int cnum;
2124 int outsize = set_message(outbuf,0,0,True);
2125 uint16 vuid;
2127 cnum = SVAL(inbuf,smb_tid);
2128 vuid = SVAL(inbuf,smb_uid);
2130 if (!OPEN_CNUM(cnum)) {
2131 DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum));
2132 return(ERROR(ERRSRV,ERRinvnid));
2135 Connections[cnum].used = False;
2137 close_cnum(cnum,vuid);
2139 DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum));
2141 return outsize;
2146 /****************************************************************************
2147 reply to a echo
2148 ****************************************************************************/
2149 int reply_echo(char *inbuf,char *outbuf)
2151 int cnum;
2152 int smb_reverb = SVAL(inbuf,smb_vwv0);
2153 int seq_num;
2154 int data_len = smb_buflen(inbuf);
2155 int outsize = set_message(outbuf,1,data_len,True);
2157 cnum = SVAL(inbuf,smb_tid);
2159 /* According to the latest CIFS spec we shouldn't
2160 care what the TID is.
2163 #if 0
2164 if (cnum != 0xFFFF && !OPEN_CNUM(cnum))
2166 DEBUG(4,("Invalid cnum in echo (%d)\n",cnum));
2167 return(ERROR(ERRSRV,ERRinvnid));
2169 #endif
2171 /* copy any incoming data back out */
2172 if (data_len > 0)
2173 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2175 if (smb_reverb > 100)
2177 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2178 smb_reverb = 100;
2181 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++)
2183 SSVAL(outbuf,smb_vwv0,seq_num);
2185 smb_setlen(outbuf,outsize - 4);
2187 send_smb(Client,outbuf);
2190 DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum));
2192 return -1;
2196 /****************************************************************************
2197 reply to a printopen
2198 ****************************************************************************/
2199 int reply_printopen(char *inbuf,char *outbuf)
2201 pstring fname;
2202 pstring fname2;
2203 int cnum;
2204 int fnum = -1;
2205 int outsize = 0;
2207 *fname = *fname2 = 0;
2209 cnum = SVAL(inbuf,smb_tid);
2211 if (!CAN_PRINT(cnum))
2212 return(ERROR(ERRDOS,ERRnoaccess));
2215 pstring s;
2216 char *p;
2217 StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1);
2218 p = s;
2219 while (*p)
2221 if (!(isalnum(*p) || strchr("._-",*p)))
2222 *p = 'X';
2223 p++;
2226 if (strlen(s) > 10) s[10] = 0;
2228 sprintf(fname,"%s.XXXXXX",s);
2231 fnum = find_free_file();
2232 if (fnum < 0)
2233 return(ERROR(ERRSRV,ERRnofids));
2235 strcpy(fname2,(char *)mktemp(fname));
2237 if (!check_name(fname2,cnum))
2238 return(ERROR(ERRDOS,ERRnoaccess));
2240 /* Open for exclusive use, write only. */
2241 open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL);
2243 if (!Files[fnum].open)
2244 return(UNIXERROR(ERRDOS,ERRnoaccess));
2246 /* force it to be a print file */
2247 Files[fnum].print_file = True;
2249 outsize = set_message(outbuf,1,0,True);
2250 SSVAL(outbuf,smb_vwv0,fnum);
2252 DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum));
2254 return(outsize);
2258 /****************************************************************************
2259 reply to a printclose
2260 ****************************************************************************/
2261 int reply_printclose(char *inbuf,char *outbuf)
2263 int fnum,cnum;
2264 int outsize = set_message(outbuf,0,0,True);
2266 cnum = SVAL(inbuf,smb_tid);
2267 fnum = GETFNUM(inbuf,smb_vwv0);
2269 CHECK_FNUM(fnum,cnum);
2270 CHECK_ERROR(fnum);
2272 if (!CAN_PRINT(cnum))
2273 return(ERROR(ERRDOS,ERRnoaccess));
2275 close_file(fnum);
2277 DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
2279 return(outsize);
2283 /****************************************************************************
2284 reply to a printqueue
2285 ****************************************************************************/
2286 int reply_printqueue(char *inbuf,char *outbuf)
2288 int cnum;
2289 int outsize = set_message(outbuf,2,3,True);
2290 int max_count = SVAL(inbuf,smb_vwv0);
2291 int start_index = SVAL(inbuf,smb_vwv1);
2292 uint16 vuid;
2294 cnum = SVAL(inbuf,smb_tid);
2295 vuid = SVAL(inbuf,smb_uid);
2297 /* allow checking the queue for anyone */
2298 #if 0
2299 if (!CAN_PRINT(cnum))
2300 return(ERROR(ERRDOS,ERRnoaccess));
2301 #endif
2303 SSVAL(outbuf,smb_vwv0,0);
2304 SSVAL(outbuf,smb_vwv1,0);
2305 CVAL(smb_buf(outbuf),0) = 1;
2306 SSVAL(smb_buf(outbuf),1,0);
2308 DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n",
2309 timestring(),cnum,start_index,max_count));
2311 if (!OPEN_CNUM(cnum) || !Connections[cnum].printer)
2313 int i;
2314 cnum = -1;
2316 for (i=0;i<MAX_CONNECTIONS;i++)
2317 if (CAN_PRINT(i) && Connections[i].printer)
2318 cnum = i;
2320 if (cnum == -1)
2321 for (i=0;i<MAX_CONNECTIONS;i++)
2322 if (OPEN_CNUM(i))
2323 cnum = i;
2325 if (!OPEN_CNUM(cnum))
2326 return(ERROR(ERRSRV,ERRinvnid));
2328 DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
2331 if (!become_user(cnum,vuid))
2332 return(ERROR(ERRSRV,ERRinvnid));
2335 print_queue_struct *queue = NULL;
2336 char *p = smb_buf(outbuf) + 3;
2337 int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL);
2338 int num_to_get = ABS(max_count);
2339 int first = (max_count>0?start_index:start_index+max_count+1);
2340 int i;
2342 if (first >= count)
2343 num_to_get = 0;
2344 else
2345 num_to_get = MIN(num_to_get,count-first);
2348 for (i=first;i<first+num_to_get;i++)
2350 put_dos_date2(p,0,queue[i].time);
2351 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2352 SSVAL(p,5,queue[i].job);
2353 SIVAL(p,7,queue[i].size);
2354 CVAL(p,11) = 0;
2355 StrnCpy(p+12,queue[i].user,16);
2356 p += 28;
2359 if (count > 0)
2361 outsize = set_message(outbuf,2,28*count+3,False);
2362 SSVAL(outbuf,smb_vwv0,count);
2363 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2364 CVAL(smb_buf(outbuf),0) = 1;
2365 SSVAL(smb_buf(outbuf),1,28*count);
2368 if (queue) free(queue);
2370 DEBUG(3,("%d entries returned in queue\n",count));
2373 return(outsize);
2377 /****************************************************************************
2378 reply to a printwrite
2379 ****************************************************************************/
2380 int reply_printwrite(char *inbuf,char *outbuf)
2382 int cnum,numtowrite,fnum;
2383 int outsize = set_message(outbuf,0,0,True);
2384 char *data;
2386 cnum = SVAL(inbuf,smb_tid);
2388 if (!CAN_PRINT(cnum))
2389 return(ERROR(ERRDOS,ERRnoaccess));
2391 fnum = GETFNUM(inbuf,smb_vwv0);
2393 CHECK_FNUM(fnum,cnum);
2394 CHECK_WRITE(fnum);
2395 CHECK_ERROR(fnum);
2397 numtowrite = SVAL(smb_buf(inbuf),1);
2398 data = smb_buf(inbuf) + 3;
2400 if (write_file(fnum,data,numtowrite) != numtowrite)
2401 return(UNIXERROR(ERRDOS,ERRnoaccess));
2403 DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite));
2405 return(outsize);
2409 /****************************************************************************
2410 reply to a mkdir
2411 ****************************************************************************/
2412 int reply_mkdir(char *inbuf,char *outbuf)
2414 pstring directory;
2415 int cnum;
2416 int outsize,ret= -1;
2418 strcpy(directory,smb_buf(inbuf) + 1);
2419 cnum = SVAL(inbuf,smb_tid);
2420 unix_convert(directory,cnum,0);
2422 if (check_name(directory,cnum))
2423 ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
2425 if (ret < 0)
2426 return(UNIXERROR(ERRDOS,ERRnoaccess));
2428 outsize = set_message(outbuf,0,0,True);
2430 DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret));
2432 return(outsize);
2436 /****************************************************************************
2437 reply to a rmdir
2438 ****************************************************************************/
2439 int reply_rmdir(char *inbuf,char *outbuf)
2441 pstring directory;
2442 int cnum;
2443 int outsize = 0;
2444 BOOL ok = False;
2446 cnum = SVAL(inbuf,smb_tid);
2447 strcpy(directory,smb_buf(inbuf) + 1);
2448 unix_convert(directory,cnum,0);
2450 if (check_name(directory,cnum))
2452 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2453 ok = (sys_rmdir(directory) == 0);
2454 if (!ok)
2455 DEBUG(3,("couldn't remove directory %s : %s\n",
2456 directory,strerror(errno)));
2459 if (!ok)
2460 return(UNIXERROR(ERRDOS,ERRbadpath));
2462 outsize = set_message(outbuf,0,0,True);
2464 DEBUG(3,("%s rmdir %s\n",timestring(),directory));
2466 return(outsize);
2470 /*******************************************************************
2471 resolve wildcards in a filename rename
2472 ********************************************************************/
2473 static BOOL resolve_wildcards(char *name1,char *name2)
2475 fstring root1,root2;
2476 fstring ext1,ext2;
2477 char *p,*p2;
2479 name1 = strrchr(name1,'/');
2480 name2 = strrchr(name2,'/');
2482 if (!name1 || !name2) return(False);
2484 strcpy(root1,name1);
2485 strcpy(root2,name2);
2486 p = strrchr(root1,'.');
2487 if (p) {
2488 *p = 0;
2489 strcpy(ext1,p+1);
2490 } else {
2491 strcpy(ext1,"");
2493 p = strrchr(root2,'.');
2494 if (p) {
2495 *p = 0;
2496 strcpy(ext2,p+1);
2497 } else {
2498 strcpy(ext2,"");
2501 p = root1;
2502 p2 = root2;
2503 while (*p2) {
2504 if (*p2 == '?') {
2505 *p2 = *p;
2506 p2++;
2507 } else {
2508 p2++;
2510 if (*p) p++;
2513 p = ext1;
2514 p2 = ext2;
2515 while (*p2) {
2516 if (*p2 == '?') {
2517 *p2 = *p;
2518 p2++;
2519 } else {
2520 p2++;
2522 if (*p) p++;
2525 strcpy(name2,root2);
2526 if (ext2[0]) {
2527 strcat(name2,".");
2528 strcat(name2,ext2);
2531 return(True);
2534 /*******************************************************************
2535 check if a user is allowed to rename a file
2536 ********************************************************************/
2537 static BOOL can_rename(char *fname,int cnum)
2539 struct stat sbuf;
2541 if (!CAN_WRITE(cnum)) return(False);
2543 if (sys_lstat(fname,&sbuf) != 0) return(False);
2544 if (!check_file_sharing(cnum,fname)) return(False);
2546 return(True);
2549 /****************************************************************************
2550 reply to a mv
2551 ****************************************************************************/
2552 int reply_mv(char *inbuf,char *outbuf)
2554 int outsize = 0;
2555 pstring name;
2556 int cnum;
2557 pstring directory;
2558 pstring mask,newname;
2559 pstring newname_last_component;
2560 char *p;
2561 int count=0;
2562 int error = ERRnoaccess;
2563 BOOL has_wild;
2564 BOOL exists=False;
2566 *directory = *mask = 0;
2568 cnum = SVAL(inbuf,smb_tid);
2570 strcpy(name,smb_buf(inbuf) + 1);
2571 strcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
2573 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
2575 unix_convert(name,cnum,0);
2576 unix_convert(newname,cnum,newname_last_component);
2579 * Split the old name into directory and last component
2580 * strings. Note that unix_convert may have stripped off a
2581 * leading ./ from both name and newname if the rename is
2582 * at the root of the share. We need to make sure either both
2583 * name and newname contain a / character or neither of them do
2584 * as this is checked in resolve_wildcards().
2587 p = strrchr(name,'/');
2588 if (!p) {
2589 strcpy(directory,".");
2590 strcpy(mask,name);
2591 } else {
2592 *p = 0;
2593 strcpy(directory,name);
2594 strcpy(mask,p+1);
2595 *p = '/'; /* Replace needed for exceptional test below. */
2598 if (is_mangled(mask))
2599 check_mangled_stack(mask);
2601 has_wild = strchr(mask,'*') || strchr(mask,'?');
2603 if (!has_wild) {
2604 BOOL is_short_name = is_8_3(name, True);
2606 /* Add a terminating '/' to the directory name. */
2607 strcat(directory,"/");
2608 strcat(directory,mask);
2610 /* Ensure newname contains a '/' also */
2611 if(strrchr(newname,'/') == 0) {
2612 pstring tmpstr;
2614 strcpy(tmpstr, "./");
2615 strcat(tmpstr, newname);
2616 strcpy(newname, tmpstr);
2619 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",
2620 case_sensitive, case_preserve, short_case_preserve, directory,
2621 newname, newname_last_component, is_short_name));
2624 * Check for special case with case preserving and not
2625 * case sensitive, if directory and newname are identical,
2626 * and the old last component differs from the original
2627 * last component only by case, then we should allow
2628 * the rename (user is trying to change the case of the
2629 * filename).
2631 if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) ||
2632 ((short_case_preserve == True) && (is_short_name == True))) &&
2633 strcsequal(directory, newname)) {
2634 pstring newname_modified_last_component;
2637 * Get the last component of the modified name.
2638 * Note that we guarantee that newname contains a '/'
2639 * character above.
2641 p = strrchr(newname,'/');
2642 strcpy(newname_modified_last_component,p+1);
2644 if(strcsequal(newname_modified_last_component,
2645 newname_last_component) == False) {
2647 * Replace the modified last component with
2648 * the original.
2650 strcpy(p+1, newname_last_component);
2654 if (resolve_wildcards(directory,newname) &&
2655 can_rename(directory,cnum) &&
2656 !file_exist(newname,NULL) &&
2657 !sys_rename(directory,newname)) count++;
2659 DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
2660 directory,newname));
2662 if (!count) exists = file_exist(directory,NULL);
2663 if (!count && exists && file_exist(newname,NULL)) {
2664 exists = True;
2665 error = 183;
2667 } else {
2668 void *dirptr = NULL;
2669 char *dname;
2670 pstring destname;
2672 if (check_name(directory,cnum))
2673 dirptr = OpenDir(directory);
2675 if (dirptr)
2677 error = ERRbadfile;
2679 if (strequal(mask,"????????.???"))
2680 strcpy(mask,"*");
2682 while ((dname = ReadDirName(dirptr)))
2684 pstring fname;
2685 strcpy(fname,dname);
2687 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2689 error = ERRnoaccess;
2690 sprintf(fname,"%s/%s",directory,dname);
2691 if (!can_rename(fname,cnum)) continue;
2692 strcpy(destname,newname);
2694 if (!resolve_wildcards(fname,destname)) continue;
2696 if (file_exist(destname,NULL)) {
2697 error = 183;
2698 continue;
2700 if (!sys_rename(fname,destname)) count++;
2701 DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
2703 CloseDir(dirptr);
2707 if (count == 0) {
2708 if (exists)
2709 return(ERROR(ERRDOS,error));
2710 else
2711 return(UNIXERROR(ERRDOS,error));
2714 outsize = set_message(outbuf,0,0,True);
2716 return(outsize);
2719 /*******************************************************************
2720 copy a file as part of a reply_copy
2721 ******************************************************************/
2722 static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
2723 int count,BOOL target_is_directory)
2725 int Access,action;
2726 struct stat st;
2727 int ret=0;
2728 int fnum1,fnum2;
2729 pstring dest;
2731 strcpy(dest,dest1);
2732 if (target_is_directory) {
2733 char *p = strrchr(src,'/');
2734 if (p)
2735 p++;
2736 else
2737 p = src;
2738 strcat(dest,"/");
2739 strcat(dest,p);
2742 if (!file_exist(src,&st)) return(False);
2744 fnum1 = find_free_file();
2745 if (fnum1<0) return(False);
2746 open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
2747 1,0,&Access,&action);
2749 if (!Files[fnum1].open) return(False);
2751 if (!target_is_directory && count)
2752 ofun = 1;
2754 fnum2 = find_free_file();
2755 if (fnum2<0) {
2756 close_file(fnum1);
2757 return(False);
2759 open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
2760 ofun,st.st_mode,&Access,&action);
2762 if (!Files[fnum2].open) {
2763 close_file(fnum1);
2764 return(False);
2767 if ((ofun&3) == 1) {
2768 lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END);
2771 if (st.st_size)
2772 ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
2774 close_file(fnum1);
2775 close_file(fnum2);
2777 return(ret == st.st_size);
2782 /****************************************************************************
2783 reply to a file copy.
2784 ****************************************************************************/
2785 int reply_copy(char *inbuf,char *outbuf)
2787 int outsize = 0;
2788 pstring name;
2789 int cnum;
2790 pstring directory;
2791 pstring mask,newname;
2792 char *p;
2793 int count=0;
2794 int error = ERRnoaccess;
2795 BOOL has_wild;
2796 BOOL exists=False;
2797 int tid2 = SVAL(inbuf,smb_vwv0);
2798 int ofun = SVAL(inbuf,smb_vwv1);
2799 int flags = SVAL(inbuf,smb_vwv2);
2800 BOOL target_is_directory=False;
2802 *directory = *mask = 0;
2804 cnum = SVAL(inbuf,smb_tid);
2806 strcpy(name,smb_buf(inbuf));
2807 strcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
2809 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
2811 if (tid2 != cnum) {
2812 /* can't currently handle inter share copies XXXX */
2813 DEBUG(3,("Rejecting inter-share copy\n"));
2814 return(ERROR(ERRSRV,ERRinvdevice));
2817 unix_convert(name,cnum,0);
2818 unix_convert(newname,cnum,0);
2820 target_is_directory = directory_exist(newname,NULL);
2822 if ((flags&1) && target_is_directory) {
2823 return(ERROR(ERRDOS,ERRbadfile));
2826 if ((flags&2) && !target_is_directory) {
2827 return(ERROR(ERRDOS,ERRbadpath));
2830 if ((flags&(1<<5)) && directory_exist(name,NULL)) {
2831 /* wants a tree copy! XXXX */
2832 DEBUG(3,("Rejecting tree copy\n"));
2833 return(ERROR(ERRSRV,ERRerror));
2836 p = strrchr(name,'/');
2837 if (!p) {
2838 strcpy(directory,"./");
2839 strcpy(mask,name);
2840 } else {
2841 *p = 0;
2842 strcpy(directory,name);
2843 strcpy(mask,p+1);
2846 if (is_mangled(mask))
2847 check_mangled_stack(mask);
2849 has_wild = strchr(mask,'*') || strchr(mask,'?');
2851 if (!has_wild) {
2852 strcat(directory,"/");
2853 strcat(directory,mask);
2854 if (resolve_wildcards(directory,newname) &&
2855 copy_file(directory,newname,cnum,ofun,
2856 count,target_is_directory)) count++;
2857 if (!count) exists = file_exist(directory,NULL);
2858 } else {
2859 void *dirptr = NULL;
2860 char *dname;
2861 pstring destname;
2863 if (check_name(directory,cnum))
2864 dirptr = OpenDir(directory);
2866 if (dirptr)
2868 error = ERRbadfile;
2870 if (strequal(mask,"????????.???"))
2871 strcpy(mask,"*");
2873 while ((dname = ReadDirName(dirptr)))
2875 pstring fname;
2876 strcpy(fname,dname);
2878 if(!mask_match(fname, mask, case_sensitive, False)) continue;
2880 error = ERRnoaccess;
2881 sprintf(fname,"%s/%s",directory,dname);
2882 strcpy(destname,newname);
2883 if (resolve_wildcards(fname,destname) &&
2884 copy_file(directory,newname,cnum,ofun,
2885 count,target_is_directory)) count++;
2886 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
2888 CloseDir(dirptr);
2892 if (count == 0) {
2893 if (exists)
2894 return(ERROR(ERRDOS,error));
2895 else
2896 return(UNIXERROR(ERRDOS,error));
2899 outsize = set_message(outbuf,1,0,True);
2900 SSVAL(outbuf,smb_vwv0,count);
2902 return(outsize);
2907 /****************************************************************************
2908 reply to a setdir
2909 ****************************************************************************/
2910 int reply_setdir(char *inbuf,char *outbuf)
2912 int cnum,snum;
2913 int outsize = 0;
2914 BOOL ok = False;
2915 pstring newdir;
2917 cnum = SVAL(inbuf,smb_tid);
2919 snum = Connections[cnum].service;
2920 if (!CAN_SETDIR(snum))
2921 return(ERROR(ERRDOS,ERRnoaccess));
2923 strcpy(newdir,smb_buf(inbuf) + 1);
2924 strlower(newdir);
2926 if (strlen(newdir) == 0)
2927 ok = True;
2928 else
2930 ok = directory_exist(newdir,NULL);
2931 if (ok)
2932 string_set(&Connections[cnum].connectpath,newdir);
2935 if (!ok)
2936 return(ERROR(ERRDOS,ERRbadpath));
2938 outsize = set_message(outbuf,0,0,True);
2939 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
2941 DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum));
2943 return(outsize);
2947 /****************************************************************************
2948 reply to a lockingX request
2949 ****************************************************************************/
2950 int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
2952 int fnum = GETFNUM(inbuf,smb_vwv2);
2953 uint16 locktype = SVAL(inbuf,smb_vwv3);
2954 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
2955 uint16 num_locks = SVAL(inbuf,smb_vwv7);
2956 uint32 count, offset;
2958 int cnum;
2959 int i;
2960 char *data;
2961 uint32 ecode=0, dummy2;
2962 int eclass=0, dummy1;
2964 cnum = SVAL(inbuf,smb_tid);
2966 CHECK_FNUM(fnum,cnum);
2967 CHECK_ERROR(fnum);
2969 data = smb_buf(inbuf);
2970 /* Data now points at the beginning of the list
2971 of smb_unlkrng structs */
2972 for(i = 0; i < (int)num_ulocks; i++) {
2973 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2974 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2975 if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode))
2976 return ERROR(eclass,ecode);
2979 /* Now do any requested locks */
2980 data += 10*num_ulocks;
2981 /* Data now points at the beginning of the list
2982 of smb_lkrng structs */
2983 for(i = 0; i < (int)num_locks; i++) {
2984 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2985 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2986 if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode))
2987 break;
2990 /* If any of the above locks failed, then we must unlock
2991 all of the previous locks (X/Open spec). */
2992 if(i != num_locks && num_locks != 0) {
2993 for(; i >= 0; i--) {
2994 count = IVAL(data,SMB_LKLEN_OFFSET(i));
2995 offset = IVAL(data,SMB_LKOFF_OFFSET(i));
2996 do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2);
2998 return ERROR(eclass,ecode);
3001 set_message(outbuf,2,0,True);
3003 DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3004 timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
3006 chain_fnum = fnum;
3008 return chain_reply(inbuf,outbuf,length,bufsize);
3012 /****************************************************************************
3013 reply to a SMBreadbmpx (read block multiplex) request
3014 ****************************************************************************/
3015 int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
3017 int cnum,fnum;
3018 int nread = -1;
3019 int total_read;
3020 char *data;
3021 int32 startpos;
3022 int outsize, mincount, maxcount;
3023 int max_per_packet;
3024 int tcount;
3025 int pad;
3027 /* this function doesn't seem to work - disable by default */
3028 if (!lp_readbmpx())
3029 return(ERROR(ERRSRV,ERRuseSTD));
3031 outsize = set_message(outbuf,8,0,True);
3033 cnum = SVAL(inbuf,smb_tid);
3034 fnum = GETFNUM(inbuf,smb_vwv0);
3036 CHECK_FNUM(fnum,cnum);
3037 CHECK_READ(fnum);
3038 CHECK_ERROR(fnum);
3040 startpos = IVAL(inbuf,smb_vwv1);
3041 maxcount = SVAL(inbuf,smb_vwv3);
3042 mincount = SVAL(inbuf,smb_vwv4);
3044 data = smb_buf(outbuf);
3045 pad = ((int)data)%4;
3046 if (pad) pad = 4 - pad;
3047 data += pad;
3049 max_per_packet = bufsize-(outsize+pad);
3050 tcount = maxcount;
3051 total_read = 0;
3053 if (is_locked(fnum,cnum,maxcount,startpos))
3054 return(ERROR(ERRDOS,ERRlock));
3058 int N = MIN(max_per_packet,tcount-total_read);
3060 nread = read_file(fnum,data,startpos,N);
3062 if (nread <= 0) nread = 0;
3064 if (nread < N)
3065 tcount = total_read + nread;
3067 set_message(outbuf,8,nread,False);
3068 SIVAL(outbuf,smb_vwv0,startpos);
3069 SSVAL(outbuf,smb_vwv2,tcount);
3070 SSVAL(outbuf,smb_vwv6,nread);
3071 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3073 send_smb(Client,outbuf);
3075 total_read += nread;
3076 startpos += nread;
3078 while (total_read < tcount);
3080 return(-1);
3084 /****************************************************************************
3085 reply to a SMBwritebmpx (write block multiplex primary) request
3086 ****************************************************************************/
3087 int reply_writebmpx(char *inbuf,char *outbuf)
3089 int cnum,numtowrite,fnum;
3090 int nwritten = -1;
3091 int outsize = 0;
3092 int32 startpos;
3093 int tcount, write_through, smb_doff;
3094 char *data;
3096 cnum = SVAL(inbuf,smb_tid);
3097 fnum = GETFNUM(inbuf,smb_vwv0);
3099 CHECK_FNUM(fnum,cnum);
3100 CHECK_WRITE(fnum);
3101 CHECK_ERROR(fnum);
3103 tcount = SVAL(inbuf,smb_vwv1);
3104 startpos = IVAL(inbuf,smb_vwv3);
3105 write_through = BITSETW(inbuf+smb_vwv7,0);
3106 numtowrite = SVAL(inbuf,smb_vwv10);
3107 smb_doff = SVAL(inbuf,smb_vwv11);
3109 data = smb_base(inbuf) + smb_doff;
3111 /* If this fails we need to send an SMBwriteC response,
3112 not an SMBwritebmpx - set this up now so we don't forget */
3113 CVAL(outbuf,smb_com) = SMBwritec;
3115 if (is_locked(fnum,cnum,tcount,startpos))
3116 return(ERROR(ERRDOS,ERRlock));
3118 seek_file(fnum,startpos);
3119 nwritten = write_file(fnum,data,numtowrite);
3121 if(lp_syncalways(SNUM(cnum)) || write_through)
3122 sync_file(fnum);
3124 if(nwritten < numtowrite)
3125 return(UNIXERROR(ERRHRD,ERRdiskfull));
3127 /* If the maximum to be written to this file
3128 is greater than what we just wrote then set
3129 up a secondary struct to be attached to this
3130 fd, we will use this to cache error messages etc. */
3131 if(tcount > nwritten)
3133 write_bmpx_struct *wbms;
3134 if(Files[fnum].wbmpx_ptr != NULL)
3135 wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */
3136 else
3137 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
3138 if(!wbms)
3140 DEBUG(0,("Out of memory in reply_readmpx\n"));
3141 return(ERROR(ERRSRV,ERRnoresource));
3143 wbms->wr_mode = write_through;
3144 wbms->wr_discard = False; /* No errors yet */
3145 wbms->wr_total_written = nwritten;
3146 wbms->wr_errclass = 0;
3147 wbms->wr_error = 0;
3148 Files[fnum].wbmpx_ptr = wbms;
3151 /* We are returning successfully, set the message type back to
3152 SMBwritebmpx */
3153 CVAL(outbuf,smb_com) = SMBwriteBmpx;
3155 outsize = set_message(outbuf,1,0,True);
3157 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
3159 DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n",
3160 timestring(),fnum,cnum,numtowrite,nwritten));
3162 if (write_through && tcount==nwritten) {
3163 /* we need to send both a primary and a secondary response */
3164 smb_setlen(outbuf,outsize - 4);
3165 send_smb(Client,outbuf);
3167 /* now the secondary */
3168 outsize = set_message(outbuf,1,0,True);
3169 CVAL(outbuf,smb_com) = SMBwritec;
3170 SSVAL(outbuf,smb_vwv0,nwritten);
3173 return(outsize);
3177 /****************************************************************************
3178 reply to a SMBwritebs (write block multiplex secondary) request
3179 ****************************************************************************/
3180 int reply_writebs(char *inbuf,char *outbuf)
3182 int cnum,numtowrite,fnum;
3183 int nwritten = -1;
3184 int outsize = 0;
3185 int32 startpos;
3186 int tcount, write_through, smb_doff;
3187 char *data;
3188 write_bmpx_struct *wbms;
3189 BOOL send_response = False;
3191 cnum = SVAL(inbuf,smb_tid);
3192 fnum = GETFNUM(inbuf,smb_vwv0);
3193 CHECK_FNUM(fnum,cnum);
3194 CHECK_WRITE(fnum);
3196 tcount = SVAL(inbuf,smb_vwv1);
3197 startpos = IVAL(inbuf,smb_vwv2);
3198 numtowrite = SVAL(inbuf,smb_vwv6);
3199 smb_doff = SVAL(inbuf,smb_vwv7);
3201 data = smb_base(inbuf) + smb_doff;
3203 /* We need to send an SMBwriteC response, not an SMBwritebs */
3204 CVAL(outbuf,smb_com) = SMBwritec;
3206 /* This fd should have an auxiliary struct attached,
3207 check that it does */
3208 wbms = Files[fnum].wbmpx_ptr;
3209 if(!wbms) return(-1);
3211 /* If write through is set we can return errors, else we must
3212 cache them */
3213 write_through = wbms->wr_mode;
3215 /* Check for an earlier error */
3216 if(wbms->wr_discard)
3217 return -1; /* Just discard the packet */
3219 seek_file(fnum,startpos);
3220 nwritten = write_file(fnum,data,numtowrite);
3222 if(lp_syncalways(SNUM(cnum)) || write_through)
3223 sync_file(fnum);
3225 if (nwritten < numtowrite)
3227 if(write_through) {
3228 /* We are returning an error - we can delete the aux struct */
3229 if (wbms) free((char *)wbms);
3230 Files[fnum].wbmpx_ptr = NULL;
3231 return(ERROR(ERRHRD,ERRdiskfull));
3233 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
3236 /* Increment the total written, if this matches tcount
3237 we can discard the auxiliary struct (hurrah !) and return a writeC */
3238 wbms->wr_total_written += nwritten;
3239 if(wbms->wr_total_written >= tcount)
3241 if (write_through) {
3242 outsize = set_message(outbuf,1,0,True);
3243 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
3244 send_response = True;
3247 free((char *)wbms);
3248 Files[fnum].wbmpx_ptr = NULL;
3251 if(send_response)
3252 return(outsize);
3254 return(-1);
3258 /****************************************************************************
3259 reply to a SMBsetattrE
3260 ****************************************************************************/
3261 int reply_setattrE(char *inbuf,char *outbuf)
3263 int cnum,fnum;
3264 struct utimbuf unix_times;
3265 int outsize = 0;
3267 outsize = set_message(outbuf,0,0,True);
3269 cnum = SVAL(inbuf,smb_tid);
3270 fnum = GETFNUM(inbuf,smb_vwv0);
3272 CHECK_FNUM(fnum,cnum);
3273 CHECK_ERROR(fnum);
3275 /* Convert the DOS times into unix times. Ignore create
3276 time as UNIX can't set this.
3278 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3279 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3281 /* Set the date on this file */
3282 if(sys_utime(Files[fnum].name, &unix_times))
3283 return(ERROR(ERRDOS,ERRnoaccess));
3285 DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3287 return(outsize);
3291 /****************************************************************************
3292 reply to a SMBgetattrE
3293 ****************************************************************************/
3294 int reply_getattrE(char *inbuf,char *outbuf)
3296 int cnum,fnum;
3297 struct stat sbuf;
3298 int outsize = 0;
3299 int mode;
3301 outsize = set_message(outbuf,11,0,True);
3303 cnum = SVAL(inbuf,smb_tid);
3304 fnum = GETFNUM(inbuf,smb_vwv0);
3306 CHECK_FNUM(fnum,cnum);
3307 CHECK_ERROR(fnum);
3309 /* Do an fstat on this file */
3310 if(fstat(Files[fnum].fd_ptr->fd, &sbuf))
3311 return(UNIXERROR(ERRDOS,ERRnoaccess));
3313 mode = dos_mode(cnum,Files[fnum].name,&sbuf);
3315 /* Convert the times into dos times. Set create
3316 date to be last modify date as UNIX doesn't save
3317 this */
3318 put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
3319 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
3320 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
3321 if (mode & aDIR)
3323 SIVAL(outbuf,smb_vwv6,0);
3324 SIVAL(outbuf,smb_vwv8,0);
3326 else
3328 SIVAL(outbuf,smb_vwv6,sbuf.st_size);
3329 SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024));
3331 SSVAL(outbuf,smb_vwv10, mode);
3333 DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum));
3335 return(outsize);