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