1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2022 iXsystems, Inc. 14 */ 15 16 /* 17 * FreeBSD exposes additional file attributes via ls -o and chflags. 18 * Under Linux, we provide ZFS_IOC_[GS]ETDOSFLAGS ioctl()s. 19 * 20 * This application is equivalent to FreeBSD chflags. 21 */ 22 23 #include <err.h> 24 #include <fcntl.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <stdbool.h> 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <sys/ioctl.h> 31 #include <sys/fs/zfs.h> 32 #include "dos_attributes.h" 33 34 int 35 main(int argc, const char *const *argv) 36 { 37 if (argc != 3) 38 errx(EXIT_FAILURE, "usage: %s flag file", argv[0]); 39 40 bool unset = false; 41 uint64_t attr = 0; 42 const char *flag = argv[1]; 43 if (strcmp(flag, "0") == 0) 44 ; 45 else if (strcmp(flag, SU_NODUMP) == 0) 46 attr = ZFS_NODUMP; 47 else if (strcmp(flag, UNSET_NODUMP) == 0) { 48 attr = ZFS_NODUMP; 49 unset = true; 50 } else { 51 if (strncmp(flag, "no", 2) == 0) { 52 unset = true; 53 flag += 2; 54 } 55 for (size_t i = 0; i < ARRAY_SIZE(all_dos_attribute_names); ++i) 56 for (const char *const *nm = all_dos_attribute_names[i]; 57 *nm; ++nm) 58 if (strcmp(flag, *nm) == 0) { 59 attr = all_dos_attributes[i]; 60 goto found; 61 } 62 63 errx(EXIT_FAILURE, "%s: unknown flag", argv[1]); 64 found:; 65 } 66 67 int fd = open(argv[2], O_RDWR | O_APPEND | O_CLOEXEC); 68 if (fd == -1) 69 err(EXIT_FAILURE, "%s", argv[2]); 70 71 uint64_t flags; 72 if (ioctl(fd, ZFS_IOC_GETDOSFLAGS, &flags) == -1) 73 err(EXIT_FAILURE, "ZFS_IOC_GETDOSFLAGS"); 74 75 if (attr == 0) 76 flags = 0; 77 else if (unset) 78 flags &= ~attr; 79 else 80 flags |= attr; 81 82 if (ioctl(fd, ZFS_IOC_SETDOSFLAGS, &flags) == -1) 83 err(EXIT_FAILURE, "ZFS_IOC_SETDOSFLAGS"); 84 85 uint64_t newflags; 86 if (ioctl(fd, ZFS_IOC_GETDOSFLAGS, &newflags) == -1) 87 err(EXIT_FAILURE, "second ZFS_IOC_GETDOSFLAGS"); 88 89 if (newflags != flags) 90 errx(EXIT_FAILURE, "expecting %#" PRIx64 ", got %#" PRIx64 91 "; %ssetting %#" PRIx64 "", 92 flags, newflags, unset ? "un" : "", attr); 93 94 (void) printf("%#" PRIx64 "\n", flags); 95 } 96