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