e2fsprogs/*: remove ioctl calling obfuscation

function                                             old     new   delta
change_attributes                                    326     416     +90
list_attributes                                      222     248     +26
close_silently                                        22       -     -22
.rodata                                           103722  103692     -30
fgetsetversion                                        74       -     -74
fgetsetprojid                                        107       -    -107
fgetsetflags                                         148       -    -148
------------------------------------------------------------------------------
(add/remove: 0/4 grow/shrink: 2/1 up/down: 116/-381)         Total: -265 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2021-06-23 12:45:51 +02:00
parent e7ff017a1a
commit 96436fb36a
5 changed files with 71 additions and 177 deletions

View File

@ -61,9 +61,9 @@
#define OPT_SET_PROJ (1 << 4) #define OPT_SET_PROJ (1 << 4)
struct globals { struct globals {
unsigned long version; unsigned version;
unsigned long af; unsigned af;
unsigned long rf; unsigned rf;
int flags; int flags;
uint32_t projid; uint32_t projid;
smallint recursive; smallint recursive;
@ -79,7 +79,7 @@ static unsigned long get_flag(char c)
static char** decode_arg(char **argv, struct globals *gp) static char** decode_arg(char **argv, struct globals *gp)
{ {
unsigned long *fl; unsigned *fl;
const char *arg = *argv; const char *arg = *argv;
char opt = *arg; char opt = *arg;
@ -149,7 +149,8 @@ static int FAST_FUNC chattr_dir_proc(const char *dir_name, struct dirent *de, vo
static void change_attributes(const char *name, struct globals *gp) static void change_attributes(const char *name, struct globals *gp)
{ {
unsigned long fsflags; unsigned fsflags;
int fd;
struct stat st; struct stat st;
if (lstat(name, &st) != 0) { if (lstat(name, &st) != 0) {
@ -166,33 +167,50 @@ static void change_attributes(const char *name, struct globals *gp)
if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode))
return; return;
if (gp->flags & OPT_SET_VER) fd = open_or_warn(name, O_RDONLY | O_NONBLOCK); /* neither read nor write asked for */
if (fsetversion(name, gp->version) != 0) if (fd >= 0) {
bb_perror_msg("setting %s on %s", "version", name); int r;
if (gp->flags & OPT_SET_PROJ) if (gp->flags & OPT_SET_VER) {
if (fsetprojid(name, gp->projid) != 0) r = ioctl(fd, EXT2_IOC_SETVERSION, &gp->version);
bb_perror_msg("setting %s on %s", "project ID", name); if (r != 0)
bb_perror_msg("setting %s on %s", "version", name);
if (gp->flags & OPT_SET) {
fsflags = gp->af;
} else {
if (fgetflags(name, &fsflags) != 0) {
bb_perror_msg("reading flags on %s", name);
goto skip_setflags;
} }
/*if (gp->flags & OPT_REM) - not needed, rf is zero otherwise */
fsflags &= ~gp->rf;
/*if (gp->flags & OPT_ADD) - not needed, af is zero otherwise */
fsflags |= gp->af;
// What is this? And why it's not done for SET case?
if (!S_ISDIR(st.st_mode))
fsflags &= ~EXT2_DIRSYNC_FL;
}
if (fsetflags(name, fsflags) != 0)
bb_perror_msg("setting flags on %s", name);
if (gp->flags & OPT_SET_PROJ) {
struct ext2_fsxattr fsxattr;
r = ioctl(fd, EXT2_IOC_FSGETXATTR, &fsxattr);
if (r != 0)
bb_perror_msg("getting %s on %s", "project ID", name);
fsxattr.fsx_projid = gp->projid;
r = ioctl(fd, EXT2_IOC_FSSETXATTR, &fsxattr);
if (r != 0)
bb_perror_msg("setting %s on %s", "project ID", name);
}
if (gp->flags & OPT_SET) {
fsflags = gp->af;
} else {
r = ioctl(fd, EXT2_IOC_GETFLAGS, &fsflags);
if (r != 0) {
bb_perror_msg("getting %s on %s", "flags", name);
goto skip_setflags;
}
/*if (gp->flags & OPT_REM) - not needed, rf is zero otherwise */
fsflags &= ~gp->rf;
/*if (gp->flags & OPT_ADD) - not needed, af is zero otherwise */
fsflags |= gp->af;
// What is this? And why it's not done for SET case?
if (!S_ISDIR(st.st_mode))
fsflags &= ~EXT2_DIRSYNC_FL;
}
r = ioctl(fd, EXT2_IOC_SETFLAGS, &fsflags);
if (r != 0)
bb_perror_msg("setting %s on %s", "flags", name);
skip_setflags: skip_setflags:
close(fd);
}
if (gp->recursive && S_ISDIR(st.st_mode)) if (gp->recursive && S_ISDIR(st.st_mode))
iterate_on_dir(name, chattr_dir_proc, gp); iterate_on_dir(name, chattr_dir_proc, gp);
} }

View File

