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