8871d568ddad58a303638e347aaa397342895f4a
[ira/wip.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   SMB_INO_T inode = 0;
205   SMB_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,NULL);
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   /*
282    * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
283    */
284   SIVAL(params,20,inode);
285  
286   /* Send the required number of replies */
287   send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
288
289   return -1;
290 }
291
292 /****************************************************************************
293   get a level dependent lanman2 dir entry.
294 ****************************************************************************/
295 static int get_lanman2_dir_entry(connection_struct *conn,
296                                  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   SMB_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(conn->dirpath,"./") ||
318                     strequal(conn->dirpath,".") ||
319                     strequal(conn->dirpath,"/"));
320   BOOL was_8_3;
321   int nt_extmode; /* Used for NT connections instead of mode */
322   BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
323
324   *fname = 0;
325   *out_of_space = False;
326
327   if (!conn->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(conn->dirptr);
345       dname = ReadDirName(conn->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                (unsigned)conn->dirptr,TellDir(conn->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,conn->dirpath);
376           if(needslash)
377             pstrcat(pathreal,"/");
378           pstrcat(pathreal,dname);
379           if (dos_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(conn,pathreal,&sbuf);
386
387           if (!dir_check_ftype(conn,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(conn)));
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(conn));
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(conn)))
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(conn->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(connection_struct *conn,
609                                 char *inbuf, char *outbuf, int bufsize,  
610                                 char **pparams, char **ppdata)
611 {
612   /* We must be careful here that we don't return more than the
613      allowed number of data bytes. If this means returning fewer than
614      maxentries then so be it. We assume that the redirector has
615      enough room for the fixed number of parameter bytes it has
616      requested. */
617   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
618   char *params = *pparams;
619   char *pdata = *ppdata;
620   int dirtype = SVAL(params,0);
621   int maxentries = SVAL(params,2);
622   BOOL close_after_first = BITSETW(params+4,0);
623   BOOL close_if_end = BITSETW(params+4,1);
624   BOOL requires_resume_key = BITSETW(params+4,2);
625   int info_level = SVAL(params,6);
626   pstring directory;
627   pstring mask;
628   char *p, *wcard;
629   int last_name_off=0;
630   int dptr_num = -1;
631   int numentries = 0;
632   int i;
633   BOOL finished = False;
634   BOOL dont_descend = False;
635   BOOL out_of_space = False;
636   int space_remaining;
637   BOOL bad_path = False;
638
639   *directory = *mask = 0;
640
641   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",
642            dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
643            info_level, max_data_bytes));
644   
645   switch (info_level) 
646     {
647     case 1:
648     case 2:
649     case 3:
650     case 4:
651     case SMB_FIND_FILE_DIRECTORY_INFO:
652     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
653     case SMB_FIND_FILE_NAMES_INFO:
654     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
655       break;
656     default:
657       return(ERROR(ERRDOS,ERRunknownlevel));
658     }
659
660   pstrcpy(directory, params + 12); /* Complete directory path with 
661                                      wildcard mask appended */
662
663   DEBUG(5,("path=%s\n",directory));
664
665   unix_convert(directory,conn,0,&bad_path,NULL);
666   if(!check_name(directory,conn)) {
667     if((errno == ENOENT) && bad_path)
668     {
669       unix_ERR_class = ERRDOS;
670       unix_ERR_code = ERRbadpath;
671     }
672
673 #if 0
674     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
675     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
676        (get_remote_arch() == RA_WINNT))
677     {
678       unix_ERR_class = ERRDOS;
679       unix_ERR_code = ERRbaddirectory;
680     }
681 #endif 
682
683     return(ERROR(ERRDOS,ERRbadpath));
684   }
685
686   p = strrchr(directory,'/');
687   if(p == NULL) {
688     pstrcpy(mask,directory);
689     pstrcpy(directory,"./");
690   } else {
691     pstrcpy(mask,p+1);
692     *p = 0;
693   }
694
695   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
696
697   pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024);
698   if(!*ppdata)
699     return(ERROR(ERRDOS,ERRnomem));
700   bzero(pdata,max_data_bytes);
701
702   /* Realloc the params space */
703   params = *pparams = Realloc(*pparams, 10);
704   if(params == NULL)
705     return(ERROR(ERRDOS,ERRnomem));
706
707   dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid));
708   if (dptr_num < 0)
709     return(ERROR(ERRDOS,ERRbadfile));
710
711   /* Convert the formatted mask. */
712   mask_convert(mask);
713
714 #if 0 /* JRA */
715   /*
716    * Now we have a working mask_match in util.c, I believe
717    * we no longer need these hacks (in fact they break
718    * things). JRA. 
719    */
720
721   /* a special case for 16 bit apps */
722   if (strequal(mask,"????????.???")) pstrcpy(mask,"*");
723
724   /* handle broken clients that send us old 8.3 format */
725   string_sub(mask,"????????","*");
726   string_sub(mask,".???",".*");
727 #endif /* JRA */
728
729   /* Save the wildcard match and attribs we are using on this directory - 
730      needed as lanman2 assumes these are being saved between calls */
731
732   if(!(wcard = strdup(mask))) {
733     dptr_close(dptr_num);
734     return(ERROR(ERRDOS,ERRnomem));
735   }
736
737   dptr_set_wcard(dptr_num, wcard);
738   dptr_set_attr(dptr_num, dirtype);
739
740   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
741
742   /* We don't need to check for VOL here as this is returned by 
743      a different TRANS2 call. */
744   
745   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
746            conn->dirpath,lp_dontdescend(SNUM(conn))));
747   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
748     dont_descend = True;
749     
750   p = pdata;
751   space_remaining = max_data_bytes;
752   out_of_space = False;
753
754   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
755     {
756
757       /* this is a heuristic to avoid seeking the dirptr except when 
758          absolutely necessary. It allows for a filename of about 40 chars */
759       if (space_remaining < DIRLEN_GUESS && numentries > 0)
760         {
761           out_of_space = True;
762           finished = False;
763         }
764       else
765         {
766           finished = 
767             !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
768                                    requires_resume_key,dont_descend,
769                                    &p,pdata,space_remaining, &out_of_space,
770                                    &last_name_off);
771         }
772
773       if (finished && out_of_space)
774         finished = False;
775
776       if (!finished && !out_of_space)
777         numentries++;
778       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
779     }
780   
781   /* Check if we can close the dirptr */
782   if(close_after_first || (finished && close_if_end))
783     {
784       dptr_close(dptr_num);
785       DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
786       dptr_num = -1;
787     }
788
789   /* 
790    * If there are no matching entries we must return ERRDOS/ERRbadfile - 
791    * from observation of NT.
792    */
793
794   if(numentries == 0)
795     return(ERROR(ERRDOS,ERRbadfile));
796
797   /* At this point pdata points to numentries directory entries. */
798
799   /* Set up the return parameter block */
800   SSVAL(params,0,dptr_num);
801   SSVAL(params,2,numentries);
802   SSVAL(params,4,finished);
803   SSVAL(params,6,0); /* Never an EA error */
804   SSVAL(params,8,last_name_off);
805
806   send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
807
808   if ((! *directory) && dptr_path(dptr_num))
809     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
810
811   DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
812             smb_fn_name(CVAL(inbuf,smb_com)), 
813             mask, directory, dirtype, numentries ) );
814
815   return(-1);
816 }
817
818
819 /****************************************************************************
820   reply to a TRANS2_FINDNEXT
821 ****************************************************************************/
822 static int call_trans2findnext(connection_struct *conn, 
823                                char *inbuf, char *outbuf, 
824                                int length, int bufsize,
825                                char **pparams, char **ppdata)
826 {
827   /* We must be careful here that we don't return more than the
828      allowed number of data bytes. If this means returning fewer than
829      maxentries then so be it. We assume that the redirector has
830      enough room for the fixed number of parameter bytes it has
831      requested. */
832   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
833   char *params = *pparams;
834   char *pdata = *ppdata;
835   int16 dptr_num = SVAL(params,0);
836   int maxentries = SVAL(params,2);
837   uint16 info_level = SVAL(params,4);
838   uint32 resume_key = IVAL(params,6);
839   BOOL close_after_request = BITSETW(params+10,0);
840   BOOL close_if_end = BITSETW(params+10,1);
841   BOOL requires_resume_key = BITSETW(params+10,2);
842   BOOL continue_bit = BITSETW(params+10,3);
843   pstring resume_name;
844   pstring mask;
845   pstring directory;
846   char *p;
847   uint16 dirtype;
848   int numentries = 0;
849   int i, last_name_off=0;
850   BOOL finished = False;
851   BOOL dont_descend = False;
852   BOOL out_of_space = False;
853   int space_remaining;
854
855   *mask = *directory = *resume_name = 0;
856
857   pstrcpy( resume_name, params+12);
858
859   DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
860 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
861 resume_key = %d resume name = %s continue=%d level = %d\n",
862            dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
863            requires_resume_key, resume_key, resume_name, continue_bit, info_level));
864
865   switch (info_level) 
866     {
867     case 1:
868     case 2:
869     case 3:
870     case 4:
871     case SMB_FIND_FILE_DIRECTORY_INFO:
872     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
873     case SMB_FIND_FILE_NAMES_INFO:
874     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
875       break;
876     default:
877       return(ERROR(ERRDOS,ERRunknownlevel));
878     }
879
880   pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024);
881   if(!*ppdata)
882     return(ERROR(ERRDOS,ERRnomem));
883   bzero(pdata,max_data_bytes);
884
885   /* Realloc the params space */
886   params = *pparams = Realloc(*pparams, 6*SIZEOFWORD);
887   if(!params)
888     return(ERROR(ERRDOS,ERRnomem));
889
890   /* Check that the dptr is valid */
891   if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
892     return(ERROR(ERRDOS,ERRnofiles));
893
894   string_set(&conn->dirpath,dptr_path(dptr_num));
895
896   /* Get the wildcard mask from the dptr */
897   if((p = dptr_wcard(dptr_num))== NULL) {
898     DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
899     return (ERROR(ERRDOS,ERRnofiles));
900   }
901   pstrcpy(mask, p);
902   pstrcpy(directory,conn->dirpath);
903
904   /* Get the attr mask from the dptr */
905   dirtype = dptr_attr(dptr_num);
906
907   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n",
908            dptr_num, mask, dirtype, 
909            (unsigned)conn->dirptr,
910            TellDir(conn->dirptr)));
911
912   /* We don't need to check for VOL here as this is returned by 
913      a different TRANS2 call. */
914
915   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
916   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
917     dont_descend = True;
918     
919   p = pdata;
920   space_remaining = max_data_bytes;
921   out_of_space = False;
922
923   /* 
924    * Seek to the correct position. We no longer use the resume key but
925    * depend on the last file name instead.
926    */
927   if(requires_resume_key && *resume_name && !continue_bit)
928   {
929     /*
930      * Fix for NT redirector problem triggered by resume key indexes
931      * changing between directory scans. We now return a resume key of 0
932      * and instead look for the filename to continue from (also given
933      * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
934      * findfirst/findnext (as is usual) then the directory pointer
935      * should already be at the correct place. Check this by scanning
936      * backwards looking for an exact (ie. case sensitive) filename match. 
937      * If we get to the beginning of the directory and haven't found it then scan
938      * forwards again looking for a match. JRA.
939      */
940
941     int current_pos, start_pos;
942     char *dname = NULL;
943     void *dirptr = conn->dirptr;
944     start_pos = TellDir(dirptr);
945     for(current_pos = start_pos; current_pos >= 0; current_pos--)
946     {
947       DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
948
949       SeekDir(dirptr, current_pos);
950       dname = ReadDirName(dirptr);
951
952       /*
953        * Remember, name_map_mangle is called by
954        * get_lanman2_dir_entry(), so the resume name
955        * could be mangled. Ensure we do the same
956        * here.
957        */
958
959       if(dname != NULL)
960         name_map_mangle( dname, False, SNUM(conn));
961
962       if(dname && strcsequal( resume_name, dname))
963       {
964         SeekDir(dirptr, current_pos+1);
965         DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
966         break;
967       }
968     }
969
970     /*
971      * Scan forward from start if not found going backwards.
972      */
973
974     if(current_pos < 0)
975     {
976       DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
977       SeekDir(dirptr, start_pos);
978       for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
979       {
980         /*
981          * Remember, name_map_mangle is called by
982          * get_lanman2_dir_entry(), so the resume name
983          * could be mangled. Ensure we do the same
984          * here.
985          */
986
987         if(dname != NULL)
988           name_map_mangle( dname, False, SNUM(conn));
989
990         if(dname && strcsequal( resume_name, dname))
991         {
992           SeekDir(dirptr, current_pos+1);
993           DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
994           break;
995         }
996       } /* end for */
997     } /* end if current_pos */
998   } /* end if requires_resume_key && !continue_bit */
999
1000   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1001     {
1002       /* this is a heuristic to avoid seeking the dirptr except when 
1003          absolutely necessary. It allows for a filename of about 40 chars */
1004       if (space_remaining < DIRLEN_GUESS && numentries > 0)
1005         {
1006           out_of_space = True;
1007           finished = False;
1008         }
1009       else
1010         {
1011           finished = 
1012             !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1013                                    requires_resume_key,dont_descend,
1014                                    &p,pdata,space_remaining, &out_of_space,
1015                                    &last_name_off);
1016         }
1017
1018       if (finished && out_of_space)
1019         finished = False;
1020
1021       if (!finished && !out_of_space)
1022         numentries++;
1023       space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1024     }
1025   
1026   /* Check if we can close the dirptr */
1027   if(close_after_request || (finished && close_if_end))
1028     {
1029       dptr_close(dptr_num); /* This frees up the saved mask */
1030       DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1031       dptr_num = -1;
1032     }
1033
1034
1035   /* Set up the return parameter block */
1036   SSVAL(params,0,numentries);
1037   SSVAL(params,2,finished);
1038   SSVAL(params,4,0); /* Never an EA error */
1039   SSVAL(params,6,last_name_off);
1040
1041   send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1042
1043   if ((! *directory) && dptr_path(dptr_num))
1044     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1045
1046   DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1047             smb_fn_name(CVAL(inbuf,smb_com)), 
1048             mask, directory, dirtype, numentries ) );
1049
1050   return(-1);
1051 }
1052
1053 /****************************************************************************
1054   reply to a TRANS2_QFSINFO (query filesystem info)
1055 ****************************************************************************/
1056 static int call_trans2qfsinfo(connection_struct *conn, 
1057                               char *inbuf, char *outbuf, 
1058                               int length, int bufsize,
1059                               char **pparams, char **ppdata)
1060 {
1061   char *pdata = *ppdata;
1062   char *params = *pparams;
1063   uint16 info_level = SVAL(params,0);
1064   int data_len;
1065   SMB_STRUCT_STAT st;
1066   char *vname = volume_label(SNUM(conn));
1067   int snum = SNUM(conn);
1068  
1069   DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1070
1071   if(dos_stat(".",&st)!=0) {
1072     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1073     return (ERROR(ERRSRV,ERRinvdevice));
1074   }
1075
1076   pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024);
1077
1078   switch (info_level) 
1079     {
1080     case 1:
1081       {
1082         int dfree,dsize,bsize;
1083         data_len = 18;
1084         sys_disk_free(".",&bsize,&dfree,&dsize);        
1085         SIVAL(pdata,l1_idFileSystem,st.st_dev);
1086         SIVAL(pdata,l1_cSectorUnit,bsize/512);
1087         SIVAL(pdata,l1_cUnit,dsize);
1088         SIVAL(pdata,l1_cUnitAvail,dfree);
1089         SSVAL(pdata,l1_cbSector,512);
1090         DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n",
1091                  bsize, (unsigned)st.st_dev, bsize/512, dsize, dfree, 512));
1092         break;
1093     }
1094     case 2:
1095     { 
1096       /* Return volume name */
1097       int volname_len = MIN(strlen(vname),11);
1098       data_len = l2_vol_szVolLabel + volname_len + 1;
1099       /* 
1100        * Add volume serial number - hash of a combination of
1101        * the called hostname and the service name.
1102        */
1103       SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1104       SCVAL(pdata,l2_vol_cch,volname_len);
1105       StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1106       DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1107                (unsigned)st.st_ctime, volname_len,
1108                pdata+l2_vol_szVolLabel));
1109       break;
1110     }
1111     case SMB_QUERY_FS_ATTRIBUTE_INFO:
1112       data_len = 12 + 2*strlen(FSTYPE_STRING);
1113       SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES); /* FS ATTRIBUTES */
1114 #if 0 /* Old code. JRA. */
1115       SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1116 #endif /* Old code. */
1117       SIVAL(pdata,4,128); /* Max filename component length */
1118       SIVAL(pdata,8,2*strlen(FSTYPE_STRING));
1119       PutUniCode(pdata+12,FSTYPE_STRING);
1120       break;
1121     case SMB_QUERY_FS_LABEL_INFO:
1122       data_len = 4 + strlen(vname);
1123       SIVAL(pdata,0,strlen(vname));
1124       pstrcpy(pdata+4,vname);      
1125       break;
1126     case SMB_QUERY_FS_VOLUME_INFO:      
1127       data_len = 18 + 2*strlen(vname);
1128       /* 
1129        * Add volume serial number - hash of a combination of
1130        * the called hostname and the service name.
1131        */
1132       SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1133       SIVAL(pdata,12,2*strlen(vname));
1134       PutUniCode(pdata+18,vname);      
1135       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
1136                vname));
1137       break;
1138     case SMB_QUERY_FS_SIZE_INFO:
1139       {
1140         int dfree,dsize,bsize;
1141         data_len = 24;
1142         sys_disk_free(".",&bsize,&dfree,&dsize);        
1143         SIVAL(pdata,0,dsize);
1144         SIVAL(pdata,8,dfree);
1145         SIVAL(pdata,16,bsize/512);
1146         SIVAL(pdata,20,512);
1147       }
1148       break;
1149     case SMB_QUERY_FS_DEVICE_INFO:
1150       data_len = 8;
1151       SIVAL(pdata,0,0); /* dev type */
1152       SIVAL(pdata,4,0); /* characteristics */
1153       break;
1154     default:
1155       return(ERROR(ERRDOS,ERRunknownlevel));
1156     }
1157
1158
1159   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1160
1161   DEBUG( 4, ( "%s info_level = %d\n",
1162             smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1163
1164   return -1;
1165 }
1166
1167 /****************************************************************************
1168   reply to a TRANS2_SETFSINFO (set filesystem info)
1169 ****************************************************************************/
1170 static int call_trans2setfsinfo(connection_struct *conn,
1171                                 char *inbuf, char *outbuf, int length, 
1172                                 int bufsize,
1173                                 char **pparams, char **ppdata)
1174 {
1175   /* Just say yes we did it - there is nothing that
1176      can be set here so it doesn't matter. */
1177   int outsize;
1178   DEBUG(3,("call_trans2setfsinfo\n"));
1179
1180   if (!CAN_WRITE(conn))
1181     return(ERROR(ERRSRV,ERRaccess));
1182
1183   outsize = set_message(outbuf,10,0,True);
1184
1185   return outsize;
1186 }
1187
1188 /****************************************************************************
1189   Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1190   file name or file id).
1191 ****************************************************************************/
1192
1193 static int call_trans2qfilepathinfo(connection_struct *conn,
1194                                     char *inbuf, char *outbuf, int length, 
1195                                     int bufsize,
1196                                     char **pparams,char **ppdata,
1197                                     int total_data)
1198 {
1199   char *params = *pparams;
1200   char *pdata = *ppdata;
1201   uint16 tran_call = SVAL(inbuf, smb_setup0);
1202   uint16 info_level;
1203   int mode=0;
1204   int size=0;
1205   unsigned int data_size;
1206   SMB_STRUCT_STAT sbuf;
1207   pstring fname1;
1208   char *fname;
1209   char *p;
1210   int l,pos;
1211   BOOL bad_path = False;
1212
1213   if (tran_call == TRANSACT2_QFILEINFO) {
1214     files_struct *fsp = file_fsp(params,0);
1215     info_level = SVAL(params,2);
1216
1217     CHECK_FSP(fsp,conn);
1218     CHECK_ERROR(fsp);
1219
1220     fname = fsp->fsp_name;
1221     if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1222       DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1223       return(UNIXERROR(ERRDOS,ERRbadfid));
1224     }
1225     pos = lseek(fsp->fd_ptr->fd,0,SEEK_CUR);
1226   } else {
1227     /* qpathinfo */
1228     info_level = SVAL(params,0);
1229     fname = &fname1[0];
1230     pstrcpy(fname,&params[6]);
1231     unix_convert(fname,conn,0,&bad_path,&sbuf);
1232     if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) {
1233       DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1234       if((errno == ENOENT) && bad_path)
1235       {
1236         unix_ERR_class = ERRDOS;
1237         unix_ERR_code = ERRbadpath;
1238       }
1239       return(UNIXERROR(ERRDOS,ERRbadpath));
1240     }
1241     pos = 0;
1242   }
1243
1244
1245   DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1246            fname,info_level,tran_call,total_data));
1247
1248   p = strrchr(fname,'/'); 
1249   if (!p) 
1250     p = fname;
1251   else
1252     p++;
1253   l = strlen(p);  
1254   mode = dos_mode(conn,fname,&sbuf);
1255   size = sbuf.st_size;
1256   if (mode & aDIR) size = 0;
1257
1258   /* from now on we only want the part after the / */
1259   fname = p;
1260   
1261   params = *pparams = Realloc(*pparams,2); bzero(params,2);
1262   data_size = 1024;
1263   pdata = *ppdata = Realloc(*ppdata, data_size); 
1264
1265   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1266     /* uggh, EAs for OS2 */
1267     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1268     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1269   }
1270
1271   bzero(pdata,data_size);
1272
1273   switch (info_level) 
1274     {
1275     case SMB_INFO_STANDARD:
1276     case SMB_INFO_QUERY_EA_SIZE:
1277       data_size = (info_level==1?22:26);
1278       put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1279       put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1280       put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1281       SIVAL(pdata,l1_cbFile,size);
1282       SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1283       SSVAL(pdata,l1_attrFile,mode);
1284       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1285       break;
1286
1287     case SMB_INFO_QUERY_EAS_FROM_LIST:
1288       data_size = 24;
1289       put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1290       put_dos_date2(pdata,4,sbuf.st_atime);
1291       put_dos_date2(pdata,8,sbuf.st_mtime);
1292       SIVAL(pdata,12,size);
1293       SIVAL(pdata,16,ROUNDUP(size,1024));
1294       SIVAL(pdata,20,mode);
1295       break;
1296
1297     case SMB_INFO_QUERY_ALL_EAS:
1298       data_size = 4;
1299       SIVAL(pdata,0,data_size);
1300       break;
1301
1302     case 6:
1303       return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */      
1304
1305     case SMB_QUERY_FILE_BASIC_INFO:
1306       data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1307       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1308       put_long_date(pdata+8,sbuf.st_atime);
1309       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1310       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1311       SIVAL(pdata,32,mode);
1312
1313       DEBUG(5,("SMB_QFBI - "));
1314       {
1315         time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1316         DEBUG(5,("create: %s ", ctime(&create_time)));
1317       }
1318       DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1319       DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1320       DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1321       DEBUG(5,("mode: %x\n", mode));
1322
1323       break;
1324
1325     case SMB_QUERY_FILE_STANDARD_INFO:
1326       data_size = 22;
1327       SIVAL(pdata,0,size);
1328       SIVAL(pdata,8,size);
1329       SIVAL(pdata,16,sbuf.st_nlink);
1330       CVAL(pdata,20) = 0;
1331       CVAL(pdata,21) = (mode&aDIR)?1:0;
1332       break;
1333
1334     case SMB_QUERY_FILE_EA_INFO:
1335       data_size = 4;
1336       break;
1337
1338     /* Get the 8.3 name - used if NT SMB was negotiated. */
1339     case SMB_QUERY_FILE_ALT_NAME_INFO:
1340       {
1341         pstring short_name;
1342         pstrcpy(short_name,p);
1343         /* Mangle if not already 8.3 */
1344         if(!is_8_3(short_name, True))
1345         {
1346           if(!name_map_mangle(short_name,True,SNUM(conn)))
1347             *short_name = '\0';
1348         }
1349         strupper(short_name);
1350         l = strlen(short_name);
1351         PutUniCode(pdata + 4, short_name);
1352         data_size = 4 + (2*l);
1353         SIVAL(pdata,0,2*l);
1354       }
1355       break;
1356
1357     case SMB_QUERY_FILE_NAME_INFO:
1358       data_size = 4 + l;
1359       SIVAL(pdata,0,l);
1360       pstrcpy(pdata+4,fname);
1361       break;
1362
1363     case SMB_QUERY_FILE_ALLOCATION_INFO:
1364     case SMB_QUERY_FILE_END_OF_FILEINFO:
1365       data_size = 8;
1366       SIVAL(pdata,0,size);
1367       break;
1368
1369     case SMB_QUERY_FILE_ALL_INFO:
1370       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1371       put_long_date(pdata+8,sbuf.st_atime);
1372       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1373       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1374       SIVAL(pdata,32,mode);
1375       pdata += 40;
1376       SIVAL(pdata,0,size);
1377       SIVAL(pdata,8,size);
1378       SIVAL(pdata,16,sbuf.st_nlink);
1379       CVAL(pdata,20) = 0;
1380       CVAL(pdata,21) = (mode&aDIR)?1:0;
1381       pdata += 24;
1382       pdata += 8; /* index number */
1383       pdata += 4; /* EA info */
1384       if (mode & aRONLY)
1385         SIVAL(pdata,0,0xA9);
1386       else
1387         SIVAL(pdata,0,0xd01BF);
1388       pdata += 4;
1389       SIVAL(pdata,0,pos); /* current offset */
1390       pdata += 8;
1391       SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1392       pdata += 4;
1393       pdata += 4; /* alignment */
1394       SIVAL(pdata,0,l);
1395       pstrcpy(pdata+4,fname);
1396       pdata += 4 + l;
1397       data_size = PTR_DIFF(pdata,(*ppdata));
1398       break;
1399
1400 #if 0
1401       /* NT4 server just returns "invalid query" to this - if we try to answer 
1402          it then NTws gets a BSOD! (tridge) */
1403     case SMB_QUERY_FILE_STREAM_INFO:
1404       data_size = 24 + l;
1405       SIVAL(pdata,0,pos);
1406       SIVAL(pdata,4,size);
1407       SIVAL(pdata,12,size);
1408       SIVAL(pdata,20,l);        
1409       pstrcpy(pdata+24,fname);
1410       break;
1411 #endif
1412
1413     default:
1414       return(ERROR(ERRDOS,ERRunknownlevel));
1415     }
1416
1417   send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1418
1419   return(-1);
1420 }
1421
1422 /****************************************************************************
1423   reply to a TRANS2_SETFILEINFO (set file info by fileid)
1424 ****************************************************************************/
1425 static int call_trans2setfilepathinfo(connection_struct *conn,
1426                                       char *inbuf, char *outbuf, int length, 
1427                                       int bufsize, char **pparams, 
1428                                       char **ppdata, int total_data)
1429 {
1430   char *params = *pparams;
1431   char *pdata = *ppdata;
1432   uint16 tran_call = SVAL(inbuf, smb_setup0);
1433   uint16 info_level;
1434   int mode=0;
1435   int size=0;
1436   struct utimbuf tvs;
1437   SMB_STRUCT_STAT st;
1438   pstring fname1;
1439   char *fname;
1440   int fd = -1;
1441   BOOL bad_path = False;
1442
1443   if (!CAN_WRITE(conn))
1444     return(ERROR(ERRSRV,ERRaccess));
1445
1446   if (tran_call == TRANSACT2_SETFILEINFO) {
1447     files_struct *fsp = file_fsp(params,0);
1448     info_level = SVAL(params,2);    
1449
1450     CHECK_FSP(fsp,conn);
1451     CHECK_ERROR(fsp);
1452
1453     fname = fsp->fsp_name;
1454     fd = fsp->fd_ptr->fd;
1455
1456     if(fstat(fd,&st)!=0) {
1457       DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
1458       return(ERROR(ERRDOS,ERRbadpath));
1459     }
1460   } else {
1461     /* set path info */
1462     info_level = SVAL(params,0);    
1463     fname = fname1;
1464     pstrcpy(fname,&params[6]);
1465     unix_convert(fname,conn,0,&bad_path,&st);
1466     if(!check_name(fname, conn))
1467     {
1468       if((errno == ENOENT) && bad_path)
1469       {
1470         unix_ERR_class = ERRDOS;
1471         unix_ERR_code = ERRbadpath;
1472       }
1473       return(UNIXERROR(ERRDOS,ERRbadpath));
1474     }
1475  
1476     if(!VALID_STAT(st) && dos_stat(fname,&st)!=0) {
1477       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1478       if((errno == ENOENT) && bad_path)
1479       {
1480         unix_ERR_class = ERRDOS;
1481         unix_ERR_code = ERRbadpath;
1482       }
1483       return(UNIXERROR(ERRDOS,ERRbadpath));
1484     }    
1485   }
1486
1487   DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1488            tran_call,fname,info_level,total_data));
1489
1490   /* Realloc the parameter and data sizes */
1491   params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1492   if(params == NULL)
1493     return(ERROR(ERRDOS,ERRnomem));
1494
1495   size = st.st_size;
1496   tvs.modtime = st.st_mtime;
1497   tvs.actime = st.st_atime;
1498   mode = dos_mode(conn,fname,&st);
1499
1500   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1501     /* uggh, EAs for OS2 */
1502     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1503     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1504   }
1505
1506   switch (info_level)
1507   {
1508     case SMB_INFO_STANDARD:
1509     case SMB_INFO_QUERY_EA_SIZE:
1510     {
1511       /* access time */
1512       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1513
1514       /* write time */
1515       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1516
1517       mode = SVAL(pdata,l1_attrFile);
1518       size = IVAL(pdata,l1_cbFile);
1519       break;
1520     }
1521
1522     /* XXXX um, i don't think this is right.
1523        it's also not in the cifs6.txt spec.
1524      */
1525     case SMB_INFO_QUERY_EAS_FROM_LIST:
1526       tvs.actime = make_unix_date2(pdata+8);
1527       tvs.modtime = make_unix_date2(pdata+12);
1528       size = IVAL(pdata,16);
1529       mode = IVAL(pdata,24);
1530       break;
1531
1532     /* XXXX nor this.  not in cifs6.txt, either. */
1533     case SMB_INFO_QUERY_ALL_EAS:
1534       tvs.actime = make_unix_date2(pdata+8);
1535       tvs.modtime = make_unix_date2(pdata+12);
1536       size = IVAL(pdata,16);
1537       mode = IVAL(pdata,24);
1538       break;
1539
1540     case SMB_SET_FILE_BASIC_INFO:
1541     {
1542       /* Ignore create time at offset pdata. */
1543
1544       /* access time */
1545       tvs.actime = interpret_long_date(pdata+8);
1546
1547       /* write time + changed time, combined. */
1548       tvs.modtime=MAX(interpret_long_date(pdata+16),
1549                       interpret_long_date(pdata+24));
1550
1551 #if 0 /* Needs more testing... */
1552       /* Test from Luke to prevent Win95 from
1553          setting incorrect values here.
1554        */
1555       if (tvs.actime < tvs.modtime)
1556         return(ERROR(ERRDOS,ERRnoaccess));
1557 #endif /* Needs more testing... */
1558
1559       /* attributes */
1560       mode = IVAL(pdata,32);
1561       break;
1562     }
1563
1564     case SMB_SET_FILE_END_OF_FILE_INFO:
1565     {
1566       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1567          return(ERROR(ERRDOS,ERRunknownlevel));
1568       size = IVAL(pdata,0);
1569       break;
1570     }
1571
1572     case SMB_SET_FILE_ALLOCATION_INFO:
1573       break; /* We don't need to do anything for this call. */
1574
1575     case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
1576     default:
1577     {
1578       return(ERROR(ERRDOS,ERRunknownlevel));
1579     }
1580   }
1581
1582   DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1583   DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1584   DEBUG(6,("size: %x "   , size));
1585   DEBUG(6,("mode: %x\n"  , mode));
1586
1587   /* get some defaults (no modifications) if any info is zero. */
1588   if (!tvs.actime) tvs.actime = st.st_atime;
1589   if (!tvs.modtime) tvs.modtime = st.st_mtime;
1590   if (!size) size = st.st_size;
1591
1592   /* Try and set the times, size and mode of this file -
1593      if they are different from the current values
1594    */
1595   if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1596   {
1597     if(file_utime(conn, fname, &tvs)!=0)
1598     {
1599       return(ERROR(ERRDOS,ERRnoaccess));
1600     }
1601   }
1602
1603   /* check the mode isn't different, before changing it */
1604   if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL))
1605   {
1606     DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1607     return(ERROR(ERRDOS,ERRnoaccess));
1608   }
1609
1610   if(size != st.st_size)
1611   {
1612     if (fd == -1)
1613     {
1614       fd = dos_open(fname,O_RDWR,0);
1615       if (fd == -1)
1616       {
1617         return(ERROR(ERRDOS,ERRbadpath));
1618       }
1619       set_filelen(fd, size);
1620       close(fd);
1621     }
1622     else
1623     {
1624       set_filelen(fd, size);
1625     }
1626   }
1627
1628   SSVAL(params,0,0);
1629
1630   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1631   
1632   return(-1);
1633 }
1634
1635 /****************************************************************************
1636   reply to a TRANS2_MKDIR (make directory with extended attributes).
1637 ****************************************************************************/
1638 static int call_trans2mkdir(connection_struct *conn,
1639                             char *inbuf, char *outbuf, int length, int bufsize,
1640                             char **pparams, char **ppdata)
1641 {
1642   char *params = *pparams;
1643   pstring directory;
1644   int ret = -1;
1645   BOOL bad_path = False;
1646
1647   if (!CAN_WRITE(conn))
1648     return(ERROR(ERRSRV,ERRaccess));
1649
1650   pstrcpy(directory, &params[4]);
1651
1652   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1653
1654   unix_convert(directory,conn,0,&bad_path,NULL);
1655   if (check_name(directory,conn))
1656     ret = dos_mkdir(directory,unix_mode(conn,aDIR));
1657   
1658   if(ret < 0)
1659     {
1660       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1661       if((errno == ENOENT) && bad_path)
1662       {
1663         unix_ERR_class = ERRDOS;
1664         unix_ERR_code = ERRbadpath;
1665       }
1666       return(UNIXERROR(ERRDOS,ERRnoaccess));
1667     }
1668
1669   /* Realloc the parameter and data sizes */
1670   params = *pparams = Realloc(*pparams,2);
1671   if(params == NULL)
1672     return(ERROR(ERRDOS,ERRnomem));
1673
1674   SSVAL(params,0,0);
1675
1676   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1677   
1678   return(-1);
1679 }
1680
1681 /****************************************************************************
1682   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1683   We don't actually do this - we just send a null response.
1684 ****************************************************************************/
1685 static int call_trans2findnotifyfirst(connection_struct *conn,
1686                                       char *inbuf, char *outbuf, 
1687                                       int length, int bufsize,
1688                                       char **pparams, char **ppdata)
1689 {
1690   static uint16 fnf_handle = 257;
1691   char *params = *pparams;
1692   uint16 info_level = SVAL(params,4);
1693
1694   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1695
1696   switch (info_level) 
1697     {
1698     case 1:
1699     case 2:
1700       break;
1701     default:
1702       return(ERROR(ERRDOS,ERRunknownlevel));
1703     }
1704
1705   /* Realloc the parameter and data sizes */
1706   params = *pparams = Realloc(*pparams,6);
1707   if(params == NULL)
1708     return(ERROR(ERRDOS,ERRnomem));
1709
1710   SSVAL(params,0,fnf_handle);
1711   SSVAL(params,2,0); /* No changes */
1712   SSVAL(params,4,0); /* No EA errors */
1713
1714   fnf_handle++;
1715
1716   if(fnf_handle == 0)
1717     fnf_handle = 257;
1718
1719   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1720   
1721   return(-1);
1722 }
1723
1724 /****************************************************************************
1725   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
1726   changes). Currently this does nothing.
1727 ****************************************************************************/
1728 static int call_trans2findnotifynext(connection_struct *conn,
1729                                      char *inbuf, char *outbuf, 
1730                                      int length, int bufsize,
1731                                      char **pparams, char **ppdata)
1732 {
1733   char *params = *pparams;
1734
1735   DEBUG(3,("call_trans2findnotifynext\n"));
1736
1737   /* Realloc the parameter and data sizes */
1738   params = *pparams = Realloc(*pparams,4);
1739   if(params == NULL)
1740     return(ERROR(ERRDOS,ERRnomem));
1741
1742   SSVAL(params,0,0); /* No changes */
1743   SSVAL(params,2,0); /* No EA errors */
1744
1745   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1746   
1747   return(-1);
1748 }
1749
1750 /****************************************************************************
1751   reply to a SMBfindclose (stop trans2 directory search)
1752 ****************************************************************************/
1753 int reply_findclose(connection_struct *conn,
1754                     char *inbuf,char *outbuf,int length,int bufsize)
1755 {
1756         int outsize = 0;
1757         int16 dptr_num=SVALS(inbuf,smb_vwv0);
1758
1759         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
1760
1761         dptr_close(dptr_num);
1762
1763         outsize = set_message(outbuf,0,0,True);
1764
1765         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
1766
1767         return(outsize);
1768 }
1769
1770 /****************************************************************************
1771   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1772 ****************************************************************************/
1773 int reply_findnclose(connection_struct *conn, 
1774                      char *inbuf,char *outbuf,int length,int bufsize)
1775 {
1776         int outsize = 0;
1777         int dptr_num= -1;
1778         
1779         dptr_num = SVAL(inbuf,smb_vwv0);
1780
1781         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
1782
1783         /* We never give out valid handles for a 
1784            findnotifyfirst - so any dptr_num is ok here. 
1785            Just ignore it. */
1786
1787         outsize = set_message(outbuf,0,0,True);
1788
1789         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
1790
1791         return(outsize);
1792 }
1793
1794
1795 /****************************************************************************
1796   reply to a SMBtranss2 - just ignore it!
1797 ****************************************************************************/
1798 int reply_transs2(connection_struct *conn,
1799                   char *inbuf,char *outbuf,int length,int bufsize)
1800 {
1801         DEBUG(4,("Ignoring transs2 of length %d\n",length));
1802         return(-1);
1803 }
1804
1805 /****************************************************************************
1806   reply to a SMBtrans2
1807 ****************************************************************************/
1808 int reply_trans2(connection_struct *conn,
1809                  char *inbuf,char *outbuf,int length,int bufsize)
1810 {
1811         int outsize = 0;
1812         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1813         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1814 #if 0
1815         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1816         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1817         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1818         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1819         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1820         int32 timeout = IVALS(inbuf,smb_timeout);
1821 #endif
1822         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1823         unsigned int tran_call = SVAL(inbuf, smb_setup0);
1824         char *params = NULL, *data = NULL;
1825         int num_params, num_params_sofar, num_data, num_data_sofar;
1826
1827         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
1828                 /* Queue this open message as we are the process of an
1829                  * oplock break.  */
1830
1831                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
1832                 DEBUGADD(2,( "in oplock break state.\n"));
1833
1834                 push_oplock_pending_smb_message(inbuf, length);
1835                 return -1;
1836         }
1837         
1838         outsize = set_message(outbuf,0,0,True);
1839
1840         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1841            is so as a sanity check */
1842         if (suwcnt != 1) {
1843                 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1844                 return(ERROR(ERRSRV,ERRerror));
1845         }
1846     
1847         /* Allocate the space for the maximum needed parameters and data */
1848         if (total_params > 0)
1849                 params = (char *)malloc(total_params);
1850         if (total_data > 0)
1851                 data = (char *)malloc(total_data);
1852   
1853         if ((total_params && !params)  || (total_data && !data)) {
1854                 DEBUG(2,("Out of memory in reply_trans2\n"));
1855                 return(ERROR(ERRDOS,ERRnomem));
1856         }
1857
1858         /* Copy the param and data bytes sent with this request into
1859            the params buffer */
1860         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
1861         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
1862
1863         if (num_params > total_params || num_data > total_data)
1864                 exit_server("invalid params in reply_trans2");
1865
1866         if(params)
1867                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
1868         if(data)
1869                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
1870
1871         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
1872                 /* We need to send an interim response then receive the rest
1873                    of the parameter/data bytes */
1874                 outsize = set_message(outbuf,0,0,True);
1875                 send_smb(Client,outbuf);
1876
1877                 while (num_data_sofar < total_data || 
1878                        num_params_sofar < total_params) {
1879                         BOOL ret;
1880
1881                         ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
1882                                                SMB_SECONDARY_WAIT);
1883                         
1884                         if ((ret && 
1885                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
1886                                 outsize = set_message(outbuf,0,0,True);
1887                                 if(ret)
1888                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
1889                                 else
1890                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
1891                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
1892                                 if(params)
1893                                         free(params);
1894                                 if(data)
1895                                         free(data);
1896                                 return(ERROR(ERRSRV,ERRerror));
1897                         }
1898       
1899                         /* Revise total_params and total_data in case
1900                            they have changed downwards */
1901                         total_params = SVAL(inbuf, smb_tpscnt);
1902                         total_data = SVAL(inbuf, smb_tdscnt);
1903                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
1904                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
1905                         if (num_params_sofar > total_params || num_data_sofar > total_data)
1906                                 exit_server("data overflow in trans2");
1907                         
1908                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
1909                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
1910                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
1911                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
1912                 }
1913         }
1914         
1915         if (Protocol >= PROTOCOL_NT1) {
1916                 uint16 flg2 = SVAL(outbuf,smb_flg2);
1917                 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
1918         }
1919
1920         /* Now we must call the relevant TRANS2 function */
1921         switch(tran_call)  {
1922         case TRANSACT2_OPEN:
1923                 outsize = call_trans2open(conn, 
1924                                           inbuf, outbuf, bufsize, 
1925                                           &params, &data);
1926                 break;
1927
1928         case TRANSACT2_FINDFIRST:
1929                 outsize = call_trans2findfirst(conn, inbuf, outbuf, 
1930                                                bufsize, &params, &data);
1931                 break;
1932
1933         case TRANSACT2_FINDNEXT:
1934                 outsize = call_trans2findnext(conn, inbuf, outbuf, 
1935                                               length, bufsize, 
1936                                               &params, &data);
1937                 break;
1938
1939         case TRANSACT2_QFSINFO:
1940             outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
1941                                          length, bufsize, &params, 
1942                                          &data);
1943             break;
1944
1945         case TRANSACT2_SETFSINFO:
1946                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
1947                                                length, bufsize, 
1948                                                &params, &data);
1949                 break;
1950
1951         case TRANSACT2_QPATHINFO:
1952         case TRANSACT2_QFILEINFO:
1953                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
1954                                                    length, bufsize, 
1955                                                    &params, &data, total_data);
1956                 break;
1957         case TRANSACT2_SETPATHINFO:
1958         case TRANSACT2_SETFILEINFO:
1959                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
1960                                                      length, bufsize, 
1961                                                      &params, &data, 
1962                                                      total_data);
1963                 break;
1964
1965         case TRANSACT2_FINDNOTIFYFIRST:
1966                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
1967                                                      length, bufsize, 
1968                                                      &params, &data);
1969                 break;
1970
1971         case TRANSACT2_FINDNOTIFYNEXT:
1972                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
1973                                                     length, bufsize, 
1974                                                     &params, &data);
1975                 break;
1976         case TRANSACT2_MKDIR:
1977                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
1978                                            bufsize, &params, &data);
1979                 break;
1980         default:
1981                 /* Error in request */
1982                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
1983                 if(params)
1984                         free(params);
1985                 if(data)
1986                         free(data);
1987                 return (ERROR(ERRSRV,ERRerror));
1988         }
1989         
1990         /* As we do not know how many data packets will need to be
1991            returned here the various call_trans2xxxx calls
1992            must send their own. Thus a call_trans2xxx routine only
1993            returns a value other than -1 when it wants to send
1994            an error packet. 
1995         */
1996         
1997         if(params)
1998                 free(params);
1999         if(data)
2000                 free(data);
2001         return outsize; /* If a correct response was needed the
2002                            call_trans2xxx calls have already sent
2003                            it. If outsize != -1 then it is returning */
2004 }