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