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