13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * lsattr.c		- List file attributes on an ext2 file system
33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *
43839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Copyright (C) 1993, 1994  Remy Card <card@masi.ibp.fr>
53839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *                           Laboratoire MASI, Institut Blaise Pascal
63839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *                           Universite Pierre et Marie Curie (Paris VI)
73839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *
83839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This file can be redistributed under the terms of the GNU General
93839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Public License
103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * History:
143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 93/10/30	- Creation
153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 93/11/13	- Replace stat() calls by lstat() to avoid loops
163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 94/02/27	- Integrated in Ted's distribution
17a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o * 98/12/29	- Display version info only when -V specified (G M Sipe)
183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
20fff18b4e76d3757a78e5583010bbce3772461f4dTheodore Ts'o#define _LARGEFILE64_SOURCE
21fff18b4e76d3757a78e5583010bbce3772461f4dTheodore Ts'o
22a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include <sys/types.h>
233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <dirent.h>
24a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef HAVE_ERRNO_H
253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <errno.h>
26a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif
273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h>
28a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef HAVE_GETOPT_H
293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <getopt.h>
30a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#else
31a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'oextern int optind;
32a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'oextern char *optarg;
33a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif
343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h>
353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h>
36a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include <stdlib.h>
3719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <string.h>
383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/param.h>
393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h>
403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
4154c637d4d29af3e6365779f8b12976abe95a4753Theodore Ts'o#include "ext2fs/ext2_fs.h"
423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h"
433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2p/e2p.h"
443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "../version.h"
46d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#include "nls-enable.h"
473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
48544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o#ifdef __GNUC__
49544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o#define EXT2FS_ATTR(x) __attribute__(x)
50544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o#else
51544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o#define EXT2FS_ATTR(x)
52544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o#endif
53544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o
54e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic const char * program_name = "lsattr";
553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
56f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'ostatic int all;
57f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'ostatic int dirs_opt;
58f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'ostatic unsigned pf_options;
59f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'ostatic int recursive;
60f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'ostatic int verbose;
61f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'ostatic int generation_opt;
623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
63b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#ifdef _LFS64_LARGEFILE
64b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define LSTAT		lstat64
65b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define STRUCT_STAT	struct stat64
66b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#else
67b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define LSTAT		lstat
68b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define STRUCT_STAT	struct stat
69b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#endif
70b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o
71818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'ostatic void usage(void)
723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
73d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	fprintf(stderr, _("Usage: %s [-RVadlv] [files...]\n"), program_name);
74818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o	exit(1);
753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
771b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeenstatic int list_attributes (const char * name)
783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	unsigned long flags;
80e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	unsigned long generation;
813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
82f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o	if (fgetflags (name, &flags) == -1) {
83d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o		com_err (program_name, errno, _("While reading flags on %s"),
843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			 name);
851b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen		return -1;
86f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o	}
87f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o	if (generation_opt) {
88f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o		if (fgetversion (name, &generation) == -1) {
89f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o			com_err (program_name, errno,
90f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o				 _("While reading version on %s"),
91f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o				 name);
921b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen			return -1;
93e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		}
94f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o		printf ("%5lu ", generation);
95f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o	}
96f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o	if (pf_options & PFOPT_LONG) {
97f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o		printf("%-28s ", name);
98f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o		print_flags(stdout, flags, pf_options);
99f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o		fputc('\n', stdout);
100f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o	} else {
101f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o		print_flags(stdout, flags, pf_options);
102f10748d88cb9b79e1f1a41a12a3e4f411f2494c7Theodore Ts'o		printf(" %s\n", name);
1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1041b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen	return 0;
1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int lsattr_dir_proc (const char *, struct dirent *, void *);
1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1091b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeenstatic int lsattr_args (const char * name)
1103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
111b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o	STRUCT_STAT	st;
1121b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen	int retval = 0;
1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1141b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen	if (LSTAT (name, &st) == -1) {
115e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		com_err (program_name, errno, _("while trying to stat %s"),
116e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o			 name);
1171b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen		retval = -1;
1181b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen	} else {
119e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		if (S_ISDIR(st.st_mode) && !dirs_opt)
1201b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen			retval = iterate_on_dir (name, lsattr_dir_proc, NULL);
1213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		else
1221b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen			retval = list_attributes (name);
1233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1241b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen	return retval;
1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
127efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic int lsattr_dir_proc (const char * dir_name, struct dirent * de,
128544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			    void * private EXT2FS_ATTR((unused)))
1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
130b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o	STRUCT_STAT	st;
131a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o	char *path;
132137ce8ca04265f1d46e622ed49ad6dbe922f6d63Theodore Ts'o	int dir_len = strlen(dir_name);
133a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o
134137ce8ca04265f1d46e622ed49ad6dbe922f6d63Theodore Ts'o	path = malloc(dir_len + strlen (de->d_name) + 2);
1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
136137ce8ca04265f1d46e622ed49ad6dbe922f6d63Theodore Ts'o	if (dir_len && dir_name[dir_len-1] == '/')
137137ce8ca04265f1d46e622ed49ad6dbe922f6d63Theodore Ts'o		sprintf (path, "%s%s", dir_name, de->d_name);
138137ce8ca04265f1d46e622ed49ad6dbe922f6d63Theodore Ts'o	else
139137ce8ca04265f1d46e622ed49ad6dbe922f6d63Theodore Ts'o		sprintf (path, "%s/%s", dir_name, de->d_name);
140b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o	if (LSTAT (path, &st) == -1)
1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		perror (path);
142a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o	else {
143a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		if (de->d_name[0] != '.' || all) {
1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			list_attributes (path);
1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (S_ISDIR(st.st_mode) && recursive &&
146a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o			    strcmp(de->d_name, ".") &&
147a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o			    strcmp(de->d_name, "..")) {
1483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				printf ("\n%s:\n", path);
149e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o				iterate_on_dir (path, lsattr_dir_proc, NULL);
1503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				printf ("\n");
1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
154a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o	free(path);
1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
1563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
1573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
15800e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv)
1593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
160519149fb458b0fa69c10fecd83fae42e838cf01dTheodore Ts'o	int c;
1613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int i;
1621b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen	int err, retval = 0;
1633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
164d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#ifdef ENABLE_NLS
165d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	setlocale(LC_MESSAGES, "");
16614308a5398984842e808faa3ff2dd6a1c52d90bdTheodore Ts'o	setlocale(LC_CTYPE, "");
167d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
168d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	textdomain(NLS_CAT_NAME);
169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	set_com_err_gettext(gettext);
170d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#endif
1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (argc && *argv)
1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		program_name = *argv;
173a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o	while ((c = getopt (argc, argv, "RVadlv")) != EOF)
1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		switch (c)
1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		{
1763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'R':
1773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				recursive = 1;
1783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
179a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o			case 'V':
180a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o				verbose = 1;
181a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o				break;
1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'a':
1833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				all = 1;
1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'd':
186e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o				dirs_opt = 1;
1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
188f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			case 'l':
189e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o				pf_options = PFOPT_LONG;
190f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				break;
1913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'v':
192e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o				generation_opt = 1;
1933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			default:
195818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o				usage();
1963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
1973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
198a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o	if (verbose)
1990f8973fb092a40fd0a11b7ec95c09128c9fb8f0cTheodore Ts'o		fprintf (stderr, "lsattr %s (%s)\n",
2000f8973fb092a40fd0a11b7ec95c09128c9fb8f0cTheodore Ts'o			 E2FSPROGS_VERSION, E2FSPROGS_DATE);
2011b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen	if (optind > argc - 1) {
2021b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen		if (lsattr_args (".") == -1)
2031b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen			retval = 1;
2041b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen	} else {
2051b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen		for (i = optind; i < argc; i++) {
2061b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen			err = lsattr_args (argv[i]);
2071b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen			if (err)
2081b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen				retval = 1;
2091b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen		}
2101b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen	}
2111b600bfa48cf55571e342208d6baa1c832f34bb1Eric Sandeen	exit(retval);
2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
213