Use defined constants not integers.
[sfrench/samba-autobuild/.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                   (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1162             SIVAL(pdata,4,255); /* Max filename component length */
1163             len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_TERMINATE);
1164             SIVAL(pdata,8,len);
1165             data_len = 12 + len;
1166             break;
1167
1168     case SMB_QUERY_FS_LABEL_INFO:
1169             len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1170             data_len = 4 + len;
1171             SIVAL(pdata,0,len);
1172             break;
1173     case SMB_QUERY_FS_VOLUME_INFO:      
1174             /* 
1175              * Add volume serial number - hash of a combination of
1176              * the called hostname and the service name.
1177              */
1178             SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
1179                   (str_checksum(local_machine)<<16));
1180
1181             len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1182             SIVAL(pdata,12,len);
1183             data_len = 18+len;
1184             DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
1185                      (int)strlen(vname),vname, lp_servicename(snum)));
1186             break;
1187     case SMB_QUERY_FS_SIZE_INFO:
1188     {
1189       SMB_BIG_UINT dfree,dsize,bsize;
1190       data_len = 24;
1191       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);     
1192       SBIG_UINT(pdata,0,dsize);
1193       SBIG_UINT(pdata,8,dfree);
1194       SIVAL(pdata,16,bsize/512);
1195       SIVAL(pdata,20,512);
1196       break;
1197     }
1198     case SMB_QUERY_FS_DEVICE_INFO:
1199       data_len = 8;
1200       SIVAL(pdata,0,0); /* dev type */
1201       SIVAL(pdata,4,0); /* characteristics */
1202       break;
1203     case SMB_MAC_QUERY_FS_INFO:
1204             /*
1205              * Thursby MAC extension... ONLY on NTFS filesystems
1206              * once we do streams then we don't need this
1207              */
1208             if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1209                     data_len = 88;
1210                     SIVAL(pdata,84,0x100); /* Don't support mac... */
1211                     break;
1212             }
1213             /* drop through */
1214   default:
1215           return ERROR_DOS(ERRDOS,ERRunknownlevel);
1216   }
1217
1218
1219   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1220
1221   DEBUG( 4, ( "%s info_level = %d\n",
1222             smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1223
1224   return -1;
1225 }
1226
1227 /****************************************************************************
1228   reply to a TRANS2_SETFSINFO (set filesystem info)
1229 ****************************************************************************/
1230 static int call_trans2setfsinfo(connection_struct *conn,
1231                                 char *inbuf, char *outbuf, int length, 
1232                                 int bufsize,
1233                                 char **pparams, char **ppdata)
1234 {
1235   /* Just say yes we did it - there is nothing that
1236      can be set here so it doesn't matter. */
1237   int outsize;
1238   DEBUG(3,("call_trans2setfsinfo\n"));
1239
1240   if (!CAN_WRITE(conn))
1241     return ERROR_DOS(ERRSRV,ERRaccess);
1242
1243   outsize = set_message(outbuf,10,0,True);
1244
1245   return outsize;
1246 }
1247
1248 /****************************************************************************
1249   Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1250   file name or file id).
1251 ****************************************************************************/
1252
1253 static int call_trans2qfilepathinfo(connection_struct *conn,
1254                                     char *inbuf, char *outbuf, int length, 
1255                                     int bufsize,
1256                                     char **pparams,char **ppdata,
1257                                     int total_data)
1258 {
1259         int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1260         char *params = *pparams;
1261         char *pdata = *ppdata;
1262         uint16 tran_call = SVAL(inbuf, smb_setup0);
1263         uint16 info_level;
1264         int mode=0;
1265         SMB_OFF_T size=0;
1266         unsigned int data_size;
1267         SMB_STRUCT_STAT sbuf;
1268         pstring fname;
1269         char *base_name;
1270         char *p;
1271         SMB_OFF_T pos = 0;
1272         BOOL bad_path = False;
1273         BOOL delete_pending = False;
1274         int len;
1275         time_t c_time;
1276
1277         if (tran_call == TRANSACT2_QFILEINFO) {
1278                 files_struct *fsp = file_fsp(params,0);
1279                 info_level = SVAL(params,2);
1280
1281                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1282
1283                 if(fsp && (fsp->is_directory || fsp->stat_open)) {
1284                         /*
1285                          * This is actually a QFILEINFO on a directory
1286                          * handle (returned from an NT SMB). NT5.0 seems
1287                          * to do this call. JRA.
1288                          */
1289                         pstrcpy(fname, fsp->fsp_name);
1290                         unix_convert(fname,conn,0,&bad_path,&sbuf);
1291                         if (!check_name(fname,conn) || 
1292                                         (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1293                                 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1294                                 if((errno == ENOENT) && bad_path) {
1295                                         unix_ERR_class = ERRDOS;
1296                                         unix_ERR_code = ERRbadpath;
1297                                 }
1298                                 return(UNIXERROR(ERRDOS,ERRbadpath));
1299                         }
1300                   
1301                   delete_pending = fsp->directory_delete_on_close;
1302           } else {
1303                   /*
1304                    * Original code - this is an open file.
1305                    */
1306                   CHECK_FSP(fsp,conn);
1307
1308                   pstrcpy(fname, fsp->fsp_name);
1309                   if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1310                           DEBUG(3,("fstat of fnum %d failed (%s)\n",
1311                                    fsp->fnum, strerror(errno)));
1312                           return(UNIXERROR(ERRDOS,ERRbadfid));
1313                   }
1314                   if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1315                           return(UNIXERROR(ERRDOS,ERRnoaccess));
1316
1317                   delete_pending = fsp->delete_on_close;
1318           }
1319   } else {
1320           /* qpathinfo */
1321           info_level = SVAL(params,0);
1322
1323           DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", 
1324                    info_level));
1325
1326           srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1327
1328           RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1329
1330           unix_convert(fname,conn,0,&bad_path,&sbuf);
1331           if (!check_name(fname,conn) || 
1332               (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1333                   DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1334                   if((errno == ENOENT) && bad_path) {
1335                           unix_ERR_class = ERRDOS;
1336                           unix_ERR_code = ERRbadpath;
1337                   }
1338                   return(UNIXERROR(ERRDOS,ERRbadpath));
1339           }
1340   }
1341
1342
1343   DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1344            fname,info_level,tran_call,total_data));
1345
1346   p = strrchr_m(fname,'/'); 
1347   if (!p) {
1348           base_name = fname;
1349   } else {
1350           base_name = p+1;
1351   }
1352
1353   mode = dos_mode(conn,fname,&sbuf);
1354   size = sbuf.st_size;
1355   if (mode & aDIR) size = 0;
1356
1357   params = Realloc(*pparams,2);
1358   if (params == NULL) {
1359           return ERROR_DOS(ERRDOS,ERRnomem);
1360   }
1361   *pparams      = params;
1362   memset((char *)params,'\0',2);
1363   data_size = max_data_bytes + 1024;
1364   pdata = Realloc(*ppdata, data_size); 
1365   if ( pdata == NULL ) {
1366     return ERROR_DOS(ERRDOS,ERRnomem);
1367   }
1368   *ppdata = pdata;
1369
1370   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1371     /* uggh, EAs for OS2 */
1372     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1373     return ERROR_DOS(ERRDOS,ERReasnotsupported);
1374   }
1375
1376   memset((char *)pdata,'\0',data_size);
1377
1378   c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1379
1380   if (lp_dos_filetime_resolution(SNUM(conn))) {
1381     c_time &= ~1;
1382     sbuf.st_atime &= ~1;
1383     sbuf.st_mtime &= ~1;
1384     sbuf.st_mtime &= ~1;
1385   }
1386
1387   switch (info_level) 
1388     {
1389     case SMB_INFO_STANDARD:
1390     case SMB_INFO_QUERY_EA_SIZE:
1391       data_size = (info_level==1?22:26);
1392       put_dos_date2(pdata,l1_fdateCreation,c_time);
1393       put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1394       put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1395       SIVAL(pdata,l1_cbFile,(uint32)size);
1396       SIVAL(pdata,l1_cbFileAlloc,SMB_ROUNDUP(size,1024));
1397       SSVAL(pdata,l1_attrFile,mode);
1398       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1399       break;
1400
1401     case SMB_INFO_QUERY_EAS_FROM_LIST:
1402       data_size = 24;
1403       put_dos_date2(pdata,0,c_time);
1404       put_dos_date2(pdata,4,sbuf.st_atime);
1405       put_dos_date2(pdata,8,sbuf.st_mtime);
1406       SIVAL(pdata,12,(uint32)size);
1407       SIVAL(pdata,16,SMB_ROUNDUP(size,1024));
1408       SIVAL(pdata,20,mode);
1409       break;
1410
1411     case SMB_INFO_QUERY_ALL_EAS:
1412       data_size = 4;
1413       SIVAL(pdata,0,data_size);
1414       break;
1415
1416     case 6:
1417       return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */      
1418
1419     case SMB_FILE_BASIC_INFORMATION:
1420     case SMB_QUERY_FILE_BASIC_INFO:
1421
1422       if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1423               data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1424       else {
1425           data_size = 40;
1426           SIVAL(pdata,36,0);
1427       }
1428       put_long_date(pdata,c_time);
1429       put_long_date(pdata+8,sbuf.st_atime);
1430       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1431       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1432       SIVAL(pdata,32,mode);
1433
1434       DEBUG(5,("SMB_QFBI - "));
1435       {
1436         time_t create_time = c_time;
1437         DEBUG(5,("create: %s ", ctime(&create_time)));
1438       }
1439       DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1440       DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1441       DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1442       DEBUG(5,("mode: %x\n", mode));
1443
1444       break;
1445
1446         case SMB_FILE_STANDARD_INFORMATION:
1447         case SMB_QUERY_FILE_STANDARD_INFO:
1448                 data_size = 24;
1449                 /* Fake up allocation size. */
1450                 SOFF_T(pdata,0,SMB_ROUNDUP(size + 1, ((SMB_OFF_T)0x100000)));
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_FILE_EA_INFORMATION:
1458         case SMB_QUERY_FILE_EA_INFO:
1459                 data_size = 4;
1460                 break;
1461
1462     /* Get the 8.3 name - used if NT SMB was negotiated. */
1463     case SMB_QUERY_FILE_ALT_NAME_INFO:
1464       {
1465         pstring short_name;
1466
1467         pstrcpy(short_name,base_name);
1468         /* Mangle if not already 8.3 */
1469         if(!is_8_3(short_name, True))
1470         {
1471           if(!name_map_mangle(short_name,True,True,SNUM(conn)))
1472             *short_name = '\0';
1473         }
1474         len = srvstr_push(outbuf, pdata+4, short_name, -1, 
1475                           STR_TERMINATE|STR_UPPER);
1476         data_size = 4 + len;
1477         SIVAL(pdata,0,len);
1478       }
1479       break;
1480
1481     case SMB_QUERY_FILE_NAME_INFO:
1482             /*
1483              * The first part of this code is essential
1484              * to get security descriptors to work on mapped
1485              * drives. Don't ask how I discovered this unless
1486              * you like hearing about me suffering.... :-). JRA.
1487              */
1488             if(strequal(".", fname)) {
1489                     len = srvstr_push(outbuf, pdata+4, "\\", -1, STR_TERMINATE);
1490             } else {
1491                     len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE);
1492             }
1493             data_size = 4 + len;
1494             SIVAL(pdata,0,len);
1495             break;
1496
1497     case SMB_FILE_ALLOCATION_INFORMATION:
1498     case SMB_FILE_END_OF_FILE_INFORMATION:
1499     case SMB_QUERY_FILE_ALLOCATION_INFO:
1500     case SMB_QUERY_FILE_END_OF_FILEINFO:
1501             data_size = 8;
1502             SOFF_T(pdata,0,size);
1503             break;
1504
1505     case SMB_QUERY_FILE_ALL_INFO:
1506       put_long_date(pdata,c_time);
1507       put_long_date(pdata+8,sbuf.st_atime);
1508       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1509       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1510       SIVAL(pdata,32,mode);
1511       pdata += 40;
1512       SOFF_T(pdata,0,size);
1513       SOFF_T(pdata,8,size);
1514       SIVAL(pdata,16,sbuf.st_nlink);
1515       CVAL(pdata,20) = delete_pending;
1516       CVAL(pdata,21) = (mode&aDIR)?1:0;
1517       pdata += 24;
1518       SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); 
1519       pdata += 8; /* index number */
1520       pdata += 4; /* EA info */
1521       if (mode & aRONLY)
1522         SIVAL(pdata,0,0xA9);
1523       else
1524         SIVAL(pdata,0,0xd01BF);
1525       pdata += 4;
1526       SOFF_T(pdata,0,pos); /* current offset */
1527       pdata += 8;
1528       SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1529       pdata += 4;
1530       pdata += 4; /* alignment */
1531       len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE);
1532       SIVAL(pdata,0,len);
1533       pdata += 4 + len;
1534       data_size = PTR_DIFF(pdata,(*ppdata));
1535       break;
1536
1537         case SMB_FILE_INTERNAL_INFORMATION:
1538                 /* This should be an index number - looks like dev/ino to me :-) */
1539                 SIVAL(pdata,0,sbuf.st_dev);
1540                 SIVAL(pdata,4,sbuf.st_ino);
1541                 data_size = 8;
1542                 break;
1543
1544         case SMB_FILE_ACCESS_INFORMATION:
1545                 SIVAL(pdata,0,0x12019F); /* ??? */
1546                 data_size = 4;
1547                 break;
1548
1549         case SMB_FILE_NAME_INFORMATION:
1550                 /* Pathname with leading '\'. */
1551                 {
1552                         pstring new_fname;
1553                         size_t byte_len;
1554
1555                         pstrcpy(new_fname, "\\");
1556                         pstrcat(new_fname, fname);
1557                         byte_len = dos_PutUniCode(pdata+4,new_fname,max_data_bytes,False);
1558                         SIVAL(pdata,0,byte_len);
1559                         data_size = 4 + byte_len;
1560                         break;
1561                 }
1562
1563         case SMB_FILE_DISPOSITION_INFORMATION:
1564                 data_size = 1;
1565                 CVAL(pdata,0) = delete_pending;
1566                 break;
1567
1568         case SMB_FILE_POSITION_INFORMATION:
1569                 data_size = 8;
1570                 SOFF_T(pdata,0,pos);
1571                 break;
1572
1573         case SMB_FILE_MODE_INFORMATION:
1574                 SIVAL(pdata,0,mode);
1575                 data_size = 4;
1576                 break;
1577
1578         case SMB_FILE_ALIGNMENT_INFORMATION:
1579                 SIVAL(pdata,0,0); /* No alignment needed. */
1580                 data_size = 4;
1581                 break;
1582
1583 #if 0
1584         /* Not yet finished... JRA */
1585         case 1018:
1586                 {
1587                         pstring new_fname;
1588                         size_t byte_len;
1589
1590                         put_long_date(pdata,c_time);
1591                         put_long_date(pdata+8,sbuf.st_atime);
1592                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1593                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1594                         SIVAL(pdata,32,mode);
1595                         SIVAL(pdata,36,0); /* ??? */
1596                         SIVAL(pdata,40,0x20); /* ??? */
1597                         SIVAL(pdata,44,0); /* ??? */
1598                         SOFF_T(pdata,48,size);
1599                         SIVAL(pdata,56,0x1); /* ??? */
1600                         SIVAL(pdata,60,0); /* ??? */
1601                         SIVAL(pdata,64,0); /* ??? */
1602                         SIVAL(pdata,68,length); /* Following string length in bytes. */
1603                         dos_PutUniCode(pdata+72,,False);
1604                         break;
1605                 }
1606 #endif
1607
1608         case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1609                 /* Last component of pathname. */
1610                 {
1611                         size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1612                         SIVAL(pdata,0,byte_len);
1613                         data_size = 4 + byte_len;
1614                         break;
1615                 }
1616                 
1617         case SMB_FILE_STREAM_INFORMATION:
1618                 if (mode & aDIR) {
1619                         data_size = 0;
1620                 } else {
1621                         size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1622                         SIVAL(pdata,0,0); /* ??? */
1623                         SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1624                         SOFF_T(pdata,8,size);
1625                         SIVAL(pdata,16,0x20); /* ??? */
1626                         SIVAL(pdata,20,0); /* ??? */
1627                         data_size = 24 + byte_len;
1628                 }
1629                 break;
1630
1631         case SMB_FILE_COMPRESSION_INFORMATION:
1632                 SOFF_T(pdata,0,size);
1633                 SIVAL(pdata,8,0); /* ??? */
1634                 SIVAL(pdata,12,0); /* ??? */
1635                 data_size = 16;
1636                 break;
1637
1638         case SMB_FILE_NETWORK_OPEN_INFORMATION:
1639                 put_long_date(pdata,c_time);
1640                 put_long_date(pdata+8,sbuf.st_atime);
1641                 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1642                 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1643                 SIVAL(pdata,32,0x20); /* ??? */
1644                 SIVAL(pdata,36,0); /* ??? */
1645                 SOFF_T(pdata,40,size);
1646                 SIVAL(pdata,48,mode);
1647                 SIVAL(pdata,52,0); /* ??? */
1648                 data_size = 56;
1649                 break;
1650
1651         case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1652                 SIVAL(pdata,0,mode);
1653                 SIVAL(pdata,4,0);
1654                 data_size = 8;
1655                 break;
1656
1657         /*
1658          * End new completely undocumented info levels... JRA.
1659          */
1660
1661 #if 0
1662       /* NT4 server just returns "invalid query" to this - if we try to answer 
1663          it then NTws gets a BSOD! (tridge) */
1664     case SMB_QUERY_FILE_STREAM_INFO:
1665       SIVAL(pdata,0,pos);
1666       SIVAL(pdata,4,size);
1667       SIVAL(pdata,12,size);
1668       len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE);
1669       SIVAL(pdata,20,len);
1670       data_size = 24 + len;
1671       break;
1672 #endif
1673
1674     default:
1675       return ERROR_DOS(ERRDOS,ERRunknownlevel);
1676     }
1677
1678   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
1679
1680   return(-1);
1681 }
1682
1683 /****************************************************************************
1684   reply to a TRANS2_SETFILEINFO (set file info by fileid)
1685 ****************************************************************************/
1686 static int call_trans2setfilepathinfo(connection_struct *conn,
1687                                       char *inbuf, char *outbuf, int length, 
1688                                       int bufsize, char **pparams, 
1689                                       char **ppdata, int total_data)
1690 {
1691   char *params = *pparams;
1692   char *pdata = *ppdata;
1693   uint16 tran_call = SVAL(inbuf, smb_setup0);
1694   uint16 info_level;
1695   int mode=0;
1696   SMB_OFF_T size=0;
1697   struct utimbuf tvs;
1698   SMB_STRUCT_STAT sbuf;
1699   pstring fname;
1700   int fd = -1;
1701   BOOL bad_path = False;
1702   files_struct *fsp = NULL;
1703
1704   if (tran_call == TRANSACT2_SETFILEINFO) {
1705     fsp = file_fsp(params,0);
1706     info_level = SVAL(params,2);    
1707
1708     if(fsp && (fsp->is_directory || fsp->stat_open)) {
1709       /*
1710        * This is actually a SETFILEINFO on a directory
1711        * handle (returned from an NT SMB). NT5.0 seems
1712        * to do this call. JRA.
1713        */
1714       pstrcpy(fname, fsp->fsp_name);
1715       unix_convert(fname,conn,0,&bad_path,&sbuf);
1716       if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
1717         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1718         if((errno == ENOENT) && bad_path)
1719         {
1720           unix_ERR_class = ERRDOS;
1721           unix_ERR_code = ERRbadpath;
1722         }
1723         return(UNIXERROR(ERRDOS,ERRbadpath));
1724       }
1725     } else if (fsp && fsp->print_file) {
1726         /*
1727          * Doing a DELETE_ON_CLOSE should cancel a print job.
1728          */
1729         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
1730           fsp->share_mode = FILE_DELETE_ON_CLOSE;
1731
1732           DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n",
1733                fsp->fsp_name ));
1734
1735           SSVAL(params,0,0);
1736           send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1737           return(-1);
1738         }
1739     } else {
1740       /*
1741        * Original code - this is an open file.
1742        */
1743       CHECK_FSP(fsp,conn);
1744
1745       pstrcpy(fname, fsp->fsp_name);
1746       fd = fsp->fd;
1747
1748       if (vfs_fstat(fsp,fd,&sbuf) != 0) {
1749         DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1750         return(UNIXERROR(ERRDOS,ERRbadfid));
1751       }
1752     }
1753   } else {
1754     /* set path info */
1755     info_level = SVAL(params,0);    
1756     srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1757     unix_convert(fname,conn,0,&bad_path,&sbuf);
1758     if(!check_name(fname, conn))
1759     {
1760       if((errno == ENOENT) && bad_path)
1761       {
1762         unix_ERR_class = ERRDOS;
1763         unix_ERR_code = ERRbadpath;
1764       }
1765       return(UNIXERROR(ERRDOS,ERRbadpath));
1766     }
1767  
1768     if(!VALID_STAT(sbuf)) {
1769       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
1770       if((errno == ENOENT) && bad_path)
1771       {
1772         unix_ERR_class = ERRDOS;
1773         unix_ERR_code = ERRbadpath;
1774       }
1775       return(UNIXERROR(ERRDOS,ERRbadpath));
1776     }    
1777   }
1778
1779   if (!CAN_WRITE(conn))
1780     return ERROR_DOS(ERRSRV,ERRaccess);
1781
1782   DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1783            tran_call,fname,info_level,total_data));
1784
1785   /* Realloc the parameter and data sizes */
1786   params = Realloc(*pparams,2);
1787   if(params == NULL) {
1788     return ERROR_DOS(ERRDOS,ERRnomem);
1789   }
1790   *pparams      = params;
1791
1792   SSVAL(params,0,0);
1793
1794   size = sbuf.st_size;
1795   tvs.modtime = sbuf.st_mtime;
1796   tvs.actime = sbuf.st_atime;
1797   mode = dos_mode(conn,fname,&sbuf);
1798
1799   if (total_data > 4 && IVAL(pdata,0) == total_data) {
1800     /* uggh, EAs for OS2 */
1801     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1802     return ERROR_DOS(ERRDOS,ERReasnotsupported);
1803   }
1804
1805   switch (info_level)
1806   {
1807     case SMB_INFO_STANDARD:
1808     case SMB_INFO_QUERY_EA_SIZE:
1809     {
1810       /* access time */
1811       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1812
1813       /* write time */
1814       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1815
1816       mode = SVAL(pdata,l1_attrFile);
1817       size = IVAL(pdata,l1_cbFile);
1818       break;
1819     }
1820
1821     /* XXXX um, i don't think this is right.
1822        it's also not in the cifs6.txt spec.
1823      */
1824     case SMB_INFO_QUERY_EAS_FROM_LIST:
1825       tvs.actime = make_unix_date2(pdata+8);
1826       tvs.modtime = make_unix_date2(pdata+12);
1827       size = IVAL(pdata,16);
1828       mode = IVAL(pdata,24);
1829       break;
1830
1831     /* XXXX nor this.  not in cifs6.txt, either. */
1832     case SMB_INFO_QUERY_ALL_EAS:
1833       tvs.actime = make_unix_date2(pdata+8);
1834       tvs.modtime = make_unix_date2(pdata+12);
1835       size = IVAL(pdata,16);
1836       mode = IVAL(pdata,24);
1837       break;
1838
1839     case SMB_SET_FILE_BASIC_INFO:
1840         case SMB_FILE_BASIC_INFORMATION:
1841     {
1842       /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
1843       time_t write_time;
1844       time_t changed_time;
1845
1846       /* Ignore create time at offset pdata. */
1847
1848       /* access time */
1849       tvs.actime = interpret_long_date(pdata+8);
1850
1851       write_time = interpret_long_date(pdata+16);
1852       changed_time = interpret_long_date(pdata+24);
1853
1854       tvs.modtime = MIN(write_time, changed_time);
1855
1856       /* Prefer a defined time to an undefined one. */
1857       if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
1858        tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
1859                       ? changed_time
1860                       : write_time);
1861
1862       /* attributes */
1863       mode = IVAL(pdata,32);
1864       break;
1865     }
1866
1867         case 1019:
1868         case 1020:
1869     case SMB_SET_FILE_ALLOCATION_INFO:
1870     {
1871       int ret = -1;
1872       size = IVAL(pdata,0);
1873 #ifdef LARGE_SMB_OFF_T
1874       size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1875 #else /* LARGE_SMB_OFF_T */
1876       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1877          return ERROR_DOS(ERRDOS,ERRunknownlevel);
1878 #endif /* LARGE_SMB_OFF_T */
1879       DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
1880                            fname, (double)size ));
1881
1882       if(size != sbuf.st_size) {
1883  
1884         DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
1885             fname, (double)size ));
1886  
1887         if (fd == -1) {
1888           files_struct *new_fsp = NULL;
1889           int access_mode = 0;
1890           int action = 0;
1891  
1892           if(global_oplock_break) {
1893             /* Queue this file modify as we are the process of an oplock break.  */
1894  
1895             DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
1896             DEBUGADD(2,( "in oplock break state.\n"));
1897  
1898             push_oplock_pending_smb_message(inbuf, length);
1899             return -1;
1900           }
1901  
1902           new_fsp = open_file_shared(conn, fname, &sbuf,
1903                              SET_OPEN_MODE(DOS_OPEN_RDWR),
1904                              (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1905                              0, 0, &access_mode, &action);
1906  
1907           if (new_fsp == NULL)
1908             return(UNIXERROR(ERRDOS,ERRbadpath));
1909           ret = vfs_allocate_file_space(new_fsp, size);
1910           close_file(new_fsp,True);
1911         } else {
1912           ret = vfs_allocate_file_space(fsp, size);
1913         }
1914         if (ret == -1) return ERROR_NT(NT_STATUS_DISK_FULL);
1915
1916         sbuf.st_size = size;
1917       }
1918
1919       break;
1920     }
1921
1922     case SMB_SET_FILE_END_OF_FILE_INFO:
1923     {
1924       size = IVAL(pdata,0);
1925 #ifdef LARGE_SMB_OFF_T
1926       size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1927 #else /* LARGE_SMB_OFF_T */
1928       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1929          return ERROR_DOS(ERRDOS,ERRunknownlevel);
1930 #endif /* LARGE_SMB_OFF_T */
1931       DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
1932       break;
1933     }
1934
1935     case SMB_FILE_DISPOSITION_INFORMATION:
1936     case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
1937     {
1938                 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
1939
1940                 if (tran_call != TRANSACT2_SETFILEINFO)
1941                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1942
1943                 if (fsp == NULL)
1944                         return(UNIXERROR(ERRDOS,ERRbadfid));
1945
1946                 /*
1947                  * Only allow delete on close for files/directories opened with delete intent.
1948                  */
1949
1950                 if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) {
1951                         DEBUG(10,("call_trans2setfilepathinfo: file %s delete on close flag set but delete access denied.\n",
1952                                         fsp->fsp_name ));
1953                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1954                 }
1955
1956                 if(fsp->is_directory) {
1957                         fsp->directory_delete_on_close = delete_on_close;
1958                         DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, directory %s\n",
1959                                 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1960                 } else if(fsp->stat_open) {
1961
1962                         DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, stat open %s\n",
1963                                 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1964
1965                 } else {
1966
1967                         files_struct *iterate_fsp;
1968
1969                         /*
1970                          * Modify the share mode entry for all files open
1971                          * on this device and inode to tell other smbds we have 
1972                          * changed the delete on close flag. This will be noticed
1973                          * in the close code, the last closer will delete the file
1974                          * if flag is set.
1975                          */
1976
1977                         DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1978                                                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1979
1980                         if (lock_share_entry_fsp(fsp) == False)
1981                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1982
1983                         if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
1984                                 DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close flag for file %s\n",
1985                                                 fsp->fsp_name ));
1986                                 unlock_share_entry_fsp(fsp);
1987                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1988                         }
1989
1990                         /*
1991                          * Release the lock.
1992                          */
1993
1994                         unlock_share_entry_fsp(fsp);
1995
1996                         /*
1997                          * Go through all files we have open on the same device and
1998                          * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1999                          * Other smbd's that have this file open will look in the share_mode on close.
2000                          * take care of this (rare) case in close_file(). See the comment there.
2001                          * NB. JRA. We don't really need to do this anymore - all should be taken
2002                          * care of in the share_mode changes in the tdb.
2003                          */
2004
2005                         for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
2006                                         iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
2007                                                         fsp->delete_on_close = delete_on_close;
2008
2009                         /*
2010                          * Set the delete on close flag in the fsp.
2011                          */
2012                         fsp->delete_on_close = delete_on_close;
2013
2014                         DEBUG(10, ("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
2015                                 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2016
2017                 }
2018
2019                 break;
2020         }
2021
2022         default:
2023         {
2024                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2025         }
2026   }
2027
2028   /* get some defaults (no modifications) if any info is zero or -1. */
2029   if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2030     tvs.actime = sbuf.st_atime;
2031
2032   if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2033     tvs.modtime = sbuf.st_mtime;
2034
2035   DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2036   DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2037   DEBUG(6,("size: %.0f ", (double)size));
2038   DEBUG(6,("mode: %x\n"  , mode));
2039
2040   if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2041      (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2042      (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2043      (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2044     /*
2045      * Only do this test if we are not explicitly
2046      * changing the size of a file.
2047      */
2048     if (!size)
2049       size = sbuf.st_size;
2050   }
2051
2052   /* Try and set the times, size and mode of this file -
2053      if they are different from the current values
2054    */
2055   if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2056     if(fsp != NULL) {
2057       /*
2058        * This was a setfileinfo on an open file.
2059        * NT does this a lot. It's actually pointless
2060        * setting the time here, as it will be overwritten
2061        * on the next write, so we save the request
2062        * away and will set it on file code. JRA.
2063        */
2064
2065        if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2066          DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n",
2067             ctime(&tvs.modtime) ));
2068          fsp->pending_modtime = tvs.modtime;
2069        }
2070
2071     } else {
2072
2073       DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2074
2075       if(file_utime(conn, fname, &tvs)!=0)
2076         return(UNIXERROR(ERRDOS,ERRnoaccess));
2077     }
2078   }
2079
2080   /* check the mode isn't different, before changing it */
2081   if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) {
2082
2083     DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n",
2084           fname, mode ));
2085
2086     if(file_chmod(conn, fname, mode, NULL)) {
2087       DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2088       return(UNIXERROR(ERRDOS,ERRnoaccess));
2089     }
2090   }
2091
2092   if(size != sbuf.st_size) {
2093
2094     DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2095           fname, (double)size ));
2096
2097     if (fd == -1) {
2098       files_struct *new_fsp = NULL;
2099       int access_mode = 0;
2100       int action = 0;
2101
2102       if(global_oplock_break) {
2103         /* Queue this file modify as we are the process of an oplock break.  */
2104
2105         DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2106         DEBUGADD(2,( "in oplock break state.\n"));
2107
2108         push_oplock_pending_smb_message(inbuf, length);
2109         return -1;
2110       }
2111
2112       new_fsp = open_file_shared(conn, fname, &sbuf,
2113                            SET_OPEN_MODE(DOS_OPEN_RDWR),
2114                            (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2115                            0, 0, &access_mode, &action);
2116         
2117       if (new_fsp == NULL)
2118         return(UNIXERROR(ERRDOS,ERRbadpath));
2119       vfs_set_filelen(new_fsp, size);
2120       close_file(new_fsp,True);
2121     } else {
2122         vfs_set_filelen(fsp, size);
2123     }
2124   }
2125
2126   SSVAL(params,0,0);
2127
2128   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2129   
2130   return(-1);
2131 }
2132
2133 /****************************************************************************
2134   reply to a TRANS2_MKDIR (make directory with extended attributes).
2135 ****************************************************************************/
2136 static int call_trans2mkdir(connection_struct *conn,
2137                             char *inbuf, char *outbuf, int length, int bufsize,
2138                             char **pparams, char **ppdata)
2139 {
2140   char *params = *pparams;
2141   pstring directory;
2142   int ret = -1;
2143   SMB_STRUCT_STAT sbuf;
2144   BOOL bad_path = False;
2145
2146   if (!CAN_WRITE(conn))
2147     return ERROR_DOS(ERRSRV,ERRaccess);
2148
2149   srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
2150
2151   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2152
2153   unix_convert(directory,conn,0,&bad_path,&sbuf);
2154   if (check_name(directory,conn))
2155     ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2156   
2157   if(ret < 0)
2158     {
2159       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2160       if((errno == ENOENT) && bad_path)
2161       {
2162         unix_ERR_class = ERRDOS;
2163         unix_ERR_code = ERRbadpath;
2164       }
2165       return(UNIXERROR(ERRDOS,ERRnoaccess));
2166     }
2167
2168   /* Realloc the parameter and data sizes */
2169   params = Realloc(*pparams,2);
2170   if(params == NULL) {
2171     return ERROR_DOS(ERRDOS,ERRnomem);
2172   }
2173   *pparams      = params;
2174
2175   SSVAL(params,0,0);
2176
2177   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2178   
2179   return(-1);
2180 }
2181
2182 /****************************************************************************
2183   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
2184   We don't actually do this - we just send a null response.
2185 ****************************************************************************/
2186 static int call_trans2findnotifyfirst(connection_struct *conn,
2187                                       char *inbuf, char *outbuf, 
2188                                       int length, int bufsize,
2189                                       char **pparams, char **ppdata)
2190 {
2191   static uint16 fnf_handle = 257;
2192   char *params = *pparams;
2193   uint16 info_level = SVAL(params,4);
2194
2195   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2196
2197   switch (info_level) 
2198     {
2199     case 1:
2200     case 2:
2201       break;
2202     default:
2203       return ERROR_DOS(ERRDOS,ERRunknownlevel);
2204     }
2205
2206   /* Realloc the parameter and data sizes */
2207   params = Realloc(*pparams,6);
2208   if(params == NULL) {
2209     return ERROR_DOS(ERRDOS,ERRnomem);
2210   }
2211   *pparams      = params;
2212
2213   SSVAL(params,0,fnf_handle);
2214   SSVAL(params,2,0); /* No changes */
2215   SSVAL(params,4,0); /* No EA errors */
2216
2217   fnf_handle++;
2218
2219   if(fnf_handle == 0)
2220     fnf_handle = 257;
2221
2222   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2223   
2224   return(-1);
2225 }
2226
2227 /****************************************************************************
2228   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
2229   changes). Currently this does nothing.
2230 ****************************************************************************/
2231 static int call_trans2findnotifynext(connection_struct *conn,
2232                                      char *inbuf, char *outbuf, 
2233                                      int length, int bufsize,
2234                                      char **pparams, char **ppdata)
2235 {
2236   char *params = *pparams;
2237
2238   DEBUG(3,("call_trans2findnotifynext\n"));
2239
2240   /* Realloc the parameter and data sizes */
2241   params = Realloc(*pparams,4);
2242   if(params == NULL) {
2243     return ERROR_DOS(ERRDOS,ERRnomem);
2244   }
2245   *pparams      = params;
2246
2247   SSVAL(params,0,0); /* No changes */
2248   SSVAL(params,2,0); /* No EA errors */
2249
2250   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2251   
2252   return(-1);
2253 }
2254
2255 /****************************************************************************
2256   reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>
2257 ****************************************************************************/
2258 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2259                                      char* outbuf, int length, int bufsize,
2260                                      char** pparams, char** ppdata)
2261 {
2262   char *params = *pparams;
2263   pstring pathname;
2264   int reply_size = 0;
2265   int max_referral_level = SVAL(params,0);
2266
2267
2268   DEBUG(10,("call_trans2getdfsreferral\n"));
2269
2270   if(!lp_host_msdfs())
2271     return ERROR_DOS(ERRDOS,ERRbadfunc);
2272
2273   srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
2274
2275   if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2276     return ERROR_DOS(ERRDOS,ERRbadfile);
2277     
2278   SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2279   send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2280
2281   return(-1);
2282 }
2283
2284 #define LMCAT_SPL       0x53
2285 #define LMFUNC_GETJOBID 0x60
2286
2287 /****************************************************************************
2288   reply to a TRANS2_IOCTL - used for OS/2 printing.
2289 ****************************************************************************/
2290
2291 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2292                             char* outbuf, int length, int bufsize,
2293                             char** pparams, char** ppdata)
2294 {
2295   char *pdata = *ppdata;
2296   files_struct *fsp = file_fsp(inbuf,smb_vwv15);
2297
2298   if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2299       (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2300     pdata = Realloc(*ppdata, 32);
2301     if(pdata == NULL) {
2302       return ERROR_DOS(ERRDOS,ERRnomem);
2303     }
2304     *ppdata = pdata;
2305
2306         /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
2307            CAN ACCEPT THIS IN UNICODE. JRA. */
2308
2309     SSVAL(pdata,0,fsp->print_jobid);                     /* Job number */
2310         srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
2311     srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
2312     send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
2313     return(-1);
2314   } else {
2315     DEBUG(2,("Unknown TRANS2_IOCTL\n"));
2316     return ERROR_DOS(ERRSRV,ERRerror);
2317   }
2318 }
2319
2320 /****************************************************************************
2321   reply to a SMBfindclose (stop trans2 directory search)
2322 ****************************************************************************/
2323 int reply_findclose(connection_struct *conn,
2324                     char *inbuf,char *outbuf,int length,int bufsize)
2325 {
2326         int outsize = 0;
2327         int dptr_num=SVALS(inbuf,smb_vwv0);
2328         START_PROFILE(SMBfindclose);
2329
2330         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
2331
2332         dptr_close(&dptr_num);
2333
2334         outsize = set_message(outbuf,0,0,True);
2335
2336         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
2337
2338         END_PROFILE(SMBfindclose);
2339         return(outsize);
2340 }
2341
2342 /****************************************************************************
2343   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
2344 ****************************************************************************/
2345 int reply_findnclose(connection_struct *conn, 
2346                      char *inbuf,char *outbuf,int length,int bufsize)
2347 {
2348         int outsize = 0;
2349         int dptr_num= -1;
2350         START_PROFILE(SMBfindnclose);
2351         
2352         dptr_num = SVAL(inbuf,smb_vwv0);
2353
2354         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2355
2356         /* We never give out valid handles for a 
2357            findnotifyfirst - so any dptr_num is ok here. 
2358            Just ignore it. */
2359
2360         outsize = set_message(outbuf,0,0,True);
2361
2362         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2363
2364         END_PROFILE(SMBfindnclose);
2365         return(outsize);
2366 }
2367
2368
2369 /****************************************************************************
2370   reply to a SMBtranss2 - just ignore it!
2371 ****************************************************************************/
2372 int reply_transs2(connection_struct *conn,
2373                   char *inbuf,char *outbuf,int length,int bufsize)
2374 {
2375         START_PROFILE(SMBtranss2);
2376         DEBUG(4,("Ignoring transs2 of length %d\n",length));
2377         END_PROFILE(SMBtranss2);
2378         return(-1);
2379 }
2380
2381 /****************************************************************************
2382   reply to a SMBtrans2
2383 ****************************************************************************/
2384 int reply_trans2(connection_struct *conn,
2385                  char *inbuf,char *outbuf,int length,int bufsize)
2386 {
2387         int outsize = 0;
2388         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2389         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2390 #if 0
2391         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2392         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2393         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2394         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2395         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2396         int32 timeout = IVALS(inbuf,smb_timeout);
2397 #endif
2398         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2399         unsigned int tran_call = SVAL(inbuf, smb_setup0);
2400         char *params = NULL, *data = NULL;
2401         int num_params, num_params_sofar, num_data, num_data_sofar;
2402         START_PROFILE(SMBtrans2);
2403
2404         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2405                 /* Queue this open message as we are the process of an
2406                  * oplock break.  */
2407
2408                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2409                 DEBUGADD(2,( "in oplock break state.\n"));
2410
2411                 push_oplock_pending_smb_message(inbuf, length);
2412                 END_PROFILE(SMBtrans2);
2413                 return -1;
2414         }
2415         
2416         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
2417             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
2418                 END_PROFILE(SMBtrans2);
2419                 return ERROR_DOS(ERRSRV,ERRaccess);
2420         }
2421
2422         outsize = set_message(outbuf,0,0,True);
2423
2424         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2425            is so as a sanity check */
2426         if (suwcnt != 1) {
2427                 /*
2428                  * Need to have rc=0 for ioctl to get job id for OS/2.
2429                  *  Network printing will fail if function is not successful.
2430                  *  Similar function in reply.c will be used if protocol
2431                  *  is LANMAN1.0 instead of LM1.2X002.
2432                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
2433                  *  outbuf doesn't have to be set(only job id is used).
2434                  */
2435                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
2436                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2437                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2438                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
2439                 } else {
2440                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
2441                         DEBUG(2,("Transaction is %d\n",tran_call));
2442                         END_PROFILE(SMBtrans2);
2443                         return ERROR_DOS(ERRSRV,ERRerror);
2444                 }
2445         }
2446     
2447         /* Allocate the space for the maximum needed parameters and data */
2448         if (total_params > 0)
2449                 params = (char *)malloc(total_params);
2450         if (total_data > 0)
2451                 data = (char *)malloc(total_data);
2452   
2453         if ((total_params && !params)  || (total_data && !data)) {
2454                 DEBUG(2,("Out of memory in reply_trans2\n"));
2455                 SAFE_FREE(params);
2456                 SAFE_FREE(data); 
2457                 END_PROFILE(SMBtrans2);
2458                 return ERROR_DOS(ERRDOS,ERRnomem);
2459         }
2460
2461         /* Copy the param and data bytes sent with this request into
2462            the params buffer */
2463         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2464         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2465
2466         if (num_params > total_params || num_data > total_data)
2467                 exit_server("invalid params in reply_trans2");
2468
2469         if(params)
2470                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2471         if(data)
2472                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2473
2474         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
2475                 /* We need to send an interim response then receive the rest
2476                    of the parameter/data bytes */
2477                 outsize = set_message(outbuf,0,0,True);
2478                 if (!send_smb(smbd_server_fd(),outbuf))
2479                         exit_server("reply_trans2: send_smb failed.");
2480
2481                 while (num_data_sofar < total_data || 
2482                        num_params_sofar < total_params) {
2483                         BOOL ret;
2484
2485                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2486                         
2487                         if ((ret && 
2488                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2489                                 outsize = set_message(outbuf,0,0,True);
2490                                 if(ret)
2491                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2492                                 else
2493                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2494                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2495                                 SAFE_FREE(params);
2496                                 SAFE_FREE(data);
2497                                 END_PROFILE(SMBtrans2);
2498                                 return ERROR_DOS(ERRSRV,ERRerror);
2499                         }
2500       
2501                         /* Revise total_params and total_data in case
2502                            they have changed downwards */
2503                         total_params = SVAL(inbuf, smb_tpscnt);
2504                         total_data = SVAL(inbuf, smb_tdscnt);
2505                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2506                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2507                         if (num_params_sofar > total_params || num_data_sofar > total_data)
2508                                 exit_server("data overflow in trans2");
2509                         
2510                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
2511                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2512                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2513                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2514                 }
2515         }
2516         
2517         if (Protocol >= PROTOCOL_NT1) {
2518                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
2519         }
2520
2521         /* Now we must call the relevant TRANS2 function */
2522         switch(tran_call)  {
2523         case TRANSACT2_OPEN:
2524                 START_PROFILE_NESTED(Trans2_open);
2525                 outsize = call_trans2open(conn, 
2526                                           inbuf, outbuf, bufsize, 
2527                                           &params, &data);
2528                 END_PROFILE_NESTED(Trans2_open);
2529                 break;
2530
2531         case TRANSACT2_FINDFIRST:
2532                 START_PROFILE_NESTED(Trans2_findfirst);
2533                 outsize = call_trans2findfirst(conn, inbuf, outbuf, 
2534                                                bufsize, &params, &data);
2535                 END_PROFILE_NESTED(Trans2_findfirst);
2536                 break;
2537
2538         case TRANSACT2_FINDNEXT:
2539                 START_PROFILE_NESTED(Trans2_findnext);
2540                 outsize = call_trans2findnext(conn, inbuf, outbuf, 
2541                                               length, bufsize, 
2542                                               &params, &data);
2543                 END_PROFILE_NESTED(Trans2_findnext);
2544                 break;
2545
2546         case TRANSACT2_QFSINFO:
2547                 START_PROFILE_NESTED(Trans2_qfsinfo);
2548             outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
2549                                          length, bufsize, &params, 
2550                                          &data);
2551                 END_PROFILE_NESTED(Trans2_qfsinfo);
2552             break;
2553
2554         case TRANSACT2_SETFSINFO:
2555                 START_PROFILE_NESTED(Trans2_setfsinfo);
2556                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
2557                                                length, bufsize, 
2558                                                &params, &data);
2559                 END_PROFILE_NESTED(Trans2_setfsinfo);
2560                 break;
2561
2562         case TRANSACT2_QPATHINFO:
2563         case TRANSACT2_QFILEINFO:
2564                 START_PROFILE_NESTED(Trans2_qpathinfo);
2565                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
2566                                                    length, bufsize, 
2567                                                    &params, &data, total_data);
2568                 END_PROFILE_NESTED(Trans2_qpathinfo);
2569                 break;
2570         case TRANSACT2_SETPATHINFO:
2571         case TRANSACT2_SETFILEINFO:
2572                 START_PROFILE_NESTED(Trans2_setpathinfo);
2573                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
2574                                                      length, bufsize, 
2575                                                      &params, &data, 
2576                                                      total_data);
2577                 END_PROFILE_NESTED(Trans2_setpathinfo);
2578                 break;
2579
2580         case TRANSACT2_FINDNOTIFYFIRST:
2581                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
2582                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
2583                                                      length, bufsize, 
2584                                                      &params, &data);
2585                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
2586                 break;
2587
2588         case TRANSACT2_FINDNOTIFYNEXT:
2589                 START_PROFILE_NESTED(Trans2_findnotifynext);
2590                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
2591                                                     length, bufsize, 
2592                                                     &params, &data);
2593                 END_PROFILE_NESTED(Trans2_findnotifynext);
2594                 break;
2595         case TRANSACT2_MKDIR:
2596                 START_PROFILE_NESTED(Trans2_mkdir);
2597                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
2598                                            bufsize, &params, &data);
2599                 END_PROFILE_NESTED(Trans2_mkdir);
2600                 break;
2601
2602         case TRANSACT2_GET_DFS_REFERRAL:
2603                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
2604         outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length,
2605                                             bufsize, &params, &data);
2606                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
2607                 break;
2608         case TRANSACT2_IOCTL:
2609                 START_PROFILE_NESTED(Trans2_ioctl);
2610                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length,
2611                                                 bufsize,&params,&data);
2612                 END_PROFILE_NESTED(Trans2_ioctl);
2613                 break;
2614         default:
2615                 /* Error in request */
2616                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
2617                 SAFE_FREE(params);
2618                 SAFE_FREE(data);
2619                 END_PROFILE(SMBtrans2);
2620                 return ERROR_DOS(ERRSRV,ERRerror);
2621         }
2622         
2623         /* As we do not know how many data packets will need to be
2624            returned here the various call_trans2xxxx calls
2625            must send their own. Thus a call_trans2xxx routine only
2626            returns a value other than -1 when it wants to send
2627            an error packet. 
2628         */
2629         
2630         SAFE_FREE(params);
2631         SAFE_FREE(data);
2632         END_PROFILE(SMBtrans2);
2633         return outsize; /* If a correct response was needed the
2634                            call_trans2xxx calls have already sent
2635                            it. If outsize != -1 then it is returning */
2636 }