Rewrite -v and -p to not use ad hoc argument parsing.
---
 toys/other/lsattr.c | 78 ++++++++++++++++++---------------------------
 1 file changed, 31 insertions(+), 47 deletions(-)
From 84660b4036f3b5a025e674872c17795098633b23 Mon Sep 17 00:00:00 2001
From: Elliott Hughes <[email protected]>
Date: Mon, 3 Feb 2020 19:32:23 -0800
Subject: [PATCH] chattr: reuse toybox argument parsing.

Rewrite -v and -p to not use ad hoc argument parsing.
---
 toys/other/lsattr.c | 78 ++++++++++++++++++---------------------------
 1 file changed, 31 insertions(+), 47 deletions(-)

diff --git a/toys/other/lsattr.c b/toys/other/lsattr.c
index 24591d53..3f4bf656 100644
--- a/toys/other/lsattr.c
+++ b/toys/other/lsattr.c
@@ -7,8 +7,8 @@
  *
  * TODO cleanup
 
-USE_LSATTR(NEWTOY(lsattr, "vpldaR", TOYFLAG_BIN))
-USE_CHATTR(NEWTOY(chattr, NULL, TOYFLAG_BIN))
+USE_LSATTR(NEWTOY(lsattr, "ldapvR", TOYFLAG_BIN))
+USE_CHATTR(NEWTOY(chattr, "?p#v#R", TOYFLAG_BIN))
 
 config LSATTR
   bool "lsattr"
@@ -62,6 +62,13 @@ config CHATTR
 #include "toys.h"
 #include <linux/fs.h>
 
+GLOBALS(
+  long v;
+  long p;
+
+  long add, rm, set;
+)
+
 #define FS_PROJINHERT_FL 0x20000000 // Linux 4.5
 #define FS_CASEFOLD_FL   0x40000000 // Linux 5.4
 #define FS_VERITY_FL     0x00100000 // Linux 5.4
@@ -217,11 +224,6 @@ void lsattr_main(void)
 #define FOR_chattr
 #include "generated/flags.h"
 
