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