Ensure we get a real fd when opening for set file allocation.
[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, 0);
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, 0);
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, 0);
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                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
684                            acl on a dir (tridge) */
685                         len = srvstr_push(outbuf, p, fname, -1, 0);
686                         SIVAL(p, -4, len);
687                         p += len;
688                         len = PTR_DIFF(p, pdata);
689                         len = (len + 3) & ~3;
690                         SIVAL(pdata,0,len);
691                         p = pdata + len;
692                         break;
693
694                 /* CIFS UNIX Extension. */
695
696 #if 0 /* JRA - FIXME - NEEDS UNICODE CONVERSION !!! */
697                 case SMB_FIND_FILE_UNIX:
698
699                         len = 108+strlen(fname)+1;      /* (length of SMB_QUERY_FILE_UNIX_BASIC = 100)+4+4+strlen(fname)*/
700                                                         /* +1 to be sure to transmit the termination of fname */
701                         len = (len + 3) & ~3;
702
703                         SIVAL(p,0,len); p+= 4;       /* Offset from this structure to the beginning of the next one */
704                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
705
706                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
707                         SOFF_T(p,0,sbuf.st_size);             /* File size 64 Bit */
708                         p+= 8;
709
710 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
711                         SOFF_T(p,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
712 #else
713                         /* Can't get the value - fake it using size. */
714                         SOFF_T(p,0,sbuf.st_size);             /* Number of bytes used on disk - 64 Bit */
715 #endif
716                         p+= 8;
717
718                         put_long_date(p,sbuf.st_ctime);       /* Creation Time 64 Bit */
719                         put_long_date(p+8,sbuf.st_atime);     /* Last access time 64 Bit */
720                         put_long_date(p+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
721                         p+= 24;
722
723                         SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
724                         SIVAL(p,4,0);
725                         p+= 8;
726
727                         SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
728                         SIVAL(p,4,0);
729                         p+= 8;
730
731                         SIVAL(p,0,unix_filetype(sbuf.st_mode));
732                         p+= 4;
733
734                         SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
735                         SIVAL(p,4,0);
736                         p+= 8;
737
738                         SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
739                         SIVAL(p,4,0);
740                         p+= 8;
741
742                         SINO_T(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
743                         p+= 8;
744
745                         SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
746                         SIVAL(p,4,0);
747                         p+= 8;
748
749                         SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
750                         SIVAL(p,4,0);
751                         p+= 8;
752
753                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
754                         pstrcpy(p,fname);
755                         p=pdata+len;
756
757                         break;
758 #endif
759
760                 default:      
761                         return(False);
762         }
763
764
765         if (PTR_DIFF(p,pdata) > space_remaining) {
766                 /* Move the dirptr back to prev_dirpos */
767                 SeekDir(conn->dirptr, prev_dirpos);
768                 *out_of_space = True;
769                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
770                 return False; /* Not finished - just out of space */
771         }
772
773         /* Setup the last_filename pointer, as an offset from base_data */
774         *last_name_off = PTR_DIFF(nameptr,base_data);
775         /* Advance the data pointer to the next slot */
776         *ppdata = p;
777
778         return(found);
779 }
780
781 /****************************************************************************
782  Reply to a TRANS2_FINDFIRST.
783 ****************************************************************************/
784
785 static int call_trans2findfirst(connection_struct *conn,
786                                 char *inbuf, char *outbuf, int bufsize,  
787                                 char **pparams, char **ppdata)
788 {
789   /* We must be careful here that we don't return more than the
790      allowed number of data bytes. If this means returning fewer than
791      maxentries then so be it. We assume that the redirector has
792      enough room for the fixed number of parameter bytes it has
793      requested. */
794   uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
795   char *params = *pparams;
796   char *pdata = *ppdata;
797   int dirtype = SVAL(params,0);
798   int maxentries = SVAL(params,2);
799   BOOL close_after_first = BITSETW(params+4,0);
800   BOOL close_if_end = BITSETW(params+4,1);
801   BOOL requires_resume_key = BITSETW(params+4,2);
802   int info_level = SVAL(params,6);
803   pstring directory;
804   pstring mask;
805   char *p, *wcard;
806   int last_name_off=0;
807   int dptr_num = -1;
808   int numentries = 0;
809   int i;
810   BOOL finished = False;
811   BOOL dont_descend = False;
812   BOOL out_of_space = False;
813   int space_remaining;
814   BOOL bad_path = False;
815   SMB_STRUCT_STAT sbuf;
816
817   *directory = *mask = 0;
818
819   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",
820            dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
821            info_level, max_data_bytes));
822   
823   switch (info_level) 
824     {
825     case 1:
826     case 2:
827     case 3:
828     case 4:
829     case SMB_FIND_FILE_DIRECTORY_INFO:
830     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
831     case SMB_FIND_FILE_NAMES_INFO:
832     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
833       break;
834     default:
835       return(ERROR_DOS(ERRDOS,ERRunknownlevel));
836     }
837
838   srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
839
840   RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
841
842   unix_convert(directory,conn,0,&bad_path,&sbuf);
843   if(!check_name(directory,conn)) {
844     if((errno == ENOENT) && bad_path)
845     {
846       unix_ERR_class = ERRDOS;
847       unix_ERR_code = ERRbadpath;
848     }
849
850 #if 0
851     /* Ugly - NT specific hack - maybe not needed ? (JRA) */
852     if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
853        (get_remote_arch() == RA_WINNT))
854     {
855       unix_ERR_class = ERRDOS;
856       unix_ERR_code = ERRbaddirectory;
857     }
858 #endif 
859
860     return(UNIXERROR(ERRDOS,ERRbadpath));
861   }
862
863   p = strrchr_m(directory,'/');
864   if(p == NULL) {
865     pstrcpy(mask,directory);
866     pstrcpy(directory,"./");
867   } else {
868     pstrcpy(mask,p+1);
869     *p = 0;
870   }
871
872   DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
873
874   pdata = Realloc(*ppdata, max_data_bytes + 1024);
875   if( pdata == NULL ) {
876     return(ERROR_DOS(ERRDOS,ERRnomem));
877   }
878   *ppdata       = pdata;
879   memset((char *)pdata,'\0',max_data_bytes + 1024);
880
881   /* Realloc the params space */
882   params = Realloc(*pparams, 10);
883   if (params == NULL) {
884     return ERROR_DOS(ERRDOS,ERRnomem);
885   }
886   *pparams      = params;
887
888   dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
889   if (dptr_num < 0)
890     return(UNIXERROR(ERRDOS,ERRbadfile));
891
892   /* Save the wildcard match and attribs we are using on this directory - 
893      needed as lanman2 assumes these are being saved between calls */
894
895   if(!(wcard = strdup(mask))) {
896     dptr_close(&dptr_num);
897     return ERROR_DOS(ERRDOS,ERRnomem);
898   }
899
900   dptr_set_wcard(dptr_num, wcard);
901   dptr_set_attr(dptr_num, dirtype);
902
903   DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
904
905   /* We don't need to check for VOL here as this is returned by 
906      a different TRANS2 call. */
907   
908   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
909            conn->dirpath,lp_dontdescend(SNUM(conn))));
910   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
911     dont_descend = True;
912     
913   p = pdata;
914   space_remaining = max_data_bytes;
915   out_of_space = False;
916
917   for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
918   {
919     BOOL got_exact_match = False;
920
921     /* this is a heuristic to avoid seeking the dirptr except when 
922        absolutely necessary. It allows for a filename of about 40 chars */
923     if (space_remaining < DIRLEN_GUESS && numentries > 0)
924     {
925       out_of_space = True;
926       finished = False;
927     }
928     else
929     {
930       finished = !get_lanman2_dir_entry(conn,
931                                         inbuf, outbuf,
932                                         mask,dirtype,info_level,
933                                         requires_resume_key,dont_descend,
934                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
935                                         &last_name_off);
936     }
937
938     if (finished && out_of_space)
939       finished = False;
940
941     if (!finished && !out_of_space)
942       numentries++;
943
944     /*
945      * As an optimisation if we know we aren't looking
946      * for a wildcard name (ie. the name matches the wildcard exactly)
947      * then we can finish on any (first) match.
948      * This speeds up large directory searches. JRA.
949      */
950
951     if(got_exact_match)
952       finished = True;
953
954     space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
955   }
956   
957   /* Check if we can close the dirptr */
958   if(close_after_first || (finished && close_if_end))
959   {
960     DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
961     dptr_close(&dptr_num);
962   }
963
964   /* 
965    * If there are no matching entries we must return ERRDOS/ERRbadfile - 
966    * from observation of NT.
967    */
968
969   if(numentries == 0) {
970           dptr_close(&dptr_num);
971           return ERROR_DOS(ERRDOS,ERRbadfile);
972   }
973
974   /* At this point pdata points to numentries directory entries. */
975
976   /* Set up the return parameter block */
977   SSVAL(params,0,dptr_num);
978   SSVAL(params,2,numentries);
979   SSVAL(params,4,finished);
980   SSVAL(params,6,0); /* Never an EA error */
981   SSVAL(params,8,last_name_off);
982
983   send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
984
985   if ((! *directory) && dptr_path(dptr_num))
986     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
987
988   DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
989             smb_fn_name(CVAL(inbuf,smb_com)), 
990             mask, directory, dirtype, numentries ) );
991
992   /* 
993    * Force a name mangle here to ensure that the
994    * mask as an 8.3 name is top of the mangled cache.
995    * The reasons for this are subtle. Don't remove
996    * this code unless you know what you are doing
997    * (see PR#13758). JRA.
998    */
999
1000   if(!is_8_3( mask, False))
1001     name_map_mangle(mask, True, True, SNUM(conn));
1002
1003   return(-1);
1004 }
1005
1006 /****************************************************************************
1007  Reply to a TRANS2_FINDNEXT.
1008 ****************************************************************************/
1009
1010 static int call_trans2findnext(connection_struct *conn, 
1011                                char *inbuf, char *outbuf, 
1012                                int length, int bufsize,
1013                                char **pparams, char **ppdata)
1014 {
1015   /* We must be careful here that we don't return more than the
1016      allowed number of data bytes. If this means returning fewer than
1017      maxentries then so be it. We assume that the redirector has
1018      enough room for the fixed number of parameter bytes it has
1019      requested. */
1020   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1021   char *params = *pparams;
1022   char *pdata = *ppdata;
1023   int dptr_num = SVAL(params,0);
1024   int maxentries = SVAL(params,2);
1025   uint16 info_level = SVAL(params,4);
1026   uint32 resume_key = IVAL(params,6);
1027   BOOL close_after_request = BITSETW(params+10,0);
1028   BOOL close_if_end = BITSETW(params+10,1);
1029   BOOL requires_resume_key = BITSETW(params+10,2);
1030   BOOL continue_bit = BITSETW(params+10,3);
1031   pstring resume_name;
1032   pstring mask;
1033   pstring directory;
1034   char *p;
1035   uint16 dirtype;
1036   int numentries = 0;
1037   int i, last_name_off=0;
1038   BOOL finished = False;
1039   BOOL dont_descend = False;
1040   BOOL out_of_space = False;
1041   int space_remaining;
1042
1043   *mask = *directory = *resume_name = 0;
1044
1045   srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1046
1047   DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1048 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1049 resume_key = %d resume name = %s continue=%d level = %d\n",
1050            dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1051            requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1052
1053   switch (info_level) 
1054     {
1055     case 1:
1056     case 2:
1057     case 3:
1058     case 4:
1059     case SMB_FIND_FILE_DIRECTORY_INFO:
1060     case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1061     case SMB_FIND_FILE_NAMES_INFO:
1062     case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1063       break;
1064     default:
1065       return ERROR_DOS(ERRDOS,ERRunknownlevel);
1066     }
1067
1068   pdata = Realloc( *ppdata, max_data_bytes + 1024);
1069   if(pdata == NULL) {
1070     return ERROR_DOS(ERRDOS,ERRnomem);
1071   }
1072   *ppdata       = pdata;
1073   memset((char *)pdata,'\0',max_data_bytes + 1024);
1074
1075   /* Realloc the params space */
1076   params = Realloc(*pparams, 6*SIZEOFWORD);
1077   if( params == NULL ) {
1078     return ERROR_DOS(ERRDOS,ERRnomem);
1079   }
1080   *pparams      = params;
1081
1082   /* Check that the dptr is valid */
1083   if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1084     return ERROR_DOS(ERRDOS,ERRnofiles);
1085
1086   string_set(&conn->dirpath,dptr_path(dptr_num));
1087
1088   /* Get the wildcard mask from the dptr */
1089   if((p = dptr_wcard(dptr_num))== NULL) {
1090     DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1091     return ERROR_DOS(ERRDOS,ERRnofiles);
1092   }
1093   pstrcpy(mask, p);
1094   pstrcpy(directory,conn->dirpath);
1095
1096   /* Get the attr mask from the dptr */
1097   dirtype = dptr_attr(dptr_num);
1098
1099   DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1100            dptr_num, mask, dirtype, 
1101            (long)conn->dirptr,
1102            TellDir(conn->dirptr)));
1103
1104   /* We don't need to check for VOL here as this is returned by 
1105      a different TRANS2 call. */
1106
1107   DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1108   if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1109     dont_descend = True;
1110     
1111   p = pdata;
1112   space_remaining = max_data_bytes;
1113   out_of_space = False;
1114
1115   /* 
1116    * Seek to the correct position. We no longer use the resume key but
1117    * depend on the last file name instead.
1118    */
1119   if(requires_resume_key && *resume_name && !continue_bit)
1120   {
1121     /*
1122      * Fix for NT redirector problem triggered by resume key indexes
1123      * changing between directory scans. We now return a resume key of 0
1124      * and instead look for the filename to continue from (also given
1125      * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1126      * findfirst/findnext (as is usual) then the directory pointer
1127      * should already be at the correct place. Check this by scanning
1128      * backwards looking for an exact (ie. case sensitive) filename match. 
1129      * If we get to the beginning of the directory and haven't found it then scan
1130      * forwards again looking for a match. JRA.
1131      */
1132
1133     int current_pos, start_pos;
1134     char *dname = NULL;
1135     void *dirptr = conn->dirptr;
1136     start_pos = TellDir(dirptr);
1137     for(current_pos = start_pos; current_pos >= 0; current_pos--)
1138     {
1139       DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1140
1141       SeekDir(dirptr, current_pos);
1142       dname = ReadDirName(dirptr);
1143
1144       /*
1145        * Remember, name_map_mangle is called by
1146        * get_lanman2_dir_entry(), so the resume name
1147        * could be mangled. Ensure we do the same
1148        * here.
1149        */
1150
1151       if(dname != NULL)
1152         name_map_mangle( dname, False, True, SNUM(conn));
1153
1154       if(dname && strcsequal( resume_name, dname))
1155       {
1156         SeekDir(dirptr, current_pos+1);
1157         DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1158         break;
1159       }
1160     }
1161
1162     /*
1163      * Scan forward from start if not found going backwards.
1164      */
1165
1166     if(current_pos < 0)
1167     {
1168       DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1169       SeekDir(dirptr, start_pos);
1170       for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
1171       {
1172         /*
1173          * Remember, name_map_mangle is called by
1174          * get_lanman2_dir_entry(), so the resume name
1175          * could be mangled. Ensure we do the same
1176          * here.
1177          */
1178
1179         if(dname != NULL)
1180           name_map_mangle( dname, False, True, SNUM(conn));
1181
1182         if(dname && strcsequal( resume_name, dname))
1183         {
1184           SeekDir(dirptr, current_pos+1);
1185           DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1186           break;
1187         }
1188       } /* end for */
1189     } /* end if current_pos */
1190   } /* end if requires_resume_key && !continue_bit */
1191
1192   for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
1193   {
1194     BOOL got_exact_match = False;
1195
1196     /* this is a heuristic to avoid seeking the dirptr except when 
1197        absolutely necessary. It allows for a filename of about 40 chars */
1198     if (space_remaining < DIRLEN_GUESS && numentries > 0)
1199     {
1200       out_of_space = True;
1201       finished = False;
1202     }
1203     else
1204     {
1205       finished = !get_lanman2_dir_entry(conn,
1206                                         inbuf, outbuf,
1207                                         mask,dirtype,info_level,
1208                                         requires_resume_key,dont_descend,
1209                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1210                                         &last_name_off);
1211     }
1212
1213     if (finished && out_of_space)
1214       finished = False;
1215
1216     if (!finished && !out_of_space)
1217       numentries++;
1218
1219     /*
1220      * As an optimisation if we know we aren't looking
1221      * for a wildcard name (ie. the name matches the wildcard exactly)
1222      * then we can finish on any (first) match.
1223      * This speeds up large directory searches. JRA.
1224      */
1225
1226     if(got_exact_match)
1227       finished = True;
1228
1229     space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1230   }
1231   
1232   /* Check if we can close the dirptr */
1233   if(close_after_request || (finished && close_if_end))
1234   {
1235     DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1236     dptr_close(&dptr_num); /* This frees up the saved mask */
1237   }
1238
1239
1240   /* Set up the return parameter block */
1241   SSVAL(params,0,numentries);
1242   SSVAL(params,2,finished);
1243   SSVAL(params,4,0); /* Never an EA error */
1244   SSVAL(params,6,last_name_off);
1245
1246   send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1247
1248   if ((! *directory) && dptr_path(dptr_num))
1249     slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1250
1251   DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1252             smb_fn_name(CVAL(inbuf,smb_com)), 
1253             mask, directory, dirtype, numentries ) );
1254
1255   return(-1);
1256 }
1257
1258 /****************************************************************************
1259  Reply to a TRANS2_QFSINFO (query filesystem info).
1260 ****************************************************************************/
1261
1262 static int call_trans2qfsinfo(connection_struct *conn, 
1263                               char *inbuf, char *outbuf, 
1264                               int length, int bufsize,
1265                               char **pparams, char **ppdata)
1266 {
1267   int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1268   char *pdata = *ppdata;
1269   char *params = *pparams;
1270   uint16 info_level = SVAL(params,0);
1271   int data_len, len;
1272   SMB_STRUCT_STAT st;
1273   char *vname = volume_label(SNUM(conn));
1274   int snum = SNUM(conn);
1275   char *fstype = lp_fstype(SNUM(conn));
1276
1277   DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1278
1279   if(vfs_stat(conn,".",&st)!=0) {
1280     DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1281     return ERROR_DOS(ERRSRV,ERRinvdevice);
1282   }
1283
1284   pdata = Realloc(*ppdata, max_data_bytes + 1024);
1285   if ( pdata == NULL ) {
1286     return ERROR_DOS(ERRDOS,ERRnomem);
1287   }
1288   *ppdata       = pdata;
1289   memset((char *)pdata,'\0',max_data_bytes + 1024);
1290
1291   switch (info_level) 
1292   {
1293     case 1:
1294     {
1295       SMB_BIG_UINT dfree,dsize,bsize;
1296       data_len = 18;
1297       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);     
1298       SIVAL(pdata,l1_idFileSystem,st.st_dev);
1299       SIVAL(pdata,l1_cSectorUnit,bsize/512);
1300       SIVAL(pdata,l1_cUnit,dsize);
1301       SIVAL(pdata,l1_cUnitAvail,dfree);
1302       SSVAL(pdata,l1_cbSector,512);
1303       DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1304                  (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1305          (unsigned int)dfree, 512));
1306       break;
1307     }
1308     case 2:
1309             /* Return volume name */
1310             /* 
1311              * Add volume serial number - hash of a combination of
1312              * the called hostname and the service name.
1313              */
1314             SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1315             len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, 
1316                               STR_TERMINATE);
1317             SCVAL(pdata,l2_vol_cch,len);
1318             data_len = l2_vol_szVolLabel + len;
1319             DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1320                      (unsigned)st.st_ctime, len, vname));
1321             break;
1322
1323     case SMB_QUERY_FS_ATTRIBUTE_INFO:
1324             SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1325                   (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1326             SIVAL(pdata,4,255); /* Max filename component length */
1327             /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1328                and will think we can't do long filenames */
1329             len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
1330             SIVAL(pdata,8,len);
1331             data_len = 12 + len;
1332             break;
1333
1334     case SMB_QUERY_FS_LABEL_INFO:
1335             len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1336             data_len = 4 + len;
1337             SIVAL(pdata,0,len);
1338             break;
1339     case SMB_QUERY_FS_VOLUME_INFO:      
1340             /* 
1341              * Add volume serial number - hash of a combination of
1342              * the called hostname and the service name.
1343              */
1344             SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
1345                   (str_checksum(local_machine)<<16));
1346
1347             len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1348             SIVAL(pdata,12,len);
1349             data_len = 18+len;
1350             DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
1351                      (int)strlen(vname),vname, lp_servicename(snum)));
1352             break;
1353     case SMB_QUERY_FS_SIZE_INFO:
1354     {
1355       SMB_BIG_UINT dfree,dsize,bsize;
1356       data_len = 24;
1357       conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);     
1358       SBIG_UINT(pdata,0,dsize);
1359       SBIG_UINT(pdata,8,dfree);
1360       SIVAL(pdata,16,bsize/512);
1361       SIVAL(pdata,20,512);
1362       break;
1363     }
1364     case SMB_QUERY_FS_DEVICE_INFO:
1365       data_len = 8;
1366       SIVAL(pdata,0,0); /* dev type */
1367       SIVAL(pdata,4,0); /* characteristics */
1368       break;
1369     case SMB_MAC_QUERY_FS_INFO:
1370             /*
1371              * Thursby MAC extension... ONLY on NTFS filesystems
1372              * once we do streams then we don't need this
1373              */
1374             if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1375                     data_len = 88;
1376                     SIVAL(pdata,84,0x100); /* Don't support mac... */
1377                     break;
1378             }
1379             /* drop through */
1380   default:
1381           return ERROR_DOS(ERRDOS,ERRunknownlevel);
1382   }
1383
1384
1385   send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1386
1387   DEBUG( 4, ( "%s info_level = %d\n",
1388             smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1389
1390   return -1;
1391 }
1392
1393 /****************************************************************************
1394  Reply to a TRANS2_SETFSINFO (set filesystem info).
1395 ****************************************************************************/
1396
1397 static int call_trans2setfsinfo(connection_struct *conn,
1398                                 char *inbuf, char *outbuf, int length, 
1399                                 int bufsize,
1400                                 char **pparams, char **ppdata)
1401 {
1402   /* Just say yes we did it - there is nothing that
1403      can be set here so it doesn't matter. */
1404   int outsize;
1405   DEBUG(3,("call_trans2setfsinfo\n"));
1406
1407   if (!CAN_WRITE(conn))
1408     return ERROR_DOS(ERRSRV,ERRaccess);
1409
1410   outsize = set_message(outbuf,10,0,True);
1411
1412   return outsize;
1413 }
1414
1415 /****************************************************************************
1416  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1417  file name or file id).
1418 ****************************************************************************/
1419
1420 static int call_trans2qfilepathinfo(connection_struct *conn,
1421                                     char *inbuf, char *outbuf, int length, 
1422                                     int bufsize,
1423                                     char **pparams,char **ppdata,
1424                                     int total_data)
1425 {
1426         int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1427         char *params = *pparams;
1428         char *pdata = *ppdata;
1429         uint16 tran_call = SVAL(inbuf, smb_setup0);
1430         uint16 info_level;
1431         int mode=0;
1432         SMB_OFF_T size=0;
1433         SMB_OFF_T allocation_size=0;
1434         unsigned int data_size;
1435         SMB_STRUCT_STAT sbuf;
1436         pstring fname, dos_fname;
1437         char *base_name;
1438         char *p;
1439         SMB_OFF_T pos = 0;
1440         BOOL bad_path = False;
1441         BOOL delete_pending = False;
1442         int len;
1443         time_t c_time;
1444
1445         if (!params) {
1446                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1447         }
1448
1449         if (tran_call == TRANSACT2_QFILEINFO) {
1450                 files_struct *fsp = file_fsp(params,0);
1451                 info_level = SVAL(params,2);
1452
1453                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1454
1455                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1456                         /*
1457                          * This is actually a QFILEINFO on a directory
1458                          * handle (returned from an NT SMB). NT5.0 seems
1459                          * to do this call. JRA.
1460                          */
1461                         pstrcpy(fname, fsp->fsp_name);
1462                         unix_convert(fname,conn,0,&bad_path,&sbuf);
1463                         if (!check_name(fname,conn) || 
1464                                         (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1465                                 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1466                                 if((errno == ENOENT) && bad_path) {
1467                                         unix_ERR_class = ERRDOS;
1468                                         unix_ERR_code = ERRbadpath;
1469                                 }
1470                                 return(UNIXERROR(ERRDOS,ERRbadpath));
1471                         }
1472                   
1473                         delete_pending = fsp->directory_delete_on_close;
1474                 } else {
1475                         /*
1476                          * Original code - this is an open file.
1477                          */
1478                         CHECK_FSP(fsp,conn);
1479
1480                         pstrcpy(fname, fsp->fsp_name);
1481                         if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1482                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1483                                 return(UNIXERROR(ERRDOS,ERRbadfid));
1484                         }
1485                         if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1486                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1487
1488                         delete_pending = fsp->delete_on_close;
1489                 }
1490         } else {
1491                 /* qpathinfo */
1492                 info_level = SVAL(params,0);
1493
1494                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1495
1496                 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1497
1498                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1499
1500                 unix_convert(fname,conn,0,&bad_path,&sbuf);
1501                 if (!check_name(fname,conn) || 
1502                                 (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1503                         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1504                         if((errno == ENOENT) && bad_path) {
1505                                 unix_ERR_class = ERRDOS;
1506                                 unix_ERR_code = ERRbadpath;
1507                         }
1508                         return(UNIXERROR(ERRDOS,ERRbadpath));
1509                 }
1510         }
1511
1512
1513         DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1514                 fname,info_level,tran_call,total_data));
1515
1516         p = strrchr_m(fname,'/'); 
1517         if (!p)
1518                 base_name = fname;
1519         else
1520                 base_name = p+1;
1521
1522         mode = dos_mode(conn,fname,&sbuf);
1523         size = sbuf.st_size;
1524         allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
1525         
1526         if (mode & aDIR)
1527                 size = 0;
1528
1529         params = Realloc(*pparams,2);
1530         if (params == NULL)
1531           return ERROR_DOS(ERRDOS,ERRnomem);
1532         *pparams = params;
1533         memset((char *)params,'\0',2);
1534         data_size = max_data_bytes + 1024;
1535         pdata = Realloc(*ppdata, data_size); 
1536         if ( pdata == NULL )
1537                 return ERROR_DOS(ERRDOS,ERRnomem);
1538         *ppdata = pdata;
1539
1540         if (total_data > 0 && IVAL(pdata,0) == total_data) {
1541                 /* uggh, EAs for OS2 */
1542                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1543                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1544         }
1545
1546         memset((char *)pdata,'\0',data_size);
1547
1548         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1549
1550         if (lp_dos_filetime_resolution(SNUM(conn))) {
1551                 c_time &= ~1;
1552                 sbuf.st_atime &= ~1;
1553                 sbuf.st_mtime &= ~1;
1554                 sbuf.st_mtime &= ~1;
1555         }
1556
1557         /* NT expects the name to be in an exact form */
1558         if (strequal(fname,".")) {
1559                 pstrcpy(dos_fname, "\\");
1560         } else {
1561                 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1562                 string_replace( dos_fname, '/', '\\');
1563         }
1564
1565         switch (info_level) {
1566                 case SMB_INFO_STANDARD:
1567                 case SMB_INFO_QUERY_EA_SIZE:
1568                         data_size = (info_level==1?22:26);
1569                         put_dos_date2(pdata,l1_fdateCreation,c_time);
1570                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1571                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1572                         SIVAL(pdata,l1_cbFile,(uint32)size);
1573                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1574                         SSVAL(pdata,l1_attrFile,mode);
1575                         SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1576                         break;
1577
1578                 case SMB_INFO_QUERY_EAS_FROM_LIST:
1579                         data_size = 24;
1580                         put_dos_date2(pdata,0,c_time);
1581                         put_dos_date2(pdata,4,sbuf.st_atime);
1582                         put_dos_date2(pdata,8,sbuf.st_mtime);
1583                         SIVAL(pdata,12,(uint32)size);
1584                         SIVAL(pdata,16,(uint32)allocation_size);
1585                         SIVAL(pdata,20,mode);
1586                         break;
1587
1588                 case SMB_INFO_QUERY_ALL_EAS:
1589                         data_size = 4;
1590                         SIVAL(pdata,0,data_size);
1591                         break;
1592
1593                 case 6:
1594                         return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */      
1595
1596                 case SMB_FILE_BASIC_INFORMATION:
1597                 case SMB_QUERY_FILE_BASIC_INFO:
1598
1599                         if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1600                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1601                         else {
1602                                 data_size = 40;
1603                                 SIVAL(pdata,36,0);
1604                         }
1605                         put_long_date(pdata,c_time);
1606                         put_long_date(pdata+8,sbuf.st_atime);
1607                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1608                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1609                         SIVAL(pdata,32,mode);
1610
1611                         DEBUG(5,("SMB_QFBI - "));
1612                         {
1613                                 time_t create_time = c_time;
1614                                 DEBUG(5,("create: %s ", ctime(&create_time)));
1615                         }
1616                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1617                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1618                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1619                         DEBUG(5,("mode: %x\n", mode));
1620
1621                         break;
1622
1623                 case SMB_FILE_STANDARD_INFORMATION:
1624                 case SMB_QUERY_FILE_STANDARD_INFO:
1625                         data_size = 24;
1626                         /* Fake up allocation size. */
1627                         SOFF_T(pdata,0,allocation_size);
1628                         SOFF_T(pdata,8,size);
1629                         SIVAL(pdata,16,sbuf.st_nlink);
1630                         SCVAL(pdata,20,0);
1631                         SCVAL(pdata,21,(mode&aDIR)?1:0);
1632                         break;
1633
1634                 case SMB_FILE_EA_INFORMATION:
1635                 case SMB_QUERY_FILE_EA_INFO:
1636                         data_size = 4;
1637                         break;
1638
1639                 /* Get the 8.3 name - used if NT SMB was negotiated. */
1640                 case SMB_QUERY_FILE_ALT_NAME_INFO:
1641                 {
1642                         pstring short_name;
1643
1644                         pstrcpy(short_name,base_name);
1645                         /* Mangle if not already 8.3 */
1646                         if(!is_8_3(short_name, True)) {
1647                                 if(!name_map_mangle(short_name,True,True,SNUM(conn)))
1648                                         *short_name = '\0';
1649                         }
1650                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER);
1651                         data_size = 4 + len;
1652                         SIVAL(pdata,0,len);
1653                         break;
1654                 }
1655
1656                 case SMB_QUERY_FILE_NAME_INFO:
1657                         /*
1658                           this must be *exactly* right for ACLs on mapped drives to work
1659                          */
1660                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
1661                         data_size = 4 + len;
1662                         SIVAL(pdata,0,len);
1663                         break;
1664
1665                 case SMB_FILE_END_OF_FILE_INFORMATION:
1666                 case SMB_QUERY_FILE_END_OF_FILEINFO:
1667                         data_size = 8;
1668                         SOFF_T(pdata,0,size);
1669                         break;
1670
1671                 case SMB_FILE_ALLOCATION_INFORMATION:
1672                 case SMB_QUERY_FILE_ALLOCATION_INFO:
1673                         data_size = 8;
1674                         SOFF_T(pdata,0,allocation_size);
1675                         break;
1676
1677                 case SMB_QUERY_FILE_ALL_INFO:
1678                         put_long_date(pdata,c_time);
1679                         put_long_date(pdata+8,sbuf.st_atime);
1680                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1681                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1682                         SIVAL(pdata,32,mode);
1683                         pdata += 40;
1684                         SOFF_T(pdata,0,allocation_size);
1685                         SOFF_T(pdata,8,size);
1686                         SIVAL(pdata,16,sbuf.st_nlink);
1687                         SCVAL(pdata,20,delete_pending);
1688                         SCVAL(pdata,21,(mode&aDIR)?1:0);
1689                         pdata += 24;
1690                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); 
1691                         pdata += 8; /* index number */
1692                         pdata += 4; /* EA info */
1693                         if (mode & aRONLY)
1694                                 SIVAL(pdata,0,0xA9);
1695                         else
1696                                 SIVAL(pdata,0,0xd01BF);
1697                         pdata += 4;
1698                         SOFF_T(pdata,0,pos); /* current offset */
1699                         pdata += 8;
1700                         SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1701                         pdata += 4;
1702                         pdata += 4; /* alignment */
1703                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE);
1704                         SIVAL(pdata,0,len);
1705                         pdata += 4 + len;
1706                         data_size = PTR_DIFF(pdata,(*ppdata));
1707                         break;
1708
1709                 case SMB_FILE_INTERNAL_INFORMATION:
1710                         /* This should be an index number - looks like dev/ino to me :-) */
1711                         SIVAL(pdata,0,sbuf.st_dev);
1712                         SIVAL(pdata,4,sbuf.st_ino);
1713                         data_size = 8;
1714                         break;
1715
1716                 case SMB_FILE_ACCESS_INFORMATION:
1717                         SIVAL(pdata,0,0x12019F); /* ??? */
1718                         data_size = 4;
1719                         break;
1720
1721                 case SMB_FILE_NAME_INFORMATION:
1722                         /* Pathname with leading '\'. */
1723                         {
1724                                 size_t byte_len;
1725                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
1726                                 SIVAL(pdata,0,byte_len);
1727                                 data_size = 4 + byte_len;
1728                                 break;
1729                         }
1730
1731                 case SMB_FILE_DISPOSITION_INFORMATION:
1732                         data_size = 1;
1733                         SCVAL(pdata,0,delete_pending);
1734                         break;
1735
1736                 case SMB_FILE_POSITION_INFORMATION:
1737                         data_size = 8;
1738                         SOFF_T(pdata,0,pos);
1739                         break;
1740
1741                 case SMB_FILE_MODE_INFORMATION:
1742                         SIVAL(pdata,0,mode);
1743                         data_size = 4;
1744                         break;
1745
1746                 case SMB_FILE_ALIGNMENT_INFORMATION:
1747                         SIVAL(pdata,0,0); /* No alignment needed. */
1748                         data_size = 4;
1749                         break;
1750
1751 #if 0
1752         /* Not yet finished... JRA */
1753         case 1018:
1754                 {
1755                         put_long_date(pdata,c_time);
1756                         put_long_date(pdata+8,sbuf.st_atime);
1757                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1758                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1759                         SIVAL(pdata,32,mode);
1760                         SIVAL(pdata,36,0); /* ??? */
1761                         SIVAL(pdata,40,0x20); /* ??? */
1762                         SIVAL(pdata,44,0); /* ??? */
1763                         SOFF_T(pdata,48,size);
1764                         SIVAL(pdata,56,0x1); /* ??? */
1765                         SIVAL(pdata,60,0); /* ??? */
1766                         SIVAL(pdata,64,0); /* ??? */
1767                         SIVAL(pdata,68,length); /* Following string length in bytes. */
1768                         dos_PutUniCode(pdata+72,,False);
1769                         break;
1770                 }
1771 #endif
1772
1773                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1774                         /* Last component of pathname. */
1775                         {
1776                                 size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1777                                 SIVAL(pdata,0,byte_len);
1778                                 data_size = 4 + byte_len;
1779                                 break;
1780                         }
1781                 
1782                 case SMB_FILE_STREAM_INFORMATION:
1783                         if (mode & aDIR) {
1784                                 data_size = 0;
1785                         } else {
1786                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1787                                 SIVAL(pdata,0,0); /* ??? */
1788                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1789                                 SOFF_T(pdata,8,size);
1790                                 SIVAL(pdata,16,allocation_size);
1791                                 SIVAL(pdata,20,0); /* ??? */
1792                                 data_size = 24 + byte_len;
1793                         }
1794                         break;
1795
1796                 case SMB_FILE_COMPRESSION_INFORMATION:
1797                         SOFF_T(pdata,0,size);
1798                         SIVAL(pdata,8,0); /* ??? */
1799                         SIVAL(pdata,12,0); /* ??? */
1800                         data_size = 16;
1801                         break;
1802
1803                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
1804                         put_long_date(pdata,c_time);
1805                         put_long_date(pdata+8,sbuf.st_atime);
1806                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1807                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1808                         SIVAL(pdata,32,allocation_size);
1809                         SOFF_T(pdata,40,size);
1810                         SIVAL(pdata,48,mode);
1811                         SIVAL(pdata,52,0); /* ??? */
1812                         data_size = 56;
1813                         break;
1814
1815                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1816                         SIVAL(pdata,0,mode);
1817                         SIVAL(pdata,4,0);
1818                         data_size = 8;
1819                         break;
1820
1821 #if 0
1822                 /* NT4 server just returns "invalid query" to this - if we try to answer 
1823                                 it then NTws gets a BSOD! (tridge) */
1824                 case SMB_QUERY_FILE_STREAM_INFO:
1825                         SIVAL(pdata,0,pos);
1826                         SIVAL(pdata,4,(uint32)size);
1827                         SIVAL(pdata,12,(uint32)allocation_size);
1828                         len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE);
1829                         SIVAL(pdata,20,len);
1830                         data_size = 24 + len;
1831                         break;
1832 #endif
1833
1834                 default:
1835                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1836         }
1837
1838         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
1839
1840         return(-1);
1841 }
1842
1843 /****************************************************************************
1844  Deal with the internal needs of setting the delete on close flag. Note that
1845  as the tdb locking is recursive, it is safe to call this from within 
1846  open_file_shared. JRA.
1847 ****************************************************************************/
1848
1849 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
1850 {
1851         /*
1852          * Only allow delete on close for writable shares.
1853          */
1854
1855         if (delete_on_close && !CAN_WRITE(fsp->conn)) {
1856                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
1857                                 fsp->fsp_name ));
1858                                 return NT_STATUS_ACCESS_DENIED;
1859         }
1860         /*
1861          * Only allow delete on close for files/directories opened with delete intent.
1862          */
1863
1864         if (delete_on_close && !GET_DELETE_ACCESS_REQUESTED(fsp->share_mode)) {
1865                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
1866                                 fsp->fsp_name ));
1867                                 return NT_STATUS_ACCESS_DENIED;
1868         }
1869
1870         if(fsp->is_directory) {
1871                 fsp->directory_delete_on_close = delete_on_close;
1872                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
1873                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1874         } else {
1875
1876                 files_struct *iterate_fsp;
1877
1878                 /*
1879                  * Modify the share mode entry for all files open
1880                  * on this device and inode to tell other smbds we have 
1881                  * changed the delete on close flag. This will be noticed
1882                  * in the close code, the last closer will delete the file
1883                  * if flag is set.
1884                  */
1885
1886                 DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
1887                                         delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1888
1889                 if (lock_share_entry_fsp(fsp) == False)
1890                                 return NT_STATUS_ACCESS_DENIED;
1891
1892                 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
1893                         DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
1894                                         fsp->fsp_name ));
1895                         unlock_share_entry_fsp(fsp);
1896                         return NT_STATUS_ACCESS_DENIED;
1897                 }
1898
1899                 /*
1900                  * Release the lock.
1901                  */
1902
1903                 unlock_share_entry_fsp(fsp);
1904
1905                 /*
1906                  * Go through all files we have open on the same device and
1907                  * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1908                  * Other smbd's that have this file open will look in the share_mode on close.
1909                  * take care of this (rare) case in close_file(). See the comment there.
1910                  * NB. JRA. We don't really need to do this anymore - all should be taken
1911                  * care of in the share_mode changes in the tdb.
1912                  */
1913
1914                 for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
1915                                 iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
1916                                                 fsp->delete_on_close = delete_on_close;
1917
1918                 /*
1919                  * Set the delete on close flag in the fsp.
1920                  */
1921                 fsp->delete_on_close = delete_on_close;
1922
1923                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
1924                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1925
1926         }
1927
1928         return NT_STATUS_OK;
1929 }
1930
1931 /****************************************************************************
1932  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
1933 ****************************************************************************/
1934
1935 static int call_trans2setfilepathinfo(connection_struct *conn,
1936                                       char *inbuf, char *outbuf, int length, 
1937                                       int bufsize, char **pparams, 
1938                                       char **ppdata, int total_data)
1939 {
1940         char *params = *pparams;
1941         char *pdata = *ppdata;
1942         uint16 tran_call = SVAL(inbuf, smb_setup0);
1943         uint16 info_level;
1944         int mode=0;
1945         SMB_OFF_T size=0;
1946         struct utimbuf tvs;
1947         SMB_STRUCT_STAT sbuf;
1948         pstring fname;
1949         int fd = -1;
1950         BOOL bad_path = False;
1951         files_struct *fsp = NULL;
1952
1953         if (tran_call == TRANSACT2_SETFILEINFO) {
1954                 fsp = file_fsp(params,0);
1955                 info_level = SVAL(params,2);    
1956
1957                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1958                         /*
1959                          * This is actually a SETFILEINFO on a directory
1960                          * handle (returned from an NT SMB). NT5.0 seems
1961                          * to do this call. JRA.
1962                          */
1963                         pstrcpy(fname, fsp->fsp_name);
1964                         unix_convert(fname,conn,0,&bad_path,&sbuf);
1965                         if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
1966                                 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1967                                 if((errno == ENOENT) && bad_path) {
1968                                         unix_ERR_class = ERRDOS;
1969                                         unix_ERR_code = ERRbadpath;
1970                                 }
1971                                 return(UNIXERROR(ERRDOS,ERRbadpath));
1972                         }
1973                 } else if (fsp && fsp->print_file) {
1974                         /*
1975                          * Doing a DELETE_ON_CLOSE should cancel a print job.
1976                          */
1977                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
1978                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
1979
1980                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
1981         
1982                                 SSVAL(params,0,0);
1983                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1984                                 return(-1);
1985                         }
1986             } else {
1987                         /*
1988                          * Original code - this is an open file.
1989                          */
1990                         CHECK_FSP(fsp,conn);
1991
1992                         pstrcpy(fname, fsp->fsp_name);
1993                         fd = fsp->fd;
1994
1995                         if (vfs_fstat(fsp,fd,&sbuf) != 0) {
1996                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1997                                 return(UNIXERROR(ERRDOS,ERRbadfid));
1998                         }
1999                 }
2000         } else {
2001                 /* set path info */
2002                 info_level = SVAL(params,0);    
2003                 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2004                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2005                 if(!check_name(fname, conn)) {
2006                         if((errno == ENOENT) && bad_path) {
2007                                 unix_ERR_class = ERRDOS;
2008                                 unix_ERR_code = ERRbadpath;
2009                         }
2010                         return(UNIXERROR(ERRDOS,ERRbadpath));
2011                 }
2012  
2013                 if(!VALID_STAT(sbuf)) {
2014                         DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
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
2023         if (!CAN_WRITE(conn))
2024                 return ERROR_DOS(ERRSRV,ERRaccess);
2025
2026         DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2027                 tran_call,fname,info_level,total_data));
2028
2029         /* Realloc the parameter and data sizes */
2030         params = Realloc(*pparams,2);
2031         if(params == NULL)
2032                 return ERROR_DOS(ERRDOS,ERRnomem);
2033         *pparams = params;
2034
2035         SSVAL(params,0,0);
2036
2037         size = sbuf.st_size;
2038         tvs.modtime = sbuf.st_mtime;
2039         tvs.actime = sbuf.st_atime;
2040         mode = dos_mode(conn,fname,&sbuf);
2041
2042         if (total_data > 4 && IVAL(pdata,0) == total_data) {
2043                 /* uggh, EAs for OS2 */
2044                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2045                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2046         }
2047
2048         switch (info_level) {
2049                 case SMB_INFO_STANDARD:
2050                 case SMB_INFO_QUERY_EA_SIZE:
2051                 {
2052                         /* access time */
2053                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2054
2055                         /* write time */
2056                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2057
2058                         mode = SVAL(pdata,l1_attrFile);
2059                         size = IVAL(pdata,l1_cbFile);
2060                         break;
2061                 }
2062
2063                 /* XXXX um, i don't think this is right.
2064                         it's also not in the cifs6.txt spec.
2065                 */
2066                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2067                         tvs.actime = make_unix_date2(pdata+8);
2068                         tvs.modtime = make_unix_date2(pdata+12);
2069                         size = IVAL(pdata,16);
2070                         mode = IVAL(pdata,24);
2071                         break;
2072
2073                 /* XXXX nor this.  not in cifs6.txt, either. */
2074                 case SMB_INFO_QUERY_ALL_EAS:
2075                         tvs.actime = make_unix_date2(pdata+8);
2076                         tvs.modtime = make_unix_date2(pdata+12);
2077                         size = IVAL(pdata,16);
2078                         mode = IVAL(pdata,24);
2079                         break;
2080
2081                 case SMB_SET_FILE_BASIC_INFO:
2082                 case SMB_FILE_BASIC_INFORMATION:
2083                 {
2084                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2085                         time_t write_time;
2086                         time_t changed_time;
2087
2088                         /* Ignore create time at offset pdata. */
2089
2090                         /* access time */
2091                         tvs.actime = interpret_long_date(pdata+8);
2092
2093                         write_time = interpret_long_date(pdata+16);
2094                         changed_time = interpret_long_date(pdata+24);
2095
2096                         tvs.modtime = MIN(write_time, changed_time);
2097
2098                         /* Prefer a defined time to an undefined one. */
2099                         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2100                                 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2101                                         ? changed_time : write_time);
2102
2103                         /* attributes */
2104                         mode = IVAL(pdata,32);
2105                         break;
2106                 }
2107
2108                 case  SMB_FILE_ALLOCATION_INFORMATION:
2109                 case SMB_SET_FILE_ALLOCATION_INFO:
2110                 {
2111                         int ret = -1;
2112                         SMB_OFF_T allocation_size = IVAL(pdata,0);
2113 #ifdef LARGE_SMB_OFF_T
2114                         allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2115 #else /* LARGE_SMB_OFF_T */
2116                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2117                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2118 #endif /* LARGE_SMB_OFF_T */
2119                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2120                                         fname, (double)allocation_size ));
2121
2122                         if(allocation_size != sbuf.st_size) {
2123                                 SMB_STRUCT_STAT new_sbuf;
2124  
2125                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2126                                         fname, (double)allocation_size ));
2127  
2128                                 if (fd == -1) {
2129                                         files_struct *new_fsp = NULL;
2130                                         int access_mode = 0;
2131                                         int action = 0;
2132  
2133                                         if(global_oplock_break) {
2134                                                 /* Queue this file modify as we are the process of an oplock break.  */
2135  
2136                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2137                                                 DEBUGADD(2,( "in oplock break state.\n"));
2138  
2139                                                 push_oplock_pending_smb_message(inbuf, length);
2140                                                 return -1;
2141                                         }
2142  
2143                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2144                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
2145                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2146                                                                         0, 0, &access_mode, &action);
2147  
2148                                         if (new_fsp == NULL)
2149                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
2150                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
2151                                         if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2152                                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",new_fsp->fnum, strerror(errno)));
2153                                                 ret = -1;
2154                                         }
2155                                         close_file(new_fsp,True);
2156                                 } else {
2157                                         ret = vfs_allocate_file_space(fsp, size);
2158                                         if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2159                                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2160                                                 ret = -1;
2161                                         }
2162                                 }
2163                                 if (ret == -1)
2164                                         return ERROR_NT(NT_STATUS_DISK_FULL);
2165
2166                                 /* Allocate can trucate size... */
2167                                 size = new_sbuf.st_size;
2168                         }
2169
2170                         break;
2171                 }
2172
2173         case SMB_FILE_END_OF_FILE_INFORMATION:
2174                 case SMB_SET_FILE_END_OF_FILE_INFO:
2175                 {
2176                         size = IVAL(pdata,0);
2177 #ifdef LARGE_SMB_OFF_T
2178                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2179 #else /* LARGE_SMB_OFF_T */
2180                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2181                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2182 #endif /* LARGE_SMB_OFF_T */
2183                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2184                         break;
2185                 }
2186
2187                 case SMB_FILE_DISPOSITION_INFORMATION:
2188                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2189                 {
2190                         BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2191                         NTSTATUS status;
2192
2193                         if (tran_call != TRANSACT2_SETFILEINFO)
2194                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2195
2196                         if (fsp == NULL)
2197                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2198
2199                         status = set_delete_on_close_internal(fsp, delete_on_close);
2200  
2201                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
2202                                 return ERROR_NT(status);
2203
2204                         break;
2205                 }
2206
2207                 default:
2208                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2209         }
2210
2211         /* get some defaults (no modifications) if any info is zero or -1. */
2212         if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2213                 tvs.actime = sbuf.st_atime;
2214
2215         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2216                 tvs.modtime = sbuf.st_mtime;
2217
2218         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2219         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2220         DEBUG(6,("size: %.0f ", (double)size));
2221         DEBUG(6,("mode: %x\n"  , mode));
2222
2223         if (S_ISDIR(sbuf.st_mode))
2224                 mode |= aDIR;
2225         else
2226                 mode &= ~aDIR;
2227
2228         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2229                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2230                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2231                         (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2232
2233                 /*
2234                  * Only do this test if we are not explicitly
2235                  * changing the size of a file.
2236                  */
2237                 if (!size)
2238                         size = sbuf.st_size;
2239         }
2240
2241         /*
2242          * Try and set the times, size and mode of this file -
2243          * if they are different from the current values
2244          */
2245         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2246                 if(fsp != NULL) {
2247                         /*
2248                          * This was a setfileinfo on an open file.
2249                          * NT does this a lot. It's actually pointless
2250                          * setting the time here, as it will be overwritten
2251                          * on the next write, so we save the request
2252                          * away and will set it on file code. JRA.
2253                          */
2254
2255                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2256                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2257                                 fsp->pending_modtime = tvs.modtime;
2258                         }
2259
2260                 } else {
2261
2262                         DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2263
2264                         if(file_utime(conn, fname, &tvs)!=0)
2265                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2266                 }
2267         }
2268
2269         /* check the mode isn't different, before changing it */
2270         if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) {
2271
2272                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, mode ));
2273
2274                 if(file_chmod(conn, fname, mode, NULL)) {
2275                         DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2276                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2277                 }
2278         }
2279
2280         if(size != sbuf.st_size) {
2281
2282                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2283                         fname, (double)size ));
2284
2285                 if (fd == -1) {
2286                         files_struct *new_fsp = NULL;
2287                         int access_mode = 0;
2288                         int action = 0;
2289
2290                         if(global_oplock_break) {
2291                                 /* Queue this file modify as we are the process of an oplock break.  */
2292
2293                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2294                                 DEBUGADD(2,( "in oplock break state.\n"));
2295
2296                                 push_oplock_pending_smb_message(inbuf, length);
2297                                 return -1;
2298                         }
2299
2300                         new_fsp = open_file_shared(conn, fname, &sbuf,
2301                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
2302                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2303                                                 0, 0, &access_mode, &action);
2304         
2305                         if (new_fsp == NULL)
2306                                 return(UNIXERROR(ERRDOS,ERRbadpath));
2307                         vfs_set_filelen(new_fsp, size);
2308                         close_file(new_fsp,True);
2309                 } else {
2310                         vfs_set_filelen(fsp, size);
2311                 }
2312         }
2313
2314         SSVAL(params,0,0);
2315
2316         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2317   
2318         return(-1);
2319 }
2320
2321 /****************************************************************************
2322  Reply to a TRANS2_MKDIR (make directory with extended attributes).
2323 ****************************************************************************/
2324
2325 static int call_trans2mkdir(connection_struct *conn,
2326                             char *inbuf, char *outbuf, int length, int bufsize,
2327                             char **pparams, char **ppdata)
2328 {
2329   char *params = *pparams;
2330   pstring directory;
2331   int ret = -1;
2332   SMB_STRUCT_STAT sbuf;
2333   BOOL bad_path = False;
2334
2335   if (!CAN_WRITE(conn))
2336     return ERROR_DOS(ERRSRV,ERRaccess);
2337
2338   srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
2339
2340   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2341
2342   unix_convert(directory,conn,0,&bad_path,&sbuf);
2343   if (check_name(directory,conn))
2344     ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2345   
2346   if(ret < 0)
2347     {
2348       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2349       if((errno == ENOENT) && bad_path)
2350       {
2351         unix_ERR_class = ERRDOS;
2352         unix_ERR_code = ERRbadpath;
2353       }
2354       return(UNIXERROR(ERRDOS,ERRnoaccess));
2355     }
2356
2357   /* Realloc the parameter and data sizes */
2358   params = Realloc(*pparams,2);
2359   if(params == NULL) {
2360     return ERROR_DOS(ERRDOS,ERRnomem);
2361   }
2362   *pparams      = params;
2363
2364   SSVAL(params,0,0);
2365
2366   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2367   
2368   return(-1);
2369 }
2370
2371 /****************************************************************************
2372  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2373  We don't actually do this - we just send a null response.
2374 ****************************************************************************/
2375
2376 static int call_trans2findnotifyfirst(connection_struct *conn,
2377                                       char *inbuf, char *outbuf, 
2378                                       int length, int bufsize,
2379                                       char **pparams, char **ppdata)
2380 {
2381   static uint16 fnf_handle = 257;
2382   char *params = *pparams;
2383   uint16 info_level = SVAL(params,4);
2384
2385   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2386
2387   switch (info_level) 
2388     {
2389     case 1:
2390     case 2:
2391       break;
2392     default:
2393       return ERROR_DOS(ERRDOS,ERRunknownlevel);
2394     }
2395
2396   /* Realloc the parameter and data sizes */
2397   params = Realloc(*pparams,6);
2398   if(params == NULL) {
2399     return ERROR_DOS(ERRDOS,ERRnomem);
2400   }
2401   *pparams      = params;
2402
2403   SSVAL(params,0,fnf_handle);
2404   SSVAL(params,2,0); /* No changes */
2405   SSVAL(params,4,0); /* No EA errors */
2406
2407   fnf_handle++;
2408
2409   if(fnf_handle == 0)
2410     fnf_handle = 257;
2411
2412   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2413   
2414   return(-1);
2415 }
2416
2417 /****************************************************************************
2418  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
2419  changes). Currently this does nothing.
2420 ****************************************************************************/
2421
2422 static int call_trans2findnotifynext(connection_struct *conn,
2423                                      char *inbuf, char *outbuf, 
2424                                      int length, int bufsize,
2425                                      char **pparams, char **ppdata)
2426 {
2427   char *params = *pparams;
2428
2429   DEBUG(3,("call_trans2findnotifynext\n"));
2430
2431   /* Realloc the parameter and data sizes */
2432   params = Realloc(*pparams,4);
2433   if(params == NULL) {
2434     return ERROR_DOS(ERRDOS,ERRnomem);
2435   }
2436   *pparams      = params;
2437
2438   SSVAL(params,0,0); /* No changes */
2439   SSVAL(params,2,0); /* No EA errors */
2440
2441   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2442   
2443   return(-1);
2444 }
2445
2446 /****************************************************************************
2447  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2448 ****************************************************************************/
2449
2450 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2451                                      char* outbuf, int length, int bufsize,
2452                                      char** pparams, char** ppdata)
2453 {
2454   char *params = *pparams;
2455   pstring pathname;
2456   int reply_size = 0;
2457   int max_referral_level = SVAL(params,0);
2458
2459
2460   DEBUG(10,("call_trans2getdfsreferral\n"));
2461
2462   if(!lp_host_msdfs())
2463     return ERROR_DOS(ERRDOS,ERRbadfunc);
2464
2465   srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
2466
2467   if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2468     return ERROR_DOS(ERRDOS,ERRbadfile);
2469     
2470   SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2471   send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2472
2473   return(-1);
2474 }
2475
2476 #define LMCAT_SPL       0x53
2477 #define LMFUNC_GETJOBID 0x60
2478
2479 /****************************************************************************
2480  Reply to a TRANS2_IOCTL - used for OS/2 printing.
2481 ****************************************************************************/
2482
2483 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2484                             char* outbuf, int length, int bufsize,
2485                             char** pparams, char** ppdata)
2486 {
2487   char *pdata = *ppdata;
2488   files_struct *fsp = file_fsp(inbuf,smb_vwv15);
2489
2490   if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2491       (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2492     pdata = Realloc(*ppdata, 32);
2493     if(pdata == NULL) {
2494       return ERROR_DOS(ERRDOS,ERRnomem);
2495     }
2496     *ppdata = pdata;
2497
2498         /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
2499            CAN ACCEPT THIS IN UNICODE. JRA. */
2500
2501     SSVAL(pdata,0,fsp->print_jobid);                     /* Job number */
2502         srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
2503     srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
2504     send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
2505     return(-1);
2506   } else {
2507     DEBUG(2,("Unknown TRANS2_IOCTL\n"));
2508     return ERROR_DOS(ERRSRV,ERRerror);
2509   }
2510 }
2511
2512 /****************************************************************************
2513  Reply to a SMBfindclose (stop trans2 directory search).
2514 ****************************************************************************/
2515
2516 int reply_findclose(connection_struct *conn,
2517                     char *inbuf,char *outbuf,int length,int bufsize)
2518 {
2519         int outsize = 0;
2520         int dptr_num=SVALS(inbuf,smb_vwv0);
2521         START_PROFILE(SMBfindclose);
2522
2523         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
2524
2525         dptr_close(&dptr_num);
2526
2527         outsize = set_message(outbuf,0,0,True);
2528
2529         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
2530
2531         END_PROFILE(SMBfindclose);
2532         return(outsize);
2533 }
2534
2535 /****************************************************************************
2536  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
2537 ****************************************************************************/
2538
2539 int reply_findnclose(connection_struct *conn, 
2540                      char *inbuf,char *outbuf,int length,int bufsize)
2541 {
2542         int outsize = 0;
2543         int dptr_num= -1;
2544         START_PROFILE(SMBfindnclose);
2545         
2546         dptr_num = SVAL(inbuf,smb_vwv0);
2547
2548         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2549
2550         /* We never give out valid handles for a 
2551            findnotifyfirst - so any dptr_num is ok here. 
2552            Just ignore it. */
2553
2554         outsize = set_message(outbuf,0,0,True);
2555
2556         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2557
2558         END_PROFILE(SMBfindnclose);
2559         return(outsize);
2560 }
2561
2562 /****************************************************************************
2563  Reply to a SMBtranss2 - just ignore it!
2564 ****************************************************************************/
2565
2566 int reply_transs2(connection_struct *conn,
2567                   char *inbuf,char *outbuf,int length,int bufsize)
2568 {
2569         START_PROFILE(SMBtranss2);
2570         DEBUG(4,("Ignoring transs2 of length %d\n",length));
2571         END_PROFILE(SMBtranss2);
2572         return(-1);
2573 }
2574
2575 /****************************************************************************
2576  Reply to a SMBtrans2.
2577 ****************************************************************************/
2578
2579 int reply_trans2(connection_struct *conn,
2580                  char *inbuf,char *outbuf,int length,int bufsize)
2581 {
2582         int outsize = 0;
2583         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2584         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2585 #if 0
2586         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2587         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2588         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2589         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2590         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2591         int32 timeout = IVALS(inbuf,smb_timeout);
2592 #endif
2593         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2594         unsigned int tran_call = SVAL(inbuf, smb_setup0);
2595         char *params = NULL, *data = NULL;
2596         int num_params, num_params_sofar, num_data, num_data_sofar;
2597         START_PROFILE(SMBtrans2);
2598
2599         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2600                 /* Queue this open message as we are the process of an
2601                  * oplock break.  */
2602
2603                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2604                 DEBUGADD(2,( "in oplock break state.\n"));
2605
2606                 push_oplock_pending_smb_message(inbuf, length);
2607                 END_PROFILE(SMBtrans2);
2608                 return -1;
2609         }
2610         
2611         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
2612             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
2613                 END_PROFILE(SMBtrans2);
2614                 return ERROR_DOS(ERRSRV,ERRaccess);
2615         }
2616
2617         outsize = set_message(outbuf,0,0,True);
2618
2619         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2620            is so as a sanity check */
2621         if (suwcnt != 1) {
2622                 /*
2623                  * Need to have rc=0 for ioctl to get job id for OS/2.
2624                  *  Network printing will fail if function is not successful.
2625                  *  Similar function in reply.c will be used if protocol
2626                  *  is LANMAN1.0 instead of LM1.2X002.
2627                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
2628                  *  outbuf doesn't have to be set(only job id is used).
2629                  */
2630                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
2631                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2632                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2633                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
2634                 } else {
2635                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
2636                         DEBUG(2,("Transaction is %d\n",tran_call));
2637                         END_PROFILE(SMBtrans2);
2638                         return ERROR_DOS(ERRSRV,ERRerror);
2639                 }
2640         }
2641     
2642         /* Allocate the space for the maximum needed parameters and data */
2643         if (total_params > 0)
2644                 params = (char *)malloc(total_params);
2645         if (total_data > 0)
2646                 data = (char *)malloc(total_data);
2647   
2648         if ((total_params && !params)  || (total_data && !data)) {
2649                 DEBUG(2,("Out of memory in reply_trans2\n"));
2650                 SAFE_FREE(params);
2651                 SAFE_FREE(data); 
2652                 END_PROFILE(SMBtrans2);
2653                 return ERROR_DOS(ERRDOS,ERRnomem);
2654         }
2655
2656         /* Copy the param and data bytes sent with this request into
2657            the params buffer */
2658         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2659         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2660
2661         if (num_params > total_params || num_data > total_data)
2662                 exit_server("invalid params in reply_trans2");
2663
2664         if(params)
2665                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2666         if(data)
2667                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2668
2669         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
2670                 /* We need to send an interim response then receive the rest
2671                    of the parameter/data bytes */
2672                 outsize = set_message(outbuf,0,0,True);
2673                 if (!send_smb(smbd_server_fd(),outbuf))
2674                         exit_server("reply_trans2: send_smb failed.");
2675
2676                 while (num_data_sofar < total_data || 
2677                        num_params_sofar < total_params) {
2678                         BOOL ret;
2679
2680                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2681                         
2682                         if ((ret && 
2683                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2684                                 outsize = set_message(outbuf,0,0,True);
2685                                 if(ret)
2686                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2687                                 else
2688                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2689                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2690                                 SAFE_FREE(params);
2691                                 SAFE_FREE(data);
2692                                 END_PROFILE(SMBtrans2);
2693                                 return ERROR_DOS(ERRSRV,ERRerror);
2694                         }
2695       
2696                         /* Revise total_params and total_data in case
2697                            they have changed downwards */
2698                         total_params = SVAL(inbuf, smb_tpscnt);
2699                         total_data = SVAL(inbuf, smb_tdscnt);
2700                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2701                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2702                         if (num_params_sofar > total_params || num_data_sofar > total_data)
2703                                 exit_server("data overflow in trans2");
2704                         
2705                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
2706                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2707                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2708                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2709                 }
2710         }
2711         
2712         if (Protocol >= PROTOCOL_NT1) {
2713                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
2714         }
2715
2716         /* Now we must call the relevant TRANS2 function */
2717         switch(tran_call)  {
2718         case TRANSACT2_OPEN:
2719                 START_PROFILE_NESTED(Trans2_open);
2720                 outsize = call_trans2open(conn, 
2721                                           inbuf, outbuf, bufsize, 
2722                                           &params, &data);
2723                 END_PROFILE_NESTED(Trans2_open);
2724                 break;
2725
2726         case TRANSACT2_FINDFIRST:
2727                 START_PROFILE_NESTED(Trans2_findfirst);
2728                 outsize = call_trans2findfirst(conn, inbuf, outbuf, 
2729                                                bufsize, &params, &data);
2730                 END_PROFILE_NESTED(Trans2_findfirst);
2731                 break;
2732
2733         case TRANSACT2_FINDNEXT:
2734                 START_PROFILE_NESTED(Trans2_findnext);
2735                 outsize = call_trans2findnext(conn, inbuf, outbuf, 
2736                                               length, bufsize, 
2737                                               &params, &data);
2738                 END_PROFILE_NESTED(Trans2_findnext);
2739                 break;
2740
2741         case TRANSACT2_QFSINFO:
2742                 START_PROFILE_NESTED(Trans2_qfsinfo);
2743             outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
2744                                          length, bufsize, &params, 
2745                                          &data);
2746                 END_PROFILE_NESTED(Trans2_qfsinfo);
2747             break;
2748
2749         case TRANSACT2_SETFSINFO:
2750                 START_PROFILE_NESTED(Trans2_setfsinfo);
2751                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
2752                                                length, bufsize, 
2753                                                &params, &data);
2754                 END_PROFILE_NESTED(Trans2_setfsinfo);
2755                 break;
2756
2757         case TRANSACT2_QPATHINFO:
2758         case TRANSACT2_QFILEINFO:
2759                 START_PROFILE_NESTED(Trans2_qpathinfo);
2760                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
2761                                                    length, bufsize, 
2762                                                    &params, &data, total_data);
2763                 END_PROFILE_NESTED(Trans2_qpathinfo);
2764                 break;
2765         case TRANSACT2_SETPATHINFO:
2766         case TRANSACT2_SETFILEINFO:
2767                 START_PROFILE_NESTED(Trans2_setpathinfo);
2768                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
2769                                                      length, bufsize, 
2770                                                      &params, &data, 
2771                                                      total_data);
2772                 END_PROFILE_NESTED(Trans2_setpathinfo);
2773                 break;
2774
2775         case TRANSACT2_FINDNOTIFYFIRST:
2776                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
2777                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
2778                                                      length, bufsize, 
2779                                                      &params, &data);
2780                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
2781                 break;
2782
2783         case TRANSACT2_FINDNOTIFYNEXT:
2784                 START_PROFILE_NESTED(Trans2_findnotifynext);
2785                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
2786                                                     length, bufsize, 
2787                                                     &params, &data);
2788                 END_PROFILE_NESTED(Trans2_findnotifynext);
2789                 break;
2790         case TRANSACT2_MKDIR:
2791                 START_PROFILE_NESTED(Trans2_mkdir);
2792                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
2793                                            bufsize, &params, &data);
2794                 END_PROFILE_NESTED(Trans2_mkdir);
2795                 break;
2796
2797         case TRANSACT2_GET_DFS_REFERRAL:
2798                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
2799         outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length,
2800                                             bufsize, &params, &data);
2801                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
2802                 break;
2803         case TRANSACT2_IOCTL:
2804                 START_PROFILE_NESTED(Trans2_ioctl);
2805                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length,
2806                                                 bufsize,&params,&data);
2807                 END_PROFILE_NESTED(Trans2_ioctl);
2808                 break;
2809         default:
2810                 /* Error in request */
2811                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
2812                 SAFE_FREE(params);
2813                 SAFE_FREE(data);
2814                 END_PROFILE(SMBtrans2);
2815                 return ERROR_DOS(ERRSRV,ERRerror);
2816         }
2817         
2818         /* As we do not know how many data packets will need to be
2819            returned here the various call_trans2xxxx calls
2820            must send their own. Thus a call_trans2xxx routine only
2821            returns a value other than -1 when it wants to send
2822            an error packet. 
2823         */
2824         
2825         SAFE_FREE(params);
2826         SAFE_FREE(data);
2827         END_PROFILE(SMBtrans2);
2828         return outsize; /* If a correct response was needed the
2829                            call_trans2xxx calls have already sent
2830                            it. If outsize != -1 then it is returning */
2831 }