1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35#include "libbb.h"
36#include "e2fs_lib.h"
37
38enum {
39 OPT_RECUR = 1 << 0,
40 OPT_ALL = 1 << 1,
41 OPT_DIRS_OPT = 1 << 2,
42 OPT_PF_LONG = 1 << 3,
43 OPT_GENERATION = 1 << 4,
44 OPT_PROJID = 1 << 5,
45};
46
47static void list_attributes(const char *name)
48{
49 unsigned fsflags;
50 int fd, r;
51
52
53
54
55
56
57 fd = open_or_warn(name, O_RDONLY | O_NONBLOCK | O_NOCTTY | O_NOFOLLOW);
58 if (fd < 0)
59 return;
60
61 if (option_mask32 & OPT_PROJID) {
62 struct ext2_fsxattr fsxattr;
63 r = ioctl(fd, EXT2_IOC_FSGETXATTR, &fsxattr);
64
65 if (r != 0)
66 goto read_err;
67 printf("%5u ", (unsigned)fsxattr.fsx_projid);
68 }
69
70 if (option_mask32 & OPT_GENERATION) {
71 unsigned generation;
72 r = ioctl(fd, EXT2_IOC_GETVERSION, &generation);
73 if (r != 0)
74 goto read_err;
75 printf("%-10u ", generation);
76 }
77
78 r = ioctl(fd, EXT2_IOC_GETFLAGS, &fsflags);
79 if (r != 0)
80 goto read_err;
81
82 close(fd);
83
84 if (option_mask32 & OPT_PF_LONG) {
85 printf("%-28s ", name);
86 print_e2flags_long(fsflags);
87 bb_putchar('\n');
88 } else {
89 print_e2flags(fsflags);
90 printf(" %s\n", name);
91 }
92
93 return;
94 read_err:
95 bb_perror_msg("reading %s", name);
96 close(fd);
97}
98
99static int FAST_FUNC lsattr_dir_proc(const char *dir_name,
100 struct dirent *de,
101 void *private UNUSED_PARAM)
102{
103 struct stat st;
104 char *path;
105
106 path = concat_path_file(dir_name, de->d_name);
107
108 if (lstat(path, &st) != 0)
109 bb_perror_msg("can't stat '%s'", path);
110
111 else if (de->d_name[0] != '.' || (option_mask32 & OPT_ALL)) {
112
113 if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode) || S_ISDIR(st.st_mode))
114 list_attributes(path);
115
116 if (S_ISDIR(st.st_mode) && (option_mask32 & OPT_RECUR)
117 && !DOT_OR_DOTDOT(de->d_name)
118 ) {
119 printf("\n%s:\n", path);
120 iterate_on_dir(path, lsattr_dir_proc, NULL);
121 bb_putchar('\n');
122 }
123 }
124
125 free(path);
126 return 0;
127}
128
129static void lsattr_args(const char *name)
130{
131 struct stat st;
132
133 if (lstat(name, &st) == -1) {
134 bb_perror_msg("can't stat '%s'", name);
135 } else if (S_ISDIR(st.st_mode) && !(option_mask32 & OPT_DIRS_OPT)) {
136 iterate_on_dir(name, lsattr_dir_proc, NULL);
137 } else {
138 list_attributes(name);
139 }
140}
141
142int lsattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
143int lsattr_main(int argc UNUSED_PARAM, char **argv)
144{
145 getopt32(argv, "Radlvp");
146 argv += optind;
147
148 if (!*argv)
149 *--argv = (char*)".";
150 do lsattr_args(*argv++); while (*argv);
151
152 return EXIT_SUCCESS;
153}
154