blob: afc882c823dad4164b5a0c9f33f0f8126af97eec [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
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
Theodore Ts'oa88fa0c1999-01-05 07:02:39 +000017 * 98/12/29 - Display version info only when -V specified (G M Sipe)
Theodore Ts'o3839e651997-04-26 13:21:57 +000018 */
19
Theodore Ts'oa418d3a1997-04-26 14:00:26 +000020#include <sys/types.h>
Theodore Ts'o3839e651997-04-26 13:21:57 +000021#include <dirent.h>
Theodore Ts'oa418d3a1997-04-26 14:00:26 +000022#ifdef HAVE_ERRNO_H
Theodore Ts'o3839e651997-04-26 13:21:57 +000023#include <errno.h>
Theodore Ts'oa418d3a1997-04-26 14:00:26 +000024#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +000025#include <fcntl.h>
Theodore Ts'oa418d3a1997-04-26 14:00:26 +000026#ifdef HAVE_GETOPT_H
Theodore Ts'o3839e651997-04-26 13:21:57 +000027#include <getopt.h>
Theodore Ts'oa418d3a1997-04-26 14:00:26 +000028#else
29extern int optind;
30extern char *optarg;
31#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +000032#include <stdio.h>
33#include <unistd.h>
Theodore Ts'oa418d3a1997-04-26 14:00:26 +000034#include <stdlib.h>
Theodore Ts'o19c78dc1997-04-29 16:17:09 +000035#include <string.h>
Theodore Ts'o3839e651997-04-26 13:21:57 +000036#include <sys/param.h>
37#include <sys/stat.h>
38#include <linux/ext2_fs.h>
39
40#include "et/com_err.h"
41#include "e2p/e2p.h"
42
43#include "../version.h"
44
45const char * program_name = "lsattr";
46
47int all = 0;
48int d_opt = 0;
Theodore Ts'of3db3561997-04-26 13:34:30 +000049int l_opt = 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +000050int recursive = 0;
Theodore Ts'oa88fa0c1999-01-05 07:02:39 +000051int verbose = 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +000052int v_opt = 0;
53
Theodore Ts'o818180c1998-06-27 05:11:14 +000054static void usage(void)
Theodore Ts'o3839e651997-04-26 13:21:57 +000055{
Theodore Ts'oa88fa0c1999-01-05 07:02:39 +000056 fprintf(stderr, "Usage: %s [-RVadlv] [files...]\n", program_name);
Theodore Ts'o818180c1998-06-27 05:11:14 +000057 exit(1);
Theodore Ts'o3839e651997-04-26 13:21:57 +000058}
59
60static void list_attributes (const char * name)
61{
62 unsigned long flags;
63 unsigned long version;
64
65 if (fgetflags (name, &flags) == -1)
66 com_err (program_name, errno, "While reading flags on %s",
67 name);
68 else if (fgetversion (name, &version) == -1)
69 com_err (program_name, errno, "While reading version on %s",
70 name);
71 else
72 {
73 if (v_opt)
74 printf ("%5lu ", version);
Theodore Ts'of3db3561997-04-26 13:34:30 +000075 print_flags (stdout, flags, l_opt);
Theodore Ts'o3839e651997-04-26 13:21:57 +000076 printf (" %s\n", name);
77 }
78}
79
80static int lsattr_dir_proc (const char *, struct dirent *, void *);
81
82static void lsattr_args (const char * name)
83{
84 struct stat st;
85
86 if (lstat (name, &st) == -1)
87 com_err (program_name, errno, "while stating %s", name);
88 else
89 {
90 if (S_ISDIR(st.st_mode) && !d_opt)
91 iterate_on_dir (name, lsattr_dir_proc, (void *) NULL);
92 else
93 list_attributes (name);
94 }
95}
96
97static int lsattr_dir_proc (const char * dir_name, struct dirent * de, void * private)
98{
Theodore Ts'o3839e651997-04-26 13:21:57 +000099 struct stat st;
Theodore Ts'oa418d3a1997-04-26 14:00:26 +0000100 char *path;
101
102 path = malloc(strlen (dir_name) + 1 + strlen (de->d_name) + 1);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000103
104 sprintf (path, "%s/%s", dir_name, de->d_name);
105 if (lstat (path, &st) == -1)
106 perror (path);
Theodore Ts'oa418d3a1997-04-26 14:00:26 +0000107 else {
108 if (de->d_name[0] != '.' || all) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000109 list_attributes (path);
110 if (S_ISDIR(st.st_mode) && recursive &&
Theodore Ts'oa418d3a1997-04-26 14:00:26 +0000111 strcmp(de->d_name, ".") &&
112 strcmp(de->d_name, "..")) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000113 printf ("\n%s:\n", path);
Theodore Ts'oa418d3a1997-04-26 14:00:26 +0000114 iterate_on_dir (path, lsattr_dir_proc,
115 (void *) NULL);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000116 printf ("\n");
117 }
118 }
119 }
Theodore Ts'oa418d3a1997-04-26 14:00:26 +0000120 free(path);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000121 return 0;
122}
123
Theodore Ts'o00e54331997-09-16 02:13:52 +0000124int main (int argc, char ** argv)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000125{
Theodore Ts'o519149f1997-10-25 03:49:49 +0000126 int c;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000127 int i;
128
Theodore Ts'o3839e651997-04-26 13:21:57 +0000129 if (argc && *argv)
130 program_name = *argv;
Theodore Ts'oa88fa0c1999-01-05 07:02:39 +0000131 while ((c = getopt (argc, argv, "RVadlv")) != EOF)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000132 switch (c)
133 {
134 case 'R':
135 recursive = 1;
136 break;
Theodore Ts'oa88fa0c1999-01-05 07:02:39 +0000137 case 'V':
138 verbose = 1;
139 break;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000140 case 'a':
141 all = 1;
142 break;
143 case 'd':
144 d_opt = 1;
145 break;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000146 case 'l':
147 l_opt = 1;
148 break;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000149 case 'v':
150 v_opt = 1;
151 break;
152 default:
Theodore Ts'o818180c1998-06-27 05:11:14 +0000153 usage();
Theodore Ts'o3839e651997-04-26 13:21:57 +0000154 }
155
Theodore Ts'oa88fa0c1999-01-05 07:02:39 +0000156 if (verbose)
157 fprintf (stderr, "lsattr %s, %s for EXT2 FS %s, %s\n",
158 E2FSPROGS_VERSION, E2FSPROGS_DATE,
159 EXT2FS_VERSION, EXT2FS_DATE);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000160 if (optind > argc - 1)
161 lsattr_args (".");
162 else
163 for (i = optind; i < argc; i++)
164 lsattr_args (argv[i]);
Theodore Ts'o00e54331997-09-16 02:13:52 +0000165 exit(0);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000166}