60e03e002db17570f8e8ab58fb4381b113e9a127
[kai/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-2001
6
7    Extensively modified by Andrew Tridgell, 1995
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 extern int Protocol;
27 extern BOOL case_sensitive;
28 extern int smb_read_error;
29 extern fstring local_machine;
30 extern int global_oplock_break;
31 extern uint32 global_client_caps;
32 extern pstring global_myname;
33
34 /****************************************************************************
35   Send the required number of replies back.
36   We assume all fields other than the data fields are
37   set correctly for the type of call.
38   HACK ! Always assumes smb_setup field is zero.
39 ****************************************************************************/
40
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 = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
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     if (!send_smb(smbd_server_fd(),outbuf))
69       exit_server("send_trans2_replies: send_smb failed.");
70     return 0;
71   }
72
73   /* When sending params and data ensure that both are nicely aligned */
74   /* Only do this alignment when there is also data to send - else
75      can cause NT redirector problems. */
76   if (((params_to_send % 4) != 0) && (data_to_send != 0))
77     data_alignment_offset = 4 - (params_to_send % 4);
78
79   /* Space is bufsize minus Netbios over TCP header minus SMB header */
80   /* The alignment_offset is to align the param bytes on an even byte
81      boundary. NT 4.0 Beta needs this to work correctly. */
82   useable_space = bufsize - ((smb_buf(outbuf)+
83                     alignment_offset+data_alignment_offset) - 
84                     outbuf);
85
86   /* useable_space can never be more than max_send minus the
87      alignment offset. */
88   useable_space = MIN(useable_space, 
89                       max_send - (alignment_offset+data_alignment_offset));
90
91
92   while (params_to_send || data_to_send)
93   {
94     /* Calculate whether we will totally or partially fill this packet */
95     total_sent_thistime = params_to_send + data_to_send + 
96                             alignment_offset + data_alignment_offset;
97     /* We can never send more than useable_space */
98     /*
99      * Note that 'useable_space' does not include the alignment offsets,
100      * but we must include the alignment offsets in the calculation of
101      * the length of the data we send over the wire, as the alignment offsets
102      * are sent here. Fix from Marc_Jacobsen@hp.com.
103      */
104     total_sent_thistime = MIN(total_sent_thistime, useable_space+
105                                 alignment_offset + data_alignment_offset);
106
107     set_message(outbuf, 10, total_sent_thistime, True);
108
109     /* Set total params and data to be sent */
110     SSVAL(outbuf,smb_tprcnt,paramsize);
111     SSVAL(outbuf,smb_tdrcnt,datasize);
112
113     /* Calculate how many parameters and data we can fit into
114        this packet. Parameters get precedence */
115
116     params_sent_thistime = MIN(params_to_send,useable_space);
117     data_sent_thistime = useable_space - params_sent_thistime;
118     data_sent_thistime = MIN(data_sent_thistime,data_to_send);
119
120     SSVAL(outbuf,smb_prcnt, params_sent_thistime);
121
122     /* smb_proff is the offset from the start of the SMB header to the
123        parameter bytes, however the first 4 bytes of outbuf are
124        the Netbios over TCP header. Thus use smb_base() to subtract
125        them from the calculation */
126
127     SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
128
129     if(params_sent_thistime == 0)
130       SSVAL(outbuf,smb_prdisp,0);
131     else
132       /* Absolute displacement of param bytes sent in this packet */
133       SSVAL(outbuf,smb_prdisp,pp - params);
134
135     SSVAL(outbuf,smb_drcnt, data_sent_thistime);
136     if(data_sent_thistime == 0)
137     {
138       SSVAL(outbuf,smb_droff,0);
139       SSVAL(outbuf,smb_drdisp, 0);
140     }
141     else
142     {
143       /* The offset of the data bytes is the offset of the
144          parameter bytes plus the number of parameters being sent this time */
145       SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
146             smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
147       SSVAL(outbuf,smb_drdisp, pd - pdata);
148     }
149
150     /* Copy the param bytes into the packet */
151     if(params_sent_thistime)
152       memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
153     /* Copy in the data bytes */
154     if(data_sent_thistime)
155       memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
156              data_alignment_offset,pd,data_sent_thistime);
157
158     DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
159           params_sent_thistime, data_sent_thistime, useable_space));
160     DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
161           params_to_send, data_to_send, paramsize, datasize));
162
163     /* Send the packet */
164     if (!send_smb(smbd_server_fd(),outbuf))
165                 exit_server("send_trans2_replies: send_smb failed.");
166
167     pp += params_sent_thistime;
168     pd += data_sent_thistime;
169
170     params_to_send -= params_sent_thistime;
171     data_to_send -= data_sent_thistime;
172
173     /* Sanity check */
174     if(params_to_send < 0 || data_to_send < 0)
175     {
176       DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
177             params_to_send, data_to_send));
178       return -1;
179     }
180   }
181
182   return 0;
183 }
184
185 /****************************************************************************
186  Reply to a TRANSACT2_OPEN.
187 ****************************************************************************/
188
189 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, 
190                            int bufsize,  
191                            char **pparams, char **ppdata)
192 {
193   char *params = *pparams;
194   int16 open_mode = SVAL(params, 2);
195   int16 open_attr = SVAL(params,6);
196   BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
197 #if 0
198   BOOL return_additional_info = BITSETW(params,0);
199   int16 open_sattr = SVAL(params, 4);
200   time_t open_time = make_unix_date3(params+8);
201 #endif
202   int16 open_ofun = SVAL(params,12);
203   int32 open_size = IVAL(params,14);
204   char *pname = &params[28];
205   pstring fname;
206   mode_t unixmode;
207   SMB_OFF_T size=0;
208   int fmode=0,mtime=0,rmode;
209   SMB_INO_T inode = 0;
210   SMB_STRUCT_STAT sbuf;
211   int smb_action = 0;
212   BOOL bad_path = False;
213   files_struct *fsp;
214
215   srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
216
217   DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
218            fname,open_mode, open_attr, open_ofun, open_size));
219
220   if (IS_IPC(conn)) {
221                 return(ERROR_DOS(ERRSRV,ERRaccess));
222   }
223
224   /* XXXX we need to handle passed times, sattr and flags */
225
226   unix_convert(fname,conn,0,&bad_path,&sbuf);
227     
228   if (!check_name(fname,conn))
229   {
230     if((errno == ENOENT) && bad_path)
231     {
232       unix_ERR_class = ERRDOS;
233       unix_ERR_code = ERRbadpath;
234     }
235     return(UNIXERROR(ERRDOS,ERRnoaccess));
236   }
237
238   unixmode = unix_mode(conn,open_attr | aARCH, fname);
239       
240   fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
241                    oplock_request, &rmode,&smb_action);
242       
243   if (!fsp)
244   {
245     if((errno == ENOENT) && bad_path)
246     {
247       unix_ERR_class = ERRDOS;
248       unix_ERR_code = ERRbadpath;
249     }
250     return(UNIXERROR(ERRDOS,ERRnoaccess));
251   }
252
253   size = sbuf.st_size;
254   fmode = dos_mode(conn,fname,&sbuf);
255   mtime = sbuf.st_mtime;
256   inode = sbuf.st_ino;
257   if (fmode & aDIR) {
258     close_file(fsp,False);
259     return(ERROR_DOS(ERRDOS,ERRnoaccess));
260   }
261
262   /* Realloc the size of parameters and data we will return */
263   params        = Realloc(*pparams, 28);
264   if( params == NULL ) {
265     return(ERROR_DOS(ERRDOS,ERRnomem));
266   }
267   *pparams      = params;
268
269   memset((char *)params,'\0',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  Routine to check if a given string matches exactly.
294  as a special case a mask of "." does NOT match. That
295  is required for correct wildcard semantics
296  Case can be significant or not.
297 **********************************************************/
298
299 static BOOL exact_match(char *str,char *mask, BOOL case_sig) 
300 {
301         if (mask[0] == '.' && mask[1] == 0)
302                 return False;
303         if (case_sig)   
304                 return strcmp(str,mask)==0;
305         return strcasecmp(str,mask) == 0;
306 }
307
308 #if 0
309
310 Not finished yet - jra.
311
312 /****************************************************************************
313  Return the filetype for UNIX extensions.
314 ****************************************************************************/
315
316 static uint32 unix_filetype(mode_t mode)
317 {
318         if(S_ISREG(mode))
319                 return UNIX_TYPE_FILE;
320         else if(S_ISDIR(mode))
321                 return UNIX_TYPE_DIR;
322 #ifdef S_ISLNK
323         else if(S_ISLNK(mode))
324                 return UNIX_TYPE_SYMLINK;
325 #endif
326 #ifdef S_ISCHR
327         else if(S_ISCHR(mode))
328                 return UNIX_TYPE_CHARDEV;
329 #endif
330 #ifdef S_ISBLK
331         else if(S_ISBLK(mode))
332                 return UNIX_TYPE_BLKDEV;
333 #endif
334 #ifdef S_ISFIFO
335         else if(S_ISFIFO(mode))
336                 return UNIX_TYPE_FIFO;
337 #endif
338 #ifdef S_ISSOCK
339         else if(S_ISSOCK(mode))
340                 return UNIX_TYPE_SOCKET;
341 #endif
342
343         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
344         return UNIX_TYPE_UNKNOWN;
345 }
346
347 /****************************************************************************
348  Return the major devicenumber for UNIX extensions.
349 ****************************************************************************/
350
351 static uint32 unix_dev_major(SMB_DEV_T dev)
352 {
353 #if defined(HAVE_DEVICE_MAJOR_FN)
354         return (uint32)major(dev);
355 #else
356         return (uint32)(dev >> 8);
357 #endif
358 }
359
360 /****************************************************************************
361  Return the minor devicenumber for UNIX extensions.
362 ****************************************************************************/
363
364 static uint32 unix_dev_minor(SMB_DEV_T dev)
365 {
366 #if defined(HAVE_DEVICE_MINOR_FN)
367         return (uint32)minor(dev);
368 #else
369         return (uint32)(dev & 0xff);
370 #endif
371 }
372
373 /****************************************************************************
374  Map standard UNIX permissions onto wire representations.
375 ****************************************************************************/
376
377 static uint32  unix_perms_to_wire(mode_t perms)
378 {
379         uint ret = 0;
380
381         ret |= ((perms & S_IXOTH) ?  UNIX_X_OTH : 0);
382         ret |= ((perms & S_IWOTH) ?  UNIX_W_OTH : 0);
383         ret |= ((perms & S_IROTH) ?  UNIX_R_OTH : 0);
384         ret |= ((perms & S_IXGRP) ?  UNIX_X_GRP : 0);
385         ret |= ((perms & S_IWGRP) ?  UNIX_W_GRP : 0);
386         ret |= ((perms & S_IRGRP) ?  UNIX_R_GRP : 0);
387         ret |= ((perms & S_IXUSR) ?  UNIX_X_USR : 0);
388         ret |= ((perms & S_IWUSR) ?  UNIX_W_USR : 0);
389         ret |= ((perms & S_IRUSR) ?  UNIX_R_USR : 0);
390 #ifdef S_ISVTX
391         ret |= ((perms & S_ISVTX) ?  UNIX_STICKY : 0);
392 #endif
393 #ifdef S_ISGID
394         ret |= ((perms & S_ISGID) ?  UNIX_SET_GID : 0);
395 #endif
396 #ifdef S_ISUID
397         ret |= ((perms & S_ISVTX) ?  UNIX_SET_UID : 0);
398 #endif
399         return ret;
400 }
401
402 #endif
403
404 /****************************************************************************
405  Get a level dependent lanman2 dir entry.
406 ****************************************************************************/
407
408 static BOOL get_lanman2_dir_entry(connection_struct *conn,
409                                   void *inbuf, void *outbuf,
410                                  char *path_mask,int dirtype,int info_level,
411                                  int requires_resume_key,
412                                  BOOL dont_descend,char **ppdata, 
413                                  char *base_data, int space_remaining, 
414                                  BOOL *out_of_space, BOOL *got_exact_match,
415                                  int *last_name_off)
416 {
417         char *dname;
418         BOOL found = False;
419         SMB_STRUCT_STAT sbuf;
420         pstring mask;
421         pstring pathreal;
422         pstring fname;
423         char *p, *q, *pdata = *ppdata;
424         uint32 reskey=0;
425         int prev_dirpos=0;
426         int mode=0;
427         SMB_OFF_T size = 0;
428         SMB_OFF_T allocation_size = 0;
429         uint32 len;
430         time_t mdate=0, adate=0, cdate=0;
431         char *nameptr;
432         BOOL was_8_3;
433         int nt_extmode; /* Used for NT connections instead of mode */
434         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
435
436         *fname = 0;
437         *out_of_space = False;
438         *got_exact_match = False;
439
440         if (!conn->dirptr)
441                 return(False);
442
443         p = strrchr_m(path_mask,'/');
444         if(p != NULL) {
445                 if(p[1] == '\0')
446                         pstrcpy(mask,"*.*");
447                 else
448                         pstrcpy(mask, p+1);
449         } else
450                 pstrcpy(mask, path_mask);
451
452         while (!found) {
453                 BOOL got_match;
454
455                 /* Needed if we run out of space */
456                 prev_dirpos = TellDir(conn->dirptr);
457                 dname = ReadDirName(conn->dirptr);
458
459                 /*
460                  * Due to bugs in NT client redirectors we are not using
461                  * resume keys any more - set them to zero.
462                  * Check out the related comments in findfirst/findnext.
463                  * JRA.
464                  */
465
466                 reskey = 0;
467
468                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
469                         (long)conn->dirptr,TellDir(conn->dirptr)));
470       
471                 if (!dname) 
472                         return(False);
473
474                 pstrcpy(fname,dname);      
475
476                 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
477                         got_match = mask_match(fname, mask, case_sensitive);
478
479                 if(!got_match && !is_8_3(fname, False)) {
480
481                         /*
482                          * It turns out that NT matches wildcards against
483                          * both long *and* short names. This may explain some
484                          * of the wildcard wierdness from old DOS clients
485                          * that some people have been seeing.... JRA.
486                          */
487
488                         pstring newname;
489                         pstrcpy( newname, fname);
490                         name_map_mangle( newname, True, False, SNUM(conn));
491                         if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
492                                 got_match = mask_match(newname, mask, case_sensitive);
493                 }
494
495                 if(got_match) {
496                         BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
497                         if (dont_descend && !isdots)
498                                 continue;
499           
500                         pstrcpy(pathreal,conn->dirpath);
501                         if(needslash)
502                                 pstrcat(pathreal,"/");
503                         pstrcat(pathreal,dname);
504
505                         if (INFO_LEVEL_IS_UNIX(info_level)) {
506                                 if (vfs_lstat(conn,pathreal,&sbuf) != 0) {
507                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
508                                                 pathreal,strerror(errno)));
509                                         continue;
510                                 }
511                         } else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
512                                 /* Needed to show the msdfs symlinks as directories */
513                                 if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn)) 
514                                                 || !is_msdfs_link(conn, pathreal)) {
515                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
516                                                         pathreal,strerror(errno)));
517                                         continue;
518                                 } else {
519                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n",
520                                                         pathreal));
521                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
522                                 }
523                         }
524
525                         mode = dos_mode(conn,pathreal,&sbuf);
526
527                         if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
528                                 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
529                                 continue;
530                         }
531
532                         size = sbuf.st_size;
533                         allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
534                         mdate = sbuf.st_mtime;
535                         adate = sbuf.st_atime;
536                         cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
537
538                         if (lp_dos_filetime_resolution(SNUM(conn))) {
539                                 cdate &= ~1;
540                                 mdate &= ~1;
541                                 adate &= ~1;
542                         }
543
544                         if(mode & aDIR)
545                                 size = 0;
546
547                         DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
548           
549                         found = True;
550                 }
551         }
552
553         name_map_mangle(fname,False,True,SNUM(conn));
554
555         p = pdata;
556         nameptr = p;
557
558         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
559
560         switch (info_level) {
561                 case 1:
562                         if(requires_resume_key) {
563                                 SIVAL(p,0,reskey);
564                                 p += 4;
565                         }
566                         put_dos_date2(p,l1_fdateCreation,cdate);
567                         put_dos_date2(p,l1_fdateLastAccess,adate);
568                         put_dos_date2(p,l1_fdateLastWrite,mdate);
569                         SIVAL(p,l1_cbFile,(uint32)size);
570                         SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
571                         SSVAL(p,l1_attrFile,mode);
572                         p += l1_achName;
573                         nameptr = p;
574                         p += align_string(outbuf, p, 0);
575                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
576                         SCVAL(nameptr, -1, len);
577                         p += len;
578                         break;
579
580                 case 2:
581                         if(requires_resume_key) {
582                                 SIVAL(p,0,reskey);
583                                 p += 4;
584                         }
585                         put_dos_date2(p,l2_fdateCreation,cdate);
586                         put_dos_date2(p,l2_fdateLastAccess,adate);
587                         put_dos_date2(p,l2_fdateLastWrite,mdate);
588                         SIVAL(p,l2_cbFile,(uint32)size);
589                         SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
590                         SSVAL(p,l2_attrFile,mode);
591                         SIVAL(p,l2_cbList,0); /* No extended attributes */
592                         p += l2_achName;
593                         nameptr = p;
594                         len = srvstr_push(outbuf, p, fname, -1, STR_NOALIGN);
595                         SCVAL(p, -1, len);
596                         p += len;
597                         *p++ = 0; /* craig from unisys pointed out we need this */
598                         break;
599
600                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
601                         was_8_3 = is_8_3(fname, True);
602                         p += 4;
603                         SIVAL(p,0,reskey); p += 4;
604                         put_long_date(p,cdate); p += 8;
605                         put_long_date(p,adate); p += 8;
606                         put_long_date(p,mdate); p += 8;
607                         put_long_date(p,mdate); p += 8;
608                         SOFF_T(p,0,size);
609                         SOFF_T(p,8,allocation_size);
610                         p += 16;
611                         SIVAL(p,0,nt_extmode); p += 4;
612                         q = p; p += 4;
613                         SIVAL(p,0,0); p += 4;
614                         if (!was_8_3) {
615                                 pstring mangled_name;
616                                 pstrcpy(mangled_name, fname);
617                                 name_map_mangle(mangled_name,True,True,SNUM(conn));
618                                 mangled_name[12] = 0;
619                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER);
620                                 SSVAL(p, 0, len);
621                         } else {
622                                 SSVAL(p,0,0);
623                                 *(p+2) = 0;
624                         }
625                         p += 2 + 24;
626                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
627                         SIVAL(q,0,len);
628                         p += len;
629                         len = PTR_DIFF(p, pdata);
630                         len = (len + 3) & ~3;
631                         SIVAL(pdata,0,len);
632                         p = pdata + len;
633                         break;
634
635                 case SMB_FIND_FILE_DIRECTORY_INFO:
636                         p += 4;
637                         SIVAL(p,0,reskey); p += 4;
638                         put_long_date(p,cdate); p += 8;
639                         put_long_date(p,adate); p += 8;
640                         put_long_date(p,mdate); p += 8;
641                         put_long_date(p,mdate); p += 8;
642                         SOFF_T(p,0,size);
643                         SOFF_T(p,8,allocation_size);
644                         p += 16;
645                         SIVAL(p,0,nt_extmode); p += 4;
646                         p += 4;
647                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
648                         SIVAL(p, -4, len);
649                         p += len;
650                         len = PTR_DIFF(p, pdata);
651                         len = (len + 3) & ~3;
652                         SIVAL(pdata,0,len);
653                         p = pdata + len;
654                         break;
655       
656                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
657                         p += 4;
658                         SIVAL(p,0,reskey); p += 4;
659                         put_long_date(p,cdate); p += 8;
660                         put_long_date(p,adate); p += 8;
661                         put_long_date(p,mdate); p += 8;
662                         put_long_date(p,mdate); p += 8;
663                         SOFF_T(p,0,size); 
664                         SOFF_T(p,8,allocation_size);
665                         p += 16;
666                         SIVAL(p,0,nt_extmode); p += 4;
667                         p += 4;
668                         SIVAL(p,0,0); p += 4;
669
670                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
671                         SIVAL(p, -4, len);
672                         p += len;
673
674                         len = PTR_DIFF(p, pdata);
675                         len = (len + 3) & ~3;
676                         SIVAL(pdata,0,len);
677                         p = pdata + len;
678                         break;
679
680                 case SMB_FIND_FILE_NAMES_INFO:
681                         p += 4;
682                         SIVAL(p,0,reskey); p += 4;
683                         p += 4;
684                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
685                         SIVAL(p, -4, len);
686                         p += len;
687                         len = PTR_DIFF(p, pdata);
688                         len = (len + 3) & ~3;
689                         SIVAL(pdata,0,len);
690                         p = pdata + len;
691                         break;
692
693                 /* CIFS UNIX Extension. */
694
695 #if 0 /* JRA - FIXME - NEEDS UNICODE CONVERSION !!! */
696                 case SMB_FIND_FILE_UNIX:
697
698                         len = 108+strlen(fname)+1;      /* (length of SMB_QUERY_FILE_UNIX_BASIC = 100)+4+4+strlen(fname)*/
699                                                         /* +1 to be sure to transmit the termination of fname */
700                         len = (len + 3) & ~3;
701
702                         SIVAL(p,0,len); p+= 4;       /* Offset from this structure to the beginning of the next one */
703                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
704
705                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
706                         SOFF_T(p,0,sbuf.st_size);             /* File size 64 Bit */
707                         p+= 8;
708
709 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
710                         SOFF_T(p,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
711 #else
712                         /* Can't get the value - fake it using size. */
713                         SOFF_T(p,0,sbuf.st_size);             /* Number of bytes used on disk - 64 Bit */
714 #endif
715                         p+= 8;
716
717                         put_long_date(p,sbuf.st_ctime);       /* Creation Time 64 Bit */
718                         put_long_date(p+8,sbuf.st_atime);     /* Last access time 64 Bit */
719                         put_long_date(p+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
720                         p+= 24;
721
722                         SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
723                         SIVAL(p,4,0);
724                         p+= 8;
725
726                         SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
727                         SIVAL(p,4,0);
728                         p+= 8;
729
730                         SIVAL(p,0,unix_filetype(sbuf.st_mode));
731                         p+= 4;
732
733                         SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
734                         SIVAL(p,4,0);
735                         p+= 8;
736
737                         SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
738                         SIVAL(p,4,0);
739                         p+= 8;
740
741                         SINO_T(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
742                         p+= 8;
743
744                         SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
745                         SIVAL(p,4,0);
746                         p+= 8;
747
748                         SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
749                         SIVAL(p,4,0);
750                         p+= 8;
751
752                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
753                         pstrcpy(p,fname);
754                         p=pdata+len;
755
756                         break;
757 #endif
758
759                 default:      
760                         return(False);
761         }
762
763
764         if (PTR_DIFF(p,pdata) > space_remaining) {
765                 /* Move the dirptr back to prev_dirpos */
766                 SeekDir(conn->dirptr, prev_dirpos);
767                 *out_of_space = True;
768                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
769                 return False; /* Not finished - just out of space */
770         }
771
772         /* Setup the last_filename pointer, as an offset from base_data */
773         *last_name_off = PTR_DIFF(nameptr,base_data);
774         /* Advance the data pointer to the next slot */
775         *ppdata = p;
776
777         return(found);
778 }
779
780 /****************************************************************************
781  Reply to a TRANS2_FINDFIRST.
782 ****************************************************************************/
783
784 static int call_trans2findfirst(connection_struct *conn,
785                                 char *inbuf, char *outbuf, int bufsize,  
786                                 char **pparams, char **ppdata)
787 {
788   /* We must be careful here that we don't return more than the
789      allowed number of data bytes. If this means returning fewer than
790      maxentries then so be it. We assume that the redirector has
791      enough room for the fixed number of parameter bytes it has
792      requested. */
793   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
794   char *params = *pparams;
795   char *pdata = *ppdata;
796   int dirtype = SVAL(params,0);
797   int maxentries = SVAL(params,2);
798   BOOL close_after_first = BITSETW(params+4,0);
799   BOOL close_if_end = BITSETW(params+4,1);
800   BOOL requires_resume_key = BITSETW(params+4,2);
801   int info_level = SVAL(params,6);
802   pstring directory;
803   pstring mask;
804   char *p, *wcard;
805   int last_name_off=0;
806   int dptr_num = -1;
807   int numentries = 0;
808   int i;
809   BOOL finished = False;
810   BOOL dont_descend = False;
811   BOOL out_of_space = False;
812   int space_remaining;
813   BOOL bad_path = False;
814   SMB_STRUCT_STAT sbuf;
815
816   *directory = *mask = 0;
817
818   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",
819            dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
820            info_level, max_data_bytes));
821   
822   switch (info_level) 
823     {
824     case 1:
825     case 2:
826     case 3:
827     case 4:
828     case SMB_FIND_FILE_DIRECTORY_INFO:
829     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
830     case SMB_FIND_FILE_NAMES_INFO:
831     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
832       break;
833     default:
834       return(ERROR_DOS(ERRDOS,ERRunknownlevel));
835     }
836
837   srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
838
839   RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
840
841   unix_convert(directory,conn,0,&bad_path,&sbuf);
842   if(!check_name(directory,conn)) {
843     if((errno == ENOENT) && bad_path)
844     {
845       unix_ERR_class = ERRDOS;
846       unix_ERR_code = ERRbadpath;
847     }
848
849 #if 0
850     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
851     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
852        (get_remote_arch() == RA_WINNT))
853     {
854       unix_ERR_class = ERRDOS;
855       unix_ERR_code = ERRbaddirectory;
856     }
857 #endif 
858
859     return(UNIXERROR(ERRDOS,ERRbadpath));
860   }
861
862   p = strrchr_m(directory,'/');
863   if(p == NULL) {
864     pstrcpy(mask,directory);
865     pstrcpy(directory,"./");
866   } else {
867     pstrcpy(mask,p+1);
868     *p = 0;
869   }
870
871   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
872
873   pdata = Realloc(*ppdata, max_data_bytes + 1024);
874   if( pdata == NULL ) {
875     return(ERROR_DOS(ERRDOS,ERRnomem));
876   }
877   *ppdata       = pdata;
878   memset((char *)pdata,'\0',max_data_bytes + 1024);
879
880   /* Realloc the params space */
881   params = Realloc(*pparams, 10);
882   if (params == NULL) {
883     return ERROR_DOS(ERRDOS,ERRnomem);
884   }
885   *pparams      = params;
886
887   dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
888   if (dptr_num < 0)
889     return(UNIXERROR(ERRDOS,ERRbadfile));
890
891   /* Save the wildcard match and attribs we are using on this directory - 
892      needed as lanman2 assumes these are being saved between calls */
893
894   if(!(wcard = strdup(mask))) {
895     dptr_close(&dptr_num);
896     return ERROR_DOS(ERRDOS,ERRnomem);
897   }
898
899   dptr_set_wcard(dptr_num, wcard);
900   dptr_set_attr(dptr_num, dirtype);
901
902   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
903
904   /* We don't need to check for VOL here as this is returned by 
905      a different TRANS2 call. */
906   
907   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
908            conn->dirpath,lp_dontdescend(SNUM(conn))));
909   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
910     dont_descend = True;
911     
912   p = pdata;
913   space_remaining = max_data_bytes;
914   out_of_space = False;
915
916   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
917   {
918     BOOL got_exact_match = False;
919
920     /* this is a heuristic to avoid seeking the dirptr except when 
921        absolutely necessary. It allows for a filename of about 40 chars */
922     if (space_remaining < DIRLEN_GUESS && numentries > 0)
923     {
924       out_of_space = True;
925       finished = False;
926     }
927     else
928     {
929       finished = !get_lanman2_dir_entry(conn,
930                                         inbuf, outbuf,
931                                         mask,dirtype,info_level,
932                                         requires_resume_key,dont_descend,
933                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
934                                         &last_name_off);
935     }
936
937     if (finished && out_of_space)
938       finished = False;
939
940     if (!finished && !out_of_space)
941       numentries++;
942
943     /*
944      * As an optimisation if we know we aren't looking
945      * for a wildcard name (ie. the name matches the wildcard exactly)
946      * then we can finish on any (first) match.
947      * This speeds up large directory searches. JRA.
948      */
949
950     if(got_exact_match)
951       finished = True;
952
953     space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
954   }
955   
956   /* Check if we can close the dirptr */
957   if(close_after_first || (finished && close_if_end))
958   {
959     DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
960     dptr_close(&dptr_num);
961   }
962
963   /* 
964    * If there are no matching entries we must return ERRDOS/ERRbadfile - 
965    * from observation of NT.
966    */
967
968   if(numentries == 0) {
969           dptr_close(&dptr_num);
970           return ERROR_DOS(ERRDOS,ERRbadfile);
971   }
972
973   /* At this point pdata points to numentries directory entries. */
974
975   /* Set up the return parameter block */
976   SSVAL(params,0,dptr_num);
977   SSVAL(params,2,numentries);
978   SSVAL(params,4,finished);
979   SSVAL(params,6,0); /* Never an EA error */
980   SSVAL(params,8,last_name_off);
981
982   send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
983
984   if ((! *directory) && dptr_path(dptr_num))
985     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
986
987   DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
988             smb_fn_name(CVAL(inbuf,smb_com)), 
989             mask, directory, dirtype, numentries ) );
990
991   /* 
992    * Force a name mangle here to ensure that the
993    * mask as an 8.3 name is top of the mangled cache.
994    * The reasons for this are subtle. Don't remove
995    * this code unless you know what you are doing
996    * (see PR#13758). JRA.
997    */
998
999   if(!is_8_3( mask, False))
1000     name_map_mangle(mask, True, True, SNUM(conn));
1001
1002   return(-1);
1003 }
1004
1005 /****************************************************************************
1006  Reply to a TRANS2_FINDNEXT.
1007 ****************************************************************************/
1008
1009 static int call_trans2findnext(connection_struct *conn, 
1010                                char *inbuf, char *outbuf, 
1011                                int length, int bufsize,
1012                                char **pparams, char **ppdata)
1013 {
1014   /* We must be careful here that we don't return more than the
1015      allowed number of data bytes. If this means returning fewer than
1016      maxentries then so be it. We assume that the redirector has
1017      enough room for the fixed number of parameter bytes it has
1018      requested. */
1019   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1020   char *params = *pparams;
1021   char *pdata = *ppdata;
1022   int dptr_num = SVAL(params,0);
1023   int maxentries = SVAL(params,2);
1024   uint16 info_level = SVAL(params,4);
1025   uint32 resume_key = IVAL(params,6);
1026   BOOL close_after_request = BITSETW(params+10,0);
1027   BOOL close_if_end = BITSETW(params+10,1);
1028   BOOL requires_resume_key = BITSETW(params+10,2);
1029   BOOL continue_bit = BITSETW(params+10,3);
1030   pstring resume_name;
1031   pstring mask;
1032   pstring directory;
1033   char *p;
1034   uint16 dirtype;
1035   int numentries = 0;
1036   int i, last_name_off=0;
1037   BOOL finished = False;
1038   BOOL dont_descend = False;
1039   BOOL out_of_space = False;
1040   int space_remaining;
1041
1042   *mask = *directory = *resume_name = 0;
1043
1044   srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1045
1046   DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1047 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1048 resume_key = %d resume name = %s continue=%d level = %d\n",
1049            dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1050            requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1051
1052   switch (info_level) 
1053     {
1054     case 1:
1055     case 2:
1056     case 3:
1057     case 4:
1058     case SMB_FIND_FILE_DIRECTORY_INFO:
1059     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1060     case SMB_FIND_FILE_NAMES_INFO:
1061     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1062       break;
1063     default:
1064       return ERROR_DOS(ERRDOS,ERRunknownlevel);
1065     }
1066
1067   pdata = Realloc( *ppdata, max_data_bytes + 1024);
1068   if(pdata == NULL) {
1069     return ERROR_DOS(ERRDOS,ERRnomem);
1070   }
1071   *ppdata       = pdata;
1072   memset((char *)pdata,'\0',max_data_bytes + 1024);
1073
1074   /* Realloc the params space */
1075   params = Realloc(*pparams, 6*SIZEOFWORD);
1076   if( params == NULL ) {
1077     return ERROR_DOS(ERRDOS,ERRnomem);
1078   }
1079   *pparams      = params;
1080
1081   /* Check that the dptr is valid */
1082   if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1083     return ERROR_DOS(ERRDOS,ERRnofiles);
1084
1085   string_set(&conn->dirpath,dptr_path(dptr_num));
1086
1087   /* Get the wildcard mask from the dptr */
1088   if((p = dptr_wcard(dptr_num))== NULL) {
1089     DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1090     return ERROR_DOS(ERRDOS,ERRnofiles);
1091   }
1092   pstrcpy(mask, p);
1093   pstrcpy(directory,conn->dirpath);
1094
1095   /* Get the attr mask from the dptr */
1096   dirtype = dptr_attr(dptr_num);
1097
1098   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1099            dptr_num, mask, dirtype, 
1100            (long)conn->dirptr,
1101            TellDir(conn->dirptr)));
1102
1103   /* We don't need to check for VOL here as this is returned by 
1104      a different TRANS2 call. */
1105
1106   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1107   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1108     dont_descend = True;
1109     
1110   p = pdata;
1111   space_remaining = max_data_bytes;
1112   out_of_space = False;
1113
1114   /* 
1115    * Seek to the correct position. We no longer use the resume key but
1116    * depend on the last file name instead.
1117    */
1118   if(requires_resume_key && *resume_name && !continue_bit)
1119   {
1120     /*
1121      * Fix for NT redirector problem triggered by resume key indexes
1122      * changing between directory scans. We now return a resume key of 0
1123      * and instead look for the filename to continue from (also given
1124      * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1125      * findfirst/findnext (as is usual) then the directory pointer
1126      * should already be at the correct place. Check this by scanning
1127      * backwards looking for an exact (ie. case sensitive) filename match. 
1128      * If we get to the beginning of the directory and haven't found it then scan
1129      * forwards again looking for a match. JRA.
1130      */
1131
1132     int current_pos, start_pos;
1133     char *dname = NULL;
1134     void *dirptr = conn->dirptr;
1135     start_pos = TellDir(dirptr);
1136     for(current_pos = start_pos; current_pos >= 0; current_pos--)
1137     {
1138       DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1139
1140       SeekDir(dirptr, current_pos);
1141       dname = ReadDirName(dirptr);
1142
1143       /*
1144        * Remember, name_map_mangle is called by
1145        * get_lanman2_dir_entry(), so the resume name
1146        * could be mangled. Ensure we do the same
1147        * here.
1148        */
1149
1150       if(dname != NULL)
1151         name_map_mangle( dname, False, True, SNUM(conn));
1152
1153       if(dname && strcsequal( resume_name, dname))
1154       {
1155         SeekDir(dirptr, current_pos+1);
1156         DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1157         break;
1158       }
1159     }
1160
1161     /*
1162      * Scan forward from start if not found going backwards.
1163      */
1164
1165     if(current_pos < 0)
1166     {
1167       DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1168       SeekDir(dirptr, start_pos);
1169       for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
1170       {
1171         /*
1172          * Remember, name_map_mangle is called by
1173          * get_lanman2_dir_entry(), so the resume name
1174          * could be mangled. Ensure we do the same
1175          * here.
1176          */
1177
1178         if(dname != NULL)
1179           name_map_mangle( dname, False, True, SNUM(conn));
1180
1181         if(dname && strcsequal( resume_name, dname))
1182         {
1183           SeekDir(dirptr, current_pos+1);
1184           DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1185           break;
1186         }
1187       } /* end for */
1188     } /* end if current_pos */
1189   } /* end if requires_resume_key && !continue_bit */
1190
1191   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1192   {
1193     BOOL got_exact_match = False;
1194
1195     /* this is a heuristic to avoid seeking the dirptr except when 
1196        absolutely necessary. It allows for a filename of about 40 chars */
1197     if (space_remaining < DIRLEN_GUESS && numentries > 0)
1198     {
1199       out_of_space = True;
1200       finished = False;
1201     }
1202     else
1203     {
1204       finished = !get_lanman2_dir_entry(conn,
1205                                         inbuf, outbuf,
1206                                         mask,dirtype,info_level,
1207                                         requires_resume_key,dont_descend,
1208                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1209                                         &last_name_off);
1210     }
1211
1212     if (finished && out_of_space)
1213       finished = False;
1214
1215     if (!finished && !out_of_space)
1216       numentries++;
1217
1218     /*
1219      * As an optimisation if we know we aren't looking
1220      * for a wildcard name (ie. the name matches the wildcard exactly)
1221      * then we can finish on any (first) match.
1222      * This speeds up large directory searches. JRA.
1223      */
1224
1225     if(got_exact_match)
1226       finished = True;
1227
1228     space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1229   }
1230   
1231   /* Check if we can close the dirptr */
1232   if(close_after_request || (finished && close_if_end))
1233   {
1234     DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1235     dptr_close(&dptr_num); /* This frees up the saved mask */
1236   }
1237
1238
1239   /* Set up the return parameter block */
1240   SSVAL(params,0,numentries);
1241   SSVAL(params,2,finished);
1242   SSVAL(params,4,0); /* Never an EA error */
1243   SSVAL(params,6,last_name_off);
1244
1245   send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1246
1247   if ((! *directory) && dptr_path(dptr_num))
1248     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1249
1250   DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1251             smb_fn_name(CVAL(inbuf,smb_com)), 
1252             mask, directory, dirtype, numentries ) );
1253
1254   return(-1);
1255 }
1256
1257 /****************************************************************************
1258  Reply to a TRANS2_QFSINFO (query filesystem info).
1259 ****************************************************************************/
1260
1261 static int call_trans2qfsinfo(connection_struct *conn, 
1262                               char *inbuf, char *outbuf, 
1263                               int length, int bufsize,
1264                               char **pparams, char **ppdata)
1265 {
1266   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1267   char *pdata = *ppdata;
1268   char *params = *pparams;
1269   uint16 info_level = SVAL(params,0);
1270   int data_len, len;
1271   SMB_STRUCT_STAT st;
1272   char *vname = volume_label(SNUM(conn));
1273   int snum = SNUM(conn);
1274   char *fstype = lp_fstype(SNUM(conn));
1275
1276   DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1277
1278   if(vfs_stat(conn,".",&st)!=0) {
1279     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1280     return ERROR_DOS(ERRSRV,ERRinvdevice);
1281   }
1282
1283   pdata = Realloc(*ppdata, max_data_bytes + 1024);
1284   if ( pdata == NULL ) {
1285     return ERROR_DOS(ERRDOS,ERRnomem);
1286   }
1287   *ppdata       = pdata;
1288   memset((char *)pdata,'\0',max_data_bytes + 1024);
1289
1290   switch (info_level) 
1291   {
1292     case 1:
1293     {
1294       SMB_BIG_UINT dfree,dsize,bsize;
1295       data_len = 18;
1296       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);     
1297       SIVAL(pdata,l1_idFileSystem,st.st_dev);
1298       SIVAL(pdata,l1_cSectorUnit,bsize/512);
1299       SIVAL(pdata,l1_cUnit,dsize);
1300       SIVAL(pdata,l1_cUnitAvail,dfree);
1301       SSVAL(pdata,l1_cbSector,512);
1302       DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1303                  (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1304          (unsigned int)dfree, 512));
1305       break;
1306     }
1307     case 2:
1308             /* Return volume name */
1309             /* 
1310              * Add volume serial number - hash of a combination of
1311              * the called hostname and the service name.
1312              */
1313             SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1314             len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, 
1315                               STR_TERMINATE);
1316             SCVAL(pdata,l2_vol_cch,len);
1317             data_len = l2_vol_szVolLabel + len;
1318             DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1319                      (unsigned)st.st_ctime, len, vname));
1320             break;
1321
1322     case SMB_QUERY_FS_ATTRIBUTE_INFO:
1323             SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1324                   (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1325             SIVAL(pdata,4,255); /* Max filename component length */
1326             /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1327                and will think we can't do long filenames */
1328             len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
1329             SIVAL(pdata,8,len);
1330             data_len = 12 + len;
1331             break;
1332
1333     case SMB_QUERY_FS_LABEL_INFO:
1334             len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1335             data_len = 4 + len;
1336             SIVAL(pdata,0,len);
1337             break;
1338     case SMB_QUERY_FS_VOLUME_INFO:      
1339             /* 
1340              * Add volume serial number - hash of a combination of
1341              * the called hostname and the service name.
1342              */
1343             SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
1344                   (str_checksum(local_machine)<<16));
1345
1346             len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1347             SIVAL(pdata,12,len);
1348             data_len = 18+len;
1349             DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
1350                      (int)strlen(vname),vname, lp_servicename(snum)));
1351             break;
1352     case SMB_QUERY_FS_SIZE_INFO:
1353     {
1354       SMB_BIG_UINT dfree,dsize,bsize;
1355       data_len = 24;
1356       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);     
1357       SBIG_UINT(pdata,0,dsize);
1358       SBIG_UINT(pdata,8,dfree);
1359       SIVAL(pdata,16,bsize/512);
1360       SIVAL(pdata,20,512);
1361       break;
1362     }
1363     case SMB_QUERY_FS_DEVICE_INFO:
1364       data_len = 8;
1365       SIVAL(pdata,0,0); /* dev type */
1366       SIVAL(pdata,4,0); /* characteristics */
1367       break;
1368     case SMB_MAC_QUERY_FS_INFO:
1369             /*
1370              * Thursby MAC extension... ONLY on NTFS filesystems
1371              * once we do streams then we don't need this
1372              */
1373             if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1374                     data_len = 88;
1375                     SIVAL(pdata,84,0x100); /* Don't support mac... */
1376                     break;
1377             }
1378             /* drop through */
1379   default:
1380           return ERROR_DOS(ERRDOS,ERRunknownlevel);
1381   }
1382
1383
1384   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1385
1386   DEBUG( 4, ( "%s info_level = %d\n",
1387             smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1388
1389   return -1;
1390 }
1391
1392 /****************************************************************************
1393  Reply to a TRANS2_SETFSINFO (set filesystem info).
1394 ****************************************************************************/
1395
1396 static int call_trans2setfsinfo(connection_struct *conn,
1397                                 char *inbuf, char *outbuf, int length, 
1398                                 int bufsize,
1399                                 char **pparams, char **ppdata)
1400 {
1401   /* Just say yes we did it - there is nothing that
1402      can be set here so it doesn't matter. */
1403   int outsize;
1404   DEBUG(3,("call_trans2setfsinfo\n"));
1405
1406   if (!CAN_WRITE(conn))
1407     return ERROR_DOS(ERRSRV,ERRaccess);
1408
1409   outsize = set_message(outbuf,10,0,True);
1410
1411   return outsize;
1412 }
1413
1414 /****************************************************************************
1415  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1416  file name or file id).
1417 ****************************************************************************/
1418
1419 static int call_trans2qfilepathinfo(connection_struct *conn,
1420                                     char *inbuf, char *outbuf, int length, 
1421                                     int bufsize,
1422                                     char **pparams,char **ppdata,
1423                                     int total_data)
1424 {
1425         int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1426         char *params = *pparams;
1427         char *pdata = *ppdata;
1428         uint16 tran_call = SVAL(inbuf, smb_setup0);
1429         uint16 info_level;
1430         int mode=0;
1431         SMB_OFF_T size=0;
1432         SMB_OFF_T allocation_size=0;
1433         unsigned int data_size;
1434         SMB_STRUCT_STAT sbuf;
1435         pstring fname;
1436         char *base_name;
1437         char *p;
1438         SMB_OFF_T pos = 0;
1439         BOOL bad_path = False;
1440         BOOL delete_pending = False;
1441         int len;
1442         time_t c_time;
1443
1444         if (tran_call == TRANSACT2_QFILEINFO) {
1445                 files_struct *fsp = file_fsp(params,0);
1446                 info_level = SVAL(params,2);
1447
1448                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1449
1450                 if(fsp && (fsp->is_directory || fsp->stat_open)) {
1451                         /*
1452                          * This is actually a QFILEINFO on a directory
1453                          * handle (returned from an NT SMB). NT5.0 seems
1454                          * to do this call. JRA.
1455                          */
1456                         pstrcpy(fname, fsp->fsp_name);
1457                         unix_convert(fname,conn,0,&bad_path,&sbuf);
1458                         if (!check_name(fname,conn) || 
1459                                         (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1460                                 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1461                                 if((errno == ENOENT) && bad_path) {
1462                                         unix_ERR_class = ERRDOS;
1463                                         unix_ERR_code = ERRbadpath;
1464                                 }
1465                                 return(UNIXERROR(ERRDOS,ERRbadpath));
1466                         }
1467                   
1468                         delete_pending = fsp->directory_delete_on_close;
1469                 } else {
1470                         /*
1471                          * Original code - this is an open file.
1472                          */
1473                         CHECK_FSP(fsp,conn);
1474
1475                         pstrcpy(fname, fsp->fsp_name);
1476                         if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1477                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1478                                 return(UNIXERROR(ERRDOS,ERRbadfid));
1479                         }
1480                         if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1481                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1482
1483                         delete_pending = fsp->delete_on_close;
1484                 }
1485         } else {
1486                 /* qpathinfo */
1487                 info_level = SVAL(params,0);
1488
1489                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1490
1491                 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1492
1493                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1494
1495                 unix_convert(fname,conn,0,&bad_path,&sbuf);
1496                 if (!check_name(fname,conn) || 
1497                                 (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1498                         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1499                         if((errno == ENOENT) && bad_path) {
1500                                 unix_ERR_class = ERRDOS;
1501                                 unix_ERR_code = ERRbadpath;
1502                         }
1503                         return(UNIXERROR(ERRDOS,ERRbadpath));
1504                 }
1505         }
1506
1507
1508         DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1509                 fname,info_level,tran_call,total_data));
1510
1511         p = strrchr_m(fname,'/'); 
1512         if (!p)
1513                 base_name = fname;
1514         else
1515                 base_name = p+1;
1516
1517         mode = dos_mode(conn,fname,&sbuf);
1518         size = sbuf.st_size;
1519         allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
1520         
1521         if (mode & aDIR)
1522                 size = 0;
1523
1524         params = Realloc(*pparams,2);
1525         if (params == NULL)
1526           return ERROR_DOS(ERRDOS,ERRnomem);
1527         *pparams = params;
1528         memset((char *)params,'\0',2);
1529         data_size = max_data_bytes + 1024;
1530         pdata = Realloc(*ppdata, data_size); 
1531         if ( pdata == NULL )
1532                 return ERROR_DOS(ERRDOS,ERRnomem);
1533         *ppdata = pdata;
1534
1535         if (total_data > 0 && IVAL(pdata,0) == total_data) {
1536                 /* uggh, EAs for OS2 */
1537                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1538                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1539         }
1540
1541         memset((char *)pdata,'\0',data_size);
1542
1543         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1544
1545         if (lp_dos_filetime_resolution(SNUM(conn))) {
1546                 c_time &= ~1;
1547                 sbuf.st_atime &= ~1;
1548                 sbuf.st_mtime &= ~1;
1549                 sbuf.st_mtime &= ~1;
1550         }
1551
1552         switch (info_level) {
1553                 case SMB_INFO_STANDARD:
1554                 case SMB_INFO_QUERY_EA_SIZE:
1555                         data_size = (info_level==1?22:26);
1556                         put_dos_date2(pdata,l1_fdateCreation,c_time);
1557                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1558                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1559                         SIVAL(pdata,l1_cbFile,(uint32)size);
1560                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1561                         SSVAL(pdata,l1_attrFile,mode);
1562                         SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1563                         break;
1564
1565                 case SMB_INFO_QUERY_EAS_FROM_LIST:
1566                         data_size = 24;
1567                         put_dos_date2(pdata,0,c_time);
1568                         put_dos_date2(pdata,4,sbuf.st_atime);
1569                         put_dos_date2(pdata,8,sbuf.st_mtime);
1570                         SIVAL(pdata,12,(uint32)size);
1571                         SIVAL(pdata,16,(uint32)allocation_size);
1572                         SIVAL(pdata,20,mode);
1573                         break;
1574
1575                 case SMB_INFO_QUERY_ALL_EAS:
1576                         data_size = 4;
1577                         SIVAL(pdata,0,data_size);
1578                         break;
1579
1580                 case 6:
1581                         return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */      
1582
1583                 case SMB_FILE_BASIC_INFORMATION:
1584                 case SMB_QUERY_FILE_BASIC_INFO:
1585
1586                         if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1587                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1588                         else {
1589                                 data_size = 40;
1590                                 SIVAL(pdata,36,0);
1591                         }
1592                         put_long_date(pdata,c_time);
1593                         put_long_date(pdata+8,sbuf.st_atime);
1594                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1595                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1596                         SIVAL(pdata,32,mode);
1597
1598                         DEBUG(5,("SMB_QFBI - "));
1599                         {
1600                                 time_t create_time = c_time;
1601                                 DEBUG(5,("create: %s ", ctime(&create_time)));
1602                         }
1603                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1604                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1605                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1606                         DEBUG(5,("mode: %x\n", mode));
1607
1608                         break;
1609
1610                 case SMB_FILE_STANDARD_INFORMATION:
1611                 case SMB_QUERY_FILE_STANDARD_INFO:
1612                         data_size = 24;
1613                         /* Fake up allocation size. */
1614                         SOFF_T(pdata,0,allocation_size);
1615                         SOFF_T(pdata,8,size);
1616                         SIVAL(pdata,16,sbuf.st_nlink);
1617                         SCVAL(pdata,20,0);
1618                         SCVAL(pdata,21,(mode&aDIR)?1:0);
1619                         break;
1620
1621                 case SMB_FILE_EA_INFORMATION:
1622                 case SMB_QUERY_FILE_EA_INFO:
1623                         data_size = 4;
1624                         break;
1625
1626                 /* Get the 8.3 name - used if NT SMB was negotiated. */
1627                 case SMB_QUERY_FILE_ALT_NAME_INFO:
1628                 {
1629                         pstring short_name;
1630
1631                         pstrcpy(short_name,base_name);
1632                         /* Mangle if not already 8.3 */
1633                         if(!is_8_3(short_name, True)) {
1634                                 if(!name_map_mangle(short_name,True,True,SNUM(conn)))
1635                                         *short_name = '\0';
1636                         }
1637                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER);
1638                         data_size = 4 + len;
1639                         SIVAL(pdata,0,len);
1640                         break;
1641                 }
1642
1643                 case SMB_QUERY_FILE_NAME_INFO:
1644                         /*
1645                          * The first part of this code is essential
1646                          * to get security descriptors to work on mapped
1647                          * drives. Don't ask how I discovered this unless
1648                          * you like hearing about me suffering.... :-). JRA.
1649                          */
1650                         if(strequal(".", fname)) {
1651                                 len = srvstr_push(outbuf, pdata+4, "\\", -1, STR_TERMINATE);
1652                         } else {
1653                                 len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE);
1654                         }
1655                         data_size = 4 + len;
1656                         SIVAL(pdata,0,len);
1657                         break;
1658
1659                 case SMB_FILE_END_OF_FILE_INFORMATION:
1660                 case SMB_QUERY_FILE_END_OF_FILEINFO:
1661                         data_size = 8;
1662                         SOFF_T(pdata,0,size);
1663                         break;
1664
1665                 case SMB_FILE_ALLOCATION_INFORMATION:
1666                 case SMB_QUERY_FILE_ALLOCATION_INFO:
1667                         data_size = 8;
1668                         SOFF_T(pdata,0,allocation_size);
1669                         break;
1670
1671                 case SMB_QUERY_FILE_ALL_INFO:
1672                         put_long_date(pdata,c_time);
1673                         put_long_date(pdata+8,sbuf.st_atime);
1674                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1675                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1676                         SIVAL(pdata,32,mode);
1677                         pdata += 40;
1678                         SOFF_T(pdata,0,allocation_size);
1679                         SOFF_T(pdata,8,size);
1680                         SIVAL(pdata,16,sbuf.st_nlink);
1681                         SCVAL(pdata,20,delete_pending);
1682                         SCVAL(pdata,21,(mode&aDIR)?1:0);
1683                         pdata += 24;
1684                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); 
1685                         pdata += 8; /* index number */
1686                         pdata += 4; /* EA info */
1687                         if (mode & aRONLY)
1688                                 SIVAL(pdata,0,0xA9);
1689                         else
1690                                 SIVAL(pdata,0,0xd01BF);
1691                         pdata += 4;
1692                         SOFF_T(pdata,0,pos); /* current offset */
1693                         pdata += 8;
1694                         SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1695                         pdata += 4;
1696                         pdata += 4; /* alignment */
1697                         len = srvstr_push(outbuf, pdata+4, fname, -1, STR_TERMINATE);
1698                         SIVAL(pdata,0,len);
1699                         pdata += 4 + len;
1700                         data_size = PTR_DIFF(pdata,(*ppdata));
1701                         break;
1702
1703                 case SMB_FILE_INTERNAL_INFORMATION:
1704                         /* This should be an index number - looks like dev/ino to me :-) */
1705                         SIVAL(pdata,0,sbuf.st_dev);
1706                         SIVAL(pdata,4,sbuf.st_ino);
1707                         data_size = 8;
1708                         break;
1709
1710                 case SMB_FILE_ACCESS_INFORMATION:
1711                         SIVAL(pdata,0,0x12019F); /* ??? */
1712                         data_size = 4;
1713                         break;
1714
1715                 case SMB_FILE_NAME_INFORMATION:
1716                         /* Pathname with leading '\'. */
1717                         {
1718                                 pstring new_fname;
1719                                 size_t byte_len;
1720
1721                                 pstrcpy(new_fname, "\\");
1722                                 pstrcat(new_fname, fname);
1723                                 byte_len = dos_PutUniCode(pdata+4,new_fname,max_data_bytes,False);
1724                                 SIVAL(pdata,0,byte_len);
1725                                 data_size = 4 + byte_len;
1726                                 break;
1727                         }
1728
1729                 case SMB_FILE_DISPOSITION_INFORMATION:
1730                         data_size = 1;
1731                         SCVAL(pdata,0,delete_pending);
1732                         break;
1733
1734                 case SMB_FILE_POSITION_INFORMATION:
1735                         data_size = 8;
1736                         SOFF_T(pdata,0,pos);
1737                         break;
1738
1739                 case SMB_FILE_MODE_INFORMATION:
1740                         SIVAL(pdata,0,mode);
1741                         data_size = 4;
1742                         break;
1743
1744                 case SMB_FILE_ALIGNMENT_INFORMATION:
1745                         SIVAL(pdata,0,0); /* No alignment needed. */
1746                         data_size = 4;
1747                         break;
1748
1749 #if 0
1750         /* Not yet finished... JRA */
1751         case 1018:
1752                 {
1753                         pstring new_fname;
1754                         size_t byte_len;
1755
1756                         put_long_date(pdata,c_time);
1757                         put_long_date(pdata+8,sbuf.st_atime);
1758                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1759                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1760                         SIVAL(pdata,32,mode);
1761                         SIVAL(pdata,36,0); /* ??? */
1762                         SIVAL(pdata,40,0x20); /* ??? */
1763                         SIVAL(pdata,44,0); /* ??? */
1764                         SOFF_T(pdata,48,size);
1765                         SIVAL(pdata,56,0x1); /* ??? */
1766                         SIVAL(pdata,60,0); /* ??? */
1767                         SIVAL(pdata,64,0); /* ??? */
1768                         SIVAL(pdata,68,length); /* Following string length in bytes. */
1769                         dos_PutUniCode(pdata+72,,False);
1770                         break;
1771                 }
1772 #endif
1773
1774                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1775                         /* Last component of pathname. */
1776                         {
1777                                 size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1778                                 SIVAL(pdata,0,byte_len);
1779                                 data_size = 4 + byte_len;
1780                                 break;
1781                         }
1782                 
1783                 case SMB_FILE_STREAM_INFORMATION:
1784                         if (mode & aDIR) {
1785                                 data_size = 0;
1786                         } else {
1787                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1788                                 SIVAL(pdata,0,0); /* ??? */
1789                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1790                                 SOFF_T(pdata,8,size);
1791                                 SIVAL(pdata,16,allocation_size);
1792                                 SIVAL(pdata,20,0); /* ??? */
1793                                 data_size = 24 + byte_len;
1794                         }
1795                         break;
1796
1797                 case SMB_FILE_COMPRESSION_INFORMATION:
1798                         SOFF_T(pdata,0,size);
1799                         SIVAL(pdata,8,0); /* ??? */
1800                         SIVAL(pdata,12,0); /* ??? */
1801                         data_size = 16;
1802                         break;
1803
1804                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
1805                         put_long_date(pdata,c_time);
1806                         put_long_date(pdata+8,sbuf.st_atime);
1807                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1808                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1809                         SIVAL(pdata,32,allocation_size);
1810                         SOFF_T(pdata,40,size);
1811                         SIVAL(pdata,48,mode);
1812                         SIVAL(pdata,52,0); /* ??? */
1813                         data_size = 56;
1814                         break;
1815
1816                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1817                         SIVAL(pdata,0,mode);
1818                         SIVAL(pdata,4,0);
1819                         data_size = 8;
1820                         break;
1821
1822 #if 0
1823                 /* NT4 server just returns "invalid query" to this - if we try to answer 
1824                                 it then NTws gets a BSOD! (tridge) */
1825                 case SMB_QUERY_FILE_STREAM_INFO:
1826                         SIVAL(pdata,0,pos);
1827                         SIVAL(pdata,4,(uint32)size);
1828                         SIVAL(pdata,12,(uint32)allocation_size);
1829                         len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE);
1830                         SIVAL(pdata,20,len);
1831                         data_size = 24 + len;
1832                         break;
1833 #endif
1834
1835                 default:
1836                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1837         }
1838
1839         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
1840
1841         return(-1);
1842 }
1843
1844 /****************************************************************************
1845  Deal with the internal needs of setting the delete on close flag. Note that
1846  as the tdb locking is recursive, it is safe to call this from within 
1847  open_file_shared. JRA.
1848 ****************************************************************************/
1849
1850 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
1851 {
1852         /*
1853          * Only allow delete on close for writable shares.
1854          */
1855
1856         if (delete_on_close && !CAN_WRITE(fsp->conn)) {
1857                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
1858                                 fsp->fsp_name ));
1859                                 return NT_STATUS_ACCESS_DENIED;
1860         }
1861         /*
1862          * Only allow delete on close for files/directories opened with delete intent.
1863          */
1864
1865         if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) {
1866                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
1867                                 fsp->fsp_name ));
1868                                 return NT_STATUS_ACCESS_DENIED;
1869         }
1870
1871         if(fsp->is_directory) {
1872                 fsp->directory_delete_on_close = delete_on_close;
1873                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
1874                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1875         } else if(fsp->stat_open) {
1876
1877                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, stat open %s\n",
1878                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1879
1880         } else {
1881
1882                 files_struct *iterate_fsp;
1883
1884                 /*
1885                  * Modify the share mode entry for all files open
1886                  * on this device and inode to tell other smbds we have 
1887                  * changed the delete on close flag. This will be noticed
1888                  * in the close code, the last closer will delete the file
1889                  * if flag is set.
1890                  */
1891
1892                 DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
1893                                         delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1894
1895                 if (lock_share_entry_fsp(fsp) == False)
1896                                 return NT_STATUS_ACCESS_DENIED;
1897
1898                 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
1899                         DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
1900                                         fsp->fsp_name ));
1901                         unlock_share_entry_fsp(fsp);
1902                         return NT_STATUS_ACCESS_DENIED;
1903                 }
1904
1905                 /*
1906                  * Release the lock.
1907                  */
1908
1909                 unlock_share_entry_fsp(fsp);
1910
1911                 /*
1912                  * Go through all files we have open on the same device and
1913                  * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1914                  * Other smbd's that have this file open will look in the share_mode on close.
1915                  * take care of this (rare) case in close_file(). See the comment there.
1916                  * NB. JRA. We don't really need to do this anymore - all should be taken
1917                  * care of in the share_mode changes in the tdb.
1918                  */
1919
1920                 for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
1921                                 iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
1922                                                 fsp->delete_on_close = delete_on_close;
1923
1924                 /*
1925                  * Set the delete on close flag in the fsp.
1926                  */
1927                 fsp->delete_on_close = delete_on_close;
1928
1929                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
1930                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1931
1932         }
1933
1934         return NT_STATUS_OK;
1935 }
1936
1937 /****************************************************************************
1938  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
1939 ****************************************************************************/
1940
1941 static int call_trans2setfilepathinfo(connection_struct *conn,
1942                                       char *inbuf, char *outbuf, int length, 
1943                                       int bufsize, char **pparams, 
1944                                       char **ppdata, int total_data)
1945 {
1946         char *params = *pparams;
1947         char *pdata = *ppdata;
1948         uint16 tran_call = SVAL(inbuf, smb_setup0);
1949         uint16 info_level;
1950         int mode=0;
1951         SMB_OFF_T size=0;
1952         struct utimbuf tvs;
1953         SMB_STRUCT_STAT sbuf;
1954         pstring fname;
1955         int fd = -1;
1956         BOOL bad_path = False;
1957         files_struct *fsp = NULL;
1958
1959         if (tran_call == TRANSACT2_SETFILEINFO) {
1960                 fsp = file_fsp(params,0);
1961                 info_level = SVAL(params,2);    
1962
1963                 if(fsp && (fsp->is_directory || fsp->stat_open)) {
1964                         /*
1965                          * This is actually a SETFILEINFO on a directory
1966                          * handle (returned from an NT SMB). NT5.0 seems
1967                          * to do this call. JRA.
1968                          */
1969                         pstrcpy(fname, fsp->fsp_name);
1970                         unix_convert(fname,conn,0,&bad_path,&sbuf);
1971                         if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
1972                                 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1973                                 if((errno == ENOENT) && bad_path) {
1974                                         unix_ERR_class = ERRDOS;
1975                                         unix_ERR_code = ERRbadpath;
1976                                 }
1977                                 return(UNIXERROR(ERRDOS,ERRbadpath));
1978                         }
1979                 } else if (fsp && fsp->print_file) {
1980                         /*
1981                          * Doing a DELETE_ON_CLOSE should cancel a print job.
1982                          */
1983                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
1984                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
1985
1986                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
1987         
1988                                 SSVAL(params,0,0);
1989                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1990                                 return(-1);
1991                         }
1992             } else {
1993                         /*
1994                          * Original code - this is an open file.
1995                          */
1996                         CHECK_FSP(fsp,conn);
1997
1998                         pstrcpy(fname, fsp->fsp_name);
1999                         fd = fsp->fd;
2000
2001                         if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2002                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2003                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2004                         }
2005                 }
2006         } else {
2007                 /* set path info */
2008                 info_level = SVAL(params,0);    
2009                 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2010                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2011                 if(!check_name(fname, conn)) {
2012                         if((errno == ENOENT) && bad_path) {
2013                                 unix_ERR_class = ERRDOS;
2014                                 unix_ERR_code = ERRbadpath;
2015                         }
2016                         return(UNIXERROR(ERRDOS,ERRbadpath));
2017                 }
2018  
2019                 if(!VALID_STAT(sbuf)) {
2020                         DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
2021                         if((errno == ENOENT) && bad_path) {
2022                                 unix_ERR_class = ERRDOS;
2023                                 unix_ERR_code = ERRbadpath;
2024                         }
2025                         return(UNIXERROR(ERRDOS,ERRbadpath));
2026                 }    
2027         }
2028
2029         if (!CAN_WRITE(conn))
2030                 return ERROR_DOS(ERRSRV,ERRaccess);
2031
2032         DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2033                 tran_call,fname,info_level,total_data));
2034
2035         /* Realloc the parameter and data sizes */
2036         params = Realloc(*pparams,2);
2037         if(params == NULL)
2038                 return ERROR_DOS(ERRDOS,ERRnomem);
2039         *pparams = params;
2040
2041         SSVAL(params,0,0);
2042
2043         size = sbuf.st_size;
2044         tvs.modtime = sbuf.st_mtime;
2045         tvs.actime = sbuf.st_atime;
2046         mode = dos_mode(conn,fname,&sbuf);
2047
2048         if (total_data > 4 && IVAL(pdata,0) == total_data) {
2049                 /* uggh, EAs for OS2 */
2050                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2051                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2052         }
2053
2054         switch (info_level) {
2055                 case SMB_INFO_STANDARD:
2056                 case SMB_INFO_QUERY_EA_SIZE:
2057                 {
2058                         /* access time */
2059                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2060
2061                         /* write time */
2062                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2063
2064                         mode = SVAL(pdata,l1_attrFile);
2065                         size = IVAL(pdata,l1_cbFile);
2066                         break;
2067                 }
2068
2069                 /* XXXX um, i don't think this is right.
2070                         it's also not in the cifs6.txt spec.
2071                 */
2072                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2073                         tvs.actime = make_unix_date2(pdata+8);
2074                         tvs.modtime = make_unix_date2(pdata+12);
2075                         size = IVAL(pdata,16);
2076                         mode = IVAL(pdata,24);
2077                         break;
2078
2079                 /* XXXX nor this.  not in cifs6.txt, either. */
2080                 case SMB_INFO_QUERY_ALL_EAS:
2081                         tvs.actime = make_unix_date2(pdata+8);
2082                         tvs.modtime = make_unix_date2(pdata+12);
2083                         size = IVAL(pdata,16);
2084                         mode = IVAL(pdata,24);
2085                         break;
2086
2087                 case SMB_SET_FILE_BASIC_INFO:
2088                 case SMB_FILE_BASIC_INFORMATION:
2089                 {
2090                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2091                         time_t write_time;
2092                         time_t changed_time;
2093
2094                         /* Ignore create time at offset pdata. */
2095
2096                         /* access time */
2097                         tvs.actime = interpret_long_date(pdata+8);
2098
2099                         write_time = interpret_long_date(pdata+16);
2100                         changed_time = interpret_long_date(pdata+24);
2101
2102                         tvs.modtime = MIN(write_time, changed_time);
2103
2104                         /* Prefer a defined time to an undefined one. */
2105                         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2106                                 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2107                                         ? changed_time : write_time);
2108
2109                         /* attributes */
2110                         mode = IVAL(pdata,32);
2111                         break;
2112                 }
2113
2114                 case  SMB_FILE_ALLOCATION_INFORMATION:
2115                 case SMB_SET_FILE_ALLOCATION_INFO:
2116                 {
2117                         int ret = -1;
2118                         SMB_OFF_T allocation_size = IVAL(pdata,0);
2119 #ifdef LARGE_SMB_OFF_T
2120                         allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2121 #else /* LARGE_SMB_OFF_T */
2122                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2123                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2124 #endif /* LARGE_SMB_OFF_T */
2125                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2126                                         fname, (double)allocation_size ));
2127
2128                         if(allocation_size != sbuf.st_size) {
2129                                 SMB_STRUCT_STAT new_sbuf;
2130  
2131                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2132                                         fname, (double)allocation_size ));
2133  
2134                                 if (fd == -1) {
2135                                         files_struct *new_fsp = NULL;
2136                                         int access_mode = 0;
2137                                         int action = 0;
2138  
2139                                         if(global_oplock_break) {
2140                                                 /* Queue this file modify as we are the process of an oplock break.  */
2141  
2142                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2143                                                 DEBUGADD(2,( "in oplock break state.\n"));
2144  
2145                                                 push_oplock_pending_smb_message(inbuf, length);
2146                                                 return -1;
2147                                         }
2148  
2149                                         new_fsp = open_file_shared(conn, fname, &sbuf,
2150                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
2151                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2152                                                                         0, 0, &access_mode, &action);
2153  
2154                                         if (new_fsp == NULL)
2155                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
2156                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
2157                                         if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2158                                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",new_fsp->fnum, strerror(errno)));
2159                                                 ret = -1;
2160                                         }
2161                                         close_file(new_fsp,True);
2162                                 } else {
2163                                         ret = vfs_allocate_file_space(fsp, size);
2164                                         if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2165                                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2166                                                 ret = -1;
2167                                         }
2168                                 }
2169                                 if (ret == -1)
2170                                         return ERROR_NT(NT_STATUS_DISK_FULL);
2171
2172                                 /* Allocate can trucate size... */
2173                                 size = new_sbuf.st_size;
2174                         }
2175
2176                         break;
2177                 }
2178
2179         case SMB_FILE_END_OF_FILE_INFORMATION:
2180                 case SMB_SET_FILE_END_OF_FILE_INFO:
2181                 {
2182                         size = IVAL(pdata,0);
2183 #ifdef LARGE_SMB_OFF_T
2184                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2185 #else /* LARGE_SMB_OFF_T */
2186                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2187                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2188 #endif /* LARGE_SMB_OFF_T */
2189                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2190                         break;
2191                 }
2192
2193                 case SMB_FILE_DISPOSITION_INFORMATION:
2194                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2195                 {
2196                         BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2197                         NTSTATUS status;
2198
2199                         if (tran_call != TRANSACT2_SETFILEINFO)
2200                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2201
2202                         if (fsp == NULL)
2203                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2204
2205                         status = set_delete_on_close_internal(fsp, delete_on_close);
2206  
2207                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
2208                                 return ERROR_NT(status);
2209
2210                         break;
2211                 }
2212
2213                 default:
2214                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2215         }
2216
2217         /* get some defaults (no modifications) if any info is zero or -1. */
2218         if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2219                 tvs.actime = sbuf.st_atime;
2220
2221         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2222                 tvs.modtime = sbuf.st_mtime;
2223
2224         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2225         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2226         DEBUG(6,("size: %.0f ", (double)size));
2227         DEBUG(6,("mode: %x\n"  , mode));
2228
2229         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2230                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2231                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2232                         (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2233
2234                 /*
2235                  * Only do this test if we are not explicitly
2236                  * changing the size of a file.
2237                  */
2238                 if (!size)
2239                         size = sbuf.st_size;
2240         }
2241
2242         /*
2243          * Try and set the times, size and mode of this file -
2244          * if they are different from the current values
2245          */
2246         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2247                 if(fsp != NULL) {
2248                         /*
2249                          * This was a setfileinfo on an open file.
2250                          * NT does this a lot. It's actually pointless
2251                          * setting the time here, as it will be overwritten
2252                          * on the next write, so we save the request
2253                          * away and will set it on file code. JRA.
2254                          */
2255
2256                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2257                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2258                                 fsp->pending_modtime = tvs.modtime;
2259                         }
2260
2261                 } else {
2262
2263                         DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2264
2265                         if(file_utime(conn, fname, &tvs)!=0)
2266                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2267                 }
2268         }
2269
2270         /* check the mode isn't different, before changing it */
2271         if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) {
2272
2273                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, mode ));
2274
2275                 if(file_chmod(conn, fname, mode, NULL)) {
2276                         DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2277                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2278                 }
2279         }
2280
2281         if(size != sbuf.st_size) {
2282
2283                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2284                         fname, (double)size ));
2285
2286                 if (fd == -1) {
2287                         files_struct *new_fsp = NULL;
2288                         int access_mode = 0;
2289                         int action = 0;
2290
2291                         if(global_oplock_break) {
2292                                 /* Queue this file modify as we are the process of an oplock break.  */
2293
2294                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2295                                 DEBUGADD(2,( "in oplock break state.\n"));
2296
2297                                 push_oplock_pending_smb_message(inbuf, length);
2298                                 return -1;
2299                         }
2300
2301                         new_fsp = open_file_shared(conn, fname, &sbuf,
2302                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
2303                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2304                                                 0, 0, &access_mode, &action);
2305         
2306                         if (new_fsp == NULL)
2307                                 return(UNIXERROR(ERRDOS,ERRbadpath));
2308                         vfs_set_filelen(new_fsp, size);
2309                         close_file(new_fsp,True);
2310                 } else {
2311                         vfs_set_filelen(fsp, size);
2312                 }
2313         }
2314
2315         SSVAL(params,0,0);
2316
2317         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2318   
2319         return(-1);
2320 }
2321
2322 /****************************************************************************
2323  Reply to a TRANS2_MKDIR (make directory with extended attributes).
2324 ****************************************************************************/
2325
2326 static int call_trans2mkdir(connection_struct *conn,
2327                             char *inbuf, char *outbuf, int length, int bufsize,
2328                             char **pparams, char **ppdata)
2329 {
2330   char *params = *pparams;
2331   pstring directory;
2332   int ret = -1;
2333   SMB_STRUCT_STAT sbuf;
2334   BOOL bad_path = False;
2335
2336   if (!CAN_WRITE(conn))
2337     return ERROR_DOS(ERRSRV,ERRaccess);
2338
2339   srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
2340
2341   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2342
2343   unix_convert(directory,conn,0,&bad_path,&sbuf);
2344   if (check_name(directory,conn))
2345     ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2346   
2347   if(ret < 0)
2348     {
2349       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2350       if((errno == ENOENT) && bad_path)
2351       {
2352         unix_ERR_class = ERRDOS;
2353         unix_ERR_code = ERRbadpath;
2354       }
2355       return(UNIXERROR(ERRDOS,ERRnoaccess));
2356     }
2357
2358   /* Realloc the parameter and data sizes */
2359   params = Realloc(*pparams,2);
2360   if(params == NULL) {
2361     return ERROR_DOS(ERRDOS,ERRnomem);
2362   }
2363   *pparams      = params;
2364
2365   SSVAL(params,0,0);
2366
2367   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2368   
2369   return(-1);
2370 }
2371
2372 /****************************************************************************
2373  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2374  We don't actually do this - we just send a null response.
2375 ****************************************************************************/
2376
2377 static int call_trans2findnotifyfirst(connection_struct *conn,
2378                                       char *inbuf, char *outbuf, 
2379                                       int length, int bufsize,
2380                                       char **pparams, char **ppdata)
2381 {
2382   static uint16 fnf_handle = 257;
2383   char *params = *pparams;
2384   uint16 info_level = SVAL(params,4);
2385
2386   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2387
2388   switch (info_level) 
2389     {
2390     case 1:
2391     case 2:
2392       break;
2393     default:
2394       return ERROR_DOS(ERRDOS,ERRunknownlevel);
2395     }
2396
2397   /* Realloc the parameter and data sizes */
2398   params = Realloc(*pparams,6);
2399   if(params == NULL) {
2400     return ERROR_DOS(ERRDOS,ERRnomem);
2401   }
2402   *pparams      = params;
2403
2404   SSVAL(params,0,fnf_handle);
2405   SSVAL(params,2,0); /* No changes */
2406   SSVAL(params,4,0); /* No EA errors */
2407
2408   fnf_handle++;
2409
2410   if(fnf_handle == 0)
2411     fnf_handle = 257;
2412
2413   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2414   
2415   return(-1);
2416 }
2417
2418 /****************************************************************************
2419  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
2420  changes). Currently this does nothing.
2421 ****************************************************************************/
2422
2423 static int call_trans2findnotifynext(connection_struct *conn,
2424                                      char *inbuf, char *outbuf, 
2425                                      int length, int bufsize,
2426                                      char **pparams, char **ppdata)
2427 {
2428   char *params = *pparams;
2429
2430   DEBUG(3,("call_trans2findnotifynext\n"));
2431
2432   /* Realloc the parameter and data sizes */
2433   params = Realloc(*pparams,4);
2434   if(params == NULL) {
2435     return ERROR_DOS(ERRDOS,ERRnomem);
2436   }
2437   *pparams      = params;
2438
2439   SSVAL(params,0,0); /* No changes */
2440   SSVAL(params,2,0); /* No EA errors */
2441
2442   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2443   
2444   return(-1);
2445 }
2446
2447 /****************************************************************************
2448  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2449 ****************************************************************************/
2450
2451 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2452                                      char* outbuf, int length, int bufsize,
2453                                      char** pparams, char** ppdata)
2454 {
2455   char *params = *pparams;
2456   pstring pathname;
2457   int reply_size = 0;
2458   int max_referral_level = SVAL(params,0);
2459
2460
2461   DEBUG(10,("call_trans2getdfsreferral\n"));
2462
2463   if(!lp_host_msdfs())
2464     return ERROR_DOS(ERRDOS,ERRbadfunc);
2465
2466   srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
2467
2468   if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2469     return ERROR_DOS(ERRDOS,ERRbadfile);
2470     
2471   SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2472   send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2473
2474   return(-1);
2475 }
2476
2477 #define LMCAT_SPL       0x53
2478 #define LMFUNC_GETJOBID 0x60
2479
2480 /****************************************************************************
2481  Reply to a TRANS2_IOCTL - used for OS/2 printing.
2482 ****************************************************************************/
2483
2484 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2485                             char* outbuf, int length, int bufsize,
2486                             char** pparams, char** ppdata)
2487 {
2488   char *pdata = *ppdata;
2489   files_struct *fsp = file_fsp(inbuf,smb_vwv15);
2490
2491   if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2492       (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2493     pdata = Realloc(*ppdata, 32);
2494     if(pdata == NULL) {
2495       return ERROR_DOS(ERRDOS,ERRnomem);
2496     }
2497     *ppdata = pdata;
2498
2499         /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
2500            CAN ACCEPT THIS IN UNICODE. JRA. */
2501
2502     SSVAL(pdata,0,fsp->print_jobid);                     /* Job number */
2503         srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
2504     srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
2505     send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
2506     return(-1);
2507   } else {
2508     DEBUG(2,("Unknown TRANS2_IOCTL\n"));
2509     return ERROR_DOS(ERRSRV,ERRerror);
2510   }
2511 }
2512
2513 /****************************************************************************
2514  Reply to a SMBfindclose (stop trans2 directory search).
2515 ****************************************************************************/
2516
2517 int reply_findclose(connection_struct *conn,
2518                     char *inbuf,char *outbuf,int length,int bufsize)
2519 {
2520         int outsize = 0;
2521         int dptr_num=SVALS(inbuf,smb_vwv0);
2522         START_PROFILE(SMBfindclose);
2523
2524         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
2525
2526         dptr_close(&dptr_num);
2527
2528         outsize = set_message(outbuf,0,0,True);
2529
2530         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
2531
2532         END_PROFILE(SMBfindclose);
2533         return(outsize);
2534 }
2535
2536 /****************************************************************************
2537  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
2538 ****************************************************************************/
2539
2540 int reply_findnclose(connection_struct *conn, 
2541                      char *inbuf,char *outbuf,int length,int bufsize)
2542 {
2543         int outsize = 0;
2544         int dptr_num= -1;
2545         START_PROFILE(SMBfindnclose);
2546         
2547         dptr_num = SVAL(inbuf,smb_vwv0);
2548
2549         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2550
2551         /* We never give out valid handles for a 
2552            findnotifyfirst - so any dptr_num is ok here. 
2553            Just ignore it. */
2554
2555         outsize = set_message(outbuf,0,0,True);
2556
2557         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2558
2559         END_PROFILE(SMBfindnclose);
2560         return(outsize);
2561 }
2562
2563 /****************************************************************************
2564  Reply to a SMBtranss2 - just ignore it!
2565 ****************************************************************************/
2566
2567 int reply_transs2(connection_struct *conn,
2568                   char *inbuf,char *outbuf,int length,int bufsize)
2569 {
2570         START_PROFILE(SMBtranss2);
2571         DEBUG(4,("Ignoring transs2 of length %d\n",length));
2572         END_PROFILE(SMBtranss2);
2573         return(-1);
2574 }
2575
2576 /****************************************************************************
2577  Reply to a SMBtrans2.
2578 ****************************************************************************/
2579
2580 int reply_trans2(connection_struct *conn,
2581                  char *inbuf,char *outbuf,int length,int bufsize)
2582 {
2583         int outsize = 0;
2584         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2585         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2586 #if 0
2587         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2588         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2589         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2590         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2591         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2592         int32 timeout = IVALS(inbuf,smb_timeout);
2593 #endif
2594         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2595         unsigned int tran_call = SVAL(inbuf, smb_setup0);
2596         char *params = NULL, *data = NULL;
2597         int num_params, num_params_sofar, num_data, num_data_sofar;
2598         START_PROFILE(SMBtrans2);
2599
2600         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2601                 /* Queue this open message as we are the process of an
2602                  * oplock break.  */
2603
2604                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2605                 DEBUGADD(2,( "in oplock break state.\n"));
2606
2607                 push_oplock_pending_smb_message(inbuf, length);
2608                 END_PROFILE(SMBtrans2);
2609                 return -1;
2610         }
2611         
2612         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
2613             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
2614                 END_PROFILE(SMBtrans2);
2615                 return ERROR_DOS(ERRSRV,ERRaccess);
2616         }
2617
2618         outsize = set_message(outbuf,0,0,True);
2619
2620         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2621            is so as a sanity check */
2622         if (suwcnt != 1) {
2623                 /*
2624                  * Need to have rc=0 for ioctl to get job id for OS/2.
2625                  *  Network printing will fail if function is not successful.
2626                  *  Similar function in reply.c will be used if protocol
2627                  *  is LANMAN1.0 instead of LM1.2X002.
2628                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
2629                  *  outbuf doesn't have to be set(only job id is used).
2630                  */
2631                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
2632                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2633                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2634                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
2635                 } else {
2636                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
2637                         DEBUG(2,("Transaction is %d\n",tran_call));
2638                         END_PROFILE(SMBtrans2);
2639                         return ERROR_DOS(ERRSRV,ERRerror);
2640                 }
2641         }
2642     
2643         /* Allocate the space for the maximum needed parameters and data */
2644         if (total_params > 0)
2645                 params = (char *)malloc(total_params);
2646         if (total_data > 0)
2647                 data = (char *)malloc(total_data);
2648   
2649         if ((total_params && !params)  || (total_data && !data)) {
2650                 DEBUG(2,("Out of memory in reply_trans2\n"));
2651                 SAFE_FREE(params);
2652                 SAFE_FREE(data); 
2653                 END_PROFILE(SMBtrans2);
2654                 return ERROR_DOS(ERRDOS,ERRnomem);
2655         }
2656
2657         /* Copy the param and data bytes sent with this request into
2658            the params buffer */
2659         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2660         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2661
2662         if (num_params > total_params || num_data > total_data)
2663                 exit_server("invalid params in reply_trans2");
2664
2665         if(params)
2666                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2667         if(data)
2668                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2669
2670         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
2671                 /* We need to send an interim response then receive the rest
2672                    of the parameter/data bytes */
2673                 outsize = set_message(outbuf,0,0,True);
2674                 if (!send_smb(smbd_server_fd(),outbuf))
2675                         exit_server("reply_trans2: send_smb failed.");
2676
2677                 while (num_data_sofar < total_data || 
2678                        num_params_sofar < total_params) {
2679                         BOOL ret;
2680
2681                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2682                         
2683                         if ((ret && 
2684                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2685                                 outsize = set_message(outbuf,0,0,True);
2686                                 if(ret)
2687                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2688                                 else
2689                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2690                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2691                                 SAFE_FREE(params);
2692                                 SAFE_FREE(data);
2693                                 END_PROFILE(SMBtrans2);
2694                                 return ERROR_DOS(ERRSRV,ERRerror);
2695                         }
2696       
2697                         /* Revise total_params and total_data in case
2698                            they have changed downwards */
2699                         total_params = SVAL(inbuf, smb_tpscnt);
2700                         total_data = SVAL(inbuf, smb_tdscnt);
2701                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2702                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2703                         if (num_params_sofar > total_params || num_data_sofar > total_data)
2704                                 exit_server("data overflow in trans2");
2705                         
2706                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
2707                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2708                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2709                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2710                 }
2711         }
2712         
2713         if (Protocol >= PROTOCOL_NT1) {
2714                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
2715         }
2716
2717         /* Now we must call the relevant TRANS2 function */
2718         switch(tran_call)  {
2719         case TRANSACT2_OPEN:
2720                 START_PROFILE_NESTED(Trans2_open);
2721                 outsize = call_trans2open(conn, 
2722                                           inbuf, outbuf, bufsize, 
2723                                           &params, &data);
2724                 END_PROFILE_NESTED(Trans2_open);
2725                 break;
2726
2727         case TRANSACT2_FINDFIRST:
2728                 START_PROFILE_NESTED(Trans2_findfirst);
2729                 outsize = call_trans2findfirst(conn, inbuf, outbuf, 
2730                                                bufsize, &params, &data);
2731                 END_PROFILE_NESTED(Trans2_findfirst);
2732                 break;
2733
2734         case TRANSACT2_FINDNEXT:
2735                 START_PROFILE_NESTED(Trans2_findnext);
2736                 outsize = call_trans2findnext(conn, inbuf, outbuf, 
2737                                               length, bufsize, 
2738                                               &params, &data);
2739                 END_PROFILE_NESTED(Trans2_findnext);
2740                 break;
2741
2742         case TRANSACT2_QFSINFO:
2743                 START_PROFILE_NESTED(Trans2_qfsinfo);
2744             outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
2745                                          length, bufsize, &params, 
2746                                          &data);
2747                 END_PROFILE_NESTED(Trans2_qfsinfo);
2748             break;
2749
2750         case TRANSACT2_SETFSINFO:
2751                 START_PROFILE_NESTED(Trans2_setfsinfo);
2752                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
2753                                                length, bufsize, 
2754                                                &params, &data);
2755                 END_PROFILE_NESTED(Trans2_setfsinfo);
2756                 break;
2757
2758         case TRANSACT2_QPATHINFO:
2759         case TRANSACT2_QFILEINFO:
2760                 START_PROFILE_NESTED(Trans2_qpathinfo);
2761                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
2762                                                    length, bufsize, 
2763                                                    &params, &data, total_data);
2764                 END_PROFILE_NESTED(Trans2_qpathinfo);
2765                 break;
2766         case TRANSACT2_SETPATHINFO:
2767         case TRANSACT2_SETFILEINFO:
2768                 START_PROFILE_NESTED(Trans2_setpathinfo);
2769                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
2770                                                      length, bufsize, 
2771                                                      &params, &data, 
2772                                                      total_data);
2773                 END_PROFILE_NESTED(Trans2_setpathinfo);
2774                 break;
2775
2776         case TRANSACT2_FINDNOTIFYFIRST:
2777                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
2778                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
2779                                                      length, bufsize, 
2780                                                      &params, &data);
2781                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
2782                 break;
2783
2784         case TRANSACT2_FINDNOTIFYNEXT:
2785                 START_PROFILE_NESTED(Trans2_findnotifynext);
2786                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
2787                                                     length, bufsize, 
2788                                                     &params, &data);
2789                 END_PROFILE_NESTED(Trans2_findnotifynext);
2790                 break;
2791         case TRANSACT2_MKDIR:
2792                 START_PROFILE_NESTED(Trans2_mkdir);
2793                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
2794                                            bufsize, &params, &data);
2795                 END_PROFILE_NESTED(Trans2_mkdir);
2796                 break;
2797
2798         case TRANSACT2_GET_DFS_REFERRAL:
2799                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
2800         outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length,
2801                                             bufsize, &params, &data);
2802                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
2803                 break;
2804         case TRANSACT2_IOCTL:
2805                 START_PROFILE_NESTED(Trans2_ioctl);
2806                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length,
2807                                                 bufsize,&params,&data);
2808                 END_PROFILE_NESTED(Trans2_ioctl);
2809                 break;
2810         default:
2811                 /* Error in request */
2812                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
2813                 SAFE_FREE(params);
2814                 SAFE_FREE(data);
2815                 END_PROFILE(SMBtrans2);
2816                 return ERROR_DOS(ERRSRV,ERRerror);
2817         }
2818         
2819         /* As we do not know how many data packets will need to be
2820            returned here the various call_trans2xxxx calls
2821            must send their own. Thus a call_trans2xxx routine only
2822            returns a value other than -1 when it wants to send
2823            an error packet. 
2824         */
2825         
2826         SAFE_FREE(params);
2827         SAFE_FREE(data);
2828         END_PROFILE(SMBtrans2);
2829         return outsize; /* If a correct response was needed the
2830                            call_trans2xxx calls have already sent
2831                            it. If outsize != -1 then it is returning */
2832 }