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