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