tests/zfs-tests/cmd/randfree_file/Makefile
tests/zfs-tests/cmd/randwritecomp/Makefile
tests/zfs-tests/cmd/readmmap/Makefile
+ tests/zfs-tests/cmd/read_dos_attributes/Makefile
tests/zfs-tests/cmd/rename_dir/Makefile
tests/zfs-tests/cmd/rm_lnkcnt_zero_file/Makefile
tests/zfs-tests/cmd/send_doall/Makefile
tests/zfs-tests/cmd/stride_dd/Makefile
tests/zfs-tests/cmd/threadsappend/Makefile
tests/zfs-tests/cmd/user_ns_exec/Makefile
+ tests/zfs-tests/cmd/write_dos_attributes/Makefile
tests/zfs-tests/cmd/xattrtest/Makefile
tests/zfs-tests/include/Makefile
tests/zfs-tests/tests/Makefile
tests/zfs-tests/tests/functional/deadman/Makefile
tests/zfs-tests/tests/functional/delegate/Makefile
tests/zfs-tests/tests/functional/devices/Makefile
+ tests/zfs-tests/tests/functional/dos_attributes/Makefile
tests/zfs-tests/tests/functional/events/Makefile
tests/zfs-tests/tests/functional/exec/Makefile
tests/zfs-tests/tests/functional/fallocate/Makefile
*/
#define BLKZNAME _IOR(0x12, 125, char[ZFS_MAX_DATASET_NAME_LEN])
+#ifdef __linux__
+
+/*
+ * IOCTLs to update and retrieve additional file level attributes on
+ * Linux.
+ */
+#define ZFS_IOC_GETDOSFLAGS _IOR(0x83, 1, uint64_t)
+#define ZFS_IOC_SETDOSFLAGS _IOW(0x83, 2, uint64_t)
+
+/*
+ * Additional file level attributes, that are stored
+ * in the upper half of z_pflags
+ */
+#define ZFS_READONLY 0x0000000100000000ull
+#define ZFS_HIDDEN 0x0000000200000000ull
+#define ZFS_SYSTEM 0x0000000400000000ull
+#define ZFS_ARCHIVE 0x0000000800000000ull
+#define ZFS_IMMUTABLE 0x0000001000000000ull
+#define ZFS_NOUNLINK 0x0000002000000000ull
+#define ZFS_APPENDONLY 0x0000004000000000ull
+#define ZFS_NODUMP 0x0000008000000000ull
+#define ZFS_OPAQUE 0x0000010000000000ull
+#define ZFS_AV_QUARANTINED 0x0000020000000000ull
+#define ZFS_AV_MODIFIED 0x0000040000000000ull
+#define ZFS_REPARSE 0x0000080000000000ull
+#define ZFS_OFFLINE 0x0000100000000000ull
+#define ZFS_SPARSE 0x0000200000000000ull
+
+#define ZFS_DOS_FL_USER_VISIBLE (ZFS_IMMUTABLE | ZFS_APPENDONLY | \
+ ZFS_NOUNLINK | ZFS_ARCHIVE | ZFS_NODUMP | ZFS_SYSTEM | \
+ ZFS_HIDDEN | ZFS_READONLY | ZFS_REPARSE | ZFS_OFFLINE | \
+ ZFS_SPARSE)
+
+#endif
+
/*
* ZFS-specific error codes used for returning descriptive errors
* to the userland through zfs ioctls.
/*
* Additional file level attributes, that are stored
- * in the upper half of zp_flags
+ * in the upper half of z_pflags
*/
#define ZFS_READONLY 0x0000000100000000ull
#define ZFS_HIDDEN 0x0000000200000000ull
xva_init(xva);
xoap = xva_getxoptattr(xva);
- XVA_SET_REQ(xva, XAT_IMMUTABLE);
- if (ioctl_flags & FS_IMMUTABLE_FL)
- xoap->xoa_immutable = B_TRUE;
-
- XVA_SET_REQ(xva, XAT_APPENDONLY);
- if (ioctl_flags & FS_APPEND_FL)
- xoap->xoa_appendonly = B_TRUE;
-
- XVA_SET_REQ(xva, XAT_NODUMP);
- if (ioctl_flags & FS_NODUMP_FL)
- xoap->xoa_nodump = B_TRUE;
-
- XVA_SET_REQ(xva, XAT_PROJINHERIT);
- if (ioctl_flags & ZFS_PROJINHERIT_FL)
- xoap->xoa_projinherit = B_TRUE;
+#define FLAG_CHANGE(iflag, zflag, xflag, xfield) do { \
+ if (((ioctl_flags & (iflag)) && !(zfs_flags & (zflag))) || \
+ ((zfs_flags & (zflag)) && !(ioctl_flags & (iflag)))) { \
+ XVA_SET_REQ(xva, (xflag)); \
+ (xfield) = ((ioctl_flags & (iflag)) != 0); \
+ } \
+} while (0)
+
+ FLAG_CHANGE(FS_IMMUTABLE_FL, ZFS_IMMUTABLE, XAT_IMMUTABLE,
+ xoap->xoa_immutable);
+ FLAG_CHANGE(FS_APPEND_FL, ZFS_APPENDONLY, XAT_APPENDONLY,
+ xoap->xoa_appendonly);
+ FLAG_CHANGE(FS_NODUMP_FL, ZFS_NODUMP, XAT_NODUMP,
+ xoap->xoa_nodump);
+ FLAG_CHANGE(ZFS_PROJINHERIT_FL, ZFS_PROJINHERIT, XAT_PROJINHERIT,
+ xoap->xoa_projinherit);
+
+#undef FLAG_CHANGE
return (0);
}
return (err);
}
+/*
+ * Expose Additional File Level Attributes of ZFS.
+ */
+static int
+zpl_ioctl_getdosflags(struct file *filp, void __user *arg)
+{
+ struct inode *ip = file_inode(filp);
+ uint64_t dosflags = ITOZ(ip)->z_pflags;
+ dosflags &= ZFS_DOS_FL_USER_VISIBLE;
+ int err = copy_to_user(arg, &dosflags, sizeof (dosflags));
+
+ return (err);
+}
+
+static int
+__zpl_ioctl_setdosflags(struct inode *ip, uint64_t ioctl_flags, xvattr_t *xva)
+{
+ uint64_t zfs_flags = ITOZ(ip)->z_pflags;
+ xoptattr_t *xoap;
+
+ if (ioctl_flags & (~ZFS_DOS_FL_USER_VISIBLE))
+ return (-EOPNOTSUPP);
+
+ if ((fchange(ioctl_flags, zfs_flags, ZFS_IMMUTABLE, ZFS_IMMUTABLE) ||
+ fchange(ioctl_flags, zfs_flags, ZFS_APPENDONLY, ZFS_APPENDONLY)) &&
+ !capable(CAP_LINUX_IMMUTABLE))
+ return (-EPERM);
+
+ if (!zpl_inode_owner_or_capable(kcred->user_ns, ip))
+ return (-EACCES);
+
+ xva_init(xva);
+ xoap = xva_getxoptattr(xva);
+
+#define FLAG_CHANGE(iflag, xflag, xfield) do { \
+ if (((ioctl_flags & (iflag)) && !(zfs_flags & (iflag))) || \
+ ((zfs_flags & (iflag)) && !(ioctl_flags & (iflag)))) { \
+ XVA_SET_REQ(xva, (xflag)); \
+ (xfield) = ((ioctl_flags & (iflag)) != 0); \
+ } \
+} while (0)
+
+ FLAG_CHANGE(ZFS_IMMUTABLE, XAT_IMMUTABLE, xoap->xoa_immutable);
+ FLAG_CHANGE(ZFS_APPENDONLY, XAT_APPENDONLY, xoap->xoa_appendonly);
+ FLAG_CHANGE(ZFS_NODUMP, XAT_NODUMP, xoap->xoa_nodump);
+ FLAG_CHANGE(ZFS_READONLY, XAT_READONLY, xoap->xoa_readonly);
+ FLAG_CHANGE(ZFS_HIDDEN, XAT_HIDDEN, xoap->xoa_hidden);
+ FLAG_CHANGE(ZFS_SYSTEM, XAT_SYSTEM, xoap->xoa_system);
+ FLAG_CHANGE(ZFS_ARCHIVE, XAT_ARCHIVE, xoap->xoa_archive);
+ FLAG_CHANGE(ZFS_NOUNLINK, XAT_NOUNLINK, xoap->xoa_nounlink);
+ FLAG_CHANGE(ZFS_REPARSE, XAT_REPARSE, xoap->xoa_reparse);
+ FLAG_CHANGE(ZFS_OFFLINE, XAT_OFFLINE, xoap->xoa_offline);
+ FLAG_CHANGE(ZFS_SPARSE, XAT_SPARSE, xoap->xoa_sparse);
+
+#undef FLAG_CHANGE
+
+ return (0);
+}
+
+/*
+ * Set Additional File Level Attributes of ZFS.
+ */
+static int
+zpl_ioctl_setdosflags(struct file *filp, void __user *arg)
+{
+ struct inode *ip = file_inode(filp);
+ uint64_t dosflags;
+ cred_t *cr = CRED();
+ xvattr_t xva;
+ int err;
+ fstrans_cookie_t cookie;
+
+ if (copy_from_user(&dosflags, arg, sizeof (dosflags)))
+ return (-EFAULT);
+
+ err = __zpl_ioctl_setdosflags(ip, dosflags, &xva);
+ if (err)
+ return (err);
+
+ crhold(cr);
+ cookie = spl_fstrans_mark();
+ err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr);
+ spl_fstrans_unmark(cookie);
+ crfree(cr);
+
+ return (err);
+}
+
static long
zpl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
return (zpl_ioctl_getxattr(filp, (void *)arg));
case ZFS_IOC_FSSETXATTR:
return (zpl_ioctl_setxattr(filp, (void *)arg));
+ case ZFS_IOC_GETDOSFLAGS:
+ return (zpl_ioctl_getdosflags(filp, (void *)arg));
+ case ZFS_IOC_SETDOSFLAGS:
+ return (zpl_ioctl_setdosflags(filp, (void *)arg));
default:
return (-ENOTTY);
}
tags = ['functional']
[tests/functional/acl/off]
-tests = ['posixmode']
+tests = ['dosmode', 'posixmode']
tags = ['functional', 'acl']
[tests/functional/alloc_class]
outputdir = /var/tmp/test_results
tags = ['functional']
-[tests/functional/acl/off:FreeBSD]
-tests = ['dosmode']
-tags = ['functional', 'acl']
-
[tests/functional/cli_root/zfs_jail:FreeBSD]
tests = ['zfs_jail_001_pos']
tags = ['functional', 'cli_root', 'zfs_jail']
'projecttree_001_pos', 'projecttree_002_pos', 'projecttree_003_neg']
tags = ['functional', 'projectquota']
+[tests/functional/dos_attributes:Linux]
+tests = ['read_dos_attrs_001', 'write_dos_attrs_001']
+tags = ['functional', 'dos_attributes']
+
[tests/functional/rsend:Linux]
tests = ['send_realloc_dnode_size', 'send_encrypted_files']
tags = ['functional', 'rsend']
SUBDIRS += \
getversion \
randfree_file \
+ read_dos_attributes \
user_ns_exec \
+ write_dos_attributes \
xattrtest
endif
--- /dev/null
+/read_dos_attributes
--- /dev/null
+include $(top_srcdir)/config/Rules.am
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
+
+pkgexec_PROGRAMS = read_dos_attributes
+read_dos_attributes_SOURCES = read_dos_attributes.c
--- /dev/null
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2022 iXsystems, Inc.
+ */
+
+/*
+ * FreeBSD allows to update and retreive additional file level attributes.
+ * For Linux, two IOCTLs have been added to update and retrieve additional
+ * level attributes.
+ *
+ * This application reads additional file level attributes on a given
+ * file and prints FreeBSD keywords that map to respective attributes.
+ *
+ * Usage: 'read_dos_attributes filepath'
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <err.h>
+#include <sys/fs/zfs.h>
+#include <string.h>
+
+#define SU_ARCH_SHORT "arch"
+#define SU_ARCH_FULL "archived"
+#define SU_NODUMP "nodump"
+#define SU_APPEND_SHORT "sappnd"
+#define SU_APPEND_FULL "sappend"
+#define SU_IMMUTABLE "schg"
+#define SU_IMMUTABLE_SHORT "schange"
+#define SU_IMMUTABLE_FULL "simmutable"
+#define SU_UNLINK_SHORT "sunlnk"
+#define SU_UNLINK_FULL "sunlink"
+#define U_APPEND_SHORT "uappnd"
+#define U_APPEND_FULL "uappend"
+#define U_ARCH_SHORT "uarch"
+#define U_ARCH_FULL "uarchive"
+#define U_IMMUTABLE "uchg"
+#define U_IMMUTABLE_SHORT "uchange"
+#define U_IMMUTABLE_FULL "uimmutable"
+#define U_HIDDEN_SHORT "hidden"
+#define U_HIDDEN_FULL "uhidden"
+#define U_OFFLINE_SHORT "offline"
+#define U_OFFLINE_FULL "uoffline"
+#define U_RDONLY "rdonly"
+#define U_RDONLY_SHORT "urdonly"
+#define U_RDONLY_FULL "readonly"
+#define U_SPARSE_SHORT "sparse"
+#define U_SPARSE_FULL "usparse"
+#define U_SYSTEM_SHORT "system"
+#define U_SYSTEM_FULL "usystem"
+#define U_REPARSE_SHORT "reparse"
+#define U_REPARSE_FULL "ureparse"
+#define U_UNLINK_SHORT "uunlnk"
+#define U_UNLINK_FULL "uunlink"
+#define UNSET_NODUMP "dump"
+
+#define NO_ATTRIBUTE "-"
+
+#define SEPARATOR ","
+
+#define BUFFER_SIZE 0x200
+
+void attribute_to_str(uint64_t attributes, char *buff);
+
+void
+attribute_to_str(uint64_t attributes, char *buff)
+{
+ if (attributes & ZFS_ARCHIVE) {
+ strcat(buff, U_ARCH_SHORT);
+ strcat(buff, SEPARATOR);
+ }
+
+ if (attributes & ZFS_APPENDONLY) {
+ strcat(buff, U_APPEND_SHORT);
+ strcat(buff, SEPARATOR);
+ }
+
+ if (attributes & ZFS_IMMUTABLE) {
+ strcat(buff, U_IMMUTABLE_FULL);
+ strcat(buff, SEPARATOR);
+ }
+
+ if (attributes & ZFS_NOUNLINK) {
+ strcat(buff, U_UNLINK_SHORT);
+ strcat(buff, SEPARATOR);
+ }
+
+ if (attributes & ZFS_NODUMP) {
+ strcat(buff, SU_NODUMP);
+ strcat(buff, SEPARATOR);
+ }
+
+ if (attributes & ZFS_HIDDEN) {
+ strcat(buff, U_HIDDEN_SHORT);
+ strcat(buff, SEPARATOR);
+ }
+
+ if (attributes & ZFS_OFFLINE) {
+ strcat(buff, U_OFFLINE_SHORT);
+ strcat(buff, SEPARATOR);
+ }
+
+ if (attributes & ZFS_READONLY) {
+ strcat(buff, U_RDONLY);
+ strcat(buff, SEPARATOR);
+ }
+
+ if (attributes & ZFS_SPARSE) {
+ strcat(buff, U_SPARSE_SHORT);
+ strcat(buff, SEPARATOR);
+ }
+
+ if (attributes & ZFS_SYSTEM) {
+ strcat(buff, U_SYSTEM_SHORT);
+ strcat(buff, SEPARATOR);
+ }
+
+ if (attributes & ZFS_REPARSE) {
+ strcat(buff, U_REPARSE_SHORT);
+ strcat(buff, SEPARATOR);
+ }
+
+ if (buff[0] == '\0')
+ strcat(buff, NO_ATTRIBUTE);
+ else
+ buff[strlen(buff) - 1] = '\0';
+}
+
+int
+main(int argc, const char * const argv[])
+{
+ if (argc != 2)
+ errx(EXIT_FAILURE, "Usage: %s filepath", argv[0]);
+
+ int fd = open(argv[1], O_RDWR | O_APPEND);
+ if (fd < 0)
+ err(EXIT_FAILURE, "Failed to open %s", argv[1]);
+
+ uint64_t dosflags = 0;
+ if (ioctl(fd, ZFS_IOC_GETDOSFLAGS, &dosflags) == -1)
+ err(EXIT_FAILURE, "ZFS_IOC_GETDOSFLAGS failed");
+
+ (void) close(fd);
+
+ char buffer[BUFFER_SIZE];
+ memset(buffer, 0, BUFFER_SIZE);
+
+ (void) attribute_to_str(dosflags, buffer);
+
+ (void) printf("%s\n", buffer);
+
+ return (EXIT_SUCCESS);
+}
--- /dev/null
+/write_dos_attributes
--- /dev/null
+include $(top_srcdir)/config/Rules.am
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
+
+pkgexec_PROGRAMS = write_dos_attributes
+write_dos_attributes_SOURCES = write_dos_attributes.c
--- /dev/null
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2022 iXsystems, Inc.
+ */
+
+/*
+ * FreeBSD allows to update and retreive additional file level attributes.
+ * For Linux, two IOCTLs have been added to update and retrieve additional
+ * level attributes.
+ *
+ * This application updates additional file level attributes on a given
+ * file. FreeBSD keywords can be used to specify the flag.
+ *
+ * Usage: 'write_dos_attributes flag filepath'
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <err.h>
+#include <sys/fs/zfs.h>
+#include <string.h>
+#include <ctype.h>
+
+#define SU_ARCH_SHORT "arch"
+#define SU_ARCH_FULL "archived"
+#define SU_NODUMP "nodump"
+#define SU_APPEND_SHORT "sappnd"
+#define SU_APPEND_FULL "sappend"
+#define SU_IMMUTABLE "schg"
+#define SU_IMMUTABLE_SHORT "schange"
+#define SU_IMMUTABLE_FULL "simmutable"
+#define SU_UNLINK_SHORT "sunlnk"
+#define SU_UNLINK_FULL "sunlink"
+#define U_APPEND_SHORT "uappnd"
+#define U_APPEND_FULL "uappend"
+#define U_ARCH_SHORT "uarch"
+#define U_ARCH_FULL "uarchive"
+#define U_IMMUTABLE "uchg"
+#define U_IMMUTABLE_SHORT "uchange"
+#define U_IMMUTABLE_FULL "uimmutable"
+#define U_HIDDEN_SHORT "hidden"
+#define U_HIDDEN_FULL "uhidden"
+#define U_OFFLINE_SHORT "offline"
+#define U_OFFLINE_FULL "uoffline"
+#define U_RDONLY "rdonly"
+#define U_RDONLY_SHORT "urdonly"
+#define U_RDONLY_FULL "readonly"
+#define U_SPARSE_SHORT "sparse"
+#define U_SPARSE_FULL "usparse"
+#define U_SYSTEM_SHORT "system"
+#define U_SYSTEM_FULL "usystem"
+#define U_REPARSE_SHORT "reparse"
+#define U_REPARSE_FULL "ureparse"
+#define U_UNLINK_SHORT "uunlnk"
+#define U_UNLINK_FULL "uunlink"
+#define UNSET_NODUMP "dump"
+
+#define IS_NO(s) (s[0] == 'n' && s[1] == 'o')
+
+uint64_t str_to_attribute(char *str);
+
+uint64_t
+str_to_attribute(char *str)
+{
+ if ((strcmp(str, SU_ARCH_SHORT) == 0) ||
+ (strcmp(str, SU_ARCH_FULL) == 0) ||
+ (strcmp(str, U_ARCH_SHORT) == 0) ||
+ (strcmp(str, U_ARCH_FULL) == 0))
+ return (ZFS_ARCHIVE);
+
+ else if ((strcmp(str, SU_APPEND_SHORT) == 0) ||
+ (strcmp(str, SU_APPEND_FULL) == 0) ||
+ (strcmp(str, U_APPEND_SHORT) == 0) ||
+ (strcmp(str, U_APPEND_FULL) == 0))
+ return (ZFS_APPENDONLY);
+
+ else if ((strcmp(str, SU_IMMUTABLE) == 0) ||
+ (strcmp(str, SU_IMMUTABLE_SHORT) == 0) ||
+ (strcmp(str, SU_IMMUTABLE_FULL) == 0))
+ return (ZFS_IMMUTABLE);
+
+ else if ((strcmp(str, SU_UNLINK_SHORT) == 0) ||
+ (strcmp(str, SU_UNLINK_FULL) == 0) ||
+ (strcmp(str, U_UNLINK_SHORT) == 0) ||
+ (strcmp(str, SU_UNLINK_FULL) == 0))
+ return (ZFS_NOUNLINK);
+
+ else if ((strcmp(str, U_HIDDEN_SHORT) == 0) ||
+ (strcmp(str, U_HIDDEN_FULL) == 0))
+ return (ZFS_HIDDEN);
+
+ else if ((strcmp(str, U_OFFLINE_SHORT) == 0) ||
+ (strcmp(str, U_OFFLINE_FULL) == 0))
+ return (ZFS_OFFLINE);
+
+ else if ((strcmp(str, U_RDONLY) == 0) ||
+ (strcmp(str, U_RDONLY_SHORT) == 0) ||
+ (strcmp(str, U_RDONLY_FULL) == 0))
+ return (ZFS_READONLY);
+
+ else if ((strcmp(str, U_SPARSE_SHORT) == 0) ||
+ (strcmp(str, U_SPARSE_FULL) == 0))
+ return (ZFS_SPARSE);
+
+ else if ((strcmp(str, U_SYSTEM_SHORT) == 0) ||
+ (strcmp(str, U_SYSTEM_FULL) == 0))
+ return (ZFS_SYSTEM);
+
+ else if ((strcmp(str, U_REPARSE_SHORT) == 0) ||
+ (strcmp(str, U_REPARSE_FULL) == 0))
+ return (ZFS_REPARSE);
+
+ return (-1);
+}
+
+int
+main(int argc, const char * const argv[])
+{
+ if (argc != 3)
+ errx(EXIT_FAILURE, "Usage: %s flag filepath", argv[0]);
+
+ uint8_t unset, unset_all;
+ uint64_t attribute, dosflags;
+ char *flag = strdup(argv[1]);
+ unset = unset_all = 0;
+ attribute = dosflags = 0;
+
+ // convert the flag to lower case
+ for (int i = 0; i < strlen(argv[1]); ++i)
+ flag[i] = tolower((unsigned char) flag[i]);
+
+ // check if flag starts with 'no'
+ if (IS_NO(flag)) {
+ if (strcmp(flag, SU_NODUMP) == 0) {
+ attribute = ZFS_NODUMP;
+ } else {
+ attribute = str_to_attribute(flag + 2);
+ unset = 1;
+ }
+ }
+ // check if '0' was passed
+ else if (strcmp(flag, "0") == 0) {
+ unset_all = 1;
+ }
+ // check if the flag is 'dump'
+ else if (strcmp(flag, UNSET_NODUMP) == 0) {
+ attribute = ZFS_NODUMP;
+ unset = 1;
+ } else {
+ attribute = str_to_attribute(flag);
+ }
+
+ if (attribute == -1)
+ errx(EXIT_FAILURE, "Invalid Flag %s", argv[1]);
+
+ int fd = open(argv[2], O_RDWR | O_APPEND);
+ if (fd < 0)
+ err(EXIT_FAILURE, "Failed to open %s", argv[2]);
+
+ if (ioctl(fd, ZFS_IOC_GETDOSFLAGS, &dosflags) == -1)
+ err(EXIT_FAILURE, "ZFS_IOC_GETDOSFLAGS failed");
+
+ if (unset == 0 && attribute != 0)
+ attribute |= dosflags;
+ else if (unset == 1 && attribute != 0)
+ attribute = dosflags & (~attribute);
+ else if (unset_all == 1)
+ attribute = 0;
+
+ // set the attribute/s
+ if (ioctl(fd, ZFS_IOC_SETDOSFLAGS, &attribute) == -1)
+ err(EXIT_FAILURE, "ZFS_IOC_SETDOSFLAGS failed");
+
+ // get the attributes to confirm
+ dosflags = -1;
+ if (ioctl(fd, ZFS_IOC_GETDOSFLAGS, &dosflags) == -1)
+ err(EXIT_FAILURE, "ZFS_IOC_GETDOSFLAGS failed");
+
+ (void) close(fd);
+
+ if (dosflags != attribute)
+ errx(EXIT_FAILURE, "Could not set %s attribute", argv[1]);
+
+ (void) printf("New Dos Flags: 0x%llx\n", (u_longlong_t)dosflags);
+
+ return (EXIT_SUCCESS);
+}
randfree_file
randwritecomp
readmmap
+ read_dos_attributes
rename_dir
rm_lnkcnt_zero_file
send_doall
threadsappend
user_ns_exec
+ write_dos_attributes
xattrtest
stride_dd'
deadman \
delegate \
devices \
+ dos_attributes \
events \
exec \
fallocate \
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/acl/off
-if BUILD_FREEBSD
pkgexec_PROGRAMS = dosmode_readonly_write
dosmode_readonly_write_SOURCES = dosmode_readonly_write.c
-endif
# DESCRIPTION:
# Verify that DOS mode flags function correctly.
#
-# These flags are not currently exposed on Linux, so the test is
-# only useful on FreeBSD.
#
# STRATEGY:
# 1. ARCHIVE
typeset flag=$1
typeset path=$2
- ls -lo $path | awk '{ gsub(",", "\n", $5); print $5 }' | grep -qxF $flag
+ if is_linux; then
+ read_dos_attributes $path | awk \
+ '{ gsub(",", "\n", $1); print $1 }' | grep -qxF $flag
+ else
+ ls -lo $path | awk '{ gsub(",", "\n", $5); print $5 }' | \
+ grep -qxF $flag
+ fi
}
log_assert "Verify DOS mode flags function correctly"
owner=$ZFS_ACL_STAFF1
other=$ZFS_ACL_STAFF2
+if is_linux; then
+ changeflags=write_dos_attributes
+else
+ changeflags=chflags
+fi
+
#
# ARCHIVE
#
#
log_must touch $testfile
log_must hasflag uarch $testfile
-log_must chflags nouarch $testfile
+log_must $changeflags nouarch $testfile
log_must hasflag - $testfile
log_must touch $testfile
-log_must hasflag uarch $testfile
+if ! is_linux; then
+ log_must hasflag uarch $testfile
+fi
log_must rm $testfile
log_must user_run $owner touch $testfile
log_must hasflag uarch $testfile
-log_must user_run $owner chflags nouarch $testfile
-log_mustnot user_run $other chflags uarch $testfile
+log_must user_run $owner $changeflags nouarch $testfile
+log_mustnot user_run $other $changeflags uarch $testfile
log_must hasflag - $testfile
log_must user_run $owner touch $testfile
-log_mustnot user_run $other chflags nouarch $testfile
-log_must hasflag uarch $testfile
+log_mustnot user_run $other $changeflags nouarch $testfile
+if ! is_linux; then
+ log_must hasflag uarch $testfile
+fi
log_must user_run $owner rm $testfile
#
# HIDDEN
#
log_must touch $testfile
-log_must chflags hidden $testfile
+log_must $changeflags hidden $testfile
log_must hasflag hidden $testfile
-log_must chflags 0 $testfile
+log_must $changeflags 0 $testfile
log_must hasflag - $testfile
log_must rm $testfile
log_must user_run $owner touch $testfile
-log_must user_run $owner chflags hidden $testfile
-log_mustnot user_run $other chflags nohidden $testfile
+log_must user_run $owner $changeflags hidden $testfile
+log_mustnot user_run $other $changeflags nohidden $testfile
log_must hasflag hidden $testfile
-log_must user_run $owner chflags 0 $testfile
-log_mustnot user_run $other chflags hidden $testfile
+log_must user_run $owner $changeflags 0 $testfile
+log_mustnot user_run $other $changeflags hidden $testfile
log_must hasflag - $testfile
log_must user_run $owner rm $testfile
# OFFLINE
#
log_must touch $testfile
-log_must chflags offline $testfile
+log_must $changeflags offline $testfile
log_must hasflag offline $testfile
-log_must chflags 0 $testfile
+log_must $changeflags 0 $testfile
log_must hasflag - $testfile
log_must rm $testfile
log_must user_run $owner touch $testfile
-log_must user_run $owner chflags offline $testfile
-log_mustnot user_run $other chflags nooffline $testfile
+log_must user_run $owner $changeflags offline $testfile
+log_mustnot user_run $other $changeflags nooffline $testfile
log_must hasflag offline $testfile
-log_must user_run $owner chflags 0 $testfile
-log_mustnot user_run $other chflags offline $testfile
+log_must user_run $owner $changeflags 0 $testfile
+log_mustnot user_run $other $changeflags offline $testfile
log_must hasflag - $testfile
log_must user_run $owner rm $testfile
# but root is always allowed the operation.
#
log_must touch $testfile
-log_must chflags rdonly $testfile
+log_must $changeflags rdonly $testfile
log_must hasflag rdonly $testfile
log_must eval "echo 'root write allowed' >> $testfile"
log_must cat $testfile
-log_must chflags 0 $testfile
-log_must hasflag - $tesfile
+log_must $changeflags 0 $testfile
+log_must hasflag - $testfile
log_must rm $testfile
# It is required to still be able to write to an fd that was opened RW before
# READONLY is set. We have a special test program for that.
log_must user_run $owner touch $testfile
-log_mustnot user_run $other chflags rdonly $testfile
+log_mustnot user_run $other $changeflags rdonly $testfile
log_must user_run $owner $tests_base/dosmode_readonly_write $testfile
-log_mustnot user_run $other chflags nordonly $testfile
+log_mustnot user_run $other $changeflags nordonly $testfile
log_must hasflag rdonly $testfile
-log_mustnot user_run $owner "echo 'user write forbidden' >> $testfile"
+if ! is_linux; then
+ log_mustnot user_run $owner "echo 'user write forbidden' >> $testfile"
+fi
log_must eval "echo 'root write allowed' >> $testfile"
# We are still allowed to read and remove the file when READONLY is set.
log_must user_run $owner cat $testfile
#
# REPARSE
#
-# FIXME: does not work, not sure if broken or testing wrong
-#
+# not allowed to be changed
#
# SPARSE
#
log_must truncate -s 1m $testfile
-log_must chflags sparse $testfile
+log_must $changeflags sparse $testfile
log_must hasflag sparse $testfile
-log_must chflags 0 $testfile
+log_must $changeflags 0 $testfile
log_must hasflag - $testfile
log_must rm $testfile
log_must user_run $owner truncate -s 1m $testfile
-log_must user_run $owner chflags sparse $testfile
-log_mustnot user_run $other chflags nosparse $testfile
+log_must user_run $owner $changeflags sparse $testfile
+log_mustnot user_run $other $changeflags nosparse $testfile
log_must hasflag sparse $testfile
-log_must user_run $owner chflags 0 $testfile
-log_mustnot user_run $other chflags sparse $testfile
+log_must user_run $owner $changeflags 0 $testfile
+log_mustnot user_run $other $changeflags sparse $testfile
log_must hasflag - $testfile
log_must user_run $owner rm $testfile
# SYSTEM
#
log_must touch $testfile
-log_must chflags system $testfile
+log_must $changeflags system $testfile
log_must hasflag system $testfile
-log_must chflags 0 $testfile
+log_must $changeflags 0 $testfile
log_must hasflag - $testfile
log_must rm $testfile
log_must user_run $owner touch $testfile
-log_must user_run $owner chflags system $testfile
-log_mustnot user_run $other chflags nosystem $testfile
+log_must user_run $owner $changeflags system $testfile
+log_mustnot user_run $other $changeflags nosystem $testfile
log_must hasflag system $testfile
-log_must user_run $owner chflags 0 $testfile
-log_mustnot user_run $other chflags system $testfile
+log_must user_run $owner $changeflags 0 $testfile
+log_mustnot user_run $other $changeflags system $testfile
log_must hasflag - $testfile
log_must user_run $owner rm $testfile
#include <string.h>
#include <unistd.h>
+#ifdef __linux__
+#include <stdint.h>
+#include <sys/fs/zfs.h>
+#endif
+
int
main(int argc, const char *argv[])
{
fd = open(path, O_CREAT|O_RDWR, 0777);
if (fd == -1)
err(EXIT_FAILURE, "%s: open failed", path);
+#ifdef __linux__
+ uint64_t dosflags = ZFS_READONLY;
+ if (ioctl(fd, ZFS_IOC_SETDOSFLAGS, &dosflags) == -1)
+ err(EXIT_FAILURE, "%s: ZFS_IOC_SETDOSFLAGS failed", path);
+#else
if (chflags(path, UF_READONLY) == -1)
err(EXIT_FAILURE, "%s: chflags failed", path);
+#endif
if (write(fd, buf, strlen(buf)) == -1)
err(EXIT_FAILURE, "%s: write failed", path);
if (close(fd) == -1)
--- /dev/null
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/dos_attributes
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ read_dos_attrs_001.ksh \
+ write_dos_attrs_001.ksh \
+ setup.ksh
--- /dev/null
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
--- /dev/null
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# Read additional file level attributes stored in upper half of z_pflags
+#
+# STARTEGY:
+# 1) Create a file
+# 2) Execute read_dos_attributes on the file we created
+# 3) Verify that read_dos_attributes exited successfully
+#
+
+verify_runnable "global"
+
+FILETOTEST="$TESTDIR/test_read_dos_attrs.txt"
+
+function cleanup
+{
+ rm -f $FILETOTEST
+}
+
+log_onexit cleanup
+
+log_must chmod 777 $TESTDIR
+log_must eval "echo 'This is a test file.' > $FILETOTEST"
+log_must read_dos_attributes $FILETOTEST
+
+log_pass "reading DOS attributes succeeded."
--- /dev/null
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
--- /dev/null
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# Write additional file level attributes stored in upper half of z_pflags
+#
+# STARTEGY:
+# 1) Create a file
+# 2) Execute write_dos_attributes on the file we created
+# 3) Verify that write_dos_attributes exited successfully
+#
+
+verify_runnable "global"
+
+FILETOTEST="$TESTDIR/test_write_dos_attrs.txt"
+
+function cleanup
+{
+ rm -f $FILETOTEST
+}
+
+log_onexit cleanup
+
+log_must chmod 777 $TESTDIR
+log_must eval "echo 'This is a test file.' > $FILETOTEST"
+log_must write_dos_attributes offline $FILETOTEST
+log_must write_dos_attributes nooffline $FILETOTEST
+
+log_pass "writing DOS attributes succeeded."