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:
		| @@ -61,9 +61,9 @@ | ||||
| #define OPT_SET_PROJ (1 << 4) | ||||
|  | ||||
| struct globals { | ||||
| 	unsigned long version; | ||||
| 	unsigned long af; | ||||
| 	unsigned long rf; | ||||
| 	unsigned version; | ||||
| 	unsigned af; | ||||
| 	unsigned rf; | ||||
| 	int flags; | ||||
| 	uint32_t projid; | ||||
| 	smallint recursive; | ||||
| @@ -79,7 +79,7 @@ static unsigned long get_flag(char c) | ||||
|  | ||||
| static char** decode_arg(char **argv, struct globals *gp) | ||||
| { | ||||
| 	unsigned long *fl; | ||||
| 	unsigned *fl; | ||||
| 	const char *arg = *argv; | ||||
| 	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) | ||||
| { | ||||
| 	unsigned long fsflags; | ||||
| 	unsigned fsflags; | ||||
| 	int fd; | ||||
| 	struct stat st; | ||||
|  | ||||
| 	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)) | ||||
| 		return; | ||||
|  | ||||
| 	if (gp->flags & OPT_SET_VER) | ||||
| 		if (fsetversion(name, gp->version) != 0) | ||||
| 			bb_perror_msg("setting %s on %s", "version", name); | ||||
| 	fd = open_or_warn(name, O_RDONLY | O_NONBLOCK); /* neither read nor write asked for */ | ||||
| 	if (fd >= 0) { | ||||
| 		int r; | ||||
|  | ||||
| 	if (gp->flags & OPT_SET_PROJ) | ||||
| 		if (fsetprojid(name, gp->projid) != 0) | ||||
| 			bb_perror_msg("setting %s on %s", "project ID", 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_SET_VER) { | ||||
| 			r = ioctl(fd, EXT2_IOC_SETVERSION, &gp->version); | ||||
| 			if (r != 0) | ||||
| 				bb_perror_msg("setting %s on %s", "version", name); | ||||
| 		} | ||||
| 		/*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: | ||||
| 		close(fd); | ||||
| 	} | ||||
|  | ||||
| 	if (gp->recursive && S_ISDIR(st.st_mode)) | ||||
| 		iterate_on_dir(name, chattr_dir_proc, gp); | ||||
| } | ||||
|   | ||||
| @@ -8,8 +8,6 @@ | ||||
| #include "libbb.h" | ||||
| #include "e2fs_lib.h" | ||||
|  | ||||
| #define HAVE_EXT2_IOCTLS 1 | ||||
|  | ||||
| #if INT_MAX == LONG_MAX | ||||
| #define IF_LONG_IS_SAME(...) __VA_ARGS__ | ||||
| #define IF_LONG_IS_WIDER(...) | ||||
| @@ -18,14 +16,6 @@ | ||||
| #define IF_LONG_IS_WIDER(...) __VA_ARGS__ | ||||
| #endif | ||||
|  | ||||
| static void close_silently(int fd) | ||||
| { | ||||
| 	int e = errno; | ||||
| 	close(fd); | ||||
| 	errno = e; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Iterate a function on each entry of a directory */ | ||||
| int iterate_on_dir(const char *dir_name, | ||||
| 		int FAST_FUNC (*func)(const char *, struct dirent *, void *), | ||||
| @@ -45,113 +35,6 @@ int iterate_on_dir(const char *dir_name, | ||||
| 	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 */ | ||||
| const uint32_t e2attr_flags_value[] ALIGN4 = { | ||||
| #ifdef ENABLE_COMPRESSION | ||||
| @@ -215,7 +98,7 @@ static const char e2attr_flags_lname[] ALIGN1 = | ||||
| 	"Verity" "\0" | ||||
| 	/* 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 char *fn; | ||||
|   | ||||
| @@ -16,25 +16,10 @@ int iterate_on_dir(const char *dir_name, | ||||
| 		int FAST_FUNC (*func)(const char *, struct dirent *, void *), | ||||
| 		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'. */ | ||||
| #define PFOPT_LONG  1 | ||||
| /* 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 char e2attr_flags_sname[]; | ||||
|   | ||||
| @@ -46,25 +46,35 @@ enum { | ||||
|  | ||||
| static void list_attributes(const char *name) | ||||
| { | ||||
| 	unsigned long fsflags; | ||||
| 	unsigned fsflags; | ||||
| 	int fd, r; | ||||
|  | ||||
| 	if (fgetflags(name, &fsflags) != 0) | ||||
| 		goto read_err; | ||||
| 	fd = open_or_warn(name, O_RDONLY | O_NONBLOCK); /* neither read nor write asked for */ | ||||
| 	if (fd < 0) /* for example, dangling links */ | ||||
| 		return; | ||||
|  | ||||
| 	if (option_mask32 & OPT_PROJID) { | ||||
| 		uint32_t p; | ||||
| 		if (fgetprojid(name, &p) != 0) | ||||
| 		struct ext2_fsxattr fsxattr; | ||||
| 		r = ioctl(fd, EXT2_IOC_FSGETXATTR, &fsxattr); | ||||
| 		if (r != 0) | ||||
| 			goto read_err; | ||||
| 		printf("%5lu ", (unsigned long)p); | ||||
| 		printf("%5u ", (unsigned)fsxattr.fsx_projid); | ||||
| 	} | ||||
|  | ||||
| 	if (option_mask32 & OPT_GENERATION) { | ||||
| 		unsigned long generation; | ||||
| 		if (fgetversion(name, &generation) != 0) | ||||
| 		unsigned generation; | ||||
| 		r = ioctl(fd, EXT2_IOC_GETVERSION, &generation); | ||||
| 		if (r != 0) | ||||
| 			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) { | ||||
| 		printf("%-28s ", name); | ||||
| 		print_e2flags(stdout, fsflags, PFOPT_LONG); | ||||
| @@ -77,6 +87,7 @@ static void list_attributes(const char *name) | ||||
| 	return; | ||||
|  read_err: | ||||
| 	bb_perror_msg("reading %s", name); | ||||
| 	close(fd); | ||||
| } | ||||
|  | ||||
| static int FAST_FUNC lsattr_dir_proc(const char *dir_name, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user