r18547: Add in fixes to mangling dir code - ensure don't
[tprouty/samba.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    Copyright (C) Volker Lendecke                2005
7    Copyright (C) Steve French                   2005
8
9    Extensively modified by Andrew Tridgell, 1995
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "includes.h"
27
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
33
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
36
37 /********************************************************************
38  Roundup a value to the nearest allocation roundup size boundary.
39  Only do this for Windows clients.
40 ********************************************************************/
41
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
43 {
44         SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
45
46         /* Only roundup for Windows clients. */
47         enum remote_arch_types ra_type = get_remote_arch();
48         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49                 val = SMB_ROUNDUP(val,rval);
50         }
51         return val;
52 }
53
54 /********************************************************************
55  Given a stat buffer return the allocated size on disk, taking into
56  account sparse files.
57 ********************************************************************/
58
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
60 {
61         SMB_BIG_UINT ret;
62
63         if(S_ISDIR(sbuf->st_mode)) {
64                 return 0;
65         }
66
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
69 #else
70         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
71 #endif
72
73         if (fsp && fsp->initial_allocation_size)
74                 ret = MAX(ret,fsp->initial_allocation_size);
75
76         return smb_roundup(conn, ret);
77 }
78
79 /****************************************************************************
80  Utility functions for dealing with extended attributes.
81 ****************************************************************************/
82
83 static const char *prohibited_ea_names[] = {
84         SAMBA_POSIX_INHERITANCE_EA_NAME,
85         SAMBA_XATTR_DOS_ATTRIB,
86         NULL
87 };
88
89 /****************************************************************************
90  Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
92
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
94 {
95         int i;
96
97         for (i = 0; prohibited_ea_names[i]; i++) {
98                 if (strequal( prohibited_ea_names[i], unix_ea_name))
99                         return True;
100         }
101         return False;
102 }
103
104 /****************************************************************************
105  Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
107
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109                                 const char *fname, char *ea_name, struct ea_struct *pea)
110 {
111         /* Get the value of this xattr. Max size is 64k. */
112         size_t attr_size = 256;
113         char *val = NULL;
114         ssize_t sizeret;
115
116  again:
117
118         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
119         if (!val) {
120                 return False;
121         }
122
123         if (fsp && fsp->fh->fd != -1) {
124                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
125         } else {
126                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
127         }
128
129         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
130                 attr_size = 65536;
131                 goto again;
132         }
133
134         if (sizeret == -1) {
135                 return False;
136         }
137
138         DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139         dump_data(10, val, sizeret);
140
141         pea->flags = 0;
142         if (strnequal(ea_name, "user.", 5)) {
143                 pea->name = &ea_name[5];
144         } else {
145                 pea->name = ea_name;
146         }
147         pea->value.data = (unsigned char *)val;
148         pea->value.length = (size_t)sizeret;
149         return True;
150 }
151
152 /****************************************************************************
153  Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
155
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157                                         const char *fname, size_t *pea_total_len)
158 {
159         /* Get a list of all xattrs. Max namesize is 64k. */
160         size_t ea_namelist_size = 1024;
161         char *ea_namelist;
162         char *p;
163         ssize_t sizeret;
164         int i;
165         struct ea_list *ea_list_head = NULL;
166
167         *pea_total_len = 0;
168
169         if (!lp_ea_support(SNUM(conn))) {
170                 return NULL;
171         }
172
173         for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
174              ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
175
176                 if (!ea_namelist) {
177                         return NULL;
178                 }
179
180                 if (fsp && fsp->fh->fd != -1) {
181                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
182                 } else {
183                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
184                 }
185
186                 if (sizeret == -1 && errno == ERANGE) {
187                         ea_namelist_size *= 2;
188                 } else {
189                         break;
190                 }
191         }
192
193         if (sizeret == -1)
194                 return NULL;
195
196         DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
197
198         if (sizeret) {
199                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
200                         struct ea_list *listp, *tmp;
201
202                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
203                                 continue;
204                 
205                         listp = TALLOC_P(mem_ctx, struct ea_list);
206                         if (!listp)
207                                 return NULL;
208
209                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
210                                 return NULL;
211                         }
212
213                         {
214                                 fstring dos_ea_name;
215                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
216                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
217                                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
218                                         (unsigned int)*pea_total_len, dos_ea_name,
219                                         (unsigned int)listp->ea.value.length ));
220                         }
221                         DLIST_ADD_END(ea_list_head, listp, tmp);
222                 }
223                 /* Add on 4 for total length. */
224                 if (*pea_total_len) {
225                         *pea_total_len += 4;
226                 }
227         }
228
229         DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
230         return ea_list_head;
231 }
232
233 /****************************************************************************
234  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
235  that was filled.
236 ****************************************************************************/
237
238 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
239         connection_struct *conn, struct ea_list *ea_list)
240 {
241         unsigned int ret_data_size = 4;
242         char *p = pdata;
243
244         SMB_ASSERT(total_data_size >= 4);
245
246         if (!lp_ea_support(SNUM(conn))) {
247                 SIVAL(pdata,4,0);
248                 return 4;
249         }
250
251         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
252                 size_t dos_namelen;
253                 fstring dos_ea_name;
254                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
255                 dos_namelen = strlen(dos_ea_name);
256                 if (dos_namelen > 255 || dos_namelen == 0) {
257                         break;
258                 }
259                 if (ea_list->ea.value.length > 65535) {
260                         break;
261                 }
262                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
263                         break;
264                 }
265
266                 /* We know we have room. */
267                 SCVAL(p,0,ea_list->ea.flags);
268                 SCVAL(p,1,dos_namelen);
269                 SSVAL(p,2,ea_list->ea.value.length);
270                 fstrcpy(p+4, dos_ea_name);
271                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
272
273                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
274                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
275         }
276
277         ret_data_size = PTR_DIFF(p, pdata);
278         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
279         SIVAL(pdata,0,ret_data_size);
280         return ret_data_size;
281 }
282
283 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
284 {
285         size_t total_ea_len = 0;
286         TALLOC_CTX *mem_ctx = NULL;
287
288         if (!lp_ea_support(SNUM(conn))) {
289                 return 0;
290         }
291         mem_ctx = talloc_init("estimate_ea_size");
292         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
293         talloc_destroy(mem_ctx);
294         return total_ea_len;
295 }
296
297 /****************************************************************************
298  Ensure the EA name is case insensitive by matching any existing EA name.
299 ****************************************************************************/
300
301 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
302 {
303         size_t total_ea_len;
304         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
305         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
306
307         for (; ea_list; ea_list = ea_list->next) {
308                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
309                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
310                                 &unix_ea_name[5], ea_list->ea.name));
311                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
312                         break;
313                 }
314         }
315         talloc_destroy(mem_ctx);
316 }
317
318 /****************************************************************************
319  Set or delete an extended attribute.
320 ****************************************************************************/
321
322 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
323 {
324         if (!lp_ea_support(SNUM(conn))) {
325                 return NT_STATUS_EAS_NOT_SUPPORTED;
326         }
327
328         for (;ea_list; ea_list = ea_list->next) {
329                 int ret;
330                 fstring unix_ea_name;
331
332                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
333                 fstrcat(unix_ea_name, ea_list->ea.name);
334
335                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
336
337                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
338
339                 if (samba_private_attr_name(unix_ea_name)) {
340                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
341                         return NT_STATUS_ACCESS_DENIED;
342                 }
343
344                 if (ea_list->ea.value.length == 0) {
345                         /* Remove the attribute. */
346                         if (fsp && (fsp->fh->fd != -1)) {
347                                 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
348                                         unix_ea_name, fsp->fsp_name));
349                                 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
350                         } else {
351                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
352                                         unix_ea_name, fname));
353                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
354                         }
355 #ifdef ENOATTR
356                         /* Removing a non existent attribute always succeeds. */
357                         if (ret == -1 && errno == ENOATTR) {
358                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
359                                                 unix_ea_name));
360                                 ret = 0;
361                         }
362 #endif
363                 } else {
364                         if (fsp && (fsp->fh->fd != -1)) {
365                                 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
366                                         unix_ea_name, fsp->fsp_name));
367                                 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
368                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
369                         } else {
370                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
371                                         unix_ea_name, fname));
372                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
373                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
374                         }
375                 }
376
377                 if (ret == -1) {
378 #ifdef ENOTSUP
379                         if (errno == ENOTSUP) {
380                                 return NT_STATUS_EAS_NOT_SUPPORTED;
381                         }
382 #endif
383                         return map_nt_error_from_unix(errno);
384                 }
385
386         }
387         return NT_STATUS_OK;
388 }
389 /****************************************************************************
390  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
391 ****************************************************************************/
392
393 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
394 {
395         struct ea_list *ea_list_head = NULL;
396         size_t offset = 0;
397
398         while (offset + 2 < data_size) {
399                 struct ea_list *tmp;
400                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
401                 unsigned int namelen = CVAL(pdata,offset);
402
403                 offset++; /* Go past the namelen byte. */
404
405                 /* integer wrap paranioa. */
406                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
407                                 (offset > data_size) || (namelen > data_size) ||
408                                 (offset + namelen >= data_size)) {
409                         break;
410                 }
411                 /* Ensure the name is null terminated. */
412                 if (pdata[offset + namelen] != '\0') {
413                         return NULL;
414                 }
415                 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
416                 if (!eal->ea.name) {
417                         return NULL;
418                 }
419
420                 offset += (namelen + 1); /* Go past the name + terminating zero. */
421                 DLIST_ADD_END(ea_list_head, eal, tmp);
422                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
423         }
424
425         return ea_list_head;
426 }
427
428 /****************************************************************************
429  Read one EA list entry from the buffer.
430 ****************************************************************************/
431
432 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
433 {
434         struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
435         uint16 val_len;
436         unsigned int namelen;
437
438         if (!eal) {
439                 return NULL;
440         }
441
442         if (data_size < 6) {
443                 return NULL;
444         }
445
446         eal->ea.flags = CVAL(pdata,0);
447         namelen = CVAL(pdata,1);
448         val_len = SVAL(pdata,2);
449
450         if (4 + namelen + 1 + val_len > data_size) {
451                 return NULL;
452         }
453
454         /* Ensure the name is null terminated. */
455         if (pdata[namelen + 4] != '\0') {
456                 return NULL;
457         }
458         pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
459         if (!eal->ea.name) {
460                 return NULL;
461         }
462
463         eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
464         if (!eal->ea.value.data) {
465                 return NULL;
466         }
467
468         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
469
470         /* Ensure we're null terminated just in case we print the value. */
471         eal->ea.value.data[val_len] = '\0';
472         /* But don't count the null. */
473         eal->ea.value.length--;
474
475         if (pbytes_used) {
476                 *pbytes_used = 4 + namelen + 1 + val_len;
477         }
478
479         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
480         dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
481
482         return eal;
483 }
484
485 /****************************************************************************
486  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
487 ****************************************************************************/
488
489 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
490 {
491         struct ea_list *ea_list_head = NULL;
492         size_t offset = 0;
493         size_t bytes_used = 0;
494
495         while (offset < data_size) {
496                 struct ea_list *tmp;
497                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
498
499                 if (!eal) {
500                         return NULL;
501                 }
502
503                 DLIST_ADD_END(ea_list_head, eal, tmp);
504                 offset += bytes_used;
505         }
506
507         return ea_list_head;
508 }
509
510 /****************************************************************************
511  Count the total EA size needed.
512 ****************************************************************************/
513
514 static size_t ea_list_size(struct ea_list *ealist)
515 {
516         fstring dos_ea_name;
517         struct ea_list *listp;
518         size_t ret = 0;
519
520         for (listp = ealist; listp; listp = listp->next) {
521                 push_ascii_fstring(dos_ea_name, listp->ea.name);
522                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
523         }
524         /* Add on 4 for total length. */
525         if (ret) {
526                 ret += 4;
527         }
528
529         return ret;
530 }
531
532 /****************************************************************************
533  Return a union of EA's from a file list and a list of names.
534  The TALLOC context for the two lists *MUST* be identical as we steal
535  memory from one list to add to another. JRA.
536 ****************************************************************************/
537
538 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
539 {
540         struct ea_list *nlistp, *flistp;
541
542         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
543                 for (flistp = file_list; flistp; flistp = flistp->next) {
544                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
545                                 break;
546                         }
547                 }
548
549                 if (flistp) {
550                         /* Copy the data from this entry. */
551                         nlistp->ea.flags = flistp->ea.flags;
552                         nlistp->ea.value = flistp->ea.value;
553                 } else {
554                         /* Null entry. */
555                         nlistp->ea.flags = 0;
556                         ZERO_STRUCT(nlistp->ea.value);
557                 }
558         }
559
560         *total_ea_len = ea_list_size(name_list);
561         return name_list;
562 }
563
564 /****************************************************************************
565   Send the required number of replies back.
566   We assume all fields other than the data fields are
567   set correctly for the type of call.
568   HACK ! Always assumes smb_setup field is zero.
569 ****************************************************************************/
570
571 int send_trans2_replies(char *outbuf,
572                         int bufsize,
573                         char *params, 
574                         int paramsize,
575                         char *pdata,
576                         int datasize,
577                         int max_data_bytes)
578 {
579         /* As we are using a protocol > LANMAN1 then the max_send
580          variable must have been set in the sessetupX call.
581          This takes precedence over the max_xmit field in the
582          global struct. These different max_xmit variables should
583          be merged as this is now too confusing */
584
585         int data_to_send = datasize;
586         int params_to_send = paramsize;
587         int useable_space;
588         char *pp = params;
589         char *pd = pdata;
590         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
591         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
592         int data_alignment_offset = 0;
593
594         /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
595         
596         set_message(outbuf,10,0,True);
597
598         /* Modify the data_to_send and datasize and set the error if
599            we're trying to send more than max_data_bytes. We still send
600            the part of the packet(s) that fit. Strange, but needed
601            for OS/2. */
602
603         if (max_data_bytes > 0 && datasize > max_data_bytes) {
604                 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
605                         max_data_bytes, datasize ));
606                 datasize = data_to_send = max_data_bytes;
607                 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
608         }
609
610         /* If there genuinely are no parameters or data to send just send the empty packet */
611
612         if(params_to_send == 0 && data_to_send == 0) {
613                 show_msg(outbuf);
614                 if (!send_smb(smbd_server_fd(),outbuf))
615                         exit_server("send_trans2_replies: send_smb failed.");
616                 return 0;
617         }
618
619         /* When sending params and data ensure that both are nicely aligned */
620         /* Only do this alignment when there is also data to send - else
621                 can cause NT redirector problems. */
622
623         if (((params_to_send % 4) != 0) && (data_to_send != 0))
624                 data_alignment_offset = 4 - (params_to_send % 4);
625
626         /* Space is bufsize minus Netbios over TCP header minus SMB header */
627         /* The alignment_offset is to align the param bytes on an even byte
628                 boundary. NT 4.0 Beta needs this to work correctly. */
629
630         useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
631
632         /* useable_space can never be more than max_send minus the alignment offset. */
633
634         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
635
636         while (params_to_send || data_to_send) {
637                 /* Calculate whether we will totally or partially fill this packet */
638
639                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
640
641                 /* We can never send more than useable_space */
642                 /*
643                  * Note that 'useable_space' does not include the alignment offsets,
644                  * but we must include the alignment offsets in the calculation of
645                  * the length of the data we send over the wire, as the alignment offsets
646                  * are sent here. Fix from Marc_Jacobsen@hp.com.
647                  */
648
649                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
650
651                 set_message(outbuf, 10, total_sent_thistime, True);
652
653                 /* Set total params and data to be sent */
654                 SSVAL(outbuf,smb_tprcnt,paramsize);
655                 SSVAL(outbuf,smb_tdrcnt,datasize);
656
657                 /* Calculate how many parameters and data we can fit into
658                  * this packet. Parameters get precedence
659                  */
660
661                 params_sent_thistime = MIN(params_to_send,useable_space);
662                 data_sent_thistime = useable_space - params_sent_thistime;
663                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
664
665                 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
666
667                 /* smb_proff is the offset from the start of the SMB header to the
668                         parameter bytes, however the first 4 bytes of outbuf are
669                         the Netbios over TCP header. Thus use smb_base() to subtract
670                         them from the calculation */
671
672                 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
673
674                 if(params_sent_thistime == 0)
675                         SSVAL(outbuf,smb_prdisp,0);
676                 else
677                         /* Absolute displacement of param bytes sent in this packet */
678                         SSVAL(outbuf,smb_prdisp,pp - params);
679
680                 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
681                 if(data_sent_thistime == 0) {
682                         SSVAL(outbuf,smb_droff,0);
683                         SSVAL(outbuf,smb_drdisp, 0);
684                 } else {
685                         /* The offset of the data bytes is the offset of the
686                                 parameter bytes plus the number of parameters being sent this time */
687                         SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
688                                 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
689                         SSVAL(outbuf,smb_drdisp, pd - pdata);
690                 }
691
692                 /* Copy the param bytes into the packet */
693
694                 if(params_sent_thistime)
695                         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
696
697                 /* Copy in the data bytes */
698                 if(data_sent_thistime)
699                         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
700                                 data_alignment_offset,pd,data_sent_thistime);
701
702                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
703                         params_sent_thistime, data_sent_thistime, useable_space));
704                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
705                         params_to_send, data_to_send, paramsize, datasize));
706
707                 /* Send the packet */
708                 show_msg(outbuf);
709                 if (!send_smb(smbd_server_fd(),outbuf))
710                         exit_server("send_trans2_replies: send_smb failed.");
711
712                 pp += params_sent_thistime;
713                 pd += data_sent_thistime;
714
715                 params_to_send -= params_sent_thistime;
716                 data_to_send -= data_sent_thistime;
717
718                 /* Sanity check */
719                 if(params_to_send < 0 || data_to_send < 0) {
720                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
721                                 params_to_send, data_to_send));
722                         return -1;
723                 }
724         }
725
726         return 0;
727 }
728
729 /****************************************************************************
730  Reply to a TRANSACT2_OPEN.
731 ****************************************************************************/
732
733 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
734                                 char **pparams, int total_params, char **ppdata, int total_data,
735                                 unsigned int max_data_bytes)
736 {
737         char *params = *pparams;
738         char *pdata = *ppdata;
739         int deny_mode;
740         int32 open_attr;
741         BOOL oplock_request;
742 #if 0
743         BOOL return_additional_info;
744         int16 open_sattr;
745         time_t open_time;
746 #endif
747         int open_ofun;
748         uint32 open_size;
749         char *pname;
750         pstring fname;
751         SMB_OFF_T size=0;
752         int fattr=0,mtime=0;
753         SMB_INO_T inode = 0;
754         SMB_STRUCT_STAT sbuf;
755         int smb_action = 0;
756         BOOL bad_path = False;
757         files_struct *fsp;
758         TALLOC_CTX *ctx = NULL;
759         struct ea_list *ea_list = NULL;
760         uint16 flags = 0;
761         NTSTATUS status;
762         uint32 access_mask;
763         uint32 share_mode;
764         uint32 create_disposition;
765         uint32 create_options = 0;
766
767         /*
768          * Ensure we have enough parameters to perform the operation.
769          */
770
771         if (total_params < 29) {
772                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
773         }
774
775         flags = SVAL(params, 0);
776         deny_mode = SVAL(params, 2);
777         open_attr = SVAL(params,6);
778         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
779         if (oplock_request) {
780                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
781         }
782
783 #if 0
784         return_additional_info = BITSETW(params,0);
785         open_sattr = SVAL(params, 4);
786         open_time = make_unix_date3(params+8);
787 #endif
788         open_ofun = SVAL(params,12);
789         open_size = IVAL(params,14);
790         pname = &params[28];
791
792         if (IS_IPC(conn)) {
793                 return(ERROR_DOS(ERRSRV,ERRaccess));
794         }
795
796         srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
797         if (!NT_STATUS_IS_OK(status)) {
798                 return ERROR_NT(status);
799         }
800
801         DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
802                 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
803                 (unsigned int)open_ofun, open_size));
804
805         /* XXXX we need to handle passed times, sattr and flags */
806
807         unix_convert(fname,conn,0,&bad_path,&sbuf);
808         if (bad_path) {
809                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
810         }
811     
812         if (!check_name(fname,conn)) {
813                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
814         }
815
816         if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
817                                 &access_mask,
818                                 &share_mode,
819                                 &create_disposition,
820                                 &create_options)) {
821                 return ERROR_DOS(ERRDOS, ERRbadaccess);
822         }
823
824         /* Any data in this call is an EA list. */
825         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
826                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
827         }
828
829         if (total_data != 4) {
830                 if (total_data < 10) {
831                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
832                 }
833
834                 if (IVAL(pdata,0) > total_data) {
835                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
836                                 IVAL(pdata,0), (unsigned int)total_data));
837                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
838                 }
839
840                 ctx = talloc_init("TRANS2_OPEN_SET_EA");
841                 if (!ctx) {
842                         return ERROR_NT(NT_STATUS_NO_MEMORY);
843                 }
844                 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
845                 if (!ea_list) {
846                         talloc_destroy(ctx);
847                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
848                 }
849         } else if (IVAL(pdata,0) != 4) {
850                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
851         }
852
853         status = open_file_ntcreate(conn,fname,&sbuf,
854                 access_mask,
855                 share_mode,
856                 create_disposition,
857                 create_options,
858                 open_attr,
859                 oplock_request,
860                 &smb_action, &fsp);
861       
862         if (!NT_STATUS_IS_OK(status)) {
863                 talloc_destroy(ctx);
864                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
865                         /* We have re-scheduled this call. */
866                         return -1;
867                 }
868                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
869         }
870
871         size = get_file_size(sbuf);
872         fattr = dos_mode(conn,fname,&sbuf);
873         mtime = sbuf.st_mtime;
874         inode = sbuf.st_ino;
875         if (fattr & aDIR) {
876                 talloc_destroy(ctx);
877                 close_file(fsp,ERROR_CLOSE);
878                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
879         }
880
881         /* Save the requested allocation size. */
882         /* Allocate space for the file if a size hint is supplied */
883         if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
884                 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
885                 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
886                         fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
887                         if (fsp->is_directory) {
888                                 close_file(fsp,ERROR_CLOSE);
889                                 /* Can't set allocation size on a directory. */
890                                 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
891                         }
892                         if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
893                                 close_file(fsp,ERROR_CLOSE);
894                                 return ERROR_NT(NT_STATUS_DISK_FULL);
895                         }
896
897                         /* Adjust size here to return the right size in the reply.
898                            Windows does it this way. */
899                         size = fsp->initial_allocation_size;
900                 } else {
901                         fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
902                 }
903         }
904
905         if (total_data && smb_action == FILE_WAS_CREATED) {
906                 status = set_ea(conn, fsp, fname, ea_list);
907                 talloc_destroy(ctx);
908                 if (!NT_STATUS_IS_OK(status)) {
909                         close_file(fsp,ERROR_CLOSE);
910                         return ERROR_NT(status);
911                 }
912         }
913
914         /* Realloc the size of parameters and data we will return */
915         *pparams = (char *)SMB_REALLOC(*pparams, 30);
916         if(*pparams == NULL ) {
917                 return ERROR_NT(NT_STATUS_NO_MEMORY);
918         }
919         params = *pparams;
920
921         SSVAL(params,0,fsp->fnum);
922         SSVAL(params,2,open_attr);
923         srv_put_dos_date2(params,4, mtime);
924         SIVAL(params,8, (uint32)size);
925         SSVAL(params,12,deny_mode);
926         SSVAL(params,14,0); /* open_type - file or directory. */
927         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
928
929         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
930                 smb_action |= EXTENDED_OPLOCK_GRANTED;
931         }
932
933         SSVAL(params,18,smb_action);
934
935         /*
936          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
937          */
938         SIVAL(params,20,inode);
939         SSVAL(params,24,0); /* Padding. */
940         if (flags & 8) {
941                 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
942                 SIVAL(params, 26, ea_size);
943         } else {
944                 SIVAL(params, 26, 0);
945         }
946
947         /* Send the required number of replies */
948         send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
949
950         return -1;
951 }
952
953 /*********************************************************
954  Routine to check if a given string matches exactly.
955  as a special case a mask of "." does NOT match. That
956  is required for correct wildcard semantics
957  Case can be significant or not.
958 **********************************************************/
959
960 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
961 {
962         if (mask[0] == '.' && mask[1] == 0)
963                 return False;
964         if (conn->case_sensitive)
965                 return strcmp(str,mask)==0;
966         if (StrCaseCmp(str,mask) != 0) {
967                 return False;
968         }
969         if (dptr_has_wild(conn->dirptr)) {
970                 return False;
971         }
972         return True;
973 }
974
975 /****************************************************************************
976  Return the filetype for UNIX extensions.
977 ****************************************************************************/
978
979 static uint32 unix_filetype(mode_t mode)
980 {
981         if(S_ISREG(mode))
982                 return UNIX_TYPE_FILE;
983         else if(S_ISDIR(mode))
984                 return UNIX_TYPE_DIR;
985 #ifdef S_ISLNK
986         else if(S_ISLNK(mode))
987                 return UNIX_TYPE_SYMLINK;
988 #endif
989 #ifdef S_ISCHR
990         else if(S_ISCHR(mode))
991                 return UNIX_TYPE_CHARDEV;
992 #endif
993 #ifdef S_ISBLK
994         else if(S_ISBLK(mode))
995                 return UNIX_TYPE_BLKDEV;
996 #endif
997 #ifdef S_ISFIFO
998         else if(S_ISFIFO(mode))
999                 return UNIX_TYPE_FIFO;
1000 #endif
1001 #ifdef S_ISSOCK
1002         else if(S_ISSOCK(mode))
1003                 return UNIX_TYPE_SOCKET;
1004 #endif
1005
1006         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1007         return UNIX_TYPE_UNKNOWN;
1008 }
1009
1010 /****************************************************************************
1011  Map wire perms onto standard UNIX permissions. Obey share restrictions.
1012 ****************************************************************************/
1013
1014 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
1015 {
1016         mode_t ret = 0;
1017
1018         if (perms == SMB_MODE_NO_CHANGE)
1019                 return pst->st_mode;
1020
1021         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1022         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1023         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1024         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1025         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1026         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1027         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1028         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1029         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1030 #ifdef S_ISVTX
1031         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1032 #endif
1033 #ifdef S_ISGID
1034         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1035 #endif
1036 #ifdef S_ISUID
1037         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1038 #endif
1039
1040         if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
1041                 ret &= lp_dir_mask(SNUM(conn));
1042                 /* Add in force bits */
1043                 ret |= lp_force_dir_mode(SNUM(conn));
1044         } else {
1045                 /* Apply mode mask */
1046                 ret &= lp_create_mask(SNUM(conn));
1047                 /* Add in force bits */
1048                 ret |= lp_force_create_mode(SNUM(conn));
1049         }
1050
1051         return ret;
1052 }
1053
1054 /****************************************************************************
1055  Get a level dependent lanman2 dir entry.
1056 ****************************************************************************/
1057
1058 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1059                                   void *inbuf, char *outbuf,
1060                                  char *path_mask,uint32 dirtype,int info_level,
1061                                  int requires_resume_key,
1062                                  BOOL dont_descend,char **ppdata, 
1063                                  char *base_data, int space_remaining, 
1064                                  BOOL *out_of_space, BOOL *got_exact_match,
1065                                  int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1066 {
1067         const char *dname;
1068         BOOL found = False;
1069         SMB_STRUCT_STAT sbuf;
1070         pstring mask;
1071         pstring pathreal;
1072         pstring fname;
1073         char *p, *q, *pdata = *ppdata;
1074         uint32 reskey=0;
1075         long prev_dirpos=0;
1076         uint32 mode=0;
1077         SMB_OFF_T file_size = 0;
1078         SMB_BIG_UINT allocation_size = 0;
1079         uint32 len;
1080         struct timespec mdate_ts, adate_ts, create_date_ts;
1081         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1082         char *nameptr;
1083         char *last_entry_ptr;
1084         BOOL was_8_3;
1085         uint32 nt_extmode; /* Used for NT connections instead of mode */
1086         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1087         BOOL check_mangled_names = lp_manglednames(conn->params);
1088
1089         *fname = 0;
1090         *out_of_space = False;
1091         *got_exact_match = False;
1092
1093         ZERO_STRUCT(mdate_ts);
1094         ZERO_STRUCT(adate_ts);
1095         ZERO_STRUCT(create_date_ts);
1096
1097         if (!conn->dirptr)
1098                 return(False);
1099
1100         p = strrchr_m(path_mask,'/');
1101         if(p != NULL) {
1102                 if(p[1] == '\0')
1103                         pstrcpy(mask,"*.*");
1104                 else
1105                         pstrcpy(mask, p+1);
1106         } else
1107                 pstrcpy(mask, path_mask);
1108
1109
1110         while (!found) {
1111                 BOOL got_match;
1112                 BOOL ms_dfs_link = False;
1113
1114                 /* Needed if we run out of space */
1115                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1116                 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1117
1118                 /*
1119                  * Due to bugs in NT client redirectors we are not using
1120                  * resume keys any more - set them to zero.
1121                  * Check out the related comments in findfirst/findnext.
1122                  * JRA.
1123                  */
1124
1125                 reskey = 0;
1126
1127                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1128                         (long)conn->dirptr,curr_dirpos));
1129       
1130                 if (!dname) 
1131                         return(False);
1132
1133                 pstrcpy(fname,dname);      
1134
1135                 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1136                         got_match = mask_match(fname, mask, conn->case_sensitive);
1137
1138                 if(!got_match && check_mangled_names &&
1139                    !mangle_is_8_3(fname, False, conn->params)) {
1140
1141                         /*
1142                          * It turns out that NT matches wildcards against
1143                          * both long *and* short names. This may explain some
1144                          * of the wildcard wierdness from old DOS clients
1145                          * that some people have been seeing.... JRA.
1146                          */
1147
1148                         pstring newname;
1149                         pstrcpy( newname, fname);
1150                         mangle_map( newname, True, False, conn->params);
1151                         if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1152                                 got_match = mask_match(newname, mask, conn->case_sensitive);
1153                 }
1154
1155                 if(got_match) {
1156                         BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1157                         if (dont_descend && !isdots)
1158                                 continue;
1159           
1160                         pstrcpy(pathreal,conn->dirpath);
1161                         if(needslash)
1162                                 pstrcat(pathreal,"/");
1163                         pstrcat(pathreal,dname);
1164
1165                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1166                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1167                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1168                                                 pathreal,strerror(errno)));
1169                                         continue;
1170                                 }
1171                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1172
1173                                 /* Needed to show the msdfs symlinks as 
1174                                  * directories */
1175
1176                                 if(lp_host_msdfs() && 
1177                                    lp_msdfs_root(SNUM(conn)) &&
1178                                    ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
1179
1180                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1181                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1182
1183                                 } else {
1184
1185                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1186                                                 pathreal,strerror(errno)));
1187                                         continue;
1188                                 }
1189                         }
1190
1191                         if (ms_dfs_link) {
1192                                 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1193                         } else {
1194                                 mode = dos_mode(conn,pathreal,&sbuf);
1195                         }
1196
1197                         if (!dir_check_ftype(conn,mode,dirtype)) {
1198                                 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1199                                 continue;
1200                         }
1201
1202                         if (!(mode & aDIR))
1203                                 file_size = get_file_size(sbuf);
1204                         allocation_size = get_allocation_size(conn,NULL,&sbuf);
1205
1206                         mdate_ts = get_mtimespec(&sbuf);
1207                         adate_ts = get_atimespec(&sbuf);
1208                         create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1209
1210                         if (lp_dos_filetime_resolution(SNUM(conn))) {
1211                                 dos_filetime_timespec(&create_date_ts);
1212                                 dos_filetime_timespec(&mdate_ts);
1213                                 dos_filetime_timespec(&adate_ts);
1214                         }
1215
1216                         create_date = convert_timespec_to_time_t(create_date_ts);
1217                         mdate = convert_timespec_to_time_t(mdate_ts);
1218                         adate = convert_timespec_to_time_t(adate_ts);
1219                         
1220                         DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1221           
1222                         found = True;
1223
1224                         dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1225                 }
1226         }
1227
1228         mangle_map(fname,False,True,conn->params);
1229
1230         p = pdata;
1231         last_entry_ptr = p;
1232
1233         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1234
1235         switch (info_level) {
1236                 case SMB_FIND_INFO_STANDARD:
1237                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1238                         if(requires_resume_key) {
1239                                 SIVAL(p,0,reskey);
1240                                 p += 4;
1241                         }
1242                         srv_put_dos_date2(p,0,create_date);
1243                         srv_put_dos_date2(p,4,adate);
1244                         srv_put_dos_date2(p,8,mdate);
1245                         SIVAL(p,12,(uint32)file_size);
1246                         SIVAL(p,16,(uint32)allocation_size);
1247                         SSVAL(p,20,mode);
1248                         p += 23;
1249                         nameptr = p;
1250                         p += align_string(outbuf, p, 0);
1251                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1252                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1253                                 if (len > 2) {
1254                                         SCVAL(nameptr, -1, len - 2);
1255                                 } else {
1256                                         SCVAL(nameptr, -1, 0);
1257                                 }
1258                         } else {
1259                                 if (len > 1) {
1260                                         SCVAL(nameptr, -1, len - 1);
1261                                 } else {
1262                                         SCVAL(nameptr, -1, 0);
1263                                 }
1264                         }
1265                         p += len;
1266                         break;
1267
1268                 case SMB_FIND_EA_SIZE:
1269                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1270                         if(requires_resume_key) {
1271                                 SIVAL(p,0,reskey);
1272                                 p += 4;
1273                         }
1274                         srv_put_dos_date2(p,0,create_date);
1275                         srv_put_dos_date2(p,4,adate);
1276                         srv_put_dos_date2(p,8,mdate);
1277                         SIVAL(p,12,(uint32)file_size);
1278                         SIVAL(p,16,(uint32)allocation_size);
1279                         SSVAL(p,20,mode);
1280                         {
1281                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1282                                 SIVAL(p,22,ea_size); /* Extended attributes */
1283                         }
1284                         p += 27;
1285                         nameptr = p - 1;
1286                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1287                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1288                                 if (len > 2) {
1289                                         len -= 2;
1290                                 } else {
1291                                         len = 0;
1292                                 }
1293                         } else {
1294                                 if (len > 1) {
1295                                         len -= 1;
1296                                 } else {
1297                                         len = 0;
1298                                 }
1299                         }
1300                         SCVAL(nameptr,0,len);
1301                         p += len;
1302                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1303                         break;
1304
1305                 case SMB_FIND_EA_LIST:
1306                 {
1307                         struct ea_list *file_list = NULL;
1308                         size_t ea_len = 0;
1309
1310                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1311                         if (!name_list) {
1312                                 return False;
1313                         }
1314                         if(requires_resume_key) {
1315                                 SIVAL(p,0,reskey);
1316                                 p += 4;
1317                         }
1318                         srv_put_dos_date2(p,0,create_date);
1319                         srv_put_dos_date2(p,4,adate);
1320                         srv_put_dos_date2(p,8,mdate);
1321                         SIVAL(p,12,(uint32)file_size);
1322                         SIVAL(p,16,(uint32)allocation_size);
1323                         SSVAL(p,20,mode);
1324                         p += 22; /* p now points to the EA area. */
1325
1326                         file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1327                         name_list = ea_list_union(name_list, file_list, &ea_len);
1328
1329                         /* We need to determine if this entry will fit in the space available. */
1330                         /* Max string size is 255 bytes. */
1331                         if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1332                                 /* Move the dirptr back to prev_dirpos */
1333                                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1334                                 *out_of_space = True;
1335                                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1336                                 return False; /* Not finished - just out of space */
1337                         }
1338
1339                         /* Push the ea_data followed by the name. */
1340                         p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1341                         nameptr = p;
1342                         len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1343                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1344                                 if (len > 2) {
1345                                         len -= 2;
1346                                 } else {
1347                                         len = 0;
1348                                 }
1349                         } else {
1350                                 if (len > 1) {
1351                                         len -= 1;
1352                                 } else {
1353                                         len = 0;
1354                                 }
1355                         }
1356                         SCVAL(nameptr,0,len);
1357                         p += len + 1;
1358                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1359                         break;
1360                 }
1361
1362                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1363                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1364                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1365                         p += 4;
1366                         SIVAL(p,0,reskey); p += 4;
1367                         put_long_date_timespec(p,create_date_ts); p += 8;
1368                         put_long_date_timespec(p,adate_ts); p += 8;
1369                         put_long_date_timespec(p,mdate_ts); p += 8;
1370                         put_long_date_timespec(p,mdate_ts); p += 8;
1371                         SOFF_T(p,0,file_size); p += 8;
1372                         SOFF_T(p,0,allocation_size); p += 8;
1373                         SIVAL(p,0,nt_extmode); p += 4;
1374                         q = p; p += 4; /* q is placeholder for name length. */
1375                         {
1376                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1377                                 SIVAL(p,0,ea_size); /* Extended attributes */
1378                                 p += 4;
1379                         }
1380                         /* Clear the short name buffer. This is
1381                          * IMPORTANT as not doing so will trigger
1382                          * a Win2k client bug. JRA.
1383                          */
1384                         if (!was_8_3 && check_mangled_names) {
1385                                 pstring mangled_name;
1386                                 pstrcpy(mangled_name, fname);
1387                                 mangle_map(mangled_name,True,True,
1388                                            conn->params);
1389                                 mangled_name[12] = 0;
1390                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1391                                 if (len < 24) {
1392                                         memset(p + 2 + len,'\0',24 - len);
1393                                 }
1394                                 SSVAL(p, 0, len);
1395                         } else {
1396                                 memset(p,'\0',26);
1397                         }
1398                         p += 2 + 24;
1399                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1400                         SIVAL(q,0,len);
1401                         p += len;
1402                         SIVAL(p,0,0); /* Ensure any padding is null. */
1403                         len = PTR_DIFF(p, pdata);
1404                         len = (len + 3) & ~3;
1405                         SIVAL(pdata,0,len);
1406                         p = pdata + len;
1407                         break;
1408
1409                 case SMB_FIND_FILE_DIRECTORY_INFO:
1410                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1411                         p += 4;
1412                         SIVAL(p,0,reskey); p += 4;
1413                         put_long_date_timespec(p,create_date_ts); p += 8;
1414                         put_long_date_timespec(p,adate_ts); p += 8;
1415                         put_long_date_timespec(p,mdate_ts); p += 8;
1416                         put_long_date_timespec(p,mdate_ts); p += 8;
1417                         SOFF_T(p,0,file_size); p += 8;
1418                         SOFF_T(p,0,allocation_size); p += 8;
1419                         SIVAL(p,0,nt_extmode); p += 4;
1420                         len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1421                         SIVAL(p,0,len);
1422                         p += 4 + len;
1423                         SIVAL(p,0,0); /* Ensure any padding is null. */
1424                         len = PTR_DIFF(p, pdata);
1425                         len = (len + 3) & ~3;
1426                         SIVAL(pdata,0,len);
1427                         p = pdata + len;
1428                         break;
1429       
1430                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1431                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1432                         p += 4;
1433                         SIVAL(p,0,reskey); p += 4;
1434                         put_long_date_timespec(p,create_date_ts); p += 8;
1435                         put_long_date_timespec(p,adate_ts); p += 8;
1436                         put_long_date_timespec(p,mdate_ts); p += 8;
1437                         put_long_date_timespec(p,mdate_ts); p += 8;
1438                         SOFF_T(p,0,file_size); p += 8;
1439                         SOFF_T(p,0,allocation_size); p += 8;
1440                         SIVAL(p,0,nt_extmode); p += 4;
1441                         q = p; p += 4; /* q is placeholder for name length. */
1442                         {
1443                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1444                                 SIVAL(p,0,ea_size); /* Extended attributes */
1445                                 p +=4;
1446                         }
1447                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1448                         SIVAL(q, 0, len);
1449                         p += len;
1450
1451                         SIVAL(p,0,0); /* Ensure any padding is null. */
1452                         len = PTR_DIFF(p, pdata);
1453                         len = (len + 3) & ~3;
1454                         SIVAL(pdata,0,len);
1455                         p = pdata + len;
1456                         break;
1457
1458                 case SMB_FIND_FILE_NAMES_INFO:
1459                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1460                         p += 4;
1461                         SIVAL(p,0,reskey); p += 4;
1462                         p += 4;
1463                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1464                            acl on a dir (tridge) */
1465                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1466                         SIVAL(p, -4, len);
1467                         p += len;
1468                         SIVAL(p,0,0); /* Ensure any padding is null. */
1469                         len = PTR_DIFF(p, pdata);
1470                         len = (len + 3) & ~3;
1471                         SIVAL(pdata,0,len);
1472                         p = pdata + len;
1473                         break;
1474
1475                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1476                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1477                         p += 4;
1478                         SIVAL(p,0,reskey); p += 4;
1479                         put_long_date_timespec(p,create_date_ts); p += 8;
1480                         put_long_date_timespec(p,adate_ts); p += 8;
1481                         put_long_date_timespec(p,mdate_ts); p += 8;
1482                         put_long_date_timespec(p,mdate_ts); p += 8;
1483                         SOFF_T(p,0,file_size); p += 8;
1484                         SOFF_T(p,0,allocation_size); p += 8;
1485                         SIVAL(p,0,nt_extmode); p += 4;
1486                         q = p; p += 4; /* q is placeholder for name length. */
1487                         {
1488                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1489                                 SIVAL(p,0,ea_size); /* Extended attributes */
1490                                 p +=4;
1491                         }
1492                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1493                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1494                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1495                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1496                         SIVAL(q, 0, len);
1497                         p += len; 
1498                         SIVAL(p,0,0); /* Ensure any padding is null. */
1499                         len = PTR_DIFF(p, pdata);
1500                         len = (len + 3) & ~3;
1501                         SIVAL(pdata,0,len);
1502                         p = pdata + len;
1503                         break;
1504
1505                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1506                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1507                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1508                         p += 4;
1509                         SIVAL(p,0,reskey); p += 4;
1510                         put_long_date_timespec(p,create_date_ts); p += 8;
1511                         put_long_date_timespec(p,adate_ts); p += 8;
1512                         put_long_date_timespec(p,mdate_ts); p += 8;
1513                         put_long_date_timespec(p,mdate_ts); p += 8;
1514                         SOFF_T(p,0,file_size); p += 8;
1515                         SOFF_T(p,0,allocation_size); p += 8;
1516                         SIVAL(p,0,nt_extmode); p += 4;
1517                         q = p; p += 4; /* q is placeholder for name length */
1518                         {
1519                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1520                                 SIVAL(p,0,ea_size); /* Extended attributes */
1521                                 p +=4;
1522                         }
1523                         /* Clear the short name buffer. This is
1524                          * IMPORTANT as not doing so will trigger
1525                          * a Win2k client bug. JRA.
1526                          */
1527                         if (!was_8_3 && check_mangled_names) {
1528                                 pstring mangled_name;
1529                                 pstrcpy(mangled_name, fname);
1530                                 mangle_map(mangled_name,True,True,
1531                                            conn->params);
1532                                 mangled_name[12] = 0;
1533                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1534                                 SSVAL(p, 0, len);
1535                                 if (len < 24) {
1536                                         memset(p + 2 + len,'\0',24 - len);
1537                                 }
1538                                 SSVAL(p, 0, len);
1539                         } else {
1540                                 memset(p,'\0',26);
1541                         }
1542                         p += 26;
1543                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1544                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1545                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1546                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1547                         SIVAL(q,0,len);
1548                         p += len;
1549                         SIVAL(p,0,0); /* Ensure any padding is null. */
1550                         len = PTR_DIFF(p, pdata);
1551                         len = (len + 3) & ~3;
1552                         SIVAL(pdata,0,len);
1553                         p = pdata + len;
1554                         break;
1555
1556                 /* CIFS UNIX Extension. */
1557
1558                 case SMB_FIND_FILE_UNIX:
1559                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1560                         p+= 4;
1561                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1562
1563                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1564                         SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
1565                         p+= 8;
1566
1567                         SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1568                         p+= 8;
1569
1570                         put_long_date_timespec(p,get_ctimespec(&sbuf));       /* Inode change Time 64 Bit */
1571                         put_long_date_timespec(p+8,get_atimespec(&sbuf));     /* Last access time 64 Bit */
1572                         put_long_date_timespec(p+16,get_mtimespec(&sbuf));    /* Last modification time 64 Bit */
1573                         p+= 24;
1574
1575                         SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
1576                         SIVAL(p,4,0);
1577                         p+= 8;
1578
1579                         SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
1580                         SIVAL(p,4,0);
1581                         p+= 8;
1582
1583                         SIVAL(p,0,unix_filetype(sbuf.st_mode));
1584                         p+= 4;
1585
1586                         SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
1587                         SIVAL(p,4,0);
1588                         p+= 8;
1589
1590                         SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
1591                         SIVAL(p,4,0);
1592                         p+= 8;
1593
1594                         SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
1595                         p+= 8;
1596
1597                         SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
1598                         SIVAL(p,4,0);
1599                         p+= 8;
1600
1601                         SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
1602                         SIVAL(p,4,0);
1603                         p+= 8;
1604
1605                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1606                         p += len;
1607                         SIVAL(p,0,0); /* Ensure any padding is null. */
1608
1609                         len = PTR_DIFF(p, pdata);
1610                         len = (len + 3) & ~3;
1611                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1612                         p = pdata + len;
1613                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1614
1615                         break;
1616
1617                 default:      
1618                         return(False);
1619         }
1620
1621
1622         if (PTR_DIFF(p,pdata) > space_remaining) {
1623                 /* Move the dirptr back to prev_dirpos */
1624                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1625                 *out_of_space = True;
1626                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1627                 return False; /* Not finished - just out of space */
1628         }
1629
1630         /* Setup the last entry pointer, as an offset from base_data */
1631         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1632         /* Advance the data pointer to the next slot */
1633         *ppdata = p;
1634
1635         return(found);
1636 }
1637
1638 /****************************************************************************
1639  Reply to a TRANS2_FINDFIRST.
1640 ****************************************************************************/
1641
1642 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
1643                                 char **pparams, int total_params, char **ppdata, int total_data,
1644                                 unsigned int max_data_bytes)
1645 {
1646         /* We must be careful here that we don't return more than the
1647                 allowed number of data bytes. If this means returning fewer than
1648                 maxentries then so be it. We assume that the redirector has
1649                 enough room for the fixed number of parameter bytes it has
1650                 requested. */
1651         char *params = *pparams;
1652         char *pdata = *ppdata;
1653         uint32 dirtype = SVAL(params,0);
1654         int maxentries = SVAL(params,2);
1655         uint16 findfirst_flags = SVAL(params,4);
1656         BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1657         BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1658         BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1659         int info_level = SVAL(params,6);
1660         pstring directory;
1661         pstring mask;
1662         char *p;
1663         int last_entry_off=0;
1664         int dptr_num = -1;
1665         int numentries = 0;
1666         int i;
1667         BOOL finished = False;
1668         BOOL dont_descend = False;
1669         BOOL out_of_space = False;
1670         int space_remaining;
1671         BOOL bad_path = False;
1672         BOOL mask_contains_wcard = False;
1673         SMB_STRUCT_STAT sbuf;
1674         TALLOC_CTX *ea_ctx = NULL;
1675         struct ea_list *ea_list = NULL;
1676         NTSTATUS ntstatus = NT_STATUS_OK;
1677
1678         if (total_params < 12) {
1679                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1680         }
1681
1682         *directory = *mask = 0;
1683
1684         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1685 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1686                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1687                 info_level, max_data_bytes));
1688
1689         if (!maxentries) {
1690                 /* W2K3 seems to treat zero as 1. */
1691                 maxentries = 1;
1692         }
1693  
1694         switch (info_level) {
1695                 case SMB_FIND_INFO_STANDARD:
1696                 case SMB_FIND_EA_SIZE:
1697                 case SMB_FIND_EA_LIST:
1698                 case SMB_FIND_FILE_DIRECTORY_INFO:
1699                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1700                 case SMB_FIND_FILE_NAMES_INFO:
1701                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1702                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1703                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1704                         break;
1705                 case SMB_FIND_FILE_UNIX:
1706                         if (!lp_unix_extensions()) {
1707                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1708                         }
1709                         break;
1710                 default:
1711                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1712         }
1713
1714         srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1715         if (!NT_STATUS_IS_OK(ntstatus)) {
1716                 return ERROR_NT(ntstatus);
1717         }
1718
1719         RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1720
1721         unix_convert(directory,conn,0,&bad_path,&sbuf);
1722         if (bad_path) {
1723                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1724         }
1725         if(!check_name(directory,conn)) {
1726                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1727         }
1728
1729         p = strrchr_m(directory,'/');
1730         if(p == NULL) {
1731                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1732                 if((directory[0] == '.') && (directory[1] == '\0')) {
1733                         pstrcpy(mask,"*");
1734                         mask_contains_wcard = True;
1735                 } else {
1736                         pstrcpy(mask,directory);
1737                 }
1738                 pstrcpy(directory,"./");
1739         } else {
1740                 pstrcpy(mask,p+1);
1741                 *p = 0;
1742         }
1743
1744         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1745
1746         if (info_level == SMB_FIND_EA_LIST) {
1747                 uint32 ea_size;
1748
1749                 if (total_data < 4) {
1750                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1751                 }
1752
1753                 ea_size = IVAL(pdata,0);
1754                 if (ea_size != total_data) {
1755                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1756 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1757                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1758                 }
1759
1760                 if (!lp_ea_support(SNUM(conn))) {
1761                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
1762                 }
1763                                                                                                                                                         
1764                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1765                         return ERROR_NT(NT_STATUS_NO_MEMORY);
1766                 }
1767                                                                                                                                                         
1768                 /* Pull out the list of names. */
1769                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1770                 if (!ea_list) {
1771                         talloc_destroy(ea_ctx);
1772                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1773                 }
1774         }
1775
1776         *ppdata = (char *)SMB_REALLOC(
1777                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1778         if(*ppdata == NULL ) {
1779                 talloc_destroy(ea_ctx);
1780                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1781         }
1782         pdata = *ppdata;
1783
1784         /* Realloc the params space */
1785         *pparams = (char *)SMB_REALLOC(*pparams, 10);
1786         if (*pparams == NULL) {
1787                 talloc_destroy(ea_ctx);
1788                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1789         }
1790         params = *pparams;
1791
1792         /* Save the wildcard match and attribs we are using on this directory - 
1793                 needed as lanman2 assumes these are being saved between calls */
1794
1795         dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1796         if (dptr_num < 0) {
1797                 talloc_destroy(ea_ctx);
1798                 return(UNIXERROR(ERRDOS,ERRbadfile));
1799         }
1800
1801         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1802
1803         /* We don't need to check for VOL here as this is returned by 
1804                 a different TRANS2 call. */
1805   
1806         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1807         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1808                 dont_descend = True;
1809     
1810         p = pdata;
1811         space_remaining = max_data_bytes;
1812         out_of_space = False;
1813
1814         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1815                 BOOL got_exact_match = False;
1816
1817                 /* this is a heuristic to avoid seeking the dirptr except when 
1818                         absolutely necessary. It allows for a filename of about 40 chars */
1819                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1820                         out_of_space = True;
1821                         finished = False;
1822                 } else {
1823                         finished = !get_lanman2_dir_entry(conn,
1824                                         inbuf, outbuf,
1825                                         mask,dirtype,info_level,
1826                                         requires_resume_key,dont_descend,
1827                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1828                                         &last_entry_off, ea_list, ea_ctx);
1829                 }
1830
1831                 if (finished && out_of_space)
1832                         finished = False;
1833
1834                 if (!finished && !out_of_space)
1835                         numentries++;
1836
1837                 /*
1838                  * As an optimisation if we know we aren't looking
1839                  * for a wildcard name (ie. the name matches the wildcard exactly)
1840                  * then we can finish on any (first) match.
1841                  * This speeds up large directory searches. JRA.
1842                  */
1843
1844                 if(got_exact_match)
1845                         finished = True;
1846
1847                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1848         }
1849   
1850         talloc_destroy(ea_ctx);
1851
1852         /* Check if we can close the dirptr */
1853         if(close_after_first || (finished && close_if_end)) {
1854                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1855                 dptr_close(&dptr_num);
1856         }
1857
1858         /* 
1859          * If there are no matching entries we must return ERRDOS/ERRbadfile - 
1860          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1861          * the protocol level is less than NT1. Tested with smbclient. JRA.
1862          * This should fix the OS/2 client bug #2335.
1863          */
1864
1865         if(numentries == 0) {
1866                 dptr_close(&dptr_num);
1867                 if (Protocol < PROTOCOL_NT1) {
1868                         return ERROR_DOS(ERRDOS,ERRnofiles);
1869                 } else {
1870                         return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1871                 }
1872         }
1873
1874         /* At this point pdata points to numentries directory entries. */
1875
1876         /* Set up the return parameter block */
1877         SSVAL(params,0,dptr_num);
1878         SSVAL(params,2,numentries);
1879         SSVAL(params,4,finished);
1880         SSVAL(params,6,0); /* Never an EA error */
1881         SSVAL(params,8,last_entry_off);
1882
1883         send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1884
1885         if ((! *directory) && dptr_path(dptr_num))
1886                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1887
1888         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1889                 smb_fn_name(CVAL(inbuf,smb_com)), 
1890                 mask, directory, dirtype, numentries ) );
1891
1892         /* 
1893          * Force a name mangle here to ensure that the
1894          * mask as an 8.3 name is top of the mangled cache.
1895          * The reasons for this are subtle. Don't remove
1896          * this code unless you know what you are doing
1897          * (see PR#13758). JRA.
1898          */
1899
1900         if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1901                 mangle_map(mask, True, True, conn->params);
1902
1903         return(-1);
1904 }
1905
1906 /****************************************************************************
1907  Reply to a TRANS2_FINDNEXT.
1908 ****************************************************************************/
1909
1910 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1911                                         char **pparams, int total_params, char **ppdata, int total_data,
1912                                         unsigned int max_data_bytes)
1913 {
1914         /* We must be careful here that we don't return more than the
1915                 allowed number of data bytes. If this means returning fewer than
1916                 maxentries then so be it. We assume that the redirector has
1917                 enough room for the fixed number of parameter bytes it has
1918                 requested. */
1919         char *params = *pparams;
1920         char *pdata = *ppdata;
1921         int dptr_num = SVAL(params,0);
1922         int maxentries = SVAL(params,2);
1923         uint16 info_level = SVAL(params,4);
1924         uint32 resume_key = IVAL(params,6);
1925         uint16 findnext_flags = SVAL(params,10);
1926         BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1927         BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1928         BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1929         BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1930         BOOL mask_contains_wcard = False;
1931         pstring resume_name;
1932         pstring mask;
1933         pstring directory;
1934         char *p;
1935         uint16 dirtype;
1936         int numentries = 0;
1937         int i, last_entry_off=0;
1938         BOOL finished = False;
1939         BOOL dont_descend = False;
1940         BOOL out_of_space = False;
1941         int space_remaining;
1942         TALLOC_CTX *ea_ctx = NULL;
1943         struct ea_list *ea_list = NULL;
1944         NTSTATUS ntstatus = NT_STATUS_OK;
1945
1946         if (total_params < 12) {
1947                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1948         }
1949
1950         *mask = *directory = *resume_name = 0;
1951
1952         srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1953         if (!NT_STATUS_IS_OK(ntstatus)) {
1954                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1955                    complain (it thinks we're asking for the directory above the shared
1956                    path or an invalid name). Catch this as the resume name is only compared, never used in
1957                    a file access. JRA. */
1958                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1959                         pstrcpy(resume_name, "..");
1960                 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1961                         pstrcpy(resume_name, ".");
1962                 } else {
1963                         return ERROR_NT(ntstatus);
1964                 }
1965         }
1966
1967         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1968 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1969 resume_key = %d resume name = %s continue=%d level = %d\n",
1970                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1971                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1972
1973         if (!maxentries) {
1974                 /* W2K3 seems to treat zero as 1. */
1975                 maxentries = 1;
1976         }
1977
1978         switch (info_level) {
1979                 case SMB_FIND_INFO_STANDARD:
1980                 case SMB_FIND_EA_SIZE:
1981                 case SMB_FIND_EA_LIST:
1982                 case SMB_FIND_FILE_DIRECTORY_INFO:
1983                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1984                 case SMB_FIND_FILE_NAMES_INFO:
1985                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1986                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1987                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1988                         break;
1989                 case SMB_FIND_FILE_UNIX:
1990                         if (!lp_unix_extensions()) {
1991                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1992                         }
1993                         break;
1994                 default:
1995                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1996         }
1997
1998         if (info_level == SMB_FIND_EA_LIST) {
1999                 uint32 ea_size;
2000
2001                 if (total_data < 4) {
2002                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2003                 }
2004
2005                 ea_size = IVAL(pdata,0);
2006                 if (ea_size != total_data) {
2007                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2008 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2009                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2010                 }
2011                                                                                                                                                      
2012                 if (!lp_ea_support(SNUM(conn))) {
2013                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
2014                 }
2015                                                                                                                                                      
2016                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2017                         return ERROR_NT(NT_STATUS_NO_MEMORY);
2018                 }
2019
2020                 /* Pull out the list of names. */
2021                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2022                 if (!ea_list) {
2023                         talloc_destroy(ea_ctx);
2024                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2025                 }
2026         }
2027
2028         *ppdata = (char *)SMB_REALLOC(
2029                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2030         if(*ppdata == NULL) {
2031                 talloc_destroy(ea_ctx);
2032                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2033         }
2034
2035         pdata = *ppdata;
2036
2037         /* Realloc the params space */
2038         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2039         if(*pparams == NULL ) {
2040                 talloc_destroy(ea_ctx);
2041                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2042         }
2043
2044         params = *pparams;
2045
2046         /* Check that the dptr is valid */
2047         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2048                 talloc_destroy(ea_ctx);
2049                 return ERROR_DOS(ERRDOS,ERRnofiles);
2050         }
2051
2052         string_set(&conn->dirpath,dptr_path(dptr_num));
2053
2054         /* Get the wildcard mask from the dptr */
2055         if((p = dptr_wcard(dptr_num))== NULL) {
2056                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2057                 talloc_destroy(ea_ctx);
2058                 return ERROR_DOS(ERRDOS,ERRnofiles);
2059         }
2060
2061         pstrcpy(mask, p);
2062         pstrcpy(directory,conn->dirpath);
2063
2064         /* Get the attr mask from the dptr */
2065         dirtype = dptr_attr(dptr_num);
2066
2067         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2068                 dptr_num, mask, dirtype, 
2069                 (long)conn->dirptr,
2070                 dptr_TellDir(conn->dirptr)));
2071
2072         /* We don't need to check for VOL here as this is returned by 
2073                 a different TRANS2 call. */
2074
2075         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2076         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2077                 dont_descend = True;
2078     
2079         p = pdata;
2080         space_remaining = max_data_bytes;
2081         out_of_space = False;
2082
2083         /* 
2084          * Seek to the correct position. We no longer use the resume key but
2085          * depend on the last file name instead.
2086          */
2087
2088         if(*resume_name && !continue_bit) {
2089                 SMB_STRUCT_STAT st;
2090
2091                 long current_pos = 0;
2092                 /*
2093                  * Remember, mangle_map is called by
2094                  * get_lanman2_dir_entry(), so the resume name
2095                  * could be mangled. Ensure we check the unmangled name.
2096                  */
2097
2098                 if (mangle_is_mangled(resume_name, conn->params)) {
2099                         mangle_check_cache(resume_name, sizeof(resume_name)-1,
2100                                            conn->params);
2101                 }
2102
2103                 /*
2104                  * Fix for NT redirector problem triggered by resume key indexes
2105                  * changing between directory scans. We now return a resume key of 0
2106                  * and instead look for the filename to continue from (also given
2107                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2108                  * findfirst/findnext (as is usual) then the directory pointer
2109                  * should already be at the correct place.
2110                  */
2111
2112                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2113         } /* end if resume_name && !continue_bit */
2114
2115         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2116                 BOOL got_exact_match = False;
2117
2118                 /* this is a heuristic to avoid seeking the dirptr except when 
2119                         absolutely necessary. It allows for a filename of about 40 chars */
2120                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2121                         out_of_space = True;
2122                         finished = False;
2123                 } else {
2124                         finished = !get_lanman2_dir_entry(conn,
2125                                                 inbuf, outbuf,
2126                                                 mask,dirtype,info_level,
2127                                                 requires_resume_key,dont_descend,
2128                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2129                                                 &last_entry_off, ea_list, ea_ctx);
2130                 }
2131
2132                 if (finished && out_of_space)
2133                         finished = False;
2134
2135                 if (!finished && !out_of_space)
2136                         numentries++;
2137
2138                 /*
2139                  * As an optimisation if we know we aren't looking
2140                  * for a wildcard name (ie. the name matches the wildcard exactly)
2141                  * then we can finish on any (first) match.
2142                  * This speeds up large directory searches. JRA.
2143                  */
2144
2145                 if(got_exact_match)
2146                         finished = True;
2147
2148                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2149         }
2150   
2151         talloc_destroy(ea_ctx);
2152
2153         /* Check if we can close the dirptr */
2154         if(close_after_request || (finished && close_if_end)) {
2155                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2156                 dptr_close(&dptr_num); /* This frees up the saved mask */
2157         }
2158
2159         /* Set up the return parameter block */
2160         SSVAL(params,0,numentries);
2161         SSVAL(params,2,finished);
2162         SSVAL(params,4,0); /* Never an EA error */
2163         SSVAL(params,6,last_entry_off);
2164
2165         send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2166
2167         if ((! *directory) && dptr_path(dptr_num))
2168                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2169
2170         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2171                 smb_fn_name(CVAL(inbuf,smb_com)), 
2172                 mask, directory, dirtype, numentries ) );
2173
2174         return(-1);
2175 }
2176
2177 /****************************************************************************
2178  Reply to a TRANS2_QFSINFO (query filesystem info).
2179 ****************************************************************************/
2180
2181 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2182                                         char **pparams, int total_params, char **ppdata, int total_data,
2183                                         unsigned int max_data_bytes)
2184 {
2185         char *pdata = *ppdata;
2186         char *params = *pparams;
2187         uint16 info_level = SVAL(params,0);
2188         int data_len, len;
2189         SMB_STRUCT_STAT st;
2190         char *vname = volume_label(SNUM(conn));
2191         int snum = SNUM(conn);
2192         char *fstype = lp_fstype(SNUM(conn));
2193         int quota_flag = 0;
2194
2195         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2196
2197         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2198                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2199                 return ERROR_DOS(ERRSRV,ERRinvdevice);
2200         }
2201
2202         *ppdata = (char *)SMB_REALLOC(
2203                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2204         if (*ppdata == NULL ) {
2205                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2206         }
2207
2208         pdata = *ppdata;
2209         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2210
2211         switch (info_level) {
2212                 case SMB_INFO_ALLOCATION:
2213                 {
2214                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2215                         data_len = 18;
2216                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2217                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2218                         }
2219
2220                         block_size = lp_block_size(snum);
2221                         if (bsize < block_size) {
2222                                 SMB_BIG_UINT factor = block_size/bsize;
2223                                 bsize = block_size;
2224                                 dsize /= factor;
2225                                 dfree /= factor;
2226                         }
2227                         if (bsize > block_size) {
2228                                 SMB_BIG_UINT factor = bsize/block_size;
2229                                 bsize = block_size;
2230                                 dsize *= factor;
2231                                 dfree *= factor;
2232                         }
2233                         bytes_per_sector = 512;
2234                         sectors_per_unit = bsize/bytes_per_sector;
2235
2236                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2237 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2238                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2239
2240                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2241                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2242                         SIVAL(pdata,l1_cUnit,dsize);
2243                         SIVAL(pdata,l1_cUnitAvail,dfree);
2244                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2245                         break;
2246                 }
2247
2248                 case SMB_INFO_VOLUME:
2249                         /* Return volume name */
2250                         /* 
2251                          * Add volume serial number - hash of a combination of
2252                          * the called hostname and the service name.
2253                          */
2254                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2255                         /*
2256                          * Win2k3 and previous mess this up by sending a name length
2257                          * one byte short. I believe only older clients (OS/2 Win9x) use
2258                          * this call so try fixing this by adding a terminating null to
2259                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2260                          */
2261                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2262                         SCVAL(pdata,l2_vol_cch,len);
2263                         data_len = l2_vol_szVolLabel + len;
2264                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2265                                 (unsigned)st.st_ctime, len, vname));
2266                         break;
2267
2268                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2269                 case SMB_FS_ATTRIBUTE_INFORMATION:
2270
2271
2272 #if defined(HAVE_SYS_QUOTAS)
2273                         quota_flag = FILE_VOLUME_QUOTAS;
2274 #endif
2275
2276                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2277                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2278                                 quota_flag); /* FS ATTRIBUTES */
2279
2280                         SIVAL(pdata,4,255); /* Max filename component length */
2281                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2282                                 and will think we can't do long filenames */
2283                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2284                         SIVAL(pdata,8,len);
2285                         data_len = 12 + len;
2286                         break;
2287
2288                 case SMB_QUERY_FS_LABEL_INFO:
2289                 case SMB_FS_LABEL_INFORMATION:
2290                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2291                         data_len = 4 + len;
2292                         SIVAL(pdata,0,len);
2293                         break;
2294
2295                 case SMB_QUERY_FS_VOLUME_INFO:      
2296                 case SMB_FS_VOLUME_INFORMATION:
2297
2298                         /* 
2299                          * Add volume serial number - hash of a combination of
2300                          * the called hostname and the service name.
2301                          */
2302                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2303                                 (str_checksum(get_local_machine_name())<<16));
2304
2305                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2306                         SIVAL(pdata,12,len);
2307                         data_len = 18+len;
2308                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2309                                 (int)strlen(vname),vname, lp_servicename(snum)));
2310                         break;
2311
2312                 case SMB_QUERY_FS_SIZE_INFO:
2313                 case SMB_FS_SIZE_INFORMATION:
2314                 {
2315                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2316                         data_len = 24;
2317                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2318                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2319                         }
2320                         block_size = lp_block_size(snum);
2321                         if (bsize < block_size) {
2322                                 SMB_BIG_UINT factor = block_size/bsize;
2323                                 bsize = block_size;
2324                                 dsize /= factor;
2325                                 dfree /= factor;
2326                         }
2327                         if (bsize > block_size) {
2328                                 SMB_BIG_UINT factor = bsize/block_size;
2329                                 bsize = block_size;
2330                                 dsize *= factor;
2331                                 dfree *= factor;
2332                         }
2333                         bytes_per_sector = 512;
2334                         sectors_per_unit = bsize/bytes_per_sector;
2335                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2336 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2337                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2338                         SBIG_UINT(pdata,0,dsize);
2339                         SBIG_UINT(pdata,8,dfree);
2340                         SIVAL(pdata,16,sectors_per_unit);
2341                         SIVAL(pdata,20,bytes_per_sector);
2342                         break;
2343                 }
2344
2345                 case SMB_FS_FULL_SIZE_INFORMATION:
2346                 {
2347                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2348                         data_len = 32;
2349                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2350                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2351                         }
2352                         block_size = lp_block_size(snum);
2353                         if (bsize < block_size) {
2354                                 SMB_BIG_UINT factor = block_size/bsize;
2355                                 bsize = block_size;
2356                                 dsize /= factor;
2357                                 dfree /= factor;
2358                         }
2359                         if (bsize > block_size) {
2360                                 SMB_BIG_UINT factor = bsize/block_size;
2361                                 bsize = block_size;
2362                                 dsize *= factor;
2363                                 dfree *= factor;
2364                         }
2365                         bytes_per_sector = 512;
2366                         sectors_per_unit = bsize/bytes_per_sector;
2367                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2368 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2369                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2370                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2371                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2372                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2373                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2374                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2375                         break;
2376                 }
2377
2378                 case SMB_QUERY_FS_DEVICE_INFO:
2379                 case SMB_FS_DEVICE_INFORMATION:
2380                         data_len = 8;
2381                         SIVAL(pdata,0,0); /* dev type */
2382                         SIVAL(pdata,4,0); /* characteristics */
2383                         break;
2384
2385 #ifdef HAVE_SYS_QUOTAS
2386                 case SMB_FS_QUOTA_INFORMATION:
2387                 /* 
2388                  * what we have to send --metze:
2389                  *
2390                  * Unknown1:            24 NULL bytes
2391                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2392                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2393                  * Quota Flags:         2 byte :
2394                  * Unknown3:            6 NULL bytes
2395                  *
2396                  * 48 bytes total
2397                  * 
2398                  * details for Quota Flags:
2399                  * 
2400                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2401                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2402                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2403                  * 0x0001 Enable Quotas: enable quota for this fs
2404                  *
2405                  */
2406                 {
2407                         /* we need to fake up a fsp here,
2408                          * because its not send in this call
2409                          */
2410                         files_struct fsp;
2411                         SMB_NTQUOTA_STRUCT quotas;
2412                         
2413                         ZERO_STRUCT(fsp);
2414                         ZERO_STRUCT(quotas);
2415                         
2416                         fsp.conn = conn;
2417                         fsp.fnum = -1;
2418                         
2419                         /* access check */
2420                         if (current_user.ut.uid != 0) {
2421                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2422                                         lp_servicename(SNUM(conn)),conn->user));
2423                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2424                         }
2425                         
2426                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2427                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2428                                 return ERROR_DOS(ERRSRV,ERRerror);
2429                         }
2430
2431                         data_len = 48;
2432
2433                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2434                 
2435                         /* Unknown1 24 NULL bytes*/
2436                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2437                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2438                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2439                 
2440                         /* Default Soft Quota 8 bytes */
2441                         SBIG_UINT(pdata,24,quotas.softlim);
2442
2443                         /* Default Hard Quota 8 bytes */
2444                         SBIG_UINT(pdata,32,quotas.hardlim);
2445         
2446                         /* Quota flag 2 bytes */
2447                         SSVAL(pdata,40,quotas.qflags);
2448                 
2449                         /* Unknown3 6 NULL bytes */
2450                         SSVAL(pdata,42,0);
2451                         SIVAL(pdata,44,0);
2452                         
2453                         break;
2454                 }
2455 #endif /* HAVE_SYS_QUOTAS */
2456                 case SMB_FS_OBJECTID_INFORMATION:
2457                         data_len = 64;
2458                         break;
2459
2460                 /*
2461                  * Query the version and capabilities of the CIFS UNIX extensions
2462                  * in use.
2463                  */
2464
2465                 case SMB_QUERY_CIFS_UNIX_INFO:
2466                         if (!lp_unix_extensions()) {
2467                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2468                         }
2469                         data_len = 12;
2470                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2471                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2472                         /* We have POSIX ACLs, pathname and locking capability. */
2473                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2474                                         CIFS_UNIX_POSIX_ACLS_CAP|
2475                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
2476                                         CIFS_UNIX_FCNTL_LOCKS_CAP)));
2477                         break;
2478
2479                 case SMB_QUERY_POSIX_FS_INFO:
2480                 {
2481                         int rc;
2482                         vfs_statvfs_struct svfs;
2483
2484                         if (!lp_unix_extensions()) {
2485                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2486                         }
2487
2488                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2489
2490                         if (!rc) {
2491                                 data_len = 56;
2492                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2493                                 SIVAL(pdata,4,svfs.BlockSize);
2494                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2495                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2496                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2497                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2498                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2499                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2500                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2501 #ifdef EOPNOTSUPP
2502                         } else if (rc == EOPNOTSUPP) {
2503                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2504 #endif /* EOPNOTSUPP */
2505                         } else {
2506                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2507                                 return ERROR_DOS(ERRSRV,ERRerror);
2508                         }
2509                         break;
2510                 }
2511
2512                 case SMB_MAC_QUERY_FS_INFO:
2513                         /*
2514                          * Thursby MAC extension... ONLY on NTFS filesystems
2515                          * once we do streams then we don't need this
2516                          */
2517                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2518                                 data_len = 88;
2519                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2520                                 break;
2521                         }
2522                         /* drop through */
2523                 default:
2524                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2525         }
2526
2527
2528         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2529
2530         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2531
2532         return -1;
2533 }
2534
2535 /****************************************************************************
2536  Reply to a TRANS2_SETFSINFO (set filesystem info).
2537 ****************************************************************************/
2538
2539 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2540                                         char **pparams, int total_params, char **ppdata, int total_data,
2541                                         unsigned int max_data_bytes)
2542 {
2543         char *pdata = *ppdata;
2544         char *params = *pparams;
2545         uint16 info_level;
2546         int outsize;
2547
2548         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2549
2550         /*  */
2551         if (total_params < 4) {
2552                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2553                         total_params));
2554                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2555         }
2556
2557         info_level = SVAL(params,2);
2558
2559         switch(info_level) {
2560                 case SMB_SET_CIFS_UNIX_INFO:
2561                         {
2562                                 uint16 client_unix_major;
2563                                 uint16 client_unix_minor;
2564                                 uint32 client_unix_cap_low;
2565                                 uint32 client_unix_cap_high;
2566
2567                                 if (!lp_unix_extensions()) {
2568                                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2569                                 }
2570
2571                                 /* There should be 12 bytes of capabilities set. */
2572                                 if (total_data < 8) {
2573                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2574                                 }
2575                                 client_unix_major = SVAL(pdata,0);
2576                                 client_unix_minor = SVAL(pdata,2);
2577                                 client_unix_cap_low = IVAL(pdata,4);
2578                                 client_unix_cap_high = IVAL(pdata,8);
2579                                 /* Just print these values for now. */
2580                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2581 cap_low = 0x%x, cap_high = 0x%x\n",
2582                                         (unsigned int)client_unix_major,
2583                                         (unsigned int)client_unix_minor,
2584                                         (unsigned int)client_unix_cap_low,
2585                                         (unsigned int)client_unix_cap_high ));
2586
2587                                 /* Here is where we must switch to posix pathname processing... */
2588                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2589                                         lp_set_posix_pathnames();
2590                                         mangle_change_to_posix();
2591                                 }
2592
2593                                 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2594                                         lp_set_posix_cifsx_locktype(POSIX_LOCK);
2595                                 }
2596                                 break;
2597                         }
2598                 case SMB_FS_QUOTA_INFORMATION:
2599                         {
2600                                 files_struct *fsp = NULL;
2601                                 SMB_NTQUOTA_STRUCT quotas;
2602         
2603                                 ZERO_STRUCT(quotas);
2604
2605                                 /* access check */
2606                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2607                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2608                                                 lp_servicename(SNUM(conn)),conn->user));
2609                                         return ERROR_DOS(ERRSRV,ERRaccess);
2610                                 }
2611
2612                                 /* note: normaly there're 48 bytes,
2613                                  * but we didn't use the last 6 bytes for now 
2614                                  * --metze 
2615                                  */
2616                                 fsp = file_fsp(params,0);
2617                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2618                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2619                                         return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2620                                 }
2621
2622                                 if (total_data < 42) {
2623                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2624                                                 total_data));
2625                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2626                                 }
2627                         
2628                                 /* unknown_1 24 NULL bytes in pdata*/
2629                 
2630                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2631                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2632 #ifdef LARGE_SMB_OFF_T
2633                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2634 #else /* LARGE_SMB_OFF_T */
2635                                 if ((IVAL(pdata,28) != 0)&&
2636                                         ((quotas.softlim != 0xFFFFFFFF)||
2637                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
2638                                         /* more than 32 bits? */
2639                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2640                                 }
2641 #endif /* LARGE_SMB_OFF_T */
2642                 
2643                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2644                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2645 #ifdef LARGE_SMB_OFF_T
2646                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2647 #else /* LARGE_SMB_OFF_T */
2648                                 if ((IVAL(pdata,36) != 0)&&
2649                                         ((quotas.hardlim != 0xFFFFFFFF)||
2650                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
2651                                         /* more than 32 bits? */
2652                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2653                                 }
2654 #endif /* LARGE_SMB_OFF_T */
2655                 
2656                                 /* quota_flags 2 bytes **/
2657                                 quotas.qflags = SVAL(pdata,40);
2658                 
2659                                 /* unknown_2 6 NULL bytes follow*/
2660                 
2661                                 /* now set the quotas */
2662                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2663                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2664                                         return ERROR_DOS(ERRSRV,ERRerror);
2665                                 }
2666                         
2667                                 break;
2668                         }
2669                 default:
2670                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2671                                 info_level));
2672                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2673                         break;
2674         }
2675
2676         /* 
2677          * sending this reply works fine, 
2678          * but I'm not sure it's the same 
2679          * like windows do...
2680          * --metze
2681          */ 
2682         outsize = set_message(outbuf,10,0,True);
2683
2684         return outsize;
2685 }
2686
2687 /****************************************************************************
2688  Utility function to set bad path error.
2689 ****************************************************************************/
2690
2691 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2692 {
2693         DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2694                         err, (int)bad_path ));
2695
2696         if(err == ENOENT) {
2697                 if (bad_path) {
2698                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2699                 } else {
2700                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2701                 }
2702         }
2703         return UNIXERROR(def_class,def_code);
2704 }
2705
2706 #if defined(HAVE_POSIX_ACLS)
2707 /****************************************************************************
2708  Utility function to count the number of entries in a POSIX acl.
2709 ****************************************************************************/
2710
2711 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2712 {
2713         unsigned int ace_count = 0;
2714         int entry_id = SMB_ACL_FIRST_ENTRY;
2715         SMB_ACL_ENTRY_T entry;
2716
2717         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2718                 /* get_next... */
2719                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2720                         entry_id = SMB_ACL_NEXT_ENTRY;
2721                 }
2722                 ace_count++;
2723         }
2724         return ace_count;
2725 }
2726
2727 /****************************************************************************
2728  Utility function to marshall a POSIX acl into wire format.
2729 ****************************************************************************/
2730
2731 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2732 {
2733         int entry_id = SMB_ACL_FIRST_ENTRY;
2734         SMB_ACL_ENTRY_T entry;
2735
2736         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2737                 SMB_ACL_TAG_T tagtype;
2738                 SMB_ACL_PERMSET_T permset;
2739                 unsigned char perms = 0;
2740                 unsigned int own_grp;
2741
2742                 /* get_next... */
2743                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2744                         entry_id = SMB_ACL_NEXT_ENTRY;
2745                 }
2746
2747                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2748                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2749                         return False;
2750                 }
2751
2752                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2753                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2754                         return False;
2755                 }
2756
2757                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2758                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2759                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2760
2761                 SCVAL(pdata,1,perms);
2762
2763                 switch (tagtype) {
2764                         case SMB_ACL_USER_OBJ:
2765                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2766                                 own_grp = (unsigned int)pst->st_uid;
2767                                 SIVAL(pdata,2,own_grp);
2768                                 SIVAL(pdata,6,0);
2769                                 break;
2770                         case SMB_ACL_USER:
2771                                 {
2772                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2773                                         if (!puid) {
2774                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2775                                         }
2776                                         own_grp = (unsigned int)*puid;
2777                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2778                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2779                                         SIVAL(pdata,2,own_grp);
2780                                         SIVAL(pdata,6,0);
2781                                         break;
2782                                 }
2783                         case SMB_ACL_GROUP_OBJ:
2784                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2785                                 own_grp = (unsigned int)pst->st_gid;
2786                                 SIVAL(pdata,2,own_grp);
2787                                 SIVAL(pdata,6,0);
2788                                 break;
2789                         case SMB_ACL_GROUP:
2790                                 {
2791                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2792                                         if (!pgid) {
2793                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2794                                         }
2795                                         own_grp = (unsigned int)*pgid;
2796                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2797                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2798                                         SIVAL(pdata,2,own_grp);
2799                                         SIVAL(pdata,6,0);
2800                                         break;
2801                                 }
2802                         case SMB_ACL_MASK:
2803                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2804                                 SIVAL(pdata,2,0xFFFFFFFF);
2805                                 SIVAL(pdata,6,0xFFFFFFFF);
2806                                 break;
2807                         case SMB_ACL_OTHER:
2808                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2809                                 SIVAL(pdata,2,0xFFFFFFFF);
2810                                 SIVAL(pdata,6,0xFFFFFFFF);
2811                                 break;
2812                         default:
2813                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2814                                 return False;
2815                 }
2816                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2817         }
2818
2819         return True;
2820 }
2821 #endif
2822
2823 /****************************************************************************
2824  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2825  file name or file id).
2826 ****************************************************************************/
2827
2828 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2829                                         unsigned int tran_call,
2830                                         char **pparams, int total_params, char **ppdata, int total_data,
2831                                         unsigned int max_data_bytes)
2832 {
2833         char *params = *pparams;
2834         char *pdata = *ppdata;
2835         uint16 info_level;
2836         int mode=0;
2837         int nlink;
2838         SMB_OFF_T file_size=0;
2839         SMB_BIG_UINT allocation_size=0;
2840         unsigned int data_size = 0;
2841         unsigned int param_size = 2;
2842         SMB_STRUCT_STAT sbuf;
2843         pstring fname, dos_fname;
2844         char *fullpathname;
2845         char *base_name;
2846         char *p;
2847         SMB_OFF_T pos = 0;
2848         BOOL bad_path = False;
2849         BOOL delete_pending = False;
2850         int len;
2851         time_t create_time, mtime, atime;
2852         struct timespec create_time_ts, mtime_ts, atime_ts;
2853         files_struct *fsp = NULL;
2854         TALLOC_CTX *data_ctx = NULL;
2855         struct ea_list *ea_list = NULL;
2856         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2857         char *lock_data = NULL;
2858
2859         if (!params)
2860                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2861
2862         ZERO_STRUCT(sbuf);
2863
2864         if (tran_call == TRANSACT2_QFILEINFO) {
2865                 if (total_params < 4) {
2866                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2867                 }
2868
2869                 fsp = file_fsp(params,0);
2870                 info_level = SVAL(params,2);
2871
2872                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2873
2874                 if(fsp && (fsp->fake_file_handle)) {
2875                         /*
2876                          * This is actually for the QUOTA_FAKE_FILE --metze
2877                          */
2878                                                 
2879                         pstrcpy(fname, fsp->fsp_name);
2880                         /* We know this name is ok, it's already passed the checks. */
2881                         
2882                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2883                         /*
2884                          * This is actually a QFILEINFO on a directory
2885                          * handle (returned from an NT SMB). NT5.0 seems
2886                          * to do this call. JRA.
2887                          */
2888                         /* We know this name is ok, it's already passed the checks. */
2889                         pstrcpy(fname, fsp->fsp_name);
2890                   
2891                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2892                                 /* Always do lstat for UNIX calls. */
2893                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2894                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2895                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2896                                 }
2897                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2898                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2899                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2900                         }
2901
2902                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2903                 } else {
2904                         /*
2905                          * Original code - this is an open file.
2906                          */
2907                         CHECK_FSP(fsp,conn);
2908
2909                         pstrcpy(fname, fsp->fsp_name);
2910                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2911                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2912                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2913                         }
2914                         pos = fsp->fh->position_information;
2915                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2916                         access_mask = fsp->access_mask;
2917                 }
2918         } else {
2919                 NTSTATUS status = NT_STATUS_OK;
2920
2921                 /* qpathinfo */
2922                 if (total_params < 6) {
2923                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2924                 }
2925
2926                 info_level = SVAL(params,0);
2927
2928                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2929
2930                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2931                 if (!NT_STATUS_IS_OK(status)) {
2932                         return ERROR_NT(status);
2933                 }
2934
2935                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2936
2937                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2938                 if (bad_path) {
2939                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2940                 }
2941                 if (!check_name(fname,conn)) {
2942                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2943                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2944                 }
2945
2946                 if (INFO_LEVEL_IS_UNIX(info_level)) {
2947                         /* Always do lstat for UNIX calls. */
2948                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2949                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2950                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2951                         }
2952                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2953                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2954                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2955                 }
2956
2957                 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2958                 if (delete_pending) {
2959                         return ERROR_NT(NT_STATUS_DELETE_PENDING);
2960                 }
2961         }
2962
2963         nlink = sbuf.st_nlink;
2964
2965         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2966                 /* NTFS does not seem to count ".." */
2967                 nlink -= 1;
2968         }
2969
2970         if ((nlink > 0) && delete_pending) {
2971                 nlink -= 1;
2972         }
2973
2974         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
2975                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2976         }
2977
2978         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2979                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2980
2981         p = strrchr_m(fname,'/'); 
2982         if (!p)
2983                 base_name = fname;
2984         else
2985                 base_name = p+1;
2986
2987         mode = dos_mode(conn,fname,&sbuf);
2988         if (!mode)
2989                 mode = FILE_ATTRIBUTE_NORMAL;
2990
2991         fullpathname = fname;
2992         if (!(mode & aDIR))
2993                 file_size = get_file_size(sbuf);
2994
2995         /* Pull out any data sent here before we realloc. */
2996         switch (info_level) {
2997                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2998                 {
2999                         /* Pull any EA list from the data portion. */
3000                         uint32 ea_size;
3001
3002                         if (total_data < 4) {
3003                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3004                         }
3005                         ea_size = IVAL(pdata,0);
3006
3007                         if (total_data > 0 && ea_size != total_data) {
3008                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3009 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3010                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3011                         }
3012
3013                         if (!lp_ea_support(SNUM(conn))) {
3014                                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3015                         }
3016
3017                         if ((data_ctx = talloc_init("ea_list")) == NULL) {
3018                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3019                         }
3020
3021                         /* Pull out the list of names. */
3022                         ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3023                         if (!ea_list) {
3024                                 talloc_destroy(data_ctx);
3025                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3026                         }
3027                         break;
3028                 }
3029
3030                 case SMB_QUERY_POSIX_LOCK:
3031                 {
3032                         if (fsp == NULL || fsp->fh->fd == -1) {
3033                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3034                         }
3035
3036                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3037                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3038                         }
3039
3040                         if ((data_ctx = talloc_init("lock_request")) == NULL) {
3041                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3042                         }
3043
3044                         /* Copy the lock range data. */
3045                         lock_data = (char *)talloc_memdup(
3046                                 data_ctx, pdata, total_data);
3047                         if (!lock_data) {
3048                                 talloc_destroy(data_ctx);
3049                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3050                         }
3051                 }
3052                 default:
3053                         break;
3054         }
3055
3056         *pparams = (char *)SMB_REALLOC(*pparams,2);
3057         if (*pparams == NULL) {
3058                 talloc_destroy(data_ctx);
3059                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3060         }
3061         params = *pparams;
3062         SSVAL(params,0,0);
3063         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3064         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3065         if (*ppdata == NULL ) {
3066                 talloc_destroy(data_ctx);
3067                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3068         }
3069         pdata = *ppdata;
3070
3071         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3072         mtime_ts = get_mtimespec(&sbuf);
3073         atime_ts = get_atimespec(&sbuf);
3074
3075         allocation_size = get_allocation_size(conn,fsp,&sbuf);
3076
3077         if (fsp) {
3078                 if (fsp->pending_modtime) {
3079                         /* the pending modtime overrides the current modtime */
3080                         mtime_ts.tv_sec = fsp->pending_modtime;
3081                         mtime_ts.tv_nsec = 0;
3082                 }
3083         } else {
3084                 /* Do we have this path open ? */
3085                 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3086                 if (fsp1 && fsp1->pending_modtime) {
3087                         /* the pending modtime overrides the current modtime */
3088                         mtime_ts.tv_sec = fsp1->pending_modtime;
3089                         mtime_ts.tv_nsec = 0;
3090                 }
3091                 if (fsp1 && fsp1->initial_allocation_size) {
3092                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3093                 }
3094         }
3095
3096         if (lp_dos_filetime_resolution(SNUM(conn))) {
3097                 dos_filetime_timespec(&create_time_ts);
3098                 dos_filetime_timespec(&mtime_ts);
3099                 dos_filetime_timespec(&atime_ts);
3100         }
3101
3102         create_time = convert_timespec_to_time_t(create_time_ts);
3103         mtime = convert_timespec_to_time_t(mtime_ts);
3104         atime = convert_timespec_to_time_t(atime_ts);
3105
3106         /* NT expects the name to be in an exact form of the *full*
3107            filename. See the trans2 torture test */
3108         if (strequal(base_name,".")) {
3109                 pstrcpy(dos_fname, "\\");
3110         } else {
3111                 pstr_sprintf(dos_fname, "\\%s", fname);
3112                 string_replace(dos_fname, '/', '\\');
3113         }
3114
3115         switch (info_level) {
3116                 case SMB_INFO_STANDARD:
3117                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3118                         data_size = 22;
3119                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3120                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3121                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3122                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3123                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3124                         SSVAL(pdata,l1_attrFile,mode);
3125                         break;
3126
3127                 case SMB_INFO_QUERY_EA_SIZE:
3128                 {
3129                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3130                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3131                         data_size = 26;
3132                         srv_put_dos_date2(pdata,0,create_time);
3133                         srv_put_dos_date2(pdata,4,atime);
3134                         srv_put_dos_date2(pdata,8,mtime); /* write time */
3135                         SIVAL(pdata,12,(uint32)file_size);
3136                         SIVAL(pdata,16,(uint32)allocation_size);
3137                         SSVAL(pdata,20,mode);
3138                         SIVAL(pdata,22,ea_size);
3139                         break;
3140                 }
3141
3142                 case SMB_INFO_IS_NAME_VALID:
3143                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3144                         if (tran_call == TRANSACT2_QFILEINFO) {
3145                                 /* os/2 needs this ? really ?*/      
3146                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
3147                         }
3148                         data_size = 0;
3149                         param_size = 0;
3150                         break;
3151                         
3152                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3153                 {
3154                         size_t total_ea_len = 0;
3155                         struct ea_list *ea_file_list = NULL;
3156
3157                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3158
3159                         ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3160                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3161
3162                         if (!ea_list || (total_ea_len > data_size)) {
3163                                 talloc_destroy(data_ctx);
3164                                 data_size = 4;
3165                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3166                                 break;
3167                         }
3168
3169                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3170                         talloc_destroy(data_ctx);
3171                         break;
3172                 }
3173
3174                 case SMB_INFO_QUERY_ALL_EAS:
3175                 {
3176                         /* We have data_size bytes to put EA's into. */
3177                         size_t total_ea_len = 0;
3178
3179                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3180
3181                         data_ctx = talloc_init("ea_ctx");
3182                         if (!data_ctx) {
3183                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3184                         }
3185
3186                         ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3187                         if (!ea_list || (total_ea_len > data_size)) {
3188                                 talloc_destroy(data_ctx);
3189                                 data_size = 4;
3190                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3191                                 break;
3192                         }
3193
3194                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3195                         talloc_destroy(data_ctx);
3196                         break;
3197                 }
3198
3199                 case SMB_FILE_BASIC_INFORMATION:
3200                 case SMB_QUERY_FILE_BASIC_INFO:
3201
3202                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3203                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3204                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3205                         } else {
3206                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3207                                 data_size = 40;
3208                                 SIVAL(pdata,36,0);
3209                         }
3210                         put_long_date_timespec(pdata,create_time_ts);
3211                         put_long_date_timespec(pdata+8,atime_ts);
3212                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3213                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3214                         SIVAL(pdata,32,mode);
3215
3216                         DEBUG(5,("SMB_QFBI - "));
3217                         DEBUG(5,("create: %s ", ctime(&create_time)));
3218                         DEBUG(5,("access: %s ", ctime(&atime)));
3219                         DEBUG(5,("write: %s ", ctime(&mtime)));
3220                         DEBUG(5,("change: %s ", ctime(&mtime)));
3221                         DEBUG(5,("mode: %x\n", mode));
3222                         break;
3223
3224                 case SMB_FILE_STANDARD_INFORMATION:
3225                 case SMB_QUERY_FILE_STANDARD_INFO:
3226
3227                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3228                         data_size = 24;
3229                         SOFF_T(pdata,0,allocation_size);
3230                         SOFF_T(pdata,8,file_size);
3231                         SIVAL(pdata,16,nlink);
3232                         SCVAL(pdata,20,delete_pending?1:0);
3233                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3234                         SSVAL(pdata,22,0); /* Padding. */
3235                         break;
3236
3237                 case SMB_FILE_EA_INFORMATION:
3238                 case SMB_QUERY_FILE_EA_INFO:
3239                 {
3240                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3241                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3242                         data_size = 4;
3243                         SIVAL(pdata,0,ea_size);
3244                         break;
3245                 }
3246
3247                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3248                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3249                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3250                 {
3251                         pstring short_name;
3252
3253                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3254                         pstrcpy(short_name,base_name);
3255                         /* Mangle if not already 8.3 */
3256                         if(!mangle_is_8_3(short_name, True, conn->params)) {
3257                                 mangle_map(short_name,True,True,conn->params);
3258                         }
3259                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3260                         data_size = 4 + len;
3261                         SIVAL(pdata,0,len);
3262                         break;
3263                 }
3264
3265                 case SMB_QUERY_FILE_NAME_INFO:
3266                         /*
3267                           this must be *exactly* right for ACLs on mapped drives to work
3268                          */
3269                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3270                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3271                         data_size = 4 + len;
3272                         SIVAL(pdata,0,len);
3273                         break;
3274
3275                 case SMB_FILE_ALLOCATION_INFORMATION:
3276                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3277                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3278                         data_size = 8;
3279                         SOFF_T(pdata,0,allocation_size);
3280                         break;
3281
3282                 case SMB_FILE_END_OF_FILE_INFORMATION:
3283                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3284                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3285                         data_size = 8;
3286                         SOFF_T(pdata,0,file_size);
3287                         break;
3288
3289                 case SMB_QUERY_FILE_ALL_INFO:
3290                 case SMB_FILE_ALL_INFORMATION:
3291                 {
3292                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3293                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3294                         put_long_date_timespec(pdata,create_time_ts);
3295                         put_long_date_timespec(pdata+8,atime_ts);
3296                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3297                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3298                         SIVAL(pdata,32,mode);
3299                         SIVAL(pdata,36,0); /* padding. */
3300                         pdata += 40;
3301                         SOFF_T(pdata,0,allocation_size);
3302                         SOFF_T(pdata,8,file_size);
3303                         SIVAL(pdata,16,nlink);
3304                         SCVAL(pdata,20,delete_pending);
3305                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3306                         SSVAL(pdata,22,0);
3307                         pdata += 24;
3308                         SIVAL(pdata,0,ea_size);
3309                         pdata += 4; /* EA info */
3310                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3311                         SIVAL(pdata,0,len);
3312                         pdata += 4 + len;
3313                         data_size = PTR_DIFF(pdata,(*ppdata));
3314                         break;
3315                 }
3316                 case SMB_FILE_INTERNAL_INFORMATION:
3317                         /* This should be an index number - looks like
3318                            dev/ino to me :-) 
3319
3320                            I think this causes us to fail the IFSKIT
3321                            BasicFileInformationTest. -tpot */
3322
3323                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3324                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3325                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3326                         data_size = 8;
3327                         break;
3328
3329                 case SMB_FILE_ACCESS_INFORMATION:
3330                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3331                         SIVAL(pdata,0,access_mask);
3332                         data_size = 4;
3333                         break;
3334
3335                 case SMB_FILE_NAME_INFORMATION:
3336                         /* Pathname with leading '\'. */
3337                         {
3338                                 size_t byte_len;
3339                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3340                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3341                                 SIVAL(pdata,0,byte_len);
3342                                 data_size = 4 + byte_len;
3343                                 break;
3344                         }
3345
3346                 case SMB_FILE_DISPOSITION_INFORMATION:
3347                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3348                         data_size = 1;
3349                         SCVAL(pdata,0,delete_pending);
3350                         break;
3351
3352                 case SMB_FILE_POSITION_INFORMATION:
3353                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3354                         data_size = 8;
3355                         SOFF_T(pdata,0,pos);
3356                         break;
3357
3358                 case SMB_FILE_MODE_INFORMATION:
3359                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3360                         SIVAL(pdata,0,mode);
3361                         data_size = 4;
3362                         break;
3363
3364                 case SMB_FILE_ALIGNMENT_INFORMATION:
3365                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3366                         SIVAL(pdata,0,0); /* No alignment needed. */
3367                         data_size = 4;
3368                         break;
3369
3370 #if 0
3371                 /*
3372                  * NT4 server just returns "invalid query" to this - if we try to answer
3373                  * it then NTws gets a BSOD! (tridge).
3374                  * W2K seems to want this. JRA.
3375                  */
3376                 case SMB_QUERY_FILE_STREAM_INFO:
3377 #endif
3378                 case SMB_FILE_STREAM_INFORMATION:
3379                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3380                         if (mode & aDIR) {
3381                                 data_size = 0;
3382                         } else {
3383                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3384                                 SIVAL(pdata,0,0); /* ??? */
3385                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3386                                 SOFF_T(pdata,8,file_size);
3387                                 SIVAL(pdata,16,allocation_size);
3388                                 SIVAL(pdata,20,0); /* ??? */
3389                                 data_size = 24 + byte_len;
3390                         }
3391                         break;
3392
3393                 case SMB_QUERY_COMPRESSION_INFO:
3394                 case SMB_FILE_COMPRESSION_INFORMATION:
3395                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3396                         SOFF_T(pdata,0,file_size);
3397                         SIVAL(pdata,8,0); /* ??? */
3398                         SIVAL(pdata,12,0); /* ??? */
3399                         data_size = 16;
3400                         break;
3401
3402                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3403                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3404                         put_long_date_timespec(pdata,create_time_ts);
3405                         put_long_date_timespec(pdata+8,atime_ts);
3406                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3407                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3408                         SIVAL(pdata,32,allocation_size);
3409                         SOFF_T(pdata,40,file_size);
3410                         SIVAL(pdata,48,mode);
3411                         SIVAL(pdata,52,0); /* ??? */
3412                         data_size = 56;
3413                         break;
3414
3415                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3416                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3417                         SIVAL(pdata,0,mode);
3418                         SIVAL(pdata,4,0);
3419                         data_size = 8;
3420                         break;
3421
3422                 /*
3423                  * CIFS UNIX Extensions.
3424                  */
3425
3426                 case SMB_QUERY_FILE_UNIX_BASIC:
3427
3428                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3429                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3430
3431                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
3432                         pdata += 8;
3433
3434                         SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3435                         pdata += 8;
3436
3437                         put_long_date_timespec(pdata,get_ctimespec(&sbuf));       /* Creation Time 64 Bit */
3438                         put_long_date_timespec(pdata+8,get_atimespec(&sbuf));     /* Last access time 64 Bit */
3439                         put_long_date_timespec(pdata+16,get_mtimespec(&sbuf));    /* Last modification time 64 Bit */
3440                         pdata += 24;
3441
3442                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
3443                         SIVAL(pdata,4,0);
3444                         pdata += 8;
3445
3446                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
3447                         SIVAL(pdata,4,0);
3448                         pdata += 8;
3449
3450                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3451                         pdata += 4;
3452
3453                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
3454                         SIVAL(pdata,4,0);
3455                         pdata += 8;
3456
3457                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
3458                         SIVAL(pdata,4,0);
3459                         pdata += 8;
3460
3461                         SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
3462                         pdata += 8;
3463                                 
3464                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
3465                         SIVAL(pdata,4,0);
3466                         pdata += 8;
3467
3468                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
3469                         SIVAL(pdata,4,0);
3470                         pdata += 8;
3471                         data_size = PTR_DIFF(pdata,(*ppdata));
3472
3473                         {
3474                                 int i;
3475                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3476
3477                                 for (i=0; i<100; i++)
3478                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3479                                 DEBUG(4,("\n"));
3480                         }
3481
3482                         break;
3483
3484                 case SMB_QUERY_FILE_UNIX_LINK:
3485                         {
3486                                 pstring buffer;
3487
3488                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3489 #ifdef S_ISLNK
3490                                 if(!S_ISLNK(sbuf.st_mode))
3491                                         return(UNIXERROR(ERRSRV,ERRbadlink));
3492 #else
3493                                 return(UNIXERROR(ERRDOS,ERRbadlink));
3494 #endif
3495                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3496                                 if (len == -1)
3497                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3498                                 buffer[len] = 0;
3499                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3500                                 pdata += len;
3501                                 data_size = PTR_DIFF(pdata,(*ppdata));
3502
3503                                 break;
3504                         }
3505
3506 #if defined(HAVE_POSIX_ACLS)
3507                 case SMB_QUERY_POSIX_ACL:
3508                         {
3509                                 SMB_ACL_T file_acl = NULL;
3510                                 SMB_ACL_T def_acl = NULL;
3511                                 uint16 num_file_acls = 0;
3512                                 uint16 num_def_acls = 0;
3513
3514                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3515                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3516                                 } else {
3517                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3518                                 }
3519
3520                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3521                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3522                                                 fname ));
3523                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3524                                 }
3525
3526                                 if (S_ISDIR(sbuf.st_mode)) {
3527                                         if (fsp && fsp->is_directory) {
3528                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3529                                         } else {
3530                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3531                                         }
3532                                         def_acl = free_empty_sys_acl(conn, def_acl);
3533                                 }
3534
3535                                 num_file_acls = count_acl_entries(conn, file_acl);
3536                                 num_def_acls = count_acl_entries(conn, def_acl);
3537
3538                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3539                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3540                                                 data_size,
3541                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3542                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
3543                                         if (file_acl) {
3544                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3545                                         }
3546                                         if (def_acl) {
3547                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3548                                         }
3549                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3550                                 }
3551
3552                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3553                                 SSVAL(pdata,2,num_file_acls);
3554                                 SSVAL(pdata,4,num_def_acls);
3555                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3556                                         if (file_acl) {
3557                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3558                                         }
3559                                         if (def_acl) {
3560                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3561                                         }
3562                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3563                                 }
3564                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3565                                         if (file_acl) {
3566                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3567                                         }
3568                                         if (def_acl) {
3569                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3570                                         }
3571                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3572                                 }
3573
3574                                 if (file_acl) {
3575                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3576                                 }
3577                                 if (def_acl) {
3578                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3579                                 }
3580                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3581                                 break;
3582                         }
3583 #endif
3584
3585
3586                 case SMB_QUERY_POSIX_LOCK:
3587                 {
3588                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3589                         SMB_BIG_UINT count;
3590                         SMB_BIG_UINT offset;
3591                         uint32 lock_pid;
3592                         enum brl_type lock_type;
3593
3594                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3595                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3596                         }
3597
3598                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3599                                 case POSIX_LOCK_TYPE_READ:
3600                                         lock_type = READ_LOCK;
3601                                         break;
3602                                 case POSIX_LOCK_TYPE_WRITE:
3603                                         lock_type = WRITE_LOCK;
3604                                         break;
3605                                 case POSIX_LOCK_TYPE_UNLOCK:
3606                                 default:
3607                                         /* There's no point in asking for an unlock... */
3608                                         talloc_destroy(data_ctx);
3609                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3610                         }
3611
3612                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3613 #if defined(HAVE_LONGLONG)
3614                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3615                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3616                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3617                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3618 #else /* HAVE_LONGLONG */
3619                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3620                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3621 #endif /* HAVE_LONGLONG */
3622
3623                         status = query_lock(fsp,
3624                                         &lock_pid,
3625                                         &count,
3626                                         &offset,
3627                                         &lock_type,
3628                                         POSIX_LOCK);
3629
3630                         if (ERROR_WAS_LOCK_DENIED(status)) {
3631                                 /* Here we need to report who has it locked... */
3632                                 data_size = POSIX_LOCK_DATA_SIZE;
3633
3634                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3635                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3636                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3637 #if defined(HAVE_LONGLONG)
3638                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3639                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3640                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3641                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3642 #else /* HAVE_LONGLONG */
3643                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3644                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3645 #endif /* HAVE_LONGLONG */
3646
3647                         } else if (NT_STATUS_IS_OK(status)) {
3648                                 /* For success we just return a copy of what we sent
3649                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3650                                 data_size = POSIX_LOCK_DATA_SIZE;
3651                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3652                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3653                         } else {
3654                                 return ERROR_NT(status);
3655                         }
3656                         break;
3657                 }
3658
3659                 default:
3660                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3661         }
3662
3663         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3664
3665         return(-1);
3666 }
3667
3668 /****************************************************************************
3669  Set a hard link (called by UNIX extensions and by NT rename with HARD link
3670  code.
3671 ****************************************************************************/
3672
3673 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3674 {
3675         BOOL bad_path_oldname = False;
3676         BOOL bad_path_newname = False;
3677         SMB_STRUCT_STAT sbuf1, sbuf2;
3678         pstring last_component_oldname;
3679         pstring last_component_newname;
3680         NTSTATUS status = NT_STATUS_OK;
3681
3682         ZERO_STRUCT(sbuf1);
3683         ZERO_STRUCT(sbuf2);
3684
3685         /* No wildcards. */
3686         if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3687                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3688         }
3689
3690         unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3691         if (bad_path_oldname) {
3692                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3693         }
3694
3695         /* Quick check for "." and ".." */
3696         if (last_component_oldname[0] == '.') {
3697                 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3698                         return NT_STATUS_OBJECT_NAME_INVALID;
3699                 }
3700         }
3701
3702         /* source must already exist. */
3703         if (!VALID_STAT(sbuf1)) {
3704                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3705         }
3706
3707         if (!check_name(oldname,conn)) {
3708                 return NT_STATUS_ACCESS_DENIED;
3709         }
3710
3711         unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3712         if (bad_path_newname) {
3713                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3714         }
3715
3716         /* Quick check for "." and ".." */
3717         if (last_component_newname[0] == '.') {
3718                 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3719                         return NT_STATUS_OBJECT_NAME_INVALID;
3720                 }
3721         }
3722
3723         /* Disallow if newname already exists. */
3724         if (VALID_STAT(sbuf2)) {
3725                 return NT_STATUS_OBJECT_NAME_COLLISION;
3726         }
3727
3728         if (!check_name(newname,conn)) {
3729                 return NT_STATUS_ACCESS_DENIED;
3730         }
3731
3732         /* No links from a directory. */
3733         if (S_ISDIR(sbuf1.st_mode)) {
3734                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3735         }
3736
3737         /* Ensure this is within the share. */
3738         if (!reduce_name(conn, oldname) != 0)
3739                 return NT_STATUS_ACCESS_DENIED;
3740
3741         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3742
3743         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3744                 status = map_nt_error_from_unix(errno);
3745                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3746                                 nt_errstr(status), newname, oldname));
3747         }
3748
3749         return status;
3750 }
3751
3752 /****************************************************************************
3753  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3754 ****************************************************************************/
3755
3756 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3757                                         unsigned int tran_call,
3758                                         char **pparams, int total_params, char **ppdata, int total_data,
3759                                         unsigned int max_data_bytes)
3760 {
3761         char *params = *pparams;
3762         char *pdata = *ppdata;
3763         uint16 info_level;
3764         int dosmode=0;
3765         SMB_OFF_T size=0;
3766         struct utimbuf tvs;
3767         SMB_STRUCT_STAT sbuf;
3768         pstring fname;
3769         int fd = -1;
3770         BOOL bad_path = False;
3771         files_struct *fsp = NULL;
3772         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3773         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3774         mode_t unixmode = 0;
3775         NTSTATUS status = NT_STATUS_OK;
3776
3777         if (!params)
3778                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3779
3780         ZERO_STRUCT(sbuf);
3781         ZERO_STRUCT(tvs);
3782
3783         if (tran_call == TRANSACT2_SETFILEINFO) {
3784                 if (total_params < 4) {
3785                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3786                 }
3787
3788                 fsp = file_fsp(params,0);
3789                 info_level = SVAL(params,2);    
3790
3791                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3792                         /*
3793                          * This is actually a SETFILEINFO on a directory
3794                          * handle (returned from an NT SMB). NT5.0 seems
3795                          * to do this call. JRA.
3796                          */
3797                         pstrcpy(fname, fsp->fsp_name);
3798                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3799                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3800                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3801                         }
3802                 } else if (fsp && fsp->print_file) {
3803                         /*
3804                          * Doing a DELETE_ON_CLOSE should cancel a print job.
3805                          */
3806                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3807                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3808
3809                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3810         
3811                                 SSVAL(params,0,0);
3812                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
3813                                 return(-1);
3814                         } else
3815                                 return (UNIXERROR(ERRDOS,ERRbadpath));
3816             } else {
3817                         /*
3818                          * Original code - this is an open file.
3819                          */
3820                         CHECK_FSP(fsp,conn);
3821
3822                         pstrcpy(fname, fsp->fsp_name);
3823                         fd = fsp->fh->fd;
3824
3825                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3826                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3827                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3828                         }
3829                 }
3830         } else {
3831                 /* set path info */
3832                 if (total_params < 6) {
3833                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3834                 }
3835
3836                 info_level = SVAL(params,0);    
3837                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
3838                 if (!NT_STATUS_IS_OK(status)) {
3839                         return ERROR_NT(status);
3840                 }
3841                 unix_convert(fname,conn,0,&bad_path,&sbuf);
3842                 if (bad_path) {
3843                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3844                 }
3845
3846                 /*
3847                  * For CIFS UNIX extensions the target name may not exist.
3848                  */
3849
3850                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3851                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3852                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3853                 }    
3854
3855                 if(!check_name(fname, conn)) {
3856                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3857                 }
3858
3859         }
3860
3861         if (!CAN_WRITE(conn))
3862                 return ERROR_DOS(ERRSRV,ERRaccess);
3863
3864         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3865                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3866         }
3867
3868         if (VALID_STAT(sbuf))
3869                 unixmode = sbuf.st_mode;
3870
3871         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3872                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3873
3874         /* Realloc the parameter size */
3875         *pparams = (char *)SMB_REALLOC(*pparams,2);
3876         if (*pparams == NULL) {
3877                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3878         }
3879         params = *pparams;
3880
3881         SSVAL(params,0,0);
3882
3883         if (fsp && fsp->pending_modtime) {
3884                 /* the pending modtime overrides the current modtime */
3885                 sbuf.st_mtime = fsp->pending_modtime;
3886         }
3887
3888         size = get_file_size(sbuf);
3889         tvs.modtime = sbuf.st_mtime;
3890         tvs.actime = sbuf.st_atime;
3891         dosmode = dos_mode(conn,fname,&sbuf);
3892         unixmode = sbuf.st_mode;
3893
3894         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3895         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3896
3897         switch (info_level) {
3898                 case SMB_INFO_STANDARD:
3899                 {
3900                         if (total_data < 12) {
3901                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3902                         }
3903
3904                         /* access time */
3905                         tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3906                         /* write time */
3907                         tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3908                         break;
3909                 }
3910
3911                 case SMB_INFO_SET_EA:
3912                 {
3913                         struct ea_list *ea_list = NULL;
3914                         TALLOC_CTX *ctx = NULL;
3915
3916                         if (total_data < 10) {
3917
3918                                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3919                                    length. They seem to have no effect. Bug #3212. JRA */
3920
3921                                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3922                                         /* We're done. We only get EA info in this call. */
3923                                         SSVAL(params,0,0);
3924                                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
3925                                         return(-1);
3926                                 }
3927
3928                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3929                         }
3930
3931                         if (IVAL(pdata,0) > total_data) {
3932                                 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3933                                         IVAL(pdata,0), (unsigned int)total_data));
3934                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3935                         }
3936
3937                         ctx = talloc_init("SMB_INFO_SET_EA");
3938                         if (!ctx) {
3939                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3940                         }
3941                         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3942                         if (!ea_list) {
3943                                 talloc_destroy(ctx);
3944                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3945                         }
3946                         status = set_ea(conn, fsp, fname, ea_list);
3947                         talloc_destroy(ctx);
3948
3949                         if (!NT_STATUS_IS_OK(status)) {
3950                                 return ERROR_NT(status);
3951                         }
3952
3953                         /* We're done. We only get EA info in this call. */
3954                         SSVAL(params,0,0);
3955                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
3956                         return(-1);
3957                 }
3958
3959 #if 0
3960                 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3961                 /* XXXX um, i don't think this is right.
3962                         it's also not in the cifs6.txt spec.
3963                 */
3964                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3965                         if (total_data < 28)
3966                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3967
3968                         tvs.actime = make_unix_date2(pdata+8);
3969                         tvs.modtime = make_unix_date2(pdata+12);
3970                         size = IVAL(pdata,16);
3971                         dosmode = IVAL(pdata,24);
3972                         break;
3973
3974                 /* XXXX nor this.  not in cifs6.txt, either. */
3975                 case SMB_INFO_QUERY_ALL_EAS:
3976                         if (total_data < 28)
3977                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3978
3979                         tvs.actime = make_unix_date2(pdata+8);
3980                         tvs.modtime = make_unix_date2(pdata+12);
3981                         size = IVAL(pdata,16);
3982                         dosmode = IVAL(pdata,24);
3983                         break;
3984 #endif
3985
3986                 case SMB_SET_FILE_BASIC_INFO:
3987                 case SMB_FILE_BASIC_INFORMATION:
3988                 {
3989                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3990                         time_t write_time;
3991                         time_t changed_time;
3992
3993                         if (total_data < 36) {
3994                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3995                         }
3996
3997                         /* Ignore create time at offset pdata. */
3998
3999                         /* access time */
4000                         tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
4001
4002                         write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
4003                         changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
4004
4005                         tvs.modtime = MIN(write_time, changed_time);
4006
4007                         if (write_time > tvs.modtime && write_time != (time_t)-1) {
4008                                 tvs.modtime = write_time;
4009                         }
4010                         /* Prefer a defined time to an undefined one. */
4011                         if (null_mtime(tvs.modtime)) {
4012                                 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
4013                         }
4014
4015                         /* attributes */
4016                         dosmode = IVAL(pdata,32);
4017                         break;
4018                 }
4019
4020                 case SMB_FILE_ALLOCATION_INFORMATION:
4021                 case SMB_SET_FILE_ALLOCATION_INFO:
4022                 {
4023                         int ret = -1;
4024                         SMB_BIG_UINT allocation_size;
4025
4026                         if (total_data < 8) {
4027                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4028                         }
4029
4030                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4031 #ifdef LARGE_SMB_OFF_T
4032                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4033 #else /* LARGE_SMB_OFF_T */
4034                         if (IVAL(pdata,4) != 0) {
4035                                 /* more than 32 bits? */
4036                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4037                         }
4038 #endif /* LARGE_SMB_OFF_T */
4039                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
4040                                         fname, (double)allocation_size ));
4041
4042                         if (allocation_size) {
4043                                 allocation_size = smb_roundup(conn, allocation_size);
4044                         }
4045
4046                         if(allocation_size != get_file_size(sbuf)) {
4047                                 SMB_STRUCT_STAT new_sbuf;
4048  
4049                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
4050                                         fname, (double)allocation_size ));
4051  
4052                                 if (fd == -1) {
4053                                         files_struct *new_fsp = NULL;
4054  
4055                                         status = open_file_ntcreate(conn, fname, &sbuf,
4056                                                                         FILE_WRITE_DATA,
4057                                                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4058                                                                         FILE_OPEN,
4059                                                                         0,
4060                                                                         FILE_ATTRIBUTE_NORMAL,
4061                                                                         FORCE_OPLOCK_BREAK_TO_NONE,
4062                                                                         NULL, &new_fsp);
4063  
4064                                         if (!NT_STATUS_IS_OK(status)) {
4065                                                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4066                                                         /* We have re-scheduled this call. */
4067                                                         return -1;
4068                                                 }
4069                                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4070                                         }
4071                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
4072                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4073                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4074                                                                         new_fsp->fnum, strerror(errno)));
4075                                                 ret = -1;
4076                                         }
4077                                         close_file(new_fsp,NORMAL_CLOSE);
4078                                 } else {
4079                                         ret = vfs_allocate_file_space(fsp, allocation_size);
4080                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4081                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4082                                                                         fsp->fnum, strerror(errno)));
4083                                                 ret = -1;
4084                                         }
4085                                 }
4086                                 if (ret == -1)
4087                                         return ERROR_NT(NT_STATUS_DISK_FULL);
4088
4089                                 /* Allocate can truncate size... */
4090                                 size = get_file_size(new_sbuf);
4091                         }
4092
4093                         break;
4094                 }
4095
4096                 case SMB_FILE_END_OF_FILE_INFORMATION:
4097                 case SMB_SET_FILE_END_OF_FILE_INFO:
4098                 {
4099                         if (total_data < 8) {
4100                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4101                         }
4102
4103                         size = IVAL(pdata,0);
4104 #ifdef LARGE_SMB_OFF_T
4105                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4106 #else /* LARGE_SMB_OFF_T */
4107                         if (IVAL(pdata,4) != 0) {
4108                                 /* more than 32 bits? */
4109                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4110                         }
4111 #endif /* LARGE_SMB_OFF_T */
4112                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4113                         break;
4114                 }
4115
4116                 case SMB_FILE_DISPOSITION_INFORMATION:
4117                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4118                 {
4119                         BOOL delete_on_close;
4120
4121                         if (total_data < 1) {
4122                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4123                         }
4124
4125                         delete_on_close = (CVAL(pdata,0) ? True : False);
4126
4127                         /* Just ignore this set on a path. */
4128                         if (tran_call != TRANSACT2_SETFILEINFO)
4129                                 break;
4130
4131                         if (fsp == NULL)
4132                                 return(UNIXERROR(ERRDOS,ERRbadfid));
4133
4134                         status = can_set_delete_on_close(fsp, delete_on_close,
4135                                                          dosmode);
4136  
4137                         if (!NT_STATUS_IS_OK(status)) {
4138                                 return ERROR_NT(status);
4139                         }
4140
4141                         /* The set is across all open files on this dev/inode pair. */
4142                         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4143                                 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4144                         }
4145
4146                         SSVAL(params,0,0);
4147                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4148                         return(-1);
4149                 }
4150
4151                 case SMB_FILE_POSITION_INFORMATION:
4152                 {
4153                         SMB_BIG_UINT position_information;
4154
4155                         if (total_data < 8) {
4156                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4157                         }
4158
4159                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4160 #ifdef LARGE_SMB_OFF_T
4161                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4162 #else /* LARGE_SMB_OFF_T */
4163                         if (IVAL(pdata,4) != 0) {
4164                                 /* more than 32 bits? */
4165                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4166                         }
4167 #endif /* LARGE_SMB_OFF_T */
4168                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4169                                         fname, (double)position_information ));
4170                         if (fsp) {
4171                                 fsp->fh->position_information = position_information;
4172                         }
4173
4174                         /* We're done. We only get position info in this call. */
4175                         SSVAL(params,0,0);
4176                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4177                         return(-1);
4178                 }
4179
4180                 /* From tridge Samba4 : 
4181                  * MODE_INFORMATION in setfileinfo (I have no
4182                  * idea what "mode information" on a file is - it takes a value of 0,
4183                  * 2, 4 or 6. What could it be?).
4184                  */
4185
4186                 case SMB_FILE_MODE_INFORMATION:
4187                 {
4188                         uint32 mode;
4189
4190                         if (total_data < 4) {
4191                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4192                         }
4193                         mode = IVAL(pdata,0);
4194                         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4195                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4196                         }
4197
4198                         /* We're done. We only get mode info in this call. */
4199                         SSVAL(params,0,0);
4200                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4201                         return(-1);
4202                 }
4203
4204                 /*
4205                  * CIFS UNIX extensions.
4206                  */
4207
4208                 case SMB_SET_FILE_UNIX_BASIC:
4209                 {
4210                         uint32 raw_unixmode;
4211
4212                         if (total_data < 100) {
4213                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4214                         }
4215
4216                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4217                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4218                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
4219 #ifdef LARGE_SMB_OFF_T
4220                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4221 #else /* LARGE_SMB_OFF_T */
4222                                 if (IVAL(pdata,4) != 0) {
4223                                         /* more than 32 bits? */
4224                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4225                                 }
4226 #endif /* LARGE_SMB_OFF_T */
4227                         }
4228                         pdata+=24;          /* ctime & st_blocks are not changed */
4229                         tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata)); /* access_time */
4230                         tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); /* modification_time */
4231                         pdata+=16;
4232                         set_owner = (uid_t)IVAL(pdata,0);
4233                         pdata += 8;
4234                         set_grp = (gid_t)IVAL(pdata,0);
4235                         pdata += 8;
4236                         raw_unixmode = IVAL(pdata,28);
4237                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4238                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
4239
4240                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4241 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4242                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4243
4244                         if (!VALID_STAT(sbuf)) {
4245
4246                                 /*
4247                                  * The only valid use of this is to create character and block
4248                                  * devices, and named pipes. This is deprecated (IMHO) and 
4249                                  * a new info level should be used for mknod. JRA.
4250                                  */
4251
4252                                 uint32 file_type = IVAL(pdata,0);
4253 #if defined(HAVE_MAKEDEV)
4254                                 uint32 dev_major = IVAL(pdata,4);
4255                                 uint32 dev_minor = IVAL(pdata,12);
4256 #endif
4257
4258                                 uid_t myuid = geteuid();
4259                                 gid_t mygid = getegid();
4260                                 SMB_DEV_T dev = (SMB_DEV_T)0;
4261
4262                                 if (tran_call == TRANSACT2_SETFILEINFO)
4263                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4264
4265                                 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4266                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4267                                 }
4268
4269 #if defined(HAVE_MAKEDEV)
4270                                 dev = makedev(dev_major, dev_minor);
4271 #endif
4272
4273                                 /* We can only create as the owner/group we are. */
4274
4275                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4276                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4277                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4278                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4279
4280                                 switch (file_type) {
4281 #if defined(S_IFIFO)
4282                                         case UNIX_TYPE_FIFO:
4283                                                 unixmode |= S_IFIFO;
4284                                                 break;
4285 #endif
4286 #if defined(S_IFSOCK)
4287                                         case UNIX_TYPE_SOCKET:
4288                                                 unixmode |= S_IFSOCK;
4289                                                 break;
4290 #endif
4291 #if defined(S_IFCHR)
4292                                         case UNIX_TYPE_CHARDEV:
4293                                                 unixmode |= S_IFCHR;
4294                                                 break;
4295 #endif
4296 #if defined(S_IFBLK)
4297                                         case UNIX_TYPE_BLKDEV:
4298                                                 unixmode |= S_IFBLK;
4299                                                 break;
4300 #endif
4301                                         default:
4302                                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4303                                 }
4304
4305                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4306 0%o for file %s\n", (double)dev, unixmode, fname ));
4307
4308                                 /* Ok - do the mknod. */
4309                                 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4310                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4311
4312                                 inherit_access_acl(conn, fname, unixmode);
4313
4314                                 SSVAL(params,0,0);
4315                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4316                                 return(-1);
4317                         }
4318
4319                         /*
4320                          * Deal with the UNIX specific mode set.
4321                          */
4322
4323                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4324                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4325                                         (unsigned int)unixmode, fname ));
4326                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4327                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4328                         }
4329
4330                         /*
4331                          * Deal with the UNIX specific uid set.
4332                          */
4333
4334                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4335                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4336                                         (unsigned int)set_owner, fname ));
4337                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4338                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4339                         }
4340
4341                         /*
4342                          * Deal with the UNIX specific gid set.
4343                          */
4344
4345                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4346                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4347                                         (unsigned int)set_owner, fname ));
4348                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4349                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4350                         }
4351                         break;
4352                 }
4353
4354                 case SMB_SET_FILE_UNIX_LINK:
4355                 {
4356                         pstring link_target;
4357                         char *newname = fname;
4358
4359                         /* Set a symbolic link. */
4360                         /* Don't allow this if follow links is false. */
4361
4362                         if (!lp_symlinks(SNUM(conn)))
4363                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4364
4365                         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4366
4367                         /* !widelinks forces the target path to be within the share. */
4368                         /* This means we can interpret the target as a pathname. */
4369                         if (!lp_widelinks(SNUM(conn))) {
4370                                 pstring rel_name;
4371                                 char *last_dirp = NULL;
4372
4373                                 unix_format(link_target);
4374                                 if (*link_target == '/') {
4375                                         /* No absolute paths allowed. */
4376                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4377                                 }
4378                                 pstrcpy(rel_name, newname);
4379                                 last_dirp = strrchr_m(rel_name, '/');
4380                                 if (last_dirp) {
4381                                         last_dirp[1] = '\0';
4382                                 } else {
4383                                         pstrcpy(rel_name, "./");
4384                                 }
4385                                 pstrcat(rel_name, link_target);
4386
4387                                 if (!check_name(rel_name, conn)) {
4388                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4389                                 }
4390                         }
4391
4392                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4393                                 fname, link_target ));
4394
4395                         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4396                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4397                         SSVAL(params,0,0);
4398                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4399                         return(-1);
4400                 }
4401
4402                 case SMB_SET_FILE_UNIX_HLINK:
4403                 {
4404                         pstring oldname;
4405                         char *newname = fname;
4406
4407                         /* Set a hard link. */
4408                         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4409                         if (!NT_STATUS_IS_OK(status)) {
4410                                 return ERROR_NT(status);
4411                         }
4412
4413                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4414                                 fname, oldname));
4415
4416                         status = hardlink_internals(conn, oldname, newname);
4417                         if (!NT_STATUS_IS_OK(status)) {
4418                                 return ERROR_NT(status);
4419                         }
4420
4421                         SSVAL(params,0,0);
4422                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4423                         return(-1);
4424                 }
4425
4426                 case SMB_FILE_RENAME_INFORMATION:
4427                 {
4428                         BOOL overwrite;
4429                         /* uint32 root_fid; */  /* Not used */
4430                         uint32 len;
4431                         pstring newname;
4432                         pstring base_name;
4433                         char *p;
4434
4435                         if (total_data < 12) {
4436                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4437                         }
4438
4439                         overwrite = (CVAL(pdata,0) ? True : False);
4440                         /* root_fid = IVAL(pdata,4); */
4441                         len = IVAL(pdata,8);
4442                         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4443                         if (!NT_STATUS_IS_OK(status)) {
4444                                 return ERROR_NT(status);
4445                         }
4446
4447                         /* Check the new name has no '/' characters. */
4448                         if (strchr_m(newname, '/'))
4449                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4450
4451                         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4452
4453                         /* Create the base directory. */
4454                         pstrcpy(base_name, fname);
4455                         p = strrchr_m(base_name, '/');
4456                         if (p)
4457                                 *p = '\0';
4458                         /* Append the new name. */
4459                         pstrcat(base_name, "/");
4460                         pstrcat(base_name, newname);
4461
4462                         if (fsp) {
4463                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4464                                         fsp->fnum, fsp->fsp_name, base_name ));
4465                                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4466                         } else {
4467                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4468                                         fname, newname ));
4469                                 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4470                         }
4471                         if (!NT_STATUS_IS_OK(status)) {
4472                                 return ERROR_NT(status);
4473                         }
4474                         process_pending_change_notify_queue((time_t)0);
4475                         SSVAL(params,0,0);
4476                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4477                         return(-1);
4478                 }
4479
4480 #if defined(HAVE_POSIX_ACLS)
4481                 case SMB_SET_POSIX_ACL:
4482                 {
4483                         uint16 posix_acl_version;
4484                         uint16 num_file_acls;
4485                         uint16 num_def_acls;
4486                         BOOL valid_file_acls = True;
4487                         BOOL valid_def_acls = True;
4488
4489                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4490                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4491                         }
4492                         posix_acl_version = SVAL(pdata,0);
4493                         num_file_acls = SVAL(pdata,2);
4494                         num_def_acls = SVAL(pdata,4);
4495
4496                         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4497                                 valid_file_acls = False;
4498                                 num_file_acls = 0;
4499                         }
4500
4501                         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4502                                 valid_def_acls = False;
4503                                 num_def_acls = 0;
4504                         }
4505
4506                         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4507                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4508                         }
4509
4510                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4511                                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4512                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4513                         }
4514
4515                         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4516                                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4517                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4518                         }
4519
4520                         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4521                                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
4522                                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4523                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4524                         }
4525
4526                         SSVAL(params,0,0);
4527                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4528                         return(-1);
4529                 }
4530 #endif
4531
4532                 case SMB_SET_POSIX_LOCK:
4533                 {
4534                         SMB_BIG_UINT count;
4535                         SMB_BIG_UINT offset;
4536                         uint32 lock_pid;
4537                         BOOL blocking_lock = False;
4538                         enum brl_type lock_type;
4539
4540                         if (fsp == NULL || fsp->fh->fd == -1) {
4541                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4542                         }
4543
4544                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4545                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4546                         }
4547
4548                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4549                                 case POSIX_LOCK_TYPE_READ:
4550                                         lock_type = READ_LOCK;
4551                                         break;
4552                                 case POSIX_LOCK_TYPE_WRITE:
4553                                         /* Return the right POSIX-mappable error code for files opened read-only. */
4554                                         if (!fsp->can_write) {
4555                                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4556                                         }
4557                                         lock_type = WRITE_LOCK;
4558                                         break;
4559                                 case POSIX_LOCK_TYPE_UNLOCK:
4560                                         lock_type = UNLOCK_LOCK;
4561                                         break;
4562                                 default:
4563                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4564                         }
4565
4566                         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4567                                 blocking_lock = False;
4568                         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4569                                 blocking_lock = True;
4570                         } else {
4571                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4572                         }
4573
4574                         if (!lp_blocking_locks(SNUM(conn))) { 
4575                                 blocking_lock = False;
4576                         }
4577
4578                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4579 #if defined(HAVE_LONGLONG)
4580                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4581                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4582                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4583                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4584 #else /* HAVE_LONGLONG */
4585                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4586                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4587 #endif /* HAVE_LONGLONG */
4588
4589                         if (lock_type == UNLOCK_LOCK) {
4590                                 status = do_unlock(fsp,
4591                                                 lock_pid,
4592                                                 count,
4593                                                 offset,
4594                                                 POSIX_LOCK);
4595                         } else {
4596                                 struct byte_range_lock *br_lck = do_lock(fsp,
4597                                                                         lock_pid,
4598                                                                         count,
4599                                                                         offset,
4600                                                                         lock_type,
4601                                                                         POSIX_LOCK,
4602                                                                         blocking_lock,
4603                                                                         &status);
4604
4605                                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4606                                         /*
4607                                          * A blocking lock was requested. Package up
4608                                          * this smb into a queued request and push it
4609                                          * onto the blocking lock queue.
4610                                          */
4611                                         if(push_blocking_lock_request(br_lck,
4612                                                                 inbuf, length,
4613                                                                 fsp,
4614                                                                 -1, /* infinite timeout. */
4615                                                                 0,
4616                                                                 lock_pid,
4617                                                                 lock_type,
4618                                                                 POSIX_LOCK,
4619                                                                 offset,
4620                                                                 count)) {
4621                                                 TALLOC_FREE(br_lck);
4622                                                 return -1;
4623                                         }
4624                                 }
4625                                 TALLOC_FREE(br_lck);
4626                         }
4627
4628                         if (!NT_STATUS_IS_OK(status)) {
4629                                 return ERROR_NT(status);
4630                         }
4631
4632                         SSVAL(params,0,0);
4633                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4634                         return(-1);
4635                 }
4636
4637                 default:
4638                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4639         }
4640
4641         /* get some defaults (no modifications) if any info is zero or -1. */
4642         if (null_mtime(tvs.actime)) {
4643                 tvs.actime = sbuf.st_atime;
4644         }
4645
4646         if (null_mtime(tvs.modtime)) {
4647                 tvs.modtime = sbuf.st_mtime;
4648         }
4649
4650         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4651         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4652         DEBUG(6,("size: %.0f ", (double)size));
4653
4654         if (dosmode) {
4655                 if (S_ISDIR(sbuf.st_mode))
4656                         dosmode |= aDIR;
4657                 else
4658                         dosmode &= ~aDIR;
4659         }
4660
4661         DEBUG(6,("dosmode: %x\n"  , dosmode));
4662
4663         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4664                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4665                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4666                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4667
4668                 /*
4669                  * Only do this test if we are not explicitly
4670                  * changing the size of a file.
4671                  */
4672                 if (!size)
4673                         size = get_file_size(sbuf);
4674         }
4675
4676         /*
4677          * Try and set the times, size and mode of this file -
4678          * if they are different from the current values
4679          */
4680
4681         /* check the mode isn't different, before changing it */
4682         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4683
4684                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4685
4686                 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4687                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4688                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4689                 }
4690         }
4691
4692         /* Now the size. */
4693         if (size != get_file_size(sbuf)) {
4694
4695                 int ret;
4696
4697                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4698                         fname, (double)size ));
4699
4700                 if (fd == -1) {
4701                         files_struct *new_fsp = NULL;
4702
4703                         status = open_file_ntcreate(conn, fname, &sbuf,
4704                                                 FILE_WRITE_DATA,
4705                                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4706                                                 FILE_OPEN,
4707                                                 0,
4708                                                 FILE_ATTRIBUTE_NORMAL,
4709                                                 FORCE_OPLOCK_BREAK_TO_NONE,
4710                                                 NULL, &new_fsp);
4711         
4712                         if (!NT_STATUS_IS_OK(status)) {
4713                                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4714                                         /* We have re-scheduled this call. */
4715                                         return -1;
4716                                 }
4717                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4718                         }
4719                         ret = vfs_set_filelen(new_fsp, size);
4720                         close_file(new_fsp,NORMAL_CLOSE);
4721                 } else {
4722                         ret = vfs_set_filelen(fsp, size);
4723                 }
4724
4725                 if (ret == -1) {
4726                         return (UNIXERROR(ERRHRD,ERRdiskfull));
4727                 }
4728         }
4729
4730         /*
4731          * Finally the times.
4732          */
4733         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4734                 if(fsp != NULL) {
4735                         /*
4736                          * This was a setfileinfo on an open file.
4737                          * NT does this a lot. We also need to 
4738                          * set the time here, as it can be read by 
4739                          * FindFirst/FindNext and with the patch for bug #2045
4740                          * in smbd/fileio.c it ensures that this timestamp is
4741                          * kept sticky even after a write. We save the request
4742                          * away and will set it on file close and after a write. JRA.
4743                          */
4744
4745                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4746                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4747                                 fsp_set_pending_modtime(fsp, tvs.modtime);
4748                         }
4749
4750                 }
4751                 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4752
4753                 if(file_utime(conn, fname, &tvs)!=0) {
4754                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4755                 }
4756         }
4757
4758         SSVAL(params,0,0);
4759         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4760   
4761         return(-1);
4762 }
4763
4764 /****************************************************************************
4765  Reply to a TRANS2_MKDIR (make directory with extended attributes).
4766 ****************************************************************************/
4767
4768 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4769                                         char **pparams, int total_params, char **ppdata, int total_data,
4770                                         unsigned int max_data_bytes)
4771 {
4772         char *params = *pparams;
4773         char *pdata = *ppdata;
4774         pstring directory;
4775         int ret = -1;
4776         SMB_STRUCT_STAT sbuf;
4777         BOOL bad_path = False;
4778         NTSTATUS status = NT_STATUS_OK;
4779         TALLOC_CTX *ctx = NULL;
4780         struct ea_list *ea_list = NULL;
4781
4782         if (!CAN_WRITE(conn))
4783                 return ERROR_DOS(ERRSRV,ERRaccess);
4784
4785         if (total_params < 4) {
4786                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4787         }
4788
4789         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
4790         if (!NT_STATUS_IS_OK(status)) {
4791                 return ERROR_NT(status);
4792         }
4793
4794         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4795
4796         unix_convert(directory,conn,0,&bad_path,&sbuf);
4797         if (bad_path) {
4798                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4799         }
4800
4801         /* Any data in this call is an EA list. */
4802         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4803                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4804         }
4805
4806         /*
4807          * OS/2 workplace shell seems to send SET_EA requests of "null"
4808          * length (4 bytes containing IVAL 4).
4809          * They seem to have no effect. Bug #3212. JRA.
4810          */
4811
4812         if (total_data != 4) {
4813                 if (total_data < 10) {
4814                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4815                 }
4816
4817                 if (IVAL(pdata,0) > total_data) {
4818                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4819                                 IVAL(pdata,0), (unsigned int)total_data));
4820                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4821                 }
4822
4823                 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4824                 if (!ctx) {
4825                         return ERROR_NT(NT_STATUS_NO_MEMORY);
4826                 }
4827                 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4828                 if (!ea_list) {
4829                         talloc_destroy(ctx);
4830                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4831                 }
4832         } else if (IVAL(pdata,0) != 4) {
4833                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4834         }
4835
4836         if (check_name(directory,conn)) {
4837                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4838         }
4839   
4840         if(ret < 0) {
4841                 talloc_destroy(ctx);
4842                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4843                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4844         }
4845
4846         /* Try and set any given EA. */
4847         if (total_data) {
4848                 status = set_ea(conn, NULL, directory, ea_list);
4849                 talloc_destroy(ctx);
4850                 if (!NT_STATUS_IS_OK(status)) {
4851                         return ERROR_NT(status);
4852                 }
4853         }
4854
4855         /* Realloc the parameter and data sizes */
4856         *pparams = (char *)SMB_REALLOC(*pparams,2);
4857         if(*pparams == NULL) {
4858                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4859         }
4860         params = *pparams;
4861
4862         SSVAL(params,0,0);
4863
4864         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4865   
4866         return(-1);
4867 }
4868
4869 /****************************************************************************
4870  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4871  We don't actually do this - we just send a null response.
4872 ****************************************************************************/
4873
4874 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4875                                         char **pparams, int total_params, char **ppdata, int total_data,
4876                                         unsigned int max_data_bytes)
4877 {
4878         static uint16 fnf_handle = 257;
4879         char *params = *pparams;
4880         uint16 info_level;
4881
4882         if (total_params < 6) {
4883                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4884         }
4885
4886         info_level = SVAL(params,4);
4887         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4888
4889         switch (info_level) {
4890                 case 1:
4891                 case 2:
4892                         break;
4893                 default:
4894                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4895         }
4896
4897         /* Realloc the parameter and data sizes */
4898         *pparams = (char *)SMB_REALLOC(*pparams,6);
4899         if (*pparams == NULL) {
4900                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4901         }
4902         params = *pparams;
4903
4904         SSVAL(params,0,fnf_handle);
4905         SSVAL(params,2,0); /* No changes */
4906         SSVAL(params,4,0); /* No EA errors */
4907
4908         fnf_handle++;
4909
4910         if(fnf_handle == 0)
4911                 fnf_handle = 257;
4912
4913         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
4914   
4915         return(-1);
4916 }
4917
4918 /****************************************************************************
4919  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
4920  changes). Currently this does nothing.
4921 ****************************************************************************/
4922
4923 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4924                                         char **pparams, int total_params, char **ppdata, int total_data,
4925                                         unsigned int max_data_bytes)
4926 {
4927         char *params = *pparams;
4928
4929         DEBUG(3,("call_trans2findnotifynext\n"));
4930
4931         /* Realloc the parameter and data sizes */
4932         *pparams = (char *)SMB_REALLOC(*pparams,4);
4933         if (*pparams == NULL) {
4934                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4935         }
4936         params = *pparams;
4937
4938         SSVAL(params,0,0); /* No changes */
4939         SSVAL(params,2,0); /* No EA errors */
4940
4941         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
4942   
4943         return(-1);
4944 }
4945
4946 /****************************************************************************
4947  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4948 ****************************************************************************/
4949
4950 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4951                                         char **pparams, int total_params, char **ppdata, int total_data,
4952                                         unsigned int max_data_bytes)
4953 {
4954         char *params = *pparams;
4955         pstring pathname;
4956         int reply_size = 0;
4957         int max_referral_level;
4958
4959         DEBUG(10,("call_trans2getdfsreferral\n"));
4960
4961         if (total_params < 2) {
4962                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4963         }
4964
4965         max_referral_level = SVAL(params,0);
4966
4967         if(!lp_host_msdfs())
4968                 return ERROR_DOS(ERRDOS,ERRbadfunc);
4969
4970         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4971         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4972                 return UNIXERROR(ERRDOS,ERRbadfile);
4973     
4974         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4975         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
4976
4977         return(-1);
4978 }
4979
4980 #define LMCAT_SPL       0x53
4981 #define LMFUNC_GETJOBID 0x60
4982
4983 /****************************************************************************
4984  Reply to a TRANS2_IOCTL - used for OS/2 printing.
4985 ****************************************************************************/
4986
4987 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4988                                         char **pparams, int total_params, char **ppdata, int total_data,
4989                                         unsigned int max_data_bytes)
4990 {
4991         char *pdata = *ppdata;
4992         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4993
4994         /* check for an invalid fid before proceeding */
4995         
4996         if (!fsp)                                
4997                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
4998
4999         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5000                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5001                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5002                 if (*ppdata == NULL) {
5003                         return ERROR_NT(NT_STATUS_NO_MEMORY);
5004                 }
5005                 pdata = *ppdata;
5006
5007                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5008                         CAN ACCEPT THIS IN UNICODE. JRA. */
5009
5010                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
5011                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
5012                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
5013                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
5014                 return(-1);
5015         } else {
5016                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5017                 return ERROR_DOS(ERRSRV,ERRerror);
5018         }
5019 }
5020
5021 /****************************************************************************
5022  Reply to a SMBfindclose (stop trans2 directory search).
5023 ****************************************************************************/
5024
5025 int reply_findclose(connection_struct *conn,
5026                     char *inbuf,char *outbuf,int length,int bufsize)
5027 {
5028         int outsize = 0;
5029         int dptr_num=SVALS(inbuf,smb_vwv0);
5030         START_PROFILE(SMBfindclose);
5031
5032         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5033
5034         dptr_close(&dptr_num);
5035
5036         outsize = set_message(outbuf,0,0,False);
5037
5038         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5039
5040         END_PROFILE(SMBfindclose);
5041         return(outsize);
5042 }
5043
5044 /****************************************************************************
5045  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5046 ****************************************************************************/
5047
5048 int reply_findnclose(connection_struct *conn, 
5049                      char *inbuf,char *outbuf,int length,int bufsize)
5050 {
5051         int outsize = 0;
5052         int dptr_num= -1;
5053         START_PROFILE(SMBfindnclose);
5054         
5055         dptr_num = SVAL(inbuf,smb_vwv0);
5056
5057         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5058
5059         /* We never give out valid handles for a 
5060            findnotifyfirst - so any dptr_num is ok here. 
5061            Just ignore it. */
5062
5063         outsize = set_message(outbuf,0,0,False);
5064
5065         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5066
5067         END_PROFILE(SMBfindnclose);
5068         return(outsize);
5069 }
5070
5071 int handle_trans2(connection_struct *conn,
5072                   struct trans_state *state,
5073                   char *inbuf, char *outbuf, int size, int bufsize)
5074 {
5075         int outsize;
5076
5077         if (Protocol >= PROTOCOL_NT1) {
5078                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5079         }
5080
5081         /* Now we must call the relevant TRANS2 function */
5082         switch(state->call)  {
5083         case TRANSACT2_OPEN:
5084         {
5085                 START_PROFILE_NESTED(Trans2_open);
5086                 outsize = call_trans2open(
5087                         conn, inbuf, outbuf, bufsize, 
5088                         &state->param, state->total_param,
5089                         &state->data, state->total_data,
5090                         state->max_data_return);
5091                 END_PROFILE_NESTED(Trans2_open);
5092                 break;
5093         }
5094
5095         case TRANSACT2_FINDFIRST:
5096         {
5097                 START_PROFILE_NESTED(Trans2_findfirst);
5098                 outsize = call_trans2findfirst(
5099                         conn, inbuf, outbuf, bufsize,
5100                         &state->param, state->total_param,
5101                         &state->data, state->total_data,
5102                         state->max_data_return);
5103                 END_PROFILE_NESTED(Trans2_findfirst);
5104                 break;
5105         }
5106
5107         case TRANSACT2_FINDNEXT:
5108         {
5109                 START_PROFILE_NESTED(Trans2_findnext);
5110                 outsize = call_trans2findnext(
5111                         conn, inbuf, outbuf, size, bufsize, 
5112                         &state->param, state->total_param,
5113                         &state->data, state->total_data,
5114                         state->max_data_return);
5115                 END_PROFILE_NESTED(Trans2_findnext);
5116                 break;
5117         }
5118
5119         case TRANSACT2_QFSINFO:
5120         {
5121                 START_PROFILE_NESTED(Trans2_qfsinfo);
5122                 outsize = call_trans2qfsinfo(
5123                         conn, inbuf, outbuf, size, bufsize,
5124                         &state->param, state->total_param,
5125                         &state->data, state->total_data,
5126                         state->max_data_return);
5127                 END_PROFILE_NESTED(Trans2_qfsinfo);
5128             break;
5129         }
5130
5131         case TRANSACT2_SETFSINFO:
5132         {
5133                 START_PROFILE_NESTED(Trans2_setfsinfo);
5134                 outsize = call_trans2setfsinfo(
5135                         conn, inbuf, outbuf, size, bufsize, 
5136                         &state->param, state->total_param,
5137                         &state->data, state->total_data,
5138                         state->max_data_return);
5139                 END_PROFILE_NESTED(Trans2_setfsinfo);
5140                 break;
5141         }
5142
5143         case TRANSACT2_QPATHINFO:
5144         case TRANSACT2_QFILEINFO:
5145         {
5146                 START_PROFILE_NESTED(Trans2_qpathinfo);
5147                 outsize = call_trans2qfilepathinfo(
5148                         conn, inbuf, outbuf, size, bufsize, state->call,
5149                         &state->param, state->total_param,
5150                         &state->data, state->total_data,
5151                         state->max_data_return);
5152                 END_PROFILE_NESTED(Trans2_qpathinfo);
5153                 break;
5154         }
5155
5156         case TRANSACT2_SETPATHINFO:
5157         case TRANSACT2_SETFILEINFO:
5158         {
5159                 START_PROFILE_NESTED(Trans2_setpathinfo);
5160                 outsize = call_trans2setfilepathinfo(
5161                         conn, inbuf, outbuf, size, bufsize, state->call,
5162                         &state->param, state->total_param,
5163                         &state->data, state->total_data,
5164                         state->max_data_return);
5165                 END_PROFILE_NESTED(Trans2_setpathinfo);
5166                 break;
5167         }
5168
5169         case TRANSACT2_FINDNOTIFYFIRST:
5170         {
5171                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5172                 outsize = call_trans2findnotifyfirst(
5173                         conn, inbuf, outbuf, size, bufsize, 
5174                         &state->param, state->total_param,
5175                         &state->data, state->total_data,
5176                         state->max_data_return);
5177                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5178                 break;
5179         }
5180
5181         case TRANSACT2_FINDNOTIFYNEXT:
5182         {
5183                 START_PROFILE_NESTED(Trans2_findnotifynext);
5184                 outsize = call_trans2findnotifynext(
5185                         conn, inbuf, outbuf, size, bufsize, 
5186                         &state->param, state->total_param,
5187                         &state->data, state->total_data,
5188                         state->max_data_return);
5189                 END_PROFILE_NESTED(Trans2_findnotifynext);
5190                 break;
5191         }
5192
5193         case TRANSACT2_MKDIR:
5194         {
5195                 START_PROFILE_NESTED(Trans2_mkdir);
5196                 outsize = call_trans2mkdir(
5197                         conn, inbuf, outbuf, size, bufsize,
5198                         &state->param, state->total_param,
5199                         &state->data, state->total_data,
5200                         state->max_data_return);
5201                 END_PROFILE_NESTED(Trans2_mkdir);
5202                 break;
5203         }
5204
5205         case TRANSACT2_GET_DFS_REFERRAL:
5206         {
5207                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5208                 outsize = call_trans2getdfsreferral(
5209                         conn, inbuf, outbuf, size, bufsize,
5210                         &state->param, state->total_param,
5211                         &state->data, state->total_data,
5212                         state->max_data_return);
5213                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5214                 break;
5215         }
5216
5217         case TRANSACT2_IOCTL:
5218         {
5219                 START_PROFILE_NESTED(Trans2_ioctl);
5220                 outsize = call_trans2ioctl(
5221                         conn, inbuf, outbuf, size, bufsize,
5222                         &state->param, state->total_param,
5223                         &state->data, state->total_data,
5224                         state->max_data_return);
5225                 END_PROFILE_NESTED(Trans2_ioctl);
5226                 break;
5227         }
5228
5229         default:
5230                 /* Error in request */
5231                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5232                 outsize = ERROR_DOS(ERRSRV,ERRerror);
5233         }
5234
5235         return outsize;
5236 }
5237
5238 /****************************************************************************
5239  Reply to a SMBtrans2.
5240  ****************************************************************************/
5241
5242 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5243                  int size, int bufsize)
5244 {
5245         int outsize = 0;
5246         unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5247         unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5248         unsigned int psoff = SVAL(inbuf, smb_psoff);
5249         unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5250         unsigned int tran_call = SVAL(inbuf, smb_setup0);
5251         struct trans_state *state;
5252         NTSTATUS result;
5253
5254         START_PROFILE(SMBtrans2);
5255
5256         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5257         if (!NT_STATUS_IS_OK(result)) {
5258                 DEBUG(2, ("Got invalid trans2 request: %s\n",
5259                           nt_errstr(result)));
5260                 END_PROFILE(SMBtrans2);
5261                 return ERROR_NT(result);
5262         }
5263
5264         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5265             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5266                 END_PROFILE(SMBtrans2);
5267                 return ERROR_DOS(ERRSRV,ERRaccess);
5268         }
5269
5270         if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
5271                 DEBUG(0, ("talloc failed\n"));
5272                 END_PROFILE(SMBtrans2);
5273                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5274         }
5275
5276         state->cmd = SMBtrans2;
5277
5278         state->mid = SVAL(inbuf, smb_mid);
5279         state->vuid = SVAL(inbuf, smb_uid);
5280         state->setup_count = SVAL(inbuf, smb_suwcnt);
5281         state->total_param = SVAL(inbuf, smb_tpscnt);
5282         state->param = NULL;
5283         state->total_data =  SVAL(inbuf, smb_tdscnt);
5284         state->data = NULL;
5285         state->max_param_return = SVAL(inbuf, smb_mprcnt);
5286         state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
5287         state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5288         state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5289         state->one_way = BITSETW(inbuf+smb_vwv5,1);
5290
5291         state->call = tran_call;
5292
5293         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5294            is so as a sanity check */
5295         if (state->setup_count != 1) {
5296                 /*
5297                  * Need to have rc=0 for ioctl to get job id for OS/2.
5298                  *  Network printing will fail if function is not successful.
5299                  *  Similar function in reply.c will be used if protocol
5300                  *  is LANMAN1.0 instead of LM1.2X002.
5301                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
5302                  *  outbuf doesn't have to be set(only job id is used).
5303                  */
5304                 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5305                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5306                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5307                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5308                 } else {
5309                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5310                         DEBUG(2,("Transaction is %d\n",tran_call));
5311                         TALLOC_FREE(state);
5312                         END_PROFILE(SMBtrans2);
5313                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5314                 }
5315         }
5316
5317         if ((dscnt > state->total_data) || (pscnt > state->total_param))
5318                 goto bad_param;
5319
5320         if (state->total_data) {
5321                 /* Can't use talloc here, the core routines do realloc on the
5322                  * params and data. */
5323                 state->data = (char *)SMB_MALLOC(state->total_data);
5324                 if (state->data == NULL) {
5325                         DEBUG(0,("reply_trans2: data malloc fail for %u "
5326                                  "bytes !\n", (unsigned int)state->total_data));
5327                         TALLOC_FREE(state);
5328                         END_PROFILE(SMBtrans2);
5329                         return(ERROR_DOS(ERRDOS,ERRnomem));
5330                 }
5331                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5332                         goto bad_param;
5333                 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5334                     (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5335                         goto bad_param;
5336
5337                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5338         }
5339
5340         if (state->total_param) {
5341                 /* Can't use talloc here, the core routines do realloc on the
5342                  * params and data. */
5343                 state->param = (char *)SMB_MALLOC(state->total_param);
5344                 if (state->param == NULL) {
5345                         DEBUG(0,("reply_trans: param malloc fail for %u "
5346                                  "bytes !\n", (unsigned int)state->total_param));
5347                         SAFE_FREE(state->data);
5348                         TALLOC_FREE(state);
5349                         END_PROFILE(SMBtrans2);
5350                         return(ERROR_DOS(ERRDOS,ERRnomem));
5351                 } 
5352                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5353                         goto bad_param;
5354                 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5355                     (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5356                         goto bad_param;
5357
5358                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5359         }
5360
5361         state->received_data  = dscnt;
5362         state->received_param = pscnt;
5363
5364         if ((state->received_param == state->total_param) &&
5365             (state->received_data == state->total_data)) {
5366
5367                 outsize = handle_trans2(conn, state, inbuf, outbuf,
5368                                         size, bufsize);
5369                 SAFE_FREE(state->data);
5370                 SAFE_FREE(state->param);
5371                 TALLOC_FREE(state);
5372                 END_PROFILE(SMBtrans2);
5373                 return outsize;
5374         }
5375
5376         DLIST_ADD(conn->pending_trans, state);
5377
5378         /* We need to send an interim response then receive the rest
5379            of the parameter/data bytes */
5380         outsize = set_message(outbuf,0,0,False);
5381         show_msg(outbuf);
5382         END_PROFILE(SMBtrans2);
5383         return outsize;
5384
5385   bad_param:
5386
5387         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5388         SAFE_FREE(state->data);
5389         SAFE_FREE(state->param);
5390         TALLOC_FREE(state);
5391         END_PROFILE(SMBtrans2);
5392         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5393 }
5394
5395
5396 /****************************************************************************
5397  Reply to a SMBtranss2
5398  ****************************************************************************/
5399
5400 int reply_transs2(connection_struct *conn,
5401                   char *inbuf,char *outbuf,int size,int bufsize)
5402 {
5403         int outsize = 0;
5404         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5405         struct trans_state *state;
5406
5407         START_PROFILE(SMBtranss2);
5408
5409         show_msg(inbuf);
5410
5411         for (state = conn->pending_trans; state != NULL;
5412              state = state->next) {
5413                 if (state->mid == SVAL(inbuf,smb_mid)) {
5414                         break;
5415                 }
5416         }
5417
5418         if ((state == NULL) || (state->cmd != SMBtrans2)) {
5419                 END_PROFILE(SMBtranss2);
5420                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5421         }
5422
5423         /* Revise state->total_param and state->total_data in case they have
5424            changed downwards */
5425
5426         if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5427                 state->total_param = SVAL(inbuf, smb_tpscnt);
5428         if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5429                 state->total_data = SVAL(inbuf, smb_tdscnt);
5430
5431         pcnt = SVAL(inbuf, smb_spscnt);
5432         poff = SVAL(inbuf, smb_spsoff);
5433         pdisp = SVAL(inbuf, smb_spsdisp);
5434
5435         dcnt = SVAL(inbuf, smb_sdscnt);
5436         doff = SVAL(inbuf, smb_sdsoff);
5437         ddisp = SVAL(inbuf, smb_sdsdisp);
5438
5439         state->received_param += pcnt;
5440         state->received_data += dcnt;
5441                 
5442         if ((state->received_data > state->total_data) ||
5443             (state->received_param > state->total_param))
5444                 goto bad_param;
5445
5446         if (pcnt) {
5447                 if (pdisp+pcnt > state->total_param)
5448                         goto bad_param;
5449                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5450                         goto bad_param;
5451                 if (pdisp > state->total_param)
5452                         goto bad_param;
5453                 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5454                     (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5455                         goto bad_param;
5456                 if (state->param + pdisp < state->param)
5457                         goto bad_param;
5458
5459                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5460                        pcnt);
5461         }
5462
5463         if (dcnt) {
5464                 if (ddisp+dcnt > state->total_data)
5465                         goto bad_param;
5466                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5467                         goto bad_param;
5468                 if (ddisp > state->total_data)
5469                         goto bad_param;
5470                 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5471                     (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5472                         goto bad_param;
5473                 if (state->data + ddisp < state->data)
5474                         goto bad_param;
5475
5476                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5477                        dcnt);      
5478         }
5479
5480         if ((state->received_param < state->total_param) ||
5481             (state->received_data < state->total_data)) {
5482                 END_PROFILE(SMBtranss2);
5483                 return -1;
5484         }
5485
5486         /* construct_reply_common has done us the favor to pre-fill the
5487          * command field with SMBtranss2 which is wrong :-)
5488          */
5489         SCVAL(outbuf,smb_com,SMBtrans2);
5490
5491         outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5492
5493         DLIST_REMOVE(conn->pending_trans, state);
5494         SAFE_FREE(state->data);
5495         SAFE_FREE(state->param);
5496         TALLOC_FREE(state);
5497
5498         if (outsize == 0) {
5499                 END_PROFILE(SMBtranss2);
5500                 return(ERROR_DOS(ERRSRV,ERRnosupport));
5501         }
5502         
5503         END_PROFILE(SMBtranss2);
5504         return(outsize);
5505
5506   bad_param:
5507
5508         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5509         DLIST_REMOVE(conn->pending_trans, state);
5510         SAFE_FREE(state->data);
5511         SAFE_FREE(state->param);
5512         TALLOC_FREE(state);
5513         END_PROFILE(SMBtranss2);
5514         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5515 }