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