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