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