1dfb488b9ef6da3ccae05a4a232d95b805012a96
[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 #if 0
1398       /* NT4 server just returns "invalid query" to this - if we try to answer 
1399          it then NTws gets a BSOD! (tridge) */
1400     case SMB_QUERY_FILE_STREAM_INFO:
1401       data_size = 24 + l;
1402       SIVAL(pdata,0,pos);
1403       SIVAL(pdata,4,size);
1404       SIVAL(pdata,12,size);
1405       SIVAL(pdata,20,l);        
1406       pstrcpy(pdata+24,fname);
1407       break;
1408 #endif
1409
1410     default:
1411       return(ERROR(ERRDOS,ERRunknownlevel));
1412     }
1413
1414   send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1415
1416   return(-1);
1417 }
1418
1419 /****************************************************************************
1420   reply to a TRANS2_SETFILEINFO (set file info by fileid)
1421 ****************************************************************************/
1422 static int call_trans2setfilepathinfo(connection_struct *conn,
1423                                       char *inbuf, char *outbuf, int length, 
1424                                       int bufsize, char **pparams, 
1425                                       char **ppdata, int total_data)
1426 {
1427   char *params = *pparams;
1428   char *pdata = *ppdata;
1429   uint16 tran_call = SVAL(inbuf, smb_setup0);
1430   uint16 info_level;
1431   int mode=0;
1432   int size=0;
1433   struct utimbuf tvs;
1434   struct stat st;
1435   pstring fname1;
1436   char *fname;
1437   int fd = -1;
1438   BOOL bad_path = False;
1439
1440   if (!CAN_WRITE(conn))
1441     return(ERROR(ERRSRV,ERRaccess));
1442
1443   if (tran_call == TRANSACT2_SETFILEINFO) {
1444     files_struct *fsp = file_fsp(params,0);
1445     info_level = SVAL(params,2);    
1446
1447     CHECK_FSP(fsp,conn);
1448     CHECK_ERROR(fsp);
1449
1450     fname = fsp->fsp_name;
1451     fd = fsp->fd_ptr->fd;
1452
1453     if(fstat(fd,&st)!=0) {
1454       DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1455       return(ERROR(ERRDOS,ERRbadpath));
1456     }
1457   } else {
1458     /* set path info */
1459     info_level = SVAL(params,0);    
1460     fname = fname1;
1461     pstrcpy(fname,&params[6]);
1462     unix_convert(fname,conn,0,&bad_path);
1463     if(!check_name(fname, conn))
1464     {
1465       if((errno == ENOENT) && bad_path)
1466       {
1467         unix_ERR_class = ERRDOS;
1468         unix_ERR_code = ERRbadpath;
1469       }
1470       return(UNIXERROR(ERRDOS,ERRbadpath));
1471     }
1472  
1473     if(sys_stat(fname,&st)!=0) {
1474       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1475       if((errno == ENOENT) && bad_path)
1476       {
1477         unix_ERR_class = ERRDOS;
1478         unix_ERR_code = ERRbadpath;
1479       }
1480       return(UNIXERROR(ERRDOS,ERRbadpath));
1481     }    
1482   }
1483
1484   DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1485            tran_call,fname,info_level,total_data));
1486
1487   /* Realloc the parameter and data sizes */
1488   params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1489   if(params == NULL)
1490     return(ERROR(ERRDOS,ERRnomem));
1491
1492   size = st.st_size;
1493   tvs.modtime = st.st_mtime;
1494   tvs.actime = st.st_atime;
1495   mode = dos_mode(conn,fname,&st);
1496
1497   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1498     /* uggh, EAs for OS2 */
1499     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1500     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1501   }
1502
1503   switch (info_level)
1504   {
1505     case SMB_INFO_STANDARD:
1506     case SMB_INFO_QUERY_EA_SIZE:
1507     {
1508       /* access time */
1509       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1510
1511       /* write time */
1512       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1513
1514       mode = SVAL(pdata,l1_attrFile);
1515       size = IVAL(pdata,l1_cbFile);
1516       break;
1517     }
1518
1519     /* XXXX um, i don't think this is right.
1520        it's also not in the cifs6.txt spec.
1521      */
1522     case SMB_INFO_QUERY_EAS_FROM_LIST:
1523       tvs.actime = make_unix_date2(pdata+8);
1524       tvs.modtime = make_unix_date2(pdata+12);
1525       size = IVAL(pdata,16);
1526       mode = IVAL(pdata,24);
1527       break;
1528
1529     /* XXXX nor this.  not in cifs6.txt, either. */
1530     case SMB_INFO_QUERY_ALL_EAS:
1531       tvs.actime = make_unix_date2(pdata+8);
1532       tvs.modtime = make_unix_date2(pdata+12);
1533       size = IVAL(pdata,16);
1534       mode = IVAL(pdata,24);
1535       break;
1536
1537     case SMB_SET_FILE_BASIC_INFO:
1538     {
1539       /* Ignore create time at offset pdata. */
1540
1541       /* access time */
1542       tvs.actime = interpret_long_date(pdata+8);
1543
1544       /* write time + changed time, combined. */
1545       tvs.modtime=MAX(interpret_long_date(pdata+16),
1546                       interpret_long_date(pdata+24));
1547
1548 #if 0 /* Needs more testing... */
1549       /* Test from Luke to prevent Win95 from
1550          setting incorrect values here.
1551        */
1552       if (tvs.actime < tvs.modtime)
1553         return(ERROR(ERRDOS,ERRnoaccess));
1554 #endif /* Needs more testing... */
1555
1556       /* attributes */
1557       mode = IVAL(pdata,32);
1558       break;
1559     }
1560
1561     case SMB_SET_FILE_END_OF_FILE_INFO:
1562     {
1563       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1564          return(ERROR(ERRDOS,ERRunknownlevel));
1565       size = IVAL(pdata,0);
1566       break;
1567     }
1568
1569     case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1570     case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
1571     default:
1572     {
1573       return(ERROR(ERRDOS,ERRunknownlevel));
1574     }
1575   }
1576
1577   DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1578   DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1579   DEBUG(6,("size: %x "   , size));
1580   DEBUG(6,("mode: %x\n"  , mode));
1581
1582   /* get some defaults (no modifications) if any info is zero. */
1583   if (!tvs.actime) tvs.actime = st.st_atime;
1584   if (!tvs.modtime) tvs.modtime = st.st_mtime;
1585   if (!size) size = st.st_size;
1586
1587   /* Try and set the times, size and mode of this file -
1588      if they are different from the current values
1589    */
1590   if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1591   {
1592     if(file_utime(conn, fname, &tvs)!=0)
1593     {
1594       return(ERROR(ERRDOS,ERRnoaccess));
1595     }
1596   }
1597
1598   /* check the mode isn't different, before changing it */
1599   if (mode != dos_mode(conn, fname, &st) && dos_chmod(conn, fname, mode, NULL))
1600   {
1601     DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1602     return(ERROR(ERRDOS,ERRnoaccess));
1603   }
1604
1605   if(size != st.st_size)
1606   {
1607     if (fd == -1)
1608     {
1609       fd = sys_open(fname,O_RDWR,0);
1610       if (fd == -1)
1611       {
1612         return(ERROR(ERRDOS,ERRbadpath));
1613       }
1614       set_filelen(fd, size);
1615       close(fd);
1616     }
1617     else
1618     {
1619       set_filelen(fd, size);
1620     }
1621   }
1622
1623   SSVAL(params,0,0);
1624
1625   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1626   
1627   return(-1);
1628 }
1629
1630 /****************************************************************************
1631   reply to a TRANS2_MKDIR (make directory with extended attributes).
1632 ****************************************************************************/
1633 static int call_trans2mkdir(connection_struct *conn,
1634                             char *inbuf, char *outbuf, int length, int bufsize,
1635                             char **pparams, char **ppdata)
1636 {
1637   char *params = *pparams;
1638   pstring directory;
1639   int ret = -1;
1640   BOOL bad_path = False;
1641
1642   if (!CAN_WRITE(conn))
1643     return(ERROR(ERRSRV,ERRaccess));
1644
1645   pstrcpy(directory, &params[4]);
1646
1647   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1648
1649   unix_convert(directory,conn,0,&bad_path);
1650   if (check_name(directory,conn))
1651     ret = sys_mkdir(directory,unix_mode(conn,aDIR));
1652   
1653   if(ret < 0)
1654     {
1655       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1656       if((errno == ENOENT) && bad_path)
1657       {
1658         unix_ERR_class = ERRDOS;
1659         unix_ERR_code = ERRbadpath;
1660       }
1661       return(UNIXERROR(ERRDOS,ERRnoaccess));
1662     }
1663
1664   /* Realloc the parameter and data sizes */
1665   params = *pparams = Realloc(*pparams,2);
1666   if(params == NULL)
1667     return(ERROR(ERRDOS,ERRnomem));
1668
1669   SSVAL(params,0,0);
1670
1671   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1672   
1673   return(-1);
1674 }
1675
1676 /****************************************************************************
1677   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1678   We don't actually do this - we just send a null response.
1679 ****************************************************************************/
1680 static int call_trans2findnotifyfirst(connection_struct *conn,
1681                                       char *inbuf, char *outbuf, 
1682                                       int length, int bufsize,
1683                                       char **pparams, char **ppdata)
1684 {
1685   static uint16 fnf_handle = 257;
1686   char *params = *pparams;
1687   uint16 info_level = SVAL(params,4);
1688
1689   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1690
1691   switch (info_level) 
1692     {
1693     case 1:
1694     case 2:
1695       break;
1696     default:
1697       return(ERROR(ERRDOS,ERRunknownlevel));
1698     }
1699
1700   /* Realloc the parameter and data sizes */
1701   params = *pparams = Realloc(*pparams,6);
1702   if(params == NULL)
1703     return(ERROR(ERRDOS,ERRnomem));
1704
1705   SSVAL(params,0,fnf_handle);
1706   SSVAL(params,2,0); /* No changes */
1707   SSVAL(params,4,0); /* No EA errors */
1708
1709   fnf_handle++;
1710
1711   if(fnf_handle == 0)
1712     fnf_handle = 257;
1713
1714   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1715   
1716   return(-1);
1717 }
1718
1719 /****************************************************************************
1720   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
1721   changes). Currently this does nothing.
1722 ****************************************************************************/
1723 static int call_trans2findnotifynext(connection_struct *conn,
1724                                      char *inbuf, char *outbuf, 
1725                                      int length, int bufsize,
1726                                      char **pparams, char **ppdata)
1727 {
1728   char *params = *pparams;
1729
1730   DEBUG(3,("call_trans2findnotifynext\n"));
1731
1732   /* Realloc the parameter and data sizes */
1733   params = *pparams = Realloc(*pparams,4);
1734   if(params == NULL)
1735     return(ERROR(ERRDOS,ERRnomem));
1736
1737   SSVAL(params,0,0); /* No changes */
1738   SSVAL(params,2,0); /* No EA errors */
1739
1740   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1741   
1742   return(-1);
1743 }
1744
1745 /****************************************************************************
1746   reply to a SMBfindclose (stop trans2 directory search)
1747 ****************************************************************************/
1748 int reply_findclose(connection_struct *conn,
1749                     char *inbuf,char *outbuf,int length,int bufsize)
1750 {
1751         int outsize = 0;
1752         int16 dptr_num=SVALS(inbuf,smb_vwv0);
1753
1754         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
1755
1756         dptr_close(dptr_num);
1757
1758         outsize = set_message(outbuf,0,0,True);
1759
1760         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
1761
1762         return(outsize);
1763 }
1764
1765 /****************************************************************************
1766   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1767 ****************************************************************************/
1768 int reply_findnclose(connection_struct *conn, 
1769                      char *inbuf,char *outbuf,int length,int bufsize)
1770 {
1771         int outsize = 0;
1772         int dptr_num= -1;
1773         
1774         dptr_num = SVAL(inbuf,smb_vwv0);
1775
1776         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
1777
1778         /* We never give out valid handles for a 
1779            findnotifyfirst - so any dptr_num is ok here. 
1780            Just ignore it. */
1781
1782         outsize = set_message(outbuf,0,0,True);
1783
1784         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
1785
1786         return(outsize);
1787 }
1788
1789
1790 /****************************************************************************
1791   reply to a SMBtranss2 - just ignore it!
1792 ****************************************************************************/
1793 int reply_transs2(connection_struct *conn,
1794                   char *inbuf,char *outbuf,int length,int bufsize)
1795 {
1796         DEBUG(4,("Ignoring transs2 of length %d\n",length));
1797         return(-1);
1798 }
1799
1800 /****************************************************************************
1801   reply to a SMBtrans2
1802 ****************************************************************************/
1803 int reply_trans2(connection_struct *conn,
1804                  char *inbuf,char *outbuf,int length,int bufsize)
1805 {
1806         int outsize = 0;
1807         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1808         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1809 #if 0
1810         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1811         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1812         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1813         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1814         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1815         int32 timeout = IVALS(inbuf,smb_timeout);
1816 #endif
1817         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1818         unsigned int tran_call = SVAL(inbuf, smb_setup0);
1819         char *params = NULL, *data = NULL;
1820         int num_params, num_params_sofar, num_data, num_data_sofar;
1821
1822         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
1823                 /* Queue this open message as we are the process of an
1824                  * oplock break.  */
1825
1826                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
1827                 DEBUGADD(2,( "in oplock break state.\n"));
1828
1829                 push_oplock_pending_smb_message(inbuf, length);
1830                 return -1;
1831         }
1832         
1833         outsize = set_message(outbuf,0,0,True);
1834
1835         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1836            is so as a sanity check */
1837         if (suwcnt != 1) {
1838                 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1839                 return(ERROR(ERRSRV,ERRerror));
1840         }
1841     
1842         /* Allocate the space for the maximum needed parameters and data */
1843         if (total_params > 0)
1844                 params = (char *)malloc(total_params);
1845         if (total_data > 0)
1846                 data = (char *)malloc(total_data);
1847   
1848         if ((total_params && !params)  || (total_data && !data)) {
1849                 DEBUG(2,("Out of memory in reply_trans2\n"));
1850                 return(ERROR(ERRDOS,ERRnomem));
1851         }
1852
1853         /* Copy the param and data bytes sent with this request into
1854            the params buffer */
1855         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1856         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1857
1858         if (num_params > total_params || num_data > total_data)
1859                 exit_server("invalid params in reply_trans2");
1860
1861         if(params)
1862                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1863         if(data)
1864                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1865
1866         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
1867                 /* We need to send an interim response then receive the rest
1868                    of the parameter/data bytes */
1869                 outsize = set_message(outbuf,0,0,True);
1870                 send_smb(Client,outbuf);
1871
1872                 while (num_data_sofar < total_data || 
1873                        num_params_sofar < total_params) {
1874                         BOOL ret;
1875
1876                         ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1877                                                SMB_SECONDARY_WAIT);
1878                         
1879                         if ((ret && 
1880                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
1881                                 outsize = set_message(outbuf,0,0,True);
1882                                 if(ret)
1883                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1884                                 else
1885                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1886                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1887                                 if(params)
1888                                         free(params);
1889                                 if(data)
1890                                         free(data);
1891                                 return(ERROR(ERRSRV,ERRerror));
1892                         }
1893       
1894                         /* Revise total_params and total_data in case
1895                            they have changed downwards */
1896                         total_params = SVAL(inbuf, smb_tpscnt);
1897                         total_data = SVAL(inbuf, smb_tdscnt);
1898                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1899                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1900                         if (num_params_sofar > total_params || num_data_sofar > total_data)
1901                                 exit_server("data overflow in trans2");
1902                         
1903                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
1904                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1905                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1906                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1907                 }
1908         }
1909         
1910         if (Protocol >= PROTOCOL_NT1) {
1911                 uint16 flg2 = SVAL(outbuf,smb_flg2);
1912                 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1913         }
1914
1915         /* Now we must call the relevant TRANS2 function */
1916         switch(tran_call)  {
1917         case TRANSACT2_OPEN:
1918                 outsize = call_trans2open(conn, 
1919                                           inbuf, outbuf, bufsize, 
1920                                           &params, &data);
1921                 break;
1922
1923         case TRANSACT2_FINDFIRST:
1924                 outsize = call_trans2findfirst(conn, inbuf, outbuf, 
1925                                                bufsize, &params, &data);
1926                 break;
1927
1928         case TRANSACT2_FINDNEXT:
1929                 outsize = call_trans2findnext(conn, inbuf, outbuf, 
1930                                               length, bufsize, 
1931                                               &params, &data);
1932                 break;
1933
1934         case TRANSACT2_QFSINFO:
1935             outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
1936                                          length, bufsize, &params, 
1937                                          &data);
1938             break;
1939
1940         case TRANSACT2_SETFSINFO:
1941                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
1942                                                length, bufsize, 
1943                                                &params, &data);
1944                 break;
1945
1946         case TRANSACT2_QPATHINFO:
1947         case TRANSACT2_QFILEINFO:
1948                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
1949                                                    length, bufsize, 
1950                                                    &params, &data, total_data);
1951                 break;
1952         case TRANSACT2_SETPATHINFO:
1953         case TRANSACT2_SETFILEINFO:
1954                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
1955                                                      length, bufsize, 
1956                                                      &params, &data, 
1957                                                      total_data);
1958                 break;
1959
1960         case TRANSACT2_FINDNOTIFYFIRST:
1961                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
1962                                                      length, bufsize, 
1963                                                      &params, &data);
1964                 break;
1965
1966         case TRANSACT2_FINDNOTIFYNEXT:
1967                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
1968                                                     length, bufsize, 
1969                                                     &params, &data);
1970                 break;
1971         case TRANSACT2_MKDIR:
1972                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
1973                                            bufsize, &params, &data);
1974                 break;
1975         default:
1976                 /* Error in request */
1977                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
1978                 if(params)
1979                         free(params);
1980                 if(data)
1981                         free(data);
1982                 return (ERROR(ERRSRV,ERRerror));
1983         }
1984         
1985         /* As we do not know how many data packets will need to be
1986            returned here the various call_trans2xxxx calls
1987            must send their own. Thus a call_trans2xxx routine only
1988            returns a value other than -1 when it wants to send
1989            an error packet. 
1990         */
1991         
1992         if(params)
1993                 free(params);
1994         if(data)
1995                 free(data);
1996         return outsize; /* If a correct response was needed the
1997                            call_trans2xxx calls have already sent
1998                            it. If outsize != -1 then it is returning */
1999 }