bug 696; check for an invalid fid before dereferencing the fsp pointer
[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
1845         if (!params)
1846                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1847
1848         if (tran_call == TRANSACT2_QFILEINFO) {
1849                 if (total_params < 4)
1850                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1851
1852                 fsp = file_fsp(params,0);
1853                 info_level = SVAL(params,2);
1854
1855                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1856
1857                 if(fsp && (fsp->fake_file_handle)) {
1858                         /*
1859                          * This is actually for the QUOTA_FAKE_FILE --metze
1860                          */
1861                                                 
1862                         pstrcpy(fname, fsp->fsp_name);
1863                         unix_convert(fname,conn,0,&bad_path,&sbuf);
1864                         if (!check_name(fname,conn)) {
1865                                 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
1866                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1867                         }
1868                         
1869                 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1870                         /*
1871                          * This is actually a QFILEINFO on a directory
1872                          * handle (returned from an NT SMB). NT5.0 seems
1873                          * to do this call. JRA.
1874                          */
1875                         pstrcpy(fname, fsp->fsp_name);
1876                         unix_convert(fname,conn,0,&bad_path,&sbuf);
1877                         if (!check_name(fname,conn)) {
1878                                 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1879                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1880                         }
1881                   
1882                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1883                                 /* Always do lstat for UNIX calls. */
1884                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1885                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1886                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1887                                 }
1888                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1889                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1890                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1891                         }
1892
1893                         delete_pending = fsp->directory_delete_on_close;
1894                 } else {
1895                         /*
1896                          * Original code - this is an open file.
1897                          */
1898                         CHECK_FSP(fsp,conn);
1899
1900                         pstrcpy(fname, fsp->fsp_name);
1901                         if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
1902                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1903                                 return(UNIXERROR(ERRDOS,ERRbadfid));
1904                         }
1905                         pos = fsp->position_information;
1906                         delete_pending = fsp->delete_on_close;
1907                 }
1908         } else {
1909                 /* qpathinfo */
1910                 if (total_params < 6)
1911                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1912
1913                 info_level = SVAL(params,0);
1914
1915                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1916
1917                 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1918
1919                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1920
1921                 unix_convert(fname,conn,0,&bad_path,&sbuf);
1922                 if (!check_name(fname,conn)) {
1923                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1924                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1925                 }
1926
1927                 if (INFO_LEVEL_IS_UNIX(info_level)) {
1928                         /* Always do lstat for UNIX calls. */
1929                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1930                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1931                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1932                         }
1933                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1934                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1935                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1936                 }
1937         }
1938
1939         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1940                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1941
1942         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
1943                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
1944
1945         p = strrchr_m(fname,'/'); 
1946         if (!p)
1947                 base_name = fname;
1948         else
1949                 base_name = p+1;
1950
1951         mode = dos_mode(conn,fname,&sbuf);
1952         if (!mode)
1953                 mode = FILE_ATTRIBUTE_NORMAL;
1954
1955         fullpathname = fname;
1956         file_size = get_file_size(sbuf);
1957         allocation_size = get_allocation_size(fsp,&sbuf);
1958         if (mode & aDIR)
1959                 file_size = 0;
1960
1961         params = Realloc(*pparams,2);
1962         if (params == NULL)
1963           return ERROR_DOS(ERRDOS,ERRnomem);
1964         *pparams = params;
1965         memset((char *)params,'\0',2);
1966         data_size = max_data_bytes + 1024;
1967         pdata = Realloc(*ppdata, data_size); 
1968         if ( pdata == NULL )
1969                 return ERROR_DOS(ERRDOS,ERRnomem);
1970         *ppdata = pdata;
1971
1972         if (total_data > 0 && IVAL(pdata,0) == total_data) {
1973                 /* uggh, EAs for OS2 */
1974                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1975                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1976         }
1977
1978         memset((char *)pdata,'\0',data_size);
1979
1980         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1981
1982         if (lp_dos_filetime_resolution(SNUM(conn))) {
1983                 c_time &= ~1;
1984                 sbuf.st_atime &= ~1;
1985                 sbuf.st_mtime &= ~1;
1986                 sbuf.st_mtime &= ~1;
1987         }
1988
1989         /* NT expects the name to be in an exact form of the *full*
1990            filename. See the trans2 torture test */
1991         if (strequal(base_name,".")) {
1992                 pstrcpy(dos_fname, "\\");
1993         } else {
1994                 pstr_sprintf(dos_fname, "\\%s", fname);
1995                 string_replace(dos_fname, '/', '\\');
1996         }
1997
1998         switch (info_level) {
1999                 case SMB_INFO_STANDARD:
2000                 case SMB_INFO_QUERY_EA_SIZE:
2001                         data_size = (info_level==1?22:26);
2002                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2003                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2004                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2005                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2006                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2007                         SSVAL(pdata,l1_attrFile,mode);
2008                         SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */
2009                         break;
2010
2011                 case SMB_INFO_IS_NAME_VALID:
2012                         if (tran_call == TRANSACT2_QFILEINFO) {
2013                                 /* os/2 needs this ? really ?*/      
2014                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
2015                         }
2016                         data_size = 0;
2017                         break;
2018                         
2019                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2020                         data_size = 24;
2021                         put_dos_date2(pdata,0,c_time);
2022                         put_dos_date2(pdata,4,sbuf.st_atime);
2023                         put_dos_date2(pdata,8,sbuf.st_mtime);
2024                         SIVAL(pdata,12,(uint32)file_size);
2025                         SIVAL(pdata,16,(uint32)allocation_size);
2026                         SIVAL(pdata,20,mode);
2027                         break;
2028
2029                 case SMB_INFO_QUERY_ALL_EAS:
2030                         data_size = 4;
2031                         SIVAL(pdata,0,0); /* ea size */
2032                         break;
2033
2034                 case SMB_FILE_BASIC_INFORMATION:
2035                 case SMB_QUERY_FILE_BASIC_INFO:
2036
2037                         if (info_level == SMB_QUERY_FILE_BASIC_INFO)
2038                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2039                         else {
2040                                 data_size = 40;
2041                                 SIVAL(pdata,36,0);
2042                         }
2043                         put_long_date(pdata,c_time);
2044                         put_long_date(pdata+8,sbuf.st_atime);
2045                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2046                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2047                         SIVAL(pdata,32,mode);
2048
2049                         DEBUG(5,("SMB_QFBI - "));
2050                         {
2051                                 time_t create_time = c_time;
2052                                 DEBUG(5,("create: %s ", ctime(&create_time)));
2053                         }
2054                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2055                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2056                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2057                         DEBUG(5,("mode: %x\n", mode));
2058
2059                         break;
2060
2061                 case SMB_FILE_STANDARD_INFORMATION:
2062                 case SMB_QUERY_FILE_STANDARD_INFO:
2063
2064                         data_size = 24;
2065                         SOFF_T(pdata,0,allocation_size);
2066                         SOFF_T(pdata,8,file_size);
2067                         if (delete_pending & sbuf.st_nlink)
2068                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2069                         else
2070                                 SIVAL(pdata,16,sbuf.st_nlink);
2071                         SCVAL(pdata,20,0);
2072                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2073                         break;
2074
2075                 case SMB_FILE_EA_INFORMATION:
2076                 case SMB_QUERY_FILE_EA_INFO:
2077                         data_size = 4;
2078                         break;
2079
2080                 /* Get the 8.3 name - used if NT SMB was negotiated. */
2081                 case SMB_QUERY_FILE_ALT_NAME_INFO:
2082                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2083                 {
2084                         pstring short_name;
2085
2086                         pstrcpy(short_name,base_name);
2087                         /* Mangle if not already 8.3 */
2088                         if(!mangle_is_8_3(short_name, True)) {
2089                                 mangle_map(short_name,True,True,SNUM(conn));
2090                         }
2091                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2092                         data_size = 4 + len;
2093                         SIVAL(pdata,0,len);
2094                         break;
2095                 }
2096
2097                 case SMB_QUERY_FILE_NAME_INFO:
2098                         /*
2099                           this must be *exactly* right for ACLs on mapped drives to work
2100                          */
2101                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2102                         data_size = 4 + len;
2103                         SIVAL(pdata,0,len);
2104                         break;
2105
2106                 case SMB_FILE_ALLOCATION_INFORMATION:
2107                 case SMB_QUERY_FILE_ALLOCATION_INFO:
2108                         data_size = 8;
2109                         SOFF_T(pdata,0,allocation_size);
2110                         break;
2111
2112                 case SMB_FILE_END_OF_FILE_INFORMATION:
2113                 case SMB_QUERY_FILE_END_OF_FILEINFO:
2114                         data_size = 8;
2115                         SOFF_T(pdata,0,file_size);
2116                         break;
2117
2118                 case SMB_QUERY_FILE_ALL_INFO:
2119                 case SMB_FILE_ALL_INFORMATION:
2120                         put_long_date(pdata,c_time);
2121                         put_long_date(pdata+8,sbuf.st_atime);
2122                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2123                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2124                         SIVAL(pdata,32,mode);
2125                         pdata += 40;
2126                         SOFF_T(pdata,0,allocation_size);
2127                         SOFF_T(pdata,8,file_size);
2128                         if (delete_pending && sbuf.st_nlink)
2129                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2130                         else
2131                                 SIVAL(pdata,16,sbuf.st_nlink);
2132                         SCVAL(pdata,20,delete_pending);
2133                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2134                         pdata += 24;
2135                         pdata += 4; /* EA info */
2136                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2137                         SIVAL(pdata,0,len);
2138                         pdata += 4 + len;
2139                         data_size = PTR_DIFF(pdata,(*ppdata));
2140                         break;
2141
2142                 case SMB_FILE_INTERNAL_INFORMATION:
2143                         /* This should be an index number - looks like
2144                            dev/ino to me :-) 
2145
2146                            I think this causes us to fail the IFSKIT
2147                            BasicFileInformationTest. -tpot */
2148
2149                         SIVAL(pdata,0,sbuf.st_dev);
2150                         SIVAL(pdata,4,sbuf.st_ino);
2151                         data_size = 8;
2152                         break;
2153
2154                 case SMB_FILE_ACCESS_INFORMATION:
2155                         SIVAL(pdata,0,0x12019F); /* ??? */
2156                         data_size = 4;
2157                         break;
2158
2159                 case SMB_FILE_NAME_INFORMATION:
2160                         /* Pathname with leading '\'. */
2161                         {
2162                                 size_t byte_len;
2163                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2164                                 SIVAL(pdata,0,byte_len);
2165                                 data_size = 4 + byte_len;
2166                                 break;
2167                         }
2168
2169                 case SMB_FILE_DISPOSITION_INFORMATION:
2170                         data_size = 1;
2171                         SCVAL(pdata,0,delete_pending);
2172                         break;
2173
2174                 case SMB_FILE_POSITION_INFORMATION:
2175                         data_size = 8;
2176                         SOFF_T(pdata,0,pos);
2177                         break;
2178
2179                 case SMB_FILE_MODE_INFORMATION:
2180                         SIVAL(pdata,0,mode);
2181                         data_size = 4;
2182                         break;
2183
2184                 case SMB_FILE_ALIGNMENT_INFORMATION:
2185                         SIVAL(pdata,0,0); /* No alignment needed. */
2186                         data_size = 4;
2187                         break;
2188
2189 #if 0
2190                 /*
2191                  * NT4 server just returns "invalid query" to this - if we try to answer
2192                  * it then NTws gets a BSOD! (tridge).
2193                  * W2K seems to want this. JRA.
2194                  */
2195                 case SMB_QUERY_FILE_STREAM_INFO:
2196 #endif
2197                 case SMB_FILE_STREAM_INFORMATION:
2198                         if (mode & aDIR) {
2199                                 data_size = 0;
2200                         } else {
2201                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2202                                 SIVAL(pdata,0,0); /* ??? */
2203                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2204                                 SOFF_T(pdata,8,file_size);
2205                                 SIVAL(pdata,16,allocation_size);
2206                                 SIVAL(pdata,20,0); /* ??? */
2207                                 data_size = 24 + byte_len;
2208                         }
2209                         break;
2210
2211                 case SMB_QUERY_COMPRESSION_INFO:
2212                 case SMB_FILE_COMPRESSION_INFORMATION:
2213                         SOFF_T(pdata,0,file_size);
2214                         SIVAL(pdata,8,0); /* ??? */
2215                         SIVAL(pdata,12,0); /* ??? */
2216                         data_size = 16;
2217                         break;
2218
2219                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2220                         put_long_date(pdata,c_time);
2221                         put_long_date(pdata+8,sbuf.st_atime);
2222                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2223                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2224                         SIVAL(pdata,32,allocation_size);
2225                         SOFF_T(pdata,40,file_size);
2226                         SIVAL(pdata,48,mode);
2227                         SIVAL(pdata,52,0); /* ??? */
2228                         data_size = 56;
2229                         break;
2230
2231                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2232                         SIVAL(pdata,0,mode);
2233                         SIVAL(pdata,4,0);
2234                         data_size = 8;
2235                         break;
2236
2237                 /*
2238                  * CIFS UNIX Extensions.
2239                  */
2240
2241                 case SMB_QUERY_FILE_UNIX_BASIC:
2242
2243                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2244
2245                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
2246                         pdata += 8;
2247
2248                         SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2249                         pdata += 8;
2250
2251                         put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
2252                         put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
2253                         put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
2254                         pdata += 24;
2255
2256                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
2257                         SIVAL(pdata,4,0);
2258                         pdata += 8;
2259
2260                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
2261                         SIVAL(pdata,4,0);
2262                         pdata += 8;
2263
2264                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2265                         pdata += 4;
2266
2267                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
2268                         SIVAL(pdata,4,0);
2269                         pdata += 8;
2270
2271                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
2272                         SIVAL(pdata,4,0);
2273                         pdata += 8;
2274
2275                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
2276                         pdata += 8;
2277                                 
2278                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
2279                         SIVAL(pdata,4,0);
2280                         pdata += 8;
2281
2282                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
2283                         SIVAL(pdata,4,0);
2284                         pdata += 8+1;
2285                         data_size = PTR_DIFF(pdata,(*ppdata));
2286
2287                         {
2288                                 int i;
2289                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2290
2291                                 for (i=0; i<100; i++)
2292                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2293                                 DEBUG(4,("\n"));
2294                         }
2295
2296                         break;
2297
2298                 case SMB_QUERY_FILE_UNIX_LINK:
2299                         {
2300                                 pstring buffer;
2301
2302 #ifdef S_ISLNK
2303                                 if(!S_ISLNK(sbuf.st_mode))
2304                                         return(UNIXERROR(ERRSRV,ERRbadlink));
2305 #else
2306                                 return(UNIXERROR(ERRDOS,ERRbadlink));
2307 #endif
2308                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
2309                                 if (len == -1)
2310                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2311                                 buffer[len] = 0;
2312                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2313                                 pdata += len;
2314                                 data_size = PTR_DIFF(pdata,(*ppdata));
2315
2316                                 break;
2317                         }
2318
2319                 default:
2320                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2321         }
2322
2323         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2324
2325         return(-1);
2326 }
2327
2328 /****************************************************************************
2329  Deal with the internal needs of setting the delete on close flag. Note that
2330  as the tdb locking is recursive, it is safe to call this from within 
2331  open_file_shared. JRA.
2332 ****************************************************************************/
2333
2334 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2335 {
2336         /*
2337          * Only allow delete on close for writable shares.
2338          */
2339
2340         if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2341                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2342                                 fsp->fsp_name ));
2343                                 return NT_STATUS_ACCESS_DENIED;
2344         }
2345         /*
2346          * Only allow delete on close for files/directories opened with delete intent.
2347          */
2348
2349         if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2350                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2351                                 fsp->fsp_name ));
2352                                 return NT_STATUS_ACCESS_DENIED;
2353         }
2354
2355         if(fsp->is_directory) {
2356                 fsp->directory_delete_on_close = delete_on_close;
2357                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2358                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2359         } else {
2360                 fsp->delete_on_close = delete_on_close;
2361                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2362                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2363         }
2364
2365         return NT_STATUS_OK;
2366 }
2367
2368 /****************************************************************************
2369  Sets the delete on close flag over all share modes on this file.
2370  Modify the share mode entry for all files open
2371  on this device and inode to tell other smbds we have
2372  changed the delete on close flag. This will be noticed
2373  in the close code, the last closer will delete the file
2374  if flag is set.
2375 ****************************************************************************/
2376
2377 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2378 {
2379         DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2380                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2381
2382         if (fsp->is_directory || fsp->is_stat)
2383                 return NT_STATUS_OK;
2384
2385         if (lock_share_entry_fsp(fsp) == False)
2386                 return NT_STATUS_ACCESS_DENIED;
2387
2388         if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2389                 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2390                         fsp->fsp_name ));
2391                 unlock_share_entry_fsp(fsp);
2392                 return NT_STATUS_ACCESS_DENIED;
2393         }
2394
2395         unlock_share_entry_fsp(fsp);
2396         return NT_STATUS_OK;
2397 }
2398
2399 /****************************************************************************
2400  Returns true if this pathname is within the share, and thus safe.
2401 ****************************************************************************/
2402
2403 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2404 {
2405 #ifdef PATH_MAX
2406         char resolved_name[PATH_MAX+1];
2407 #else
2408         pstring resolved_name;
2409 #endif
2410         fstring last_component;
2411         pstring link_dest;
2412         pstring link_test;
2413         char *p;
2414         BOOL bad_path = False;
2415         SMB_STRUCT_STAT sbuf;
2416
2417         pstrcpy(link_dest, link_dest_in);
2418         unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2419
2420         /* Store the UNIX converted path. */
2421         pstrcpy(link_dest_out, link_dest);
2422
2423         p = strrchr(link_dest, '/');
2424         if (p) {
2425                 fstrcpy(last_component, p+1);
2426                 *p = '\0';
2427         } else {
2428                 fstrcpy(last_component, link_dest);
2429                 pstrcpy(link_dest, "./");
2430         }
2431                 
2432         if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2433                 return -1;
2434
2435         pstrcpy(link_dest, resolved_name);
2436         pstrcat(link_dest, "/");
2437         pstrcat(link_dest, last_component);
2438
2439         if (*link_dest != '/') {
2440                 /* Relative path. */
2441                 pstrcpy(link_test, conn->connectpath);
2442                 pstrcat(link_test, "/");
2443                 pstrcat(link_test, link_dest);
2444         } else {
2445                 pstrcpy(link_test, link_dest);
2446         }
2447
2448         /*
2449          * Check if the link is within the share.
2450          */
2451
2452         if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2453                 errno = EACCES;
2454                 return -1;
2455         }
2456         return 0;
2457 }
2458
2459 /****************************************************************************
2460  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2461 ****************************************************************************/
2462
2463 static int call_trans2setfilepathinfo(connection_struct *conn,
2464                                         char *inbuf, char *outbuf, int length, int bufsize,
2465                                         char **pparams, int total_params, char **ppdata, int total_data)
2466 {
2467         char *params = *pparams;
2468         char *pdata = *ppdata;
2469         uint16 tran_call = SVAL(inbuf, smb_setup0);
2470         uint16 info_level;
2471         int dosmode=0;
2472         SMB_OFF_T size=0;
2473         struct utimbuf tvs;
2474         SMB_STRUCT_STAT sbuf;
2475         pstring fname;
2476         int fd = -1;
2477         BOOL bad_path = False;
2478         files_struct *fsp = NULL;
2479         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2480         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2481         mode_t unixmode = 0;
2482
2483         if (!params)
2484                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2485
2486         if (tran_call == TRANSACT2_SETFILEINFO) {
2487                 if (total_params < 4)
2488                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2489
2490                 fsp = file_fsp(params,0);
2491                 info_level = SVAL(params,2);    
2492
2493                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2494                         /*
2495                          * This is actually a SETFILEINFO on a directory
2496                          * handle (returned from an NT SMB). NT5.0 seems
2497                          * to do this call. JRA.
2498                          */
2499                         pstrcpy(fname, fsp->fsp_name);
2500                         unix_convert(fname,conn,0,&bad_path,&sbuf);
2501                         if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2502                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2503                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2504                         }
2505                 } else if (fsp && fsp->print_file) {
2506                         /*
2507                          * Doing a DELETE_ON_CLOSE should cancel a print job.
2508                          */
2509                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2510                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2511
2512                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2513         
2514                                 SSVAL(params,0,0);
2515                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2516                                 return(-1);
2517                         } else
2518                                 return (UNIXERROR(ERRDOS,ERRbadpath));
2519             } else {
2520                         /*
2521                          * Original code - this is an open file.
2522                          */
2523                         CHECK_FSP(fsp,conn);
2524
2525                         pstrcpy(fname, fsp->fsp_name);
2526                         fd = fsp->fd;
2527
2528                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
2529                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2530                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2531                         }
2532                 }
2533         } else {
2534                 /* set path info */
2535                 if (total_params < 6)
2536                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2537
2538                 info_level = SVAL(params,0);    
2539                 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2540                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2541                 if(!check_name(fname, conn)) {
2542                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2543                 }
2544
2545                 /*
2546                  * For CIFS UNIX extensions the target name may not exist.
2547                  */
2548
2549                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2550                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2551                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2552                 }    
2553         }
2554
2555         if (!CAN_WRITE(conn))
2556                 return ERROR_DOS(ERRSRV,ERRaccess);
2557
2558         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2559                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2560
2561         if (VALID_STAT(sbuf))
2562                 unixmode = sbuf.st_mode;
2563
2564         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
2565                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
2566
2567         /* Realloc the parameter and data sizes */
2568         params = Realloc(*pparams,2);
2569         if(params == NULL)
2570                 return ERROR_DOS(ERRDOS,ERRnomem);
2571         *pparams = params;
2572
2573         SSVAL(params,0,0);
2574
2575         if (fsp) {
2576                 /* the pending modtime overrides the current modtime */
2577                 sbuf.st_mtime = fsp->pending_modtime;
2578         }
2579
2580         size = get_file_size(sbuf);
2581         tvs.modtime = sbuf.st_mtime;
2582         tvs.actime = sbuf.st_atime;
2583         dosmode = dos_mode(conn,fname,&sbuf);
2584         unixmode = sbuf.st_mode;
2585
2586         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2587         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2588
2589         switch (info_level) {
2590                 case SMB_INFO_STANDARD:
2591                 {
2592                         if (total_data < 12)
2593                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2594
2595                         /* access time */
2596                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2597                         /* write time */
2598                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2599                         break;
2600                 }
2601
2602                 case SMB_INFO_SET_EA:
2603                         return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2604
2605                 /* XXXX um, i don't think this is right.
2606                         it's also not in the cifs6.txt spec.
2607                 */
2608                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2609                         if (total_data < 28)
2610                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2611
2612                         tvs.actime = make_unix_date2(pdata+8);
2613                         tvs.modtime = make_unix_date2(pdata+12);
2614                         size = IVAL(pdata,16);
2615                         dosmode = IVAL(pdata,24);
2616                         break;
2617
2618                 /* XXXX nor this.  not in cifs6.txt, either. */
2619                 case SMB_INFO_QUERY_ALL_EAS:
2620                         if (total_data < 28)
2621                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2622
2623                         tvs.actime = make_unix_date2(pdata+8);
2624                         tvs.modtime = make_unix_date2(pdata+12);
2625                         size = IVAL(pdata,16);
2626                         dosmode = IVAL(pdata,24);
2627                         break;
2628
2629                 case SMB_SET_FILE_BASIC_INFO:
2630                 case SMB_FILE_BASIC_INFORMATION:
2631                 {
2632                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2633                         time_t write_time;
2634                         time_t changed_time;
2635
2636                         if (total_data < 36)
2637                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2638
2639                         /* Ignore create time at offset pdata. */
2640
2641                         /* access time */
2642                         tvs.actime = interpret_long_date(pdata+8);
2643
2644                         write_time = interpret_long_date(pdata+16);
2645                         changed_time = interpret_long_date(pdata+24);
2646
2647                         tvs.modtime = MIN(write_time, changed_time);
2648
2649                         if (write_time > tvs.modtime && write_time != 0xffffffff) {
2650                                 tvs.modtime = write_time;
2651                         }
2652                         /* Prefer a defined time to an undefined one. */
2653                         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2654                                 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2655                                         ? changed_time : write_time);
2656
2657                         /* attributes */
2658                         dosmode = IVAL(pdata,32);
2659                         break;
2660                 }
2661
2662                 case SMB_FILE_ALLOCATION_INFORMATION:
2663                 case SMB_SET_FILE_ALLOCATION_INFO:
2664                 {
2665                         int ret = -1;
2666                         SMB_BIG_UINT allocation_size;
2667
2668                         if (total_data < 8)
2669                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2670
2671                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2672 #ifdef LARGE_SMB_OFF_T
2673                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2674 #else /* LARGE_SMB_OFF_T */
2675                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2676                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2677 #endif /* LARGE_SMB_OFF_T */
2678                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2679                                         fname, (double)allocation_size ));
2680
2681                         if (allocation_size)
2682                                 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2683
2684                         if(allocation_size != get_file_size(sbuf)) {
2685                                 SMB_STRUCT_STAT new_sbuf;
2686  
2687                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2688                                         fname, (double)allocation_size ));
2689  
2690                                 if (fd == -1) {
2691                                         files_struct *new_fsp = NULL;
2692                                         int access_mode = 0;
2693                                         int action = 0;
2694  
2695                                         if(global_oplock_break) {
2696                                                 /* Queue this file modify as we are the process of an oplock break.  */
2697  
2698                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2699                                                 DEBUGADD(2,( "in oplock break state.\n"));
2700  
2701                                                 push_oplock_pending_smb_message(inbuf, length);
2702                                                 return -1;
2703                                         }
2704  
2705                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2706                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
2707                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2708                                                                         0, 0, &access_mode, &action);
2709  
2710                                         if (new_fsp == NULL)
2711                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
2712                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
2713                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2714                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2715                                                                         new_fsp->fnum, strerror(errno)));
2716                                                 ret = -1;
2717                                         }
2718                                         close_file(new_fsp,True);
2719                                 } else {
2720                                         ret = vfs_allocate_file_space(fsp, allocation_size);
2721                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
2722                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2723                                                                         fsp->fnum, strerror(errno)));
2724                                                 ret = -1;
2725                                         }
2726                                 }
2727                                 if (ret == -1)
2728                                         return ERROR_NT(NT_STATUS_DISK_FULL);
2729
2730                                 /* Allocate can truncate size... */
2731                                 size = get_file_size(new_sbuf);
2732                         }
2733
2734                         break;
2735                 }
2736
2737                 case SMB_FILE_END_OF_FILE_INFORMATION:
2738                 case SMB_SET_FILE_END_OF_FILE_INFO:
2739                 {
2740                         if (total_data < 8)
2741                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2742
2743                         size = IVAL(pdata,0);
2744 #ifdef LARGE_SMB_OFF_T
2745                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2746 #else /* LARGE_SMB_OFF_T */
2747                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2748                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2749 #endif /* LARGE_SMB_OFF_T */
2750                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2751                         break;
2752                 }
2753
2754                 case SMB_FILE_DISPOSITION_INFORMATION:
2755                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2756                 {
2757                         BOOL delete_on_close;
2758                         NTSTATUS status;
2759
2760                         if (total_data < 1)
2761                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2762
2763                         delete_on_close = (CVAL(pdata,0) ? True : False);
2764
2765                         /* Just ignore this set on a path. */
2766                         if (tran_call != TRANSACT2_SETFILEINFO)
2767                                 break;
2768
2769                         if (fsp == NULL)
2770                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2771
2772                         status = set_delete_on_close_internal(fsp, delete_on_close);
2773  
2774                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
2775                                 return ERROR_NT(status);
2776
2777                         /* The set is across all open files on this dev/inode pair. */
2778                         status =set_delete_on_close_over_all(fsp, delete_on_close);
2779                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
2780                                 return ERROR_NT(status);
2781
2782                         break;
2783                 }
2784
2785                 case SMB_FILE_POSITION_INFORMATION:
2786                 {
2787                         SMB_BIG_UINT position_information;
2788
2789                         if (total_data < 8)
2790                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2791
2792                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
2793 #ifdef LARGE_SMB_OFF_T
2794                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2795 #else /* LARGE_SMB_OFF_T */
2796                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2797                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2798 #endif /* LARGE_SMB_OFF_T */
2799                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
2800                                         fname, (double)position_information ));
2801                         if (fsp)
2802                                 fsp->position_information = position_information;
2803                         break;
2804                 }
2805
2806                 /*
2807                  * CIFS UNIX extensions.
2808                  */
2809
2810                 case SMB_SET_FILE_UNIX_BASIC:
2811                 {
2812                         uint32 raw_unixmode;
2813
2814                         if (total_data < 100)
2815                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2816
2817                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2818                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2819                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
2820 #ifdef LARGE_SMB_OFF_T
2821                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2822 #else /* LARGE_SMB_OFF_T */
2823                                 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2824                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2825 #endif /* LARGE_SMB_OFF_T */
2826                         }
2827                         pdata+=24;          /* ctime & st_blocks are not changed */
2828                         tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2829                         tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2830                         pdata+=16;
2831                         set_owner = (uid_t)IVAL(pdata,0);
2832                         pdata += 8;
2833                         set_grp = (gid_t)IVAL(pdata,0);
2834                         pdata += 8;
2835                         raw_unixmode = IVAL(pdata,28);
2836                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2837                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
2838
2839                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2840 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2841                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2842
2843                         if (!VALID_STAT(sbuf)) {
2844
2845                                 /*
2846                                  * The only valid use of this is to create character and block
2847                                  * devices, and named pipes. This is deprecated (IMHO) and 
2848                                  * a new info level should be used for mknod. JRA.
2849                                  */
2850
2851 #if !defined(HAVE_MAKEDEV_FN)
2852                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2853 #else /* HAVE_MAKEDEV_FN */
2854                                 uint32 file_type = IVAL(pdata,0);
2855                                 uint32 dev_major = IVAL(pdata,4);
2856                                 uint32 dev_minor = IVAL(pdata,12);
2857
2858                                 uid_t myuid = geteuid();
2859                                 gid_t mygid = getegid();
2860                                 SMB_DEV_T dev;
2861
2862                                 if (tran_call == TRANSACT2_SETFILEINFO)
2863                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
2864
2865                                 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2866                                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2867
2868                                 dev = makedev(dev_major, dev_minor);
2869
2870                                 /* We can only create as the owner/group we are. */
2871
2872                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2873                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
2874                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2875                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
2876
2877                                 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2878                                                 file_type != UNIX_TYPE_FIFO)
2879                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
2880
2881                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2882 0%o for file %s\n", (double)dev, unixmode, fname ));
2883
2884                                 /* Ok - do the mknod. */
2885                                 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2886                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2887
2888                                 inherit_access_acl(conn, fname, unixmode);
2889
2890                                 SSVAL(params,0,0);
2891                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2892                                 return(-1);
2893 #endif /* HAVE_MAKEDEV_FN */
2894
2895                         }
2896
2897                         /*
2898                          * Deal with the UNIX specific mode set.
2899                          */
2900
2901                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2902                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2903                                         (unsigned int)unixmode, fname ));
2904                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
2905                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2906                         }
2907
2908                         /*
2909                          * Deal with the UNIX specific uid set.
2910                          */
2911
2912                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2913                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2914                                         (unsigned int)set_owner, fname ));
2915                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
2916                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2917                         }
2918
2919                         /*
2920                          * Deal with the UNIX specific gid set.
2921                          */
2922
2923                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2924                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2925                                         (unsigned int)set_owner, fname ));
2926                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
2927                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2928                         }
2929                         break;
2930                 }
2931
2932                 case SMB_SET_FILE_UNIX_LINK:
2933                 {
2934                         pstring link_dest;
2935                         /* Set a symbolic link. */
2936                         /* Don't allow this if follow links is false. */
2937
2938                         if (!lp_symlinks(SNUM(conn)))
2939                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2940
2941                         /* Disallow if already exists. */
2942                         if (VALID_STAT(sbuf))
2943                                 return(ERROR_DOS(ERRDOS,ERRbadpath));
2944
2945                         srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2946
2947                         if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2948                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2949
2950                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2951                                 fname, link_dest ));
2952
2953                         if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0)
2954                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2955                         SSVAL(params,0,0);
2956                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2957                         return(-1);
2958                 }
2959
2960                 case SMB_SET_FILE_UNIX_HLINK:
2961                 {
2962                         pstring link_dest;
2963
2964                         /* Set a hard link. */
2965
2966                         /* Disallow if already exists. */
2967                         if (VALID_STAT(sbuf))
2968                                 return(ERROR_DOS(ERRDOS,ERRbadpath));
2969
2970                         srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2971
2972                         if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2973                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2974
2975                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2976                                 fname, link_dest ));
2977
2978                         if (SMB_VFS_LINK(conn,link_dest,fname) != 0)
2979                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2980                         SSVAL(params,0,0);
2981                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2982                         return(-1);
2983                 }
2984
2985                 case SMB_FILE_RENAME_INFORMATION:
2986                 {
2987                         BOOL overwrite;
2988                         uint32 root_fid;
2989                         uint32 len;
2990                         pstring newname;
2991                         pstring base_name;
2992                         char *p;
2993                         NTSTATUS status;
2994
2995                         if (total_data < 12)
2996                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2997
2998                         overwrite = (CVAL(pdata,0) ? True : False);
2999                         root_fid = IVAL(pdata,4);
3000                         len = IVAL(pdata,8);
3001                         srvstr_pull(inbuf, newname, &pdata[12], sizeof(newname), len, 0);
3002
3003                         /* Check the new name has no '\' characters. */
3004                         if (strchr_m(newname, '\\') || strchr_m(newname, '/'))
3005                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3006
3007                         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3008
3009                         /* Create the base directory. */
3010                         pstrcpy(base_name, fname);
3011                         p = strrchr_m(base_name, '/');
3012                         if (p)
3013                                 *p = '\0';
3014                         /* Append the new name. */
3015                         pstrcat(base_name, "/");
3016                         pstrcat(base_name, newname);
3017
3018                         if (fsp) {
3019                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3020                                         fsp->fnum, fsp->fsp_name, base_name ));
3021                                 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3022                         } else {
3023                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3024                                         fname, newname ));
3025                                 status = rename_internals(conn, fname, base_name, overwrite);
3026                         }
3027                         if (!NT_STATUS_IS_OK(status))
3028                                 return ERROR_NT(status);
3029                         process_pending_change_notify_queue((time_t)0);
3030                         SSVAL(params,0,0);
3031                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3032                         return(-1);
3033                 }
3034                 default:
3035                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3036         }
3037
3038         /* get some defaults (no modifications) if any info is zero or -1. */
3039         if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3040                 tvs.actime = sbuf.st_atime;
3041
3042         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3043                 tvs.modtime = sbuf.st_mtime;
3044
3045         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3046         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3047         DEBUG(6,("size: %.0f ", (double)size));
3048
3049         if (dosmode) {
3050                 if (S_ISDIR(sbuf.st_mode))
3051                         dosmode |= aDIR;
3052                 else
3053                         dosmode &= ~aDIR;
3054         }
3055
3056         DEBUG(6,("dosmode: %x\n"  , dosmode));
3057
3058         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3059                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3060                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3061                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3062
3063                 /*
3064                  * Only do this test if we are not explicitly
3065                  * changing the size of a file.
3066                  */
3067                 if (!size)
3068                         size = get_file_size(sbuf);
3069         }
3070
3071         /*
3072          * Try and set the times, size and mode of this file -
3073          * if they are different from the current values
3074          */
3075         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3076                 if(fsp != NULL) {
3077                         /*
3078                          * This was a setfileinfo on an open file.
3079                          * NT does this a lot. It's actually pointless
3080                          * setting the time here, as it will be overwritten
3081                          * on the next write, so we save the request
3082                          * away and will set it on file close. JRA.
3083                          */
3084
3085                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3086                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3087                                 fsp->pending_modtime = tvs.modtime;
3088                         }
3089
3090                 } else {
3091
3092                         DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3093
3094                         if(file_utime(conn, fname, &tvs)!=0)
3095                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3096                 }
3097         }
3098
3099         /* check the mode isn't different, before changing it */
3100         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3101
3102                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3103
3104                 if(file_chmod(conn, fname, dosmode, NULL)) {
3105                         DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
3106                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3107                 }
3108         }
3109
3110         if (size != get_file_size(sbuf)) {
3111
3112                 int ret;
3113
3114                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3115                         fname, (double)size ));
3116
3117                 if (fd == -1) {
3118                         files_struct *new_fsp = NULL;
3119                         int access_mode = 0;
3120                         int action = 0;
3121
3122                         if(global_oplock_break) {
3123                                 /* Queue this file modify as we are the process of an oplock break.  */
3124
3125                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3126                                 DEBUGADD(2,( "in oplock break state.\n"));
3127
3128                                 push_oplock_pending_smb_message(inbuf, length);
3129                                 return -1;
3130                         }
3131
3132                         new_fsp = open_file_shared(conn, fname, &sbuf,
3133                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
3134                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3135                                                 0, 0, &access_mode, &action);
3136         
3137                         if (new_fsp == NULL)
3138                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3139                         ret = vfs_set_filelen(new_fsp, size);
3140                         close_file(new_fsp,True);
3141                 } else {
3142                         ret = vfs_set_filelen(fsp, size);
3143                 }
3144
3145                 if (ret == -1)
3146                         return (UNIXERROR(ERRHRD,ERRdiskfull));
3147         }
3148
3149         SSVAL(params,0,0);
3150         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3151   
3152         return(-1);
3153 }
3154
3155 /****************************************************************************
3156  Reply to a TRANS2_MKDIR (make directory with extended attributes).
3157 ****************************************************************************/
3158
3159 static int call_trans2mkdir(connection_struct *conn,
3160                             char *inbuf, char *outbuf, int length, int bufsize,
3161                                 char **pparams, int total_params, char **ppdata, int total_data)
3162 {
3163         char *params = *pparams;
3164         pstring directory;
3165         int ret = -1;
3166         SMB_STRUCT_STAT sbuf;
3167         BOOL bad_path = False;
3168
3169         if (!CAN_WRITE(conn))
3170                 return ERROR_DOS(ERRSRV,ERRaccess);
3171
3172         if (total_params < 4)
3173                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3174
3175         srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
3176
3177         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3178
3179         unix_convert(directory,conn,0,&bad_path,&sbuf);
3180         if (check_name(directory,conn))
3181                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3182   
3183         if(ret < 0) {
3184                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3185                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3186         }
3187
3188         /* Realloc the parameter and data sizes */
3189         params = Realloc(*pparams,2);
3190         if(params == NULL)
3191                 return ERROR_DOS(ERRDOS,ERRnomem);
3192         *pparams = params;
3193
3194         SSVAL(params,0,0);
3195
3196         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3197   
3198         return(-1);
3199 }
3200
3201 /****************************************************************************
3202  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3203  We don't actually do this - we just send a null response.
3204 ****************************************************************************/
3205
3206 static int call_trans2findnotifyfirst(connection_struct *conn,
3207                                         char *inbuf, char *outbuf, int length, int bufsize,
3208                                         char **pparams, int total_params, char **ppdata, int total_data)
3209 {
3210         static uint16 fnf_handle = 257;
3211         char *params = *pparams;
3212         uint16 info_level;
3213
3214         if (total_params < 6)
3215                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3216
3217         info_level = SVAL(params,4);
3218         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3219
3220         switch (info_level) {
3221                 case 1:
3222                 case 2:
3223                         break;
3224                 default:
3225                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3226         }
3227
3228         /* Realloc the parameter and data sizes */
3229         params = Realloc(*pparams,6);
3230         if(params == NULL) 
3231                 return ERROR_DOS(ERRDOS,ERRnomem);
3232         *pparams = params;
3233
3234         SSVAL(params,0,fnf_handle);
3235         SSVAL(params,2,0); /* No changes */
3236         SSVAL(params,4,0); /* No EA errors */
3237
3238         fnf_handle++;
3239
3240         if(fnf_handle == 0)
3241                 fnf_handle = 257;
3242
3243         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3244   
3245         return(-1);
3246 }
3247
3248 /****************************************************************************
3249  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
3250  changes). Currently this does nothing.
3251 ****************************************************************************/
3252
3253 static int call_trans2findnotifynext(connection_struct *conn,
3254                                         char *inbuf, char *outbuf, int length, int bufsize,
3255                                         char **pparams, int total_params, char **ppdata, int total_data)
3256 {
3257         char *params = *pparams;
3258
3259         DEBUG(3,("call_trans2findnotifynext\n"));
3260
3261         /* Realloc the parameter and data sizes */
3262         params = Realloc(*pparams,4);
3263         if(params == NULL)
3264                 return ERROR_DOS(ERRDOS,ERRnomem);
3265         *pparams = params;
3266
3267         SSVAL(params,0,0); /* No changes */
3268         SSVAL(params,2,0); /* No EA errors */
3269
3270         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3271   
3272         return(-1);
3273 }
3274
3275 /****************************************************************************
3276  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3277 ****************************************************************************/
3278
3279 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3280                                         char* outbuf, int length, int bufsize,
3281                                         char **pparams, int total_params, char **ppdata, int total_data)
3282 {
3283         char *params = *pparams;
3284         pstring pathname;
3285         int reply_size = 0;
3286         int max_referral_level;
3287
3288         DEBUG(10,("call_trans2getdfsreferral\n"));
3289
3290         if (total_params < 2)
3291                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3292
3293         max_referral_level = SVAL(params,0);
3294
3295         if(!lp_host_msdfs())
3296                 return ERROR_DOS(ERRDOS,ERRbadfunc);
3297
3298         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3299
3300         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3301                 return UNIXERROR(ERRDOS,ERRbadfile);
3302     
3303         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3304         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3305
3306         return(-1);
3307 }
3308
3309 #define LMCAT_SPL       0x53
3310 #define LMFUNC_GETJOBID 0x60
3311
3312 /****************************************************************************
3313  Reply to a TRANS2_IOCTL - used for OS/2 printing.
3314 ****************************************************************************/
3315
3316 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3317                                         char* outbuf, int length, int bufsize,
3318                                         char **pparams, int total_params, char **ppdata, int total_data)
3319 {
3320         char *pdata = *ppdata;
3321         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3322
3323         /* check for an invalid fid before proceeding */
3324         
3325         if (!fsp)                                
3326                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
3327
3328         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3329                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3330                 pdata = Realloc(*ppdata, 32);
3331                 if(pdata == NULL)
3332                         return ERROR_DOS(ERRDOS,ERRnomem);
3333                 *ppdata = pdata;
3334
3335                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3336                         CAN ACCEPT THIS IN UNICODE. JRA. */
3337
3338                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
3339                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3340                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3341                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3342                 return(-1);
3343         } else {
3344                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3345                 return ERROR_DOS(ERRSRV,ERRerror);
3346         }
3347 }
3348
3349 /****************************************************************************
3350  Reply to a SMBfindclose (stop trans2 directory search).
3351 ****************************************************************************/
3352
3353 int reply_findclose(connection_struct *conn,
3354                     char *inbuf,char *outbuf,int length,int bufsize)
3355 {
3356         int outsize = 0;
3357         int dptr_num=SVALS(inbuf,smb_vwv0);
3358         START_PROFILE(SMBfindclose);
3359
3360         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3361
3362         dptr_close(&dptr_num);
3363
3364         outsize = set_message(outbuf,0,0,True);
3365
3366         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3367
3368         END_PROFILE(SMBfindclose);
3369         return(outsize);
3370 }
3371
3372 /****************************************************************************
3373  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3374 ****************************************************************************/
3375
3376 int reply_findnclose(connection_struct *conn, 
3377                      char *inbuf,char *outbuf,int length,int bufsize)
3378 {
3379         int outsize = 0;
3380         int dptr_num= -1;
3381         START_PROFILE(SMBfindnclose);
3382         
3383         dptr_num = SVAL(inbuf,smb_vwv0);
3384
3385         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3386
3387         /* We never give out valid handles for a 
3388            findnotifyfirst - so any dptr_num is ok here. 
3389            Just ignore it. */
3390
3391         outsize = set_message(outbuf,0,0,True);
3392
3393         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3394
3395         END_PROFILE(SMBfindnclose);
3396         return(outsize);
3397 }
3398
3399 /****************************************************************************
3400  Reply to a SMBtranss2 - just ignore it!
3401 ****************************************************************************/
3402
3403 int reply_transs2(connection_struct *conn,
3404                   char *inbuf,char *outbuf,int length,int bufsize)
3405 {
3406         START_PROFILE(SMBtranss2);
3407         DEBUG(4,("Ignoring transs2 of length %d\n",length));
3408         END_PROFILE(SMBtranss2);
3409         return(-1);
3410 }
3411
3412 /****************************************************************************
3413  Reply to a SMBtrans2.
3414 ****************************************************************************/
3415
3416 int reply_trans2(connection_struct *conn,
3417                  char *inbuf,char *outbuf,int length,int bufsize)
3418 {
3419         int outsize = 0;
3420         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3421         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3422 #if 0
3423         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3424         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3425         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3426         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3427         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3428         int32 timeout = IVALS(inbuf,smb_timeout);
3429 #endif
3430         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3431         unsigned int tran_call = SVAL(inbuf, smb_setup0);
3432         char *params = NULL, *data = NULL;
3433         unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3434         START_PROFILE(SMBtrans2);
3435
3436         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3437                 /* Queue this open message as we are the process of an
3438                  * oplock break.  */
3439
3440                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3441                 DEBUGADD(2,( "in oplock break state.\n"));
3442
3443                 push_oplock_pending_smb_message(inbuf, length);
3444                 END_PROFILE(SMBtrans2);
3445                 return -1;
3446         }
3447         
3448         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3449             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3450                 END_PROFILE(SMBtrans2);
3451                 return ERROR_DOS(ERRSRV,ERRaccess);
3452         }
3453
3454         outsize = set_message(outbuf,0,0,True);
3455
3456         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3457            is so as a sanity check */
3458         if (suwcnt != 1) {
3459                 /*
3460                  * Need to have rc=0 for ioctl to get job id for OS/2.
3461                  *  Network printing will fail if function is not successful.
3462                  *  Similar function in reply.c will be used if protocol
3463                  *  is LANMAN1.0 instead of LM1.2X002.
3464                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
3465                  *  outbuf doesn't have to be set(only job id is used).
3466                  */
3467                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3468                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3469                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3470                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3471                 } else {
3472                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3473                         DEBUG(2,("Transaction is %d\n",tran_call));
3474                         END_PROFILE(SMBtrans2);
3475                         ERROR_DOS(ERRDOS,ERRinvalidparam);
3476                 }
3477         }
3478     
3479         /* Allocate the space for the maximum needed parameters and data */
3480         if (total_params > 0)
3481                 params = (char *)malloc(total_params);
3482         if (total_data > 0)
3483                 data = (char *)malloc(total_data);
3484   
3485         if ((total_params && !params)  || (total_data && !data)) {
3486                 DEBUG(2,("Out of memory in reply_trans2\n"));
3487                 SAFE_FREE(params);
3488                 SAFE_FREE(data); 
3489                 END_PROFILE(SMBtrans2);
3490                 return ERROR_DOS(ERRDOS,ERRnomem);
3491         }
3492
3493         /* Copy the param and data bytes sent with this request into
3494            the params buffer */
3495         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3496         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3497
3498         if (num_params > total_params || num_data > total_data)
3499                 exit_server("invalid params in reply_trans2");
3500
3501         if(params) {
3502                 unsigned int psoff = SVAL(inbuf, smb_psoff);
3503                 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3504                         goto bad_param;
3505                 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
3506                                 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
3507                         goto bad_param;
3508                 memcpy( params, smb_base(inbuf) + psoff, num_params);
3509         }
3510         if(data) {
3511                 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3512                 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3513                         goto bad_param;
3514                 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
3515                                 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
3516                         goto bad_param;
3517                 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3518         }
3519
3520         srv_signing_trans_start(SVAL(inbuf,smb_mid));
3521
3522         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
3523                 /* We need to send an interim response then receive the rest
3524                    of the parameter/data bytes */
3525                 outsize = set_message(outbuf,0,0,True);
3526                 if (!send_smb(smbd_server_fd(),outbuf))
3527                         exit_server("reply_trans2: send_smb failed.");
3528
3529                 while (num_data_sofar < total_data || 
3530                        num_params_sofar < total_params) {
3531                         BOOL ret;
3532                         unsigned int param_disp;
3533                         unsigned int param_off;
3534                         unsigned int data_disp;
3535                         unsigned int data_off;
3536
3537                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3538                         
3539                         if ((ret && 
3540                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3541                                 outsize = set_message(outbuf,0,0,True);
3542                                 if(ret)
3543                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3544                                 else
3545                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3546                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3547                                 goto bad_param;
3548                         }
3549       
3550                         /* Revise total_params and total_data in case
3551                            they have changed downwards */
3552                         if (SVAL(inbuf, smb_tpscnt) < total_params)
3553                                 total_params = SVAL(inbuf, smb_tpscnt);
3554                         if (SVAL(inbuf, smb_tdscnt) < total_data)
3555                                 total_data = SVAL(inbuf, smb_tdscnt);
3556
3557                         num_params = SVAL(inbuf,smb_spscnt);
3558                         param_off = SVAL(inbuf, smb_spsoff);
3559                         param_disp = SVAL(inbuf, smb_spsdisp);
3560                         num_params_sofar += num_params;
3561
3562                         num_data = SVAL(inbuf, smb_sdscnt);
3563                         data_off = SVAL(inbuf, smb_sdsoff);
3564                         data_disp = SVAL(inbuf, smb_sdsdisp);
3565                         num_data_sofar += num_data;
3566
3567                         if (num_params_sofar > total_params || num_data_sofar > total_data)
3568                                 goto bad_param;
3569                         
3570                         if (num_params) {
3571                                 if (param_disp + num_params >= total_params)
3572                                         goto bad_param;
3573                                 if ((param_disp + num_params < param_disp) ||
3574                                                 (param_disp + num_params < num_params))
3575                                         goto bad_param;
3576                                 if (param_disp > total_params)
3577                                         goto bad_param;
3578                                 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
3579                                                 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
3580                                         goto bad_param;
3581                                 if (params + param_disp < params)
3582                                         goto bad_param;
3583
3584                                 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
3585                         }
3586                         if (num_data) {
3587                                 if (data_disp + num_data >= total_data)
3588                                         goto bad_param;
3589                                 if ((data_disp + num_data < data_disp) ||
3590                                                 (data_disp + num_data < num_data))
3591                                         goto bad_param;
3592                                 if (data_disp > total_data)
3593                                         goto bad_param;
3594                                 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
3595                                                 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
3596                                         goto bad_param;
3597                                 if (data + data_disp < data)
3598                                         goto bad_param;
3599
3600                                 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3601                         }
3602                 }
3603         }
3604         
3605         if (Protocol >= PROTOCOL_NT1) {
3606                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3607         }
3608
3609         /* Now we must call the relevant TRANS2 function */
3610         switch(tran_call)  {
3611         case TRANSACT2_OPEN:
3612                 START_PROFILE_NESTED(Trans2_open);
3613                 outsize = call_trans2open(conn, inbuf, outbuf, bufsize, 
3614                                           &params, total_params, &data, total_data);
3615                 END_PROFILE_NESTED(Trans2_open);
3616                 break;
3617
3618         case TRANSACT2_FINDFIRST:
3619                 START_PROFILE_NESTED(Trans2_findfirst);
3620                 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3621                                           &params, total_params, &data, total_data);
3622                 END_PROFILE_NESTED(Trans2_findfirst);
3623                 break;
3624
3625         case TRANSACT2_FINDNEXT:
3626                 START_PROFILE_NESTED(Trans2_findnext);
3627                 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, 
3628                                           &params, total_params, &data, total_data);
3629                 END_PROFILE_NESTED(Trans2_findnext);
3630                 break;
3631
3632         case TRANSACT2_QFSINFO:
3633                 START_PROFILE_NESTED(Trans2_qfsinfo);
3634                 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3635                                           &params, total_params, &data, total_data);
3636                 END_PROFILE_NESTED(Trans2_qfsinfo);
3637             break;
3638
3639 #ifdef HAVE_SYS_QUOTAS
3640         case TRANSACT2_SETFSINFO:
3641                 START_PROFILE_NESTED(Trans2_setfsinfo);
3642                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, 
3643                                           &params, total_params, &data, total_data);
3644                 END_PROFILE_NESTED(Trans2_setfsinfo);
3645                 break;
3646 #endif
3647         case TRANSACT2_QPATHINFO:
3648         case TRANSACT2_QFILEINFO:
3649                 START_PROFILE_NESTED(Trans2_qpathinfo);
3650                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
3651                                           &params, total_params, &data, total_data);
3652                 END_PROFILE_NESTED(Trans2_qpathinfo);
3653                 break;
3654         case TRANSACT2_SETPATHINFO:
3655         case TRANSACT2_SETFILEINFO:
3656                 START_PROFILE_NESTED(Trans2_setpathinfo);
3657                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
3658                                           &params, total_params, &data, total_data);
3659                 END_PROFILE_NESTED(Trans2_setpathinfo);
3660                 break;
3661
3662         case TRANSACT2_FINDNOTIFYFIRST:
3663                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3664                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, 
3665                                           &params, total_params, &data, total_data);
3666                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3667                 break;
3668
3669         case TRANSACT2_FINDNOTIFYNEXT:
3670                 START_PROFILE_NESTED(Trans2_findnotifynext);
3671                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, 
3672                                           &params, total_params, &data, total_data);
3673                 END_PROFILE_NESTED(Trans2_findnotifynext);
3674                 break;
3675         case TRANSACT2_MKDIR:
3676                 START_PROFILE_NESTED(Trans2_mkdir);
3677                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3678                                           &params, total_params, &data, total_data);
3679                 END_PROFILE_NESTED(Trans2_mkdir);
3680                 break;
3681
3682         case TRANSACT2_GET_DFS_REFERRAL:
3683                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3684                 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3685                                           &params, total_params, &data, total_data);
3686                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3687                 break;
3688         case TRANSACT2_IOCTL:
3689                 START_PROFILE_NESTED(Trans2_ioctl);
3690                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3691                                           &params, total_params, &data, total_data);
3692                 END_PROFILE_NESTED(Trans2_ioctl);
3693                 break;
3694         default:
3695                 /* Error in request */
3696                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3697                 SAFE_FREE(params);
3698                 SAFE_FREE(data);
3699                 END_PROFILE(SMBtrans2);
3700                 srv_signing_trans_stop();
3701                 return ERROR_DOS(ERRSRV,ERRerror);
3702         }
3703         
3704         /* As we do not know how many data packets will need to be
3705            returned here the various call_trans2xxxx calls
3706            must send their own. Thus a call_trans2xxx routine only
3707            returns a value other than -1 when it wants to send
3708            an error packet. 
3709         */
3710         
3711         srv_signing_trans_stop();
3712
3713         SAFE_FREE(params);
3714         SAFE_FREE(data);
3715         END_PROFILE(SMBtrans2);
3716         return outsize; /* If a correct response was needed the
3717                            call_trans2xxx calls have already sent
3718                            it. If outsize != -1 then it is returning */
3719
3720   bad_param:
3721
3722         srv_signing_trans_stop();
3723         SAFE_FREE(params);
3724         SAFE_FREE(data);
3725         END_PROFILE(SMBtrans2);
3726         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3727 }