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