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