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