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