]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Add recursive modes to lsattr/chattr. Ensure command line command are applied to...
authorNathan Scott <nathans@sgi.com>
Fri, 17 Sep 2004 06:41:01 +0000 (06:41 +0000)
committerNathan Scott <nathans@sgi.com>
Fri, 17 Sep 2004 06:41:01 +0000 (06:41 +0000)
Merge of xfs-cmds-melb:slinx:19498a by kenmcd.

io/attr.c
io/init.c

index 68f0ea0e2e3325006d804f01bea4c82e75272fb0..0e82b39cd4e7ac7b920d34678de4c89f9271fefa 100644 (file)
--- a/io/attr.c
+++ b/io/attr.c
 #include "init.h"
 #include "io.h"
 
+#define HAVE_FTW_H 1   /* TODO: configure me */
+
+#ifdef HAVE_FTW_H
+#include <ftw.h>
+#else
+static int
+nftw(
+       char    *dir,
+       int     (*fn)(const char *, const struct stat *, int, struct FTW *),
+       int     depth,
+       int     flags)
+{
+       fprintf(stderr, "%s: not implemented, no recursion available\n",
+               __FUNCTION__);
+       return 0;
+}
+#endif
+
 static cmdinfo_t chattr_cmd;
 static cmdinfo_t lsattr_cmd;
+static unsigned int orflags;
+static unsigned int andflags;
+static unsigned int recurse_all;
+static unsigned int recurse_dir;
 
 #define CHATTR_XFLAG_LIST      "riasAdtPn"
 
@@ -46,16 +68,16 @@ static struct xflags {
        char    *shortname;
        char    *longname;
 } xflags[] = {
-       { XFS_XFLAG_REALTIME,   "r", "realtime" },
-       { XFS_XFLAG_PREALLOC,   "p", "prealloc" },
-       { XFS_XFLAG_IMMUTABLE,  "i", "immutable" },
-       { XFS_XFLAG_APPEND,     "a", "append-only" },
-       { XFS_XFLAG_SYNC,       "s", "sync" },
-       { XFS_XFLAG_NOATIME,    "A", "no-atime" },
-       { XFS_XFLAG_NODUMP,     "d", "no-dump" },
-       { XFS_XFLAG_RTINHERIT,  "t", "rt-inherit" },
-       { XFS_XFLAG_PROJINHERIT,"P", "proj-inherit" },
-       { XFS_XFLAG_NOSYMLINKS, "n", "nosymlinks" },
+       { XFS_XFLAG_REALTIME,   "r", "realtime"         },
+       { XFS_XFLAG_PREALLOC,   "p", "prealloc"         },
+       { XFS_XFLAG_IMMUTABLE,  "i", "immutable"        },
+       { XFS_XFLAG_APPEND,     "a", "append-only"      },
+       { XFS_XFLAG_SYNC,       "s", "sync"             },
+       { XFS_XFLAG_NOATIME,    "A", "no-atime"         },
+       { XFS_XFLAG_NODUMP,     "d", "no-dump"          },
+       { XFS_XFLAG_RTINHERIT,  "t", "rt-inherit"       },
+       { XFS_XFLAG_PROJINHERIT,"P", "proj-inherit"     },
+       { XFS_XFLAG_NOSYMLINKS, "n", "nosymlinks"       },
        { 0, NULL, NULL }
 };
 
@@ -79,6 +101,8 @@ lsattr_help(void)
 " n -- symbolic links cannot be created in this directory\n"
 "\n"
 " Options:\n"
+" -R -- recursively descend (useful when current file is a directory)\n"
+" -D -- recursively descend, but only list attributes on directories\n"
 " -a -- show all flags which can be set alongside those which are set\n"
 " -v -- verbose mode; show long names of flags, not single characters\n"
 "\n"));
@@ -95,6 +119,8 @@ chattr_help(void)
 " 'chattr +a' - sets the append-only flag\n"
 " 'chattr -a' - clears the append-only flag\n"
 "\n"
