aboutsummaryrefslogtreecommitdiffstats
path: root/tests/zfs-tests/cmd/linux_dos_attributes
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 /tests/zfs-tests/cmd/linux_dos_attributes
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
Diffstat (limited to 'tests/zfs-tests/cmd/linux_dos_attributes')
-rw-r--r--tests/zfs-tests/cmd/linux_dos_attributes/.gitignore2
-rw-r--r--tests/zfs-tests/cmd/linux_dos_attributes/Makefile.am8
-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
5 files changed, 247 insertions, 0 deletions
diff --git a/tests/zfs-tests/cmd/linux_dos_attributes/.gitignore b/tests/zfs-tests/cmd/linux_dos_attributes/.gitignore
new file mode 100644
index 000000000..14a62551d
--- /dev/null
+++ b/tests/zfs-tests/cmd/linux_dos_attributes/.gitignore
@@ -0,0 +1,2 @@
+/read_dos_attributes
+/write_dos_attributes
diff --git a/tests/zfs-tests/cmd/linux_dos_attributes/Makefile.am b/tests/zfs-tests/cmd/linux_dos_attributes/Makefile.am
new file mode 100644
index 000000000..2e383e94f
--- /dev/null
+++ b/tests/zfs-tests/cmd/linux_dos_attributes/Makefile.am
@@ -0,0 +1,8 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
+
+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);
+}