diff options
Diffstat (limited to 'e2fsprogs/chattr.c')
-rw-r--r-- | e2fsprogs/chattr.c | 70 |
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 | ||
63 | struct globals { | 63 | struct 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 | ||
80 | static char** decode_arg(char **argv, struct globals *gp) | 80 | static 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 | ||
150 | static void change_attributes(const char *name, struct globals *gp) | 150 | static 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 | } |