aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorнаб <[email protected]>2022-03-12 04:30:22 +0100
committerBrian Behlendorf <[email protected]>2022-04-01 17:58:17 -0700
commitcaeab993ec77ce15bcb25484017ff18f18a6550b (patch)
treeca2bcfa167e199e2317741f059cc54a25cde3f09
parentd30577c9dd811688f2609ad532b011b99bceb485 (diff)
tests: {read,write}_dos_attributes: despaghettify
Also: actually accept all the flags in write_d_a Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: John Kennedy <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Signed-off-by: Ahelenia Ziemiańska <[email protected]> Closes #13259
-rw-r--r--configure.ac3
-rw-r--r--tests/zfs-tests/cmd/Makefile.am3
-rw-r--r--tests/zfs-tests/cmd/linux_dos_attributes/.gitignore (renamed from tests/zfs-tests/cmd/write_dos_attributes/.gitignore)1
-rw-r--r--tests/zfs-tests/cmd/linux_dos_attributes/Makefile.am (renamed from tests/zfs-tests/cmd/write_dos_attributes/Makefile.am)4
-rw-r--r--tests/zfs-tests/cmd/linux_dos_attributes/dos_attributes.h82
-rw-r--r--tests/zfs-tests/cmd/linux_dos_attributes/read_dos_attributes.c60
-rw-r--r--tests/zfs-tests/cmd/linux_dos_attributes/write_dos_attributes.c95
-rw-r--r--tests/zfs-tests/cmd/read_dos_attributes/.gitignore1
-rw-r--r--tests/zfs-tests/cmd/read_dos_attributes/Makefile.am6
-rw-r--r--tests/zfs-tests/cmd/read_dos_attributes/read_dos_attributes.c166
-rw-r--r--tests/zfs-tests/cmd/write_dos_attributes/write_dos_attributes.c201
11 files changed, 243 insertions, 379 deletions
diff --git a/configure.ac b/configure.ac
index 990958baf..04fbb491a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -226,14 +226,13 @@ AC_CONFIG_FILES([
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/linux_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
diff --git a/tests/zfs-tests/cmd/Makefile.am b/tests/zfs-tests/cmd/Makefile.am
index 88d8c8cf0..fb49edd3a 100644
--- a/tests/zfs-tests/cmd/Makefile.am
+++ b/tests/zfs-tests/cmd/Makefile.am
@@ -34,8 +34,7 @@ if BUILD_LINUX
SUBDIRS += \
getversion \
randfree_file \
- read_dos_attributes \
+ linux_dos_attributes \
user_ns_exec \
- write_dos_attributes \
xattrtest
endif
diff --git a/tests/zfs-tests/cmd/write_dos_attributes/.gitignore b/tests/zfs-tests/cmd/linux_dos_attributes/.gitignore
index f3949ac82..14a62551d 100644
--- a/tests/zfs-tests/cmd/write_dos_attributes/.gitignore
+++ b/tests/zfs-tests/cmd/linux_dos_attributes/.gitignore
@@ -1 +1,2 @@
+/read_dos_attributes
/write_dos_attributes
diff --git a/tests/zfs-tests/cmd/write_dos_attributes/Makefile.am b/tests/zfs-tests/cmd/linux_dos_attributes/Makefile.am
index c297fd49e..2e383e94f 100644
--- a/tests/zfs-tests/cmd/write_dos_attributes/Makefile.am
+++ b/tests/zfs-tests/cmd/linux_dos_attributes/Makefile.am
@@ -2,5 +2,7 @@ include $(top_srcdir)/config/Rules.am
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
-pkgexec_PROGRAMS = write_dos_attributes
+EXTRA_DIST = dos_attributes.h
+pkgexec_PROGRAMS = read_dos_attributes write_dos_attributes
+read_dos_attributes_SOURCES = read_dos_attributes.c
write_dos_attributes_SOURCES = write_dos_attributes.c
diff --git a/tests/zfs-tests/cmd/linux_dos_attributes/dos_attributes.h b/tests/zfs-tests/cmd/linux_dos_attributes/dos_attributes.h
new file mode 100644
index 000000000..dd3a820ff
--- /dev/null
+++ b/tests/zfs-tests/cmd/linux_dos_attributes/dos_attributes.h
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: 0BSD
+
+#include <inttypes.h>
+
+
+#define U_APPEND_SHORT "uappnd"
+#define U_APPEND_FULL "uappend"
+#define SU_APPEND_SHORT "sappnd"
+#define SU_APPEND_FULL "sappend"
+
+#define U_ARCH_SHORT "uarch"
+#define U_ARCH_FULL "uarchive"
+#define SU_ARCH_SHORT "arch"
+#define SU_ARCH_FULL "archived"
+
+#define U_HIDDEN_SHORT "hidden"
+#define U_HIDDEN_FULL "uhidden"
+
+#define SU_IMMUTABLE_FULL "simmutable"
+#define SU_IMMUTABLE_SHORT "schange"
+#define SU_IMMUTABLE "schg"
+#define U_IMMUTABLE_FULL "uimmutable"
+#define U_IMMUTABLE_SHORT "uchange"
+#define U_IMMUTABLE "uchg"
+
+#define SU_NODUMP "nodump"
+#define UNSET_NODUMP "dump"
+
+#define U_UNLINK_SHORT "uunlnk"
+#define U_UNLINK_FULL "uunlink"
+#define SU_UNLINK_SHORT "sunlnk"
+#define SU_UNLINK_FULL "sunlink"
+
+#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_REPARSE_SHORT "reparse"
+#define U_REPARSE_FULL "ureparse"
+
+#define U_SPARSE_SHORT "sparse"
+#define U_SPARSE_FULL "usparse"
+
+#define U_SYSTEM_SHORT "system"
+#define U_SYSTEM_FULL "usystem"
+
+
+static const uint64_t all_dos_attributes[] = {
+ ZFS_ARCHIVE,
+ ZFS_APPENDONLY,
+ ZFS_IMMUTABLE,
+ ZFS_NOUNLINK,
+ ZFS_NODUMP,
+ ZFS_HIDDEN,
+ ZFS_OFFLINE,
+ ZFS_READONLY,
+ ZFS_SPARSE,
+ ZFS_SYSTEM,
+ ZFS_REPARSE,
+};
+
+static const char *const all_dos_attribute_names[][7] = {
+ {U_ARCH_SHORT, U_ARCH_FULL, SU_ARCH_SHORT, SU_ARCH_FULL},
+ {U_APPEND_SHORT, U_APPEND_FULL, SU_APPEND_SHORT, SU_APPEND_FULL},
+ {SU_IMMUTABLE_FULL, SU_IMMUTABLE_SHORT, SU_IMMUTABLE,
+ U_IMMUTABLE_FULL, U_IMMUTABLE_SHORT, U_IMMUTABLE},
+ {U_UNLINK_SHORT, U_UNLINK_FULL, SU_UNLINK_FULL, SU_UNLINK_SHORT},
+ {SU_NODUMP, /* UNSET_NODUMP */},
+ {U_HIDDEN_SHORT, U_HIDDEN_FULL},
+ {U_OFFLINE_SHORT, U_OFFLINE_FULL},
+ {U_RDONLY, U_RDONLY_SHORT, U_RDONLY_FULL},
+ {U_SPARSE_SHORT, U_SPARSE_FULL},
+ {U_SYSTEM_SHORT, U_SYSTEM_FULL},
+ {U_REPARSE_SHORT, U_REPARSE_FULL},
+};
+
+_Static_assert(
+ ARRAY_SIZE(all_dos_attributes) == ARRAY_SIZE(all_dos_attribute_names),
+ "attribute list length mismatch");
diff --git a/tests/zfs-tests/cmd/linux_dos_attributes/read_dos_attributes.c b/tests/zfs-tests/cmd/linux_dos_attributes/read_dos_attributes.c
new file mode 100644
index 000000000..078211405
--- /dev/null
+++ b/tests/zfs-tests/cmd/linux_dos_attributes/read_dos_attributes.c
@@ -0,0 +1,60 @@
+/*
+ * 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 exposes additional file attributes via ls -o and chflags.
+ * Under Linux, we provide ZFS_IOC_[GS]ETDOSFLAGS ioctl()s.
+ *
+ * This application is the equivalent to FreeBSD ls -lo $1 | awk '{print $5}'.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/fs/zfs.h>
+#include "dos_attributes.h"
+
+int
+main(int argc, const char *const *argv)
+{
+ if (argc != 2)
+ errx(EXIT_FAILURE, "usage: %s file", argv[0]);
+
+ int fd = open(argv[1], O_RDONLY | O_CLOEXEC);
+ if (fd == -1)
+ err(EXIT_FAILURE, "%s", argv[1]);
+
+ uint64_t flags;
+ if (ioctl(fd, ZFS_IOC_GETDOSFLAGS, &flags) == -1)
+ err(EXIT_FAILURE, "ZFS_IOC_GETDOSFLAGS");
+
+ bool any = false;
+ for (size_t i = 0; i < ARRAY_SIZE(all_dos_attributes); ++i)
+ if (flags & all_dos_attributes[i]) {
+ if (any)
+ putchar(',');
+ (void) fputs(*all_dos_attribute_names[i], stdout);
+ any = true;
+ }
+ if (any)
+ (void) putchar('\n');
+ else
+ (void) puts("-");
+}
diff --git a/tests/zfs-tests/cmd/linux_dos_attributes/write_dos_attributes.c b/tests/zfs-tests/cmd/linux_dos_attributes/write_dos_attributes.c
new file mode 100644
index 000000000..3cea7d4b1
--- /dev/null
+++ b/tests/zfs-tests/cmd/linux_dos_attributes/write_dos_attributes.c
@@ -0,0 +1,95 @@
+/*
+ * 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 exposes additional file attributes via ls -o and chflags.
+ * Under Linux, we provide ZFS_IOC_[GS]ETDOSFLAGS ioctl()s.
+ *
+ * This application is equivalent to FreeBSD chflags.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/fs/zfs.h>
+#include "dos_attributes.h"
+
+int
+main(int argc, const char *const *argv)
+{
+ if (argc != 3)
+ errx(EXIT_FAILURE, "usage: %s flag file", argv[0]);
+
+ bool unset = false;
+ uint64_t attr = 0;
+ const char *flag = argv[1];
+ if (strcmp(flag, "0") == 0)
+ ;
+ else if (strcmp(flag, SU_NODUMP) == 0)
+ attr = ZFS_NODUMP;
+ else if (strcmp(flag, UNSET_NODUMP) == 0) {
+ attr = ZFS_NODUMP;
+ unset = true;
+ } else {
+ if (strncmp(flag, "no", 2) == 0) {
+ unset = true;
+ flag += 2;
+ }
+ for (size_t i = 0; i < ARRAY_SIZE(all_dos_attribute_names); ++i)
+ for (const char *const *nm = all_dos_attribute_names[i];
+ *nm; ++nm)
+ if (strcmp(flag, *nm) == 0) {
+ attr = all_dos_attributes[i];
+ goto found;
+ }
+
+ errx(EXIT_FAILURE, "%s: unknown flag", argv[1]);
+found:;
+ }
+
+ int fd = open(argv[2], O_RDWR | O_APPEND | O_CLOEXEC);
+ if (fd == -1)
+ err(EXIT_FAILURE, "%s", argv[2]);
+
+ uint64_t flags;
+ if (ioctl(fd, ZFS_IOC_GETDOSFLAGS, &flags) == -1)
+ err(EXIT_FAILURE, "ZFS_IOC_GETDOSFLAGS");
+
+ if (attr == 0)
+ flags = 0;
+ else if (unset)
+ flags &= ~attr;
+ else
+ flags |= attr;
+
+ if (ioctl(fd, ZFS_IOC_SETDOSFLAGS, &flags) == -1)
+ err(EXIT_FAILURE, "ZFS_IOC_SETDOSFLAGS");
+
+ uint64_t newflags;
+ if (ioctl(fd, ZFS_IOC_GETDOSFLAGS, &newflags) == -1)
+ err(EXIT_FAILURE, "second ZFS_IOC_GETDOSFLAGS");
+
+ if (newflags != flags)
+ errx(EXIT_FAILURE, "expecting %#" PRIx64 ", got %#" PRIx64
+ "; %ssetting %#" PRIx64 "",
+ flags, newflags, unset ? "un" : "", attr);
+
+ (void) printf("%#" PRIx64 "\n", flags);
+}
diff --git a/tests/zfs-tests/cmd/read_dos_attributes/.gitignore b/tests/zfs-tests/cmd/read_dos_attributes/.gitignore
deleted file mode 100644
index 52584e4a7..000000000
--- a/tests/zfs-tests/cmd/read_dos_attributes/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/read_dos_attributes
diff --git a/tests/zfs-tests/cmd/read_dos_attributes/Makefile.am b/tests/zfs-tests/cmd/read_dos_attributes/Makefile.am
deleted file mode 100644
index 69412f05f..000000000
--- a/tests/zfs-tests/cmd/read_dos_attributes/Makefile.am
+++ /dev/null
@@ -1,6 +0,0 @@
-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
diff --git a/tests/zfs-tests/cmd/read_dos_attributes/read_dos_attributes.c b/tests/zfs-tests/cmd/read_dos_attributes/read_dos_attributes.c
deleted file mode 100644
index 36d7b31ba..000000000
--- a/tests/zfs-tests/cmd/read_dos_attributes/read_dos_attributes.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * 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] = "";
-
- (void) attribute_to_str(dosflags, buffer);
-
- (void) puts(buffer);
-
- return (EXIT_SUCCESS);
-}
diff --git a/tests/zfs-tests/cmd/write_dos_attributes/write_dos_attributes.c b/tests/zfs-tests/cmd/write_dos_attributes/write_dos_attributes.c
deleted file mode 100644
index c373d3b15..000000000
--- a/tests/zfs-tests/cmd/write_dos_attributes/write_dos_attributes.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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);
-}