Contents of /trunk/mkinitrd-magellan/busybox/e2fsprogs/chattr.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 4317 byte(s)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 4317 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
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 |
29 | static int flags; |
30 | static int recursive; |
31 | |
32 | static unsigned long version; |
33 | |
34 | static unsigned long af; |
35 | static unsigned long rf; |
36 | static unsigned long sf; |
37 | |
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 | }; |
58 | |
59 | static unsigned long get_flag(char c) |
60 | { |
61 | const struct flags_char *fp; |
62 | for (fp = flags_array; fp->optchar; fp++) |
63 | if (fp->optchar == c) |
64 | return fp->flag; |
65 | bb_show_usage(); |
66 | } |
67 | |
68 | static int decode_arg(const char *arg) |
69 | { |
70 | unsigned long *fl; |
71 | char opt = *arg++; |
72 | |
73 | if (opt == '-') { |
74 | flags |= OPT_REM; |
75 | fl = &rf; |
76 | } else if (opt == '+') { |
77 | flags |= OPT_ADD; |
78 | fl = ⁡ |
79 | } else if (opt == '=') { |
80 | flags |= OPT_SET; |
81 | fl = &sf; |
82 | } else |
83 | return 0; |
84 | |
85 | while (*arg) |
86 | *fl |= get_flag(*arg++); |
87 | |
88 | return 1; |
89 | } |
90 | |
91 | static void change_attributes(const char *name); |
92 | |
93 | static int chattr_dir_proc(const char *dir_name, struct dirent *de, |
94 | void *private ATTRIBUTE_UNUSED) |
95 | { |
96 | char *path = concat_subpath_file(dir_name, de->d_name); |
97 | /* path is NULL if de->d_name is "." or "..", else... */ |
98 | if (path) { |
99 | change_attributes(path); |
100 | free(path); |
101 | } |
102 | return 0; |
103 | } |
104 | |
105 | static void change_attributes(const char *name) |
106 | { |
107 | unsigned long fsflags; |
108 | struct stat st; |
109 | |
110 | if (lstat(name, &st) == -1) { |
111 | bb_perror_msg("stat %s", name); |
112 | return; |
113 | } |
114 | if (S_ISLNK(st.st_mode) && recursive) |
115 | return; |
116 | |
117 | /* Don't try to open device files, fifos etc. We probably |
118 | * ought to display an error if the file was explicitly given |
119 | * on the command line (whether or not recursive was |
120 | * requested). */ |
121 | if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) |
122 | return; |
123 | |
124 | if (flags & OPT_SET_VER) |
125 | if (fsetversion(name, version) == -1) |
126 | bb_perror_msg("setting version on %s", name); |
127 | |
128 | if (flags & OPT_SET) { |
129 | fsflags = sf; |
130 | } else { |
131 | if (fgetflags(name, &fsflags) == -1) { |
132 | bb_perror_msg("reading flags on %s", name); |
133 | goto skip_setflags; |
134 | } |
135 | if (flags & OPT_REM) |
136 | fsflags &= ~rf; |
137 | if (flags & OPT_ADD) |
138 | fsflags |= af; |
139 | if (!S_ISDIR(st.st_mode)) |
140 | fsflags &= ~EXT2_DIRSYNC_FL; |
141 | } |
142 | if (fsetflags(name, fsflags) == -1) |
143 | bb_perror_msg("setting flags on %s", name); |
144 | |
145 | skip_setflags: |
146 | if (recursive && S_ISDIR(st.st_mode)) |
147 | iterate_on_dir(name, chattr_dir_proc, NULL); |
148 | } |
149 | |
150 | int chattr_main(int argc, char **argv) |
151 | { |
152 | char *arg; |
153 | |
154 | /* parse the args */ |
155 | while ((arg = *++argv)) { |
156 | /* take care of -R and -v <version> */ |
157 | if (arg[0] == '-') { |
158 | if (arg[1] == 'R' && arg[2] == '\0') { |
159 | recursive = 1; |
160 | continue; |
161 | } |
162 | if (arg[1] == 'v' && arg[2] == '\0') { |
163 | if (!*++argv) |
164 | bb_show_usage(); |
165 | version = xatoul(*argv); |
166 | flags |= OPT_SET_VER; |
167 | continue; |
168 | } |
169 | } |
170 | |
171 | if (!decode_arg(arg)) |
172 | break; |
173 | } |
174 | |
175 | /* run sanity checks on all the arguments given us */ |
176 | if (!*argv) |
177 | bb_show_usage(); |
178 | if ((flags & OPT_SET) && (flags & (OPT_ADD|OPT_REM))) |
179 | bb_error_msg_and_die("= is incompatible with - and +"); |
180 | if (rf & af) |
181 | bb_error_msg_and_die("can't set and unset a flag"); |
182 | if (!flags) |
183 | bb_error_msg_and_die("must use '-v', =, - or +"); |
184 | |
185 | /* now run chattr on all the files passed to us */ |
186 | do change_attributes(*argv); while (*++argv); |
187 | |
188 | return EXIT_SUCCESS; |
189 | } |