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