conf: Remove "smb3 unix extensions" parameter
[Samba.git] / source3 / smbd / smb2_trans2.c
blobffd966f561467aac9ed54419ab3d9a6ecc8542f5
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 "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
44 #include "messages.h"
45 #include "libcli/smb/smb2_posix.h"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/lib/substitute.h"
48 #include "source3/lib/adouble.h"
50 #define DIR_ENTRY_SAFETY_MARGIN 4096
52 static uint32_t generate_volume_serial_number(
53 const struct loadparm_substitution *lp_sub,
54 int snum);
56 /****************************************************************************
57 Check if an open file handle is a symlink.
58 ****************************************************************************/
60 NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
63 if (!VALID_STAT(fsp->fsp_name->st)) {
64 return NT_STATUS_ACCESS_DENIED;
66 if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
67 return NT_STATUS_ACCESS_DENIED;
69 if (fsp_get_pathref_fd(fsp) == -1) {
70 return NT_STATUS_ACCESS_DENIED;
72 return NT_STATUS_OK;
75 NTSTATUS check_access_fsp(struct files_struct *fsp,
76 uint32_t access_mask)
78 if (!fsp->fsp_flags.is_fsa) {
79 return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
80 fsp,
81 false,
82 access_mask);
84 if (!(fsp->access_mask & access_mask)) {
85 return NT_STATUS_ACCESS_DENIED;
87 return NT_STATUS_OK;
90 /********************************************************************
91 Roundup a value to the nearest allocation roundup size boundary.
92 Only do this for Windows clients.
93 ********************************************************************/
95 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
97 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
99 /* Only roundup for Windows clients. */
100 enum remote_arch_types ra_type = get_remote_arch();
101 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
102 val = SMB_ROUNDUP(val,rval);
104 return val;
107 /****************************************************************************
108 Utility functions for dealing with extended attributes.
109 ****************************************************************************/
111 /****************************************************************************
112 Refuse to allow clients to overwrite our private xattrs.
113 ****************************************************************************/
115 bool samba_private_attr_name(const char *unix_ea_name)
117 bool prohibited = false;
119 prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
120 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
121 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
122 prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
123 prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
125 if (prohibited) {
126 return true;
129 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
130 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
131 return true;
133 return false;
136 /****************************************************************************
137 Get one EA value. Fill in a struct ea_struct.
138 ****************************************************************************/
140 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
141 files_struct *fsp,
142 const char *ea_name,
143 struct ea_struct *pea)
145 /* Get the value of this xattr. Max size is 64k. */
146 size_t attr_size = 256;
147 char *val = NULL;
148 ssize_t sizeret;
149 size_t max_xattr_size = 0;
151 if (fsp == NULL) {
152 return NT_STATUS_INVALID_HANDLE;
155 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
157 again:
159 val = talloc_realloc(mem_ctx, val, char, attr_size);
160 if (!val) {
161 return NT_STATUS_NO_MEMORY;
164 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
165 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
166 attr_size = max_xattr_size;
167 goto again;
170 if (sizeret == -1) {
171 return map_nt_error_from_unix(errno);
174 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
175 dump_data(10, (uint8_t *)val, sizeret);
177 pea->flags = 0;
178 if (strnequal(ea_name, "user.", 5)) {
179 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
180 } else {
181 pea->name = talloc_strdup(mem_ctx, ea_name);
183 if (pea->name == NULL) {
184 TALLOC_FREE(val);
185 return NT_STATUS_NO_MEMORY;
187 pea->value.data = (unsigned char *)val;
188 pea->value.length = (size_t)sizeret;
189 return NT_STATUS_OK;
192 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
193 files_struct *fsp,
194 char ***pnames,
195 size_t *pnum_names)
197 char smallbuf[1024];
198 /* Get a list of all xattrs. Max namesize is 64k. */
199 size_t ea_namelist_size = 1024;
200 char *ea_namelist = smallbuf;
201 char *to_free = NULL;
203 char *p;
204 char **names;
205 size_t num_names;
206 ssize_t sizeret = -1;
207 NTSTATUS status;
209 if (pnames) {
210 *pnames = NULL;
212 *pnum_names = 0;
214 if (fsp == NULL) {
216 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
217 * symlink. This is ok, handle it here, by just return no EA's
218 * on a symlink.
220 return NT_STATUS_OK;
223 /* should be the case that fsp != NULL */
224 SMB_ASSERT(fsp != NULL);
226 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
227 ea_namelist_size);
229 if ((sizeret == -1) && (errno == ERANGE)) {
230 ea_namelist_size = 65536;
231 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
232 if (ea_namelist == NULL) {
233 return NT_STATUS_NO_MEMORY;
235 to_free = ea_namelist;
237 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
238 ea_namelist_size);
241 if (sizeret == -1) {
242 status = map_nt_error_from_unix(errno);
243 TALLOC_FREE(to_free);
244 return status;
247 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
249 if (sizeret == 0) {
250 TALLOC_FREE(to_free);
251 return NT_STATUS_OK;
255 * Ensure the result is 0-terminated
258 if (ea_namelist[sizeret-1] != '\0') {
259 TALLOC_FREE(to_free);
260 return NT_STATUS_INTERNAL_ERROR;
264 * count the names
266 num_names = 0;
268 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
269 num_names += 1;
272 *pnum_names = num_names;
274 if (pnames == NULL) {
275 TALLOC_FREE(to_free);
276 return NT_STATUS_OK;
279 names = talloc_array(mem_ctx, char *, num_names);
280 if (names == NULL) {
281 DEBUG(0, ("talloc failed\n"));
282 TALLOC_FREE(to_free);
283 return NT_STATUS_NO_MEMORY;
286 if (ea_namelist == smallbuf) {
287 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
288 if (ea_namelist == NULL) {
289 TALLOC_FREE(names);
290 return NT_STATUS_NO_MEMORY;
292 } else {
293 talloc_steal(names, ea_namelist);
295 ea_namelist = talloc_realloc(names, ea_namelist, char,
296 sizeret);
297 if (ea_namelist == NULL) {
298 TALLOC_FREE(names);
299 return NT_STATUS_NO_MEMORY;
303 num_names = 0;
305 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
306 names[num_names++] = p;
309 *pnames = names;
311 return NT_STATUS_OK;
314 /****************************************************************************
315 Return a linked list of the total EA's. Plus the total size
316 ****************************************************************************/
318 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
319 files_struct *fsp,
320 size_t *pea_total_len,
321 struct ea_list **ea_list)
323 /* Get a list of all xattrs. Max namesize is 64k. */
324 size_t i, num_names;
325 char **names;
326 struct ea_list *ea_list_head = NULL;
327 bool posix_pathnames = false;
328 NTSTATUS status;
330 *pea_total_len = 0;
331 *ea_list = NULL;
333 /* symlink */
334 if (fsp == NULL) {
335 return NT_STATUS_OK;
338 if (!lp_ea_support(SNUM(fsp->conn))) {
339 return NT_STATUS_OK;
342 if (fsp_is_alternate_stream(fsp)) {
343 return NT_STATUS_INVALID_PARAMETER;
346 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
348 status = get_ea_names_from_fsp(talloc_tos(),
349 fsp,
350 &names,
351 &num_names);
353 if (!NT_STATUS_IS_OK(status)) {
354 return status;
357 if (num_names == 0) {
358 return NT_STATUS_OK;
361 for (i=0; i<num_names; i++) {
362 struct ea_list *listp;
363 fstring dos_ea_name;
366 * POSIX EA names are divided into several namespaces by
367 * means of string prefixes. Usually, the system controls
368 * semantics for each namespace, but the 'user' namespace is
369 * available for arbitrary use, which comes closest to
370 * Windows EA semantics. Hence, we map POSIX EAs from the
371 * 'user' namespace to Windows EAs, and just ignore all the
372 * other namespaces. Also, a few specific names in the 'user'
373 * namespace are used by Samba internally. Filter them out as
374 * well, and only present the EAs that are available for
375 * arbitrary use.
377 if (!strnequal(names[i], "user.", 5)
378 || samba_private_attr_name(names[i]))
379 continue;
382 * Filter out any underlying POSIX EA names
383 * that a Windows client can't handle.
385 if (!posix_pathnames &&
386 is_invalid_windows_ea_name(names[i])) {
387 continue;
390 listp = talloc(mem_ctx, struct ea_list);
391 if (listp == NULL) {
392 return NT_STATUS_NO_MEMORY;
395 status = get_ea_value_fsp(listp,
396 fsp,
397 names[i],
398 &listp->ea);
400 if (!NT_STATUS_IS_OK(status)) {
401 TALLOC_FREE(listp);
402 return status;
405 if (listp->ea.value.length == 0) {
407 * We can never return a zero length EA.
408 * Windows reports the EA's as corrupted.
410 TALLOC_FREE(listp);
411 continue;
412 } else if (listp->ea.value.length > 65536) {
414 * SMB clients may report error with file
415 * if large EA is presented to them.
417 DBG_ERR("EA [%s] on file [%s] exceeds "
418 "maximum permitted EA size of 64KiB: %zu\n.",
419 listp->ea.name, fsp_str_dbg(fsp),
420 listp->ea.value.length);
421 TALLOC_FREE(listp);
422 continue;
425 push_ascii_fstring(dos_ea_name, listp->ea.name);
427 *pea_total_len +=
428 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
430 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
431 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
432 (unsigned int)listp->ea.value.length));
434 DLIST_ADD_END(ea_list_head, listp);
438 /* Add on 4 for total length. */
439 if (*pea_total_len) {
440 *pea_total_len += 4;
443 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
444 (unsigned int)*pea_total_len));
446 *ea_list = ea_list_head;
447 return NT_STATUS_OK;
450 /****************************************************************************
451 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
452 that was filled.
453 ****************************************************************************/
455 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
456 connection_struct *conn, struct ea_list *ea_list)
458 unsigned int ret_data_size = 4;
459 char *p = pdata;
461 SMB_ASSERT(total_data_size >= 4);
463 if (!lp_ea_support(SNUM(conn))) {
464 SIVAL(pdata,4,0);
465 return 4;
468 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
469 size_t dos_namelen;
470 fstring dos_ea_name;
471 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
472 dos_namelen = strlen(dos_ea_name);
473 if (dos_namelen > 255 || dos_namelen == 0) {
474 break;
476 if (ea_list->ea.value.length > 65535) {
477 break;
479 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
480 break;
483 /* We know we have room. */
484 SCVAL(p,0,ea_list->ea.flags);
485 SCVAL(p,1,dos_namelen);
486 SSVAL(p,2,ea_list->ea.value.length);
487 strlcpy(p+4, dos_ea_name, dos_namelen+1);
488 if (ea_list->ea.value.length > 0) {
489 memcpy(p + 4 + dos_namelen + 1,
490 ea_list->ea.value.data,
491 ea_list->ea.value.length);
494 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
495 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
498 ret_data_size = PTR_DIFF(p, pdata);
499 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
500 SIVAL(pdata,0,ret_data_size);
501 return ret_data_size;
504 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
505 char *pdata,
506 unsigned int total_data_size,
507 unsigned int *ret_data_size,
508 connection_struct *conn,
509 struct ea_list *ea_list)
511 uint8_t *p = (uint8_t *)pdata;
512 uint8_t *last_start = NULL;
513 bool do_store_data = (pdata != NULL);
515 *ret_data_size = 0;
517 if (!lp_ea_support(SNUM(conn))) {
518 return NT_STATUS_NO_EAS_ON_FILE;
521 for (; ea_list; ea_list = ea_list->next) {
522 size_t dos_namelen;
523 fstring dos_ea_name;
524 size_t this_size;
525 size_t pad = 0;
527 if (last_start != NULL && do_store_data) {
528 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
530 last_start = p;
532 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
533 dos_namelen = strlen(dos_ea_name);
534 if (dos_namelen > 255 || dos_namelen == 0) {
535 return NT_STATUS_INTERNAL_ERROR;
537 if (ea_list->ea.value.length > 65535) {
538 return NT_STATUS_INTERNAL_ERROR;
541 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
543 if (ea_list->next) {
544 pad = (4 - (this_size % 4)) % 4;
545 this_size += pad;
548 if (do_store_data) {
549 if (this_size > total_data_size) {
550 return NT_STATUS_INFO_LENGTH_MISMATCH;
553 /* We know we have room. */
554 SIVAL(p, 0x00, 0); /* next offset */
555 SCVAL(p, 0x04, ea_list->ea.flags);
556 SCVAL(p, 0x05, dos_namelen);
557 SSVAL(p, 0x06, ea_list->ea.value.length);
558 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
559 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
560 if (pad) {
561 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
562 '\0',
563 pad);
565 total_data_size -= this_size;
568 p += this_size;
571 *ret_data_size = PTR_DIFF(p, pdata);
572 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
573 return NT_STATUS_OK;
576 unsigned int estimate_ea_size(files_struct *fsp)
578 size_t total_ea_len = 0;
579 TALLOC_CTX *mem_ctx;
580 struct ea_list *ea_list = NULL;
581 NTSTATUS status;
583 /* symlink */
584 if (fsp == NULL) {
585 return 0;
588 if (!lp_ea_support(SNUM(fsp->conn))) {
589 return 0;
592 mem_ctx = talloc_stackframe();
594 /* If this is a stream fsp, then we need to instead find the
595 * estimated ea len from the main file, not the stream
596 * (streams cannot have EAs), but the estimate isn't just 0 in
597 * this case! */
598 fsp = metadata_fsp(fsp);
599 (void)get_ea_list_from_fsp(mem_ctx,
600 fsp,
601 &total_ea_len,
602 &ea_list);
604 if(fsp->conn->sconn->using_smb2) {
605 unsigned int ret_data_size;
607 * We're going to be using fill_ea_chained_buffer() to
608 * marshall EA's - this size is significantly larger
609 * than the SMB1 buffer. Re-calculate the size without
610 * marshalling.
612 status = fill_ea_chained_buffer(mem_ctx,
613 NULL,
615 &ret_data_size,
616 fsp->conn,
617 ea_list);
618 if (!NT_STATUS_IS_OK(status)) {
619 ret_data_size = 0;
621 total_ea_len = ret_data_size;
623 TALLOC_FREE(mem_ctx);
624 return total_ea_len;
627 /****************************************************************************
628 Ensure the EA name is case insensitive by matching any existing EA name.
629 ****************************************************************************/
631 static void canonicalize_ea_name(files_struct *fsp,
632 fstring unix_ea_name)
634 size_t total_ea_len;
635 TALLOC_CTX *mem_ctx = talloc_tos();
636 struct ea_list *ea_list;
637 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
638 fsp,
639 &total_ea_len,
640 &ea_list);
641 if (!NT_STATUS_IS_OK(status)) {
642 return;
645 for (; ea_list; ea_list = ea_list->next) {
646 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
647 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
648 &unix_ea_name[5], ea_list->ea.name));
649 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
650 break;
655 /****************************************************************************
656 Set or delete an extended attribute.
657 ****************************************************************************/
659 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
660 struct ea_list *ea_list)
662 NTSTATUS status;
663 bool posix_pathnames = false;
665 if (!lp_ea_support(SNUM(conn))) {
666 return NT_STATUS_EAS_NOT_SUPPORTED;
669 if (fsp == NULL) {
670 return NT_STATUS_INVALID_HANDLE;
673 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
675 status = refuse_symlink_fsp(fsp);
676 if (!NT_STATUS_IS_OK(status)) {
677 return status;
680 status = check_access_fsp(fsp, FILE_WRITE_EA);
681 if (!NT_STATUS_IS_OK(status)) {
682 return status;
685 /* Setting EAs on streams isn't supported. */
686 if (fsp_is_alternate_stream(fsp)) {
687 return NT_STATUS_INVALID_PARAMETER;
691 * Filter out invalid Windows EA names - before
692 * we set *any* of them.
695 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
696 return STATUS_INVALID_EA_NAME;
699 for (;ea_list; ea_list = ea_list->next) {
700 int ret;
701 fstring unix_ea_name;
704 * Complementing the forward mapping from POSIX EAs to
705 * Windows EAs in get_ea_list_from_fsp(), here we map in the
706 * opposite direction from Windows EAs to the 'user' namespace
707 * of POSIX EAs. Hence, all POSIX EA names the we set here must
708 * start with a 'user.' prefix.
710 fstrcpy(unix_ea_name, "user.");
711 fstrcat(unix_ea_name, ea_list->ea.name);
713 canonicalize_ea_name(fsp, unix_ea_name);
715 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
717 if (samba_private_attr_name(unix_ea_name)) {
718 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
719 return NT_STATUS_ACCESS_DENIED;
722 if (ea_list->ea.value.length == 0) {
723 /* Remove the attribute. */
724 DBG_DEBUG("deleting ea name %s on "
725 "file %s by file descriptor.\n",
726 unix_ea_name, fsp_str_dbg(fsp));
727 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
728 #ifdef ENOATTR
729 /* Removing a non existent attribute always succeeds. */
730 if (ret == -1 && errno == ENOATTR) {
731 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
732 unix_ea_name));
733 ret = 0;
735 #endif
736 } else {
737 DEBUG(10,("set_ea: setting ea name %s on file "
738 "%s by file descriptor.\n",
739 unix_ea_name, fsp_str_dbg(fsp)));
740 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
741 ea_list->ea.value.data, ea_list->ea.value.length, 0);
744 if (ret == -1) {
745 #ifdef ENOTSUP
746 if (errno == ENOTSUP) {
747 return NT_STATUS_EAS_NOT_SUPPORTED;
749 #endif
750 return map_nt_error_from_unix(errno);
754 return NT_STATUS_OK;
757 /****************************************************************************
758 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
759 ****************************************************************************/
761 struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
763 struct ea_list *ea_list_head = NULL;
764 size_t offset = 0;
765 size_t bytes_used = 0;
767 while (offset < data_size) {
768 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
770 if (!eal) {
771 return NULL;
774 DLIST_ADD_END(ea_list_head, eal);
775 offset += bytes_used;
778 return ea_list_head;
781 /****************************************************************************
782 Count the total EA size needed.
783 ****************************************************************************/
785 static size_t ea_list_size(struct ea_list *ealist)
787 fstring dos_ea_name;
788 struct ea_list *listp;
789 size_t ret = 0;
791 for (listp = ealist; listp; listp = listp->next) {
792 push_ascii_fstring(dos_ea_name, listp->ea.name);
793 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
795 /* Add on 4 for total length. */
796 if (ret) {
797 ret += 4;
800 return ret;
803 /****************************************************************************
804 Return a union of EA's from a file list and a list of names.
805 The TALLOC context for the two lists *MUST* be identical as we steal
806 memory from one list to add to another. JRA.
807 ****************************************************************************/
809 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
811 struct ea_list *nlistp, *flistp;
813 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
814 for (flistp = file_list; flistp; flistp = flistp->next) {
815 if (strequal(nlistp->ea.name, flistp->ea.name)) {
816 break;
820 if (flistp) {
821 /* Copy the data from this entry. */
822 nlistp->ea.flags = flistp->ea.flags;
823 nlistp->ea.value = flistp->ea.value;
824 } else {
825 /* Null entry. */
826 nlistp->ea.flags = 0;
827 ZERO_STRUCT(nlistp->ea.value);
831 *total_ea_len = ea_list_size(name_list);
832 return name_list;
835 /****************************************************************************
836 Return the filetype for UNIX extensions.
837 ****************************************************************************/
839 static uint32_t unix_filetype(mode_t mode)
841 if(S_ISREG(mode))
842 return UNIX_TYPE_FILE;
843 else if(S_ISDIR(mode))
844 return UNIX_TYPE_DIR;
845 #ifdef S_ISLNK
846 else if(S_ISLNK(mode))
847 return UNIX_TYPE_SYMLINK;
848 #endif
849 #ifdef S_ISCHR
850 else if(S_ISCHR(mode))
851 return UNIX_TYPE_CHARDEV;
852 #endif
853 #ifdef S_ISBLK
854 else if(S_ISBLK(mode))
855 return UNIX_TYPE_BLKDEV;
856 #endif
857 #ifdef S_ISFIFO
858 else if(S_ISFIFO(mode))
859 return UNIX_TYPE_FIFO;
860 #endif
861 #ifdef S_ISSOCK
862 else if(S_ISSOCK(mode))
863 return UNIX_TYPE_SOCKET;
864 #endif
866 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
867 return UNIX_TYPE_UNKNOWN;
870 /****************************************************************************
871 Map wire perms onto standard UNIX permissions. Obey share restrictions.
872 ****************************************************************************/
874 NTSTATUS unix_perms_from_wire(connection_struct *conn,
875 const SMB_STRUCT_STAT *psbuf,
876 uint32_t perms,
877 enum perm_type ptype,
878 mode_t *ret_perms)
880 mode_t ret = 0;
882 if (perms == SMB_MODE_NO_CHANGE) {
883 if (!VALID_STAT(*psbuf)) {
884 return NT_STATUS_INVALID_PARAMETER;
885 } else {
886 *ret_perms = psbuf->st_ex_mode;
887 return NT_STATUS_OK;
891 ret = wire_perms_to_unix(perms);
893 if (ptype == PERM_NEW_FILE) {
895 * "create mask"/"force create mode" are
896 * only applied to new files, not existing ones.
898 ret &= lp_create_mask(SNUM(conn));
899 /* Add in force bits */
900 ret |= lp_force_create_mode(SNUM(conn));
901 } else if (ptype == PERM_NEW_DIR) {
903 * "directory mask"/"force directory mode" are
904 * only applied to new directories, not existing ones.
906 ret &= lp_directory_mask(SNUM(conn));
907 /* Add in force bits */
908 ret |= lp_force_directory_mode(SNUM(conn));
911 *ret_perms = ret;
912 return NT_STATUS_OK;
915 /****************************************************************************
916 Get a level dependent lanman2 dir entry.
917 ****************************************************************************/
919 struct smbd_dirptr_lanman2_state {
920 connection_struct *conn;
921 uint32_t info_level;
922 bool check_mangled_names;
923 bool case_sensitive;
926 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
927 void *private_data,
928 const char *dname,
929 const char *mask,
930 char **_fname)
932 struct smbd_dirptr_lanman2_state *state =
933 (struct smbd_dirptr_lanman2_state *)private_data;
934 bool ok;
935 char mangled_name[13]; /* mangled 8.3 name. */
936 bool got_match;
937 const char *fname;
939 /* Mangle fname if it's an illegal name. */
940 if (mangle_must_mangle(dname, state->conn->params)) {
942 * Slow path - ensure we can push the original name as UCS2. If
943 * not, then just don't return this name.
945 NTSTATUS status;
946 size_t ret_len = 0;
947 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
948 uint8_t *tmp = talloc_array(talloc_tos(),
949 uint8_t,
950 len);
952 status = srvstr_push(NULL,
953 FLAGS2_UNICODE_STRINGS,
954 tmp,
955 dname,
956 len,
957 STR_TERMINATE,
958 &ret_len);
960 TALLOC_FREE(tmp);
962 if (!NT_STATUS_IS_OK(status)) {
963 return false;
966 ok = name_to_8_3(dname, mangled_name,
967 true, state->conn->params);
968 if (!ok) {
969 return false;
971 fname = mangled_name;
972 } else {
973 fname = dname;
976 got_match = mask_match(fname, mask,
977 state->case_sensitive);
979 if(!got_match && state->check_mangled_names &&
980 !mangle_is_8_3(fname, false, state->conn->params)) {
982 * It turns out that NT matches wildcards against
983 * both long *and* short names. This may explain some
984 * of the wildcard weirdness from old DOS clients
985 * that some people have been seeing.... JRA.
987 /* Force the mangling into 8.3. */
988 ok = name_to_8_3(fname, mangled_name,
989 false, state->conn->params);
990 if (!ok) {
991 return false;
994 got_match = mask_match(mangled_name, mask,
995 state->case_sensitive);
998 if (!got_match) {
999 return false;
1002 *_fname = talloc_strdup(ctx, fname);
1003 if (*_fname == NULL) {
1004 return false;
1007 return true;
1010 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1011 void *private_data,
1012 struct files_struct *dirfsp,
1013 struct smb_filename *smb_fname,
1014 bool get_dosmode,
1015 uint32_t *_mode)
1017 if (get_dosmode) {
1018 SMB_ASSERT(smb_fname != NULL);
1019 *_mode = fdos_mode(smb_fname->fsp);
1020 if (smb_fname->fsp != NULL) {
1021 smb_fname->st = smb_fname->fsp->fsp_name->st;
1024 return true;
1027 static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1029 if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1030 unsigned ea_size = estimate_ea_size(fsp);
1031 return ea_size;
1033 return IO_REPARSE_TAG_DFS;
1036 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1037 connection_struct *conn,
1038 uint16_t flags2,
1039 uint32_t info_level,
1040 struct ea_list *name_list,
1041 bool check_mangled_names,
1042 bool requires_resume_key,
1043 uint32_t mode,
1044 const char *fname,
1045 const struct smb_filename *smb_fname,
1046 int space_remaining,
1047 uint8_t align,
1048 bool do_pad,
1049 char *base_data,
1050 char **ppdata,
1051 char *end_data,
1052 uint64_t *last_entry_off)
1054 char *p, *q, *pdata = *ppdata;
1055 uint32_t reskey=0;
1056 uint64_t file_size = 0;
1057 uint64_t allocation_size = 0;
1058 uint64_t file_id = 0;
1059 size_t len = 0;
1060 struct timespec mdate_ts = {0};
1061 struct timespec adate_ts = {0};
1062 struct timespec cdate_ts = {0};
1063 struct timespec create_date_ts = {0};
1064 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1065 char *nameptr;
1066 char *last_entry_ptr;
1067 bool was_8_3;
1068 int off;
1069 int pad = 0;
1070 NTSTATUS status;
1071 struct readdir_attr_data *readdir_attr_data = NULL;
1072 uint32_t ea_size;
1074 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1075 file_size = get_file_size_stat(&smb_fname->st);
1077 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1080 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1081 * a DFS symlink.
1083 if (smb_fname->fsp != NULL &&
1084 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1085 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1086 ctx,
1087 &readdir_attr_data);
1088 if (!NT_STATUS_IS_OK(status)) {
1089 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1090 status)) {
1091 return status;
1096 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1098 mdate_ts = smb_fname->st.st_ex_mtime;
1099 adate_ts = smb_fname->st.st_ex_atime;
1100 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1101 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1103 if (lp_dos_filetime_resolution(SNUM(conn))) {
1104 dos_filetime_timespec(&create_date_ts);
1105 dos_filetime_timespec(&mdate_ts);
1106 dos_filetime_timespec(&adate_ts);
1107 dos_filetime_timespec(&cdate_ts);
1110 create_date = convert_timespec_to_time_t(create_date_ts);
1111 mdate = convert_timespec_to_time_t(mdate_ts);
1112 adate = convert_timespec_to_time_t(adate_ts);
1114 /* align the record */
1115 SMB_ASSERT(align >= 1);
1117 off = (int)PTR_DIFF(pdata, base_data);
1118 pad = (off + (align-1)) & ~(align-1);
1119 pad -= off;
1121 if (pad && pad > space_remaining) {
1122 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1123 "for padding (wanted %u, had %d)\n",
1124 (unsigned int)pad,
1125 space_remaining ));
1126 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1129 off += pad;
1130 /* initialize padding to 0 */
1131 if (pad) {
1132 memset(pdata, 0, pad);
1134 space_remaining -= pad;
1136 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1137 space_remaining ));
1139 pdata += pad;
1140 p = pdata;
1141 last_entry_ptr = p;
1143 pad = 0;
1144 off = 0;
1146 switch (info_level) {
1147 case SMB_FIND_INFO_STANDARD:
1148 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1149 if(requires_resume_key) {
1150 SIVAL(p,0,reskey);
1151 p += 4;
1153 srv_put_dos_date2(p,0,create_date);
1154 srv_put_dos_date2(p,4,adate);
1155 srv_put_dos_date2(p,8,mdate);
1156 SIVAL(p,12,(uint32_t)file_size);
1157 SIVAL(p,16,(uint32_t)allocation_size);
1158 SSVAL(p,20,mode);
1159 p += 23;
1160 nameptr = p;
1161 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1162 p += ucs2_align(base_data, p, 0);
1164 status = srvstr_push(base_data, flags2, p,
1165 fname, PTR_DIFF(end_data, p),
1166 STR_TERMINATE, &len);
1167 if (!NT_STATUS_IS_OK(status)) {
1168 return status;
1170 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1171 if (len > 2) {
1172 SCVAL(nameptr, -1, len - 2);
1173 } else {
1174 SCVAL(nameptr, -1, 0);
1176 } else {
1177 if (len > 1) {
1178 SCVAL(nameptr, -1, len - 1);
1179 } else {
1180 SCVAL(nameptr, -1, 0);
1183 p += len;
1184 break;
1186 case SMB_FIND_EA_SIZE:
1187 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1188 if (requires_resume_key) {
1189 SIVAL(p,0,reskey);
1190 p += 4;
1192 srv_put_dos_date2(p,0,create_date);
1193 srv_put_dos_date2(p,4,adate);
1194 srv_put_dos_date2(p,8,mdate);
1195 SIVAL(p,12,(uint32_t)file_size);
1196 SIVAL(p,16,(uint32_t)allocation_size);
1197 SSVAL(p,20,mode);
1199 ea_size = estimate_ea_size(smb_fname->fsp);
1200 SIVAL(p,22,ea_size); /* Extended attributes */
1202 p += 27;
1203 nameptr = p - 1;
1204 status = srvstr_push(base_data, flags2,
1205 p, fname, PTR_DIFF(end_data, p),
1206 STR_TERMINATE | STR_NOALIGN, &len);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 return status;
1210 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1211 if (len > 2) {
1212 len -= 2;
1213 } else {
1214 len = 0;
1216 } else {
1217 if (len > 1) {
1218 len -= 1;
1219 } else {
1220 len = 0;
1223 SCVAL(nameptr,0,len);
1224 p += len;
1225 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1226 break;
1228 case SMB_FIND_EA_LIST:
1230 struct ea_list *file_list = NULL;
1231 size_t ea_len = 0;
1233 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1234 if (!name_list) {
1235 return NT_STATUS_INVALID_PARAMETER;
1237 if (requires_resume_key) {
1238 SIVAL(p,0,reskey);
1239 p += 4;
1241 srv_put_dos_date2(p,0,create_date);
1242 srv_put_dos_date2(p,4,adate);
1243 srv_put_dos_date2(p,8,mdate);
1244 SIVAL(p,12,(uint32_t)file_size);
1245 SIVAL(p,16,(uint32_t)allocation_size);
1246 SSVAL(p,20,mode);
1247 p += 22; /* p now points to the EA area. */
1249 status = get_ea_list_from_fsp(ctx,
1250 smb_fname->fsp,
1251 &ea_len, &file_list);
1252 if (!NT_STATUS_IS_OK(status)) {
1253 file_list = NULL;
1255 name_list = ea_list_union(name_list, file_list, &ea_len);
1257 /* We need to determine if this entry will fit in the space available. */
1258 /* Max string size is 255 bytes. */
1259 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1260 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1261 "(wanted %u, had %d)\n",
1262 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1263 space_remaining ));
1264 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1267 /* Push the ea_data followed by the name. */
1268 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1269 nameptr = p;
1270 status = srvstr_push(base_data, flags2,
1271 p + 1, fname, PTR_DIFF(end_data, p+1),
1272 STR_TERMINATE | STR_NOALIGN, &len);
1273 if (!NT_STATUS_IS_OK(status)) {
1274 return status;
1276 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1277 if (len > 2) {
1278 len -= 2;
1279 } else {
1280 len = 0;
1282 } else {
1283 if (len > 1) {
1284 len -= 1;
1285 } else {
1286 len = 0;
1289 SCVAL(nameptr,0,len);
1290 p += len + 1;
1291 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1292 break;
1295 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1296 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1297 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1298 p += 4;
1299 SIVAL(p,0,reskey); p += 4;
1300 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1301 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1302 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1303 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1304 SOFF_T(p,0,file_size); p += 8;
1305 SOFF_T(p,0,allocation_size); p += 8;
1306 SIVAL(p,0,mode); p += 4;
1307 q = p; p += 4; /* q is placeholder for name length. */
1308 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1309 SIVAL(p, 0, ea_size);
1310 p += 4;
1311 /* Clear the short name buffer. This is
1312 * IMPORTANT as not doing so will trigger
1313 * a Win2k client bug. JRA.
1315 if (!was_8_3 && check_mangled_names) {
1316 char mangled_name[13]; /* mangled 8.3 name. */
1317 if (!name_to_8_3(fname,mangled_name,True,
1318 conn->params)) {
1319 /* Error - mangle failed ! */
1320 memset(mangled_name,'\0',12);
1322 mangled_name[12] = 0;
1323 status = srvstr_push(base_data, flags2,
1324 p+2, mangled_name, 24,
1325 STR_UPPER|STR_UNICODE, &len);
1326 if (!NT_STATUS_IS_OK(status)) {
1327 return status;
1329 if (len < 24) {
1330 memset(p + 2 + len,'\0',24 - len);
1332 SSVAL(p, 0, len);
1333 } else {
1334 memset(p,'\0',26);
1336 p += 2 + 24;
1337 status = srvstr_push(base_data, flags2, p,
1338 fname, PTR_DIFF(end_data, p),
1339 STR_TERMINATE_ASCII, &len);
1340 if (!NT_STATUS_IS_OK(status)) {
1341 return status;
1343 SIVAL(q,0,len);
1344 p += len;
1346 len = PTR_DIFF(p, pdata);
1347 pad = (len + (align-1)) & ~(align-1);
1349 * offset to the next entry, the caller
1350 * will overwrite it for the last entry
1351 * that's why we always include the padding
1353 SIVAL(pdata,0,pad);
1355 * set padding to zero
1357 if (do_pad) {
1358 memset(p, 0, pad - len);
1359 p = pdata + pad;
1360 } else {
1361 p = pdata + len;
1363 break;
1365 case SMB_FIND_FILE_DIRECTORY_INFO:
1366 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1367 p += 4;
1368 SIVAL(p,0,reskey); p += 4;
1369 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1370 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1371 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1372 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1373 SOFF_T(p,0,file_size); p += 8;
1374 SOFF_T(p,0,allocation_size); p += 8;
1375 SIVAL(p,0,mode); p += 4;
1376 status = srvstr_push(base_data, flags2,
1377 p + 4, fname, PTR_DIFF(end_data, p+4),
1378 STR_TERMINATE_ASCII, &len);
1379 if (!NT_STATUS_IS_OK(status)) {
1380 return status;
1382 SIVAL(p,0,len);
1383 p += 4 + len;
1385 len = PTR_DIFF(p, pdata);
1386 pad = (len + (align-1)) & ~(align-1);
1388 * offset to the next entry, the caller
1389 * will overwrite it for the last entry
1390 * that's why we always include the padding
1392 SIVAL(pdata,0,pad);
1394 * set padding to zero
1396 if (do_pad) {
1397 memset(p, 0, pad - len);
1398 p = pdata + pad;
1399 } else {
1400 p = pdata + len;
1402 break;
1404 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1405 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1406 p += 4;
1407 SIVAL(p,0,reskey); p += 4;
1408 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1409 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1410 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1411 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1412 SOFF_T(p,0,file_size); p += 8;
1413 SOFF_T(p,0,allocation_size); p += 8;
1414 SIVAL(p,0,mode); p += 4;
1415 q = p; p += 4; /* q is placeholder for name length. */
1416 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1417 SIVAL(p, 0, ea_size);
1418 p +=4;
1419 status = srvstr_push(base_data, flags2, p,
1420 fname, PTR_DIFF(end_data, p),
1421 STR_TERMINATE_ASCII, &len);
1422 if (!NT_STATUS_IS_OK(status)) {
1423 return status;
1425 SIVAL(q, 0, len);
1426 p += len;
1428 len = PTR_DIFF(p, pdata);
1429 pad = (len + (align-1)) & ~(align-1);
1431 * offset to the next entry, the caller
1432 * will overwrite it for the last entry
1433 * that's why we always include the padding
1435 SIVAL(pdata,0,pad);
1437 * set padding to zero
1439 if (do_pad) {
1440 memset(p, 0, pad - len);
1441 p = pdata + pad;
1442 } else {
1443 p = pdata + len;
1445 break;
1447 case SMB_FIND_FILE_NAMES_INFO:
1448 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1449 p += 4;
1450 SIVAL(p,0,reskey); p += 4;
1451 p += 4;
1452 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1453 acl on a dir (tridge) */
1454 status = srvstr_push(base_data, flags2, p,
1455 fname, PTR_DIFF(end_data, p),
1456 STR_TERMINATE_ASCII, &len);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 return status;
1460 SIVAL(p, -4, len);
1461 p += len;
1463 len = PTR_DIFF(p, pdata);
1464 pad = (len + (align-1)) & ~(align-1);
1466 * offset to the next entry, the caller
1467 * will overwrite it for the last entry
1468 * that's why we always include the padding
1470 SIVAL(pdata,0,pad);
1472 * set padding to zero
1474 if (do_pad) {
1475 memset(p, 0, pad - len);
1476 p = pdata + pad;
1477 } else {
1478 p = pdata + len;
1480 break;
1482 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1483 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1484 p += 4;
1485 SIVAL(p,0,reskey); p += 4;
1486 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1487 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1488 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1489 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1490 SOFF_T(p,0,file_size); p += 8;
1491 SOFF_T(p,0,allocation_size); p += 8;
1492 SIVAL(p,0,mode); p += 4;
1493 q = p; p += 4; /* q is placeholder for name length. */
1494 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1495 SIVAL(p, 0, ea_size);
1496 p += 4;
1497 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1498 SBVAL(p,0,file_id); p += 8;
1499 status = srvstr_push(base_data, flags2, p,
1500 fname, PTR_DIFF(end_data, p),
1501 STR_TERMINATE_ASCII, &len);
1502 if (!NT_STATUS_IS_OK(status)) {
1503 return status;
1505 SIVAL(q, 0, len);
1506 p += len;
1508 len = PTR_DIFF(p, pdata);
1509 pad = (len + (align-1)) & ~(align-1);
1511 * offset to the next entry, the caller
1512 * will overwrite it for the last entry
1513 * that's why we always include the padding
1515 SIVAL(pdata,0,pad);
1517 * set padding to zero
1519 if (do_pad) {
1520 memset(p, 0, pad - len);
1521 p = pdata + pad;
1522 } else {
1523 p = pdata + len;
1525 break;
1527 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1528 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1529 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1530 p += 4;
1531 SIVAL(p,0,reskey); p += 4;
1532 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1533 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1534 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1535 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1536 SOFF_T(p,0,file_size); p += 8;
1537 SOFF_T(p,0,allocation_size); p += 8;
1538 SIVAL(p,0,mode); p += 4;
1539 q = p; p += 4; /* q is placeholder for name length */
1540 if (readdir_attr_data &&
1541 readdir_attr_data->type == RDATTR_AAPL) {
1543 * OS X specific SMB2 extension negotiated via
1544 * AAPL create context: return max_access in
1545 * ea_size field.
1547 ea_size = readdir_attr_data->attr_data.aapl.max_access;
1548 } else {
1549 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1551 SIVAL(p,0,ea_size); /* Extended attributes */
1552 p += 4;
1554 if (readdir_attr_data &&
1555 readdir_attr_data->type == RDATTR_AAPL) {
1557 * OS X specific SMB2 extension negotiated via
1558 * AAPL create context: return resource fork
1559 * length and compressed FinderInfo in
1560 * shortname field.
1562 * According to documentation short_name_len
1563 * should be 0, but on the wire behaviour
1564 * shows its set to 24 by clients.
1566 SSVAL(p, 0, 24);
1568 /* Resourefork length */
1569 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1571 /* Compressed FinderInfo */
1572 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1573 } else if (!was_8_3 && check_mangled_names) {
1574 char mangled_name[13]; /* mangled 8.3 name. */
1575 if (!name_to_8_3(fname,mangled_name,True,
1576 conn->params)) {
1577 /* Error - mangle failed ! */
1578 memset(mangled_name,'\0',12);
1580 mangled_name[12] = 0;
1581 status = srvstr_push(base_data, flags2,
1582 p+2, mangled_name, 24,
1583 STR_UPPER|STR_UNICODE, &len);
1584 if (!NT_STATUS_IS_OK(status)) {
1585 return status;
1587 SSVAL(p, 0, len);
1588 if (len < 24) {
1589 memset(p + 2 + len,'\0',24 - len);
1591 SSVAL(p, 0, len);
1592 } else {
1593 /* Clear the short name buffer. This is
1594 * IMPORTANT as not doing so will trigger
1595 * a Win2k client bug. JRA.
1597 memset(p,'\0',26);
1599 p += 26;
1601 /* Reserved ? */
1602 if (readdir_attr_data &&
1603 readdir_attr_data->type == RDATTR_AAPL) {
1605 * OS X specific SMB2 extension negotiated via
1606 * AAPL create context: return UNIX mode in
1607 * reserved field.
1609 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1610 SSVAL(p, 0, aapl_mode);
1611 } else {
1612 SSVAL(p, 0, 0);
1614 p += 2;
1616 SBVAL(p,0,file_id); p += 8;
1617 status = srvstr_push(base_data, flags2, p,
1618 fname, PTR_DIFF(end_data, p),
1619 STR_TERMINATE_ASCII, &len);
1620 if (!NT_STATUS_IS_OK(status)) {
1621 return status;
1623 SIVAL(q,0,len);
1624 p += len;
1626 len = PTR_DIFF(p, pdata);
1627 pad = (len + (align-1)) & ~(align-1);
1629 * offset to the next entry, the caller
1630 * will overwrite it for the last entry
1631 * that's why we always include the padding
1633 SIVAL(pdata,0,pad);
1635 * set padding to zero
1637 if (do_pad) {
1638 memset(p, 0, pad - len);
1639 p = pdata + pad;
1640 } else {
1641 p = pdata + len;
1643 break;
1645 /* CIFS UNIX Extension. */
1647 case SMB_FIND_FILE_UNIX:
1648 case SMB_FIND_FILE_UNIX_INFO2:
1649 p+= 4;
1650 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1652 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1654 if (info_level == SMB_FIND_FILE_UNIX) {
1655 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1656 p = store_file_unix_basic(conn, p,
1657 NULL, &smb_fname->st);
1658 status = srvstr_push(base_data, flags2, p,
1659 fname, PTR_DIFF(end_data, p),
1660 STR_TERMINATE, &len);
1661 if (!NT_STATUS_IS_OK(status)) {
1662 return status;
1664 } else {
1665 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1666 p = store_file_unix_basic_info2(conn, p,
1667 NULL, &smb_fname->st);
1668 nameptr = p;
1669 p += 4;
1670 status = srvstr_push(base_data, flags2, p, fname,
1671 PTR_DIFF(end_data, p), 0, &len);
1672 if (!NT_STATUS_IS_OK(status)) {
1673 return status;
1675 SIVAL(nameptr, 0, len);
1678 p += len;
1680 len = PTR_DIFF(p, pdata);
1681 pad = (len + (align-1)) & ~(align-1);
1683 * offset to the next entry, the caller
1684 * will overwrite it for the last entry
1685 * that's why we always include the padding
1687 SIVAL(pdata,0,pad);
1689 * set padding to zero
1691 if (do_pad) {
1692 memset(p, 0, pad - len);
1693 p = pdata + pad;
1694 } else {
1695 p = pdata + len;
1697 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1699 break;
1701 /* SMB2 UNIX Extension. */
1703 case SMB2_FILE_POSIX_INFORMATION:
1705 uint8_t *buf = NULL;
1706 ssize_t plen = 0;
1707 p+= 4;
1708 SIVAL(p,0,reskey); p+= 4;
1710 DEBUG(10,("smbd_marshall_dir_entry: "
1711 "SMB2_FILE_POSIX_INFORMATION\n"));
1712 if (!(conn->sconn->using_smb2)) {
1713 return NT_STATUS_INVALID_LEVEL;
1716 /* Determine the size of the posix info context */
1717 plen = store_smb2_posix_info(conn,
1718 &smb_fname->st,
1720 mode,
1721 NULL,
1723 if (plen == -1) {
1724 return NT_STATUS_INVALID_PARAMETER;
1726 buf = talloc_zero_size(ctx, plen);
1727 if (buf == NULL) {
1728 return NT_STATUS_NO_MEMORY;
1731 /* Store the context in buf */
1732 store_smb2_posix_info(conn,
1733 &smb_fname->st,
1735 mode,
1736 buf,
1737 plen);
1738 memcpy(p, buf, plen);
1739 p += plen;
1740 TALLOC_FREE(buf);
1742 nameptr = p;
1743 p += 4;
1744 status = srvstr_push(base_data, flags2, p, fname,
1745 PTR_DIFF(end_data, p), 0, &len);
1746 if (!NT_STATUS_IS_OK(status)) {
1747 return status;
1749 SIVAL(nameptr, 0, len);
1751 p += len;
1753 len = PTR_DIFF(p, pdata);
1754 pad = (len + (align-1)) & ~(align-1);
1756 * offset to the next entry, the caller
1757 * will overwrite it for the last entry
1758 * that's why we always include the padding
1760 SIVAL(pdata,0,pad);
1761 break;
1764 default:
1765 return NT_STATUS_INVALID_LEVEL;
1768 if (PTR_DIFF(p,pdata) > space_remaining) {
1769 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1770 "(wanted %u, had %d)\n",
1771 (unsigned int)PTR_DIFF(p,pdata),
1772 space_remaining ));
1773 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1776 /* Setup the last entry pointer, as an offset from base_data */
1777 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1778 /* Advance the data pointer to the next slot */
1779 *ppdata = p;
1781 return NT_STATUS_OK;
1784 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1785 connection_struct *conn,
1786 struct dptr_struct *dirptr,
1787 uint16_t flags2,
1788 const char *path_mask,
1789 uint32_t dirtype,
1790 int info_level,
1791 int requires_resume_key,
1792 bool dont_descend,
1793 bool ask_sharemode,
1794 bool get_dosmode,
1795 uint8_t align,
1796 bool do_pad,
1797 char **ppdata,
1798 char *base_data,
1799 char *end_data,
1800 int space_remaining,
1801 struct smb_filename **_smb_fname,
1802 int *_last_entry_off,
1803 struct ea_list *name_list,
1804 struct file_id *file_id)
1806 const char *p;
1807 const char *mask = NULL;
1808 uint32_t mode = 0;
1809 char *fname = NULL;
1810 struct smb_filename *smb_fname = NULL;
1811 struct smbd_dirptr_lanman2_state state;
1812 bool ok;
1813 uint64_t last_entry_off = 0;
1814 NTSTATUS status;
1815 enum mangled_names_options mangled_names;
1816 bool marshall_with_83_names;
1818 mangled_names = lp_mangled_names(conn->params);
1820 ZERO_STRUCT(state);
1821 state.conn = conn;
1822 state.info_level = info_level;
1823 if (mangled_names != MANGLED_NAMES_NO) {
1824 state.check_mangled_names = true;
1826 state.case_sensitive = dptr_case_sensitive(dirptr);
1828 p = strrchr_m(path_mask,'/');
1829 if(p != NULL) {
1830 if(p[1] == '\0') {
1831 mask = "*.*";
1832 } else {
1833 mask = p+1;
1835 } else {
1836 mask = path_mask;
1839 ok = smbd_dirptr_get_entry(ctx,
1840 dirptr,
1841 mask,
1842 dirtype,
1843 dont_descend,
1844 ask_sharemode,
1845 get_dosmode,
1846 smbd_dirptr_lanman2_match_fn,
1847 smbd_dirptr_lanman2_mode_fn,
1848 &state,
1849 &fname,
1850 &smb_fname,
1851 &mode);
1852 if (!ok) {
1853 return NT_STATUS_END_OF_FILE;
1856 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1858 status = smbd_marshall_dir_entry(ctx,
1859 conn,
1860 flags2,
1861 info_level,
1862 name_list,
1863 marshall_with_83_names,
1864 requires_resume_key,
1865 mode,
1866 fname,
1867 smb_fname,
1868 space_remaining,
1869 align,
1870 do_pad,
1871 base_data,
1872 ppdata,
1873 end_data,
1874 &last_entry_off);
1875 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1876 DEBUG(1,("Conversion error: illegal character: %s\n",
1877 smb_fname_str_dbg(smb_fname)));
1880 if (file_id != NULL) {
1881 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1884 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1885 smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1888 if (!NT_STATUS_IS_OK(status)) {
1889 TALLOC_FREE(smb_fname);
1890 TALLOC_FREE(fname);
1891 return status;
1894 smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1896 if (_smb_fname != NULL) {
1898 * smb_fname is already talloc'ed off ctx.
1899 * We just need to make sure we don't return
1900 * any stream_name, and replace base_name
1901 * with fname in case base_name got mangled.
1902 * This allows us to preserve any smb_fname->fsp
1903 * for asynchronous handle lookups.
1905 TALLOC_FREE(smb_fname->stream_name);
1908 * smbd_dirptr_set_last_name_sent() above consumed
1909 * base_name
1911 smb_fname->base_name = talloc_strdup(smb_fname, fname);
1913 if (smb_fname->base_name == NULL) {
1914 TALLOC_FREE(smb_fname);
1915 TALLOC_FREE(fname);
1916 return NT_STATUS_NO_MEMORY;
1918 *_smb_fname = smb_fname;
1919 } else {
1920 TALLOC_FREE(smb_fname);
1922 TALLOC_FREE(fname);
1924 *_last_entry_off = last_entry_off;
1925 return NT_STATUS_OK;
1928 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1930 const struct loadparm_substitution *lp_sub =
1931 loadparm_s3_global_substitution();
1933 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1934 return objid;
1937 static void samba_extended_info_version(struct smb_extended_info *extended_info)
1939 SMB_ASSERT(extended_info != NULL);
1941 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1942 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1943 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1944 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1945 #ifdef SAMBA_VERSION_REVISION
1946 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1947 #endif
1948 extended_info->samba_subversion = 0;
1949 #ifdef SAMBA_VERSION_RC_RELEASE
1950 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1951 #else
1952 #ifdef SAMBA_VERSION_PRE_RELEASE
1953 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
1954 #endif
1955 #endif
1956 #ifdef SAMBA_VERSION_VENDOR_PATCH
1957 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
1958 #endif
1959 extended_info->samba_gitcommitdate = 0;
1960 #ifdef SAMBA_VERSION_COMMIT_TIME
1961 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
1962 #endif
1964 memset(extended_info->samba_version_string, 0,
1965 sizeof(extended_info->samba_version_string));
1967 snprintf (extended_info->samba_version_string,
1968 sizeof(extended_info->samba_version_string),
1969 "%s", samba_version_string());
1972 static bool fsinfo_unix_valid_level(connection_struct *conn,
1973 uint16_t info_level)
1975 if (conn->sconn->using_smb2 &&
1976 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) {
1977 return true;
1979 #if defined(SMB1SERVER)
1980 if (lp_smb1_unix_extensions() &&
1981 info_level == SMB_QUERY_POSIX_FS_INFO) {
1982 return true;
1984 #endif
1985 return false;
1988 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
1989 connection_struct *conn,
1990 TALLOC_CTX *mem_ctx,
1991 uint16_t info_level,
1992 uint16_t flags2,
1993 unsigned int max_data_bytes,
1994 size_t *fixed_portion,
1995 struct smb_filename *fname,
1996 char **ppdata,
1997 int *ret_data_len)
1999 const struct loadparm_substitution *lp_sub =
2000 loadparm_s3_global_substitution();
2001 char *pdata, *end_data;
2002 int data_len = 0;
2003 size_t len = 0;
2004 const char *vname = volume_label(talloc_tos(), SNUM(conn));
2005 int snum = SNUM(conn);
2006 const char *fstype = lp_fstype(SNUM(conn));
2007 const char *filename = NULL;
2008 const uint64_t bytes_per_sector = 512;
2009 uint32_t additional_flags = 0;
2010 struct smb_filename smb_fname;
2011 SMB_STRUCT_STAT st;
2012 NTSTATUS status = NT_STATUS_OK;
2013 uint64_t df_ret;
2014 uint32_t serial;
2016 if (fname == NULL || fname->base_name == NULL) {
2017 filename = ".";
2018 } else {
2019 filename = fname->base_name;
2022 if (IS_IPC(conn)) {
2023 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2024 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2025 "info level (0x%x) on IPC$.\n",
2026 (unsigned int)info_level));
2027 return NT_STATUS_ACCESS_DENIED;
2031 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2033 smb_fname = (struct smb_filename) {
2034 .base_name = discard_const_p(char, filename),
2035 .flags = fname ? fname->flags : 0,
2036 .twrp = fname ? fname->twrp : 0,
2039 if(info_level != SMB_FS_QUOTA_INFORMATION
2040 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2041 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2042 return map_nt_error_from_unix(errno);
2045 st = smb_fname.st;
2047 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2048 return NT_STATUS_INVALID_PARAMETER;
2051 *ppdata = (char *)SMB_REALLOC(
2052 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2053 if (*ppdata == NULL) {
2054 return NT_STATUS_NO_MEMORY;
2057 pdata = *ppdata;
2058 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2059 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2061 *fixed_portion = 0;
2063 switch (info_level) {
2064 case SMB_INFO_ALLOCATION:
2066 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2067 data_len = 18;
2068 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2069 &dfree, &dsize);
2070 if (df_ret == (uint64_t)-1) {
2071 return map_nt_error_from_unix(errno);
2074 block_size = lp_block_size(snum);
2075 if (bsize < block_size) {
2076 uint64_t factor = block_size/bsize;
2077 bsize = block_size;
2078 dsize /= factor;
2079 dfree /= factor;
2081 if (bsize > block_size) {
2082 uint64_t factor = bsize/block_size;
2083 bsize = block_size;
2084 dsize *= factor;
2085 dfree *= factor;
2087 sectors_per_unit = bsize/bytes_per_sector;
2089 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2090 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2091 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2094 * For large drives, return max values and not modulo.
2096 dsize = MIN(dsize, UINT32_MAX);
2097 dfree = MIN(dfree, UINT32_MAX);
2099 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2100 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2101 SIVAL(pdata,l1_cUnit,dsize);
2102 SIVAL(pdata,l1_cUnitAvail,dfree);
2103 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2104 break;
2107 case SMB_INFO_VOLUME:
2108 /* Return volume name */
2110 * Add volume serial number - hash of a combination of
2111 * the called hostname and the service name.
2113 serial = generate_volume_serial_number(lp_sub, snum);
2114 SIVAL(pdata,0,serial);
2116 * Win2k3 and previous mess this up by sending a name length
2117 * one byte short. I believe only older clients (OS/2 Win9x) use
2118 * this call so try fixing this by adding a terminating null to
2119 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2121 status = srvstr_push(
2122 pdata, flags2,
2123 pdata+l2_vol_szVolLabel, vname,
2124 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2125 STR_NOALIGN|STR_TERMINATE, &len);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 return status;
2129 SCVAL(pdata,l2_vol_cch,len);
2130 data_len = l2_vol_szVolLabel + len;
2131 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2132 "name = %s serial = 0x%04"PRIx32"\n",
2133 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2134 (unsigned)len, vname, serial));
2135 break;
2137 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2138 case SMB_FS_ATTRIBUTE_INFORMATION:
2140 additional_flags = 0;
2141 #if defined(HAVE_SYS_QUOTAS)
2142 additional_flags |= FILE_VOLUME_QUOTAS;
2143 #endif
2145 if(lp_nt_acl_support(SNUM(conn))) {
2146 additional_flags |= FILE_PERSISTENT_ACLS;
2149 /* Capabilities are filled in at connection time through STATVFS call */
2150 additional_flags |= conn->fs_capabilities;
2151 additional_flags |= lp_parm_int(conn->params->service,
2152 "share", "fake_fscaps",
2155 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2156 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2157 additional_flags); /* FS ATTRIBUTES */
2159 SIVAL(pdata,4,255); /* Max filename component length */
2160 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2161 and will think we can't do long filenames */
2162 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2163 PTR_DIFF(end_data, pdata+12),
2164 STR_UNICODE, &len);
2165 if (!NT_STATUS_IS_OK(status)) {
2166 return status;
2168 SIVAL(pdata,8,len);
2169 data_len = 12 + len;
2170 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2171 /* the client only requested a portion of the
2172 file system name */
2173 data_len = max_data_bytes;
2174 status = STATUS_BUFFER_OVERFLOW;
2176 *fixed_portion = 16;
2177 break;
2179 case SMB_QUERY_FS_LABEL_INFO:
2180 case SMB_FS_LABEL_INFORMATION:
2181 status = srvstr_push(pdata, flags2, pdata+4, vname,
2182 PTR_DIFF(end_data, pdata+4), 0, &len);
2183 if (!NT_STATUS_IS_OK(status)) {
2184 return status;
2186 data_len = 4 + len;
2187 SIVAL(pdata,0,len);
2188 break;
2190 case SMB_QUERY_FS_VOLUME_INFO:
2191 case SMB_FS_VOLUME_INFORMATION:
2192 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2193 pdata, &st.st_ex_btime);
2195 * Add volume serial number - hash of a combination of
2196 * the called hostname and the service name.
2198 serial = generate_volume_serial_number(lp_sub, snum);
2199 SIVAL(pdata,8,serial);
2201 /* Max label len is 32 characters. */
2202 status = srvstr_push(pdata, flags2, pdata+18, vname,
2203 PTR_DIFF(end_data, pdata+18),
2204 STR_UNICODE, &len);
2205 if (!NT_STATUS_IS_OK(status)) {
2206 return status;
2208 SIVAL(pdata,12,len);
2209 data_len = 18+len;
2211 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2212 "namelen = %d, vol=%s serv=%s "
2213 "serial=0x%04"PRIx32"\n",
2214 (int)strlen(vname),vname,
2215 lp_servicename(talloc_tos(), lp_sub, snum),
2216 serial));
2217 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2218 /* the client only requested a portion of the
2219 volume label */
2220 data_len = max_data_bytes;
2221 status = STATUS_BUFFER_OVERFLOW;
2223 *fixed_portion = 24;
2224 break;
2226 case SMB_QUERY_FS_SIZE_INFO:
2227 case SMB_FS_SIZE_INFORMATION:
2229 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2230 data_len = 24;
2231 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2232 &dfree, &dsize);
2233 if (df_ret == (uint64_t)-1) {
2234 return map_nt_error_from_unix(errno);
2236 block_size = lp_block_size(snum);
2237 if (bsize < block_size) {
2238 uint64_t factor = block_size/bsize;
2239 bsize = block_size;
2240 dsize /= factor;
2241 dfree /= factor;
2243 if (bsize > block_size) {
2244 uint64_t factor = bsize/block_size;
2245 bsize = block_size;
2246 dsize *= factor;
2247 dfree *= factor;
2249 sectors_per_unit = bsize/bytes_per_sector;
2250 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2251 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2252 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2253 SBIG_UINT(pdata,0,dsize);
2254 SBIG_UINT(pdata,8,dfree);
2255 SIVAL(pdata,16,sectors_per_unit);
2256 SIVAL(pdata,20,bytes_per_sector);
2257 *fixed_portion = 24;
2258 break;
2261 case SMB_FS_FULL_SIZE_INFORMATION:
2263 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2264 data_len = 32;
2265 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2266 &dfree, &dsize);
2267 if (df_ret == (uint64_t)-1) {
2268 return map_nt_error_from_unix(errno);
2270 block_size = lp_block_size(snum);
2271 if (bsize < block_size) {
2272 uint64_t factor = block_size/bsize;
2273 bsize = block_size;
2274 dsize /= factor;
2275 dfree /= factor;
2277 if (bsize > block_size) {
2278 uint64_t factor = bsize/block_size;
2279 bsize = block_size;
2280 dsize *= factor;
2281 dfree *= factor;
2283 sectors_per_unit = bsize/bytes_per_sector;
2284 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2285 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2286 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2287 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2288 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2289 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2290 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2291 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2292 *fixed_portion = 32;
2293 break;
2296 case SMB_QUERY_FS_DEVICE_INFO:
2297 case SMB_FS_DEVICE_INFORMATION:
2299 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2301 if (!CAN_WRITE(conn)) {
2302 characteristics |= FILE_READ_ONLY_DEVICE;
2304 data_len = 8;
2305 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2306 SIVAL(pdata,4,characteristics);
2307 *fixed_portion = 8;
2308 break;
2311 #ifdef HAVE_SYS_QUOTAS
2312 case SMB_FS_QUOTA_INFORMATION:
2314 * what we have to send --metze:
2316 * Unknown1: 24 NULL bytes
2317 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2318 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2319 * Quota Flags: 2 byte :
2320 * Unknown3: 6 NULL bytes
2322 * 48 bytes total
2324 * details for Quota Flags:
2326 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2327 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2328 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2329 * 0x0001 Enable Quotas: enable quota for this fs
2333 /* we need to fake up a fsp here,
2334 * because its not send in this call
2336 files_struct fsp;
2337 SMB_NTQUOTA_STRUCT quotas;
2339 ZERO_STRUCT(fsp);
2340 ZERO_STRUCT(quotas);
2342 fsp.conn = conn;
2343 fsp.fnum = FNUM_FIELD_INVALID;
2345 /* access check */
2346 if (get_current_uid(conn) != 0) {
2347 DEBUG(0,("get_user_quota: access_denied "
2348 "service [%s] user [%s]\n",
2349 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2350 conn->session_info->unix_info->unix_name));
2351 return NT_STATUS_ACCESS_DENIED;
2354 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
2355 NULL, &quotas);
2356 if (!NT_STATUS_IS_OK(status)) {
2357 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2358 return status;
2361 data_len = 48;
2363 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2364 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2366 /* Unknown1 24 NULL bytes*/
2367 SBIG_UINT(pdata,0,(uint64_t)0);
2368 SBIG_UINT(pdata,8,(uint64_t)0);
2369 SBIG_UINT(pdata,16,(uint64_t)0);
2371 /* Default Soft Quota 8 bytes */
2372 SBIG_UINT(pdata,24,quotas.softlim);
2374 /* Default Hard Quota 8 bytes */
2375 SBIG_UINT(pdata,32,quotas.hardlim);
2377 /* Quota flag 2 bytes */
2378 SSVAL(pdata,40,quotas.qflags);
2380 /* Unknown3 6 NULL bytes */
2381 SSVAL(pdata,42,0);
2382 SIVAL(pdata,44,0);
2384 break;
2386 #endif /* HAVE_SYS_QUOTAS */
2387 case SMB_FS_OBJECTID_INFORMATION:
2389 unsigned char objid[16];
2390 struct smb_extended_info extended_info;
2391 memcpy(pdata,create_volume_objectid(conn, objid),16);
2392 samba_extended_info_version (&extended_info);
2393 SIVAL(pdata,16,extended_info.samba_magic);
2394 SIVAL(pdata,20,extended_info.samba_version);
2395 SIVAL(pdata,24,extended_info.samba_subversion);
2396 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2397 memcpy(pdata+36,extended_info.samba_version_string,28);
2398 data_len = 64;
2399 break;
2402 case SMB_FS_SECTOR_SIZE_INFORMATION:
2404 data_len = 28;
2406 * These values match a physical Windows Server 2012
2407 * share backed by NTFS atop spinning rust.
2409 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2410 /* logical_bytes_per_sector */
2411 SIVAL(pdata, 0, bytes_per_sector);
2412 /* phys_bytes_per_sector_atomic */
2413 SIVAL(pdata, 4, bytes_per_sector);
2414 /* phys_bytes_per_sector_perf */
2415 SIVAL(pdata, 8, bytes_per_sector);
2416 /* fs_effective_phys_bytes_per_sector_atomic */
2417 SIVAL(pdata, 12, bytes_per_sector);
2418 /* flags */
2419 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2420 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2421 /* byte_off_sector_align */
2422 SIVAL(pdata, 20, 0);
2423 /* byte_off_partition_align */
2424 SIVAL(pdata, 24, 0);
2425 *fixed_portion = 28;
2426 break;
2430 #if defined(WITH_SMB1SERVER)
2432 * Query the version and capabilities of the CIFS UNIX extensions
2433 * in use.
2436 case SMB_QUERY_CIFS_UNIX_INFO:
2438 bool large_write = lp_min_receive_file_size() &&
2439 !smb1_srv_is_signing_active(xconn);
2440 bool large_read = !smb1_srv_is_signing_active(xconn);
2441 int encrypt_caps = 0;
2443 if (!lp_smb1_unix_extensions()) {
2444 return NT_STATUS_INVALID_LEVEL;
2447 switch (conn->encrypt_level) {
2448 case SMB_SIGNING_OFF:
2449 encrypt_caps = 0;
2450 break;
2451 case SMB_SIGNING_DESIRED:
2452 case SMB_SIGNING_IF_REQUIRED:
2453 case SMB_SIGNING_DEFAULT:
2454 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2455 break;
2456 case SMB_SIGNING_REQUIRED:
2457 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2458 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2459 large_write = false;
2460 large_read = false;
2461 break;
2464 data_len = 12;
2465 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2466 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2468 /* We have POSIX ACLs, pathname, encryption,
2469 * large read/write, and locking capability. */
2471 SBIG_UINT(pdata,4,((uint64_t)(
2472 CIFS_UNIX_POSIX_ACLS_CAP|
2473 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2474 CIFS_UNIX_FCNTL_LOCKS_CAP|
2475 CIFS_UNIX_EXTATTR_CAP|
2476 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2477 encrypt_caps|
2478 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2479 (large_write ?
2480 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2481 break;
2483 #endif
2485 case SMB_QUERY_POSIX_FS_INFO:
2486 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2488 int rc;
2489 struct vfs_statvfs_struct svfs;
2491 if (!fsinfo_unix_valid_level(conn, info_level)) {
2492 return NT_STATUS_INVALID_LEVEL;
2495 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2497 if (!rc) {
2498 data_len = 56;
2499 SIVAL(pdata,0,svfs.OptimalTransferSize);
2500 SIVAL(pdata,4,svfs.BlockSize);
2501 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2502 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2503 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2504 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2505 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2506 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2507 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2508 #ifdef EOPNOTSUPP
2509 } else if (rc == EOPNOTSUPP) {
2510 return NT_STATUS_INVALID_LEVEL;
2511 #endif /* EOPNOTSUPP */
2512 } else {
2513 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2514 return NT_STATUS_DOS(ERRSRV, ERRerror);
2516 break;
2519 case SMB_QUERY_POSIX_WHOAMI:
2521 uint32_t flags = 0;
2522 uint32_t sid_bytes;
2523 uint32_t i;
2525 if (!lp_smb1_unix_extensions()) {
2526 return NT_STATUS_INVALID_LEVEL;
2529 if (max_data_bytes < 40) {
2530 return NT_STATUS_BUFFER_TOO_SMALL;
2533 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2534 flags |= SMB_WHOAMI_GUEST;
2537 /* NOTE: 8 bytes for UID/GID, irrespective of native
2538 * platform size. This matches
2539 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2541 data_len = 4 /* flags */
2542 + 4 /* flag mask */
2543 + 8 /* uid */
2544 + 8 /* gid */
2545 + 4 /* ngroups */
2546 + 4 /* num_sids */
2547 + 4 /* SID bytes */
2548 + 4 /* pad/reserved */
2549 + (conn->session_info->unix_token->ngroups * 8)
2550 /* groups list */
2551 + (conn->session_info->security_token->num_sids *
2552 SID_MAX_SIZE)
2553 /* SID list */;
2555 SIVAL(pdata, 0, flags);
2556 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2557 SBIG_UINT(pdata, 8,
2558 (uint64_t)conn->session_info->unix_token->uid);
2559 SBIG_UINT(pdata, 16,
2560 (uint64_t)conn->session_info->unix_token->gid);
2563 if (data_len >= max_data_bytes) {
2564 /* Potential overflow, skip the GIDs and SIDs. */
2566 SIVAL(pdata, 24, 0); /* num_groups */
2567 SIVAL(pdata, 28, 0); /* num_sids */
2568 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2569 SIVAL(pdata, 36, 0); /* reserved */
2571 data_len = 40;
2572 break;
2575 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2576 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2578 /* We walk the SID list twice, but this call is fairly
2579 * infrequent, and I don't expect that it's performance
2580 * sensitive -- jpeach
2582 for (i = 0, sid_bytes = 0;
2583 i < conn->session_info->security_token->num_sids; ++i) {
2584 sid_bytes += ndr_size_dom_sid(
2585 &conn->session_info->security_token->sids[i],
2589 /* SID list byte count */
2590 SIVAL(pdata, 32, sid_bytes);
2592 /* 4 bytes pad/reserved - must be zero */
2593 SIVAL(pdata, 36, 0);
2594 data_len = 40;
2596 /* GID list */
2597 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2598 SBIG_UINT(pdata, data_len,
2599 (uint64_t)conn->session_info->unix_token->groups[i]);
2600 data_len += 8;
2603 /* SID list */
2604 for (i = 0;
2605 i < conn->session_info->security_token->num_sids; ++i) {
2606 int sid_len = ndr_size_dom_sid(
2607 &conn->session_info->security_token->sids[i],
2610 sid_linearize((uint8_t *)(pdata + data_len),
2611 sid_len,
2612 &conn->session_info->security_token->sids[i]);
2613 data_len += sid_len;
2616 break;
2619 case SMB_MAC_QUERY_FS_INFO:
2621 * Thursby MAC extension... ONLY on NTFS filesystems
2622 * once we do streams then we don't need this
2624 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2625 data_len = 88;
2626 SIVAL(pdata,84,0x100); /* Don't support mac... */
2627 break;
2630 FALL_THROUGH;
2631 default:
2632 return NT_STATUS_INVALID_LEVEL;
2635 *ret_data_len = data_len;
2636 return status;
2639 NTSTATUS smb_set_fsquota(connection_struct *conn,
2640 struct smb_request *req,
2641 files_struct *fsp,
2642 const DATA_BLOB *qdata)
2644 const struct loadparm_substitution *lp_sub =
2645 loadparm_s3_global_substitution();
2646 NTSTATUS status;
2647 SMB_NTQUOTA_STRUCT quotas;
2649 ZERO_STRUCT(quotas);
2651 /* access check */
2652 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2653 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
2654 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2655 conn->session_info->unix_info->unix_name));
2656 return NT_STATUS_ACCESS_DENIED;
2659 if (!check_fsp_ntquota_handle(conn, req,
2660 fsp)) {
2661 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
2662 return NT_STATUS_INVALID_HANDLE;
2665 /* note: normally there're 48 bytes,
2666 * but we didn't use the last 6 bytes for now
2667 * --metze
2669 if (qdata->length < 42) {
2670 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
2671 (unsigned int)qdata->length));
2672 return NT_STATUS_INVALID_PARAMETER;
2675 /* unknown_1 24 NULL bytes in pdata*/
2677 /* the soft quotas 8 bytes (uint64_t)*/
2678 quotas.softlim = BVAL(qdata->data,24);
2680 /* the hard quotas 8 bytes (uint64_t)*/
2681 quotas.hardlim = BVAL(qdata->data,32);
2683 /* quota_flags 2 bytes **/
2684 quotas.qflags = SVAL(qdata->data,40);
2686 /* unknown_2 6 NULL bytes follow*/
2688 /* now set the quotas */
2689 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2690 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
2691 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2692 status = map_nt_error_from_unix(errno);
2693 } else {
2694 status = NT_STATUS_OK;
2696 return status;
2699 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2700 struct smb_request *req,
2701 TALLOC_CTX *mem_ctx,
2702 uint16_t info_level,
2703 files_struct *fsp,
2704 const DATA_BLOB *pdata)
2706 switch (info_level) {
2707 case SMB_FS_QUOTA_INFORMATION:
2709 return smb_set_fsquota(conn,
2710 req,
2711 fsp,
2712 pdata);
2715 default:
2716 break;
2718 return NT_STATUS_INVALID_LEVEL;
2721 /****************************************************************************
2722 Store the FILE_UNIX_BASIC info.
2723 ****************************************************************************/
2725 char *store_file_unix_basic(connection_struct *conn,
2726 char *pdata,
2727 files_struct *fsp,
2728 const SMB_STRUCT_STAT *psbuf)
2730 dev_t devno;
2732 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2733 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
2735 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2736 pdata += 8;
2738 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2739 pdata += 8;
2741 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2742 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2743 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2744 pdata += 24;
2746 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2747 SIVAL(pdata,4,0);
2748 pdata += 8;
2750 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2751 SIVAL(pdata,4,0);
2752 pdata += 8;
2754 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2755 pdata += 4;
2757 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2758 devno = psbuf->st_ex_rdev;
2759 } else {
2760 devno = psbuf->st_ex_dev;
2763 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2764 SIVAL(pdata,4,0);
2765 pdata += 8;
2767 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2768 SIVAL(pdata,4,0);
2769 pdata += 8;
2771 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2772 pdata += 8;
2774 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2775 SIVAL(pdata,4,0);
2776 pdata += 8;
2778 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2779 SIVAL(pdata,4,0);
2780 pdata += 8;
2782 return pdata;
2785 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2786 * the chflags(2) (or equivalent) flags.
2788 * XXX: this really should be behind the VFS interface. To do this, we would
2789 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2790 * Each VFS module could then implement its own mapping as appropriate for the
2791 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2793 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2794 info2_flags_map[] =
2796 #ifdef UF_NODUMP
2797 { UF_NODUMP, EXT_DO_NOT_BACKUP },
2798 #endif
2800 #ifdef UF_IMMUTABLE
2801 { UF_IMMUTABLE, EXT_IMMUTABLE },
2802 #endif
2804 #ifdef UF_APPEND
2805 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2806 #endif
2808 #ifdef UF_HIDDEN
2809 { UF_HIDDEN, EXT_HIDDEN },
2810 #endif
2812 /* Do not remove. We need to guarantee that this array has at least one
2813 * entry to build on HP-UX.
2815 { 0, 0 }
2819 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2820 uint32_t *smb_fflags, uint32_t *smb_fmask)
2822 size_t i;
2824 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2825 *smb_fmask |= info2_flags_map[i].smb_fflag;
2826 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2827 *smb_fflags |= info2_flags_map[i].smb_fflag;
2832 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2833 const uint32_t smb_fflags,
2834 const uint32_t smb_fmask,
2835 int *stat_fflags)
2837 uint32_t max_fmask = 0;
2838 size_t i;
2840 *stat_fflags = psbuf->st_ex_flags;
2842 /* For each flags requested in smb_fmask, check the state of the
2843 * corresponding flag in smb_fflags and set or clear the matching
2844 * stat flag.
2847 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2848 max_fmask |= info2_flags_map[i].smb_fflag;
2849 if (smb_fmask & info2_flags_map[i].smb_fflag) {
2850 if (smb_fflags & info2_flags_map[i].smb_fflag) {
2851 *stat_fflags |= info2_flags_map[i].stat_fflag;
2852 } else {
2853 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2858 /* If smb_fmask is asking to set any bits that are not supported by
2859 * our flag mappings, we should fail.
2861 if ((smb_fmask & max_fmask) != smb_fmask) {
2862 return False;
2865 return True;
2869 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2870 * of file flags and birth (create) time.
2872 char *store_file_unix_basic_info2(connection_struct *conn,
2873 char *pdata,
2874 files_struct *fsp,
2875 const SMB_STRUCT_STAT *psbuf)
2877 uint32_t file_flags = 0;
2878 uint32_t flags_mask = 0;
2880 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2882 /* Create (birth) time 64 bit */
2883 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2884 pdata += 8;
2886 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2887 SIVAL(pdata, 0, file_flags); /* flags */
2888 SIVAL(pdata, 4, flags_mask); /* mask */
2889 pdata += 8;
2891 return pdata;
2894 static NTSTATUS marshall_stream_info(unsigned int num_streams,
2895 const struct stream_struct *streams,
2896 char *data,
2897 unsigned int max_data_bytes,
2898 unsigned int *data_size)
2900 unsigned int i;
2901 unsigned int ofs = 0;
2903 if (max_data_bytes < 32) {
2904 return NT_STATUS_INFO_LENGTH_MISMATCH;
2907 for (i = 0; i < num_streams; i++) {
2908 unsigned int next_offset;
2909 size_t namelen;
2910 smb_ucs2_t *namebuf;
2912 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2913 streams[i].name, &namelen) ||
2914 namelen <= 2)
2916 return NT_STATUS_INVALID_PARAMETER;
2920 * name_buf is now null-terminated, we need to marshall as not
2921 * terminated
2924 namelen -= 2;
2927 * We cannot overflow ...
2929 if ((ofs + 24 + namelen) > max_data_bytes) {
2930 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2931 i));
2932 TALLOC_FREE(namebuf);
2933 return STATUS_BUFFER_OVERFLOW;
2936 SIVAL(data, ofs+4, namelen);
2937 SOFF_T(data, ofs+8, streams[i].size);
2938 SOFF_T(data, ofs+16, streams[i].alloc_size);
2939 memcpy(data+ofs+24, namebuf, namelen);
2940 TALLOC_FREE(namebuf);
2942 next_offset = ofs + 24 + namelen;
2944 if (i == num_streams-1) {
2945 SIVAL(data, ofs, 0);
2947 else {
2948 unsigned int align = ndr_align_size(next_offset, 8);
2950 if ((next_offset + align) > max_data_bytes) {
2951 DEBUG(10, ("refusing to overflow align "
2952 "reply at stream %u\n",
2953 i));
2954 TALLOC_FREE(namebuf);
2955 return STATUS_BUFFER_OVERFLOW;
2958 memset(data+next_offset, 0, align);
2959 next_offset += align;
2961 SIVAL(data, ofs, next_offset - ofs);
2962 ofs = next_offset;
2965 ofs = next_offset;
2968 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
2970 *data_size = ofs;
2972 return NT_STATUS_OK;
2975 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
2976 TALLOC_CTX *mem_ctx,
2977 struct smb_request *req,
2978 uint16_t info_level,
2979 files_struct *fsp,
2980 struct smb_filename *smb_fname,
2981 bool delete_pending,
2982 struct timespec write_time_ts,
2983 struct ea_list *ea_list,
2984 uint16_t flags2,
2985 unsigned int max_data_bytes,
2986 size_t *fixed_portion,
2987 char **ppdata,
2988 unsigned int *pdata_size)
2990 char *pdata = *ppdata;
2991 char *dstart, *dend;
2992 unsigned int data_size;
2993 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
2994 time_t create_time, mtime, atime, c_time;
2995 SMB_STRUCT_STAT *psbuf = NULL;
2996 SMB_STRUCT_STAT *base_sp = NULL;
2997 char *p;
2998 char *base_name;
2999 char *dos_fname;
3000 int mode;
3001 int nlink;
3002 NTSTATUS status;
3003 uint64_t file_size = 0;
3004 uint64_t pos = 0;
3005 uint64_t allocation_size = 0;
3006 uint64_t file_id = 0;
3007 uint32_t access_mask = 0;
3008 size_t len = 0;
3010 if (INFO_LEVEL_IS_UNIX(info_level)) {
3011 bool ok = false;
3013 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3014 DBG_DEBUG("SMB1 unix extensions activated\n");
3015 ok = true;
3018 if ((fsp != NULL) &&
3019 (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3020 DBG_DEBUG("SMB2 posix open\n");
3021 ok = true;
3024 if (!ok) {
3025 return NT_STATUS_INVALID_LEVEL;
3029 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3030 smb_fname_str_dbg(smb_fname),
3031 fsp_fnum_dbg(fsp),
3032 info_level, max_data_bytes));
3035 * In case of querying a symlink in POSIX context,
3036 * fsp will be NULL. fdos_mode() deals with it.
3038 if (fsp != NULL) {
3039 smb_fname = fsp->fsp_name;
3041 mode = fdos_mode(fsp);
3042 psbuf = &smb_fname->st;
3044 if (fsp != NULL) {
3045 base_sp = fsp->base_fsp ?
3046 &fsp->base_fsp->fsp_name->st :
3047 &fsp->fsp_name->st;
3048 } else {
3049 base_sp = &smb_fname->st;
3052 nlink = psbuf->st_ex_nlink;
3054 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3055 nlink = 1;
3058 if ((nlink > 0) && delete_pending) {
3059 nlink -= 1;
3062 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3063 return NT_STATUS_INVALID_PARAMETER;
3066 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3067 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3068 if (*ppdata == NULL) {
3069 return NT_STATUS_NO_MEMORY;
3071 pdata = *ppdata;
3072 dstart = pdata;
3073 dend = dstart + data_size - 1;
3075 if (!is_omit_timespec(&write_time_ts) &&
3076 !INFO_LEVEL_IS_UNIX(info_level))
3078 update_stat_ex_mtime(psbuf, write_time_ts);
3081 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3082 mtime_ts = psbuf->st_ex_mtime;
3083 atime_ts = psbuf->st_ex_atime;
3084 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3086 if (lp_dos_filetime_resolution(SNUM(conn))) {
3087 dos_filetime_timespec(&create_time_ts);
3088 dos_filetime_timespec(&mtime_ts);
3089 dos_filetime_timespec(&atime_ts);
3090 dos_filetime_timespec(&ctime_ts);
3093 create_time = convert_timespec_to_time_t(create_time_ts);
3094 mtime = convert_timespec_to_time_t(mtime_ts);
3095 atime = convert_timespec_to_time_t(atime_ts);
3096 c_time = convert_timespec_to_time_t(ctime_ts);
3098 p = strrchr_m(smb_fname->base_name,'/');
3099 if (!p)
3100 base_name = smb_fname->base_name;
3101 else
3102 base_name = p+1;
3104 /* NT expects the name to be in an exact form of the *full*
3105 filename. See the trans2 torture test */
3106 if (ISDOT(base_name)) {
3107 dos_fname = talloc_strdup(mem_ctx, "\\");
3108 if (!dos_fname) {
3109 return NT_STATUS_NO_MEMORY;
3111 } else {
3112 dos_fname = talloc_asprintf(mem_ctx,
3113 "\\%s",
3114 smb_fname->base_name);
3115 if (!dos_fname) {
3116 return NT_STATUS_NO_MEMORY;
3118 if (is_named_stream(smb_fname)) {
3119 dos_fname = talloc_asprintf(dos_fname, "%s",
3120 smb_fname->stream_name);
3121 if (!dos_fname) {
3122 return NT_STATUS_NO_MEMORY;
3126 string_replace(dos_fname, '/', '\\');
3129 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3131 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3132 /* Do we have this path open ? */
3133 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3134 files_struct *fsp1 = file_find_di_first(
3135 conn->sconn, fileid, true);
3136 if (fsp1 && fsp1->initial_allocation_size) {
3137 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3141 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3142 file_size = get_file_size_stat(psbuf);
3145 if (fsp) {
3146 pos = fh_get_position_information(fsp->fh);
3149 if (fsp) {
3150 access_mask = fsp->access_mask;
3151 } else {
3152 /* GENERIC_EXECUTE mapping from Windows */
3153 access_mask = 0x12019F;
3156 /* This should be an index number - looks like
3157 dev/ino to me :-)
3159 I think this causes us to fail the IFSKIT
3160 BasicFileInformationTest. -tpot */
3161 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3163 *fixed_portion = 0;
3165 switch (info_level) {
3166 case SMB_INFO_STANDARD:
3167 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3168 data_size = 22;
3169 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3170 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3171 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3172 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3173 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3174 SSVAL(pdata,l1_attrFile,mode);
3175 break;
3177 case SMB_INFO_QUERY_EA_SIZE:
3179 unsigned int ea_size =
3180 estimate_ea_size(smb_fname->fsp);
3181 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3182 data_size = 26;
3183 srv_put_dos_date2(pdata,0,create_time);
3184 srv_put_dos_date2(pdata,4,atime);
3185 srv_put_dos_date2(pdata,8,mtime); /* write time */
3186 SIVAL(pdata,12,(uint32_t)file_size);
3187 SIVAL(pdata,16,(uint32_t)allocation_size);
3188 SSVAL(pdata,20,mode);
3189 SIVAL(pdata,22,ea_size);
3190 break;
3193 case SMB_INFO_IS_NAME_VALID:
3194 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3195 if (fsp) {
3196 /* os/2 needs this ? really ?*/
3197 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3199 /* This is only reached for qpathinfo */
3200 data_size = 0;
3201 break;
3203 case SMB_INFO_QUERY_EAS_FROM_LIST:
3205 size_t total_ea_len = 0;
3206 struct ea_list *ea_file_list = NULL;
3207 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3209 status =
3210 get_ea_list_from_fsp(mem_ctx,
3211 smb_fname->fsp,
3212 &total_ea_len, &ea_file_list);
3213 if (!NT_STATUS_IS_OK(status)) {
3214 return status;
3217 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3219 if (!ea_list || (total_ea_len > data_size)) {
3220 data_size = 4;
3221 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3222 break;
3225 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3226 break;
3229 case SMB_INFO_QUERY_ALL_EAS:
3231 /* We have data_size bytes to put EA's into. */
3232 size_t total_ea_len = 0;
3233 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3235 status = get_ea_list_from_fsp(mem_ctx,
3236 smb_fname->fsp,
3237 &total_ea_len, &ea_list);
3238 if (!NT_STATUS_IS_OK(status)) {
3239 return status;
3242 if (!ea_list || (total_ea_len > data_size)) {
3243 data_size = 4;
3244 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3245 break;
3248 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3249 break;
3252 case SMB2_FILE_FULL_EA_INFORMATION:
3254 /* We have data_size bytes to put EA's into. */
3255 size_t total_ea_len = 0;
3256 struct ea_list *ea_file_list = NULL;
3258 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3260 /*TODO: add filtering and index handling */
3262 status =
3263 get_ea_list_from_fsp(mem_ctx,
3264 smb_fname->fsp,
3265 &total_ea_len, &ea_file_list);
3266 if (!NT_STATUS_IS_OK(status)) {
3267 return status;
3269 if (!ea_file_list) {
3270 return NT_STATUS_NO_EAS_ON_FILE;
3273 status = fill_ea_chained_buffer(mem_ctx,
3274 pdata,
3275 data_size,
3276 &data_size,
3277 conn, ea_file_list);
3278 if (!NT_STATUS_IS_OK(status)) {
3279 return status;
3281 break;
3284 case SMB_FILE_BASIC_INFORMATION:
3285 case SMB_QUERY_FILE_BASIC_INFO:
3287 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3288 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3289 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3290 } else {
3291 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3292 data_size = 40;
3293 SIVAL(pdata,36,0);
3295 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3296 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3297 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3298 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3299 SIVAL(pdata,32,mode);
3301 DEBUG(5,("SMB_QFBI - "));
3302 DEBUG(5,("create: %s ", ctime(&create_time)));
3303 DEBUG(5,("access: %s ", ctime(&atime)));
3304 DEBUG(5,("write: %s ", ctime(&mtime)));
3305 DEBUG(5,("change: %s ", ctime(&c_time)));
3306 DEBUG(5,("mode: %x\n", mode));
3307 *fixed_portion = data_size;
3308 break;
3310 case SMB_FILE_STANDARD_INFORMATION:
3311 case SMB_QUERY_FILE_STANDARD_INFO:
3313 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3314 data_size = 24;
3315 SOFF_T(pdata,0,allocation_size);
3316 SOFF_T(pdata,8,file_size);
3317 SIVAL(pdata,16,nlink);
3318 SCVAL(pdata,20,delete_pending?1:0);
3319 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3320 SSVAL(pdata,22,0); /* Padding. */
3321 *fixed_portion = 24;
3322 break;
3324 case SMB_FILE_EA_INFORMATION:
3325 case SMB_QUERY_FILE_EA_INFO:
3327 unsigned int ea_size =
3328 estimate_ea_size(smb_fname->fsp);
3329 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3330 data_size = 4;
3331 *fixed_portion = 4;
3332 SIVAL(pdata,0,ea_size);
3333 break;
3336 /* Get the 8.3 name - used if NT SMB was negotiated. */
3337 case SMB_QUERY_FILE_ALT_NAME_INFO:
3338 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3340 char mangled_name[13];
3341 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3342 if (!name_to_8_3(base_name,mangled_name,
3343 True,conn->params)) {
3344 return NT_STATUS_NO_MEMORY;
3346 status = srvstr_push(dstart, flags2,
3347 pdata+4, mangled_name,
3348 PTR_DIFF(dend, pdata+4),
3349 STR_UNICODE, &len);
3350 if (!NT_STATUS_IS_OK(status)) {
3351 return status;
3353 data_size = 4 + len;
3354 SIVAL(pdata,0,len);
3355 *fixed_portion = 8;
3356 break;
3359 case SMB_QUERY_FILE_NAME_INFO:
3362 this must be *exactly* right for ACLs on mapped drives to work
3364 status = srvstr_push(dstart, flags2,
3365 pdata+4, dos_fname,
3366 PTR_DIFF(dend, pdata+4),
3367 STR_UNICODE, &len);
3368 if (!NT_STATUS_IS_OK(status)) {
3369 return status;
3371 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3372 data_size = 4 + len;
3373 SIVAL(pdata,0,len);
3374 break;
3377 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3379 char *nfname = NULL;
3381 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
3382 return NT_STATUS_INVALID_LEVEL;
3385 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3386 if (nfname == NULL) {
3387 return NT_STATUS_NO_MEMORY;
3390 if (ISDOT(nfname)) {
3391 nfname[0] = '\0';
3393 string_replace(nfname, '/', '\\');
3395 if (fsp_is_alternate_stream(fsp)) {
3396 const char *s = smb_fname->stream_name;
3397 const char *e = NULL;
3398 size_t n;
3400 SMB_ASSERT(s[0] != '\0');
3403 * smb_fname->stream_name is in form
3404 * of ':StrEam:$DATA', but we should only
3405 * append ':StrEam' here.
3408 e = strchr(&s[1], ':');
3409 if (e == NULL) {
3410 n = strlen(s);
3411 } else {
3412 n = PTR_DIFF(e, s);
3414 nfname = talloc_strndup_append(nfname, s, n);
3415 if (nfname == NULL) {
3416 return NT_STATUS_NO_MEMORY;
3420 status = srvstr_push(dstart, flags2,
3421 pdata+4, nfname,
3422 PTR_DIFF(dend, pdata+4),
3423 STR_UNICODE, &len);
3424 if (!NT_STATUS_IS_OK(status)) {
3425 return status;
3427 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3428 data_size = 4 + len;
3429 SIVAL(pdata,0,len);
3430 *fixed_portion = 8;
3431 break;
3434 case SMB_FILE_ALLOCATION_INFORMATION:
3435 case SMB_QUERY_FILE_ALLOCATION_INFO:
3436 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3437 data_size = 8;
3438 SOFF_T(pdata,0,allocation_size);
3439 break;
3441 case SMB_FILE_END_OF_FILE_INFORMATION:
3442 case SMB_QUERY_FILE_END_OF_FILEINFO:
3443 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3444 data_size = 8;
3445 SOFF_T(pdata,0,file_size);
3446 break;
3448 case SMB_QUERY_FILE_ALL_INFO:
3449 case SMB_FILE_ALL_INFORMATION:
3451 unsigned int ea_size =
3452 estimate_ea_size(smb_fname->fsp);
3453 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3454 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3455 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3456 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3457 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3458 SIVAL(pdata,32,mode);
3459 SIVAL(pdata,36,0); /* padding. */
3460 pdata += 40;
3461 SOFF_T(pdata,0,allocation_size);
3462 SOFF_T(pdata,8,file_size);
3463 SIVAL(pdata,16,nlink);
3464 SCVAL(pdata,20,delete_pending);
3465 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3466 SSVAL(pdata,22,0);
3467 pdata += 24;
3468 SIVAL(pdata,0,ea_size);
3469 pdata += 4; /* EA info */
3470 status = srvstr_push(dstart, flags2,
3471 pdata+4, dos_fname,
3472 PTR_DIFF(dend, pdata+4),
3473 STR_UNICODE, &len);
3474 if (!NT_STATUS_IS_OK(status)) {
3475 return status;
3477 SIVAL(pdata,0,len);
3478 pdata += 4 + len;
3479 data_size = PTR_DIFF(pdata,(*ppdata));
3480 *fixed_portion = 10;
3481 break;
3484 case SMB2_FILE_ALL_INFORMATION:
3486 unsigned int ea_size =
3487 estimate_ea_size(smb_fname->fsp);
3488 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3489 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3490 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3491 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3492 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3493 SIVAL(pdata, 0x20, mode);
3494 SIVAL(pdata, 0x24, 0); /* padding. */
3495 SBVAL(pdata, 0x28, allocation_size);
3496 SBVAL(pdata, 0x30, file_size);
3497 SIVAL(pdata, 0x38, nlink);
3498 SCVAL(pdata, 0x3C, delete_pending);
3499 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3500 SSVAL(pdata, 0x3E, 0); /* padding */
3501 SBVAL(pdata, 0x40, file_id);
3502 SIVAL(pdata, 0x48, ea_size);
3503 SIVAL(pdata, 0x4C, access_mask);
3504 SBVAL(pdata, 0x50, pos);
3505 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3506 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3508 pdata += 0x60;
3510 status = srvstr_push(dstart, flags2,
3511 pdata+4, dos_fname,
3512 PTR_DIFF(dend, pdata+4),
3513 STR_UNICODE, &len);
3514 if (!NT_STATUS_IS_OK(status)) {
3515 return status;
3517 SIVAL(pdata,0,len);
3518 pdata += 4 + len;
3519 data_size = PTR_DIFF(pdata,(*ppdata));
3520 *fixed_portion = 104;
3521 break;
3523 case SMB_FILE_INTERNAL_INFORMATION:
3525 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3526 SBVAL(pdata, 0, file_id);
3527 data_size = 8;
3528 *fixed_portion = 8;
3529 break;
3531 case SMB_FILE_ACCESS_INFORMATION:
3532 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3533 SIVAL(pdata, 0, access_mask);
3534 data_size = 4;
3535 *fixed_portion = 4;
3536 break;
3538 case SMB_FILE_NAME_INFORMATION:
3539 /* Pathname with leading '\'. */
3541 size_t byte_len;
3542 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3543 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3544 SIVAL(pdata,0,byte_len);
3545 data_size = 4 + byte_len;
3546 break;
3549 case SMB_FILE_DISPOSITION_INFORMATION:
3550 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3551 data_size = 1;
3552 SCVAL(pdata,0,delete_pending);
3553 *fixed_portion = 1;
3554 break;
3556 case SMB_FILE_POSITION_INFORMATION:
3557 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3558 data_size = 8;
3559 SOFF_T(pdata,0,pos);
3560 *fixed_portion = 8;
3561 break;
3563 case SMB_FILE_MODE_INFORMATION:
3564 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3565 SIVAL(pdata,0,mode);
3566 data_size = 4;
3567 *fixed_portion = 4;
3568 break;
3570 case SMB_FILE_ALIGNMENT_INFORMATION:
3571 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3572 SIVAL(pdata,0,0); /* No alignment needed. */
3573 data_size = 4;
3574 *fixed_portion = 4;
3575 break;
3578 * NT4 server just returns "invalid query" to this - if we try
3579 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3580 * want this. JRA.
3582 /* The first statement above is false - verified using Thursby
3583 * client against NT4 -- gcolley.
3585 case SMB_QUERY_FILE_STREAM_INFO:
3586 case SMB_FILE_STREAM_INFORMATION: {
3587 unsigned int num_streams = 0;
3588 struct stream_struct *streams = NULL;
3590 DEBUG(10,("smbd_do_qfilepathinfo: "
3591 "SMB_FILE_STREAM_INFORMATION\n"));
3593 if (is_ntfs_stream_smb_fname(smb_fname)) {
3594 return NT_STATUS_INVALID_PARAMETER;
3597 status = vfs_fstreaminfo(fsp,
3598 mem_ctx,
3599 &num_streams,
3600 &streams);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 DEBUG(10, ("could not get stream info: %s\n",
3604 nt_errstr(status)));
3605 return status;
3608 status = marshall_stream_info(num_streams, streams,
3609 pdata, max_data_bytes,
3610 &data_size);
3612 if (!NT_STATUS_IS_OK(status)) {
3613 DEBUG(10, ("marshall_stream_info failed: %s\n",
3614 nt_errstr(status)));
3615 TALLOC_FREE(streams);
3616 return status;
3619 TALLOC_FREE(streams);
3621 *fixed_portion = 32;
3623 break;
3625 case SMB_QUERY_COMPRESSION_INFO:
3626 case SMB_FILE_COMPRESSION_INFORMATION:
3627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3628 SOFF_T(pdata,0,file_size);
3629 SIVAL(pdata,8,0); /* ??? */
3630 SIVAL(pdata,12,0); /* ??? */
3631 data_size = 16;
3632 *fixed_portion = 16;
3633 break;
3635 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3636 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3637 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3638 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3639 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3640 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3641 SOFF_T(pdata,32,allocation_size);
3642 SOFF_T(pdata,40,file_size);
3643 SIVAL(pdata,48,mode);
3644 SIVAL(pdata,52,0); /* ??? */
3645 data_size = 56;
3646 *fixed_portion = 56;
3647 break;
3649 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3650 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3651 SIVAL(pdata,0,mode);
3652 SIVAL(pdata,4,0);
3653 data_size = 8;
3654 *fixed_portion = 8;
3655 break;
3658 * SMB2 UNIX Extensions.
3660 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3662 uint8_t *buf = NULL;
3663 ssize_t plen = 0;
3665 if (!(conn->sconn->using_smb2)) {
3666 return NT_STATUS_INVALID_LEVEL;
3668 if (fsp == NULL) {
3669 return NT_STATUS_INVALID_HANDLE;
3671 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3672 return NT_STATUS_INVALID_LEVEL;
3675 /* Determine the size of the posix info context */
3676 plen = store_smb2_posix_info(conn,
3677 &smb_fname->st,
3679 mode,
3680 NULL,
3682 if (plen == -1 || data_size < plen) {
3683 return NT_STATUS_INVALID_PARAMETER;
3685 buf = talloc_zero_size(mem_ctx, plen);
3686 if (buf == NULL) {
3687 return NT_STATUS_NO_MEMORY;
3690 /* Store the context in buf */
3691 store_smb2_posix_info(conn,
3692 &smb_fname->st,
3694 mode,
3695 buf,
3696 plen);
3697 memcpy(pdata, buf, plen);
3698 data_size = plen;
3699 break;
3702 default:
3703 return NT_STATUS_INVALID_LEVEL;
3706 *pdata_size = data_size;
3707 return NT_STATUS_OK;
3710 /****************************************************************************
3711 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3712 code.
3713 ****************************************************************************/
3715 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3716 connection_struct *conn,
3717 struct smb_request *req,
3718 bool overwrite_if_exists,
3719 const struct smb_filename *smb_fname_old,
3720 struct smb_filename *smb_fname_new)
3722 NTSTATUS status = NT_STATUS_OK;
3723 int ret;
3724 bool ok;
3725 struct smb_filename *parent_fname_old = NULL;
3726 struct smb_filename *base_name_old = NULL;
3727 struct smb_filename *parent_fname_new = NULL;
3728 struct smb_filename *base_name_new = NULL;
3730 /* source must already exist. */
3731 if (!VALID_STAT(smb_fname_old->st)) {
3732 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3733 goto out;
3736 /* No links from a directory. */
3737 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3738 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3739 goto out;
3742 /* Setting a hardlink to/from a stream isn't currently supported. */
3743 ok = is_ntfs_stream_smb_fname(smb_fname_old);
3744 if (ok) {
3745 DBG_DEBUG("Old name has streams\n");
3746 status = NT_STATUS_INVALID_PARAMETER;
3747 goto out;
3749 ok = is_ntfs_stream_smb_fname(smb_fname_new);
3750 if (ok) {
3751 DBG_DEBUG("New name has streams\n");
3752 status = NT_STATUS_INVALID_PARAMETER;
3753 goto out;
3756 status = parent_pathref(talloc_tos(),
3757 conn->cwd_fsp,
3758 smb_fname_old,
3759 &parent_fname_old,
3760 &base_name_old);
3761 if (!NT_STATUS_IS_OK(status)) {
3762 goto out;
3765 status = parent_pathref(talloc_tos(),
3766 conn->cwd_fsp,
3767 smb_fname_new,
3768 &parent_fname_new,
3769 &base_name_new);
3770 if (!NT_STATUS_IS_OK(status)) {
3771 goto out;
3774 if (VALID_STAT(smb_fname_new->st)) {
3775 if (overwrite_if_exists) {
3776 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3777 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3778 goto out;
3780 status = unlink_internals(conn,
3781 req,
3782 FILE_ATTRIBUTE_NORMAL,
3783 NULL, /* new_dirfsp */
3784 smb_fname_new);
3785 if (!NT_STATUS_IS_OK(status)) {
3786 goto out;
3788 } else {
3789 /* Disallow if newname already exists. */
3790 status = NT_STATUS_OBJECT_NAME_COLLISION;
3791 goto out;
3795 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3796 smb_fname_old->base_name, smb_fname_new->base_name));
3798 ret = SMB_VFS_LINKAT(conn,
3799 parent_fname_old->fsp,
3800 base_name_old,
3801 parent_fname_new->fsp,
3802 base_name_new,
3805 if (ret != 0) {
3806 status = map_nt_error_from_unix(errno);
3807 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3808 nt_errstr(status), smb_fname_old->base_name,
3809 smb_fname_new->base_name));
3812 out:
3814 TALLOC_FREE(parent_fname_old);
3815 TALLOC_FREE(parent_fname_new);
3816 return status;
3819 /****************************************************************************
3820 Deal with setting the time from any of the setfilepathinfo functions.
3821 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3822 calling this function.
3823 ****************************************************************************/
3825 NTSTATUS smb_set_file_time(connection_struct *conn,
3826 files_struct *fsp,
3827 struct smb_filename *smb_fname,
3828 struct smb_file_time *ft,
3829 bool setting_write_time)
3831 struct files_struct *set_fsp = NULL;
3832 struct timeval_buf tbuf[4];
3833 uint32_t action =
3834 FILE_NOTIFY_CHANGE_LAST_ACCESS
3835 |FILE_NOTIFY_CHANGE_LAST_WRITE
3836 |FILE_NOTIFY_CHANGE_CREATION;
3837 int ret;
3839 if (!VALID_STAT(smb_fname->st)) {
3840 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3843 if (fsp == NULL) {
3844 /* A symlink */
3845 return NT_STATUS_OK;
3848 set_fsp = metadata_fsp(fsp);
3850 /* get some defaults (no modifications) if any info is zero or -1. */
3851 if (is_omit_timespec(&ft->create_time)) {
3852 action &= ~FILE_NOTIFY_CHANGE_CREATION;
3855 if (is_omit_timespec(&ft->atime)) {
3856 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3859 if (is_omit_timespec(&ft->mtime)) {
3860 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3863 if (!setting_write_time) {
3864 /* ft->mtime comes from change time, not write time. */
3865 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3868 /* Ensure the resolution is the correct for
3869 * what we can store on this filesystem. */
3871 round_timespec(conn->ts_res, &ft->create_time);
3872 round_timespec(conn->ts_res, &ft->ctime);
3873 round_timespec(conn->ts_res, &ft->atime);
3874 round_timespec(conn->ts_res, &ft->mtime);
3876 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3877 timespec_string_buf(&ft->atime, true, &tbuf[0]));
3878 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3879 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3880 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3881 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3882 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3883 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3885 if (setting_write_time) {
3887 * This was a Windows setfileinfo on an open file.
3888 * NT does this a lot. We also need to
3889 * set the time here, as it can be read by
3890 * FindFirst/FindNext and with the patch for bug #2045
3891 * in smbd/fileio.c it ensures that this timestamp is
3892 * kept sticky even after a write. We save the request
3893 * away and will set it on file close and after a write. JRA.
3896 DBG_DEBUG("setting pending modtime to %s\n",
3897 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3899 if (set_fsp != NULL) {
3900 set_sticky_write_time_fsp(set_fsp, ft->mtime);
3901 } else {
3902 set_sticky_write_time_path(
3903 vfs_file_id_from_sbuf(conn, &smb_fname->st),
3904 ft->mtime);
3908 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3910 ret = file_ntimes(conn, set_fsp, ft);
3911 if (ret != 0) {
3912 return map_nt_error_from_unix(errno);
3915 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
3916 smb_fname->base_name);
3917 return NT_STATUS_OK;
3920 /****************************************************************************
3921 Deal with setting the dosmode from any of the setfilepathinfo functions.
3922 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3923 done before calling this function.
3924 ****************************************************************************/
3926 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3927 struct files_struct *fsp,
3928 uint32_t dosmode)
3930 struct files_struct *dos_fsp = NULL;
3931 uint32_t current_dosmode;
3932 int ret;
3934 if (!VALID_STAT(fsp->fsp_name->st)) {
3935 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3938 dos_fsp = metadata_fsp(fsp);
3940 if (dosmode != 0) {
3941 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3942 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3943 } else {
3944 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3948 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3950 /* check the mode isn't different, before changing it */
3951 if (dosmode == 0) {
3952 return NT_STATUS_OK;
3954 current_dosmode = fdos_mode(dos_fsp);
3955 if (dosmode == current_dosmode) {
3956 return NT_STATUS_OK;
3959 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
3960 fsp_str_dbg(dos_fsp), dosmode);
3962 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
3963 if (ret != 0) {
3964 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3965 fsp_str_dbg(dos_fsp), strerror(errno));
3966 return map_nt_error_from_unix(errno);
3969 return NT_STATUS_OK;
3972 /****************************************************************************
3973 Deal with setting the size from any of the setfilepathinfo functions.
3974 ****************************************************************************/
3976 NTSTATUS smb_set_file_size(connection_struct *conn,
3977 struct smb_request *req,
3978 files_struct *fsp,
3979 struct smb_filename *smb_fname,
3980 const SMB_STRUCT_STAT *psbuf,
3981 off_t size,
3982 bool fail_after_createfile)
3984 NTSTATUS status = NT_STATUS_OK;
3985 files_struct *new_fsp = NULL;
3987 if (!VALID_STAT(*psbuf)) {
3988 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3991 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
3992 (uint64_t)size,
3993 get_file_size_stat(psbuf));
3995 if (size == get_file_size_stat(psbuf)) {
3996 if (fsp == NULL) {
3997 return NT_STATUS_OK;
3999 if (!fsp->fsp_flags.modified) {
4000 return NT_STATUS_OK;
4002 trigger_write_time_update_immediate(fsp);
4003 return NT_STATUS_OK;
4006 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4007 smb_fname_str_dbg(smb_fname), (double)size));
4009 if (fsp &&
4010 !fsp->fsp_flags.is_pathref &&
4011 fsp_get_io_fd(fsp) != -1)
4013 /* Handle based call. */
4014 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4015 return NT_STATUS_ACCESS_DENIED;
4018 if (vfs_set_filelen(fsp, size) == -1) {
4019 return map_nt_error_from_unix(errno);
4021 trigger_write_time_update_immediate(fsp);
4022 return NT_STATUS_OK;
4025 status = SMB_VFS_CREATE_FILE(
4026 conn, /* conn */
4027 req, /* req */
4028 NULL, /* dirfsp */
4029 smb_fname, /* fname */
4030 FILE_WRITE_DATA, /* access_mask */
4031 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4032 FILE_SHARE_DELETE),
4033 FILE_OPEN, /* create_disposition*/
4034 0, /* create_options */
4035 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4036 0, /* oplock_request */
4037 NULL, /* lease */
4038 0, /* allocation_size */
4039 0, /* private_flags */
4040 NULL, /* sd */
4041 NULL, /* ea_list */
4042 &new_fsp, /* result */
4043 NULL, /* pinfo */
4044 NULL, NULL); /* create context */
4046 if (!NT_STATUS_IS_OK(status)) {
4047 /* NB. We check for open_was_deferred in the caller. */
4048 return status;
4051 /* See RAW-SFILEINFO-END-OF-FILE */
4052 if (fail_after_createfile) {
4053 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4054 return NT_STATUS_INVALID_LEVEL;
4057 if (vfs_set_filelen(new_fsp, size) == -1) {
4058 status = map_nt_error_from_unix(errno);
4059 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4060 return status;
4063 trigger_write_time_update_immediate(new_fsp);
4064 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4065 return NT_STATUS_OK;
4068 /****************************************************************************
4069 Deal with SMB_INFO_SET_EA.
4070 ****************************************************************************/
4072 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4073 const char *pdata,
4074 int total_data,
4075 files_struct *fsp,
4076 struct smb_filename *smb_fname)
4078 struct ea_list *ea_list = NULL;
4079 TALLOC_CTX *ctx = NULL;
4080 NTSTATUS status = NT_STATUS_OK;
4082 if (total_data < 10) {
4084 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4085 length. They seem to have no effect. Bug #3212. JRA */
4087 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4088 /* We're done. We only get EA info in this call. */
4089 return NT_STATUS_OK;
4092 return NT_STATUS_INVALID_PARAMETER;
4095 if (IVAL(pdata,0) > total_data) {
4096 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4097 IVAL(pdata,0), (unsigned int)total_data));
4098 return NT_STATUS_INVALID_PARAMETER;
4101 ctx = talloc_tos();
4102 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4103 if (!ea_list) {
4104 return NT_STATUS_INVALID_PARAMETER;
4107 if (fsp == NULL) {
4109 * The only way fsp can be NULL here is if
4110 * smb_fname points at a symlink and
4111 * and we're in POSIX context.
4112 * Ensure this is the case.
4114 * In this case we cannot set the EA.
4116 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4117 return NT_STATUS_ACCESS_DENIED;
4120 status = set_ea(conn, fsp, ea_list);
4122 return status;
4125 /****************************************************************************
4126 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4127 ****************************************************************************/
4129 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4130 const char *pdata,
4131 int total_data,
4132 files_struct *fsp)
4134 struct ea_list *ea_list = NULL;
4135 NTSTATUS status;
4137 if (fsp == NULL) {
4138 return NT_STATUS_INVALID_HANDLE;
4141 if (!lp_ea_support(SNUM(conn))) {
4142 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4143 "EA's not supported.\n",
4144 (unsigned int)total_data));
4145 return NT_STATUS_EAS_NOT_SUPPORTED;
4148 if (total_data < 10) {
4149 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4150 "too small.\n",
4151 (unsigned int)total_data));
4152 return NT_STATUS_INVALID_PARAMETER;
4155 ea_list = read_nttrans_ea_list(talloc_tos(),
4156 pdata,
4157 total_data);
4159 if (!ea_list) {
4160 return NT_STATUS_INVALID_PARAMETER;
4163 status = set_ea(conn, fsp, ea_list);
4165 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4166 smb_fname_str_dbg(fsp->fsp_name),
4167 nt_errstr(status) ));
4169 return status;
4173 /****************************************************************************
4174 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4175 ****************************************************************************/
4177 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4178 const char *pdata,
4179 int total_data,
4180 files_struct *fsp,
4181 struct smb_filename *smb_fname)
4183 NTSTATUS status = NT_STATUS_OK;
4184 bool delete_on_close;
4185 uint32_t dosmode = 0;
4187 if (total_data < 1) {
4188 return NT_STATUS_INVALID_PARAMETER;
4191 if (fsp == NULL) {
4192 return NT_STATUS_INVALID_HANDLE;
4195 delete_on_close = (CVAL(pdata,0) ? True : False);
4196 dosmode = fdos_mode(fsp);
4198 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4199 "delete_on_close = %u\n",
4200 smb_fname_str_dbg(smb_fname),
4201 (unsigned int)dosmode,
4202 (unsigned int)delete_on_close ));
4204 if (delete_on_close) {
4205 status = can_set_delete_on_close(fsp, dosmode);
4206 if (!NT_STATUS_IS_OK(status)) {
4207 return status;
4211 /* The set is across all open files on this dev/inode pair. */
4212 if (!set_delete_on_close(fsp, delete_on_close,
4213 conn->session_info->security_token,
4214 conn->session_info->unix_token)) {
4215 return NT_STATUS_ACCESS_DENIED;
4217 return NT_STATUS_OK;
4220 /****************************************************************************
4221 Deal with SMB_FILE_POSITION_INFORMATION.
4222 ****************************************************************************/
4224 static NTSTATUS smb_file_position_information(connection_struct *conn,
4225 const char *pdata,
4226 int total_data,
4227 files_struct *fsp)
4229 uint64_t position_information;
4231 if (total_data < 8) {
4232 return NT_STATUS_INVALID_PARAMETER;
4235 if (fsp == NULL) {
4236 /* Ignore on pathname based set. */
4237 return NT_STATUS_OK;
4240 position_information = (uint64_t)IVAL(pdata,0);
4241 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4243 DEBUG(10,("smb_file_position_information: Set file position "
4244 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4245 (double)position_information));
4246 fh_set_position_information(fsp->fh, position_information);
4247 return NT_STATUS_OK;
4250 /****************************************************************************
4251 Deal with SMB_FILE_MODE_INFORMATION.
4252 ****************************************************************************/
4254 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4255 const char *pdata,
4256 int total_data)
4258 uint32_t mode;
4260 if (total_data < 4) {
4261 return NT_STATUS_INVALID_PARAMETER;
4263 mode = IVAL(pdata,0);
4264 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4265 return NT_STATUS_INVALID_PARAMETER;
4267 return NT_STATUS_OK;
4270 /****************************************************************************
4271 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4272 ****************************************************************************/
4274 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4275 struct smb_request *req,
4276 const char *pdata,
4277 int total_data,
4278 files_struct *fsp,
4279 struct smb_filename *smb_fname_src)
4281 bool overwrite;
4282 uint32_t len;
4283 char *newname = NULL;
4284 struct files_struct *dst_dirfsp = NULL;
4285 struct smb_filename *smb_fname_dst = NULL;
4286 const char *dst_original_lcomp = NULL;
4287 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4288 NTSTATUS status = NT_STATUS_OK;
4289 TALLOC_CTX *ctx = talloc_tos();
4291 if (!fsp) {
4292 return NT_STATUS_INVALID_HANDLE;
4295 if (total_data < 20) {
4296 return NT_STATUS_INVALID_PARAMETER;
4299 overwrite = (CVAL(pdata,0) ? True : False);
4300 len = IVAL(pdata,16);
4302 if (len > (total_data - 20) || (len == 0)) {
4303 return NT_STATUS_INVALID_PARAMETER;
4306 (void)srvstr_pull_talloc(ctx,
4307 pdata,
4308 req->flags2,
4309 &newname,
4310 &pdata[20],
4311 len,
4312 STR_TERMINATE);
4314 if (newname == NULL) {
4315 return NT_STATUS_INVALID_PARAMETER;
4318 /* SMB2 rename paths are never DFS. */
4319 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4320 ucf_flags &= ~UCF_DFS_PATHNAME;
4322 status = check_path_syntax(newname,
4323 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4324 if (!NT_STATUS_IS_OK(status)) {
4325 return status;
4328 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4329 newname));
4331 if (newname[0] == ':') {
4332 /* Create an smb_fname to call rename_internals_fsp() with. */
4333 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4334 fsp->base_fsp->fsp_name->base_name,
4335 newname,
4336 NULL,
4337 fsp->base_fsp->fsp_name->twrp,
4338 fsp->base_fsp->fsp_name->flags);
4339 if (smb_fname_dst == NULL) {
4340 status = NT_STATUS_NO_MEMORY;
4341 goto out;
4343 } else {
4344 status = filename_convert_dirfsp(ctx,
4345 conn,
4346 newname,
4347 ucf_flags,
4348 0, /* Never a TWRP. */
4349 &dst_dirfsp,
4350 &smb_fname_dst);
4351 if (!NT_STATUS_IS_OK(status)) {
4352 goto out;
4357 * Set the original last component, since
4358 * rename_internals_fsp() requires it.
4360 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4361 conn,
4362 newname,
4363 ucf_flags);
4364 if (dst_original_lcomp == NULL) {
4365 status = NT_STATUS_NO_MEMORY;
4366 goto out;
4369 DEBUG(10,("smb2_file_rename_information: "
4370 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4371 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4372 smb_fname_str_dbg(smb_fname_dst)));
4373 status = rename_internals_fsp(conn,
4374 fsp,
4375 smb_fname_dst,
4376 dst_original_lcomp,
4377 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4378 overwrite);
4380 out:
4381 TALLOC_FREE(smb_fname_dst);
4382 return status;
4385 static NTSTATUS smb2_file_link_information(connection_struct *conn,
4386 struct smb_request *req,
4387 const char *pdata,
4388 int total_data,
4389 files_struct *fsp,
4390 struct smb_filename *smb_fname_src)
4392 bool overwrite;
4393 uint32_t len;
4394 char *newname = NULL;
4395 struct files_struct *dst_dirfsp = NULL;
4396 struct smb_filename *smb_fname_dst = NULL;
4397 NTSTATUS status = NT_STATUS_OK;
4398 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4399 size_t ret;
4400 TALLOC_CTX *ctx = talloc_tos();
4402 if (!fsp) {
4403 return NT_STATUS_INVALID_HANDLE;
4406 if (total_data < 20) {
4407 return NT_STATUS_INVALID_PARAMETER;
4410 overwrite = (CVAL(pdata,0) ? true : false);
4411 len = IVAL(pdata,16);
4413 if (len > (total_data - 20) || (len == 0)) {
4414 return NT_STATUS_INVALID_PARAMETER;
4417 ret = srvstr_pull_talloc(ctx,
4418 pdata,
4419 req->flags2,
4420 &newname,
4421 &pdata[20],
4422 len,
4423 STR_TERMINATE);
4425 if (ret == (size_t)-1 || newname == NULL) {
4426 return NT_STATUS_INVALID_PARAMETER;
4429 /* SMB2 hardlink paths are never DFS. */
4430 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4431 ucf_flags &= ~UCF_DFS_PATHNAME;
4433 status = check_path_syntax(newname,
4434 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4435 if (!NT_STATUS_IS_OK(status)) {
4436 return status;
4439 DBG_DEBUG("got name |%s|\n", newname);
4441 status = filename_convert_dirfsp(ctx,
4442 conn,
4443 newname,
4444 ucf_flags,
4445 0, /* No TWRP. */
4446 &dst_dirfsp,
4447 &smb_fname_dst);
4448 if (!NT_STATUS_IS_OK(status)) {
4449 return status;
4452 if (fsp->base_fsp) {
4453 /* No stream names. */
4454 return NT_STATUS_NOT_SUPPORTED;
4457 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4458 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4459 smb_fname_str_dbg(smb_fname_dst));
4460 status = hardlink_internals(ctx,
4461 conn,
4462 req,
4463 overwrite,
4464 fsp->fsp_name,
4465 smb_fname_dst);
4467 TALLOC_FREE(smb_fname_dst);
4468 return status;
4471 static NTSTATUS smb_file_link_information(connection_struct *conn,
4472 struct smb_request *req,
4473 const char *pdata,
4474 int total_data,
4475 files_struct *fsp,
4476 struct smb_filename *smb_fname_src)
4478 bool overwrite;
4479 uint32_t len;
4480 char *newname = NULL;
4481 struct files_struct *dst_dirfsp = NULL;
4482 struct smb_filename *smb_fname_dst = NULL;
4483 NTSTATUS status = NT_STATUS_OK;
4484 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4485 NTTIME dst_twrp = 0;
4486 TALLOC_CTX *ctx = talloc_tos();
4488 if (!fsp) {
4489 return NT_STATUS_INVALID_HANDLE;
4492 if (total_data < 20) {
4493 return NT_STATUS_INVALID_PARAMETER;
4496 overwrite = (CVAL(pdata,0) ? true : false);
4497 len = IVAL(pdata,16);
4499 if (len > (total_data - 20) || (len == 0)) {
4500 return NT_STATUS_INVALID_PARAMETER;
4503 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4504 srvstr_get_path_posix(ctx,
4505 pdata,
4506 req->flags2,
4507 &newname,
4508 &pdata[20],
4509 len,
4510 STR_TERMINATE,
4511 &status);
4512 ucf_flags |= UCF_POSIX_PATHNAMES;
4513 } else {
4514 srvstr_get_path(ctx,
4515 pdata,
4516 req->flags2,
4517 &newname,
4518 &pdata[20],
4519 len,
4520 STR_TERMINATE,
4521 &status);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 return status;
4527 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4528 newname));
4530 if (ucf_flags & UCF_GMT_PATHNAME) {
4531 extract_snapshot_token(newname, &dst_twrp);
4533 /* hardlink paths are never DFS. */
4534 ucf_flags &= ~UCF_DFS_PATHNAME;
4536 status = filename_convert_dirfsp(ctx,
4537 conn,
4538 newname,
4539 ucf_flags,
4540 dst_twrp,
4541 &dst_dirfsp,
4542 &smb_fname_dst);
4543 if (!NT_STATUS_IS_OK(status)) {
4544 return status;
4547 if (fsp->base_fsp) {
4548 /* No stream names. */
4549 return NT_STATUS_NOT_SUPPORTED;
4552 DEBUG(10,("smb_file_link_information: "
4553 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4554 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4555 smb_fname_str_dbg(smb_fname_dst)));
4556 status = hardlink_internals(ctx,
4557 conn,
4558 req,
4559 overwrite,
4560 fsp->fsp_name,
4561 smb_fname_dst);
4563 TALLOC_FREE(smb_fname_dst);
4564 return status;
4568 /****************************************************************************
4569 Deal with SMB_FILE_RENAME_INFORMATION.
4570 ****************************************************************************/
4572 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4573 struct smb_request *req,
4574 const char *pdata,
4575 int total_data,
4576 files_struct *fsp,
4577 struct smb_filename *smb_fname_src)
4579 bool overwrite;
4580 uint32_t root_fid;
4581 uint32_t len;
4582 char *newname = NULL;
4583 struct files_struct *dst_dirfsp = NULL;
4584 struct smb_filename *smb_fname_dst = NULL;
4585 const char *dst_original_lcomp = NULL;
4586 NTSTATUS status = NT_STATUS_OK;
4587 char *p;
4588 TALLOC_CTX *ctx = talloc_tos();
4590 if (total_data < 13) {
4591 return NT_STATUS_INVALID_PARAMETER;
4594 overwrite = (CVAL(pdata,0) != 0);
4595 root_fid = IVAL(pdata,4);
4596 len = IVAL(pdata,8);
4598 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4599 return NT_STATUS_INVALID_PARAMETER;
4602 if (req->posix_pathnames) {
4603 srvstr_get_path_posix(ctx,
4604 pdata,
4605 req->flags2,
4606 &newname,
4607 &pdata[12],
4608 len,
4610 &status);
4611 } else {
4612 srvstr_get_path(ctx,
4613 pdata,
4614 req->flags2,
4615 &newname,
4616 &pdata[12],
4617 len,
4619 &status);
4621 if (!NT_STATUS_IS_OK(status)) {
4622 return status;
4625 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4626 newname));
4628 /* Check the new name has no '/' characters. */
4629 if (strchr_m(newname, '/')) {
4630 return NT_STATUS_NOT_SUPPORTED;
4633 if (fsp && fsp->base_fsp) {
4634 /* newname must be a stream name. */
4635 if (newname[0] != ':') {
4636 return NT_STATUS_NOT_SUPPORTED;
4639 /* Create an smb_fname to call rename_internals_fsp() with. */
4640 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4641 fsp->base_fsp->fsp_name->base_name,
4642 newname,
4643 NULL,
4644 fsp->base_fsp->fsp_name->twrp,
4645 fsp->base_fsp->fsp_name->flags);
4646 if (smb_fname_dst == NULL) {
4647 status = NT_STATUS_NO_MEMORY;
4648 goto out;
4652 * Get the original last component, since
4653 * rename_internals_fsp() requires it.
4655 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4656 conn,
4657 newname,
4659 if (dst_original_lcomp == NULL) {
4660 status = NT_STATUS_NO_MEMORY;
4661 goto out;
4664 } else {
4666 * Build up an smb_fname_dst based on the filename passed in.
4667 * We basically just strip off the last component, and put on
4668 * the newname instead.
4670 char *base_name = NULL;
4671 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4672 NTTIME dst_twrp = 0;
4674 /* newname must *not* be a stream name. */
4675 if (newname[0] == ':') {
4676 return NT_STATUS_NOT_SUPPORTED;
4680 * Strip off the last component (filename) of the path passed
4681 * in.
4683 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4684 if (!base_name) {
4685 return NT_STATUS_NO_MEMORY;
4687 p = strrchr_m(base_name, '/');
4688 if (p) {
4689 p[1] = '\0';
4690 } else {
4691 base_name = talloc_strdup(ctx, "");
4692 if (!base_name) {
4693 return NT_STATUS_NO_MEMORY;
4696 /* Append the new name. */
4697 base_name = talloc_asprintf_append(base_name,
4698 "%s",
4699 newname);
4700 if (!base_name) {
4701 return NT_STATUS_NO_MEMORY;
4704 if (ucf_flags & UCF_GMT_PATHNAME) {
4705 extract_snapshot_token(base_name, &dst_twrp);
4708 /* The newname is *not* a DFS path. */
4709 ucf_flags &= ~UCF_DFS_PATHNAME;
4711 status = filename_convert_dirfsp(ctx,
4712 conn,
4713 base_name,
4714 ucf_flags,
4715 dst_twrp,
4716 &dst_dirfsp,
4717 &smb_fname_dst);
4719 if (!NT_STATUS_IS_OK(status)) {
4720 goto out;
4722 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4723 conn,
4724 newname,
4725 ucf_flags);
4726 if (dst_original_lcomp == NULL) {
4727 status = NT_STATUS_NO_MEMORY;
4728 goto out;
4732 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4733 DEBUG(10,("smb_file_rename_information: "
4734 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4735 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4736 smb_fname_str_dbg(smb_fname_dst)));
4737 status = rename_internals_fsp(conn,
4738 fsp,
4739 smb_fname_dst,
4740 dst_original_lcomp,
4742 overwrite);
4743 } else {
4744 DEBUG(10,("smb_file_rename_information: "
4745 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4746 smb_fname_str_dbg(smb_fname_src),
4747 smb_fname_str_dbg(smb_fname_dst)));
4748 status = rename_internals(ctx,
4749 conn,
4750 req,
4751 NULL, /* src_dirfsp */
4752 smb_fname_src,
4753 smb_fname_dst,
4754 dst_original_lcomp,
4756 overwrite,
4757 FILE_WRITE_ATTRIBUTES);
4759 out:
4760 TALLOC_FREE(smb_fname_dst);
4761 return status;
4764 /****************************************************************************
4765 Deal with SMB_SET_FILE_BASIC_INFO.
4766 ****************************************************************************/
4768 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4769 const char *pdata,
4770 int total_data,
4771 files_struct *fsp,
4772 struct smb_filename *smb_fname)
4774 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4775 struct smb_file_time ft;
4776 uint32_t dosmode = 0;
4777 NTSTATUS status = NT_STATUS_OK;
4779 init_smb_file_time(&ft);
4781 if (total_data < 36) {
4782 return NT_STATUS_INVALID_PARAMETER;
4785 if (fsp == NULL) {
4786 return NT_STATUS_INVALID_HANDLE;
4789 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4790 if (!NT_STATUS_IS_OK(status)) {
4791 return status;
4794 /* Set the attributes */
4795 dosmode = IVAL(pdata,32);
4796 status = smb_set_file_dosmode(conn, fsp, dosmode);
4797 if (!NT_STATUS_IS_OK(status)) {
4798 return status;
4801 /* create time */
4802 ft.create_time = pull_long_date_full_timespec(pdata);
4804 /* access time */
4805 ft.atime = pull_long_date_full_timespec(pdata+8);
4807 /* write time. */
4808 ft.mtime = pull_long_date_full_timespec(pdata+16);
4810 /* change time. */
4811 ft.ctime = pull_long_date_full_timespec(pdata+24);
4813 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4814 smb_fname_str_dbg(smb_fname)));
4816 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4817 if (!NT_STATUS_IS_OK(status)) {
4818 return status;
4821 if (fsp->fsp_flags.modified) {
4822 trigger_write_time_update_immediate(fsp);
4824 return NT_STATUS_OK;
4827 /****************************************************************************
4828 Deal with SMB_INFO_STANDARD.
4829 ****************************************************************************/
4831 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4832 const char *pdata,
4833 int total_data,
4834 files_struct *fsp,
4835 struct smb_filename *smb_fname)
4837 NTSTATUS status;
4838 struct smb_file_time ft;
4840 init_smb_file_time(&ft);
4842 if (total_data < 12) {
4843 return NT_STATUS_INVALID_PARAMETER;
4846 if (fsp == NULL) {
4847 return NT_STATUS_INVALID_HANDLE;
4850 /* create time */
4851 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4852 /* access time */
4853 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4854 /* write time */
4855 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4857 DEBUG(10,("smb_set_info_standard: file %s\n",
4858 smb_fname_str_dbg(smb_fname)));
4860 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4861 if (!NT_STATUS_IS_OK(status)) {
4862 return status;
4865 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4866 if (!NT_STATUS_IS_OK(status)) {
4867 return status;
4870 if (fsp->fsp_flags.modified) {
4871 trigger_write_time_update_immediate(fsp);
4873 return NT_STATUS_OK;
4876 /****************************************************************************
4877 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4878 ****************************************************************************/
4880 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4881 struct smb_request *req,
4882 const char *pdata,
4883 int total_data,
4884 files_struct *fsp,
4885 struct smb_filename *smb_fname)
4887 uint64_t allocation_size = 0;
4888 NTSTATUS status = NT_STATUS_OK;
4889 files_struct *new_fsp = NULL;
4891 if (!VALID_STAT(smb_fname->st)) {
4892 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4895 if (total_data < 8) {
4896 return NT_STATUS_INVALID_PARAMETER;
4899 allocation_size = (uint64_t)IVAL(pdata,0);
4900 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4901 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4902 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4903 (double)allocation_size));
4905 if (allocation_size) {
4906 allocation_size = smb_roundup(conn, allocation_size);
4909 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4910 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
4911 (double)allocation_size));
4913 if (fsp &&
4914 !fsp->fsp_flags.is_pathref &&
4915 fsp_get_io_fd(fsp) != -1)
4917 /* Open file handle. */
4918 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4919 return NT_STATUS_ACCESS_DENIED;
4922 /* Only change if needed. */
4923 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4924 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4925 return map_nt_error_from_unix(errno);
4928 /* But always update the time. */
4930 * This is equivalent to a write. Ensure it's seen immediately
4931 * if there are no pending writes.
4933 trigger_write_time_update_immediate(fsp);
4934 return NT_STATUS_OK;
4937 /* Pathname or stat or directory file. */
4938 status = SMB_VFS_CREATE_FILE(
4939 conn, /* conn */
4940 req, /* req */
4941 NULL, /* dirfsp */
4942 smb_fname, /* fname */
4943 FILE_WRITE_DATA, /* access_mask */
4944 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4945 FILE_SHARE_DELETE),
4946 FILE_OPEN, /* create_disposition*/
4947 0, /* create_options */
4948 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4949 0, /* oplock_request */
4950 NULL, /* lease */
4951 0, /* allocation_size */
4952 0, /* private_flags */
4953 NULL, /* sd */
4954 NULL, /* ea_list */
4955 &new_fsp, /* result */
4956 NULL, /* pinfo */
4957 NULL, NULL); /* create context */
4959 if (!NT_STATUS_IS_OK(status)) {
4960 /* NB. We check for open_was_deferred in the caller. */
4961 return status;
4964 /* Only change if needed. */
4965 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4966 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4967 status = map_nt_error_from_unix(errno);
4968 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4969 return status;
4973 /* Changing the allocation size should set the last mod time. */
4975 * This is equivalent to a write. Ensure it's seen immediately
4976 * if there are no pending writes.
4978 trigger_write_time_update_immediate(new_fsp);
4979 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4980 return NT_STATUS_OK;
4983 /****************************************************************************
4984 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4985 ****************************************************************************/
4987 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4988 struct smb_request *req,
4989 const char *pdata,
4990 int total_data,
4991 files_struct *fsp,
4992 struct smb_filename *smb_fname,
4993 bool fail_after_createfile)
4995 off_t size;
4997 if (total_data < 8) {
4998 return NT_STATUS_INVALID_PARAMETER;
5001 size = IVAL(pdata,0);
5002 size |= (((off_t)IVAL(pdata,4)) << 32);
5003 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5004 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5005 (double)size));
5007 return smb_set_file_size(conn, req,
5008 fsp,
5009 smb_fname,
5010 &smb_fname->st,
5011 size,
5012 fail_after_createfile);
5015 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5016 struct smb_request *req,
5017 TALLOC_CTX *mem_ctx,
5018 uint16_t info_level,
5019 files_struct *fsp,
5020 struct smb_filename *smb_fname,
5021 char **ppdata, int total_data,
5022 int *ret_data_size)
5024 char *pdata = *ppdata;
5025 NTSTATUS status = NT_STATUS_OK;
5026 int data_return_size = 0;
5028 *ret_data_size = 0;
5030 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5031 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5032 fsp_fnum_dbg(fsp),
5033 info_level, total_data));
5035 switch (info_level) {
5037 case SMB_INFO_STANDARD:
5039 status = smb_set_info_standard(conn,
5040 pdata,
5041 total_data,
5042 fsp,
5043 smb_fname);
5044 break;
5047 case SMB_INFO_SET_EA:
5049 status = smb_info_set_ea(conn,
5050 pdata,
5051 total_data,
5052 fsp,
5053 smb_fname);
5054 break;
5057 case SMB_SET_FILE_BASIC_INFO:
5058 case SMB_FILE_BASIC_INFORMATION:
5060 status = smb_set_file_basic_info(conn,
5061 pdata,
5062 total_data,
5063 fsp,
5064 smb_fname);
5065 break;
5068 case SMB_FILE_ALLOCATION_INFORMATION:
5069 case SMB_SET_FILE_ALLOCATION_INFO:
5071 status = smb_set_file_allocation_info(conn, req,
5072 pdata,
5073 total_data,
5074 fsp,
5075 smb_fname);
5076 break;
5079 case SMB_FILE_END_OF_FILE_INFORMATION:
5080 case SMB_SET_FILE_END_OF_FILE_INFO:
5083 * XP/Win7 both fail after the createfile with
5084 * SMB_SET_FILE_END_OF_FILE_INFO but not
5085 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5086 * The level is known here, so pass it down
5087 * appropriately.
5089 bool should_fail =
5090 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5092 status = smb_set_file_end_of_file_info(conn, req,
5093 pdata,
5094 total_data,
5095 fsp,
5096 smb_fname,
5097 should_fail);
5098 break;
5101 case SMB_FILE_DISPOSITION_INFORMATION:
5102 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5104 #if 0
5105 /* JRA - We used to just ignore this on a path ?
5106 * Shouldn't this be invalid level on a pathname
5107 * based call ?
5109 if (tran_call != TRANSACT2_SETFILEINFO) {
5110 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5112 #endif
5113 status = smb_set_file_disposition_info(conn,
5114 pdata,
5115 total_data,
5116 fsp,
5117 smb_fname);
5118 break;
5121 case SMB_FILE_POSITION_INFORMATION:
5123 status = smb_file_position_information(conn,
5124 pdata,
5125 total_data,
5126 fsp);
5127 break;
5130 case SMB_FILE_FULL_EA_INFORMATION:
5132 status = smb_set_file_full_ea_info(conn,
5133 pdata,
5134 total_data,
5135 fsp);
5136 break;
5139 /* From tridge Samba4 :
5140 * MODE_INFORMATION in setfileinfo (I have no
5141 * idea what "mode information" on a file is - it takes a value of 0,
5142 * 2, 4 or 6. What could it be?).
5145 case SMB_FILE_MODE_INFORMATION:
5147 status = smb_file_mode_information(conn,
5148 pdata,
5149 total_data);
5150 break;
5153 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5154 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5155 case SMB_FILE_SHORT_NAME_INFORMATION:
5156 return NT_STATUS_NOT_SUPPORTED;
5158 case SMB_FILE_RENAME_INFORMATION:
5160 status = smb_file_rename_information(conn, req,
5161 pdata, total_data,
5162 fsp, smb_fname);
5163 break;
5166 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5168 /* SMB2 rename information. */
5169 status = smb2_file_rename_information(conn, req,
5170 pdata, total_data,
5171 fsp, smb_fname);
5172 break;
5175 case SMB_FILE_LINK_INFORMATION:
5177 if (conn->sconn->using_smb2) {
5178 status = smb2_file_link_information(conn,
5179 req,
5180 pdata,
5181 total_data,
5182 fsp,
5183 smb_fname);
5184 } else {
5185 status = smb_file_link_information(conn,
5186 req,
5187 pdata,
5188 total_data,
5189 fsp,
5190 smb_fname);
5192 break;
5195 default:
5196 return NT_STATUS_INVALID_LEVEL;
5199 if (!NT_STATUS_IS_OK(status)) {
5200 return status;
5203 *ret_data_size = data_return_size;
5204 return NT_STATUS_OK;
5207 static uint32_t generate_volume_serial_number(
5208 const struct loadparm_substitution *lp_sub,
5209 int snum)
5211 int serial = lp_volume_serial_number(snum);
5212 return serial != -1 ? serial:
5213 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5214 (str_checksum(get_local_machine_name())<<16);