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