lsattr,chattr: support -p
function old new delta fgetsetprojid - 107 +107 list_attributes 169 222 +53 change_attributes 277 326 +49 chattr_main 272 307 +35 close_silently - 22 +22 .rodata 103378 103393 +15 packed_usage 33658 33666 +8 fgetsetversion 88 74 -14 fgetsetflags 162 148 -14 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 5/2 up/down: 289/-28) Total: 261 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		| @@ -20,12 +20,12 @@ | ||||
| //kbuild:lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o | ||||
|  | ||||
| //usage:#define chattr_trivial_usage | ||||
| //usage:       "[-R] [-v VERSION] [-+=AacDdijsStTu] FILE..." | ||||
| //usage:       "[-R] [-v VERSION] [-p PROJID] [-+=AacDdijsStTu] FILE..." | ||||
| //usage:#define chattr_full_usage "\n\n" | ||||
| //usage:       "Change ext2 file attributes\n" | ||||
| //usage:     "\n	-R	Recurse" | ||||
| //TODD?      "\n	-p NUM	Set project number" | ||||
| //usage:     "\n	-v NUM	Set version/generation number" | ||||
| //usage:     "\n	-p NUM	Set project number" | ||||
| //-V, -f accepted but ignored | ||||
| //usage:     "\nModifiers:" | ||||
| //usage:     "\n	-,+,=	Remove/add/set attributes" | ||||
| @@ -45,16 +45,18 @@ | ||||
| #include "libbb.h" | ||||
| #include "e2fs_lib.h" | ||||
|  | ||||
| #define OPT_ADD 1 | ||||
| #define OPT_REM 2 | ||||
| #define OPT_SET 4 | ||||
| #define OPT_SET_VER 8 | ||||
| #define OPT_ADD      (1 << 0) | ||||
| #define OPT_REM      (1 << 1) | ||||
| #define OPT_SET      (1 << 2) | ||||
| #define OPT_SET_VER  (1 << 3) | ||||
| #define OPT_SET_PROJ (1 << 4) | ||||
|  | ||||
| struct globals { | ||||
| 	unsigned long version; | ||||
| 	unsigned long af; | ||||
| 	unsigned long rf; | ||||
| 	int flags; | ||||
| 	uint32_t projid; | ||||
| 	smallint recursive; | ||||
| }; | ||||
|  | ||||
| @@ -108,7 +110,13 @@ static char** decode_arg(char **argv, struct globals *gp) | ||||
| 				gp->flags |= OPT_SET_VER; | ||||
| 				continue; | ||||
| 			} | ||||
| //TODO: "-p PROJECT_NUM" ? | ||||
| 			if (*arg == 'p') { | ||||
| 				if (!*++argv) | ||||
| 					bb_show_usage(); | ||||
| 				gp->projid = xatou32(*argv); | ||||
| 				gp->flags |= OPT_SET_PROJ; | ||||
| 				continue; | ||||
| 			} | ||||
| 			/* not a known option, try as an attribute */ | ||||
| 		} | ||||
| 		*fl |= get_flag(*arg); | ||||
| @@ -151,7 +159,11 @@ static void change_attributes(const char *name, struct globals *gp) | ||||
|  | ||||
| 	if (gp->flags & OPT_SET_VER) | ||||
| 		if (fsetversion(name, gp->version) != 0) | ||||
| 			bb_perror_msg("setting version on %s", name); | ||||
| 			bb_perror_msg("setting %s on %s", "version", name); | ||||
|  | ||||
| 	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; | ||||
|   | ||||
| @@ -51,14 +51,14 @@ int fgetsetversion(const char *name, unsigned long *get_version, unsigned long s | ||||
| { | ||||
| #if HAVE_EXT2_IOCTLS | ||||
| 	int fd, r; | ||||
| 	IF_LONG_IS_WIDER(int ver;) | ||||
| 	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 = (int) set_version; | ||||
| 			ver = (unsigned) set_version; | ||||
| 			r = ioctl(fd, EXT2_IOC_SETVERSION, &ver); | ||||
| 		) | ||||
| 		IF_LONG_IS_SAME( | ||||
| @@ -81,6 +81,32 @@ int fgetsetversion(const char *name, unsigned long *get_version, unsigned long s | ||||
| #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) | ||||
| @@ -88,7 +114,7 @@ int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_f | ||||
| #if HAVE_EXT2_IOCTLS | ||||
| 	struct stat buf; | ||||
| 	int fd, r; | ||||
| 	IF_LONG_IS_WIDER(int f;) | ||||
| 	IF_LONG_IS_WIDER(unsigned f;) | ||||
|  | ||||
| 	if (stat(name, &buf) == 0 /* stat is ok */ | ||||
| 	 && !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) | ||||
| @@ -101,7 +127,7 @@ int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_f | ||||
|  | ||||
| 	if (!get_flags) { | ||||
| 		IF_LONG_IS_WIDER( | ||||
| 			f = (int) set_flags; | ||||
| 			f = (unsigned) set_flags; | ||||
| 			r = ioctl(fd, EXT2_IOC_SETFLAGS, &f); | ||||
| 		) | ||||
| 		IF_LONG_IS_SAME( | ||||
|   | ||||
| @@ -21,6 +21,11 @@ int fgetsetversion(const char *name, unsigned long *get_version, unsigned long s | ||||
| #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) | ||||
|   | ||||
| @@ -21,38 +21,48 @@ | ||||
| //kbuild:lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o | ||||
|  | ||||
| //usage:#define lsattr_trivial_usage | ||||
| //usage:       "[-Radlv] [FILE]..." | ||||
| //usage:       "[-Radlpv] [FILE]..." | ||||
| //usage:#define lsattr_full_usage "\n\n" | ||||
| //usage:       "List ext2 file attributes\n" | ||||
| //usage:     "\n	-R	Recurse" | ||||
| //usage:     "\n	-a	Don't hide entries starting with ." | ||||
| //usage:     "\n	-d	List directory entries instead of contents" | ||||
| //usage:     "\n	-a	Include names starting with ." | ||||
| //usage:     "\n	-d	List directory names, not contents" | ||||
| // -a,-d text should match ls --help | ||||
| //usage:     "\n	-l	List long flag names" | ||||
| //usage:     "\n	-p	List project ID" | ||||
| //usage:     "\n	-v	List version/generation number" | ||||
|  | ||||
| #include "libbb.h" | ||||
| #include "e2fs_lib.h" | ||||
|  | ||||
| enum { | ||||
| 	OPT_RECUR      = 0x1, | ||||
| 	OPT_ALL        = 0x2, | ||||
| 	OPT_DIRS_OPT   = 0x4, | ||||
| 	OPT_PF_LONG    = 0x8, | ||||
| 	OPT_GENERATION = 0x10, | ||||
| 	OPT_RECUR      = 1 << 0, | ||||
| 	OPT_ALL        = 1 << 1, | ||||
| 	OPT_DIRS_OPT   = 1 << 2, | ||||
| 	OPT_PF_LONG    = 1 << 3, | ||||
| 	OPT_GENERATION = 1 << 4, | ||||
| 	OPT_PROJID     = 1 << 5, | ||||
| }; | ||||
|  | ||||
| static void list_attributes(const char *name) | ||||
| { | ||||
| 	unsigned long fsflags; | ||||
| 	unsigned long generation; | ||||
|  | ||||
| 	if (fgetflags(name, &fsflags) != 0) | ||||
| 		goto read_err; | ||||
|  | ||||
| 	if (option_mask32 & OPT_PROJID) { | ||||
| 		uint32_t p; | ||||
| 		if (fgetprojid(name, &p) != 0) | ||||
| 			goto read_err; | ||||
| 		printf("%5lu ", (unsigned long)p); | ||||
| 	} | ||||
|  | ||||
| 	if (option_mask32 & OPT_GENERATION) { | ||||
| 		unsigned long generation; | ||||
| 		if (fgetversion(name, &generation) != 0) | ||||
| 			goto read_err; | ||||
| 		printf("%5lu ", generation); | ||||
| 		printf("%-10lu ", generation); | ||||
| 	} | ||||
|  | ||||
| 	if (option_mask32 & OPT_PF_LONG) { | ||||
| @@ -111,7 +121,7 @@ static void lsattr_args(const char *name) | ||||
| int lsattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||||
| int lsattr_main(int argc UNUSED_PARAM, char **argv) | ||||
| { | ||||
| 	getopt32(argv, "Radlv"); | ||||
| 	getopt32(argv, "Radlvp"); | ||||
| 	argv += optind; | ||||
|  | ||||
| 	if (!*argv) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user