- use bb_msg_{read,write}_error where appropriate.
[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 #define OPT_RECUR 1
37 #define OPT_ALL 2
38 #define OPT_DIRS_OPT 4
39 #define OPT_PF_LONG 8
40 #define OPT_GENERATION 16
41 static int flags;
42
43 #ifdef CONFIG_LFS
44 # define LSTAT lstat64
45 # define STRUCT_STAT struct stat64
46 #else
47 # define LSTAT lstat
48 # define STRUCT_STAT struct stat
49 #endif
50
51 static void list_attributes(const char *name)
52 {
53         unsigned long fsflags;
54         unsigned long generation;
55
56         if (fgetflags(name, &fsflags) == -1)
57                 goto read_err;
58         if (flags & OPT_GENERATION) {
59                 if (fgetversion(name, &generation) == -1)
60                         goto read_err;
61                 printf("%5lu ", generation);
62         }
63
64         if (flags & OPT_PF_LONG) {
65                 printf("%-28s ", name);
66                 print_flags(stdout, fsflags, PFOPT_LONG);
67                 printf("\n");
68         } else {
69                 print_flags(stdout, fsflags, 0);
70                 printf(" %s\n", name);
71         }
72
73         return;
74 read_err:
75         bb_perror_msg("reading %s", name);
76 }
77
78 static int lsattr_dir_proc(const char *, struct dirent *, void *);
79
80 static void lsattr_args(const char *name)
81 {
82         STRUCT_STAT     st;
83
84         if (LSTAT(name, &st) == -1) {
85                 bb_perror_msg("stating %s", name);
86         } else {
87                 if (S_ISDIR(st.st_mode) && !(flags & OPT_DIRS_OPT))
88                         iterate_on_dir(name, lsattr_dir_proc, NULL);
89                 else
90                         list_attributes(name);
91         }
92 }
93
94 static int lsattr_dir_proc(const char *dir_name, struct dirent *de,
95                            void *private)
96 {
97         STRUCT_STAT     st;
98         char *path;
99
100         path = concat_path_file(dir_name, de->d_name);
101
102         if (LSTAT(path, &st) == -1)
103                 bb_perror_msg(path);
104         else {
105                 if (de->d_name[0] != '.' || (flags & OPT_ALL)) {
106                         list_attributes(path);
107                         if (S_ISDIR(st.st_mode) && (flags & OPT_RECUR) &&
108                            (de->d_name[0] != '.' && (de->d_name[1] != '\0' ||
109                            (de->d_name[1] != '.' && de->d_name[2] != '\0')))) {
110                                 printf("\n%s:\n", path);
111                                 iterate_on_dir(path, lsattr_dir_proc, NULL);
112                                 printf("\n");
113                         }
114                 }
115         }
116
117         free(path);
118
119         return 0;
120 }
121
122 int lsattr_main(int argc, char **argv)
123 {
124         int i;
125
126         flags = bb_getopt_ulflags(argc, argv, "Radlv");
127
128         if (optind > argc - 1)
129                 lsattr_args(".");
130         else
131                 for (i = optind; i < argc; i++)
132                         lsattr_args(argv[i]);
133
134         return EXIT_SUCCESS;
135 }