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