-static struct _chattr {
-  unsigned long add, rm, set, projid, version;
-  unsigned char pflag, vflag, recursive;
-} chattr;
-
 // Set file flags on a Linux second extended file system.
 static inline int ext2_setflag(int fd, struct stat *sb, unsigned long flag)
 {
@@ -244,40 +246,21 @@ static unsigned long get_flag_val(char ch)
 // Parse command line argument and fill the chattr structure.
 static void parse_cmdline_arg(char ***argv)
 {
-  char *arg = **argv, *ptr = NULL;
+  char *arg = **argv, *ptr;
 
   while (arg) {
     switch (arg[0]) {
       case '-':
-        for (ptr = ++arg; *ptr; ptr++) {
-          if (*ptr == 'R') {
-            chattr.recursive = 1;
-            continue;
-          } else if (*ptr == 'p' || *ptr == 'v') {
-            unsigned val;
-
-            arg = *(*argv += 1);
-            if (!arg) help_exit("missing arg to -%c", *ptr);
-
-            val = atolx_range(arg, 0, UINT_MAX);
-            if (*ptr == 'v') {
-              chattr.version = val;
-              chattr.vflag = 1;
-            } else {
-              chattr.projid = val;
-              chattr.pflag = 1;
-            }
-            continue;
-          } else chattr.rm |= get_flag_val(*ptr);
-        }
+        for (ptr = ++arg; *ptr; ptr++)
+          TT.rm |= get_flag_val(*ptr);
         break;
       case '+':
         for (ptr = ++arg; *ptr; ptr++)
-          chattr.add |= get_flag_val(*ptr);
+          TT.add |= get_flag_val(*ptr);
         break;
       case '=':
         for (ptr = ++arg; *ptr; ptr++)
-          chattr.set |= get_flag_val(*ptr);
+          TT.set |= get_flag_val(*ptr);
         break;
       default: return;
     }
@@ -290,7 +273,7 @@ static int update_attr(struct dirtree *root)
 {
   unsigned long fval = 0;
   char *fpath = NULL;
-  int fd;
+  int v = TT.v, fd;
 
   if (!dirtree_notdotdot(root)) return 0;
 
@@ -298,7 +281,7 @@ static int update_attr(struct dirtree *root)
    * if file is a link and recursive is set or file is not regular+link+dir
    * (like fifo or dev file) then escape the file.
    */
-  if ((S_ISLNK(root->st.st_mode) && chattr.recursive)
+  if ((S_ISLNK(root->st.st_mode) && FLAG(R))
     || (!S_ISREG(root->st.st_mode) && !S_ISLNK(root->st.st_mode)
       && !S_ISDIR(root->st.st_mode)))
     return 0;
@@ -315,12 +298,12 @@ static int update_attr(struct dirtree *root)
     xclose(fd);
     return DIRTREE_ABORT;
   }
-  if (chattr.set) { // for '=' operator.
-    if (ext2_setflag(fd, &(root->st), chattr.set) < 0)
+  if (TT.set) { // for '=' operator.
+    if (ext2_setflag(fd, &(root->st), TT.set) < 0)
       perror_msg("setting flags '%s'", fpath);
   } else { // for '-' / '+' operator.
-    fval &= ~(chattr.rm);
-    fval |= chattr.add;
+    fval &= ~(TT.rm);
+    fval |= TT.add;
     if (!S_ISDIR(root->st.st_mode)) fval &= ~FS_DIRSYNC_FL;
     if (ext2_setflag(fd, &(root->st), fval) < 0)
       perror_msg("setting flags '%s'", fpath);
@@ -328,35 +311,36 @@ static int update_attr(struct dirtree *root)
 
   // (FS_IOC_SETVERSION works all the way back to 2.6, but FS_IOC_FSSETXATTR
   // isn't available until 4.5.)
-  if (chattr.vflag && (ioctl(fd, FS_IOC_SETVERSION, &chattr.version)<0))
-    perror_msg("while setting version on '%s'", fpath);
+  if (FLAG(v) && (ioctl(fd, FS_IOC_SETVERSION, &v)<0))
+    perror_msg("%s: setting version to %d failed", fpath, v);
 
-  if (chattr.pflag) {
+  if (FLAG(p)) {
     struct fsxattr_4_5 fsx;
 
     if (ioctl(fd, FS_IOC_FSGETXATTR_4_5, &fsx))
       perror_exit("%s: FS_IOC_FSGETXATTR failed", fpath);
-    fsx.fsx_projid = chattr.projid;
+    fsx.fsx_projid = TT.p;
     if (ioctl(fd, FS_IOC_FSSETXATTR_4_5, &fsx))
-      perror_exit("%s: FS_IOC_FSSETXATTR failed", fpath);
+      perror_exit("%s: setting projid to %u failed", fpath, fsx.fsx_projid);
   }
 
   free(fpath);
   xclose(fd);
-  return (S_ISDIR(root->st.st_mode) && chattr.recursive) ? DIRTREE_RECURSE : 0;
+  return (FLAG(R) && S_ISDIR(root->st.st_mode)) ? DIRTREE_RECURSE : 0;
 }
 
 void chattr_main(void)
 {
   char **argv = toys.optargs;
 
-  memset(&chattr, 0, sizeof(struct _chattr));
   parse_cmdline_arg(&argv);
+  if (TT.p < 0 || TT.p > UINT_MAX) error_exit("bad projid %lu", TT.p);
+  if (TT.v < 0 || TT.v > UINT_MAX) error_exit("bad version %ld", TT.v);
   if (!*argv) help_exit("no file");
-  if (chattr.set && (chattr.add || chattr.rm))
+  if (TT.set && (TT.add || TT.rm))
     error_exit("no '=' with '-' or '+'");
-  if (chattr.rm & chattr.add) error_exit("set/unset same flag");
-  if (!(chattr.add || chattr.rm || chattr.set || chattr.pflag || chattr.vflag))
+  if (TT.rm & TT.add) error_exit("set/unset same flag");
+  if (!(TT.add || TT.rm || TT.set || FLAG(p) || FLAG(v)))
     error_exit("need '-p', '-v', '=', '-', or '+'");
   for (; *argv; argv++) dirtree_read(*argv, update_attr);
   toys.exitval = 0; //always set success at this point.
-- 
2.25.0.341.g760bfbb309-goog

_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to