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