aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-06-20 10:57:24 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-06-20 11:02:49 +0200
commit526b8347906a18d756386092fafa0b42ba0b4563 (patch)
treeaafe396ff964a194f183bead405b5f1045f67a61
parent9c291f2cc0e0e76869c315b5c7e7883827b5ae95 (diff)
downloadbusybox-w32-526b8347906a18d756386092fafa0b42ba0b4563.tar.gz
busybox-w32-526b8347906a18d756386092fafa0b42ba0b4563.tar.bz2
busybox-w32-526b8347906a18d756386092fafa0b42ba0b4563.zip
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>
-rw-r--r--e2fsprogs/chattr.c28
-rw-r--r--e2fsprogs/e2fs_lib.c34
-rw-r--r--e2fsprogs/e2fs_lib.h5
-rw-r--r--e2fsprogs/lsattr.c32
-rw-r--r--include/bb_e2fs_defs.h12
5 files changed, 88 insertions, 23 deletions
diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c
index 1d267f7a4..5a7545e09 100644
--- a/e2fsprogs/chattr.c
+++ b/e2fsprogs/chattr.c
@@ -20,12 +20,12 @@
20//kbuild:lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o 20//kbuild:lib-$(CONFIG_CHATTR) += chattr.o e2fs_lib.o
21 21
22//usage:#define chattr_trivial_usage 22//usage:#define chattr_trivial_usage
23//usage: "[-R] [-v VERSION] [-+=AacDdijsStTu] FILE..." 23//usage: "[-R] [-v VERSION] [-p PROJID] [-+=AacDdijsStTu] FILE..."
24//usage:#define chattr_full_usage "\n\n" 24//usage:#define chattr_full_usage "\n\n"
25//usage: "Change ext2 file attributes\n" 25//usage: "Change ext2 file attributes\n"
26//usage: "\n -R Recurse" 26//usage: "\n -R Recurse"
27//TODD? "\n -p NUM Set project number"
28//usage: "\n -v NUM Set version/generation number" 27//usage: "\n -v NUM Set version/generation number"
28//usage: "\n -p NUM Set project number"
29//-V, -f accepted but ignored 29//-V, -f accepted but ignored
30//usage: "\nModifiers:" 30//usage: "\nModifiers:"
31//usage: "\n -,+,= Remove/add/set attributes" 31//usage: "\n -,+,= Remove/add/set attributes"
@@ -45,16 +45,18 @@
45#include "libbb.h" 45#include "libbb.h"
46#include "e2fs_lib.h" 46#include "e2fs_lib.h"
47 47
48#define OPT_ADD 1 48#define OPT_ADD (1 << 0)
49#define OPT_REM 2 49#define OPT_REM (1 << 1)
50#define OPT_SET 4 50#define OPT_SET (1 << 2)
51#define OPT_SET_VER 8 51#define OPT_SET_VER (1 << 3)
52#define OPT_SET_PROJ (1 << 4)
52 53
53struct globals { 54struct globals {
54 unsigned long version; 55 unsigned long version;
55 unsigned long af; 56 unsigned long af;
56 unsigned long rf; 57 unsigned long rf;
57 int flags; 58 int flags;
59 uint32_t projid;
58 smallint recursive; 60 smallint recursive;
59}; 61};
60 62
@@ -108,7 +110,13 @@ static char** decode_arg(char **argv, struct globals *gp)
108 gp->flags |= OPT_SET_VER; 110 gp->flags |= OPT_SET_VER;
109 continue; 111 continue;
110 } 112 }
111//TODO: "-p PROJECT_NUM" ? 113 if (*arg == 'p') {
114 if (!*++argv)
115 bb_show_usage();
116 gp->projid = xatou32(*argv);
117 gp->flags |= OPT_SET_PROJ;
118 continue;
119 }
112 /* not a known option, try as an attribute */ 120 /* not a known option, try as an attribute */
113 } 121 }
114 *fl |= get_flag(*arg); 122 *fl |= get_flag(*arg);
@@ -151,7 +159,11 @@ static void change_attributes(const char *name, struct globals *gp)
151 159
152 if (gp->flags & OPT_SET_VER) 160 if (gp->flags & OPT_SET_VER)
153 if (fsetversion(name, gp->version) != 0) 161 if (fsetversion(name, gp->version) != 0)
154 bb_perror_msg("setting version on %s", name); 162 bb_perror_msg("setting %s on %s", "version", name);
163
164 if (gp->flags & OPT_SET_PROJ)
165 if (fsetprojid(name, gp->projid) != 0)
166 bb_perror_msg("setting %s on %s", "project ID", name);
155 167
156 if (gp->flags & OPT_SET) { 168 if (gp->flags & OPT_SET) {
157 fsflags = gp->af; 169 fsflags = gp->af;
diff --git a/e2fsprogs/e2fs_lib.c b/e2fsprogs/e2fs_lib.c
index 8bd4da622..bc9aa53e5 100644
--- a/e2fsprogs/e2fs_lib.c
+++ b/e2fsprogs/e2fs_lib.c
@@ -51,14 +51,14 @@ int fgetsetversion(const char *name, unsigned long *get_version, unsigned long s
51{ 51{
52#if HAVE_EXT2_IOCTLS 52#if HAVE_EXT2_IOCTLS
53 int fd, r; 53 int fd, r;
54 IF_LONG_IS_WIDER(int ver;) 54 IF_LONG_IS_WIDER(unsigned ver;)
55 55
56 fd = open(name, O_RDONLY | O_NONBLOCK); 56 fd = open(name, O_RDONLY | O_NONBLOCK);
57 if (fd == -1) 57 if (fd == -1)
58 return -1; 58 return -1;
59 if (!get_version) { 59 if (!get_version) {
60 IF_LONG_IS_WIDER( 60 IF_LONG_IS_WIDER(
61 ver = (int) set_version; 61 ver = (unsigned) set_version;
62 r = ioctl(fd, EXT2_IOC_SETVERSION, &ver); 62 r = ioctl(fd, EXT2_IOC_SETVERSION, &ver);
63 ) 63 )
64 IF_LONG_IS_SAME( 64 IF_LONG_IS_SAME(
@@ -81,6 +81,32 @@ int fgetsetversion(const char *name, unsigned long *get_version, unsigned long s
81#endif /* ! HAVE_EXT2_IOCTLS */ 81#endif /* ! HAVE_EXT2_IOCTLS */
82} 82}
83 83
84int fgetsetprojid(const char *name, uint32_t *get, uint32_t set)
85{
86#if HAVE_EXT2_IOCTLS
87 struct ext2_fsxattr fsxattr;
88 int fd, r;
89
90 fd = open(name, O_RDONLY | O_NONBLOCK);
91 if (fd == -1)
92 return -1;
93 r = ioctl(fd, EXT2_IOC_FSGETXATTR, &fsxattr);
94 /* note: ^^^ may fail in 32-bit userspace on 64-bit kernel (seen on 4.12.0) */
95 if (r == 0) {
96 if (get) {
97 *get = fsxattr.fsx_projid;
98 } else {
99 fsxattr.fsx_projid = set;
100 r = ioctl(fd, EXT2_IOC_FSSETXATTR, &fsxattr);
101 }
102 }
103 close_silently(fd);
104 return r;
105#else /* ! HAVE_EXT2_IOCTLS */
106 errno = EOPNOTSUPP;
107 return -1;
108#endif /* ! HAVE_EXT2_IOCTLS */
109}
84 110
85/* Get/set a file flags on an ext2 file system */ 111/* Get/set a file flags on an ext2 file system */
86int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_flags) 112int 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
88#if HAVE_EXT2_IOCTLS 114#if HAVE_EXT2_IOCTLS
89 struct stat buf; 115 struct stat buf;
90 int fd, r; 116 int fd, r;
91 IF_LONG_IS_WIDER(int f;) 117 IF_LONG_IS_WIDER(unsigned f;)
92 118
93 if (stat(name, &buf) == 0 /* stat is ok */ 119 if (stat(name, &buf) == 0 /* stat is ok */
94 && !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) 120 && !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
101 127
102 if (!get_flags) { 128 if (!get_flags) {
103 IF_LONG_IS_WIDER( 129 IF_LONG_IS_WIDER(
104 f = (int) set_flags; 130 f = (unsigned) set_flags;
105 r = ioctl(fd, EXT2_IOC_SETFLAGS, &f); 131 r = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
106 ) 132 )
107 IF_LONG_IS_SAME( 133 IF_LONG_IS_SAME(
diff --git a/e2fsprogs/e2fs_lib.h b/e2fsprogs/e2fs_lib.h
index ae28c353b..82a1581cb 100644
--- a/e2fsprogs/e2fs_lib.h
+++ b/e2fsprogs/e2fs_lib.h
@@ -21,6 +21,11 @@ int fgetsetversion(const char *name, unsigned long *get_version, unsigned long s
21#define fgetversion(name, version) fgetsetversion(name, version, 0) 21#define fgetversion(name, version) fgetsetversion(name, version, 0)
22#define fsetversion(name, version) fgetsetversion(name, NULL, version) 22#define fsetversion(name, version) fgetsetversion(name, NULL, version)
23 23
24/* Get/set a file project ID on an ext2 file system */
25int fgetsetprojid(const char *name, uint32_t *get, uint32_t set);
26#define fgetprojid(name, projid) fgetsetprojid(name, projid, 0)
27#define fsetprojid(name, projid) fgetsetprojid(name, NULL, projid)
28
24/* Get/set a file flags on an ext2 file system */ 29/* Get/set a file flags on an ext2 file system */
25int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_flags); 30int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_flags);
26#define fgetflags(name, flags) fgetsetflags(name, flags, 0) 31#define fgetflags(name, flags) fgetsetflags(name, flags, 0)
diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c
index 91205ff65..9b035f584 100644
--- a/e2fsprogs/lsattr.c
+++ b/e2fsprogs/lsattr.c
@@ -21,38 +21,48 @@
21//kbuild:lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o 21//kbuild:lib-$(CONFIG_LSATTR) += lsattr.o e2fs_lib.o
22 22
23//usage:#define lsattr_trivial_usage 23//usage:#define lsattr_trivial_usage
24//usage: "[-Radlv] [FILE]..." 24//usage: "[-Radlpv] [FILE]..."
25//usage:#define lsattr_full_usage "\n\n" 25//usage:#define lsattr_full_usage "\n\n"
26//usage: "List ext2 file attributes\n" 26//usage: "List ext2 file attributes\n"
27//usage: "\n -R Recurse" 27//usage: "\n -R Recurse"
28//usage: "\n -a Don't hide entries starting with ." 28//usage: "\n -a Include names starting with ."
29//usage: "\n -d List directory entries instead of contents" 29//usage: "\n -d List directory names, not contents"
30// -a,-d text should match ls --help
30//usage: "\n -l List long flag names" 31//usage: "\n -l List long flag names"
32//usage: "\n -p List project ID"
31//usage: "\n -v List version/generation number" 33//usage: "\n -v List version/generation number"
32 34
33#include "libbb.h" 35#include "libbb.h"
34#include "e2fs_lib.h" 36#include "e2fs_lib.h"
35 37
36enum { 38enum {
37 OPT_RECUR = 0x1, 39 OPT_RECUR = 1 << 0,
38 OPT_ALL = 0x2, 40 OPT_ALL = 1 << 1,
39 OPT_DIRS_OPT = 0x4, 41 OPT_DIRS_OPT = 1 << 2,
40 OPT_PF_LONG = 0x8, 42 OPT_PF_LONG = 1 << 3,
41 OPT_GENERATION = 0x10, 43 OPT_GENERATION = 1 << 4,
44 OPT_PROJID = 1 << 5,
42}; 45};
43 46
44static void list_attributes(const char *name) 47static void list_attributes(const char *name)
45{ 48{
46 unsigned long fsflags; 49 unsigned long fsflags;
47 unsigned long generation;
48 50
49 if (fgetflags(name, &fsflags) != 0) 51 if (fgetflags(name, &fsflags) != 0)
50 goto read_err; 52 goto read_err;
51 53
54 if (option_mask32 & OPT_PROJID) {
55 uint32_t p;
56 if (fgetprojid(name, &p) != 0)
57 goto read_err;
58 printf("%5lu ", (unsigned long)p);
59 }
60
52 if (option_mask32 & OPT_GENERATION) { 61 if (option_mask32 & OPT_GENERATION) {
62 unsigned long generation;
53 if (fgetversion(name, &generation) != 0) 63 if (fgetversion(name, &generation) != 0)
54 goto read_err; 64 goto read_err;
55 printf("%5lu ", generation); 65 printf("%-10lu ", generation);
56 } 66 }
57 67
58 if (option_mask32 & OPT_PF_LONG) { 68 if (option_mask32 & OPT_PF_LONG) {
@@ -111,7 +121,7 @@ static void lsattr_args(const char *name)
111int lsattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 121int lsattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
112int lsattr_main(int argc UNUSED_PARAM, char **argv) 122int lsattr_main(int argc UNUSED_PARAM, char **argv)
113{ 123{
114 getopt32(argv, "Radlv"); 124 getopt32(argv, "Radlvp");
115 argv += optind; 125 argv += optind;
116 126
117 if (!*argv) 127 if (!*argv)
diff --git a/include/bb_e2fs_defs.h b/include/bb_e2fs_defs.h
index 3f5e3c45b..2d72288ed 100644
--- a/include/bb_e2fs_defs.h
+++ b/include/bb_e2fs_defs.h
@@ -195,6 +195,18 @@ struct ext2_dx_countlimit {
195#define EXT2_IOC_SETFLAGS _IOW('f', 2, long) 195#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
196#define EXT2_IOC_GETVERSION _IOR('v', 1, long) 196#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
197#define EXT2_IOC_SETVERSION _IOW('v', 2, long) 197#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
198//NB: despite "long" in defs above, these ioctls use an _int_!
199//passing them a pointer to long will read/write only int-sized data!
200struct ext2_fsxattr {
201 uint32_t fsx_xflags; /* xflags field value (get/set) */
202 uint32_t fsx_extsize; /* extsize field value (get/set)*/
203 uint32_t fsx_nextents; /* nextents field value (get) */
204 uint32_t fsx_projid; /* project identifier (get/set) */
205 uint32_t fsx_cowextsize; /* CoW extsize field value (get/set)*/
206 unsigned char fsx_pad[8];
207};
208#define EXT2_IOC_FSGETXATTR _IOR('X', 31, struct ext2_fsxattr)
209#define EXT2_IOC_FSSETXATTR _IOW('X', 32, struct ext2_fsxattr)
198 210
199/* 211/*
200 * Structure of an inode on the disk 212 * Structure of an inode on the disk