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