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