Annotation of /trunk/mkinitrd-magellan/busybox/e2fsprogs/chattr.c
Parent Directory | Revision Log
Revision 984 -
(hide annotations)
(download)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 4183 byte(s)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 4183 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 | niro | 532 | /* 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 | niro | 816 | #include "libbb.h" |
23 | niro | 532 | #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 | |||
30 | niro | 816 | struct globals { |
31 | unsigned long version; | ||
32 | unsigned long af; | ||
33 | unsigned long rf; | ||
34 | smallint flags; | ||
35 | smallint recursive; | ||
36 | niro | 532 | }; |
37 | |||
38 | static unsigned long get_flag(char c) | ||
39 | { | ||
40 | niro | 816 | const char *fp = strchr(e2attr_flags_sname_chattr, c); |
41 | if (fp) | ||
42 | return e2attr_flags_value_chattr[fp - e2attr_flags_sname_chattr]; | ||
43 | niro | 532 | bb_show_usage(); |
44 | } | ||
45 | |||
46 | niro | 816 | static int decode_arg(const char *arg, struct globals *gp) |
47 | niro | 532 | { |
48 | unsigned long *fl; | ||
49 | char opt = *arg++; | ||
50 | |||
51 | niro | 816 | fl = &gp->af; |
52 | niro | 532 | if (opt == '-') { |
53 | niro | 816 | gp->flags |= OPT_REM; |
54 | fl = &gp->rf; | ||
55 | niro | 532 | } else if (opt == '+') { |
56 | niro | 816 | gp->flags |= OPT_ADD; |
57 | niro | 532 | } else if (opt == '=') { |
58 | niro | 816 | gp->flags |= OPT_SET; |
59 | niro | 532 | } else |
60 | return 0; | ||
61 | |||
62 | while (*arg) | ||
63 | *fl |= get_flag(*arg++); | ||
64 | |||
65 | return 1; | ||
66 | } | ||
67 | |||
68 | niro | 816 | static void change_attributes(const char *name, struct globals *gp); |
69 | niro | 532 | |
70 | niro | 984 | static int FAST_FUNC chattr_dir_proc(const char *dir_name, struct dirent *de, void *gp) |
71 | niro | 532 | { |
72 | char *path = concat_subpath_file(dir_name, de->d_name); | ||
73 | /* path is NULL if de->d_name is "." or "..", else... */ | ||
74 | if (path) { | ||
75 | niro | 816 | change_attributes(path, gp); |
76 | niro | 532 | free(path); |
77 | } | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | niro | 816 | static void change_attributes(const char *name, struct globals *gp) |
82 | niro | 532 | { |
83 | unsigned long fsflags; | ||
84 | struct stat st; | ||
85 | |||
86 | niro | 816 | if (lstat(name, &st) != 0) { |
87 | niro | 532 | bb_perror_msg("stat %s", name); |
88 | return; | ||
89 | } | ||
90 | niro | 816 | if (S_ISLNK(st.st_mode) && gp->recursive) |
91 | niro | 532 | return; |
92 | |||
93 | /* Don't try to open device files, fifos etc. We probably | ||
94 | * ought to display an error if the file was explicitly given | ||
95 | * on the command line (whether or not recursive was | ||
96 | * requested). */ | ||
97 | if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) | ||
98 | return; | ||
99 | |||
100 | niro | 816 | if (gp->flags & OPT_SET_VER) |
101 | if (fsetversion(name, gp->version) != 0) | ||
102 | niro | 532 | bb_perror_msg("setting version on %s", name); |
103 | |||
104 | niro | 816 | if (gp->flags & OPT_SET) { |
105 | fsflags = gp->af; | ||
106 | niro | 532 | } else { |
107 | niro | 816 | if (fgetflags(name, &fsflags) != 0) { |
108 | niro | 532 | bb_perror_msg("reading flags on %s", name); |
109 | goto skip_setflags; | ||
110 | } | ||
111 | niro | 816 | /*if (gp->flags & OPT_REM) - not needed, rf is zero otherwise */ |
112 | fsflags &= ~gp->rf; | ||
113 | /*if (gp->flags & OPT_ADD) - not needed, af is zero otherwise */ | ||
114 | fsflags |= gp->af; | ||
115 | /* What is this? And why it's not done for SET case? */ | ||
116 | niro | 532 | if (!S_ISDIR(st.st_mode)) |
117 | fsflags &= ~EXT2_DIRSYNC_FL; | ||
118 | } | ||
119 | niro | 816 | if (fsetflags(name, fsflags) != 0) |
120 | niro | 532 | bb_perror_msg("setting flags on %s", name); |
121 | |||
122 | skip_setflags: | ||
123 | niro | 816 | if (gp->recursive && S_ISDIR(st.st_mode)) |
124 | iterate_on_dir(name, chattr_dir_proc, gp); | ||
125 | niro | 532 | } |
126 | |||
127 | niro | 816 | int chattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
128 | int chattr_main(int argc UNUSED_PARAM, char **argv) | ||
129 | niro | 532 | { |
130 | niro | 816 | struct globals g; |
131 | niro | 532 | char *arg; |
132 | |||
133 | niro | 816 | memset(&g, 0, sizeof(g)); |
134 | |||
135 | niro | 532 | /* parse the args */ |
136 | while ((arg = *++argv)) { | ||
137 | /* take care of -R and -v <version> */ | ||
138 | niro | 816 | if (arg[0] == '-' |
139 | && (arg[1] == 'R' || arg[1] == 'v') | ||
140 | && !arg[2] | ||
141 | ) { | ||
142 | if (arg[1] == 'R') { | ||
143 | g.recursive = 1; | ||
144 | niro | 532 | continue; |
145 | } | ||
146 | niro | 816 | /* arg[1] == 'v' */ |
147 | if (!*++argv) | ||
148 | bb_show_usage(); | ||
149 | g.version = xatoul(*argv); | ||
150 | g.flags |= OPT_SET_VER; | ||
151 | continue; | ||
152 | niro | 532 | } |
153 | |||
154 | niro | 816 | if (!decode_arg(arg, &g)) |
155 | niro | 532 | break; |
156 | } | ||
157 | |||
158 | /* run sanity checks on all the arguments given us */ | ||
159 | if (!*argv) | ||
160 | bb_show_usage(); | ||
161 | niro | 816 | if ((g.flags & OPT_SET) && (g.flags & (OPT_ADD|OPT_REM))) |
162 | niro | 532 | bb_error_msg_and_die("= is incompatible with - and +"); |
163 | niro | 816 | if (g.rf & g.af) |
164 | niro | 532 | bb_error_msg_and_die("can't set and unset a flag"); |
165 | niro | 816 | if (!g.flags) |
166 | niro | 532 | bb_error_msg_and_die("must use '-v', =, - or +"); |
167 | |||
168 | /* now run chattr on all the files passed to us */ | ||
169 | niro | 816 | do change_attributes(*argv, &g); while (*++argv); |
170 | niro | 532 | |
171 | return EXIT_SUCCESS; | ||
172 | } |