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