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