Fixed debug reporting in the changed code.
[samba.git] / source3 / smbd / trans2.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB transaction2 handling
5    Copyright (C) Jeremy Allison 1994-1998
6
7    Extensively modified by Andrew Tridgell, 1995
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "trans2.h"
26
27 extern int DEBUGLEVEL;
28 extern int Protocol;
29 extern BOOL case_sensitive;
30 extern int Client;
31 extern int smb_read_error;
32 extern fstring local_machine;
33 extern int global_oplock_break;
34
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 (sys_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 (dos_stat(pathreal,&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,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,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,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,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(dos_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       sys_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       PutUniCode(pdata+12,fstype);
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               PutUniCode(pdata+18,vname);      
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       sys_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
1244   if (tran_call == TRANSACT2_QFILEINFO) {
1245     files_struct *fsp = file_fsp(params,0);
1246     info_level = SVAL(params,2);
1247
1248     if(fsp && fsp->open && fsp->is_directory) {
1249       /*
1250        * This is actually a QFILEINFO on a directory
1251        * handle (returned from an NT SMB). NT5.0 seems
1252        * to do this call. JRA.
1253        */
1254       fname = fsp->fsp_name;
1255       unix_convert(fname,conn,0,&bad_path,&sbuf);
1256       if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) {
1257         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1258         if((errno == ENOENT) && bad_path)
1259         {
1260           unix_ERR_class = ERRDOS;
1261           unix_ERR_code = ERRbadpath;
1262         }
1263         return(UNIXERROR(ERRDOS,ERRbadpath));
1264       }
1265     } else {
1266       /*
1267        * Original code - this is an open file.
1268        */
1269       CHECK_FSP(fsp,conn);
1270       CHECK_ERROR(fsp);
1271
1272       fname = fsp->fsp_name;
1273       if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
1274         DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1275         return(UNIXERROR(ERRDOS,ERRbadfid));
1276       }
1277       if((pos = sys_lseek(fsp->fd_ptr->fd,0,SEEK_CUR)) == -1)
1278         return(UNIXERROR(ERRDOS,ERRnoaccess));
1279     }
1280   } else {
1281     /* qpathinfo */
1282     info_level = SVAL(params,0);
1283     fname = &fname1[0];
1284     pstrcpy(fname,&params[6]);
1285     unix_convert(fname,conn,0,&bad_path,&sbuf);
1286     if (!check_name(fname,conn) || (!VALID_STAT(sbuf) && dos_stat(fname,&sbuf))) {
1287       DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1288       if((errno == ENOENT) && bad_path)
1289       {
1290         unix_ERR_class = ERRDOS;
1291         unix_ERR_code = ERRbadpath;
1292       }
1293       return(UNIXERROR(ERRDOS,ERRbadpath));
1294     }
1295   }
1296
1297
1298   DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1299            fname,info_level,tran_call,total_data));
1300
1301   p = strrchr(fname,'/'); 
1302   if (!p) 
1303     p = fname;
1304   else
1305     p++;
1306   l = strlen(p);  
1307   mode = dos_mode(conn,fname,&sbuf);
1308   size = sbuf.st_size;
1309   if (mode & aDIR) size = 0;
1310
1311   /* from now on we only want the part after the / */
1312   fname = p;
1313   
1314   params = *pparams = Realloc(*pparams,2); bzero(params,2);
1315   data_size = 1024;
1316   pdata = *ppdata = Realloc(*ppdata, data_size); 
1317
1318   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1319     /* uggh, EAs for OS2 */
1320     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1321     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1322   }
1323
1324   bzero(pdata,data_size);
1325
1326   switch (info_level) 
1327     {
1328     case SMB_INFO_STANDARD:
1329     case SMB_INFO_QUERY_EA_SIZE:
1330       data_size = (info_level==1?22:26);
1331       put_dos_date2(pdata,l1_fdateCreation,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1332       put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1333       put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1334       SIVAL(pdata,l1_cbFile,(uint32)size);
1335       SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
1336       SSVAL(pdata,l1_attrFile,mode);
1337       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1338       break;
1339
1340     case SMB_INFO_QUERY_EAS_FROM_LIST:
1341       data_size = 24;
1342       put_dos_date2(pdata,0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1343       put_dos_date2(pdata,4,sbuf.st_atime);
1344       put_dos_date2(pdata,8,sbuf.st_mtime);
1345       SIVAL(pdata,12,(uint32)size);
1346       SIVAL(pdata,16,ROUNDUP(size,1024));
1347       SIVAL(pdata,20,mode);
1348       break;
1349
1350     case SMB_INFO_QUERY_ALL_EAS:
1351       data_size = 4;
1352       SIVAL(pdata,0,data_size);
1353       break;
1354
1355     case 6:
1356       return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */      
1357
1358     case SMB_QUERY_FILE_BASIC_INFO:
1359       data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1360       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1361       put_long_date(pdata+8,sbuf.st_atime);
1362       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1363       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1364       SIVAL(pdata,32,mode);
1365
1366       DEBUG(5,("SMB_QFBI - "));
1367       {
1368         time_t create_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1369         DEBUG(5,("create: %s ", ctime(&create_time)));
1370       }
1371       DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1372       DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1373       DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1374       DEBUG(5,("mode: %x\n", mode));
1375
1376       break;
1377
1378     case SMB_QUERY_FILE_STANDARD_INFO:
1379       data_size = 22;
1380       SOFF_T(pdata,0,size);
1381       SOFF_T(pdata,8,size);
1382       SIVAL(pdata,16,sbuf.st_nlink);
1383       CVAL(pdata,20) = 0;
1384       CVAL(pdata,21) = (mode&aDIR)?1:0;
1385       break;
1386
1387     case SMB_QUERY_FILE_EA_INFO:
1388       data_size = 4;
1389       break;
1390
1391     /* Get the 8.3 name - used if NT SMB was negotiated. */
1392     case SMB_QUERY_FILE_ALT_NAME_INFO:
1393       {
1394         pstring short_name;
1395         pstrcpy(short_name,p);
1396         /* Mangle if not already 8.3 */
1397         if(!is_8_3(short_name, True))
1398         {
1399           if(!name_map_mangle(short_name,True,SNUM(conn)))
1400             *short_name = '\0';
1401         }
1402         strupper(short_name);
1403         l = strlen(short_name);
1404         PutUniCode(pdata + 4, short_name);
1405         data_size = 4 + (2*l);
1406         SIVAL(pdata,0,2*l);
1407       }
1408       break;
1409
1410     case SMB_QUERY_FILE_NAME_INFO:
1411       data_size = 4 + l;
1412       SIVAL(pdata,0,l);
1413       pstrcpy(pdata+4,fname);
1414       break;
1415
1416     case SMB_QUERY_FILE_ALLOCATION_INFO:
1417     case SMB_QUERY_FILE_END_OF_FILEINFO:
1418       data_size = 8;
1419       SOFF_T(pdata,0,size);
1420       break;
1421
1422     case SMB_QUERY_FILE_ALL_INFO:
1423       put_long_date(pdata,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
1424       put_long_date(pdata+8,sbuf.st_atime);
1425       put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1426       put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1427       SIVAL(pdata,32,mode);
1428       pdata += 40;
1429       SOFF_T(pdata,0,size);
1430       SOFF_T(pdata,8,size);
1431       SIVAL(pdata,16,sbuf.st_nlink);
1432       CVAL(pdata,20) = 0;
1433       CVAL(pdata,21) = (mode&aDIR)?1:0;
1434       pdata += 24;
1435       pdata += 8; /* index number */
1436       pdata += 4; /* EA info */
1437       if (mode & aRONLY)
1438         SIVAL(pdata,0,0xA9);
1439       else
1440         SIVAL(pdata,0,0xd01BF);
1441       pdata += 4;
1442       SIVAL(pdata,0,pos); /* current offset */
1443       pdata += 8;
1444       SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1445       pdata += 4;
1446       pdata += 4; /* alignment */
1447       SIVAL(pdata,0,l);
1448       pstrcpy(pdata+4,fname);
1449       pdata += 4 + l;
1450       data_size = PTR_DIFF(pdata,(*ppdata));
1451       break;
1452
1453 #if 0
1454       /* NT4 server just returns "invalid query" to this - if we try to answer 
1455          it then NTws gets a BSOD! (tridge) */
1456     case SMB_QUERY_FILE_STREAM_INFO:
1457       data_size = 24 + l;
1458       SIVAL(pdata,0,pos);
1459       SIVAL(pdata,4,size);
1460       SIVAL(pdata,12,size);
1461       SIVAL(pdata,20,l);        
1462       pstrcpy(pdata+24,fname);
1463       break;
1464 #endif
1465
1466     default:
1467       return(ERROR(ERRDOS,ERRunknownlevel));
1468     }
1469
1470   send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
1471
1472   return(-1);
1473 }
1474
1475 /****************************************************************************
1476   reply to a TRANS2_SETFILEINFO (set file info by fileid)
1477 ****************************************************************************/
1478 static int call_trans2setfilepathinfo(connection_struct *conn,
1479                                       char *inbuf, char *outbuf, int length, 
1480                                       int bufsize, char **pparams, 
1481                                       char **ppdata, int total_data)
1482 {
1483   char *params = *pparams;
1484   char *pdata = *ppdata;
1485   uint16 tran_call = SVAL(inbuf, smb_setup0);
1486   uint16 info_level;
1487   int mode=0;
1488   SMB_OFF_T size=0;
1489   struct utimbuf tvs;
1490   SMB_STRUCT_STAT st;
1491   pstring fname1;
1492   char *fname;
1493   int fd = -1;
1494   BOOL bad_path = False;
1495
1496   if (!CAN_WRITE(conn))
1497     return(ERROR(ERRSRV,ERRaccess));
1498
1499   if (tran_call == TRANSACT2_SETFILEINFO) {
1500     files_struct *fsp = file_fsp(params,0);
1501     info_level = SVAL(params,2);    
1502
1503     if(fsp && fsp->open && fsp->is_directory) {
1504       /*
1505        * This is actually a SETFILEINFO on a directory
1506        * handle (returned from an NT SMB). NT5.0 seems
1507        * to do this call. JRA.
1508        */
1509       fname = fsp->fsp_name;
1510       unix_convert(fname,conn,0,&bad_path,&st);
1511       if (!check_name(fname,conn) || (!VALID_STAT(st) && dos_stat(fname,&st))) {
1512         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1513         if((errno == ENOENT) && bad_path)
1514         {
1515           unix_ERR_class = ERRDOS;
1516           unix_ERR_code = ERRbadpath;
1517         }
1518         return(UNIXERROR(ERRDOS,ERRbadpath));
1519       }
1520     } else {
1521       /*
1522        * Original code - this is an open file.
1523        */
1524       CHECK_FSP(fsp,conn);
1525       CHECK_ERROR(fsp);
1526
1527       fname = fsp->fsp_name;
1528       fd = fsp->fd_ptr->fd;
1529
1530       if (sys_fstat(fd,&st) != 0) {
1531         DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1532         return(UNIXERROR(ERRDOS,ERRbadfid));
1533       }
1534     }
1535   } else {
1536     /* set path info */
1537     info_level = SVAL(params,0);    
1538     fname = fname1;
1539     pstrcpy(fname,&params[6]);
1540     unix_convert(fname,conn,0,&bad_path,&st);
1541     if(!check_name(fname, conn))
1542     {
1543       if((errno == ENOENT) && bad_path)
1544       {
1545         unix_ERR_class = ERRDOS;
1546         unix_ERR_code = ERRbadpath;
1547       }
1548       return(UNIXERROR(ERRDOS,ERRbadpath));
1549     }
1550  
1551     if(!VALID_STAT(st) && dos_stat(fname,&st)!=0) {
1552       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
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
1562   DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
1563            tran_call,fname,info_level,total_data));
1564
1565   /* Realloc the parameter and data sizes */
1566   params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0);
1567   if(params == NULL)
1568     return(ERROR(ERRDOS,ERRnomem));
1569
1570   size = st.st_size;
1571   tvs.modtime = st.st_mtime;
1572   tvs.actime = st.st_atime;
1573   mode = dos_mode(conn,fname,&st);
1574
1575   if (total_data > 0 && IVAL(pdata,0) == total_data) {
1576     /* uggh, EAs for OS2 */
1577     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1578     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
1579   }
1580
1581   switch (info_level)
1582   {
1583     case SMB_INFO_STANDARD:
1584     case SMB_INFO_QUERY_EA_SIZE:
1585     {
1586       /* access time */
1587       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
1588
1589       /* write time */
1590       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
1591
1592       mode = SVAL(pdata,l1_attrFile);
1593       size = IVAL(pdata,l1_cbFile);
1594       break;
1595     }
1596
1597     /* XXXX um, i don't think this is right.
1598        it's also not in the cifs6.txt spec.
1599      */
1600     case SMB_INFO_QUERY_EAS_FROM_LIST:
1601       tvs.actime = make_unix_date2(pdata+8);
1602       tvs.modtime = make_unix_date2(pdata+12);
1603       size = IVAL(pdata,16);
1604       mode = IVAL(pdata,24);
1605       break;
1606
1607     /* XXXX nor this.  not in cifs6.txt, either. */
1608     case SMB_INFO_QUERY_ALL_EAS:
1609       tvs.actime = make_unix_date2(pdata+8);
1610       tvs.modtime = make_unix_date2(pdata+12);
1611       size = IVAL(pdata,16);
1612       mode = IVAL(pdata,24);
1613       break;
1614
1615     case SMB_SET_FILE_BASIC_INFO:
1616     {
1617       /* Ignore create time at offset pdata. */
1618
1619       /* access time */
1620       tvs.actime = interpret_long_date(pdata+8);
1621
1622       /* write time + changed time, combined. */
1623       tvs.modtime=MAX(interpret_long_date(pdata+16),
1624                       interpret_long_date(pdata+24));
1625
1626 #if 0 /* Needs more testing... */
1627       /* Test from Luke to prevent Win95 from
1628          setting incorrect values here.
1629        */
1630       if (tvs.actime < tvs.modtime)
1631         return(ERROR(ERRDOS,ERRnoaccess));
1632 #endif /* Needs more testing... */
1633
1634       /* attributes */
1635       mode = IVAL(pdata,32);
1636       break;
1637     }
1638
1639     case SMB_SET_FILE_END_OF_FILE_INFO:
1640     {
1641       size = IVAL(pdata,0);
1642 #ifdef LARGE_SMB_OFF_T
1643       size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
1644 #else /* LARGE_SMB_OFF_T */
1645       if (IVAL(pdata,4) != 0)   /* more than 32 bits? */
1646          return(ERROR(ERRDOS,ERRunknownlevel));
1647 #endif /* LARGE_SMB_OFF_T */
1648       break;
1649     }
1650
1651     case SMB_SET_FILE_ALLOCATION_INFO:
1652       break; /* We don't need to do anything for this call. */
1653
1654     case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
1655     {
1656       if (tran_call == TRANSACT2_SETFILEINFO) {
1657         files_struct *fsp = file_fsp(params,0);
1658         BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
1659
1660         if(fsp->is_directory)
1661           return(ERROR(ERRDOS,ERRnoaccess));
1662
1663         /*
1664          * We can only set the delete on close flag if
1665          * the share mode contained ALLOW_SHARE_DELETE
1666          */
1667
1668         if(!GET_ALLOW_SHARE_DELETE(fsp->share_mode))
1669           return(ERROR(ERRDOS,ERRnoaccess));
1670
1671         /*
1672          * If the flag has changed from its previous value then
1673          * modify the share mode entry for all files we have open
1674          * on this device and inode to tell other smbds we have 
1675          * changed the delete on close flag.
1676          */
1677
1678         if(GET_DELETE_ON_CLOSE_FLAG(fsp->share_mode) != delete_on_close)
1679         {
1680           int token;
1681           files_struct *iterate_fsp;
1682           SMB_DEV_T dev = fsp->fd_ptr->dev;
1683           SMB_INO_T inode = fsp->fd_ptr->inode;
1684
1685           DEBUG(10,("call_trans2setfilepathinfo: %s delete on close flag for fnum = %d, file %s\n",
1686                delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1687
1688           if(lock_share_entry(fsp->conn, dev, inode, &token) == False)
1689             return(ERROR(ERRDOS,ERRnoaccess));
1690
1691           /*
1692            * Go through all files we have open on the same device and
1693            * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1694            */
1695
1696           for(iterate_fsp = file_find_di_first(dev, inode); iterate_fsp;
1697                                 iterate_fsp = file_find_di_next(iterate_fsp))
1698           {
1699             int new_share_mode = (delete_on_close ? 
1700                                   (iterate_fsp->share_mode | DELETE_ON_CLOSE_FLAG) :
1701                                   (iterate_fsp->share_mode & ~DELETE_ON_CLOSE_FLAG) );
1702
1703             DEBUG(10,("call_trans2setfilepathinfo: Changing share mode for fnum %d, file %s\
1704 dev = %x, inode = %.0f from %x to %x\n", 
1705                     iterate_fsp->fnum, iterate_fsp->fsp_name, (unsigned int)dev, 
1706                     (double)inode, iterate_fsp->share_mode, new_share_mode ));
1707
1708             if(modify_share_mode(token, iterate_fsp, new_share_mode)==False)
1709               DEBUG(0,("call_trans2setfilepathinfo: failed to change delete on close for fnum %d, \
1710 dev = %x, inode = %.0f\n", iterate_fsp->fnum, (unsigned int)dev, (double)inode));
1711           }
1712
1713           unlock_share_entry(fsp->conn, dev, inode, token);
1714         }
1715
1716         /*
1717          * Set the delete on close flag in the reference
1718          * counted struct. Delete when the last reference
1719          * goes away.
1720          */
1721         fsp->fd_ptr->delete_on_close = delete_on_close;
1722       } else
1723         return(ERROR(ERRDOS,ERRunknownlevel));
1724       break;
1725     }
1726
1727     default:
1728     {
1729       return(ERROR(ERRDOS,ERRunknownlevel));
1730     }
1731   }
1732
1733   DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
1734   DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
1735   DEBUG(6,("size: %.0f ", (double)size));
1736   DEBUG(6,("mode: %x\n"  , mode));
1737
1738   /* get some defaults (no modifications) if any info is zero. */
1739   if (!tvs.actime) tvs.actime = st.st_atime;
1740   if (!tvs.modtime) tvs.modtime = st.st_mtime;
1741   if (!size) size = st.st_size;
1742
1743   /* Try and set the times, size and mode of this file -
1744      if they are different from the current values
1745    */
1746   if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
1747   {
1748     if(file_utime(conn, fname, &tvs)!=0)
1749     {
1750       return(UNIXERROR(ERRDOS,ERRnoaccess));
1751     }
1752   }
1753
1754   /* check the mode isn't different, before changing it */
1755   if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL))
1756   {
1757     DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
1758     return(UNIXERROR(ERRDOS,ERRnoaccess));
1759   }
1760
1761   if(size != st.st_size)
1762   {
1763     if (fd == -1)
1764     {
1765       fd = dos_open(fname,O_RDWR,0);
1766       if (fd == -1)
1767       {
1768         return(UNIXERROR(ERRDOS,ERRbadpath));
1769       }
1770       set_filelen(fd, size);
1771       close(fd);
1772     }
1773     else
1774     {
1775       set_filelen(fd, size);
1776     }
1777   }
1778
1779   SSVAL(params,0,0);
1780
1781   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1782   
1783   return(-1);
1784 }
1785
1786 /****************************************************************************
1787   reply to a TRANS2_MKDIR (make directory with extended attributes).
1788 ****************************************************************************/
1789 static int call_trans2mkdir(connection_struct *conn,
1790                             char *inbuf, char *outbuf, int length, int bufsize,
1791                             char **pparams, char **ppdata)
1792 {
1793   char *params = *pparams;
1794   pstring directory;
1795   int ret = -1;
1796   BOOL bad_path = False;
1797
1798   if (!CAN_WRITE(conn))
1799     return(ERROR(ERRSRV,ERRaccess));
1800
1801   pstrcpy(directory, &params[4]);
1802
1803   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
1804
1805   unix_convert(directory,conn,0,&bad_path,NULL);
1806   if (check_name(directory,conn))
1807     ret = dos_mkdir(directory,unix_mode(conn,aDIR));
1808   
1809   if(ret < 0)
1810     {
1811       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
1812       if((errno == ENOENT) && bad_path)
1813       {
1814         unix_ERR_class = ERRDOS;
1815         unix_ERR_code = ERRbadpath;
1816       }
1817       return(UNIXERROR(ERRDOS,ERRnoaccess));
1818     }
1819
1820   /* Realloc the parameter and data sizes */
1821   params = *pparams = Realloc(*pparams,2);
1822   if(params == NULL)
1823     return(ERROR(ERRDOS,ERRnomem));
1824
1825   SSVAL(params,0,0);
1826
1827   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1828   
1829   return(-1);
1830 }
1831
1832 /****************************************************************************
1833   reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes)
1834   We don't actually do this - we just send a null response.
1835 ****************************************************************************/
1836 static int call_trans2findnotifyfirst(connection_struct *conn,
1837                                       char *inbuf, char *outbuf, 
1838                                       int length, int bufsize,
1839                                       char **pparams, char **ppdata)
1840 {
1841   static uint16 fnf_handle = 257;
1842   char *params = *pparams;
1843   uint16 info_level = SVAL(params,4);
1844
1845   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
1846
1847   switch (info_level) 
1848     {
1849     case 1:
1850     case 2:
1851       break;
1852     default:
1853       return(ERROR(ERRDOS,ERRunknownlevel));
1854     }
1855
1856   /* Realloc the parameter and data sizes */
1857   params = *pparams = Realloc(*pparams,6);
1858   if(params == NULL)
1859     return(ERROR(ERRDOS,ERRnomem));
1860
1861   SSVAL(params,0,fnf_handle);
1862   SSVAL(params,2,0); /* No changes */
1863   SSVAL(params,4,0); /* No EA errors */
1864
1865   fnf_handle++;
1866
1867   if(fnf_handle == 0)
1868     fnf_handle = 257;
1869
1870   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
1871   
1872   return(-1);
1873 }
1874
1875 /****************************************************************************
1876   reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
1877   changes). Currently this does nothing.
1878 ****************************************************************************/
1879 static int call_trans2findnotifynext(connection_struct *conn,
1880                                      char *inbuf, char *outbuf, 
1881                                      int length, int bufsize,
1882                                      char **pparams, char **ppdata)
1883 {
1884   char *params = *pparams;
1885
1886   DEBUG(3,("call_trans2findnotifynext\n"));
1887
1888   /* Realloc the parameter and data sizes */
1889   params = *pparams = Realloc(*pparams,4);
1890   if(params == NULL)
1891     return(ERROR(ERRDOS,ERRnomem));
1892
1893   SSVAL(params,0,0); /* No changes */
1894   SSVAL(params,2,0); /* No EA errors */
1895
1896   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
1897   
1898   return(-1);
1899 }
1900
1901 /****************************************************************************
1902   reply to a SMBfindclose (stop trans2 directory search)
1903 ****************************************************************************/
1904 int reply_findclose(connection_struct *conn,
1905                     char *inbuf,char *outbuf,int length,int bufsize)
1906 {
1907         int outsize = 0;
1908         int16 dptr_num=SVALS(inbuf,smb_vwv0);
1909
1910         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
1911
1912         dptr_close(dptr_num);
1913
1914         outsize = set_message(outbuf,0,0,True);
1915
1916         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
1917
1918         return(outsize);
1919 }
1920
1921 /****************************************************************************
1922   reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search)
1923 ****************************************************************************/
1924 int reply_findnclose(connection_struct *conn, 
1925                      char *inbuf,char *outbuf,int length,int bufsize)
1926 {
1927         int outsize = 0;
1928         int dptr_num= -1;
1929         
1930         dptr_num = SVAL(inbuf,smb_vwv0);
1931
1932         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
1933
1934         /* We never give out valid handles for a 
1935            findnotifyfirst - so any dptr_num is ok here. 
1936            Just ignore it. */
1937
1938         outsize = set_message(outbuf,0,0,True);
1939
1940         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
1941
1942         return(outsize);
1943 }
1944
1945
1946 /****************************************************************************
1947   reply to a SMBtranss2 - just ignore it!
1948 ****************************************************************************/
1949 int reply_transs2(connection_struct *conn,
1950                   char *inbuf,char *outbuf,int length,int bufsize)
1951 {
1952         DEBUG(4,("Ignoring transs2 of length %d\n",length));
1953         return(-1);
1954 }
1955
1956 /****************************************************************************
1957   reply to a SMBtrans2
1958 ****************************************************************************/
1959 int reply_trans2(connection_struct *conn,
1960                  char *inbuf,char *outbuf,int length,int bufsize)
1961 {
1962         int outsize = 0;
1963         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
1964         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
1965 #if 0
1966         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
1967         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
1968         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
1969         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
1970         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
1971         int32 timeout = IVALS(inbuf,smb_timeout);
1972 #endif
1973         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
1974         unsigned int tran_call = SVAL(inbuf, smb_setup0);
1975         char *params = NULL, *data = NULL;
1976         int num_params, num_params_sofar, num_data, num_data_sofar;
1977
1978         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
1979                 /* Queue this open message as we are the process of an
1980                  * oplock break.  */
1981
1982                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
1983                 DEBUGADD(2,( "in oplock break state.\n"));
1984
1985                 push_oplock_pending_smb_message(inbuf, length);
1986                 return -1;
1987         }
1988         
1989         outsize = set_message(outbuf,0,0,True);
1990
1991         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
1992            is so as a sanity check */
1993         if (suwcnt != 1) {
1994                 DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
1995                 return(ERROR(ERRSRV,ERRerror));
1996         }
1997     
1998         /* Allocate the space for the maximum needed parameters and data */
1999         if (total_params > 0)
2000                 params = (char *)malloc(total_params);
2001         if (total_data > 0)
2002                 data = (char *)malloc(total_data);
2003   
2004         if ((total_params && !params)  || (total_data && !data)) {
2005                 DEBUG(2,("Out of memory in reply_trans2\n"));
2006         if(params)
2007           free(params);
2008         if(data)
2009           free(data); 
2010                 return(ERROR(ERRDOS,ERRnomem));
2011         }
2012
2013         /* Copy the param and data bytes sent with this request into
2014            the params buffer */
2015         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2016         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2017
2018         if (num_params > total_params || num_data > total_data)
2019                 exit_server("invalid params in reply_trans2");
2020
2021         if(params)
2022                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2023         if(data)
2024                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2025
2026         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
2027                 /* We need to send an interim response then receive the rest
2028                    of the parameter/data bytes */
2029                 outsize = set_message(outbuf,0,0,True);
2030                 send_smb(Client,outbuf);
2031
2032                 while (num_data_sofar < total_data || 
2033                        num_params_sofar < total_params) {
2034                         BOOL ret;
2035
2036                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2037                         
2038                         if ((ret && 
2039                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2040                                 outsize = set_message(outbuf,0,0,True);
2041                                 if(ret)
2042                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2043                                 else
2044                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2045                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2046                                 if(params)
2047                                         free(params);
2048                                 if(data)
2049                                         free(data);
2050                                 return(ERROR(ERRSRV,ERRerror));
2051                         }
2052       
2053                         /* Revise total_params and total_data in case
2054                            they have changed downwards */
2055                         total_params = SVAL(inbuf, smb_tpscnt);
2056                         total_data = SVAL(inbuf, smb_tdscnt);
2057                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2058                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2059                         if (num_params_sofar > total_params || num_data_sofar > total_data)
2060                                 exit_server("data overflow in trans2");
2061                         
2062                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
2063                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2064                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2065                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2066                 }
2067         }
2068         
2069         if (Protocol >= PROTOCOL_NT1) {
2070                 uint16 flg2 = SVAL(outbuf,smb_flg2);
2071                 SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */
2072         }
2073
2074         /* Now we must call the relevant TRANS2 function */
2075         switch(tran_call)  {
2076         case TRANSACT2_OPEN:
2077                 outsize = call_trans2open(conn, 
2078                                           inbuf, outbuf, bufsize, 
2079                                           &params, &data);
2080                 break;
2081
2082         case TRANSACT2_FINDFIRST:
2083                 outsize = call_trans2findfirst(conn, inbuf, outbuf, 
2084                                                bufsize, &params, &data);
2085                 break;
2086
2087         case TRANSACT2_FINDNEXT:
2088                 outsize = call_trans2findnext(conn, inbuf, outbuf, 
2089                                               length, bufsize, 
2090                                               &params, &data);
2091                 break;
2092
2093         case TRANSACT2_QFSINFO:
2094             outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
2095                                          length, bufsize, &params, 
2096                                          &data);
2097             break;
2098
2099         case TRANSACT2_SETFSINFO:
2100                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
2101                                                length, bufsize, 
2102                                                &params, &data);
2103                 break;
2104
2105         case TRANSACT2_QPATHINFO:
2106         case TRANSACT2_QFILEINFO:
2107                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
2108                                                    length, bufsize, 
2109                                                    &params, &data, total_data);
2110                 break;
2111         case TRANSACT2_SETPATHINFO:
2112         case TRANSACT2_SETFILEINFO:
2113                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
2114                                                      length, bufsize, 
2115                                                      &params, &data, 
2116                                                      total_data);
2117                 break;
2118
2119         case TRANSACT2_FINDNOTIFYFIRST:
2120                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
2121                                                      length, bufsize, 
2122                                                      &params, &data);
2123                 break;
2124
2125         case TRANSACT2_FINDNOTIFYNEXT:
2126                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
2127                                                     length, bufsize, 
2128                                                     &params, &data);
2129                 break;
2130         case TRANSACT2_MKDIR:
2131                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
2132                                            bufsize, &params, &data);
2133                 break;
2134         default:
2135                 /* Error in request */
2136                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
2137                 if(params)
2138                         free(params);
2139                 if(data)
2140                         free(data);
2141                 return (ERROR(ERRSRV,ERRerror));
2142         }
2143         
2144         /* As we do not know how many data packets will need to be
2145            returned here the various call_trans2xxxx calls
2146            must send their own. Thus a call_trans2xxx routine only
2147            returns a value other than -1 when it wants to send
2148            an error packet. 
2149         */
2150         
2151         if(params)
2152                 free(params);
2153         if(data)
2154                 free(data);
2155         return outsize; /* If a correct response was needed the
2156                            call_trans2xxx calls have already sent
2157                            it. If outsize != -1 then it is returning */
2158 }