14fa26dd5595862bad3dec46aae1e7373ad6ae85
[kai/samba.git] / source3 / smbd / trans2.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB transaction2 handling
5    Copyright (C) Jeremy Allison 1994-1998
6
7    Extensively modified by Andrew Tridgell, 1995
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "trans2.h"
26
27 extern int DEBUGLEVEL;
28 extern int Protocol;
29 extern BOOL case_sensitive;
30 extern int Client;
31 extern int smb_read_error;
32 extern fstring local_machine;
33 extern int global_oplock_break;
34 extern dfs_internal dfs_struct;
35
36 /****************************************************************************
37   Send the required number of replies back.
38   We assume all fields other than the data fields are
39   set correctly for the type of call.
40   HACK ! Always assumes smb_setup field is zero.
41 ****************************************************************************/
42 static int send_trans2_replies(char *outbuf, int bufsize, char *params, 
43                                int paramsize, char *pdata, int datasize)
44 {
45   /* As we are using a protocol > LANMAN1 then the max_send
46      variable must have been set in the sessetupX call.
47      This takes precedence over the max_xmit field in the
48      global struct. These different max_xmit variables should
49      be merged as this is now too confusing */
50
51   extern int max_send;
52   int data_to_send = datasize;
53   int params_to_send = paramsize;
54   int useable_space;
55   char *pp = params;
56   char *pd = pdata;
57   int params_sent_thistime, data_sent_thistime, total_sent_thistime;
58   int alignment_offset = 3;
59   int data_alignment_offset = 0;
60
61   /* Initially set the wcnt area to be 10 - this is true for all
62      trans2 replies */
63   set_message(outbuf,10,0,True);
64
65   /* If there genuinely are no parameters or data to send just send
66      the empty packet */
67   if(params_to_send == 0 && data_to_send == 0)
68   {
69     send_smb(Client,outbuf);
70     return 0;
71   }
72
73   /* When sending params and data ensure that both are nicely aligned */
74   /* Only do this alignment when there is also data to send - else
75      can cause NT redirector problems. */
76   if (((params_to_send % 4) != 0) && (data_to_send != 0))
77     data_alignment_offset = 4 - (params_to_send % 4);
78
79   /* Space is bufsize minus Netbios over TCP header minus SMB header */
80   /* The alignment_offset is to align the param bytes on an even byte
81      boundary. NT 4.0 Beta needs this to work correctly. */
82   useable_space = bufsize - ((smb_buf(outbuf)+
83                     alignment_offset+data_alignment_offset) - 
84                     outbuf);
85
86   /* useable_space can never be more than max_send minus the
87      alignment offset. */
88   useable_space = MIN(useable_space, 
89                       max_send - (alignment_offset+data_alignment_offset));
90
91
92   while (params_to_send || data_to_send)
93   {
94     /* Calculate whether we will totally or partially fill this packet */
95     total_sent_thistime = params_to_send + data_to_send + 
96                             alignment_offset + data_alignment_offset;
97     /* We can never send more than useable_space */
98     total_sent_thistime = MIN(total_sent_thistime, useable_space);
99
100     set_message(outbuf, 10, total_sent_thistime, True);
101
102     /* Set total params and data to be sent */
103     SSVAL(outbuf,smb_tprcnt,paramsize);
104     SSVAL(outbuf,smb_tdrcnt,datasize);
105
106     /* Calculate how many parameters and data we can fit into
107        this packet. Parameters get precedence */
108
109     params_sent_thistime = MIN(params_to_send,useable_space);
110     data_sent_thistime = useable_space - params_sent_thistime;
111     data_sent_thistime = MIN(data_sent_thistime,data_to_send);
112
113     SSVAL(outbuf,smb_prcnt, params_sent_thistime);
114     if(params_sent_thistime == 0)
115     {
116       /*SSVAL(outbuf,smb_proff,0);*/
117       SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
118       SSVAL(outbuf,smb_prdisp,0);
119     }
120     else
121     {
122       /* smb_proff is the offset from the start of the SMB header to the
123          parameter bytes, however the first 4 bytes of outbuf are
124          the Netbios over TCP header. Thus use smb_base() to subtract
125          them from the calculation */
126       SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
127       /* Absolute displacement of param bytes sent in this packet */
128       SSVAL(outbuf,smb_prdisp,pp - params);
129     }
130
131     SSVAL(outbuf,smb_drcnt, data_sent_thistime);
132     if(data_sent_thistime == 0)
133     {
134       SSVAL(outbuf,smb_droff,0);
135       SSVAL(outbuf,smb_drdisp, 0);
136     }
137     else
138     {
139       /* The offset of the data bytes is the offset of the
140          parameter bytes plus the number of parameters being sent this time */
141       SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
142             smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
143       SSVAL(outbuf,smb_drdisp, pd - pdata);
144     }
145
146     /* Copy the param bytes into the packet */
147     if(params_sent_thistime)
148       memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
149     /* Copy in the data bytes */
150     if(data_sent_thistime)
151       memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
152              data_alignment_offset,pd,data_sent_thistime);
153
154     DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
155           params_sent_thistime, data_sent_thistime, useable_space));
156     DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
157           params_to_send, data_to_send, paramsize, datasize));
158
159     /* Send the packet */
160     send_smb(Client,outbuf);
161
162     pp += params_sent_thistime;
163     pd += data_sent_thistime;
164
165     params_to_send -= params_sent_thistime;
166     data_to_send -= data_sent_thistime;
167
168     /* Sanity check */
169     if(params_to_send < 0 || data_to_send < 0)
170     {
171       DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
172             params_to_send, data_to_send));
173       return -1;
174     }
175   }
176
177   return 0;
178 }
179
180
181 /****************************************************************************
182   reply to a TRANSACT2_OPEN
183 ****************************************************************************/
184 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, 
185                            int bufsize,  
186                            char **pparams, char **ppdata)
187 {
188   char *params = *pparams;
189   int16 open_mode = SVAL(params, 2);
190   int16 open_attr = SVAL(params,6);
191   BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
192 #if 0
193   BOOL return_additional_info = BITSETW(params,0);
194   int16 open_sattr = SVAL(params, 4);
195   time_t open_time = make_unix_date3(params+8);
196 #endif
197   int16 open_ofun = SVAL(params,12);
198   int32 open_size = IVAL(params,14);
199   char *pname = &params[28];
200   int16 namelen = strlen(pname)+1;
201
202   pstring fname;
203   mode_t unixmode;
204   SMB_OFF_T size=0;
205   int fmode=0,mtime=0,rmode;
206   SMB_INO_T inode = 0;
207   SMB_STRUCT_STAT sbuf;
208   int smb_action = 0;
209   BOOL bad_path = False;
210   files_struct *fsp;
211
212   StrnCpy(fname,pname,namelen);
213
214   DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
215            fname,open_mode, open_attr, open_ofun, open_size));
216
217   /* XXXX we need to handle passed times, sattr and flags */
218
219   if (!unix_dfs_convert(fname,conn,0,&bad_path,NULL))
220         {
221                 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
222                 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
223         }
224     
225   fsp = file_new();
226   if (!fsp)
227     return(ERROR(ERRSRV,ERRnofids));
228
229   if (!check_name(fname,conn))
230   {
231     if((errno == ENOENT) && bad_path)
232     {
233       unix_ERR_class = ERRDOS;
234       unix_ERR_code = ERRbadpath;
235     }
236     file_free(fsp);
237     return(UNIXERROR(ERRDOS,ERRnoaccess));
238   }
239
240   unixmode = unix_mode(conn,open_attr | aARCH);
241       
242   open_file_shared(fsp,conn,fname,open_mode,open_ofun,unixmode,
243                    oplock_request, &rmode,&smb_action);
244       
245   if (!fsp->open)
246   {
247     if((errno == ENOENT) && bad_path)
248     {
249       unix_ERR_class = ERRDOS;
250       unix_ERR_code = ERRbadpath;
251     }
252     file_free(fsp);
253     return(UNIXERROR(ERRDOS,ERRnoaccess));
254   }
255
256   if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
257     close_file(fsp,False);
258     return(UNIXERROR(ERRDOS,ERRnoaccess));
259   }
260     
261   size = sbuf.st_size;
262   fmode = dos_mode(conn,fname,&sbuf);
263   mtime = sbuf.st_mtime;
264   inode = sbuf.st_ino;
265   if (fmode & aDIR) {
266     close_file(fsp,False);
267     return(ERROR(ERRDOS,ERRnoaccess));
268   }
269
270   /* Realloc the size of parameters and data we will return */
271   params = *pparams = Realloc(*pparams, 28);
272   if(params == NULL)
273     return(ERROR(ERRDOS,ERRnomem));
274
275   bzero(params,28);
276   SSVAL(params,0,fsp->fnum);
277   SSVAL(params,2,fmode);
278   put_dos_date2(params,4, mtime);
279   SIVAL(params,8, (uint32)size);
280   SSVAL(params,12,rmode);
281
282   if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
283     smb_action |= EXTENDED_OPLOCK_GRANTED;
284   }
285
286   SSVAL(params,18,smb_action);
287   /*
288    * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
289    */
290   SIVAL(params,20,inode);
291  
292   /* Send the required number of replies */
293   send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
294
295   return -1;
296 }
297
298 /****************************************************************************
299   get a level dependent lanman2 dir entry.
300 ****************************************************************************/
301 static int get_lanman2_dir_entry(connection_struct *conn,
302                                  char *path_mask,int dirtype,int info_level,
303                                  int requires_resume_key,
304                                  BOOL dont_descend,char **ppdata, 
305                                  char *base_data, int space_remaining, 
306                                  BOOL *out_of_space,
307                                  int *last_name_off)
308 {
309   char *dname;
310   BOOL found = False;
311   SMB_STRUCT_STAT sbuf;
312   pstring mask;
313   pstring pathreal;
314   pstring fname;
315   char *p, *pdata = *ppdata;
316   uint32 reskey=0;
317   int prev_dirpos=0;
318   int mode=0;
319   SMB_OFF_T size = 0;
320   uint32 len;
321   time_t mdate=0, adate=0, cdate=0;
322   char *nameptr;
323   BOOL isrootdir = (strequal(conn->dirpath,"./") ||
324                     strequal(conn->dirpath,".") ||
325                     strequal(conn->dirpath,"/"));
326   BOOL was_8_3;
327   int nt_extmode; /* Used for NT connections instead of mode */
328   BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
329
330   *fname = 0;
331   *out_of_space = False;
332
333   if (!conn->dirptr)
334     return(False);
335
336   p = strrchr(path_mask,'/');
337   if(p != NULL)
338   {
339     if(p[1] == '\0')
340       pstrcpy(mask,"*.*");
341     else
342       pstrcpy(mask, p+1);
343   }
344   else
345     pstrcpy(mask, path_mask);
346
347   while (!found)
348   {
349     /* Needed if we run out of space */
350     prev_dirpos = TellDir(conn->dirptr);
351     dname = ReadDirName(conn->dirptr);
352
353     /*
354      * Due to bugs in NT client redirectors we are not using
355      * resume keys any more - set them to zero.
356      * Check out the related comments in findfirst/findnext.
357      * JRA.
358      */
359
360     reskey = 0;
361
362     DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
363       (long)conn->dirptr,TellDir(conn->dirptr)));
364       
365     if (!dname) 
366       return(False);
367
368     pstrcpy(fname,dname);      
369
370     if(mask_match(fname, mask, case_sensitive, True))
371     {
372       BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
373       if (dont_descend && !isdots)
374         continue;
375           
376       if (isrootdir && isdots)
377         continue;
378
379       pstrcpy(pathreal,conn->dirpath);
380       if(needslash)
381         pstrcat(pathreal,"/");
382       pstrcat(pathreal,dname);
383       if (conn->vfs_ops.stat(dos_to_unix(pathreal,False),&sbuf) != 0) 
384       {
385         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
386         continue;
387       }
388
389       mode = dos_mode(conn,pathreal,&sbuf);
390
391       if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
392         DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
393         continue;
394       }
395
396       size = sbuf.st_size;
397       mdate = sbuf.st_mtime;
398       adate = sbuf.st_atime;
399       cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
400       if(mode & aDIR)
401         size = 0;
402
403       DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
404           
405       found = True;
406     }
407   }
408
409   name_map_mangle(fname,False,SNUM(conn));
410
411   p = pdata;
412   nameptr = p;
413
414   nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
415
416   switch (info_level)
417   {
418     case 1:
419       if(requires_resume_key) {
420         SIVAL(p,0,reskey);
421         p += 4;
422       }
423       put_dos_date2(p,l1_fdateCreation,cdate);
424       put_dos_date2(p,l1_fdateLastAccess,adate);
425       put_dos_date2(p,l1_fdateLastWrite,mdate);
426       SIVAL(p,l1_cbFile,(uint32)size);
427       SIVAL(p,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
428       SSVAL(p,l1_attrFile,mode);
429       SCVAL(p,l1_cchName,strlen(fname));
430       pstrcpy(p + l1_achName, fname);
431       nameptr = p + l1_achName;
432       p += l1_achName + strlen(fname) + 1;
433       break;
434
435     case 2:
436       /* info_level 2 */
437       if(requires_resume_key) {
438         SIVAL(p,0,reskey);
439         p += 4;
440       }
441       put_dos_date2(p,l2_fdateCreation,cdate);
442       put_dos_date2(p,l2_fdateLastAccess,adate);
443       put_dos_date2(p,l2_fdateLastWrite,mdate);
444       SIVAL(p,l2_cbFile,(uint32)size);
445       SIVAL(p,l2_cbFileAlloc,SMB_ROUNDUP(size,1024));
446       SSVAL(p,l2_attrFile,mode);
447       SIVAL(p,l2_cbList,0); /* No extended attributes */
448       SCVAL(p,l2_cchName,strlen(fname));
449       pstrcpy(p + l2_achName, fname);
450       nameptr = p + l2_achName;
451       p += l2_achName + strlen(fname) + 1;
452       break;
453
454     case 3:
455       SIVAL(p,0,reskey);
456       put_dos_date2(p,4,cdate);
457       put_dos_date2(p,8,adate);
458       put_dos_date2(p,12,mdate);
459       SIVAL(p,16,(uint32)size);
460       SIVAL(p,20,SMB_ROUNDUP(size,1024));
461       SSVAL(p,24,mode);
462       SIVAL(p,26,4);
463       CVAL(p,30) = strlen(fname);
464       pstrcpy(p+31, fname);
465       nameptr = p+31;
466       p += 31 + strlen(fname) + 1;
467       break;
468
469     case 4:
470       if(requires_resume_key) {
471         SIVAL(p,0,reskey);
472         p += 4;
473       }
474       SIVAL(p,0,33+strlen(fname)+1);
475       put_dos_date2(p,4,cdate);
476       put_dos_date2(p,8,adate);
477       put_dos_date2(p,12,mdate);
478       SIVAL(p,16,(uint32)size);
479       SIVAL(p,20,SMB_ROUNDUP(size,1024));
480       SSVAL(p,24,mode);
481       CVAL(p,32) = strlen(fname);
482       pstrcpy(p + 33, fname);
483       nameptr = p+33;
484       p += 33 + strlen(fname) + 1;
485       break;
486
487     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
488       was_8_3 = is_8_3(fname, True);
489       len = 94+strlen(fname);
490       len = (len + 3) & ~3;
491       SIVAL(p,0,len); p += 4;
492       SIVAL(p,0,reskey); p += 4;
493       put_long_date(p,cdate); p += 8;
494       put_long_date(p,adate); p += 8;
495       put_long_date(p,mdate); p += 8;
496       put_long_date(p,mdate); p += 8;
497       SOFF_T(p,0,size);
498       SOFF_T(p,8,size);
499       p += 16;
500       SIVAL(p,0,nt_extmode); p += 4;
501       SIVAL(p,0,strlen(fname)); p += 4;
502       SIVAL(p,0,0); p += 4;
503       if (!was_8_3) {
504         pstrcpy(p+2,fname);
505         if (!name_map_mangle(p+2,True,SNUM(conn)))
506           (p+2)[12] = 0;
507       } else
508         *(p+2) = 0;
509       strupper(p+2);
510       SSVAL(p,0,strlen(p+2));
511       p += 2 + 24;
512       /* nameptr = p;  */
513       pstrcpy(p,fname); p += strlen(p);
514       p = pdata + len;
515       break;
516
517     case SMB_FIND_FILE_DIRECTORY_INFO:
518       len = 64+strlen(fname);
519       len = (len + 3) & ~3;
520       SIVAL(p,0,len); p += 4;
521       SIVAL(p,0,reskey); p += 4;
522       put_long_date(p,cdate); p += 8;
523       put_long_date(p,adate); p += 8;
524       put_long_date(p,mdate); p += 8;
525       put_long_date(p,mdate); p += 8;
526       SOFF_T(p,0,size);
527       SOFF_T(p,8,size);
528       p += 16;
529       SIVAL(p,0,nt_extmode); p += 4;
530       SIVAL(p,0,strlen(fname)); p += 4;
531       pstrcpy(p,fname);
532       p = pdata + len;
533       break;
534       
535       
536     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
537       len = 68+strlen(fname);
538       len = (len + 3) & ~3;
539       SIVAL(p,0,len); p += 4;
540       SIVAL(p,0,reskey); p += 4;
541       put_long_date(p,cdate); p += 8;
542       put_long_date(p,adate); p += 8;
543       put_long_date(p,mdate); p += 8;
544       put_long_date(p,mdate); p += 8;
545       SOFF_T(p,0,size); 
546       SOFF_T(p,8,size);
547       p += 16;
548       SIVAL(p,0,nt_extmode); p += 4;
549       SIVAL(p,0,strlen(fname)); p += 4;
550       SIVAL(p,0,0); p += 4;
551       pstrcpy(p,fname);
552       p = pdata + len;
553       break;
554
555     case SMB_FIND_FILE_NAMES_INFO:
556       len = 12+strlen(fname);
557       len = (len + 3) & ~3;
558       SIVAL(p,0,len); p += 4;
559       SIVAL(p,0,reskey); p += 4;
560       SIVAL(p,0,strlen(fname)); p += 4;
561       pstrcpy(p,fname);
562       p = pdata + len;
563       break;
564
565     default:      
566       return(False);
567     }
568
569
570   if (PTR_DIFF(p,pdata) > space_remaining) {
571     /* Move the dirptr back to prev_dirpos */
572     SeekDir(conn->dirptr, prev_dirpos);
573     *out_of_space = True;
574     DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
575     return False; /* Not finished - just out of space */
576   }
577
578   /* Setup the last_filename pointer, as an offset from base_data */
579   *last_name_off = PTR_DIFF(nameptr,base_data);
580   /* Advance the data pointer to the next slot */
581   *ppdata = p;
582   return(found);
583 }
584   
585 /****************************************************************************
586  Convert the directory masks formated for the wire.
587 ****************************************************************************/
588
589 void mask_convert( char *mask)
590 {
591   /*
592    * We know mask is a pstring.
593    */
594   char *p = mask;
595   while (*p) {
596     if (*p == '<') {
597       pstring expnd;
598       if(p[1] != '"' && p[1] != '.') {
599         pstrcpy( expnd, p+1 );
600         *p++ = '*';
601         *p = '.';
602         safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2);
603       } else
604         *p = '*';
605     }
606     if (*p == '>') *p = '?';
607     if (*p == '"') *p = '.';
608     p++;
609   }
610 }
611
612 /****************************************************************************
613   reply to a TRANS2_FINDFIRST
614 ****************************************************************************/
615 static int call_trans2findfirst(connection_struct *conn,
616                                 char *inbuf, char *outbuf, int bufsize,  
617                                 char **pparams, char **ppdata)
618 {
619   /* We must be careful here that we don't return more than the
620      allowed number of data bytes. If this means returning fewer than
621      maxentries then so be it. We assume that the redirector has
622      enough room for the fixed number of parameter bytes it has
623      requested. */
624   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
625   char *params = *pparams;
626   char *pdata = *ppdata;
627   int dirtype = SVAL(params,0);
628   int maxentries = SVAL(params,2);
629   BOOL close_after_first = BITSETW(params+4,0);
630   BOOL close_if_end = BITSETW(params+4,1);
631   BOOL requires_resume_key = BITSETW(params+4,2);
632   int info_level = SVAL(params,6);
633   pstring directory;
634   pstring mask;
635   char *p, *wcard;
636   int last_name_off=0;
637   int dptr_num = -1;
638   int numentries = 0;
639   int i;
640   BOOL finished = False;
641   BOOL dont_descend = False;
642   BOOL out_of_space = False;
643   int space_remaining;
644   BOOL bad_path = False;
645
646   *directory = *mask = 0;
647
648   DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
649            dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
650            info_level, max_data_bytes));
651   
652   switch (info_level) 
653     {
654     case 1:
655     case 2:
656     case 3:
657     case 4:
658     case SMB_FIND_FILE_DIRECTORY_INFO:
659     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
660     case SMB_FIND_FILE_NAMES_INFO:
661     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
662       break;
663     default:
664       return(ERROR(ERRDOS,ERRunknownlevel));
665     }
666
667   pstrcpy(directory, params + 12); /* Complete directory path with 
668                                      wildcard mask appended */
669
670   DEBUG(5,("path=%s\n",directory));
671
672   if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL))
673         {
674                 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
675                 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
676         }
677   if(!check_name(directory,conn)) {
678     if((errno == ENOENT) && bad_path)
679     {
680       unix_ERR_class = ERRDOS;
681       unix_ERR_code = ERRbadpath;
682     }
683
684 #if 0
685     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
686     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
687        (get_remote_arch() == RA_WINNT))
688     {
689       unix_ERR_class = ERRDOS;
690       unix_ERR_code = ERRbaddirectory;
691     }
692 #endif 
693
694     return(UNIXERROR(ERRDOS,ERRbadpath));
695   }
696
697   p = strrchr(directory,'/');
698   if(p == NULL) {
699     pstrcpy(mask,directory);
700     pstrcpy(directory,"./");
701   } else {
702     pstrcpy(mask,p+1);
703     *p = 0;
704   }
705
706   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
707
708   pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
709   if(!*ppdata)
710     return(ERROR(ERRDOS,ERRnomem));
711   bzero(pdata,max_data_bytes);
712
713   /* Realloc the params space */
714   params = *pparams = Realloc(*pparams, 10);
715   if(params == NULL)
716     return(ERROR(ERRDOS,ERRnomem));
717
718   dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid));
719   if (dptr_num < 0)
720     return(UNIXERROR(ERRDOS,ERRbadfile));
721
722   /* Convert the formatted mask. */
723   mask_convert(mask);
724
725 #if 0 /* JRA */
726   /*
727    * Now we have a working mask_match in util.c, I believe
728    * we no longer need these hacks (in fact they break
729    * things). JRA. 
730    */
731
732   /* a special case for 16 bit apps */
733   if (strequal(mask,"????????.???")) pstrcpy(mask,"*");
734
735   /* handle broken clients that send us old 8.3 format */
736   string_sub(mask,"????????","*");
737   string_sub(mask,".???",".*");
738 #endif /* JRA */
739
740   /* Save the wildcard match and attribs we are using on this directory - 
741      needed as lanman2 assumes these are being saved between calls */
742
743   if(!(wcard = strdup(mask))) {
744     dptr_close(dptr_num);
745     return(ERROR(ERRDOS,ERRnomem));
746   }
747
748   dptr_set_wcard(dptr_num, wcard);
749   dptr_set_attr(dptr_num, dirtype);
750
751   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
752
753   /* We don't need to check for VOL here as this is returned by 
754      a different TRANS2 call. */
755   
756   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
757            conn->dirpath,lp_dontdescend(SNUM(conn))));
758   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
759     dont_descend = True;
760     
761   p = pdata;
762   space_remaining = max_data_bytes;
763   out_of_space = False;
764
765   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
766     {
767
768       /* this is a heuristic to avoid seeking the dirptr except when 
769          absolutely necessary. It allows for a filename of about 40 chars */
770       if (space_remaining < DIRLEN_GUESS && numentries > 0)
771         {
772           out_of_space = True;
773           finished = False;
774         }
775       else
776         {
777           finished = 
778             !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
779                                    requires_resume_key,dont_descend,
780                                    &p,pdata,space_remaining, &out_of_space,
781                                    &last_name_off);
782         }
783
784       if (finished && out_of_space)
785         finished = False;
786
787       if (!finished && !out_of_space)
788         numentries++;
789       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
790     }
791   
792   /* Check if we can close the dirptr */
793   if(close_after_first || (finished && close_if_end))
794     {
795       dptr_close(dptr_num);
796       DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
797       dptr_num = -1;
798     }
799
800   /* 
801    * If there are no matching entries we must return ERRDOS/ERRbadfile - 
802    * from observation of NT.
803    */
804
805   if(numentries == 0)
806     return(ERROR(ERRDOS,ERRbadfile));
807
808   /* At this point pdata points to numentries directory entries. */
809
810   /* Set up the return parameter block */
811   SSVAL(params,0,dptr_num);
812   SSVAL(params,2,numentries);
813   SSVAL(params,4,finished);
814   SSVAL(params,6,0); /* Never an EA error */
815   SSVAL(params,8,last_name_off);
816
817   send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
818
819   if ((! *directory) && dptr_path(dptr_num))
820     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
821
822   DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
823             smb_fn_name(CVAL(inbuf,smb_com)), 
824             mask, directory, dirtype, numentries ) );
825
826   return(-1);
827 }
828
829
830 /****************************************************************************
831   reply to a TRANS2_FINDNEXT
832 ****************************************************************************/
833 static int call_trans2findnext(connection_struct *conn, 
834                                char *inbuf, char *outbuf, 
835                                int length, int bufsize,
836                                char **pparams, char **ppdata)
837 {
838   /* We must be careful here that we don't return more than the
839      allowed number of data bytes. If this means returning fewer than
840      maxentries then so be it. We assume that the redirector has
841      enough room for the fixed number of parameter bytes it has
842      requested. */
843   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
844   char *params = *pparams;
845   char *pdata = *ppdata;
846   int16 dptr_num = SVAL(params,0);
847   int maxentries = SVAL(params,2);
848   uint16 info_level = SVAL(params,4);
849   uint32 resume_key = IVAL(params,6);
850   BOOL close_after_request = BITSETW(params+10,0);
851   BOOL close_if_end = BITSETW(params+10,1);
852   BOOL requires_resume_key = BITSETW(params+10,2);
853   BOOL continue_bit = BITSETW(params+10,3);
854   pstring resume_name;
855   pstring mask;
856   pstring directory;
857   char *p;
858   uint16 dirtype;
859   int numentries = 0;
860   int i, last_name_off=0;
861   BOOL finished = False;
862   BOOL dont_descend = False;
863   BOOL out_of_space = False;
864   int space_remaining;
865
866   *mask = *directory = *resume_name = 0;
867
868   pstrcpy( resume_name, params+12);
869
870   DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
871 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
872 resume_key = %d resume name = %s continue=%d level = %d\n",
873            dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
874            requires_resume_key, resume_key, resume_name, continue_bit, info_level));
875
876   switch (info_level) 
877     {
878     case 1:
879     case 2:
880     case 3:
881     case 4:
882     case SMB_FIND_FILE_DIRECTORY_INFO:
883     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
884     case SMB_FIND_FILE_NAMES_INFO:
885     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
886       break;
887     default:
888       return(ERROR(ERRDOS,ERRunknownlevel));
889     }
890
891   pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
892   if(!*ppdata)
893     return(ERROR(ERRDOS,ERRnomem));
894   bzero(pdata,max_data_bytes);
895
896   /* Realloc the params space */
897   params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
898   if(!params)
899     return(ERROR(ERRDOS,ERRnomem));
900
901   /* Check that the dptr is valid */
902   if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
903     return(ERROR(ERRDOS,ERRnofiles));
904
905   string_set(&conn->dirpath,dptr_path(dptr_num));
906
907   /* Get the wildcard mask from the dptr */
908   if((p = dptr_wcard(dptr_num))== NULL) {
909     DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
910     return (ERROR(ERRDOS,ERRnofiles));
911   }
912   pstrcpy(mask, p);
913   pstrcpy(directory,conn->dirpath);
914
915   /* Get the attr mask from the dptr */
916   dirtype = dptr_attr(dptr_num);
917
918   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
919            dptr_num, mask, dirtype, 
920            (long)conn->dirptr,
921            TellDir(conn->dirptr)));
922
923   /* We don't need to check for VOL here as this is returned by 
924      a different TRANS2 call. */
925
926   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
927   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
928     dont_descend = True;
929     
930   p = pdata;
931   space_remaining = max_data_bytes;
932   out_of_space = False;
933
934   /* 
935    * Seek to the correct position. We no longer use the resume key but
936    * depend on the last file name instead.
937    */
938   if(requires_resume_key && *resume_name && !continue_bit)
939   {
940     /*
941      * Fix for NT redirector problem triggered by resume key indexes
942      * changing between directory scans. We now return a resume key of 0
943      * and instead look for the filename to continue from (also given
944      * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
945      * findfirst/findnext (as is usual) then the directory pointer
946      * should already be at the correct place. Check this by scanning
947      * backwards looking for an exact (ie. case sensitive) filename match. 
948      * If we get to the beginning of the directory and haven't found it then scan
949      * forwards again looking for a match. JRA.
950      */
951
952     int current_pos, start_pos;
953     char *dname = NULL;
954     void *dirptr = conn->dirptr;
955     start_pos = TellDir(dirptr);
956     for(current_pos = start_pos; current_pos >= 0; current_pos--)
957     {
958       DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
959
960       SeekDir(dirptr, current_pos);
961       dname = ReadDirName(dirptr);
962
963       /*
964        * Remember, name_map_mangle is called by
965        * get_lanman2_dir_entry(), so the resume name
966        * could be mangled. Ensure we do the same
967        * here.
968        */
969
970       if(dname != NULL)
971         name_map_mangle( dname, False, SNUM(conn));
972
973       if(dname && strcsequal( resume_name, dname))
974       {
975         SeekDir(dirptr, current_pos+1);
976         DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
977         break;
978       }
979     }
980
981     /*
982      * Scan forward from start if not found going backwards.
983      */
984
985     if(current_pos < 0)
986     {
987       DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
988       SeekDir(dirptr, start_pos);
989       for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
990       {
991         /*
992          * Remember, name_map_mangle is called by
993          * get_lanman2_dir_entry(), so the resume name
994          * could be mangled. Ensure we do the same
995          * here.
996          */
997
998         if(dname != NULL)
999           name_map_mangle( dname, False, SNUM(conn));
1000
1001         if(dname && strcsequal( resume_name, dname))
1002         {
1003           SeekDir(dirptr, current_pos+1);
1004           DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1005           break;
1006         }
1007       } /* end for */
1008     } /* end if current_pos */
1009   } /* end if requires_resume_key && !continue_bit */
1010
1011   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1012     {
1013       /* this is a heuristic to avoid seeking the dirptr except when 
1014          absolutely necessary. It allows for a filename of about 40 chars */
1015       if (space_remaining < DIRLEN_GUESS && numentries > 0)
1016         {
1017           out_of_space = True;
1018           finished = False;
1019         }
1020       else
1021         {
1022           finished = 
1023             !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1024                                    requires_resume_key,dont_descend,
1025                                    &p,pdata,space_remaining, &out_of_space,
1026                                    &last_name_off);
1027         }
1028
1029       if (finished && out_of_space)
1030         finished = False;
1031
1032       if (!finished && !out_of_space)
1033         numentries++;
1034       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1035     }
1036   
1037   /* Check if we can close the dirptr */
1038   if(close_after_request || (finished && close_if_end))
1039     {
1040       dptr_close(dptr_num); /* This frees up the saved mask */
1041       DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1042       dptr_num = -1;
1043     }
1044
1045
1046   /* Set up the return parameter block */
1047   SSVAL(params,0,numentries);
1048   SSVAL(params,2,finished);
1049   SSVAL(params,4,0); /* Never an EA error */
1050   SSVAL(params,6,last_name_off);
1051
1052   send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1053
1054   if ((! *directory) && dptr_path(dptr_num))
1055     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1056
1057   DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1058             smb_fn_name(CVAL(inbuf,smb_com)), 
1059             mask, directory, dirtype, numentries ) );
1060
1061   return(-1);
1062 }
1063
1064 /****************************************************************************
1065   reply to a TRANS2_QFSINFO (query filesystem info)
1066 ****************************************************************************/
1067
1068 static int call_trans2qfsinfo(connection_struct *conn, 
1069                               char *inbuf, char *outbuf, 
1070                               int length, int bufsize,
1071                               char **pparams, char **ppdata)
1072 {
1073   char *pdata = *ppdata;
1074   char *params = *pparams;
1075   uint16 info_level = SVAL(params,0);
1076   int data_len;
1077   SMB_STRUCT_STAT st;
1078   char *vname = volume_label(SNUM(conn));
1079   int snum = SNUM(conn);
1080   char *fstype = lp_fstype(SNUM(conn));
1081   extern uint32 global_client_caps;
1082
1083   DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1084
1085   if(conn->vfs_ops.stat(".",&st)!=0) {
1086     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1087     return (ERROR(ERRSRV,ERRinvdevice));
1088   }
1089
1090   pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
1091
1092   switch (info_level) 
1093   {
1094     case 1:
1095     {
1096       SMB_BIG_UINT dfree,dsize,bsize;
1097       data_len = 18;
1098       conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);        
1099       SIVAL(pdata,l1_idFileSystem,st.st_dev);
1100       SIVAL(pdata,l1_cSectorUnit,bsize/512);
1101       SIVAL(pdata,l1_cUnit,dsize);
1102       SIVAL(pdata,l1_cUnitAvail,dfree);
1103       SSVAL(pdata,l1_cbSector,512);
1104       DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1105                  (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1106          (unsigned int)dfree, 512));
1107       break;
1108     }
1109     case 2:
1110     { 
1111       /* Return volume name */
1112       int volname_len = MIN(strlen(vname),11);
1113       data_len = l2_vol_szVolLabel + volname_len + 1;
1114       /* 
1115        * Add volume serial number - hash of a combination of
1116        * the called hostname and the service name.
1117        */
1118       SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1119       SCVAL(pdata,l2_vol_cch,volname_len);
1120       StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1121       DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1122                (unsigned)st.st_ctime, volname_len,
1123                pdata+l2_vol_szVolLabel));
1124       break;
1125     }
1126     case SMB_QUERY_FS_ATTRIBUTE_INFO:
1127       data_len = 12 + 2*strlen(fstype);
1128       SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH); /* FS ATTRIBUTES */
1129 #if 0 /* Old code. JRA. */
1130       SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1131 #endif /* Old code. */
1132       SIVAL(pdata,4,128); /* Max filename component length */
1133       SIVAL(pdata,8,2*strlen(fstype));
1134       ascii_to_unibuf(pdata+12, fstype, 1024-2-12);
1135       SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1136       break;
1137     case SMB_QUERY_FS_LABEL_INFO:
1138       data_len = 4 + strlen(vname);
1139       SIVAL(pdata,0,strlen(vname));
1140       pstrcpy(pdata+4,vname);      
1141       break;
1142     case SMB_QUERY_FS_VOLUME_INFO:      
1143
1144       /* 
1145        * Add volume serial number - hash of a combination of
1146        * the called hostname and the service name.
1147        */
1148       SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
1149             (str_checksum(local_machine)<<16));
1150
1151       /* NT4 always serves this up as unicode but expects it to be
1152        * delivered as ascii! (tridge && JRA)
1153        */
1154       if (global_client_caps & CAP_NT_SMBS) {
1155               data_len = 18 + strlen(vname);
1156               SIVAL(pdata,12,strlen(vname));
1157               pstrcpy(pdata+18,vname);      
1158       } else {
1159               data_len = 18 + 2*strlen(vname);
1160               SIVAL(pdata,12,strlen(vname)*2);
1161               ascii_to_unibuf(pdata+18, vname, 1024-2-18);
1162       }
1163
1164       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", 
1165                strlen(vname),vname));
1166       break;
1167     case SMB_QUERY_FS_SIZE_INFO:
1168     {
1169       SMB_BIG_UINT dfree,dsize,bsize;
1170       data_len = 24;
1171       conn->vfs_ops.disk_free(".",&bsize,&dfree,&dsize);        
1172       SIVAL(pdata,0,dsize);
1173       SIVAL(pdata,8,dfree);
1174       SIVAL(pdata,16,bsize/512);
1175       SIVAL(pdata,20,512);
1176       break;
1177     }
1178     case SMB_QUERY_FS_DEVICE_INFO:
1179       data_len = 8;
1180       SIVAL(pdata,0,0); /* dev type */
1181       SIVAL(pdata,4,0); /* characteristics */
1182       break;
1183     case SMB_MAC_QUERY_FS_INFO:
1184             /*
1185              * Thursby MAC extension... ONLY on NTFS filesystems
1186              * once we do streams then we don't need this
1187              */
1188             if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1189                     data_len = 88;
1190                     SIVAL(pdata,84,0x100); /* Don't support mac... */
1191                     break;
1192             }
1193             /* drop through */
1194     default:
1195       return(ERROR(ERRDOS,ERRunknownlevel));
1196   }
1197
1198
1199   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1200
1201   DEBUG( 4, ( "%s info_level = %d\n",
1202             smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1203
1204   return -1;
1205 }
1206
1207 /****************************************************************************
1208   reply to a TRANS2_SETFSINFO (set filesystem info)
1209 ****************************************************************************/
1210 static int call_trans2setfsinfo(connection_struct *conn,
1211                                 char *inbuf, char *outbuf, int length, 
1212                                 int bufsize,
1213                                 char **pparams, char **ppdata)
1214 {
1215   /* Just say yes we did it - there is nothing that
1216      can be set here so it doesn't matter. */
1217   int outsize;
1218   DEBUG(3,("call_trans2setfsinfo\n"));
1219
1220   if (!CAN_WRITE(conn))
1221     return(ERROR(ERRSRV,ERRaccess));
1222
1223   outsize = set_message(outbuf,10,0,True);
1224
1225   return outsize;
1226 }
1227
1228 /****************************************************************************
1229   Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1230   file name or file id).
1231 ****************************************************************************/
1232
1233 static int call_trans2qfilepathinfo(connection_struct *conn,
1234                                     char *inbuf, char *outbuf, int length, 
1235                                     int bufsize,
1236                                     char **pparams,char **ppdata,
1237                                     int total_data)
1238 {
1239   char *params = *pparams;
1240   char *pdata = *ppdata;
1241   uint16 tran_call = SVAL(inbuf, smb_setup0);
1242   uint16 info_level;
1243   int mode=0;
1244   SMB_OFF_T size=0;
1245   unsigned int data_size;
1246   SMB_STRUCT_STAT sbuf;
1247   pstring fname1;
1248   char *fname;
1249   char *p;
1250   int l;
1251   SMB_OFF_T pos = 0;
1252   BOOL bad_path = False;
1253   BOOL delete_pending = False;
1254
1255   if (tran_call == TRANSACT2_QFILEINFO) {
1256     files_struct *fsp = file_fsp(params,0);
1257     info_level = SVAL(params,2);
1258
1259     if(fsp && fsp->open && fsp->is_directory) {
1260       /*
1261        * This is actually a QFILEINFO on a directory
1262        * handle (returned from an NT SMB). NT5.0 seems
1263        * to do this call. JRA.
1264        */
1265       fname = fsp->fsp_name;
1266       if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf))
1267         {
1268                 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1269                 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1270         }
1271       if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && 
1272           conn->vfs_ops.stat(dos_to_unix(fname,False),&sbuf))) {
1273         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1274         if((errno == ENOENT) && bad_path)
1275         {
1276           unix_ERR_class = ERRDOS;
1277           unix_ERR_code = ERRbadpath;
1278         }
1279         return(UNIXERROR(ERRDOS,ERRbadpath));
1280       }
1281     } else {
1282       /*
1283        * Original code - this is an open file.
1284        */
1285       CHECK_FSP(fsp,conn);
1286       CHECK_ERROR(fsp);
1287
1288       fname = fsp->fsp_name;
1289       if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1290         DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1291         return(UNIXERROR(ERRDOS,ERRbadfid));
1292       }
1293       if((pos = fsp->conn->vfs_ops.lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1)
1294         return(UNIXERROR(ERRDOS,ERRnoaccess));
1295
1296       delete_pending = fsp->fd_ptr->delete_on_close;
1297     }
1298   } else {
1299     /* qpathinfo */
1300     info_level = SVAL(params,0);
1301     fname = &fname1[0];
1302     pstrcpy(fname,&params[6]);
1303     if (!unix_dfs_convert(fname,conn,0,&bad_path,&sbuf))
1304         {
1305                 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1306                 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1307         }
1308     if (!check_name(fname,conn) || 
1309         (!VALID_STAT(sbuf) && conn->vfs_ops.stat(dos_to_unix(fname,False),
1310                                                  &sbuf))) {
1311       DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1312       if((errno == ENOENT) && bad_path)
1313       {
1314         unix_ERR_class = ERRDOS;
1315         unix_ERR_code = ERRbadpath;
1316       }
1317       return(UNIXERROR(ERRDOS,ERRbadpath));
1318     }
1319   }
1320
1321
1322   DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1323            fname,info_level,tran_call,total_data));
1324
1325   p = strrchr(fname,'/'); 
1326   if (!p) 
1327     p = fname;
1328   else
1329     p++;
1330   l = strlen(p);  
1331   mode = dos_mode(conn,fname,&sbuf);
1332   size = sbuf.st_size;
1333   if (mode & aDIR) size = 0;
1334
1335   /* from now on we only want the part after the / */
1336   fname = p;
1337   
1338   params = *pparams = Realloc(*pparams,2); bzero(params,2);
1339   data_size = 1024;
1340   pdata = *ppdata = Realloc(*ppdata, data_size); 
1341
1342   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1343     /* uggh, EAs for OS2 */
1344     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1345     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1346   }
1347
1348   bzero(pdata,data_size);
1349
1350   switch (info_level) 
1351     {
1352     case SMB_INFO_STANDARD:
1353     case SMB_INFO_QUERY_EA_SIZE:
1354       data_size = (info_level==1?22:26);
1355       put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1356       put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1357       put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1358       SIVAL(pdata,l1_cbFile,(uint32)size);
1359       SIVAL(pdata,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
1360       SSVAL(pdata,l1_attrFile,mode);
1361       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1362       break;
1363
1364     case SMB_INFO_QUERY_EAS_FROM_LIST:
1365       data_size = 24;
1366       put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1367       put_dos_date2(pdata,4,sbuf.st_atime);
1368       put_dos_date2(pdata,8,sbuf.st_mtime);
1369       SIVAL(pdata,12,(uint32)size);
1370       SIVAL(pdata,16,SMB_ROUNDUP(size,1024));
1371       SIVAL(pdata,20,mode);
1372       break;
1373
1374     case SMB_INFO_QUERY_ALL_EAS:
1375       data_size = 4;
1376       SIVAL(pdata,0,data_size);
1377       break;
1378
1379     case 6:
1380       return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */      
1381
1382     case SMB_QUERY_FILE_BASIC_INFO:
1383       data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1384       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1385       put_long_date(pdata+8,sbuf.st_atime);
1386       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1387       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1388       SIVAL(pdata,32,mode);
1389
1390       DEBUG(5,("SMB_QFBI - "));
1391       {
1392         time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1393         DEBUG(5,("create: %s ", ctime(&create_time)));
1394       }
1395       DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1396       DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1397       DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1398       DEBUG(5,("mode: %x\n", mode));
1399
1400       break;
1401
1402     case SMB_QUERY_FILE_STANDARD_INFO:
1403       data_size = 22;
1404       SOFF_T(pdata,0,size);
1405       SOFF_T(pdata,8,size);
1406       SIVAL(pdata,16,sbuf.st_nlink);
1407       CVAL(pdata,20) = 0;
1408       CVAL(pdata,21) = (mode&aDIR)?1:0;
1409       break;
1410
1411     case SMB_QUERY_FILE_EA_INFO:
1412       data_size = 4;
1413       break;
1414
1415     /* Get the 8.3 name - used if NT SMB was negotiated. */
1416     case SMB_QUERY_FILE_ALT_NAME_INFO:
1417       {
1418         pstring short_name;
1419         char *data_end;
1420
1421         pstrcpy(short_name,p);
1422         /* Mangle if not already 8.3 */
1423         if(!is_8_3(short_name, True))
1424         {
1425           if(!name_map_mangle(short_name,True,SNUM(conn)))
1426             *short_name = '\0';
1427         }
1428         strupper(short_name);
1429         data_end = ascii_to_unibuf(pdata + 4, short_name, 1024-2-4);
1430         data_size = data_end - pdata;
1431         SIVAL(pdata,0,2*(data_size-4));
1432       }
1433       break;
1434
1435     case SMB_QUERY_FILE_NAME_INFO:
1436       data_size = 4 + l;
1437       SIVAL(pdata,0,l);
1438       pstrcpy(pdata+4,fname);
1439       break;
1440
1441     case SMB_QUERY_FILE_ALLOCATION_INFO:
1442     case SMB_QUERY_FILE_END_OF_FILEINFO:
1443       data_size = 8;
1444       SOFF_T(pdata,0,size);
1445       break;
1446
1447     case SMB_QUERY_FILE_ALL_INFO:
1448       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1449       put_long_date(pdata+8,sbuf.st_atime);
1450       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1451       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1452       SIVAL(pdata,32,mode);
1453       pdata += 40;
1454       SOFF_T(pdata,0,size);
1455       SOFF_T(pdata,8,size);
1456       SIVAL(pdata,16,sbuf.st_nlink);
1457       CVAL(pdata,20) = delete_pending;
1458       CVAL(pdata,21) = (mode&aDIR)?1:0;
1459       pdata += 24;
1460       SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); 
1461       pdata += 8; /* index number */
1462       pdata += 4; /* EA info */
1463       if (mode & aRONLY)
1464         SIVAL(pdata,0,0xA9);
1465       else
1466         SIVAL(pdata,0,0xd01BF);
1467       pdata += 4;
1468       SOFF_T(pdata,0,pos); /* current offset */
1469       pdata += 8;
1470       SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1471       pdata += 4;
1472       pdata += 4; /* alignment */
1473       SIVAL(pdata,0,l);
1474       pstrcpy(pdata+4,fname);
1475       pdata += 4 + l;
1476       data_size = PTR_DIFF(pdata,(*ppdata));
1477       break;
1478
1479 #if 0
1480       /* NT4 server just returns "invalid query" to this - if we try to answer 
1481          it then NTws gets a BSOD! (tridge) */
1482     case SMB_QUERY_FILE_STREAM_INFO:
1483       data_size = 24 + l;
1484       SIVAL(pdata,0,pos);
1485       SIVAL(pdata,4,size);
1486       SIVAL(pdata,12,size);
1487       SIVAL(pdata,20,l);        
1488       pstrcpy(pdata+24,fname);
1489       break;
1490 #endif
1491
1492     default:
1493       return(ERROR(ERRDOS,ERRunknownlevel));
1494     }
1495
1496   send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1497
1498   return(-1);
1499 }
1500
1501 /****************************************************************************
1502   reply to a TRANS2_SETFILEINFO (set file info by fileid)
1503 ****************************************************************************/
1504 static int call_trans2setfilepathinfo(connection_struct *conn,
1505                                       char *inbuf, char *outbuf, int length, 
1506                                       int bufsize, char **pparams, 
1507                                       char **ppdata, int total_data)
1508 {
1509   char *params = *pparams;
1510   char *pdata = *ppdata;
1511   uint16 tran_call = SVAL(inbuf, smb_setup0);
1512   uint16 info_level;
1513   int mode=0;
1514   SMB_OFF_T size=0;
1515   struct utimbuf tvs;
1516   SMB_STRUCT_STAT st;
1517   pstring fname1;
1518   char *fname;
1519   int fd = -1;
1520   BOOL bad_path = False;
1521   files_struct *fsp = NULL;
1522
1523   if (!CAN_WRITE(conn))
1524     return(ERROR(ERRSRV,ERRaccess));
1525
1526   if (tran_call == TRANSACT2_SETFILEINFO) {
1527     fsp = file_fsp(params,0);
1528     info_level = SVAL(params,2);    
1529
1530     if(fsp && fsp->open && fsp->is_directory) {
1531       /*
1532        * This is actually a SETFILEINFO on a directory
1533        * handle (returned from an NT SMB). NT5.0 seems
1534        * to do this call. JRA.
1535        */
1536       fname = fsp->fsp_name;
1537       if (!unix_dfs_convert(fname,conn,0,&bad_path,&st))
1538         {
1539                 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1540                 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1541         }
1542       if (!check_name(fname,conn) || (!VALID_STAT(st) && 
1543                                       conn->vfs_ops.stat(dos_to_unix(fname,False),&st))) {
1544         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1545         if((errno == ENOENT) && bad_path)
1546         {
1547           unix_ERR_class = ERRDOS;
1548           unix_ERR_code = ERRbadpath;
1549         }
1550         return(UNIXERROR(ERRDOS,ERRbadpath));
1551       }
1552     } else {
1553       /*
1554        * Original code - this is an open file.
1555        */
1556       CHECK_FSP(fsp,conn);
1557       CHECK_ERROR(fsp);
1558
1559       fname = fsp->fsp_name;
1560       fd = fsp->fd_ptr->fd;
1561
1562       if (fsp->conn->vfs_ops.fstat(fd,&st) != 0) {
1563         DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1564         return(UNIXERROR(ERRDOS,ERRbadfid));
1565       }
1566     }
1567   } else {
1568     /* set path info */
1569     info_level = SVAL(params,0);    
1570     fname = fname1;
1571     pstrcpy(fname,&params[6]);
1572     if (!unix_dfs_convert(fname,conn,0,&bad_path,&st))
1573         {
1574                 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1575                 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1576         }
1577     if(!check_name(fname, conn))
1578     {
1579       if((errno == ENOENT) && bad_path)
1580       {
1581         unix_ERR_class = ERRDOS;
1582         unix_ERR_code = ERRbadpath;
1583       }
1584       return(UNIXERROR(ERRDOS,ERRbadpath));
1585     }
1586  
1587     if(!VALID_STAT(st) && conn->vfs_ops.stat(dos_to_unix(fname,False),&st)!=0) {
1588       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1589       if((errno == ENOENT) && bad_path)
1590       {
1591         unix_ERR_class = ERRDOS;
1592         unix_ERR_code = ERRbadpath;
1593       }
1594       return(UNIXERROR(ERRDOS,ERRbadpath));
1595     }    
1596   }
1597
1598   DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1599            tran_call,fname,info_level,total_data));
1600
1601   /* Realloc the parameter and data sizes */
1602   params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1603   if(params == NULL)
1604     return(ERROR(ERRDOS,ERRnomem));
1605
1606   size = st.st_size;
1607   tvs.modtime = st.st_mtime;
1608   tvs.actime = st.st_atime;
1609   mode = dos_mode(conn,fname,&st);
1610
1611   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1612     /* uggh, EAs for OS2 */
1613     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1614     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1615   }
1616
1617   switch (info_level)
1618   {
1619     case SMB_INFO_STANDARD:
1620     case SMB_INFO_QUERY_EA_SIZE:
1621     {
1622       /* access time */
1623       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1624
1625       /* write time */
1626       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1627
1628       mode = SVAL(pdata,l1_attrFile);
1629       size = IVAL(pdata,l1_cbFile);
1630       break;
1631     }
1632
1633     /* XXXX um, i don't think this is right.
1634        it's also not in the cifs6.txt spec.
1635      */
1636     case SMB_INFO_QUERY_EAS_FROM_LIST:
1637       tvs.actime = make_unix_date2(pdata+8);
1638       tvs.modtime = make_unix_date2(pdata+12);
1639       size = IVAL(pdata,16);
1640       mode = IVAL(pdata,24);
1641       break;
1642
1643     /* XXXX nor this.  not in cifs6.txt, either. */
1644     case SMB_INFO_QUERY_ALL_EAS:
1645       tvs.actime = make_unix_date2(pdata+8);
1646       tvs.modtime = make_unix_date2(pdata+12);
1647       size = IVAL(pdata,16);
1648       mode = IVAL(pdata,24);
1649       break;
1650
1651     case SMB_SET_FILE_BASIC_INFO:
1652     {
1653       /* Ignore create time at offset pdata. */
1654
1655       /* access time */
1656       tvs.actime = interpret_long_date(pdata+8);
1657
1658       /* write time + changed time, combined. */
1659       tvs.modtime=MAX(interpret_long_date(pdata+16),
1660                       interpret_long_date(pdata+24));
1661
1662 #if 0 /* Needs more testing... */
1663       /* Test from Luke to prevent Win95 from
1664          setting incorrect values here.
1665        */
1666       if (tvs.actime < tvs.modtime)
1667         return(ERROR(ERRDOS,ERRnoaccess));
1668 #endif /* Needs more testing... */
1669
1670       /* attributes */
1671       mode = IVAL(pdata,32);
1672       break;
1673     }
1674
1675     case SMB_SET_FILE_END_OF_FILE_INFO:
1676     {
1677       size = IVAL(pdata,0);
1678 #ifdef LARGE_SMB_OFF_T
1679       size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1680 #else /* LARGE_SMB_OFF_T */
1681       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1682          return(ERROR(ERRDOS,ERRunknownlevel));
1683 #endif /* LARGE_SMB_OFF_T */
1684       break;
1685     }
1686
1687     case SMB_SET_FILE_ALLOCATION_INFO:
1688       break; /* We don't need to do anything for this call. */
1689
1690     case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
1691     {
1692       if ((tran_call == TRANSACT2_SETFILEINFO) && (fsp != NULL))
1693       {
1694         BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
1695
1696         if(fsp->is_directory)
1697           return(ERROR(ERRDOS,ERRnoaccess));
1698
1699         /*
1700          * We can only set the delete on close flag if
1701          * the share mode contained ALLOW_SHARE_DELETE
1702          */
1703
1704         if(lp_share_modes(SNUM(conn)))
1705         {
1706           if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode))
1707             return(ERROR(ERRDOS,ERRnoaccess));
1708
1709           /*
1710            * If the flag has been set then
1711            * modify the share mode entry for all files we have open
1712            * on this device and inode to tell other smbds we have 
1713            * changed the delete on close flag.
1714            */
1715
1716           if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode))
1717           {
1718             int token;
1719             int i;
1720             files_struct *iterate_fsp;
1721             SMB_DEV_T dev = fsp->fd_ptr->dev;
1722             SMB_INO_T inode = fsp->fd_ptr->inode;
1723             int num_share_modes;
1724             share_mode_entry *current_shares = NULL;
1725
1726             if(lock_share_entry(fsp->conn, dev, inode, &token) == False)
1727               return(ERROR(ERRDOS,ERRnoaccess));
1728
1729             /*
1730              * Before we allow this we need to ensure that all current opens
1731              * on the file have the GET_ALLOW_SHARE_DELETE flag set. If they
1732              * do not then we deny this (as we are essentially deleting the
1733              * file at this point.
1734              */
1735
1736             num_share_modes = get_share_modes(conn, token, dev, inode, &current_shares);
1737             for(i = 0; i < num_share_modes; i++)
1738             {
1739               if(!GET_ALLOW_SHARE_DELETE(current_shares[i].share_mode))
1740               {
1741                 DEBUG(5,("call_trans2setfilepathinfo: refusing to set delete on close flag for fnum = %d, \
1742 file %s as a share exists that was not opened with FILE_DELETE access.\n",
1743                       fsp->fnum, fsp->fsp_name ));
1744                 /*
1745                  * Release the lock.
1746                  */
1747
1748                 unlock_share_entry(fsp->conn, dev, inode, token);
1749
1750                 /*
1751                  * current_shares was malloced by get_share_modes - free it here.
1752                  */
1753
1754                 free((char *)current_shares);
1755
1756                 /*
1757                  * Even though share violation would be more appropriate here,
1758                  * return ERRnoaccess as that's what NT does.
1759                  */
1760
1761                 return(ERROR(ERRDOS,ERRnoaccess));
1762               }
1763             }
1764
1765             /*
1766              * current_shares was malloced by get_share_modes - free it here.
1767              */
1768
1769             free((char *)current_shares);
1770
1771             DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1772                  delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1773
1774             /*
1775              * Go through all files we have open on the same device and
1776              * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1777              * Other smbd's that have this file open will have to fend for themselves. We
1778              * take care of this (rare) case in close_file(). See the comment there.
1779              */
1780
1781             for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp;
1782                                   iterate_fsp = file_find_di_next(iterate_fsp))
1783             {
1784               int new_share_mode = (delete_on_close ? 
1785                                     (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) :
1786                                     (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) );
1787
1788               DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s \
1789 dev = %x, inode = %.0f from %x to %x\n", 
1790                     iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, 
1791                     (double)inode, iterate_fsp->share_mode, new_share_mode ));
1792
1793               if(modify_share_mode(token, iterate_fsp, new_share_mode)==False)
1794                 DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
1795 dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode));
1796             }
1797
1798             /*
1799              * Set the delete on close flag in the reference
1800              * counted struct. Delete when the last reference
1801              * goes away.
1802              */
1803            fsp->fd_ptr->delete_on_close = delete_on_close;
1804            unlock_share_entry(fsp->conn, dev, inode, token);
1805
1806            DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1807                  delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1808
1809           } /* end if(delete_on_close && !GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode)) */
1810         } /* end if lp_share_modes() */
1811
1812       } else
1813         return(ERROR(ERRDOS,ERRunknownlevel));
1814       break;
1815     }
1816
1817     default:
1818     {
1819       return(ERROR(ERRDOS,ERRunknownlevel));
1820     }
1821   }
1822
1823   DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1824   DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1825   DEBUG(6,("size: %.0f ", (double)size));
1826   DEBUG(6,("mode: %x\n"  , mode));
1827
1828   /* get some defaults (no modifications) if any info is zero. */
1829   if (!tvs.actime) tvs.actime = st.st_atime;
1830   if (!tvs.modtime) tvs.modtime = st.st_mtime;
1831   if (!size) size = st.st_size;
1832
1833   /* Try and set the times, size and mode of this file -
1834      if they are different from the current values
1835    */
1836   if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1837   {
1838     if(fsp != NULL)
1839     {
1840       /*
1841        * This was a setfileinfo on an open file.
1842        * NT does this a lot. It's actually pointless
1843        * setting the time here, as it will be overwritten
1844        * on the next write, so we save the request
1845        * away and will set it on file code. JRA.
1846        */
1847       fsp->pending_modtime = tvs.modtime;
1848     }
1849     else if(file_utime(conn, fname, &tvs)!=0)
1850     {
1851       return(UNIXERROR(ERRDOS,ERRnoaccess));
1852     }
1853   }
1854
1855   /* check the mode isn't different, before changing it */
1856   if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL))
1857   {
1858     DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1859     return(UNIXERROR(ERRDOS,ERRnoaccess));
1860   }
1861
1862   if(size != st.st_size)
1863   {
1864     if (fd == -1)
1865     {
1866 DEBUG(0, ("@@@ 23 @@@\n"));
1867       fd = dos_open(fname,O_RDWR,0);
1868       if (fd == -1)
1869       {
1870         return(UNIXERROR(ERRDOS,ERRbadpath));
1871       }
1872       set_filelen(fd, size);
1873       close(fd);
1874     }
1875     else
1876     {
1877       set_filelen(fd, size);
1878     }
1879   }
1880
1881   SSVAL(params,0,0);
1882
1883   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1884   
1885   return(-1);
1886 }
1887
1888 /****************************************************************************
1889   reply to a TRANS2_MKDIR (make directory with extended attributes).
1890 ****************************************************************************/
1891 static int call_trans2mkdir(connection_struct *conn,
1892                             char *inbuf, char *outbuf, int length, int bufsize,
1893                             char **pparams, char **ppdata)
1894 {
1895   char *params = *pparams;
1896   pstring directory;
1897   int ret = -1;
1898   BOOL bad_path = False;
1899
1900   if (!CAN_WRITE(conn))
1901     return(ERROR(ERRSRV,ERRaccess));
1902
1903   pstrcpy(directory, &params[4]);
1904
1905   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1906
1907   if (!unix_dfs_convert(directory,conn,0,&bad_path,NULL))
1908         {
1909                 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
1910                 return(ERROR(0, 0xc0000000|NT_STATUS_PATH_NOT_COVERED));
1911         }
1912   if (check_name(directory,conn))
1913     ret = conn->vfs_ops.mkdir(dos_to_unix(directory,False),
1914                               unix_mode(conn,aDIR));
1915   
1916   if(ret < 0)
1917     {
1918       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1919       if((errno == ENOENT) && bad_path)
1920       {
1921         unix_ERR_class = ERRDOS;
1922         unix_ERR_code = ERRbadpath;
1923       }
1924       return(UNIXERROR(ERRDOS,ERRnoaccess));
1925     }
1926
1927   /* Realloc the parameter and data sizes */
1928   params = *pparams = Realloc(*pparams,2);
1929   if(params == NULL)
1930     return(ERROR(ERRDOS,ERRnomem));
1931
1932   SSVAL(params,0,0);
1933
1934   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1935   
1936   return(-1);
1937 }
1938
1939 /****************************************************************************
1940   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1941   We don't actually do this - we just send a null response.
1942 ****************************************************************************/
1943 static int call_trans2findnotifyfirst(connection_struct *conn,
1944                                       char *inbuf, char *outbuf, 
1945                                       int length, int bufsize,
1946                                       char **pparams, char **ppdata)
1947 {
1948   static uint16 fnf_handle = 257;
1949   char *params = *pparams;
1950   uint16 info_level = SVAL(params,4);
1951
1952   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1953
1954   switch (info_level) 
1955     {
1956     case 1:
1957     case 2:
1958       break;
1959     default:
1960       return(ERROR(ERRDOS,ERRunknownlevel));
1961     }
1962
1963   /* Realloc the parameter and data sizes */
1964   params = *pparams = Realloc(*pparams,6);
1965   if(params == NULL)
1966     return(ERROR(ERRDOS,ERRnomem));
1967
1968   SSVAL(params,0,fnf_handle);
1969   SSVAL(params,2,0); /* No changes */
1970   SSVAL(params,4,0); /* No EA errors */
1971
1972   fnf_handle++;
1973
1974   if(fnf_handle == 0)
1975     fnf_handle = 257;
1976
1977   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1978   
1979   return(-1);
1980 }
1981
1982 /****************************************************************************
1983   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
1984   changes). Currently this does nothing.
1985 ****************************************************************************/
1986 static int call_trans2findnotifynext(connection_struct *conn,
1987                                      char *inbuf, char *outbuf, 
1988                                      int length, int bufsize,
1989                                      char **pparams, char **ppdata)
1990 {
1991   char *params = *pparams;
1992
1993   DEBUG(3,("call_trans2findnotifynext\n"));
1994
1995   /* Realloc the parameter and data sizes */
1996   params = *pparams = Realloc(*pparams,4);
1997   if(params == NULL)
1998     return(ERROR(ERRDOS,ERRnomem));
1999
2000   SSVAL(params,0,0); /* No changes */
2001   SSVAL(params,2,0); /* No EA errors */
2002
2003   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2004   
2005   return(-1);
2006 }
2007
2008 /****************************************************************************
2009   reply to a SMBfindclose (stop trans2 directory search)
2010 ****************************************************************************/
2011 int reply_findclose(connection_struct *conn,
2012                     char *inbuf,char *outbuf,int length,int bufsize)
2013 {
2014         int outsize = 0;
2015         int16 dptr_num=SVALS(inbuf,smb_vwv0);
2016
2017         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
2018
2019         dptr_close(dptr_num);
2020
2021         outsize = set_message(outbuf,0,0,True);
2022
2023         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
2024
2025         return(outsize);
2026 }
2027
2028 /****************************************************************************
2029   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
2030 ****************************************************************************/
2031 int reply_findnclose(connection_struct *conn, 
2032                      char *inbuf,char *outbuf,int length,int bufsize)
2033 {
2034         int outsize = 0;
2035         int dptr_num= -1;
2036         
2037         dptr_num = SVAL(inbuf,smb_vwv0);
2038
2039         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2040
2041         /* We never give out valid handles for a 
2042            findnotifyfirst - so any dptr_num is ok here. 
2043            Just ignore it. */
2044
2045         outsize = set_message(outbuf,0,0,True);
2046
2047         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2048
2049         return(outsize);
2050 }
2051
2052 #define UNICODE_DFS
2053
2054 /****************************************************************************
2055  reply to a TRANS2_GET_DFS_REFERRAL
2056  ****************************************************************************/
2057 static int call_trans2getdfsreferral(connection_struct *conn,
2058                                      char *inbuf, char *outbuf, int length, 
2059                                      int bufsize, 
2060                                      char **pparams, char **ppdata,
2061                                      int total_data)
2062 {
2063         char *params = *pparams;
2064         char *pdata;
2065         char *pheader;
2066         char *localstring_offset;
2067         char *mangledstring_offset;
2068         char *sharename_offset;
2069         char *referal_offset;
2070         
2071         int i;
2072         int j;
2073         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2074         int query_file_len=0;
2075         int bytesreq=0;
2076         int filename_len;
2077         
2078         BOOL first_one=True;
2079         
2080         referal_trans_param rtp;
2081         dfs_internal_table *list=dfs_struct.table;
2082         dfs_response reply;
2083
2084         DEBUG(0,("call_trans2getdfsreferral:1\n"));
2085
2086         ZERO_STRUCT(rtp);
2087         ZERO_STRUCT(reply);
2088
2089         /* decode the param member of query */
2090         rtp.level=SVAL(params, 0);
2091         DEBUGADD(0,("rtp.level:[%d]\n",rtp.level));
2092         
2093         DEBUGADD(0,("total_params:[%d]\n",total_params));
2094         for (i=0; i<(total_params-2)/2; i++)
2095         {
2096                 rtp.directory[i]=SVAL(params, 2+2*i);
2097         }
2098 /*
2099         strupper(rtp.directory);
2100 */
2101         query_file_len=strlen(rtp.directory);
2102         DEBUGADD(0,("rtp.directory:[%s]\n",rtp.directory));
2103         DEBUGADD(0,("query_file_len:[%d]\n",query_file_len));
2104                 
2105         /*
2106           lookup in the internal DFS table all the entries
2107           and calculate the required data buffer size
2108         */
2109         bytesreq=8;     /* the header */
2110         reply.number_of_referal=0;
2111         DEBUGADD(0,("call_trans2getdfsreferral:2\n"));
2112         
2113         for(i=0; i<dfs_struct.size; i++)
2114         {
2115                 filename_len=list[i].localpath_length;
2116         DEBUGADD(0,("checking against [%s][%d]\n", list[i].localpath, filename_len));
2117  
2118                 if( (filename_len==query_file_len) && 
2119                     (!StrnCaseCmp(rtp.directory, list[i].localpath, query_file_len)) )
2120                 {
2121                         
2122                         bytesreq+=22;                             /* the referal size */
2123                         bytesreq+=2*(list[i].sharename_length+1); /* the string length */
2124                         reply.number_of_referal++;
2125         DEBUGADD(0,("found\n"));
2126                         
2127                         if (first_one) {
2128         DEBUGADD(0,("first one\n"));
2129                                 bytesreq+=2*(list[i].localpath_length+1);
2130                                 bytesreq+=2*(list[i].mangledpath_length+1);
2131                                 
2132                                 reply.path_consumed=list[i].localpath_length;
2133                                 
2134                                 strncpy(reply.filename, list[i].localpath, list[i].localpath_length+1);
2135                                 strncpy(reply.mangledname, list[i].mangledpath, list[i].mangledpath_length+1);
2136                                 rtp.type=list[i].type;
2137                                 first_one=False;
2138                         }
2139                 }
2140         }
2141         DEBUGADD(0,("call_trans2getdfsreferral:3\n"));
2142
2143         /* allocate memory for the reply data */        
2144         pdata = *ppdata = Realloc(*ppdata, bytesreq + 1024); 
2145         bzero(*ppdata, bytesreq+22);
2146
2147         pdata = *ppdata;
2148         pheader = pdata;
2149
2150         localstring_offset  = pdata + 8 + reply.number_of_referal*22;
2151
2152 #ifdef UNICODE_DFS
2153         mangledstring_offset = localstring_offset + 2*(1+strlen(reply.filename));
2154         sharename_offset = mangledstring_offset + 2*(1+strlen(reply.mangledname));
2155
2156 #else
2157         mangledstring_offset = localstring_offset + (1+strlen(reply.filename));
2158         sharename_offset = mangledstring_offset + (1+strlen(reply.mangledname));
2159 #endif
2160         referal_offset = pdata + 8;
2161
2162         /* right now respond storage server */
2163 /*
2164         reply.server_function=rtp.type;
2165 */
2166         reply.server_function=0x3;
2167
2168         /* write the header */
2169 #ifdef UNICODE_DFS
2170         SSVAL(pheader, 0, reply.path_consumed*2);
2171 #else
2172         SSVAL(pheader, 0, reply.path_consumed);
2173 #endif
2174         SSVAL(pheader, 2, reply.number_of_referal);
2175         SIVAL(pheader, 4, reply.server_function);
2176
2177         /* write the local path string */
2178 #ifdef UNICODE_DFS
2179         for(i=0; i<strlen(reply.filename); i++)
2180         {
2181                 SSVAL(localstring_offset, 2*i, (uint16) reply.filename[i]);
2182         }
2183         SSVAL(localstring_offset, 2*strlen(reply.filename), 0);
2184 #else
2185
2186         for(i=0; i<strlen(reply.filename); i++)
2187         {
2188                 localstring_offset[i]=reply.filename[i];
2189         }
2190         localstring_offset[strlen(reply.filename)]=0;
2191 #endif
2192         DEBUG(0,("reply.filename is [%s]:[%d], i is [%d]\n", reply.filename, strlen(reply.filename), i));
2193
2194         /* write the mangled local path string */ 
2195 #ifdef UNICODE_DFS
2196         for(i=0; i<strlen(reply.mangledname); i++)
2197         {
2198                 SSVAL(mangledstring_offset, 2*i, (uint16) reply.mangledname[i]);
2199         }
2200         SSVAL(mangledstring_offset, 2*i, 0);
2201 #else
2202         for(i=0; i<strlen(reply.mangledname); i++)
2203         {
2204                 mangledstring_offset[i]=reply.mangledname[i];
2205         }
2206         mangledstring_offset[i]=0;
2207 #endif
2208         DEBUGADD(0,("call_trans2getdfsreferral:4\n"));
2209
2210         /* the order of the referals defines the load balancing */
2211
2212         /* write each referal */
2213         for(i=0; i<dfs_struct.size; i++)
2214         {
2215                 filename_len=list[i].localpath_length;
2216   
2217                 if(filename_len==query_file_len && 
2218                    !strncasecmp(rtp.directory, list[i].localpath, query_file_len))
2219                 {
2220                 
2221                         SSVAL(referal_offset,  0, 2);                   /* version */
2222                         SSVAL(referal_offset,  2, 22);                  /* size */
2223                         
2224                         if (rtp.type==3)
2225                                 SSVAL(referal_offset,  4, 1);           /* type SMB server*/
2226                         else            
2227                                 SSVAL(referal_offset,  4, 0);           /* type unknown */
2228                         SSVAL(referal_offset,  6, 1);                   /* flags */
2229                         SIVAL(referal_offset,  8, list[i].proximity);   /* proximity */
2230                         SIVAL(referal_offset, 12, 300);                 /* ttl */
2231                         SSVAL(referal_offset, 16, localstring_offset-referal_offset);
2232                         SSVAL(referal_offset, 18, mangledstring_offset-referal_offset);
2233                         SSVAL(referal_offset, 20, sharename_offset-referal_offset); 
2234
2235 #ifdef UNICODE_DFS
2236                         for(j=0; j<list[i].sharename_length; j++)
2237                         {
2238                                 SSVAL(sharename_offset, 2*j, (uint16) list[i].sharename[j]);
2239                         }
2240                         SSVAL(sharename_offset, 2*j, 0);
2241                 
2242                         sharename_offset=sharename_offset + 2*(1+list[i].sharename_length);
2243 #else
2244                         for(j=0; j<list[i].sharename_length; j++)
2245                         {
2246                                 sharename_offset[j]=list[i].sharename[j];
2247                         }
2248                         sharename_offset[j]=0;
2249                 
2250                         sharename_offset=sharename_offset + (1+list[i].sharename_length);
2251 #endif
2252
2253                         referal_offset=referal_offset+22;
2254                 }                                       
2255         }
2256         
2257         DEBUGADD(0,("call_trans2getdfsreferral:5\n"));
2258
2259         send_trans2_replies(outbuf, bufsize, params, 0, *ppdata, bytesreq+22);
2260
2261 /*      send_trans2_replies(outbuf, bufsize, *ppdata, bytesreq, params, 0);*/
2262         DEBUGADD(0,("call_trans2getdfsreferral:6\n"));
2263
2264         return(-1);
2265 }
2266                 
2267  
2268 /****************************************************************************
2269 reply to a TRANS2_REPORT_DFS_INCONSISTANCY
2270 ****************************************************************************/
2271 static int call_trans2reportdfsinconsistancy(connection_struct *conn,
2272                                              char *inbuf, char *outbuf, int length, 
2273                                              int bufsize, 
2274                                              char **pparams, char **ppdata)
2275 {
2276         char *params = *pparams;
2277
2278         DEBUG(4,("call_trans2reportdfsinconsistancy\n"));
2279         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2280         return(-1);
2281 }
2282
2283
2284 /****************************************************************************
2285   reply to a SMBtranss2 - just ignore it!
2286 ****************************************************************************/
2287 int reply_transs2(connection_struct *conn,
2288                   char *inbuf,char *outbuf,int length,int bufsize)
2289 {
2290         DEBUG(4,("Ignoring transs2 of length %d\n",length));
2291         return(-1);
2292 }
2293
2294 /****************************************************************************
2295   reply to a SMBtrans2
2296 ****************************************************************************/
2297 int reply_trans2(connection_struct *conn,
2298                  char *inbuf,char *outbuf,int length,int bufsize)
2299 {
2300         int outsize = 0;
2301         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2302         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2303 #if 0
2304         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2305         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2306         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2307         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2308         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2309         int32 timeout = IVALS(inbuf,smb_timeout);
2310 #endif
2311         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2312         unsigned int tran_call = SVAL(inbuf, smb_setup0);
2313         char *params = NULL, *data = NULL;
2314         int num_params, num_params_sofar, num_data, num_data_sofar;
2315
2316         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2317                 /* Queue this open message as we are the process of an
2318                  * oplock break.  */
2319
2320                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2321                 DEBUGADD(2,( "in oplock break state.\n"));
2322
2323                 push_oplock_pending_smb_message(inbuf, length);
2324                 return -1;
2325         }
2326         
2327         outsize = set_message(outbuf,0,0,True);
2328
2329         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2330            is so as a sanity check */
2331         if (suwcnt != 1) {
2332                 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
2333                 return(ERROR(ERRSRV,ERRerror));
2334         }
2335     
2336         /* Allocate the space for the maximum needed parameters and data */
2337         if (total_params > 0)
2338                 params = (char *)malloc(total_params);
2339         if (total_data > 0)
2340                 data = (char *)malloc(total_data);
2341   
2342         if ((total_params && !params)  || (total_data && !data)) {
2343                 DEBUG(2,("Out of memory in reply_trans2\n"));
2344         if(params)
2345           free(params);
2346         if(data)
2347           free(data); 
2348                 return(ERROR(ERRDOS,ERRnomem));
2349         }
2350
2351         /* Copy the param and data bytes sent with this request into
2352            the params buffer */
2353         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2354         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2355
2356         if (num_params > total_params || num_data > total_data)
2357                 exit_server("invalid params in reply_trans2");
2358
2359         if(params)
2360                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2361         if(data)
2362                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2363
2364         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
2365                 /* We need to send an interim response then receive the rest
2366                    of the parameter/data bytes */
2367                 outsize = set_message(outbuf,0,0,True);
2368                 send_smb(Client,outbuf);
2369
2370                 while (num_data_sofar < total_data || 
2371                        num_params_sofar < total_params) {
2372                         BOOL ret;
2373
2374                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2375                         
2376                         if ((ret && 
2377                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2378                                 outsize = set_message(outbuf,0,0,True);
2379                                 if(ret)
2380                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2381                                 else
2382                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2383                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2384                                 if(params)
2385                                         free(params);
2386                                 if(data)
2387                                         free(data);
2388                                 return(ERROR(ERRSRV,ERRerror));
2389                         }
2390       
2391                         /* Revise total_params and total_data in case
2392                            they have changed downwards */
2393                         total_params = SVAL(inbuf, smb_tpscnt);
2394                         total_data = SVAL(inbuf, smb_tdscnt);
2395                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2396                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2397                         if (num_params_sofar > total_params || num_data_sofar > total_data)
2398                                 exit_server("data overflow in trans2");
2399                         
2400                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
2401                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2402                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2403                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2404                 }
2405         }
2406         
2407         if (Protocol >= PROTOCOL_NT1) {
2408                 uint16 flg2 = SVAL(outbuf,smb_flg2);
2409                 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
2410         }
2411
2412         /* Now we must call the relevant TRANS2 function */
2413         switch(tran_call)
2414         {
2415                 case TRANSACT2_OPEN:
2416                 {
2417                         outsize = call_trans2open(conn, 
2418                                           inbuf, outbuf, bufsize, 
2419                                           &params, &data);
2420                         break;
2421                 }
2422                 case TRANSACT2_FINDFIRST:
2423                 {
2424                         outsize = call_trans2findfirst(conn, inbuf, outbuf, 
2425                                                        bufsize, &params, &data);
2426                         break;
2427                 }
2428                 case TRANSACT2_FINDNEXT:
2429                 {
2430                         outsize = call_trans2findnext(conn, inbuf, outbuf, 
2431                                                       length, bufsize, 
2432                                                       &params, &data);
2433                         break;
2434                 }
2435                 case TRANSACT2_QFSINFO:
2436                 {
2437                         outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
2438                                                  length, bufsize, &params, 
2439                                                  &data);
2440                         break;
2441                 }
2442                 case TRANSACT2_SETFSINFO:
2443                 {
2444                         outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
2445                                                        length, bufsize, 
2446                                                        &params, &data);
2447                         break;
2448                 }
2449                 case TRANSACT2_QPATHINFO:
2450                 case TRANSACT2_QFILEINFO:
2451                 {
2452                         outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
2453                                                            length, bufsize, 
2454                                                            &params, &data, total_data);
2455                         break;
2456                 }
2457                 case TRANSACT2_SETPATHINFO:
2458                 case TRANSACT2_SETFILEINFO:
2459                 {
2460                         outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
2461                                                              length, bufsize, 
2462                                                              &params, &data, 
2463                                                              total_data);
2464                         break;
2465                 }
2466                 case TRANSACT2_FINDNOTIFYFIRST:
2467                 {
2468                         outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
2469                                                              length, bufsize, 
2470                                                              &params, &data);
2471                         break;
2472                 }
2473                 case TRANSACT2_FINDNOTIFYNEXT:
2474                 {
2475                         outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
2476                                                             length, bufsize, 
2477                                                             &params, &data);
2478                         break;
2479                 }
2480                 case TRANSACT2_MKDIR:
2481                 {
2482                         outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
2483                                                    bufsize, &params, &data);
2484                         break;
2485                 }
2486                 case TRANSACT2_GET_DFS_REFERRAL:
2487                 {
2488                         outsize = call_trans2getdfsreferral(conn, inbuf, outbuf, 
2489                                                             length, bufsize, &params, 
2490                                                             &data, total_data);
2491                         break;
2492                 }
2493                 case TRANSACT2_REPORT_DFS_INCONSISTANCY:
2494                 {
2495                         outsize = call_trans2reportdfsinconsistancy(conn, inbuf, outbuf,
2496                                                                     length, bufsize, 
2497                                                                     &params, &data);
2498                         break;
2499                 }
2500                 default:
2501                 {
2502                         /* Error in request */
2503                         DEBUG(2,("Unknown request %d in trans2 call\n",
2504                                   tran_call));
2505                         if(params)
2506                                 free(params);
2507                         if(data)
2508                                 free(data);
2509                         return (ERROR(ERRSRV,ERRerror));
2510                 }
2511         }
2512         
2513         /* As we do not know how many data packets will need to be
2514            returned here the various call_trans2xxxx calls
2515            must send their own. Thus a call_trans2xxx routine only
2516            returns a value other than -1 when it wants to send
2517            an error packet. 
2518         */
2519         
2520         if(params)
2521                 free(params);
2522         if(data)
2523                 free(data);
2524         return outsize; /* If a correct response was needed the
2525                            call_trans2xxx calls have already sent
2526                            it. If outsize != -1 then it is returning */
2527 }
2528