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