1/* vi: set sw=4 ts=4: */
2/*
3 * lsattr.c		- List file attributes on an ext2 file system
4 *
5 * Copyright (C) 1993, 1994  Remy Card <card@masi.ibp.fr>
6 *                           Laboratoire MASI, Institut Blaise Pascal
7 *                           Universite Pierre et Marie Curie (Paris VI)
8 *
9 * This file can be redistributed under the terms of the GNU General
10 * Public License
11 */
12
13/*
14 * History:
15 * 93/10/30	- Creation
16 * 93/11/13	- Replace stat() calls by lstat() to avoid loops
17 * 94/02/27	- Integrated in Ted's distribution
18 * 98/12/29	- Display version info only when -V specified (G M Sipe)
19 */
20
21#include "libbb.h"
22#include "e2fs_lib.h"
23
24enum {
25	OPT_RECUR      = 0x1,
26	OPT_ALL        = 0x2,
27	OPT_DIRS_OPT   = 0x4,
28	OPT_PF_LONG    = 0x8,
29	OPT_GENERATION = 0x10,
30};
31
32static void list_attributes(const char *name)
33{
34	unsigned long fsflags;
35	unsigned long generation;
36
37	if (fgetflags(name, &fsflags) != 0)
38		goto read_err;
39
40	if (option_mask32 & OPT_GENERATION) {
41		if (fgetversion(name, &generation) != 0)
42			goto read_err;
43		printf("%5lu ", generation);
44	}
45
46	if (option_mask32 & OPT_PF_LONG) {
47		printf("%-28s ", name);
48		print_flags(stdout, fsflags, PFOPT_LONG);
49		puts("");
50	} else {
51		print_flags(stdout, fsflags, 0);
52		printf(" %s\n", name);
53	}
54
55	return;
56 read_err:
57	bb_perror_msg("reading %s", name);
58}
59
60static int lsattr_dir_proc(const char *dir_name, struct dirent *de,
61			   void *private)
62{
63	struct stat st;
64	char *path;
65
66	path = concat_path_file(dir_name, de->d_name);
67
68	if (lstat(path, &st) != 0)
69		bb_perror_msg("stat %s", path);
70	else if (de->d_name[0] != '.' || (option_mask32 & OPT_ALL)) {
71		list_attributes(path);
72		if (S_ISDIR(st.st_mode) && (option_mask32 & OPT_RECUR)
73		 && !DOT_OR_DOTDOT(de->d_name)
74		) {
75			printf("\n%s:\n", path);
76			iterate_on_dir(path, lsattr_dir_proc, NULL);
77			puts("");
78		}
79	}
80
81	free(path);
82	return 0;
83}
84
85static void lsattr_args(const char *name)
86{
87	struct stat st;
88
89	if (lstat(name, &st) == -1) {
90		bb_perror_msg("stat %s", name);
91	} else if (S_ISDIR(st.st_mode) && !(option_mask32 & OPT_DIRS_OPT)) {
92		iterate_on_dir(name, lsattr_dir_proc, NULL);
93	} else {
94		list_attributes(name);
95	}
96}
97
98int lsattr_main(int argc, char **argv);
99int lsattr_main(int argc, char **argv)
100{
101	getopt32(argv, "Radlv");
102	argv += optind;
103
104	if (!*argv)
105		lsattr_args(".");
106	else {
107		while (*argv)
108			lsattr_args(*argv++);
109	}
110
111	return EXIT_SUCCESS;
112}
113