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