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