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