@ -8,8 +8,6 @@
#include "libbb.h" #include "libbb.h"
#include "e2fs_lib.h" #include "e2fs_lib.h"
#define HAVE_EXT2_IOCTLS 1
#if INT_MAX == LONG_MAX #if INT_MAX == LONG_MAX
#define IF_LONG_IS_SAME(...) __VA_ARGS__ #define IF_LONG_IS_SAME(...) __VA_ARGS__
#define IF_LONG_IS_WIDER(...) #define IF_LONG_IS_WIDER(...)
@ -18,14 +16,6 @@
#define IF_LONG_IS_WIDER(...) __VA_ARGS__ #define IF_LONG_IS_WIDER(...) __VA_ARGS__
#endif #endif
static void close_silently(int fd)
{
int e = errno;
close(fd);
errno = e;
}
/* Iterate a function on each entry of a directory */ /* Iterate a function on each entry of a directory */
int iterate_on_dir(const char *dir_name, int iterate_on_dir(const char *dir_name,
int FAST_FUNC (*func)(const char *, struct dirent *, void *), int FAST_FUNC (*func)(const char *, struct dirent *, void *),
@ -45,113 +35,6 @@ int iterate_on_dir(const char *dir_name,
return 0; return 0;
} }
/* Get/set a file version on an ext2 file system */
int fgetsetversion(const char *name, unsigned long *get_version, unsigned long set_version)
{
#if HAVE_EXT2_IOCTLS
int fd, r;
IF_LONG_IS_WIDER(unsigned ver;)
fd = open(name, O_RDONLY | O_NONBLOCK);
if (fd == -1)
return -1;
if (!get_version) {
IF_LONG_IS_WIDER(
ver = (unsigned) set_version;
r = ioctl(fd, EXT2_IOC_SETVERSION, &ver);
)
IF_LONG_IS_SAME(
r = ioctl(fd, EXT2_IOC_SETVERSION, (void*)&set_version);
)
} else {
IF_LONG_IS_WIDER(
r = ioctl(fd, EXT2_IOC_GETVERSION, &ver);
*get_version = ver;
)
IF_LONG_IS_SAME(
r = ioctl(fd, EXT2_IOC_GETVERSION, (void*)get_version);
)
}
close_silently(fd);
return r;
#else /* ! HAVE_EXT2_IOCTLS */
errno = EOPNOTSUPP;
return -1;
#endif /* ! HAVE_EXT2_IOCTLS */
}
int fgetsetprojid(const char *name, uint32_t *get, uint32_t set)
{
#if HAVE_EXT2_IOCTLS
struct ext2_fsxattr fsxattr;
int fd, r;
fd = open(name, O_RDONLY | O_NONBLOCK);
if (fd == -1)
return -1;
r = ioctl(fd, EXT2_IOC_FSGETXATTR, &fsxattr);
/* note: ^^^ may fail in 32-bit userspace on 64-bit kernel (seen on 4.12.0) */
if (r == 0) {
if (get) {
*get = fsxattr.fsx_projid;
} else {
fsxattr.fsx_projid = set;
r = ioctl(fd, EXT2_IOC_FSSETXATTR, &fsxattr);
}
}
close_silently(fd);
return r;
#else /* ! HAVE_EXT2_IOCTLS */
errno = EOPNOTSUPP;
return -1;
#endif /* ! HAVE_EXT2_IOCTLS */
}
/* Get/set a file flags on an ext2 file system */
int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_flags)
{
#if HAVE_EXT2_IOCTLS
struct stat buf;
int fd, r;
IF_LONG_IS_WIDER(unsigned f;)
if (stat(name, &buf) == 0 /* stat is ok */
&& !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)
) {
goto notsupp;
}
fd = open(name, O_RDONLY | O_NONBLOCK); /* neither read nor write asked for */
if (fd == -1)
return -1;
if (!get_flags) {
IF_LONG_IS_WIDER(
f = (unsigned) set_flags;
r = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
)
IF_LONG_IS_SAME(
r = ioctl(fd, EXT2_IOC_SETFLAGS, (void*)&set_flags);
)
} else {
IF_LONG_IS_WIDER(
r = ioctl(fd, EXT2_IOC_GETFLAGS, &f);
*get_flags = f;
)
IF_LONG_IS_SAME(
r = ioctl(fd, EXT2_IOC_GETFLAGS, (void*)get_flags);
)
}
close_silently(fd);
return r;
notsupp:
#endif /* HAVE_EXT2_IOCTLS */
errno = EOPNOTSUPP;
return -1;
}
/* Print file attributes on an ext2 file system */ /* Print file attributes on an ext2 file system */
const uint32_t e2attr_flags_value[] ALIGN4 = { const uint32_t e2attr_flags_value[] ALIGN4 = {
#ifdef ENABLE_COMPRESSION #ifdef ENABLE_COMPRESSION
@ -215,7 +98,7 @@ static const char e2attr_flags_lname[] ALIGN1 =
"Verity" "\0" "Verity" "\0"
/* Another trailing NUL is added by compiler */; /* Another trailing NUL is added by compiler */;
void print_e2flags(FILE *f, unsigned long flags, unsigned options) void print_e2flags(FILE *f, unsigned flags, unsigned options)
{ {
const uint32_t *fv; const uint32_t *fv;
const char *fn; const char *fn;

View File

@ -16,25 +16,10 @@ int iterate_on_dir(const char *dir_name,
int FAST_FUNC (*func)(const char *, struct dirent *, void *), int FAST_FUNC (*func)(const char *, struct dirent *, void *),
void *private); void *private);
/* Get/set a file version on an ext2 file system */
int fgetsetversion(const char *name, unsigned long *get_version, unsigned long set_version);
#define fgetversion(name, version) fgetsetversion(name, version, 0)
#define fsetversion(name, version) fgetsetversion(name, NULL, version)
/* Get/set a file project ID on an ext2 file system */
int fgetsetprojid(const char *name, uint32_t *get, uint32_t set);
#define fgetprojid(name, projid) fgetsetprojid(name, projid, 0)
#define fsetprojid(name, projid) fgetsetprojid(name, NULL, projid)
/* Get/set a file flags on an ext2 file system */
int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_flags);
#define fgetflags(name, flags) fgetsetflags(name, flags, 0)
#define fsetflags(name, flags) fgetsetflags(name, NULL, flags)
/* Must be 1 for compatibility with 'int long_format'. */ /* Must be 1 for compatibility with 'int long_format'. */
#define PFOPT_LONG 1 #define PFOPT_LONG 1
/* Print file attributes on an ext2 file system */ /* Print file attributes on an ext2 file system */
void print_e2flags(FILE *f, unsigned long flags, unsigned options); void print_e2flags(FILE *f, unsigned flags, unsigned options);
extern const uint32_t e2attr_flags_value[]; extern const uint32_t e2attr_flags_value[];
extern const char e2attr_flags_sname[]; extern const char e2attr_flags_sname[];

View File

@ -46,25 +46,35 @@ enum {
static void list_attributes(const char *name) static void list_attributes(const char *name)
{ {
unsigned long fsflags; unsigned fsflags;
int fd, r;
if (fgetflags(name, &fsflags) != 0) fd = open_or_warn(name, O_RDONLY | O_NONBLOCK); /* neither read nor write asked for */
goto read_err; if (fd < 0) /* for example, dangling links */
return;
if (option_mask32 & OPT_PROJID) { if (option_mask32 & OPT_PROJID) {
uint32_t p; struct ext2_fsxattr fsxattr;
if (fgetprojid(name, &p) != 0) r = ioctl(fd, EXT2_IOC_FSGETXATTR, &fsxattr);
if (r != 0)
goto read_err; goto read_err;
printf("%5lu ", (unsigned long)p); printf("%5u ", (unsigned)fsxattr.fsx_projid);
} }
if (option_mask32 & OPT_GENERATION) { if (option_mask32 & OPT_GENERATION) {
unsigned long generation; unsigned generation;
if (fgetversion(name, &generation) != 0) r = ioctl(fd, EXT2_IOC_GETVERSION, &generation);
if (r != 0)
goto read_err; goto read_err;
printf("%-10lu ", generation); printf("%-10u ", generation);
} }
r = ioctl(fd, EXT2_IOC_GETFLAGS, &fsflags);
if (r != 0)
goto read_err;
close(fd);
if (option_mask32 & OPT_PF_LONG) { if (option_mask32 & OPT_PF_LONG) {
printf("%-28s ", name); printf("%-28s ", name);
print_e2flags(stdout, fsflags, PFOPT_LONG); print_e2flags(stdout, fsflags, PFOPT_LONG);
@ -77,6 +87,7 @@ static void list_attributes(const char *name)
return; return;
read_err: read_err:
bb_perror_msg("reading %s", name); bb_perror_msg("reading %s", name);
close(fd);
} }
static int FAST_FUNC lsattr_dir_proc(const char *dir_name, static int FAST_FUNC lsattr_dir_proc(const char *dir_name,

View File

@ -12751,7 +12751,7 @@ parsesub: {
do { do {
STPUTC(c, out); STPUTC(c, out);
c = pgetc_eatbnl(); c = pgetc_eatbnl();
} while (!subtype && isdigit(c)); } while ((subtype == 0 || subtype == VSLENGTH) && isdigit(c));
} else if (c != '}') { } else if (c != '}') {
/* $[{[#]]<specialchar>[}] */ /* $[{[#]]<specialchar>[}] */
int cc = c; int cc = c;
@ -12781,11 +12781,6 @@ parsesub: {
} else } else
goto badsub; goto badsub;
if (c != '}' && subtype == VSLENGTH) {
/* ${#VAR didn't end with } */
goto badsub;
}
if (subtype == 0) { if (subtype == 0) {
static const char types[] ALIGN1 = "}-+?="; static const char types[] ALIGN1 = "}-+?=";
/* ${VAR...} but not $VAR or ${#VAR} */ /* ${VAR...} but not $VAR or ${#VAR} */
@ -12842,6 +12837,8 @@ parsesub: {
#endif #endif
} }
} else { } else {
if (subtype == VSLENGTH && c != '}')
subtype = 0;
badsub: badsub:
pungetc(); pungetc();
} }