From 4aca87515a5083ae0e31ce3177189fd43b6d05ac Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 3 Jan 2015 13:58:15 +0100 Subject: patch to Vanilla Tomato 1.28 --- release/src/router/busybox/e2fsprogs/chattr.c | 172 ++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 release/src/router/busybox/e2fsprogs/chattr.c (limited to 'release/src/router/busybox/e2fsprogs/chattr.c') diff --git a/release/src/router/busybox/e2fsprogs/chattr.c b/release/src/router/busybox/e2fsprogs/chattr.c new file mode 100644 index 00000000..b41919be --- /dev/null +++ b/release/src/router/busybox/e2fsprogs/chattr.c @@ -0,0 +1,172 @@ +/* vi: set sw=4 ts=4: */ +/* + * chattr.c - Change file attributes on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * This file can be redistributed under the terms of the GNU General + * Public License + */ + +/* + * History: + * 93/10/30 - Creation + * 93/11/13 - Replace stat() calls by lstat() to avoid loops + * 94/02/27 - Integrated in Ted's distribution + * 98/12/29 - Ignore symlinks when working recursively (G M Sipe) + * 98/12/29 - Display version info only when -V specified (G M Sipe) + */ + +#include "libbb.h" +#include "e2fs_lib.h" + +#define OPT_ADD 1 +#define OPT_REM 2 +#define OPT_SET 4 +#define OPT_SET_VER 8 + +struct globals { + unsigned long version; + unsigned long af; + unsigned long rf; + smallint flags; + smallint recursive; +}; + +static unsigned long get_flag(char c) +{ + const char *fp = strchr(e2attr_flags_sname_chattr, c); + if (fp) + return e2attr_flags_value_chattr[fp - e2attr_flags_sname_chattr]; + bb_show_usage(); +} + +static int decode_arg(const char *arg, struct globals *gp) +{ + unsigned long *fl; + char opt = *arg++; + + fl = &gp->af; + if (opt == '-') { + gp->flags |= OPT_REM; + fl = &gp->rf; + } else if (opt == '+') { + gp->flags |= OPT_ADD; + } else if (opt == '=') { + gp->flags |= OPT_SET; + } else + return 0; + + while (*arg) + *fl |= get_flag(*arg++); + + return 1; +} + +static void change_attributes(const char *name, struct globals *gp); + +static int chattr_dir_proc(const char *dir_name, struct dirent *de, void *gp) +{ + char *path = concat_subpath_file(dir_name, de->d_name); + /* path is NULL if de->d_name is "." or "..", else... */ + if (path) { + change_attributes(path, gp); + free(path); + } + return 0; +} + +static void change_attributes(const char *name, struct globals *gp) +{ + unsigned long fsflags; + struct stat st; + + if (lstat(name, &st) != 0) { + bb_perror_msg("stat %s", name); + return; + } + if (S_ISLNK(st.st_mode) && gp->recursive) + return; + + /* Don't try to open device files, fifos etc. We probably + * ought to display an error if the file was explicitly given + * on the command line (whether or not recursive was + * requested). */ + if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) + return; + + if (gp->flags & OPT_SET_VER) + if (fsetversion(name, gp->version) != 0) + bb_perror_msg("setting version on %s", name); + + if (gp->flags & OPT_SET) { + fsflags = gp->af; + } else { + if (fgetflags(name, &fsflags) != 0) { + bb_perror_msg("reading flags on %s", name); + goto skip_setflags; + } + /*if (gp->flags & OPT_REM) - not needed, rf is zero otherwise */ + fsflags &= ~gp->rf; + /*if (gp->flags & OPT_ADD) - not needed, af is zero otherwise */ + fsflags |= gp->af; + /* What is this? And why it's not done for SET case? */ + if (!S_ISDIR(st.st_mode)) + fsflags &= ~EXT2_DIRSYNC_FL; + } + if (fsetflags(name, fsflags) != 0) + bb_perror_msg("setting flags on %s", name); + + skip_setflags: + if (gp->recursive && S_ISDIR(st.st_mode)) + iterate_on_dir(name, chattr_dir_proc, gp); +} + +int chattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int chattr_main(int argc UNUSED_PARAM, char **argv) +{ + struct globals g; + char *arg; + + memset(&g, 0, sizeof(g)); + + /* parse the args */ + while ((arg = *++argv)) { + /* take care of -R and -v */ + if (arg[0] == '-' + && (arg[1] == 'R' || arg[1] == 'v') + && !arg[2] + ) { + if (arg[1] == 'R') { + g.recursive = 1; + continue; + } + /* arg[1] == 'v' */ + if (!*++argv) + bb_show_usage(); + g.version = xatoul(*argv); + g.flags |= OPT_SET_VER; + continue; + } + + if (!decode_arg(arg, &g)) + break; + } + + /* run sanity checks on all the arguments given us */ + if (!*argv) + bb_show_usage(); + if ((g.flags & OPT_SET) && (g.flags & (OPT_ADD|OPT_REM))) + bb_error_msg_and_die("= is incompatible with - and +"); + if (g.rf & g.af) + bb_error_msg_and_die("can't set and unset a flag"); + if (!g.flags) + bb_error_msg_and_die("must use '-v', =, - or +"); + + /* now run chattr on all the files passed to us */ + do change_attributes(*argv, &g); while (*++argv); + + return EXIT_SUCCESS; +} -- cgit v1.2.3-54-g00ecf