]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blob - misc/chattr.c
Many files:
[thirdparty/e2fsprogs.git] / misc / chattr.c
1 /*
2 * chattr.c - Change file attributes on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU General
9 * Public License
10 */
11
12 /*
13 * History:
14 * 93/10/30 - Creation
15 * 93/11/13 - Replace stat() calls by lstat() to avoid loops
16 * 94/02/27 - Integrated in Ted's distribution
17 */
18
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <getopt.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/param.h>
26 #include <sys/stat.h>
27 #include <linux/ext2_fs.h>
28
29 #include "et/com_err.h"
30 #include "e2p/e2p.h"
31
32 #include "../version.h"
33
34 const char * program_name = "chattr";
35
36 int add = 0;
37 int rem = 0;
38 int set = 0;
39 int set_version = 0;
40
41 unsigned long version;
42
43 int recursive = 0;
44 int verbose = 0;
45
46 unsigned long af;
47 unsigned long rf;
48 unsigned long sf;
49
50 static void volatile fatal_error (const char * fmt_string, int errcode)
51 {
52 fprintf (stderr, fmt_string, program_name);
53 exit (errcode);
54 }
55
56 #define usage() fatal_error ("usage: %s [-RV] [-+=acdisSu] [-v version] files...\n", \
57 1)
58
59 static int decode_arg (int * i, int argc, char ** argv)
60 {
61 char * p;
62 char * tmp;
63
64 switch (argv[*i][0])
65 {
66 case '-':
67 for (p = &argv[*i][1]; *p; p++)
68 switch (*p)
69 {
70 case 'R':
71 recursive = 1;
72 break;
73 case 'S':
74 rf |= EXT2_SYNC_FL;
75 rem = 1;
76 break;
77 case 'V':
78 verbose = 1;
79 break;
80 #ifdef EXT2_APPEND_FL
81 case 'a':
82 rf |= EXT2_APPEND_FL;
83 rem = 1;
84 break;
85 #endif
86 case 'c':
87 rf |= EXT2_COMPR_FL;
88 rem = 1;
89 break;
90 #ifdef EXT2_NODUMP_FL
91 case 'd':
92 rf |= EXT2_NODUMP_FL;
93 rem = 1;
94 break;
95 #endif
96 #ifdef EXT2_IMMUTABLE_FL
97 case 'i':
98 rf |= EXT2_IMMUTABLE_FL;
99 rem = 1;
100 break;
101 #endif
102 case 's':
103 rf |= EXT2_SECRM_FL;
104 rem = 1;
105 break;
106 case 'u':
107 rf |= EXT2_UNRM_FL;
108 rem = 1;
109 break;
110 case 'v':
111 if (*i >= argc)
112 usage ();
113 (*i)++;
114 version = strtol (argv[*i], &tmp, 0);
115 if (*tmp)
116 {
117 com_err (program_name, 0,
118 "bad version - %s\n", argv[*i]);
119 usage ();
120 }
121 set_version = 1;
122 break;
123 default:
124 fprintf (stderr, "%s: Unrecognized argument: %c\n",
125 program_name, *p);
126 usage ();
127 }
128 break;
129 case '+':
130 add = 1;
131 for (p = &argv[*i][1]; *p; p++)
132 switch (*p)
133 {
134 case 'S':
135 af |= EXT2_SYNC_FL;
136 break;
137 #ifdef EXT2_APPEND_FL
138 case 'a':
139 af |= EXT2_APPEND_FL;
140 break;
141 #endif
142 case 'c':
143 af |= EXT2_COMPR_FL;
144 break;
145 #ifdef EXT2_NODUMP_FL
146 case 'd':
147 af |= EXT2_NODUMP_FL;
148 break;
149 #endif
150 #ifdef EXT2_IMMUTABLE_FL
151 case 'i':
152 af |= EXT2_IMMUTABLE_FL;
153 break;
154 #endif
155 case 's':
156 af |= EXT2_SECRM_FL;
157 break;
158 case 'u':
159 af |= EXT2_UNRM_FL;
160 break;
161 default:
162 usage ();
163 }
164 break;
165 case '=':
166 set = 1;
167 for (p = &argv[*i][1]; *p; p++)
168 switch (*p)
169 {
170 case 'S':
171 sf |= EXT2_SYNC_FL;
172 break;
173 #ifdef EXT2_APPEND_FL
174 case 'a':
175 sf |= EXT2_APPEND_FL;
176 break;
177 #endif
178 case 'c':
179 sf |= EXT2_COMPR_FL;
180 break;
181 #ifdef EXT2_NODUMP_FL
182 case 'd':
183 sf |= EXT2_NODUMP_FL;
184 break;
185 #endif
186 #ifdef EXT2_IMMUTABLE_FL
187 case 'i':
188 sf |= EXT2_IMMUTABLE_FL;
189 break;
190 #endif
191 case 's':
192 sf |= EXT2_SECRM_FL;
193 break;
194 case 'u':
195 sf |= EXT2_UNRM_FL;
196 break;
197 default:
198 usage ();
199 }
200 break;
201 default:
202 return EOF;
203 break;
204 }
205 return 1;
206 }
207
208 static int chattr_dir_proc (const char *, struct dirent *, void *);
209
210 static void change_attributes (const char * name)
211 {
212 unsigned long flags;
213 struct stat st;
214
215 if (lstat (name, &st) == -1)
216 {
217 com_err (program_name, errno, "while stating %s", name);
218 return;
219 }
220 if (set)
221 {
222 if (verbose)
223 {
224 printf ("Flags of %s set as ", name);
225 print_flags (stdout, sf, 0);
226 printf ("\n");
227 }
228 if (fsetflags (name, sf) == -1)
229 perror (name);
230 }
231 else
232 {
233 if (fgetflags (name, &flags) == -1)
234 com_err (program_name, errno,
235 "while reading flags on %s", name);
236 else
237 {
238 if (rem)
239 flags &= ~rf;
240 if (add)
241 flags |= af;
242 if (verbose)
243 {
244 printf ("Flags of %s set as ", name);
245 print_flags (stdout, flags, 0);
246 printf ("\n");
247 }
248 if (fsetflags (name, flags) == -1)
249 com_err (program_name, errno,
250 "while setting flags on %s", name);
251 }
252 }
253 if (set_version)
254 {
255 if (verbose)
256 printf ("Version of %s set as %lu\n", name, version);
257 if (fsetversion (name, version) == -1)
258 com_err (program_name, errno,
259 "while setting version on %s", name);
260 }
261 if (S_ISDIR(st.st_mode) && recursive)
262 iterate_on_dir (name, chattr_dir_proc, (void *) NULL);
263 }
264
265 static int chattr_dir_proc (const char * dir_name, struct dirent * de, void * private)
266 {
267 char path[MAXPATHLEN];
268
269 if (strcmp (de->d_name, ".") && strcmp (de->d_name, ".."))
270 {
271 sprintf (path, "%s/%s", dir_name, de->d_name);
272 change_attributes (path);
273 }
274 return 0;
275 }
276
277 void main (int argc, char ** argv)
278 {
279 int i, j;
280 int end_arg = 0;
281
282 fprintf (stderr, "chattr %s, %s for EXT2 FS %s, %s\n",
283 E2FSPROGS_VERSION, E2FSPROGS_DATE,
284 EXT2FS_VERSION, EXT2FS_DATE);
285 if (argc && *argv)
286 program_name = *argv;
287 i = 1;
288 while (i < argc && !end_arg)
289 {
290 if (decode_arg (&i, argc, argv) == EOF)
291 end_arg = 1;
292 else
293 i++;
294 }
295 if (i >= argc)
296 usage ();
297 if (set && (add || rem))
298 {
299 fprintf (stderr, "= is incompatible with - and +\n");
300 exit (1);
301 }
302 if (!(add || rem || set))
303 {
304 fprintf (stderr, "Must use =, - or +\n");
305 exit (1);
306 }
307 for (j = i; j < argc; j++)
308 change_attributes (argv[j]);
309 }