diff options
Diffstat (limited to 'e2fsprogs/lsattr.c')
-rw-r--r-- | e2fsprogs/lsattr.c | 80 |
1 files changed, 57 insertions, 23 deletions
diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c index ed7b67c6f..d82861e14 100644 --- a/e2fsprogs/lsattr.c +++ b/e2fsprogs/lsattr.c | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | //usage:#define lsattr_trivial_usage | 23 | //usage:#define lsattr_trivial_usage |
24 | //usage: IF_NOT_PLATFORM_MINGW32( | 24 | //usage: IF_NOT_PLATFORM_MINGW32( |
25 | //usage: "[-Radlv] [FILE]..." | 25 | //usage: "[-Radlpv] [FILE]..." |
26 | //usage: ) | 26 | //usage: ) |
27 | //usage: IF_PLATFORM_MINGW32( | 27 | //usage: IF_PLATFORM_MINGW32( |
28 | //usage: "[-Radl] [FILE]..." | 28 | //usage: "[-Radl] [FILE]..." |
@@ -30,10 +30,12 @@ | |||
30 | //usage:#define lsattr_full_usage "\n\n" | 30 | //usage:#define lsattr_full_usage "\n\n" |
31 | //usage: "List ext2 file attributes\n" | 31 | //usage: "List ext2 file attributes\n" |
32 | //usage: "\n -R Recurse" | 32 | //usage: "\n -R Recurse" |
33 | //usage: "\n -a Don't hide entries starting with ." | 33 | //usage: "\n -a Include names starting with ." |
34 | //usage: "\n -d List directory entries instead of contents" | 34 | //usage: "\n -d List directory names, not contents" |
35 | // -a,-d text should match ls --help | ||
35 | //usage: "\n -l List long flag names" | 36 | //usage: "\n -l List long flag names" |
36 | //usage: IF_NOT_PLATFORM_MINGW32( | 37 | //usage: IF_NOT_PLATFORM_MINGW32( |
38 | //usage: "\n -p List project ID" | ||
37 | //usage: "\n -v List version/generation number" | 39 | //usage: "\n -v List version/generation number" |
38 | //usage: ) | 40 | //usage: ) |
39 | 41 | ||
@@ -41,43 +43,71 @@ | |||
41 | #include "e2fs_lib.h" | 43 | #include "e2fs_lib.h" |
42 | 44 | ||
43 | enum { | 45 | enum { |
44 | OPT_RECUR = 0x1, | 46 | OPT_RECUR = 1 << 0, |
45 | OPT_ALL = 0x2, | 47 | OPT_ALL = 1 << 1, |
46 | OPT_DIRS_OPT = 0x4, | 48 | OPT_DIRS_OPT = 1 << 2, |
47 | OPT_PF_LONG = 0x8, | 49 | OPT_PF_LONG = 1 << 3, |
48 | OPT_GENERATION = 0x10, | 50 | OPT_GENERATION = 1 << 4, |
51 | OPT_PROJID = 1 << 5, | ||
49 | }; | 52 | }; |
50 | 53 | ||
51 | static void list_attributes(const char *name) | 54 | static void list_attributes(const char *name) |
52 | { | 55 | { |
53 | unsigned long fsflags; | 56 | unsigned fsflags; |
54 | #if !ENABLE_PLATFORM_MINGW32 | 57 | #if !ENABLE_PLATFORM_MINGW32 |
55 | unsigned long generation; | 58 | int fd, r; |
56 | #endif | 59 | |
57 | 60 | /* There is no way to run needed ioctls on a symlink. | |
58 | if (fgetflags(name, &fsflags) != 0) | 61 | * open(O_PATH | O_NOFOLLOW) _can_ be used to get a fd referring to the symlink, |
59 | goto read_err; | 62 | * but ioctls fail on such a fd (tried on 4.12.0 kernel). |
63 | * e2fsprogs-1.46.2 uses open(O_NOFOLLOW), it fails on symlinks. | ||
64 | */ | ||
65 | fd = open_or_warn(name, O_RDONLY | O_NONBLOCK | O_NOCTTY | O_NOFOLLOW); | ||
66 | if (fd < 0) | ||
67 | return; | ||
68 | |||
69 | if (option_mask32 & OPT_PROJID) { | ||
70 | struct ext2_fsxattr fsxattr; | ||
71 | r = ioctl(fd, EXT2_IOC_FSGETXATTR, &fsxattr); | ||
72 | /* note: ^^^ may fail in 32-bit userspace on 64-bit kernel (seen on 4.12.0) */ | ||
73 | if (r != 0) | ||
74 | goto read_err; | ||
75 | printf("%5u ", (unsigned)fsxattr.fsx_projid); | ||
76 | } | ||
60 | 77 | ||
61 | #if !ENABLE_PLATFORM_MINGW32 | ||
62 | if (option_mask32 & OPT_GENERATION) { | 78 | if (option_mask32 & OPT_GENERATION) { |
63 | if (fgetversion(name, &generation) != 0) | 79 | unsigned generation; |
80 | r = ioctl(fd, EXT2_IOC_GETVERSION, &generation); | ||
81 | if (r != 0) | ||
64 | goto read_err; | 82 | goto read_err; |
65 | printf("%5lu ", generation); | 83 | printf("%-10u ", generation); |
66 | } | 84 | } |
85 | |||
86 | r = ioctl(fd, EXT2_IOC_GETFLAGS, &fsflags); | ||
87 | if (r != 0) | ||
88 | goto read_err; | ||
89 | |||
90 | close(fd); | ||
91 | #else /* ENABLE_PLATFORM_MINGW32 */ | ||
92 | if (fgetflags(name, &fsflags) != 0) | ||
93 | goto read_err; | ||
67 | #endif | 94 | #endif |
68 | 95 | ||
69 | if (option_mask32 & OPT_PF_LONG) { | 96 | if (option_mask32 & OPT_PF_LONG) { |
70 | printf("%-28s ", name); | 97 | printf("%-28s ", name); |
71 | print_e2flags(stdout, fsflags, PFOPT_LONG); | 98 | print_e2flags_long(fsflags); |
72 | bb_putchar('\n'); | 99 | bb_putchar('\n'); |
73 | } else { | 100 | } else { |
74 | print_e2flags(stdout, fsflags, 0); | 101 | print_e2flags(fsflags); |
75 | printf(" %s\n", name); | 102 | printf(" %s\n", name); |
76 | } | 103 | } |
77 | 104 | ||
78 | return; | 105 | return; |
79 | read_err: | 106 | read_err: |
80 | bb_perror_msg("reading %s", name); | 107 | bb_perror_msg("reading %s", name); |
108 | #if !ENABLE_PLATFORM_MINGW32 | ||
109 | close(fd); | ||
110 | #endif | ||
81 | } | 111 | } |
82 | 112 | ||
83 | static int FAST_FUNC lsattr_dir_proc(const char *dir_name, | 113 | static int FAST_FUNC lsattr_dir_proc(const char *dir_name, |
@@ -90,9 +120,13 @@ static int FAST_FUNC lsattr_dir_proc(const char *dir_name, | |||
90 | path = concat_path_file(dir_name, de->d_name); | 120 | path = concat_path_file(dir_name, de->d_name); |
91 | 121 | ||
92 | if (lstat(path, &st) != 0) | 122 | if (lstat(path, &st) != 0) |
93 | bb_perror_msg("stat %s", path); | 123 | bb_perror_msg("can't stat '%s'", path); |
124 | |||
94 | else if (de->d_name[0] != '.' || (option_mask32 & OPT_ALL)) { | 125 | else if (de->d_name[0] != '.' || (option_mask32 & OPT_ALL)) { |
95 | list_attributes(path); | 126 | /* Don't try to open device files, fifos etc */ |
127 | if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode) || S_ISDIR(st.st_mode)) | ||
128 | list_attributes(path); | ||
129 | |||
96 | if (S_ISDIR(st.st_mode) && (option_mask32 & OPT_RECUR) | 130 | if (S_ISDIR(st.st_mode) && (option_mask32 & OPT_RECUR) |
97 | && !DOT_OR_DOTDOT(de->d_name) | 131 | && !DOT_OR_DOTDOT(de->d_name) |
98 | ) { | 132 | ) { |
@@ -111,7 +145,7 @@ static void lsattr_args(const char *name) | |||
111 | struct stat st; | 145 | struct stat st; |
112 | 146 | ||
113 | if (lstat(name, &st) == -1) { | 147 | if (lstat(name, &st) == -1) { |
114 | bb_perror_msg("stat %s", name); | 148 | bb_perror_msg("can't stat '%s'", name); |
115 | } else if (S_ISDIR(st.st_mode) && !(option_mask32 & OPT_DIRS_OPT)) { | 149 | } else if (S_ISDIR(st.st_mode) && !(option_mask32 & OPT_DIRS_OPT)) { |
116 | iterate_on_dir(name, lsattr_dir_proc, NULL); | 150 | iterate_on_dir(name, lsattr_dir_proc, NULL); |
117 | } else { | 151 | } else { |
@@ -125,7 +159,7 @@ int lsattr_main(int argc UNUSED_PARAM, char **argv) | |||
125 | #if ENABLE_PLATFORM_MINGW32 | 159 | #if ENABLE_PLATFORM_MINGW32 |
126 | getopt32(argv, "Radl"); | 160 | getopt32(argv, "Radl"); |
127 | #else | 161 | #else |
128 | getopt32(argv, "Radlv"); | 162 | getopt32(argv, "Radlvp"); |
129 | #endif | 163 | #endif |
130 | argv += optind; | 164 | argv += optind; |
131 | 165 | ||