2 * chattr.c - Change file attributes on an ext2 file system
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)
8 * This file can be redistributed under the terms of the GNU General
15 * 93/11/13 - Replace stat() calls by lstat() to avoid loops
16 * 94/02/27 - Integrated in Ted's distribution
17 * 98/12/29 - Ignore symlinks when working recursively (G M Sipe)
18 * 98/12/29 - Display version info only when -V specified (G M Sipe)
21 #include <sys/types.h>
31 #include <sys/param.h>
33 #include <linux/ext2_fs.h>
35 #ifndef S_ISLNK /* So we can compile even with gcc-warn */
37 # define S_ISLNK(mode) __S_ISTYPE((mode), __S_IFLNK)
39 # define S_ISLNK(mode) 0
43 #include "et/com_err.h"
46 #include "../version.h"
48 const char * program_name = "chattr";
55 unsigned long version;
64 static void fatal_error(const char * fmt_string, int errcode)
66 fprintf (stderr, fmt_string, program_name);
70 #define usage() fatal_error("usage: %s [-RV] [-+=AacdisSu] [-v version] files...\n", \
73 static int decode_arg (int * i, int argc, char ** argv)
81 for (p = &argv[*i][1]; *p; p++)
100 #ifdef EXT2_NOATIME_FL
102 rf |= EXT2_NOATIME_FL;
110 #ifdef EXT2_NODUMP_FL
112 rf |= EXT2_NODUMP_FL;
116 #ifdef EXT2_IMMUTABLE_FL
118 rf |= EXT2_IMMUTABLE_FL;
134 version = strtol (argv[*i], &tmp, 0);
137 com_err (program_name, 0,
138 "bad version - %s\n", argv[*i]);
144 fprintf (stderr, "%s: Unrecognized argument: %c\n",
151 for (p = &argv[*i][1]; *p; p++)
157 #ifdef EXT2_APPEND_FL
159 af |= EXT2_APPEND_FL;
162 #ifdef EXT2_NOATIME_FL
164 af |= EXT2_NOATIME_FL;
170 #ifdef EXT2_NODUMP_FL
172 af |= EXT2_NODUMP_FL;
175 #ifdef EXT2_IMMUTABLE_FL
177 af |= EXT2_IMMUTABLE_FL;
192 for (p = &argv[*i][1]; *p; p++)
198 #ifdef EXT2_APPEND_FL
200 sf |= EXT2_APPEND_FL;
203 #ifdef EXT2_NOATIME_FL
205 sf |= EXT2_NOATIME_FL;
211 #ifdef EXT2_NODUMP_FL
213 sf |= EXT2_NODUMP_FL;
216 #ifdef EXT2_IMMUTABLE_FL
218 sf |= EXT2_IMMUTABLE_FL;
238 static int chattr_dir_proc (const char *, struct dirent *, void *);
240 static void change_attributes (const char * name)
245 if (lstat (name, &st) == -1)
247 com_err (program_name, errno, "while stating %s", name);
250 if (S_ISLNK(st.st_mode) && recursive)
256 printf ("Flags of %s set as ", name);
257 print_flags (stdout, sf, 0);
260 if (fsetflags (name, sf) == -1)
265 if (fgetflags (name, &flags) == -1)
266 com_err (program_name, errno,
267 "while reading flags on %s", name);
276 printf ("Flags of %s set as ", name);
277 print_flags (stdout, flags, 0);
280 if (fsetflags (name, flags) == -1)
281 com_err (program_name, errno,
282 "while setting flags on %s", name);
288 printf ("Version of %s set as %lu\n", name, version);
289 if (fsetversion (name, version) == -1)
290 com_err (program_name, errno,
291 "while setting version on %s", name);
293 if (S_ISDIR(st.st_mode) && recursive)
294 iterate_on_dir (name, chattr_dir_proc, (void *) NULL);
297 static int chattr_dir_proc (const char * dir_name, struct dirent * de, void * private)
299 if (strcmp (de->d_name, ".") && strcmp (de->d_name, ".."))
303 path = malloc(strlen (dir_name) + 1 + strlen (de->d_name) + 1);
305 fatal_error("Couldn't allocate path variable "
306 "in chattr_dir_proc", 1);
307 sprintf (path, "%s/%s", dir_name, de->d_name);
308 change_attributes (path);
314 int main (int argc, char ** argv)
320 program_name = *argv;
322 while (i < argc && !end_arg)
324 if (decode_arg (&i, argc, argv) == EOF)
331 if (set && (add || rem))
333 fprintf (stderr, "= is incompatible with - and +\n");
336 if (!(add || rem || set || set_version))
338 fprintf (stderr, "Must use '-v', =, - or +\n");
342 fprintf (stderr, "chattr %s, %s for EXT2 FS %s, %s\n",
343 E2FSPROGS_VERSION, E2FSPROGS_DATE,
344 EXT2FS_VERSION, EXT2FS_DATE);
345 for (j = i; j < argc; j++)
346 change_attributes (argv[j]);