3 Prints or changes exFAT file attributes
5 Free exFAT implementation.
6 Copyright (C) 2020-2023 Endless OS Foundation LLC
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 static void usage(const char* prog)
31 "Display current attributes:\n"
32 " %1$s -d <device> <file>\n"
35 " %1$s [FLAGS] -d <device> <file>\n"
38 " -r Set read-only flag\n"
39 " -R Clear read-only flag\n"
40 " -i Set hidden flag\n"
41 " -I Clear hidden flag\n"
42 " -s Set system flag\n"
43 " -S Clear system flag\n"
44 " -a Set archive flag\n"
45 " -A Clear archive flag\n"
47 " -h Display this help message\n"
48 " -V Display version information\n",
53 static void print_attribute(uint16_t attribs, uint16_t attrib,
56 printf("%9s: %s\n", label, (attribs & attrib) ? "yes" : "no");
59 static int attribute(struct exfat* ef, struct exfat_node* node,
60 uint16_t add_flags, uint16_t clear_flags)
62 if ((add_flags | clear_flags) != 0)
64 uint16_t attrib = node->attrib;
67 attrib &= ~clear_flags;
69 if (node->attrib != attrib)
73 node->attrib = attrib;
74 node->is_dirty = true;
76 ret = exfat_flush_node(ef, node);
79 char buffer[EXFAT_UTF8_NAME_BUFFER_MAX];
81 exfat_get_name(node, buffer);
82 exfat_error("failed to flush changes to '%s': %s", buffer,
90 print_attribute(node->attrib, EXFAT_ATTRIB_RO, "Read-only");
91 print_attribute(node->attrib, EXFAT_ATTRIB_HIDDEN, "Hidden");
92 print_attribute(node->attrib, EXFAT_ATTRIB_SYSTEM, "System");
93 print_attribute(node->attrib, EXFAT_ATTRIB_ARCH, "Archive");
94 /* read-only attributes */
95 print_attribute(node->attrib, EXFAT_ATTRIB_VOLUME, "Volume");
96 print_attribute(node->attrib, EXFAT_ATTRIB_DIR, "Directory");
102 int main(int argc, char* argv[])
106 const char* spec = NULL;
107 const char* options = "";
108 const char* file_path = NULL;
110 struct exfat_node* node;
111 uint16_t add_flags = 0;
112 uint16_t clear_flags = 0;
114 while ((opt = getopt(argc, argv, "d:rRiIsSaAhV")) != -1)
119 printf("exfatattrib %s\n", VERSION);
120 puts("Copyright (C) 2011-2023 Andrew Nayenko");
121 puts("Copyright (C) 2020-2023 Endless OS Foundation LLC");
124 The path to the unmounted exFAT partition is a (mandatory) named
125 option rather than a positional parameter. If the FUSE file system
126 ever gains an ioctl to get and set attributes, this option could be
127 made optional, and this tool taught to use the ioctl.
133 add_flags |= EXFAT_ATTRIB_RO;
136 clear_flags |= EXFAT_ATTRIB_RO;
138 /* "-h[elp]" is taken; i is the second letter of "hidden" and
139 its synonym "invisible" */
141 add_flags |= EXFAT_ATTRIB_HIDDEN;
144 clear_flags |= EXFAT_ATTRIB_HIDDEN;
147 add_flags |= EXFAT_ATTRIB_SYSTEM;
150 clear_flags |= EXFAT_ATTRIB_SYSTEM;
153 add_flags |= EXFAT_ATTRIB_ARCH;
156 clear_flags |= EXFAT_ATTRIB_ARCH;
163 if ((add_flags & clear_flags) != 0)
165 exfat_error("can't set and clear the same flag");
169 if (spec == NULL || argc - optind != 1)
172 file_path = argv[optind];
174 if ((add_flags | clear_flags) == 0)
177 ret = exfat_mount(&ef, spec, options);
180 exfat_error("failed to mount %s: %s", spec, strerror(-ret));
184 ret = exfat_lookup(&ef, &node, file_path);
187 exfat_error("failed to look up '%s': %s", file_path, strerror(-ret));
192 ret = attribute(&ef, node, add_flags, clear_flags);
194 exfat_put_node(&ef, node);