d3896637db86358020f9e48d225a8a8c6086baf7
[oweals/busybox.git] / e2fsprogs / lsattr.c
1 /*
2  * lsattr.c             - List file attributes on an ext2 file system
3  *
4  * Copyright (C) 1993, 1994  Remy Card <card@masi.ibp.fr>
5  *                           Laboratoire MASI, Institut Blaise Pascal
6  *                           Universite Pierre et Marie Curie (Paris VI)
7  *
8  * This file can be redistributed under the terms of the GNU General
9  * Public License
10  */
11
12 /*
13  * History:
14  * 93/10/30     - Creation
15  * 93/11/13     - Replace stat() calls by lstat() to avoid loops
16  * 94/02/27     - Integrated in Ted's distribution
17  * 98/12/29     - Display version info only when -V specified (G M Sipe)
18  */
19
20 #include <sys/types.h>
21 #include <dirent.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <getopt.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/param.h>
30 #include <sys/stat.h>
31
32 #include <ext2fs/ext2_fs.h>
33 #include "e2fsbb.h"
34 #include "e2p/e2p.h"
35
36 #ifdef __GNUC__
37 #define EXT2FS_ATTR(x) __attribute__(x)
38 #else
39 #define EXT2FS_ATTR(x)
40 #endif
41
42 #define OPT_RECUR 1
43 #define OPT_ALL 2
44 #define OPT_DIRS_OPT 4
45 #define OPT_PF_LONG 8
46 #define OPT_GENERATION 16
47 static int flags;
48
49 #ifdef CONFIG_LFS
50 # define LSTAT lstat64
51 # define STRUCT_STAT struct stat64
52 #else
53 # define LSTAT lstat
54 # define STRUCT_STAT struct stat
55 #endif
56
57 static void list_attributes(const char *name)
58 {
59         unsigned long fsflags;
60         unsigned long generation;
61
62         if (fgetflags(name, &fsflags) == -1) {
63                 bb_perror_msg("While reading flags on %s", name);
64                 return;
65         }
66         if (flags & OPT_GENERATION) {
67                 if (fgetversion(name, &generation) == -1) {
68                         bb_perror_msg("While reading version on %s", name);
69                         return;
70                 }
71                 printf("%5lu ", generation);
72         }
73         if (flags & OPT_PF_LONG) {
74                 printf("%-28s ", name);
75                 print_flags(stdout, fsflags, PFOPT_LONG);
76                 fputc('\n', stdout);
77         } else {
78                 print_flags(stdout, fsflags, 0);
79                 printf(" %s\n", name);
80         }
81 }
82
83 static int lsattr_dir_proc(const char *, struct dirent *, void *);
84
85 static void lsattr_args(const char *name)
86 {
87         STRUCT_STAT     st;
88
89         if (LSTAT(name, &st) == -1)
90                 bb_perror_msg("while trying to stat %s", name);
91         else {
92                 if (S_ISDIR(st.st_mode) && !(flags & OPT_DIRS_OPT))
93                         iterate_on_dir(name, lsattr_dir_proc, NULL);
94                 else
95                         list_attributes(name);
96         }
97 }
98
99 static int lsattr_dir_proc(const char *dir_name, struct dirent *de, 
100                            void *private EXT2FS_ATTR((unused)))
101 {
102         STRUCT_STAT     st;
103         char *path;
104         int i = strlen(dir_name);
105
106         if (i && dir_name[i-1] == '/')
107                 i = asprintf(&path, "%s%s", dir_name, de->d_name);
108         else
109                 i = asprintf(&path, "%s/%s", dir_name, de->d_name);
110         if (i == -1)
111                 bb_perror_msg_and_die("asprintf failed");
112
113         if (LSTAT(path, &st) == -1)
114                 bb_perror_msg(path);
115         else {
116                 if (de->d_name[0] != '.' || (flags & OPT_ALL)) {
117                         list_attributes(path);
118                         if (S_ISDIR(st.st_mode) && (flags & OPT_RECUR) &&
119                             strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) {
120                                 printf("\n%s:\n", path);
121                                 iterate_on_dir(path, lsattr_dir_proc, NULL);
122                                 printf("\n");
123                         }
124                 }
125         }
126
127         free(path);
128
129         return 0;
130 }
131
132 int lsattr_main(int argc, char **argv)
133 {
134         int i;
135
136         flags = bb_getopt_ulflags(argc, argv, "Radlv");
137
138         if (optind > argc - 1)
139                 lsattr_args(".");
140         else
141                 for (i = optind; i < argc; i++)
142                         lsattr_args(argv[i]);
143
144         return EXIT_SUCCESS;
145 }