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