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