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