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