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