summaryrefslogtreecommitdiff
path: root/e2fsprogs/chattr.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2005-04-24 05:07:59 +0000
committerMike Frysinger <vapier@gentoo.org>2005-04-24 05:07:59 +0000
commitd89e629e52c3b525424be958de238ed1dc5a0361 (patch)
tree9aec1ca3d0a479bef39bd63c14f4292061d34675 /e2fsprogs/chattr.c
parent408ae211ceaf33bf758207cd5329903c39e8880c (diff)
downloadbusybox-w32-d89e629e52c3b525424be958de238ed1dc5a0361.tar.gz
busybox-w32-d89e629e52c3b525424be958de238ed1dc5a0361.tar.bz2
busybox-w32-d89e629e52c3b525424be958de238ed1dc5a0361.zip
add new subdir for e2fsprogs
Diffstat (limited to 'e2fsprogs/chattr.c')
-rw-r--r--e2fsprogs/chattr.c305
1 files changed, 305 insertions, 0 deletions
diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c
new file mode 100644
index 000000000..7abc83176
--- /dev/null
+++ b/e2fsprogs/chattr.c
@@ -0,0 +1,305 @@
1/*
2 * chattr.c - Change file attributes on an ext2 file system
3 *
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)
7 *
8 * This file can be redistributed under the terms of the GNU General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
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)
19 */
20
21#include <sys/types.h>
22#include <dirent.h>
23#include <fcntl.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <unistd.h>
27#include <string.h>
28#include <errno.h>
29#include <sys/param.h>
30#include <sys/stat.h>
31#include <ext2fs/ext2_fs.h>
32
33#ifdef __GNUC__
34#define EXT2FS_ATTR(x) __attribute__(x)
35#else
36#define EXT2FS_ATTR(x)
37#endif
38
39#ifndef S_ISLNK /* So we can compile even with gcc-warn */
40# ifdef __S_IFLNK
41# define S_ISLNK(mode) __S_ISTYPE((mode), __S_IFLNK)
42# else
43# define S_ISLNK(mode) 0
44# endif
45#endif
46
47#include "e2fsbb.h"
48#include "e2p/e2p.h"
49
50static int add;
51static int rem;
52static int set;
53static int set_version;
54
55static unsigned long version;
56
57static int recursive;
58static int verbose;
59
60static unsigned long af;
61static unsigned long rf;
62static unsigned long sf;
63
64#ifdef _LFS64_LARGEFILE
65#define LSTAT lstat64
66#define STRUCT_STAT struct stat64
67#else
68#define LSTAT lstat
69#define STRUCT_STAT struct stat
70#endif
71
72#if 0
73static void fatal_error(const char * fmt_string, int errcode)
74{
75 fprintf (stderr, fmt_string, program_name);
76 exit (errcode);
77}
78
79#define usage() fatal_error(_("usage: %s [-RV] [-+=AacDdijsSu] [-v version] files...\n"), \
80 1)
81#endif
82
83struct flags_char {
84 unsigned long flag;
85 char optchar;
86};
87
88static const struct flags_char flags_array[] = {
89 { EXT2_NOATIME_FL, 'A' },
90 { EXT2_SYNC_FL, 'S' },
91 { EXT2_DIRSYNC_FL, 'D' },
92 { EXT2_APPEND_FL, 'a' },
93 { EXT2_COMPR_FL, 'c' },
94 { EXT2_NODUMP_FL, 'd' },
95 { EXT2_IMMUTABLE_FL, 'i' },
96 { EXT3_JOURNAL_DATA_FL, 'j' },
97 { EXT2_SECRM_FL, 's' },
98 { EXT2_UNRM_FL, 'u' },
99 { EXT2_NOTAIL_FL, 't' },
100 { EXT2_TOPDIR_FL, 'T' },
101 { 0, 0 }
102};
103
104static unsigned long get_flag(char c)
105{
106 const struct flags_char *fp;
107
108 for (fp = flags_array; fp->flag != 0; fp++) {
109 if (fp->optchar == c)
110 return fp->flag;
111 }
112 return 0;
113}
114
115
116static int decode_arg (int * i, int argc, char ** argv)
117{
118 char * p;
119 char * tmp;
120 unsigned long fl;
121
122 switch (argv[*i][0])
123 {
124 case '-':
125 for (p = &argv[*i][1]; *p; p++) {
126 if (*p == 'R') {
127 recursive = 1;
128 continue;
129 }
130 if (*p == 'V') {
131 verbose = 1;
132 continue;
133 }
134 if (*p == 'v') {
135 (*i)++;
136 if (*i >= argc)
137 usage ();
138 version = strtol (argv[*i], &tmp, 0);
139 if (*tmp) {
140 com_err (program_name, 0,
141 _("bad version - %s\n"),
142 argv[*i]);
143 usage ();
144 }
145 set_version = 1;
146 continue;
147 }
148 if ((fl = get_flag(*p)) == 0)
149 usage();
150 rf |= fl;
151 rem = 1;
152 }
153 break;
154 case '+':
155 add = 1;
156 for (p = &argv[*i][1]; *p; p++) {
157 if ((fl = get_flag(*p)) == 0)
158 usage();
159 af |= fl;
160 }
161 break;
162 case '=':
163 set = 1;
164 for (p = &argv[*i][1]; *p; p++) {
165 if ((fl = get_flag(*p)) == 0)
166 usage();
167 sf |= fl;
168 }
169 break;
170 default:
171 return EOF;
172 break;
173 }
174 return 1;
175}
176
177static int chattr_dir_proc (const char *, struct dirent *, void *);
178
179static void change_attributes (const char * name)
180{
181 unsigned long flags;
182 STRUCT_STAT st;
183
184 if (LSTAT (name, &st) == -1) {
185 com_err (program_name, errno, _("while trying to stat %s"),
186 name);
187 return;
188 }
189 if (S_ISLNK(st.st_mode) && recursive)
190 return;
191
192 /* Don't try to open device files, fifos etc. We probably
193 ought to display an error if the file was explicitly given
194 on the command line (whether or not recursive was
195 requested). */
196 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) &&
197 !S_ISDIR(st.st_mode))
198 return;
199
200 if (set) {
201 if (verbose) {
202 printf (_("Flags of %s set as "), name);
203 print_flags (stdout, sf, 0);
204 printf ("\n");
205 }
206 if (fsetflags (name, sf) == -1)
207 perror (name);
208 } else {
209 if (fgetflags (name, &flags) == -1)
210 com_err (program_name, errno,
211 _("while reading flags on %s"), name);
212 else {
213 if (rem)
214 flags &= ~rf;
215 if (add)
216 flags |= af;
217 if (verbose) {
218 printf (_("Flags of %s set as "), name);
219 print_flags (stdout, flags, 0);
220 printf ("\n");
221 }
222 if (!S_ISDIR(st.st_mode))
223 flags &= ~EXT2_DIRSYNC_FL;
224 if (fsetflags (name, flags) == -1)
225 com_err (program_name, errno,
226 _("while setting flags on %s"), name);
227 }
228 }
229 if (set_version) {
230 if (verbose)
231 printf (_("Version of %s set as %lu\n"), name, version);
232 if (fsetversion (name, version) == -1)
233 com_err (program_name, errno,
234 _("while setting version on %s"), name);
235 }
236 if (S_ISDIR(st.st_mode) && recursive)
237 iterate_on_dir (name, chattr_dir_proc, NULL);
238}
239
240static int chattr_dir_proc (const char * dir_name, struct dirent * de,
241 void * private EXT2FS_ATTR((unused)))
242{
243 if (strcmp (de->d_name, ".") && strcmp (de->d_name, "..")) {
244 char *path;
245
246 path = malloc(strlen (dir_name) + 1 + strlen (de->d_name) + 1);
247 if (!path)
248 fatal_error(_("Couldn't allocate path variable "
249 "in chattr_dir_proc"), 1);
250 sprintf (path, "%s/%s", dir_name, de->d_name);
251 change_attributes (path);
252 free(path);
253 }
254 return 0;
255}
256
257int chattr_main (int argc, char ** argv)
258{
259 int i, j;
260 int end_arg = 0;
261
262#ifdef ENABLE_NLS
263 setlocale(LC_MESSAGES, "");
264 setlocale(LC_CTYPE, "");
265 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
266 textdomain(NLS_CAT_NAME);
267#endif
268#if 0
269 if (argc && *argv)
270 program_name = *argv;
271#endif
272 i = 1;
273 while (i < argc && !end_arg) {
274 /* '--' arg should end option processing */
275 if (strcmp(argv[i], "--") == 0) {
276 i++;
277 end_arg = 1;
278 } else if (decode_arg (&i, argc, argv) == EOF)
279 end_arg = 1;
280 else
281 i++;
282 }
283 if (i >= argc)
284 usage ();
285 if (set && (add || rem)) {
286 fputs(_("= is incompatible with - and +\n"), stderr);
287 exit (1);
288 }
289 if ((rf & af) != 0) {
290 fputs("Can't both set and unset same flag.\n", stderr);
291 exit (1);
292 }
293 if (!(add || rem || set || set_version)) {
294 fputs(_("Must use '-v', =, - or +\n"), stderr);
295 exit (1);
296 }
297#if 0
298 if (verbose)
299 fprintf (stderr, "chattr %s (%s)\n",
300 E2FSPROGS_VERSION, E2FSPROGS_DATE);
301#endif
302 for (j = i; j < argc; j++)
303 change_attributes (argv[j]);
304 exit(0);
305}