aboutsummaryrefslogtreecommitdiff
path: root/e2fsprogs/chattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'e2fsprogs/chattr.c')
-rw-r--r--e2fsprogs/chattr.c70
1 files changed, 44 insertions, 26 deletions
diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c
index 4dfe803d2..f6a9fcf30 100644
--- a/e2fsprogs/chattr.c
+++ b/e2fsprogs/chattr.c
@@ -61,9 +61,9 @@
61#define OPT_SET_PROJ (1 << 4) 61#define OPT_SET_PROJ (1 << 4)
62 62
63struct globals { 63struct globals {
64 unsigned long version; 64 unsigned version;
65 unsigned long af; 65 unsigned af;
66 unsigned long rf; 66 unsigned rf;
67 int flags; 67 int flags;
68 uint32_t projid; 68 uint32_t projid;
69 smallint recursive; 69 smallint recursive;
@@ -79,7 +79,7 @@ static unsigned long get_flag(char c)
79 79
80static char** decode_arg(char **argv, struct globals *gp) 80static char** decode_arg(char **argv, struct globals *gp)
81{ 81{
82 unsigned long *fl; 82 unsigned *fl;
83 const char *arg = *argv; 83 const char *arg = *argv;
84 char opt = *arg; 84 char opt = *arg;
85 85
@@ -149,7 +149,8 @@ static int FAST_FUNC chattr_dir_proc(const char *dir_name, struct dirent *de, vo
149 149
150static void change_attributes(const char *name, struct globals *gp) 150static void change_attributes(const char *name, struct globals *gp)
151{ 151{
152 unsigned long fsflags; 152 unsigned fsflags;
153 int fd;
153 struct stat st; 154 struct stat st;
154 155
155 if (lstat(name, &st) != 0) { 156 if (lstat(name, &st) != 0) {
@@ -166,33 +167,50 @@ static void change_attributes(const char *name, struct globals *gp)
166 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) 167 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode))
167 return; 168 return;
168 169
169 if (gp->flags & OPT_SET_VER) 170 fd = open_or_warn(name, O_RDONLY | O_NONBLOCK); /* neither read nor write asked for */
170 if (fsetversion(name, gp->version) != 0) 171 if (fd >= 0) {
171 bb_perror_msg("setting %s on %s", "version", name); 172 int r;
172 173
173 if (gp->flags & OPT_SET_PROJ) 174 if (gp->flags & OPT_SET_VER) {
174 if (fsetprojid(name, gp->projid) != 0) 175 r = ioctl(fd, EXT2_IOC_SETVERSION, &gp->version);
175 bb_perror_msg("setting %s on %s", "project ID", name); 176 if (r != 0)
177 bb_perror_msg("setting %s on %s", "version", name);
178 }
176 179
177 if (gp->flags & OPT_SET) { 180 if (gp->flags & OPT_SET_PROJ) {
178 fsflags = gp->af; 181 struct ext2_fsxattr fsxattr;
179 } else { 182 r = ioctl(fd, EXT2_IOC_FSGETXATTR, &fsxattr);
180 if (fgetflags(name, &fsflags) != 0) { 183 if (r != 0)
181 bb_perror_msg("reading flags on %s", name); 184 bb_perror_msg("getting %s on %s", "project ID", name);
182 goto skip_setflags; 185 fsxattr.fsx_projid = gp->projid;
186 r = ioctl(fd, EXT2_IOC_FSSETXATTR, &fsxattr);
187 if (r != 0)
188 bb_perror_msg("setting %s on %s", "project ID", name);
183 } 189 }
184 /*if (gp->flags & OPT_REM) - not needed, rf is zero otherwise */ 190
185 fsflags &= ~gp->rf; 191 if (gp->flags & OPT_SET) {
186 /*if (gp->flags & OPT_ADD) - not needed, af is zero otherwise */ 192 fsflags = gp->af;
187 fsflags |= gp->af; 193 } else {
194 r = ioctl(fd, EXT2_IOC_GETFLAGS, &fsflags);
195 if (r != 0) {
196 bb_perror_msg("getting %s on %s", "flags", name);
197 goto skip_setflags;
198 }
199 /*if (gp->flags & OPT_REM) - not needed, rf is zero otherwise */
200 fsflags &= ~gp->rf;
201 /*if (gp->flags & OPT_ADD) - not needed, af is zero otherwise */
202 fsflags |= gp->af;
188// What is this? And why it's not done for SET case? 203// What is this? And why it's not done for SET case?
189 if (!S_ISDIR(st.st_mode)) 204 if (!S_ISDIR(st.st_mode))
190 fsflags &= ~EXT2_DIRSYNC_FL; 205 fsflags &= ~EXT2_DIRSYNC_FL;
206 }
207 r = ioctl(fd, EXT2_IOC_SETFLAGS, &fsflags);
208 if (r != 0)
209 bb_perror_msg("setting %s on %s", "flags", name);
210 skip_setflags:
211 close(fd);
191 } 212 }
192 if (fsetflags(name, fsflags) != 0)
193 bb_perror_msg("setting flags on %s", name);
194 213
195 skip_setflags:
196 if (gp->recursive && S_ISDIR(st.st_mode)) 214 if (gp->recursive && S_ISDIR(st.st_mode))
197 iterate_on_dir(name, chattr_dir_proc, gp); 215 iterate_on_dir(name, chattr_dir_proc, gp);
198} 216}