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