smbd: rename check_access_fsp() to check_any_access_fsp()
[Samba.git] / source3 / smbd / smb2_trans2.c
blob81fa867688d795c45532bfef6e549b5e1a13a842
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"
50 #include "source3/smbd/dir.h"
52 #define DIR_ENTRY_SAFETY_MARGIN 4096
54 static uint32_t generate_volume_serial_number(
55 const struct loadparm_substitution *lp_sub,
56 int snum);
58 /****************************************************************************
59 Check if an open file handle is a symlink.
60 ****************************************************************************/
62 NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
65 if (!VALID_STAT(fsp->fsp_name->st)) {
66 return NT_STATUS_ACCESS_DENIED;
68 if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
69 return NT_STATUS_ACCESS_DENIED;
71 if (fsp_get_pathref_fd(fsp) == -1) {
72 return NT_STATUS_ACCESS_DENIED;
74 return NT_STATUS_OK;
77 /**
78 * Check that one or more of the rights in access_mask are
79 * allowed. Iow, access_mask can contain more then one right and
80 * it is sufficient having only one of those granted to pass.
81 **/
82 NTSTATUS check_any_access_fsp(struct files_struct *fsp,
83 uint32_t access_mask)
85 if (!fsp->fsp_flags.is_fsa) {
86 return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
87 fsp,
88 false,
89 access_mask);
91 if (!(fsp->access_mask & access_mask)) {
92 return NT_STATUS_ACCESS_DENIED;
94 return NT_STATUS_OK;
97 /********************************************************************
98 Roundup a value to the nearest allocation roundup size boundary.
99 Only do this for Windows clients.
100 ********************************************************************/
102 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
104 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
106 /* Only roundup for Windows clients. */
107 enum remote_arch_types ra_type = get_remote_arch();
108 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
109 val = SMB_ROUNDUP(val,rval);
111 return val;
114 /****************************************************************************
115 Utility functions for dealing with extended attributes.
116 ****************************************************************************/
118 /****************************************************************************
119 Refuse to allow clients to overwrite our private xattrs.
120 ****************************************************************************/
122 bool samba_private_attr_name(const char *unix_ea_name)
124 bool prohibited = false;
126 prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
127 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
128 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
129 prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
130 prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
132 if (prohibited) {
133 return true;
136 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
137 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
138 return true;
140 return false;
143 /****************************************************************************
144 Get one EA value. Fill in a struct ea_struct.
145 ****************************************************************************/
147 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
148 files_struct *fsp,
149 const char *ea_name,
150 struct ea_struct *pea)
152 /* Get the value of this xattr. Max size is 64k. */
153 size_t attr_size = 256;
154 char *val = NULL;
155 ssize_t sizeret;
156 size_t max_xattr_size = 0;
157 NTSTATUS status;
159 if (fsp == NULL) {
160 return NT_STATUS_INVALID_HANDLE;
162 status = refuse_symlink_fsp(fsp);
163 if (!NT_STATUS_IS_OK(status)) {
164 return status;
167 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
169 again:
171 val = talloc_realloc(mem_ctx, val, char, attr_size);
172 if (!val) {
173 return NT_STATUS_NO_MEMORY;
176 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
177 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
178 attr_size = max_xattr_size;
179 goto again;
182 if (sizeret == -1) {
183 return map_nt_error_from_unix(errno);
186 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
187 dump_data(10, (uint8_t *)val, sizeret);
189 pea->flags = 0;
190 if (strnequal(ea_name, "user.", 5)) {
191 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
192 } else {
193 pea->name = talloc_strdup(mem_ctx, ea_name);
195 if (pea->name == NULL) {
196 TALLOC_FREE(val);
197 return NT_STATUS_NO_MEMORY;
199 pea->value.data = (unsigned char *)val;
200 pea->value.length = (size_t)sizeret;
201 return NT_STATUS_OK;
204 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
205 files_struct *fsp,
206 char ***pnames,
207 size_t *pnum_names)
209 char smallbuf[1024];
210 /* Get a list of all xattrs. Max namesize is 64k. */
211 size_t ea_namelist_size = 1024;
212 char *ea_namelist = smallbuf;
213 char *to_free = NULL;
215 char *p;
216 char **names;
217 size_t num_names;
218 ssize_t sizeret = -1;
219 NTSTATUS status;
221 if (pnames) {
222 *pnames = NULL;
224 *pnum_names = 0;
226 if ((fsp == NULL) || !NT_STATUS_IS_OK(refuse_symlink_fsp(fsp))) {
228 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
229 * symlink. This is ok, handle it here, by just return no EA's
230 * on a symlink.
232 return NT_STATUS_OK;
235 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
236 ea_namelist_size);
238 if ((sizeret == -1) && (errno == ERANGE)) {
239 ea_namelist_size = 65536;
240 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
241 if (ea_namelist == NULL) {
242 return NT_STATUS_NO_MEMORY;
244 to_free = ea_namelist;
246 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
247 ea_namelist_size);
250 if (sizeret == -1) {
251 status = map_nt_error_from_unix(errno);
252 TALLOC_FREE(to_free);
253 return status;
256 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
258 if (sizeret == 0) {
259 TALLOC_FREE(to_free);
260 return NT_STATUS_OK;
264 * Ensure the result is 0-terminated
267 if (ea_namelist[sizeret-1] != '\0') {
268 TALLOC_FREE(to_free);
269 return NT_STATUS_INTERNAL_ERROR;
273 * count the names
275 num_names = 0;
277 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
278 num_names += 1;
281 *pnum_names = num_names;
283 if (pnames == NULL) {
284 TALLOC_FREE(to_free);
285 return NT_STATUS_OK;
288 names = talloc_array(mem_ctx, char *, num_names);
289 if (names == NULL) {
290 DEBUG(0, ("talloc failed\n"));
291 TALLOC_FREE(to_free);
292 return NT_STATUS_NO_MEMORY;
295 if (ea_namelist == smallbuf) {
296 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
297 if (ea_namelist == NULL) {
298 TALLOC_FREE(names);
299 return NT_STATUS_NO_MEMORY;
301 } else {
302 talloc_steal(names, ea_namelist);
304 ea_namelist = talloc_realloc(names, ea_namelist, char,
305 sizeret);
306 if (ea_namelist == NULL) {
307 TALLOC_FREE(names);
308 return NT_STATUS_NO_MEMORY;
312 num_names = 0;
314 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
315 names[num_names++] = p;
318 *pnames = names;
320 return NT_STATUS_OK;
323 /****************************************************************************
324 Return a linked list of the total EA's. Plus the total size
325 ****************************************************************************/
327 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
328 files_struct *fsp,
329 size_t *pea_total_len,
330 struct ea_list **ea_list)
332 /* Get a list of all xattrs. Max namesize is 64k. */
333 size_t i, num_names;
334 char **names;
335 struct ea_list *ea_list_head = NULL;
336 bool posix_pathnames = false;
337 NTSTATUS status;
339 *pea_total_len = 0;
340 *ea_list = NULL;
342 /* symlink */
343 if (fsp == NULL) {
344 return NT_STATUS_OK;
347 if (!lp_ea_support(SNUM(fsp->conn))) {
348 return NT_STATUS_OK;
351 if (fsp_is_alternate_stream(fsp)) {
352 return NT_STATUS_INVALID_PARAMETER;
355 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
357 status = get_ea_names_from_fsp(talloc_tos(),
358 fsp,
359 &names,
360 &num_names);
362 if (!NT_STATUS_IS_OK(status)) {
363 return status;
366 if (num_names == 0) {
367 return NT_STATUS_OK;
370 for (i=0; i<num_names; i++) {
371 struct ea_list *listp;
372 fstring dos_ea_name;
375 * POSIX EA names are divided into several namespaces by
376 * means of string prefixes. Usually, the system controls
377 * semantics for each namespace, but the 'user' namespace is
378 * available for arbitrary use, which comes closest to
379 * Windows EA semantics. Hence, we map POSIX EAs from the
380 * 'user' namespace to Windows EAs, and just ignore all the
381 * other namespaces. Also, a few specific names in the 'user'
382 * namespace are used by Samba internally. Filter them out as
383 * well, and only present the EAs that are available for
384 * arbitrary use.
386 if (!strnequal(names[i], "user.", 5)
387 || samba_private_attr_name(names[i]))
388 continue;
391 * Filter out any underlying POSIX EA names
392 * that a Windows client can't handle.
394 if (!posix_pathnames &&
395 is_invalid_windows_ea_name(names[i])) {
396 continue;
399 listp = talloc(mem_ctx, struct ea_list);
400 if (listp == NULL) {
401 return NT_STATUS_NO_MEMORY;
404 status = get_ea_value_fsp(listp,
405 fsp,
406 names[i],
407 &listp->ea);
409 if (!NT_STATUS_IS_OK(status)) {
410 TALLOC_FREE(listp);
411 return status;
414 if (listp->ea.value.length == 0) {
416 * We can never return a zero length EA.
417 * Windows reports the EA's as corrupted.
419 TALLOC_FREE(listp);
420 continue;
421 } else if (listp->ea.value.length > 65536) {
423 * SMB clients may report error with file
424 * if large EA is presented to them.
426 DBG_ERR("EA [%s] on file [%s] exceeds "
427 "maximum permitted EA size of 64KiB: %zu\n.",
428 listp->ea.name, fsp_str_dbg(fsp),
429 listp->ea.value.length);
430 TALLOC_FREE(listp);
431 continue;
434 push_ascii_fstring(dos_ea_name, listp->ea.name);
436 *pea_total_len +=
437 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
439 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
440 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
441 (unsigned int)listp->ea.value.length));
443 DLIST_ADD_END(ea_list_head, listp);
447 /* Add on 4 for total length. */
448 if (*pea_total_len) {
449 *pea_total_len += 4;
452 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
453 (unsigned int)*pea_total_len));
455 *ea_list = ea_list_head;
456 return NT_STATUS_OK;
459 /****************************************************************************
460 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
461 that was filled.
462 ****************************************************************************/
464 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
465 connection_struct *conn, struct ea_list *ea_list)
467 unsigned int ret_data_size = 4;
468 char *p = pdata;
470 SMB_ASSERT(total_data_size >= 4);
472 if (!lp_ea_support(SNUM(conn))) {
473 SIVAL(pdata,4,0);
474 return 4;
477 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
478 size_t dos_namelen;
479 fstring dos_ea_name;
480 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
481 dos_namelen = strlen(dos_ea_name);
482 if (dos_namelen > 255 || dos_namelen == 0) {
483 break;
485 if (ea_list->ea.value.length > 65535) {
486 break;
488 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
489 break;
492 /* We know we have room. */
493 SCVAL(p,0,ea_list->ea.flags);
494 SCVAL(p,1,dos_namelen);
495 SSVAL(p,2,ea_list->ea.value.length);
496 strlcpy(p+4, dos_ea_name, dos_namelen+1);
497 if (ea_list->ea.value.length > 0) {
498 memcpy(p + 4 + dos_namelen + 1,
499 ea_list->ea.value.data,
500 ea_list->ea.value.length);
503 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
504 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
507 ret_data_size = PTR_DIFF(p, pdata);
508 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
509 SIVAL(pdata,0,ret_data_size);
510 return ret_data_size;
513 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
514 char *pdata,
515 unsigned int total_data_size,
516 unsigned int *ret_data_size,
517 connection_struct *conn,
518 struct ea_list *ea_list)
520 uint8_t *p = (uint8_t *)pdata;
521 uint8_t *last_start = NULL;
522 bool do_store_data = (pdata != NULL);
524 *ret_data_size = 0;
526 if (!lp_ea_support(SNUM(conn))) {
527 return NT_STATUS_NO_EAS_ON_FILE;
530 for (; ea_list; ea_list = ea_list->next) {
531 size_t dos_namelen;
532 fstring dos_ea_name;
533 size_t this_size;
534 size_t pad = 0;
536 if (last_start != NULL && do_store_data) {
537 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
539 last_start = p;
541 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
542 dos_namelen = strlen(dos_ea_name);
543 if (dos_namelen > 255 || dos_namelen == 0) {
544 return NT_STATUS_INTERNAL_ERROR;
546 if (ea_list->ea.value.length > 65535) {
547 return NT_STATUS_INTERNAL_ERROR;
550 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
552 if (ea_list->next) {
553 pad = (4 - (this_size % 4)) % 4;
554 this_size += pad;
557 if (do_store_data) {
558 if (this_size > total_data_size) {
559 return NT_STATUS_INFO_LENGTH_MISMATCH;
562 /* We know we have room. */
563 SIVAL(p, 0x00, 0); /* next offset */
564 SCVAL(p, 0x04, ea_list->ea.flags);
565 SCVAL(p, 0x05, dos_namelen);
566 SSVAL(p, 0x06, ea_list->ea.value.length);
567 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
568 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
569 if (pad) {
570 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
571 '\0',
572 pad);
574 total_data_size -= this_size;
577 p += this_size;
580 *ret_data_size = PTR_DIFF(p, pdata);
581 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
582 return NT_STATUS_OK;
585 unsigned int estimate_ea_size(files_struct *fsp)
587 size_t total_ea_len = 0;
588 TALLOC_CTX *mem_ctx;
589 struct ea_list *ea_list = NULL;
590 NTSTATUS status;
592 /* symlink */
593 if (fsp == NULL) {
594 return 0;
597 if (!lp_ea_support(SNUM(fsp->conn))) {
598 return 0;
601 mem_ctx = talloc_stackframe();
603 /* If this is a stream fsp, then we need to instead find the
604 * estimated ea len from the main file, not the stream
605 * (streams cannot have EAs), but the estimate isn't just 0 in
606 * this case! */
607 fsp = metadata_fsp(fsp);
608 (void)get_ea_list_from_fsp(mem_ctx,
609 fsp,
610 &total_ea_len,
611 &ea_list);
613 if(fsp->conn->sconn->using_smb2) {
614 unsigned int ret_data_size;
616 * We're going to be using fill_ea_chained_buffer() to
617 * marshall EA's - this size is significantly larger
618 * than the SMB1 buffer. Re-calculate the size without
619 * marshalling.
621 status = fill_ea_chained_buffer(mem_ctx,
622 NULL,
624 &ret_data_size,
625 fsp->conn,
626 ea_list);
627 if (!NT_STATUS_IS_OK(status)) {
628 ret_data_size = 0;
630 total_ea_len = ret_data_size;
632 TALLOC_FREE(mem_ctx);
633 return total_ea_len;
636 /****************************************************************************
637 Ensure the EA name is case insensitive by matching any existing EA name.
638 ****************************************************************************/
640 static void canonicalize_ea_name(files_struct *fsp,
641 fstring unix_ea_name)
643 size_t total_ea_len;
644 TALLOC_CTX *mem_ctx = talloc_tos();
645 struct ea_list *ea_list;
646 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
647 fsp,
648 &total_ea_len,
649 &ea_list);
650 if (!NT_STATUS_IS_OK(status)) {
651 return;
654 for (; ea_list; ea_list = ea_list->next) {
655 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
656 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
657 &unix_ea_name[5], ea_list->ea.name));
658 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
659 break;
664 /****************************************************************************
665 Set or delete an extended attribute.
666 ****************************************************************************/
668 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
669 struct ea_list *ea_list)
671 NTSTATUS status;
672 bool posix_pathnames = false;
674 if (!lp_ea_support(SNUM(conn))) {
675 return NT_STATUS_EAS_NOT_SUPPORTED;
678 if (fsp == NULL) {
679 return NT_STATUS_INVALID_HANDLE;
682 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
684 status = refuse_symlink_fsp(fsp);
685 if (!NT_STATUS_IS_OK(status)) {
686 return status;
689 status = check_any_access_fsp(fsp, FILE_WRITE_EA);
690 if (!NT_STATUS_IS_OK(status)) {
691 return status;
694 /* Setting EAs on streams isn't supported. */
695 if (fsp_is_alternate_stream(fsp)) {
696 return NT_STATUS_INVALID_PARAMETER;
700 * Filter out invalid Windows EA names - before
701 * we set *any* of them.
704 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
705 return STATUS_INVALID_EA_NAME;
708 for (;ea_list; ea_list = ea_list->next) {
709 int ret;
710 fstring unix_ea_name;
713 * Complementing the forward mapping from POSIX EAs to
714 * Windows EAs in get_ea_list_from_fsp(), here we map in the
715 * opposite direction from Windows EAs to the 'user' namespace
716 * of POSIX EAs. Hence, all POSIX EA names the we set here must
717 * start with a 'user.' prefix.
719 fstrcpy(unix_ea_name, "user.");
720 fstrcat(unix_ea_name, ea_list->ea.name);
722 canonicalize_ea_name(fsp, unix_ea_name);
724 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
726 if (samba_private_attr_name(unix_ea_name)) {
727 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
728 return NT_STATUS_ACCESS_DENIED;
731 if (ea_list->ea.value.length == 0) {
732 /* Remove the attribute. */
733 DBG_DEBUG("deleting ea name %s on "
734 "file %s by file descriptor.\n",
735 unix_ea_name, fsp_str_dbg(fsp));
736 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
737 #ifdef ENOATTR
738 /* Removing a non existent attribute always succeeds. */
739 if (ret == -1 && errno == ENOATTR) {
740 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
741 unix_ea_name));
742 ret = 0;
744 #endif
745 } else {
746 DEBUG(10,("set_ea: setting ea name %s on file "
747 "%s by file descriptor.\n",
748 unix_ea_name, fsp_str_dbg(fsp)));
749 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
750 ea_list->ea.value.data, ea_list->ea.value.length, 0);
753 if (ret == -1) {
754 #ifdef ENOTSUP
755 if (errno == ENOTSUP) {
756 return NT_STATUS_EAS_NOT_SUPPORTED;
758 #endif
759 return map_nt_error_from_unix(errno);
763 return NT_STATUS_OK;
766 /****************************************************************************
767 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
768 ****************************************************************************/
770 struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
772 struct ea_list *ea_list_head = NULL;
773 size_t offset = 0;
774 size_t bytes_used = 0;
776 while (offset < data_size) {
777 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
779 if (!eal) {
780 return NULL;
783 DLIST_ADD_END(ea_list_head, eal);
784 offset += bytes_used;
787 return ea_list_head;
790 /****************************************************************************
791 Count the total EA size needed.
792 ****************************************************************************/
794 static size_t ea_list_size(struct ea_list *ealist)
796 fstring dos_ea_name;
797 struct ea_list *listp;
798 size_t ret = 0;
800 for (listp = ealist; listp; listp = listp->next) {
801 push_ascii_fstring(dos_ea_name, listp->ea.name);
802 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
804 /* Add on 4 for total length. */
805 if (ret) {
806 ret += 4;
809 return ret;
812 /****************************************************************************
813 Return a union of EA's from a file list and a list of names.
814 The TALLOC context for the two lists *MUST* be identical as we steal
815 memory from one list to add to another. JRA.
816 ****************************************************************************/
818 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
820 struct ea_list *nlistp, *flistp;
822 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
823 for (flistp = file_list; flistp; flistp = flistp->next) {
824 if (strequal(nlistp->ea.name, flistp->ea.name)) {
825 break;
829 if (flistp) {
830 /* Copy the data from this entry. */
831 nlistp->ea.flags = flistp->ea.flags;
832 nlistp->ea.value = flistp->ea.value;
833 } else {
834 /* Null entry. */
835 nlistp->ea.flags = 0;
836 ZERO_STRUCT(nlistp->ea.value);
840 *total_ea_len = ea_list_size(name_list);
841 return name_list;
844 /****************************************************************************
845 Return the filetype for UNIX extensions.
846 ****************************************************************************/
848 static uint32_t unix_filetype(mode_t mode)
850 if(S_ISREG(mode))
851 return UNIX_TYPE_FILE;
852 else if(S_ISDIR(mode))
853 return UNIX_TYPE_DIR;
854 #ifdef S_ISLNK
855 else if(S_ISLNK(mode))
856 return UNIX_TYPE_SYMLINK;
857 #endif
858 #ifdef S_ISCHR
859 else if(S_ISCHR(mode))
860 return UNIX_TYPE_CHARDEV;
861 #endif
862 #ifdef S_ISBLK
863 else if(S_ISBLK(mode))
864 return UNIX_TYPE_BLKDEV;
865 #endif
866 #ifdef S_ISFIFO
867 else if(S_ISFIFO(mode))
868 return UNIX_TYPE_FIFO;
869 #endif
870 #ifdef S_ISSOCK
871 else if(S_ISSOCK(mode))
872 return UNIX_TYPE_SOCKET;
873 #endif
875 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
876 return UNIX_TYPE_UNKNOWN;
879 /****************************************************************************
880 Map wire perms onto standard UNIX permissions. Obey share restrictions.
881 ****************************************************************************/
883 NTSTATUS unix_perms_from_wire(connection_struct *conn,
884 const SMB_STRUCT_STAT *psbuf,
885 uint32_t perms,
886 enum perm_type ptype,
887 mode_t *ret_perms)
889 mode_t ret = 0;
891 if (perms == SMB_MODE_NO_CHANGE) {
892 if (!VALID_STAT(*psbuf)) {
893 return NT_STATUS_INVALID_PARAMETER;
894 } else {
895 *ret_perms = psbuf->st_ex_mode;
896 return NT_STATUS_OK;
900 ret = wire_perms_to_unix(perms);
902 if (ptype == PERM_NEW_FILE) {
904 * "create mask"/"force create mode" are
905 * only applied to new files, not existing ones.
907 ret &= lp_create_mask(SNUM(conn));
908 /* Add in force bits */
909 ret |= lp_force_create_mode(SNUM(conn));
910 } else if (ptype == PERM_NEW_DIR) {
912 * "directory mask"/"force directory mode" are
913 * only applied to new directories, not existing ones.
915 ret &= lp_directory_mask(SNUM(conn));
916 /* Add in force bits */
917 ret |= lp_force_directory_mode(SNUM(conn));
920 *ret_perms = ret;
921 return NT_STATUS_OK;
924 /****************************************************************************
925 Get a level dependent lanman2 dir entry.
926 ****************************************************************************/
928 struct smbd_dirptr_lanman2_state {
929 connection_struct *conn;
930 uint32_t info_level;
931 bool check_mangled_names;
932 bool case_sensitive;
935 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
936 void *private_data,
937 const char *dname,
938 const char *mask,
939 char **_fname)
941 struct smbd_dirptr_lanman2_state *state =
942 (struct smbd_dirptr_lanman2_state *)private_data;
943 bool ok;
944 char mangled_name[13]; /* mangled 8.3 name. */
945 bool got_match;
946 const char *fname;
948 /* Mangle fname if it's an illegal name. */
949 if (mangle_must_mangle(dname, state->conn->params)) {
951 * Slow path - ensure we can push the original name as UCS2. If
952 * not, then just don't return this name.
954 NTSTATUS status;
955 size_t ret_len = 0;
956 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
957 uint8_t *tmp = talloc_array(talloc_tos(),
958 uint8_t,
959 len);
961 status = srvstr_push(NULL,
962 FLAGS2_UNICODE_STRINGS,
963 tmp,
964 dname,
965 len,
966 STR_TERMINATE,
967 &ret_len);
969 TALLOC_FREE(tmp);
971 if (!NT_STATUS_IS_OK(status)) {
972 return false;
975 ok = name_to_8_3(dname, mangled_name,
976 true, state->conn->params);
977 if (!ok) {
978 return false;
980 fname = mangled_name;
981 } else {
982 fname = dname;
985 got_match = mask_match(fname, mask,
986 state->case_sensitive);
988 if(!got_match && state->check_mangled_names &&
989 !mangle_is_8_3(fname, false, state->conn->params)) {
991 * It turns out that NT matches wildcards against
992 * both long *and* short names. This may explain some
993 * of the wildcard weirdness from old DOS clients
994 * that some people have been seeing.... JRA.
996 /* Force the mangling into 8.3. */
997 ok = name_to_8_3(fname, mangled_name,
998 false, state->conn->params);
999 if (!ok) {
1000 return false;
1003 got_match = mask_match(mangled_name, mask,
1004 state->case_sensitive);
1007 if (!got_match) {
1008 return false;
1011 *_fname = talloc_strdup(ctx, fname);
1012 if (*_fname == NULL) {
1013 return false;
1016 return true;
1019 static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1021 if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1022 unsigned ea_size = estimate_ea_size(fsp);
1023 return ea_size;
1025 return IO_REPARSE_TAG_DFS;
1028 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1029 connection_struct *conn,
1030 uint16_t flags2,
1031 uint32_t info_level,
1032 struct ea_list *name_list,
1033 bool check_mangled_names,
1034 bool requires_resume_key,
1035 uint32_t mode,
1036 const char *fname,
1037 const struct smb_filename *smb_fname,
1038 int space_remaining,
1039 uint8_t align,
1040 bool do_pad,
1041 char *base_data,
1042 char **ppdata,
1043 char *end_data,
1044 uint64_t *last_entry_off)
1046 char *p, *q, *pdata = *ppdata;
1047 uint32_t reskey=0;
1048 uint64_t file_size = 0;
1049 uint64_t allocation_size = 0;
1050 uint64_t file_id = 0;
1051 size_t len = 0;
1052 struct timespec mdate_ts = {0};
1053 struct timespec adate_ts = {0};
1054 struct timespec cdate_ts = {0};
1055 struct timespec create_date_ts = {0};
1056 char *nameptr;
1057 char *last_entry_ptr;
1058 bool was_8_3;
1059 int off;
1060 int pad = 0;
1061 NTSTATUS status;
1062 struct readdir_attr_data *readdir_attr_data = NULL;
1063 uint32_t ea_size;
1065 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1066 file_size = get_file_size_stat(&smb_fname->st);
1068 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1071 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1072 * a DFS symlink.
1074 if (smb_fname->fsp != NULL &&
1075 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1076 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1077 ctx,
1078 &readdir_attr_data);
1079 if (!NT_STATUS_IS_OK(status)) {
1080 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1081 status)) {
1082 return status;
1087 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1089 mdate_ts = smb_fname->st.st_ex_mtime;
1090 adate_ts = smb_fname->st.st_ex_atime;
1091 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1092 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1094 if (lp_dos_filetime_resolution(SNUM(conn))) {
1095 dos_filetime_timespec(&create_date_ts);
1096 dos_filetime_timespec(&mdate_ts);
1097 dos_filetime_timespec(&adate_ts);
1098 dos_filetime_timespec(&cdate_ts);
1101 /* align the record */
1102 SMB_ASSERT(align >= 1);
1104 off = (int)PTR_DIFF(pdata, base_data);
1105 pad = (off + (align-1)) & ~(align-1);
1106 pad -= off;
1108 if (pad && pad > space_remaining) {
1109 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1110 "for padding (wanted %u, had %d)\n",
1111 (unsigned int)pad,
1112 space_remaining ));
1113 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1116 off += pad;
1117 /* initialize padding to 0 */
1118 if (pad) {
1119 memset(pdata, 0, pad);
1121 space_remaining -= pad;
1123 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1124 space_remaining ));
1126 pdata += pad;
1127 p = pdata;
1128 last_entry_ptr = p;
1130 pad = 0;
1131 off = 0;
1133 switch (info_level) {
1134 case SMB_FIND_INFO_STANDARD:
1135 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1136 if(requires_resume_key) {
1137 SIVAL(p,0,reskey);
1138 p += 4;
1140 srv_put_dos_date2_ts(p, 0, create_date_ts);
1141 srv_put_dos_date2_ts(p, 4, adate_ts);
1142 srv_put_dos_date2_ts(p, 8, mdate_ts);
1143 SIVAL(p,12,(uint32_t)file_size);
1144 SIVAL(p,16,(uint32_t)allocation_size);
1145 SSVAL(p,20,mode);
1146 p += 23;
1147 nameptr = p;
1148 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1149 p += ucs2_align(base_data, p, 0);
1151 status = srvstr_push(base_data, flags2, p,
1152 fname, PTR_DIFF(end_data, p),
1153 STR_TERMINATE, &len);
1154 if (!NT_STATUS_IS_OK(status)) {
1155 return status;
1157 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1158 if (len > 2) {
1159 SCVAL(nameptr, -1, len - 2);
1160 } else {
1161 SCVAL(nameptr, -1, 0);
1163 } else {
1164 if (len > 1) {
1165 SCVAL(nameptr, -1, len - 1);
1166 } else {
1167 SCVAL(nameptr, -1, 0);
1170 p += len;
1171 break;
1173 case SMB_FIND_EA_SIZE:
1174 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1175 if (requires_resume_key) {
1176 SIVAL(p,0,reskey);
1177 p += 4;
1179 srv_put_dos_date2_ts(p, 0, create_date_ts);
1180 srv_put_dos_date2_ts(p, 4, adate_ts);
1181 srv_put_dos_date2_ts(p, 8, mdate_ts);
1182 SIVAL(p,12,(uint32_t)file_size);
1183 SIVAL(p,16,(uint32_t)allocation_size);
1184 SSVAL(p,20,mode);
1186 ea_size = estimate_ea_size(smb_fname->fsp);
1187 SIVAL(p,22,ea_size); /* Extended attributes */
1189 p += 27;
1190 nameptr = p - 1;
1191 status = srvstr_push(base_data, flags2,
1192 p, fname, PTR_DIFF(end_data, p),
1193 STR_TERMINATE | STR_NOALIGN, &len);
1194 if (!NT_STATUS_IS_OK(status)) {
1195 return status;
1197 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1198 if (len > 2) {
1199 len -= 2;
1200 } else {
1201 len = 0;
1203 } else {
1204 if (len > 1) {
1205 len -= 1;
1206 } else {
1207 len = 0;
1210 SCVAL(nameptr,0,len);
1211 p += len;
1212 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1213 break;
1215 case SMB_FIND_EA_LIST:
1217 struct ea_list *file_list = NULL;
1218 size_t ea_len = 0;
1220 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1221 if (!name_list) {
1222 return NT_STATUS_INVALID_PARAMETER;
1224 if (requires_resume_key) {
1225 SIVAL(p,0,reskey);
1226 p += 4;
1228 srv_put_dos_date2_ts(p, 0, create_date_ts);
1229 srv_put_dos_date2_ts(p, 4, adate_ts);
1230 srv_put_dos_date2_ts(p, 8, mdate_ts);
1231 SIVAL(p,12,(uint32_t)file_size);
1232 SIVAL(p,16,(uint32_t)allocation_size);
1233 SSVAL(p,20,mode);
1234 p += 22; /* p now points to the EA area. */
1236 status = get_ea_list_from_fsp(ctx,
1237 smb_fname->fsp,
1238 &ea_len, &file_list);
1239 if (!NT_STATUS_IS_OK(status)) {
1240 file_list = NULL;
1242 name_list = ea_list_union(name_list, file_list, &ea_len);
1244 /* We need to determine if this entry will fit in the space available. */
1245 /* Max string size is 255 bytes. */
1246 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1247 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1248 "(wanted %u, had %d)\n",
1249 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1250 space_remaining ));
1251 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1254 /* Push the ea_data followed by the name. */
1255 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1256 nameptr = p;
1257 status = srvstr_push(base_data, flags2,
1258 p + 1, fname, PTR_DIFF(end_data, p+1),
1259 STR_TERMINATE | STR_NOALIGN, &len);
1260 if (!NT_STATUS_IS_OK(status)) {
1261 return status;
1263 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1264 if (len > 2) {
1265 len -= 2;
1266 } else {
1267 len = 0;
1269 } else {
1270 if (len > 1) {
1271 len -= 1;
1272 } else {
1273 len = 0;
1276 SCVAL(nameptr,0,len);
1277 p += len + 1;
1278 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1279 break;
1282 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1283 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1284 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1285 p += 4;
1286 SIVAL(p,0,reskey); p += 4;
1287 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1288 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1289 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1290 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1291 SOFF_T(p,0,file_size); p += 8;
1292 SOFF_T(p,0,allocation_size); p += 8;
1293 SIVAL(p,0,mode); p += 4;
1294 q = p; p += 4; /* q is placeholder for name length. */
1295 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1296 SIVAL(p, 0, ea_size);
1297 p += 4;
1298 /* Clear the short name buffer. This is
1299 * IMPORTANT as not doing so will trigger
1300 * a Win2k client bug. JRA.
1302 if (!was_8_3 && check_mangled_names) {
1303 char mangled_name[13]; /* mangled 8.3 name. */
1304 if (!name_to_8_3(fname,mangled_name,True,
1305 conn->params)) {
1306 /* Error - mangle failed ! */
1307 memset(mangled_name,'\0',12);
1309 mangled_name[12] = 0;
1310 status = srvstr_push(base_data, flags2,
1311 p+2, mangled_name, 24,
1312 STR_UPPER|STR_UNICODE, &len);
1313 if (!NT_STATUS_IS_OK(status)) {
1314 return status;
1316 if (len < 24) {
1317 memset(p + 2 + len,'\0',24 - len);
1319 SSVAL(p, 0, len);
1320 } else {
1321 memset(p,'\0',26);
1323 p += 2 + 24;
1324 status = srvstr_push(base_data, flags2, p,
1325 fname, PTR_DIFF(end_data, p),
1326 STR_TERMINATE_ASCII, &len);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 return status;
1330 SIVAL(q,0,len);
1331 p += len;
1333 len = PTR_DIFF(p, pdata);
1334 pad = (len + (align-1)) & ~(align-1);
1336 * offset to the next entry, the caller
1337 * will overwrite it for the last entry
1338 * that's why we always include the padding
1340 SIVAL(pdata,0,pad);
1342 * set padding to zero
1344 if (do_pad) {
1345 memset(p, 0, pad - len);
1346 p = pdata + pad;
1347 } else {
1348 p = pdata + len;
1350 break;
1352 case SMB_FIND_FILE_DIRECTORY_INFO:
1353 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1354 p += 4;
1355 SIVAL(p,0,reskey); p += 4;
1356 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1357 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1358 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1359 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1360 SOFF_T(p,0,file_size); p += 8;
1361 SOFF_T(p,0,allocation_size); p += 8;
1362 SIVAL(p,0,mode); p += 4;
1363 status = srvstr_push(base_data, flags2,
1364 p + 4, fname, PTR_DIFF(end_data, p+4),
1365 STR_TERMINATE_ASCII, &len);
1366 if (!NT_STATUS_IS_OK(status)) {
1367 return status;
1369 SIVAL(p,0,len);
1370 p += 4 + len;
1372 len = PTR_DIFF(p, pdata);
1373 pad = (len + (align-1)) & ~(align-1);
1375 * offset to the next entry, the caller
1376 * will overwrite it for the last entry
1377 * that's why we always include the padding
1379 SIVAL(pdata,0,pad);
1381 * set padding to zero
1383 if (do_pad) {
1384 memset(p, 0, pad - len);
1385 p = pdata + pad;
1386 } else {
1387 p = pdata + len;
1389 break;
1391 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1392 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1393 p += 4;
1394 SIVAL(p,0,reskey); p += 4;
1395 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1396 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1397 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1398 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1399 SOFF_T(p,0,file_size); p += 8;
1400 SOFF_T(p,0,allocation_size); p += 8;
1401 SIVAL(p,0,mode); p += 4;
1402 q = p; p += 4; /* q is placeholder for name length. */
1403 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1404 SIVAL(p, 0, ea_size);
1405 p +=4;
1406 status = srvstr_push(base_data, flags2, p,
1407 fname, PTR_DIFF(end_data, p),
1408 STR_TERMINATE_ASCII, &len);
1409 if (!NT_STATUS_IS_OK(status)) {
1410 return status;
1412 SIVAL(q, 0, len);
1413 p += len;
1415 len = PTR_DIFF(p, pdata);
1416 pad = (len + (align-1)) & ~(align-1);
1418 * offset to the next entry, the caller
1419 * will overwrite it for the last entry
1420 * that's why we always include the padding
1422 SIVAL(pdata,0,pad);
1424 * set padding to zero
1426 if (do_pad) {
1427 memset(p, 0, pad - len);
1428 p = pdata + pad;
1429 } else {
1430 p = pdata + len;
1432 break;
1434 case SMB_FIND_FILE_NAMES_INFO:
1435 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1436 p += 4;
1437 SIVAL(p,0,reskey); p += 4;
1438 p += 4;
1439 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1440 acl on a dir (tridge) */
1441 status = srvstr_push(base_data, flags2, p,
1442 fname, PTR_DIFF(end_data, p),
1443 STR_TERMINATE_ASCII, &len);
1444 if (!NT_STATUS_IS_OK(status)) {
1445 return status;
1447 SIVAL(p, -4, len);
1448 p += len;
1450 len = PTR_DIFF(p, pdata);
1451 pad = (len + (align-1)) & ~(align-1);
1453 * offset to the next entry, the caller
1454 * will overwrite it for the last entry
1455 * that's why we always include the padding
1457 SIVAL(pdata,0,pad);
1459 * set padding to zero
1461 if (do_pad) {
1462 memset(p, 0, pad - len);
1463 p = pdata + pad;
1464 } else {
1465 p = pdata + len;
1467 break;
1469 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1470 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1471 p += 4;
1472 SIVAL(p,0,reskey); p += 4;
1473 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1474 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1475 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1476 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1477 SOFF_T(p,0,file_size); p += 8;
1478 SOFF_T(p,0,allocation_size); p += 8;
1479 SIVAL(p,0,mode); p += 4;
1480 q = p; p += 4; /* q is placeholder for name length. */
1481 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1482 SIVAL(p, 0, ea_size);
1483 p += 4;
1484 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1485 SBVAL(p,0,file_id); p += 8;
1486 status = srvstr_push(base_data, flags2, p,
1487 fname, PTR_DIFF(end_data, p),
1488 STR_TERMINATE_ASCII, &len);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 return status;
1492 SIVAL(q, 0, len);
1493 p += len;
1495 len = PTR_DIFF(p, pdata);
1496 pad = (len + (align-1)) & ~(align-1);
1498 * offset to the next entry, the caller
1499 * will overwrite it for the last entry
1500 * that's why we always include the padding
1502 SIVAL(pdata,0,pad);
1504 * set padding to zero
1506 if (do_pad) {
1507 memset(p, 0, pad - len);
1508 p = pdata + pad;
1509 } else {
1510 p = pdata + len;
1512 break;
1514 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1515 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1516 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1517 p += 4;
1518 SIVAL(p,0,reskey); p += 4;
1519 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1520 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1521 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1522 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1523 SOFF_T(p,0,file_size); p += 8;
1524 SOFF_T(p,0,allocation_size); p += 8;
1525 SIVAL(p,0,mode); p += 4;
1526 q = p; p += 4; /* q is placeholder for name length */
1527 if (readdir_attr_data &&
1528 readdir_attr_data->type == RDATTR_AAPL) {
1530 * OS X specific SMB2 extension negotiated via
1531 * AAPL create context: return max_access in
1532 * ea_size field.
1534 ea_size = readdir_attr_data->attr_data.aapl.max_access;
1535 } else {
1536 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1538 SIVAL(p,0,ea_size); /* Extended attributes */
1539 p += 4;
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 resource fork
1546 * length and compressed FinderInfo in
1547 * shortname field.
1549 * According to documentation short_name_len
1550 * should be 0, but on the wire behaviour
1551 * shows its set to 24 by clients.
1553 SSVAL(p, 0, 24);
1555 /* Resourefork length */
1556 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1558 /* Compressed FinderInfo */
1559 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1560 } else if (!was_8_3 && check_mangled_names) {
1561 char mangled_name[13]; /* mangled 8.3 name. */
1562 if (!name_to_8_3(fname,mangled_name,True,
1563 conn->params)) {
1564 /* Error - mangle failed ! */
1565 memset(mangled_name,'\0',12);
1567 mangled_name[12] = 0;
1568 status = srvstr_push(base_data, flags2,
1569 p+2, mangled_name, 24,
1570 STR_UPPER|STR_UNICODE, &len);
1571 if (!NT_STATUS_IS_OK(status)) {
1572 return status;
1574 SSVAL(p, 0, len);
1575 if (len < 24) {
1576 memset(p + 2 + len,'\0',24 - len);
1578 SSVAL(p, 0, len);
1579 } else {
1580 /* Clear the short name buffer. This is
1581 * IMPORTANT as not doing so will trigger
1582 * a Win2k client bug. JRA.
1584 memset(p,'\0',26);
1586 p += 26;
1588 /* Reserved ? */
1589 if (readdir_attr_data &&
1590 readdir_attr_data->type == RDATTR_AAPL) {
1592 * OS X specific SMB2 extension negotiated via
1593 * AAPL create context: return UNIX mode in
1594 * reserved field.
1596 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1597 SSVAL(p, 0, aapl_mode);
1598 } else {
1599 SSVAL(p, 0, 0);
1601 p += 2;
1603 SBVAL(p,0,file_id); p += 8;
1604 status = srvstr_push(base_data, flags2, p,
1605 fname, PTR_DIFF(end_data, p),
1606 STR_TERMINATE_ASCII, &len);
1607 if (!NT_STATUS_IS_OK(status)) {
1608 return status;
1610 SIVAL(q,0,len);
1611 p += len;
1613 len = PTR_DIFF(p, pdata);
1614 pad = (len + (align-1)) & ~(align-1);
1616 * offset to the next entry, the caller
1617 * will overwrite it for the last entry
1618 * that's why we always include the padding
1620 SIVAL(pdata,0,pad);
1622 * set padding to zero
1624 if (do_pad) {
1625 memset(p, 0, pad - len);
1626 p = pdata + pad;
1627 } else {
1628 p = pdata + len;
1630 break;
1632 /* CIFS UNIX Extension. */
1634 case SMB_FIND_FILE_UNIX:
1635 case SMB_FIND_FILE_UNIX_INFO2:
1636 p+= 4;
1637 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1639 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1641 if (info_level == SMB_FIND_FILE_UNIX) {
1642 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1643 p = store_file_unix_basic(conn, p,
1644 NULL, &smb_fname->st);
1645 status = srvstr_push(base_data, flags2, p,
1646 fname, PTR_DIFF(end_data, p),
1647 STR_TERMINATE, &len);
1648 if (!NT_STATUS_IS_OK(status)) {
1649 return status;
1651 } else {
1652 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1653 p = store_file_unix_basic_info2(conn, p,
1654 NULL, &smb_fname->st);
1655 nameptr = p;
1656 p += 4;
1657 status = srvstr_push(base_data, flags2, p, fname,
1658 PTR_DIFF(end_data, p), 0, &len);
1659 if (!NT_STATUS_IS_OK(status)) {
1660 return status;
1662 SIVAL(nameptr, 0, len);
1665 p += len;
1667 len = PTR_DIFF(p, pdata);
1668 pad = (len + (align-1)) & ~(align-1);
1670 * offset to the next entry, the caller
1671 * will overwrite it for the last entry
1672 * that's why we always include the padding
1674 SIVAL(pdata,0,pad);
1676 * set padding to zero
1678 if (do_pad) {
1679 memset(p, 0, pad - len);
1680 p = pdata + pad;
1681 } else {
1682 p = pdata + len;
1684 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1686 break;
1688 /* SMB2 UNIX Extension. */
1690 case SMB2_FILE_POSIX_INFORMATION:
1692 struct smb3_file_posix_information info = {};
1693 uint8_t buf[sizeof(info)];
1694 struct ndr_push ndr = {
1695 .data = buf,
1696 .alloc_size = sizeof(buf),
1697 .fixed_buf_size = true,
1699 enum ndr_err_code ndr_err;
1701 p+= 4;
1702 SIVAL(p,0,reskey); p+= 4;
1704 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1706 if (!(conn->sconn->using_smb2)) {
1707 return NT_STATUS_INVALID_LEVEL;
1710 smb3_file_posix_information_init(
1711 conn, &smb_fname->st, 0, mode, &info);
1713 ndr_err = ndr_push_smb3_file_posix_information(
1714 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
1715 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1716 return NT_STATUS_INSUFFICIENT_RESOURCES;
1719 memcpy(p, buf, ndr.offset);
1720 p += ndr.offset;
1722 nameptr = p;
1723 p += 4;
1724 status = srvstr_push(base_data, flags2, p, fname,
1725 PTR_DIFF(end_data, p), 0, &len);
1726 if (!NT_STATUS_IS_OK(status)) {
1727 return status;
1729 SIVAL(nameptr, 0, len);
1731 p += len;
1733 len = PTR_DIFF(p, pdata);
1734 pad = (len + (align-1)) & ~(align-1);
1736 * offset to the next entry, the caller
1737 * will overwrite it for the last entry
1738 * that's why we always include the padding
1740 SIVAL(pdata,0,pad);
1741 break;
1744 default:
1745 return NT_STATUS_INVALID_LEVEL;
1748 if (PTR_DIFF(p,pdata) > space_remaining) {
1749 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1750 "(wanted %u, had %d)\n",
1751 (unsigned int)PTR_DIFF(p,pdata),
1752 space_remaining ));
1753 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1756 /* Setup the last entry pointer, as an offset from base_data */
1757 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1758 /* Advance the data pointer to the next slot */
1759 *ppdata = p;
1761 return NT_STATUS_OK;
1764 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1765 connection_struct *conn,
1766 struct dptr_struct *dirptr,
1767 uint16_t flags2,
1768 const char *path_mask,
1769 uint32_t dirtype,
1770 int info_level,
1771 int requires_resume_key,
1772 bool dont_descend,
1773 bool ask_sharemode,
1774 bool get_dosmode,
1775 uint8_t align,
1776 bool do_pad,
1777 char **ppdata,
1778 char *base_data,
1779 char *end_data,
1780 int space_remaining,
1781 struct smb_filename **_smb_fname,
1782 int *_last_entry_off,
1783 struct ea_list *name_list,
1784 struct file_id *file_id)
1786 const char *p;
1787 const char *mask = NULL;
1788 uint32_t mode = 0;
1789 char *fname = NULL;
1790 struct smb_filename *smb_fname = NULL;
1791 struct smbd_dirptr_lanman2_state state;
1792 bool ok;
1793 uint64_t last_entry_off = 0;
1794 NTSTATUS status;
1795 enum mangled_names_options mangled_names;
1796 bool marshall_with_83_names;
1798 mangled_names = lp_mangled_names(conn->params);
1800 ZERO_STRUCT(state);
1801 state.conn = conn;
1802 state.info_level = info_level;
1803 if (mangled_names != MANGLED_NAMES_NO) {
1804 state.check_mangled_names = true;
1806 state.case_sensitive = dptr_case_sensitive(dirptr);
1808 p = strrchr_m(path_mask,'/');
1809 if(p != NULL) {
1810 if(p[1] == '\0') {
1811 mask = "*.*";
1812 } else {
1813 mask = p+1;
1815 } else {
1816 mask = path_mask;
1819 ok = smbd_dirptr_get_entry(ctx,
1820 dirptr,
1821 mask,
1822 dirtype,
1823 dont_descend,
1824 ask_sharemode,
1825 get_dosmode,
1826 smbd_dirptr_lanman2_match_fn,
1827 &state,
1828 &fname,
1829 &smb_fname,
1830 &mode);
1831 if (!ok) {
1832 return NT_STATUS_END_OF_FILE;
1835 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1837 status = smbd_marshall_dir_entry(ctx,
1838 conn,
1839 flags2,
1840 info_level,
1841 name_list,
1842 marshall_with_83_names,
1843 requires_resume_key,
1844 mode,
1845 fname,
1846 smb_fname,
1847 space_remaining,
1848 align,
1849 do_pad,
1850 base_data,
1851 ppdata,
1852 end_data,
1853 &last_entry_off);
1854 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1855 DEBUG(1,("Conversion error: illegal character: %s\n",
1856 smb_fname_str_dbg(smb_fname)));
1859 if (file_id != NULL) {
1860 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1863 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1864 smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1867 if (!NT_STATUS_IS_OK(status)) {
1868 TALLOC_FREE(smb_fname);
1869 TALLOC_FREE(fname);
1870 return status;
1873 smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1875 if (_smb_fname != NULL) {
1877 * smb_fname is already talloc'ed off ctx.
1878 * We just need to make sure we don't return
1879 * any stream_name, and replace base_name
1880 * with fname in case base_name got mangled.
1881 * This allows us to preserve any smb_fname->fsp
1882 * for asynchronous handle lookups.
1884 TALLOC_FREE(smb_fname->stream_name);
1887 * smbd_dirptr_set_last_name_sent() above consumed
1888 * base_name
1890 smb_fname->base_name = talloc_strdup(smb_fname, fname);
1892 if (smb_fname->base_name == NULL) {
1893 TALLOC_FREE(smb_fname);
1894 TALLOC_FREE(fname);
1895 return NT_STATUS_NO_MEMORY;
1897 *_smb_fname = smb_fname;
1898 } else {
1899 TALLOC_FREE(smb_fname);
1901 TALLOC_FREE(fname);
1903 *_last_entry_off = last_entry_off;
1904 return NT_STATUS_OK;
1907 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1909 const struct loadparm_substitution *lp_sub =
1910 loadparm_s3_global_substitution();
1912 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1913 return objid;
1916 static void samba_extended_info_version(struct smb_extended_info *extended_info)
1918 SMB_ASSERT(extended_info != NULL);
1920 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1921 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1922 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1923 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1924 #ifdef SAMBA_VERSION_REVISION
1925 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1926 #endif
1927 extended_info->samba_subversion = 0;
1928 #ifdef SAMBA_VERSION_RC_RELEASE
1929 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1930 #else
1931 #ifdef SAMBA_VERSION_PRE_RELEASE
1932 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
1933 #endif
1934 #endif
1935 #ifdef SAMBA_VERSION_VENDOR_PATCH
1936 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
1937 #endif
1938 extended_info->samba_gitcommitdate = 0;
1939 #ifdef SAMBA_VERSION_COMMIT_TIME
1940 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
1941 #endif
1943 memset(extended_info->samba_version_string, 0,
1944 sizeof(extended_info->samba_version_string));
1946 snprintf (extended_info->samba_version_string,
1947 sizeof(extended_info->samba_version_string),
1948 "%s", samba_version_string());
1951 static bool fsinfo_unix_valid_level(connection_struct *conn,
1952 struct files_struct *fsp,
1953 uint16_t info_level)
1955 if (conn->sconn->using_smb2 &&
1956 fsp->posix_flags == FSP_POSIX_FLAGS_OPEN &&
1957 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL)
1959 return true;
1961 #if defined(SMB1SERVER)
1962 if (lp_smb1_unix_extensions() &&
1963 info_level == SMB_QUERY_POSIX_FS_INFO) {
1964 return true;
1966 #endif
1967 return false;
1971 * fsp is only valid for SMB2.
1973 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
1974 connection_struct *conn,
1975 TALLOC_CTX *mem_ctx,
1976 uint16_t info_level,
1977 uint16_t flags2,
1978 unsigned int max_data_bytes,
1979 size_t *fixed_portion,
1980 struct files_struct *fsp,
1981 struct smb_filename *fname,
1982 char **ppdata,
1983 int *ret_data_len)
1985 const struct loadparm_substitution *lp_sub =
1986 loadparm_s3_global_substitution();
1987 char *pdata, *end_data;
1988 int data_len = 0;
1989 size_t len = 0;
1990 const char *vname = volume_label(talloc_tos(), SNUM(conn));
1991 int snum = SNUM(conn);
1992 const char *fstype = lp_fstype(SNUM(conn));
1993 const char *filename = NULL;
1994 const uint64_t bytes_per_sector = 512;
1995 uint32_t additional_flags = 0;
1996 struct smb_filename smb_fname;
1997 SMB_STRUCT_STAT st;
1998 NTSTATUS status = NT_STATUS_OK;
1999 uint64_t df_ret;
2000 uint32_t serial;
2002 if (fname == NULL || fname->base_name == NULL) {
2003 filename = ".";
2004 } else {
2005 filename = fname->base_name;
2008 if (IS_IPC(conn)) {
2009 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2010 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2011 "info level (0x%x) on IPC$.\n",
2012 (unsigned int)info_level));
2013 return NT_STATUS_ACCESS_DENIED;
2017 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2019 smb_fname = (struct smb_filename) {
2020 .base_name = discard_const_p(char, filename),
2021 .flags = fname ? fname->flags : 0,
2022 .twrp = fname ? fname->twrp : 0,
2025 if(info_level != SMB_FS_QUOTA_INFORMATION
2026 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2027 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2028 return map_nt_error_from_unix(errno);
2031 st = smb_fname.st;
2033 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2034 return NT_STATUS_INVALID_PARAMETER;
2037 *ppdata = (char *)SMB_REALLOC(
2038 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2039 if (*ppdata == NULL) {
2040 return NT_STATUS_NO_MEMORY;
2043 pdata = *ppdata;
2044 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2045 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2047 *fixed_portion = 0;
2049 switch (info_level) {
2050 case SMB_INFO_ALLOCATION:
2052 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2053 data_len = 18;
2054 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2055 &dfree, &dsize);
2056 if (df_ret == (uint64_t)-1) {
2057 return map_nt_error_from_unix(errno);
2060 block_size = lp_block_size(snum);
2061 if (bsize < block_size) {
2062 uint64_t factor = block_size/bsize;
2063 bsize = block_size;
2064 dsize /= factor;
2065 dfree /= factor;
2067 if (bsize > block_size) {
2068 uint64_t factor = bsize/block_size;
2069 bsize = block_size;
2070 dsize *= factor;
2071 dfree *= factor;
2073 sectors_per_unit = bsize/bytes_per_sector;
2075 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2076 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2077 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2080 * For large drives, return max values and not modulo.
2082 dsize = MIN(dsize, UINT32_MAX);
2083 dfree = MIN(dfree, UINT32_MAX);
2085 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2086 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2087 SIVAL(pdata,l1_cUnit,dsize);
2088 SIVAL(pdata,l1_cUnitAvail,dfree);
2089 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2090 break;
2093 case SMB_INFO_VOLUME:
2094 /* Return volume name */
2096 * Add volume serial number - hash of a combination of
2097 * the called hostname and the service name.
2099 serial = generate_volume_serial_number(lp_sub, snum);
2100 SIVAL(pdata,0,serial);
2102 * Win2k3 and previous mess this up by sending a name length
2103 * one byte short. I believe only older clients (OS/2 Win9x) use
2104 * this call so try fixing this by adding a terminating null to
2105 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2107 status = srvstr_push(
2108 pdata, flags2,
2109 pdata+l2_vol_szVolLabel, vname,
2110 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2111 STR_NOALIGN|STR_TERMINATE, &len);
2112 if (!NT_STATUS_IS_OK(status)) {
2113 return status;
2115 SCVAL(pdata,l2_vol_cch,len);
2116 data_len = l2_vol_szVolLabel + len;
2117 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2118 "name = %s serial = 0x%04"PRIx32"\n",
2119 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2120 (unsigned)len, vname, serial));
2121 break;
2123 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2124 case SMB_FS_ATTRIBUTE_INFORMATION:
2126 additional_flags = 0;
2127 #if defined(HAVE_SYS_QUOTAS)
2128 additional_flags |= FILE_VOLUME_QUOTAS;
2129 #endif
2131 if(lp_nt_acl_support(SNUM(conn))) {
2132 additional_flags |= FILE_PERSISTENT_ACLS;
2135 /* Capabilities are filled in at connection time through STATVFS call */
2136 additional_flags |= conn->fs_capabilities;
2137 additional_flags |= lp_parm_int(conn->params->service,
2138 "share", "fake_fscaps",
2141 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2142 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2143 additional_flags); /* FS ATTRIBUTES */
2145 SIVAL(pdata,4,255); /* Max filename component length */
2146 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2147 and will think we can't do long filenames */
2148 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2149 PTR_DIFF(end_data, pdata+12),
2150 STR_UNICODE, &len);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 return status;
2154 SIVAL(pdata,8,len);
2155 data_len = 12 + len;
2156 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2157 /* the client only requested a portion of the
2158 file system name */
2159 data_len = max_data_bytes;
2160 status = STATUS_BUFFER_OVERFLOW;
2162 *fixed_portion = 16;
2163 break;
2165 case SMB_QUERY_FS_LABEL_INFO:
2166 case SMB_FS_LABEL_INFORMATION:
2167 status = srvstr_push(pdata, flags2, pdata+4, vname,
2168 PTR_DIFF(end_data, pdata+4), 0, &len);
2169 if (!NT_STATUS_IS_OK(status)) {
2170 return status;
2172 data_len = 4 + len;
2173 SIVAL(pdata,0,len);
2174 break;
2176 case SMB_QUERY_FS_VOLUME_INFO:
2177 case SMB_FS_VOLUME_INFORMATION:
2178 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2179 pdata, &st.st_ex_btime);
2181 * Add volume serial number - hash of a combination of
2182 * the called hostname and the service name.
2184 serial = generate_volume_serial_number(lp_sub, snum);
2185 SIVAL(pdata,8,serial);
2187 /* Max label len is 32 characters. */
2188 status = srvstr_push(pdata, flags2, pdata+18, vname,
2189 PTR_DIFF(end_data, pdata+18),
2190 STR_UNICODE, &len);
2191 if (!NT_STATUS_IS_OK(status)) {
2192 return status;
2194 SIVAL(pdata,12,len);
2195 data_len = 18+len;
2197 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2198 "namelen = %d, vol=%s serv=%s "
2199 "serial=0x%04"PRIx32"\n",
2200 (int)strlen(vname),vname,
2201 lp_servicename(talloc_tos(), lp_sub, snum),
2202 serial));
2203 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2204 /* the client only requested a portion of the
2205 volume label */
2206 data_len = max_data_bytes;
2207 status = STATUS_BUFFER_OVERFLOW;
2209 *fixed_portion = 24;
2210 break;
2212 case SMB_QUERY_FS_SIZE_INFO:
2213 case SMB_FS_SIZE_INFORMATION:
2215 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2216 data_len = 24;
2217 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2218 &dfree, &dsize);
2219 if (df_ret == (uint64_t)-1) {
2220 return map_nt_error_from_unix(errno);
2222 block_size = lp_block_size(snum);
2223 if (bsize < block_size) {
2224 uint64_t factor = block_size/bsize;
2225 bsize = block_size;
2226 dsize /= factor;
2227 dfree /= factor;
2229 if (bsize > block_size) {
2230 uint64_t factor = bsize/block_size;
2231 bsize = block_size;
2232 dsize *= factor;
2233 dfree *= factor;
2235 sectors_per_unit = bsize/bytes_per_sector;
2236 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2237 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2238 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2239 SBIG_UINT(pdata,0,dsize);
2240 SBIG_UINT(pdata,8,dfree);
2241 SIVAL(pdata,16,sectors_per_unit);
2242 SIVAL(pdata,20,bytes_per_sector);
2243 *fixed_portion = 24;
2244 break;
2247 case SMB_FS_FULL_SIZE_INFORMATION:
2249 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2250 data_len = 32;
2251 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2252 &dfree, &dsize);
2253 if (df_ret == (uint64_t)-1) {
2254 return map_nt_error_from_unix(errno);
2256 block_size = lp_block_size(snum);
2257 if (bsize < block_size) {
2258 uint64_t factor = block_size/bsize;
2259 bsize = block_size;
2260 dsize /= factor;
2261 dfree /= factor;
2263 if (bsize > block_size) {
2264 uint64_t factor = bsize/block_size;
2265 bsize = block_size;
2266 dsize *= factor;
2267 dfree *= factor;
2269 sectors_per_unit = bsize/bytes_per_sector;
2270 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2271 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2272 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2273 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2274 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2275 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2276 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2277 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2278 *fixed_portion = 32;
2279 break;
2282 case SMB_QUERY_FS_DEVICE_INFO:
2283 case SMB_FS_DEVICE_INFORMATION:
2285 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2287 if (!CAN_WRITE(conn)) {
2288 characteristics |= FILE_READ_ONLY_DEVICE;
2290 data_len = 8;
2291 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2292 SIVAL(pdata,4,characteristics);
2293 *fixed_portion = 8;
2294 break;
2297 #ifdef HAVE_SYS_QUOTAS
2298 case SMB_FS_QUOTA_INFORMATION:
2300 * what we have to send --metze:
2302 * Unknown1: 24 NULL bytes
2303 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2304 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2305 * Quota Flags: 2 byte :
2306 * Unknown3: 6 NULL bytes
2308 * 48 bytes total
2310 * details for Quota Flags:
2312 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2313 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2314 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2315 * 0x0001 Enable Quotas: enable quota for this fs
2319 /* we need to fake up a fsp here,
2320 * because its not send in this call
2322 files_struct tmpfsp;
2323 SMB_NTQUOTA_STRUCT quotas;
2325 ZERO_STRUCT(tmpfsp);
2326 ZERO_STRUCT(quotas);
2328 tmpfsp.conn = conn;
2329 tmpfsp.fnum = FNUM_FIELD_INVALID;
2331 /* access check */
2332 if (get_current_uid(conn) != 0) {
2333 DEBUG(0,("get_user_quota: access_denied "
2334 "service [%s] user [%s]\n",
2335 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2336 conn->session_info->unix_info->unix_name));
2337 return NT_STATUS_ACCESS_DENIED;
2340 status = vfs_get_ntquota(&tmpfsp, SMB_USER_FS_QUOTA_TYPE,
2341 NULL, &quotas);
2342 if (!NT_STATUS_IS_OK(status)) {
2343 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2344 return status;
2347 data_len = 48;
2349 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2350 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2352 /* Unknown1 24 NULL bytes*/
2353 SBIG_UINT(pdata,0,(uint64_t)0);
2354 SBIG_UINT(pdata,8,(uint64_t)0);
2355 SBIG_UINT(pdata,16,(uint64_t)0);
2357 /* Default Soft Quota 8 bytes */
2358 SBIG_UINT(pdata,24,quotas.softlim);
2360 /* Default Hard Quota 8 bytes */
2361 SBIG_UINT(pdata,32,quotas.hardlim);
2363 /* Quota flag 2 bytes */
2364 SSVAL(pdata,40,quotas.qflags);
2366 /* Unknown3 6 NULL bytes */
2367 SSVAL(pdata,42,0);
2368 SIVAL(pdata,44,0);
2370 break;
2372 #endif /* HAVE_SYS_QUOTAS */
2373 case SMB_FS_OBJECTID_INFORMATION:
2375 unsigned char objid[16];
2376 struct smb_extended_info extended_info;
2377 memcpy(pdata,create_volume_objectid(conn, objid),16);
2378 samba_extended_info_version (&extended_info);
2379 SIVAL(pdata,16,extended_info.samba_magic);
2380 SIVAL(pdata,20,extended_info.samba_version);
2381 SIVAL(pdata,24,extended_info.samba_subversion);
2382 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2383 memcpy(pdata+36,extended_info.samba_version_string,28);
2384 data_len = 64;
2385 break;
2388 case SMB_FS_SECTOR_SIZE_INFORMATION:
2390 data_len = 28;
2392 * These values match a physical Windows Server 2012
2393 * share backed by NTFS atop spinning rust.
2395 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2396 /* logical_bytes_per_sector */
2397 SIVAL(pdata, 0, bytes_per_sector);
2398 /* phys_bytes_per_sector_atomic */
2399 SIVAL(pdata, 4, bytes_per_sector);
2400 /* phys_bytes_per_sector_perf */
2401 SIVAL(pdata, 8, bytes_per_sector);
2402 /* fs_effective_phys_bytes_per_sector_atomic */
2403 SIVAL(pdata, 12, bytes_per_sector);
2404 /* flags */
2405 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2406 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2407 /* byte_off_sector_align */
2408 SIVAL(pdata, 20, 0);
2409 /* byte_off_partition_align */
2410 SIVAL(pdata, 24, 0);
2411 *fixed_portion = 28;
2412 break;
2416 #if defined(WITH_SMB1SERVER)
2418 * Query the version and capabilities of the CIFS UNIX extensions
2419 * in use.
2422 case SMB_QUERY_CIFS_UNIX_INFO:
2424 bool large_write = lp_min_receive_file_size() &&
2425 !smb1_srv_is_signing_active(xconn);
2426 bool large_read = !smb1_srv_is_signing_active(xconn);
2427 int encrypt_caps = 0;
2429 if (!lp_smb1_unix_extensions()) {
2430 return NT_STATUS_INVALID_LEVEL;
2433 switch (conn->encrypt_level) {
2434 case SMB_SIGNING_OFF:
2435 encrypt_caps = 0;
2436 break;
2437 case SMB_SIGNING_DESIRED:
2438 case SMB_SIGNING_IF_REQUIRED:
2439 case SMB_SIGNING_DEFAULT:
2440 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2441 break;
2442 case SMB_SIGNING_REQUIRED:
2443 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2444 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2445 large_write = false;
2446 large_read = false;
2447 break;
2450 data_len = 12;
2451 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2452 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2454 /* We have POSIX ACLs, pathname, encryption,
2455 * large read/write, and locking capability. */
2457 SBIG_UINT(pdata,4,((uint64_t)(
2458 CIFS_UNIX_POSIX_ACLS_CAP|
2459 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2460 CIFS_UNIX_FCNTL_LOCKS_CAP|
2461 CIFS_UNIX_EXTATTR_CAP|
2462 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2463 encrypt_caps|
2464 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2465 (large_write ?
2466 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2467 break;
2469 #endif
2471 case SMB_QUERY_POSIX_FS_INFO:
2472 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2474 int rc;
2475 struct vfs_statvfs_struct svfs;
2477 if (!fsinfo_unix_valid_level(conn, fsp, info_level)) {
2478 return NT_STATUS_INVALID_LEVEL;
2481 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2483 if (!rc) {
2484 data_len = 56;
2485 SIVAL(pdata,0,svfs.OptimalTransferSize);
2486 SIVAL(pdata,4,svfs.BlockSize);
2487 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2488 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2489 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2490 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2491 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2492 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2493 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2494 #ifdef EOPNOTSUPP
2495 } else if (rc == EOPNOTSUPP) {
2496 return NT_STATUS_INVALID_LEVEL;
2497 #endif /* EOPNOTSUPP */
2498 } else {
2499 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2500 return NT_STATUS_DOS(ERRSRV, ERRerror);
2502 break;
2505 case SMB_QUERY_POSIX_WHOAMI:
2507 uint32_t flags = 0;
2508 uint32_t sid_bytes;
2509 uint32_t i;
2511 if (!lp_smb1_unix_extensions()) {
2512 return NT_STATUS_INVALID_LEVEL;
2515 if (max_data_bytes < 40) {
2516 return NT_STATUS_BUFFER_TOO_SMALL;
2519 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2520 flags |= SMB_WHOAMI_GUEST;
2523 /* NOTE: 8 bytes for UID/GID, irrespective of native
2524 * platform size. This matches
2525 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2527 data_len = 4 /* flags */
2528 + 4 /* flag mask */
2529 + 8 /* uid */
2530 + 8 /* gid */
2531 + 4 /* ngroups */
2532 + 4 /* num_sids */
2533 + 4 /* SID bytes */
2534 + 4 /* pad/reserved */
2535 + (conn->session_info->unix_token->ngroups * 8)
2536 /* groups list */
2537 + (conn->session_info->security_token->num_sids *
2538 SID_MAX_SIZE)
2539 /* SID list */;
2541 SIVAL(pdata, 0, flags);
2542 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2543 SBIG_UINT(pdata, 8,
2544 (uint64_t)conn->session_info->unix_token->uid);
2545 SBIG_UINT(pdata, 16,
2546 (uint64_t)conn->session_info->unix_token->gid);
2549 if (data_len >= max_data_bytes) {
2550 /* Potential overflow, skip the GIDs and SIDs. */
2552 SIVAL(pdata, 24, 0); /* num_groups */
2553 SIVAL(pdata, 28, 0); /* num_sids */
2554 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2555 SIVAL(pdata, 36, 0); /* reserved */
2557 data_len = 40;
2558 break;
2561 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2562 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2564 /* We walk the SID list twice, but this call is fairly
2565 * infrequent, and I don't expect that it's performance
2566 * sensitive -- jpeach
2568 for (i = 0, sid_bytes = 0;
2569 i < conn->session_info->security_token->num_sids; ++i) {
2570 sid_bytes += ndr_size_dom_sid(
2571 &conn->session_info->security_token->sids[i],
2575 /* SID list byte count */
2576 SIVAL(pdata, 32, sid_bytes);
2578 /* 4 bytes pad/reserved - must be zero */
2579 SIVAL(pdata, 36, 0);
2580 data_len = 40;
2582 /* GID list */
2583 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2584 SBIG_UINT(pdata, data_len,
2585 (uint64_t)conn->session_info->unix_token->groups[i]);
2586 data_len += 8;
2589 /* SID list */
2590 for (i = 0;
2591 i < conn->session_info->security_token->num_sids; ++i) {
2592 int sid_len = ndr_size_dom_sid(
2593 &conn->session_info->security_token->sids[i],
2596 sid_linearize((uint8_t *)(pdata + data_len),
2597 sid_len,
2598 &conn->session_info->security_token->sids[i]);
2599 data_len += sid_len;
2602 break;
2605 case SMB_MAC_QUERY_FS_INFO:
2607 * Thursby MAC extension... ONLY on NTFS filesystems
2608 * once we do streams then we don't need this
2610 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2611 data_len = 88;
2612 SIVAL(pdata,84,0x100); /* Don't support mac... */
2613 break;
2616 FALL_THROUGH;
2617 default:
2618 return NT_STATUS_INVALID_LEVEL;
2621 *ret_data_len = data_len;
2622 return status;
2625 NTSTATUS smb_set_fsquota(connection_struct *conn,
2626 struct smb_request *req,
2627 files_struct *fsp,
2628 const DATA_BLOB *qdata)
2630 const struct loadparm_substitution *lp_sub =
2631 loadparm_s3_global_substitution();
2632 NTSTATUS status;
2633 SMB_NTQUOTA_STRUCT quotas;
2635 ZERO_STRUCT(quotas);
2637 /* access check */
2638 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2639 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2640 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2641 conn->session_info->unix_info->unix_name);
2642 return NT_STATUS_ACCESS_DENIED;
2645 if (!check_fsp_ntquota_handle(conn, req,
2646 fsp)) {
2647 DBG_WARNING("no valid QUOTA HANDLE\n");
2648 return NT_STATUS_INVALID_HANDLE;
2651 /* note: normally there're 48 bytes,
2652 * but we didn't use the last 6 bytes for now
2653 * --metze
2655 if (qdata->length < 42) {
2656 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2657 qdata->length);
2658 return NT_STATUS_INVALID_PARAMETER;
2661 /* unknown_1 24 NULL bytes in pdata*/
2663 /* the soft quotas 8 bytes (uint64_t)*/
2664 quotas.softlim = BVAL(qdata->data,24);
2666 /* the hard quotas 8 bytes (uint64_t)*/
2667 quotas.hardlim = BVAL(qdata->data,32);
2669 /* quota_flags 2 bytes **/
2670 quotas.qflags = SVAL(qdata->data,40);
2672 /* unknown_2 6 NULL bytes follow*/
2674 /* now set the quotas */
2675 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2676 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2677 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)));
2678 status = map_nt_error_from_unix(errno);
2679 } else {
2680 status = NT_STATUS_OK;
2682 return status;
2685 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2686 struct smb_request *req,
2687 TALLOC_CTX *mem_ctx,
2688 uint16_t info_level,
2689 files_struct *fsp,
2690 const DATA_BLOB *pdata)
2692 switch (info_level) {
2693 case SMB_FS_QUOTA_INFORMATION:
2695 return smb_set_fsquota(conn,
2696 req,
2697 fsp,
2698 pdata);
2701 default:
2702 break;
2704 return NT_STATUS_INVALID_LEVEL;
2707 /****************************************************************************
2708 Store the FILE_UNIX_BASIC info.
2709 ****************************************************************************/
2711 char *store_file_unix_basic(connection_struct *conn,
2712 char *pdata,
2713 files_struct *fsp,
2714 const SMB_STRUCT_STAT *psbuf)
2716 dev_t devno;
2718 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2719 DBG_NOTICE("st_mode=%o\n", (int)psbuf->st_ex_mode);
2721 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2722 pdata += 8;
2724 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2725 pdata += 8;
2727 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2728 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2729 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2730 pdata += 24;
2732 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2733 SIVAL(pdata,4,0);
2734 pdata += 8;
2736 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2737 SIVAL(pdata,4,0);
2738 pdata += 8;
2740 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2741 pdata += 4;
2743 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2744 devno = psbuf->st_ex_rdev;
2745 } else {
2746 devno = psbuf->st_ex_dev;
2749 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2750 SIVAL(pdata,4,0);
2751 pdata += 8;
2753 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2754 SIVAL(pdata,4,0);
2755 pdata += 8;
2757 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2758 pdata += 8;
2760 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2761 SIVAL(pdata,4,0);
2762 pdata += 8;
2764 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2765 SIVAL(pdata,4,0);
2766 pdata += 8;
2768 return pdata;
2771 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2772 * the chflags(2) (or equivalent) flags.
2774 * XXX: this really should be behind the VFS interface. To do this, we would
2775 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2776 * Each VFS module could then implement its own mapping as appropriate for the
2777 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2779 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2780 info2_flags_map[] =
2782 #ifdef UF_NODUMP
2783 { UF_NODUMP, EXT_DO_NOT_BACKUP },
2784 #endif
2786 #ifdef UF_IMMUTABLE
2787 { UF_IMMUTABLE, EXT_IMMUTABLE },
2788 #endif
2790 #ifdef UF_APPEND
2791 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2792 #endif
2794 #ifdef UF_HIDDEN
2795 { UF_HIDDEN, EXT_HIDDEN },
2796 #endif
2798 /* Do not remove. We need to guarantee that this array has at least one
2799 * entry to build on HP-UX.
2801 { 0, 0 }
2805 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2806 uint32_t *smb_fflags, uint32_t *smb_fmask)
2808 size_t i;
2810 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2811 *smb_fmask |= info2_flags_map[i].smb_fflag;
2812 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2813 *smb_fflags |= info2_flags_map[i].smb_fflag;
2818 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2819 const uint32_t smb_fflags,
2820 const uint32_t smb_fmask,
2821 int *stat_fflags)
2823 uint32_t max_fmask = 0;
2824 size_t i;
2826 *stat_fflags = psbuf->st_ex_flags;
2828 /* For each flags requested in smb_fmask, check the state of the
2829 * corresponding flag in smb_fflags and set or clear the matching
2830 * stat flag.
2833 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2834 max_fmask |= info2_flags_map[i].smb_fflag;
2835 if (smb_fmask & info2_flags_map[i].smb_fflag) {
2836 if (smb_fflags & info2_flags_map[i].smb_fflag) {
2837 *stat_fflags |= info2_flags_map[i].stat_fflag;
2838 } else {
2839 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2844 /* If smb_fmask is asking to set any bits that are not supported by
2845 * our flag mappings, we should fail.
2847 if ((smb_fmask & max_fmask) != smb_fmask) {
2848 return False;
2851 return True;
2855 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2856 * of file flags and birth (create) time.
2858 char *store_file_unix_basic_info2(connection_struct *conn,
2859 char *pdata,
2860 files_struct *fsp,
2861 const SMB_STRUCT_STAT *psbuf)
2863 uint32_t file_flags = 0;
2864 uint32_t flags_mask = 0;
2866 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2868 /* Create (birth) time 64 bit */
2869 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2870 pdata += 8;
2872 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2873 SIVAL(pdata, 0, file_flags); /* flags */
2874 SIVAL(pdata, 4, flags_mask); /* mask */
2875 pdata += 8;
2877 return pdata;
2880 static NTSTATUS marshall_stream_info(unsigned int num_streams,
2881 const struct stream_struct *streams,
2882 char *data,
2883 unsigned int max_data_bytes,
2884 unsigned int *data_size)
2886 unsigned int i;
2887 unsigned int ofs = 0;
2889 if (max_data_bytes < 32) {
2890 return NT_STATUS_INFO_LENGTH_MISMATCH;
2893 for (i = 0; i < num_streams; i++) {
2894 unsigned int next_offset;
2895 size_t namelen;
2896 smb_ucs2_t *namebuf;
2898 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2899 streams[i].name, &namelen) ||
2900 namelen <= 2)
2902 return NT_STATUS_INVALID_PARAMETER;
2906 * name_buf is now null-terminated, we need to marshall as not
2907 * terminated
2910 namelen -= 2;
2913 * We cannot overflow ...
2915 if ((ofs + 24 + namelen) > max_data_bytes) {
2916 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2917 i));
2918 TALLOC_FREE(namebuf);
2919 return STATUS_BUFFER_OVERFLOW;
2922 SIVAL(data, ofs+4, namelen);
2923 SOFF_T(data, ofs+8, streams[i].size);
2924 SOFF_T(data, ofs+16, streams[i].alloc_size);
2925 memcpy(data+ofs+24, namebuf, namelen);
2926 TALLOC_FREE(namebuf);
2928 next_offset = ofs + 24 + namelen;
2930 if (i == num_streams-1) {
2931 SIVAL(data, ofs, 0);
2933 else {
2934 unsigned int align = ndr_align_size(next_offset, 8);
2936 if ((next_offset + align) > max_data_bytes) {
2937 DEBUG(10, ("refusing to overflow align "
2938 "reply at stream %u\n",
2939 i));
2940 TALLOC_FREE(namebuf);
2941 return STATUS_BUFFER_OVERFLOW;
2944 memset(data+next_offset, 0, align);
2945 next_offset += align;
2947 SIVAL(data, ofs, next_offset - ofs);
2948 ofs = next_offset;
2951 ofs = next_offset;
2954 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
2956 *data_size = ofs;
2958 return NT_STATUS_OK;
2961 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
2962 TALLOC_CTX *mem_ctx,
2963 struct smb_request *req,
2964 uint16_t info_level,
2965 files_struct *fsp,
2966 struct smb_filename *smb_fname,
2967 bool delete_pending,
2968 struct timespec write_time_ts,
2969 struct ea_list *ea_list,
2970 uint16_t flags2,
2971 unsigned int max_data_bytes,
2972 size_t *fixed_portion,
2973 char **ppdata,
2974 unsigned int *pdata_size)
2976 char *pdata = *ppdata;
2977 char *dstart, *dend;
2978 unsigned int data_size;
2979 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
2980 SMB_STRUCT_STAT *psbuf = NULL;
2981 SMB_STRUCT_STAT *base_sp = NULL;
2982 char *p;
2983 char *base_name;
2984 char *dos_fname;
2985 int mode;
2986 int nlink;
2987 NTSTATUS status;
2988 uint64_t file_size = 0;
2989 uint64_t pos = 0;
2990 uint64_t allocation_size = 0;
2991 uint64_t file_id = 0;
2992 uint32_t access_mask = 0;
2993 size_t len = 0;
2995 if (INFO_LEVEL_IS_UNIX(info_level)) {
2996 bool ok = false;
2998 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
2999 DBG_DEBUG("SMB1 unix extensions activated\n");
3000 ok = true;
3003 if (conn->sconn->using_smb2 &&
3004 (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN))
3006 DBG_DEBUG("SMB2 posix open\n");
3007 ok = true;
3010 if (!ok) {
3011 return NT_STATUS_INVALID_LEVEL;
3015 DBG_INFO("%s (%s) level=%d max_data=%u\n",
3016 smb_fname_str_dbg(smb_fname),
3017 fsp_fnum_dbg(fsp),
3018 info_level, max_data_bytes);
3021 * In case of querying a symlink in POSIX context,
3022 * fsp will be NULL. fdos_mode() deals with it.
3024 if (fsp != NULL) {
3025 smb_fname = fsp->fsp_name;
3027 mode = fdos_mode(fsp);
3028 psbuf = &smb_fname->st;
3030 if (fsp != NULL) {
3031 base_sp = fsp->base_fsp ?
3032 &fsp->base_fsp->fsp_name->st :
3033 &fsp->fsp_name->st;
3034 } else {
3035 base_sp = &smb_fname->st;
3038 nlink = psbuf->st_ex_nlink;
3040 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3041 nlink = 1;
3044 if ((nlink > 0) && delete_pending) {
3045 nlink -= 1;
3048 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3049 return NT_STATUS_INVALID_PARAMETER;
3052 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3053 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3054 if (*ppdata == NULL) {
3055 return NT_STATUS_NO_MEMORY;
3057 pdata = *ppdata;
3058 dstart = pdata;
3059 dend = dstart + data_size - 1;
3061 if (!is_omit_timespec(&write_time_ts) &&
3062 !INFO_LEVEL_IS_UNIX(info_level))
3064 update_stat_ex_mtime(psbuf, write_time_ts);
3067 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3068 mtime_ts = psbuf->st_ex_mtime;
3069 atime_ts = psbuf->st_ex_atime;
3070 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3072 if (lp_dos_filetime_resolution(SNUM(conn))) {
3073 dos_filetime_timespec(&create_time_ts);
3074 dos_filetime_timespec(&mtime_ts);
3075 dos_filetime_timespec(&atime_ts);
3076 dos_filetime_timespec(&ctime_ts);
3079 p = strrchr_m(smb_fname->base_name,'/');
3080 if (!p)
3081 base_name = smb_fname->base_name;
3082 else
3083 base_name = p+1;
3085 /* NT expects the name to be in an exact form of the *full*
3086 filename. See the trans2 torture test */
3087 if (ISDOT(base_name)) {
3088 dos_fname = talloc_strdup(mem_ctx, "\\");
3089 if (!dos_fname) {
3090 return NT_STATUS_NO_MEMORY;
3092 } else {
3093 dos_fname = talloc_asprintf(mem_ctx,
3094 "\\%s",
3095 smb_fname->base_name);
3096 if (!dos_fname) {
3097 return NT_STATUS_NO_MEMORY;
3099 if (is_named_stream(smb_fname)) {
3100 dos_fname = talloc_asprintf(dos_fname, "%s",
3101 smb_fname->stream_name);
3102 if (!dos_fname) {
3103 return NT_STATUS_NO_MEMORY;
3107 string_replace(dos_fname, '/', '\\');
3110 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3112 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3113 /* Do we have this path open ? */
3114 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3115 files_struct *fsp1 = file_find_di_first(
3116 conn->sconn, fileid, true);
3117 if (fsp1 && fsp1->initial_allocation_size) {
3118 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3122 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3123 file_size = get_file_size_stat(psbuf);
3126 if (fsp) {
3127 pos = fh_get_position_information(fsp->fh);
3130 if (fsp) {
3131 access_mask = fsp->access_mask;
3132 } else {
3133 /* GENERIC_EXECUTE mapping from Windows */
3134 access_mask = 0x12019F;
3137 /* This should be an index number - looks like
3138 dev/ino to me :-)
3140 I think this causes us to fail the IFSKIT
3141 BasicFileInformationTest. -tpot */
3142 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3144 *fixed_portion = 0;
3146 switch (info_level) {
3147 case SMB_INFO_STANDARD:
3148 DBG_DEBUG("SMB_INFO_STANDARD\n");
3149 data_size = 22;
3150 srv_put_dos_date2_ts(pdata,
3151 l1_fdateCreation,
3152 create_time_ts);
3153 srv_put_dos_date2_ts(pdata,
3154 l1_fdateLastAccess,
3155 atime_ts);
3156 srv_put_dos_date2_ts(pdata,
3157 l1_fdateLastWrite,
3158 mtime_ts); /* write time */
3159 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3160 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3161 SSVAL(pdata,l1_attrFile,mode);
3162 break;
3164 case SMB_INFO_QUERY_EA_SIZE:
3166 unsigned int ea_size =
3167 estimate_ea_size(smb_fname->fsp);
3168 DBG_DEBUG("SMB_INFO_QUERY_EA_SIZE\n");
3169 data_size = 26;
3170 srv_put_dos_date2_ts(pdata, 0, create_time_ts);
3171 srv_put_dos_date2_ts(pdata, 4, atime_ts);
3172 srv_put_dos_date2_ts(pdata,
3174 mtime_ts); /* write time */
3175 SIVAL(pdata,12,(uint32_t)file_size);
3176 SIVAL(pdata,16,(uint32_t)allocation_size);
3177 SSVAL(pdata,20,mode);
3178 SIVAL(pdata,22,ea_size);
3179 break;
3182 case SMB_INFO_IS_NAME_VALID:
3183 DBG_DEBUG("SMB_INFO_IS_NAME_VALID\n");
3184 if (fsp) {
3185 /* os/2 needs this ? really ?*/
3186 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3188 /* This is only reached for qpathinfo */
3189 data_size = 0;
3190 break;
3192 case SMB_INFO_QUERY_EAS_FROM_LIST:
3194 size_t total_ea_len = 0;
3195 struct ea_list *ea_file_list = NULL;
3196 DBG_DEBUG("SMB_INFO_QUERY_EAS_FROM_LIST\n");
3198 status =
3199 get_ea_list_from_fsp(mem_ctx,
3200 smb_fname->fsp,
3201 &total_ea_len, &ea_file_list);
3202 if (!NT_STATUS_IS_OK(status)) {
3203 return status;
3206 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3208 if (!ea_list || (total_ea_len > data_size)) {
3209 data_size = 4;
3210 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3211 break;
3214 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3215 break;
3218 case SMB_INFO_QUERY_ALL_EAS:
3220 /* We have data_size bytes to put EA's into. */
3221 size_t total_ea_len = 0;
3222 DBG_DEBUG(" SMB_INFO_QUERY_ALL_EAS\n");
3224 status = get_ea_list_from_fsp(mem_ctx,
3225 smb_fname->fsp,
3226 &total_ea_len, &ea_list);
3227 if (!NT_STATUS_IS_OK(status)) {
3228 return status;
3231 if (!ea_list || (total_ea_len > data_size)) {
3232 data_size = 4;
3233 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3234 break;
3237 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3238 break;
3241 case SMB2_FILE_FULL_EA_INFORMATION:
3243 /* We have data_size bytes to put EA's into. */
3244 size_t total_ea_len = 0;
3245 struct ea_list *ea_file_list = NULL;
3247 DBG_DEBUG("SMB2_INFO_QUERY_ALL_EAS\n");
3249 /*TODO: add filtering and index handling */
3251 status =
3252 get_ea_list_from_fsp(mem_ctx,
3253 smb_fname->fsp,
3254 &total_ea_len, &ea_file_list);
3255 if (!NT_STATUS_IS_OK(status)) {
3256 return status;
3258 if (!ea_file_list) {
3259 return NT_STATUS_NO_EAS_ON_FILE;
3262 status = fill_ea_chained_buffer(mem_ctx,
3263 pdata,
3264 data_size,
3265 &data_size,
3266 conn, ea_file_list);
3267 if (!NT_STATUS_IS_OK(status)) {
3268 return status;
3270 break;
3273 case SMB_FILE_BASIC_INFORMATION:
3274 case SMB_QUERY_FILE_BASIC_INFO:
3276 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3277 DBG_DEBUG("SMB_QUERY_FILE_BASIC_INFO\n");
3278 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3279 } else {
3280 DBG_DEBUG("SMB_FILE_BASIC_INFORMATION\n");
3281 data_size = 40;
3282 SIVAL(pdata,36,0);
3284 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3285 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3286 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3287 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3288 SIVAL(pdata,32,mode);
3290 DBG_INFO("SMB_QFBI - create: %s access: %s "
3291 "write: %s change: %s mode: %x\n",
3292 ctime(&create_time_ts.tv_sec),
3293 ctime(&atime_ts.tv_sec),
3294 ctime(&mtime_ts.tv_sec),
3295 ctime(&ctime_ts.tv_sec),
3296 mode);
3297 *fixed_portion = data_size;
3298 break;
3300 case SMB_FILE_STANDARD_INFORMATION:
3301 case SMB_QUERY_FILE_STANDARD_INFO:
3303 DBG_DEBUG("SMB_FILE_STANDARD_INFORMATION\n");
3304 data_size = 24;
3305 SOFF_T(pdata,0,allocation_size);
3306 SOFF_T(pdata,8,file_size);
3307 SIVAL(pdata,16,nlink);
3308 SCVAL(pdata,20,delete_pending?1:0);
3309 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3310 SSVAL(pdata,22,0); /* Padding. */
3311 *fixed_portion = 24;
3312 break;
3314 case SMB_FILE_EA_INFORMATION:
3315 case SMB_QUERY_FILE_EA_INFO:
3317 unsigned int ea_size =
3318 estimate_ea_size(smb_fname->fsp);
3319 DBG_DEBUG("SMB_FILE_EA_INFORMATION\n");
3320 data_size = 4;
3321 *fixed_portion = 4;
3322 SIVAL(pdata,0,ea_size);
3323 break;
3326 /* Get the 8.3 name - used if NT SMB was negotiated. */
3327 case SMB_QUERY_FILE_ALT_NAME_INFO:
3328 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3330 char mangled_name[13];
3331 DBG_DEBUG("SMB_FILE_ALTERNATE_NAME_INFORMATION\n");
3332 if (!name_to_8_3(base_name,mangled_name,
3333 True,conn->params)) {
3334 return NT_STATUS_NO_MEMORY;
3336 status = srvstr_push(dstart, flags2,
3337 pdata+4, mangled_name,
3338 PTR_DIFF(dend, pdata+4),
3339 STR_UNICODE, &len);
3340 if (!NT_STATUS_IS_OK(status)) {
3341 return status;
3343 data_size = 4 + len;
3344 SIVAL(pdata,0,len);
3345 *fixed_portion = 8;
3346 break;
3349 case SMB_QUERY_FILE_NAME_INFO:
3352 this must be *exactly* right for ACLs on mapped drives to work
3354 status = srvstr_push(dstart, flags2,
3355 pdata+4, dos_fname,
3356 PTR_DIFF(dend, pdata+4),
3357 STR_UNICODE, &len);
3358 if (!NT_STATUS_IS_OK(status)) {
3359 return status;
3361 DBG_DEBUG("SMB_QUERY_FILE_NAME_INFO\n");
3362 data_size = 4 + len;
3363 SIVAL(pdata,0,len);
3364 break;
3367 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3369 char *nfname = NULL;
3371 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
3372 return NT_STATUS_INVALID_LEVEL;
3375 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3376 if (nfname == NULL) {
3377 return NT_STATUS_NO_MEMORY;
3380 if (ISDOT(nfname)) {
3381 nfname[0] = '\0';
3383 string_replace(nfname, '/', '\\');
3385 if (fsp_is_alternate_stream(fsp)) {
3386 const char *s = smb_fname->stream_name;
3387 const char *e = NULL;
3388 size_t n;
3390 SMB_ASSERT(s[0] != '\0');
3393 * smb_fname->stream_name is in form
3394 * of ':StrEam:$DATA', but we should only
3395 * append ':StrEam' here.
3398 e = strchr(&s[1], ':');
3399 if (e == NULL) {
3400 n = strlen(s);
3401 } else {
3402 n = PTR_DIFF(e, s);
3404 nfname = talloc_strndup_append(nfname, s, n);
3405 if (nfname == NULL) {
3406 return NT_STATUS_NO_MEMORY;
3410 status = srvstr_push(dstart, flags2,
3411 pdata+4, nfname,
3412 PTR_DIFF(dend, pdata+4),
3413 STR_UNICODE, &len);
3414 if (!NT_STATUS_IS_OK(status)) {
3415 return status;
3417 DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3418 data_size = 4 + len;
3419 SIVAL(pdata,0,len);
3420 *fixed_portion = 8;
3421 break;
3424 case SMB_FILE_ALLOCATION_INFORMATION:
3425 case SMB_QUERY_FILE_ALLOCATION_INFO:
3426 DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3427 data_size = 8;
3428 SOFF_T(pdata,0,allocation_size);
3429 break;
3431 case SMB_FILE_END_OF_FILE_INFORMATION:
3432 case SMB_QUERY_FILE_END_OF_FILEINFO:
3433 DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3434 data_size = 8;
3435 SOFF_T(pdata,0,file_size);
3436 break;
3438 case SMB_QUERY_FILE_ALL_INFO:
3439 case SMB_FILE_ALL_INFORMATION:
3441 unsigned int ea_size =
3442 estimate_ea_size(smb_fname->fsp);
3443 DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3444 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3445 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3446 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3447 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3448 SIVAL(pdata,32,mode);
3449 SIVAL(pdata,36,0); /* padding. */
3450 pdata += 40;
3451 SOFF_T(pdata,0,allocation_size);
3452 SOFF_T(pdata,8,file_size);
3453 SIVAL(pdata,16,nlink);
3454 SCVAL(pdata,20,delete_pending);
3455 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3456 SSVAL(pdata,22,0);
3457 pdata += 24;
3458 SIVAL(pdata,0,ea_size);
3459 pdata += 4; /* EA info */
3460 status = srvstr_push(dstart, flags2,
3461 pdata+4, dos_fname,
3462 PTR_DIFF(dend, pdata+4),
3463 STR_UNICODE, &len);
3464 if (!NT_STATUS_IS_OK(status)) {
3465 return status;
3467 SIVAL(pdata,0,len);
3468 pdata += 4 + len;
3469 data_size = PTR_DIFF(pdata,(*ppdata));
3470 *fixed_portion = 10;
3471 break;
3474 case SMB2_FILE_ALL_INFORMATION:
3476 unsigned int ea_size =
3477 estimate_ea_size(smb_fname->fsp);
3478 DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3479 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3480 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3481 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3482 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3483 SIVAL(pdata, 0x20, mode);
3484 SIVAL(pdata, 0x24, 0); /* padding. */
3485 SBVAL(pdata, 0x28, allocation_size);
3486 SBVAL(pdata, 0x30, file_size);
3487 SIVAL(pdata, 0x38, nlink);
3488 SCVAL(pdata, 0x3C, delete_pending);
3489 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3490 SSVAL(pdata, 0x3E, 0); /* padding */
3491 SBVAL(pdata, 0x40, file_id);
3492 SIVAL(pdata, 0x48, ea_size);
3493 SIVAL(pdata, 0x4C, access_mask);
3494 SBVAL(pdata, 0x50, pos);
3495 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3496 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3498 pdata += 0x60;
3500 status = srvstr_push(dstart, flags2,
3501 pdata+4, dos_fname,
3502 PTR_DIFF(dend, pdata+4),
3503 STR_UNICODE, &len);
3504 if (!NT_STATUS_IS_OK(status)) {
3505 return status;
3507 SIVAL(pdata,0,len);
3508 pdata += 4 + len;
3509 data_size = PTR_DIFF(pdata,(*ppdata));
3510 *fixed_portion = 104;
3511 break;
3513 case SMB_FILE_INTERNAL_INFORMATION:
3515 DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3516 SBVAL(pdata, 0, file_id);
3517 data_size = 8;
3518 *fixed_portion = 8;
3519 break;
3521 case SMB_FILE_ACCESS_INFORMATION:
3522 DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3523 SIVAL(pdata, 0, access_mask);
3524 data_size = 4;
3525 *fixed_portion = 4;
3526 break;
3528 case SMB_FILE_NAME_INFORMATION:
3529 /* Pathname with leading '\'. */
3531 size_t byte_len;
3532 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3533 DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3534 SIVAL(pdata,0,byte_len);
3535 data_size = 4 + byte_len;
3536 break;
3539 case SMB_FILE_DISPOSITION_INFORMATION:
3540 DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3541 data_size = 1;
3542 SCVAL(pdata,0,delete_pending);
3543 *fixed_portion = 1;
3544 break;
3546 case SMB_FILE_POSITION_INFORMATION:
3547 DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3548 data_size = 8;
3549 SOFF_T(pdata,0,pos);
3550 *fixed_portion = 8;
3551 break;
3553 case SMB_FILE_MODE_INFORMATION:
3554 DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3555 SIVAL(pdata,0,mode);
3556 data_size = 4;
3557 *fixed_portion = 4;
3558 break;
3560 case SMB_FILE_ALIGNMENT_INFORMATION:
3561 DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3562 SIVAL(pdata,0,0); /* No alignment needed. */
3563 data_size = 4;
3564 *fixed_portion = 4;
3565 break;
3568 * NT4 server just returns "invalid query" to this - if we try
3569 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3570 * want this. JRA.
3572 /* The first statement above is false - verified using Thursby
3573 * client against NT4 -- gcolley.
3575 case SMB_QUERY_FILE_STREAM_INFO:
3576 case SMB_FILE_STREAM_INFORMATION: {
3577 unsigned int num_streams = 0;
3578 struct stream_struct *streams = NULL;
3580 DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3582 if (is_ntfs_stream_smb_fname(smb_fname)) {
3583 return NT_STATUS_INVALID_PARAMETER;
3586 status = vfs_fstreaminfo(fsp,
3587 mem_ctx,
3588 &num_streams,
3589 &streams);
3591 if (!NT_STATUS_IS_OK(status)) {
3592 DBG_DEBUG("could not get stream info: %s\n",
3593 nt_errstr(status));
3594 return status;
3597 status = marshall_stream_info(num_streams, streams,
3598 pdata, max_data_bytes,
3599 &data_size);
3601 if (!NT_STATUS_IS_OK(status)) {
3602 DBG_DEBUG("marshall_stream_info failed: %s\n",
3603 nt_errstr(status));
3604 TALLOC_FREE(streams);
3605 return status;
3608 TALLOC_FREE(streams);
3610 *fixed_portion = 32;
3612 break;
3614 case SMB_QUERY_COMPRESSION_INFO:
3615 case SMB_FILE_COMPRESSION_INFORMATION:
3616 DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3617 SOFF_T(pdata,0,file_size);
3618 SIVAL(pdata,8,0); /* ??? */
3619 SIVAL(pdata,12,0); /* ??? */
3620 data_size = 16;
3621 *fixed_portion = 16;
3622 break;
3624 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3625 DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3626 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3627 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3628 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3629 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3630 SOFF_T(pdata,32,allocation_size);
3631 SOFF_T(pdata,40,file_size);
3632 SIVAL(pdata,48,mode);
3633 SIVAL(pdata,52,0); /* ??? */
3634 data_size = 56;
3635 *fixed_portion = 56;
3636 break;
3638 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3639 DBG_DEBUG(" SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3640 SIVAL(pdata,0,mode);
3641 SIVAL(pdata,4,0);
3642 data_size = 8;
3643 *fixed_portion = 8;
3644 break;
3647 * SMB2 UNIX Extensions.
3649 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3651 struct smb3_file_posix_information info = {};
3652 uint8_t buf[sizeof(info)];
3653 struct ndr_push ndr = {
3654 .data = buf,
3655 .alloc_size = sizeof(buf),
3656 .fixed_buf_size = true,
3658 enum ndr_err_code ndr_err;
3660 if (!(conn->sconn->using_smb2)) {
3661 return NT_STATUS_INVALID_LEVEL;
3663 if (fsp == NULL) {
3664 return NT_STATUS_INVALID_HANDLE;
3666 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3667 return NT_STATUS_INVALID_LEVEL;
3670 smb3_file_posix_information_init(
3671 conn, &smb_fname->st, 0, mode, &info);
3673 ndr_err = ndr_push_smb3_file_posix_information(
3674 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
3675 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3676 return NT_STATUS_INSUFFICIENT_RESOURCES;
3679 memcpy(pdata, buf, ndr.offset);
3680 data_size = ndr.offset;
3681 break;
3684 default:
3685 return NT_STATUS_INVALID_LEVEL;
3688 *pdata_size = data_size;
3689 return NT_STATUS_OK;
3692 /****************************************************************************
3693 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3694 code.
3695 ****************************************************************************/
3697 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3698 connection_struct *conn,
3699 struct smb_request *req,
3700 bool overwrite_if_exists,
3701 const struct smb_filename *smb_fname_old,
3702 struct smb_filename *smb_fname_new)
3704 NTSTATUS status = NT_STATUS_OK;
3705 int ret;
3706 bool ok;
3707 struct smb_filename *parent_fname_old = NULL;
3708 struct smb_filename *base_name_old = NULL;
3709 struct smb_filename *parent_fname_new = NULL;
3710 struct smb_filename *base_name_new = NULL;
3712 /* source must already exist. */
3713 if (!VALID_STAT(smb_fname_old->st)) {
3714 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3715 goto out;
3718 /* No links from a directory. */
3719 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3720 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3721 goto out;
3724 /* Setting a hardlink to/from a stream isn't currently supported. */
3725 ok = is_ntfs_stream_smb_fname(smb_fname_old);
3726 if (ok) {
3727 DBG_DEBUG("Old name has streams\n");
3728 status = NT_STATUS_INVALID_PARAMETER;
3729 goto out;
3731 ok = is_ntfs_stream_smb_fname(smb_fname_new);
3732 if (ok) {
3733 DBG_DEBUG("New name has streams\n");
3734 status = NT_STATUS_INVALID_PARAMETER;
3735 goto out;
3738 status = parent_pathref(talloc_tos(),
3739 conn->cwd_fsp,
3740 smb_fname_old,
3741 &parent_fname_old,
3742 &base_name_old);
3743 if (!NT_STATUS_IS_OK(status)) {
3744 goto out;
3747 status = parent_pathref(talloc_tos(),
3748 conn->cwd_fsp,
3749 smb_fname_new,
3750 &parent_fname_new,
3751 &base_name_new);
3752 if (!NT_STATUS_IS_OK(status)) {
3753 goto out;
3756 if (VALID_STAT(smb_fname_new->st)) {
3757 if (overwrite_if_exists) {
3758 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3759 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3760 goto out;
3762 status = unlink_internals(conn,
3763 req,
3764 FILE_ATTRIBUTE_NORMAL,
3765 NULL, /* new_dirfsp */
3766 smb_fname_new);
3767 if (!NT_STATUS_IS_OK(status)) {
3768 goto out;
3770 } else {
3771 /* Disallow if newname already exists. */
3772 status = NT_STATUS_OBJECT_NAME_COLLISION;
3773 goto out;
3777 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3778 smb_fname_old->base_name, smb_fname_new->base_name));
3780 ret = SMB_VFS_LINKAT(conn,
3781 parent_fname_old->fsp,
3782 base_name_old,
3783 parent_fname_new->fsp,
3784 base_name_new,
3787 if (ret != 0) {
3788 status = map_nt_error_from_unix(errno);
3789 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3790 nt_errstr(status), smb_fname_old->base_name,
3791 smb_fname_new->base_name));
3794 out:
3796 TALLOC_FREE(parent_fname_old);
3797 TALLOC_FREE(parent_fname_new);
3798 return status;
3801 /****************************************************************************
3802 Deal with setting the time from any of the setfilepathinfo functions.
3803 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3804 calling this function.
3805 ****************************************************************************/
3807 NTSTATUS smb_set_file_time(connection_struct *conn,
3808 files_struct *fsp,
3809 struct smb_filename *smb_fname,
3810 struct smb_file_time *ft,
3811 bool setting_write_time)
3813 struct files_struct *set_fsp = NULL;
3814 struct timeval_buf tbuf[4];
3815 uint32_t action =
3816 FILE_NOTIFY_CHANGE_LAST_ACCESS
3817 |FILE_NOTIFY_CHANGE_LAST_WRITE
3818 |FILE_NOTIFY_CHANGE_CREATION;
3819 int ret;
3821 if (!VALID_STAT(smb_fname->st)) {
3822 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3825 if (fsp == NULL) {
3826 /* A symlink */
3827 return NT_STATUS_OK;
3830 set_fsp = metadata_fsp(fsp);
3832 /* get some defaults (no modifications) if any info is zero or -1. */
3833 if (is_omit_timespec(&ft->create_time)) {
3834 action &= ~FILE_NOTIFY_CHANGE_CREATION;
3837 if (is_omit_timespec(&ft->atime)) {
3838 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3841 if (is_omit_timespec(&ft->mtime)) {
3842 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3845 if (!setting_write_time) {
3846 /* ft->mtime comes from change time, not write time. */
3847 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3850 /* Ensure the resolution is the correct for
3851 * what we can store on this filesystem. */
3853 round_timespec(conn->ts_res, &ft->create_time);
3854 round_timespec(conn->ts_res, &ft->ctime);
3855 round_timespec(conn->ts_res, &ft->atime);
3856 round_timespec(conn->ts_res, &ft->mtime);
3858 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3859 timespec_string_buf(&ft->atime, true, &tbuf[0]));
3860 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3861 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3862 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3863 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3864 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3865 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3867 if (setting_write_time) {
3869 * This was a Windows setfileinfo on an open file.
3870 * NT does this a lot. We also need to
3871 * set the time here, as it can be read by
3872 * FindFirst/FindNext and with the patch for bug #2045
3873 * in smbd/fileio.c it ensures that this timestamp is
3874 * kept sticky even after a write. We save the request
3875 * away and will set it on file close and after a write. JRA.
3878 DBG_DEBUG("setting pending modtime to %s\n",
3879 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3881 if (set_fsp != NULL) {
3882 set_sticky_write_time_fsp(set_fsp, ft->mtime);
3883 } else {
3884 set_sticky_write_time_path(
3885 vfs_file_id_from_sbuf(conn, &smb_fname->st),
3886 ft->mtime);
3890 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3892 ret = file_ntimes(conn, set_fsp, ft);
3893 if (ret != 0) {
3894 return map_nt_error_from_unix(errno);
3897 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
3898 smb_fname->base_name);
3899 return NT_STATUS_OK;
3902 /****************************************************************************
3903 Deal with setting the dosmode from any of the setfilepathinfo functions.
3904 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3905 done before calling this function.
3906 ****************************************************************************/
3908 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3909 struct files_struct *fsp,
3910 uint32_t dosmode)
3912 struct files_struct *dos_fsp = NULL;
3913 uint32_t current_dosmode;
3914 int ret;
3916 if (!VALID_STAT(fsp->fsp_name->st)) {
3917 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3920 dos_fsp = metadata_fsp(fsp);
3922 if (dosmode != 0) {
3923 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3924 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3925 } else {
3926 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3930 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3932 /* check the mode isn't different, before changing it */
3933 if (dosmode == 0) {
3934 return NT_STATUS_OK;
3936 current_dosmode = fdos_mode(dos_fsp);
3937 if (dosmode == current_dosmode) {
3938 return NT_STATUS_OK;
3941 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
3942 fsp_str_dbg(dos_fsp), dosmode);
3944 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
3945 if (ret != 0) {
3946 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3947 fsp_str_dbg(dos_fsp), strerror(errno));
3948 return map_nt_error_from_unix(errno);
3951 return NT_STATUS_OK;
3954 /****************************************************************************
3955 Deal with setting the size from any of the setfilepathinfo functions.
3956 ****************************************************************************/
3958 NTSTATUS smb_set_file_size(connection_struct *conn,
3959 struct smb_request *req,
3960 files_struct *fsp,
3961 struct smb_filename *smb_fname,
3962 const SMB_STRUCT_STAT *psbuf,
3963 off_t size,
3964 bool fail_after_createfile)
3966 NTSTATUS status = NT_STATUS_OK;
3967 files_struct *new_fsp = NULL;
3969 if (!VALID_STAT(*psbuf)) {
3970 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3973 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
3974 (uint64_t)size,
3975 get_file_size_stat(psbuf));
3977 if (size == get_file_size_stat(psbuf)) {
3978 if (fsp == NULL) {
3979 return NT_STATUS_OK;
3981 if (!fsp->fsp_flags.modified) {
3982 return NT_STATUS_OK;
3984 trigger_write_time_update_immediate(fsp);
3985 return NT_STATUS_OK;
3988 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
3989 smb_fname_str_dbg(smb_fname), (double)size));
3991 if (fsp &&
3992 !fsp->fsp_flags.is_pathref &&
3993 fsp_get_io_fd(fsp) != -1)
3995 /* Handle based call. */
3996 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
3997 return NT_STATUS_ACCESS_DENIED;
4000 if (vfs_set_filelen(fsp, size) == -1) {
4001 return map_nt_error_from_unix(errno);
4003 trigger_write_time_update_immediate(fsp);
4004 return NT_STATUS_OK;
4007 status = SMB_VFS_CREATE_FILE(
4008 conn, /* conn */
4009 req, /* req */
4010 NULL, /* dirfsp */
4011 smb_fname, /* fname */
4012 FILE_WRITE_DATA, /* access_mask */
4013 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4014 FILE_SHARE_DELETE),
4015 FILE_OPEN, /* create_disposition*/
4016 0, /* create_options */
4017 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4018 0, /* oplock_request */
4019 NULL, /* lease */
4020 0, /* allocation_size */
4021 0, /* private_flags */
4022 NULL, /* sd */
4023 NULL, /* ea_list */
4024 &new_fsp, /* result */
4025 NULL, /* pinfo */
4026 NULL, NULL); /* create context */
4028 if (!NT_STATUS_IS_OK(status)) {
4029 /* NB. We check for open_was_deferred in the caller. */
4030 return status;
4033 /* See RAW-SFILEINFO-END-OF-FILE */
4034 if (fail_after_createfile) {
4035 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4036 return NT_STATUS_INVALID_LEVEL;
4039 if (vfs_set_filelen(new_fsp, size) == -1) {
4040 status = map_nt_error_from_unix(errno);
4041 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4042 return status;
4045 trigger_write_time_update_immediate(new_fsp);
4046 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4047 return NT_STATUS_OK;
4050 /****************************************************************************
4051 Deal with SMB_INFO_SET_EA.
4052 ****************************************************************************/
4054 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4055 const char *pdata,
4056 int total_data,
4057 files_struct *fsp,
4058 struct smb_filename *smb_fname)
4060 struct ea_list *ea_list = NULL;
4061 TALLOC_CTX *ctx = NULL;
4062 NTSTATUS status = NT_STATUS_OK;
4064 if (total_data < 10) {
4066 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4067 length. They seem to have no effect. Bug #3212. JRA */
4069 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4070 /* We're done. We only get EA info in this call. */
4071 return NT_STATUS_OK;
4074 return NT_STATUS_INVALID_PARAMETER;
4077 if (IVAL(pdata,0) > total_data) {
4078 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4079 IVAL(pdata,0), (unsigned int)total_data));
4080 return NT_STATUS_INVALID_PARAMETER;
4083 ctx = talloc_tos();
4084 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4085 if (!ea_list) {
4086 return NT_STATUS_INVALID_PARAMETER;
4089 if (fsp == NULL) {
4091 * The only way fsp can be NULL here is if
4092 * smb_fname points at a symlink and
4093 * and we're in POSIX context.
4094 * Ensure this is the case.
4096 * In this case we cannot set the EA.
4098 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4099 return NT_STATUS_ACCESS_DENIED;
4102 status = set_ea(conn, fsp, ea_list);
4104 return status;
4107 /****************************************************************************
4108 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4109 ****************************************************************************/
4111 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4112 const char *pdata,
4113 int total_data,
4114 files_struct *fsp)
4116 struct ea_list *ea_list = NULL;
4117 NTSTATUS status;
4119 if (fsp == NULL) {
4120 return NT_STATUS_INVALID_HANDLE;
4123 if (!lp_ea_support(SNUM(conn))) {
4124 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4125 "EA's not supported.\n",
4126 (unsigned int)total_data));
4127 return NT_STATUS_EAS_NOT_SUPPORTED;
4130 if (total_data < 10) {
4131 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4132 "too small.\n",
4133 (unsigned int)total_data));
4134 return NT_STATUS_INVALID_PARAMETER;
4137 ea_list = read_nttrans_ea_list(talloc_tos(),
4138 pdata,
4139 total_data);
4141 if (!ea_list) {
4142 return NT_STATUS_INVALID_PARAMETER;
4145 status = set_ea(conn, fsp, ea_list);
4147 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4148 smb_fname_str_dbg(fsp->fsp_name),
4149 nt_errstr(status) ));
4151 return status;
4155 /****************************************************************************
4156 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4157 ****************************************************************************/
4159 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4160 const char *pdata,
4161 int total_data,
4162 files_struct *fsp,
4163 struct smb_filename *smb_fname)
4165 NTSTATUS status = NT_STATUS_OK;
4166 bool delete_on_close;
4167 uint32_t dosmode = 0;
4169 if (total_data < 1) {
4170 return NT_STATUS_INVALID_PARAMETER;
4173 if (fsp == NULL) {
4174 return NT_STATUS_INVALID_HANDLE;
4177 delete_on_close = (CVAL(pdata,0) ? True : False);
4178 dosmode = fdos_mode(fsp);
4180 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4181 "delete_on_close = %u\n",
4182 smb_fname_str_dbg(smb_fname),
4183 (unsigned int)dosmode,
4184 (unsigned int)delete_on_close ));
4186 if (delete_on_close) {
4187 status = can_set_delete_on_close(fsp, dosmode);
4188 if (!NT_STATUS_IS_OK(status)) {
4189 return status;
4193 /* The set is across all open files on this dev/inode pair. */
4194 if (!set_delete_on_close(fsp, delete_on_close,
4195 conn->session_info->security_token,
4196 conn->session_info->unix_token)) {
4197 return NT_STATUS_ACCESS_DENIED;
4199 return NT_STATUS_OK;
4202 /****************************************************************************
4203 Deal with SMB_FILE_POSITION_INFORMATION.
4204 ****************************************************************************/
4206 static NTSTATUS smb_file_position_information(connection_struct *conn,
4207 const char *pdata,
4208 int total_data,
4209 files_struct *fsp)
4211 uint64_t position_information;
4213 if (total_data < 8) {
4214 return NT_STATUS_INVALID_PARAMETER;
4217 if (fsp == NULL) {
4218 /* Ignore on pathname based set. */
4219 return NT_STATUS_OK;
4222 position_information = (uint64_t)IVAL(pdata,0);
4223 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4225 DEBUG(10,("smb_file_position_information: Set file position "
4226 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4227 (double)position_information));
4228 fh_set_position_information(fsp->fh, position_information);
4229 return NT_STATUS_OK;
4232 /****************************************************************************
4233 Deal with SMB_FILE_MODE_INFORMATION.
4234 ****************************************************************************/
4236 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4237 const char *pdata,
4238 int total_data)
4240 uint32_t mode;
4242 if (total_data < 4) {
4243 return NT_STATUS_INVALID_PARAMETER;
4245 mode = IVAL(pdata,0);
4246 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4247 return NT_STATUS_INVALID_PARAMETER;
4249 return NT_STATUS_OK;
4252 /****************************************************************************
4253 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4254 ****************************************************************************/
4256 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4257 struct smb_request *req,
4258 const char *pdata,
4259 int total_data,
4260 files_struct *fsp,
4261 struct smb_filename *smb_fname_src)
4263 bool overwrite;
4264 uint32_t len;
4265 char *newname = NULL;
4266 struct files_struct *dst_dirfsp = NULL;
4267 struct smb_filename *smb_fname_dst = NULL;
4268 const char *dst_original_lcomp = NULL;
4269 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4270 NTSTATUS status = NT_STATUS_OK;
4271 TALLOC_CTX *ctx = talloc_tos();
4273 if (!fsp) {
4274 return NT_STATUS_INVALID_HANDLE;
4277 if (total_data < 20) {
4278 return NT_STATUS_INVALID_PARAMETER;
4281 overwrite = (CVAL(pdata,0) ? True : False);
4282 len = IVAL(pdata,16);
4284 if (len > (total_data - 20) || (len == 0)) {
4285 return NT_STATUS_INVALID_PARAMETER;
4288 (void)srvstr_pull_talloc(ctx,
4289 pdata,
4290 req->flags2,
4291 &newname,
4292 &pdata[20],
4293 len,
4294 STR_TERMINATE);
4296 if (newname == NULL) {
4297 return NT_STATUS_INVALID_PARAMETER;
4300 /* SMB2 rename paths are never DFS. */
4301 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4302 ucf_flags &= ~UCF_DFS_PATHNAME;
4304 status = check_path_syntax(newname,
4305 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4306 if (!NT_STATUS_IS_OK(status)) {
4307 return status;
4310 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4311 newname));
4313 if (newname[0] == ':') {
4314 /* Create an smb_fname to call rename_internals_fsp() with. */
4315 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4316 fsp->base_fsp->fsp_name->base_name,
4317 newname,
4318 NULL,
4319 fsp->base_fsp->fsp_name->twrp,
4320 fsp->base_fsp->fsp_name->flags);
4321 if (smb_fname_dst == NULL) {
4322 status = NT_STATUS_NO_MEMORY;
4323 goto out;
4325 } else {
4326 status = filename_convert_dirfsp(ctx,
4327 conn,
4328 newname,
4329 ucf_flags,
4330 0, /* Never a TWRP. */
4331 &dst_dirfsp,
4332 &smb_fname_dst);
4333 if (!NT_STATUS_IS_OK(status)) {
4334 goto out;
4339 * Set the original last component, since
4340 * rename_internals_fsp() requires it.
4342 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4343 conn,
4344 newname,
4345 ucf_flags);
4346 if (dst_original_lcomp == NULL) {
4347 status = NT_STATUS_NO_MEMORY;
4348 goto out;
4351 DEBUG(10,("smb2_file_rename_information: "
4352 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4353 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4354 smb_fname_str_dbg(smb_fname_dst)));
4355 status = rename_internals_fsp(conn,
4356 fsp,
4357 smb_fname_dst,
4358 dst_original_lcomp,
4359 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4360 overwrite);
4362 out:
4363 TALLOC_FREE(smb_fname_dst);
4364 return status;
4367 static NTSTATUS smb2_file_link_information(connection_struct *conn,
4368 struct smb_request *req,
4369 const char *pdata,
4370 int total_data,
4371 files_struct *fsp,
4372 struct smb_filename *smb_fname_src)
4374 bool overwrite;
4375 uint32_t len;
4376 char *newname = NULL;
4377 struct files_struct *dst_dirfsp = NULL;
4378 struct smb_filename *smb_fname_dst = NULL;
4379 NTSTATUS status = NT_STATUS_OK;
4380 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4381 size_t ret;
4382 TALLOC_CTX *ctx = talloc_tos();
4384 if (!fsp) {
4385 return NT_STATUS_INVALID_HANDLE;
4388 if (total_data < 20) {
4389 return NT_STATUS_INVALID_PARAMETER;
4392 overwrite = (CVAL(pdata,0) ? true : false);
4393 len = IVAL(pdata,16);
4395 if (len > (total_data - 20) || (len == 0)) {
4396 return NT_STATUS_INVALID_PARAMETER;
4399 ret = srvstr_pull_talloc(ctx,
4400 pdata,
4401 req->flags2,
4402 &newname,
4403 &pdata[20],
4404 len,
4405 STR_TERMINATE);
4407 if (ret == (size_t)-1 || newname == NULL) {
4408 return NT_STATUS_INVALID_PARAMETER;
4411 /* SMB2 hardlink paths are never DFS. */
4412 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4413 ucf_flags &= ~UCF_DFS_PATHNAME;
4415 status = check_path_syntax(newname,
4416 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4417 if (!NT_STATUS_IS_OK(status)) {
4418 return status;
4421 DBG_DEBUG("got name |%s|\n", newname);
4423 status = filename_convert_dirfsp(ctx,
4424 conn,
4425 newname,
4426 ucf_flags,
4427 0, /* No TWRP. */
4428 &dst_dirfsp,
4429 &smb_fname_dst);
4430 if (!NT_STATUS_IS_OK(status)) {
4431 return status;
4434 if (fsp->base_fsp) {
4435 /* No stream names. */
4436 return NT_STATUS_NOT_SUPPORTED;
4439 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4440 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4441 smb_fname_str_dbg(smb_fname_dst));
4442 status = hardlink_internals(ctx,
4443 conn,
4444 req,
4445 overwrite,
4446 fsp->fsp_name,
4447 smb_fname_dst);
4449 TALLOC_FREE(smb_fname_dst);
4450 return status;
4453 static NTSTATUS smb_file_link_information(connection_struct *conn,
4454 struct smb_request *req,
4455 const char *pdata,
4456 int total_data,
4457 files_struct *fsp,
4458 struct smb_filename *smb_fname_src)
4460 bool overwrite;
4461 uint32_t len;
4462 char *newname = NULL;
4463 struct files_struct *dst_dirfsp = NULL;
4464 struct smb_filename *smb_fname_dst = NULL;
4465 NTSTATUS status = NT_STATUS_OK;
4466 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4467 NTTIME dst_twrp = 0;
4468 TALLOC_CTX *ctx = talloc_tos();
4470 if (!fsp) {
4471 return NT_STATUS_INVALID_HANDLE;
4474 if (total_data < 20) {
4475 return NT_STATUS_INVALID_PARAMETER;
4478 overwrite = (CVAL(pdata,0) ? true : false);
4479 len = IVAL(pdata,16);
4481 if (len > (total_data - 20) || (len == 0)) {
4482 return NT_STATUS_INVALID_PARAMETER;
4485 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4486 srvstr_get_path_posix(ctx,
4487 pdata,
4488 req->flags2,
4489 &newname,
4490 &pdata[20],
4491 len,
4492 STR_TERMINATE,
4493 &status);
4494 ucf_flags |= UCF_POSIX_PATHNAMES;
4495 } else {
4496 srvstr_get_path(ctx,
4497 pdata,
4498 req->flags2,
4499 &newname,
4500 &pdata[20],
4501 len,
4502 STR_TERMINATE,
4503 &status);
4505 if (!NT_STATUS_IS_OK(status)) {
4506 return status;
4509 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4510 newname));
4512 if (ucf_flags & UCF_GMT_PATHNAME) {
4513 extract_snapshot_token(newname, &dst_twrp);
4515 /* hardlink paths are never DFS. */
4516 ucf_flags &= ~UCF_DFS_PATHNAME;
4518 status = filename_convert_dirfsp(ctx,
4519 conn,
4520 newname,
4521 ucf_flags,
4522 dst_twrp,
4523 &dst_dirfsp,
4524 &smb_fname_dst);
4525 if (!NT_STATUS_IS_OK(status)) {
4526 return status;
4529 if (fsp->base_fsp) {
4530 /* No stream names. */
4531 return NT_STATUS_NOT_SUPPORTED;
4534 DEBUG(10,("smb_file_link_information: "
4535 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4536 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4537 smb_fname_str_dbg(smb_fname_dst)));
4538 status = hardlink_internals(ctx,
4539 conn,
4540 req,
4541 overwrite,
4542 fsp->fsp_name,
4543 smb_fname_dst);
4545 TALLOC_FREE(smb_fname_dst);
4546 return status;
4550 /****************************************************************************
4551 Deal with SMB_FILE_RENAME_INFORMATION.
4552 ****************************************************************************/
4554 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4555 struct smb_request *req,
4556 const char *pdata,
4557 int total_data,
4558 files_struct *fsp,
4559 struct smb_filename *smb_fname_src)
4561 bool overwrite;
4562 uint32_t root_fid;
4563 uint32_t len;
4564 char *newname = NULL;
4565 struct files_struct *dst_dirfsp = NULL;
4566 struct smb_filename *smb_fname_dst = NULL;
4567 const char *dst_original_lcomp = NULL;
4568 NTSTATUS status = NT_STATUS_OK;
4569 char *p;
4570 TALLOC_CTX *ctx = talloc_tos();
4572 if (total_data < 13) {
4573 return NT_STATUS_INVALID_PARAMETER;
4576 overwrite = (CVAL(pdata,0) != 0);
4577 root_fid = IVAL(pdata,4);
4578 len = IVAL(pdata,8);
4580 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4581 return NT_STATUS_INVALID_PARAMETER;
4584 if (req->posix_pathnames) {
4585 srvstr_get_path_posix(ctx,
4586 pdata,
4587 req->flags2,
4588 &newname,
4589 &pdata[12],
4590 len,
4592 &status);
4593 } else {
4594 srvstr_get_path(ctx,
4595 pdata,
4596 req->flags2,
4597 &newname,
4598 &pdata[12],
4599 len,
4601 &status);
4603 if (!NT_STATUS_IS_OK(status)) {
4604 return status;
4607 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4608 newname));
4610 /* Check the new name has no '/' characters. */
4611 if (strchr_m(newname, '/')) {
4612 return NT_STATUS_NOT_SUPPORTED;
4615 if (fsp && fsp->base_fsp) {
4616 /* newname must be a stream name. */
4617 if (newname[0] != ':') {
4618 return NT_STATUS_NOT_SUPPORTED;
4621 /* Create an smb_fname to call rename_internals_fsp() with. */
4622 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4623 fsp->base_fsp->fsp_name->base_name,
4624 newname,
4625 NULL,
4626 fsp->base_fsp->fsp_name->twrp,
4627 fsp->base_fsp->fsp_name->flags);
4628 if (smb_fname_dst == NULL) {
4629 status = NT_STATUS_NO_MEMORY;
4630 goto out;
4634 * Get the original last component, since
4635 * rename_internals_fsp() requires it.
4637 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4638 conn,
4639 newname,
4641 if (dst_original_lcomp == NULL) {
4642 status = NT_STATUS_NO_MEMORY;
4643 goto out;
4646 } else {
4648 * Build up an smb_fname_dst based on the filename passed in.
4649 * We basically just strip off the last component, and put on
4650 * the newname instead.
4652 char *base_name = NULL;
4653 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4654 NTTIME dst_twrp = 0;
4656 /* newname must *not* be a stream name. */
4657 if (newname[0] == ':') {
4658 return NT_STATUS_NOT_SUPPORTED;
4662 * Strip off the last component (filename) of the path passed
4663 * in.
4665 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4666 if (!base_name) {
4667 return NT_STATUS_NO_MEMORY;
4669 p = strrchr_m(base_name, '/');
4670 if (p) {
4671 p[1] = '\0';
4672 } else {
4673 base_name = talloc_strdup(ctx, "");
4674 if (!base_name) {
4675 return NT_STATUS_NO_MEMORY;
4678 /* Append the new name. */
4679 base_name = talloc_asprintf_append(base_name,
4680 "%s",
4681 newname);
4682 if (!base_name) {
4683 return NT_STATUS_NO_MEMORY;
4686 if (ucf_flags & UCF_GMT_PATHNAME) {
4687 extract_snapshot_token(base_name, &dst_twrp);
4690 /* The newname is *not* a DFS path. */
4691 ucf_flags &= ~UCF_DFS_PATHNAME;
4693 status = filename_convert_dirfsp(ctx,
4694 conn,
4695 base_name,
4696 ucf_flags,
4697 dst_twrp,
4698 &dst_dirfsp,
4699 &smb_fname_dst);
4701 if (!NT_STATUS_IS_OK(status)) {
4702 goto out;
4704 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4705 conn,
4706 newname,
4707 ucf_flags);
4708 if (dst_original_lcomp == NULL) {
4709 status = NT_STATUS_NO_MEMORY;
4710 goto out;
4714 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4715 DEBUG(10,("smb_file_rename_information: "
4716 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4717 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4718 smb_fname_str_dbg(smb_fname_dst)));
4719 status = rename_internals_fsp(conn,
4720 fsp,
4721 smb_fname_dst,
4722 dst_original_lcomp,
4724 overwrite);
4725 } else {
4726 DEBUG(10,("smb_file_rename_information: "
4727 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4728 smb_fname_str_dbg(smb_fname_src),
4729 smb_fname_str_dbg(smb_fname_dst)));
4730 status = rename_internals(ctx,
4731 conn,
4732 req,
4733 NULL, /* src_dirfsp */
4734 smb_fname_src,
4735 smb_fname_dst,
4736 dst_original_lcomp,
4738 overwrite,
4739 FILE_WRITE_ATTRIBUTES);
4741 out:
4742 TALLOC_FREE(smb_fname_dst);
4743 return status;
4746 /****************************************************************************
4747 Deal with SMB_SET_FILE_BASIC_INFO.
4748 ****************************************************************************/
4750 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4751 const char *pdata,
4752 int total_data,
4753 files_struct *fsp,
4754 struct smb_filename *smb_fname)
4756 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4757 struct smb_file_time ft;
4758 uint32_t dosmode = 0;
4759 NTSTATUS status = NT_STATUS_OK;
4761 init_smb_file_time(&ft);
4763 if (total_data < 36) {
4764 return NT_STATUS_INVALID_PARAMETER;
4767 if (fsp == NULL) {
4768 return NT_STATUS_INVALID_HANDLE;
4771 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4772 if (!NT_STATUS_IS_OK(status)) {
4773 return status;
4776 /* Set the attributes */
4777 dosmode = IVAL(pdata,32);
4778 status = smb_set_file_dosmode(conn, fsp, dosmode);
4779 if (!NT_STATUS_IS_OK(status)) {
4780 return status;
4783 /* create time */
4784 ft.create_time = pull_long_date_full_timespec(pdata);
4786 /* access time */
4787 ft.atime = pull_long_date_full_timespec(pdata+8);
4789 /* write time. */
4790 ft.mtime = pull_long_date_full_timespec(pdata+16);
4792 /* change time. */
4793 ft.ctime = pull_long_date_full_timespec(pdata+24);
4795 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4796 smb_fname_str_dbg(smb_fname)));
4798 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4799 if (!NT_STATUS_IS_OK(status)) {
4800 return status;
4803 if (fsp->fsp_flags.modified) {
4804 trigger_write_time_update_immediate(fsp);
4806 return NT_STATUS_OK;
4809 /****************************************************************************
4810 Deal with SMB_INFO_STANDARD.
4811 ****************************************************************************/
4813 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4814 const char *pdata,
4815 int total_data,
4816 files_struct *fsp,
4817 struct smb_filename *smb_fname)
4819 NTSTATUS status;
4820 struct smb_file_time ft;
4822 init_smb_file_time(&ft);
4824 if (total_data < 12) {
4825 return NT_STATUS_INVALID_PARAMETER;
4828 if (fsp == NULL) {
4829 return NT_STATUS_INVALID_HANDLE;
4832 /* create time */
4833 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4834 /* access time */
4835 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4836 /* write time */
4837 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4839 DEBUG(10,("smb_set_info_standard: file %s\n",
4840 smb_fname_str_dbg(smb_fname)));
4842 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4843 if (!NT_STATUS_IS_OK(status)) {
4844 return status;
4847 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4848 if (!NT_STATUS_IS_OK(status)) {
4849 return status;
4852 if (fsp->fsp_flags.modified) {
4853 trigger_write_time_update_immediate(fsp);
4855 return NT_STATUS_OK;
4858 /****************************************************************************
4859 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4860 ****************************************************************************/
4862 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4863 struct smb_request *req,
4864 const char *pdata,
4865 int total_data,
4866 files_struct *fsp,
4867 struct smb_filename *smb_fname)
4869 uint64_t allocation_size = 0;
4870 NTSTATUS status = NT_STATUS_OK;
4871 files_struct *new_fsp = NULL;
4873 if (!VALID_STAT(smb_fname->st)) {
4874 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4877 if (total_data < 8) {
4878 return NT_STATUS_INVALID_PARAMETER;
4881 allocation_size = (uint64_t)IVAL(pdata,0);
4882 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4883 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4884 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4885 (double)allocation_size));
4887 if (allocation_size) {
4888 allocation_size = smb_roundup(conn, allocation_size);
4891 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4892 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
4893 (double)allocation_size));
4895 if (fsp &&
4896 !fsp->fsp_flags.is_pathref &&
4897 fsp_get_io_fd(fsp) != -1)
4899 /* Open file handle. */
4900 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4901 return NT_STATUS_ACCESS_DENIED;
4904 /* Only change if needed. */
4905 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4906 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4907 return map_nt_error_from_unix(errno);
4910 /* But always update the time. */
4912 * This is equivalent to a write. Ensure it's seen immediately
4913 * if there are no pending writes.
4915 trigger_write_time_update_immediate(fsp);
4916 return NT_STATUS_OK;
4919 /* Pathname or stat or directory file. */
4920 status = SMB_VFS_CREATE_FILE(
4921 conn, /* conn */
4922 req, /* req */
4923 NULL, /* dirfsp */
4924 smb_fname, /* fname */
4925 FILE_WRITE_DATA, /* access_mask */
4926 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4927 FILE_SHARE_DELETE),
4928 FILE_OPEN, /* create_disposition*/
4929 0, /* create_options */
4930 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4931 0, /* oplock_request */
4932 NULL, /* lease */
4933 0, /* allocation_size */
4934 0, /* private_flags */
4935 NULL, /* sd */
4936 NULL, /* ea_list */
4937 &new_fsp, /* result */
4938 NULL, /* pinfo */
4939 NULL, NULL); /* create context */
4941 if (!NT_STATUS_IS_OK(status)) {
4942 /* NB. We check for open_was_deferred in the caller. */
4943 return status;
4946 /* Only change if needed. */
4947 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4948 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4949 status = map_nt_error_from_unix(errno);
4950 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4951 return status;
4955 /* Changing the allocation size should set the last mod time. */
4957 * This is equivalent to a write. Ensure it's seen immediately
4958 * if there are no pending writes.
4960 trigger_write_time_update_immediate(new_fsp);
4961 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4962 return NT_STATUS_OK;
4965 /****************************************************************************
4966 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4967 ****************************************************************************/
4969 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4970 struct smb_request *req,
4971 const char *pdata,
4972 int total_data,
4973 files_struct *fsp,
4974 struct smb_filename *smb_fname,
4975 bool fail_after_createfile)
4977 off_t size;
4979 if (total_data < 8) {
4980 return NT_STATUS_INVALID_PARAMETER;
4983 size = IVAL(pdata,0);
4984 size |= (((off_t)IVAL(pdata,4)) << 32);
4985 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4986 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4987 (double)size));
4989 return smb_set_file_size(conn, req,
4990 fsp,
4991 smb_fname,
4992 &smb_fname->st,
4993 size,
4994 fail_after_createfile);
4997 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
4998 struct smb_request *req,
4999 TALLOC_CTX *mem_ctx,
5000 uint16_t info_level,
5001 files_struct *fsp,
5002 struct smb_filename *smb_fname,
5003 char **ppdata, int total_data,
5004 int *ret_data_size)
5006 char *pdata = *ppdata;
5007 NTSTATUS status = NT_STATUS_OK;
5008 int data_return_size = 0;
5010 *ret_data_size = 0;
5012 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5013 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5014 fsp_fnum_dbg(fsp),
5015 info_level, total_data));
5017 switch (info_level) {
5019 case SMB_INFO_STANDARD:
5021 status = smb_set_info_standard(conn,
5022 pdata,
5023 total_data,
5024 fsp,
5025 smb_fname);
5026 break;
5029 case SMB_INFO_SET_EA:
5031 status = smb_info_set_ea(conn,
5032 pdata,
5033 total_data,
5034 fsp,
5035 smb_fname);
5036 break;
5039 case SMB_SET_FILE_BASIC_INFO:
5040 case SMB_FILE_BASIC_INFORMATION:
5042 status = smb_set_file_basic_info(conn,
5043 pdata,
5044 total_data,
5045 fsp,
5046 smb_fname);
5047 break;
5050 case SMB_FILE_ALLOCATION_INFORMATION:
5051 case SMB_SET_FILE_ALLOCATION_INFO:
5053 status = smb_set_file_allocation_info(conn, req,
5054 pdata,
5055 total_data,
5056 fsp,
5057 smb_fname);
5058 break;
5061 case SMB_FILE_END_OF_FILE_INFORMATION:
5062 case SMB_SET_FILE_END_OF_FILE_INFO:
5065 * XP/Win7 both fail after the createfile with
5066 * SMB_SET_FILE_END_OF_FILE_INFO but not
5067 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5068 * The level is known here, so pass it down
5069 * appropriately.
5071 bool should_fail =
5072 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5074 status = smb_set_file_end_of_file_info(conn, req,
5075 pdata,
5076 total_data,
5077 fsp,
5078 smb_fname,
5079 should_fail);
5080 break;
5083 case SMB_FILE_DISPOSITION_INFORMATION:
5084 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5086 #if 0
5087 /* JRA - We used to just ignore this on a path ?
5088 * Shouldn't this be invalid level on a pathname
5089 * based call ?
5091 if (tran_call != TRANSACT2_SETFILEINFO) {
5092 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5094 #endif
5095 status = smb_set_file_disposition_info(conn,
5096 pdata,
5097 total_data,
5098 fsp,
5099 smb_fname);
5100 break;
5103 case SMB_FILE_POSITION_INFORMATION:
5105 status = smb_file_position_information(conn,
5106 pdata,
5107 total_data,
5108 fsp);
5109 break;
5112 case SMB_FILE_FULL_EA_INFORMATION:
5114 status = smb_set_file_full_ea_info(conn,
5115 pdata,
5116 total_data,
5117 fsp);
5118 break;
5121 /* From tridge Samba4 :
5122 * MODE_INFORMATION in setfileinfo (I have no
5123 * idea what "mode information" on a file is - it takes a value of 0,
5124 * 2, 4 or 6. What could it be?).
5127 case SMB_FILE_MODE_INFORMATION:
5129 status = smb_file_mode_information(conn,
5130 pdata,
5131 total_data);
5132 break;
5135 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5136 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5137 case SMB_FILE_SHORT_NAME_INFORMATION:
5138 return NT_STATUS_NOT_SUPPORTED;
5140 case SMB_FILE_RENAME_INFORMATION:
5142 status = smb_file_rename_information(conn, req,
5143 pdata, total_data,
5144 fsp, smb_fname);
5145 break;
5148 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5150 /* SMB2 rename information. */
5151 status = smb2_file_rename_information(conn, req,
5152 pdata, total_data,
5153 fsp, smb_fname);
5154 break;
5157 case SMB_FILE_LINK_INFORMATION:
5159 if (conn->sconn->using_smb2) {
5160 status = smb2_file_link_information(conn,
5161 req,
5162 pdata,
5163 total_data,
5164 fsp,
5165 smb_fname);
5166 } else {
5167 status = smb_file_link_information(conn,
5168 req,
5169 pdata,
5170 total_data,
5171 fsp,
5172 smb_fname);
5174 break;
5177 default:
5178 return NT_STATUS_INVALID_LEVEL;
5181 if (!NT_STATUS_IS_OK(status)) {
5182 return status;
5185 *ret_data_size = data_return_size;
5186 return NT_STATUS_OK;
5189 static uint32_t generate_volume_serial_number(
5190 const struct loadparm_substitution *lp_sub,
5191 int snum)
5193 int serial = lp_volume_serial_number(snum);
5194 return serial != -1 ? serial:
5195 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5196 (str_checksum(get_local_machine_name())<<16);