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