From caeab993ec77ce15bcb25484017ff18f18a6550b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Sat, 12 Mar 2022 04:30:22 +0100 Subject: [PATCH] tests: {read,write}_dos_attributes: despaghettify MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also: actually accept all the flags in write_d_a Reviewed-by: Brian Behlendorf Reviewed-by: John Kennedy Reviewed-by: Ryan Moeller Signed-off-by: Ahelenia ZiemiaƄska Closes #13259 --- configure.ac | 3 +- tests/zfs-tests/cmd/Makefile.am | 3 +- .../.gitignore | 1 + .../Makefile.am | 4 +- .../cmd/linux_dos_attributes/dos_attributes.h | 82 +++++++ .../read_dos_attributes.c | 60 ++++++ .../write_dos_attributes.c | 95 +++++++++ .../cmd/read_dos_attributes/.gitignore | 1 - .../cmd/read_dos_attributes/Makefile.am | 6 - .../read_dos_attributes/read_dos_attributes.c | 166 --------------- .../write_dos_attributes.c | 201 ------------------ 11 files changed, 243 insertions(+), 379 deletions(-) rename tests/zfs-tests/cmd/{write_dos_attributes => linux_dos_attributes}/.gitignore (51%) rename tests/zfs-tests/cmd/{write_dos_attributes => linux_dos_attributes}/Makefile.am (50%) create mode 100644 tests/zfs-tests/cmd/linux_dos_attributes/dos_attributes.h create mode 100644 tests/zfs-tests/cmd/linux_dos_attributes/read_dos_attributes.c create mode 100644 tests/zfs-tests/cmd/linux_dos_attributes/write_dos_attributes.c delete mode 100644 tests/zfs-tests/cmd/read_dos_attributes/.gitignore delete mode 100644 tests/zfs-tests/cmd/read_dos_attributes/Makefile.am delete mode 100644 tests/zfs-tests/cmd/read_dos_attributes/read_dos_attributes.c delete mode 100644 tests/zfs-tests/cmd/write_dos_attributes/write_dos_attributes.c diff --git a/configure.ac b/configure.ac index 990958bafa..04fbb491ad 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 88d8c8cf08..fb49edd3a5 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 similarity index 51% rename from tests/zfs-tests/cmd/write_dos_attributes/.gitignore rename to tests/zfs-tests/cmd/linux_dos_attributes/.gitignore index f3949ac828..14a62551da 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 similarity index 50% rename from tests/zfs-tests/cmd/write_dos_attributes/Makefile.am rename to tests/zfs-tests/cmd/linux_dos_attributes/Makefile.am index c297fd49e0..2e383e94f2 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 0000000000..dd3a820ff2 --- /dev/null +++ b/tests/zfs-tests/cmd/linux_dos_attributes/dos_attributes.h @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: 0BSD + +#include + + +#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 0000000000..0782114051 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#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 0000000000..3cea7d4b1c --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#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 52584e4a73..0000000000 --- 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 69412f05f6..0000000000 --- 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 36d7b31ba1..0000000000 --- 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#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 c373d3b153..0000000000 --- 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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); -}