configure: Changes for extra headers.
[ab/samba.git/.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 files_struct Files[];
30 extern BOOL case_sensitive;
31 extern int Client;
32 extern int oplock_sock;
33 extern int smb_read_error;
34 extern fstring local_machine;
35 extern int global_oplock_break;
36
37 /****************************************************************************
38   Send the required number of replies back.
39   We assume all fields other than the data fields are
40   set correctly for the type of call.
41   HACK ! Always assumes smb_setup field is zero.
42 ****************************************************************************/
43 static int send_trans2_replies(char *outbuf, int bufsize, char *params, 
44                                int paramsize, char *pdata, int datasize)
45 {
46   /* As we are using a protocol > LANMAN1 then the max_send
47      variable must have been set in the sessetupX call.
48      This takes precedence over the max_xmit field in the
49      global struct. These different max_xmit variables should
50      be merged as this is now too confusing */
51
52   extern int max_send;
53   int data_to_send = datasize;
54   int params_to_send = paramsize;
55   int useable_space;
56   char *pp = params;
57   char *pd = pdata;
58   int params_sent_thistime, data_sent_thistime, total_sent_thistime;
59   int alignment_offset = 3;
60   int data_alignment_offset = 0;
61
62   /* Initially set the wcnt area to be 10 - this is true for all
63      trans2 replies */
64   set_message(outbuf,10,0,True);
65
66   /* If there genuinely are no parameters or data to send just send
67      the empty packet */
68   if(params_to_send == 0 && data_to_send == 0)
69   {
70     send_smb(Client,outbuf);
71     return 0;
72   }
73
74   /* When sending params and data ensure that both are nicely aligned */
75   /* Only do this alignment when there is also data to send - else
76      can cause NT redirector problems. */
77   if (((params_to_send % 4) != 0) && (data_to_send != 0))
78     data_alignment_offset = 4 - (params_to_send % 4);
79
80   /* Space is bufsize minus Netbios over TCP header minus SMB header */
81   /* The alignment_offset is to align the param bytes on an even byte
82      boundary. NT 4.0 Beta needs this to work correctly. */
83   useable_space = bufsize - ((smb_buf(outbuf)+
84                     alignment_offset+data_alignment_offset) - 
85                     outbuf);
86
87   /* useable_space can never be more than max_send minus the
88      alignment offset. */
89   useable_space = MIN(useable_space, 
90                       max_send - (alignment_offset+data_alignment_offset));
91
92
93   while (params_to_send || data_to_send)
94   {
95     /* Calculate whether we will totally or partially fill this packet */
96     total_sent_thistime = params_to_send + data_to_send + 
97                             alignment_offset + data_alignment_offset;
98     /* We can never send more than useable_space */
99     total_sent_thistime = MIN(total_sent_thistime, useable_space);
100
101     set_message(outbuf, 10, total_sent_thistime, True);
102
103     /* Set total params and data to be sent */
104     SSVAL(outbuf,smb_tprcnt,paramsize);
105     SSVAL(outbuf,smb_tdrcnt,datasize);
106
107     /* Calculate how many parameters and data we can fit into
108        this packet. Parameters get precedence */
109
110     params_sent_thistime = MIN(params_to_send,useable_space);
111     data_sent_thistime = useable_space - params_sent_thistime;
112     data_sent_thistime = MIN(data_sent_thistime,data_to_send);
113
114     SSVAL(outbuf,smb_prcnt, params_sent_thistime);
115     if(params_sent_thistime == 0)
116     {
117       SSVAL(outbuf,smb_proff,0);
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   int fnum = -1;
204   int unixmode;
205   int size=0,fmode=0,mtime=0,rmode;
206   int32 inode = 0;
207   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   unix_convert(fname,conn,0,&bad_path);
220     
221   fnum = find_free_file();
222   if (fnum < 0)
223     return(ERROR(ERRSRV,ERRnofids));
224
225   fsp = &Files[fnum];
226
227   if (!check_name(fname,conn))
228   {
229     if((errno == ENOENT) && bad_path)
230     {
231       unix_ERR_class = ERRDOS;
232       unix_ERR_code = ERRbadpath;
233     }
234     fsp->reserved = False;
235     return(UNIXERROR(ERRDOS,ERRnoaccess));
236   }
237
238   unixmode = unix_mode(conn,open_attr | aARCH);
239       
240   open_file_shared(fnum,conn,fname,open_mode,open_ofun,unixmode,
241                    oplock_request, &rmode,&smb_action);
242       
243   if (!fsp->open)
244   {
245     if((errno == ENOENT) && bad_path)
246     {
247       unix_ERR_class = ERRDOS;
248       unix_ERR_code = ERRbadpath;
249     }
250     fsp->reserved = False;
251     return(UNIXERROR(ERRDOS,ERRnoaccess));
252   }
253
254   if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
255     close_file(fnum,False);
256     return(ERROR(ERRDOS,ERRnoaccess));
257   }
258     
259   size = sbuf.st_size;
260   fmode = dos_mode(conn,fname,&sbuf);
261   mtime = sbuf.st_mtime;
262   inode = sbuf.st_ino;
263   if (fmode & aDIR) {
264     close_file(fnum,False);
265     return(ERROR(ERRDOS,ERRnoaccess));
266   }
267
268   /* Realloc the size of parameters and data we will return */
269   params = *pparams = Realloc(*pparams, 28);
270   if(params == NULL)
271     return(ERROR(ERRDOS,ERRnomem));
272
273   bzero(params,28);
274   SSVAL(params,0,fnum);
275   SSVAL(params,2,fmode);
276   put_dos_date2(params,4, mtime);
277   SIVAL(params,8, size);
278   SSVAL(params,12,rmode);
279
280   if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
281     smb_action |= EXTENDED_OPLOCK_GRANTED;
282   }
283
284   SSVAL(params,18,smb_action);
285   SIVAL(params,20,inode);
286  
287   /* Send the required number of replies */
288   send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
289
290   return -1;
291 }
292
293 /****************************************************************************
294   get a level dependent lanman2 dir entry.
295 ****************************************************************************/
296 static int get_lanman2_dir_entry(connection_struct *conn,
297                                  char *path_mask,int dirtype,int info_level,
298                                  int requires_resume_key,
299                                  BOOL dont_descend,char **ppdata, 
300                                  char *base_data, int space_remaining, 
301                                  BOOL *out_of_space,
302                                  int *last_name_off)
303 {
304   char *dname;
305   BOOL found = False;
306   struct stat sbuf;
307   pstring mask;
308   pstring pathreal;
309   pstring fname;
310   BOOL matched;
311   char *p, *pdata = *ppdata;
312   uint32 reskey=0;
313   int prev_dirpos=0;
314   int mode=0;
315   uint32 size=0,len;
316   uint32 mdate=0, adate=0, cdate=0;
317   char *nameptr;
318   BOOL isrootdir = (strequal(conn->dirpath,"./") ||
319                     strequal(conn->dirpath,".") ||
320                     strequal(conn->dirpath,"/"));
321   BOOL was_8_3;
322   int nt_extmode; /* Used for NT connections instead of mode */
323   BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
324
325   *fname = 0;
326   *out_of_space = False;
327
328   if (!conn->dirptr)
329     return(False);
330
331   p = strrchr(path_mask,'/');
332   if(p != NULL)
333     {
334       if(p[1] == '\0')
335         pstrcpy(mask,"*.*");
336       else
337         pstrcpy(mask, p+1);
338     }
339   else
340     pstrcpy(mask, path_mask);
341
342   while (!found)
343     {
344       /* Needed if we run out of space */
345       prev_dirpos = TellDir(conn->dirptr);
346       dname = ReadDirName(conn->dirptr);
347
348       /*
349        * Due to bugs in NT client redirectors we are not using
350        * resume keys any more - set them to zero.
351        * Check out the related comments in findfirst/findnext.
352        * JRA.
353        */
354
355       reskey = 0;
356
357       DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
358                (unsigned)conn->dirptr,TellDir(conn->dirptr)));
359       
360       if (!dname) 
361         return(False);
362
363       matched = False;
364
365       pstrcpy(fname,dname);      
366
367       if(mask_match(fname, mask, case_sensitive, True))
368         {
369           BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
370           if (dont_descend && !isdots)
371             continue;
372           
373           if (isrootdir && isdots)
374             continue;
375
376           pstrcpy(pathreal,conn->dirpath);
377           if(needslash)
378             pstrcat(pathreal,"/");
379           pstrcat(pathreal,dname);
380           if (sys_stat(pathreal,&sbuf) != 0) 
381             {
382               DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
383               continue;
384             }
385
386           mode = dos_mode(conn,pathreal,&sbuf);
387
388           if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
389             DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
390             continue;
391           }
392
393           size = sbuf.st_size;
394           mdate = sbuf.st_mtime;
395           adate = sbuf.st_atime;
396           cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
397           if(mode & aDIR)
398             size = 0;
399
400           DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
401           
402           found = True;
403         }
404     }
405
406   name_map_mangle(fname,False,SNUM(conn));
407
408   p = pdata;
409   nameptr = p;
410
411   nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
412
413   switch (info_level)
414     {
415     case 1:
416       if(requires_resume_key) {
417         SIVAL(p,0,reskey);
418         p += 4;
419       }
420       put_dos_date2(p,l1_fdateCreation,cdate);
421       put_dos_date2(p,l1_fdateLastAccess,adate);
422       put_dos_date2(p,l1_fdateLastWrite,mdate);
423       SIVAL(p,l1_cbFile,size);
424       SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
425       SSVAL(p,l1_attrFile,mode);
426       SCVAL(p,l1_cchName,strlen(fname));
427       pstrcpy(p + l1_achName, fname);
428       nameptr = p + l1_achName;
429       p += l1_achName + strlen(fname) + 1;
430       break;
431
432     case 2:
433       /* info_level 2 */
434       if(requires_resume_key) {
435         SIVAL(p,0,reskey);
436         p += 4;
437       }
438       put_dos_date2(p,l2_fdateCreation,cdate);
439       put_dos_date2(p,l2_fdateLastAccess,adate);
440       put_dos_date2(p,l2_fdateLastWrite,mdate);
441       SIVAL(p,l2_cbFile,size);
442       SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
443       SSVAL(p,l2_attrFile,mode);
444       SIVAL(p,l2_cbList,0); /* No extended attributes */
445       SCVAL(p,l2_cchName,strlen(fname));
446       pstrcpy(p + l2_achName, fname);
447       nameptr = p + l2_achName;
448       p += l2_achName + strlen(fname) + 1;
449       break;
450
451     case 3:
452       SIVAL(p,0,reskey);
453       put_dos_date2(p,4,cdate);
454       put_dos_date2(p,8,adate);
455       put_dos_date2(p,12,mdate);
456       SIVAL(p,16,size);
457       SIVAL(p,20,ROUNDUP(size,1024));
458       SSVAL(p,24,mode);
459       SIVAL(p,26,4);
460       CVAL(p,30) = strlen(fname);
461       pstrcpy(p+31, fname);
462       nameptr = p+31;
463       p += 31 + strlen(fname) + 1;
464       break;
465
466     case 4:
467       if(requires_resume_key) {
468         SIVAL(p,0,reskey);
469         p += 4;
470       }
471       SIVAL(p,0,33+strlen(fname)+1);
472       put_dos_date2(p,4,cdate);
473       put_dos_date2(p,8,adate);
474       put_dos_date2(p,12,mdate);
475       SIVAL(p,16,size);
476       SIVAL(p,20,ROUNDUP(size,1024));
477       SSVAL(p,24,mode);
478       CVAL(p,32) = strlen(fname);
479       pstrcpy(p + 33, fname);
480       nameptr = p+33;
481       p += 33 + strlen(fname) + 1;
482       break;
483
484     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
485       was_8_3 = is_8_3(fname, True);
486       len = 94+strlen(fname);
487       len = (len + 3) & ~3;
488       SIVAL(p,0,len); p += 4;
489       SIVAL(p,0,reskey); p += 4;
490       put_long_date(p,cdate); p += 8;
491       put_long_date(p,adate); p += 8;
492       put_long_date(p,mdate); p += 8;
493       put_long_date(p,mdate); p += 8;
494       SIVAL(p,0,size); p += 8;
495       SIVAL(p,0,size); p += 8;
496       SIVAL(p,0,nt_extmode); p += 4;
497       SIVAL(p,0,strlen(fname)); p += 4;
498       SIVAL(p,0,0); p += 4;
499       if (!was_8_3) {
500         pstrcpy(p+2,fname);
501         if (!name_map_mangle(p+2,True,SNUM(conn)))
502           (p+2)[12] = 0;
503       } else
504         *(p+2) = 0;
505       strupper(p+2);
506       SSVAL(p,0,strlen(p+2));
507       p += 2 + 24;
508       /* nameptr = p;  */
509       pstrcpy(p,fname); p += strlen(p);
510       p = pdata + len;
511       break;
512
513     case SMB_FIND_FILE_DIRECTORY_INFO:
514       len = 64+strlen(fname);
515       len = (len + 3) & ~3;
516       SIVAL(p,0,len); p += 4;
517       SIVAL(p,0,reskey); p += 4;
518       put_long_date(p,cdate); p += 8;
519       put_long_date(p,adate); p += 8;
520       put_long_date(p,mdate); p += 8;
521       put_long_date(p,mdate); p += 8;
522       SIVAL(p,0,size); p += 8;
523       SIVAL(p,0,size); p += 8;
524       SIVAL(p,0,nt_extmode); p += 4;
525       SIVAL(p,0,strlen(fname)); p += 4;
526       pstrcpy(p,fname);
527       p = pdata + len;
528       break;
529       
530       
531     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
532       len = 68+strlen(fname);
533       len = (len + 3) & ~3;
534       SIVAL(p,0,len); p += 4;
535       SIVAL(p,0,reskey); p += 4;
536       put_long_date(p,cdate); p += 8;
537       put_long_date(p,adate); p += 8;
538       put_long_date(p,mdate); p += 8;
539       put_long_date(p,mdate); p += 8;
540       SIVAL(p,0,size); p += 8;
541       SIVAL(p,0,size); p += 8;
542       SIVAL(p,0,nt_extmode); p += 4;
543       SIVAL(p,0,strlen(fname)); p += 4;
544       SIVAL(p,0,0); p += 4;
545       pstrcpy(p,fname);
546       p = pdata + len;
547       break;
548
549     case SMB_FIND_FILE_NAMES_INFO:
550       len = 12+strlen(fname);
551       len = (len + 3) & ~3;
552       SIVAL(p,0,len); p += 4;
553       SIVAL(p,0,reskey); p += 4;
554       SIVAL(p,0,strlen(fname)); p += 4;
555       pstrcpy(p,fname);
556       p = pdata + len;
557       break;
558
559     default:      
560       return(False);
561     }
562
563
564   if (PTR_DIFF(p,pdata) > space_remaining) {
565     /* Move the dirptr back to prev_dirpos */
566     SeekDir(conn->dirptr, prev_dirpos);
567     *out_of_space = True;
568     DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
569     return False; /* Not finished - just out of space */
570   }
571
572   /* Setup the last_filename pointer, as an offset from base_data */
573   *last_name_off = PTR_DIFF(nameptr,base_data);
574   /* Advance the data pointer to the next slot */
575   *ppdata = p;
576   return(found);
577 }
578   
579 /****************************************************************************
580  Convert the directory masks formated for the wire.
581 ****************************************************************************/
582
583 void mask_convert( char *mask)
584 {
585   /*
586    * We know mask is a pstring.
587    */
588   char *p = mask;
589   while (*p) {
590     if (*p == '<') {
591       pstring expnd;
592       if(p[1] != '"' && p[1] != '.') {
593         pstrcpy( expnd, p+1 );
594         *p++ = '*';
595         *p = '.';
596         safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2);
597       } else
598         *p = '*';
599     }
600     if (*p == '>') *p = '?';
601     if (*p == '"') *p = '.';
602     p++;
603   }
604 }
605
606 /****************************************************************************
607   reply to a TRANS2_FINDFIRST
608 ****************************************************************************/
609 static int call_trans2findfirst(connection_struct *conn,
610                                 char *inbuf, char *outbuf, int bufsize,  
611                                 char **pparams, char **ppdata)
612 {
613   /* We must be careful here that we don't return more than the
614      allowed number of data bytes. If this means returning fewer than
615      maxentries then so be it. We assume that the redirector has
616      enough room for the fixed number of parameter bytes it has
617      requested. */
618   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
619   char *params = *pparams;
620   char *pdata = *ppdata;
621   int dirtype = SVAL(params,0);
622   int maxentries = SVAL(params,2);
623   BOOL close_after_first = BITSETW(params+4,0);
624   BOOL close_if_end = BITSETW(params+4,1);
625   BOOL requires_resume_key = BITSETW(params+4,2);
626   int info_level = SVAL(params,6);
627   pstring directory;
628   pstring mask;
629   char *p, *wcard;
630   int last_name_off=0;
631   int dptr_num = -1;
632   int numentries = 0;
633   int i;
634   BOOL finished = False;
635   BOOL dont_descend = False;
636   BOOL out_of_space = False;
637   int space_remaining;
638   BOOL bad_path = False;
639
640   *directory = *mask = 0;
641
642   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",
643            dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
644            info_level, max_data_bytes));
645   
646   switch (info_level) 
647     {
648     case 1:
649     case 2:
650     case 3:
651     case 4:
652     case SMB_FIND_FILE_DIRECTORY_INFO:
653     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
654     case SMB_FIND_FILE_NAMES_INFO:
655     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
656       break;
657     default:
658       return(ERROR(ERRDOS,ERRunknownlevel));
659     }
660
661   pstrcpy(directory, params + 12); /* Complete directory path with 
662                                      wildcard mask appended */
663
664   DEBUG(5,("path=%s\n",directory));
665
666   unix_convert(directory,conn,0,&bad_path);
667   if(!check_name(directory,conn)) {
668     if((errno == ENOENT) && bad_path)
669     {
670       unix_ERR_class = ERRDOS;
671       unix_ERR_code = ERRbadpath;
672     }
673
674 #if 0
675     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
676     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
677        (get_remote_arch() == RA_WINNT))
678     {
679       unix_ERR_class = ERRDOS;
680       unix_ERR_code = ERRbaddirectory;
681     }
682 #endif 
683
684     return(ERROR(ERRDOS,ERRbadpath));
685   }
686
687   p = strrchr(directory,'/');
688   if(p == NULL) {
689     pstrcpy(mask,directory);
690     pstrcpy(directory,"./");
691   } else {
692     pstrcpy(mask,p+1);
693     *p = 0;
694   }
695
696   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
697
698   pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
699   if(!*ppdata)
700     return(ERROR(ERRDOS,ERRnomem));
701   bzero(pdata,max_data_bytes);
702
703   /* Realloc the params space */
704   params = *pparams = Realloc(*pparams, 10);
705   if(params == NULL)
706     return(ERROR(ERRDOS,ERRnomem));
707
708   dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid));
709   if (dptr_num < 0)
710     return(ERROR(ERRDOS,ERRbadfile));
711
712   /* Convert the formatted mask. */
713   mask_convert(mask);
714
715 #if 0 /* JRA */
716   /*
717    * Now we have a working mask_match in util.c, I believe
718    * we no longer need these hacks (in fact they break
719    * things). JRA. 
720    */
721
722   /* a special case for 16 bit apps */
723   if (strequal(mask,"????????.???")) pstrcpy(mask,"*");
724
725   /* handle broken clients that send us old 8.3 format */
726   string_sub(mask,"????????","*");
727   string_sub(mask,".???",".*");
728 #endif /* JRA */
729
730   /* Save the wildcard match and attribs we are using on this directory - 
731      needed as lanman2 assumes these are being saved between calls */
732
733   if(!(wcard = strdup(mask))) {
734     dptr_close(dptr_num);
735     return(ERROR(ERRDOS,ERRnomem));
736   }
737
738   dptr_set_wcard(dptr_num, wcard);
739   dptr_set_attr(dptr_num, dirtype);
740
741   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
742
743   /* We don't need to check for VOL here as this is returned by 
744      a different TRANS2 call. */
745   
746   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
747            conn->dirpath,lp_dontdescend(SNUM(conn))));
748   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
749     dont_descend = True;
750     
751   p = pdata;
752   space_remaining = max_data_bytes;
753   out_of_space = False;
754
755   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
756     {
757
758       /* this is a heuristic to avoid seeking the dirptr except when 
759          absolutely necessary. It allows for a filename of about 40 chars */
760       if (space_remaining < DIRLEN_GUESS && numentries > 0)
761         {
762           out_of_space = True;
763           finished = False;
764         }
765       else
766         {
767           finished = 
768             !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
769                                    requires_resume_key,dont_descend,
770                                    &p,pdata,space_remaining, &out_of_space,
771                                    &last_name_off);
772         }
773
774       if (finished && out_of_space)
775         finished = False;
776
777       if (!finished && !out_of_space)
778         numentries++;
779       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
780     }
781   
782   /* Check if we can close the dirptr */
783   if(close_after_first || (finished && close_if_end))
784     {
785       dptr_close(dptr_num);
786       DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
787       dptr_num = -1;
788     }
789
790   /* 
791    * If there are no matching entries we must return ERRDOS/ERRbadfile - 
792    * from observation of NT.
793    */
794
795   if(numentries == 0)
796     return(ERROR(ERRDOS,ERRbadfile));
797
798   /* At this point pdata points to numentries directory entries. */
799
800   /* Set up the return parameter block */
801   SSVAL(params,0,dptr_num);
802   SSVAL(params,2,numentries);
803   SSVAL(params,4,finished);
804   SSVAL(params,6,0); /* Never an EA error */
805   SSVAL(params,8,last_name_off);
806
807   send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
808
809   if ((! *directory) && dptr_path(dptr_num))
810     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
811
812   DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
813             smb_fn_name(CVAL(inbuf,smb_com)), 
814             mask, directory, dirtype, numentries ) );
815
816   return(-1);
817 }
818
819
820 /****************************************************************************
821   reply to a TRANS2_FINDNEXT
822 ****************************************************************************/
823 static int call_trans2findnext(connection_struct *conn, 
824                                char *inbuf, char *outbuf, 
825                                int length, int bufsize,
826                                char **pparams, char **ppdata)
827 {
828   /* We must be careful here that we don't return more than the
829      allowed number of data bytes. If this means returning fewer than
830      maxentries then so be it. We assume that the redirector has
831      enough room for the fixed number of parameter bytes it has
832      requested. */
833   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
834   char *params = *pparams;
835   char *pdata = *ppdata;
836   int16 dptr_num = SVAL(params,0);
837   int maxentries = SVAL(params,2);
838   uint16 info_level = SVAL(params,4);
839   uint32 resume_key = IVAL(params,6);
840   BOOL close_after_request = BITSETW(params+10,0);
841   BOOL close_if_end = BITSETW(params+10,1);
842   BOOL requires_resume_key = BITSETW(params+10,2);
843   BOOL continue_bit = BITSETW(params+10,3);
844   pstring resume_name;
845   pstring mask;
846   pstring directory;
847   char *p;
848   uint16 dirtype;
849   int numentries = 0;
850   int i, last_name_off=0;
851   BOOL finished = False;
852   BOOL dont_descend = False;
853   BOOL out_of_space = False;
854   int space_remaining;
855
856   *mask = *directory = *resume_name = 0;
857
858   pstrcpy( resume_name, params+12);
859
860   DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
861 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
862 resume_key = %d resume name = %s continue=%d level = %d\n",
863            dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
864            requires_resume_key, resume_key, resume_name, continue_bit, info_level));
865
866   switch (info_level) 
867     {
868     case 1:
869     case 2:
870     case 3:
871     case 4:
872     case SMB_FIND_FILE_DIRECTORY_INFO:
873     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
874     case SMB_FIND_FILE_NAMES_INFO:
875     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
876       break;
877     default:
878       return(ERROR(ERRDOS,ERRunknownlevel));
879     }
880
881   pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
882   if(!*ppdata)
883     return(ERROR(ERRDOS,ERRnomem));
884   bzero(pdata,max_data_bytes);
885
886   /* Realloc the params space */
887   params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
888   if(!params)
889     return(ERROR(ERRDOS,ERRnomem));
890
891   /* Check that the dptr is valid */
892   if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
893     return(ERROR(ERRDOS,ERRnofiles));
894
895   string_set(&conn->dirpath,dptr_path(dptr_num));
896
897   /* Get the wildcard mask from the dptr */
898   if((p = dptr_wcard(dptr_num))== NULL) {
899     DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
900     return (ERROR(ERRDOS,ERRnofiles));
901   }
902   pstrcpy(mask, p);
903   pstrcpy(directory,conn->dirpath);
904
905   /* Get the attr mask from the dptr */
906   dirtype = dptr_attr(dptr_num);
907
908   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
909            dptr_num, mask, dirtype, 
910            (unsigned)conn->dirptr,
911            TellDir(conn->dirptr)));
912
913   /* We don't need to check for VOL here as this is returned by 
914      a different TRANS2 call. */
915
916   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
917   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
918     dont_descend = True;
919     
920   p = pdata;
921   space_remaining = max_data_bytes;
922   out_of_space = False;
923
924   /* 
925    * Seek to the correct position. We no longer use the resume key but
926    * depend on the last file name instead.
927    */
928   if(requires_resume_key && *resume_name && !continue_bit)
929   {
930     /*
931      * Fix for NT redirector problem triggered by resume key indexes
932      * changing between directory scans. We now return a resume key of 0
933      * and instead look for the filename to continue from (also given
934      * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
935      * findfirst/findnext (as is usual) then the directory pointer
936      * should already be at the correct place. Check this by scanning
937      * backwards looking for an exact (ie. case sensitive) filename match. 
938      * If we get to the beginning of the directory and haven't found it then scan
939      * forwards again looking for a match. JRA.
940      */
941
942     int current_pos, start_pos;
943     char *dname = NULL;
944     void *dirptr = conn->dirptr;
945     start_pos = TellDir(dirptr);
946     for(current_pos = start_pos; current_pos >= 0; current_pos--)
947     {
948       DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
949
950       SeekDir(dirptr, current_pos);
951       dname = ReadDirName(dirptr);
952
953       /*
954        * Remember, name_map_mangle is called by
955        * get_lanman2_dir_entry(), so the resume name
956        * could be mangled. Ensure we do the same
957        * here.
958        */
959
960       if(dname != NULL)
961         name_map_mangle( dname, False, SNUM(conn));
962
963       if(dname && strcsequal( resume_name, dname))
964       {
965         SeekDir(dirptr, current_pos+1);
966         DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
967         break;
968       }
969     }
970
971     /*
972      * Scan forward from start if not found going backwards.
973      */
974
975     if(current_pos < 0)
976     {
977       DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
978       SeekDir(dirptr, start_pos);
979       for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
980       {
981         /*
982          * Remember, name_map_mangle is called by
983          * get_lanman2_dir_entry(), so the resume name
984          * could be mangled. Ensure we do the same
985          * here.
986          */
987
988         if(dname != NULL)
989           name_map_mangle( dname, False, SNUM(conn));
990
991         if(dname && strcsequal( resume_name, dname))
992         {
993           SeekDir(dirptr, current_pos+1);
994           DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
995           break;
996         }
997       } /* end for */
998     } /* end if current_pos */
999   } /* end if requires_resume_key && !continue_bit */
1000
1001   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1002     {
1003       /* this is a heuristic to avoid seeking the dirptr except when 
1004          absolutely necessary. It allows for a filename of about 40 chars */
1005       if (space_remaining < DIRLEN_GUESS && numentries > 0)
1006         {
1007           out_of_space = True;
1008           finished = False;
1009         }
1010       else
1011         {
1012           finished = 
1013             !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1014                                    requires_resume_key,dont_descend,
1015                                    &p,pdata,space_remaining, &out_of_space,
1016                                    &last_name_off);
1017         }
1018
1019       if (finished && out_of_space)
1020         finished = False;
1021
1022       if (!finished && !out_of_space)
1023         numentries++;
1024       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1025     }
1026   
1027   /* Check if we can close the dirptr */
1028   if(close_after_request || (finished && close_if_end))
1029     {
1030       dptr_close(dptr_num); /* This frees up the saved mask */
1031       DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1032       dptr_num = -1;
1033     }
1034
1035
1036   /* Set up the return parameter block */
1037   SSVAL(params,0,numentries);
1038   SSVAL(params,2,finished);
1039   SSVAL(params,4,0); /* Never an EA error */
1040   SSVAL(params,6,last_name_off);
1041
1042   send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1043
1044   if ((! *directory) && dptr_path(dptr_num))
1045     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1046
1047   DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1048             smb_fn_name(CVAL(inbuf,smb_com)), 
1049             mask, directory, dirtype, numentries ) );
1050
1051   return(-1);
1052 }
1053
1054 /****************************************************************************
1055   reply to a TRANS2_QFSINFO (query filesystem info)
1056 ****************************************************************************/
1057 static int call_trans2qfsinfo(connection_struct *conn, 
1058                               char *inbuf, char *outbuf, 
1059                               int length, int bufsize,
1060                               char **pparams, char **ppdata)
1061 {
1062   char *pdata = *ppdata;
1063   char *params = *pparams;
1064   uint16 info_level = SVAL(params,0);
1065   int data_len;
1066   struct stat st;
1067   char *vname = volume_label(SNUM(conn));
1068   int snum = SNUM(conn);
1069  
1070   DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1071
1072   if(sys_stat(".",&st)!=0) {
1073     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1074     return (ERROR(ERRSRV,ERRinvdevice));
1075   }
1076
1077   pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
1078
1079   switch (info_level) 
1080     {
1081     case 1:
1082       {
1083         int dfree,dsize,bsize;
1084         data_len = 18;
1085         sys_disk_free(".",&bsize,&dfree,&dsize);        
1086         SIVAL(pdata,l1_idFileSystem,st.st_dev);
1087         SIVAL(pdata,l1_cSectorUnit,bsize/512);
1088         SIVAL(pdata,l1_cUnit,dsize);
1089         SIVAL(pdata,l1_cUnitAvail,dfree);
1090         SSVAL(pdata,l1_cbSector,512);
1091         DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
1092                  bsize, (unsigned)st.st_dev, bsize/512, dsize, dfree, 512));
1093         break;
1094     }
1095     case 2:
1096     { 
1097       /* Return volume name */
1098       int volname_len = MIN(strlen(vname),11);
1099       data_len = l2_vol_szVolLabel + volname_len + 1;
1100       /* 
1101        * Add volume serial number - hash of a combination of
1102        * the called hostname and the service name.
1103        */
1104       SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1105       SCVAL(pdata,l2_vol_cch,volname_len);
1106       StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1107       DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1108                (unsigned)st.st_ctime, volname_len,
1109                pdata+l2_vol_szVolLabel));
1110       break;
1111     }
1112     case SMB_QUERY_FS_ATTRIBUTE_INFO:
1113       data_len = 12 + 2*strlen(FSTYPE_STRING);
1114       SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES); /* FS ATTRIBUTES */
1115 #if 0 /* Old code. JRA. */
1116       SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1117 #endif /* Old code. */
1118       SIVAL(pdata,4,128); /* Max filename component length */
1119       SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
1120       PutUniCode(pdata+12,FSTYPE_STRING);
1121       break;
1122     case SMB_QUERY_FS_LABEL_INFO:
1123       data_len = 4 + strlen(vname);
1124       SIVAL(pdata,0,strlen(vname));
1125       pstrcpy(pdata+4,vname);      
1126       break;
1127     case SMB_QUERY_FS_VOLUME_INFO:      
1128       data_len = 18 + 2*strlen(vname);
1129       /* 
1130        * Add volume serial number - hash of a combination of
1131        * the called hostname and the service name.
1132        */
1133       SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1134       SIVAL(pdata,12,2*strlen(vname));
1135       PutUniCode(pdata+18,vname);      
1136       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
1137                vname));
1138       break;
1139     case SMB_QUERY_FS_SIZE_INFO:
1140       {
1141         int dfree,dsize,bsize;
1142         data_len = 24;
1143         sys_disk_free(".",&bsize,&dfree,&dsize);        
1144         SIVAL(pdata,0,dsize);
1145         SIVAL(pdata,8,dfree);
1146         SIVAL(pdata,16,bsize/512);
1147         SIVAL(pdata,20,512);
1148       }
1149       break;
1150     case SMB_QUERY_FS_DEVICE_INFO:
1151       data_len = 8;
1152       SIVAL(pdata,0,0); /* dev type */
1153       SIVAL(pdata,4,0); /* characteristics */
1154       break;
1155     default:
1156       return(ERROR(ERRDOS,ERRunknownlevel));
1157     }
1158
1159
1160   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1161
1162   DEBUG( 4, ( "%s info_level = %d\n",
1163             smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1164
1165   return -1;
1166 }
1167
1168 /****************************************************************************
1169   reply to a TRANS2_SETFSINFO (set filesystem info)
1170 ****************************************************************************/
1171 static int call_trans2setfsinfo(connection_struct *conn,
1172                                 char *inbuf, char *outbuf, int length, 
1173                                 int bufsize,
1174                                 char **pparams, char **ppdata)
1175 {
1176   /* Just say yes we did it - there is nothing that
1177      can be set here so it doesn't matter. */
1178   int outsize;
1179   DEBUG(3,("call_trans2setfsinfo\n"));
1180
1181   if (!CAN_WRITE(conn))
1182     return(ERROR(ERRSRV,ERRaccess));
1183
1184   outsize = set_message(outbuf,10,0,True);
1185
1186   return outsize;
1187 }
1188
1189 /****************************************************************************
1190   Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1191   file name or file id).
1192 ****************************************************************************/
1193
1194 static int call_trans2qfilepathinfo(connection_struct *conn,
1195                                     char *inbuf, char *outbuf, int length, 
1196                                     int bufsize,
1197                                     char **pparams,char **ppdata,
1198                                     int total_data)
1199 {
1200   char *params = *pparams;
1201   char *pdata = *ppdata;
1202   uint16 tran_call = SVAL(inbuf, smb_setup0);
1203   uint16 info_level;
1204   int mode=0;
1205   int size=0;
1206   unsigned int data_size;
1207   struct stat sbuf;
1208   pstring fname1;
1209   char *fname;
1210   char *p;
1211   int l,pos;
1212   BOOL bad_path = False;
1213
1214   if (tran_call == TRANSACT2_QFILEINFO) {
1215     int16 fnum = SVALS(params,0);
1216     info_level = SVAL(params,2);
1217
1218     CHECK_FNUM(fnum,conn);
1219     CHECK_ERROR(fnum);
1220
1221     fname = Files[fnum].fsp_name;
1222     if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
1223       DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno)));
1224       return(UNIXERROR(ERRDOS,ERRbadfid));
1225     }
1226     pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR);
1227   } else {
1228     /* qpathinfo */
1229     info_level = SVAL(params,0);
1230     fname = &fname1[0];
1231     pstrcpy(fname,&params[6]);
1232     unix_convert(fname,conn,0,&bad_path);
1233     if (!check_name(fname,conn) || sys_stat(fname,&sbuf)) {
1234       DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1235       if((errno == ENOENT) && bad_path)
1236       {
1237         unix_ERR_class = ERRDOS;
1238         unix_ERR_code = ERRbadpath;
1239       }
1240       return(UNIXERROR(ERRDOS,ERRbadpath));
1241     }
1242     pos = 0;
1243   }
1244
1245
1246   DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1247            fname,info_level,tran_call,total_data));
1248
1249   p = strrchr(fname,'/'); 
1250   if (!p) 
1251     p = fname;
1252   else
1253     p++;
1254   l = strlen(p);  
1255   mode = dos_mode(conn,fname,&sbuf);
1256   size = sbuf.st_size;
1257   if (mode & aDIR) size = 0;
1258   
1259   params = *pparams = Realloc(*pparams,2); bzero(params,2);
1260   data_size = 1024;
1261   pdata = *ppdata = Realloc(*ppdata, data_size); 
1262
1263   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1264     /* uggh, EAs for OS2 */
1265     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1266     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1267   }
1268
1269   bzero(pdata,data_size);
1270
1271   switch (info_level) 
1272     {
1273     case SMB_INFO_STANDARD:
1274     case SMB_INFO_QUERY_EA_SIZE:
1275       data_size = (info_level==1?22:26);
1276       put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1277       put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1278       put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1279       SIVAL(pdata,l1_cbFile,size);
1280       SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1281       SSVAL(pdata,l1_attrFile,mode);
1282       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1283       break;
1284
1285     case SMB_INFO_QUERY_EAS_FROM_LIST:
1286       data_size = 24;
1287       put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1288       put_dos_date2(pdata,4,sbuf.st_atime);
1289       put_dos_date2(pdata,8,sbuf.st_mtime);
1290       SIVAL(pdata,12,size);
1291       SIVAL(pdata,16,ROUNDUP(size,1024));
1292       SIVAL(pdata,20,mode);
1293       break;
1294
1295     case SMB_INFO_QUERY_ALL_EAS:
1296       data_size = 4;
1297       SIVAL(pdata,0,data_size);
1298       break;
1299
1300     case 6:
1301       return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */      
1302
1303     case SMB_QUERY_FILE_BASIC_INFO:
1304       data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1305       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1306       put_long_date(pdata+8,sbuf.st_atime);
1307       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1308       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1309       SIVAL(pdata,32,mode);
1310
1311       DEBUG(5,("SMB_QFBI - "));
1312       {
1313         time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1314         DEBUG(5,("create: %s ", ctime(&create_time)));
1315       }
1316       DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1317       DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1318       DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1319       DEBUG(5,("mode: %x\n", mode));
1320
1321       break;
1322
1323     case SMB_QUERY_FILE_STANDARD_INFO:
1324       data_size = 22;
1325       SIVAL(pdata,0,size);
1326       SIVAL(pdata,8,size);
1327       SIVAL(pdata,16,sbuf.st_nlink);
1328       CVAL(pdata,20) = 0;
1329       CVAL(pdata,21) = (mode&aDIR)?1:0;
1330       break;
1331
1332     case SMB_QUERY_FILE_EA_INFO:
1333       data_size = 4;
1334       break;
1335
1336     /* Get the 8.3 name - used if NT SMB was negotiated. */
1337     case SMB_QUERY_FILE_ALT_NAME_INFO:
1338       {
1339         pstring short_name;
1340         pstrcpy(short_name,p);
1341         /* Mangle if not already 8.3 */
1342         if(!is_8_3(short_name, True))
1343         {
1344           if(!name_map_mangle(short_name,True,SNUM(conn)))
1345             *short_name = '\0';
1346         }
1347         strupper(short_name);
1348         l = strlen(short_name);
1349         PutUniCode(pdata + 4, short_name);
1350         data_size = 4 + (2*l);
1351         SIVAL(pdata,0,2*l);
1352       }
1353       break;
1354
1355     case SMB_QUERY_FILE_NAME_INFO:
1356       data_size = 4 + l;
1357       SIVAL(pdata,0,l);
1358       pstrcpy(pdata+4,fname);
1359       break;
1360
1361     case SMB_QUERY_FILE_ALLOCATION_INFO:
1362     case SMB_QUERY_FILE_END_OF_FILEINFO:
1363       data_size = 8;
1364       SIVAL(pdata,0,size);
1365       break;
1366
1367     case SMB_QUERY_FILE_ALL_INFO:
1368       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1369       put_long_date(pdata+8,sbuf.st_atime);
1370       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1371       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1372       SIVAL(pdata,32,mode);
1373       pdata += 40;
1374       SIVAL(pdata,0,size);
1375       SIVAL(pdata,8,size);
1376       SIVAL(pdata,16,sbuf.st_nlink);
1377       CVAL(pdata,20) = 0;
1378       CVAL(pdata,21) = (mode&aDIR)?1:0;
1379       pdata += 24;
1380       pdata += 8; /* index number */
1381       pdata += 4; /* EA info */
1382       if (mode & aRONLY)
1383         SIVAL(pdata,0,0xA9);
1384       else
1385         SIVAL(pdata,0,0xd01BF);
1386       pdata += 4;
1387       SIVAL(pdata,0,pos); /* current offset */
1388       pdata += 8;
1389       SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1390       pdata += 4;
1391       pdata += 4; /* alignment */
1392       SIVAL(pdata,0,l);
1393       pstrcpy(pdata+4,fname);
1394       pdata += 4 + l;
1395       data_size = PTR_DIFF(pdata,(*ppdata));
1396       break;
1397
1398     case SMB_QUERY_FILE_STREAM_INFO:
1399       data_size = 24 + l;
1400       SIVAL(pdata,0,pos);
1401       SIVAL(pdata,4,size);
1402       SIVAL(pdata,12,size);
1403       SIVAL(pdata,20,l);        
1404       pstrcpy(pdata+24,fname);
1405       break;
1406     default:
1407       return(ERROR(ERRDOS,ERRunknownlevel));
1408     }
1409
1410   send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1411
1412   return(-1);
1413 }
1414
1415 /****************************************************************************
1416   reply to a TRANS2_SETFILEINFO (set file info by fileid)
1417 ****************************************************************************/
1418 static int call_trans2setfilepathinfo(connection_struct *conn,
1419                                       char *inbuf, char *outbuf, int length, 
1420                                       int bufsize, char **pparams, 
1421                                       char **ppdata, int total_data)
1422 {
1423   char *params = *pparams;
1424   char *pdata = *ppdata;
1425   uint16 tran_call = SVAL(inbuf, smb_setup0);
1426   uint16 info_level;
1427   int mode=0;
1428   int size=0;
1429   struct utimbuf tvs;
1430   struct stat st;
1431   pstring fname1;
1432   char *fname;
1433   int fd = -1;
1434   BOOL bad_path = False;
1435
1436   if (!CAN_WRITE(conn))
1437     return(ERROR(ERRSRV,ERRaccess));
1438
1439   if (tran_call == TRANSACT2_SETFILEINFO) {
1440     int16 fnum = SVALS(params,0);
1441     info_level = SVAL(params,2);    
1442
1443     CHECK_FNUM(fnum,conn);
1444     CHECK_ERROR(fnum);
1445
1446     fname = Files[fnum].fsp_name;
1447     fd = Files[fnum].fd_ptr->fd;
1448
1449     if(fstat(fd,&st)!=0) {
1450       DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1451       return(ERROR(ERRDOS,ERRbadpath));
1452     }
1453   } else {
1454     /* set path info */
1455     info_level = SVAL(params,0);    
1456     fname = fname1;
1457     pstrcpy(fname,&params[6]);
1458     unix_convert(fname,conn,0,&bad_path);
1459     if(!check_name(fname, conn))
1460     {
1461       if((errno == ENOENT) && bad_path)
1462       {
1463         unix_ERR_class = ERRDOS;
1464         unix_ERR_code = ERRbadpath;
1465       }
1466       return(UNIXERROR(ERRDOS,ERRbadpath));
1467     }
1468  
1469     if(sys_stat(fname,&st)!=0) {
1470       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1471       if((errno == ENOENT) && bad_path)
1472       {
1473         unix_ERR_class = ERRDOS;
1474         unix_ERR_code = ERRbadpath;
1475       }
1476       return(UNIXERROR(ERRDOS,ERRbadpath));
1477     }    
1478   }
1479
1480   DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1481            tran_call,fname,info_level,total_data));
1482
1483   /* Realloc the parameter and data sizes */
1484   params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1485   if(params == NULL)
1486     return(ERROR(ERRDOS,ERRnomem));
1487
1488   size = st.st_size;
1489   tvs.modtime = st.st_mtime;
1490   tvs.actime = st.st_atime;
1491   mode = dos_mode(conn,fname,&st);
1492
1493   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1494     /* uggh, EAs for OS2 */
1495     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1496     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1497   }
1498
1499   switch (info_level)
1500   {
1501     case SMB_INFO_STANDARD:
1502     case SMB_INFO_QUERY_EA_SIZE:
1503     {
1504       /* access time */
1505       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1506
1507       /* write time */
1508       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1509
1510       mode = SVAL(pdata,l1_attrFile);
1511       size = IVAL(pdata,l1_cbFile);
1512       break;
1513     }
1514
1515     /* XXXX um, i don't think this is right.
1516        it's also not in the cifs6.txt spec.
1517      */
1518     case SMB_INFO_QUERY_EAS_FROM_LIST:
1519       tvs.actime = make_unix_date2(pdata+8);
1520       tvs.modtime = make_unix_date2(pdata+12);
1521       size = IVAL(pdata,16);
1522       mode = IVAL(pdata,24);
1523       break;
1524
1525     /* XXXX nor this.  not in cifs6.txt, either. */
1526     case SMB_INFO_QUERY_ALL_EAS:
1527       tvs.actime = make_unix_date2(pdata+8);
1528       tvs.modtime = make_unix_date2(pdata+12);
1529       size = IVAL(pdata,16);
1530       mode = IVAL(pdata,24);
1531       break;
1532
1533     case SMB_SET_FILE_BASIC_INFO:
1534     {
1535       /* Ignore create time at offset pdata. */
1536
1537       /* access time */
1538       tvs.actime = interpret_long_date(pdata+8);
1539
1540       /* write time + changed time, combined. */
1541       tvs.modtime=MAX(interpret_long_date(pdata+16),
1542                       interpret_long_date(pdata+24));
1543
1544 #if 0 /* Needs more testing... */
1545       /* Test from Luke to prevent Win95 from
1546          setting incorrect values here.
1547        */
1548       if (tvs.actime < tvs.modtime)
1549         return(ERROR(ERRDOS,ERRnoaccess));
1550 #endif /* Needs more testing... */
1551
1552       /* attributes */
1553       mode = IVAL(pdata,32);
1554       break;
1555     }
1556
1557     case SMB_SET_FILE_END_OF_FILE_INFO:
1558     {
1559       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1560          return(ERROR(ERRDOS,ERRunknownlevel));
1561       size = IVAL(pdata,0);
1562       break;
1563     }
1564
1565     case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1566     case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1567     default:
1568     {
1569       return(ERROR(ERRDOS,ERRunknownlevel));
1570     }
1571   }
1572
1573   DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1574   DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1575   DEBUG(6,("size: %x "   , size));
1576   DEBUG(6,("mode: %x\n"  , mode));
1577
1578   /* get some defaults (no modifications) if any info is zero. */
1579   if (!tvs.actime) tvs.actime = st.st_atime;
1580   if (!tvs.modtime) tvs.modtime = st.st_mtime;
1581   if (!size) size = st.st_size;
1582
1583   /* Try and set the times, size and mode of this file -
1584      if they are different from the current values
1585    */
1586   if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1587   {
1588     if(file_utime(conn, fname, &tvs)!=0)
1589     {
1590       return(ERROR(ERRDOS,ERRnoaccess));
1591     }
1592   }
1593
1594   /* check the mode isn't different, before changing it */
1595   if (mode != dos_mode(conn, fname, &st) && dos_chmod(conn, fname, mode, NULL))
1596   {
1597     DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1598     return(ERROR(ERRDOS,ERRnoaccess));
1599   }
1600
1601   if(size != st.st_size)
1602   {
1603     if (fd == -1)
1604     {
1605       fd = sys_open(fname,O_RDWR,0);
1606       if (fd == -1)
1607       {
1608         return(ERROR(ERRDOS,ERRbadpath));
1609       }
1610       set_filelen(fd, size);
1611       close(fd);
1612     }
1613     else
1614     {
1615       set_filelen(fd, size);
1616     }
1617   }
1618
1619   SSVAL(params,0,0);
1620
1621   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1622   
1623   return(-1);
1624 }
1625
1626 /****************************************************************************
1627   reply to a TRANS2_MKDIR (make directory with extended attributes).
1628 ****************************************************************************/
1629 static int call_trans2mkdir(connection_struct *conn,
1630                             char *inbuf, char *outbuf, int length, int bufsize,
1631                             char **pparams, char **ppdata)
1632 {
1633   char *params = *pparams;
1634   pstring directory;
1635   int ret = -1;
1636   BOOL bad_path = False;
1637
1638   if (!CAN_WRITE(conn))
1639     return(ERROR(ERRSRV,ERRaccess));
1640
1641   pstrcpy(directory, &params[4]);
1642
1643   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1644
1645   unix_convert(directory,conn,0,&bad_path);
1646   if (check_name(directory,conn))
1647     ret = sys_mkdir(directory,unix_mode(conn,aDIR));
1648   
1649   if(ret < 0)
1650     {
1651       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1652       if((errno == ENOENT) && bad_path)
1653       {
1654         unix_ERR_class = ERRDOS;
1655         unix_ERR_code = ERRbadpath;
1656       }
1657       return(UNIXERROR(ERRDOS,ERRnoaccess));
1658     }
1659
1660   /* Realloc the parameter and data sizes */
1661   params = *pparams = Realloc(*pparams,2);
1662   if(params == NULL)
1663     return(ERROR(ERRDOS,ERRnomem));
1664
1665   SSVAL(params,0,0);
1666
1667   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1668   
1669   return(-1);
1670 }
1671
1672 /****************************************************************************
1673   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1674   We don't actually do this - we just send a null response.
1675 ****************************************************************************/
1676 static int call_trans2findnotifyfirst(connection_struct *conn,
1677                                       char *inbuf, char *outbuf, 
1678                                       int length, int bufsize,
1679                                       char **pparams, char **ppdata)
1680 {
1681   static uint16 fnf_handle = 257;
1682   char *params = *pparams;
1683   uint16 info_level = SVAL(params,4);
1684
1685   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1686
1687   switch (info_level) 
1688     {
1689     case 1:
1690     case 2:
1691       break;
1692     default:
1693       return(ERROR(ERRDOS,ERRunknownlevel));
1694     }
1695
1696   /* Realloc the parameter and data sizes */
1697   params = *pparams = Realloc(*pparams,6);
1698   if(params == NULL)
1699     return(ERROR(ERRDOS,ERRnomem));
1700
1701   SSVAL(params,0,fnf_handle);
1702   SSVAL(params,2,0); /* No changes */
1703   SSVAL(params,4,0); /* No EA errors */
1704
1705   fnf_handle++;
1706
1707   if(fnf_handle == 0)
1708     fnf_handle = 257;
1709
1710   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1711   
1712   return(-1);
1713 }
1714
1715 /****************************************************************************
1716   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
1717   changes). Currently this does nothing.
1718 ****************************************************************************/
1719 static int call_trans2findnotifynext(connection_struct *conn,
1720                                      char *inbuf, char *outbuf, 
1721                                      int length, int bufsize,
1722                                      char **pparams, char **ppdata)
1723 {
1724   char *params = *pparams;
1725
1726   DEBUG(3,("call_trans2findnotifynext\n"));
1727
1728   /* Realloc the parameter and data sizes */
1729   params = *pparams = Realloc(*pparams,4);
1730   if(params == NULL)
1731     return(ERROR(ERRDOS,ERRnomem));
1732
1733   SSVAL(params,0,0); /* No changes */
1734   SSVAL(params,2,0); /* No EA errors */
1735
1736   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1737   
1738   return(-1);
1739 }
1740
1741 /****************************************************************************
1742   reply to a SMBfindclose (stop trans2 directory search)
1743 ****************************************************************************/
1744 int reply_findclose(connection_struct *conn,
1745                     char *inbuf,char *outbuf,int length,int bufsize)
1746 {
1747         int outsize = 0;
1748         int16 dptr_num=SVALS(inbuf,smb_vwv0);
1749
1750         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
1751
1752         dptr_close(dptr_num);
1753
1754         outsize = set_message(outbuf,0,0,True);
1755
1756         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
1757
1758         return(outsize);
1759 }
1760
1761 /****************************************************************************
1762   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1763 ****************************************************************************/
1764 int reply_findnclose(connection_struct *conn, 
1765                      char *inbuf,char *outbuf,int length,int bufsize)
1766 {
1767         int outsize = 0;
1768         int dptr_num= -1;
1769         
1770         dptr_num = SVAL(inbuf,smb_vwv0);
1771
1772         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
1773
1774         /* We never give out valid handles for a 
1775            findnotifyfirst - so any dptr_num is ok here. 
1776            Just ignore it. */
1777
1778         outsize = set_message(outbuf,0,0,True);
1779
1780         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
1781
1782         return(outsize);
1783 }
1784
1785
1786 /****************************************************************************
1787   reply to a SMBtranss2 - just ignore it!
1788 ****************************************************************************/
1789 int reply_transs2(connection_struct *conn,
1790                   char *inbuf,char *outbuf,int length,int bufsize)
1791 {
1792         DEBUG(4,("Ignoring transs2 of length %d\n",length));
1793         return(-1);
1794 }
1795
1796 /****************************************************************************
1797   reply to a SMBtrans2
1798 ****************************************************************************/
1799 int reply_trans2(connection_struct *conn,
1800                  char *inbuf,char *outbuf,int length,int bufsize)
1801 {
1802         int outsize = 0;
1803         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1804         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1805 #if 0
1806         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1807         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1808         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1809         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1810         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1811         int32 timeout = IVALS(inbuf,smb_timeout);
1812 #endif
1813         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1814         unsigned int tran_call = SVAL(inbuf, smb_setup0);
1815         char *params = NULL, *data = NULL;
1816         int num_params, num_params_sofar, num_data, num_data_sofar;
1817
1818         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
1819                 /* Queue this open message as we are the process of an
1820                  * oplock break.  */
1821
1822                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
1823                 DEBUGADD(2,( "in oplock break state.\n"));
1824
1825                 push_oplock_pending_smb_message(inbuf, length);
1826                 return -1;
1827         }
1828         
1829         outsize = set_message(outbuf,0,0,True);
1830
1831         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1832            is so as a sanity check */
1833         if (suwcnt != 1) {
1834                 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1835                 return(ERROR(ERRSRV,ERRerror));
1836         }
1837     
1838         /* Allocate the space for the maximum needed parameters and data */
1839         if (total_params > 0)
1840                 params = (char *)malloc(total_params);
1841         if (total_data > 0)
1842                 data = (char *)malloc(total_data);
1843   
1844         if ((total_params && !params)  || (total_data && !data)) {
1845                 DEBUG(2,("Out of memory in reply_trans2\n"));
1846                 return(ERROR(ERRDOS,ERRnomem));
1847         }
1848
1849         /* Copy the param and data bytes sent with this request into
1850            the params buffer */
1851         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1852         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1853
1854         if (num_params > total_params || num_data > total_data)
1855                 exit_server("invalid params in reply_trans2");
1856
1857         if(params)
1858                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1859         if(data)
1860                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1861
1862         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
1863                 /* We need to send an interim response then receive the rest
1864                    of the parameter/data bytes */
1865                 outsize = set_message(outbuf,0,0,True);
1866                 send_smb(Client,outbuf);
1867
1868                 while (num_data_sofar < total_data || 
1869                        num_params_sofar < total_params) {
1870                         BOOL ret;
1871
1872                         ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1873                                                SMB_SECONDARY_WAIT);
1874                         
1875                         if ((ret && 
1876                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
1877                                 outsize = set_message(outbuf,0,0,True);
1878                                 if(ret)
1879                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1880                                 else
1881                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1882                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1883                                 if(params)
1884                                         free(params);
1885                                 if(data)
1886                                         free(data);
1887                                 return(ERROR(ERRSRV,ERRerror));
1888                         }
1889       
1890                         /* Revise total_params and total_data in case
1891                            they have changed downwards */
1892                         total_params = SVAL(inbuf, smb_tpscnt);
1893                         total_data = SVAL(inbuf, smb_tdscnt);
1894                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1895                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1896                         if (num_params_sofar > total_params || num_data_sofar > total_data)
1897                                 exit_server("data overflow in trans2");
1898                         
1899                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
1900                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1901                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1902                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1903                 }
1904         }
1905         
1906         if (Protocol >= PROTOCOL_NT1) {
1907                 uint16 flg2 = SVAL(outbuf,smb_flg2);
1908                 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1909         }
1910
1911         /* Now we must call the relevant TRANS2 function */
1912         switch(tran_call)  {
1913         case TRANSACT2_OPEN:
1914                 outsize = call_trans2open(conn, 
1915                                           inbuf, outbuf, bufsize, 
1916                                           &params, &data);
1917                 break;
1918
1919         case TRANSACT2_FINDFIRST:
1920                 outsize = call_trans2findfirst(conn, inbuf, outbuf, 
1921                                                bufsize, &params, &data);
1922                 break;
1923
1924         case TRANSACT2_FINDNEXT:
1925                 outsize = call_trans2findnext(conn, inbuf, outbuf, 
1926                                               length, bufsize, 
1927                                               &params, &data);
1928                 break;
1929
1930         case TRANSACT2_QFSINFO:
1931             outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
1932                                          length, bufsize, &params, 
1933                                          &data);
1934             break;
1935
1936         case TRANSACT2_SETFSINFO:
1937                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
1938                                                length, bufsize, 
1939                                                &params, &data);
1940                 break;
1941
1942         case TRANSACT2_QPATHINFO:
1943         case TRANSACT2_QFILEINFO:
1944                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
1945                                                    length, bufsize, 
1946                                                    &params, &data, total_data);
1947                 break;
1948         case TRANSACT2_SETPATHINFO:
1949         case TRANSACT2_SETFILEINFO:
1950                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
1951                                                      length, bufsize, 
1952                                                      &params, &data, 
1953                                                      total_data);
1954                 break;
1955
1956         case TRANSACT2_FINDNOTIFYFIRST:
1957                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
1958                                                      length, bufsize, 
1959                                                      &params, &data);
1960                 break;
1961
1962         case TRANSACT2_FINDNOTIFYNEXT:
1963                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
1964                                                     length, bufsize, 
1965                                                     &params, &data);
1966                 break;
1967         case TRANSACT2_MKDIR:
1968                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
1969                                            bufsize, &params, &data);
1970                 break;
1971         default:
1972                 /* Error in request */
1973                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
1974                 if(params)
1975                         free(params);
1976                 if(data)
1977                         free(data);
1978                 return (ERROR(ERRSRV,ERRerror));
1979         }
1980         
1981         /* As we do not know how many data packets will need to be
1982            returned here the various call_trans2xxxx calls
1983            must send their own. Thus a call_trans2xxx routine only
1984            returns a value other than -1 when it wants to send
1985            an error packet. 
1986         */
1987         
1988         if(params)
1989                 free(params);
1990         if(data)
1991                 free(data);
1992         return outsize; /* If a correct response was needed the
1993                            call_trans2xxx calls have already sent
1994                            it. If outsize != -1 then it is returning */
1995 }