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