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