Set support for info levels...
[samba.git] / source / 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
26 extern int DEBUGLEVEL;
27 extern int Protocol;
28 extern BOOL case_sensitive;
29 extern int smb_read_error;
30 extern fstring local_machine;
31 extern int global_oplock_break;
32 extern uint32 global_client_caps;
33 extern pstring global_myname;
34
35 /****************************************************************************
36   Send the required number of replies back.
37   We assume all fields other than the data fields are
38   set correctly for the type of call.
39   HACK ! Always assumes smb_setup field is zero.
40 ****************************************************************************/
41 static int send_trans2_replies(char *outbuf, int bufsize, char *params, 
42                                int paramsize, char *pdata, int datasize)
43 {
44   /* As we are using a protocol > LANMAN1 then the max_send
45      variable must have been set in the sessetupX call.
46      This takes precedence over the max_xmit field in the
47      global struct. These different max_xmit variables should
48      be merged as this is now too confusing */
49
50   extern int max_send;
51   int data_to_send = datasize;
52   int params_to_send = paramsize;
53   int useable_space;
54   char *pp = params;
55   char *pd = pdata;
56   int params_sent_thistime, data_sent_thistime, total_sent_thistime;
57   int alignment_offset = 3;
58   int data_alignment_offset = 0;
59
60   /* Initially set the wcnt area to be 10 - this is true for all
61      trans2 replies */
62   set_message(outbuf,10,0,True);
63
64   /* If there genuinely are no parameters or data to send just send
65      the empty packet */
66   if(params_to_send == 0 && data_to_send == 0)
67   {
68     if (!send_smb(smbd_server_fd(),outbuf))
69       exit_server("send_trans2_replies: send_smb failed.\n");
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     /*
99      * Note that 'useable_space' does not include the alignment offsets,
100      * but we must include the alignment offsets in the calculation of
101      * the length of the data we send over the wire, as the alignment offsets
102      * are sent here. Fix from Marc_Jacobsen@hp.com.
103      */
104     total_sent_thistime = MIN(total_sent_thistime, useable_space+
105                                 alignment_offset + data_alignment_offset);
106
107     set_message(outbuf, 10, total_sent_thistime, True);
108
109     /* Set total params and data to be sent */
110     SSVAL(outbuf,smb_tprcnt,paramsize);
111     SSVAL(outbuf,smb_tdrcnt,datasize);
112
113     /* Calculate how many parameters and data we can fit into
114        this packet. Parameters get precedence */
115
116     params_sent_thistime = MIN(params_to_send,useable_space);
117     data_sent_thistime = useable_space - params_sent_thistime;
118     data_sent_thistime = MIN(data_sent_thistime,data_to_send);
119
120     SSVAL(outbuf,smb_prcnt, params_sent_thistime);
121
122     /* smb_proff is the offset from the start of the SMB header to the
123        parameter bytes, however the first 4 bytes of outbuf are
124        the Netbios over TCP header. Thus use smb_base() to subtract
125        them from the calculation */
126
127     SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
128
129     if(params_sent_thistime == 0)
130       SSVAL(outbuf,smb_prdisp,0);
131     else
132       /* Absolute displacement of param bytes sent in this packet */
133       SSVAL(outbuf,smb_prdisp,pp - params);
134
135     SSVAL(outbuf,smb_drcnt, data_sent_thistime);
136     if(data_sent_thistime == 0)
137     {
138       SSVAL(outbuf,smb_droff,0);
139       SSVAL(outbuf,smb_drdisp, 0);
140     }
141     else
142     {
143       /* The offset of the data bytes is the offset of the
144          parameter bytes plus the number of parameters being sent this time */
145       SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
146             smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
147       SSVAL(outbuf,smb_drdisp, pd - pdata);
148     }
149
150     /* Copy the param bytes into the packet */
151     if(params_sent_thistime)
152       memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
153     /* Copy in the data bytes */
154     if(data_sent_thistime)
155       memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
156              data_alignment_offset,pd,data_sent_thistime);
157
158     DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
159           params_sent_thistime, data_sent_thistime, useable_space));
160     DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
161           params_to_send, data_to_send, paramsize, datasize));
162
163     /* Send the packet */
164     if (!send_smb(smbd_server_fd(),outbuf))
165                 exit_server("send_trans2_replies: send_smb failed.\n");
166
167     pp += params_sent_thistime;
168     pd += data_sent_thistime;
169
170     params_to_send -= params_sent_thistime;
171     data_to_send -= data_sent_thistime;
172
173     /* Sanity check */
174     if(params_to_send < 0 || data_to_send < 0)
175     {
176       DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
177             params_to_send, data_to_send));
178       return -1;
179     }
180   }
181
182   return 0;
183 }
184
185
186 /****************************************************************************
187   reply to a TRANSACT2_OPEN
188 ****************************************************************************/
189 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, 
190                            int bufsize,  
191                            char **pparams, char **ppdata)
192 {
193   char *params = *pparams;
194   int16 open_mode = SVAL(params, 2);
195   int16 open_attr = SVAL(params,6);
196   BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
197 #if 0
198   BOOL return_additional_info = BITSETW(params,0);
199   int16 open_sattr = SVAL(params, 4);
200   time_t open_time = make_unix_date3(params+8);
201 #endif
202   int16 open_ofun = SVAL(params,12);
203   int32 open_size = IVAL(params,14);
204   char *pname = &params[28];
205   pstring fname;
206   mode_t unixmode;
207   SMB_OFF_T size=0;
208   int fmode=0,mtime=0,rmode;
209   SMB_INO_T inode = 0;
210   SMB_STRUCT_STAT sbuf;
211   int smb_action = 0;
212   BOOL bad_path = False;
213   files_struct *fsp;
214
215   srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
216
217   DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
218            fname,open_mode, open_attr, open_ofun, open_size));
219
220   if (IS_IPC(conn)) {
221                 return(ERROR(ERRSRV,ERRaccess));
222   }
223
224   /* XXXX we need to handle passed times, sattr and flags */
225
226   unix_convert(fname,conn,0,&bad_path,&sbuf);
227     
228   if (!check_name(fname,conn))
229   {
230     if((errno == ENOENT) && bad_path)
231     {
232       unix_ERR_class = ERRDOS;
233       unix_ERR_code = ERRbadpath;
234     }
235     return(UNIXERROR(ERRDOS,ERRnoaccess));
236   }
237
238   unixmode = unix_mode(conn,open_attr | aARCH, fname);
239       
240   fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
241                    oplock_request, &rmode,&smb_action);
242       
243   if (!fsp)
244   {
245     if((errno == ENOENT) && bad_path)
246     {
247       unix_ERR_class = ERRDOS;
248       unix_ERR_code = ERRbadpath;
249     }
250     return(UNIXERROR(ERRDOS,ERRnoaccess));
251   }
252
253   size = sbuf.st_size;
254   fmode = dos_mode(conn,fname,&sbuf);
255   mtime = sbuf.st_mtime;
256   inode = sbuf.st_ino;
257   if (fmode & aDIR) {
258     close_file(fsp,False);
259     return(ERROR(ERRDOS,ERRnoaccess));
260   }
261
262   /* Realloc the size of parameters and data we will return */
263   params        = Realloc(*pparams, 28);
264   if( params == NULL ) {
265     return(ERROR(ERRDOS,ERRnomem));
266   }
267   *pparams      = params;
268
269   memset((char *)params,'\0',28);
270   SSVAL(params,0,fsp->fnum);
271   SSVAL(params,2,fmode);
272   put_dos_date2(params,4, mtime);
273   SIVAL(params,8, (uint32)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 * Routine to check if a given string matches exactly.
294 * as a special case a mask of "." does NOT match. That
295 * is required for correct wildcard semantics
296 * Case can be significant or not.
297 **********************************************************/
298 static BOOL exact_match(char *str,char *mask, BOOL case_sig) 
299 {
300         if (mask[0] == '.' && mask[1] == 0) return False;
301         if (case_sig) return strcmp(str,mask)==0;
302         return strcasecmp(str,mask) == 0;
303 }
304
305 /****************************************************************************
306   get a level dependent lanman2 dir entry.
307 ****************************************************************************/
308 static BOOL get_lanman2_dir_entry(connection_struct *conn,
309                                   void *inbuf, void *outbuf,
310                                  char *path_mask,int dirtype,int info_level,
311                                  int requires_resume_key,
312                                  BOOL dont_descend,char **ppdata, 
313                                  char *base_data, int space_remaining, 
314                                  BOOL *out_of_space, BOOL *got_exact_match,
315                                  int *last_name_off)
316 {
317   char *dname;
318   BOOL found = False;
319   SMB_STRUCT_STAT sbuf;
320   pstring mask;
321   pstring pathreal;
322   pstring fname;
323   char *p, *q, *pdata = *ppdata;
324   uint32 reskey=0;
325   int prev_dirpos=0;
326   int mode=0;
327   SMB_OFF_T size = 0;
328   uint32 len;
329   time_t mdate=0, adate=0, cdate=0;
330   char *nameptr;
331   BOOL was_8_3;
332   int nt_extmode; /* Used for NT connections instead of mode */
333   BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
334
335   *fname = 0;
336   *out_of_space = False;
337   *got_exact_match = False;
338
339   if (!conn->dirptr)
340     return(False);
341
342   p = strrchr(path_mask,'/');
343   if(p != NULL)
344   {
345     if(p[1] == '\0')
346       pstrcpy(mask,"*.*");
347     else
348       pstrcpy(mask, p+1);
349   }
350   else
351     pstrcpy(mask, path_mask);
352
353   while (!found)
354   {
355     BOOL got_match;
356
357     /* Needed if we run out of space */
358     prev_dirpos = TellDir(conn->dirptr);
359     dname = ReadDirName(conn->dirptr);
360
361     /*
362      * Due to bugs in NT client redirectors we are not using
363      * resume keys any more - set them to zero.
364      * Check out the related comments in findfirst/findnext.
365      * JRA.
366      */
367
368     reskey = 0;
369
370     DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
371       (long)conn->dirptr,TellDir(conn->dirptr)));
372       
373     if (!dname) 
374       return(False);
375
376     pstrcpy(fname,dname);      
377
378     if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive))) {
379         got_match = mask_match(fname, mask, case_sensitive);
380     }
381
382     if(!got_match && !is_8_3(fname, False)) {
383
384       /*
385        * It turns out that NT matches wildcards against
386        * both long *and* short names. This may explain some
387        * of the wildcard wierdness from old DOS clients
388        * that some people have been seeing.... JRA.
389        */
390
391       pstring newname;
392       pstrcpy( newname, fname);
393       name_map_mangle( newname, True, False, SNUM(conn));
394       if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
395         got_match = mask_match(newname, mask, case_sensitive);
396     }
397
398     if(got_match)
399     {
400       BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
401       if (dont_descend && !isdots)
402         continue;
403           
404       pstrcpy(pathreal,conn->dirpath);
405       if(needslash)
406         pstrcat(pathreal,"/");
407       pstrcat(pathreal,dname);
408       if (vfs_stat(conn,pathreal,&sbuf) != 0) 
409       {
410         /* Needed to show the msdfs symlinks as directories */
411         if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) 
412            || !is_msdfs_link(conn, pathreal))
413           {
414             DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
415                      pathreal,strerror(errno)));
416             continue;
417           }
418         else
419           {
420             DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
421             sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
422           }
423       }
424
425       mode = dos_mode(conn,pathreal,&sbuf);
426
427       if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
428         DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
429         continue;
430       }
431
432       size = sbuf.st_size;
433       mdate = sbuf.st_mtime;
434       adate = sbuf.st_atime;
435       cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
436       if(mode & aDIR)
437         size = 0;
438
439       DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
440           
441       found = True;
442     }
443   }
444
445   name_map_mangle(fname,False,True,SNUM(conn));
446
447   p = pdata;
448   nameptr = p;
449
450   nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
451
452   switch (info_level)
453   {
454     case 1:
455       if(requires_resume_key) {
456         SIVAL(p,0,reskey);
457         p += 4;
458       }
459       put_dos_date2(p,l1_fdateCreation,cdate);
460       put_dos_date2(p,l1_fdateLastAccess,adate);
461       put_dos_date2(p,l1_fdateLastWrite,mdate);
462       SIVAL(p,l1_cbFile,(uint32)size);
463       SIVAL(p,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
464       SSVAL(p,l1_attrFile,mode);
465       p += l1_achName;
466       nameptr = p;
467       len = srvstr_push(outbuf, p, fname, -1, 
468                         STR_TERMINATE|STR_CONVERT);
469       SCVAL(p, -1, len);
470       p += len;
471       break;
472
473     case 2:
474       /* info_level 2 */
475       if(requires_resume_key) {
476         SIVAL(p,0,reskey);
477         p += 4;
478       }
479       put_dos_date2(p,l2_fdateCreation,cdate);
480       put_dos_date2(p,l2_fdateLastAccess,adate);
481       put_dos_date2(p,l2_fdateLastWrite,mdate);
482       SIVAL(p,l2_cbFile,(uint32)size);
483       SIVAL(p,l2_cbFileAlloc,SMB_ROUNDUP(size,1024));
484       SSVAL(p,l2_attrFile,mode);
485       SIVAL(p,l2_cbList,0); /* No extended attributes */
486       p += l2_achName;
487       nameptr = p;
488       len = srvstr_push(outbuf, p, fname, -1, 
489                         STR_TERMINATE|STR_CONVERT);
490       SCVAL(p, -1, len);
491       p += len;
492       break;
493
494     case 3:
495       SIVAL(p,0,reskey);
496       put_dos_date2(p,4,cdate);
497       put_dos_date2(p,8,adate);
498       put_dos_date2(p,12,mdate);
499       SIVAL(p,16,(uint32)size);
500       SIVAL(p,20,SMB_ROUNDUP(size,1024));
501       SSVAL(p,24,mode);
502       SIVAL(p,26,4);
503       p += 31;
504       nameptr = p;
505       len = srvstr_push(outbuf, p, fname, -1, 
506                         STR_TERMINATE|STR_CONVERT);
507       SCVAL(p, -1, len);
508       p += len;
509       break;
510
511     case 4:
512       if(requires_resume_key) {
513         SIVAL(p,0,reskey);
514         p += 4;
515       }
516       q = p;
517       put_dos_date2(p,4,cdate);
518       put_dos_date2(p,8,adate);
519       put_dos_date2(p,12,mdate);
520       SIVAL(p,16,(uint32)size);
521       SIVAL(p,20,SMB_ROUNDUP(size,1024));
522       SSVAL(p,24,mode);
523       p += 33;
524       nameptr = p;
525       len = srvstr_push(outbuf, p, fname, -1, 
526                         STR_TERMINATE|STR_CONVERT);
527       SCVAL(p, -1, len);
528       p += len;
529       SIVAL(q,4,PTR_DIFF(p, q));
530
531       break;
532
533     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
534       was_8_3 = is_8_3(fname, True);
535       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       SOFF_T(p,0,size);
542       SOFF_T(p,8,size);
543       p += 16;
544       SIVAL(p,0,nt_extmode); p += 4;
545       q = p; p += 4;
546       SIVAL(p,0,0); p += 4;
547       if (!was_8_3) {
548               pstring mangled_name;
549               pstrcpy(mangled_name, fname);
550               name_map_mangle(mangled_name,True,True,SNUM(conn));
551               mangled_name[12] = 0;
552               len = srvstr_push(outbuf, p+2, mangled_name, 24, 
553                                 STR_CONVERT|STR_UPPER);
554               SSVAL(p, 0, len);
555       } else {
556               SSVAL(p,0,0);
557               *(p+2) = 0;
558       }
559       p += 2 + 24;
560       len = srvstr_push(outbuf, p, fname, -1, 
561                         STR_TERMINATE|STR_CONVERT);
562       SIVAL(q,0,len);
563       p += len;
564       len = PTR_DIFF(p, pdata);
565       len = (len + 3) & ~3;
566       SIVAL(pdata,0,len);
567       p = pdata + len;
568       break;
569
570     case SMB_FIND_FILE_DIRECTORY_INFO:
571       p += 4;
572       SIVAL(p,0,reskey); p += 4;
573       put_long_date(p,cdate); p += 8;
574       put_long_date(p,adate); p += 8;
575       put_long_date(p,mdate); p += 8;
576       put_long_date(p,mdate); p += 8;
577       SOFF_T(p,0,size);
578       SOFF_T(p,8,size);
579       p += 16;
580       SIVAL(p,0,nt_extmode); p += 4;
581       p += 4;
582       len = srvstr_push(outbuf, p, fname, -1, 
583                         STR_TERMINATE|STR_CONVERT);
584       SIVAL(p, -4, len);
585       p += len;
586       len = PTR_DIFF(p, pdata);
587       len = (len + 3) & ~3;
588       SIVAL(pdata,0,len);
589       p = pdata + len;
590       break;
591       
592       
593     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
594       p += 4;
595       SIVAL(p,0,reskey); p += 4;
596       put_long_date(p,cdate); p += 8;
597       put_long_date(p,adate); p += 8;
598       put_long_date(p,mdate); p += 8;
599       put_long_date(p,mdate); p += 8;
600       SOFF_T(p,0,size); 
601       SOFF_T(p,8,size);
602       p += 16;
603       SIVAL(p,0,nt_extmode); p += 4;
604       p += 4;
605       SIVAL(p,0,0); p += 4;
606
607       len = srvstr_push(outbuf, p, fname, -1, 
608                         STR_TERMINATE|STR_CONVERT);
609       SIVAL(p, -4, len);
610       p += len;
611
612       len = PTR_DIFF(p, pdata);
613       len = (len + 3) & ~3;
614       SIVAL(pdata,0,len);
615       p = pdata + len;
616       break;
617
618     case SMB_FIND_FILE_NAMES_INFO:
619       p += 4;
620       SIVAL(p,0,reskey); p += 4;
621       p += 4;
622       len = srvstr_push(outbuf, p, fname, -1, 
623                         STR_TERMINATE|STR_CONVERT);
624       SIVAL(p, -4, len);
625       p += len;
626       len = PTR_DIFF(p, pdata);
627       len = (len + 3) & ~3;
628       SIVAL(pdata,0,len);
629       p = pdata + len;
630       break;
631
632     default:      
633       return(False);
634     }
635
636
637   if (PTR_DIFF(p,pdata) > space_remaining) {
638     /* Move the dirptr back to prev_dirpos */
639     SeekDir(conn->dirptr, prev_dirpos);
640     *out_of_space = True;
641     DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
642     return False; /* Not finished - just out of space */
643   }
644
645   /* Setup the last_filename pointer, as an offset from base_data */
646   *last_name_off = PTR_DIFF(nameptr,base_data);
647   /* Advance the data pointer to the next slot */
648   *ppdata = p;
649
650   return(found);
651 }
652   
653
654 /****************************************************************************
655  Reply to a TRANS2_FINDFIRST.
656 ****************************************************************************/
657
658 static int call_trans2findfirst(connection_struct *conn,
659                                 char *inbuf, char *outbuf, int bufsize,  
660                                 char **pparams, char **ppdata)
661 {
662   /* We must be careful here that we don't return more than the
663      allowed number of data bytes. If this means returning fewer than
664      maxentries then so be it. We assume that the redirector has
665      enough room for the fixed number of parameter bytes it has
666      requested. */
667   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
668   char *params = *pparams;
669   char *pdata = *ppdata;
670   int dirtype = SVAL(params,0);
671   int maxentries = SVAL(params,2);
672   BOOL close_after_first = BITSETW(params+4,0);
673   BOOL close_if_end = BITSETW(params+4,1);
674   BOOL requires_resume_key = BITSETW(params+4,2);
675   int info_level = SVAL(params,6);
676   pstring directory;
677   pstring mask;
678   char *p, *wcard;
679   int last_name_off=0;
680   int dptr_num = -1;
681   int numentries = 0;
682   int i;
683   BOOL finished = False;
684   BOOL dont_descend = False;
685   BOOL out_of_space = False;
686   int space_remaining;
687   BOOL bad_path = False;
688   SMB_STRUCT_STAT sbuf;
689
690   *directory = *mask = 0;
691
692   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",
693            dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
694            info_level, max_data_bytes));
695   
696   switch (info_level) 
697     {
698     case 1:
699     case 2:
700     case 3:
701     case 4:
702     case SMB_FIND_FILE_DIRECTORY_INFO:
703     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
704     case SMB_FIND_FILE_NAMES_INFO:
705     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
706       break;
707     default:
708       return(ERROR(ERRDOS,ERRunknownlevel));
709     }
710
711   srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
712
713   RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
714
715   unix_convert(directory,conn,0,&bad_path,&sbuf);
716   if(!check_name(directory,conn)) {
717     if((errno == ENOENT) && bad_path)
718     {
719       unix_ERR_class = ERRDOS;
720       unix_ERR_code = ERRbadpath;
721     }
722
723 #if 0
724     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
725     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
726        (get_remote_arch() == RA_WINNT))
727     {
728       unix_ERR_class = ERRDOS;
729       unix_ERR_code = ERRbaddirectory;
730     }
731 #endif 
732
733     return(UNIXERROR(ERRDOS,ERRbadpath));
734   }
735
736   p = strrchr(directory,'/');
737   if(p == NULL) {
738     pstrcpy(mask,directory);
739     pstrcpy(directory,"./");
740   } else {
741     pstrcpy(mask,p+1);
742     *p = 0;
743   }
744
745   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
746
747   pdata = Realloc(*ppdata, max_data_bytes + 1024);
748   if( pdata == NULL ) {
749     return(ERROR(ERRDOS,ERRnomem));
750   }
751   *ppdata       = pdata;
752   memset((char *)pdata,'\0',max_data_bytes + 1024);
753
754   /* Realloc the params space */
755   params = Realloc(*pparams, 10);
756   if( params == NULL ) {
757     return(ERROR(ERRDOS,ERRnomem));
758   }
759   *pparams      = params;
760
761   dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
762   if (dptr_num < 0)
763     return(UNIXERROR(ERRDOS,ERRbadfile));
764
765   /* Save the wildcard match and attribs we are using on this directory - 
766      needed as lanman2 assumes these are being saved between calls */
767
768   if(!(wcard = strdup(mask))) {
769     dptr_close(&dptr_num);
770     return(ERROR(ERRDOS,ERRnomem));
771   }
772
773   dptr_set_wcard(dptr_num, wcard);
774   dptr_set_attr(dptr_num, dirtype);
775
776   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
777
778   /* We don't need to check for VOL here as this is returned by 
779      a different TRANS2 call. */
780   
781   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
782            conn->dirpath,lp_dontdescend(SNUM(conn))));
783   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
784     dont_descend = True;
785     
786   p = pdata;
787   space_remaining = max_data_bytes;
788   out_of_space = False;
789
790   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
791   {
792     BOOL got_exact_match = False;
793
794     /* this is a heuristic to avoid seeking the dirptr except when 
795        absolutely necessary. It allows for a filename of about 40 chars */
796     if (space_remaining < DIRLEN_GUESS && numentries > 0)
797     {
798       out_of_space = True;
799       finished = False;
800     }
801     else
802     {
803       finished = !get_lanman2_dir_entry(conn,
804                                         inbuf, outbuf,
805                                         mask,dirtype,info_level,
806                                         requires_resume_key,dont_descend,
807                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
808                                         &last_name_off);
809     }
810
811     if (finished && out_of_space)
812       finished = False;
813
814     if (!finished && !out_of_space)
815       numentries++;
816
817     /*
818      * As an optimisation if we know we aren't looking
819      * for a wildcard name (ie. the name matches the wildcard exactly)
820      * then we can finish on any (first) match.
821      * This speeds up large directory searches. JRA.
822      */
823
824     if(got_exact_match)
825       finished = True;
826
827     space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
828   }
829   
830   /* Check if we can close the dirptr */
831   if(close_after_first || (finished && close_if_end))
832   {
833     DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
834     dptr_close(&dptr_num);
835   }
836
837   /* 
838    * If there are no matching entries we must return ERRDOS/ERRbadfile - 
839    * from observation of NT.
840    */
841
842   if(numentries == 0)
843   {
844     dptr_close(&dptr_num);
845     return(ERROR(ERRDOS,ERRbadfile));
846   }
847
848   /* At this point pdata points to numentries directory entries. */
849
850   /* Set up the return parameter block */
851   SSVAL(params,0,dptr_num);
852   SSVAL(params,2,numentries);
853   SSVAL(params,4,finished);
854   SSVAL(params,6,0); /* Never an EA error */
855   SSVAL(params,8,last_name_off);
856
857   send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
858
859   if ((! *directory) && dptr_path(dptr_num))
860     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
861
862   DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
863             smb_fn_name(CVAL(inbuf,smb_com)), 
864             mask, directory, dirtype, numentries ) );
865
866   /* 
867    * Force a name mangle here to ensure that the
868    * mask as an 8.3 name is top of the mangled cache.
869    * The reasons for this are subtle. Don't remove
870    * this code unless you know what you are doing
871    * (see PR#13758). JRA.
872    */
873
874   if(!is_8_3( mask, False))
875     name_map_mangle(mask, True, True, SNUM(conn));
876
877   return(-1);
878 }
879
880
881 /****************************************************************************
882   reply to a TRANS2_FINDNEXT
883 ****************************************************************************/
884 static int call_trans2findnext(connection_struct *conn, 
885                                char *inbuf, char *outbuf, 
886                                int length, int bufsize,
887                                char **pparams, char **ppdata)
888 {
889   /* We must be careful here that we don't return more than the
890      allowed number of data bytes. If this means returning fewer than
891      maxentries then so be it. We assume that the redirector has
892      enough room for the fixed number of parameter bytes it has
893      requested. */
894   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
895   char *params = *pparams;
896   char *pdata = *ppdata;
897   int dptr_num = SVAL(params,0);
898   int maxentries = SVAL(params,2);
899   uint16 info_level = SVAL(params,4);
900   uint32 resume_key = IVAL(params,6);
901   BOOL close_after_request = BITSETW(params+10,0);
902   BOOL close_if_end = BITSETW(params+10,1);
903   BOOL requires_resume_key = BITSETW(params+10,2);
904   BOOL continue_bit = BITSETW(params+10,3);
905   pstring resume_name;
906   pstring mask;
907   pstring directory;
908   char *p;
909   uint16 dirtype;
910   int numentries = 0;
911   int i, last_name_off=0;
912   BOOL finished = False;
913   BOOL dont_descend = False;
914   BOOL out_of_space = False;
915   int space_remaining;
916
917   *mask = *directory = *resume_name = 0;
918
919   srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE|STR_CONVERT);
920
921   DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
922 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
923 resume_key = %d resume name = %s continue=%d level = %d\n",
924            dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
925            requires_resume_key, resume_key, resume_name, continue_bit, info_level));
926
927   switch (info_level) 
928     {
929     case 1:
930     case 2:
931     case 3:
932     case 4:
933     case SMB_FIND_FILE_DIRECTORY_INFO:
934     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
935     case SMB_FIND_FILE_NAMES_INFO:
936     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
937       break;
938     default:
939       return(ERROR(ERRDOS,ERRunknownlevel));
940     }
941
942   pdata = Realloc( *ppdata, max_data_bytes + 1024);
943   if(pdata == NULL) {
944     return(ERROR(ERRDOS,ERRnomem));
945   }
946   *ppdata       = pdata;
947   memset((char *)pdata,'\0',max_data_bytes + 1024);
948
949   /* Realloc the params space */
950   params = Realloc(*pparams, 6*SIZEOFWORD);
951   if( params == NULL ) {
952     return(ERROR(ERRDOS,ERRnomem));
953   }
954   *pparams      = params;
955
956   /* Check that the dptr is valid */
957   if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
958     return(ERROR(ERRDOS,ERRnofiles));
959
960   string_set(&conn->dirpath,dptr_path(dptr_num));
961
962   /* Get the wildcard mask from the dptr */
963   if((p = dptr_wcard(dptr_num))== NULL) {
964     DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
965     return (ERROR(ERRDOS,ERRnofiles));
966   }
967   pstrcpy(mask, p);
968   pstrcpy(directory,conn->dirpath);
969
970   /* Get the attr mask from the dptr */
971   dirtype = dptr_attr(dptr_num);
972
973   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
974            dptr_num, mask, dirtype, 
975            (long)conn->dirptr,
976            TellDir(conn->dirptr)));
977
978   /* We don't need to check for VOL here as this is returned by 
979      a different TRANS2 call. */
980
981   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
982   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
983     dont_descend = True;
984     
985   p = pdata;
986   space_remaining = max_data_bytes;
987   out_of_space = False;
988
989   /* 
990    * Seek to the correct position. We no longer use the resume key but
991    * depend on the last file name instead.
992    */
993   if(requires_resume_key && *resume_name && !continue_bit)
994   {
995     /*
996      * Fix for NT redirector problem triggered by resume key indexes
997      * changing between directory scans. We now return a resume key of 0
998      * and instead look for the filename to continue from (also given
999      * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1000      * findfirst/findnext (as is usual) then the directory pointer
1001      * should already be at the correct place. Check this by scanning
1002      * backwards looking for an exact (ie. case sensitive) filename match. 
1003      * If we get to the beginning of the directory and haven't found it then scan
1004      * forwards again looking for a match. JRA.
1005      */
1006
1007     int current_pos, start_pos;
1008     char *dname = NULL;
1009     void *dirptr = conn->dirptr;
1010     start_pos = TellDir(dirptr);
1011     for(current_pos = start_pos; current_pos >= 0; current_pos--)
1012     {
1013       DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1014
1015       SeekDir(dirptr, current_pos);
1016       dname = ReadDirName(dirptr);
1017
1018       /*
1019        * Remember, name_map_mangle is called by
1020        * get_lanman2_dir_entry(), so the resume name
1021        * could be mangled. Ensure we do the same
1022        * here.
1023        */
1024
1025       if(dname != NULL)
1026         name_map_mangle( dname, False, True, SNUM(conn));
1027
1028       if(dname && strcsequal( resume_name, dname))
1029       {
1030         SeekDir(dirptr, current_pos+1);
1031         DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1032         break;
1033       }
1034     }
1035
1036     /*
1037      * Scan forward from start if not found going backwards.
1038      */
1039
1040     if(current_pos < 0)
1041     {
1042       DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1043       SeekDir(dirptr, start_pos);
1044       for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
1045       {
1046         /*
1047          * Remember, name_map_mangle is called by
1048          * get_lanman2_dir_entry(), so the resume name
1049          * could be mangled. Ensure we do the same
1050          * here.
1051          */
1052
1053         if(dname != NULL)
1054           name_map_mangle( dname, False, True, SNUM(conn));
1055
1056         if(dname && strcsequal( resume_name, dname))
1057         {
1058           SeekDir(dirptr, current_pos+1);
1059           DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1060           break;
1061         }
1062       } /* end for */
1063     } /* end if current_pos */
1064   } /* end if requires_resume_key && !continue_bit */
1065
1066   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1067   {
1068     BOOL got_exact_match = False;
1069
1070     /* this is a heuristic to avoid seeking the dirptr except when 
1071        absolutely necessary. It allows for a filename of about 40 chars */
1072     if (space_remaining < DIRLEN_GUESS && numentries > 0)
1073     {
1074       out_of_space = True;
1075       finished = False;
1076     }
1077     else
1078     {
1079       finished = !get_lanman2_dir_entry(conn,
1080                                         inbuf, outbuf,
1081                                         mask,dirtype,info_level,
1082                                         requires_resume_key,dont_descend,
1083                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1084                                         &last_name_off);
1085     }
1086
1087     if (finished && out_of_space)
1088       finished = False;
1089
1090     if (!finished && !out_of_space)
1091       numentries++;
1092
1093     /*
1094      * As an optimisation if we know we aren't looking
1095      * for a wildcard name (ie. the name matches the wildcard exactly)
1096      * then we can finish on any (first) match.
1097      * This speeds up large directory searches. JRA.
1098      */
1099
1100     if(got_exact_match)
1101       finished = True;
1102
1103     space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1104   }
1105   
1106   /* Check if we can close the dirptr */
1107   if(close_after_request || (finished && close_if_end))
1108   {
1109     DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1110     dptr_close(&dptr_num); /* This frees up the saved mask */
1111   }
1112
1113
1114   /* Set up the return parameter block */
1115   SSVAL(params,0,numentries);
1116   SSVAL(params,2,finished);
1117   SSVAL(params,4,0); /* Never an EA error */
1118   SSVAL(params,6,last_name_off);
1119
1120   send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1121
1122   if ((! *directory) && dptr_path(dptr_num))
1123     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1124
1125   DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1126             smb_fn_name(CVAL(inbuf,smb_com)), 
1127             mask, directory, dirtype, numentries ) );
1128
1129   return(-1);
1130 }
1131
1132 /****************************************************************************
1133   reply to a TRANS2_QFSINFO (query filesystem info)
1134 ****************************************************************************/
1135
1136 static int call_trans2qfsinfo(connection_struct *conn, 
1137                               char *inbuf, char *outbuf, 
1138                               int length, int bufsize,
1139                               char **pparams, char **ppdata)
1140 {
1141   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1142   char *pdata = *ppdata;
1143   char *params = *pparams;
1144   uint16 info_level = SVAL(params,0);
1145   int data_len, len;
1146   SMB_STRUCT_STAT st;
1147   char *vname = volume_label(SNUM(conn));
1148   int snum = SNUM(conn);
1149   char *fstype = lp_fstype(SNUM(conn));
1150
1151   DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1152
1153   if(vfs_stat(conn,".",&st)!=0) {
1154     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1155     return (ERROR(ERRSRV,ERRinvdevice));
1156   }
1157
1158   pdata = Realloc(*ppdata, max_data_bytes + 1024);
1159   if ( pdata == NULL ) {
1160     return(ERROR(ERRDOS,ERRnomem));
1161   }
1162   *ppdata       = pdata;
1163   memset((char *)pdata,'\0',max_data_bytes + 1024);
1164
1165   switch (info_level) 
1166   {
1167     case 1:
1168     {
1169       SMB_BIG_UINT dfree,dsize,bsize;
1170       data_len = 18;
1171       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);     
1172       SIVAL(pdata,l1_idFileSystem,st.st_dev);
1173       SIVAL(pdata,l1_cSectorUnit,bsize/512);
1174       SIVAL(pdata,l1_cUnit,dsize);
1175       SIVAL(pdata,l1_cUnitAvail,dfree);
1176       SSVAL(pdata,l1_cbSector,512);
1177       DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1178                  (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1179          (unsigned int)dfree, 512));
1180       break;
1181     }
1182     case 2:
1183             /* Return volume name */
1184             /* 
1185              * Add volume serial number - hash of a combination of
1186              * the called hostname and the service name.
1187              */
1188             SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1189             len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, 
1190                               STR_TERMINATE|STR_CONVERT);
1191             SCVAL(pdata,l2_vol_cch,len);
1192             data_len = l2_vol_szVolLabel + len;
1193             DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1194                      (unsigned)st.st_ctime, len, vname));
1195             break;
1196
1197     case SMB_QUERY_FS_ATTRIBUTE_INFO:
1198             SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1199                   FILE_DEVICE_IS_MOUNTED|
1200                   (lp_nt_acl_support() ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1201             SIVAL(pdata,4,255); /* Max filename component length */
1202             len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_TERMINATE|STR_CONVERT);
1203             SIVAL(pdata,8,len);
1204             data_len = 12 + len;
1205             break;
1206
1207     case SMB_QUERY_FS_LABEL_INFO:
1208             len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE|STR_CONVERT);
1209             data_len = 4 + len;
1210             SIVAL(pdata,0,len);
1211             break;
1212     case SMB_QUERY_FS_VOLUME_INFO:      
1213             /* 
1214              * Add volume serial number - hash of a combination of
1215              * the called hostname and the service name.
1216              */
1217             SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
1218                   (str_checksum(local_machine)<<16));
1219
1220             len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE|STR_CONVERT);
1221             SIVAL(pdata,12,len);
1222             data_len = 18+len;
1223             DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
1224                      (int)strlen(vname),vname, lp_servicename(snum)));
1225             break;
1226     case SMB_QUERY_FS_SIZE_INFO:
1227     {
1228       SMB_BIG_UINT dfree,dsize,bsize;
1229       data_len = 24;
1230       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);     
1231       SBIG_UINT(pdata,0,dsize);
1232       SBIG_UINT(pdata,8,dfree);
1233       SIVAL(pdata,16,bsize/512);
1234       SIVAL(pdata,20,512);
1235       break;
1236     }
1237     case SMB_QUERY_FS_DEVICE_INFO:
1238       data_len = 8;
1239       SIVAL(pdata,0,0); /* dev type */
1240       SIVAL(pdata,4,0); /* characteristics */
1241       break;
1242     case SMB_MAC_QUERY_FS_INFO:
1243             /*
1244              * Thursby MAC extension... ONLY on NTFS filesystems
1245              * once we do streams then we don't need this
1246              */
1247             if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1248                     data_len = 88;
1249                     SIVAL(pdata,84,0x100); /* Don't support mac... */
1250                     break;
1251             }
1252             /* drop through */
1253   default:
1254           return(ERROR(ERRDOS,ERRunknownlevel));
1255   }
1256
1257
1258   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1259
1260   DEBUG( 4, ( "%s info_level = %d\n",
1261             smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1262
1263   return -1;
1264 }
1265
1266 /****************************************************************************
1267   reply to a TRANS2_SETFSINFO (set filesystem info)
1268 ****************************************************************************/
1269 static int call_trans2setfsinfo(connection_struct *conn,
1270                                 char *inbuf, char *outbuf, int length, 
1271                                 int bufsize,
1272                                 char **pparams, char **ppdata)
1273 {
1274   /* Just say yes we did it - there is nothing that
1275      can be set here so it doesn't matter. */
1276   int outsize;
1277   DEBUG(3,("call_trans2setfsinfo\n"));
1278
1279   if (!CAN_WRITE(conn))
1280     return(ERROR(ERRSRV,ERRaccess));
1281
1282   outsize = set_message(outbuf,10,0,True);
1283
1284   return outsize;
1285 }
1286
1287 /****************************************************************************
1288   Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1289   file name or file id).
1290 ****************************************************************************/
1291
1292 static int call_trans2qfilepathinfo(connection_struct *conn,
1293                                     char *inbuf, char *outbuf, int length, 
1294                                     int bufsize,
1295                                     char **pparams,char **ppdata,
1296                                     int total_data)
1297 {
1298   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1299   char *params = *pparams;
1300   char *pdata = *ppdata;
1301   uint16 tran_call = SVAL(inbuf, smb_setup0);
1302   uint16 info_level;
1303   int mode=0;
1304   SMB_OFF_T size=0;
1305   unsigned int data_size;
1306   SMB_STRUCT_STAT sbuf;
1307   pstring fname;
1308   char *base_name;
1309   char *p;
1310   SMB_OFF_T pos = 0;
1311   BOOL bad_path = False;
1312   BOOL delete_pending = False;
1313   int len;
1314
1315   if (tran_call == TRANSACT2_QFILEINFO) {
1316           files_struct *fsp = file_fsp(params,0);
1317           info_level = SVAL(params,2);
1318
1319           DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", 
1320                    info_level));
1321
1322           if(fsp && (fsp->is_directory || fsp->stat_open)) {
1323                   /*
1324                    * This is actually a QFILEINFO on a directory
1325                    * handle (returned from an NT SMB). NT5.0 seems
1326                    * to do this call. JRA.
1327                    */
1328                   pstrcpy(fname, fsp->fsp_name);
1329                   unix_convert(fname,conn,0,&bad_path,&sbuf);
1330                   if (!check_name(fname,conn) || 
1331                       (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1332                           DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1333                           if((errno == ENOENT) && bad_path) {
1334                                   unix_ERR_class = ERRDOS;
1335                                   unix_ERR_code = ERRbadpath;
1336                           }
1337                           return(UNIXERROR(ERRDOS,ERRbadpath));
1338                   }
1339                   
1340                   delete_pending = fsp->directory_delete_on_close;
1341           } else {
1342                   /*
1343                    * Original code - this is an open file.
1344                    */
1345                   CHECK_FSP(fsp,conn);
1346                   CHECK_ERROR(fsp);
1347
1348                   pstrcpy(fname, fsp->fsp_name);
1349                   if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1350                           DEBUG(3,("fstat of fnum %d failed (%s)\n",
1351                                    fsp->fnum, strerror(errno)));
1352                           return(UNIXERROR(ERRDOS,ERRbadfid));
1353                   }
1354                   if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1355                           return(UNIXERROR(ERRDOS,ERRnoaccess));
1356
1357                   delete_pending = fsp->delete_on_close;
1358           }
1359   } else {
1360           /* qpathinfo */
1361           info_level = SVAL(params,0);
1362
1363           DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", 
1364                    info_level));
1365
1366           srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1367
1368           RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1369
1370           unix_convert(fname,conn,0,&bad_path,&sbuf);
1371           if (!check_name(fname,conn) || 
1372               (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1373                   DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1374                   if((errno == ENOENT) && bad_path) {
1375                           unix_ERR_class = ERRDOS;
1376                           unix_ERR_code = ERRbadpath;
1377                   }
1378                   return(UNIXERROR(ERRDOS,ERRbadpath));
1379           }
1380   }
1381
1382
1383   DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1384            fname,info_level,tran_call,total_data));
1385
1386   p = strrchr(fname,'/'); 
1387   if (!p) {
1388           base_name = fname;
1389   } else {
1390           base_name = p+1;
1391   }
1392
1393   mode = dos_mode(conn,fname,&sbuf);
1394   size = sbuf.st_size;
1395   if (mode & aDIR) size = 0;
1396
1397   params = Realloc(*pparams,2);
1398   if (params == NULL) {
1399           return(ERROR(ERRDOS,ERRnomem));
1400   }
1401   *pparams      = params;
1402   memset((char *)params,'\0',2);
1403   data_size = max_data_bytes + 1024;
1404   pdata = Realloc(*ppdata, data_size); 
1405   if ( pdata == NULL ) {
1406     return(ERROR(ERRDOS,ERRnomem));
1407   }
1408   *ppdata = pdata;
1409
1410   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1411     /* uggh, EAs for OS2 */
1412     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1413     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1414   }
1415
1416   memset((char *)pdata,'\0',data_size);
1417
1418   switch (info_level) 
1419     {
1420     case SMB_INFO_STANDARD:
1421     case SMB_INFO_QUERY_EA_SIZE:
1422       data_size = (info_level==1?22:26);
1423       put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1424       put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1425       put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1426       SIVAL(pdata,l1_cbFile,(uint32)size);
1427       SIVAL(pdata,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
1428       SSVAL(pdata,l1_attrFile,mode);
1429       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1430       break;
1431
1432     case SMB_INFO_QUERY_EAS_FROM_LIST:
1433       data_size = 24;
1434       put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1435       put_dos_date2(pdata,4,sbuf.st_atime);
1436       put_dos_date2(pdata,8,sbuf.st_mtime);
1437       SIVAL(pdata,12,(uint32)size);
1438       SIVAL(pdata,16,SMB_ROUNDUP(size,1024));
1439       SIVAL(pdata,20,mode);
1440       break;
1441
1442     case SMB_INFO_QUERY_ALL_EAS:
1443       data_size = 4;
1444       SIVAL(pdata,0,data_size);
1445       break;
1446
1447     case 6:
1448       return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */      
1449
1450     case SMB_QUERY_FILE_BASIC_INFO:
1451         case 1004:
1452
1453       if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1454               data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1455       else {
1456           data_size = 40;
1457           SIVAL(pdata,36,0);
1458       }
1459       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1460       put_long_date(pdata+8,sbuf.st_atime);
1461       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1462       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1463       SIVAL(pdata,32,mode);
1464
1465       DEBUG(5,("SMB_QFBI - "));
1466       {
1467         time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1468         DEBUG(5,("create: %s ", ctime(&create_time)));
1469       }
1470       DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1471       DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1472       DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1473       DEBUG(5,("mode: %x\n", mode));
1474
1475       break;
1476
1477     case SMB_QUERY_FILE_STANDARD_INFO:
1478       data_size = 22;
1479       SOFF_T(pdata,0,size);
1480       SOFF_T(pdata,8,size);
1481       SIVAL(pdata,16,sbuf.st_nlink);
1482       CVAL(pdata,20) = 0;
1483       CVAL(pdata,21) = (mode&aDIR)?1:0;
1484       break;
1485
1486     case SMB_QUERY_FILE_EA_INFO:
1487       data_size = 4;
1488       break;
1489
1490     /* Get the 8.3 name - used if NT SMB was negotiated. */
1491     case SMB_QUERY_FILE_ALT_NAME_INFO:
1492       {
1493         pstring short_name;
1494
1495         pstrcpy(short_name,base_name);
1496         /* Mangle if not already 8.3 */
1497         if(!is_8_3(short_name, True))
1498         {
1499           if(!name_map_mangle(short_name,True,True,SNUM(conn)))
1500             *short_name = '\0';
1501         }
1502         len = srvstr_push(outbuf, pdata+4, short_name, -1, 
1503                           STR_TERMINATE|STR_CONVERT|STR_UPPER);
1504         data_size = 4 + len;
1505         SIVAL(pdata,0,len);
1506       }
1507       break;
1508
1509     case SMB_QUERY_FILE_NAME_INFO:
1510             /*
1511              * The first part of this code is essential
1512              * to get security descriptors to work on mapped
1513              * drives. Don't ask how I discovered this unless
1514              * you like hearing about me suffering.... :-). JRA.
1515              */
1516             if(strequal(".", fname)) {
1517                     len = srvstr_push(outbuf, pdata+4, "\\", -1, STR_TERMINATE|STR_CONVERT);
1518             } else {
1519                     len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE|STR_CONVERT);
1520             }
1521             data_size = 4 + len;
1522             SIVAL(pdata,0,len);
1523             break;
1524
1525     case SMB_QUERY_FILE_ALLOCATION_INFO:
1526     case SMB_QUERY_FILE_END_OF_FILEINFO:
1527             data_size = 8;
1528             SOFF_T(pdata,0,size);
1529             break;
1530
1531     case SMB_QUERY_FILE_ALL_INFO:
1532       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1533       put_long_date(pdata+8,sbuf.st_atime);
1534       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1535       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1536       SIVAL(pdata,32,mode);
1537       pdata += 40;
1538       SOFF_T(pdata,0,size);
1539       SOFF_T(pdata,8,size);
1540       SIVAL(pdata,16,sbuf.st_nlink);
1541       CVAL(pdata,20) = delete_pending;
1542       CVAL(pdata,21) = (mode&aDIR)?1:0;
1543       pdata += 24;
1544       SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); 
1545       pdata += 8; /* index number */
1546       pdata += 4; /* EA info */
1547       if (mode & aRONLY)
1548         SIVAL(pdata,0,0xA9);
1549       else
1550         SIVAL(pdata,0,0xd01BF);
1551       pdata += 4;
1552       SOFF_T(pdata,0,pos); /* current offset */
1553       pdata += 8;
1554       SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1555       pdata += 4;
1556       pdata += 4; /* alignment */
1557       len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE|STR_CONVERT);
1558       SIVAL(pdata,0,len);
1559       pdata += 4 + len;
1560       data_size = PTR_DIFF(pdata,(*ppdata));
1561       break;
1562
1563         /*
1564          * Windows 2000 completely undocumented new SMB info levels.
1565          * Thanks Microsoft.... sure you're working on making this
1566          * protocol a standard.... sure you are... :-).
1567          * Lying rat-bastards. JRA.
1568          */
1569
1570         case 1005:
1571                 SIVAL(pdata,0,mode);
1572                 SIVAL(pdata,4,0); /* ??? */
1573                 SOFF_T(pdata,8,size);
1574                 SIVAL(pdata,16,1); /* ??? */
1575                 SIVAL(pdata,20,0); /* ??? */
1576                 data_size = 24;
1577                 break;
1578
1579         case 1006:
1580                 SIVAL(pdata,0,0x907); /* ??? */
1581                 SIVAL(pdata,4,0x690000); /* ??? */
1582                 data_size = 8;
1583                 break;
1584
1585         case 1007:
1586                 SIVAL(pdata,0,0); /* ??? */
1587                 data_size = 4;
1588                 break;
1589
1590         case 1008:
1591                 SIVAL(pdata,0,0x12019F); /* ??? */
1592                 data_size = 4;
1593                 break;
1594
1595         case 1009:
1596                 /* Pathname with leading '\'. */
1597                 {
1598                         pstring new_fname;
1599                         size_t byte_len;
1600
1601                         pstrcpy(new_fname, "\\");
1602                         pstrcat(new_fname, fname);
1603                         byte_len = dos_PutUniCode(pdata+4,new_fname,max_data_bytes,False);
1604                         SIVAL(pdata,0,byte_len);
1605                         data_size = 4 + byte_len;
1606                         break;
1607                 }
1608
1609         case 1014:
1610                 SIVAL(pdata,0,0); /* ??? */
1611                 SIVAL(pdata,4,0); /* ??? */
1612                 data_size = 8;
1613                 break;
1614
1615         case 1016:
1616                 SIVAL(pdata,0,0); /* ??? */
1617                 data_size = 4;
1618                 break;
1619
1620         case 1017:
1621                 SIVAL(pdata,0,0); /* ??? */
1622                 data_size = 4;
1623                 break;
1624
1625 #if 0
1626         /* Not yet finished... JRA */
1627         case 1018:
1628                 {
1629                         pstring new_fname;
1630                         size_t byte_len;
1631
1632                         put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1633                         put_long_date(pdata+8,sbuf.st_atime);
1634                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1635                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1636                         SIVAL(pdata,32,mode);
1637                         SIVAL(pdata,36,0); /* ??? */
1638                         SIVAL(pdata,40,0x20); /* ??? */
1639                         SIVAL(pdata,44,0); /* ??? */
1640                         SOFF_T(pdata,48,size);
1641                         SIVAL(pdata,56,0x1); /* ??? */
1642                         SIVAL(pdata,60,0); /* ??? */
1643                         SIVAL(pdata,64,0); /* ??? */
1644                         SIVAL(pdata,68,length); /* Following string length in bytes. */
1645                         dos_PutUniCode(pdata+72,,False);
1646                         break;
1647                 }
1648 #endif
1649
1650         case 1021:
1651                 /* Last component of pathname. */
1652                 {
1653                         size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1654                         SIVAL(pdata,0,byte_len);
1655                         data_size = 4 + byte_len;
1656                         break;
1657                 }
1658                 
1659         case 1022:
1660                 {
1661                         size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1662                         SIVAL(pdata,0,0); /* ??? */
1663                         SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1664                         SOFF_T(pdata,8,size);
1665                         SIVAL(pdata,16,0x20); /* ??? */
1666                         SIVAL(pdata,20,0); /* ??? */
1667                         data_size = 24 + byte_len;
1668                         break;
1669                 }
1670
1671         case 1028:
1672                 SOFF_T(pdata,0,size);
1673                 SIVAL(pdata,8,0); /* ??? */
1674                 SIVAL(pdata,12,0); /* ??? */
1675                 data_size = 16;
1676                 break;
1677
1678         case 1034:
1679                 put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1680                 put_long_date(pdata+8,sbuf.st_atime);
1681                 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1682                 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1683                 SIVAL(pdata,32,0x20); /* ??? */
1684                 SIVAL(pdata,36,0); /* ??? */
1685                 SOFF_T(pdata,40,size);
1686                 SIVAL(pdata,48,mode);
1687                 SIVAL(pdata,52,0); /* ??? */
1688                 data_size = 56;
1689                 break;
1690
1691         case 1035:
1692                 SIVAL(pdata,0,mode);
1693                 SIVAL(pdata,4,0);
1694                 data_size = 8;
1695                 break;
1696
1697         /*
1698          * End new completely undocumented info levels... JRA.
1699          */
1700
1701 #if 0
1702       /* NT4 server just returns "invalid query" to this - if we try to answer 
1703          it then NTws gets a BSOD! (tridge) */
1704     case SMB_QUERY_FILE_STREAM_INFO:
1705       SIVAL(pdata,0,pos);
1706       SIVAL(pdata,4,size);
1707       SIVAL(pdata,12,size);
1708       len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE|STR_CONVERT);
1709       SIVAL(pdata,20,len);
1710       data_size = 24 + len;
1711       break;
1712 #endif
1713
1714     default:
1715       return(ERROR(ERRDOS,ERRunknownlevel));
1716     }
1717
1718   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
1719
1720   return(-1);
1721 }
1722
1723 /****************************************************************************
1724   reply to a TRANS2_SETFILEINFO (set file info by fileid)
1725 ****************************************************************************/
1726 static int call_trans2setfilepathinfo(connection_struct *conn,
1727                                       char *inbuf, char *outbuf, int length, 
1728                                       int bufsize, char **pparams, 
1729                                       char **ppdata, int total_data)
1730 {
1731   char *params = *pparams;
1732   char *pdata = *ppdata;
1733   uint16 tran_call = SVAL(inbuf, smb_setup0);
1734   uint16 info_level;
1735   int mode=0;
1736   SMB_OFF_T size=0;
1737   struct utimbuf tvs;
1738   SMB_STRUCT_STAT sbuf;
1739   pstring fname;
1740   int fd = -1;
1741   BOOL bad_path = False;
1742   files_struct *fsp = NULL;
1743
1744   if (tran_call == TRANSACT2_SETFILEINFO) {
1745     fsp = file_fsp(params,0);
1746     info_level = SVAL(params,2);    
1747
1748     if(fsp && (fsp->is_directory || fsp->stat_open)) {
1749       /*
1750        * This is actually a SETFILEINFO on a directory
1751        * handle (returned from an NT SMB). NT5.0 seems
1752        * to do this call. JRA.
1753        */
1754       pstrcpy(fname, fsp->fsp_name);
1755       unix_convert(fname,conn,0,&bad_path,&sbuf);
1756       if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
1757         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1758         if((errno == ENOENT) && bad_path)
1759         {
1760           unix_ERR_class = ERRDOS;
1761           unix_ERR_code = ERRbadpath;
1762         }
1763         return(UNIXERROR(ERRDOS,ERRbadpath));
1764       }
1765     } else if (fsp->print_file) {
1766         /*
1767          * Doing a DELETE_ON_CLOSE should cancel a print job.
1768          */
1769         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
1770           fsp->share_mode = FILE_DELETE_ON_CLOSE;
1771
1772           DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n",
1773                fsp->fsp_name ));
1774
1775           SSVAL(params,0,0);
1776           send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1777           return(-1);
1778         }
1779     } else {
1780       /*
1781        * Original code - this is an open file.
1782        */
1783       CHECK_FSP(fsp,conn);
1784       CHECK_ERROR(fsp);
1785
1786       pstrcpy(fname, fsp->fsp_name);
1787       fd = fsp->fd;
1788
1789       if (vfs_fstat(fsp,fd,&sbuf) != 0) {
1790         DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1791         return(UNIXERROR(ERRDOS,ERRbadfid));
1792       }
1793     }
1794   } else {
1795     /* set path info */
1796     info_level = SVAL(params,0);    
1797     srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1798     unix_convert(fname,conn,0,&bad_path,&sbuf);
1799     if(!check_name(fname, conn))
1800     {
1801       if((errno == ENOENT) && bad_path)
1802       {
1803         unix_ERR_class = ERRDOS;
1804         unix_ERR_code = ERRbadpath;
1805       }
1806       return(UNIXERROR(ERRDOS,ERRbadpath));
1807     }
1808  
1809     if(!VALID_STAT(sbuf)) {
1810       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1811       if((errno == ENOENT) && bad_path)
1812       {
1813         unix_ERR_class = ERRDOS;
1814         unix_ERR_code = ERRbadpath;
1815       }
1816       return(UNIXERROR(ERRDOS,ERRbadpath));
1817     }    
1818   }
1819
1820   if (!CAN_WRITE(conn))
1821     return(ERROR(ERRSRV,ERRaccess));
1822
1823   DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1824            tran_call,fname,info_level,total_data));
1825
1826   /* Realloc the parameter and data sizes */
1827   params = Realloc(*pparams,2);
1828   if(params == NULL) {
1829     return(ERROR(ERRDOS,ERRnomem));
1830   }
1831   *pparams      = params;
1832
1833   SSVAL(params,0,0);
1834
1835   size = sbuf.st_size;
1836   tvs.modtime = sbuf.st_mtime;
1837   tvs.actime = sbuf.st_atime;
1838   mode = dos_mode(conn,fname,&sbuf);
1839
1840   if (total_data > 4 && IVAL(pdata,0) == total_data) {
1841     /* uggh, EAs for OS2 */
1842     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1843     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1844   }
1845
1846   switch (info_level)
1847   {
1848     case SMB_INFO_STANDARD:
1849     case SMB_INFO_QUERY_EA_SIZE:
1850     {
1851       /* access time */
1852       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1853
1854       /* write time */
1855       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1856
1857       mode = SVAL(pdata,l1_attrFile);
1858       size = IVAL(pdata,l1_cbFile);
1859       break;
1860     }
1861
1862     /* XXXX um, i don't think this is right.
1863        it's also not in the cifs6.txt spec.
1864      */
1865     case SMB_INFO_QUERY_EAS_FROM_LIST:
1866       tvs.actime = make_unix_date2(pdata+8);
1867       tvs.modtime = make_unix_date2(pdata+12);
1868       size = IVAL(pdata,16);
1869       mode = IVAL(pdata,24);
1870       break;
1871
1872     /* XXXX nor this.  not in cifs6.txt, either. */
1873     case SMB_INFO_QUERY_ALL_EAS:
1874       tvs.actime = make_unix_date2(pdata+8);
1875       tvs.modtime = make_unix_date2(pdata+12);
1876       size = IVAL(pdata,16);
1877       mode = IVAL(pdata,24);
1878       break;
1879
1880     case SMB_SET_FILE_BASIC_INFO:
1881         case 1004:
1882     {
1883       /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
1884       time_t write_time;
1885       time_t changed_time;
1886
1887       /* Ignore create time at offset pdata. */
1888
1889       /* access time */
1890       tvs.actime = interpret_long_date(pdata+8);
1891
1892       write_time = interpret_long_date(pdata+16);
1893       changed_time = interpret_long_date(pdata+24);
1894
1895       tvs.modtime = MIN(write_time, changed_time);
1896
1897       /* Prefer a defined time to an undefined one. */
1898       if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
1899        tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
1900                       ? changed_time
1901                       : write_time);
1902
1903       /* attributes */
1904       mode = IVAL(pdata,32);
1905       break;
1906     }
1907
1908     /*
1909      * NT seems to use this call with a size of zero
1910      * to mean truncate the file. JRA.
1911      */
1912
1913         case 1019:
1914         case 1020:
1915     case SMB_SET_FILE_ALLOCATION_INFO:
1916     {
1917       SMB_OFF_T newsize = IVAL(pdata,0);
1918 #ifdef LARGE_SMB_OFF_T
1919       newsize |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1920 #else /* LARGE_SMB_OFF_T */
1921       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1922          return(ERROR(ERRDOS,ERRunknownlevel));
1923 #endif /* LARGE_SMB_OFF_T */
1924       DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)newsize ));
1925       if(newsize == 0)
1926         size = 0;
1927       break;
1928     }
1929
1930     case SMB_SET_FILE_END_OF_FILE_INFO:
1931     {
1932       size = IVAL(pdata,0);
1933 #ifdef LARGE_SMB_OFF_T
1934       size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1935 #else /* LARGE_SMB_OFF_T */
1936       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1937          return(ERROR(ERRDOS,ERRunknownlevel));
1938 #endif /* LARGE_SMB_OFF_T */
1939       DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
1940       break;
1941     }
1942
1943     case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
1944     {
1945                 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
1946
1947                 if (tran_call != TRANSACT2_SETFILEINFO)
1948                         return(ERROR(ERRDOS,ERRunknownlevel));
1949
1950                 if (fsp == NULL)
1951                         return(UNIXERROR(ERRDOS,ERRbadfid));
1952
1953                 /*
1954                  * Only allow delete on close for files/directories opened with delete intent.
1955                  */
1956
1957                 if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) {
1958                         DEBUG(10,("call_trans2setfilepathinfo: file %s delete on close flag set but delete access denied.\n",
1959                                         fsp->fsp_name ));
1960                                 return(ERROR(ERRDOS,ERRnoaccess));
1961                 }
1962
1963                 if(fsp->is_directory) {
1964                         fsp->directory_delete_on_close = delete_on_close;
1965                         DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, directory %s\n",
1966                                 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1967                 } else if(fsp->stat_open) {
1968
1969                         DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, stat open %s\n",
1970                                 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1971
1972                 } else {
1973
1974                         files_struct *iterate_fsp;
1975
1976                         /*
1977                          * Modify the share mode entry for all files open
1978                          * on this device and inode to tell other smbds we have 
1979                          * changed the delete on close flag. This will be noticed
1980                          * in the close code, the last closer will delete the file
1981                          * if flag is set.
1982                          */
1983
1984                         DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1985                                                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1986
1987                         if (lock_share_entry_fsp(fsp) == False)
1988                                 return(ERROR(ERRDOS,ERRnoaccess));
1989
1990                         if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
1991                                 DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close flag for file %s\n",
1992                                                 fsp->fsp_name ));
1993                                 unlock_share_entry_fsp(fsp);
1994                                 return(ERROR(ERRDOS,ERRnoaccess));
1995                         }
1996
1997                         /*
1998                          * Release the lock.
1999                          */
2000
2001                         unlock_share_entry_fsp(fsp);
2002
2003                         /*
2004                          * Go through all files we have open on the same device and
2005                          * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
2006                          * Other smbd's that have this file open will look in the share_mode on close.
2007                          * take care of this (rare) case in close_file(). See the comment there.
2008                          * NB. JRA. We don't really need to do this anymore - all should be taken
2009                          * care of in the share_mode changes in the tdb.
2010                          */
2011
2012                         for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
2013                                         iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
2014                                                         fsp->delete_on_close = delete_on_close;
2015
2016                         /*
2017                          * Set the delete on close flag in the fsp.
2018                          */
2019                         fsp->delete_on_close = delete_on_close;
2020
2021                         DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
2022                                 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2023
2024                 }
2025
2026                 break;
2027         }
2028
2029         default:
2030         {
2031                 return(ERROR(ERRDOS,ERRunknownlevel));
2032         }
2033   }
2034
2035   /* get some defaults (no modifications) if any info is zero or -1. */
2036   if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2037     tvs.actime = sbuf.st_atime;
2038
2039   if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2040     tvs.modtime = sbuf.st_mtime;
2041
2042   DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2043   DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2044   DEBUG(6,("size: %.0f ", (double)size));
2045   DEBUG(6,("mode: %x\n"  , mode));
2046
2047   if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2048      (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2049      (info_level == 1019) ||
2050      (info_level == 1020))) {
2051     /*
2052      * Only do this test if we are not explicitly
2053      * changing the size of a file.
2054      */
2055     if (!size)
2056       size = sbuf.st_size;
2057   }
2058
2059   /* Try and set the times, size and mode of this file -
2060      if they are different from the current values
2061    */
2062   if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2063     if(fsp != NULL) {
2064       /*
2065        * This was a setfileinfo on an open file.
2066        * NT does this a lot. It's actually pointless
2067        * setting the time here, as it will be overwritten
2068        * on the next write, so we save the request
2069        * away and will set it on file code. JRA.
2070        */
2071
2072        if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2073          DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n",
2074             ctime(&tvs.modtime) ));
2075          fsp->pending_modtime = tvs.modtime;
2076        }
2077
2078     } else {
2079
2080       DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2081
2082       if(file_utime(conn, fname, &tvs)!=0)
2083         return(UNIXERROR(ERRDOS,ERRnoaccess));
2084     }
2085   }
2086
2087   /* check the mode isn't different, before changing it */
2088   if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) {
2089
2090     DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n",
2091           fname, mode ));
2092
2093     if(file_chmod(conn, fname, mode, NULL)) {
2094       DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2095       return(UNIXERROR(ERRDOS,ERRnoaccess));
2096     }
2097   }
2098
2099   if(size != sbuf.st_size) {
2100
2101     DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2102           fname, (double)size ));
2103
2104     if (fd == -1) {
2105       files_struct *new_fsp = NULL;
2106       int access_mode = 0;
2107       int action = 0;
2108
2109       if(global_oplock_break) {
2110         /* Queue this file modify as we are the process of an oplock break.  */
2111
2112         DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2113         DEBUGADD(2,( "in oplock break state.\n"));
2114
2115         push_oplock_pending_smb_message(inbuf, length);
2116         return -1;
2117       }
2118
2119       new_fsp = open_file_shared(conn, fname, &sbuf,
2120                            SET_OPEN_MODE(DOS_OPEN_RDWR),
2121                            (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2122                            0, 0, &access_mode, &action);
2123         
2124       if (new_fsp == NULL)
2125         return(UNIXERROR(ERRDOS,ERRbadpath));
2126       vfs_set_filelen(new_fsp, size);
2127       close_file(new_fsp,True);
2128     } else {
2129         vfs_set_filelen(fsp, size);
2130     }
2131   }
2132
2133   SSVAL(params,0,0);
2134
2135   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2136   
2137   return(-1);
2138 }
2139
2140 /****************************************************************************
2141   reply to a TRANS2_MKDIR (make directory with extended attributes).
2142 ****************************************************************************/
2143 static int call_trans2mkdir(connection_struct *conn,
2144                             char *inbuf, char *outbuf, int length, int bufsize,
2145                             char **pparams, char **ppdata)
2146 {
2147   char *params = *pparams;
2148   pstring directory;
2149   int ret = -1;
2150   SMB_STRUCT_STAT sbuf;
2151   BOOL bad_path = False;
2152
2153   if (!CAN_WRITE(conn))
2154     return(ERROR(ERRSRV,ERRaccess));
2155
2156   srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
2157
2158   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2159
2160   unix_convert(directory,conn,0,&bad_path,&sbuf);
2161   if (check_name(directory,conn))
2162     ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2163   
2164   if(ret < 0)
2165     {
2166       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2167       if((errno == ENOENT) && bad_path)
2168       {
2169         unix_ERR_class = ERRDOS;
2170         unix_ERR_code = ERRbadpath;
2171       }
2172       return(UNIXERROR(ERRDOS,ERRnoaccess));
2173     }
2174
2175   /* Realloc the parameter and data sizes */
2176   params = Realloc(*pparams,2);
2177   if(params == NULL) {
2178     return(ERROR(ERRDOS,ERRnomem));
2179   }
2180   *pparams      = params;
2181
2182   SSVAL(params,0,0);
2183
2184   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2185   
2186   return(-1);
2187 }
2188
2189 /****************************************************************************
2190   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
2191   We don't actually do this - we just send a null response.
2192 ****************************************************************************/
2193 static int call_trans2findnotifyfirst(connection_struct *conn,
2194                                       char *inbuf, char *outbuf, 
2195                                       int length, int bufsize,
2196                                       char **pparams, char **ppdata)
2197 {
2198   static uint16 fnf_handle = 257;
2199   char *params = *pparams;
2200   uint16 info_level = SVAL(params,4);
2201
2202   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2203
2204   switch (info_level) 
2205     {
2206     case 1:
2207     case 2:
2208       break;
2209     default:
2210       return(ERROR(ERRDOS,ERRunknownlevel));
2211     }
2212
2213   /* Realloc the parameter and data sizes */
2214   params = Realloc(*pparams,6);
2215   if(params == NULL) {
2216     return(ERROR(ERRDOS,ERRnomem));
2217   }
2218   *pparams      = params;
2219
2220   SSVAL(params,0,fnf_handle);
2221   SSVAL(params,2,0); /* No changes */
2222   SSVAL(params,4,0); /* No EA errors */
2223
2224   fnf_handle++;
2225
2226   if(fnf_handle == 0)
2227     fnf_handle = 257;
2228
2229   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2230   
2231   return(-1);
2232 }
2233
2234 /****************************************************************************
2235   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
2236   changes). Currently this does nothing.
2237 ****************************************************************************/
2238 static int call_trans2findnotifynext(connection_struct *conn,
2239                                      char *inbuf, char *outbuf, 
2240                                      int length, int bufsize,
2241                                      char **pparams, char **ppdata)
2242 {
2243   char *params = *pparams;
2244
2245   DEBUG(3,("call_trans2findnotifynext\n"));
2246
2247   /* Realloc the parameter and data sizes */
2248   params = Realloc(*pparams,4);
2249   if(params == NULL) {
2250     return(ERROR(ERRDOS,ERRnomem));
2251   }
2252   *pparams      = params;
2253
2254   SSVAL(params,0,0); /* No changes */
2255   SSVAL(params,2,0); /* No EA errors */
2256
2257   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2258   
2259   return(-1);
2260 }
2261
2262 /****************************************************************************
2263   reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>
2264 ****************************************************************************/
2265 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2266                                      char* outbuf, int length, int bufsize,
2267                                      char** pparams, char** ppdata)
2268 {
2269   char *params = *pparams;
2270   pstring pathname;
2271   int reply_size = 0;
2272   int max_referral_level = SVAL(params,0);
2273
2274
2275   DEBUG(10,("call_trans2getdfsreferral\n"));
2276
2277   if(!lp_host_msdfs())
2278     return(ERROR(ERRDOS,ERRbadfunc));
2279
2280   srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE|STR_CONVERT);
2281
2282   if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2283     return(ERROR(ERRDOS,ERRbadfile));
2284     
2285   SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2286   send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2287
2288   return(-1);
2289 }
2290
2291 #define LMCAT_SPL       0x53
2292 #define LMFUNC_GETJOBID 0x60
2293
2294 /****************************************************************************
2295   reply to a TRANS2_IOCTL - used for OS/2 printing.
2296 ****************************************************************************/
2297
2298 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2299                             char* outbuf, int length, int bufsize,
2300                             char** pparams, char** ppdata)
2301 {
2302   char *pdata = *ppdata;
2303   files_struct *fsp = file_fsp(inbuf,smb_vwv15);
2304
2305   if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2306       (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2307     pdata = Realloc(*ppdata, 32);
2308     if(pdata == NULL) {
2309       return(ERROR(ERRDOS,ERRnomem));
2310     }
2311     *ppdata = pdata;
2312
2313         /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
2314            CAN ACCEPT THIS IN UNICODE. JRA. */
2315
2316     SSVAL(pdata,0,fsp->print_jobid);                     /* Job number */
2317         srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_CONVERT|STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
2318     srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_CONVERT|STR_ASCII|STR_TERMINATE); /* Service name */
2319     send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
2320     return(-1);
2321   } else {
2322     DEBUG(2,("Unknown TRANS2_IOCTL\n"));
2323     return(ERROR(ERRSRV,ERRerror));
2324   }
2325 }
2326
2327 /****************************************************************************
2328   reply to a SMBfindclose (stop trans2 directory search)
2329 ****************************************************************************/
2330 int reply_findclose(connection_struct *conn,
2331                     char *inbuf,char *outbuf,int length,int bufsize)
2332 {
2333         int outsize = 0;
2334         int dptr_num=SVALS(inbuf,smb_vwv0);
2335         START_PROFILE(SMBfindclose);
2336
2337         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
2338
2339         dptr_close(&dptr_num);
2340
2341         outsize = set_message(outbuf,0,0,True);
2342
2343         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
2344
2345         END_PROFILE(SMBfindclose);
2346         return(outsize);
2347 }
2348
2349 /****************************************************************************
2350   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
2351 ****************************************************************************/
2352 int reply_findnclose(connection_struct *conn, 
2353                      char *inbuf,char *outbuf,int length,int bufsize)
2354 {
2355         int outsize = 0;
2356         int dptr_num= -1;
2357         START_PROFILE(SMBfindnclose);
2358         
2359         dptr_num = SVAL(inbuf,smb_vwv0);
2360
2361         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2362
2363         /* We never give out valid handles for a 
2364            findnotifyfirst - so any dptr_num is ok here. 
2365            Just ignore it. */
2366
2367         outsize = set_message(outbuf,0,0,True);
2368
2369         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2370
2371         END_PROFILE(SMBfindnclose);
2372         return(outsize);
2373 }
2374
2375
2376 /****************************************************************************
2377   reply to a SMBtranss2 - just ignore it!
2378 ****************************************************************************/
2379 int reply_transs2(connection_struct *conn,
2380                   char *inbuf,char *outbuf,int length,int bufsize)
2381 {
2382         START_PROFILE(SMBtranss2);
2383         DEBUG(4,("Ignoring transs2 of length %d\n",length));
2384         END_PROFILE(SMBtranss2);
2385         return(-1);
2386 }
2387
2388 /****************************************************************************
2389   reply to a SMBtrans2
2390 ****************************************************************************/
2391 int reply_trans2(connection_struct *conn,
2392                  char *inbuf,char *outbuf,int length,int bufsize)
2393 {
2394         int outsize = 0;
2395         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2396         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2397 #if 0
2398         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2399         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2400         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2401         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2402         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2403         int32 timeout = IVALS(inbuf,smb_timeout);
2404 #endif
2405         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2406         unsigned int tran_call = SVAL(inbuf, smb_setup0);
2407         char *params = NULL, *data = NULL;
2408         int num_params, num_params_sofar, num_data, num_data_sofar;
2409         START_PROFILE(SMBtrans2);
2410
2411         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2412                 /* Queue this open message as we are the process of an
2413                  * oplock break.  */
2414
2415                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2416                 DEBUGADD(2,( "in oplock break state.\n"));
2417
2418                 push_oplock_pending_smb_message(inbuf, length);
2419                 END_PROFILE(SMBtrans2);
2420                 return -1;
2421         }
2422         
2423         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
2424             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
2425                 END_PROFILE(SMBtrans2);
2426                 return(ERROR(ERRSRV,ERRaccess));
2427         }
2428
2429         outsize = set_message(outbuf,0,0,True);
2430
2431         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2432            is so as a sanity check */
2433         if (suwcnt != 1) {
2434                 /*
2435                  * Need to have rc=0 for ioctl to get job id for OS/2.
2436                  *  Network printing will fail if function is not successful.
2437                  *  Similar function in reply.c will be used if protocol
2438                  *  is LANMAN1.0 instead of LM1.2X002.
2439                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
2440                  *  outbuf doesn't have to be set(only job id is used).
2441                  */
2442                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
2443                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2444                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2445                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
2446                 } else {
2447                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
2448                         DEBUG(2,("Transaction is %d\n",tran_call));
2449                         END_PROFILE(SMBtrans2);
2450                         return(ERROR(ERRSRV,ERRerror));
2451                 }
2452         }
2453     
2454         /* Allocate the space for the maximum needed parameters and data */
2455         if (total_params > 0)
2456                 params = (char *)malloc(total_params);
2457         if (total_data > 0)
2458                 data = (char *)malloc(total_data);
2459   
2460         if ((total_params && !params)  || (total_data && !data)) {
2461                 DEBUG(2,("Out of memory in reply_trans2\n"));
2462                 if(params)
2463                   free(params);
2464                 if(data)
2465                   free(data); 
2466                 END_PROFILE(SMBtrans2);
2467                 return(ERROR(ERRDOS,ERRnomem));
2468         }
2469
2470         /* Copy the param and data bytes sent with this request into
2471            the params buffer */
2472         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2473         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2474
2475         if (num_params > total_params || num_data > total_data)
2476                 exit_server("invalid params in reply_trans2");
2477
2478         if(params)
2479                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2480         if(data)
2481                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2482
2483         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
2484                 /* We need to send an interim response then receive the rest
2485                    of the parameter/data bytes */
2486                 outsize = set_message(outbuf,0,0,True);
2487                 if (!send_smb(smbd_server_fd(),outbuf))
2488                         exit_server("reply_trans2: send_smb failed.\n");
2489
2490                 while (num_data_sofar < total_data || 
2491                        num_params_sofar < total_params) {
2492                         BOOL ret;
2493
2494                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2495                         
2496                         if ((ret && 
2497                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2498                                 outsize = set_message(outbuf,0,0,True);
2499                                 if(ret)
2500                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2501                                 else
2502                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2503                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2504                                 if(params)
2505                                         free(params);
2506                                 if(data)
2507                                         free(data);
2508                                 END_PROFILE(SMBtrans2);
2509                                 return(ERROR(ERRSRV,ERRerror));
2510                         }
2511       
2512                         /* Revise total_params and total_data in case
2513                            they have changed downwards */
2514                         total_params = SVAL(inbuf, smb_tpscnt);
2515                         total_data = SVAL(inbuf, smb_tdscnt);
2516                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2517                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2518                         if (num_params_sofar > total_params || num_data_sofar > total_data)
2519                                 exit_server("data overflow in trans2");
2520                         
2521                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
2522                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2523                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2524                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2525                 }
2526         }
2527         
2528         if (Protocol >= PROTOCOL_NT1) {
2529                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
2530         }
2531
2532         /* Now we must call the relevant TRANS2 function */
2533         switch(tran_call)  {
2534         case TRANSACT2_OPEN:
2535                 START_PROFILE_NESTED(Trans2_open);
2536                 outsize = call_trans2open(conn, 
2537                                           inbuf, outbuf, bufsize, 
2538                                           &params, &data);
2539                 END_PROFILE_NESTED(Trans2_open);
2540                 break;
2541
2542         case TRANSACT2_FINDFIRST:
2543                 START_PROFILE_NESTED(Trans2_findfirst);
2544                 outsize = call_trans2findfirst(conn, inbuf, outbuf, 
2545                                                bufsize, &params, &data);
2546                 END_PROFILE_NESTED(Trans2_findfirst);
2547                 break;
2548
2549         case TRANSACT2_FINDNEXT:
2550                 START_PROFILE_NESTED(Trans2_findnext);
2551                 outsize = call_trans2findnext(conn, inbuf, outbuf, 
2552                                               length, bufsize, 
2553                                               &params, &data);
2554                 END_PROFILE_NESTED(Trans2_findnext);
2555                 break;
2556
2557         case TRANSACT2_QFSINFO:
2558                 START_PROFILE_NESTED(Trans2_qfsinfo);
2559             outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
2560                                          length, bufsize, &params, 
2561                                          &data);
2562                 END_PROFILE_NESTED(Trans2_qfsinfo);
2563             break;
2564
2565         case TRANSACT2_SETFSINFO:
2566                 START_PROFILE_NESTED(Trans2_setfsinfo);
2567                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
2568                                                length, bufsize, 
2569                                                &params, &data);
2570                 END_PROFILE_NESTED(Trans2_setfsinfo);
2571                 break;
2572
2573         case TRANSACT2_QPATHINFO:
2574         case TRANSACT2_QFILEINFO:
2575                 START_PROFILE_NESTED(Trans2_qpathinfo);
2576                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
2577                                                    length, bufsize, 
2578                                                    &params, &data, total_data);
2579                 END_PROFILE_NESTED(Trans2_qpathinfo);
2580                 break;
2581         case TRANSACT2_SETPATHINFO:
2582         case TRANSACT2_SETFILEINFO:
2583                 START_PROFILE_NESTED(Trans2_setpathinfo);
2584                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
2585                                                      length, bufsize, 
2586                                                      &params, &data, 
2587                                                      total_data);
2588                 END_PROFILE_NESTED(Trans2_setpathinfo);
2589                 break;
2590
2591         case TRANSACT2_FINDNOTIFYFIRST:
2592                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
2593                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
2594                                                      length, bufsize, 
2595                                                      &params, &data);
2596                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
2597                 break;
2598
2599         case TRANSACT2_FINDNOTIFYNEXT:
2600                 START_PROFILE_NESTED(Trans2_findnotifynext);
2601                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
2602                                                     length, bufsize, 
2603                                                     &params, &data);
2604                 END_PROFILE_NESTED(Trans2_findnotifynext);
2605                 break;
2606         case TRANSACT2_MKDIR:
2607                 START_PROFILE_NESTED(Trans2_mkdir);
2608                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
2609                                            bufsize, &params, &data);
2610                 END_PROFILE_NESTED(Trans2_mkdir);
2611                 break;
2612
2613         case TRANSACT2_GET_DFS_REFERRAL:
2614                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
2615         outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length,
2616                                             bufsize, &params, &data);
2617                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
2618                 break;
2619         case TRANSACT2_IOCTL:
2620                 START_PROFILE_NESTED(Trans2_ioctl);
2621                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length,
2622                                                 bufsize,&params,&data);
2623                 END_PROFILE_NESTED(Trans2_ioctl);
2624                 break;
2625         default:
2626                 /* Error in request */
2627                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
2628                 if(params)
2629                         free(params);
2630                 if(data)
2631                         free(data);
2632                 END_PROFILE(SMBtrans2);
2633                 return (ERROR(ERRSRV,ERRerror));
2634         }
2635         
2636         /* As we do not know how many data packets will need to be
2637            returned here the various call_trans2xxxx calls
2638            must send their own. Thus a call_trans2xxx routine only
2639            returns a value other than -1 when it wants to send
2640            an error packet. 
2641         */
2642         
2643         if(params)
2644                 free(params);
2645         if(data)
2646                 free(data);
2647         END_PROFILE(SMBtrans2);
2648         return outsize; /* If a correct response was needed the
2649                            call_trans2xxx calls have already sent
2650                            it. If outsize != -1 then it is returning */
2651 }