Ignore silently set disposition information when set on a path.
[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         if (!mode)
1875                 mode = FILE_ATTRIBUTE_NORMAL;
1876
1877         fullpathname = fname;
1878         file_size = get_file_size(sbuf);
1879         allocation_size = get_allocation_size(fsp,&sbuf);
1880         if (mode & aDIR)
1881                 file_size = 0;
1882
1883         params = Realloc(*pparams,2);
1884         if (params == NULL)
1885           return ERROR_DOS(ERRDOS,ERRnomem);
1886         *pparams = params;
1887         memset((char *)params,'\0',2);
1888         data_size = max_data_bytes + 1024;
1889         pdata = Realloc(*ppdata, data_size); 
1890         if ( pdata == NULL )
1891                 return ERROR_DOS(ERRDOS,ERRnomem);
1892         *ppdata = pdata;
1893
1894         if (total_data > 0 && IVAL(pdata,0) == total_data) {
1895                 /* uggh, EAs for OS2 */
1896                 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1897                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1898         }
1899
1900         memset((char *)pdata,'\0',data_size);
1901
1902         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1903
1904         if (lp_dos_filetime_resolution(SNUM(conn))) {
1905                 c_time &= ~1;
1906                 sbuf.st_atime &= ~1;
1907                 sbuf.st_mtime &= ~1;
1908                 sbuf.st_mtime &= ~1;
1909         }
1910
1911         /* NT expects the name to be in an exact form of the *full*
1912            filename. See the trans2 torture test */
1913         if (strequal(base_name,".")) {
1914                 pstrcpy(dos_fname, "\\");
1915         } else {
1916                 pstr_sprintf(dos_fname, "\\%s", fname);
1917                 string_replace(dos_fname, '/', '\\');
1918         }
1919
1920         switch (info_level) {
1921                 case SMB_INFO_STANDARD:
1922                 case SMB_INFO_QUERY_EA_SIZE:
1923                         data_size = (info_level==1?22:26);
1924                         put_dos_date2(pdata,l1_fdateCreation,c_time);
1925                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1926                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1927                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
1928                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1929                         SSVAL(pdata,l1_attrFile,mode);
1930                         SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */
1931                         break;
1932
1933                 case SMB_INFO_IS_NAME_VALID:
1934                         if (tran_call == TRANSACT2_QFILEINFO) {
1935                                 /* os/2 needs this ? really ?*/      
1936                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
1937                         }
1938                         data_size = 0;
1939                         break;
1940                         
1941                 case SMB_INFO_QUERY_EAS_FROM_LIST:
1942                         data_size = 24;
1943                         put_dos_date2(pdata,0,c_time);
1944                         put_dos_date2(pdata,4,sbuf.st_atime);
1945                         put_dos_date2(pdata,8,sbuf.st_mtime);
1946                         SIVAL(pdata,12,(uint32)file_size);
1947                         SIVAL(pdata,16,(uint32)allocation_size);
1948                         SIVAL(pdata,20,mode);
1949                         break;
1950
1951                 case SMB_INFO_QUERY_ALL_EAS:
1952                         data_size = 4;
1953                         SIVAL(pdata,0,0); /* ea size */
1954                         break;
1955
1956                 case SMB_FILE_BASIC_INFORMATION:
1957                 case SMB_QUERY_FILE_BASIC_INFO:
1958
1959                         if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1960                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1961                         else {
1962                                 data_size = 40;
1963                                 SIVAL(pdata,36,0);
1964                         }
1965                         put_long_date(pdata,c_time);
1966                         put_long_date(pdata+8,sbuf.st_atime);
1967                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1968                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1969                         SIVAL(pdata,32,mode);
1970
1971                         DEBUG(5,("SMB_QFBI - "));
1972                         {
1973                                 time_t create_time = c_time;
1974                                 DEBUG(5,("create: %s ", ctime(&create_time)));
1975                         }
1976                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1977                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1978                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1979                         DEBUG(5,("mode: %x\n", mode));
1980
1981                         break;
1982
1983                 case SMB_FILE_STANDARD_INFORMATION:
1984                 case SMB_QUERY_FILE_STANDARD_INFO:
1985
1986                         data_size = 24;
1987                         SOFF_T(pdata,0,allocation_size);
1988                         SOFF_T(pdata,8,file_size);
1989                         if (delete_pending & sbuf.st_nlink)
1990                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
1991                         else
1992                                 SIVAL(pdata,16,sbuf.st_nlink);
1993                         SCVAL(pdata,20,0);
1994                         SCVAL(pdata,21,(mode&aDIR)?1:0);
1995                         break;
1996
1997                 case SMB_FILE_EA_INFORMATION:
1998                 case SMB_QUERY_FILE_EA_INFO:
1999                         data_size = 4;
2000                         break;
2001
2002                 /* Get the 8.3 name - used if NT SMB was negotiated. */
2003                 case SMB_QUERY_FILE_ALT_NAME_INFO:
2004                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2005                 {
2006                         pstring short_name;
2007
2008                         pstrcpy(short_name,base_name);
2009                         /* Mangle if not already 8.3 */
2010                         if(!mangle_is_8_3(short_name, True)) {
2011                                 mangle_map(short_name,True,True,SNUM(conn));
2012                         }
2013                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2014                         data_size = 4 + len;
2015                         SIVAL(pdata,0,len);
2016                         break;
2017                 }
2018
2019                 case SMB_QUERY_FILE_NAME_INFO:
2020                         /*
2021                           this must be *exactly* right for ACLs on mapped drives to work
2022                          */
2023                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2024                         data_size = 4 + len;
2025                         SIVAL(pdata,0,len);
2026                         break;
2027
2028                 case SMB_FILE_ALLOCATION_INFORMATION:
2029                 case SMB_QUERY_FILE_ALLOCATION_INFO:
2030                         data_size = 8;
2031                         SOFF_T(pdata,0,allocation_size);
2032                         break;
2033
2034                 case SMB_FILE_END_OF_FILE_INFORMATION:
2035                 case SMB_QUERY_FILE_END_OF_FILEINFO:
2036                         data_size = 8;
2037                         SOFF_T(pdata,0,file_size);
2038                         break;
2039
2040                 case SMB_QUERY_FILE_ALL_INFO:
2041                 case SMB_FILE_ALL_INFORMATION:
2042                         put_long_date(pdata,c_time);
2043                         put_long_date(pdata+8,sbuf.st_atime);
2044                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2045                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2046                         SIVAL(pdata,32,mode);
2047                         pdata += 40;
2048                         SOFF_T(pdata,0,allocation_size);
2049                         SOFF_T(pdata,8,file_size);
2050                         if (delete_pending && sbuf.st_nlink)
2051                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2052                         else
2053                                 SIVAL(pdata,16,sbuf.st_nlink);
2054                         SCVAL(pdata,20,delete_pending);
2055                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2056                         pdata += 24;
2057                         pdata += 4; /* EA info */
2058                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2059                         SIVAL(pdata,0,len);
2060                         pdata += 4 + len;
2061                         data_size = PTR_DIFF(pdata,(*ppdata));
2062                         break;
2063
2064                 case SMB_FILE_INTERNAL_INFORMATION:
2065                         /* This should be an index number - looks like
2066                            dev/ino to me :-) 
2067
2068                            I think this causes us to fail the IFSKIT
2069                            BasicFileInformationTest. -tpot */
2070
2071                         SIVAL(pdata,0,sbuf.st_dev);
2072                         SIVAL(pdata,4,sbuf.st_ino);
2073                         data_size = 8;
2074                         break;
2075
2076                 case SMB_FILE_ACCESS_INFORMATION:
2077                         SIVAL(pdata,0,0x12019F); /* ??? */
2078                         data_size = 4;
2079                         break;
2080
2081                 case SMB_FILE_NAME_INFORMATION:
2082                         /* Pathname with leading '\'. */
2083                         {
2084                                 size_t byte_len;
2085                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2086                                 SIVAL(pdata,0,byte_len);
2087                                 data_size = 4 + byte_len;
2088                                 break;
2089                         }
2090
2091                 case SMB_FILE_DISPOSITION_INFORMATION:
2092                         data_size = 1;
2093                         SCVAL(pdata,0,delete_pending);
2094                         break;
2095
2096                 case SMB_FILE_POSITION_INFORMATION:
2097                         data_size = 8;
2098                         SOFF_T(pdata,0,pos);
2099                         break;
2100
2101                 case SMB_FILE_MODE_INFORMATION:
2102                         SIVAL(pdata,0,mode);
2103                         data_size = 4;
2104                         break;
2105
2106                 case SMB_FILE_ALIGNMENT_INFORMATION:
2107                         SIVAL(pdata,0,0); /* No alignment needed. */
2108                         data_size = 4;
2109                         break;
2110
2111 #if 0
2112                 /*
2113                  * NT4 server just returns "invalid query" to this - if we try to answer
2114                  * it then NTws gets a BSOD! (tridge).
2115                  * W2K seems to want this. JRA.
2116                  */
2117                 case SMB_QUERY_FILE_STREAM_INFO:
2118 #endif
2119                 case SMB_FILE_STREAM_INFORMATION:
2120                         if (mode & aDIR) {
2121                                 data_size = 0;
2122                         } else {
2123                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2124                                 SIVAL(pdata,0,0); /* ??? */
2125                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2126                                 SOFF_T(pdata,8,file_size);
2127                                 SIVAL(pdata,16,allocation_size);
2128                                 SIVAL(pdata,20,0); /* ??? */
2129                                 data_size = 24 + byte_len;
2130                         }
2131                         break;
2132
2133                 case SMB_QUERY_COMPRESSION_INFO:
2134                 case SMB_FILE_COMPRESSION_INFORMATION:
2135                         SOFF_T(pdata,0,file_size);
2136                         SIVAL(pdata,8,0); /* ??? */
2137                         SIVAL(pdata,12,0); /* ??? */
2138                         data_size = 16;
2139                         break;
2140
2141                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2142                         put_long_date(pdata,c_time);
2143                         put_long_date(pdata+8,sbuf.st_atime);
2144                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2145                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2146                         SIVAL(pdata,32,allocation_size);
2147                         SOFF_T(pdata,40,file_size);
2148                         SIVAL(pdata,48,mode);
2149                         SIVAL(pdata,52,0); /* ??? */
2150                         data_size = 56;
2151                         break;
2152
2153                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2154                         SIVAL(pdata,0,mode);
2155                         SIVAL(pdata,4,0);
2156                         data_size = 8;
2157                         break;
2158
2159                 /*
2160                  * CIFS UNIX Extensions.
2161                  */
2162
2163                 case SMB_QUERY_FILE_UNIX_BASIC:
2164
2165                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2166
2167                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
2168                         pdata += 8;
2169
2170                         SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2171                         pdata += 8;
2172
2173                         put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
2174                         put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
2175                         put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
2176                         pdata += 24;
2177
2178                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
2179                         SIVAL(pdata,4,0);
2180                         pdata += 8;
2181
2182                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
2183                         SIVAL(pdata,4,0);
2184                         pdata += 8;
2185
2186                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2187                         pdata += 4;
2188
2189                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
2190                         SIVAL(pdata,4,0);
2191                         pdata += 8;
2192
2193                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
2194                         SIVAL(pdata,4,0);
2195                         pdata += 8;
2196
2197                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
2198                         pdata += 8;
2199                                 
2200                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
2201                         SIVAL(pdata,4,0);
2202                         pdata += 8;
2203
2204                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
2205                         SIVAL(pdata,4,0);
2206                         pdata += 8+1;
2207                         data_size = PTR_DIFF(pdata,(*ppdata));
2208
2209                         {
2210                                 int i;
2211                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2212
2213                                 for (i=0; i<100; i++)
2214                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2215                                 DEBUG(4,("\n"));
2216                         }
2217
2218                         break;
2219
2220                 case SMB_QUERY_FILE_UNIX_LINK:
2221                         {
2222                                 pstring buffer;
2223
2224 #ifdef S_ISLNK
2225                                 if(!S_ISLNK(sbuf.st_mode))
2226                                         return(UNIXERROR(ERRSRV,ERRbadlink));
2227 #else
2228                                 return(UNIXERROR(ERRDOS,ERRbadlink));
2229 #endif
2230                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
2231                                 if (len == -1)
2232                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2233                                 buffer[len] = 0;
2234                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2235                                 pdata += len;
2236                                 data_size = PTR_DIFF(pdata,(*ppdata));
2237
2238                                 break;
2239                         }
2240
2241                 default:
2242                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2243         }
2244
2245         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2246
2247         return(-1);
2248 }
2249
2250 /****************************************************************************
2251  Deal with the internal needs of setting the delete on close flag. Note that
2252  as the tdb locking is recursive, it is safe to call this from within 
2253  open_file_shared. JRA.
2254 ****************************************************************************/
2255
2256 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2257 {
2258         /*
2259          * Only allow delete on close for writable shares.
2260          */
2261
2262         if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2263                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2264                                 fsp->fsp_name ));
2265                                 return NT_STATUS_ACCESS_DENIED;
2266         }
2267         /*
2268          * Only allow delete on close for files/directories opened with delete intent.
2269          */
2270
2271         if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2272                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2273                                 fsp->fsp_name ));
2274                                 return NT_STATUS_ACCESS_DENIED;
2275         }
2276
2277         if(fsp->is_directory) {
2278                 fsp->directory_delete_on_close = delete_on_close;
2279                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2280                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2281         } else {
2282                 fsp->delete_on_close = delete_on_close;
2283                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2284                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2285         }
2286
2287         return NT_STATUS_OK;
2288 }
2289
2290 /****************************************************************************
2291  Sets the delete on close flag over all share modes on this file.
2292  Modify the share mode entry for all files open
2293  on this device and inode to tell other smbds we have
2294  changed the delete on close flag. This will be noticed
2295  in the close code, the last closer will delete the file
2296  if flag is set.
2297 ****************************************************************************/
2298
2299 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2300 {
2301         DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2302                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2303
2304         if (fsp->is_directory || fsp->is_stat)
2305                 return NT_STATUS_OK;
2306
2307         if (lock_share_entry_fsp(fsp) == False)
2308                 return NT_STATUS_ACCESS_DENIED;
2309
2310         if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2311                 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2312                         fsp->fsp_name ));
2313                 unlock_share_entry_fsp(fsp);
2314                 return NT_STATUS_ACCESS_DENIED;
2315         }
2316
2317         unlock_share_entry_fsp(fsp);
2318         return NT_STATUS_OK;
2319 }
2320
2321 /****************************************************************************
2322  Returns true if this pathname is within the share, and thus safe.
2323 ****************************************************************************/
2324
2325 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2326 {
2327 #ifdef PATH_MAX
2328         char resolved_name[PATH_MAX+1];
2329 #else
2330         pstring resolved_name;
2331 #endif
2332         fstring last_component;
2333         pstring link_dest;
2334         pstring link_test;
2335         char *p;
2336         BOOL bad_path = False;
2337         SMB_STRUCT_STAT sbuf;
2338
2339         pstrcpy(link_dest, link_dest_in);
2340         unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2341
2342         /* Store the UNIX converted path. */
2343         pstrcpy(link_dest_out, link_dest);
2344
2345         p = strrchr(link_dest, '/');
2346         if (p) {
2347                 fstrcpy(last_component, p+1);
2348                 *p = '\0';
2349         } else {
2350                 fstrcpy(last_component, link_dest);
2351                 pstrcpy(link_dest, "./");
2352         }
2353                 
2354         if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2355                 return -1;
2356
2357         pstrcpy(link_dest, resolved_name);
2358         pstrcat(link_dest, "/");
2359         pstrcat(link_dest, last_component);
2360
2361         if (*link_dest != '/') {
2362                 /* Relative path. */
2363                 pstrcpy(link_test, conn->connectpath);
2364                 pstrcat(link_test, "/");
2365                 pstrcat(link_test, link_dest);
2366         } else {
2367                 pstrcpy(link_test, link_dest);
2368         }
2369
2370         /*
2371          * Check if the link is within the share.
2372          */
2373
2374         if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2375                 errno = EACCES;
2376                 return -1;
2377         }
2378         return 0;
2379 }
2380
2381 /****************************************************************************
2382  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2383 ****************************************************************************/
2384
2385 static int call_trans2setfilepathinfo(connection_struct *conn,
2386                                         char *inbuf, char *outbuf, int length, int bufsize,
2387                                         char **pparams, int total_params, char **ppdata, int total_data)
2388 {
2389         char *params = *pparams;
2390         char *pdata = *ppdata;
2391         uint16 tran_call = SVAL(inbuf, smb_setup0);
2392         uint16 info_level;
2393         int dosmode=0;
2394         SMB_OFF_T size=0;
2395         struct utimbuf tvs;
2396         SMB_STRUCT_STAT sbuf;
2397         pstring fname;
2398         int fd = -1;
2399         BOOL bad_path = False;
2400         files_struct *fsp = NULL;
2401         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2402         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2403         mode_t unixmode = 0;
2404
2405         if (!params)
2406                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2407
2408         if (tran_call == TRANSACT2_SETFILEINFO) {
2409                 if (total_params < 4)
2410                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2411
2412                 fsp = file_fsp(params,0);
2413                 info_level = SVAL(params,2);    
2414
2415                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2416                         /*
2417                          * This is actually a SETFILEINFO on a directory
2418                          * handle (returned from an NT SMB). NT5.0 seems
2419                          * to do this call. JRA.
2420                          */
2421                         pstrcpy(fname, fsp->fsp_name);
2422                         unix_convert(fname,conn,0,&bad_path,&sbuf);
2423                         if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2424                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2425                                 set_bad_path_error(errno, bad_path);
2426                                 return(UNIXERROR(ERRDOS,ERRbadpath));
2427                         }
2428                 } else if (fsp && fsp->print_file) {
2429                         /*
2430                          * Doing a DELETE_ON_CLOSE should cancel a print job.
2431                          */
2432                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2433                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2434
2435                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2436         
2437                                 SSVAL(params,0,0);
2438                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2439                                 return(-1);
2440                         } else
2441                                 return (UNIXERROR(ERRDOS,ERRbadpath));
2442             } else {
2443                         /*
2444                          * Original code - this is an open file.
2445                          */
2446                         CHECK_FSP(fsp,conn);
2447
2448                         pstrcpy(fname, fsp->fsp_name);
2449                         fd = fsp->fd;
2450
2451                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
2452                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2453                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2454                         }
2455                 }
2456         } else {
2457                 /* set path info */
2458                 if (total_params < 6)
2459                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2460
2461                 info_level = SVAL(params,0);    
2462                 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2463                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2464                 if(!check_name(fname, conn)) {
2465                         set_bad_path_error(errno, bad_path);
2466                         return(UNIXERROR(ERRDOS,ERRbadpath));
2467                 }
2468
2469                 /*
2470                  * For CIFS UNIX extensions the target name may not exist.
2471                  */
2472
2473                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2474                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2475                         set_bad_path_error(errno, bad_path);
2476                         return(UNIXERROR(ERRDOS,ERRbadpath));
2477                 }    
2478         }
2479
2480         if (!CAN_WRITE(conn))
2481                 return ERROR_DOS(ERRSRV,ERRaccess);
2482
2483         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2484                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2485
2486         if (VALID_STAT(sbuf))
2487                 unixmode = sbuf.st_mode;
2488
2489         DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2490                 tran_call,fname,info_level,total_data));
2491
2492         /* Realloc the parameter and data sizes */
2493         params = Realloc(*pparams,2);
2494         if(params == NULL)
2495                 return ERROR_DOS(ERRDOS,ERRnomem);
2496         *pparams = params;
2497
2498         SSVAL(params,0,0);
2499
2500         if (fsp) {
2501                 /* the pending modtime overrides the current modtime */
2502                 sbuf.st_mtime = fsp->pending_modtime;
2503         }
2504
2505         size = get_file_size(sbuf);
2506         tvs.modtime = sbuf.st_mtime;
2507         tvs.actime = sbuf.st_atime;
2508         dosmode = dos_mode(conn,fname,&sbuf);
2509         unixmode = sbuf.st_mode;
2510
2511         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2512         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2513
2514         switch (info_level) {
2515                 case SMB_INFO_STANDARD:
2516                 {
2517                         if (total_data < 12)
2518                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2519
2520                         /* access time */
2521                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2522                         /* write time */
2523                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2524                         break;
2525                 }
2526
2527                 case SMB_INFO_SET_EA:
2528                         return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2529
2530                 /* XXXX um, i don't think this is right.
2531                         it's also not in the cifs6.txt spec.
2532                 */
2533                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2534                         if (total_data < 28)
2535                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2536
2537                         tvs.actime = make_unix_date2(pdata+8);
2538                         tvs.modtime = make_unix_date2(pdata+12);
2539                         size = IVAL(pdata,16);
2540                         dosmode = IVAL(pdata,24);
2541                         break;
2542
2543                 /* XXXX nor this.  not in cifs6.txt, either. */
2544                 case SMB_INFO_QUERY_ALL_EAS:
2545                         if (total_data < 28)
2546                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2547
2548                         tvs.actime = make_unix_date2(pdata+8);
2549                         tvs.modtime = make_unix_date2(pdata+12);
2550                         size = IVAL(pdata,16);
2551                         dosmode = IVAL(pdata,24);
2552                         break;
2553
2554                 case SMB_SET_FILE_BASIC_INFO:
2555                 case SMB_FILE_BASIC_INFORMATION:
2556                 {
2557                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2558                         time_t write_time;
2559                         time_t changed_time;
2560
2561                         if (total_data < 36)
2562                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2563
2564                         /* Ignore create time at offset pdata. */
2565
2566                         /* access time */
2567                         tvs.actime = interpret_long_date(pdata+8);
2568
2569                         write_time = interpret_long_date(pdata+16);
2570                         changed_time = interpret_long_date(pdata+24);
2571
2572                         tvs.modtime = MIN(write_time, changed_time);
2573
2574                         if (write_time > tvs.modtime && write_time != 0xffffffff) {
2575                                 tvs.modtime = write_time;
2576                         }
2577                         /* Prefer a defined time to an undefined one. */
2578                         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2579                                 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2580                                         ? changed_time : write_time);
2581
2582                         /* attributes */
2583                         dosmode = IVAL(pdata,32);
2584                         break;
2585                 }
2586
2587                 case SMB_FILE_ALLOCATION_INFORMATION:
2588                 case SMB_SET_FILE_ALLOCATION_INFO:
2589                 {
2590                         int ret = -1;
2591                         SMB_BIG_UINT allocation_size;
2592
2593                         if (total_data < 8)
2594                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2595
2596                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2597 #ifdef LARGE_SMB_OFF_T
2598                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2599 #else /* LARGE_SMB_OFF_T */
2600                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2601                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2602 #endif /* LARGE_SMB_OFF_T */
2603                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2604                                         fname, (double)allocation_size ));
2605
2606                         if (allocation_size)
2607                                 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2608
2609                         if(allocation_size != get_file_size(sbuf)) {
2610                                 SMB_STRUCT_STAT new_sbuf;
2611  
2612                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2613                                         fname, (double)allocation_size ));
2614  
2615                                 if (fd == -1) {
2616                                         files_struct *new_fsp = NULL;
2617                                         int access_mode = 0;
2618                                         int action = 0;
2619  
2620                                         if(global_oplock_break) {
2621                                                 /* Queue this file modify as we are the process of an oplock break.  */
2622  
2623                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2624                                                 DEBUGADD(2,( "in oplock break state.\n"));
2625  
2626                                                 push_oplock_pending_smb_message(inbuf, length);
2627                                                 return -1;
2628                                         }
2629  
2630                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2631                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
2632                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2633                                                                         0, 0, &access_mode, &action);
2634  
2635                                         if (new_fsp == NULL)
2636                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
2637                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
2638                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2639                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2640                                                                         new_fsp->fnum, strerror(errno)));
2641                                                 ret = -1;
2642                                         }
2643                                         close_file(new_fsp,True);
2644                                 } else {
2645                                         ret = vfs_allocate_file_space(fsp, allocation_size);
2646                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
2647                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2648                                                                         fsp->fnum, strerror(errno)));
2649                                                 ret = -1;
2650                                         }
2651                                 }
2652                                 if (ret == -1)
2653                                         return ERROR_NT(NT_STATUS_DISK_FULL);
2654
2655                                 /* Allocate can truncate size... */
2656                                 size = get_file_size(new_sbuf);
2657                         }
2658
2659                         break;
2660                 }
2661
2662                 case SMB_FILE_END_OF_FILE_INFORMATION:
2663                 case SMB_SET_FILE_END_OF_FILE_INFO:
2664                 {
2665                         if (total_data < 8)
2666                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2667
2668                         size = IVAL(pdata,0);
2669 #ifdef LARGE_SMB_OFF_T
2670                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2671 #else /* LARGE_SMB_OFF_T */
2672                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2673                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2674 #endif /* LARGE_SMB_OFF_T */
2675                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2676                         break;
2677                 }
2678
2679                 case SMB_FILE_DISPOSITION_INFORMATION:
2680                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2681                 {
2682                         BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2683                         NTSTATUS status;
2684
2685                         if (total_data < 1)
2686                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2687
2688                         /* Just ignore this set on a path. */
2689                         if (tran_call != TRANSACT2_SETFILEINFO)
2690                                 break;
2691
2692                         if (fsp == NULL)
2693                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2694
2695                         status = set_delete_on_close_internal(fsp, delete_on_close);
2696  
2697                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
2698                                 return ERROR_NT(status);
2699
2700                         /* The set is across all open files on this dev/inode pair. */
2701                         status =set_delete_on_close_over_all(fsp, delete_on_close);
2702                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
2703                                 return ERROR_NT(status);
2704
2705                         break;
2706                 }
2707
2708                 case SMB_FILE_POSITION_INFORMATION:
2709                 {
2710                         SMB_BIG_UINT position_information;
2711
2712                         if (total_data < 8)
2713                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2714
2715                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
2716 #ifdef LARGE_SMB_OFF_T
2717                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2718 #else /* LARGE_SMB_OFF_T */
2719                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2720                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2721 #endif /* LARGE_SMB_OFF_T */
2722                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
2723                                         fname, (double)position_information ));
2724                         if (fsp)
2725                                 fsp->position_information = position_information;
2726                         break;
2727                 }
2728
2729                 /*
2730                  * CIFS UNIX extensions.
2731                  */
2732
2733                 case SMB_SET_FILE_UNIX_BASIC:
2734                 {
2735                         uint32 raw_unixmode;
2736
2737                         if (total_data < 100)
2738                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2739
2740                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2741                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2742                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
2743 #ifdef LARGE_SMB_OFF_T
2744                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2745 #else /* LARGE_SMB_OFF_T */
2746                                 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2747                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2748 #endif /* LARGE_SMB_OFF_T */
2749                         }
2750                         pdata+=24;          /* ctime & st_blocks are not changed */
2751                         tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2752                         tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2753                         pdata+=16;
2754                         set_owner = (uid_t)IVAL(pdata,0);
2755                         pdata += 8;
2756                         set_grp = (gid_t)IVAL(pdata,0);
2757                         pdata += 8;
2758                         raw_unixmode = IVAL(pdata,28);
2759                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2760                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
2761
2762                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2763 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2764                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2765
2766                         if (!VALID_STAT(sbuf)) {
2767
2768                                 /*
2769                                  * The only valid use of this is to create character and block
2770                                  * devices, and named pipes. This is deprecated (IMHO) and 
2771                                  * a new info level should be used for mknod. JRA.
2772                                  */
2773
2774 #if !defined(HAVE_MAKEDEV_FN)
2775                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2776 #else /* HAVE_MAKEDEV_FN */
2777                                 uint32 file_type = IVAL(pdata,0);
2778                                 uint32 dev_major = IVAL(pdata,4);
2779                                 uint32 dev_minor = IVAL(pdata,12);
2780
2781                                 uid_t myuid = geteuid();
2782                                 gid_t mygid = getegid();
2783                                 SMB_DEV_T dev;
2784
2785                                 if (tran_call == TRANSACT2_SETFILEINFO)
2786                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
2787
2788                                 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2789                                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2790
2791                                 dev = makedev(dev_major, dev_minor);
2792
2793                                 /* We can only create as the owner/group we are. */
2794
2795                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2796                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
2797                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2798                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
2799
2800                                 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2801                                                 file_type != UNIX_TYPE_FIFO)
2802                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
2803
2804                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2805 0%o for file %s\n", (double)dev, unixmode, fname ));
2806
2807                                 /* Ok - do the mknod. */
2808                                 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2809                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2810
2811                                 inherit_access_acl(conn, fname, unixmode);
2812
2813                                 SSVAL(params,0,0);
2814                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2815                                 return(-1);
2816 #endif /* HAVE_MAKEDEV_FN */
2817
2818                         }
2819
2820                         /*
2821                          * Deal with the UNIX specific mode set.
2822                          */
2823
2824                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2825                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2826                                         (unsigned int)unixmode, fname ));
2827                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
2828                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2829                         }
2830
2831                         /*
2832                          * Deal with the UNIX specific uid set.
2833                          */
2834
2835                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2836                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2837                                         (unsigned int)set_owner, fname ));
2838                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
2839                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2840                         }
2841
2842                         /*
2843                          * Deal with the UNIX specific gid set.
2844                          */
2845
2846                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2847                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2848                                         (unsigned int)set_owner, fname ));
2849                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
2850                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2851                         }
2852                         break;
2853                 }
2854
2855                 case SMB_SET_FILE_UNIX_LINK:
2856                 {
2857                         pstring link_dest;
2858                         /* Set a symbolic link. */
2859                         /* Don't allow this if follow links is false. */
2860
2861                         if (!lp_symlinks(SNUM(conn)))
2862                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2863
2864                         /* Disallow if already exists. */
2865                         if (VALID_STAT(sbuf))
2866                                 return(ERROR_DOS(ERRDOS,ERRbadpath));
2867
2868                         srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2869
2870                         if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2871                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2872
2873                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2874                                 fname, link_dest ));
2875
2876                         if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0)
2877                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2878                         SSVAL(params,0,0);
2879                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2880                         return(-1);
2881                 }
2882
2883                 case SMB_SET_FILE_UNIX_HLINK:
2884                 {
2885                         pstring link_dest;
2886
2887                         /* Set a hard link. */
2888
2889                         /* Disallow if already exists. */
2890                         if (VALID_STAT(sbuf))
2891                                 return(ERROR_DOS(ERRDOS,ERRbadpath));
2892
2893                         srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2894
2895                         if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2896                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2897
2898                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2899                                 fname, link_dest ));
2900
2901                         if (SMB_VFS_LINK(conn,link_dest,fname) != 0)
2902                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2903                         SSVAL(params,0,0);
2904                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2905                         return(-1);
2906                 }
2907
2908                 default:
2909                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2910         }
2911
2912         /* get some defaults (no modifications) if any info is zero or -1. */
2913         if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2914                 tvs.actime = sbuf.st_atime;
2915
2916         if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2917                 tvs.modtime = sbuf.st_mtime;
2918
2919         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2920         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2921         DEBUG(6,("size: %.0f ", (double)size));
2922
2923         if (dosmode == FILE_ATTRIBUTE_NORMAL)
2924                 dosmode = 0;
2925
2926         if (dosmode) {
2927                 if (S_ISDIR(sbuf.st_mode))
2928                         dosmode |= aDIR;
2929                 else
2930                         dosmode &= ~aDIR;
2931         }
2932
2933         DEBUG(6,("dosmode: %x\n"  , dosmode));
2934
2935         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2936                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2937                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2938                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2939
2940                 /*
2941                  * Only do this test if we are not explicitly
2942                  * changing the size of a file.
2943                  */
2944                 if (!size)
2945                         size = get_file_size(sbuf);
2946         }
2947
2948         /*
2949          * Try and set the times, size and mode of this file -
2950          * if they are different from the current values
2951          */
2952         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2953                 if(fsp != NULL) {
2954                         /*
2955                          * This was a setfileinfo on an open file.
2956                          * NT does this a lot. It's actually pointless
2957                          * setting the time here, as it will be overwritten
2958                          * on the next write, so we save the request
2959                          * away and will set it on file close. JRA.
2960                          */
2961
2962                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2963                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2964                                 fsp->pending_modtime = tvs.modtime;
2965                         }
2966
2967                 } else {
2968
2969                         DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2970
2971                         if(file_utime(conn, fname, &tvs)!=0)
2972                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2973                 }
2974         }
2975
2976         /* check the mode isn't different, before changing it */
2977         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2978
2979                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2980
2981                 if(file_chmod(conn, fname, dosmode, NULL)) {
2982                         DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2983                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2984                 }
2985         }
2986
2987         if (size != get_file_size(sbuf)) {
2988
2989                 int ret;
2990
2991                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2992                         fname, (double)size ));
2993
2994                 if (fd == -1) {
2995                         files_struct *new_fsp = NULL;
2996                         int access_mode = 0;
2997                         int action = 0;
2998
2999                         if(global_oplock_break) {
3000                                 /* Queue this file modify as we are the process of an oplock break.  */
3001
3002                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3003                                 DEBUGADD(2,( "in oplock break state.\n"));
3004
3005                                 push_oplock_pending_smb_message(inbuf, length);
3006                                 return -1;
3007                         }
3008
3009                         new_fsp = open_file_shared(conn, fname, &sbuf,
3010                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
3011                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3012                                                 0, 0, &access_mode, &action);
3013         
3014                         if (new_fsp == NULL)
3015                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3016                         ret = vfs_set_filelen(new_fsp, size);
3017                         close_file(new_fsp,True);
3018                 } else {
3019                         ret = vfs_set_filelen(fsp, size);
3020                 }
3021
3022                 if (ret == -1)
3023                         return (UNIXERROR(ERRHRD,ERRdiskfull));
3024         }
3025
3026         SSVAL(params,0,0);
3027         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3028   
3029         return(-1);
3030 }
3031
3032 /****************************************************************************
3033  Reply to a TRANS2_MKDIR (make directory with extended attributes).
3034 ****************************************************************************/
3035
3036 static int call_trans2mkdir(connection_struct *conn,
3037                             char *inbuf, char *outbuf, int length, int bufsize,
3038                                 char **pparams, int total_params, char **ppdata, int total_data)
3039 {
3040         char *params = *pparams;
3041         pstring directory;
3042         int ret = -1;
3043         SMB_STRUCT_STAT sbuf;
3044         BOOL bad_path = False;
3045
3046         if (!CAN_WRITE(conn))
3047                 return ERROR_DOS(ERRSRV,ERRaccess);
3048
3049         if (total_params < 4)
3050                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3051
3052         srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
3053
3054         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3055
3056         unix_convert(directory,conn,0,&bad_path,&sbuf);
3057         if (check_name(directory,conn))
3058                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3059   
3060         if(ret < 0) {
3061                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3062                 set_bad_path_error(errno, bad_path);
3063                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3064         }
3065
3066         /* Realloc the parameter and data sizes */
3067         params = Realloc(*pparams,2);
3068         if(params == NULL)
3069                 return ERROR_DOS(ERRDOS,ERRnomem);
3070         *pparams = params;
3071
3072         SSVAL(params,0,0);
3073
3074         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3075   
3076         return(-1);
3077 }
3078
3079 /****************************************************************************
3080  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3081  We don't actually do this - we just send a null response.
3082 ****************************************************************************/
3083
3084 static int call_trans2findnotifyfirst(connection_struct *conn,
3085                                         char *inbuf, char *outbuf, int length, int bufsize,
3086                                         char **pparams, int total_params, char **ppdata, int total_data)
3087 {
3088         static uint16 fnf_handle = 257;
3089         char *params = *pparams;
3090         uint16 info_level;
3091
3092         if (total_params < 6)
3093                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3094
3095         info_level = SVAL(params,4);
3096         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3097
3098         switch (info_level) {
3099                 case 1:
3100                 case 2:
3101                         break;
3102                 default:
3103                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3104         }
3105
3106         /* Realloc the parameter and data sizes */
3107         params = Realloc(*pparams,6);
3108         if(params == NULL) 
3109                 return ERROR_DOS(ERRDOS,ERRnomem);
3110         *pparams = params;
3111
3112         SSVAL(params,0,fnf_handle);
3113         SSVAL(params,2,0); /* No changes */
3114         SSVAL(params,4,0); /* No EA errors */
3115
3116         fnf_handle++;
3117
3118         if(fnf_handle == 0)
3119                 fnf_handle = 257;
3120
3121         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3122   
3123         return(-1);
3124 }
3125
3126 /****************************************************************************
3127  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
3128  changes). Currently this does nothing.
3129 ****************************************************************************/
3130
3131 static int call_trans2findnotifynext(connection_struct *conn,
3132                                         char *inbuf, char *outbuf, int length, int bufsize,
3133                                         char **pparams, int total_params, char **ppdata, int total_data)
3134 {
3135         char *params = *pparams;
3136
3137         DEBUG(3,("call_trans2findnotifynext\n"));
3138
3139         /* Realloc the parameter and data sizes */
3140         params = Realloc(*pparams,4);
3141         if(params == NULL)
3142                 return ERROR_DOS(ERRDOS,ERRnomem);
3143         *pparams = params;
3144
3145         SSVAL(params,0,0); /* No changes */
3146         SSVAL(params,2,0); /* No EA errors */
3147
3148         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3149   
3150         return(-1);
3151 }
3152
3153 /****************************************************************************
3154  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3155 ****************************************************************************/
3156
3157 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3158                                         char* outbuf, int length, int bufsize,
3159                                         char **pparams, int total_params, char **ppdata, int total_data)
3160 {
3161         char *params = *pparams;
3162         pstring pathname;
3163         int reply_size = 0;
3164         int max_referral_level;
3165
3166         DEBUG(10,("call_trans2getdfsreferral\n"));
3167
3168         if (total_params < 2)
3169                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3170
3171         max_referral_level = SVAL(params,0);
3172
3173         if(!lp_host_msdfs())
3174                 return ERROR_DOS(ERRDOS,ERRbadfunc);
3175
3176         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3177
3178         if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
3179                 return ERROR_DOS(ERRDOS,ERRbadfile);
3180     
3181         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3182         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3183
3184         return(-1);
3185 }
3186
3187 #define LMCAT_SPL       0x53
3188 #define LMFUNC_GETJOBID 0x60
3189
3190 /****************************************************************************
3191  Reply to a TRANS2_IOCTL - used for OS/2 printing.
3192 ****************************************************************************/
3193
3194 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3195                                         char* outbuf, int length, int bufsize,
3196                                         char **pparams, int total_params, char **ppdata, int total_data)
3197 {
3198         char *pdata = *ppdata;
3199         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3200         
3201         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3202                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3203                 pdata = Realloc(*ppdata, 32);
3204                 if(pdata == NULL)
3205                         return ERROR_DOS(ERRDOS,ERRnomem);
3206                 *ppdata = pdata;
3207
3208                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3209                         CAN ACCEPT THIS IN UNICODE. JRA. */
3210
3211                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
3212                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3213                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3214                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3215                 return(-1);
3216         } else {
3217                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3218                 return ERROR_DOS(ERRSRV,ERRerror);
3219         }
3220 }
3221
3222 /****************************************************************************
3223  Reply to a SMBfindclose (stop trans2 directory search).
3224 ****************************************************************************/
3225
3226 int reply_findclose(connection_struct *conn,
3227                     char *inbuf,char *outbuf,int length,int bufsize)
3228 {
3229         int outsize = 0;
3230         int dptr_num=SVALS(inbuf,smb_vwv0);
3231         START_PROFILE(SMBfindclose);
3232
3233         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3234
3235         dptr_close(&dptr_num);
3236
3237         outsize = set_message(outbuf,0,0,True);
3238
3239         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3240
3241         END_PROFILE(SMBfindclose);
3242         return(outsize);
3243 }
3244
3245 /****************************************************************************
3246  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3247 ****************************************************************************/
3248
3249 int reply_findnclose(connection_struct *conn, 
3250                      char *inbuf,char *outbuf,int length,int bufsize)
3251 {
3252         int outsize = 0;
3253         int dptr_num= -1;
3254         START_PROFILE(SMBfindnclose);
3255         
3256         dptr_num = SVAL(inbuf,smb_vwv0);
3257
3258         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3259
3260         /* We never give out valid handles for a 
3261            findnotifyfirst - so any dptr_num is ok here. 
3262            Just ignore it. */
3263
3264         outsize = set_message(outbuf,0,0,True);
3265
3266         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3267
3268         END_PROFILE(SMBfindnclose);
3269         return(outsize);
3270 }
3271
3272 /****************************************************************************
3273  Reply to a SMBtranss2 - just ignore it!
3274 ****************************************************************************/
3275
3276 int reply_transs2(connection_struct *conn,
3277                   char *inbuf,char *outbuf,int length,int bufsize)
3278 {
3279         START_PROFILE(SMBtranss2);
3280         DEBUG(4,("Ignoring transs2 of length %d\n",length));
3281         END_PROFILE(SMBtranss2);
3282         return(-1);
3283 }
3284
3285 /****************************************************************************
3286  Reply to a SMBtrans2.
3287 ****************************************************************************/
3288
3289 int reply_trans2(connection_struct *conn,
3290                  char *inbuf,char *outbuf,int length,int bufsize)
3291 {
3292         int outsize = 0;
3293         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3294         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3295 #if 0
3296         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3297         unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3298         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3299         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3300         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3301         int32 timeout = IVALS(inbuf,smb_timeout);
3302 #endif
3303         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3304         unsigned int tran_call = SVAL(inbuf, smb_setup0);
3305         char *params = NULL, *data = NULL;
3306         unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3307         START_PROFILE(SMBtrans2);
3308
3309         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3310                 /* Queue this open message as we are the process of an
3311                  * oplock break.  */
3312
3313                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3314                 DEBUGADD(2,( "in oplock break state.\n"));
3315
3316                 push_oplock_pending_smb_message(inbuf, length);
3317                 END_PROFILE(SMBtrans2);
3318                 return -1;
3319         }
3320         
3321         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3322             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3323                 END_PROFILE(SMBtrans2);
3324                 return ERROR_DOS(ERRSRV,ERRaccess);
3325         }
3326
3327         outsize = set_message(outbuf,0,0,True);
3328
3329         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3330            is so as a sanity check */
3331         if (suwcnt != 1) {
3332                 /*
3333                  * Need to have rc=0 for ioctl to get job id for OS/2.
3334                  *  Network printing will fail if function is not successful.
3335                  *  Similar function in reply.c will be used if protocol
3336                  *  is LANMAN1.0 instead of LM1.2X002.
3337                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
3338                  *  outbuf doesn't have to be set(only job id is used).
3339                  */
3340                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3341                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3342                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3343                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3344                 } else {
3345                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3346                         DEBUG(2,("Transaction is %d\n",tran_call));
3347                         END_PROFILE(SMBtrans2);
3348                         ERROR_DOS(ERRDOS,ERRinvalidparam);
3349                 }
3350         }
3351     
3352         /* Allocate the space for the maximum needed parameters and data */
3353         if (total_params > 0)
3354                 params = (char *)malloc(total_params);
3355         if (total_data > 0)
3356                 data = (char *)malloc(total_data);
3357   
3358         if ((total_params && !params)  || (total_data && !data)) {
3359                 DEBUG(2,("Out of memory in reply_trans2\n"));
3360                 SAFE_FREE(params);
3361                 SAFE_FREE(data); 
3362                 END_PROFILE(SMBtrans2);
3363                 return ERROR_DOS(ERRDOS,ERRnomem);
3364         }
3365
3366         /* Copy the param and data bytes sent with this request into
3367            the params buffer */
3368         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3369         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3370
3371         if (num_params > total_params || num_data > total_data)
3372                 exit_server("invalid params in reply_trans2");
3373
3374         if(params) {
3375                 unsigned int psoff = SVAL(inbuf, smb_psoff);
3376                 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3377                         goto bad_param;
3378                 if (smb_base(inbuf) + psoff + num_params > inbuf + length)
3379                         goto bad_param;
3380                 memcpy( params, smb_base(inbuf) + psoff, num_params);
3381         }
3382         if(data) {
3383                 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3384                 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3385                         goto bad_param;
3386                 if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
3387                         goto bad_param;
3388                 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3389         }
3390
3391         srv_signing_trans_start(SVAL(inbuf,smb_mid));
3392
3393         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
3394                 /* We need to send an interim response then receive the rest
3395                    of the parameter/data bytes */
3396                 outsize = set_message(outbuf,0,0,True);
3397                 if (!send_smb(smbd_server_fd(),outbuf))
3398                         exit_server("reply_trans2: send_smb failed.");
3399
3400                 while (num_data_sofar < total_data || 
3401                        num_params_sofar < total_params) {
3402                         BOOL ret;
3403                         unsigned int param_disp;
3404                         unsigned int param_off;
3405                         unsigned int data_disp;
3406                         unsigned int data_off;
3407
3408                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3409                         
3410                         if ((ret && 
3411                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3412                                 outsize = set_message(outbuf,0,0,True);
3413                                 if(ret)
3414                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3415                                 else
3416                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3417                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3418                                 goto bad_param;
3419                         }
3420       
3421                         /* Revise total_params and total_data in case
3422                            they have changed downwards */
3423                         if (SVAL(inbuf, smb_tpscnt) < total_params)
3424                                 total_params = SVAL(inbuf, smb_tpscnt);
3425                         if (SVAL(inbuf, smb_tdscnt) < total_data)
3426                                 total_data = SVAL(inbuf, smb_tdscnt);
3427
3428                         num_params = SVAL(inbuf,smb_spscnt);
3429                         param_off = SVAL(inbuf, smb_spsoff);
3430                         param_disp = SVAL(inbuf, smb_spsdisp);
3431                         num_params_sofar += num_params;
3432
3433                         num_data = SVAL(inbuf, smb_sdscnt);
3434                         data_off = SVAL(inbuf, smb_sdsoff);
3435                         data_disp = SVAL(inbuf, smb_sdsdisp);
3436                         num_data_sofar += num_data;
3437
3438                         if (num_params_sofar > total_params || num_data_sofar > total_data)
3439                                 goto bad_param;
3440                         
3441                         if (num_params) {
3442                                 if (param_disp + num_params >= total_params)
3443                                         goto bad_param;
3444                                 if ((param_disp + num_params < param_disp) ||
3445                                                 (param_disp + num_params < num_params))
3446                                         goto bad_param;
3447                                 if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
3448                                         goto bad_param;
3449                                 if (params + param_disp < params)
3450                                         goto bad_param;
3451
3452                                 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
3453                         }
3454                         if (num_data) {
3455                                 if (data_disp + num_data >= total_data)
3456                                         goto bad_param;
3457                                 if ((data_disp + num_data < data_disp) ||
3458                                                 (data_disp + num_data < num_data))
3459                                         goto bad_param;
3460                                 if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
3461                                         goto bad_param;
3462                                 if (data + data_disp < data)
3463                                         goto bad_param;
3464
3465                                 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3466                         }
3467                 }
3468         }
3469         
3470         if (Protocol >= PROTOCOL_NT1) {
3471                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3472         }
3473
3474         /* Now we must call the relevant TRANS2 function */
3475         switch(tran_call)  {
3476         case TRANSACT2_OPEN:
3477                 START_PROFILE_NESTED(Trans2_open);
3478                 outsize = call_trans2open(conn, inbuf, outbuf, bufsize, 
3479                                           &params, total_params, &data, total_data);
3480                 END_PROFILE_NESTED(Trans2_open);
3481                 break;
3482
3483         case TRANSACT2_FINDFIRST:
3484                 START_PROFILE_NESTED(Trans2_findfirst);
3485                 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3486                                           &params, total_params, &data, total_data);
3487                 END_PROFILE_NESTED(Trans2_findfirst);
3488                 break;
3489
3490         case TRANSACT2_FINDNEXT:
3491                 START_PROFILE_NESTED(Trans2_findnext);
3492                 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, 
3493                                           &params, total_params, &data, total_data);
3494                 END_PROFILE_NESTED(Trans2_findnext);
3495                 break;
3496
3497         case TRANSACT2_QFSINFO:
3498                 START_PROFILE_NESTED(Trans2_qfsinfo);
3499                 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3500                                           &params, total_params, &data, total_data);
3501                 END_PROFILE_NESTED(Trans2_qfsinfo);
3502             break;
3503
3504 #ifdef HAVE_SYS_QUOTAS
3505         case TRANSACT2_SETFSINFO:
3506                 START_PROFILE_NESTED(Trans2_setfsinfo);
3507                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, 
3508                                           &params, total_params, &data, total_data);
3509                 END_PROFILE_NESTED(Trans2_setfsinfo);
3510                 break;
3511 #endif
3512         case TRANSACT2_QPATHINFO:
3513         case TRANSACT2_QFILEINFO:
3514                 START_PROFILE_NESTED(Trans2_qpathinfo);
3515                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
3516                                           &params, total_params, &data, total_data);
3517                 END_PROFILE_NESTED(Trans2_qpathinfo);
3518                 break;
3519         case TRANSACT2_SETPATHINFO:
3520         case TRANSACT2_SETFILEINFO:
3521                 START_PROFILE_NESTED(Trans2_setpathinfo);
3522                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
3523                                           &params, total_params, &data, total_data);
3524                 END_PROFILE_NESTED(Trans2_setpathinfo);
3525                 break;
3526
3527         case TRANSACT2_FINDNOTIFYFIRST:
3528                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3529                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, 
3530                                           &params, total_params, &data, total_data);
3531                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3532                 break;
3533
3534         case TRANSACT2_FINDNOTIFYNEXT:
3535                 START_PROFILE_NESTED(Trans2_findnotifynext);
3536                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, 
3537                                           &params, total_params, &data, total_data);
3538                 END_PROFILE_NESTED(Trans2_findnotifynext);
3539                 break;
3540         case TRANSACT2_MKDIR:
3541                 START_PROFILE_NESTED(Trans2_mkdir);
3542                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3543                                           &params, total_params, &data, total_data);
3544                 END_PROFILE_NESTED(Trans2_mkdir);
3545                 break;
3546
3547         case TRANSACT2_GET_DFS_REFERRAL:
3548                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3549                 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3550                                           &params, total_params, &data, total_data);
3551                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3552                 break;
3553         case TRANSACT2_IOCTL:
3554                 START_PROFILE_NESTED(Trans2_ioctl);
3555                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3556                                           &params, total_params, &data, total_data);
3557                 END_PROFILE_NESTED(Trans2_ioctl);
3558                 break;
3559         default:
3560                 /* Error in request */
3561                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3562                 SAFE_FREE(params);
3563                 SAFE_FREE(data);
3564                 END_PROFILE(SMBtrans2);
3565                 srv_signing_trans_stop();
3566                 return ERROR_DOS(ERRSRV,ERRerror);
3567         }
3568         
3569         /* As we do not know how many data packets will need to be
3570            returned here the various call_trans2xxxx calls
3571            must send their own. Thus a call_trans2xxx routine only
3572            returns a value other than -1 when it wants to send
3573            an error packet. 
3574         */
3575         
3576         srv_signing_trans_stop();
3577
3578         SAFE_FREE(params);
3579         SAFE_FREE(data);
3580         END_PROFILE(SMBtrans2);
3581         return outsize; /* If a correct response was needed the
3582                            call_trans2xxx calls have already sent
3583                            it. If outsize != -1 then it is returning */
3584
3585   bad_param:
3586
3587         srv_signing_trans_stop();
3588         SAFE_FREE(params);
3589         SAFE_FREE(data);
3590         END_PROFILE(SMBtrans2);
3591         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3592 }