diff options
Diffstat (limited to 'e2fsprogs/chattr.c')
-rw-r--r-- | e2fsprogs/chattr.c | 144 |
1 files changed, 72 insertions, 72 deletions
diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c index 1b7942e1f..82dba4adf 100644 --- a/e2fsprogs/chattr.c +++ b/e2fsprogs/chattr.c | |||
@@ -26,59 +26,54 @@ | |||
26 | #define OPT_REM 2 | 26 | #define OPT_REM 2 |
27 | #define OPT_SET 4 | 27 | #define OPT_SET 4 |
28 | #define OPT_SET_VER 8 | 28 | #define OPT_SET_VER 8 |
29 | static int flags; | ||
30 | static int recursive; | ||
31 | 29 | ||
32 | static unsigned long version; | 30 | struct globals { |
33 | 31 | unsigned long version; | |
34 | static unsigned long af; | 32 | unsigned long af; |
35 | static unsigned long rf; | 33 | unsigned long rf; |
36 | static unsigned long sf; | 34 | smallint flags; |
37 | 35 | smallint recursive; | |
38 | struct flags_char { | ||
39 | unsigned long flag; | ||
40 | char optchar; | ||
41 | }; | ||
42 | |||
43 | static const struct flags_char flags_array[] = { | ||
44 | { EXT2_NOATIME_FL, 'A' }, | ||
45 | { EXT2_SYNC_FL, 'S' }, | ||
46 | { EXT2_DIRSYNC_FL, 'D' }, | ||
47 | { EXT2_APPEND_FL, 'a' }, | ||
48 | { EXT2_COMPR_FL, 'c' }, | ||
49 | { EXT2_NODUMP_FL, 'd' }, | ||
50 | { EXT2_IMMUTABLE_FL, 'i' }, | ||
51 | { EXT3_JOURNAL_DATA_FL, 'j' }, | ||
52 | { EXT2_SECRM_FL, 's' }, | ||
53 | { EXT2_UNRM_FL, 'u' }, | ||
54 | { EXT2_NOTAIL_FL, 't' }, | ||
55 | { EXT2_TOPDIR_FL, 'T' }, | ||
56 | { 0, 0 } | ||
57 | }; | 36 | }; |
58 | 37 | ||
59 | static unsigned long get_flag(char c) | 38 | static unsigned long get_flag(char c) |
60 | { | 39 | { |
61 | const struct flags_char *fp; | 40 | /* Two separate vectors take less space than vector of structs */ |
62 | for (fp = flags_array; fp->optchar; fp++) | 41 | static const char flags_letter[] = "ASDacdijsutT"; |
63 | if (fp->optchar == c) | 42 | static const unsigned long flags_val[] = { |
64 | return fp->flag; | 43 | /* A */ EXT2_NOATIME_FL, |
44 | /* S */ EXT2_SYNC_FL, | ||
45 | /* D */ EXT2_DIRSYNC_FL, | ||
46 | /* a */ EXT2_APPEND_FL, | ||
47 | /* c */ EXT2_COMPR_FL, | ||
48 | /* d */ EXT2_NODUMP_FL, | ||
49 | /* i */ EXT2_IMMUTABLE_FL, | ||
50 | /* j */ EXT3_JOURNAL_DATA_FL, | ||
51 | /* s */ EXT2_SECRM_FL, | ||
52 | /* u */ EXT2_UNRM_FL, | ||
53 | /* t */ EXT2_NOTAIL_FL, | ||
54 | /* T */ EXT2_TOPDIR_FL, | ||
55 | }; | ||
56 | const char *fp; | ||
57 | |||
58 | for (fp = flags_letter; *fp; fp++) | ||
59 | if (*fp == c) | ||
60 | return flags_val[fp - flags_letter]; | ||
65 | bb_show_usage(); | 61 | bb_show_usage(); |
66 | } | 62 | } |
67 | 63 | ||
68 | static int decode_arg(const char *arg) | 64 | static int decode_arg(const char *arg, struct globals *gp) |
69 | { | 65 | { |
70 | unsigned long *fl; | 66 | unsigned long *fl; |
71 | char opt = *arg++; | 67 | char opt = *arg++; |
72 | 68 | ||
69 | fl = &gp->af; | ||
73 | if (opt == '-') { | 70 | if (opt == '-') { |
74 | flags |= OPT_REM; | 71 | gp->flags |= OPT_REM; |
75 | fl = &rf; | 72 | fl = &gp->rf; |
76 | } else if (opt == '+') { | 73 | } else if (opt == '+') { |
77 | flags |= OPT_ADD; | 74 | gp->flags |= OPT_ADD; |
78 | fl = ⁡ | ||
79 | } else if (opt == '=') { | 75 | } else if (opt == '=') { |
80 | flags |= OPT_SET; | 76 | gp->flags |= OPT_SET; |
81 | fl = &sf; | ||
82 | } else | 77 | } else |
83 | return 0; | 78 | return 0; |
84 | 79 | ||
@@ -88,30 +83,29 @@ static int decode_arg(const char *arg) | |||
88 | return 1; | 83 | return 1; |
89 | } | 84 | } |
90 | 85 | ||
91 | static void change_attributes(const char *name); | 86 | static void change_attributes(const char *name, struct globals *gp); |
92 | 87 | ||
93 | static int chattr_dir_proc(const char *dir_name, struct dirent *de, | 88 | static int chattr_dir_proc(const char *dir_name, struct dirent *de, void *gp) |
94 | void *private ATTRIBUTE_UNUSED) | ||
95 | { | 89 | { |
96 | char *path = concat_subpath_file(dir_name, de->d_name); | 90 | char *path = concat_subpath_file(dir_name, de->d_name); |
97 | /* path is NULL if de->d_name is "." or "..", else... */ | 91 | /* path is NULL if de->d_name is "." or "..", else... */ |
98 | if (path) { | 92 | if (path) { |
99 | change_attributes(path); | 93 | change_attributes(path, gp); |
100 | free(path); | 94 | free(path); |
101 | } | 95 | } |
102 | return 0; | 96 | return 0; |
103 | } | 97 | } |
104 | 98 | ||
105 | static void change_attributes(const char *name) | 99 | static void change_attributes(const char *name, struct globals *gp) |
106 | { | 100 | { |
107 | unsigned long fsflags; | 101 | unsigned long fsflags; |
108 | struct stat st; | 102 | struct stat st; |
109 | 103 | ||
110 | if (lstat(name, &st) == -1) { | 104 | if (lstat(name, &st) != 0) { |
111 | bb_perror_msg("stat %s", name); | 105 | bb_perror_msg("stat %s", name); |
112 | return; | 106 | return; |
113 | } | 107 | } |
114 | if (S_ISLNK(st.st_mode) && recursive) | 108 | if (S_ISLNK(st.st_mode) && gp->recursive) |
115 | return; | 109 | return; |
116 | 110 | ||
117 | /* Don't try to open device files, fifos etc. We probably | 111 | /* Don't try to open device files, fifos etc. We probably |
@@ -121,70 +115,76 @@ static void change_attributes(const char *name) | |||
121 | if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) | 115 | if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) |
122 | return; | 116 | return; |
123 | 117 | ||
124 | if (flags & OPT_SET_VER) | 118 | if (gp->flags & OPT_SET_VER) |
125 | if (fsetversion(name, version) == -1) | 119 | if (fsetversion(name, gp->version) != 0) |
126 | bb_perror_msg("setting version on %s", name); | 120 | bb_perror_msg("setting version on %s", name); |
127 | 121 | ||
128 | if (flags & OPT_SET) { | 122 | if (gp->flags & OPT_SET) { |
129 | fsflags = sf; | 123 | fsflags = gp->af; |
130 | } else { | 124 | } else { |
131 | if (fgetflags(name, &fsflags) == -1) { | 125 | if (fgetflags(name, &fsflags) != 0) { |
132 | bb_perror_msg("reading flags on %s", name); | 126 | bb_perror_msg("reading flags on %s", name); |
133 | goto skip_setflags; | 127 | goto skip_setflags; |
134 | } | 128 | } |
135 | if (flags & OPT_REM) | 129 | /*if (gp->flags & OPT_REM) - not needed, rf is zero otherwise */ |
136 | fsflags &= ~rf; | 130 | fsflags &= ~gp->rf; |
137 | if (flags & OPT_ADD) | 131 | /*if (gp->flags & OPT_ADD) - not needed, af is zero otherwise */ |
138 | fsflags |= af; | 132 | fsflags |= gp->af; |
133 | /* What is this? And why it's not done for SET case? */ | ||
139 | if (!S_ISDIR(st.st_mode)) | 134 | if (!S_ISDIR(st.st_mode)) |
140 | fsflags &= ~EXT2_DIRSYNC_FL; | 135 | fsflags &= ~EXT2_DIRSYNC_FL; |
141 | } | 136 | } |
142 | if (fsetflags(name, fsflags) == -1) | 137 | if (fsetflags(name, fsflags) != 0) |
143 | bb_perror_msg("setting flags on %s", name); | 138 | bb_perror_msg("setting flags on %s", name); |
144 | 139 | ||
145 | skip_setflags: | 140 | skip_setflags: |
146 | if (recursive && S_ISDIR(st.st_mode)) | 141 | if (gp->recursive && S_ISDIR(st.st_mode)) |
147 | iterate_on_dir(name, chattr_dir_proc, NULL); | 142 | iterate_on_dir(name, chattr_dir_proc, gp); |
148 | } | 143 | } |
149 | 144 | ||
150 | int chattr_main(int argc, char **argv); | 145 | int chattr_main(int argc, char **argv); |
151 | int chattr_main(int argc, char **argv) | 146 | int chattr_main(int argc, char **argv) |
152 | { | 147 | { |
148 | struct globals g; | ||
153 | char *arg; | 149 | char *arg; |
154 | 150 | ||
151 | memset(&g, 0, sizeof(g)); | ||
152 | |||
155 | /* parse the args */ | 153 | /* parse the args */ |
156 | while ((arg = *++argv)) { | 154 | while ((arg = *++argv)) { |
157 | /* take care of -R and -v <version> */ | 155 | /* take care of -R and -v <version> */ |
158 | if (arg[0] == '-') { | 156 | if (arg[0] == '-' |
159 | if (arg[1] == 'R' && arg[2] == '\0') { | 157 | && (arg[1] == 'R' || arg[1] == 'v') |
160 | recursive = 1; | 158 | && !arg[2] |
161 | continue; | 159 | ) { |
162 | } | 160 | if (arg[1] == 'R') { |
163 | if (arg[1] == 'v' && arg[2] == '\0') { | 161 | g.recursive = 1; |
164 | if (!*++argv) | ||
165 | bb_show_usage(); | ||
166 | version = xatoul(*argv); | ||
167 | flags |= OPT_SET_VER; | ||
168 | continue; | 162 | continue; |
169 | } | 163 | } |
164 | /* arg[1] == 'v' */ | ||
165 | if (!*++argv) | ||
166 | bb_show_usage(); | ||
167 | g.version = xatoul(*argv); | ||
168 | g.flags |= OPT_SET_VER; | ||
169 | continue; | ||
170 | } | 170 | } |
171 | 171 | ||
172 | if (!decode_arg(arg)) | 172 | if (!decode_arg(arg, &g)) |
173 | break; | 173 | break; |
174 | } | 174 | } |
175 | 175 | ||
176 | /* run sanity checks on all the arguments given us */ | 176 | /* run sanity checks on all the arguments given us */ |
177 | if (!*argv) | 177 | if (!*argv) |
178 | bb_show_usage(); | 178 | bb_show_usage(); |
179 | if ((flags & OPT_SET) && (flags & (OPT_ADD|OPT_REM))) | 179 | if ((g.flags & OPT_SET) && (g.flags & (OPT_ADD|OPT_REM))) |
180 | bb_error_msg_and_die("= is incompatible with - and +"); | 180 | bb_error_msg_and_die("= is incompatible with - and +"); |
181 | if (rf & af) | 181 | if (g.rf & g.af) |
182 | bb_error_msg_and_die("can't set and unset a flag"); | 182 | bb_error_msg_and_die("can't set and unset a flag"); |
183 | if (!flags) | 183 | if (!g.flags) |
184 | bb_error_msg_and_die("must use '-v', =, - or +"); | 184 | bb_error_msg_and_die("must use '-v', =, - or +"); |
185 | 185 | ||
186 | /* now run chattr on all the files passed to us */ | 186 | /* now run chattr on all the files passed to us */ |
187 | do change_attributes(*argv); while (*++argv); | 187 | do change_attributes(*argv, &g); while (*++argv); |
188 | 188 | ||
189 | return EXIT_SUCCESS; | 189 | return EXIT_SUCCESS; |
190 | } | 190 | } |