blob: 030978f64b236789438d09531800e00a5bf6f49c
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * Display or change file attributes on a fat file system |
4 | * |
5 | * Copyright 2005 H. Peter Anvin |
6 | * Busybox'ed (2014) by Pascal Bellard <pascal.bellard@ads-lu.com> |
7 | * |
8 | * This file can be redistributed under the terms of the GNU General |
9 | * Public License |
10 | */ |
11 | //config:config FATATTR |
12 | //config: bool "fatattr" |
13 | //config: default y |
14 | //config: select PLATFORM_LINUX |
15 | //config: help |
16 | //config: fatattr lists or changes the file attributes on a fat file system. |
17 | |
18 | //applet:IF_FATATTR(APPLET(fatattr, BB_DIR_BIN, BB_SUID_DROP)) |
19 | |
20 | //kbuild:lib-$(CONFIG_FATATTR) += fatattr.o |
21 | |
22 | //usage:#define fatattr_trivial_usage |
23 | //usage: "[-+rhsvda] FILE..." |
24 | //usage:#define fatattr_full_usage "\n\n" |
25 | //usage: "Change file attributes on FAT filesystem\n" |
26 | //usage: "\n - Clear attributes" |
27 | //usage: "\n + Set attributes" |
28 | //usage: "\n r Read only" |
29 | //usage: "\n h Hidden" |
30 | //usage: "\n s System" |
31 | //usage: "\n v Volume label" |
32 | //usage: "\n d Directory" |
33 | //usage: "\n a Archive" |
34 | |
35 | #include "libbb.h" |
36 | /* linux/msdos_fs.h says: */ |
37 | #ifndef FAT_IOCTL_GET_ATTRIBUTES |
38 | # define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, uint32_t) |
39 | # define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, uint32_t) |
40 | #endif |
41 | |
42 | /* Currently supports only the FAT flags, not the NTFS ones. |
43 | * Extra space at the end is a hack to print space separator in file listing. |
44 | * Let's hope no one ever passes space as an option char :) |
45 | */ |
46 | static const char bit_to_char[] ALIGN1 = "rhsvda67 "; |
47 | |
48 | static inline unsigned long get_flag(char c) |
49 | { |
50 | const char *fp = strchr(bit_to_char, c); |
51 | if (!fp) |
52 | bb_error_msg_and_die("invalid character '%c'", c); |
53 | return 1 << (fp - bit_to_char); |
54 | } |
55 | |
56 | static unsigned decode_arg(const char *arg) |
57 | { |
58 | unsigned fl = 0; |
59 | while (*++arg) |
60 | fl |= get_flag(*arg); |
61 | return fl; |
62 | } |
63 | |
64 | int fatattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
65 | int fatattr_main(int argc UNUSED_PARAM, char **argv) |
66 | { |
67 | unsigned set_mask = 0; |
68 | unsigned clear_mask = 0; |
69 | |
70 | for (;;) { |
71 | unsigned fl; |
72 | char *arg = *++argv; |
73 | |
74 | if (!arg) |
75 | bb_show_usage(); |
76 | if (arg[0] != '-' && arg[0] != '+') |
77 | break; |
78 | fl = decode_arg(arg); |
79 | if (arg[0] == '+') |
80 | set_mask |= fl; |
81 | else |
82 | clear_mask |= fl; |
83 | } |
84 | |
85 | do { |
86 | int fd, i; |
87 | uint32_t attr; |
88 | |
89 | fd = xopen(*argv, O_RDONLY); |
90 | xioctl(fd, FAT_IOCTL_GET_ATTRIBUTES, &attr); |
91 | attr = (attr | set_mask) & ~clear_mask; |
92 | if (set_mask | clear_mask) |
93 | xioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr); |
94 | else { |
95 | for (i = 0; bit_to_char[i]; i++) { |
96 | bb_putchar((attr & 1) ? bit_to_char[i] : ' '); |
97 | attr >>= 1; |
98 | } |
99 | puts(*argv); |
100 | } |
101 | close(fd); |
102 | } while (*++argv); |
103 | |
104 | return EXIT_SUCCESS; |
105 | } |
106 |