aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/other/lsattr.c78
1 files 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.