summaryrefslogtreecommitdiff
path: root/e2fsprogs/chattr.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-12-26 01:30:59 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-12-26 01:30:59 +0000
commitc4f623ef2a7980a63de7c9f1d539a656b83f10e7 (patch)
treea294e28b0112052cb9d58b403554b3390e76f50c /e2fsprogs/chattr.c
parent64c54025842f205ad722675105b88044a5b6845a (diff)
downloadbusybox-w32-c4f623ef2a7980a63de7c9f1d539a656b83f10e7.tar.gz
busybox-w32-c4f623ef2a7980a63de7c9f1d539a656b83f10e7.tar.bz2
busybox-w32-c4f623ef2a7980a63de7c9f1d539a656b83f10e7.zip
put small subset of e2fsprogs back in the tree:
lsattr, chattr, fsck. Old e2fsprogs tree is in e2fsprogs/old_e2fsprogs/*.
Diffstat (limited to 'e2fsprogs/chattr.c')
-rw-r--r--e2fsprogs/chattr.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c
new file mode 100644
index 000000000..28a391771
--- /dev/null
+++ b/e2fsprogs/chattr.c
@@ -0,0 +1,199 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * chattr.c - Change file attributes on an ext2 file system
4 *
5 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
6 * Laboratoire MASI, Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
9 * This file can be redistributed under the terms of the GNU General
10 * Public License
11 */
12
13/*
14 * History:
15 * 93/10/30 - Creation
16 * 93/11/13 - Replace stat() calls by lstat() to avoid loops
17 * 94/02/27 - Integrated in Ted's distribution
18 * 98/12/29 - Ignore symlinks when working recursively (G M Sipe)
19 * 98/12/29 - Display version info only when -V specified (G M Sipe)
20 */
21
22#include "busybox.h"
23#include "e2fs_lib.h"
24
25#define OPT_ADD 1
26#define OPT_REM 2
27#define OPT_SET 4
28#define OPT_SET_VER 8
29static int flags;
30static int recursive;
31
32static unsigned long version;
33
34static unsigned long af;
35static unsigned long rf;
36static unsigned long sf;
37
38struct flags_char {
39 unsigned long flag;
40 char optchar;
41};
42
43static 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};
58
59static unsigned long get_flag(char c)
60{
61 const struct flags_char *fp;
62 for (fp = flags_array; fp->flag; fp++)
63 if (fp->optchar == c)
64 return fp->flag;
65 bb_show_usage();
66 /*return 0;*/
67}
68
69static int decode_arg(char *arg)
70{
71 unsigned long *fl;
72 char opt = *arg++;
73
74 if (opt == '-') {
75 flags |= OPT_REM;
76 fl = &rf;
77 } else if (opt == '+') {
78 flags |= OPT_ADD;
79 fl = &af;
80 } else if (opt == '=') {
81 flags |= OPT_SET;
82 fl = &sf;
83 } else
84 return 0;
85
86 while (*arg)
87 *fl |= get_flag(*arg++);
88
89 return 1;
90}
91
92static int chattr_dir_proc(const char *, struct dirent *, void *);
93
94static void change_attributes(const char * name)
95{
96 unsigned long fsflags;
97 struct stat st;
98
99 if (lstat(name, &st) == -1) {
100 bb_error_msg("stat %s failed", name);
101 return;
102 }
103 if (S_ISLNK(st.st_mode) && recursive)
104 return;
105
106 /* Don't try to open device files, fifos etc. We probably
107 * ought to display an error if the file was explicitly given
108 * on the command line (whether or not recursive was
109 * requested). */
110 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode))
111 return;
112
113 if (flags & OPT_SET_VER)
114 if (fsetversion(name, version) == -1)
115 bb_error_msg("setting version on %s", name);
116
117 if (flags & OPT_SET) {
118 fsflags = sf;
119 } else {
120 if (fgetflags(name, &fsflags) == -1) {
121 bb_error_msg("reading flags on %s", name);
122 goto skip_setflags;
123 }
124 if (flags & OPT_REM)
125 fsflags &= ~rf;
126 if (flags & OPT_ADD)
127 fsflags |= af;
128 if (!S_ISDIR(st.st_mode))
129 fsflags &= ~EXT2_DIRSYNC_FL;
130 }
131 if (fsetflags(name, fsflags) == -1)
132 bb_error_msg("setting flags on %s", name);
133
134 skip_setflags:
135 if (S_ISDIR(st.st_mode) && recursive)
136 iterate_on_dir(name, chattr_dir_proc, NULL);
137}
138
139static int chattr_dir_proc(const char *dir_name, struct dirent *de,
140 void *private ATTRIBUTE_UNUSED)
141{
142 /*if (strcmp(de->d_name, ".") || strcmp(de->d_name, "..")) {*/
143 if (de->d_name[0] == '.'
144 && (!de->d_name[1] || LONE_CHAR(de->d_name+1, '.'))
145 ) {
146 char *path = concat_subpath_file(dir_name, de->d_name);
147 if (path) {
148 change_attributes(path);
149 free(path);
150 }
151 }
152 return 0;
153}
154
155int chattr_main(int argc, char **argv)
156{
157 int i;
158 char *arg;
159
160 /* parse the args */
161 for (i = 1; i < argc; ++i) {
162 arg = argv[i];
163
164 /* take care of -R and -v <version> */
165 if (arg[0] == '-') {
166 if (arg[1] == 'R' && arg[2] == '\0') {
167 recursive = 1;
168 continue;
169 }
170 if (arg[1] == 'v' && arg[2] == '\0') {
171 ++i;
172 if (i >= argc)
173 bb_show_usage();
174 version = xatoul(argv[i]);
175 flags |= OPT_SET_VER;
176 continue;
177 }
178 }
179
180 if (!decode_arg(arg))
181 break;
182 }
183
184 /* run sanity checks on all the arguments given us */
185 if (i >= argc)
186 bb_show_usage();
187 if ((flags & OPT_SET) && (flags & (OPT_ADD|OPT_REM)))
188 bb_error_msg_and_die("= is incompatible with - and +");
189 if (rf & af)
190 bb_error_msg_and_die("Can't set and unset a flag");
191 if (!flags)
192 bb_error_msg_and_die("Must use '-v', =, - or +");
193
194 /* now run chattr on all the files passed to us */
195 while (i < argc)
196 change_attributes(argv[i++]);
197
198 return EXIT_SUCCESS;
199}