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