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