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