smbd: Use Use smb3posix marshalling in in smbd_marshall_dir_entry()
[Samba.git] / source3 / smbd / smb2_trans2.c
blob2ab8119735a5ed5803b4994c0151a8464a015fa7
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
10 Extensively modified by Andrew Tridgell, 1995
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.
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.
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/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
30 #include "version.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "../librpc/gen_ndr/ndr_smb3posix.h"
37 #include "libcli/security/security.h"
38 #include "trans2.h"
39 #include "auth.h"
40 #include "smbprofile.h"
41 #include "rpc_server/srv_pipe_hnd.h"
42 #include "printing.h"
43 #include "lib/util_ea.h"
44 #include "lib/readdir_attr.h"
45 #include "messages.h"
46 #include "libcli/smb/smb2_posix.h"
47 #include "lib/util/string_wrappers.h"
48 #include "source3/lib/substitute.h"
49 #include "source3/lib/adouble.h"
51 #define DIR_ENTRY_SAFETY_MARGIN 4096
53 static uint32_t generate_volume_serial_number(
54 const struct loadparm_substitution *lp_sub,
55 int snum);
57 /****************************************************************************
58 Check if an open file handle is a symlink.
59 ****************************************************************************/
61 NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
64 if (!VALID_STAT(fsp->fsp_name->st)) {
65 return NT_STATUS_ACCESS_DENIED;
67 if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
68 return NT_STATUS_ACCESS_DENIED;
70 if (fsp_get_pathref_fd(fsp) == -1) {
71 return NT_STATUS_ACCESS_DENIED;
73 return NT_STATUS_OK;
76 NTSTATUS check_access_fsp(struct files_struct *fsp,
77 uint32_t access_mask)
79 if (!fsp->fsp_flags.is_fsa) {
80 return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
81 fsp,
82 false,
83 access_mask);
85 if (!(fsp->access_mask & access_mask)) {
86 return NT_STATUS_ACCESS_DENIED;
88 return NT_STATUS_OK;
91 /********************************************************************
92 Roundup a value to the nearest allocation roundup size boundary.
93 Only do this for Windows clients.
94 ********************************************************************/
96 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
98 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
100 /* Only roundup for Windows clients. */
101 enum remote_arch_types ra_type = get_remote_arch();
102 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
103 val = SMB_ROUNDUP(val,rval);
105 return val;
108 /****************************************************************************
109 Utility functions for dealing with extended attributes.
110 ****************************************************************************/
112 /****************************************************************************
113 Refuse to allow clients to overwrite our private xattrs.
114 ****************************************************************************/
116 bool samba_private_attr_name(const char *unix_ea_name)
118 bool prohibited = false;
120 prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
121 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
122 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
123 prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
124 prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
126 if (prohibited) {
127 return true;
130 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
131 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
132 return true;
134 return false;
137 /****************************************************************************
138 Get one EA value. Fill in a struct ea_struct.
139 ****************************************************************************/
141 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
142 files_struct *fsp,
143 const char *ea_name,
144 struct ea_struct *pea)
146 /* Get the value of this xattr. Max size is 64k. */
147 size_t attr_size = 256;
148 char *val = NULL;
149 ssize_t sizeret;
150 size_t max_xattr_size = 0;
152 if (fsp == NULL) {
153 return NT_STATUS_INVALID_HANDLE;
156 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
158 again:
160 val = talloc_realloc(mem_ctx, val, char, attr_size);
161 if (!val) {
162 return NT_STATUS_NO_MEMORY;
165 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
166 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
167 attr_size = max_xattr_size;
168 goto again;
171 if (sizeret == -1) {
172 return map_nt_error_from_unix(errno);
175 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
176 dump_data(10, (uint8_t *)val, sizeret);
178 pea->flags = 0;
179 if (strnequal(ea_name, "user.", 5)) {
180 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
181 } else {
182 pea->name = talloc_strdup(mem_ctx, ea_name);
184 if (pea->name == NULL) {
185 TALLOC_FREE(val);
186 return NT_STATUS_NO_MEMORY;
188 pea->value.data = (unsigned char *)val;
189 pea->value.length = (size_t)sizeret;
190 return NT_STATUS_OK;
193 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
194 files_struct *fsp,
195 char ***pnames,
196 size_t *pnum_names)
198 char smallbuf[1024];
199 /* Get a list of all xattrs. Max namesize is 64k. */
200 size_t ea_namelist_size = 1024;
201 char *ea_namelist = smallbuf;
202 char *to_free = NULL;
204 char *p;
205 char **names;
206 size_t num_names;
207 ssize_t sizeret = -1;
208 NTSTATUS status;
210 if (pnames) {
211 *pnames = NULL;
213 *pnum_names = 0;
215 if (fsp == NULL) {
217 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
218 * symlink. This is ok, handle it here, by just return no EA's
219 * on a symlink.
221 return NT_STATUS_OK;
224 /* should be the case that fsp != NULL */
225 SMB_ASSERT(fsp != NULL);
227 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
228 ea_namelist_size);
230 if ((sizeret == -1) && (errno == ERANGE)) {
231 ea_namelist_size = 65536;
232 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
233 if (ea_namelist == NULL) {
234 return NT_STATUS_NO_MEMORY;
236 to_free = ea_namelist;
238 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
239 ea_namelist_size);
242 if (sizeret == -1) {
243 status = map_nt_error_from_unix(errno);
244 TALLOC_FREE(to_free);
245 return status;
248 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
250 if (sizeret == 0) {
251 TALLOC_FREE(to_free);
252 return NT_STATUS_OK;
256 * Ensure the result is 0-terminated
259 if (ea_namelist[sizeret-1] != '\0') {
260 TALLOC_FREE(to_free);
261 return NT_STATUS_INTERNAL_ERROR;
265 * count the names
267 num_names = 0;
269 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
270 num_names += 1;
273 *pnum_names = num_names;
275 if (pnames == NULL) {
276 TALLOC_FREE(to_free);
277 return NT_STATUS_OK;
280 names = talloc_array(mem_ctx, char *, num_names);
281 if (names == NULL) {
282 DEBUG(0, ("talloc failed\n"));
283 TALLOC_FREE(to_free);
284 return NT_STATUS_NO_MEMORY;
287 if (ea_namelist == smallbuf) {
288 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
289 if (ea_namelist == NULL) {
290 TALLOC_FREE(names);
291 return NT_STATUS_NO_MEMORY;
293 } else {
294 talloc_steal(names, ea_namelist);
296 ea_namelist = talloc_realloc(names, ea_namelist, char,
297 sizeret);
298 if (ea_namelist == NULL) {
299 TALLOC_FREE(names);
300 return NT_STATUS_NO_MEMORY;
304 num_names = 0;
306 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
307 names[num_names++] = p;
310 *pnames = names;
312 return NT_STATUS_OK;
315 /****************************************************************************
316 Return a linked list of the total EA's. Plus the total size
317 ****************************************************************************/
319 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
320 files_struct *fsp,
321 size_t *pea_total_len,
322 struct ea_list **ea_list)
324 /* Get a list of all xattrs. Max namesize is 64k. */
325 size_t i, num_names;
326 char **names;
327 struct ea_list *ea_list_head = NULL;
328 bool posix_pathnames = false;
329 NTSTATUS status;
331 *pea_total_len = 0;
332 *ea_list = NULL;
334 /* symlink */
335 if (fsp == NULL) {
336 return NT_STATUS_OK;
339 if (!lp_ea_support(SNUM(fsp->conn))) {
340 return NT_STATUS_OK;
343 if (fsp_is_alternate_stream(fsp)) {
344 return NT_STATUS_INVALID_PARAMETER;
347 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
349 status = get_ea_names_from_fsp(talloc_tos(),
350 fsp,
351 &names,
352 &num_names);
354 if (!NT_STATUS_IS_OK(status)) {
355 return status;
358 if (num_names == 0) {
359 return NT_STATUS_OK;
362 for (i=0; i<num_names; i++) {
363 struct ea_list *listp;
364 fstring dos_ea_name;
367 * POSIX EA names are divided into several namespaces by
368 * means of string prefixes. Usually, the system controls
369 * semantics for each namespace, but the 'user' namespace is
370 * available for arbitrary use, which comes closest to
371 * Windows EA semantics. Hence, we map POSIX EAs from the
372 * 'user' namespace to Windows EAs, and just ignore all the
373 * other namespaces. Also, a few specific names in the 'user'
374 * namespace are used by Samba internally. Filter them out as
375 * well, and only present the EAs that are available for
376 * arbitrary use.
378 if (!strnequal(names[i], "user.", 5)
379 || samba_private_attr_name(names[i]))
380 continue;
383 * Filter out any underlying POSIX EA names
384 * that a Windows client can't handle.
386 if (!posix_pathnames &&
387 is_invalid_windows_ea_name(names[i])) {
388 continue;
391 listp = talloc(mem_ctx, struct ea_list);
392 if (listp == NULL) {
393 return NT_STATUS_NO_MEMORY;
396 status = get_ea_value_fsp(listp,
397 fsp,
398 names[i],
399 &listp->ea);
401 if (!NT_STATUS_IS_OK(status)) {
402 TALLOC_FREE(listp);
403 return status;
406 if (listp->ea.value.length == 0) {
408 * We can never return a zero length EA.
409 * Windows reports the EA's as corrupted.
411 TALLOC_FREE(listp);
412 continue;
413 } else if (listp->ea.value.length > 65536) {
415 * SMB clients may report error with file
416 * if large EA is presented to them.
418 DBG_ERR("EA [%s] on file [%s] exceeds "
419 "maximum permitted EA size of 64KiB: %zu\n.",
420 listp->ea.name, fsp_str_dbg(fsp),
421 listp->ea.value.length);
422 TALLOC_FREE(listp);
423 continue;
426 push_ascii_fstring(dos_ea_name, listp->ea.name);
428 *pea_total_len +=
429 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
431 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
432 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
433 (unsigned int)listp->ea.value.length));
435 DLIST_ADD_END(ea_list_head, listp);
439 /* Add on 4 for total length. */
440 if (*pea_total_len) {
441 *pea_total_len += 4;
444 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
445 (unsigned int)*pea_total_len));
447 *ea_list = ea_list_head;
448 return NT_STATUS_OK;
451 /****************************************************************************
452 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
453 that was filled.
454 ****************************************************************************/
456 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
457 connection_struct *conn, struct ea_list *ea_list)
459 unsigned int ret_data_size = 4;
460 char *p = pdata;
462 SMB_ASSERT(total_data_size >= 4);
464 if (!lp_ea_support(SNUM(conn))) {
465 SIVAL(pdata,4,0);
466 return 4;
469 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
470 size_t dos_namelen;
471 fstring dos_ea_name;
472 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
473 dos_namelen = strlen(dos_ea_name);
474 if (dos_namelen > 255 || dos_namelen == 0) {
475 break;
477 if (ea_list->ea.value.length > 65535) {
478 break;
480 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
481 break;
484 /* We know we have room. */
485 SCVAL(p,0,ea_list->ea.flags);
486 SCVAL(p,1,dos_namelen);
487 SSVAL(p,2,ea_list->ea.value.length);
488 strlcpy(p+4, dos_ea_name, dos_namelen+1);
489 if (ea_list->ea.value.length > 0) {
490 memcpy(p + 4 + dos_namelen + 1,
491 ea_list->ea.value.data,
492 ea_list->ea.value.length);
495 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
496 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
499 ret_data_size = PTR_DIFF(p, pdata);
500 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
501 SIVAL(pdata,0,ret_data_size);
502 return ret_data_size;
505 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
506 char *pdata,
507 unsigned int total_data_size,
508 unsigned int *ret_data_size,
509 connection_struct *conn,
510 struct ea_list *ea_list)
512 uint8_t *p = (uint8_t *)pdata;
513 uint8_t *last_start = NULL;
514 bool do_store_data = (pdata != NULL);
516 *ret_data_size = 0;
518 if (!lp_ea_support(SNUM(conn))) {
519 return NT_STATUS_NO_EAS_ON_FILE;
522 for (; ea_list; ea_list = ea_list->next) {
523 size_t dos_namelen;
524 fstring dos_ea_name;
525 size_t this_size;
526 size_t pad = 0;
528 if (last_start != NULL && do_store_data) {
529 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
531 last_start = p;
533 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
534 dos_namelen = strlen(dos_ea_name);
535 if (dos_namelen > 255 || dos_namelen == 0) {
536 return NT_STATUS_INTERNAL_ERROR;
538 if (ea_list->ea.value.length > 65535) {
539 return NT_STATUS_INTERNAL_ERROR;
542 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
544 if (ea_list->next) {
545 pad = (4 - (this_size % 4)) % 4;
546 this_size += pad;
549 if (do_store_data) {
550 if (this_size > total_data_size) {
551 return NT_STATUS_INFO_LENGTH_MISMATCH;
554 /* We know we have room. */
555 SIVAL(p, 0x00, 0); /* next offset */
556 SCVAL(p, 0x04, ea_list->ea.flags);
557 SCVAL(p, 0x05, dos_namelen);
558 SSVAL(p, 0x06, ea_list->ea.value.length);
559 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
560 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
561 if (pad) {
562 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
563 '\0',
564 pad);
566 total_data_size -= this_size;
569 p += this_size;
572 *ret_data_size = PTR_DIFF(p, pdata);
573 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
574 return NT_STATUS_OK;
577 unsigned int estimate_ea_size(files_struct *fsp)
579 size_t total_ea_len = 0;
580 TALLOC_CTX *mem_ctx;
581 struct ea_list *ea_list = NULL;
582 NTSTATUS status;
584 /* symlink */
585 if (fsp == NULL) {
586 return 0;
589 if (!lp_ea_support(SNUM(fsp->conn))) {
590 return 0;
593 mem_ctx = talloc_stackframe();
595 /* If this is a stream fsp, then we need to instead find the
596 * estimated ea len from the main file, not the stream
597 * (streams cannot have EAs), but the estimate isn't just 0 in
598 * this case! */
599 fsp = metadata_fsp(fsp);
600 (void)get_ea_list_from_fsp(mem_ctx,
601 fsp,
602 &total_ea_len,
603 &ea_list);
605 if(fsp->conn->sconn->using_smb2) {
606 unsigned int ret_data_size;
608 * We're going to be using fill_ea_chained_buffer() to
609 * marshall EA's - this size is significantly larger
610 * than the SMB1 buffer. Re-calculate the size without
611 * marshalling.
613 status = fill_ea_chained_buffer(mem_ctx,
614 NULL,
616 &ret_data_size,
617 fsp->conn,
618 ea_list);
619 if (!NT_STATUS_IS_OK(status)) {
620 ret_data_size = 0;
622 total_ea_len = ret_data_size;
624 TALLOC_FREE(mem_ctx);
625 return total_ea_len;
628 /****************************************************************************
629 Ensure the EA name is case insensitive by matching any existing EA name.
630 ****************************************************************************/
632 static void canonicalize_ea_name(files_struct *fsp,
633 fstring unix_ea_name)
635 size_t total_ea_len;
636 TALLOC_CTX *mem_ctx = talloc_tos();
637 struct ea_list *ea_list;
638 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
639 fsp,
640 &total_ea_len,
641 &ea_list);
642 if (!NT_STATUS_IS_OK(status)) {
643 return;
646 for (; ea_list; ea_list = ea_list->next) {
647 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
648 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
649 &unix_ea_name[5], ea_list->ea.name));
650 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
651 break;
656 /****************************************************************************
657 Set or delete an extended attribute.
658 ****************************************************************************/
660 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
661 struct ea_list *ea_list)
663 NTSTATUS status;
664 bool posix_pathnames = false;
666 if (!lp_ea_support(SNUM(conn))) {
667 return NT_STATUS_EAS_NOT_SUPPORTED;
670 if (fsp == NULL) {
671 return NT_STATUS_INVALID_HANDLE;
674 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
676 status = refuse_symlink_fsp(fsp);
677 if (!NT_STATUS_IS_OK(status)) {
678 return status;
681 status = check_access_fsp(fsp, FILE_WRITE_EA);
682 if (!NT_STATUS_IS_OK(status)) {
683 return status;
686 /* Setting EAs on streams isn't supported. */
687 if (fsp_is_alternate_stream(fsp)) {
688 return NT_STATUS_INVALID_PARAMETER;
692 * Filter out invalid Windows EA names - before
693 * we set *any* of them.
696 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
697 return STATUS_INVALID_EA_NAME;
700 for (;ea_list; ea_list = ea_list->next) {
701 int ret;
702 fstring unix_ea_name;
705 * Complementing the forward mapping from POSIX EAs to
706 * Windows EAs in get_ea_list_from_fsp(), here we map in the
707 * opposite direction from Windows EAs to the 'user' namespace
708 * of POSIX EAs. Hence, all POSIX EA names the we set here must
709 * start with a 'user.' prefix.
711 fstrcpy(unix_ea_name, "user.");
712 fstrcat(unix_ea_name, ea_list->ea.name);
714 canonicalize_ea_name(fsp, unix_ea_name);
716 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
718 if (samba_private_attr_name(unix_ea_name)) {
719 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
720 return NT_STATUS_ACCESS_DENIED;
723 if (ea_list->ea.value.length == 0) {
724 /* Remove the attribute. */
725 DBG_DEBUG("deleting ea name %s on "
726 "file %s by file descriptor.\n",
727 unix_ea_name, fsp_str_dbg(fsp));
728 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
729 #ifdef ENOATTR
730 /* Removing a non existent attribute always succeeds. */
731 if (ret == -1 && errno == ENOATTR) {
732 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
733 unix_ea_name));
734 ret = 0;
736 #endif
737 } else {
738 DEBUG(10,("set_ea: setting ea name %s on file "
739 "%s by file descriptor.\n",
740 unix_ea_name, fsp_str_dbg(fsp)));
741 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
742 ea_list->ea.value.data, ea_list->ea.value.length, 0);
745 if (ret == -1) {
746 #ifdef ENOTSUP
747 if (errno == ENOTSUP) {
748 return NT_STATUS_EAS_NOT_SUPPORTED;
750 #endif
751 return map_nt_error_from_unix(errno);
755 return NT_STATUS_OK;
758 /****************************************************************************
759 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
760 ****************************************************************************/
762 struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
764 struct ea_list *ea_list_head = NULL;
765 size_t offset = 0;
766 size_t bytes_used = 0;
768 while (offset < data_size) {
769 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
771 if (!eal) {
772 return NULL;
775 DLIST_ADD_END(ea_list_head, eal);
776 offset += bytes_used;
779 return ea_list_head;
782 /****************************************************************************
783 Count the total EA size needed.
784 ****************************************************************************/
786 static size_t ea_list_size(struct ea_list *ealist)
788 fstring dos_ea_name;
789 struct ea_list *listp;
790 size_t ret = 0;
792 for (listp = ealist; listp; listp = listp->next) {
793 push_ascii_fstring(dos_ea_name, listp->ea.name);
794 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
796 /* Add on 4 for total length. */
797 if (ret) {
798 ret += 4;
801 return ret;
804 /****************************************************************************
805 Return a union of EA's from a file list and a list of names.
806 The TALLOC context for the two lists *MUST* be identical as we steal
807 memory from one list to add to another. JRA.
808 ****************************************************************************/
810 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
812 struct ea_list *nlistp, *flistp;
814 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
815 for (flistp = file_list; flistp; flistp = flistp->next) {
816 if (strequal(nlistp->ea.name, flistp->ea.name)) {
817 break;
821 if (flistp) {
822 /* Copy the data from this entry. */
823 nlistp->ea.flags = flistp->ea.flags;
824 nlistp->ea.value = flistp->ea.value;
825 } else {
826 /* Null entry. */
827 nlistp->ea.flags = 0;
828 ZERO_STRUCT(nlistp->ea.value);
832 *total_ea_len = ea_list_size(name_list);
833 return name_list;
836 /****************************************************************************
837 Return the filetype for UNIX extensions.
838 ****************************************************************************/
840 static uint32_t unix_filetype(mode_t mode)
842 if(S_ISREG(mode))
843 return UNIX_TYPE_FILE;
844 else if(S_ISDIR(mode))
845 return UNIX_TYPE_DIR;
846 #ifdef S_ISLNK
847 else if(S_ISLNK(mode))
848 return UNIX_TYPE_SYMLINK;
849 #endif
850 #ifdef S_ISCHR
851 else if(S_ISCHR(mode))
852 return UNIX_TYPE_CHARDEV;
853 #endif
854 #ifdef S_ISBLK
855 else if(S_ISBLK(mode))
856 return UNIX_TYPE_BLKDEV;
857 #endif
858 #ifdef S_ISFIFO
859 else if(S_ISFIFO(mode))
860 return UNIX_TYPE_FIFO;
861 #endif
862 #ifdef S_ISSOCK
863 else if(S_ISSOCK(mode))
864 return UNIX_TYPE_SOCKET;
865 #endif
867 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
868 return UNIX_TYPE_UNKNOWN;
871 /****************************************************************************
872 Map wire perms onto standard UNIX permissions. Obey share restrictions.
873 ****************************************************************************/
875 NTSTATUS unix_perms_from_wire(connection_struct *conn,
876 const SMB_STRUCT_STAT *psbuf,
877 uint32_t perms,
878 enum perm_type ptype,
879 mode_t *ret_perms)
881 mode_t ret = 0;
883 if (perms == SMB_MODE_NO_CHANGE) {
884 if (!VALID_STAT(*psbuf)) {
885 return NT_STATUS_INVALID_PARAMETER;
886 } else {
887 *ret_perms = psbuf->st_ex_mode;
888 return NT_STATUS_OK;
892 ret = wire_perms_to_unix(perms);
894 if (ptype == PERM_NEW_FILE) {
896 * "create mask"/"force create mode" are
897 * only applied to new files, not existing ones.
899 ret &= lp_create_mask(SNUM(conn));
900 /* Add in force bits */
901 ret |= lp_force_create_mode(SNUM(conn));
902 } else if (ptype == PERM_NEW_DIR) {
904 * "directory mask"/"force directory mode" are
905 * only applied to new directories, not existing ones.
907 ret &= lp_directory_mask(SNUM(conn));
908 /* Add in force bits */
909 ret |= lp_force_directory_mode(SNUM(conn));
912 *ret_perms = ret;
913 return NT_STATUS_OK;
916 /****************************************************************************
917 Get a level dependent lanman2 dir entry.
918 ****************************************************************************/
920 struct smbd_dirptr_lanman2_state {
921 connection_struct *conn;
922 uint32_t info_level;
923 bool check_mangled_names;
924 bool case_sensitive;
927 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
928 void *private_data,
929 const char *dname,
930 const char *mask,
931 char **_fname)
933 struct smbd_dirptr_lanman2_state *state =
934 (struct smbd_dirptr_lanman2_state *)private_data;
935 bool ok;
936 char mangled_name[13]; /* mangled 8.3 name. */
937 bool got_match;
938 const char *fname;
940 /* Mangle fname if it's an illegal name. */
941 if (mangle_must_mangle(dname, state->conn->params)) {
943 * Slow path - ensure we can push the original name as UCS2. If
944 * not, then just don't return this name.
946 NTSTATUS status;
947 size_t ret_len = 0;
948 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
949 uint8_t *tmp = talloc_array(talloc_tos(),
950 uint8_t,
951 len);
953 status = srvstr_push(NULL,
954 FLAGS2_UNICODE_STRINGS,
955 tmp,
956 dname,
957 len,
958 STR_TERMINATE,
959 &ret_len);
961 TALLOC_FREE(tmp);
963 if (!NT_STATUS_IS_OK(status)) {
964 return false;
967 ok = name_to_8_3(dname, mangled_name,
968 true, state->conn->params);
969 if (!ok) {
970 return false;
972 fname = mangled_name;
973 } else {
974 fname = dname;
977 got_match = mask_match(fname, mask,
978 state->case_sensitive);
980 if(!got_match && state->check_mangled_names &&
981 !mangle_is_8_3(fname, false, state->conn->params)) {
983 * It turns out that NT matches wildcards against
984 * both long *and* short names. This may explain some
985 * of the wildcard weirdness from old DOS clients
986 * that some people have been seeing.... JRA.
988 /* Force the mangling into 8.3. */
989 ok = name_to_8_3(fname, mangled_name,
990 false, state->conn->params);
991 if (!ok) {
992 return false;
995 got_match = mask_match(mangled_name, mask,
996 state->case_sensitive);
999 if (!got_match) {
1000 return false;
1003 *_fname = talloc_strdup(ctx, fname);
1004 if (*_fname == NULL) {
1005 return false;
1008 return true;
1011 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1012 void *private_data,
1013 struct files_struct *dirfsp,
1014 struct smb_filename *smb_fname,
1015 bool get_dosmode,
1016 uint32_t *_mode)
1018 if (get_dosmode) {
1019 SMB_ASSERT(smb_fname != NULL);
1020 *_mode = fdos_mode(smb_fname->fsp);
1021 if (smb_fname->fsp != NULL) {
1022 smb_fname->st = smb_fname->fsp->fsp_name->st;
1025 return true;
1028 static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1030 if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1031 unsigned ea_size = estimate_ea_size(fsp);
1032 return ea_size;
1034 return IO_REPARSE_TAG_DFS;
1037 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1038 connection_struct *conn,
1039 uint16_t flags2,
1040 uint32_t info_level,
1041 struct ea_list *name_list,
1042 bool check_mangled_names,
1043 bool requires_resume_key,
1044 uint32_t mode,
1045 const char *fname,
1046 const struct smb_filename *smb_fname,
1047 int space_remaining,
1048 uint8_t align,
1049 bool do_pad,
1050 char *base_data,
1051 char **ppdata,
1052 char *end_data,
1053 uint64_t *last_entry_off)
1055 char *p, *q, *pdata = *ppdata;
1056 uint32_t reskey=0;
1057 uint64_t file_size = 0;
1058 uint64_t allocation_size = 0;
1059 uint64_t file_id = 0;
1060 size_t len = 0;
1061 struct timespec mdate_ts = {0};
1062 struct timespec adate_ts = {0};
1063 struct timespec cdate_ts = {0};
1064 struct timespec create_date_ts = {0};
1065 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1066 char *nameptr;
1067 char *last_entry_ptr;
1068 bool was_8_3;
1069 int off;
1070 int pad = 0;
1071 NTSTATUS status;
1072 struct readdir_attr_data *readdir_attr_data = NULL;
1073 uint32_t ea_size;
1075 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1076 file_size = get_file_size_stat(&smb_fname->st);
1078 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1081 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1082 * a DFS symlink.
1084 if (smb_fname->fsp != NULL &&
1085 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1086 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1087 ctx,
1088 &readdir_attr_data);
1089 if (!NT_STATUS_IS_OK(status)) {
1090 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1091 status)) {
1092 return status;
1097 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1099 mdate_ts = smb_fname->st.st_ex_mtime;
1100 adate_ts = smb_fname->st.st_ex_atime;
1101 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1102 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1104 if (lp_dos_filetime_resolution(SNUM(conn))) {
1105 dos_filetime_timespec(&create_date_ts);
1106 dos_filetime_timespec(&mdate_ts);
1107 dos_filetime_timespec(&adate_ts);
1108 dos_filetime_timespec(&cdate_ts);
1111 create_date = convert_timespec_to_time_t(create_date_ts);
1112 mdate = convert_timespec_to_time_t(mdate_ts);
1113 adate = convert_timespec_to_time_t(adate_ts);
1115 /* align the record */
1116 SMB_ASSERT(align >= 1);
1118 off = (int)PTR_DIFF(pdata, base_data);
1119 pad = (off + (align-1)) & ~(align-1);
1120 pad -= off;
1122 if (pad && pad > space_remaining) {
1123 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1124 "for padding (wanted %u, had %d)\n",
1125 (unsigned int)pad,
1126 space_remaining ));
1127 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1130 off += pad;
1131 /* initialize padding to 0 */
1132 if (pad) {
1133 memset(pdata, 0, pad);
1135 space_remaining -= pad;
1137 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1138 space_remaining ));
1140 pdata += pad;
1141 p = pdata;
1142 last_entry_ptr = p;
1144 pad = 0;
1145 off = 0;
1147 switch (info_level) {
1148 case SMB_FIND_INFO_STANDARD:
1149 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1150 if(requires_resume_key) {
1151 SIVAL(p,0,reskey);
1152 p += 4;
1154 srv_put_dos_date2(p,0,create_date);
1155 srv_put_dos_date2(p,4,adate);
1156 srv_put_dos_date2(p,8,mdate);
1157 SIVAL(p,12,(uint32_t)file_size);
1158 SIVAL(p,16,(uint32_t)allocation_size);
1159 SSVAL(p,20,mode);
1160 p += 23;
1161 nameptr = p;
1162 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1163 p += ucs2_align(base_data, p, 0);
1165 status = srvstr_push(base_data, flags2, p,
1166 fname, PTR_DIFF(end_data, p),
1167 STR_TERMINATE, &len);
1168 if (!NT_STATUS_IS_OK(status)) {
1169 return status;
1171 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1172 if (len > 2) {
1173 SCVAL(nameptr, -1, len - 2);
1174 } else {
1175 SCVAL(nameptr, -1, 0);
1177 } else {
1178 if (len > 1) {
1179 SCVAL(nameptr, -1, len - 1);
1180 } else {
1181 SCVAL(nameptr, -1, 0);
1184 p += len;
1185 break;
1187 case SMB_FIND_EA_SIZE:
1188 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1189 if (requires_resume_key) {
1190 SIVAL(p,0,reskey);
1191 p += 4;
1193 srv_put_dos_date2(p,0,create_date);
1194 srv_put_dos_date2(p,4,adate);
1195 srv_put_dos_date2(p,8,mdate);
1196 SIVAL(p,12,(uint32_t)file_size);
1197 SIVAL(p,16,(uint32_t)allocation_size);
1198 SSVAL(p,20,mode);
1200 ea_size = estimate_ea_size(smb_fname->fsp);
1201 SIVAL(p,22,ea_size); /* Extended attributes */
1203 p += 27;
1204 nameptr = p - 1;
1205 status = srvstr_push(base_data, flags2,
1206 p, fname, PTR_DIFF(end_data, p),
1207 STR_TERMINATE | STR_NOALIGN, &len);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 return status;
1211 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1212 if (len > 2) {
1213 len -= 2;
1214 } else {
1215 len = 0;
1217 } else {
1218 if (len > 1) {
1219 len -= 1;
1220 } else {
1221 len = 0;
1224 SCVAL(nameptr,0,len);
1225 p += len;
1226 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1227 break;
1229 case SMB_FIND_EA_LIST:
1231 struct ea_list *file_list = NULL;
1232 size_t ea_len = 0;
1234 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1235 if (!name_list) {
1236 return NT_STATUS_INVALID_PARAMETER;
1238 if (requires_resume_key) {
1239 SIVAL(p,0,reskey);
1240 p += 4;
1242 srv_put_dos_date2(p,0,create_date);
1243 srv_put_dos_date2(p,4,adate);
1244 srv_put_dos_date2(p,8,mdate);
1245 SIVAL(p,12,(uint32_t)file_size);
1246 SIVAL(p,16,(uint32_t)allocation_size);
1247 SSVAL(p,20,mode);
1248 p += 22; /* p now points to the EA area. */
1250 status = get_ea_list_from_fsp(ctx,
1251 smb_fname->fsp,
1252 &ea_len, &file_list);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 file_list = NULL;
1256 name_list = ea_list_union(name_list, file_list, &ea_len);
1258 /* We need to determine if this entry will fit in the space available. */
1259 /* Max string size is 255 bytes. */
1260 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1261 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1262 "(wanted %u, had %d)\n",
1263 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1264 space_remaining ));
1265 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1268 /* Push the ea_data followed by the name. */
1269 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1270 nameptr = p;
1271 status = srvstr_push(base_data, flags2,
1272 p + 1, fname, PTR_DIFF(end_data, p+1),
1273 STR_TERMINATE | STR_NOALIGN, &len);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 return status;
1277 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1278 if (len > 2) {
1279 len -= 2;
1280 } else {
1281 len = 0;
1283 } else {
1284 if (len > 1) {
1285 len -= 1;
1286 } else {
1287 len = 0;
1290 SCVAL(nameptr,0,len);
1291 p += len + 1;
1292 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1293 break;
1296 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1297 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1298 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1299 p += 4;
1300 SIVAL(p,0,reskey); p += 4;
1301 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1302 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1303 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1304 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1305 SOFF_T(p,0,file_size); p += 8;
1306 SOFF_T(p,0,allocation_size); p += 8;
1307 SIVAL(p,0,mode); p += 4;
1308 q = p; p += 4; /* q is placeholder for name length. */
1309 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1310 SIVAL(p, 0, ea_size);
1311 p += 4;
1312 /* Clear the short name buffer. This is
1313 * IMPORTANT as not doing so will trigger
1314 * a Win2k client bug. JRA.
1316 if (!was_8_3 && check_mangled_names) {
1317 char mangled_name[13]; /* mangled 8.3 name. */
1318 if (!name_to_8_3(fname,mangled_name,True,
1319 conn->params)) {
1320 /* Error - mangle failed ! */
1321 memset(mangled_name,'\0',12);
1323 mangled_name[12] = 0;
1324 status = srvstr_push(base_data, flags2,
1325 p+2, mangled_name, 24,
1326 STR_UPPER|STR_UNICODE, &len);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 return status;
1330 if (len < 24) {
1331 memset(p + 2 + len,'\0',24 - len);
1333 SSVAL(p, 0, len);
1334 } else {
1335 memset(p,'\0',26);
1337 p += 2 + 24;
1338 status = srvstr_push(base_data, flags2, p,
1339 fname, PTR_DIFF(end_data, p),
1340 STR_TERMINATE_ASCII, &len);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 return status;
1344 SIVAL(q,0,len);
1345 p += len;
1347 len = PTR_DIFF(p, pdata);
1348 pad = (len + (align-1)) & ~(align-1);
1350 * offset to the next entry, the caller
1351 * will overwrite it for the last entry
1352 * that's why we always include the padding
1354 SIVAL(pdata,0,pad);
1356 * set padding to zero
1358 if (do_pad) {
1359 memset(p, 0, pad - len);
1360 p = pdata + pad;
1361 } else {
1362 p = pdata + len;
1364 break;
1366 case SMB_FIND_FILE_DIRECTORY_INFO:
1367 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1368 p += 4;
1369 SIVAL(p,0,reskey); p += 4;
1370 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1371 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1372 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1373 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1374 SOFF_T(p,0,file_size); p += 8;
1375 SOFF_T(p,0,allocation_size); p += 8;
1376 SIVAL(p,0,mode); p += 4;
1377 status = srvstr_push(base_data, flags2,
1378 p + 4, fname, PTR_DIFF(end_data, p+4),
1379 STR_TERMINATE_ASCII, &len);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 return status;
1383 SIVAL(p,0,len);
1384 p += 4 + len;
1386 len = PTR_DIFF(p, pdata);
1387 pad = (len + (align-1)) & ~(align-1);
1389 * offset to the next entry, the caller
1390 * will overwrite it for the last entry
1391 * that's why we always include the padding
1393 SIVAL(pdata,0,pad);
1395 * set padding to zero
1397 if (do_pad) {
1398 memset(p, 0, pad - len);
1399 p = pdata + pad;
1400 } else {
1401 p = pdata + len;
1403 break;
1405 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1406 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1407 p += 4;
1408 SIVAL(p,0,reskey); p += 4;
1409 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1410 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1411 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1412 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1413 SOFF_T(p,0,file_size); p += 8;
1414 SOFF_T(p,0,allocation_size); p += 8;
1415 SIVAL(p,0,mode); p += 4;
1416 q = p; p += 4; /* q is placeholder for name length. */
1417 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1418 SIVAL(p, 0, ea_size);
1419 p +=4;
1420 status = srvstr_push(base_data, flags2, p,
1421 fname, PTR_DIFF(end_data, p),
1422 STR_TERMINATE_ASCII, &len);
1423 if (!NT_STATUS_IS_OK(status)) {
1424 return status;
1426 SIVAL(q, 0, len);
1427 p += len;
1429 len = PTR_DIFF(p, pdata);
1430 pad = (len + (align-1)) & ~(align-1);
1432 * offset to the next entry, the caller
1433 * will overwrite it for the last entry
1434 * that's why we always include the padding
1436 SIVAL(pdata,0,pad);
1438 * set padding to zero
1440 if (do_pad) {
1441 memset(p, 0, pad - len);
1442 p = pdata + pad;
1443 } else {
1444 p = pdata + len;
1446 break;
1448 case SMB_FIND_FILE_NAMES_INFO:
1449 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1450 p += 4;
1451 SIVAL(p,0,reskey); p += 4;
1452 p += 4;
1453 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1454 acl on a dir (tridge) */
1455 status = srvstr_push(base_data, flags2, p,
1456 fname, PTR_DIFF(end_data, p),
1457 STR_TERMINATE_ASCII, &len);
1458 if (!NT_STATUS_IS_OK(status)) {
1459 return status;
1461 SIVAL(p, -4, len);
1462 p += len;
1464 len = PTR_DIFF(p, pdata);
1465 pad = (len + (align-1)) & ~(align-1);
1467 * offset to the next entry, the caller
1468 * will overwrite it for the last entry
1469 * that's why we always include the padding
1471 SIVAL(pdata,0,pad);
1473 * set padding to zero
1475 if (do_pad) {
1476 memset(p, 0, pad - len);
1477 p = pdata + pad;
1478 } else {
1479 p = pdata + len;
1481 break;
1483 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1484 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1485 p += 4;
1486 SIVAL(p,0,reskey); p += 4;
1487 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1488 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1489 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1490 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1491 SOFF_T(p,0,file_size); p += 8;
1492 SOFF_T(p,0,allocation_size); p += 8;
1493 SIVAL(p,0,mode); p += 4;
1494 q = p; p += 4; /* q is placeholder for name length. */
1495 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1496 SIVAL(p, 0, ea_size);
1497 p += 4;
1498 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1499 SBVAL(p,0,file_id); p += 8;
1500 status = srvstr_push(base_data, flags2, p,
1501 fname, PTR_DIFF(end_data, p),
1502 STR_TERMINATE_ASCII, &len);
1503 if (!NT_STATUS_IS_OK(status)) {
1504 return status;
1506 SIVAL(q, 0, len);
1507 p += len;
1509 len = PTR_DIFF(p, pdata);
1510 pad = (len + (align-1)) & ~(align-1);
1512 * offset to the next entry, the caller
1513 * will overwrite it for the last entry
1514 * that's why we always include the padding
1516 SIVAL(pdata,0,pad);
1518 * set padding to zero
1520 if (do_pad) {
1521 memset(p, 0, pad - len);
1522 p = pdata + pad;
1523 } else {
1524 p = pdata + len;
1526 break;
1528 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1529 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1530 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1531 p += 4;
1532 SIVAL(p,0,reskey); p += 4;
1533 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1534 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1535 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1536 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1537 SOFF_T(p,0,file_size); p += 8;
1538 SOFF_T(p,0,allocation_size); p += 8;
1539 SIVAL(p,0,mode); p += 4;
1540 q = p; p += 4; /* q is placeholder for name length */
1541 if (readdir_attr_data &&
1542 readdir_attr_data->type == RDATTR_AAPL) {
1544 * OS X specific SMB2 extension negotiated via
1545 * AAPL create context: return max_access in
1546 * ea_size field.
1548 ea_size = readdir_attr_data->attr_data.aapl.max_access;
1549 } else {
1550 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1552 SIVAL(p,0,ea_size); /* Extended attributes */
1553 p += 4;
1555 if (readdir_attr_data &&
1556 readdir_attr_data->type == RDATTR_AAPL) {
1558 * OS X specific SMB2 extension negotiated via
1559 * AAPL create context: return resource fork
1560 * length and compressed FinderInfo in
1561 * shortname field.
1563 * According to documentation short_name_len
1564 * should be 0, but on the wire behaviour
1565 * shows its set to 24 by clients.
1567 SSVAL(p, 0, 24);
1569 /* Resourefork length */
1570 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1572 /* Compressed FinderInfo */
1573 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1574 } else if (!was_8_3 && check_mangled_names) {
1575 char mangled_name[13]; /* mangled 8.3 name. */
1576 if (!name_to_8_3(fname,mangled_name,True,
1577 conn->params)) {
1578 /* Error - mangle failed ! */
1579 memset(mangled_name,'\0',12);
1581 mangled_name[12] = 0;
1582 status = srvstr_push(base_data, flags2,
1583 p+2, mangled_name, 24,
1584 STR_UPPER|STR_UNICODE, &len);
1585 if (!NT_STATUS_IS_OK(status)) {
1586 return status;
1588 SSVAL(p, 0, len);
1589 if (len < 24) {
1590 memset(p + 2 + len,'\0',24 - len);
1592 SSVAL(p, 0, len);
1593 } else {
1594 /* Clear the short name buffer. This is
1595 * IMPORTANT as not doing so will trigger
1596 * a Win2k client bug. JRA.
1598 memset(p,'\0',26);
1600 p += 26;
1602 /* Reserved ? */
1603 if (readdir_attr_data &&
1604 readdir_attr_data->type == RDATTR_AAPL) {
1606 * OS X specific SMB2 extension negotiated via
1607 * AAPL create context: return UNIX mode in
1608 * reserved field.
1610 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1611 SSVAL(p, 0, aapl_mode);
1612 } else {
1613 SSVAL(p, 0, 0);
1615 p += 2;
1617 SBVAL(p,0,file_id); p += 8;
1618 status = srvstr_push(base_data, flags2, p,
1619 fname, PTR_DIFF(end_data, p),
1620 STR_TERMINATE_ASCII, &len);
1621 if (!NT_STATUS_IS_OK(status)) {
1622 return status;
1624 SIVAL(q,0,len);
1625 p += len;
1627 len = PTR_DIFF(p, pdata);
1628 pad = (len + (align-1)) & ~(align-1);
1630 * offset to the next entry, the caller
1631 * will overwrite it for the last entry
1632 * that's why we always include the padding
1634 SIVAL(pdata,0,pad);
1636 * set padding to zero
1638 if (do_pad) {
1639 memset(p, 0, pad - len);
1640 p = pdata + pad;
1641 } else {
1642 p = pdata + len;
1644 break;
1646 /* CIFS UNIX Extension. */
1648 case SMB_FIND_FILE_UNIX:
1649 case SMB_FIND_FILE_UNIX_INFO2:
1650 p+= 4;
1651 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1653 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1655 if (info_level == SMB_FIND_FILE_UNIX) {
1656 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1657 p = store_file_unix_basic(conn, p,
1658 NULL, &smb_fname->st);
1659 status = srvstr_push(base_data, flags2, p,
1660 fname, PTR_DIFF(end_data, p),
1661 STR_TERMINATE, &len);
1662 if (!NT_STATUS_IS_OK(status)) {
1663 return status;
1665 } else {
1666 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1667 p = store_file_unix_basic_info2(conn, p,
1668 NULL, &smb_fname->st);
1669 nameptr = p;
1670 p += 4;
1671 status = srvstr_push(base_data, flags2, p, fname,
1672 PTR_DIFF(end_data, p), 0, &len);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 return status;
1676 SIVAL(nameptr, 0, len);
1679 p += len;
1681 len = PTR_DIFF(p, pdata);
1682 pad = (len + (align-1)) & ~(align-1);
1684 * offset to the next entry, the caller
1685 * will overwrite it for the last entry
1686 * that's why we always include the padding
1688 SIVAL(pdata,0,pad);
1690 * set padding to zero
1692 if (do_pad) {
1693 memset(p, 0, pad - len);
1694 p = pdata + pad;
1695 } else {
1696 p = pdata + len;
1698 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1700 break;
1702 /* SMB2 UNIX Extension. */
1704 case SMB2_FILE_POSIX_INFORMATION:
1706 struct smb3_file_posix_information info = {};
1707 uint8_t buf[sizeof(info)];
1708 struct ndr_push ndr = {
1709 .data = buf,
1710 .alloc_size = sizeof(buf),
1711 .fixed_buf_size = true,
1713 enum ndr_err_code ndr_err;
1715 p+= 4;
1716 SIVAL(p,0,reskey); p+= 4;
1718 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1720 if (!(conn->sconn->using_smb2)) {
1721 return NT_STATUS_INVALID_LEVEL;
1724 smb3_file_posix_information_init(
1725 conn, &smb_fname->st, 0, mode, &info);
1727 ndr_err = ndr_push_smb3_file_posix_information(
1728 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
1729 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1730 return NT_STATUS_INSUFFICIENT_RESOURCES;
1733 memcpy(p, buf, ndr.offset);
1734 p += ndr.offset;
1736 nameptr = p;
1737 p += 4;
1738 status = srvstr_push(base_data, flags2, p, fname,
1739 PTR_DIFF(end_data, p), 0, &len);
1740 if (!NT_STATUS_IS_OK(status)) {
1741 return status;
1743 SIVAL(nameptr, 0, len);
1745 p += len;
1747 len = PTR_DIFF(p, pdata);
1748 pad = (len + (align-1)) & ~(align-1);
1750 * offset to the next entry, the caller
1751 * will overwrite it for the last entry
1752 * that's why we always include the padding
1754 SIVAL(pdata,0,pad);
1755 break;
1758 default:
1759 return NT_STATUS_INVALID_LEVEL;
1762 if (PTR_DIFF(p,pdata) > space_remaining) {
1763 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1764 "(wanted %u, had %d)\n",
1765 (unsigned int)PTR_DIFF(p,pdata),
1766 space_remaining ));
1767 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1770 /* Setup the last entry pointer, as an offset from base_data */
1771 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1772 /* Advance the data pointer to the next slot */
1773 *ppdata = p;
1775 return NT_STATUS_OK;
1778 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1779 connection_struct *conn,
1780 struct dptr_struct *dirptr,
1781 uint16_t flags2,
1782 const char *path_mask,
1783 uint32_t dirtype,
1784 int info_level,
1785 int requires_resume_key,
1786 bool dont_descend,
1787 bool ask_sharemode,
1788 bool get_dosmode,
1789 uint8_t align,
1790 bool do_pad,
1791 char **ppdata,
1792 char *base_data,
1793 char *end_data,
1794 int space_remaining,
1795 struct smb_filename **_smb_fname,
1796 int *_last_entry_off,
1797 struct ea_list *name_list,
1798 struct file_id *file_id)
1800 const char *p;
1801 const char *mask = NULL;
1802 uint32_t mode = 0;
1803 char *fname = NULL;
1804 struct smb_filename *smb_fname = NULL;
1805 struct smbd_dirptr_lanman2_state state;
1806 bool ok;
1807 uint64_t last_entry_off = 0;
1808 NTSTATUS status;
1809 enum mangled_names_options mangled_names;
1810 bool marshall_with_83_names;
1812 mangled_names = lp_mangled_names(conn->params);
1814 ZERO_STRUCT(state);
1815 state.conn = conn;
1816 state.info_level = info_level;
1817 if (mangled_names != MANGLED_NAMES_NO) {
1818 state.check_mangled_names = true;
1820 state.case_sensitive = dptr_case_sensitive(dirptr);
1822 p = strrchr_m(path_mask,'/');
1823 if(p != NULL) {
1824 if(p[1] == '\0') {
1825 mask = "*.*";
1826 } else {
1827 mask = p+1;
1829 } else {
1830 mask = path_mask;
1833 ok = smbd_dirptr_get_entry(ctx,
1834 dirptr,
1835 mask,
1836 dirtype,
1837 dont_descend,
1838 ask_sharemode,
1839 get_dosmode,
1840 smbd_dirptr_lanman2_match_fn,
1841 smbd_dirptr_lanman2_mode_fn,
1842 &state,
1843 &fname,
1844 &smb_fname,
1845 &mode);
1846 if (!ok) {
1847 return NT_STATUS_END_OF_FILE;
1850 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1852 status = smbd_marshall_dir_entry(ctx,
1853 conn,
1854 flags2,
1855 info_level,
1856 name_list,
1857 marshall_with_83_names,
1858 requires_resume_key,
1859 mode,
1860 fname,
1861 smb_fname,
1862 space_remaining,
1863 align,
1864 do_pad,
1865 base_data,
1866 ppdata,
1867 end_data,
1868 &last_entry_off);
1869 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1870 DEBUG(1,("Conversion error: illegal character: %s\n",
1871 smb_fname_str_dbg(smb_fname)));
1874 if (file_id != NULL) {
1875 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1878 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1879 smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1882 if (!NT_STATUS_IS_OK(status)) {
1883 TALLOC_FREE(smb_fname);
1884 TALLOC_FREE(fname);
1885 return status;
1888 smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1890 if (_smb_fname != NULL) {
1892 * smb_fname is already talloc'ed off ctx.
1893 * We just need to make sure we don't return
1894 * any stream_name, and replace base_name
1895 * with fname in case base_name got mangled.
1896 * This allows us to preserve any smb_fname->fsp
1897 * for asynchronous handle lookups.
1899 TALLOC_FREE(smb_fname->stream_name);
1902 * smbd_dirptr_set_last_name_sent() above consumed
1903 * base_name
1905 smb_fname->base_name = talloc_strdup(smb_fname, fname);
1907 if (smb_fname->base_name == NULL) {
1908 TALLOC_FREE(smb_fname);
1909 TALLOC_FREE(fname);
1910 return NT_STATUS_NO_MEMORY;
1912 *_smb_fname = smb_fname;
1913 } else {
1914 TALLOC_FREE(smb_fname);
1916 TALLOC_FREE(fname);
1918 *_last_entry_off = last_entry_off;
1919 return NT_STATUS_OK;
1922 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1924 const struct loadparm_substitution *lp_sub =
1925 loadparm_s3_global_substitution();
1927 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1928 return objid;
1931 static void samba_extended_info_version(struct smb_extended_info *extended_info)
1933 SMB_ASSERT(extended_info != NULL);
1935 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1936 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1937 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1938 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1939 #ifdef SAMBA_VERSION_REVISION
1940 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1941 #endif
1942 extended_info->samba_subversion = 0;
1943 #ifdef SAMBA_VERSION_RC_RELEASE
1944 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1945 #else
1946 #ifdef SAMBA_VERSION_PRE_RELEASE
1947 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
1948 #endif
1949 #endif
1950 #ifdef SAMBA_VERSION_VENDOR_PATCH
1951 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
1952 #endif
1953 extended_info->samba_gitcommitdate = 0;
1954 #ifdef SAMBA_VERSION_COMMIT_TIME
1955 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
1956 #endif
1958 memset(extended_info->samba_version_string, 0,
1959 sizeof(extended_info->samba_version_string));
1961 snprintf (extended_info->samba_version_string,
1962 sizeof(extended_info->samba_version_string),
1963 "%s", samba_version_string());
1966 static bool fsinfo_unix_valid_level(connection_struct *conn,
1967 uint16_t info_level)
1969 if (conn->sconn->using_smb2 &&
1970 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) {
1971 return true;
1973 #if defined(SMB1SERVER)
1974 if (lp_smb1_unix_extensions() &&
1975 info_level == SMB_QUERY_POSIX_FS_INFO) {
1976 return true;
1978 #endif
1979 return false;
1982 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
1983 connection_struct *conn,
1984 TALLOC_CTX *mem_ctx,
1985 uint16_t info_level,
1986 uint16_t flags2,
1987 unsigned int max_data_bytes,
1988 size_t *fixed_portion,
1989 struct smb_filename *fname,
1990 char **ppdata,
1991 int *ret_data_len)
1993 const struct loadparm_substitution *lp_sub =
1994 loadparm_s3_global_substitution();
1995 char *pdata, *end_data;
1996 int data_len = 0;
1997 size_t len = 0;
1998 const char *vname = volume_label(talloc_tos(), SNUM(conn));
1999 int snum = SNUM(conn);
2000 const char *fstype = lp_fstype(SNUM(conn));
2001 const char *filename = NULL;
2002 const uint64_t bytes_per_sector = 512;
2003 uint32_t additional_flags = 0;
2004 struct smb_filename smb_fname;
2005 SMB_STRUCT_STAT st;
2006 NTSTATUS status = NT_STATUS_OK;
2007 uint64_t df_ret;
2008 uint32_t serial;
2010 if (fname == NULL || fname->base_name == NULL) {
2011 filename = ".";
2012 } else {
2013 filename = fname->base_name;
2016 if (IS_IPC(conn)) {
2017 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2018 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2019 "info level (0x%x) on IPC$.\n",
2020 (unsigned int)info_level));
2021 return NT_STATUS_ACCESS_DENIED;
2025 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2027 smb_fname = (struct smb_filename) {
2028 .base_name = discard_const_p(char, filename),
2029 .flags = fname ? fname->flags : 0,
2030 .twrp = fname ? fname->twrp : 0,
2033 if(info_level != SMB_FS_QUOTA_INFORMATION
2034 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2035 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2036 return map_nt_error_from_unix(errno);
2039 st = smb_fname.st;
2041 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2042 return NT_STATUS_INVALID_PARAMETER;
2045 *ppdata = (char *)SMB_REALLOC(
2046 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2047 if (*ppdata == NULL) {
2048 return NT_STATUS_NO_MEMORY;
2051 pdata = *ppdata;
2052 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2053 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2055 *fixed_portion = 0;
2057 switch (info_level) {
2058 case SMB_INFO_ALLOCATION:
2060 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2061 data_len = 18;
2062 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2063 &dfree, &dsize);
2064 if (df_ret == (uint64_t)-1) {
2065 return map_nt_error_from_unix(errno);
2068 block_size = lp_block_size(snum);
2069 if (bsize < block_size) {
2070 uint64_t factor = block_size/bsize;
2071 bsize = block_size;
2072 dsize /= factor;
2073 dfree /= factor;
2075 if (bsize > block_size) {
2076 uint64_t factor = bsize/block_size;
2077 bsize = block_size;
2078 dsize *= factor;
2079 dfree *= factor;
2081 sectors_per_unit = bsize/bytes_per_sector;
2083 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2084 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2085 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2088 * For large drives, return max values and not modulo.
2090 dsize = MIN(dsize, UINT32_MAX);
2091 dfree = MIN(dfree, UINT32_MAX);
2093 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2094 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2095 SIVAL(pdata,l1_cUnit,dsize);
2096 SIVAL(pdata,l1_cUnitAvail,dfree);
2097 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2098 break;
2101 case SMB_INFO_VOLUME:
2102 /* Return volume name */
2104 * Add volume serial number - hash of a combination of
2105 * the called hostname and the service name.
2107 serial = generate_volume_serial_number(lp_sub, snum);
2108 SIVAL(pdata,0,serial);
2110 * Win2k3 and previous mess this up by sending a name length
2111 * one byte short. I believe only older clients (OS/2 Win9x) use
2112 * this call so try fixing this by adding a terminating null to
2113 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2115 status = srvstr_push(
2116 pdata, flags2,
2117 pdata+l2_vol_szVolLabel, vname,
2118 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2119 STR_NOALIGN|STR_TERMINATE, &len);
2120 if (!NT_STATUS_IS_OK(status)) {
2121 return status;
2123 SCVAL(pdata,l2_vol_cch,len);
2124 data_len = l2_vol_szVolLabel + len;
2125 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2126 "name = %s serial = 0x%04"PRIx32"\n",
2127 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2128 (unsigned)len, vname, serial));
2129 break;
2131 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2132 case SMB_FS_ATTRIBUTE_INFORMATION:
2134 additional_flags = 0;
2135 #if defined(HAVE_SYS_QUOTAS)
2136 additional_flags |= FILE_VOLUME_QUOTAS;
2137 #endif
2139 if(lp_nt_acl_support(SNUM(conn))) {
2140 additional_flags |= FILE_PERSISTENT_ACLS;
2143 /* Capabilities are filled in at connection time through STATVFS call */
2144 additional_flags |= conn->fs_capabilities;
2145 additional_flags |= lp_parm_int(conn->params->service,
2146 "share", "fake_fscaps",
2149 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2150 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2151 additional_flags); /* FS ATTRIBUTES */
2153 SIVAL(pdata,4,255); /* Max filename component length */
2154 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2155 and will think we can't do long filenames */
2156 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2157 PTR_DIFF(end_data, pdata+12),
2158 STR_UNICODE, &len);
2159 if (!NT_STATUS_IS_OK(status)) {
2160 return status;
2162 SIVAL(pdata,8,len);
2163 data_len = 12 + len;
2164 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2165 /* the client only requested a portion of the
2166 file system name */
2167 data_len = max_data_bytes;
2168 status = STATUS_BUFFER_OVERFLOW;
2170 *fixed_portion = 16;
2171 break;
2173 case SMB_QUERY_FS_LABEL_INFO:
2174 case SMB_FS_LABEL_INFORMATION:
2175 status = srvstr_push(pdata, flags2, pdata+4, vname,
2176 PTR_DIFF(end_data, pdata+4), 0, &len);
2177 if (!NT_STATUS_IS_OK(status)) {
2178 return status;
2180 data_len = 4 + len;
2181 SIVAL(pdata,0,len);
2182 break;
2184 case SMB_QUERY_FS_VOLUME_INFO:
2185 case SMB_FS_VOLUME_INFORMATION:
2186 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2187 pdata, &st.st_ex_btime);
2189 * Add volume serial number - hash of a combination of
2190 * the called hostname and the service name.
2192 serial = generate_volume_serial_number(lp_sub, snum);
2193 SIVAL(pdata,8,serial);
2195 /* Max label len is 32 characters. */
2196 status = srvstr_push(pdata, flags2, pdata+18, vname,
2197 PTR_DIFF(end_data, pdata+18),
2198 STR_UNICODE, &len);
2199 if (!NT_STATUS_IS_OK(status)) {
2200 return status;
2202 SIVAL(pdata,12,len);
2203 data_len = 18+len;
2205 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2206 "namelen = %d, vol=%s serv=%s "
2207 "serial=0x%04"PRIx32"\n",
2208 (int)strlen(vname),vname,
2209 lp_servicename(talloc_tos(), lp_sub, snum),
2210 serial));
2211 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2212 /* the client only requested a portion of the
2213 volume label */
2214 data_len = max_data_bytes;
2215 status = STATUS_BUFFER_OVERFLOW;
2217 *fixed_portion = 24;
2218 break;
2220 case SMB_QUERY_FS_SIZE_INFO:
2221 case SMB_FS_SIZE_INFORMATION:
2223 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2224 data_len = 24;
2225 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2226 &dfree, &dsize);
2227 if (df_ret == (uint64_t)-1) {
2228 return map_nt_error_from_unix(errno);
2230 block_size = lp_block_size(snum);
2231 if (bsize < block_size) {
2232 uint64_t factor = block_size/bsize;
2233 bsize = block_size;
2234 dsize /= factor;
2235 dfree /= factor;
2237 if (bsize > block_size) {
2238 uint64_t factor = bsize/block_size;
2239 bsize = block_size;
2240 dsize *= factor;
2241 dfree *= factor;
2243 sectors_per_unit = bsize/bytes_per_sector;
2244 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2245 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2246 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2247 SBIG_UINT(pdata,0,dsize);
2248 SBIG_UINT(pdata,8,dfree);
2249 SIVAL(pdata,16,sectors_per_unit);
2250 SIVAL(pdata,20,bytes_per_sector);
2251 *fixed_portion = 24;
2252 break;
2255 case SMB_FS_FULL_SIZE_INFORMATION:
2257 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2258 data_len = 32;
2259 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2260 &dfree, &dsize);
2261 if (df_ret == (uint64_t)-1) {
2262 return map_nt_error_from_unix(errno);
2264 block_size = lp_block_size(snum);
2265 if (bsize < block_size) {
2266 uint64_t factor = block_size/bsize;
2267 bsize = block_size;
2268 dsize /= factor;
2269 dfree /= factor;
2271 if (bsize > block_size) {
2272 uint64_t factor = bsize/block_size;
2273 bsize = block_size;
2274 dsize *= factor;
2275 dfree *= factor;
2277 sectors_per_unit = bsize/bytes_per_sector;
2278 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2279 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2280 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2281 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2282 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2283 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2284 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2285 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2286 *fixed_portion = 32;
2287 break;
2290 case SMB_QUERY_FS_DEVICE_INFO:
2291 case SMB_FS_DEVICE_INFORMATION:
2293 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2295 if (!CAN_WRITE(conn)) {
2296 characteristics |= FILE_READ_ONLY_DEVICE;
2298 data_len = 8;
2299 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2300 SIVAL(pdata,4,characteristics);
2301 *fixed_portion = 8;
2302 break;
2305 #ifdef HAVE_SYS_QUOTAS
2306 case SMB_FS_QUOTA_INFORMATION:
2308 * what we have to send --metze:
2310 * Unknown1: 24 NULL bytes
2311 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2312 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2313 * Quota Flags: 2 byte :
2314 * Unknown3: 6 NULL bytes
2316 * 48 bytes total
2318 * details for Quota Flags:
2320 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2321 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2322 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2323 * 0x0001 Enable Quotas: enable quota for this fs
2327 /* we need to fake up a fsp here,
2328 * because its not send in this call
2330 files_struct fsp;
2331 SMB_NTQUOTA_STRUCT quotas;
2333 ZERO_STRUCT(fsp);
2334 ZERO_STRUCT(quotas);
2336 fsp.conn = conn;
2337 fsp.fnum = FNUM_FIELD_INVALID;
2339 /* access check */
2340 if (get_current_uid(conn) != 0) {
2341 DEBUG(0,("get_user_quota: access_denied "
2342 "service [%s] user [%s]\n",
2343 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2344 conn->session_info->unix_info->unix_name));
2345 return NT_STATUS_ACCESS_DENIED;
2348 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
2349 NULL, &quotas);
2350 if (!NT_STATUS_IS_OK(status)) {
2351 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2352 return status;
2355 data_len = 48;
2357 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2358 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2360 /* Unknown1 24 NULL bytes*/
2361 SBIG_UINT(pdata,0,(uint64_t)0);
2362 SBIG_UINT(pdata,8,(uint64_t)0);
2363 SBIG_UINT(pdata,16,(uint64_t)0);
2365 /* Default Soft Quota 8 bytes */
2366 SBIG_UINT(pdata,24,quotas.softlim);
2368 /* Default Hard Quota 8 bytes */
2369 SBIG_UINT(pdata,32,quotas.hardlim);
2371 /* Quota flag 2 bytes */
2372 SSVAL(pdata,40,quotas.qflags);
2374 /* Unknown3 6 NULL bytes */
2375 SSVAL(pdata,42,0);
2376 SIVAL(pdata,44,0);
2378 break;
2380 #endif /* HAVE_SYS_QUOTAS */
2381 case SMB_FS_OBJECTID_INFORMATION:
2383 unsigned char objid[16];
2384 struct smb_extended_info extended_info;
2385 memcpy(pdata,create_volume_objectid(conn, objid),16);
2386 samba_extended_info_version (&extended_info);
2387 SIVAL(pdata,16,extended_info.samba_magic);
2388 SIVAL(pdata,20,extended_info.samba_version);
2389 SIVAL(pdata,24,extended_info.samba_subversion);
2390 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2391 memcpy(pdata+36,extended_info.samba_version_string,28);
2392 data_len = 64;
2393 break;
2396 case SMB_FS_SECTOR_SIZE_INFORMATION:
2398 data_len = 28;
2400 * These values match a physical Windows Server 2012
2401 * share backed by NTFS atop spinning rust.
2403 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2404 /* logical_bytes_per_sector */
2405 SIVAL(pdata, 0, bytes_per_sector);
2406 /* phys_bytes_per_sector_atomic */
2407 SIVAL(pdata, 4, bytes_per_sector);
2408 /* phys_bytes_per_sector_perf */
2409 SIVAL(pdata, 8, bytes_per_sector);
2410 /* fs_effective_phys_bytes_per_sector_atomic */
2411 SIVAL(pdata, 12, bytes_per_sector);
2412 /* flags */
2413 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2414 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2415 /* byte_off_sector_align */
2416 SIVAL(pdata, 20, 0);
2417 /* byte_off_partition_align */
2418 SIVAL(pdata, 24, 0);
2419 *fixed_portion = 28;
2420 break;
2424 #if defined(WITH_SMB1SERVER)
2426 * Query the version and capabilities of the CIFS UNIX extensions
2427 * in use.
2430 case SMB_QUERY_CIFS_UNIX_INFO:
2432 bool large_write = lp_min_receive_file_size() &&
2433 !smb1_srv_is_signing_active(xconn);
2434 bool large_read = !smb1_srv_is_signing_active(xconn);
2435 int encrypt_caps = 0;
2437 if (!lp_smb1_unix_extensions()) {
2438 return NT_STATUS_INVALID_LEVEL;
2441 switch (conn->encrypt_level) {
2442 case SMB_SIGNING_OFF:
2443 encrypt_caps = 0;
2444 break;
2445 case SMB_SIGNING_DESIRED:
2446 case SMB_SIGNING_IF_REQUIRED:
2447 case SMB_SIGNING_DEFAULT:
2448 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2449 break;
2450 case SMB_SIGNING_REQUIRED:
2451 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2452 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2453 large_write = false;
2454 large_read = false;
2455 break;
2458 data_len = 12;
2459 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2460 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2462 /* We have POSIX ACLs, pathname, encryption,
2463 * large read/write, and locking capability. */
2465 SBIG_UINT(pdata,4,((uint64_t)(
2466 CIFS_UNIX_POSIX_ACLS_CAP|
2467 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2468 CIFS_UNIX_FCNTL_LOCKS_CAP|
2469 CIFS_UNIX_EXTATTR_CAP|
2470 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2471 encrypt_caps|
2472 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2473 (large_write ?
2474 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2475 break;
2477 #endif
2479 case SMB_QUERY_POSIX_FS_INFO:
2480 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2482 int rc;
2483 struct vfs_statvfs_struct svfs;
2485 if (!fsinfo_unix_valid_level(conn, info_level)) {
2486 return NT_STATUS_INVALID_LEVEL;
2489 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2491 if (!rc) {
2492 data_len = 56;
2493 SIVAL(pdata,0,svfs.OptimalTransferSize);
2494 SIVAL(pdata,4,svfs.BlockSize);
2495 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2496 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2497 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2498 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2499 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2500 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2501 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2502 #ifdef EOPNOTSUPP
2503 } else if (rc == EOPNOTSUPP) {
2504 return NT_STATUS_INVALID_LEVEL;
2505 #endif /* EOPNOTSUPP */
2506 } else {
2507 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2508 return NT_STATUS_DOS(ERRSRV, ERRerror);
2510 break;
2513 case SMB_QUERY_POSIX_WHOAMI:
2515 uint32_t flags = 0;
2516 uint32_t sid_bytes;
2517 uint32_t i;
2519 if (!lp_smb1_unix_extensions()) {
2520 return NT_STATUS_INVALID_LEVEL;
2523 if (max_data_bytes < 40) {
2524 return NT_STATUS_BUFFER_TOO_SMALL;
2527 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2528 flags |= SMB_WHOAMI_GUEST;
2531 /* NOTE: 8 bytes for UID/GID, irrespective of native
2532 * platform size. This matches
2533 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2535 data_len = 4 /* flags */
2536 + 4 /* flag mask */
2537 + 8 /* uid */
2538 + 8 /* gid */
2539 + 4 /* ngroups */
2540 + 4 /* num_sids */
2541 + 4 /* SID bytes */
2542 + 4 /* pad/reserved */
2543 + (conn->session_info->unix_token->ngroups * 8)
2544 /* groups list */
2545 + (conn->session_info->security_token->num_sids *
2546 SID_MAX_SIZE)
2547 /* SID list */;
2549 SIVAL(pdata, 0, flags);
2550 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2551 SBIG_UINT(pdata, 8,
2552 (uint64_t)conn->session_info->unix_token->uid);
2553 SBIG_UINT(pdata, 16,
2554 (uint64_t)conn->session_info->unix_token->gid);
2557 if (data_len >= max_data_bytes) {
2558 /* Potential overflow, skip the GIDs and SIDs. */
2560 SIVAL(pdata, 24, 0); /* num_groups */
2561 SIVAL(pdata, 28, 0); /* num_sids */
2562 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2563 SIVAL(pdata, 36, 0); /* reserved */
2565 data_len = 40;
2566 break;
2569 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2570 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2572 /* We walk the SID list twice, but this call is fairly
2573 * infrequent, and I don't expect that it's performance
2574 * sensitive -- jpeach
2576 for (i = 0, sid_bytes = 0;
2577 i < conn->session_info->security_token->num_sids; ++i) {
2578 sid_bytes += ndr_size_dom_sid(
2579 &conn->session_info->security_token->sids[i],
2583 /* SID list byte count */
2584 SIVAL(pdata, 32, sid_bytes);
2586 /* 4 bytes pad/reserved - must be zero */
2587 SIVAL(pdata, 36, 0);
2588 data_len = 40;
2590 /* GID list */
2591 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2592 SBIG_UINT(pdata, data_len,
2593 (uint64_t)conn->session_info->unix_token->groups[i]);
2594 data_len += 8;
2597 /* SID list */
2598 for (i = 0;
2599 i < conn->session_info->security_token->num_sids; ++i) {
2600 int sid_len = ndr_size_dom_sid(
2601 &conn->session_info->security_token->sids[i],
2604 sid_linearize((uint8_t *)(pdata + data_len),
2605 sid_len,
2606 &conn->session_info->security_token->sids[i]);
2607 data_len += sid_len;
2610 break;
2613 case SMB_MAC_QUERY_FS_INFO:
2615 * Thursby MAC extension... ONLY on NTFS filesystems
2616 * once we do streams then we don't need this
2618 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2619 data_len = 88;
2620 SIVAL(pdata,84,0x100); /* Don't support mac... */
2621 break;
2624 FALL_THROUGH;
2625 default:
2626 return NT_STATUS_INVALID_LEVEL;
2629 *ret_data_len = data_len;
2630 return status;
2633 NTSTATUS smb_set_fsquota(connection_struct *conn,
2634 struct smb_request *req,
2635 files_struct *fsp,
2636 const DATA_BLOB *qdata)
2638 const struct loadparm_substitution *lp_sub =
2639 loadparm_s3_global_substitution();
2640 NTSTATUS status;
2641 SMB_NTQUOTA_STRUCT quotas;
2643 ZERO_STRUCT(quotas);
2645 /* access check */
2646 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2647 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2648 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2649 conn->session_info->unix_info->unix_name);
2650 return NT_STATUS_ACCESS_DENIED;
2653 if (!check_fsp_ntquota_handle(conn, req,
2654 fsp)) {
2655 DBG_WARNING("no valid QUOTA HANDLE\n");
2656 return NT_STATUS_INVALID_HANDLE;
2659 /* note: normally there're 48 bytes,
2660 * but we didn't use the last 6 bytes for now
2661 * --metze
2663 if (qdata->length < 42) {
2664 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2665 qdata->length);
2666 return NT_STATUS_INVALID_PARAMETER;
2669 /* unknown_1 24 NULL bytes in pdata*/
2671 /* the soft quotas 8 bytes (uint64_t)*/
2672 quotas.softlim = BVAL(qdata->data,24);
2674 /* the hard quotas 8 bytes (uint64_t)*/
2675 quotas.hardlim = BVAL(qdata->data,32);
2677 /* quota_flags 2 bytes **/
2678 quotas.qflags = SVAL(qdata->data,40);
2680 /* unknown_2 6 NULL bytes follow*/
2682 /* now set the quotas */
2683 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2684 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2685 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)));
2686 status = map_nt_error_from_unix(errno);
2687 } else {
2688 status = NT_STATUS_OK;
2690 return status;
2693 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2694 struct smb_request *req,
2695 TALLOC_CTX *mem_ctx,
2696 uint16_t info_level,
2697 files_struct *fsp,
2698 const DATA_BLOB *pdata)
2700 switch (info_level) {
2701 case SMB_FS_QUOTA_INFORMATION:
2703 return smb_set_fsquota(conn,
2704 req,
2705 fsp,
2706 pdata);
2709 default:
2710 break;
2712 return NT_STATUS_INVALID_LEVEL;
2715 /****************************************************************************
2716 Store the FILE_UNIX_BASIC info.
2717 ****************************************************************************/
2719 char *store_file_unix_basic(connection_struct *conn,
2720 char *pdata,
2721 files_struct *fsp,
2722 const SMB_STRUCT_STAT *psbuf)
2724 dev_t devno;
2726 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2727 DBG_NOTICE("st_mode=%o\n", (int)psbuf->st_ex_mode);
2729 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2730 pdata += 8;
2732 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2733 pdata += 8;
2735 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2736 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2737 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2738 pdata += 24;
2740 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2741 SIVAL(pdata,4,0);
2742 pdata += 8;
2744 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2745 SIVAL(pdata,4,0);
2746 pdata += 8;
2748 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2749 pdata += 4;
2751 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2752 devno = psbuf->st_ex_rdev;
2753 } else {
2754 devno = psbuf->st_ex_dev;
2757 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2758 SIVAL(pdata,4,0);
2759 pdata += 8;
2761 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2762 SIVAL(pdata,4,0);
2763 pdata += 8;
2765 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2766 pdata += 8;
2768 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2769 SIVAL(pdata,4,0);
2770 pdata += 8;
2772 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2773 SIVAL(pdata,4,0);
2774 pdata += 8;
2776 return pdata;
2779 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2780 * the chflags(2) (or equivalent) flags.
2782 * XXX: this really should be behind the VFS interface. To do this, we would
2783 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2784 * Each VFS module could then implement its own mapping as appropriate for the
2785 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2787 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2788 info2_flags_map[] =
2790 #ifdef UF_NODUMP
2791 { UF_NODUMP, EXT_DO_NOT_BACKUP },
2792 #endif
2794 #ifdef UF_IMMUTABLE
2795 { UF_IMMUTABLE, EXT_IMMUTABLE },
2796 #endif
2798 #ifdef UF_APPEND
2799 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2800 #endif
2802 #ifdef UF_HIDDEN
2803 { UF_HIDDEN, EXT_HIDDEN },
2804 #endif
2806 /* Do not remove. We need to guarantee that this array has at least one
2807 * entry to build on HP-UX.
2809 { 0, 0 }
2813 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2814 uint32_t *smb_fflags, uint32_t *smb_fmask)
2816 size_t i;
2818 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2819 *smb_fmask |= info2_flags_map[i].smb_fflag;
2820 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2821 *smb_fflags |= info2_flags_map[i].smb_fflag;
2826 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2827 const uint32_t smb_fflags,
2828 const uint32_t smb_fmask,
2829 int *stat_fflags)
2831 uint32_t max_fmask = 0;
2832 size_t i;
2834 *stat_fflags = psbuf->st_ex_flags;
2836 /* For each flags requested in smb_fmask, check the state of the
2837 * corresponding flag in smb_fflags and set or clear the matching
2838 * stat flag.
2841 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2842 max_fmask |= info2_flags_map[i].smb_fflag;
2843 if (smb_fmask & info2_flags_map[i].smb_fflag) {
2844 if (smb_fflags & info2_flags_map[i].smb_fflag) {
2845 *stat_fflags |= info2_flags_map[i].stat_fflag;
2846 } else {
2847 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2852 /* If smb_fmask is asking to set any bits that are not supported by
2853 * our flag mappings, we should fail.
2855 if ((smb_fmask & max_fmask) != smb_fmask) {
2856 return False;
2859 return True;
2863 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2864 * of file flags and birth (create) time.
2866 char *store_file_unix_basic_info2(connection_struct *conn,
2867 char *pdata,
2868 files_struct *fsp,
2869 const SMB_STRUCT_STAT *psbuf)
2871 uint32_t file_flags = 0;
2872 uint32_t flags_mask = 0;
2874 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2876 /* Create (birth) time 64 bit */
2877 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2878 pdata += 8;
2880 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2881 SIVAL(pdata, 0, file_flags); /* flags */
2882 SIVAL(pdata, 4, flags_mask); /* mask */
2883 pdata += 8;
2885 return pdata;
2888 static NTSTATUS marshall_stream_info(unsigned int num_streams,
2889 const struct stream_struct *streams,
2890 char *data,
2891 unsigned int max_data_bytes,
2892 unsigned int *data_size)
2894 unsigned int i;
2895 unsigned int ofs = 0;
2897 if (max_data_bytes < 32) {
2898 return NT_STATUS_INFO_LENGTH_MISMATCH;
2901 for (i = 0; i < num_streams; i++) {
2902 unsigned int next_offset;
2903 size_t namelen;
2904 smb_ucs2_t *namebuf;
2906 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2907 streams[i].name, &namelen) ||
2908 namelen <= 2)
2910 return NT_STATUS_INVALID_PARAMETER;
2914 * name_buf is now null-terminated, we need to marshall as not
2915 * terminated
2918 namelen -= 2;
2921 * We cannot overflow ...
2923 if ((ofs + 24 + namelen) > max_data_bytes) {
2924 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2925 i));
2926 TALLOC_FREE(namebuf);
2927 return STATUS_BUFFER_OVERFLOW;
2930 SIVAL(data, ofs+4, namelen);
2931 SOFF_T(data, ofs+8, streams[i].size);
2932 SOFF_T(data, ofs+16, streams[i].alloc_size);
2933 memcpy(data+ofs+24, namebuf, namelen);
2934 TALLOC_FREE(namebuf);
2936 next_offset = ofs + 24 + namelen;
2938 if (i == num_streams-1) {
2939 SIVAL(data, ofs, 0);
2941 else {
2942 unsigned int align = ndr_align_size(next_offset, 8);
2944 if ((next_offset + align) > max_data_bytes) {
2945 DEBUG(10, ("refusing to overflow align "
2946 "reply at stream %u\n",
2947 i));
2948 TALLOC_FREE(namebuf);
2949 return STATUS_BUFFER_OVERFLOW;
2952 memset(data+next_offset, 0, align);
2953 next_offset += align;
2955 SIVAL(data, ofs, next_offset - ofs);
2956 ofs = next_offset;
2959 ofs = next_offset;
2962 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
2964 *data_size = ofs;
2966 return NT_STATUS_OK;
2969 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
2970 TALLOC_CTX *mem_ctx,
2971 struct smb_request *req,
2972 uint16_t info_level,
2973 files_struct *fsp,
2974 struct smb_filename *smb_fname,
2975 bool delete_pending,
2976 struct timespec write_time_ts,
2977 struct ea_list *ea_list,
2978 uint16_t flags2,
2979 unsigned int max_data_bytes,
2980 size_t *fixed_portion,
2981 char **ppdata,
2982 unsigned int *pdata_size)
2984 char *pdata = *ppdata;
2985 char *dstart, *dend;
2986 unsigned int data_size;
2987 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
2988 time_t create_time, mtime, atime, c_time;
2989 SMB_STRUCT_STAT *psbuf = NULL;
2990 SMB_STRUCT_STAT *base_sp = NULL;
2991 char *p;
2992 char *base_name;
2993 char *dos_fname;
2994 int mode;
2995 int nlink;
2996 NTSTATUS status;
2997 uint64_t file_size = 0;
2998 uint64_t pos = 0;
2999 uint64_t allocation_size = 0;
3000 uint64_t file_id = 0;
3001 uint32_t access_mask = 0;
3002 size_t len = 0;
3004 if (INFO_LEVEL_IS_UNIX(info_level)) {
3005 bool ok = false;
3007 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3008 DBG_DEBUG("SMB1 unix extensions activated\n");
3009 ok = true;
3012 if ((fsp != NULL) &&
3013 (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3014 DBG_DEBUG("SMB2 posix open\n");
3015 ok = true;
3018 if (!ok) {
3019 return NT_STATUS_INVALID_LEVEL;
3023 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3024 smb_fname_str_dbg(smb_fname),
3025 fsp_fnum_dbg(fsp),
3026 info_level, max_data_bytes));
3029 * In case of querying a symlink in POSIX context,
3030 * fsp will be NULL. fdos_mode() deals with it.
3032 if (fsp != NULL) {
3033 smb_fname = fsp->fsp_name;
3035 mode = fdos_mode(fsp);
3036 psbuf = &smb_fname->st;
3038 if (fsp != NULL) {
3039 base_sp = fsp->base_fsp ?
3040 &fsp->base_fsp->fsp_name->st :
3041 &fsp->fsp_name->st;
3042 } else {
3043 base_sp = &smb_fname->st;
3046 nlink = psbuf->st_ex_nlink;
3048 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3049 nlink = 1;
3052 if ((nlink > 0) && delete_pending) {
3053 nlink -= 1;
3056 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3057 return NT_STATUS_INVALID_PARAMETER;
3060 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3061 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3062 if (*ppdata == NULL) {
3063 return NT_STATUS_NO_MEMORY;
3065 pdata = *ppdata;
3066 dstart = pdata;
3067 dend = dstart + data_size - 1;
3069 if (!is_omit_timespec(&write_time_ts) &&
3070 !INFO_LEVEL_IS_UNIX(info_level))
3072 update_stat_ex_mtime(psbuf, write_time_ts);
3075 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3076 mtime_ts = psbuf->st_ex_mtime;
3077 atime_ts = psbuf->st_ex_atime;
3078 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3080 if (lp_dos_filetime_resolution(SNUM(conn))) {
3081 dos_filetime_timespec(&create_time_ts);
3082 dos_filetime_timespec(&mtime_ts);
3083 dos_filetime_timespec(&atime_ts);
3084 dos_filetime_timespec(&ctime_ts);
3087 create_time = convert_timespec_to_time_t(create_time_ts);
3088 mtime = convert_timespec_to_time_t(mtime_ts);
3089 atime = convert_timespec_to_time_t(atime_ts);
3090 c_time = convert_timespec_to_time_t(ctime_ts);
3092 p = strrchr_m(smb_fname->base_name,'/');
3093 if (!p)
3094 base_name = smb_fname->base_name;
3095 else
3096 base_name = p+1;
3098 /* NT expects the name to be in an exact form of the *full*
3099 filename. See the trans2 torture test */
3100 if (ISDOT(base_name)) {
3101 dos_fname = talloc_strdup(mem_ctx, "\\");
3102 if (!dos_fname) {
3103 return NT_STATUS_NO_MEMORY;
3105 } else {
3106 dos_fname = talloc_asprintf(mem_ctx,
3107 "\\%s",
3108 smb_fname->base_name);
3109 if (!dos_fname) {
3110 return NT_STATUS_NO_MEMORY;
3112 if (is_named_stream(smb_fname)) {
3113 dos_fname = talloc_asprintf(dos_fname, "%s",
3114 smb_fname->stream_name);
3115 if (!dos_fname) {
3116 return NT_STATUS_NO_MEMORY;
3120 string_replace(dos_fname, '/', '\\');
3123 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3125 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3126 /* Do we have this path open ? */
3127 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3128 files_struct *fsp1 = file_find_di_first(
3129 conn->sconn, fileid, true);
3130 if (fsp1 && fsp1->initial_allocation_size) {
3131 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3135 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3136 file_size = get_file_size_stat(psbuf);
3139 if (fsp) {
3140 pos = fh_get_position_information(fsp->fh);
3143 if (fsp) {
3144 access_mask = fsp->access_mask;
3145 } else {
3146 /* GENERIC_EXECUTE mapping from Windows */
3147 access_mask = 0x12019F;
3150 /* This should be an index number - looks like
3151 dev/ino to me :-)
3153 I think this causes us to fail the IFSKIT
3154 BasicFileInformationTest. -tpot */
3155 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3157 *fixed_portion = 0;
3159 switch (info_level) {
3160 case SMB_INFO_STANDARD:
3161 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3162 data_size = 22;
3163 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3164 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3165 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3166 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3167 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3168 SSVAL(pdata,l1_attrFile,mode);
3169 break;
3171 case SMB_INFO_QUERY_EA_SIZE:
3173 unsigned int ea_size =
3174 estimate_ea_size(smb_fname->fsp);
3175 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3176 data_size = 26;
3177 srv_put_dos_date2(pdata,0,create_time);
3178 srv_put_dos_date2(pdata,4,atime);
3179 srv_put_dos_date2(pdata,8,mtime); /* write time */
3180 SIVAL(pdata,12,(uint32_t)file_size);
3181 SIVAL(pdata,16,(uint32_t)allocation_size);
3182 SSVAL(pdata,20,mode);
3183 SIVAL(pdata,22,ea_size);
3184 break;
3187 case SMB_INFO_IS_NAME_VALID:
3188 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3189 if (fsp) {
3190 /* os/2 needs this ? really ?*/
3191 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3193 /* This is only reached for qpathinfo */
3194 data_size = 0;
3195 break;
3197 case SMB_INFO_QUERY_EAS_FROM_LIST:
3199 size_t total_ea_len = 0;
3200 struct ea_list *ea_file_list = NULL;
3201 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3203 status =
3204 get_ea_list_from_fsp(mem_ctx,
3205 smb_fname->fsp,
3206 &total_ea_len, &ea_file_list);
3207 if (!NT_STATUS_IS_OK(status)) {
3208 return status;
3211 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3213 if (!ea_list || (total_ea_len > data_size)) {
3214 data_size = 4;
3215 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3216 break;
3219 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3220 break;
3223 case SMB_INFO_QUERY_ALL_EAS:
3225 /* We have data_size bytes to put EA's into. */
3226 size_t total_ea_len = 0;
3227 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3229 status = get_ea_list_from_fsp(mem_ctx,
3230 smb_fname->fsp,
3231 &total_ea_len, &ea_list);
3232 if (!NT_STATUS_IS_OK(status)) {
3233 return status;
3236 if (!ea_list || (total_ea_len > data_size)) {
3237 data_size = 4;
3238 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3239 break;
3242 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3243 break;
3246 case SMB2_FILE_FULL_EA_INFORMATION:
3248 /* We have data_size bytes to put EA's into. */
3249 size_t total_ea_len = 0;
3250 struct ea_list *ea_file_list = NULL;
3252 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3254 /*TODO: add filtering and index handling */
3256 status =
3257 get_ea_list_from_fsp(mem_ctx,
3258 smb_fname->fsp,
3259 &total_ea_len, &ea_file_list);
3260 if (!NT_STATUS_IS_OK(status)) {
3261 return status;
3263 if (!ea_file_list) {
3264 return NT_STATUS_NO_EAS_ON_FILE;
3267 status = fill_ea_chained_buffer(mem_ctx,
3268 pdata,
3269 data_size,
3270 &data_size,
3271 conn, ea_file_list);
3272 if (!NT_STATUS_IS_OK(status)) {
3273 return status;
3275 break;
3278 case SMB_FILE_BASIC_INFORMATION:
3279 case SMB_QUERY_FILE_BASIC_INFO:
3281 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3282 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3283 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3284 } else {
3285 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3286 data_size = 40;
3287 SIVAL(pdata,36,0);
3289 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3290 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3291 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3292 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3293 SIVAL(pdata,32,mode);
3295 DEBUG(5,("SMB_QFBI - "));
3296 DEBUG(5,("create: %s ", ctime(&create_time)));
3297 DEBUG(5,("access: %s ", ctime(&atime)));
3298 DEBUG(5,("write: %s ", ctime(&mtime)));
3299 DEBUG(5,("change: %s ", ctime(&c_time)));
3300 DEBUG(5,("mode: %x\n", mode));
3301 *fixed_portion = data_size;
3302 break;
3304 case SMB_FILE_STANDARD_INFORMATION:
3305 case SMB_QUERY_FILE_STANDARD_INFO:
3307 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3308 data_size = 24;
3309 SOFF_T(pdata,0,allocation_size);
3310 SOFF_T(pdata,8,file_size);
3311 SIVAL(pdata,16,nlink);
3312 SCVAL(pdata,20,delete_pending?1:0);
3313 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3314 SSVAL(pdata,22,0); /* Padding. */
3315 *fixed_portion = 24;
3316 break;
3318 case SMB_FILE_EA_INFORMATION:
3319 case SMB_QUERY_FILE_EA_INFO:
3321 unsigned int ea_size =
3322 estimate_ea_size(smb_fname->fsp);
3323 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3324 data_size = 4;
3325 *fixed_portion = 4;
3326 SIVAL(pdata,0,ea_size);
3327 break;
3330 /* Get the 8.3 name - used if NT SMB was negotiated. */
3331 case SMB_QUERY_FILE_ALT_NAME_INFO:
3332 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3334 char mangled_name[13];
3335 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3336 if (!name_to_8_3(base_name,mangled_name,
3337 True,conn->params)) {
3338 return NT_STATUS_NO_MEMORY;
3340 status = srvstr_push(dstart, flags2,
3341 pdata+4, mangled_name,
3342 PTR_DIFF(dend, pdata+4),
3343 STR_UNICODE, &len);
3344 if (!NT_STATUS_IS_OK(status)) {
3345 return status;
3347 data_size = 4 + len;
3348 SIVAL(pdata,0,len);
3349 *fixed_portion = 8;
3350 break;
3353 case SMB_QUERY_FILE_NAME_INFO:
3356 this must be *exactly* right for ACLs on mapped drives to work
3358 status = srvstr_push(dstart, flags2,
3359 pdata+4, dos_fname,
3360 PTR_DIFF(dend, pdata+4),
3361 STR_UNICODE, &len);
3362 if (!NT_STATUS_IS_OK(status)) {
3363 return status;
3365 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3366 data_size = 4 + len;
3367 SIVAL(pdata,0,len);
3368 break;
3371 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3373 char *nfname = NULL;
3375 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
3376 return NT_STATUS_INVALID_LEVEL;
3379 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3380 if (nfname == NULL) {
3381 return NT_STATUS_NO_MEMORY;
3384 if (ISDOT(nfname)) {
3385 nfname[0] = '\0';
3387 string_replace(nfname, '/', '\\');
3389 if (fsp_is_alternate_stream(fsp)) {
3390 const char *s = smb_fname->stream_name;
3391 const char *e = NULL;
3392 size_t n;
3394 SMB_ASSERT(s[0] != '\0');
3397 * smb_fname->stream_name is in form
3398 * of ':StrEam:$DATA', but we should only
3399 * append ':StrEam' here.
3402 e = strchr(&s[1], ':');
3403 if (e == NULL) {
3404 n = strlen(s);
3405 } else {
3406 n = PTR_DIFF(e, s);
3408 nfname = talloc_strndup_append(nfname, s, n);
3409 if (nfname == NULL) {
3410 return NT_STATUS_NO_MEMORY;
3414 status = srvstr_push(dstart, flags2,
3415 pdata+4, nfname,
3416 PTR_DIFF(dend, pdata+4),
3417 STR_UNICODE, &len);
3418 if (!NT_STATUS_IS_OK(status)) {
3419 return status;
3421 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3422 data_size = 4 + len;
3423 SIVAL(pdata,0,len);
3424 *fixed_portion = 8;
3425 break;
3428 case SMB_FILE_ALLOCATION_INFORMATION:
3429 case SMB_QUERY_FILE_ALLOCATION_INFO:
3430 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3431 data_size = 8;
3432 SOFF_T(pdata,0,allocation_size);
3433 break;
3435 case SMB_FILE_END_OF_FILE_INFORMATION:
3436 case SMB_QUERY_FILE_END_OF_FILEINFO:
3437 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3438 data_size = 8;
3439 SOFF_T(pdata,0,file_size);
3440 break;
3442 case SMB_QUERY_FILE_ALL_INFO:
3443 case SMB_FILE_ALL_INFORMATION:
3445 unsigned int ea_size =
3446 estimate_ea_size(smb_fname->fsp);
3447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3448 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3449 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3450 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3451 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3452 SIVAL(pdata,32,mode);
3453 SIVAL(pdata,36,0); /* padding. */
3454 pdata += 40;
3455 SOFF_T(pdata,0,allocation_size);
3456 SOFF_T(pdata,8,file_size);
3457 SIVAL(pdata,16,nlink);
3458 SCVAL(pdata,20,delete_pending);
3459 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3460 SSVAL(pdata,22,0);
3461 pdata += 24;
3462 SIVAL(pdata,0,ea_size);
3463 pdata += 4; /* EA info */
3464 status = srvstr_push(dstart, flags2,
3465 pdata+4, dos_fname,
3466 PTR_DIFF(dend, pdata+4),
3467 STR_UNICODE, &len);
3468 if (!NT_STATUS_IS_OK(status)) {
3469 return status;
3471 SIVAL(pdata,0,len);
3472 pdata += 4 + len;
3473 data_size = PTR_DIFF(pdata,(*ppdata));
3474 *fixed_portion = 10;
3475 break;
3478 case SMB2_FILE_ALL_INFORMATION:
3480 unsigned int ea_size =
3481 estimate_ea_size(smb_fname->fsp);
3482 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3483 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3484 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3485 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3486 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3487 SIVAL(pdata, 0x20, mode);
3488 SIVAL(pdata, 0x24, 0); /* padding. */
3489 SBVAL(pdata, 0x28, allocation_size);
3490 SBVAL(pdata, 0x30, file_size);
3491 SIVAL(pdata, 0x38, nlink);
3492 SCVAL(pdata, 0x3C, delete_pending);
3493 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3494 SSVAL(pdata, 0x3E, 0); /* padding */
3495 SBVAL(pdata, 0x40, file_id);
3496 SIVAL(pdata, 0x48, ea_size);
3497 SIVAL(pdata, 0x4C, access_mask);
3498 SBVAL(pdata, 0x50, pos);
3499 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3500 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3502 pdata += 0x60;
3504 status = srvstr_push(dstart, flags2,
3505 pdata+4, dos_fname,
3506 PTR_DIFF(dend, pdata+4),
3507 STR_UNICODE, &len);
3508 if (!NT_STATUS_IS_OK(status)) {
3509 return status;
3511 SIVAL(pdata,0,len);
3512 pdata += 4 + len;
3513 data_size = PTR_DIFF(pdata,(*ppdata));
3514 *fixed_portion = 104;
3515 break;
3517 case SMB_FILE_INTERNAL_INFORMATION:
3519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3520 SBVAL(pdata, 0, file_id);
3521 data_size = 8;
3522 *fixed_portion = 8;
3523 break;
3525 case SMB_FILE_ACCESS_INFORMATION:
3526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3527 SIVAL(pdata, 0, access_mask);
3528 data_size = 4;
3529 *fixed_portion = 4;
3530 break;
3532 case SMB_FILE_NAME_INFORMATION:
3533 /* Pathname with leading '\'. */
3535 size_t byte_len;
3536 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3538 SIVAL(pdata,0,byte_len);
3539 data_size = 4 + byte_len;
3540 break;
3543 case SMB_FILE_DISPOSITION_INFORMATION:
3544 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3545 data_size = 1;
3546 SCVAL(pdata,0,delete_pending);
3547 *fixed_portion = 1;
3548 break;
3550 case SMB_FILE_POSITION_INFORMATION:
3551 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3552 data_size = 8;
3553 SOFF_T(pdata,0,pos);
3554 *fixed_portion = 8;
3555 break;
3557 case SMB_FILE_MODE_INFORMATION:
3558 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3559 SIVAL(pdata,0,mode);
3560 data_size = 4;
3561 *fixed_portion = 4;
3562 break;
3564 case SMB_FILE_ALIGNMENT_INFORMATION:
3565 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3566 SIVAL(pdata,0,0); /* No alignment needed. */
3567 data_size = 4;
3568 *fixed_portion = 4;
3569 break;
3572 * NT4 server just returns "invalid query" to this - if we try
3573 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3574 * want this. JRA.
3576 /* The first statement above is false - verified using Thursby
3577 * client against NT4 -- gcolley.
3579 case SMB_QUERY_FILE_STREAM_INFO:
3580 case SMB_FILE_STREAM_INFORMATION: {
3581 unsigned int num_streams = 0;
3582 struct stream_struct *streams = NULL;
3584 DEBUG(10,("smbd_do_qfilepathinfo: "
3585 "SMB_FILE_STREAM_INFORMATION\n"));
3587 if (is_ntfs_stream_smb_fname(smb_fname)) {
3588 return NT_STATUS_INVALID_PARAMETER;
3591 status = vfs_fstreaminfo(fsp,
3592 mem_ctx,
3593 &num_streams,
3594 &streams);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 DEBUG(10, ("could not get stream info: %s\n",
3598 nt_errstr(status)));
3599 return status;
3602 status = marshall_stream_info(num_streams, streams,
3603 pdata, max_data_bytes,
3604 &data_size);
3606 if (!NT_STATUS_IS_OK(status)) {
3607 DEBUG(10, ("marshall_stream_info failed: %s\n",
3608 nt_errstr(status)));
3609 TALLOC_FREE(streams);
3610 return status;
3613 TALLOC_FREE(streams);
3615 *fixed_portion = 32;
3617 break;
3619 case SMB_QUERY_COMPRESSION_INFO:
3620 case SMB_FILE_COMPRESSION_INFORMATION:
3621 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3622 SOFF_T(pdata,0,file_size);
3623 SIVAL(pdata,8,0); /* ??? */
3624 SIVAL(pdata,12,0); /* ??? */
3625 data_size = 16;
3626 *fixed_portion = 16;
3627 break;
3629 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3630 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3631 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3632 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3633 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3634 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3635 SOFF_T(pdata,32,allocation_size);
3636 SOFF_T(pdata,40,file_size);
3637 SIVAL(pdata,48,mode);
3638 SIVAL(pdata,52,0); /* ??? */
3639 data_size = 56;
3640 *fixed_portion = 56;
3641 break;
3643 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3644 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3645 SIVAL(pdata,0,mode);
3646 SIVAL(pdata,4,0);
3647 data_size = 8;
3648 *fixed_portion = 8;
3649 break;
3652 * SMB2 UNIX Extensions.
3654 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3656 uint8_t *buf = NULL;
3657 ssize_t plen = 0;
3659 if (!(conn->sconn->using_smb2)) {
3660 return NT_STATUS_INVALID_LEVEL;
3662 if (fsp == NULL) {
3663 return NT_STATUS_INVALID_HANDLE;
3665 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3666 return NT_STATUS_INVALID_LEVEL;
3669 /* Determine the size of the posix info context */
3670 plen = store_smb2_posix_info(conn,
3671 &smb_fname->st,
3673 mode,
3674 NULL,
3676 if (plen == -1 || data_size < plen) {
3677 return NT_STATUS_INVALID_PARAMETER;
3679 buf = talloc_zero_size(mem_ctx, plen);
3680 if (buf == NULL) {
3681 return NT_STATUS_NO_MEMORY;
3684 /* Store the context in buf */
3685 store_smb2_posix_info(conn,
3686 &smb_fname->st,
3688 mode,
3689 buf,
3690 plen);
3691 memcpy(pdata, buf, plen);
3692 data_size = plen;
3693 break;
3696 default:
3697 return NT_STATUS_INVALID_LEVEL;
3700 *pdata_size = data_size;
3701 return NT_STATUS_OK;
3704 /****************************************************************************
3705 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3706 code.
3707 ****************************************************************************/
3709 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3710 connection_struct *conn,
3711 struct smb_request *req,
3712 bool overwrite_if_exists,
3713 const struct smb_filename *smb_fname_old,
3714 struct smb_filename *smb_fname_new)
3716 NTSTATUS status = NT_STATUS_OK;
3717 int ret;
3718 bool ok;
3719 struct smb_filename *parent_fname_old = NULL;
3720 struct smb_filename *base_name_old = NULL;
3721 struct smb_filename *parent_fname_new = NULL;
3722 struct smb_filename *base_name_new = NULL;
3724 /* source must already exist. */
3725 if (!VALID_STAT(smb_fname_old->st)) {
3726 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3727 goto out;
3730 /* No links from a directory. */
3731 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3732 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3733 goto out;
3736 /* Setting a hardlink to/from a stream isn't currently supported. */
3737 ok = is_ntfs_stream_smb_fname(smb_fname_old);
3738 if (ok) {
3739 DBG_DEBUG("Old name has streams\n");
3740 status = NT_STATUS_INVALID_PARAMETER;
3741 goto out;
3743 ok = is_ntfs_stream_smb_fname(smb_fname_new);
3744 if (ok) {
3745 DBG_DEBUG("New name has streams\n");
3746 status = NT_STATUS_INVALID_PARAMETER;
3747 goto out;
3750 status = parent_pathref(talloc_tos(),
3751 conn->cwd_fsp,
3752 smb_fname_old,
3753 &parent_fname_old,
3754 &base_name_old);
3755 if (!NT_STATUS_IS_OK(status)) {
3756 goto out;
3759 status = parent_pathref(talloc_tos(),
3760 conn->cwd_fsp,
3761 smb_fname_new,
3762 &parent_fname_new,
3763 &base_name_new);
3764 if (!NT_STATUS_IS_OK(status)) {
3765 goto out;
3768 if (VALID_STAT(smb_fname_new->st)) {
3769 if (overwrite_if_exists) {
3770 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3771 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3772 goto out;
3774 status = unlink_internals(conn,
3775 req,
3776 FILE_ATTRIBUTE_NORMAL,
3777 NULL, /* new_dirfsp */
3778 smb_fname_new);
3779 if (!NT_STATUS_IS_OK(status)) {
3780 goto out;
3782 } else {
3783 /* Disallow if newname already exists. */
3784 status = NT_STATUS_OBJECT_NAME_COLLISION;
3785 goto out;
3789 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3790 smb_fname_old->base_name, smb_fname_new->base_name));
3792 ret = SMB_VFS_LINKAT(conn,
3793 parent_fname_old->fsp,
3794 base_name_old,
3795 parent_fname_new->fsp,
3796 base_name_new,
3799 if (ret != 0) {
3800 status = map_nt_error_from_unix(errno);
3801 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3802 nt_errstr(status), smb_fname_old->base_name,
3803 smb_fname_new->base_name));
3806 out:
3808 TALLOC_FREE(parent_fname_old);
3809 TALLOC_FREE(parent_fname_new);
3810 return status;
3813 /****************************************************************************
3814 Deal with setting the time from any of the setfilepathinfo functions.
3815 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3816 calling this function.
3817 ****************************************************************************/
3819 NTSTATUS smb_set_file_time(connection_struct *conn,
3820 files_struct *fsp,
3821 struct smb_filename *smb_fname,
3822 struct smb_file_time *ft,
3823 bool setting_write_time)
3825 struct files_struct *set_fsp = NULL;
3826 struct timeval_buf tbuf[4];
3827 uint32_t action =
3828 FILE_NOTIFY_CHANGE_LAST_ACCESS
3829 |FILE_NOTIFY_CHANGE_LAST_WRITE
3830 |FILE_NOTIFY_CHANGE_CREATION;
3831 int ret;
3833 if (!VALID_STAT(smb_fname->st)) {
3834 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3837 if (fsp == NULL) {
3838 /* A symlink */
3839 return NT_STATUS_OK;
3842 set_fsp = metadata_fsp(fsp);
3844 /* get some defaults (no modifications) if any info is zero or -1. */
3845 if (is_omit_timespec(&ft->create_time)) {
3846 action &= ~FILE_NOTIFY_CHANGE_CREATION;
3849 if (is_omit_timespec(&ft->atime)) {
3850 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3853 if (is_omit_timespec(&ft->mtime)) {
3854 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3857 if (!setting_write_time) {
3858 /* ft->mtime comes from change time, not write time. */
3859 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3862 /* Ensure the resolution is the correct for
3863 * what we can store on this filesystem. */
3865 round_timespec(conn->ts_res, &ft->create_time);
3866 round_timespec(conn->ts_res, &ft->ctime);
3867 round_timespec(conn->ts_res, &ft->atime);
3868 round_timespec(conn->ts_res, &ft->mtime);
3870 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3871 timespec_string_buf(&ft->atime, true, &tbuf[0]));
3872 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3873 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3874 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3875 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3876 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3877 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3879 if (setting_write_time) {
3881 * This was a Windows setfileinfo on an open file.
3882 * NT does this a lot. We also need to
3883 * set the time here, as it can be read by
3884 * FindFirst/FindNext and with the patch for bug #2045
3885 * in smbd/fileio.c it ensures that this timestamp is
3886 * kept sticky even after a write. We save the request
3887 * away and will set it on file close and after a write. JRA.
3890 DBG_DEBUG("setting pending modtime to %s\n",
3891 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3893 if (set_fsp != NULL) {
3894 set_sticky_write_time_fsp(set_fsp, ft->mtime);
3895 } else {
3896 set_sticky_write_time_path(
3897 vfs_file_id_from_sbuf(conn, &smb_fname->st),
3898 ft->mtime);
3902 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3904 ret = file_ntimes(conn, set_fsp, ft);
3905 if (ret != 0) {
3906 return map_nt_error_from_unix(errno);
3909 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
3910 smb_fname->base_name);
3911 return NT_STATUS_OK;
3914 /****************************************************************************
3915 Deal with setting the dosmode from any of the setfilepathinfo functions.
3916 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3917 done before calling this function.
3918 ****************************************************************************/
3920 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3921 struct files_struct *fsp,
3922 uint32_t dosmode)
3924 struct files_struct *dos_fsp = NULL;
3925 uint32_t current_dosmode;
3926 int ret;
3928 if (!VALID_STAT(fsp->fsp_name->st)) {
3929 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3932 dos_fsp = metadata_fsp(fsp);
3934 if (dosmode != 0) {
3935 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3936 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3937 } else {
3938 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3942 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3944 /* check the mode isn't different, before changing it */
3945 if (dosmode == 0) {
3946 return NT_STATUS_OK;
3948 current_dosmode = fdos_mode(dos_fsp);
3949 if (dosmode == current_dosmode) {
3950 return NT_STATUS_OK;
3953 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
3954 fsp_str_dbg(dos_fsp), dosmode);
3956 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
3957 if (ret != 0) {
3958 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3959 fsp_str_dbg(dos_fsp), strerror(errno));
3960 return map_nt_error_from_unix(errno);
3963 return NT_STATUS_OK;
3966 /****************************************************************************
3967 Deal with setting the size from any of the setfilepathinfo functions.
3968 ****************************************************************************/
3970 NTSTATUS smb_set_file_size(connection_struct *conn,
3971 struct smb_request *req,
3972 files_struct *fsp,
3973 struct smb_filename *smb_fname,
3974 const SMB_STRUCT_STAT *psbuf,
3975 off_t size,
3976 bool fail_after_createfile)
3978 NTSTATUS status = NT_STATUS_OK;
3979 files_struct *new_fsp = NULL;
3981 if (!VALID_STAT(*psbuf)) {
3982 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3985 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
3986 (uint64_t)size,
3987 get_file_size_stat(psbuf));
3989 if (size == get_file_size_stat(psbuf)) {
3990 if (fsp == NULL) {
3991 return NT_STATUS_OK;
3993 if (!fsp->fsp_flags.modified) {
3994 return NT_STATUS_OK;
3996 trigger_write_time_update_immediate(fsp);
3997 return NT_STATUS_OK;
4000 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4001 smb_fname_str_dbg(smb_fname), (double)size));
4003 if (fsp &&
4004 !fsp->fsp_flags.is_pathref &&
4005 fsp_get_io_fd(fsp) != -1)
4007 /* Handle based call. */
4008 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4009 return NT_STATUS_ACCESS_DENIED;
4012 if (vfs_set_filelen(fsp, size) == -1) {
4013 return map_nt_error_from_unix(errno);
4015 trigger_write_time_update_immediate(fsp);
4016 return NT_STATUS_OK;
4019 status = SMB_VFS_CREATE_FILE(
4020 conn, /* conn */
4021 req, /* req */
4022 NULL, /* dirfsp */
4023 smb_fname, /* fname */
4024 FILE_WRITE_DATA, /* access_mask */
4025 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4026 FILE_SHARE_DELETE),
4027 FILE_OPEN, /* create_disposition*/
4028 0, /* create_options */
4029 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4030 0, /* oplock_request */
4031 NULL, /* lease */
4032 0, /* allocation_size */
4033 0, /* private_flags */
4034 NULL, /* sd */
4035 NULL, /* ea_list */
4036 &new_fsp, /* result */
4037 NULL, /* pinfo */
4038 NULL, NULL); /* create context */
4040 if (!NT_STATUS_IS_OK(status)) {
4041 /* NB. We check for open_was_deferred in the caller. */
4042 return status;
4045 /* See RAW-SFILEINFO-END-OF-FILE */
4046 if (fail_after_createfile) {
4047 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4048 return NT_STATUS_INVALID_LEVEL;
4051 if (vfs_set_filelen(new_fsp, size) == -1) {
4052 status = map_nt_error_from_unix(errno);
4053 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4054 return status;
4057 trigger_write_time_update_immediate(new_fsp);
4058 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4059 return NT_STATUS_OK;
4062 /****************************************************************************
4063 Deal with SMB_INFO_SET_EA.
4064 ****************************************************************************/
4066 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4067 const char *pdata,
4068 int total_data,
4069 files_struct *fsp,
4070 struct smb_filename *smb_fname)
4072 struct ea_list *ea_list = NULL;
4073 TALLOC_CTX *ctx = NULL;
4074 NTSTATUS status = NT_STATUS_OK;
4076 if (total_data < 10) {
4078 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4079 length. They seem to have no effect. Bug #3212. JRA */
4081 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4082 /* We're done. We only get EA info in this call. */
4083 return NT_STATUS_OK;
4086 return NT_STATUS_INVALID_PARAMETER;
4089 if (IVAL(pdata,0) > total_data) {
4090 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4091 IVAL(pdata,0), (unsigned int)total_data));
4092 return NT_STATUS_INVALID_PARAMETER;
4095 ctx = talloc_tos();
4096 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4097 if (!ea_list) {
4098 return NT_STATUS_INVALID_PARAMETER;
4101 if (fsp == NULL) {
4103 * The only way fsp can be NULL here is if
4104 * smb_fname points at a symlink and
4105 * and we're in POSIX context.
4106 * Ensure this is the case.
4108 * In this case we cannot set the EA.
4110 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4111 return NT_STATUS_ACCESS_DENIED;
4114 status = set_ea(conn, fsp, ea_list);
4116 return status;
4119 /****************************************************************************
4120 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4121 ****************************************************************************/
4123 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4124 const char *pdata,
4125 int total_data,
4126 files_struct *fsp)
4128 struct ea_list *ea_list = NULL;
4129 NTSTATUS status;
4131 if (fsp == NULL) {
4132 return NT_STATUS_INVALID_HANDLE;
4135 if (!lp_ea_support(SNUM(conn))) {
4136 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4137 "EA's not supported.\n",
4138 (unsigned int)total_data));
4139 return NT_STATUS_EAS_NOT_SUPPORTED;
4142 if (total_data < 10) {
4143 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4144 "too small.\n",
4145 (unsigned int)total_data));
4146 return NT_STATUS_INVALID_PARAMETER;
4149 ea_list = read_nttrans_ea_list(talloc_tos(),
4150 pdata,
4151 total_data);
4153 if (!ea_list) {
4154 return NT_STATUS_INVALID_PARAMETER;
4157 status = set_ea(conn, fsp, ea_list);
4159 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4160 smb_fname_str_dbg(fsp->fsp_name),
4161 nt_errstr(status) ));
4163 return status;
4167 /****************************************************************************
4168 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4169 ****************************************************************************/
4171 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4172 const char *pdata,
4173 int total_data,
4174 files_struct *fsp,
4175 struct smb_filename *smb_fname)
4177 NTSTATUS status = NT_STATUS_OK;
4178 bool delete_on_close;
4179 uint32_t dosmode = 0;
4181 if (total_data < 1) {
4182 return NT_STATUS_INVALID_PARAMETER;
4185 if (fsp == NULL) {
4186 return NT_STATUS_INVALID_HANDLE;
4189 delete_on_close = (CVAL(pdata,0) ? True : False);
4190 dosmode = fdos_mode(fsp);
4192 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4193 "delete_on_close = %u\n",
4194 smb_fname_str_dbg(smb_fname),
4195 (unsigned int)dosmode,
4196 (unsigned int)delete_on_close ));
4198 if (delete_on_close) {
4199 status = can_set_delete_on_close(fsp, dosmode);
4200 if (!NT_STATUS_IS_OK(status)) {
4201 return status;
4205 /* The set is across all open files on this dev/inode pair. */
4206 if (!set_delete_on_close(fsp, delete_on_close,
4207 conn->session_info->security_token,
4208 conn->session_info->unix_token)) {
4209 return NT_STATUS_ACCESS_DENIED;
4211 return NT_STATUS_OK;
4214 /****************************************************************************
4215 Deal with SMB_FILE_POSITION_INFORMATION.
4216 ****************************************************************************/
4218 static NTSTATUS smb_file_position_information(connection_struct *conn,
4219 const char *pdata,
4220 int total_data,
4221 files_struct *fsp)
4223 uint64_t position_information;
4225 if (total_data < 8) {
4226 return NT_STATUS_INVALID_PARAMETER;
4229 if (fsp == NULL) {
4230 /* Ignore on pathname based set. */
4231 return NT_STATUS_OK;
4234 position_information = (uint64_t)IVAL(pdata,0);
4235 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4237 DEBUG(10,("smb_file_position_information: Set file position "
4238 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4239 (double)position_information));
4240 fh_set_position_information(fsp->fh, position_information);
4241 return NT_STATUS_OK;
4244 /****************************************************************************
4245 Deal with SMB_FILE_MODE_INFORMATION.
4246 ****************************************************************************/
4248 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4249 const char *pdata,
4250 int total_data)
4252 uint32_t mode;
4254 if (total_data < 4) {
4255 return NT_STATUS_INVALID_PARAMETER;
4257 mode = IVAL(pdata,0);
4258 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4259 return NT_STATUS_INVALID_PARAMETER;
4261 return NT_STATUS_OK;
4264 /****************************************************************************
4265 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4266 ****************************************************************************/
4268 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4269 struct smb_request *req,
4270 const char *pdata,
4271 int total_data,
4272 files_struct *fsp,
4273 struct smb_filename *smb_fname_src)
4275 bool overwrite;
4276 uint32_t len;
4277 char *newname = NULL;
4278 struct files_struct *dst_dirfsp = NULL;
4279 struct smb_filename *smb_fname_dst = NULL;
4280 const char *dst_original_lcomp = NULL;
4281 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4282 NTSTATUS status = NT_STATUS_OK;
4283 TALLOC_CTX *ctx = talloc_tos();
4285 if (!fsp) {
4286 return NT_STATUS_INVALID_HANDLE;
4289 if (total_data < 20) {
4290 return NT_STATUS_INVALID_PARAMETER;
4293 overwrite = (CVAL(pdata,0) ? True : False);
4294 len = IVAL(pdata,16);
4296 if (len > (total_data - 20) || (len == 0)) {
4297 return NT_STATUS_INVALID_PARAMETER;
4300 (void)srvstr_pull_talloc(ctx,
4301 pdata,
4302 req->flags2,
4303 &newname,
4304 &pdata[20],
4305 len,
4306 STR_TERMINATE);
4308 if (newname == NULL) {
4309 return NT_STATUS_INVALID_PARAMETER;
4312 /* SMB2 rename paths are never DFS. */
4313 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4314 ucf_flags &= ~UCF_DFS_PATHNAME;
4316 status = check_path_syntax(newname,
4317 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4318 if (!NT_STATUS_IS_OK(status)) {
4319 return status;
4322 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4323 newname));
4325 if (newname[0] == ':') {
4326 /* Create an smb_fname to call rename_internals_fsp() with. */
4327 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4328 fsp->base_fsp->fsp_name->base_name,
4329 newname,
4330 NULL,
4331 fsp->base_fsp->fsp_name->twrp,
4332 fsp->base_fsp->fsp_name->flags);
4333 if (smb_fname_dst == NULL) {
4334 status = NT_STATUS_NO_MEMORY;
4335 goto out;
4337 } else {
4338 status = filename_convert_dirfsp(ctx,
4339 conn,
4340 newname,
4341 ucf_flags,
4342 0, /* Never a TWRP. */
4343 &dst_dirfsp,
4344 &smb_fname_dst);
4345 if (!NT_STATUS_IS_OK(status)) {
4346 goto out;
4351 * Set the original last component, since
4352 * rename_internals_fsp() requires it.
4354 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4355 conn,
4356 newname,
4357 ucf_flags);
4358 if (dst_original_lcomp == NULL) {
4359 status = NT_STATUS_NO_MEMORY;
4360 goto out;
4363 DEBUG(10,("smb2_file_rename_information: "
4364 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4365 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4366 smb_fname_str_dbg(smb_fname_dst)));
4367 status = rename_internals_fsp(conn,
4368 fsp,
4369 smb_fname_dst,
4370 dst_original_lcomp,
4371 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4372 overwrite);
4374 out:
4375 TALLOC_FREE(smb_fname_dst);
4376 return status;
4379 static NTSTATUS smb2_file_link_information(connection_struct *conn,
4380 struct smb_request *req,
4381 const char *pdata,
4382 int total_data,
4383 files_struct *fsp,
4384 struct smb_filename *smb_fname_src)
4386 bool overwrite;
4387 uint32_t len;
4388 char *newname = NULL;
4389 struct files_struct *dst_dirfsp = NULL;
4390 struct smb_filename *smb_fname_dst = NULL;
4391 NTSTATUS status = NT_STATUS_OK;
4392 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4393 size_t ret;
4394 TALLOC_CTX *ctx = talloc_tos();
4396 if (!fsp) {
4397 return NT_STATUS_INVALID_HANDLE;
4400 if (total_data < 20) {
4401 return NT_STATUS_INVALID_PARAMETER;
4404 overwrite = (CVAL(pdata,0) ? true : false);
4405 len = IVAL(pdata,16);
4407 if (len > (total_data - 20) || (len == 0)) {
4408 return NT_STATUS_INVALID_PARAMETER;
4411 ret = srvstr_pull_talloc(ctx,
4412 pdata,
4413 req->flags2,
4414 &newname,
4415 &pdata[20],
4416 len,
4417 STR_TERMINATE);
4419 if (ret == (size_t)-1 || newname == NULL) {
4420 return NT_STATUS_INVALID_PARAMETER;
4423 /* SMB2 hardlink paths are never DFS. */
4424 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4425 ucf_flags &= ~UCF_DFS_PATHNAME;
4427 status = check_path_syntax(newname,
4428 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4429 if (!NT_STATUS_IS_OK(status)) {
4430 return status;
4433 DBG_DEBUG("got name |%s|\n", newname);
4435 status = filename_convert_dirfsp(ctx,
4436 conn,
4437 newname,
4438 ucf_flags,
4439 0, /* No TWRP. */
4440 &dst_dirfsp,
4441 &smb_fname_dst);
4442 if (!NT_STATUS_IS_OK(status)) {
4443 return status;
4446 if (fsp->base_fsp) {
4447 /* No stream names. */
4448 return NT_STATUS_NOT_SUPPORTED;
4451 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4452 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4453 smb_fname_str_dbg(smb_fname_dst));
4454 status = hardlink_internals(ctx,
4455 conn,
4456 req,
4457 overwrite,
4458 fsp->fsp_name,
4459 smb_fname_dst);
4461 TALLOC_FREE(smb_fname_dst);
4462 return status;
4465 static NTSTATUS smb_file_link_information(connection_struct *conn,
4466 struct smb_request *req,
4467 const char *pdata,
4468 int total_data,
4469 files_struct *fsp,
4470 struct smb_filename *smb_fname_src)
4472 bool overwrite;
4473 uint32_t len;
4474 char *newname = NULL;
4475 struct files_struct *dst_dirfsp = NULL;
4476 struct smb_filename *smb_fname_dst = NULL;
4477 NTSTATUS status = NT_STATUS_OK;
4478 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4479 NTTIME dst_twrp = 0;
4480 TALLOC_CTX *ctx = talloc_tos();
4482 if (!fsp) {
4483 return NT_STATUS_INVALID_HANDLE;
4486 if (total_data < 20) {
4487 return NT_STATUS_INVALID_PARAMETER;
4490 overwrite = (CVAL(pdata,0) ? true : false);
4491 len = IVAL(pdata,16);
4493 if (len > (total_data - 20) || (len == 0)) {
4494 return NT_STATUS_INVALID_PARAMETER;
4497 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4498 srvstr_get_path_posix(ctx,
4499 pdata,
4500 req->flags2,
4501 &newname,
4502 &pdata[20],
4503 len,
4504 STR_TERMINATE,
4505 &status);
4506 ucf_flags |= UCF_POSIX_PATHNAMES;
4507 } else {
4508 srvstr_get_path(ctx,
4509 pdata,
4510 req->flags2,
4511 &newname,
4512 &pdata[20],
4513 len,
4514 STR_TERMINATE,
4515 &status);
4517 if (!NT_STATUS_IS_OK(status)) {
4518 return status;
4521 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4522 newname));
4524 if (ucf_flags & UCF_GMT_PATHNAME) {
4525 extract_snapshot_token(newname, &dst_twrp);
4527 /* hardlink paths are never DFS. */
4528 ucf_flags &= ~UCF_DFS_PATHNAME;
4530 status = filename_convert_dirfsp(ctx,
4531 conn,
4532 newname,
4533 ucf_flags,
4534 dst_twrp,
4535 &dst_dirfsp,
4536 &smb_fname_dst);
4537 if (!NT_STATUS_IS_OK(status)) {
4538 return status;
4541 if (fsp->base_fsp) {
4542 /* No stream names. */
4543 return NT_STATUS_NOT_SUPPORTED;
4546 DEBUG(10,("smb_file_link_information: "
4547 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4548 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4549 smb_fname_str_dbg(smb_fname_dst)));
4550 status = hardlink_internals(ctx,
4551 conn,
4552 req,
4553 overwrite,
4554 fsp->fsp_name,
4555 smb_fname_dst);
4557 TALLOC_FREE(smb_fname_dst);
4558 return status;
4562 /****************************************************************************
4563 Deal with SMB_FILE_RENAME_INFORMATION.
4564 ****************************************************************************/
4566 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4567 struct smb_request *req,
4568 const char *pdata,
4569 int total_data,
4570 files_struct *fsp,
4571 struct smb_filename *smb_fname_src)
4573 bool overwrite;
4574 uint32_t root_fid;
4575 uint32_t len;
4576 char *newname = NULL;
4577 struct files_struct *dst_dirfsp = NULL;
4578 struct smb_filename *smb_fname_dst = NULL;
4579 const char *dst_original_lcomp = NULL;
4580 NTSTATUS status = NT_STATUS_OK;
4581 char *p;
4582 TALLOC_CTX *ctx = talloc_tos();
4584 if (total_data < 13) {
4585 return NT_STATUS_INVALID_PARAMETER;
4588 overwrite = (CVAL(pdata,0) != 0);
4589 root_fid = IVAL(pdata,4);
4590 len = IVAL(pdata,8);
4592 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4593 return NT_STATUS_INVALID_PARAMETER;
4596 if (req->posix_pathnames) {
4597 srvstr_get_path_posix(ctx,
4598 pdata,
4599 req->flags2,
4600 &newname,
4601 &pdata[12],
4602 len,
4604 &status);
4605 } else {
4606 srvstr_get_path(ctx,
4607 pdata,
4608 req->flags2,
4609 &newname,
4610 &pdata[12],
4611 len,
4613 &status);
4615 if (!NT_STATUS_IS_OK(status)) {
4616 return status;
4619 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4620 newname));
4622 /* Check the new name has no '/' characters. */
4623 if (strchr_m(newname, '/')) {
4624 return NT_STATUS_NOT_SUPPORTED;
4627 if (fsp && fsp->base_fsp) {
4628 /* newname must be a stream name. */
4629 if (newname[0] != ':') {
4630 return NT_STATUS_NOT_SUPPORTED;
4633 /* Create an smb_fname to call rename_internals_fsp() with. */
4634 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4635 fsp->base_fsp->fsp_name->base_name,
4636 newname,
4637 NULL,
4638 fsp->base_fsp->fsp_name->twrp,
4639 fsp->base_fsp->fsp_name->flags);
4640 if (smb_fname_dst == NULL) {
4641 status = NT_STATUS_NO_MEMORY;
4642 goto out;
4646 * Get the original last component, since
4647 * rename_internals_fsp() requires it.
4649 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4650 conn,
4651 newname,
4653 if (dst_original_lcomp == NULL) {
4654 status = NT_STATUS_NO_MEMORY;
4655 goto out;
4658 } else {
4660 * Build up an smb_fname_dst based on the filename passed in.
4661 * We basically just strip off the last component, and put on
4662 * the newname instead.
4664 char *base_name = NULL;
4665 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4666 NTTIME dst_twrp = 0;
4668 /* newname must *not* be a stream name. */
4669 if (newname[0] == ':') {
4670 return NT_STATUS_NOT_SUPPORTED;
4674 * Strip off the last component (filename) of the path passed
4675 * in.
4677 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4678 if (!base_name) {
4679 return NT_STATUS_NO_MEMORY;
4681 p = strrchr_m(base_name, '/');
4682 if (p) {
4683 p[1] = '\0';
4684 } else {
4685 base_name = talloc_strdup(ctx, "");
4686 if (!base_name) {
4687 return NT_STATUS_NO_MEMORY;
4690 /* Append the new name. */
4691 base_name = talloc_asprintf_append(base_name,
4692 "%s",
4693 newname);
4694 if (!base_name) {
4695 return NT_STATUS_NO_MEMORY;
4698 if (ucf_flags & UCF_GMT_PATHNAME) {
4699 extract_snapshot_token(base_name, &dst_twrp);
4702 /* The newname is *not* a DFS path. */
4703 ucf_flags &= ~UCF_DFS_PATHNAME;
4705 status = filename_convert_dirfsp(ctx,
4706 conn,
4707 base_name,
4708 ucf_flags,
4709 dst_twrp,
4710 &dst_dirfsp,
4711 &smb_fname_dst);
4713 if (!NT_STATUS_IS_OK(status)) {
4714 goto out;
4716 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4717 conn,
4718 newname,
4719 ucf_flags);
4720 if (dst_original_lcomp == NULL) {
4721 status = NT_STATUS_NO_MEMORY;
4722 goto out;
4726 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4727 DEBUG(10,("smb_file_rename_information: "
4728 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4729 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4730 smb_fname_str_dbg(smb_fname_dst)));
4731 status = rename_internals_fsp(conn,
4732 fsp,
4733 smb_fname_dst,
4734 dst_original_lcomp,
4736 overwrite);
4737 } else {
4738 DEBUG(10,("smb_file_rename_information: "
4739 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4740 smb_fname_str_dbg(smb_fname_src),
4741 smb_fname_str_dbg(smb_fname_dst)));
4742 status = rename_internals(ctx,
4743 conn,
4744 req,
4745 NULL, /* src_dirfsp */
4746 smb_fname_src,
4747 smb_fname_dst,
4748 dst_original_lcomp,
4750 overwrite,
4751 FILE_WRITE_ATTRIBUTES);
4753 out:
4754 TALLOC_FREE(smb_fname_dst);
4755 return status;
4758 /****************************************************************************
4759 Deal with SMB_SET_FILE_BASIC_INFO.
4760 ****************************************************************************/
4762 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4763 const char *pdata,
4764 int total_data,
4765 files_struct *fsp,
4766 struct smb_filename *smb_fname)
4768 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4769 struct smb_file_time ft;
4770 uint32_t dosmode = 0;
4771 NTSTATUS status = NT_STATUS_OK;
4773 init_smb_file_time(&ft);
4775 if (total_data < 36) {
4776 return NT_STATUS_INVALID_PARAMETER;
4779 if (fsp == NULL) {
4780 return NT_STATUS_INVALID_HANDLE;
4783 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4784 if (!NT_STATUS_IS_OK(status)) {
4785 return status;
4788 /* Set the attributes */
4789 dosmode = IVAL(pdata,32);
4790 status = smb_set_file_dosmode(conn, fsp, dosmode);
4791 if (!NT_STATUS_IS_OK(status)) {
4792 return status;
4795 /* create time */
4796 ft.create_time = pull_long_date_full_timespec(pdata);
4798 /* access time */
4799 ft.atime = pull_long_date_full_timespec(pdata+8);
4801 /* write time. */
4802 ft.mtime = pull_long_date_full_timespec(pdata+16);
4804 /* change time. */
4805 ft.ctime = pull_long_date_full_timespec(pdata+24);
4807 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4808 smb_fname_str_dbg(smb_fname)));
4810 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4811 if (!NT_STATUS_IS_OK(status)) {
4812 return status;
4815 if (fsp->fsp_flags.modified) {
4816 trigger_write_time_update_immediate(fsp);
4818 return NT_STATUS_OK;
4821 /****************************************************************************
4822 Deal with SMB_INFO_STANDARD.
4823 ****************************************************************************/
4825 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4826 const char *pdata,
4827 int total_data,
4828 files_struct *fsp,
4829 struct smb_filename *smb_fname)
4831 NTSTATUS status;
4832 struct smb_file_time ft;
4834 init_smb_file_time(&ft);
4836 if (total_data < 12) {
4837 return NT_STATUS_INVALID_PARAMETER;
4840 if (fsp == NULL) {
4841 return NT_STATUS_INVALID_HANDLE;
4844 /* create time */
4845 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4846 /* access time */
4847 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4848 /* write time */
4849 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4851 DEBUG(10,("smb_set_info_standard: file %s\n",
4852 smb_fname_str_dbg(smb_fname)));
4854 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4855 if (!NT_STATUS_IS_OK(status)) {
4856 return status;
4859 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4860 if (!NT_STATUS_IS_OK(status)) {
4861 return status;
4864 if (fsp->fsp_flags.modified) {
4865 trigger_write_time_update_immediate(fsp);
4867 return NT_STATUS_OK;
4870 /****************************************************************************
4871 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4872 ****************************************************************************/
4874 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4875 struct smb_request *req,
4876 const char *pdata,
4877 int total_data,
4878 files_struct *fsp,
4879 struct smb_filename *smb_fname)
4881 uint64_t allocation_size = 0;
4882 NTSTATUS status = NT_STATUS_OK;
4883 files_struct *new_fsp = NULL;
4885 if (!VALID_STAT(smb_fname->st)) {
4886 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4889 if (total_data < 8) {
4890 return NT_STATUS_INVALID_PARAMETER;
4893 allocation_size = (uint64_t)IVAL(pdata,0);
4894 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4895 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4896 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4897 (double)allocation_size));
4899 if (allocation_size) {
4900 allocation_size = smb_roundup(conn, allocation_size);
4903 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4904 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
4905 (double)allocation_size));
4907 if (fsp &&
4908 !fsp->fsp_flags.is_pathref &&
4909 fsp_get_io_fd(fsp) != -1)
4911 /* Open file handle. */
4912 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4913 return NT_STATUS_ACCESS_DENIED;
4916 /* Only change if needed. */
4917 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4918 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4919 return map_nt_error_from_unix(errno);
4922 /* But always update the time. */
4924 * This is equivalent to a write. Ensure it's seen immediately
4925 * if there are no pending writes.
4927 trigger_write_time_update_immediate(fsp);
4928 return NT_STATUS_OK;
4931 /* Pathname or stat or directory file. */
4932 status = SMB_VFS_CREATE_FILE(
4933 conn, /* conn */
4934 req, /* req */
4935 NULL, /* dirfsp */
4936 smb_fname, /* fname */
4937 FILE_WRITE_DATA, /* access_mask */
4938 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4939 FILE_SHARE_DELETE),
4940 FILE_OPEN, /* create_disposition*/
4941 0, /* create_options */
4942 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4943 0, /* oplock_request */
4944 NULL, /* lease */
4945 0, /* allocation_size */
4946 0, /* private_flags */
4947 NULL, /* sd */
4948 NULL, /* ea_list */
4949 &new_fsp, /* result */
4950 NULL, /* pinfo */
4951 NULL, NULL); /* create context */
4953 if (!NT_STATUS_IS_OK(status)) {
4954 /* NB. We check for open_was_deferred in the caller. */
4955 return status;
4958 /* Only change if needed. */
4959 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4960 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4961 status = map_nt_error_from_unix(errno);
4962 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4963 return status;
4967 /* Changing the allocation size should set the last mod time. */
4969 * This is equivalent to a write. Ensure it's seen immediately
4970 * if there are no pending writes.
4972 trigger_write_time_update_immediate(new_fsp);
4973 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4974 return NT_STATUS_OK;
4977 /****************************************************************************
4978 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4979 ****************************************************************************/
4981 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4982 struct smb_request *req,
4983 const char *pdata,
4984 int total_data,
4985 files_struct *fsp,
4986 struct smb_filename *smb_fname,
4987 bool fail_after_createfile)
4989 off_t size;
4991 if (total_data < 8) {
4992 return NT_STATUS_INVALID_PARAMETER;
4995 size = IVAL(pdata,0);
4996 size |= (((off_t)IVAL(pdata,4)) << 32);
4997 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4998 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4999 (double)size));
5001 return smb_set_file_size(conn, req,
5002 fsp,
5003 smb_fname,
5004 &smb_fname->st,
5005 size,
5006 fail_after_createfile);
5009 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5010 struct smb_request *req,
5011 TALLOC_CTX *mem_ctx,
5012 uint16_t info_level,
5013 files_struct *fsp,
5014 struct smb_filename *smb_fname,
5015 char **ppdata, int total_data,
5016 int *ret_data_size)
5018 char *pdata = *ppdata;
5019 NTSTATUS status = NT_STATUS_OK;
5020 int data_return_size = 0;
5022 *ret_data_size = 0;
5024 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5025 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5026 fsp_fnum_dbg(fsp),
5027 info_level, total_data));
5029 switch (info_level) {
5031 case SMB_INFO_STANDARD:
5033 status = smb_set_info_standard(conn,
5034 pdata,
5035 total_data,
5036 fsp,
5037 smb_fname);
5038 break;
5041 case SMB_INFO_SET_EA:
5043 status = smb_info_set_ea(conn,
5044 pdata,
5045 total_data,
5046 fsp,
5047 smb_fname);
5048 break;
5051 case SMB_SET_FILE_BASIC_INFO:
5052 case SMB_FILE_BASIC_INFORMATION:
5054 status = smb_set_file_basic_info(conn,
5055 pdata,
5056 total_data,
5057 fsp,
5058 smb_fname);
5059 break;
5062 case SMB_FILE_ALLOCATION_INFORMATION:
5063 case SMB_SET_FILE_ALLOCATION_INFO:
5065 status = smb_set_file_allocation_info(conn, req,
5066 pdata,
5067 total_data,
5068 fsp,
5069 smb_fname);
5070 break;
5073 case SMB_FILE_END_OF_FILE_INFORMATION:
5074 case SMB_SET_FILE_END_OF_FILE_INFO:
5077 * XP/Win7 both fail after the createfile with
5078 * SMB_SET_FILE_END_OF_FILE_INFO but not
5079 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5080 * The level is known here, so pass it down
5081 * appropriately.
5083 bool should_fail =
5084 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5086 status = smb_set_file_end_of_file_info(conn, req,
5087 pdata,
5088 total_data,
5089 fsp,
5090 smb_fname,
5091 should_fail);
5092 break;
5095 case SMB_FILE_DISPOSITION_INFORMATION:
5096 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5098 #if 0
5099 /* JRA - We used to just ignore this on a path ?
5100 * Shouldn't this be invalid level on a pathname
5101 * based call ?
5103 if (tran_call != TRANSACT2_SETFILEINFO) {
5104 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5106 #endif
5107 status = smb_set_file_disposition_info(conn,
5108 pdata,
5109 total_data,
5110 fsp,
5111 smb_fname);
5112 break;
5115 case SMB_FILE_POSITION_INFORMATION:
5117 status = smb_file_position_information(conn,
5118 pdata,
5119 total_data,
5120 fsp);
5121 break;
5124 case SMB_FILE_FULL_EA_INFORMATION:
5126 status = smb_set_file_full_ea_info(conn,
5127 pdata,
5128 total_data,
5129 fsp);
5130 break;
5133 /* From tridge Samba4 :
5134 * MODE_INFORMATION in setfileinfo (I have no
5135 * idea what "mode information" on a file is - it takes a value of 0,
5136 * 2, 4 or 6. What could it be?).
5139 case SMB_FILE_MODE_INFORMATION:
5141 status = smb_file_mode_information(conn,
5142 pdata,
5143 total_data);
5144 break;
5147 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5148 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5149 case SMB_FILE_SHORT_NAME_INFORMATION:
5150 return NT_STATUS_NOT_SUPPORTED;
5152 case SMB_FILE_RENAME_INFORMATION:
5154 status = smb_file_rename_information(conn, req,
5155 pdata, total_data,
5156 fsp, smb_fname);
5157 break;
5160 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5162 /* SMB2 rename information. */
5163 status = smb2_file_rename_information(conn, req,
5164 pdata, total_data,
5165 fsp, smb_fname);
5166 break;
5169 case SMB_FILE_LINK_INFORMATION:
5171 if (conn->sconn->using_smb2) {
5172 status = smb2_file_link_information(conn,
5173 req,
5174 pdata,
5175 total_data,
5176 fsp,
5177 smb_fname);
5178 } else {
5179 status = smb_file_link_information(conn,
5180 req,
5181 pdata,
5182 total_data,
5183 fsp,
5184 smb_fname);
5186 break;
5189 default:
5190 return NT_STATUS_INVALID_LEVEL;
5193 if (!NT_STATUS_IS_OK(status)) {
5194 return status;
5197 *ret_data_size = data_return_size;
5198 return NT_STATUS_OK;
5201 static uint32_t generate_volume_serial_number(
5202 const struct loadparm_substitution *lp_sub,
5203 int snum)
5205 int serial = lp_volume_serial_number(snum);
5206 return serial != -1 ? serial:
5207 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5208 (str_checksum(get_local_machine_name())<<16);