+" -R -- recursively descend (useful when current file is a directory)\n"
+" -D -- recursively descend, only modifying attributes on directories\n"
 " +/-r -- set/clear the realtime flag\n"
 " +/-i -- set/clear the immutable flag\n"
 " +/-a -- set/clear the append-only flag\n"
@@ -149,6 +175,33 @@ printxattr(
                fputs("\n", stdout);
 }
 
+static int
+lsattr_callback(
+       const char              *path,
+       const struct stat       *stat,
+       int                     status,
+       struct FTW              *data)
+{
+       struct fsxattr          fsx;
+       int                     fd;
+
+       if (recurse_dir && !S_ISDIR(stat->st_mode))
+               return 0;
+
+       if ((fd = open(path, O_RDONLY)) == -1)
+               fprintf(stderr, _("%s: cannot open %s: %s\n"),
+                       progname, path, strerror(errno));
+       else if ((xfsctl(path, fd, XFS_IOC_FSGETXATTR, &fsx)) < 0)
+               fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
+                       progname, path, strerror(errno));
+       else
+               printxattr(fsx.fsx_xflags, 0, 1, path, 0, 1);
+
+       if (fd != -1)
+               close(fd);
+       return 0;
+}
+
 static int
 lsattr_f(
        int             argc,
@@ -158,8 +211,17 @@ lsattr_f(
        char            *name = file->name;
        int             c, aflag = 0, vflag = 0;
 
-       while ((c = getopt(argc, argv, "av")) != EOF) {
+       recurse_all = recurse_dir = 0;
+       while ((c = getopt(argc, argv, "DRav")) != EOF) {
                switch (c) {
+               case 'D':
+                       recurse_all = 0;
+                       recurse_dir = 1;
+                       break;
+               case 'R':
+                       recurse_all = 1;
+                       recurse_dir = 0;
+                       break;
                case 'a':
                        aflag = 1;
                        vflag = 0;
@@ -169,13 +231,16 @@ lsattr_f(
                        vflag = 1;
                        break;
                default:
-                       printf(_("invalid lsattr argument -- '%c'\n"), c);
-                       return 0;
+                       return command_usage(&lsattr_cmd);
                }
        }
 
-       if ((xfsctl(name, file->fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
-               perror("XFS_IOC_FSGETXATTR");
+       if (recurse_all || recurse_dir) {
+               nftw(name, lsattr_callback,
+                       100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
+       } else if ((xfsctl(name, file->fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
+               fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
+                       progname, name, strerror(errno));
        } else {
                printxattr(fsx.fsx_xflags, vflag, !aflag, name, vflag, !aflag);
                if (aflag) {
@@ -186,6 +251,38 @@ lsattr_f(
        return 0;
 }
 
+static int
+chattr_callback(
+       const char              *path,
+       const struct stat       *stat,
+       int                     status,
+       struct FTW              *data)
+{
+       struct fsxattr          attr;
+       int                     fd;
+
+       if (recurse_dir && !S_ISDIR(stat->st_mode))
+               return 0;
+
+       if ((fd = open(path, O_RDONLY)) == -1) {
+               fprintf(stderr, _("%s: cannot open %s: %s\n"),
+                       progname, path, strerror(errno));
+       } else if (xfsctl(path, fd, XFS_IOC_FSGETXATTR, &attr) < 0) {
+               fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
+                       progname, path, strerror(errno));
+       } else {
+               attr.fsx_xflags |= orflags;
+               attr.fsx_xflags &= ~andflags;
+               if (xfsctl(path, fd, XFS_IOC_FSSETXATTR, &attr) < 0)
+                       fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
+                               progname, path, strerror(errno));
+       }
+
+       if (fd != -1)
+               close(fd);
+       return 0;
+}
+
 static int
 chattr_f(
        int             argc,
@@ -196,16 +293,18 @@ chattr_f(
        unsigned int    i = 0;
        char            *c, *name = file->name;
 
-       if (xfsctl(name, file->fd, XFS_IOC_FSGETXATTR, &attr) < 0) {
-               perror("XFS_IOC_FSGETXATTR");
-               return 0;
-       }
+       orflags = andflags = 0;
+       recurse_all = recurse_dir = 0;
        while (++i < argc) {
-               if (argv[i][0] == '+') {
+               if (argv[i][0] == '-' && argv[i][1] == 'R') {
+                       recurse_all = 1;
+               } else if (argv[i][0] == '-' && argv[i][1] == 'D') {
+                       recurse_dir = 1;
+               } else if (argv[i][0] == '+') {
                        for (c = &argv[i][1]; *c; c++) {
                                for (p = xflags; p->flag; p++) {
                                        if (strncmp(p->shortname, c, 1) == 0) {
-                                               attr.fsx_xflags |= p->flag;
+                                               orflags |= p->flag;
                                                break;
                                        }
                                }
@@ -219,7 +318,7 @@ chattr_f(
                        for (c = &argv[i][1]; *c; c++) {
                                for (p = xflags; p->flag; p++) {
                                        if (strncmp(p->shortname, c, 1) == 0) {
-                                               attr.fsx_xflags &= ~p->flag;
+                                               andflags |= p->flag;
                                                break;
                                        }
                                }
@@ -235,8 +334,20 @@ chattr_f(
                        return 0;
                }
        }
-       if (xfsctl(name, file->fd, XFS_IOC_FSSETXATTR, &attr) < 0)
-               perror("XFS_IOC_FSSETXATTR");
+
+       if (recurse_all || recurse_dir) {
+               nftw(name, chattr_callback,
+                       100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
+       } else if (xfsctl(name, file->fd, XFS_IOC_FSGETXATTR, &attr) < 0) {
+               fprintf(stderr, _("%s: cannot get flags on %s: %s\n"),
+                       progname, name, strerror(errno));
+       } else {
+               attr.fsx_xflags |= orflags;
+               attr.fsx_xflags &= ~andflags;
+               if (xfsctl(name, file->fd, XFS_IOC_FSSETXATTR, &attr) < 0)
+                       fprintf(stderr, _("%s: cannot set flags on %s: %s\n"),
+                               progname, name, strerror(errno));
+       }
        return 0;
 }
 
@@ -245,7 +356,7 @@ attr_init(void)
 {
        chattr_cmd.name = _("chattr");
        chattr_cmd.cfunc = chattr_f;
-       chattr_cmd.args = _("[+/-"CHATTR_XFLAG_LIST"]");
+       chattr_cmd.args = _("[-R|-D] [+/-"CHATTR_XFLAG_LIST"]");
        chattr_cmd.argmin = 1;
        chattr_cmd.argmax = -1;
        chattr_cmd.flags = CMD_NOMAP_OK;
@@ -255,7 +366,7 @@ attr_init(void)
 
        lsattr_cmd.name = _("lsattr");
        lsattr_cmd.cfunc = lsattr_f;
-       lsattr_cmd.args = _("[-a|-v]");
+       lsattr_cmd.args = _("[-R|-D|-a|-v]");
        lsattr_cmd.argmin = 0;
        lsattr_cmd.argmax = 1;
        lsattr_cmd.flags = CMD_NOMAP_OK;
index d3089a89d152344177463e395965a568b1e241c6..dec5f53048602a12c8a22da4e8f118860da81a8e 100644 (file)
--- a/io/init.c
+++ b/io/init.c
@@ -165,17 +165,20 @@ main(
        int     argc,
        char    **argv)
 {
-       int     c, i, done = 0;
+       int     c, i, j, done = 0;
        char    *input;
        char    **v;
 
        init(argc, argv);
 
        for (i = 0; !done && i < ncmdline; i++) {
-               v = breakline(cmdline[i], &c);
-               if (c)
-                       done = command(c, v);
-               free(v);
+               for (j = 0; !done && j < filecount; j++) {
+                       file = &filetable[j];
+                       v = breakline(cmdline[i], &c);
+                       if (c)
+                               done = command(c, v);
+                       free(v);
+               }
        }
        if (cmdline) {
                free(cmdline);