s3: smbd: Remove 'is_dfs' parameter to check_path_syntax_smb2().
[Samba.git] / source3 / smbd / smb2_trans2.c
blob2cd882bd88979e6f96b4405d8d29fe7191d6aa4b
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 Routine to check if a given string matches exactly.
837 as a special case a mask of "." does NOT match. That
838 is required for correct wildcard semantics
839 Case can be significant or not.
840 **********************************************************/
842 static bool exact_match(bool has_wild,
843 bool case_sensitive,
844 const char *str,
845 const char *mask)
847 if (mask[0] == '.' && mask[1] == 0) {
848 return false;
851 if (has_wild) {
852 return false;
855 if (case_sensitive) {
856 return strcmp(str,mask)==0;
857 } else {
858 return strcasecmp_m(str,mask) == 0;
862 /****************************************************************************
863 Return the filetype for UNIX extensions.
864 ****************************************************************************/
866 static uint32_t unix_filetype(mode_t mode)
868 if(S_ISREG(mode))
869 return UNIX_TYPE_FILE;
870 else if(S_ISDIR(mode))
871 return UNIX_TYPE_DIR;
872 #ifdef S_ISLNK
873 else if(S_ISLNK(mode))
874 return UNIX_TYPE_SYMLINK;
875 #endif
876 #ifdef S_ISCHR
877 else if(S_ISCHR(mode))
878 return UNIX_TYPE_CHARDEV;
879 #endif
880 #ifdef S_ISBLK
881 else if(S_ISBLK(mode))
882 return UNIX_TYPE_BLKDEV;
883 #endif
884 #ifdef S_ISFIFO
885 else if(S_ISFIFO(mode))
886 return UNIX_TYPE_FIFO;
887 #endif
888 #ifdef S_ISSOCK
889 else if(S_ISSOCK(mode))
890 return UNIX_TYPE_SOCKET;
891 #endif
893 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
894 return UNIX_TYPE_UNKNOWN;
897 /****************************************************************************
898 Map wire perms onto standard UNIX permissions. Obey share restrictions.
899 ****************************************************************************/
901 NTSTATUS unix_perms_from_wire(connection_struct *conn,
902 const SMB_STRUCT_STAT *psbuf,
903 uint32_t perms,
904 enum perm_type ptype,
905 mode_t *ret_perms)
907 mode_t ret = 0;
909 if (perms == SMB_MODE_NO_CHANGE) {
910 if (!VALID_STAT(*psbuf)) {
911 return NT_STATUS_INVALID_PARAMETER;
912 } else {
913 *ret_perms = psbuf->st_ex_mode;
914 return NT_STATUS_OK;
918 ret = wire_perms_to_unix(perms);
920 if (ptype == PERM_NEW_FILE) {
922 * "create mask"/"force create mode" are
923 * only applied to new files, not existing ones.
925 ret &= lp_create_mask(SNUM(conn));
926 /* Add in force bits */
927 ret |= lp_force_create_mode(SNUM(conn));
928 } else if (ptype == PERM_NEW_DIR) {
930 * "directory mask"/"force directory mode" are
931 * only applied to new directories, not existing ones.
933 ret &= lp_directory_mask(SNUM(conn));
934 /* Add in force bits */
935 ret |= lp_force_directory_mode(SNUM(conn));
938 *ret_perms = ret;
939 return NT_STATUS_OK;
942 /****************************************************************************
943 Needed to show the msdfs symlinks as directories. Modifies psbuf
944 to be a directory if it's a msdfs link.
945 ****************************************************************************/
947 static bool check_msdfs_link(struct files_struct *dirfsp,
948 struct smb_filename *atname,
949 struct smb_filename *smb_fname)
951 int saved_errno = errno;
952 if(lp_host_msdfs() &&
953 lp_msdfs_root(SNUM(dirfsp->conn)) &&
954 is_msdfs_link(dirfsp, atname)) {
957 * Copy the returned stat struct from the relative
958 * to the full pathname.
960 smb_fname->st = atname->st;
962 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
963 "as a directory\n",
964 smb_fname->base_name));
965 smb_fname->st.st_ex_mode =
966 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
967 errno = saved_errno;
968 return true;
970 errno = saved_errno;
971 return false;
975 /****************************************************************************
976 Get a level dependent lanman2 dir entry.
977 ****************************************************************************/
979 struct smbd_dirptr_lanman2_state {
980 connection_struct *conn;
981 uint32_t info_level;
982 bool check_mangled_names;
983 bool has_wild;
984 bool got_exact_match;
985 bool case_sensitive;
988 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
989 void *private_data,
990 const char *dname,
991 const char *mask,
992 char **_fname)
994 struct smbd_dirptr_lanman2_state *state =
995 (struct smbd_dirptr_lanman2_state *)private_data;
996 bool ok;
997 char mangled_name[13]; /* mangled 8.3 name. */
998 bool got_match;
999 const char *fname;
1001 /* Mangle fname if it's an illegal name. */
1002 if (mangle_must_mangle(dname, state->conn->params)) {
1004 * Slow path - ensure we can push the original name as UCS2. If
1005 * not, then just don't return this name.
1007 NTSTATUS status;
1008 size_t ret_len = 0;
1009 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1010 uint8_t *tmp = talloc_array(talloc_tos(),
1011 uint8_t,
1012 len);
1014 status = srvstr_push(NULL,
1015 FLAGS2_UNICODE_STRINGS,
1016 tmp,
1017 dname,
1018 len,
1019 STR_TERMINATE,
1020 &ret_len);
1022 TALLOC_FREE(tmp);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 return false;
1028 ok = name_to_8_3(dname, mangled_name,
1029 true, state->conn->params);
1030 if (!ok) {
1031 return false;
1033 fname = mangled_name;
1034 } else {
1035 fname = dname;
1038 got_match = exact_match(state->has_wild,
1039 state->case_sensitive,
1040 fname, mask);
1041 state->got_exact_match = got_match;
1042 if (!got_match) {
1043 got_match = mask_match(fname, mask,
1044 state->case_sensitive);
1047 if(!got_match && state->check_mangled_names &&
1048 !mangle_is_8_3(fname, false, state->conn->params)) {
1050 * It turns out that NT matches wildcards against
1051 * both long *and* short names. This may explain some
1052 * of the wildcard wierdness from old DOS clients
1053 * that some people have been seeing.... JRA.
1055 /* Force the mangling into 8.3. */
1056 ok = name_to_8_3(fname, mangled_name,
1057 false, state->conn->params);
1058 if (!ok) {
1059 return false;
1062 got_match = exact_match(state->has_wild,
1063 state->case_sensitive,
1064 mangled_name, mask);
1065 state->got_exact_match = got_match;
1066 if (!got_match) {
1067 got_match = mask_match(mangled_name, mask,
1068 state->case_sensitive);
1072 if (!got_match) {
1073 return false;
1076 *_fname = talloc_strdup(ctx, fname);
1077 if (*_fname == NULL) {
1078 return false;
1081 return true;
1084 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1085 void *private_data,
1086 struct files_struct *dirfsp,
1087 struct smb_filename *atname,
1088 struct smb_filename *smb_fname,
1089 bool get_dosmode,
1090 uint32_t *_mode)
1092 struct smbd_dirptr_lanman2_state *state =
1093 (struct smbd_dirptr_lanman2_state *)private_data;
1094 bool ms_dfs_link = false;
1096 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1097 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1098 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1099 "Couldn't lstat [%s] (%s)\n",
1100 smb_fname_str_dbg(smb_fname),
1101 strerror(errno)));
1102 return false;
1104 return true;
1107 if (!VALID_STAT(smb_fname->st) &&
1108 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1109 /* Needed to show the msdfs symlinks as
1110 * directories */
1112 ms_dfs_link = check_msdfs_link(dirfsp,
1113 atname,
1114 smb_fname);
1115 if (!ms_dfs_link) {
1116 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1117 "Couldn't stat [%s] (%s)\n",
1118 smb_fname_str_dbg(smb_fname),
1119 strerror(errno)));
1120 return false;
1123 *_mode = dos_mode_msdfs(state->conn, smb_fname);
1124 return true;
1127 if (!get_dosmode) {
1128 return true;
1131 *_mode = fdos_mode(smb_fname->fsp);
1132 smb_fname->st = smb_fname->fsp->fsp_name->st;
1134 return true;
1137 static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1139 if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1140 unsigned ea_size = estimate_ea_size(fsp);
1141 return ea_size;
1143 return IO_REPARSE_TAG_DFS;
1146 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1147 connection_struct *conn,
1148 uint16_t flags2,
1149 uint32_t info_level,
1150 struct ea_list *name_list,
1151 bool check_mangled_names,
1152 bool requires_resume_key,
1153 uint32_t mode,
1154 const char *fname,
1155 const struct smb_filename *smb_fname,
1156 int space_remaining,
1157 uint8_t align,
1158 bool do_pad,
1159 char *base_data,
1160 char **ppdata,
1161 char *end_data,
1162 uint64_t *last_entry_off)
1164 char *p, *q, *pdata = *ppdata;
1165 uint32_t reskey=0;
1166 uint64_t file_size = 0;
1167 uint64_t allocation_size = 0;
1168 uint64_t file_id = 0;
1169 size_t len = 0;
1170 struct timespec mdate_ts = {0};
1171 struct timespec adate_ts = {0};
1172 struct timespec cdate_ts = {0};
1173 struct timespec create_date_ts = {0};
1174 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1175 char *nameptr;
1176 char *last_entry_ptr;
1177 bool was_8_3;
1178 int off;
1179 int pad = 0;
1180 NTSTATUS status;
1181 struct readdir_attr_data *readdir_attr_data = NULL;
1182 uint32_t ea_size;
1184 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1185 file_size = get_file_size_stat(&smb_fname->st);
1187 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1190 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1191 * a DFS symlink.
1193 if (smb_fname->fsp != NULL &&
1194 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1195 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1196 ctx,
1197 &readdir_attr_data);
1198 if (!NT_STATUS_IS_OK(status)) {
1199 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1200 status)) {
1201 return status;
1206 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1208 mdate_ts = smb_fname->st.st_ex_mtime;
1209 adate_ts = smb_fname->st.st_ex_atime;
1210 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1211 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1213 if (lp_dos_filetime_resolution(SNUM(conn))) {
1214 dos_filetime_timespec(&create_date_ts);
1215 dos_filetime_timespec(&mdate_ts);
1216 dos_filetime_timespec(&adate_ts);
1217 dos_filetime_timespec(&cdate_ts);
1220 create_date = convert_timespec_to_time_t(create_date_ts);
1221 mdate = convert_timespec_to_time_t(mdate_ts);
1222 adate = convert_timespec_to_time_t(adate_ts);
1224 /* align the record */
1225 SMB_ASSERT(align >= 1);
1227 off = (int)PTR_DIFF(pdata, base_data);
1228 pad = (off + (align-1)) & ~(align-1);
1229 pad -= off;
1231 if (pad && pad > space_remaining) {
1232 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1233 "for padding (wanted %u, had %d)\n",
1234 (unsigned int)pad,
1235 space_remaining ));
1236 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1239 off += pad;
1240 /* initialize padding to 0 */
1241 if (pad) {
1242 memset(pdata, 0, pad);
1244 space_remaining -= pad;
1246 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1247 space_remaining ));
1249 pdata += pad;
1250 p = pdata;
1251 last_entry_ptr = p;
1253 pad = 0;
1254 off = 0;
1256 switch (info_level) {
1257 case SMB_FIND_INFO_STANDARD:
1258 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1259 if(requires_resume_key) {
1260 SIVAL(p,0,reskey);
1261 p += 4;
1263 srv_put_dos_date2(p,0,create_date);
1264 srv_put_dos_date2(p,4,adate);
1265 srv_put_dos_date2(p,8,mdate);
1266 SIVAL(p,12,(uint32_t)file_size);
1267 SIVAL(p,16,(uint32_t)allocation_size);
1268 SSVAL(p,20,mode);
1269 p += 23;
1270 nameptr = p;
1271 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1272 p += ucs2_align(base_data, p, 0);
1274 status = srvstr_push(base_data, flags2, p,
1275 fname, PTR_DIFF(end_data, p),
1276 STR_TERMINATE, &len);
1277 if (!NT_STATUS_IS_OK(status)) {
1278 return status;
1280 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1281 if (len > 2) {
1282 SCVAL(nameptr, -1, len - 2);
1283 } else {
1284 SCVAL(nameptr, -1, 0);
1286 } else {
1287 if (len > 1) {
1288 SCVAL(nameptr, -1, len - 1);
1289 } else {
1290 SCVAL(nameptr, -1, 0);
1293 p += len;
1294 break;
1296 case SMB_FIND_EA_SIZE:
1297 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1298 if (requires_resume_key) {
1299 SIVAL(p,0,reskey);
1300 p += 4;
1302 srv_put_dos_date2(p,0,create_date);
1303 srv_put_dos_date2(p,4,adate);
1304 srv_put_dos_date2(p,8,mdate);
1305 SIVAL(p,12,(uint32_t)file_size);
1306 SIVAL(p,16,(uint32_t)allocation_size);
1307 SSVAL(p,20,mode);
1309 ea_size = estimate_ea_size(smb_fname->fsp);
1310 SIVAL(p,22,ea_size); /* Extended attributes */
1312 p += 27;
1313 nameptr = p - 1;
1314 status = srvstr_push(base_data, flags2,
1315 p, fname, PTR_DIFF(end_data, p),
1316 STR_TERMINATE | STR_NOALIGN, &len);
1317 if (!NT_STATUS_IS_OK(status)) {
1318 return status;
1320 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1321 if (len > 2) {
1322 len -= 2;
1323 } else {
1324 len = 0;
1326 } else {
1327 if (len > 1) {
1328 len -= 1;
1329 } else {
1330 len = 0;
1333 SCVAL(nameptr,0,len);
1334 p += len;
1335 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1336 break;
1338 case SMB_FIND_EA_LIST:
1340 struct ea_list *file_list = NULL;
1341 size_t ea_len = 0;
1343 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1344 if (!name_list) {
1345 return NT_STATUS_INVALID_PARAMETER;
1347 if (requires_resume_key) {
1348 SIVAL(p,0,reskey);
1349 p += 4;
1351 srv_put_dos_date2(p,0,create_date);
1352 srv_put_dos_date2(p,4,adate);
1353 srv_put_dos_date2(p,8,mdate);
1354 SIVAL(p,12,(uint32_t)file_size);
1355 SIVAL(p,16,(uint32_t)allocation_size);
1356 SSVAL(p,20,mode);
1357 p += 22; /* p now points to the EA area. */
1359 status = get_ea_list_from_fsp(ctx,
1360 smb_fname->fsp,
1361 &ea_len, &file_list);
1362 if (!NT_STATUS_IS_OK(status)) {
1363 file_list = NULL;
1365 name_list = ea_list_union(name_list, file_list, &ea_len);
1367 /* We need to determine if this entry will fit in the space available. */
1368 /* Max string size is 255 bytes. */
1369 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1370 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1371 "(wanted %u, had %d)\n",
1372 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1373 space_remaining ));
1374 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1377 /* Push the ea_data followed by the name. */
1378 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1379 nameptr = p;
1380 status = srvstr_push(base_data, flags2,
1381 p + 1, fname, PTR_DIFF(end_data, p+1),
1382 STR_TERMINATE | STR_NOALIGN, &len);
1383 if (!NT_STATUS_IS_OK(status)) {
1384 return status;
1386 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1387 if (len > 2) {
1388 len -= 2;
1389 } else {
1390 len = 0;
1392 } else {
1393 if (len > 1) {
1394 len -= 1;
1395 } else {
1396 len = 0;
1399 SCVAL(nameptr,0,len);
1400 p += len + 1;
1401 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1402 break;
1405 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1406 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1407 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1408 p += 4;
1409 SIVAL(p,0,reskey); p += 4;
1410 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1411 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1412 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1413 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1414 SOFF_T(p,0,file_size); p += 8;
1415 SOFF_T(p,0,allocation_size); p += 8;
1416 SIVAL(p,0,mode); p += 4;
1417 q = p; p += 4; /* q is placeholder for name length. */
1418 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1419 SIVAL(p, 0, ea_size);
1420 p += 4;
1421 /* Clear the short name buffer. This is
1422 * IMPORTANT as not doing so will trigger
1423 * a Win2k client bug. JRA.
1425 if (!was_8_3 && check_mangled_names) {
1426 char mangled_name[13]; /* mangled 8.3 name. */
1427 if (!name_to_8_3(fname,mangled_name,True,
1428 conn->params)) {
1429 /* Error - mangle failed ! */
1430 memset(mangled_name,'\0',12);
1432 mangled_name[12] = 0;
1433 status = srvstr_push(base_data, flags2,
1434 p+2, mangled_name, 24,
1435 STR_UPPER|STR_UNICODE, &len);
1436 if (!NT_STATUS_IS_OK(status)) {
1437 return status;
1439 if (len < 24) {
1440 memset(p + 2 + len,'\0',24 - len);
1442 SSVAL(p, 0, len);
1443 } else {
1444 memset(p,'\0',26);
1446 p += 2 + 24;
1447 status = srvstr_push(base_data, flags2, p,
1448 fname, PTR_DIFF(end_data, p),
1449 STR_TERMINATE_ASCII, &len);
1450 if (!NT_STATUS_IS_OK(status)) {
1451 return status;
1453 SIVAL(q,0,len);
1454 p += len;
1456 len = PTR_DIFF(p, pdata);
1457 pad = (len + (align-1)) & ~(align-1);
1459 * offset to the next entry, the caller
1460 * will overwrite it for the last entry
1461 * that's why we always include the padding
1463 SIVAL(pdata,0,pad);
1465 * set padding to zero
1467 if (do_pad) {
1468 memset(p, 0, pad - len);
1469 p = pdata + pad;
1470 } else {
1471 p = pdata + len;
1473 break;
1475 case SMB_FIND_FILE_DIRECTORY_INFO:
1476 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1477 p += 4;
1478 SIVAL(p,0,reskey); p += 4;
1479 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1480 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1481 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1482 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1483 SOFF_T(p,0,file_size); p += 8;
1484 SOFF_T(p,0,allocation_size); p += 8;
1485 SIVAL(p,0,mode); p += 4;
1486 status = srvstr_push(base_data, flags2,
1487 p + 4, fname, PTR_DIFF(end_data, p+4),
1488 STR_TERMINATE_ASCII, &len);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 return status;
1492 SIVAL(p,0,len);
1493 p += 4 + len;
1495 len = PTR_DIFF(p, pdata);
1496 pad = (len + (align-1)) & ~(align-1);
1498 * offset to the next entry, the caller
1499 * will overwrite it for the last entry
1500 * that's why we always include the padding
1502 SIVAL(pdata,0,pad);
1504 * set padding to zero
1506 if (do_pad) {
1507 memset(p, 0, pad - len);
1508 p = pdata + pad;
1509 } else {
1510 p = pdata + len;
1512 break;
1514 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1515 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1516 p += 4;
1517 SIVAL(p,0,reskey); p += 4;
1518 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1519 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1520 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1521 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1522 SOFF_T(p,0,file_size); p += 8;
1523 SOFF_T(p,0,allocation_size); p += 8;
1524 SIVAL(p,0,mode); p += 4;
1525 q = p; p += 4; /* q is placeholder for name length. */
1526 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1527 SIVAL(p, 0, ea_size);
1528 p +=4;
1529 status = srvstr_push(base_data, flags2, p,
1530 fname, PTR_DIFF(end_data, p),
1531 STR_TERMINATE_ASCII, &len);
1532 if (!NT_STATUS_IS_OK(status)) {
1533 return status;
1535 SIVAL(q, 0, len);
1536 p += len;
1538 len = PTR_DIFF(p, pdata);
1539 pad = (len + (align-1)) & ~(align-1);
1541 * offset to the next entry, the caller
1542 * will overwrite it for the last entry
1543 * that's why we always include the padding
1545 SIVAL(pdata,0,pad);
1547 * set padding to zero
1549 if (do_pad) {
1550 memset(p, 0, pad - len);
1551 p = pdata + pad;
1552 } else {
1553 p = pdata + len;
1555 break;
1557 case SMB_FIND_FILE_NAMES_INFO:
1558 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1559 p += 4;
1560 SIVAL(p,0,reskey); p += 4;
1561 p += 4;
1562 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1563 acl on a dir (tridge) */
1564 status = srvstr_push(base_data, flags2, p,
1565 fname, PTR_DIFF(end_data, p),
1566 STR_TERMINATE_ASCII, &len);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 return status;
1570 SIVAL(p, -4, len);
1571 p += len;
1573 len = PTR_DIFF(p, pdata);
1574 pad = (len + (align-1)) & ~(align-1);
1576 * offset to the next entry, the caller
1577 * will overwrite it for the last entry
1578 * that's why we always include the padding
1580 SIVAL(pdata,0,pad);
1582 * set padding to zero
1584 if (do_pad) {
1585 memset(p, 0, pad - len);
1586 p = pdata + pad;
1587 } else {
1588 p = pdata + len;
1590 break;
1592 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1593 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1594 p += 4;
1595 SIVAL(p,0,reskey); p += 4;
1596 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1597 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1598 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1599 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1600 SOFF_T(p,0,file_size); p += 8;
1601 SOFF_T(p,0,allocation_size); p += 8;
1602 SIVAL(p,0,mode); p += 4;
1603 q = p; p += 4; /* q is placeholder for name length. */
1604 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1605 SIVAL(p, 0, ea_size);
1606 p += 4;
1607 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1608 SBVAL(p,0,file_id); p += 8;
1609 status = srvstr_push(base_data, flags2, p,
1610 fname, PTR_DIFF(end_data, p),
1611 STR_TERMINATE_ASCII, &len);
1612 if (!NT_STATUS_IS_OK(status)) {
1613 return status;
1615 SIVAL(q, 0, len);
1616 p += len;
1618 len = PTR_DIFF(p, pdata);
1619 pad = (len + (align-1)) & ~(align-1);
1621 * offset to the next entry, the caller
1622 * will overwrite it for the last entry
1623 * that's why we always include the padding
1625 SIVAL(pdata,0,pad);
1627 * set padding to zero
1629 if (do_pad) {
1630 memset(p, 0, pad - len);
1631 p = pdata + pad;
1632 } else {
1633 p = pdata + len;
1635 break;
1637 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1638 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1639 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1640 p += 4;
1641 SIVAL(p,0,reskey); p += 4;
1642 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1643 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1644 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1645 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1646 SOFF_T(p,0,file_size); p += 8;
1647 SOFF_T(p,0,allocation_size); p += 8;
1648 SIVAL(p,0,mode); p += 4;
1649 q = p; p += 4; /* q is placeholder for name length */
1650 if (readdir_attr_data &&
1651 readdir_attr_data->type == RDATTR_AAPL) {
1653 * OS X specific SMB2 extension negotiated via
1654 * AAPL create context: return max_access in
1655 * ea_size field.
1657 ea_size = readdir_attr_data->attr_data.aapl.max_access;
1658 } else {
1659 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1661 SIVAL(p,0,ea_size); /* Extended attributes */
1662 p += 4;
1664 if (readdir_attr_data &&
1665 readdir_attr_data->type == RDATTR_AAPL) {
1667 * OS X specific SMB2 extension negotiated via
1668 * AAPL create context: return resource fork
1669 * length and compressed FinderInfo in
1670 * shortname field.
1672 * According to documentation short_name_len
1673 * should be 0, but on the wire behaviour
1674 * shows its set to 24 by clients.
1676 SSVAL(p, 0, 24);
1678 /* Resourefork length */
1679 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1681 /* Compressed FinderInfo */
1682 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1683 } else if (!was_8_3 && check_mangled_names) {
1684 char mangled_name[13]; /* mangled 8.3 name. */
1685 if (!name_to_8_3(fname,mangled_name,True,
1686 conn->params)) {
1687 /* Error - mangle failed ! */
1688 memset(mangled_name,'\0',12);
1690 mangled_name[12] = 0;
1691 status = srvstr_push(base_data, flags2,
1692 p+2, mangled_name, 24,
1693 STR_UPPER|STR_UNICODE, &len);
1694 if (!NT_STATUS_IS_OK(status)) {
1695 return status;
1697 SSVAL(p, 0, len);
1698 if (len < 24) {
1699 memset(p + 2 + len,'\0',24 - len);
1701 SSVAL(p, 0, len);
1702 } else {
1703 /* Clear the short name buffer. This is
1704 * IMPORTANT as not doing so will trigger
1705 * a Win2k client bug. JRA.
1707 memset(p,'\0',26);
1709 p += 26;
1711 /* Reserved ? */
1712 if (readdir_attr_data &&
1713 readdir_attr_data->type == RDATTR_AAPL) {
1715 * OS X specific SMB2 extension negotiated via
1716 * AAPL create context: return UNIX mode in
1717 * reserved field.
1719 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1720 SSVAL(p, 0, aapl_mode);
1721 } else {
1722 SSVAL(p, 0, 0);
1724 p += 2;
1726 SBVAL(p,0,file_id); p += 8;
1727 status = srvstr_push(base_data, flags2, p,
1728 fname, PTR_DIFF(end_data, p),
1729 STR_TERMINATE_ASCII, &len);
1730 if (!NT_STATUS_IS_OK(status)) {
1731 return status;
1733 SIVAL(q,0,len);
1734 p += len;
1736 len = PTR_DIFF(p, pdata);
1737 pad = (len + (align-1)) & ~(align-1);
1739 * offset to the next entry, the caller
1740 * will overwrite it for the last entry
1741 * that's why we always include the padding
1743 SIVAL(pdata,0,pad);
1745 * set padding to zero
1747 if (do_pad) {
1748 memset(p, 0, pad - len);
1749 p = pdata + pad;
1750 } else {
1751 p = pdata + len;
1753 break;
1755 /* CIFS UNIX Extension. */
1757 case SMB_FIND_FILE_UNIX:
1758 case SMB_FIND_FILE_UNIX_INFO2:
1759 p+= 4;
1760 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1762 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1764 if (info_level == SMB_FIND_FILE_UNIX) {
1765 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1766 p = store_file_unix_basic(conn, p,
1767 NULL, &smb_fname->st);
1768 status = srvstr_push(base_data, flags2, p,
1769 fname, PTR_DIFF(end_data, p),
1770 STR_TERMINATE, &len);
1771 if (!NT_STATUS_IS_OK(status)) {
1772 return status;
1774 } else {
1775 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1776 p = store_file_unix_basic_info2(conn, p,
1777 NULL, &smb_fname->st);
1778 nameptr = p;
1779 p += 4;
1780 status = srvstr_push(base_data, flags2, p, fname,
1781 PTR_DIFF(end_data, p), 0, &len);
1782 if (!NT_STATUS_IS_OK(status)) {
1783 return status;
1785 SIVAL(nameptr, 0, len);
1788 p += len;
1790 len = PTR_DIFF(p, pdata);
1791 pad = (len + (align-1)) & ~(align-1);
1793 * offset to the next entry, the caller
1794 * will overwrite it for the last entry
1795 * that's why we always include the padding
1797 SIVAL(pdata,0,pad);
1799 * set padding to zero
1801 if (do_pad) {
1802 memset(p, 0, pad - len);
1803 p = pdata + pad;
1804 } else {
1805 p = pdata + len;
1807 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1809 break;
1811 /* SMB2 UNIX Extension. */
1813 case SMB2_FILE_POSIX_INFORMATION:
1815 uint8_t *buf = NULL;
1816 ssize_t plen = 0;
1817 p+= 4;
1818 SIVAL(p,0,reskey); p+= 4;
1820 DEBUG(10,("smbd_marshall_dir_entry: "
1821 "SMB2_FILE_POSIX_INFORMATION\n"));
1822 if (!(conn->sconn->using_smb2)) {
1823 return NT_STATUS_INVALID_LEVEL;
1825 if (!lp_smb3_unix_extensions()) {
1826 return NT_STATUS_INVALID_LEVEL;
1829 /* Determine the size of the posix info context */
1830 plen = store_smb2_posix_info(conn,
1831 &smb_fname->st,
1833 mode,
1834 NULL,
1836 if (plen == -1) {
1837 return NT_STATUS_INVALID_PARAMETER;
1839 buf = talloc_zero_size(ctx, plen);
1840 if (buf == NULL) {
1841 return NT_STATUS_NO_MEMORY;
1844 /* Store the context in buf */
1845 store_smb2_posix_info(conn,
1846 &smb_fname->st,
1848 mode,
1849 buf,
1850 plen);
1851 memcpy(p, buf, plen);
1852 p += plen;
1853 TALLOC_FREE(buf);
1855 nameptr = p;
1856 p += 4;
1857 status = srvstr_push(base_data, flags2, p, fname,
1858 PTR_DIFF(end_data, p), 0, &len);
1859 if (!NT_STATUS_IS_OK(status)) {
1860 return status;
1862 SIVAL(nameptr, 0, len);
1864 p += len;
1866 len = PTR_DIFF(p, pdata);
1867 pad = (len + (align-1)) & ~(align-1);
1869 * offset to the next entry, the caller
1870 * will overwrite it for the last entry
1871 * that's why we always include the padding
1873 SIVAL(pdata,0,pad);
1874 break;
1877 default:
1878 return NT_STATUS_INVALID_LEVEL;
1881 if (PTR_DIFF(p,pdata) > space_remaining) {
1882 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1883 "(wanted %u, had %d)\n",
1884 (unsigned int)PTR_DIFF(p,pdata),
1885 space_remaining ));
1886 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1889 /* Setup the last entry pointer, as an offset from base_data */
1890 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1891 /* Advance the data pointer to the next slot */
1892 *ppdata = p;
1894 return NT_STATUS_OK;
1897 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1898 connection_struct *conn,
1899 struct dptr_struct *dirptr,
1900 uint16_t flags2,
1901 const char *path_mask,
1902 uint32_t dirtype,
1903 int info_level,
1904 int requires_resume_key,
1905 bool dont_descend,
1906 bool ask_sharemode,
1907 bool get_dosmode,
1908 uint8_t align,
1909 bool do_pad,
1910 char **ppdata,
1911 char *base_data,
1912 char *end_data,
1913 int space_remaining,
1914 struct smb_filename **_smb_fname,
1915 bool *got_exact_match,
1916 int *_last_entry_off,
1917 struct ea_list *name_list,
1918 struct file_id *file_id)
1920 const char *p;
1921 const char *mask = NULL;
1922 long prev_dirpos = 0;
1923 uint32_t mode = 0;
1924 char *fname = NULL;
1925 struct smb_filename *smb_fname = NULL;
1926 struct smbd_dirptr_lanman2_state state;
1927 bool ok;
1928 uint64_t last_entry_off = 0;
1929 NTSTATUS status;
1930 enum mangled_names_options mangled_names;
1931 bool marshall_with_83_names;
1933 mangled_names = lp_mangled_names(conn->params);
1935 ZERO_STRUCT(state);
1936 state.conn = conn;
1937 state.info_level = info_level;
1938 if (mangled_names != MANGLED_NAMES_NO) {
1939 state.check_mangled_names = true;
1941 state.has_wild = dptr_has_wild(dirptr);
1942 state.got_exact_match = false;
1943 state.case_sensitive = dptr_case_sensitive(dirptr);
1945 *got_exact_match = false;
1947 p = strrchr_m(path_mask,'/');
1948 if(p != NULL) {
1949 if(p[1] == '\0') {
1950 mask = "*.*";
1951 } else {
1952 mask = p+1;
1954 } else {
1955 mask = path_mask;
1958 ok = smbd_dirptr_get_entry(ctx,
1959 dirptr,
1960 mask,
1961 dirtype,
1962 dont_descend,
1963 ask_sharemode,
1964 get_dosmode,
1965 smbd_dirptr_lanman2_match_fn,
1966 smbd_dirptr_lanman2_mode_fn,
1967 &state,
1968 &fname,
1969 &smb_fname,
1970 &mode,
1971 &prev_dirpos);
1972 if (!ok) {
1973 return NT_STATUS_END_OF_FILE;
1976 *got_exact_match = state.got_exact_match;
1978 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1980 status = smbd_marshall_dir_entry(ctx,
1981 conn,
1982 flags2,
1983 info_level,
1984 name_list,
1985 marshall_with_83_names,
1986 requires_resume_key,
1987 mode,
1988 fname,
1989 smb_fname,
1990 space_remaining,
1991 align,
1992 do_pad,
1993 base_data,
1994 ppdata,
1995 end_data,
1996 &last_entry_off);
1997 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1998 DEBUG(1,("Conversion error: illegal character: %s\n",
1999 smb_fname_str_dbg(smb_fname)));
2002 if (file_id != NULL) {
2003 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2006 if (!NT_STATUS_IS_OK(status) &&
2007 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2009 TALLOC_FREE(smb_fname);
2010 TALLOC_FREE(fname);
2011 return status;
2014 if (_smb_fname != NULL) {
2016 * smb_fname is already talloc'ed off ctx.
2017 * We just need to make sure we don't return
2018 * any stream_name, and replace base_name
2019 * with fname in case base_name got mangled.
2020 * This allows us to preserve any smb_fname->fsp
2021 * for asynchronous handle lookups.
2023 TALLOC_FREE(smb_fname->stream_name);
2024 TALLOC_FREE(smb_fname->base_name);
2025 smb_fname->base_name = talloc_strdup(smb_fname, fname);
2027 if (smb_fname->base_name == NULL) {
2028 TALLOC_FREE(smb_fname);
2029 TALLOC_FREE(fname);
2030 return NT_STATUS_NO_MEMORY;
2032 *_smb_fname = smb_fname;
2033 } else {
2034 TALLOC_FREE(smb_fname);
2036 TALLOC_FREE(fname);
2038 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2039 dptr_SeekDir(dirptr, prev_dirpos);
2040 return status;
2043 *_last_entry_off = last_entry_off;
2044 return NT_STATUS_OK;
2047 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2049 const struct loadparm_substitution *lp_sub =
2050 loadparm_s3_global_substitution();
2052 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
2053 return objid;
2056 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2058 SMB_ASSERT(extended_info != NULL);
2060 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2061 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2062 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2063 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2064 #ifdef SAMBA_VERSION_REVISION
2065 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2066 #endif
2067 extended_info->samba_subversion = 0;
2068 #ifdef SAMBA_VERSION_RC_RELEASE
2069 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2070 #else
2071 #ifdef SAMBA_VERSION_PRE_RELEASE
2072 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2073 #endif
2074 #endif
2075 #ifdef SAMBA_VERSION_VENDOR_PATCH
2076 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2077 #endif
2078 extended_info->samba_gitcommitdate = 0;
2079 #ifdef SAMBA_VERSION_COMMIT_TIME
2080 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2081 #endif
2083 memset(extended_info->samba_version_string, 0,
2084 sizeof(extended_info->samba_version_string));
2086 snprintf (extended_info->samba_version_string,
2087 sizeof(extended_info->samba_version_string),
2088 "%s", samba_version_string());
2091 static bool fsinfo_unix_valid_level(connection_struct *conn,
2092 uint16_t info_level)
2094 if (conn->sconn->using_smb2 &&
2095 lp_smb3_unix_extensions() &&
2096 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) {
2097 return true;
2099 #if defined(SMB1SERVER)
2100 if (lp_smb1_unix_extensions() &&
2101 info_level == SMB_QUERY_POSIX_FS_INFO) {
2102 return true;
2104 #endif
2105 return false;
2108 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
2109 connection_struct *conn,
2110 TALLOC_CTX *mem_ctx,
2111 uint16_t info_level,
2112 uint16_t flags2,
2113 unsigned int max_data_bytes,
2114 size_t *fixed_portion,
2115 struct smb_filename *fname,
2116 char **ppdata,
2117 int *ret_data_len)
2119 const struct loadparm_substitution *lp_sub =
2120 loadparm_s3_global_substitution();
2121 char *pdata, *end_data;
2122 int data_len = 0;
2123 size_t len = 0;
2124 const char *vname = volume_label(talloc_tos(), SNUM(conn));
2125 int snum = SNUM(conn);
2126 const char *fstype = lp_fstype(SNUM(conn));
2127 const char *filename = NULL;
2128 const uint64_t bytes_per_sector = 512;
2129 uint32_t additional_flags = 0;
2130 struct smb_filename smb_fname;
2131 SMB_STRUCT_STAT st;
2132 NTSTATUS status = NT_STATUS_OK;
2133 uint64_t df_ret;
2134 uint32_t serial;
2136 if (fname == NULL || fname->base_name == NULL) {
2137 filename = ".";
2138 } else {
2139 filename = fname->base_name;
2142 if (IS_IPC(conn)) {
2143 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2144 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2145 "info level (0x%x) on IPC$.\n",
2146 (unsigned int)info_level));
2147 return NT_STATUS_ACCESS_DENIED;
2151 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2153 smb_fname = (struct smb_filename) {
2154 .base_name = discard_const_p(char, filename),
2155 .flags = fname ? fname->flags : 0,
2156 .twrp = fname ? fname->twrp : 0,
2159 if(info_level != SMB_FS_QUOTA_INFORMATION
2160 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2161 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2162 return map_nt_error_from_unix(errno);
2165 st = smb_fname.st;
2167 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2168 return NT_STATUS_INVALID_PARAMETER;
2171 *ppdata = (char *)SMB_REALLOC(
2172 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2173 if (*ppdata == NULL) {
2174 return NT_STATUS_NO_MEMORY;
2177 pdata = *ppdata;
2178 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2179 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2181 *fixed_portion = 0;
2183 switch (info_level) {
2184 case SMB_INFO_ALLOCATION:
2186 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2187 data_len = 18;
2188 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2189 &dfree, &dsize);
2190 if (df_ret == (uint64_t)-1) {
2191 return map_nt_error_from_unix(errno);
2194 block_size = lp_block_size(snum);
2195 if (bsize < block_size) {
2196 uint64_t factor = block_size/bsize;
2197 bsize = block_size;
2198 dsize /= factor;
2199 dfree /= factor;
2201 if (bsize > block_size) {
2202 uint64_t factor = bsize/block_size;
2203 bsize = block_size;
2204 dsize *= factor;
2205 dfree *= factor;
2207 sectors_per_unit = bsize/bytes_per_sector;
2209 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2210 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2211 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2214 * For large drives, return max values and not modulo.
2216 dsize = MIN(dsize, UINT32_MAX);
2217 dfree = MIN(dfree, UINT32_MAX);
2219 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2220 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2221 SIVAL(pdata,l1_cUnit,dsize);
2222 SIVAL(pdata,l1_cUnitAvail,dfree);
2223 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2224 break;
2227 case SMB_INFO_VOLUME:
2228 /* Return volume name */
2230 * Add volume serial number - hash of a combination of
2231 * the called hostname and the service name.
2233 serial = generate_volume_serial_number(lp_sub, snum);
2234 SIVAL(pdata,0,serial);
2236 * Win2k3 and previous mess this up by sending a name length
2237 * one byte short. I believe only older clients (OS/2 Win9x) use
2238 * this call so try fixing this by adding a terminating null to
2239 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2241 status = srvstr_push(
2242 pdata, flags2,
2243 pdata+l2_vol_szVolLabel, vname,
2244 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2245 STR_NOALIGN|STR_TERMINATE, &len);
2246 if (!NT_STATUS_IS_OK(status)) {
2247 return status;
2249 SCVAL(pdata,l2_vol_cch,len);
2250 data_len = l2_vol_szVolLabel + len;
2251 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2252 "name = %s serial = 0x%04"PRIx32"\n",
2253 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2254 (unsigned)len, vname, serial));
2255 break;
2257 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2258 case SMB_FS_ATTRIBUTE_INFORMATION:
2260 additional_flags = 0;
2261 #if defined(HAVE_SYS_QUOTAS)
2262 additional_flags |= FILE_VOLUME_QUOTAS;
2263 #endif
2265 if(lp_nt_acl_support(SNUM(conn))) {
2266 additional_flags |= FILE_PERSISTENT_ACLS;
2269 /* Capabilities are filled in at connection time through STATVFS call */
2270 additional_flags |= conn->fs_capabilities;
2271 additional_flags |= lp_parm_int(conn->params->service,
2272 "share", "fake_fscaps",
2275 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2276 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2277 additional_flags); /* FS ATTRIBUTES */
2279 SIVAL(pdata,4,255); /* Max filename component length */
2280 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2281 and will think we can't do long filenames */
2282 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2283 PTR_DIFF(end_data, pdata+12),
2284 STR_UNICODE, &len);
2285 if (!NT_STATUS_IS_OK(status)) {
2286 return status;
2288 SIVAL(pdata,8,len);
2289 data_len = 12 + len;
2290 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2291 /* the client only requested a portion of the
2292 file system name */
2293 data_len = max_data_bytes;
2294 status = STATUS_BUFFER_OVERFLOW;
2296 *fixed_portion = 16;
2297 break;
2299 case SMB_QUERY_FS_LABEL_INFO:
2300 case SMB_FS_LABEL_INFORMATION:
2301 status = srvstr_push(pdata, flags2, pdata+4, vname,
2302 PTR_DIFF(end_data, pdata+4), 0, &len);
2303 if (!NT_STATUS_IS_OK(status)) {
2304 return status;
2306 data_len = 4 + len;
2307 SIVAL(pdata,0,len);
2308 break;
2310 case SMB_QUERY_FS_VOLUME_INFO:
2311 case SMB_FS_VOLUME_INFORMATION:
2312 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2313 pdata, &st.st_ex_btime);
2315 * Add volume serial number - hash of a combination of
2316 * the called hostname and the service name.
2318 serial = generate_volume_serial_number(lp_sub, snum);
2319 SIVAL(pdata,8,serial);
2321 /* Max label len is 32 characters. */
2322 status = srvstr_push(pdata, flags2, pdata+18, vname,
2323 PTR_DIFF(end_data, pdata+18),
2324 STR_UNICODE, &len);
2325 if (!NT_STATUS_IS_OK(status)) {
2326 return status;
2328 SIVAL(pdata,12,len);
2329 data_len = 18+len;
2331 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2332 "namelen = %d, vol=%s serv=%s "
2333 "serial=0x%04"PRIx32"\n",
2334 (int)strlen(vname),vname,
2335 lp_servicename(talloc_tos(), lp_sub, snum),
2336 serial));
2337 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2338 /* the client only requested a portion of the
2339 volume label */
2340 data_len = max_data_bytes;
2341 status = STATUS_BUFFER_OVERFLOW;
2343 *fixed_portion = 24;
2344 break;
2346 case SMB_QUERY_FS_SIZE_INFO:
2347 case SMB_FS_SIZE_INFORMATION:
2349 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2350 data_len = 24;
2351 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2352 &dfree, &dsize);
2353 if (df_ret == (uint64_t)-1) {
2354 return map_nt_error_from_unix(errno);
2356 block_size = lp_block_size(snum);
2357 if (bsize < block_size) {
2358 uint64_t factor = block_size/bsize;
2359 bsize = block_size;
2360 dsize /= factor;
2361 dfree /= factor;
2363 if (bsize > block_size) {
2364 uint64_t factor = bsize/block_size;
2365 bsize = block_size;
2366 dsize *= factor;
2367 dfree *= factor;
2369 sectors_per_unit = bsize/bytes_per_sector;
2370 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2371 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2372 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2373 SBIG_UINT(pdata,0,dsize);
2374 SBIG_UINT(pdata,8,dfree);
2375 SIVAL(pdata,16,sectors_per_unit);
2376 SIVAL(pdata,20,bytes_per_sector);
2377 *fixed_portion = 24;
2378 break;
2381 case SMB_FS_FULL_SIZE_INFORMATION:
2383 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2384 data_len = 32;
2385 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2386 &dfree, &dsize);
2387 if (df_ret == (uint64_t)-1) {
2388 return map_nt_error_from_unix(errno);
2390 block_size = lp_block_size(snum);
2391 if (bsize < block_size) {
2392 uint64_t factor = block_size/bsize;
2393 bsize = block_size;
2394 dsize /= factor;
2395 dfree /= factor;
2397 if (bsize > block_size) {
2398 uint64_t factor = bsize/block_size;
2399 bsize = block_size;
2400 dsize *= factor;
2401 dfree *= factor;
2403 sectors_per_unit = bsize/bytes_per_sector;
2404 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2405 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2406 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2407 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2408 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2409 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2410 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2411 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2412 *fixed_portion = 32;
2413 break;
2416 case SMB_QUERY_FS_DEVICE_INFO:
2417 case SMB_FS_DEVICE_INFORMATION:
2419 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2421 if (!CAN_WRITE(conn)) {
2422 characteristics |= FILE_READ_ONLY_DEVICE;
2424 data_len = 8;
2425 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2426 SIVAL(pdata,4,characteristics);
2427 *fixed_portion = 8;
2428 break;
2431 #ifdef HAVE_SYS_QUOTAS
2432 case SMB_FS_QUOTA_INFORMATION:
2434 * what we have to send --metze:
2436 * Unknown1: 24 NULL bytes
2437 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2438 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2439 * Quota Flags: 2 byte :
2440 * Unknown3: 6 NULL bytes
2442 * 48 bytes total
2444 * details for Quota Flags:
2446 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2447 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2448 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2449 * 0x0001 Enable Quotas: enable quota for this fs
2453 /* we need to fake up a fsp here,
2454 * because its not send in this call
2456 files_struct fsp;
2457 SMB_NTQUOTA_STRUCT quotas;
2459 ZERO_STRUCT(fsp);
2460 ZERO_STRUCT(quotas);
2462 fsp.conn = conn;
2463 fsp.fnum = FNUM_FIELD_INVALID;
2465 /* access check */
2466 if (get_current_uid(conn) != 0) {
2467 DEBUG(0,("get_user_quota: access_denied "
2468 "service [%s] user [%s]\n",
2469 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2470 conn->session_info->unix_info->unix_name));
2471 return NT_STATUS_ACCESS_DENIED;
2474 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
2475 NULL, &quotas);
2476 if (!NT_STATUS_IS_OK(status)) {
2477 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2478 return status;
2481 data_len = 48;
2483 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2484 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2486 /* Unknown1 24 NULL bytes*/
2487 SBIG_UINT(pdata,0,(uint64_t)0);
2488 SBIG_UINT(pdata,8,(uint64_t)0);
2489 SBIG_UINT(pdata,16,(uint64_t)0);
2491 /* Default Soft Quota 8 bytes */
2492 SBIG_UINT(pdata,24,quotas.softlim);
2494 /* Default Hard Quota 8 bytes */
2495 SBIG_UINT(pdata,32,quotas.hardlim);
2497 /* Quota flag 2 bytes */
2498 SSVAL(pdata,40,quotas.qflags);
2500 /* Unknown3 6 NULL bytes */
2501 SSVAL(pdata,42,0);
2502 SIVAL(pdata,44,0);
2504 break;
2506 #endif /* HAVE_SYS_QUOTAS */
2507 case SMB_FS_OBJECTID_INFORMATION:
2509 unsigned char objid[16];
2510 struct smb_extended_info extended_info;
2511 memcpy(pdata,create_volume_objectid(conn, objid),16);
2512 samba_extended_info_version (&extended_info);
2513 SIVAL(pdata,16,extended_info.samba_magic);
2514 SIVAL(pdata,20,extended_info.samba_version);
2515 SIVAL(pdata,24,extended_info.samba_subversion);
2516 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2517 memcpy(pdata+36,extended_info.samba_version_string,28);
2518 data_len = 64;
2519 break;
2522 case SMB_FS_SECTOR_SIZE_INFORMATION:
2524 data_len = 28;
2526 * These values match a physical Windows Server 2012
2527 * share backed by NTFS atop spinning rust.
2529 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2530 /* logical_bytes_per_sector */
2531 SIVAL(pdata, 0, bytes_per_sector);
2532 /* phys_bytes_per_sector_atomic */
2533 SIVAL(pdata, 4, bytes_per_sector);
2534 /* phys_bytes_per_sector_perf */
2535 SIVAL(pdata, 8, bytes_per_sector);
2536 /* fs_effective_phys_bytes_per_sector_atomic */
2537 SIVAL(pdata, 12, bytes_per_sector);
2538 /* flags */
2539 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2540 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2541 /* byte_off_sector_align */
2542 SIVAL(pdata, 20, 0);
2543 /* byte_off_partition_align */
2544 SIVAL(pdata, 24, 0);
2545 *fixed_portion = 28;
2546 break;
2550 #if defined(WITH_SMB1SERVER)
2552 * Query the version and capabilities of the CIFS UNIX extensions
2553 * in use.
2556 case SMB_QUERY_CIFS_UNIX_INFO:
2558 bool large_write = lp_min_receive_file_size() &&
2559 !smb1_srv_is_signing_active(xconn);
2560 bool large_read = !smb1_srv_is_signing_active(xconn);
2561 int encrypt_caps = 0;
2563 if (!lp_smb1_unix_extensions()) {
2564 return NT_STATUS_INVALID_LEVEL;
2567 switch (conn->encrypt_level) {
2568 case SMB_SIGNING_OFF:
2569 encrypt_caps = 0;
2570 break;
2571 case SMB_SIGNING_DESIRED:
2572 case SMB_SIGNING_IF_REQUIRED:
2573 case SMB_SIGNING_DEFAULT:
2574 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2575 break;
2576 case SMB_SIGNING_REQUIRED:
2577 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2578 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2579 large_write = false;
2580 large_read = false;
2581 break;
2584 data_len = 12;
2585 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2586 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2588 /* We have POSIX ACLs, pathname, encryption,
2589 * large read/write, and locking capability. */
2591 SBIG_UINT(pdata,4,((uint64_t)(
2592 CIFS_UNIX_POSIX_ACLS_CAP|
2593 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2594 CIFS_UNIX_FCNTL_LOCKS_CAP|
2595 CIFS_UNIX_EXTATTR_CAP|
2596 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2597 encrypt_caps|
2598 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2599 (large_write ?
2600 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2601 break;
2603 #endif
2605 case SMB_QUERY_POSIX_FS_INFO:
2606 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2608 int rc;
2609 struct vfs_statvfs_struct svfs;
2611 if (!fsinfo_unix_valid_level(conn, info_level)) {
2612 return NT_STATUS_INVALID_LEVEL;
2615 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2617 if (!rc) {
2618 data_len = 56;
2619 SIVAL(pdata,0,svfs.OptimalTransferSize);
2620 SIVAL(pdata,4,svfs.BlockSize);
2621 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2622 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2623 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2624 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2625 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2626 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2627 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2628 #ifdef EOPNOTSUPP
2629 } else if (rc == EOPNOTSUPP) {
2630 return NT_STATUS_INVALID_LEVEL;
2631 #endif /* EOPNOTSUPP */
2632 } else {
2633 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2634 return NT_STATUS_DOS(ERRSRV, ERRerror);
2636 break;
2639 case SMB_QUERY_POSIX_WHOAMI:
2641 uint32_t flags = 0;
2642 uint32_t sid_bytes;
2643 uint32_t i;
2645 if (!lp_smb1_unix_extensions()) {
2646 return NT_STATUS_INVALID_LEVEL;
2649 if (max_data_bytes < 40) {
2650 return NT_STATUS_BUFFER_TOO_SMALL;
2653 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2654 flags |= SMB_WHOAMI_GUEST;
2657 /* NOTE: 8 bytes for UID/GID, irrespective of native
2658 * platform size. This matches
2659 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2661 data_len = 4 /* flags */
2662 + 4 /* flag mask */
2663 + 8 /* uid */
2664 + 8 /* gid */
2665 + 4 /* ngroups */
2666 + 4 /* num_sids */
2667 + 4 /* SID bytes */
2668 + 4 /* pad/reserved */
2669 + (conn->session_info->unix_token->ngroups * 8)
2670 /* groups list */
2671 + (conn->session_info->security_token->num_sids *
2672 SID_MAX_SIZE)
2673 /* SID list */;
2675 SIVAL(pdata, 0, flags);
2676 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2677 SBIG_UINT(pdata, 8,
2678 (uint64_t)conn->session_info->unix_token->uid);
2679 SBIG_UINT(pdata, 16,
2680 (uint64_t)conn->session_info->unix_token->gid);
2683 if (data_len >= max_data_bytes) {
2684 /* Potential overflow, skip the GIDs and SIDs. */
2686 SIVAL(pdata, 24, 0); /* num_groups */
2687 SIVAL(pdata, 28, 0); /* num_sids */
2688 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2689 SIVAL(pdata, 36, 0); /* reserved */
2691 data_len = 40;
2692 break;
2695 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2696 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2698 /* We walk the SID list twice, but this call is fairly
2699 * infrequent, and I don't expect that it's performance
2700 * sensitive -- jpeach
2702 for (i = 0, sid_bytes = 0;
2703 i < conn->session_info->security_token->num_sids; ++i) {
2704 sid_bytes += ndr_size_dom_sid(
2705 &conn->session_info->security_token->sids[i],
2709 /* SID list byte count */
2710 SIVAL(pdata, 32, sid_bytes);
2712 /* 4 bytes pad/reserved - must be zero */
2713 SIVAL(pdata, 36, 0);
2714 data_len = 40;
2716 /* GID list */
2717 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2718 SBIG_UINT(pdata, data_len,
2719 (uint64_t)conn->session_info->unix_token->groups[i]);
2720 data_len += 8;
2723 /* SID list */
2724 for (i = 0;
2725 i < conn->session_info->security_token->num_sids; ++i) {
2726 int sid_len = ndr_size_dom_sid(
2727 &conn->session_info->security_token->sids[i],
2730 sid_linearize((uint8_t *)(pdata + data_len),
2731 sid_len,
2732 &conn->session_info->security_token->sids[i]);
2733 data_len += sid_len;
2736 break;
2739 case SMB_MAC_QUERY_FS_INFO:
2741 * Thursby MAC extension... ONLY on NTFS filesystems
2742 * once we do streams then we don't need this
2744 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2745 data_len = 88;
2746 SIVAL(pdata,84,0x100); /* Don't support mac... */
2747 break;
2750 FALL_THROUGH;
2751 default:
2752 return NT_STATUS_INVALID_LEVEL;
2755 *ret_data_len = data_len;
2756 return status;
2759 NTSTATUS smb_set_fsquota(connection_struct *conn,
2760 struct smb_request *req,
2761 files_struct *fsp,
2762 const DATA_BLOB *qdata)
2764 const struct loadparm_substitution *lp_sub =
2765 loadparm_s3_global_substitution();
2766 NTSTATUS status;
2767 SMB_NTQUOTA_STRUCT quotas;
2769 ZERO_STRUCT(quotas);
2771 /* access check */
2772 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2773 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
2774 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2775 conn->session_info->unix_info->unix_name));
2776 return NT_STATUS_ACCESS_DENIED;
2779 if (!check_fsp_ntquota_handle(conn, req,
2780 fsp)) {
2781 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
2782 return NT_STATUS_INVALID_HANDLE;
2785 /* note: normally there're 48 bytes,
2786 * but we didn't use the last 6 bytes for now
2787 * --metze
2789 if (qdata->length < 42) {
2790 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
2791 (unsigned int)qdata->length));
2792 return NT_STATUS_INVALID_PARAMETER;
2795 /* unknown_1 24 NULL bytes in pdata*/
2797 /* the soft quotas 8 bytes (uint64_t)*/
2798 quotas.softlim = BVAL(qdata->data,24);
2800 /* the hard quotas 8 bytes (uint64_t)*/
2801 quotas.hardlim = BVAL(qdata->data,32);
2803 /* quota_flags 2 bytes **/
2804 quotas.qflags = SVAL(qdata->data,40);
2806 /* unknown_2 6 NULL bytes follow*/
2808 /* now set the quotas */
2809 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2810 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
2811 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2812 status = map_nt_error_from_unix(errno);
2813 } else {
2814 status = NT_STATUS_OK;
2816 return status;
2819 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2820 struct smb_request *req,
2821 TALLOC_CTX *mem_ctx,
2822 uint16_t info_level,
2823 files_struct *fsp,
2824 const DATA_BLOB *pdata)
2826 switch (info_level) {
2827 case SMB_FS_QUOTA_INFORMATION:
2829 return smb_set_fsquota(conn,
2830 req,
2831 fsp,
2832 pdata);
2835 default:
2836 break;
2838 return NT_STATUS_INVALID_LEVEL;
2841 /****************************************************************************
2842 Store the FILE_UNIX_BASIC info.
2843 ****************************************************************************/
2845 char *store_file_unix_basic(connection_struct *conn,
2846 char *pdata,
2847 files_struct *fsp,
2848 const SMB_STRUCT_STAT *psbuf)
2850 dev_t devno;
2852 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2853 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
2855 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2856 pdata += 8;
2858 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2859 pdata += 8;
2861 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2862 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2863 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2864 pdata += 24;
2866 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2867 SIVAL(pdata,4,0);
2868 pdata += 8;
2870 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2871 SIVAL(pdata,4,0);
2872 pdata += 8;
2874 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2875 pdata += 4;
2877 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2878 devno = psbuf->st_ex_rdev;
2879 } else {
2880 devno = psbuf->st_ex_dev;
2883 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2884 SIVAL(pdata,4,0);
2885 pdata += 8;
2887 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2888 SIVAL(pdata,4,0);
2889 pdata += 8;
2891 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2892 pdata += 8;
2894 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2895 SIVAL(pdata,4,0);
2896 pdata += 8;
2898 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2899 SIVAL(pdata,4,0);
2900 pdata += 8;
2902 return pdata;
2905 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2906 * the chflags(2) (or equivalent) flags.
2908 * XXX: this really should be behind the VFS interface. To do this, we would
2909 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2910 * Each VFS module could then implement its own mapping as appropriate for the
2911 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2913 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2914 info2_flags_map[] =
2916 #ifdef UF_NODUMP
2917 { UF_NODUMP, EXT_DO_NOT_BACKUP },
2918 #endif
2920 #ifdef UF_IMMUTABLE
2921 { UF_IMMUTABLE, EXT_IMMUTABLE },
2922 #endif
2924 #ifdef UF_APPEND
2925 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2926 #endif
2928 #ifdef UF_HIDDEN
2929 { UF_HIDDEN, EXT_HIDDEN },
2930 #endif
2932 /* Do not remove. We need to guarantee that this array has at least one
2933 * entry to build on HP-UX.
2935 { 0, 0 }
2939 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2940 uint32_t *smb_fflags, uint32_t *smb_fmask)
2942 size_t i;
2944 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2945 *smb_fmask |= info2_flags_map[i].smb_fflag;
2946 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2947 *smb_fflags |= info2_flags_map[i].smb_fflag;
2952 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2953 const uint32_t smb_fflags,
2954 const uint32_t smb_fmask,
2955 int *stat_fflags)
2957 uint32_t max_fmask = 0;
2958 size_t i;
2960 *stat_fflags = psbuf->st_ex_flags;
2962 /* For each flags requested in smb_fmask, check the state of the
2963 * corresponding flag in smb_fflags and set or clear the matching
2964 * stat flag.
2967 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2968 max_fmask |= info2_flags_map[i].smb_fflag;
2969 if (smb_fmask & info2_flags_map[i].smb_fflag) {
2970 if (smb_fflags & info2_flags_map[i].smb_fflag) {
2971 *stat_fflags |= info2_flags_map[i].stat_fflag;
2972 } else {
2973 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2978 /* If smb_fmask is asking to set any bits that are not supported by
2979 * our flag mappings, we should fail.
2981 if ((smb_fmask & max_fmask) != smb_fmask) {
2982 return False;
2985 return True;
2989 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2990 * of file flags and birth (create) time.
2992 char *store_file_unix_basic_info2(connection_struct *conn,
2993 char *pdata,
2994 files_struct *fsp,
2995 const SMB_STRUCT_STAT *psbuf)
2997 uint32_t file_flags = 0;
2998 uint32_t flags_mask = 0;
3000 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3002 /* Create (birth) time 64 bit */
3003 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
3004 pdata += 8;
3006 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3007 SIVAL(pdata, 0, file_flags); /* flags */
3008 SIVAL(pdata, 4, flags_mask); /* mask */
3009 pdata += 8;
3011 return pdata;
3014 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3015 const struct stream_struct *streams,
3016 char *data,
3017 unsigned int max_data_bytes,
3018 unsigned int *data_size)
3020 unsigned int i;
3021 unsigned int ofs = 0;
3023 if (max_data_bytes < 32) {
3024 return NT_STATUS_INFO_LENGTH_MISMATCH;
3027 for (i = 0; i < num_streams; i++) {
3028 unsigned int next_offset;
3029 size_t namelen;
3030 smb_ucs2_t *namebuf;
3032 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3033 streams[i].name, &namelen) ||
3034 namelen <= 2)
3036 return NT_STATUS_INVALID_PARAMETER;
3040 * name_buf is now null-terminated, we need to marshall as not
3041 * terminated
3044 namelen -= 2;
3047 * We cannot overflow ...
3049 if ((ofs + 24 + namelen) > max_data_bytes) {
3050 DEBUG(10, ("refusing to overflow reply at stream %u\n",
3051 i));
3052 TALLOC_FREE(namebuf);
3053 return STATUS_BUFFER_OVERFLOW;
3056 SIVAL(data, ofs+4, namelen);
3057 SOFF_T(data, ofs+8, streams[i].size);
3058 SOFF_T(data, ofs+16, streams[i].alloc_size);
3059 memcpy(data+ofs+24, namebuf, namelen);
3060 TALLOC_FREE(namebuf);
3062 next_offset = ofs + 24 + namelen;
3064 if (i == num_streams-1) {
3065 SIVAL(data, ofs, 0);
3067 else {
3068 unsigned int align = ndr_align_size(next_offset, 8);
3070 if ((next_offset + align) > max_data_bytes) {
3071 DEBUG(10, ("refusing to overflow align "
3072 "reply at stream %u\n",
3073 i));
3074 TALLOC_FREE(namebuf);
3075 return STATUS_BUFFER_OVERFLOW;
3078 memset(data+next_offset, 0, align);
3079 next_offset += align;
3081 SIVAL(data, ofs, next_offset - ofs);
3082 ofs = next_offset;
3085 ofs = next_offset;
3088 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
3090 *data_size = ofs;
3092 return NT_STATUS_OK;
3095 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3096 TALLOC_CTX *mem_ctx,
3097 struct smb_request *req,
3098 uint16_t info_level,
3099 files_struct *fsp,
3100 struct smb_filename *smb_fname,
3101 bool delete_pending,
3102 struct timespec write_time_ts,
3103 struct ea_list *ea_list,
3104 uint16_t flags2,
3105 unsigned int max_data_bytes,
3106 size_t *fixed_portion,
3107 char **ppdata,
3108 unsigned int *pdata_size)
3110 char *pdata = *ppdata;
3111 char *dstart, *dend;
3112 unsigned int data_size;
3113 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
3114 time_t create_time, mtime, atime, c_time;
3115 SMB_STRUCT_STAT *psbuf = NULL;
3116 SMB_STRUCT_STAT *base_sp = NULL;
3117 char *p;
3118 char *base_name;
3119 char *dos_fname;
3120 int mode;
3121 int nlink;
3122 NTSTATUS status;
3123 uint64_t file_size = 0;
3124 uint64_t pos = 0;
3125 uint64_t allocation_size = 0;
3126 uint64_t file_id = 0;
3127 uint32_t access_mask = 0;
3128 size_t len = 0;
3130 if (INFO_LEVEL_IS_UNIX(info_level)) {
3131 bool ok = false;
3133 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3134 DBG_DEBUG("SMB1 unix extensions activated\n");
3135 ok = true;
3138 if (lp_smb3_unix_extensions() &&
3139 (fsp != NULL) &&
3140 (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3141 DBG_DEBUG("SMB2 posix open\n");
3142 ok = true;
3145 if (!ok) {
3146 return NT_STATUS_INVALID_LEVEL;
3150 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3151 smb_fname_str_dbg(smb_fname),
3152 fsp_fnum_dbg(fsp),
3153 info_level, max_data_bytes));
3156 * In case of querying a symlink in POSIX context,
3157 * fsp will be NULL. fdos_mode() deals with it.
3159 if (fsp != NULL) {
3160 smb_fname = fsp->fsp_name;
3162 mode = fdos_mode(fsp);
3163 psbuf = &smb_fname->st;
3165 if (fsp != NULL) {
3166 base_sp = fsp->base_fsp ?
3167 &fsp->base_fsp->fsp_name->st :
3168 &fsp->fsp_name->st;
3169 } else {
3170 base_sp = &smb_fname->st;
3173 nlink = psbuf->st_ex_nlink;
3175 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3176 nlink = 1;
3179 if ((nlink > 0) && delete_pending) {
3180 nlink -= 1;
3183 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3184 return NT_STATUS_INVALID_PARAMETER;
3187 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3188 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3189 if (*ppdata == NULL) {
3190 return NT_STATUS_NO_MEMORY;
3192 pdata = *ppdata;
3193 dstart = pdata;
3194 dend = dstart + data_size - 1;
3196 if (!is_omit_timespec(&write_time_ts) &&
3197 !INFO_LEVEL_IS_UNIX(info_level))
3199 update_stat_ex_mtime(psbuf, write_time_ts);
3202 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3203 mtime_ts = psbuf->st_ex_mtime;
3204 atime_ts = psbuf->st_ex_atime;
3205 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3207 if (lp_dos_filetime_resolution(SNUM(conn))) {
3208 dos_filetime_timespec(&create_time_ts);
3209 dos_filetime_timespec(&mtime_ts);
3210 dos_filetime_timespec(&atime_ts);
3211 dos_filetime_timespec(&ctime_ts);
3214 create_time = convert_timespec_to_time_t(create_time_ts);
3215 mtime = convert_timespec_to_time_t(mtime_ts);
3216 atime = convert_timespec_to_time_t(atime_ts);
3217 c_time = convert_timespec_to_time_t(ctime_ts);
3219 p = strrchr_m(smb_fname->base_name,'/');
3220 if (!p)
3221 base_name = smb_fname->base_name;
3222 else
3223 base_name = p+1;
3225 /* NT expects the name to be in an exact form of the *full*
3226 filename. See the trans2 torture test */
3227 if (ISDOT(base_name)) {
3228 dos_fname = talloc_strdup(mem_ctx, "\\");
3229 if (!dos_fname) {
3230 return NT_STATUS_NO_MEMORY;
3232 } else {
3233 dos_fname = talloc_asprintf(mem_ctx,
3234 "\\%s",
3235 smb_fname->base_name);
3236 if (!dos_fname) {
3237 return NT_STATUS_NO_MEMORY;
3239 if (is_named_stream(smb_fname)) {
3240 dos_fname = talloc_asprintf(dos_fname, "%s",
3241 smb_fname->stream_name);
3242 if (!dos_fname) {
3243 return NT_STATUS_NO_MEMORY;
3247 string_replace(dos_fname, '/', '\\');
3250 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3252 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3253 /* Do we have this path open ? */
3254 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3255 files_struct *fsp1 = file_find_di_first(
3256 conn->sconn, fileid, true);
3257 if (fsp1 && fsp1->initial_allocation_size) {
3258 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3262 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3263 file_size = get_file_size_stat(psbuf);
3266 if (fsp) {
3267 pos = fh_get_position_information(fsp->fh);
3270 if (fsp) {
3271 access_mask = fsp->access_mask;
3272 } else {
3273 /* GENERIC_EXECUTE mapping from Windows */
3274 access_mask = 0x12019F;
3277 /* This should be an index number - looks like
3278 dev/ino to me :-)
3280 I think this causes us to fail the IFSKIT
3281 BasicFileInformationTest. -tpot */
3282 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3284 *fixed_portion = 0;
3286 switch (info_level) {
3287 case SMB_INFO_STANDARD:
3288 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3289 data_size = 22;
3290 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3291 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3292 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3293 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3294 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3295 SSVAL(pdata,l1_attrFile,mode);
3296 break;
3298 case SMB_INFO_QUERY_EA_SIZE:
3300 unsigned int ea_size =
3301 estimate_ea_size(smb_fname->fsp);
3302 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3303 data_size = 26;
3304 srv_put_dos_date2(pdata,0,create_time);
3305 srv_put_dos_date2(pdata,4,atime);
3306 srv_put_dos_date2(pdata,8,mtime); /* write time */
3307 SIVAL(pdata,12,(uint32_t)file_size);
3308 SIVAL(pdata,16,(uint32_t)allocation_size);
3309 SSVAL(pdata,20,mode);
3310 SIVAL(pdata,22,ea_size);
3311 break;
3314 case SMB_INFO_IS_NAME_VALID:
3315 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3316 if (fsp) {
3317 /* os/2 needs this ? really ?*/
3318 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3320 /* This is only reached for qpathinfo */
3321 data_size = 0;
3322 break;
3324 case SMB_INFO_QUERY_EAS_FROM_LIST:
3326 size_t total_ea_len = 0;
3327 struct ea_list *ea_file_list = NULL;
3328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3330 status =
3331 get_ea_list_from_fsp(mem_ctx,
3332 smb_fname->fsp,
3333 &total_ea_len, &ea_file_list);
3334 if (!NT_STATUS_IS_OK(status)) {
3335 return status;
3338 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3340 if (!ea_list || (total_ea_len > data_size)) {
3341 data_size = 4;
3342 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3343 break;
3346 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3347 break;
3350 case SMB_INFO_QUERY_ALL_EAS:
3352 /* We have data_size bytes to put EA's into. */
3353 size_t total_ea_len = 0;
3354 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3356 status = get_ea_list_from_fsp(mem_ctx,
3357 smb_fname->fsp,
3358 &total_ea_len, &ea_list);
3359 if (!NT_STATUS_IS_OK(status)) {
3360 return status;
3363 if (!ea_list || (total_ea_len > data_size)) {
3364 data_size = 4;
3365 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3366 break;
3369 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3370 break;
3373 case SMB2_FILE_FULL_EA_INFORMATION:
3375 /* We have data_size bytes to put EA's into. */
3376 size_t total_ea_len = 0;
3377 struct ea_list *ea_file_list = NULL;
3379 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3381 /*TODO: add filtering and index handling */
3383 status =
3384 get_ea_list_from_fsp(mem_ctx,
3385 smb_fname->fsp,
3386 &total_ea_len, &ea_file_list);
3387 if (!NT_STATUS_IS_OK(status)) {
3388 return status;
3390 if (!ea_file_list) {
3391 return NT_STATUS_NO_EAS_ON_FILE;
3394 status = fill_ea_chained_buffer(mem_ctx,
3395 pdata,
3396 data_size,
3397 &data_size,
3398 conn, ea_file_list);
3399 if (!NT_STATUS_IS_OK(status)) {
3400 return status;
3402 break;
3405 case SMB_FILE_BASIC_INFORMATION:
3406 case SMB_QUERY_FILE_BASIC_INFO:
3408 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3409 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3410 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3411 } else {
3412 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3413 data_size = 40;
3414 SIVAL(pdata,36,0);
3416 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3417 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3418 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3419 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3420 SIVAL(pdata,32,mode);
3422 DEBUG(5,("SMB_QFBI - "));
3423 DEBUG(5,("create: %s ", ctime(&create_time)));
3424 DEBUG(5,("access: %s ", ctime(&atime)));
3425 DEBUG(5,("write: %s ", ctime(&mtime)));
3426 DEBUG(5,("change: %s ", ctime(&c_time)));
3427 DEBUG(5,("mode: %x\n", mode));
3428 *fixed_portion = data_size;
3429 break;
3431 case SMB_FILE_STANDARD_INFORMATION:
3432 case SMB_QUERY_FILE_STANDARD_INFO:
3434 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3435 data_size = 24;
3436 SOFF_T(pdata,0,allocation_size);
3437 SOFF_T(pdata,8,file_size);
3438 SIVAL(pdata,16,nlink);
3439 SCVAL(pdata,20,delete_pending?1:0);
3440 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3441 SSVAL(pdata,22,0); /* Padding. */
3442 *fixed_portion = 24;
3443 break;
3445 case SMB_FILE_EA_INFORMATION:
3446 case SMB_QUERY_FILE_EA_INFO:
3448 unsigned int ea_size =
3449 estimate_ea_size(smb_fname->fsp);
3450 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3451 data_size = 4;
3452 *fixed_portion = 4;
3453 SIVAL(pdata,0,ea_size);
3454 break;
3457 /* Get the 8.3 name - used if NT SMB was negotiated. */
3458 case SMB_QUERY_FILE_ALT_NAME_INFO:
3459 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3461 char mangled_name[13];
3462 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3463 if (!name_to_8_3(base_name,mangled_name,
3464 True,conn->params)) {
3465 return NT_STATUS_NO_MEMORY;
3467 status = srvstr_push(dstart, flags2,
3468 pdata+4, mangled_name,
3469 PTR_DIFF(dend, pdata+4),
3470 STR_UNICODE, &len);
3471 if (!NT_STATUS_IS_OK(status)) {
3472 return status;
3474 data_size = 4 + len;
3475 SIVAL(pdata,0,len);
3476 *fixed_portion = 8;
3477 break;
3480 case SMB_QUERY_FILE_NAME_INFO:
3483 this must be *exactly* right for ACLs on mapped drives to work
3485 status = srvstr_push(dstart, flags2,
3486 pdata+4, dos_fname,
3487 PTR_DIFF(dend, pdata+4),
3488 STR_UNICODE, &len);
3489 if (!NT_STATUS_IS_OK(status)) {
3490 return status;
3492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3493 data_size = 4 + len;
3494 SIVAL(pdata,0,len);
3495 break;
3498 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3500 char *nfname = NULL;
3502 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
3503 return NT_STATUS_INVALID_LEVEL;
3506 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3507 if (nfname == NULL) {
3508 return NT_STATUS_NO_MEMORY;
3511 if (ISDOT(nfname)) {
3512 nfname[0] = '\0';
3514 string_replace(nfname, '/', '\\');
3516 if (fsp_is_alternate_stream(fsp)) {
3517 const char *s = smb_fname->stream_name;
3518 const char *e = NULL;
3519 size_t n;
3521 SMB_ASSERT(s[0] != '\0');
3524 * smb_fname->stream_name is in form
3525 * of ':StrEam:$DATA', but we should only
3526 * append ':StrEam' here.
3529 e = strchr(&s[1], ':');
3530 if (e == NULL) {
3531 n = strlen(s);
3532 } else {
3533 n = PTR_DIFF(e, s);
3535 nfname = talloc_strndup_append(nfname, s, n);
3536 if (nfname == NULL) {
3537 return NT_STATUS_NO_MEMORY;
3541 status = srvstr_push(dstart, flags2,
3542 pdata+4, nfname,
3543 PTR_DIFF(dend, pdata+4),
3544 STR_UNICODE, &len);
3545 if (!NT_STATUS_IS_OK(status)) {
3546 return status;
3548 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3549 data_size = 4 + len;
3550 SIVAL(pdata,0,len);
3551 *fixed_portion = 8;
3552 break;
3555 case SMB_FILE_ALLOCATION_INFORMATION:
3556 case SMB_QUERY_FILE_ALLOCATION_INFO:
3557 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3558 data_size = 8;
3559 SOFF_T(pdata,0,allocation_size);
3560 break;
3562 case SMB_FILE_END_OF_FILE_INFORMATION:
3563 case SMB_QUERY_FILE_END_OF_FILEINFO:
3564 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3565 data_size = 8;
3566 SOFF_T(pdata,0,file_size);
3567 break;
3569 case SMB_QUERY_FILE_ALL_INFO:
3570 case SMB_FILE_ALL_INFORMATION:
3572 unsigned int ea_size =
3573 estimate_ea_size(smb_fname->fsp);
3574 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3575 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3576 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3577 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3578 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3579 SIVAL(pdata,32,mode);
3580 SIVAL(pdata,36,0); /* padding. */
3581 pdata += 40;
3582 SOFF_T(pdata,0,allocation_size);
3583 SOFF_T(pdata,8,file_size);
3584 SIVAL(pdata,16,nlink);
3585 SCVAL(pdata,20,delete_pending);
3586 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3587 SSVAL(pdata,22,0);
3588 pdata += 24;
3589 SIVAL(pdata,0,ea_size);
3590 pdata += 4; /* EA info */
3591 status = srvstr_push(dstart, flags2,
3592 pdata+4, dos_fname,
3593 PTR_DIFF(dend, pdata+4),
3594 STR_UNICODE, &len);
3595 if (!NT_STATUS_IS_OK(status)) {
3596 return status;
3598 SIVAL(pdata,0,len);
3599 pdata += 4 + len;
3600 data_size = PTR_DIFF(pdata,(*ppdata));
3601 *fixed_portion = 10;
3602 break;
3605 case SMB2_FILE_ALL_INFORMATION:
3607 unsigned int ea_size =
3608 estimate_ea_size(smb_fname->fsp);
3609 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3610 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3611 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3612 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3613 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3614 SIVAL(pdata, 0x20, mode);
3615 SIVAL(pdata, 0x24, 0); /* padding. */
3616 SBVAL(pdata, 0x28, allocation_size);
3617 SBVAL(pdata, 0x30, file_size);
3618 SIVAL(pdata, 0x38, nlink);
3619 SCVAL(pdata, 0x3C, delete_pending);
3620 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3621 SSVAL(pdata, 0x3E, 0); /* padding */
3622 SBVAL(pdata, 0x40, file_id);
3623 SIVAL(pdata, 0x48, ea_size);
3624 SIVAL(pdata, 0x4C, access_mask);
3625 SBVAL(pdata, 0x50, pos);
3626 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3627 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3629 pdata += 0x60;
3631 status = srvstr_push(dstart, flags2,
3632 pdata+4, dos_fname,
3633 PTR_DIFF(dend, pdata+4),
3634 STR_UNICODE, &len);
3635 if (!NT_STATUS_IS_OK(status)) {
3636 return status;
3638 SIVAL(pdata,0,len);
3639 pdata += 4 + len;
3640 data_size = PTR_DIFF(pdata,(*ppdata));
3641 *fixed_portion = 104;
3642 break;
3644 case SMB_FILE_INTERNAL_INFORMATION:
3646 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3647 SBVAL(pdata, 0, file_id);
3648 data_size = 8;
3649 *fixed_portion = 8;
3650 break;
3652 case SMB_FILE_ACCESS_INFORMATION:
3653 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3654 SIVAL(pdata, 0, access_mask);
3655 data_size = 4;
3656 *fixed_portion = 4;
3657 break;
3659 case SMB_FILE_NAME_INFORMATION:
3660 /* Pathname with leading '\'. */
3662 size_t byte_len;
3663 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3665 SIVAL(pdata,0,byte_len);
3666 data_size = 4 + byte_len;
3667 break;
3670 case SMB_FILE_DISPOSITION_INFORMATION:
3671 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3672 data_size = 1;
3673 SCVAL(pdata,0,delete_pending);
3674 *fixed_portion = 1;
3675 break;
3677 case SMB_FILE_POSITION_INFORMATION:
3678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3679 data_size = 8;
3680 SOFF_T(pdata,0,pos);
3681 *fixed_portion = 8;
3682 break;
3684 case SMB_FILE_MODE_INFORMATION:
3685 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3686 SIVAL(pdata,0,mode);
3687 data_size = 4;
3688 *fixed_portion = 4;
3689 break;
3691 case SMB_FILE_ALIGNMENT_INFORMATION:
3692 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3693 SIVAL(pdata,0,0); /* No alignment needed. */
3694 data_size = 4;
3695 *fixed_portion = 4;
3696 break;
3699 * NT4 server just returns "invalid query" to this - if we try
3700 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3701 * want this. JRA.
3703 /* The first statement above is false - verified using Thursby
3704 * client against NT4 -- gcolley.
3706 case SMB_QUERY_FILE_STREAM_INFO:
3707 case SMB_FILE_STREAM_INFORMATION: {
3708 unsigned int num_streams = 0;
3709 struct stream_struct *streams = NULL;
3711 DEBUG(10,("smbd_do_qfilepathinfo: "
3712 "SMB_FILE_STREAM_INFORMATION\n"));
3714 if (is_ntfs_stream_smb_fname(smb_fname)) {
3715 return NT_STATUS_INVALID_PARAMETER;
3718 status = vfs_fstreaminfo(fsp,
3719 mem_ctx,
3720 &num_streams,
3721 &streams);
3723 if (!NT_STATUS_IS_OK(status)) {
3724 DEBUG(10, ("could not get stream info: %s\n",
3725 nt_errstr(status)));
3726 return status;
3729 status = marshall_stream_info(num_streams, streams,
3730 pdata, max_data_bytes,
3731 &data_size);
3733 if (!NT_STATUS_IS_OK(status)) {
3734 DEBUG(10, ("marshall_stream_info failed: %s\n",
3735 nt_errstr(status)));
3736 TALLOC_FREE(streams);
3737 return status;
3740 TALLOC_FREE(streams);
3742 *fixed_portion = 32;
3744 break;
3746 case SMB_QUERY_COMPRESSION_INFO:
3747 case SMB_FILE_COMPRESSION_INFORMATION:
3748 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3749 SOFF_T(pdata,0,file_size);
3750 SIVAL(pdata,8,0); /* ??? */
3751 SIVAL(pdata,12,0); /* ??? */
3752 data_size = 16;
3753 *fixed_portion = 16;
3754 break;
3756 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3757 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3758 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3759 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3760 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3761 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3762 SOFF_T(pdata,32,allocation_size);
3763 SOFF_T(pdata,40,file_size);
3764 SIVAL(pdata,48,mode);
3765 SIVAL(pdata,52,0); /* ??? */
3766 data_size = 56;
3767 *fixed_portion = 56;
3768 break;
3770 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3771 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3772 SIVAL(pdata,0,mode);
3773 SIVAL(pdata,4,0);
3774 data_size = 8;
3775 *fixed_portion = 8;
3776 break;
3779 * SMB2 UNIX Extensions.
3781 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3783 uint8_t *buf = NULL;
3784 ssize_t plen = 0;
3786 if (!(conn->sconn->using_smb2)) {
3787 return NT_STATUS_INVALID_LEVEL;
3789 if (!lp_smb3_unix_extensions()) {
3790 return NT_STATUS_INVALID_LEVEL;
3792 if (fsp == NULL) {
3793 return NT_STATUS_INVALID_HANDLE;
3795 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3796 return NT_STATUS_INVALID_LEVEL;
3799 /* Determine the size of the posix info context */
3800 plen = store_smb2_posix_info(conn,
3801 &smb_fname->st,
3803 mode,
3804 NULL,
3806 if (plen == -1 || data_size < plen) {
3807 return NT_STATUS_INVALID_PARAMETER;
3809 buf = talloc_zero_size(mem_ctx, plen);
3810 if (buf == NULL) {
3811 return NT_STATUS_NO_MEMORY;
3814 /* Store the context in buf */
3815 store_smb2_posix_info(conn,
3816 &smb_fname->st,
3818 mode,
3819 buf,
3820 plen);
3821 memcpy(pdata, buf, plen);
3822 data_size = plen;
3823 break;
3826 default:
3827 return NT_STATUS_INVALID_LEVEL;
3830 *pdata_size = data_size;
3831 return NT_STATUS_OK;
3834 /****************************************************************************
3835 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3836 code.
3837 ****************************************************************************/
3839 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3840 connection_struct *conn,
3841 struct smb_request *req,
3842 bool overwrite_if_exists,
3843 struct files_struct *old_dirfsp,
3844 const struct smb_filename *smb_fname_old,
3845 struct files_struct *new_dirfsp,
3846 struct smb_filename *smb_fname_new)
3848 NTSTATUS status = NT_STATUS_OK;
3849 int ret;
3850 bool ok;
3851 struct smb_filename *parent_fname_old = NULL;
3852 struct smb_filename *base_name_old = NULL;
3853 struct smb_filename *parent_fname_new = NULL;
3854 struct smb_filename *base_name_new = NULL;
3856 /* source must already exist. */
3857 if (!VALID_STAT(smb_fname_old->st)) {
3858 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3859 goto out;
3862 /* No links from a directory. */
3863 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3864 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3865 goto out;
3868 /* Setting a hardlink to/from a stream isn't currently supported. */
3869 ok = is_ntfs_stream_smb_fname(smb_fname_old);
3870 if (ok) {
3871 DBG_DEBUG("Old name has streams\n");
3872 status = NT_STATUS_INVALID_PARAMETER;
3873 goto out;
3875 ok = is_ntfs_stream_smb_fname(smb_fname_new);
3876 if (ok) {
3877 DBG_DEBUG("New name has streams\n");
3878 status = NT_STATUS_INVALID_PARAMETER;
3879 goto out;
3882 status = parent_pathref(talloc_tos(),
3883 conn->cwd_fsp,
3884 smb_fname_old,
3885 &parent_fname_old,
3886 &base_name_old);
3887 if (!NT_STATUS_IS_OK(status)) {
3888 goto out;
3891 status = parent_pathref(talloc_tos(),
3892 conn->cwd_fsp,
3893 smb_fname_new,
3894 &parent_fname_new,
3895 &base_name_new);
3896 if (!NT_STATUS_IS_OK(status)) {
3897 goto out;
3900 if (VALID_STAT(smb_fname_new->st)) {
3901 if (overwrite_if_exists) {
3902 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3903 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3904 goto out;
3906 status = unlink_internals(conn,
3907 req,
3908 FILE_ATTRIBUTE_NORMAL,
3909 NULL, /* new_dirfsp */
3910 smb_fname_new);
3911 if (!NT_STATUS_IS_OK(status)) {
3912 goto out;
3914 } else {
3915 /* Disallow if newname already exists. */
3916 status = NT_STATUS_OBJECT_NAME_COLLISION;
3917 goto out;
3921 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3922 smb_fname_old->base_name, smb_fname_new->base_name));
3924 ret = SMB_VFS_LINKAT(conn,
3925 parent_fname_old->fsp,
3926 base_name_old,
3927 parent_fname_new->fsp,
3928 base_name_new,
3931 if (ret != 0) {
3932 status = map_nt_error_from_unix(errno);
3933 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3934 nt_errstr(status), smb_fname_old->base_name,
3935 smb_fname_new->base_name));
3938 out:
3940 TALLOC_FREE(parent_fname_old);
3941 TALLOC_FREE(parent_fname_new);
3942 return status;
3945 /****************************************************************************
3946 Deal with setting the time from any of the setfilepathinfo functions.
3947 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3948 calling this function.
3949 ****************************************************************************/
3951 NTSTATUS smb_set_file_time(connection_struct *conn,
3952 files_struct *fsp,
3953 struct smb_filename *smb_fname,
3954 struct smb_file_time *ft,
3955 bool setting_write_time)
3957 struct files_struct *set_fsp = NULL;
3958 struct timeval_buf tbuf[4];
3959 uint32_t action =
3960 FILE_NOTIFY_CHANGE_LAST_ACCESS
3961 |FILE_NOTIFY_CHANGE_LAST_WRITE
3962 |FILE_NOTIFY_CHANGE_CREATION;
3963 int ret;
3965 if (!VALID_STAT(smb_fname->st)) {
3966 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3969 if (fsp == NULL) {
3970 /* A symlink */
3971 return NT_STATUS_OK;
3974 set_fsp = metadata_fsp(fsp);
3976 /* get some defaults (no modifications) if any info is zero or -1. */
3977 if (is_omit_timespec(&ft->create_time)) {
3978 action &= ~FILE_NOTIFY_CHANGE_CREATION;
3981 if (is_omit_timespec(&ft->atime)) {
3982 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3985 if (is_omit_timespec(&ft->mtime)) {
3986 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3989 if (!setting_write_time) {
3990 /* ft->mtime comes from change time, not write time. */
3991 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3994 /* Ensure the resolution is the correct for
3995 * what we can store on this filesystem. */
3997 round_timespec(conn->ts_res, &ft->create_time);
3998 round_timespec(conn->ts_res, &ft->ctime);
3999 round_timespec(conn->ts_res, &ft->atime);
4000 round_timespec(conn->ts_res, &ft->mtime);
4002 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
4003 timespec_string_buf(&ft->atime, true, &tbuf[0]));
4004 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
4005 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
4006 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
4007 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
4008 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
4009 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
4011 if (setting_write_time) {
4013 * This was a Windows setfileinfo on an open file.
4014 * NT does this a lot. We also need to
4015 * set the time here, as it can be read by
4016 * FindFirst/FindNext and with the patch for bug #2045
4017 * in smbd/fileio.c it ensures that this timestamp is
4018 * kept sticky even after a write. We save the request
4019 * away and will set it on file close and after a write. JRA.
4022 DBG_DEBUG("setting pending modtime to %s\n",
4023 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
4025 if (set_fsp != NULL) {
4026 set_sticky_write_time_fsp(set_fsp, ft->mtime);
4027 } else {
4028 set_sticky_write_time_path(
4029 vfs_file_id_from_sbuf(conn, &smb_fname->st),
4030 ft->mtime);
4034 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4036 ret = file_ntimes(conn, set_fsp, ft);
4037 if (ret != 0) {
4038 return map_nt_error_from_unix(errno);
4041 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
4042 smb_fname->base_name);
4043 return NT_STATUS_OK;
4046 /****************************************************************************
4047 Deal with setting the dosmode from any of the setfilepathinfo functions.
4048 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
4049 done before calling this function.
4050 ****************************************************************************/
4052 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4053 struct files_struct *fsp,
4054 uint32_t dosmode)
4056 struct files_struct *dos_fsp = NULL;
4057 uint32_t current_dosmode;
4058 int ret;
4060 if (!VALID_STAT(fsp->fsp_name->st)) {
4061 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4064 dos_fsp = metadata_fsp(fsp);
4066 if (dosmode != 0) {
4067 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4068 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
4069 } else {
4070 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
4074 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
4076 /* check the mode isn't different, before changing it */
4077 if (dosmode == 0) {
4078 return NT_STATUS_OK;
4080 current_dosmode = fdos_mode(dos_fsp);
4081 if (dosmode == current_dosmode) {
4082 return NT_STATUS_OK;
4085 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
4086 fsp_str_dbg(dos_fsp), dosmode);
4088 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
4089 if (ret != 0) {
4090 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4091 fsp_str_dbg(dos_fsp), strerror(errno));
4092 return map_nt_error_from_unix(errno);
4095 return NT_STATUS_OK;
4098 /****************************************************************************
4099 Deal with setting the size from any of the setfilepathinfo functions.
4100 ****************************************************************************/
4102 NTSTATUS smb_set_file_size(connection_struct *conn,
4103 struct smb_request *req,
4104 files_struct *fsp,
4105 struct smb_filename *smb_fname,
4106 const SMB_STRUCT_STAT *psbuf,
4107 off_t size,
4108 bool fail_after_createfile)
4110 NTSTATUS status = NT_STATUS_OK;
4111 files_struct *new_fsp = NULL;
4113 if (!VALID_STAT(*psbuf)) {
4114 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4117 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4118 (uint64_t)size,
4119 get_file_size_stat(psbuf));
4121 if (size == get_file_size_stat(psbuf)) {
4122 if (fsp == NULL) {
4123 return NT_STATUS_OK;
4125 if (!fsp->fsp_flags.modified) {
4126 return NT_STATUS_OK;
4128 trigger_write_time_update_immediate(fsp);
4129 return NT_STATUS_OK;
4132 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4133 smb_fname_str_dbg(smb_fname), (double)size));
4135 if (fsp &&
4136 !fsp->fsp_flags.is_pathref &&
4137 fsp_get_io_fd(fsp) != -1)
4139 /* Handle based call. */
4140 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4141 return NT_STATUS_ACCESS_DENIED;
4144 if (vfs_set_filelen(fsp, size) == -1) {
4145 return map_nt_error_from_unix(errno);
4147 trigger_write_time_update_immediate(fsp);
4148 return NT_STATUS_OK;
4151 status = SMB_VFS_CREATE_FILE(
4152 conn, /* conn */
4153 req, /* req */
4154 NULL, /* dirfsp */
4155 smb_fname, /* fname */
4156 FILE_WRITE_DATA, /* access_mask */
4157 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4158 FILE_SHARE_DELETE),
4159 FILE_OPEN, /* create_disposition*/
4160 0, /* create_options */
4161 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4162 0, /* oplock_request */
4163 NULL, /* lease */
4164 0, /* allocation_size */
4165 0, /* private_flags */
4166 NULL, /* sd */
4167 NULL, /* ea_list */
4168 &new_fsp, /* result */
4169 NULL, /* pinfo */
4170 NULL, NULL); /* create context */
4172 if (!NT_STATUS_IS_OK(status)) {
4173 /* NB. We check for open_was_deferred in the caller. */
4174 return status;
4177 /* See RAW-SFILEINFO-END-OF-FILE */
4178 if (fail_after_createfile) {
4179 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4180 return NT_STATUS_INVALID_LEVEL;
4183 if (vfs_set_filelen(new_fsp, size) == -1) {
4184 status = map_nt_error_from_unix(errno);
4185 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4186 return status;
4189 trigger_write_time_update_immediate(new_fsp);
4190 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4191 return NT_STATUS_OK;
4194 /****************************************************************************
4195 Deal with SMB_INFO_SET_EA.
4196 ****************************************************************************/
4198 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4199 const char *pdata,
4200 int total_data,
4201 files_struct *fsp,
4202 struct smb_filename *smb_fname)
4204 struct ea_list *ea_list = NULL;
4205 TALLOC_CTX *ctx = NULL;
4206 NTSTATUS status = NT_STATUS_OK;
4208 if (total_data < 10) {
4210 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4211 length. They seem to have no effect. Bug #3212. JRA */
4213 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4214 /* We're done. We only get EA info in this call. */
4215 return NT_STATUS_OK;
4218 return NT_STATUS_INVALID_PARAMETER;
4221 if (IVAL(pdata,0) > total_data) {
4222 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4223 IVAL(pdata,0), (unsigned int)total_data));
4224 return NT_STATUS_INVALID_PARAMETER;
4227 ctx = talloc_tos();
4228 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4229 if (!ea_list) {
4230 return NT_STATUS_INVALID_PARAMETER;
4233 if (fsp == NULL) {
4235 * The only way fsp can be NULL here is if
4236 * smb_fname points at a symlink and
4237 * and we're in POSIX context.
4238 * Ensure this is the case.
4240 * In this case we cannot set the EA.
4242 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4243 return NT_STATUS_ACCESS_DENIED;
4246 status = set_ea(conn, fsp, ea_list);
4248 return status;
4251 /****************************************************************************
4252 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4253 ****************************************************************************/
4255 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4256 const char *pdata,
4257 int total_data,
4258 files_struct *fsp)
4260 struct ea_list *ea_list = NULL;
4261 NTSTATUS status;
4263 if (fsp == NULL) {
4264 return NT_STATUS_INVALID_HANDLE;
4267 if (!lp_ea_support(SNUM(conn))) {
4268 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4269 "EA's not supported.\n",
4270 (unsigned int)total_data));
4271 return NT_STATUS_EAS_NOT_SUPPORTED;
4274 if (total_data < 10) {
4275 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4276 "too small.\n",
4277 (unsigned int)total_data));
4278 return NT_STATUS_INVALID_PARAMETER;
4281 ea_list = read_nttrans_ea_list(talloc_tos(),
4282 pdata,
4283 total_data);
4285 if (!ea_list) {
4286 return NT_STATUS_INVALID_PARAMETER;
4289 status = set_ea(conn, fsp, ea_list);
4291 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4292 smb_fname_str_dbg(fsp->fsp_name),
4293 nt_errstr(status) ));
4295 return status;
4299 /****************************************************************************
4300 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4301 ****************************************************************************/
4303 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4304 const char *pdata,
4305 int total_data,
4306 files_struct *fsp,
4307 struct smb_filename *smb_fname)
4309 NTSTATUS status = NT_STATUS_OK;
4310 bool delete_on_close;
4311 uint32_t dosmode = 0;
4313 if (total_data < 1) {
4314 return NT_STATUS_INVALID_PARAMETER;
4317 if (fsp == NULL) {
4318 return NT_STATUS_INVALID_HANDLE;
4321 delete_on_close = (CVAL(pdata,0) ? True : False);
4322 dosmode = fdos_mode(fsp);
4324 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4325 "delete_on_close = %u\n",
4326 smb_fname_str_dbg(smb_fname),
4327 (unsigned int)dosmode,
4328 (unsigned int)delete_on_close ));
4330 if (delete_on_close) {
4331 status = can_set_delete_on_close(fsp, dosmode);
4332 if (!NT_STATUS_IS_OK(status)) {
4333 return status;
4337 /* The set is across all open files on this dev/inode pair. */
4338 if (!set_delete_on_close(fsp, delete_on_close,
4339 conn->session_info->security_token,
4340 conn->session_info->unix_token)) {
4341 return NT_STATUS_ACCESS_DENIED;
4343 return NT_STATUS_OK;
4346 /****************************************************************************
4347 Deal with SMB_FILE_POSITION_INFORMATION.
4348 ****************************************************************************/
4350 static NTSTATUS smb_file_position_information(connection_struct *conn,
4351 const char *pdata,
4352 int total_data,
4353 files_struct *fsp)
4355 uint64_t position_information;
4357 if (total_data < 8) {
4358 return NT_STATUS_INVALID_PARAMETER;
4361 if (fsp == NULL) {
4362 /* Ignore on pathname based set. */
4363 return NT_STATUS_OK;
4366 position_information = (uint64_t)IVAL(pdata,0);
4367 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4369 DEBUG(10,("smb_file_position_information: Set file position "
4370 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4371 (double)position_information));
4372 fh_set_position_information(fsp->fh, position_information);
4373 return NT_STATUS_OK;
4376 /****************************************************************************
4377 Deal with SMB_FILE_MODE_INFORMATION.
4378 ****************************************************************************/
4380 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4381 const char *pdata,
4382 int total_data)
4384 uint32_t mode;
4386 if (total_data < 4) {
4387 return NT_STATUS_INVALID_PARAMETER;
4389 mode = IVAL(pdata,0);
4390 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4391 return NT_STATUS_INVALID_PARAMETER;
4393 return NT_STATUS_OK;
4396 /****************************************************************************
4397 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4398 ****************************************************************************/
4400 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4401 struct smb_request *req,
4402 const char *pdata,
4403 int total_data,
4404 files_struct *fsp,
4405 struct smb_filename *smb_fname_src)
4407 bool overwrite;
4408 uint32_t len;
4409 char *newname = NULL;
4410 struct files_struct *dst_dirfsp = NULL;
4411 struct smb_filename *smb_fname_dst = NULL;
4412 const char *dst_original_lcomp = NULL;
4413 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4414 NTSTATUS status = NT_STATUS_OK;
4415 TALLOC_CTX *ctx = talloc_tos();
4417 if (!fsp) {
4418 return NT_STATUS_INVALID_HANDLE;
4421 if (total_data < 20) {
4422 return NT_STATUS_INVALID_PARAMETER;
4425 overwrite = (CVAL(pdata,0) ? True : False);
4426 len = IVAL(pdata,16);
4428 if (len > (total_data - 20) || (len == 0)) {
4429 return NT_STATUS_INVALID_PARAMETER;
4432 (void)srvstr_pull_talloc(ctx,
4433 pdata,
4434 req->flags2,
4435 &newname,
4436 &pdata[20],
4437 len,
4438 STR_TERMINATE);
4440 if (newname == NULL) {
4441 return NT_STATUS_INVALID_PARAMETER;
4444 /* SMB2 rename paths are never DFS. */
4445 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4446 ucf_flags &= ~UCF_DFS_PATHNAME;
4448 status = check_path_syntax_smb2(newname);
4449 if (!NT_STATUS_IS_OK(status)) {
4450 return status;
4453 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4454 newname));
4456 if (newname[0] == ':') {
4457 /* Create an smb_fname to call rename_internals_fsp() with. */
4458 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4459 fsp->base_fsp->fsp_name->base_name,
4460 newname,
4461 NULL,
4462 fsp->base_fsp->fsp_name->twrp,
4463 fsp->base_fsp->fsp_name->flags);
4464 if (smb_fname_dst == NULL) {
4465 status = NT_STATUS_NO_MEMORY;
4466 goto out;
4468 } else {
4469 status = filename_convert_dirfsp(ctx,
4470 conn,
4471 newname,
4472 ucf_flags,
4473 0, /* Never a TWRP. */
4474 &dst_dirfsp,
4475 &smb_fname_dst);
4476 if (!NT_STATUS_IS_OK(status)) {
4477 goto out;
4482 * Set the original last component, since
4483 * rename_internals_fsp() requires it.
4485 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4486 conn,
4487 newname,
4488 ucf_flags);
4489 if (dst_original_lcomp == NULL) {
4490 status = NT_STATUS_NO_MEMORY;
4491 goto out;
4494 DEBUG(10,("smb2_file_rename_information: "
4495 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4496 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4497 smb_fname_str_dbg(smb_fname_dst)));
4498 status = rename_internals_fsp(conn,
4499 fsp,
4500 NULL, /* dst_dirfsp */
4501 smb_fname_dst,
4502 dst_original_lcomp,
4503 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4504 overwrite);
4506 out:
4507 TALLOC_FREE(smb_fname_dst);
4508 return status;
4511 static NTSTATUS smb2_file_link_information(connection_struct *conn,
4512 struct smb_request *req,
4513 const char *pdata,
4514 int total_data,
4515 files_struct *fsp,
4516 struct smb_filename *smb_fname_src)
4518 bool overwrite;
4519 uint32_t len;
4520 char *newname = NULL;
4521 struct files_struct *dst_dirfsp = NULL;
4522 struct smb_filename *smb_fname_dst = NULL;
4523 NTSTATUS status = NT_STATUS_OK;
4524 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4525 size_t ret;
4526 TALLOC_CTX *ctx = talloc_tos();
4528 if (!fsp) {
4529 return NT_STATUS_INVALID_HANDLE;
4532 if (total_data < 20) {
4533 return NT_STATUS_INVALID_PARAMETER;
4536 overwrite = (CVAL(pdata,0) ? true : false);
4537 len = IVAL(pdata,16);
4539 if (len > (total_data - 20) || (len == 0)) {
4540 return NT_STATUS_INVALID_PARAMETER;
4543 ret = srvstr_pull_talloc(ctx,
4544 pdata,
4545 req->flags2,
4546 &newname,
4547 &pdata[20],
4548 len,
4549 STR_TERMINATE);
4551 if (ret == (size_t)-1 || newname == NULL) {
4552 return NT_STATUS_INVALID_PARAMETER;
4555 /* SMB2 hardlink paths are never DFS. */
4556 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4557 ucf_flags &= ~UCF_DFS_PATHNAME;
4559 status = check_path_syntax_smb2(newname);
4560 if (!NT_STATUS_IS_OK(status)) {
4561 return status;
4564 DBG_DEBUG("got name |%s|\n", newname);
4566 status = filename_convert_dirfsp(ctx,
4567 conn,
4568 newname,
4569 ucf_flags,
4570 0, /* No TWRP. */
4571 &dst_dirfsp,
4572 &smb_fname_dst);
4573 if (!NT_STATUS_IS_OK(status)) {
4574 return status;
4577 if (fsp->base_fsp) {
4578 /* No stream names. */
4579 return NT_STATUS_NOT_SUPPORTED;
4582 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4583 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4584 smb_fname_str_dbg(smb_fname_dst));
4585 status = hardlink_internals(ctx,
4586 conn,
4587 req,
4588 overwrite,
4589 NULL, /* src_dirfsp */
4590 fsp->fsp_name,
4591 dst_dirfsp, /* dst_dirfsp */
4592 smb_fname_dst);
4594 TALLOC_FREE(smb_fname_dst);
4595 return status;
4598 static NTSTATUS smb_file_link_information(connection_struct *conn,
4599 struct smb_request *req,
4600 const char *pdata,
4601 int total_data,
4602 files_struct *fsp,
4603 struct smb_filename *smb_fname_src)
4605 bool overwrite;
4606 uint32_t len;
4607 char *newname = NULL;
4608 struct files_struct *dst_dirfsp = NULL;
4609 struct smb_filename *smb_fname_dst = NULL;
4610 NTSTATUS status = NT_STATUS_OK;
4611 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4612 NTTIME dst_twrp = 0;
4613 TALLOC_CTX *ctx = talloc_tos();
4615 if (!fsp) {
4616 return NT_STATUS_INVALID_HANDLE;
4619 if (total_data < 20) {
4620 return NT_STATUS_INVALID_PARAMETER;
4623 overwrite = (CVAL(pdata,0) ? true : false);
4624 len = IVAL(pdata,16);
4626 if (len > (total_data - 20) || (len == 0)) {
4627 return NT_STATUS_INVALID_PARAMETER;
4630 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4631 srvstr_get_path_posix(ctx,
4632 pdata,
4633 req->flags2,
4634 &newname,
4635 &pdata[20],
4636 len,
4637 STR_TERMINATE,
4638 &status);
4639 ucf_flags |= UCF_POSIX_PATHNAMES;
4640 } else {
4641 srvstr_get_path(ctx,
4642 pdata,
4643 req->flags2,
4644 &newname,
4645 &pdata[20],
4646 len,
4647 STR_TERMINATE,
4648 &status);
4650 if (!NT_STATUS_IS_OK(status)) {
4651 return status;
4654 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4655 newname));
4657 if (ucf_flags & UCF_GMT_PATHNAME) {
4658 extract_snapshot_token(newname, &dst_twrp);
4660 status = filename_convert_dirfsp(ctx,
4661 conn,
4662 newname,
4663 ucf_flags,
4664 dst_twrp,
4665 &dst_dirfsp,
4666 &smb_fname_dst);
4667 if (!NT_STATUS_IS_OK(status)) {
4668 return status;
4671 if (fsp->base_fsp) {
4672 /* No stream names. */
4673 return NT_STATUS_NOT_SUPPORTED;
4676 DEBUG(10,("smb_file_link_information: "
4677 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4678 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4679 smb_fname_str_dbg(smb_fname_dst)));
4680 status = hardlink_internals(ctx,
4681 conn,
4682 req,
4683 overwrite,
4684 NULL, /* src_dirfsp */
4685 fsp->fsp_name,
4686 dst_dirfsp, /* dst_dirfsp */
4687 smb_fname_dst);
4689 TALLOC_FREE(smb_fname_dst);
4690 return status;
4694 /****************************************************************************
4695 Deal with SMB_FILE_RENAME_INFORMATION.
4696 ****************************************************************************/
4698 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4699 struct smb_request *req,
4700 const char *pdata,
4701 int total_data,
4702 files_struct *fsp,
4703 struct smb_filename *smb_fname_src)
4705 bool overwrite;
4706 uint32_t root_fid;
4707 uint32_t len;
4708 char *newname = NULL;
4709 struct files_struct *dst_dirfsp = NULL;
4710 struct smb_filename *smb_fname_dst = NULL;
4711 const char *dst_original_lcomp = NULL;
4712 NTSTATUS status = NT_STATUS_OK;
4713 char *p;
4714 TALLOC_CTX *ctx = talloc_tos();
4716 if (total_data < 13) {
4717 return NT_STATUS_INVALID_PARAMETER;
4720 overwrite = (CVAL(pdata,0) != 0);
4721 root_fid = IVAL(pdata,4);
4722 len = IVAL(pdata,8);
4724 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4725 return NT_STATUS_INVALID_PARAMETER;
4728 if (req->posix_pathnames) {
4729 srvstr_get_path_posix(ctx,
4730 pdata,
4731 req->flags2,
4732 &newname,
4733 &pdata[12],
4734 len,
4736 &status);
4737 } else {
4738 srvstr_get_path(ctx,
4739 pdata,
4740 req->flags2,
4741 &newname,
4742 &pdata[12],
4743 len,
4745 &status);
4747 if (!NT_STATUS_IS_OK(status)) {
4748 return status;
4751 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4752 newname));
4754 /* Check the new name has no '/' characters. */
4755 if (strchr_m(newname, '/')) {
4756 return NT_STATUS_NOT_SUPPORTED;
4759 if (fsp && fsp->base_fsp) {
4760 /* newname must be a stream name. */
4761 if (newname[0] != ':') {
4762 return NT_STATUS_NOT_SUPPORTED;
4765 /* Create an smb_fname to call rename_internals_fsp() with. */
4766 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4767 fsp->base_fsp->fsp_name->base_name,
4768 newname,
4769 NULL,
4770 fsp->base_fsp->fsp_name->twrp,
4771 fsp->base_fsp->fsp_name->flags);
4772 if (smb_fname_dst == NULL) {
4773 status = NT_STATUS_NO_MEMORY;
4774 goto out;
4778 * Get the original last component, since
4779 * rename_internals_fsp() requires it.
4781 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4782 conn,
4783 newname,
4785 if (dst_original_lcomp == NULL) {
4786 status = NT_STATUS_NO_MEMORY;
4787 goto out;
4790 } else {
4792 * Build up an smb_fname_dst based on the filename passed in.
4793 * We basically just strip off the last component, and put on
4794 * the newname instead.
4796 char *base_name = NULL;
4797 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4798 NTTIME dst_twrp = 0;
4800 /* newname must *not* be a stream name. */
4801 if (newname[0] == ':') {
4802 return NT_STATUS_NOT_SUPPORTED;
4806 * Strip off the last component (filename) of the path passed
4807 * in.
4809 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4810 if (!base_name) {
4811 return NT_STATUS_NO_MEMORY;
4813 p = strrchr_m(base_name, '/');
4814 if (p) {
4815 p[1] = '\0';
4816 } else {
4817 base_name = talloc_strdup(ctx, "");
4818 if (!base_name) {
4819 return NT_STATUS_NO_MEMORY;
4822 /* Append the new name. */
4823 base_name = talloc_asprintf_append(base_name,
4824 "%s",
4825 newname);
4826 if (!base_name) {
4827 return NT_STATUS_NO_MEMORY;
4830 if (ucf_flags & UCF_GMT_PATHNAME) {
4831 extract_snapshot_token(base_name, &dst_twrp);
4833 status = filename_convert_dirfsp(ctx,
4834 conn,
4835 base_name,
4836 ucf_flags,
4837 dst_twrp,
4838 &dst_dirfsp,
4839 &smb_fname_dst);
4841 if (!NT_STATUS_IS_OK(status)) {
4842 goto out;
4844 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4845 conn,
4846 newname,
4847 ucf_flags);
4848 if (dst_original_lcomp == NULL) {
4849 status = NT_STATUS_NO_MEMORY;
4850 goto out;
4854 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4855 DEBUG(10,("smb_file_rename_information: "
4856 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4857 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4858 smb_fname_str_dbg(smb_fname_dst)));
4859 status = rename_internals_fsp(conn,
4860 fsp,
4861 dst_dirfsp,
4862 smb_fname_dst,
4863 dst_original_lcomp,
4865 overwrite);
4866 } else {
4867 DEBUG(10,("smb_file_rename_information: "
4868 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4869 smb_fname_str_dbg(smb_fname_src),
4870 smb_fname_str_dbg(smb_fname_dst)));
4871 status = rename_internals(ctx,
4872 conn,
4873 req,
4874 NULL, /* src_dirfsp */
4875 smb_fname_src,
4876 dst_dirfsp,
4877 smb_fname_dst,
4878 dst_original_lcomp,
4880 overwrite,
4881 FILE_WRITE_ATTRIBUTES);
4883 out:
4884 TALLOC_FREE(smb_fname_dst);
4885 return status;
4888 /****************************************************************************
4889 Deal with SMB_SET_FILE_BASIC_INFO.
4890 ****************************************************************************/
4892 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4893 const char *pdata,
4894 int total_data,
4895 files_struct *fsp,
4896 struct smb_filename *smb_fname)
4898 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4899 struct smb_file_time ft;
4900 uint32_t dosmode = 0;
4901 NTSTATUS status = NT_STATUS_OK;
4903 init_smb_file_time(&ft);
4905 if (total_data < 36) {
4906 return NT_STATUS_INVALID_PARAMETER;
4909 if (fsp == NULL) {
4910 return NT_STATUS_INVALID_HANDLE;
4913 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4914 if (!NT_STATUS_IS_OK(status)) {
4915 return status;
4918 /* Set the attributes */
4919 dosmode = IVAL(pdata,32);
4920 status = smb_set_file_dosmode(conn, fsp, dosmode);
4921 if (!NT_STATUS_IS_OK(status)) {
4922 return status;
4925 /* create time */
4926 ft.create_time = pull_long_date_full_timespec(pdata);
4928 /* access time */
4929 ft.atime = pull_long_date_full_timespec(pdata+8);
4931 /* write time. */
4932 ft.mtime = pull_long_date_full_timespec(pdata+16);
4934 /* change time. */
4935 ft.ctime = pull_long_date_full_timespec(pdata+24);
4937 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4938 smb_fname_str_dbg(smb_fname)));
4940 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4941 if (!NT_STATUS_IS_OK(status)) {
4942 return status;
4945 if (fsp->fsp_flags.modified) {
4946 trigger_write_time_update_immediate(fsp);
4948 return NT_STATUS_OK;
4951 /****************************************************************************
4952 Deal with SMB_INFO_STANDARD.
4953 ****************************************************************************/
4955 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4956 const char *pdata,
4957 int total_data,
4958 files_struct *fsp,
4959 struct smb_filename *smb_fname)
4961 NTSTATUS status;
4962 struct smb_file_time ft;
4964 init_smb_file_time(&ft);
4966 if (total_data < 12) {
4967 return NT_STATUS_INVALID_PARAMETER;
4970 if (fsp == NULL) {
4971 return NT_STATUS_INVALID_HANDLE;
4974 /* create time */
4975 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4976 /* access time */
4977 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4978 /* write time */
4979 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4981 DEBUG(10,("smb_set_info_standard: file %s\n",
4982 smb_fname_str_dbg(smb_fname)));
4984 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4985 if (!NT_STATUS_IS_OK(status)) {
4986 return status;
4989 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4990 if (!NT_STATUS_IS_OK(status)) {
4991 return status;
4994 if (fsp->fsp_flags.modified) {
4995 trigger_write_time_update_immediate(fsp);
4997 return NT_STATUS_OK;
5000 /****************************************************************************
5001 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5002 ****************************************************************************/
5004 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5005 struct smb_request *req,
5006 const char *pdata,
5007 int total_data,
5008 files_struct *fsp,
5009 struct smb_filename *smb_fname)
5011 uint64_t allocation_size = 0;
5012 NTSTATUS status = NT_STATUS_OK;
5013 files_struct *new_fsp = NULL;
5015 if (!VALID_STAT(smb_fname->st)) {
5016 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5019 if (total_data < 8) {
5020 return NT_STATUS_INVALID_PARAMETER;
5023 allocation_size = (uint64_t)IVAL(pdata,0);
5024 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5025 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
5026 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5027 (double)allocation_size));
5029 if (allocation_size) {
5030 allocation_size = smb_roundup(conn, allocation_size);
5033 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
5034 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
5035 (double)allocation_size));
5037 if (fsp &&
5038 !fsp->fsp_flags.is_pathref &&
5039 fsp_get_io_fd(fsp) != -1)
5041 /* Open file handle. */
5042 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5043 return NT_STATUS_ACCESS_DENIED;
5046 /* Only change if needed. */
5047 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5048 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5049 return map_nt_error_from_unix(errno);
5052 /* But always update the time. */
5054 * This is equivalent to a write. Ensure it's seen immediately
5055 * if there are no pending writes.
5057 trigger_write_time_update_immediate(fsp);
5058 return NT_STATUS_OK;
5061 /* Pathname or stat or directory file. */
5062 status = SMB_VFS_CREATE_FILE(
5063 conn, /* conn */
5064 req, /* req */
5065 NULL, /* dirfsp */
5066 smb_fname, /* fname */
5067 FILE_WRITE_DATA, /* access_mask */
5068 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5069 FILE_SHARE_DELETE),
5070 FILE_OPEN, /* create_disposition*/
5071 0, /* create_options */
5072 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5073 0, /* oplock_request */
5074 NULL, /* lease */
5075 0, /* allocation_size */
5076 0, /* private_flags */
5077 NULL, /* sd */
5078 NULL, /* ea_list */
5079 &new_fsp, /* result */
5080 NULL, /* pinfo */
5081 NULL, NULL); /* create context */
5083 if (!NT_STATUS_IS_OK(status)) {
5084 /* NB. We check for open_was_deferred in the caller. */
5085 return status;
5088 /* Only change if needed. */
5089 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5090 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5091 status = map_nt_error_from_unix(errno);
5092 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5093 return status;
5097 /* Changing the allocation size should set the last mod time. */
5099 * This is equivalent to a write. Ensure it's seen immediately
5100 * if there are no pending writes.
5102 trigger_write_time_update_immediate(new_fsp);
5103 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5104 return NT_STATUS_OK;
5107 /****************************************************************************
5108 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5109 ****************************************************************************/
5111 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5112 struct smb_request *req,
5113 const char *pdata,
5114 int total_data,
5115 files_struct *fsp,
5116 struct smb_filename *smb_fname,
5117 bool fail_after_createfile)
5119 off_t size;
5121 if (total_data < 8) {
5122 return NT_STATUS_INVALID_PARAMETER;
5125 size = IVAL(pdata,0);
5126 size |= (((off_t)IVAL(pdata,4)) << 32);
5127 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5128 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5129 (double)size));
5131 return smb_set_file_size(conn, req,
5132 fsp,
5133 smb_fname,
5134 &smb_fname->st,
5135 size,
5136 fail_after_createfile);
5139 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5140 struct smb_request *req,
5141 TALLOC_CTX *mem_ctx,
5142 uint16_t info_level,
5143 files_struct *fsp,
5144 struct smb_filename *smb_fname,
5145 char **ppdata, int total_data,
5146 int *ret_data_size)
5148 char *pdata = *ppdata;
5149 NTSTATUS status = NT_STATUS_OK;
5150 int data_return_size = 0;
5152 *ret_data_size = 0;
5154 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5155 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5156 fsp_fnum_dbg(fsp),
5157 info_level, total_data));
5159 switch (info_level) {
5161 case SMB_INFO_STANDARD:
5163 status = smb_set_info_standard(conn,
5164 pdata,
5165 total_data,
5166 fsp,
5167 smb_fname);
5168 break;
5171 case SMB_INFO_SET_EA:
5173 status = smb_info_set_ea(conn,
5174 pdata,
5175 total_data,
5176 fsp,
5177 smb_fname);
5178 break;
5181 case SMB_SET_FILE_BASIC_INFO:
5182 case SMB_FILE_BASIC_INFORMATION:
5184 status = smb_set_file_basic_info(conn,
5185 pdata,
5186 total_data,
5187 fsp,
5188 smb_fname);
5189 break;
5192 case SMB_FILE_ALLOCATION_INFORMATION:
5193 case SMB_SET_FILE_ALLOCATION_INFO:
5195 status = smb_set_file_allocation_info(conn, req,
5196 pdata,
5197 total_data,
5198 fsp,
5199 smb_fname);
5200 break;
5203 case SMB_FILE_END_OF_FILE_INFORMATION:
5204 case SMB_SET_FILE_END_OF_FILE_INFO:
5207 * XP/Win7 both fail after the createfile with
5208 * SMB_SET_FILE_END_OF_FILE_INFO but not
5209 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5210 * The level is known here, so pass it down
5211 * appropriately.
5213 bool should_fail =
5214 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5216 status = smb_set_file_end_of_file_info(conn, req,
5217 pdata,
5218 total_data,
5219 fsp,
5220 smb_fname,
5221 should_fail);
5222 break;
5225 case SMB_FILE_DISPOSITION_INFORMATION:
5226 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5228 #if 0
5229 /* JRA - We used to just ignore this on a path ?
5230 * Shouldn't this be invalid level on a pathname
5231 * based call ?
5233 if (tran_call != TRANSACT2_SETFILEINFO) {
5234 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5236 #endif
5237 status = smb_set_file_disposition_info(conn,
5238 pdata,
5239 total_data,
5240 fsp,
5241 smb_fname);
5242 break;
5245 case SMB_FILE_POSITION_INFORMATION:
5247 status = smb_file_position_information(conn,
5248 pdata,
5249 total_data,
5250 fsp);
5251 break;
5254 case SMB_FILE_FULL_EA_INFORMATION:
5256 status = smb_set_file_full_ea_info(conn,
5257 pdata,
5258 total_data,
5259 fsp);
5260 break;
5263 /* From tridge Samba4 :
5264 * MODE_INFORMATION in setfileinfo (I have no
5265 * idea what "mode information" on a file is - it takes a value of 0,
5266 * 2, 4 or 6. What could it be?).
5269 case SMB_FILE_MODE_INFORMATION:
5271 status = smb_file_mode_information(conn,
5272 pdata,
5273 total_data);
5274 break;
5277 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5278 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5279 case SMB_FILE_SHORT_NAME_INFORMATION:
5280 return NT_STATUS_NOT_SUPPORTED;
5282 case SMB_FILE_RENAME_INFORMATION:
5284 status = smb_file_rename_information(conn, req,
5285 pdata, total_data,
5286 fsp, smb_fname);
5287 break;
5290 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5292 /* SMB2 rename information. */
5293 status = smb2_file_rename_information(conn, req,
5294 pdata, total_data,
5295 fsp, smb_fname);
5296 break;
5299 case SMB_FILE_LINK_INFORMATION:
5301 if (conn->sconn->using_smb2) {
5302 status = smb2_file_link_information(conn,
5303 req,
5304 pdata,
5305 total_data,
5306 fsp,
5307 smb_fname);
5308 } else {
5309 status = smb_file_link_information(conn,
5310 req,
5311 pdata,
5312 total_data,
5313 fsp,
5314 smb_fname);
5316 break;
5319 default:
5320 return NT_STATUS_INVALID_LEVEL;
5323 if (!NT_STATUS_IS_OK(status)) {
5324 return status;
5327 *ret_data_size = data_return_size;
5328 return NT_STATUS_OK;
5331 static uint32_t generate_volume_serial_number(
5332 const struct loadparm_substitution *lp_sub,
5333 int snum)
5335 int serial = lp_volume_serial_number(snum);
5336 return serial != -1 ? serial:
5337 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5338 (str_checksum(get_local_machine_name())<<16);