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