Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/e2fsprogs/chattr.c

Parent Directory Parent Directory | Revision Log 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)
-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     }