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