190910bd97f1be92d5ca8fa57db8be24e88330b3
[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 oplock_sock;
32 extern int smb_read_error;
33 extern fstring local_machine;
34 extern int global_oplock_break;
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_prdisp,0);
118     }
119     else
120     {
121       /* smb_proff is the offset from the start of the SMB header to the
122          parameter bytes, however the first 4 bytes of outbuf are
123          the Netbios over TCP header. Thus use smb_base() to subtract
124          them from the calculation */
125       SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
126       /* Absolute displacement of param bytes sent in this packet */
127       SSVAL(outbuf,smb_prdisp,pp - params);
128     }
129
130     SSVAL(outbuf,smb_drcnt, data_sent_thistime);
131     if(data_sent_thistime == 0)
132     {
133       SSVAL(outbuf,smb_droff,0);
134       SSVAL(outbuf,smb_drdisp, 0);
135     }
136     else
137     {
138       /* The offset of the data bytes is the offset of the
139          parameter bytes plus the number of parameters being sent this time */
140       SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
141             smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
142       SSVAL(outbuf,smb_drdisp, pd - pdata);
143     }
144
145     /* Copy the param bytes into the packet */
146     if(params_sent_thistime)
147       memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
148     /* Copy in the data bytes */
149     if(data_sent_thistime)
150       memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
151              data_alignment_offset,pd,data_sent_thistime);
152
153     DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
154           params_sent_thistime, data_sent_thistime, useable_space));
155     DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
156           params_to_send, data_to_send, paramsize, datasize));
157
158     /* Send the packet */
159     send_smb(Client,outbuf);
160
161     pp += params_sent_thistime;
162     pd += data_sent_thistime;
163
164     params_to_send -= params_sent_thistime;
165     data_to_send -= data_sent_thistime;
166
167     /* Sanity check */
168     if(params_to_send < 0 || data_to_send < 0)
169     {
170       DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
171             params_to_send, data_to_send));
172       return -1;
173     }
174   }
175
176   return 0;
177 }
178
179
180 /****************************************************************************
181   reply to a TRANSACT2_OPEN
182 ****************************************************************************/
183 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, 
184                            int bufsize,  
185                            char **pparams, char **ppdata)
186 {
187   char *params = *pparams;
188   int16 open_mode = SVAL(params, 2);
189   int16 open_attr = SVAL(params,6);
190   BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
191 #if 0
192   BOOL return_additional_info = BITSETW(params,0);
193   int16 open_sattr = SVAL(params, 4);
194   time_t open_time = make_unix_date3(params+8);
195 #endif
196   int16 open_ofun = SVAL(params,12);
197   int32 open_size = IVAL(params,14);
198   char *pname = &params[28];
199   int16 namelen = strlen(pname)+1;
200
201   pstring fname;
202   int unixmode;
203   int size=0,fmode=0,mtime=0,rmode;
204   int32 inode = 0;
205   struct stat sbuf;
206   int smb_action = 0;
207   BOOL bad_path = False;
208   files_struct *fsp;
209
210   StrnCpy(fname,pname,namelen);
211
212   DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
213            fname,open_mode, open_attr, open_ofun, open_size));
214
215   /* XXXX we need to handle passed times, sattr and flags */
216
217   unix_convert(fname,conn,0,&bad_path);
218     
219   fsp = file_new();
220   if (!fsp)
221     return(ERROR(ERRSRV,ERRnofids));
222
223   if (!check_name(fname,conn))
224   {
225     if((errno == ENOENT) && bad_path)
226     {
227       unix_ERR_class = ERRDOS;
228       unix_ERR_code = ERRbadpath;
229     }
230     file_free(fsp);
231     return(UNIXERROR(ERRDOS,ERRnoaccess));
232   }
233
234   unixmode = unix_mode(conn,open_attr | aARCH);
235       
236   open_file_shared(fsp,conn,fname,open_mode,open_ofun,unixmode,
237                    oplock_request, &rmode,&smb_action);
238       
239   if (!fsp->open)
240   {
241     if((errno == ENOENT) && bad_path)
242     {
243       unix_ERR_class = ERRDOS;
244       unix_ERR_code = ERRbadpath;
245     }
246     file_free(fsp);
247     return(UNIXERROR(ERRDOS,ERRnoaccess));
248   }
249
250   if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
251     close_file(fsp,False);
252     return(ERROR(ERRDOS,ERRnoaccess));
253   }
254     
255   size = sbuf.st_size;
256   fmode = dos_mode(conn,fname,&sbuf);
257   mtime = sbuf.st_mtime;
258   inode = sbuf.st_ino;
259   if (fmode & aDIR) {
260     close_file(fsp,False);
261     return(ERROR(ERRDOS,ERRnoaccess));
262   }
263
264   /* Realloc the size of parameters and data we will return */
265   params = *pparams = Realloc(*pparams, 28);
266   if(params == NULL)
267     return(ERROR(ERRDOS,ERRnomem));
268
269   bzero(params,28);
270   SSVAL(params,0,fsp->fnum);
271   SSVAL(params,2,fmode);
272   put_dos_date2(params,4, mtime);
273   SIVAL(params,8, size);
274   SSVAL(params,12,rmode);
275
276   if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
277     smb_action |= EXTENDED_OPLOCK_GRANTED;
278   }
279
280   SSVAL(params,18,smb_action);
281   SIVAL(params,20,inode);
282  
283   /* Send the required number of replies */
284   send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
285
286   return -1;
287 }
288
289 /****************************************************************************
290   get a level dependent lanman2 dir entry.
291 ****************************************************************************/
292 static int get_lanman2_dir_entry(connection_struct *conn,
293                                  char *path_mask,int dirtype,int info_level,
294                                  int requires_resume_key,
295                                  BOOL dont_descend,char **ppdata, 
296                                  char *base_data, int space_remaining, 
297                                  BOOL *out_of_space,
298                                  int *last_name_off)
299 {
300   char *dname;
301   BOOL found = False;
302   struct stat sbuf;
303   pstring mask;
304   pstring pathreal;
305   pstring fname;
306   BOOL matched;
307   char *p, *pdata = *ppdata;
308   uint32 reskey=0;
309   int prev_dirpos=0;
310   int mode=0;
311   uint32 size=0,len;
312   uint32 mdate=0, adate=0, cdate=0;
313   char *nameptr;
314   BOOL isrootdir = (strequal(conn->dirpath,"./") ||
315                     strequal(conn->dirpath,".") ||
316                     strequal(conn->dirpath,"/"));
317   BOOL was_8_3;
318   int nt_extmode; /* Used for NT connections instead of mode */
319   BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
320
321   *fname = 0;
322   *out_of_space = False;
323
324   if (!conn->dirptr)
325     return(False);
326
327   p = strrchr(path_mask,'/');
328   if(p != NULL)
329     {
330       if(p[1] == '\0')
331         pstrcpy(mask,"*.*");
332       else
333         pstrcpy(mask, p+1);
334     }
335   else
336     pstrcpy(mask, path_mask);
337
338   while (!found)
339     {
340       /* Needed if we run out of space */
341       prev_dirpos = TellDir(conn->dirptr);
342       dname = ReadDirName(conn->dirptr);
343
344       /*
345        * Due to bugs in NT client redirectors we are not using
346        * resume keys any more - set them to zero.
347        * Check out the related comments in findfirst/findnext.
348        * JRA.
349        */
350
351       reskey = 0;
352
353       DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
354                (unsigned)conn->dirptr,TellDir(conn->dirptr)));
355       
356       if (!dname) 
357         return(False);
358
359       matched = False;
360
361       pstrcpy(fname,dname);      
362
363       if(mask_match(fname, mask, case_sensitive, True))
364         {
365           BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
366           if (dont_descend && !isdots)
367             continue;
368           
369           if (isrootdir && isdots)
370             continue;
371
372           pstrcpy(pathreal,conn->dirpath);
373           if(needslash)
374             pstrcat(pathreal,"/");
375           pstrcat(pathreal,dname);
376           if (sys_stat(pathreal,&sbuf) != 0) 
377             {
378               DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
379               continue;
380             }
381
382           mode = dos_mode(conn,pathreal,&sbuf);
383
384           if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
385             DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
386             continue;
387           }
388
389           size = sbuf.st_size;
390           mdate = sbuf.st_mtime;
391           adate = sbuf.st_atime;
392           cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
393           if(mode & aDIR)
394             size = 0;
395
396           DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
397           
398           found = True;
399         }
400     }
401
402   name_map_mangle(fname,False,SNUM(conn));
403
404   p = pdata;
405   nameptr = p;
406
407   nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
408
409   switch (info_level)
410     {
411     case 1:
412       if(requires_resume_key) {
413         SIVAL(p,0,reskey);
414         p += 4;
415       }
416       put_dos_date2(p,l1_fdateCreation,cdate);
417       put_dos_date2(p,l1_fdateLastAccess,adate);
418       put_dos_date2(p,l1_fdateLastWrite,mdate);
419       SIVAL(p,l1_cbFile,size);
420       SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024));
421       SSVAL(p,l1_attrFile,mode);
422       SCVAL(p,l1_cchName,strlen(fname));
423       pstrcpy(p + l1_achName, fname);
424       nameptr = p + l1_achName;
425       p += l1_achName + strlen(fname) + 1;
426       break;
427
428     case 2:
429       /* info_level 2 */
430       if(requires_resume_key) {
431         SIVAL(p,0,reskey);
432         p += 4;
433       }
434       put_dos_date2(p,l2_fdateCreation,cdate);
435       put_dos_date2(p,l2_fdateLastAccess,adate);
436       put_dos_date2(p,l2_fdateLastWrite,mdate);
437       SIVAL(p,l2_cbFile,size);
438       SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024));
439       SSVAL(p,l2_attrFile,mode);
440       SIVAL(p,l2_cbList,0); /* No extended attributes */
441       SCVAL(p,l2_cchName,strlen(fname));
442       pstrcpy(p + l2_achName, fname);
443       nameptr = p + l2_achName;
444       p += l2_achName + strlen(fname) + 1;
445       break;
446
447     case 3:
448       SIVAL(p,0,reskey);
449       put_dos_date2(p,4,cdate);
450       put_dos_date2(p,8,adate);
451       put_dos_date2(p,12,mdate);
452       SIVAL(p,16,size);
453       SIVAL(p,20,ROUNDUP(size,1024));
454       SSVAL(p,24,mode);
455       SIVAL(p,26,4);
456       CVAL(p,30) = strlen(fname);
457       pstrcpy(p+31, fname);
458       nameptr = p+31;
459       p += 31 + strlen(fname) + 1;
460       break;
461
462     case 4:
463       if(requires_resume_key) {
464         SIVAL(p,0,reskey);
465         p += 4;
466       }
467       SIVAL(p,0,33+strlen(fname)+1);
468       put_dos_date2(p,4,cdate);
469       put_dos_date2(p,8,adate);
470       put_dos_date2(p,12,mdate);
471       SIVAL(p,16,size);
472       SIVAL(p,20,ROUNDUP(size,1024));
473       SSVAL(p,24,mode);
474       CVAL(p,32) = strlen(fname);
475       pstrcpy(p + 33, fname);
476       nameptr = p+33;
477       p += 33 + strlen(fname) + 1;
478       break;
479
480     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
481       was_8_3 = is_8_3(fname, True);
482       len = 94+strlen(fname);
483       len = (len + 3) & ~3;
484       SIVAL(p,0,len); p += 4;
485       SIVAL(p,0,reskey); p += 4;
486       put_long_date(p,cdate); p += 8;
487       put_long_date(p,adate); p += 8;
488       put_long_date(p,mdate); p += 8;
489       put_long_date(p,mdate); p += 8;
490       SIVAL(p,0,size); p += 8;
491       SIVAL(p,0,size); p += 8;
492       SIVAL(p,0,nt_extmode); p += 4;
493       SIVAL(p,0,strlen(fname)); p += 4;
494       SIVAL(p,0,0); p += 4;
495       if (!was_8_3) {
496         pstrcpy(p+2,fname);
497         if (!name_map_mangle(p+2,True,SNUM(conn)))
498           (p+2)[12] = 0;
499       } else
500         *(p+2) = 0;
501       strupper(p+2);
502       SSVAL(p,0,strlen(p+2));
503       p += 2 + 24;
504       /* nameptr = p;  */
505       pstrcpy(p,fname); p += strlen(p);
506       p = pdata + len;
507       break;
508
509     case SMB_FIND_FILE_DIRECTORY_INFO:
510       len = 64+strlen(fname);
511       len = (len + 3) & ~3;
512       SIVAL(p,0,len); p += 4;
513       SIVAL(p,0,reskey); p += 4;
514       put_long_date(p,cdate); p += 8;
515       put_long_date(p,adate); p += 8;
516       put_long_date(p,mdate); p += 8;
517       put_long_date(p,mdate); p += 8;
518       SIVAL(p,0,size); p += 8;
519       SIVAL(p,0,size); p += 8;
520       SIVAL(p,0,nt_extmode); p += 4;
521       SIVAL(p,0,strlen(fname)); p += 4;
522       pstrcpy(p,fname);
523       p = pdata + len;
524       break;
525       
526       
527     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
528       len = 68+strlen(fname);
529       len = (len + 3) & ~3;
530       SIVAL(p,0,len); p += 4;
531       SIVAL(p,0,reskey); p += 4;
532       put_long_date(p,cdate); p += 8;
533       put_long_date(p,adate); p += 8;
534       put_long_date(p,mdate); p += 8;
535       put_long_date(p,mdate); p += 8;
536       SIVAL(p,0,size); p += 8;
537       SIVAL(p,0,size); p += 8;
538       SIVAL(p,0,nt_extmode); p += 4;
539       SIVAL(p,0,strlen(fname)); p += 4;
540       SIVAL(p,0,0); p += 4;
541       pstrcpy(p,fname);
542       p = pdata + len;
543       break;
544
545     case SMB_FIND_FILE_NAMES_INFO:
546       len = 12+strlen(fname);
547       len = (len + 3) & ~3;
548       SIVAL(p,0,len); p += 4;
549       SIVAL(p,0,reskey); p += 4;
550       SIVAL(p,0,strlen(fname)); p += 4;
551       pstrcpy(p,fname);
552       p = pdata + len;
553       break;
554
555     default:      
556       return(False);
557     }
558
559
560   if (PTR_DIFF(p,pdata) > space_remaining) {
561     /* Move the dirptr back to prev_dirpos */
562     SeekDir(conn->dirptr, prev_dirpos);
563     *out_of_space = True;
564     DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
565     return False; /* Not finished - just out of space */
566   }
567
568   /* Setup the last_filename pointer, as an offset from base_data */
569   *last_name_off = PTR_DIFF(nameptr,base_data);
570   /* Advance the data pointer to the next slot */
571   *ppdata = p;
572   return(found);
573 }
574   
575 /****************************************************************************
576  Convert the directory masks formated for the wire.
577 ****************************************************************************/
578
579 void mask_convert( char *mask)
580 {
581   /*
582    * We know mask is a pstring.
583    */
584   char *p = mask;
585   while (*p) {
586     if (*p == '<') {
587       pstring expnd;
588       if(p[1] != '"' && p[1] != '.') {
589         pstrcpy( expnd, p+1 );
590         *p++ = '*';
591         *p = '.';
592         safe_strcpy( p+1, expnd, sizeof(pstring) - (p - mask) - 2);
593       } else
594         *p = '*';
595     }
596     if (*p == '>') *p = '?';
597     if (*p == '"') *p = '.';
598     p++;
599   }
600 }
601
602 /****************************************************************************
603   reply to a TRANS2_FINDFIRST
604 ****************************************************************************/
605 static int call_trans2findfirst(connection_struct *conn,
606                                 char *inbuf, char *outbuf, int bufsize,  
607                                 char **pparams, char **ppdata)
608 {
609   /* We must be careful here that we don't return more than the
610      allowed number of data bytes. If this means returning fewer than
611      maxentries then so be it. We assume that the redirector has
612      enough room for the fixed number of parameter bytes it has
613      requested. */
614   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
615   char *params = *pparams;
616   char *pdata = *ppdata;
617   int dirtype = SVAL(params,0);
618   int maxentries = SVAL(params,2);
619   BOOL close_after_first = BITSETW(params+4,0);
620   BOOL close_if_end = BITSETW(params+4,1);
621   BOOL requires_resume_key = BITSETW(params+4,2);
622   int info_level = SVAL(params,6);
623   pstring directory;
624   pstring mask;
625   char *p, *wcard;
626   int last_name_off=0;
627   int dptr_num = -1;
628   int numentries = 0;
629   int i;
630   BOOL finished = False;
631   BOOL dont_descend = False;
632   BOOL out_of_space = False;
633   int space_remaining;
634   BOOL bad_path = False;
635
636   *directory = *mask = 0;
637
638   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",
639            dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
640            info_level, max_data_bytes));
641   
642   switch (info_level) 
643     {
644     case 1:
645     case 2:
646     case 3:
647     case 4:
648     case SMB_FIND_FILE_DIRECTORY_INFO:
649     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
650     case SMB_FIND_FILE_NAMES_INFO:
651     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
652       break;
653     default:
654       return(ERROR(ERRDOS,ERRunknownlevel));
655     }
656
657   pstrcpy(directory, params + 12); /* Complete directory path with 
658                                      wildcard mask appended */
659
660   DEBUG(5,("path=%s\n",directory));
661
662   unix_convert(directory,conn,0,&bad_path);
663   if(!check_name(directory,conn)) {
664     if((errno == ENOENT) && bad_path)
665     {
666       unix_ERR_class = ERRDOS;
667       unix_ERR_code = ERRbadpath;
668     }
669
670 #if 0
671     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
672     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
673        (get_remote_arch() == RA_WINNT))
674     {
675       unix_ERR_class = ERRDOS;
676       unix_ERR_code = ERRbaddirectory;
677     }
678 #endif 
679
680     return(ERROR(ERRDOS,ERRbadpath));
681   }
682
683   p = strrchr(directory,'/');
684   if(p == NULL) {
685     pstrcpy(mask,directory);
686     pstrcpy(directory,"./");
687   } else {
688     pstrcpy(mask,p+1);
689     *p = 0;
690   }
691
692   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
693
694   pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
695   if(!*ppdata)
696     return(ERROR(ERRDOS,ERRnomem));
697   bzero(pdata,max_data_bytes);
698
699   /* Realloc the params space */
700   params = *pparams = Realloc(*pparams, 10);
701   if(params == NULL)
702     return(ERROR(ERRDOS,ERRnomem));
703
704   dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid));
705   if (dptr_num < 0)
706     return(ERROR(ERRDOS,ERRbadfile));
707
708   /* Convert the formatted mask. */
709   mask_convert(mask);
710
711 #if 0 /* JRA */
712   /*
713    * Now we have a working mask_match in util.c, I believe
714    * we no longer need these hacks (in fact they break
715    * things). JRA. 
716    */
717
718   /* a special case for 16 bit apps */
719   if (strequal(mask,"????????.???")) pstrcpy(mask,"*");
720
721   /* handle broken clients that send us old 8.3 format */
722   string_sub(mask,"????????","*");
723   string_sub(mask,".???",".*");
724 #endif /* JRA */
725
726   /* Save the wildcard match and attribs we are using on this directory - 
727      needed as lanman2 assumes these are being saved between calls */
728
729   if(!(wcard = strdup(mask))) {
730     dptr_close(dptr_num);
731     return(ERROR(ERRDOS,ERRnomem));
732   }
733
734   dptr_set_wcard(dptr_num, wcard);
735   dptr_set_attr(dptr_num, dirtype);
736
737   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
738
739   /* We don't need to check for VOL here as this is returned by 
740      a different TRANS2 call. */
741   
742   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
743            conn->dirpath,lp_dontdescend(SNUM(conn))));
744   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
745     dont_descend = True;
746     
747   p = pdata;
748   space_remaining = max_data_bytes;
749   out_of_space = False;
750
751   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
752     {
753
754       /* this is a heuristic to avoid seeking the dirptr except when 
755          absolutely necessary. It allows for a filename of about 40 chars */
756       if (space_remaining < DIRLEN_GUESS && numentries > 0)
757         {
758           out_of_space = True;
759           finished = False;
760         }
761       else
762         {
763           finished = 
764             !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
765                                    requires_resume_key,dont_descend,
766                                    &p,pdata,space_remaining, &out_of_space,
767                                    &last_name_off);
768         }
769
770       if (finished && out_of_space)
771         finished = False;
772
773       if (!finished && !out_of_space)
774         numentries++;
775       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
776     }
777   
778   /* Check if we can close the dirptr */
779   if(close_after_first || (finished && close_if_end))
780     {
781       dptr_close(dptr_num);
782       DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
783       dptr_num = -1;
784     }
785
786   /* 
787    * If there are no matching entries we must return ERRDOS/ERRbadfile - 
788    * from observation of NT.
789    */
790
791   if(numentries == 0)
792     return(ERROR(ERRDOS,ERRbadfile));
793
794   /* At this point pdata points to numentries directory entries. */
795
796   /* Set up the return parameter block */
797   SSVAL(params,0,dptr_num);
798   SSVAL(params,2,numentries);
799   SSVAL(params,4,finished);
800   SSVAL(params,6,0); /* Never an EA error */
801   SSVAL(params,8,last_name_off);
802
803   send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
804
805   if ((! *directory) && dptr_path(dptr_num))
806     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
807
808   DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
809             smb_fn_name(CVAL(inbuf,smb_com)), 
810             mask, directory, dirtype, numentries ) );
811
812   return(-1);
813 }
814
815
816 /****************************************************************************
817   reply to a TRANS2_FINDNEXT
818 ****************************************************************************/
819 static int call_trans2findnext(connection_struct *conn, 
820                                char *inbuf, char *outbuf, 
821                                int length, int bufsize,
822                                char **pparams, char **ppdata)
823 {
824   /* We must be careful here that we don't return more than the
825      allowed number of data bytes. If this means returning fewer than
826      maxentries then so be it. We assume that the redirector has
827      enough room for the fixed number of parameter bytes it has
828      requested. */
829   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
830   char *params = *pparams;
831   char *pdata = *ppdata;
832   int16 dptr_num = SVAL(params,0);
833   int maxentries = SVAL(params,2);
834   uint16 info_level = SVAL(params,4);
835   uint32 resume_key = IVAL(params,6);
836   BOOL close_after_request = BITSETW(params+10,0);
837   BOOL close_if_end = BITSETW(params+10,1);
838   BOOL requires_resume_key = BITSETW(params+10,2);
839   BOOL continue_bit = BITSETW(params+10,3);
840   pstring resume_name;
841   pstring mask;
842   pstring directory;
843   char *p;
844   uint16 dirtype;
845   int numentries = 0;
846   int i, last_name_off=0;
847   BOOL finished = False;
848   BOOL dont_descend = False;
849   BOOL out_of_space = False;
850   int space_remaining;
851
852   *mask = *directory = *resume_name = 0;
853
854   pstrcpy( resume_name, params+12);
855
856   DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
857 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
858 resume_key = %d resume name = %s continue=%d level = %d\n",
859            dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
860            requires_resume_key, resume_key, resume_name, continue_bit, info_level));
861
862   switch (info_level) 
863     {
864     case 1:
865     case 2:
866     case 3:
867     case 4:
868     case SMB_FIND_FILE_DIRECTORY_INFO:
869     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
870     case SMB_FIND_FILE_NAMES_INFO:
871     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
872       break;
873     default:
874       return(ERROR(ERRDOS,ERRunknownlevel));
875     }
876
877   pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
878   if(!*ppdata)
879     return(ERROR(ERRDOS,ERRnomem));
880   bzero(pdata,max_data_bytes);
881
882   /* Realloc the params space */
883   params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
884   if(!params)
885     return(ERROR(ERRDOS,ERRnomem));
886
887   /* Check that the dptr is valid */
888   if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
889     return(ERROR(ERRDOS,ERRnofiles));
890
891   string_set(&conn->dirpath,dptr_path(dptr_num));
892
893   /* Get the wildcard mask from the dptr */
894   if((p = dptr_wcard(dptr_num))== NULL) {
895     DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
896     return (ERROR(ERRDOS,ERRnofiles));
897   }
898   pstrcpy(mask, p);
899   pstrcpy(directory,conn->dirpath);
900
901   /* Get the attr mask from the dptr */
902   dirtype = dptr_attr(dptr_num);
903
904   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
905            dptr_num, mask, dirtype, 
906            (unsigned)conn->dirptr,
907            TellDir(conn->dirptr)));
908
909   /* We don't need to check for VOL here as this is returned by 
910      a different TRANS2 call. */
911
912   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
913   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
914     dont_descend = True;
915     
916   p = pdata;
917   space_remaining = max_data_bytes;
918   out_of_space = False;
919
920   /* 
921    * Seek to the correct position. We no longer use the resume key but
922    * depend on the last file name instead.
923    */
924   if(requires_resume_key && *resume_name && !continue_bit)
925   {
926     /*
927      * Fix for NT redirector problem triggered by resume key indexes
928      * changing between directory scans. We now return a resume key of 0
929      * and instead look for the filename to continue from (also given
930      * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
931      * findfirst/findnext (as is usual) then the directory pointer
932      * should already be at the correct place. Check this by scanning
933      * backwards looking for an exact (ie. case sensitive) filename match. 
934      * If we get to the beginning of the directory and haven't found it then scan
935      * forwards again looking for a match. JRA.
936      */
937
938     int current_pos, start_pos;
939     char *dname = NULL;
940     void *dirptr = conn->dirptr;
941     start_pos = TellDir(dirptr);
942     for(current_pos = start_pos; current_pos >= 0; current_pos--)
943     {
944       DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
945
946       SeekDir(dirptr, current_pos);
947       dname = ReadDirName(dirptr);
948
949       /*
950        * Remember, name_map_mangle is called by
951        * get_lanman2_dir_entry(), so the resume name
952        * could be mangled. Ensure we do the same
953        * here.
954        */
955
956       if(dname != NULL)
957         name_map_mangle( dname, False, SNUM(conn));
958
959       if(dname && strcsequal( resume_name, dname))
960       {
961         SeekDir(dirptr, current_pos+1);
962         DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
963         break;
964       }
965     }
966
967     /*
968      * Scan forward from start if not found going backwards.
969      */
970
971     if(current_pos < 0)
972     {
973       DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
974       SeekDir(dirptr, start_pos);
975       for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
976       {
977         /*
978          * Remember, name_map_mangle is called by
979          * get_lanman2_dir_entry(), so the resume name
980          * could be mangled. Ensure we do the same
981          * here.
982          */
983
984         if(dname != NULL)
985           name_map_mangle( dname, False, SNUM(conn));
986
987         if(dname && strcsequal( resume_name, dname))
988         {
989           SeekDir(dirptr, current_pos+1);
990           DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
991           break;
992         }
993       } /* end for */
994     } /* end if current_pos */
995   } /* end if requires_resume_key && !continue_bit */
996
997   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
998     {
999       /* this is a heuristic to avoid seeking the dirptr except when 
1000          absolutely necessary. It allows for a filename of about 40 chars */
1001       if (space_remaining < DIRLEN_GUESS && numentries > 0)
1002         {
1003           out_of_space = True;
1004           finished = False;
1005         }
1006       else
1007         {
1008           finished = 
1009             !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1010                                    requires_resume_key,dont_descend,
1011                                    &p,pdata,space_remaining, &out_of_space,
1012                                    &last_name_off);
1013         }
1014
1015       if (finished && out_of_space)
1016         finished = False;
1017
1018       if (!finished && !out_of_space)
1019         numentries++;
1020       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1021     }
1022   
1023   /* Check if we can close the dirptr */
1024   if(close_after_request || (finished && close_if_end))
1025     {
1026       dptr_close(dptr_num); /* This frees up the saved mask */
1027       DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1028       dptr_num = -1;
1029     }
1030
1031
1032   /* Set up the return parameter block */
1033   SSVAL(params,0,numentries);
1034   SSVAL(params,2,finished);
1035   SSVAL(params,4,0); /* Never an EA error */
1036   SSVAL(params,6,last_name_off);
1037
1038   send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1039
1040   if ((! *directory) && dptr_path(dptr_num))
1041     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1042
1043   DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1044             smb_fn_name(CVAL(inbuf,smb_com)), 
1045             mask, directory, dirtype, numentries ) );
1046
1047   return(-1);
1048 }
1049
1050 /****************************************************************************
1051   reply to a TRANS2_QFSINFO (query filesystem info)
1052 ****************************************************************************/
1053 static int call_trans2qfsinfo(connection_struct *conn, 
1054                               char *inbuf, char *outbuf, 
1055                               int length, int bufsize,
1056                               char **pparams, char **ppdata)
1057 {
1058   char *pdata = *ppdata;
1059   char *params = *pparams;
1060   uint16 info_level = SVAL(params,0);
1061   int data_len;
1062   struct stat st;
1063   char *vname = volume_label(SNUM(conn));
1064   int snum = SNUM(conn);
1065  
1066   DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1067
1068   if(sys_stat(".",&st)!=0) {
1069     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1070     return (ERROR(ERRSRV,ERRinvdevice));
1071   }
1072
1073   pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
1074
1075   switch (info_level) 
1076     {
1077     case 1:
1078       {
1079         int dfree,dsize,bsize;
1080         data_len = 18;
1081         sys_disk_free(".",&bsize,&dfree,&dsize);        
1082         SIVAL(pdata,l1_idFileSystem,st.st_dev);
1083         SIVAL(pdata,l1_cSectorUnit,bsize/512);
1084         SIVAL(pdata,l1_cUnit,dsize);
1085         SIVAL(pdata,l1_cUnitAvail,dfree);
1086         SSVAL(pdata,l1_cbSector,512);
1087         DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
1088                  bsize, (unsigned)st.st_dev, bsize/512, dsize, dfree, 512));
1089         break;
1090     }
1091     case 2:
1092     { 
1093       /* Return volume name */
1094       int volname_len = MIN(strlen(vname),11);
1095       data_len = l2_vol_szVolLabel + volname_len + 1;
1096       /* 
1097        * Add volume serial number - hash of a combination of
1098        * the called hostname and the service name.
1099        */
1100       SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1101       SCVAL(pdata,l2_vol_cch,volname_len);
1102       StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1103       DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1104                (unsigned)st.st_ctime, volname_len,
1105                pdata+l2_vol_szVolLabel));
1106       break;
1107     }
1108     case SMB_QUERY_FS_ATTRIBUTE_INFO:
1109       data_len = 12 + 2*strlen(FSTYPE_STRING);
1110       SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES); /* FS ATTRIBUTES */
1111 #if 0 /* Old code. JRA. */
1112       SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1113 #endif /* Old code. */
1114       SIVAL(pdata,4,128); /* Max filename component length */
1115       SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
1116       PutUniCode(pdata+12,FSTYPE_STRING);
1117       break;
1118     case SMB_QUERY_FS_LABEL_INFO:
1119       data_len = 4 + strlen(vname);
1120       SIVAL(pdata,0,strlen(vname));
1121       pstrcpy(pdata+4,vname);      
1122       break;
1123     case SMB_QUERY_FS_VOLUME_INFO:      
1124       data_len = 18 + 2*strlen(vname);
1125       /* 
1126        * Add volume serial number - hash of a combination of
1127        * the called hostname and the service name.
1128        */
1129       SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1130       SIVAL(pdata,12,2*strlen(vname));
1131       PutUniCode(pdata+18,vname);      
1132       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
1133                vname));
1134       break;
1135     case SMB_QUERY_FS_SIZE_INFO:
1136       {
1137         int dfree,dsize,bsize;
1138         data_len = 24;
1139         sys_disk_free(".",&bsize,&dfree,&dsize);        
1140         SIVAL(pdata,0,dsize);
1141         SIVAL(pdata,8,dfree);
1142         SIVAL(pdata,16,bsize/512);
1143         SIVAL(pdata,20,512);
1144       }
1145       break;
1146     case SMB_QUERY_FS_DEVICE_INFO:
1147       data_len = 8;
1148       SIVAL(pdata,0,0); /* dev type */
1149       SIVAL(pdata,4,0); /* characteristics */
1150       break;
1151     default:
1152       return(ERROR(ERRDOS,ERRunknownlevel));
1153     }
1154
1155
1156   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1157
1158   DEBUG( 4, ( "%s info_level = %d\n",
1159             smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1160
1161   return -1;
1162 }
1163
1164 /****************************************************************************
1165   reply to a TRANS2_SETFSINFO (set filesystem info)
1166 ****************************************************************************/
1167 static int call_trans2setfsinfo(connection_struct *conn,
1168                                 char *inbuf, char *outbuf, int length, 
1169                                 int bufsize,
1170                                 char **pparams, char **ppdata)
1171 {
1172   /* Just say yes we did it - there is nothing that
1173      can be set here so it doesn't matter. */
1174   int outsize;
1175   DEBUG(3,("call_trans2setfsinfo\n"));
1176
1177   if (!CAN_WRITE(conn))
1178     return(ERROR(ERRSRV,ERRaccess));
1179
1180   outsize = set_message(outbuf,10,0,True);
1181
1182   return outsize;
1183 }
1184
1185 /****************************************************************************
1186   Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1187   file name or file id).
1188 ****************************************************************************/
1189
1190 static int call_trans2qfilepathinfo(connection_struct *conn,
1191                                     char *inbuf, char *outbuf, int length, 
1192                                     int bufsize,
1193                                     char **pparams,char **ppdata,
1194                                     int total_data)
1195 {
1196   char *params = *pparams;
1197   char *pdata = *ppdata;
1198   uint16 tran_call = SVAL(inbuf, smb_setup0);
1199   uint16 info_level;
1200   int mode=0;
1201   int size=0;
1202   unsigned int data_size;
1203   struct stat sbuf;
1204   pstring fname1;
1205   char *fname;
1206   char *p;
1207   int l,pos;
1208   BOOL bad_path = False;
1209
1210   if (tran_call == TRANSACT2_QFILEINFO) {
1211     files_struct *fsp = file_fsp(params,0);
1212     info_level = SVAL(params,2);
1213
1214     CHECK_FSP(fsp,conn);
1215     CHECK_ERROR(fsp);
1216
1217     fname = fsp->fsp_name;
1218     if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1219       DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1220       return(UNIXERROR(ERRDOS,ERRbadfid));
1221     }
1222     pos = lseek(fsp->fd_ptr->fd,0,SEEK_CUR);
1223   } else {
1224     /* qpathinfo */
1225     info_level = SVAL(params,0);
1226     fname = &fname1[0];
1227     pstrcpy(fname,&params[6]);
1228     unix_convert(fname,conn,0,&bad_path);
1229     if (!check_name(fname,conn) || sys_stat(fname,&sbuf)) {
1230       DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1231       if((errno == ENOENT) && bad_path)
1232       {
1233         unix_ERR_class = ERRDOS;
1234         unix_ERR_code = ERRbadpath;
1235       }
1236       return(UNIXERROR(ERRDOS,ERRbadpath));
1237     }
1238     pos = 0;
1239   }
1240
1241
1242   DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1243            fname,info_level,tran_call,total_data));
1244
1245   p = strrchr(fname,'/'); 
1246   if (!p) 
1247     p = fname;
1248   else
1249     p++;
1250   l = strlen(p);  
1251   mode = dos_mode(conn,fname,&sbuf);
1252   size = sbuf.st_size;
1253   if (mode & aDIR) size = 0;
1254
1255   /* from now on we only want the part after the / */
1256   fname = p;
1257   
1258   params = *pparams = Realloc(*pparams,2); bzero(params,2);
1259   data_size = 1024;
1260   pdata = *ppdata = Realloc(*ppdata, data_size); 
1261
1262   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1263     /* uggh, EAs for OS2 */
1264     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1265     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1266   }
1267
1268   bzero(pdata,data_size);
1269
1270   switch (info_level) 
1271     {
1272     case SMB_INFO_STANDARD:
1273     case SMB_INFO_QUERY_EA_SIZE:
1274       data_size = (info_level==1?22:26);
1275       put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1276       put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1277       put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1278       SIVAL(pdata,l1_cbFile,size);
1279       SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1280       SSVAL(pdata,l1_attrFile,mode);
1281       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1282       break;
1283
1284     case SMB_INFO_QUERY_EAS_FROM_LIST:
1285       data_size = 24;
1286       put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1287       put_dos_date2(pdata,4,sbuf.st_atime);
1288       put_dos_date2(pdata,8,sbuf.st_mtime);
1289       SIVAL(pdata,12,size);
1290       SIVAL(pdata,16,ROUNDUP(size,1024));
1291       SIVAL(pdata,20,mode);
1292       break;
1293
1294     case SMB_INFO_QUERY_ALL_EAS:
1295       data_size = 4;
1296       SIVAL(pdata,0,data_size);
1297       break;
1298
1299     case 6:
1300       return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */      
1301
1302     case SMB_QUERY_FILE_BASIC_INFO:
1303       data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1304       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1305       put_long_date(pdata+8,sbuf.st_atime);
1306       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1307       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1308       SIVAL(pdata,32,mode);
1309
1310       DEBUG(5,("SMB_QFBI - "));
1311       {
1312         time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1313         DEBUG(5,("create: %s ", ctime(&create_time)));
1314       }
1315       DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1316       DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1317       DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1318       DEBUG(5,("mode: %x\n", mode));
1319
1320       break;
1321
1322     case SMB_QUERY_FILE_STANDARD_INFO:
1323       data_size = 22;
1324       SIVAL(pdata,0,size);
1325       SIVAL(pdata,8,size);
1326       SIVAL(pdata,16,sbuf.st_nlink);
1327       CVAL(pdata,20) = 0;
1328       CVAL(pdata,21) = (mode&aDIR)?1:0;
1329       break;
1330
1331     case SMB_QUERY_FILE_EA_INFO:
1332       data_size = 4;
1333       break;
1334
1335     /* Get the 8.3 name - used if NT SMB was negotiated. */
1336     case SMB_QUERY_FILE_ALT_NAME_INFO:
1337       {
1338         pstring short_name;
1339         pstrcpy(short_name,p);
1340         /* Mangle if not already 8.3 */
1341         if(!is_8_3(short_name, True))
1342         {
1343           if(!name_map_mangle(short_name,True,SNUM(conn)))
1344             *short_name = '\0';
1345         }
1346         strupper(short_name);
1347         l = strlen(short_name);
1348         PutUniCode(pdata + 4, short_name);
1349         data_size = 4 + (2*l);
1350         SIVAL(pdata,0,2*l);
1351       }
1352       break;
1353
1354     case SMB_QUERY_FILE_NAME_INFO:
1355       data_size = 4 + l;
1356       SIVAL(pdata,0,l);
1357       pstrcpy(pdata+4,fname);
1358       break;
1359
1360     case SMB_QUERY_FILE_ALLOCATION_INFO:
1361     case SMB_QUERY_FILE_END_OF_FILEINFO:
1362       data_size = 8;
1363       SIVAL(pdata,0,size);
1364       break;
1365
1366     case SMB_QUERY_FILE_ALL_INFO:
1367       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1368       put_long_date(pdata+8,sbuf.st_atime);
1369       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1370       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1371       SIVAL(pdata,32,mode);
1372       pdata += 40;
1373       SIVAL(pdata,0,size);
1374       SIVAL(pdata,8,size);
1375       SIVAL(pdata,16,sbuf.st_nlink);
1376       CVAL(pdata,20) = 0;
1377       CVAL(pdata,21) = (mode&aDIR)?1:0;
1378       pdata += 24;
1379       pdata += 8; /* index number */
1380       pdata += 4; /* EA info */
1381       if (mode & aRONLY)
1382         SIVAL(pdata,0,0xA9);
1383       else
1384         SIVAL(pdata,0,0xd01BF);
1385       pdata += 4;
1386       SIVAL(pdata,0,pos); /* current offset */
1387       pdata += 8;
1388       SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1389       pdata += 4;
1390       pdata += 4; /* alignment */
1391       SIVAL(pdata,0,l);
1392       pstrcpy(pdata+4,fname);
1393       pdata += 4 + l;
1394       data_size = PTR_DIFF(pdata,(*ppdata));
1395       break;
1396
1397     case SMB_QUERY_FILE_STREAM_INFO:
1398       data_size = 24 + l;
1399       SIVAL(pdata,0,pos);
1400       SIVAL(pdata,4,size);
1401       SIVAL(pdata,12,size);
1402       SIVAL(pdata,20,l);        
1403       pstrcpy(pdata+24,fname);
1404       break;
1405
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     files_struct *fsp = file_fsp(params,0);
1441     info_level = SVAL(params,2);    
1442
1443     CHECK_FSP(fsp,conn);
1444     CHECK_ERROR(fsp);
1445
1446     fname = fsp->fsp_name;
1447     fd = fsp->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 }