Fixed the error bad path for recursive mkdir so mkdir \a\b\c\d works.
[tprouty/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  *  Utility function to set bad path error.
1417  ****************************************************************************/
1418
1419 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1420 {
1421         if((err == ENOENT) && bad_path) {
1422                 unix_ERR_class = ERRDOS;
1423                 unix_ERR_code = ERRbadpath;
1424                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1425         }
1426         return NT_STATUS_OK;
1427 }
1428
1429 /****************************************************************************
1430  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1431  file name or file id).
1432 ****************************************************************************/
1433
1434 static int call_trans2qfilepathinfo(connection_struct *conn,
1435                                     char *inbuf, char *outbuf, int length, 
1436                                     int bufsize,
1437                                     char **pparams,char **ppdata,
1438                                     int total_data)
1439 {
1440         int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1441         char *params = *pparams;
1442         char *pdata = *ppdata;
1443         uint16 tran_call = SVAL(inbuf, smb_setup0);
1444         uint16 info_level;
1445         int mode=0;
1446         SMB_OFF_T size=0;
1447         SMB_OFF_T allocation_size=0;
1448         unsigned int data_size;
1449         SMB_STRUCT_STAT sbuf;
1450         pstring fname, dos_fname;
1451         char *base_name;
1452         char *p;
1453         SMB_OFF_T pos = 0;
1454         BOOL bad_path = False;
1455         BOOL delete_pending = False;
1456         int len;
1457         time_t c_time;
1458
1459         if (!params) {
1460                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1461         }
1462
1463         if (tran_call == TRANSACT2_QFILEINFO) {
1464                 files_struct *fsp = file_fsp(params,0);
1465                 info_level = SVAL(params,2);
1466
1467                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1468
1469                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1470                         /*
1471                          * This is actually a QFILEINFO on a directory
1472                          * handle (returned from an NT SMB). NT5.0 seems
1473                          * to do this call. JRA.
1474                          */
1475                         pstrcpy(fname, fsp->fsp_name);
1476                         unix_convert(fname,conn,0,&bad_path,&sbuf);
1477                         if (!check_name(fname,conn) || 
1478                                         (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1479                                 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1480                                 if((errno == ENOENT) && bad_path) {
1481                                         unix_ERR_class = ERRDOS;
1482                                         unix_ERR_code = ERRbadpath;
1483                                 }
1484                                 return(UNIXERROR(ERRDOS,ERRbadpath));
1485                         }
1486                   
1487                         delete_pending = fsp->directory_delete_on_close;
1488                 } else {
1489                         /*
1490                          * Original code - this is an open file.
1491                          */
1492                         CHECK_FSP(fsp,conn);
1493
1494                         pstrcpy(fname, fsp->fsp_name);
1495                         if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1496                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1497                                 return(UNIXERROR(ERRDOS,ERRbadfid));
1498                         }
1499                         if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1500                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1501
1502                         delete_pending = fsp->delete_on_close;
1503                 }
1504         } else {
1505                 /* qpathinfo */
1506                 info_level = SVAL(params,0);
1507
1508                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1509
1510                 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1511
1512                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1513
1514                 unix_convert(fname,conn,0,&bad_path,&sbuf);
1515                 if (!check_name(fname,conn) || 
1516                                 (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
1517                         DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1518                         if((errno == ENOENT) && bad_path) {
1519                                 unix_ERR_class = ERRDOS;
1520                                 unix_ERR_code = ERRbadpath;
1521                         }
1522                         return(UNIXERROR(ERRDOS,ERRbadpath));
1523                 }
1524         }
1525
1526
1527         DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1528                 fname,info_level,tran_call,total_data));
1529
1530         p = strrchr_m(fname,'/'); 
1531         if (!p)
1532                 base_name = fname;
1533         else
1534                 base_name = p+1;
1535
1536         mode = dos_mode(conn,fname,&sbuf);
1537         size = sbuf.st_size;
1538         allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
1539         
1540         if (mode & aDIR)
1541                 size = 0;
1542
1543         params = Realloc(*pparams,2);
1544         if (params == NULL)
1545           return ERROR_DOS(ERRDOS,ERRnomem);
1546         *pparams = params;
1547         memset((char *)params,'\0',2);
1548         data_size = max_data_bytes + 1024;
1549         pdata = Realloc(*ppdata, data_size); 
1550         if ( pdata == NULL )
1551                 return ERROR_DOS(ERRDOS,ERRnomem);
1552         *ppdata = pdata;
1553
1554         if (total_data > 0 && IVAL(pdata,0) == total_data) {
1555                 /* uggh, EAs for OS2 */
1556                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1557                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1558         }
1559
1560         memset((char *)pdata,'\0',data_size);
1561
1562         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1563
1564         if (lp_dos_filetime_resolution(SNUM(conn))) {
1565                 c_time &= ~1;
1566                 sbuf.st_atime &= ~1;
1567                 sbuf.st_mtime &= ~1;
1568                 sbuf.st_mtime &= ~1;
1569         }
1570
1571         /* NT expects the name to be in an exact form */
1572         if (strequal(fname,".")) {
1573                 pstrcpy(dos_fname, "\\");
1574         } else {
1575                 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1576                 string_replace( dos_fname, '/', '\\');
1577         }
1578
1579         switch (info_level) {
1580                 case SMB_INFO_STANDARD:
1581                 case SMB_INFO_QUERY_EA_SIZE:
1582                         data_size = (info_level==1?22:26);
1583                         put_dos_date2(pdata,l1_fdateCreation,c_time);
1584                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1585                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1586                         SIVAL(pdata,l1_cbFile,(uint32)size);
1587                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1588                         SSVAL(pdata,l1_attrFile,mode);
1589                         SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1590                         break;
1591
1592                 case SMB_INFO_QUERY_EAS_FROM_LIST:
1593                         data_size = 24;
1594                         put_dos_date2(pdata,0,c_time);
1595                         put_dos_date2(pdata,4,sbuf.st_atime);
1596                         put_dos_date2(pdata,8,sbuf.st_mtime);
1597                         SIVAL(pdata,12,(uint32)size);
1598                         SIVAL(pdata,16,(uint32)allocation_size);
1599                         SIVAL(pdata,20,mode);
1600                         break;
1601
1602                 case SMB_INFO_QUERY_ALL_EAS:
1603                         data_size = 4;
1604                         SIVAL(pdata,0,data_size);
1605                         break;
1606
1607                 case 6:
1608                         return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */      
1609
1610                 case SMB_FILE_BASIC_INFORMATION:
1611                 case SMB_QUERY_FILE_BASIC_INFO:
1612
1613                         if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1614                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1615                         else {
1616                                 data_size = 40;
1617                                 SIVAL(pdata,36,0);
1618                         }
1619                         put_long_date(pdata,c_time);
1620                         put_long_date(pdata+8,sbuf.st_atime);
1621                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1622                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1623                         SIVAL(pdata,32,mode);
1624
1625                         DEBUG(5,("SMB_QFBI - "));
1626                         {
1627                                 time_t create_time = c_time;
1628                                 DEBUG(5,("create: %s ", ctime(&create_time)));
1629                         }
1630                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1631                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1632                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1633                         DEBUG(5,("mode: %x\n", mode));
1634
1635                         break;
1636
1637                 case SMB_FILE_STANDARD_INFORMATION:
1638                 case SMB_QUERY_FILE_STANDARD_INFO:
1639                         data_size = 24;
1640                         /* Fake up allocation size. */
1641                         SOFF_T(pdata,0,allocation_size);
1642                         SOFF_T(pdata,8,size);
1643                         SIVAL(pdata,16,sbuf.st_nlink);
1644                         SCVAL(pdata,20,0);
1645                         SCVAL(pdata,21,(mode&aDIR)?1:0);
1646                         break;
1647
1648                 case SMB_FILE_EA_INFORMATION:
1649                 case SMB_QUERY_FILE_EA_INFO:
1650                         data_size = 4;
1651                         break;
1652
1653                 /* Get the 8.3 name - used if NT SMB was negotiated. */
1654                 case SMB_QUERY_FILE_ALT_NAME_INFO:
1655                 {
1656                         pstring short_name;
1657
1658                         pstrcpy(short_name,base_name);
1659                         /* Mangle if not already 8.3 */
1660                         if(!is_8_3(short_name, True)) {
1661                                 if(!name_map_mangle(short_name,True,True,SNUM(conn)))
1662                                         *short_name = '\0';
1663                         }
1664                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER);
1665                         data_size = 4 + len;
1666                         SIVAL(pdata,0,len);
1667                         break;
1668                 }
1669
1670                 case SMB_QUERY_FILE_NAME_INFO:
1671                         /*
1672                           this must be *exactly* right for ACLs on mapped drives to work
1673                          */
1674                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
1675                         data_size = 4 + len;
1676                         SIVAL(pdata,0,len);
1677                         break;
1678
1679                 case SMB_FILE_END_OF_FILE_INFORMATION:
1680                 case SMB_QUERY_FILE_END_OF_FILEINFO:
1681                         data_size = 8;
1682                         SOFF_T(pdata,0,size);
1683                         break;
1684
1685                 case SMB_FILE_ALLOCATION_INFORMATION:
1686                 case SMB_QUERY_FILE_ALLOCATION_INFO:
1687                         data_size = 8;
1688                         SOFF_T(pdata,0,allocation_size);
1689                         break;
1690
1691                 case SMB_QUERY_FILE_ALL_INFO:
1692                         put_long_date(pdata,c_time);
1693                         put_long_date(pdata+8,sbuf.st_atime);
1694                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1695                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1696                         SIVAL(pdata,32,mode);
1697                         pdata += 40;
1698                         SOFF_T(pdata,0,allocation_size);
1699                         SOFF_T(pdata,8,size);
1700                         SIVAL(pdata,16,sbuf.st_nlink);
1701                         SCVAL(pdata,20,delete_pending);
1702                         SCVAL(pdata,21,(mode&aDIR)?1:0);
1703                         pdata += 24;
1704                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); 
1705                         pdata += 8; /* index number */
1706                         pdata += 4; /* EA info */
1707                         if (mode & aRONLY)
1708                                 SIVAL(pdata,0,0xA9);
1709                         else
1710                                 SIVAL(pdata,0,0xd01BF);
1711                         pdata += 4;
1712                         SOFF_T(pdata,0,pos); /* current offset */
1713                         pdata += 8;
1714                         SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1715                         pdata += 4;
1716                         pdata += 4; /* alignment */
1717                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE);
1718                         SIVAL(pdata,0,len);
1719                         pdata += 4 + len;
1720                         data_size = PTR_DIFF(pdata,(*ppdata));
1721                         break;
1722
1723                 case SMB_FILE_INTERNAL_INFORMATION:
1724                         /* This should be an index number - looks like dev/ino to me :-) */
1725                         SIVAL(pdata,0,sbuf.st_dev);
1726                         SIVAL(pdata,4,sbuf.st_ino);
1727                         data_size = 8;
1728                         break;
1729
1730                 case SMB_FILE_ACCESS_INFORMATION:
1731                         SIVAL(pdata,0,0x12019F); /* ??? */
1732                         data_size = 4;
1733                         break;
1734
1735                 case SMB_FILE_NAME_INFORMATION:
1736                         /* Pathname with leading '\'. */
1737                         {
1738                                 size_t byte_len;
1739                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
1740                                 SIVAL(pdata,0,byte_len);
1741                                 data_size = 4 + byte_len;
1742                                 break;
1743                         }
1744
1745                 case SMB_FILE_DISPOSITION_INFORMATION:
1746                         data_size = 1;
1747                         SCVAL(pdata,0,delete_pending);
1748                         break;
1749
1750                 case SMB_FILE_POSITION_INFORMATION:
1751                         data_size = 8;
1752                         SOFF_T(pdata,0,pos);
1753                         break;
1754
1755                 case SMB_FILE_MODE_INFORMATION:
1756                         SIVAL(pdata,0,mode);
1757                         data_size = 4;
1758                         break;
1759
1760                 case SMB_FILE_ALIGNMENT_INFORMATION:
1761                         SIVAL(pdata,0,0); /* No alignment needed. */
1762                         data_size = 4;
1763                         break;
1764
1765 #if 0
1766         /* Not yet finished... JRA */
1767         case 1018:
1768                 {
1769                         put_long_date(pdata,c_time);
1770                         put_long_date(pdata+8,sbuf.st_atime);
1771                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1772                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1773                         SIVAL(pdata,32,mode);
1774                         SIVAL(pdata,36,0); /* ??? */
1775                         SIVAL(pdata,40,0x20); /* ??? */
1776                         SIVAL(pdata,44,0); /* ??? */
1777                         SOFF_T(pdata,48,size);
1778                         SIVAL(pdata,56,0x1); /* ??? */
1779                         SIVAL(pdata,60,0); /* ??? */
1780                         SIVAL(pdata,64,0); /* ??? */
1781                         SIVAL(pdata,68,length); /* Following string length in bytes. */
1782                         dos_PutUniCode(pdata+72,,False);
1783                         break;
1784                 }
1785 #endif
1786
1787                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1788                         /* Last component of pathname. */
1789                         {
1790                                 size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1791                                 SIVAL(pdata,0,byte_len);
1792                                 data_size = 4 + byte_len;
1793                                 break;
1794                         }
1795                 
1796                 case SMB_FILE_STREAM_INFORMATION:
1797                         if (mode & aDIR) {
1798                                 data_size = 0;
1799                         } else {
1800                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1801                                 SIVAL(pdata,0,0); /* ??? */
1802                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1803                                 SOFF_T(pdata,8,size);
1804                                 SIVAL(pdata,16,allocation_size);
1805                                 SIVAL(pdata,20,0); /* ??? */
1806                                 data_size = 24 + byte_len;
1807                         }
1808                         break;
1809
1810                 case SMB_FILE_COMPRESSION_INFORMATION:
1811                         SOFF_T(pdata,0,size);
1812                         SIVAL(pdata,8,0); /* ??? */
1813                         SIVAL(pdata,12,0); /* ??? */
1814                         data_size = 16;
1815                         break;
1816
1817                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
1818                         put_long_date(pdata,c_time);
1819                         put_long_date(pdata+8,sbuf.st_atime);
1820                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1821                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1822                         SIVAL(pdata,32,allocation_size);
1823                         SOFF_T(pdata,40,size);
1824                         SIVAL(pdata,48,mode);
1825                         SIVAL(pdata,52,0); /* ??? */
1826                         data_size = 56;
1827                         break;
1828
1829                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1830                         SIVAL(pdata,0,mode);
1831                         SIVAL(pdata,4,0);
1832                         data_size = 8;
1833                         break;
1834
1835 #if 0
1836                 /* NT4 server just returns "invalid query" to this - if we try to answer 
1837                                 it then NTws gets a BSOD! (tridge) */
1838                 case SMB_QUERY_FILE_STREAM_INFO:
1839                         SIVAL(pdata,0,pos);
1840                         SIVAL(pdata,4,(uint32)size);
1841                         SIVAL(pdata,12,(uint32)allocation_size);
1842                         len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE);
1843                         SIVAL(pdata,20,len);
1844                         data_size = 24 + len;
1845                         break;
1846 #endif
1847
1848                 default:
1849                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1850         }
1851
1852         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
1853
1854         return(-1);
1855 }
1856
1857 /****************************************************************************
1858  Deal with the internal needs of setting the delete on close flag. Note that
1859  as the tdb locking is recursive, it is safe to call this from within 
1860  open_file_shared. JRA.
1861 ****************************************************************************/
1862
1863 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
1864 {
1865         /*
1866          * Only allow delete on close for writable shares.
1867          */
1868
1869         if (delete_on_close && !CAN_WRITE(fsp->conn)) {
1870                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
1871                                 fsp->fsp_name ));
1872                                 return NT_STATUS_ACCESS_DENIED;
1873         }
1874         /*
1875          * Only allow delete on close for files/directories opened with delete intent.
1876          */
1877
1878         if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
1879                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
1880                                 fsp->fsp_name ));
1881                                 return NT_STATUS_ACCESS_DENIED;
1882         }
1883
1884         if(fsp->is_directory) {
1885                 fsp->directory_delete_on_close = delete_on_close;
1886                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
1887                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1888         } else {
1889
1890                 files_struct *iterate_fsp;
1891
1892                 /*
1893                  * Modify the share mode entry for all files open
1894                  * on this device and inode to tell other smbds we have 
1895                  * changed the delete on close flag. This will be noticed
1896                  * in the close code, the last closer will delete the file
1897                  * if flag is set.
1898                  */
1899
1900                 DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
1901                                         delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
1902
1903                 if (lock_share_entry_fsp(fsp) == False)
1904                                 return NT_STATUS_ACCESS_DENIED;
1905
1906                 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
1907                         DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
1908                                         fsp->fsp_name ));
1909                         unlock_share_entry_fsp(fsp);
1910                         return NT_STATUS_ACCESS_DENIED;
1911                 }
1912
1913                 /*
1914                  * Release the lock.
1915                  */
1916
1917                 unlock_share_entry_fsp(fsp);
1918
1919                 /*
1920                  * Go through all files we have open on the same device and
1921                  * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
1922                  * Other smbd's that have this file open will look in the share_mode on close.
1923                  * take care of this (rare) case in close_file(). See the comment there.
1924                  * NB. JRA. We don't really need to do this anymore - all should be taken
1925                  * care of in the share_mode changes in the tdb.
1926                  */
1927
1928                 for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
1929                                 iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
1930                                                 fsp->delete_on_close = delete_on_close;
1931
1932                 /*
1933                  * Set the delete on close flag in the fsp.
1934                  */
1935                 fsp->delete_on_close = delete_on_close;
1936
1937                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
1938                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
1939
1940         }
1941
1942         return NT_STATUS_OK;
1943 }
1944
1945 /****************************************************************************
1946  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
1947 ****************************************************************************/
1948
1949 static int call_trans2setfilepathinfo(connection_struct *conn,
1950                                       char *inbuf, char *outbuf, int length, 
1951                                       int bufsize, char **pparams, 
1952                                       char **ppdata, int total_data)
1953 {
1954         char *params = *pparams;
1955         char *pdata = *ppdata;
1956         uint16 tran_call = SVAL(inbuf, smb_setup0);
1957         uint16 info_level;
1958         int mode=0;
1959         SMB_OFF_T size=0;
1960         struct utimbuf tvs;
1961         SMB_STRUCT_STAT sbuf;
1962         pstring fname;
1963         int fd = -1;
1964         BOOL bad_path = False;
1965         files_struct *fsp = NULL;
1966
1967         if (tran_call == TRANSACT2_SETFILEINFO) {
1968                 fsp = file_fsp(params,0);
1969                 info_level = SVAL(params,2);    
1970
1971                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1972                         /*
1973                          * This is actually a SETFILEINFO on a directory
1974                          * handle (returned from an NT SMB). NT5.0 seems
1975                          * to do this call. JRA.
1976                          */
1977                         pstrcpy(fname, fsp->fsp_name);
1978                         unix_convert(fname,conn,0,&bad_path,&sbuf);
1979                         if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
1980                                 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1981                                 if((errno == ENOENT) && bad_path) {
1982                                         unix_ERR_class = ERRDOS;
1983                                         unix_ERR_code = ERRbadpath;
1984                                 }
1985                                 return(UNIXERROR(ERRDOS,ERRbadpath));
1986                         }
1987                 } else if (fsp && fsp->print_file) {
1988                         /*
1989                          * Doing a DELETE_ON_CLOSE should cancel a print job.
1990                          */
1991                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
1992                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
1993
1994                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
1995         
1996                                 SSVAL(params,0,0);
1997                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
1998                                 return(-1);
1999                         }
2000             } else {
2001                         /*
2002                          * Original code - this is an open file.
2003                          */
2004                         CHECK_FSP(fsp,conn);
2005
2006                         pstrcpy(fname, fsp->fsp_name);
2007                         fd = fsp->fd;
2008
2009                         if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2010                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2011                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2012                         }
2013                 }
2014         } else {
2015                 /* set path info */
2016                 info_level = SVAL(params,0);    
2017                 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2018                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2019                 if(!check_name(fname, conn)) {
2020                         if((errno == ENOENT) && bad_path) {
2021                                 unix_ERR_class = ERRDOS;
2022                                 unix_ERR_code = ERRbadpath;
2023                         }
2024                         return(UNIXERROR(ERRDOS,ERRbadpath));
2025                 }
2026  
2027                 if(!VALID_STAT(sbuf)) {
2028                         DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
2029                         if((errno == ENOENT) && bad_path) {
2030                                 unix_ERR_class = ERRDOS;
2031                                 unix_ERR_code = ERRbadpath;
2032                         }
2033                         return(UNIXERROR(ERRDOS,ERRbadpath));
2034                 }    
2035         }
2036
2037         if (!CAN_WRITE(conn))
2038                 return ERROR_DOS(ERRSRV,ERRaccess);
2039
2040         DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2041                 tran_call,fname,info_level,total_data));
2042
2043         /* Realloc the parameter and data sizes */
2044         params = Realloc(*pparams,2);
2045         if(params == NULL)
2046                 return ERROR_DOS(ERRDOS,ERRnomem);
2047         *pparams = params;
2048
2049         SSVAL(params,0,0);
2050
2051         size = sbuf.st_size;
2052         tvs.modtime = sbuf.st_mtime;
2053         tvs.actime = sbuf.st_atime;
2054         mode = dos_mode(conn,fname,&sbuf);
2055
2056         if (total_data > 4 && IVAL(pdata,0) == total_data) {
2057                 /* uggh, EAs for OS2 */
2058                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2059                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2060         }
2061
2062         switch (info_level) {
2063                 case SMB_INFO_STANDARD:
2064                 case SMB_INFO_QUERY_EA_SIZE:
2065                 {
2066                         /* access time */
2067                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2068
2069                         /* write time */
2070                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2071
2072                         mode = SVAL(pdata,l1_attrFile);
2073                         size = IVAL(pdata,l1_cbFile);
2074                         break;
2075                 }
2076
2077                 /* XXXX um, i don't think this is right.
2078                         it's also not in the cifs6.txt spec.
2079                 */
2080                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2081                         tvs.actime = make_unix_date2(pdata+8);
2082                         tvs.modtime = make_unix_date2(pdata+12);
2083                         size = IVAL(pdata,16);
2084                         mode = IVAL(pdata,24);
2085                         break;
2086
2087                 /* XXXX nor this.  not in cifs6.txt, either. */
2088                 case SMB_INFO_QUERY_ALL_EAS:
2089                         tvs.actime = make_unix_date2(pdata+8);
2090                         tvs.modtime = make_unix_date2(pdata+12);
2091                         size = IVAL(pdata,16);
2092                         mode = IVAL(pdata,24);
2093                         break;
2094
2095                 case SMB_SET_FILE_BASIC_INFO:
2096                 case SMB_FILE_BASIC_INFORMATION:
2097                 {
2098                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2099                         time_t write_time;
2100                         time_t changed_time;
2101
2102                         /* Ignore create time at offset pdata. */
2103
2104                         /* access time */
2105                         tvs.actime = interpret_long_date(pdata+8);
2106
2107                         write_time = interpret_long_date(pdata+16);
2108                         changed_time = interpret_long_date(pdata+24);
2109
2110                         tvs.modtime = MIN(write_time, changed_time);
2111
2112                         /* Prefer a defined time to an undefined one. */
2113                         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2114                                 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2115                                         ? changed_time : write_time);
2116
2117                         /* attributes */
2118                         mode = IVAL(pdata,32);
2119                         break;
2120                 }
2121
2122                 case  SMB_FILE_ALLOCATION_INFORMATION:
2123                 case SMB_SET_FILE_ALLOCATION_INFO:
2124                 {
2125                         int ret = -1;
2126                         SMB_OFF_T allocation_size = IVAL(pdata,0);
2127 #ifdef LARGE_SMB_OFF_T
2128                         allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2129 #else /* LARGE_SMB_OFF_T */
2130                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2131                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2132 #endif /* LARGE_SMB_OFF_T */
2133                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2134                                         fname, (double)allocation_size ));
2135
2136                         if(allocation_size != sbuf.st_size) {
2137                                 SMB_STRUCT_STAT new_sbuf;
2138  
2139                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2140                                         fname, (double)allocation_size ));
2141  
2142                                 if (fd == -1) {
2143                                         files_struct *new_fsp = NULL;
2144                                         int access_mode = 0;
2145                                         int action = 0;
2146  
2147                                         if(global_oplock_break) {
2148                                                 /* Queue this file modify as we are the process of an oplock break.  */
2149  
2150                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2151                                                 DEBUGADD(2,( "in oplock break state.\n"));
2152  
2153                                                 push_oplock_pending_smb_message(inbuf, length);
2154                                                 return -1;
2155                                         }
2156  
2157                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2158                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
2159                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2160                                                                         0, 0, &access_mode, &action);
2161  
2162                                         if (new_fsp == NULL)
2163                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
2164                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
2165                                         if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2166                                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",new_fsp->fnum, strerror(errno)));
2167                                                 ret = -1;
2168                                         }
2169                                         close_file(new_fsp,True);
2170                                 } else {
2171                                         ret = vfs_allocate_file_space(fsp, allocation_size);
2172                                         if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2173                                                 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2174                                                 ret = -1;
2175                                         }
2176                                 }
2177                                 if (ret == -1)
2178                                         return ERROR_NT(NT_STATUS_DISK_FULL);
2179
2180                                 /* Allocate can trucate size... */
2181                                 size = new_sbuf.st_size;
2182                         }
2183
2184                         break;
2185                 }
2186
2187         case SMB_FILE_END_OF_FILE_INFORMATION:
2188                 case SMB_SET_FILE_END_OF_FILE_INFO:
2189                 {
2190                         size = IVAL(pdata,0);
2191 #ifdef LARGE_SMB_OFF_T
2192                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2193 #else /* LARGE_SMB_OFF_T */
2194                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2195                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2196 #endif /* LARGE_SMB_OFF_T */
2197                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2198                         break;
2199                 }
2200
2201                 case SMB_FILE_DISPOSITION_INFORMATION:
2202                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2203                 {
2204                         BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2205                         NTSTATUS status;
2206
2207                         if (tran_call != TRANSACT2_SETFILEINFO)
2208                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2209
2210                         if (fsp == NULL)
2211                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2212
2213                         status = set_delete_on_close_internal(fsp, delete_on_close);
2214  
2215                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
2216                                 return ERROR_NT(status);
2217
2218                         break;
2219                 }
2220
2221                 default:
2222                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2223         }
2224
2225         /* get some defaults (no modifications) if any info is zero or -1. */
2226         if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2227                 tvs.actime = sbuf.st_atime;
2228
2229         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2230                 tvs.modtime = sbuf.st_mtime;
2231
2232         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2233         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2234         DEBUG(6,("size: %.0f ", (double)size));
2235         DEBUG(6,("mode: %x\n"  , mode));
2236
2237         if (S_ISDIR(sbuf.st_mode))
2238                 mode |= aDIR;
2239         else
2240                 mode &= ~aDIR;
2241
2242         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2243                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2244                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2245                         (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2246
2247                 /*
2248                  * Only do this test if we are not explicitly
2249                  * changing the size of a file.
2250                  */
2251                 if (!size)
2252                         size = sbuf.st_size;
2253         }
2254
2255         /*
2256          * Try and set the times, size and mode of this file -
2257          * if they are different from the current values
2258          */
2259         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2260                 if(fsp != NULL) {
2261                         /*
2262                          * This was a setfileinfo on an open file.
2263                          * NT does this a lot. It's actually pointless
2264                          * setting the time here, as it will be overwritten
2265                          * on the next write, so we save the request
2266                          * away and will set it on file code. JRA.
2267                          */
2268
2269                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2270                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2271                                 fsp->pending_modtime = tvs.modtime;
2272                         }
2273
2274                 } else {
2275
2276                         DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2277
2278                         if(file_utime(conn, fname, &tvs)!=0)
2279                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2280                 }
2281         }
2282
2283         /* check the mode isn't different, before changing it */
2284         if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) {
2285
2286                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, mode ));
2287
2288                 if(file_chmod(conn, fname, mode, NULL)) {
2289                         DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2290                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2291                 }
2292         }
2293
2294         if(size != sbuf.st_size) {
2295
2296                 int ret;
2297
2298                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2299                         fname, (double)size ));
2300
2301                 if (fd == -1) {
2302                         files_struct *new_fsp = NULL;
2303                         int access_mode = 0;
2304                         int action = 0;
2305
2306                         if(global_oplock_break) {
2307                                 /* Queue this file modify as we are the process of an oplock break.  */
2308
2309                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2310                                 DEBUGADD(2,( "in oplock break state.\n"));
2311
2312                                 push_oplock_pending_smb_message(inbuf, length);
2313                                 return -1;
2314                         }
2315
2316                         new_fsp = open_file_shared(conn, fname, &sbuf,
2317                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
2318                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2319                                                 0, 0, &access_mode, &action);
2320         
2321                         if (new_fsp == NULL)
2322                                 return(UNIXERROR(ERRDOS,ERRbadpath));
2323                         ret = vfs_set_filelen(new_fsp, size);
2324                         close_file(new_fsp,True);
2325                 } else {
2326                         ret = vfs_set_filelen(fsp, size);
2327                 }
2328
2329                 if (ret == -1)
2330                         return (UNIXERROR(ERRHRD,ERRdiskfull));
2331         }
2332
2333         SSVAL(params,0,0);
2334
2335         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2336   
2337         return(-1);
2338 }
2339
2340 /****************************************************************************
2341  Reply to a TRANS2_MKDIR (make directory with extended attributes).
2342 ****************************************************************************/
2343
2344 static int call_trans2mkdir(connection_struct *conn,
2345                             char *inbuf, char *outbuf, int length, int bufsize,
2346                             char **pparams, char **ppdata)
2347 {
2348   char *params = *pparams;
2349   pstring directory;
2350   int ret = -1;
2351   SMB_STRUCT_STAT sbuf;
2352   BOOL bad_path = False;
2353
2354   if (!CAN_WRITE(conn))
2355     return ERROR_DOS(ERRSRV,ERRaccess);
2356
2357   srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
2358
2359   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2360
2361   unix_convert(directory,conn,0,&bad_path,&sbuf);
2362   if (check_name(directory,conn))
2363     ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2364   
2365   if(ret < 0)
2366     {
2367       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2368       if((errno == ENOENT) && bad_path)
2369       {
2370         unix_ERR_class = ERRDOS;
2371         unix_ERR_code = ERRbadpath;
2372       }
2373       return(UNIXERROR(ERRDOS,ERRnoaccess));
2374     }
2375
2376   /* Realloc the parameter and data sizes */
2377   params = Realloc(*pparams,2);
2378   if(params == NULL) {
2379     return ERROR_DOS(ERRDOS,ERRnomem);
2380   }
2381   *pparams      = params;
2382
2383   SSVAL(params,0,0);
2384
2385   send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2386   
2387   return(-1);
2388 }
2389
2390 /****************************************************************************
2391  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2392  We don't actually do this - we just send a null response.
2393 ****************************************************************************/
2394
2395 static int call_trans2findnotifyfirst(connection_struct *conn,
2396                                       char *inbuf, char *outbuf, 
2397                                       int length, int bufsize,
2398                                       char **pparams, char **ppdata)
2399 {
2400   static uint16 fnf_handle = 257;
2401   char *params = *pparams;
2402   uint16 info_level = SVAL(params,4);
2403
2404   DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2405
2406   switch (info_level) 
2407     {
2408     case 1:
2409     case 2:
2410       break;
2411     default:
2412       return ERROR_DOS(ERRDOS,ERRunknownlevel);
2413     }
2414
2415   /* Realloc the parameter and data sizes */
2416   params = Realloc(*pparams,6);
2417   if(params == NULL) {
2418     return ERROR_DOS(ERRDOS,ERRnomem);
2419   }
2420   *pparams      = params;
2421
2422   SSVAL(params,0,fnf_handle);
2423   SSVAL(params,2,0); /* No changes */
2424   SSVAL(params,4,0); /* No EA errors */
2425
2426   fnf_handle++;
2427
2428   if(fnf_handle == 0)
2429     fnf_handle = 257;
2430
2431   send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2432   
2433   return(-1);
2434 }
2435
2436 /****************************************************************************
2437  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
2438  changes). Currently this does nothing.
2439 ****************************************************************************/
2440
2441 static int call_trans2findnotifynext(connection_struct *conn,
2442                                      char *inbuf, char *outbuf, 
2443                                      int length, int bufsize,
2444                                      char **pparams, char **ppdata)
2445 {
2446   char *params = *pparams;
2447
2448   DEBUG(3,("call_trans2findnotifynext\n"));
2449
2450   /* Realloc the parameter and data sizes */
2451   params = Realloc(*pparams,4);
2452   if(params == NULL) {
2453     return ERROR_DOS(ERRDOS,ERRnomem);
2454   }
2455   *pparams      = params;
2456
2457   SSVAL(params,0,0); /* No changes */
2458   SSVAL(params,2,0); /* No EA errors */
2459
2460   send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2461   
2462   return(-1);
2463 }
2464
2465 /****************************************************************************
2466  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2467 ****************************************************************************/
2468
2469 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2470                                      char* outbuf, int length, int bufsize,
2471                                      char** pparams, char** ppdata)
2472 {
2473   char *params = *pparams;
2474   pstring pathname;
2475   int reply_size = 0;
2476   int max_referral_level = SVAL(params,0);
2477
2478
2479   DEBUG(10,("call_trans2getdfsreferral\n"));
2480
2481   if(!lp_host_msdfs())
2482     return ERROR_DOS(ERRDOS,ERRbadfunc);
2483
2484   srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
2485
2486   if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2487     return ERROR_DOS(ERRDOS,ERRbadfile);
2488     
2489   SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2490   send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2491
2492   return(-1);
2493 }
2494
2495 #define LMCAT_SPL       0x53
2496 #define LMFUNC_GETJOBID 0x60
2497
2498 /****************************************************************************
2499  Reply to a TRANS2_IOCTL - used for OS/2 printing.
2500 ****************************************************************************/
2501
2502 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2503                             char* outbuf, int length, int bufsize,
2504                             char** pparams, char** ppdata)
2505 {
2506   char *pdata = *ppdata;
2507   files_struct *fsp = file_fsp(inbuf,smb_vwv15);
2508
2509   if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2510       (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2511     pdata = Realloc(*ppdata, 32);
2512     if(pdata == NULL) {
2513       return ERROR_DOS(ERRDOS,ERRnomem);
2514     }
2515     *ppdata = pdata;
2516
2517         /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
2518            CAN ACCEPT THIS IN UNICODE. JRA. */
2519
2520     SSVAL(pdata,0,fsp->print_jobid);                     /* Job number */
2521         srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
2522     srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
2523     send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
2524     return(-1);
2525   } else {
2526     DEBUG(2,("Unknown TRANS2_IOCTL\n"));
2527     return ERROR_DOS(ERRSRV,ERRerror);
2528   }
2529 }
2530
2531 /****************************************************************************
2532  Reply to a SMBfindclose (stop trans2 directory search).
2533 ****************************************************************************/
2534
2535 int reply_findclose(connection_struct *conn,
2536                     char *inbuf,char *outbuf,int length,int bufsize)
2537 {
2538         int outsize = 0;
2539         int dptr_num=SVALS(inbuf,smb_vwv0);
2540         START_PROFILE(SMBfindclose);
2541
2542         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
2543
2544         dptr_close(&dptr_num);
2545
2546         outsize = set_message(outbuf,0,0,True);
2547
2548         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
2549
2550         END_PROFILE(SMBfindclose);
2551         return(outsize);
2552 }
2553
2554 /****************************************************************************
2555  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
2556 ****************************************************************************/
2557
2558 int reply_findnclose(connection_struct *conn, 
2559                      char *inbuf,char *outbuf,int length,int bufsize)
2560 {
2561         int outsize = 0;
2562         int dptr_num= -1;
2563         START_PROFILE(SMBfindnclose);
2564         
2565         dptr_num = SVAL(inbuf,smb_vwv0);
2566
2567         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
2568
2569         /* We never give out valid handles for a 
2570            findnotifyfirst - so any dptr_num is ok here. 
2571            Just ignore it. */
2572
2573         outsize = set_message(outbuf,0,0,True);
2574
2575         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
2576
2577         END_PROFILE(SMBfindnclose);
2578         return(outsize);
2579 }
2580
2581 /****************************************************************************
2582  Reply to a SMBtranss2 - just ignore it!
2583 ****************************************************************************/
2584
2585 int reply_transs2(connection_struct *conn,
2586                   char *inbuf,char *outbuf,int length,int bufsize)
2587 {
2588         START_PROFILE(SMBtranss2);
2589         DEBUG(4,("Ignoring transs2 of length %d\n",length));
2590         END_PROFILE(SMBtranss2);
2591         return(-1);
2592 }
2593
2594 /****************************************************************************
2595  Reply to a SMBtrans2.
2596 ****************************************************************************/
2597
2598 int reply_trans2(connection_struct *conn,
2599                  char *inbuf,char *outbuf,int length,int bufsize)
2600 {
2601         int outsize = 0;
2602         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
2603         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
2604 #if 0
2605         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
2606         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
2607         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
2608         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
2609         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
2610         int32 timeout = IVALS(inbuf,smb_timeout);
2611 #endif
2612         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
2613         unsigned int tran_call = SVAL(inbuf, smb_setup0);
2614         char *params = NULL, *data = NULL;
2615         int num_params, num_params_sofar, num_data, num_data_sofar;
2616         START_PROFILE(SMBtrans2);
2617
2618         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
2619                 /* Queue this open message as we are the process of an
2620                  * oplock break.  */
2621
2622                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
2623                 DEBUGADD(2,( "in oplock break state.\n"));
2624
2625                 push_oplock_pending_smb_message(inbuf, length);
2626                 END_PROFILE(SMBtrans2);
2627                 return -1;
2628         }
2629         
2630         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
2631             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
2632                 END_PROFILE(SMBtrans2);
2633                 return ERROR_DOS(ERRSRV,ERRaccess);
2634         }
2635
2636         outsize = set_message(outbuf,0,0,True);
2637
2638         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
2639            is so as a sanity check */
2640         if (suwcnt != 1) {
2641                 /*
2642                  * Need to have rc=0 for ioctl to get job id for OS/2.
2643                  *  Network printing will fail if function is not successful.
2644                  *  Similar function in reply.c will be used if protocol
2645                  *  is LANMAN1.0 instead of LM1.2X002.
2646                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
2647                  *  outbuf doesn't have to be set(only job id is used).
2648                  */
2649                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
2650                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2651                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2652                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
2653                 } else {
2654                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
2655                         DEBUG(2,("Transaction is %d\n",tran_call));
2656                         END_PROFILE(SMBtrans2);
2657                         return ERROR_DOS(ERRSRV,ERRerror);
2658                 }
2659         }
2660     
2661         /* Allocate the space for the maximum needed parameters and data */
2662         if (total_params > 0)
2663                 params = (char *)malloc(total_params);
2664         if (total_data > 0)
2665                 data = (char *)malloc(total_data);
2666   
2667         if ((total_params && !params)  || (total_data && !data)) {
2668                 DEBUG(2,("Out of memory in reply_trans2\n"));
2669                 SAFE_FREE(params);
2670                 SAFE_FREE(data); 
2671                 END_PROFILE(SMBtrans2);
2672                 return ERROR_DOS(ERRDOS,ERRnomem);
2673         }
2674
2675         /* Copy the param and data bytes sent with this request into
2676            the params buffer */
2677         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
2678         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
2679
2680         if (num_params > total_params || num_data > total_data)
2681                 exit_server("invalid params in reply_trans2");
2682
2683         if(params)
2684                 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
2685         if(data)
2686                 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
2687
2688         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
2689                 /* We need to send an interim response then receive the rest
2690                    of the parameter/data bytes */
2691                 outsize = set_message(outbuf,0,0,True);
2692                 if (!send_smb(smbd_server_fd(),outbuf))
2693                         exit_server("reply_trans2: send_smb failed.");
2694
2695                 while (num_data_sofar < total_data || 
2696                        num_params_sofar < total_params) {
2697                         BOOL ret;
2698
2699                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
2700                         
2701                         if ((ret && 
2702                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
2703                                 outsize = set_message(outbuf,0,0,True);
2704                                 if(ret)
2705                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
2706                                 else
2707                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
2708                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
2709                                 SAFE_FREE(params);
2710                                 SAFE_FREE(data);
2711                                 END_PROFILE(SMBtrans2);
2712                                 return ERROR_DOS(ERRSRV,ERRerror);
2713                         }
2714       
2715                         /* Revise total_params and total_data in case
2716                            they have changed downwards */
2717                         total_params = SVAL(inbuf, smb_tpscnt);
2718                         total_data = SVAL(inbuf, smb_tdscnt);
2719                         num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
2720                         num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
2721                         if (num_params_sofar > total_params || num_data_sofar > total_data)
2722                                 exit_server("data overflow in trans2");
2723                         
2724                         memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
2725                                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
2726                         memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
2727                                 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
2728                 }
2729         }
2730         
2731         if (Protocol >= PROTOCOL_NT1) {
2732                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
2733         }
2734
2735         /* Now we must call the relevant TRANS2 function */
2736         switch(tran_call)  {
2737         case TRANSACT2_OPEN:
2738                 START_PROFILE_NESTED(Trans2_open);
2739                 outsize = call_trans2open(conn, 
2740                                           inbuf, outbuf, bufsize, 
2741                                           &params, &data);
2742                 END_PROFILE_NESTED(Trans2_open);
2743                 break;
2744
2745         case TRANSACT2_FINDFIRST:
2746                 START_PROFILE_NESTED(Trans2_findfirst);
2747                 outsize = call_trans2findfirst(conn, inbuf, outbuf, 
2748                                                bufsize, &params, &data);
2749                 END_PROFILE_NESTED(Trans2_findfirst);
2750                 break;
2751
2752         case TRANSACT2_FINDNEXT:
2753                 START_PROFILE_NESTED(Trans2_findnext);
2754                 outsize = call_trans2findnext(conn, inbuf, outbuf, 
2755                                               length, bufsize, 
2756                                               &params, &data);
2757                 END_PROFILE_NESTED(Trans2_findnext);
2758                 break;
2759
2760         case TRANSACT2_QFSINFO:
2761                 START_PROFILE_NESTED(Trans2_qfsinfo);
2762             outsize = call_trans2qfsinfo(conn, inbuf, outbuf, 
2763                                          length, bufsize, &params, 
2764                                          &data);
2765                 END_PROFILE_NESTED(Trans2_qfsinfo);
2766             break;
2767
2768         case TRANSACT2_SETFSINFO:
2769                 START_PROFILE_NESTED(Trans2_setfsinfo);
2770                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, 
2771                                                length, bufsize, 
2772                                                &params, &data);
2773                 END_PROFILE_NESTED(Trans2_setfsinfo);
2774                 break;
2775
2776         case TRANSACT2_QPATHINFO:
2777         case TRANSACT2_QFILEINFO:
2778                 START_PROFILE_NESTED(Trans2_qpathinfo);
2779                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, 
2780                                                    length, bufsize, 
2781                                                    &params, &data, total_data);
2782                 END_PROFILE_NESTED(Trans2_qpathinfo);
2783                 break;
2784         case TRANSACT2_SETPATHINFO:
2785         case TRANSACT2_SETFILEINFO:
2786                 START_PROFILE_NESTED(Trans2_setpathinfo);
2787                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, 
2788                                                      length, bufsize, 
2789                                                      &params, &data, 
2790                                                      total_data);
2791                 END_PROFILE_NESTED(Trans2_setpathinfo);
2792                 break;
2793
2794         case TRANSACT2_FINDNOTIFYFIRST:
2795                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
2796                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, 
2797                                                      length, bufsize, 
2798                                                      &params, &data);
2799                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
2800                 break;
2801
2802         case TRANSACT2_FINDNOTIFYNEXT:
2803                 START_PROFILE_NESTED(Trans2_findnotifynext);
2804                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, 
2805                                                     length, bufsize, 
2806                                                     &params, &data);
2807                 END_PROFILE_NESTED(Trans2_findnotifynext);
2808                 break;
2809         case TRANSACT2_MKDIR:
2810                 START_PROFILE_NESTED(Trans2_mkdir);
2811                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, 
2812                                            bufsize, &params, &data);
2813                 END_PROFILE_NESTED(Trans2_mkdir);
2814                 break;
2815
2816         case TRANSACT2_GET_DFS_REFERRAL:
2817                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
2818         outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length,
2819                                             bufsize, &params, &data);
2820                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
2821                 break;
2822         case TRANSACT2_IOCTL:
2823                 START_PROFILE_NESTED(Trans2_ioctl);
2824                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length,
2825                                                 bufsize,&params,&data);
2826                 END_PROFILE_NESTED(Trans2_ioctl);
2827                 break;
2828         default:
2829                 /* Error in request */
2830                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
2831                 SAFE_FREE(params);
2832                 SAFE_FREE(data);
2833                 END_PROFILE(SMBtrans2);
2834                 return ERROR_DOS(ERRSRV,ERRerror);
2835         }
2836         
2837         /* As we do not know how many data packets will need to be
2838            returned here the various call_trans2xxxx calls
2839            must send their own. Thus a call_trans2xxx routine only
2840            returns a value other than -1 when it wants to send
2841            an error packet. 
2842         */
2843         
2844         SAFE_FREE(params);
2845         SAFE_FREE(data);
2846         END_PROFILE(SMBtrans2);
2847         return outsize; /* If a correct response was needed the
2848                            call_trans2xxx calls have already sent
2849                            it. If outsize != -1 then it is returning */
2850 }