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