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