Whamcloud - gitweb
9e1cc33fcbd4f5f47b38dc598c388170acac2771
[tools/e2fsprogs.git] / misc / 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 #define _LARGEFILE64_SOURCE
21
22 #include <sys/types.h>
23 #include <dirent.h>
24 #ifdef HAVE_ERRNO_H
25 #include <errno.h>
26 #endif
27 #include <fcntl.h>
28 #ifdef HAVE_GETOPT_H
29 #include <getopt.h>
30 #else
31 extern int optind;
32 extern char *optarg;
33 #endif
34 #include <stdio.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/param.h>
39 #include <sys/stat.h>
40
41 #include "ext2fs/ext2_fs.h"
42 #include "et/com_err.h"
43 #include "e2p/e2p.h"
44
45 #include "../version.h"
46 #include "nls-enable.h"
47
48 static const char * program_name = "lsattr";
49
50 static int all;
51 static int dirs_opt;
52 static unsigned pf_options;
53 static int recursive;
54 static int verbose;
55 static int generation_opt;
56
57 #ifdef _LFS64_LARGEFILE
58 #define LSTAT           lstat64
59 #define STRUCT_STAT     struct stat64
60 #else
61 #define LSTAT           lstat
62 #define STRUCT_STAT     struct stat
63 #endif
64
65 static void usage(void)
66 {
67         fprintf(stderr, _("Usage: %s [-RVadlv] [files...]\n"), program_name);
68         exit(1);
69 }
70
71 static void list_attributes (const char * name)
72 {
73         unsigned long flags;
74         unsigned long generation;
75
76         if (fgetflags (name, &flags) == -1) {
77                 com_err (program_name, errno, _("While reading flags on %s"),
78                          name);
79                 return;
80         }
81         if (generation_opt) {
82                 if (fgetversion (name, &generation) == -1) {
83                         com_err (program_name, errno,
84                                  _("While reading version on %s"),
85                                  name);
86                         return;
87                 }
88                 printf ("%5lu ", generation);
89         }
90         if (pf_options & PFOPT_LONG) {
91                 printf("%-28s ", name);
92                 print_flags(stdout, flags, pf_options);
93                 fputc('\n', stdout);
94         } else {
95                 print_flags(stdout, flags, pf_options);
96                 printf(" %s\n", name);
97         }
98 }
99
100 static int lsattr_dir_proc (const char *, struct dirent *, void *);
101
102 static void lsattr_args (const char * name)
103 {
104         STRUCT_STAT     st;
105
106         if (LSTAT (name, &st) == -1)
107                 com_err (program_name, errno, _("while trying to stat %s"),
108                          name);
109         else {
110                 if (S_ISDIR(st.st_mode) && !dirs_opt)
111                         iterate_on_dir (name, lsattr_dir_proc, NULL);
112                 else
113                         list_attributes (name);
114         }
115 }
116
117 static int lsattr_dir_proc (const char * dir_name, struct dirent * de, void * private)
118 {
119         STRUCT_STAT     st;
120         char *path;
121
122         path = malloc(strlen (dir_name) + 1 + strlen (de->d_name) + 1);
123
124         sprintf (path, "%s/%s", dir_name, de->d_name);
125         if (LSTAT (path, &st) == -1)
126                 perror (path);
127         else {
128                 if (de->d_name[0] != '.' || all) {
129                         list_attributes (path);
130                         if (S_ISDIR(st.st_mode) && recursive &&
131                             strcmp(de->d_name, ".") &&
132                             strcmp(de->d_name, "..")) {
133                                 printf ("\n%s:\n", path);
134                                 iterate_on_dir (path, lsattr_dir_proc, NULL);
135                                 printf ("\n");
136                         }
137                 }
138         }
139         free(path);
140         return 0;
141 }
142
143 int main (int argc, char ** argv)
144 {
145         int c;
146         int i;
147
148 #ifdef ENABLE_NLS
149         setlocale(LC_MESSAGES, "");
150         bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
151         textdomain(NLS_CAT_NAME);
152 #endif
153         if (argc && *argv)
154                 program_name = *argv;
155         while ((c = getopt (argc, argv, "RVadlv")) != EOF)
156                 switch (c)
157                 {
158                         case 'R':
159                                 recursive = 1;
160                                 break;
161                         case 'V':
162                                 verbose = 1;
163                                 break;
164                         case 'a':
165                                 all = 1;
166                                 break;
167                         case 'd':
168                                 dirs_opt = 1;
169                                 break;
170                         case 'l':
171                                 pf_options = PFOPT_LONG;
172                                 break;
173                         case 'v':
174                                 generation_opt = 1;
175                                 break;
176                         default:
177                                 usage();
178                 }
179
180         if (verbose)
181                 fprintf (stderr, "lsattr %s (%s)\n",
182                          E2FSPROGS_VERSION, E2FSPROGS_DATE);
183         if (optind > argc - 1)
184                 lsattr_args (".");
185         else
186                 for (i = optind; i < argc; i++)
187                         lsattr_args (argv[i]);
188         exit(0);
189 }