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