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