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