aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/other/lsattr.c108
1 files changed, 75 insertions, 33 deletions
diff --git a/toys/other/lsattr.c b/toys/other/lsattr.c
index 2dff4f99..76db649f 100644
--- a/toys/other/lsattr.c
+++ b/toys/other/lsattr.c
@@ -7,14 +7,14 @@
*
* TODO cleanup
-USE_LSATTR(NEWTOY(lsattr, "vldaR", TOYFLAG_BIN))
+USE_LSATTR(NEWTOY(lsattr, "vpldaR", TOYFLAG_BIN))
USE_CHATTR(NEWTOY(chattr, NULL, TOYFLAG_BIN))
config LSATTR
bool "lsattr"
default y
help
- usage: lsattr [-Radlv] [file...]
+ usage: lsattr [-Radlpv] [file...]
List file attributes on a Linux second extended file system.
Flag letters are defined in chattr help.
@@ -23,17 +23,19 @@ config LSATTR
-a List all files in directories, including files that start with '.'
-d List directories like other files, rather than listing their contents
-l List long flag names
+ -p List the file's project number
-v List the file's version/generation number
config CHATTR
bool "chattr"
default y
help
- usage: chattr [-R] [-+=AacDdijsStTu] [-v version] [file...]
+ usage: chattr [-R] [-+=AacDdijsStTu] [-p projid] [-v version] [file...]
Change file attributes on a Linux second extended file system.
-R Recurse
+ -p Set the file's project number
-v Set the file's version/generation number
Operators:
@@ -64,29 +66,47 @@ config CHATTR
#define FS_PROJINHERT_FL 0x20000000 // Linux 4.5
#define FS_CASEFOLD_FL 0x40000000 // Linux 5.4
+#define FS_VERITY_FL 0x00100000 // Linux 5.4
+
+// Linux 4.5
+struct fsxattr_4_5 {
+ unsigned fsx_xflags;
+ unsigned fsx_extsize;
+ unsigned fsx_nextents;
+ unsigned fsx_projid;
+ unsigned fsx_cowextsize;
+ char fsx_pad[8];
+};
+#define FS_IOC_FSGETXATTR_4_5 _IOR('X', 31, struct fsxattr_4_5)
+#define FS_IOC_FSSETXATTR_4_5 _IOW('X', 32, struct fsxattr_4_5)
static struct ext2_attr {
char *name;
unsigned long flag;
char opt;
} e2attrs[] = {
- {"No_Atime", FS_NOATIME_FL, 'A'},
- {"Append_Only", FS_APPEND_FL, 'a'},
- {"No_COW", FS_NOCOW_FL, 'C'},
- {"Compression_Requested", FS_COMPR_FL, 'c'},
+ // Do not sort! These are in the order that lsattr outputs them.
+ {"Secure_Deletion", FS_SECRM_FL, 's'},
+ {"Undelete", FS_UNRM_FL, 'u'},
+ {"Synchronous_Updates", FS_SYNC_FL, 'S'},
{"Synchronous_Directory_Updates", FS_DIRSYNC_FL, 'D'},
- {"No_Dump", FS_NODUMP_FL, 'd'},
- {"Casefold", FS_CASEFOLD_FL, 'F'},
- {"Indexed_directory", FS_INDEX_FL, 'I'},
{"Immutable", FS_IMMUTABLE_FL, 'i'},
+ {"Append_Only", FS_APPEND_FL, 'a'},
+ {"No_Dump", FS_NODUMP_FL, 'd'},
+ {"No_Atime", FS_NOATIME_FL, 'A'},
+ {"Compression_Requested", FS_COMPR_FL, 'c'},
+ {"Encrypted", FS_ENCRYPT_FL, 'E'},
{"Journaled_Data", FS_JOURNAL_DATA_FL, 'j'},
- {"Project_Hierarchy", FS_PROJINHERIT_FL, 'P'},
- {"Synchronous_Updates", FS_SYNC_FL, 'S'},
- {"Secure_Deletion", FS_SECRM_FL, 's'},
- {"Top_of_Directory_Hierarchies", FS_TOPDIR_FL, 'T'},
+ {"Indexed_directory", FS_INDEX_FL, 'I'},
{"No_Tailmerging", FS_NOTAIL_FL, 't'},
- {"Undelete", FS_UNRM_FL, 'u'},
- {NULL, -1, 0},
+ {"Top_of_Directory_Hierarchies", FS_TOPDIR_FL, 'T'},
+ {"Extents", FS_EXTENT_FL, 'e'},
+ {"No_COW", FS_NOCOW_FL, 'C'},
+ {"Casefold", FS_CASEFOLD_FL, 'F'},
+ {"Inline_Data", FS_INLINE_DATA_FL, 'N'},
+ {"Project_Hierarchy", FS_PROJINHERIT_FL, 'P'},
+ {"Verity", FS_VERITY_FL, 'V'},
+ {NULL, 0, 0},
};
// Get file flags on a Linux second extended file system.
@@ -111,9 +131,15 @@ static void print_file_attr(char *path)
}
if (-1 == (fd=open(path, O_RDONLY | O_NONBLOCK))) goto LABEL1;
+ if (FLAG(p)) {
+ struct fsxattr_4_5 fsx;
+
+ if (ioctl(fd, FS_IOC_FSGETXATTR_4_5, &fsx)) goto LABEL2;
+ xprintf("%5u ", fsx.fsx_projid);
+ }
if (FLAG(v)) {
if (ioctl(fd, FS_IOC_GETVERSION, (void*)&version) < 0) goto LABEL2;
- xprintf("%5lu ", version);
+ xprintf("%-10lu ", version);
}
if (ext2_getflag(fd, &sb, &flag) < 0) perror_msg("reading flags '%s'", path);
@@ -152,12 +178,12 @@ LABEL1: perror_msg("reading '%s'", path);
static int retell_dir(struct dirtree *root)
{
char *fpath = NULL;
-
+
if (root->again) {
xputc('\n');
return 0;
}
- if (S_ISDIR(root->st.st_mode) && !root->parent)
+ if (S_ISDIR(root->st.st_mode) && !root->parent)
return (DIRTREE_RECURSE | DIRTREE_COMEAGAIN);
fpath = dirtree_path(root, NULL);
@@ -194,8 +220,8 @@ void lsattr_main(void)
#include "generated/flags.h"
static struct _chattr {
- unsigned long add, rm, set, version;
- unsigned char vflag, recursive;
+ unsigned long add, rm, set, projid, version;
+ unsigned char pflag, vflag, recursive;
} chattr;
// Set file flags on a Linux second extended file system.
@@ -229,16 +255,20 @@ static void parse_cmdline_arg(char ***argv)
if (*ptr == 'R') {
chattr.recursive = 1;
continue;
- } else if (*ptr == 'v') {// get version from next argv.
- char *endptr;
+ } else if (*ptr == 'p' || *ptr == 'v') {
+ unsigned val;
- errno = 0;
arg = *(*argv += 1);
- if (!arg) help_exit("bad -v");
- if (*arg == '-') perror_exit("Invalid Number '%s'", arg);
- chattr.version = strtoul(arg, &endptr, 0);
- if (errno || *endptr) perror_exit("bad version '%s'", arg);
- chattr.vflag = 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);
}
@@ -297,12 +327,24 @@ static int update_attr(struct dirtree *root)
if (ext2_setflag(fd, &(root->st), fval) < 0)
perror_msg("setting flags '%s'", fpath);
}
- // set file version
+
+ // (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 (chattr.pflag) {
+ 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;
+ if (ioctl(fd, FS_IOC_FSSETXATTR_4_5, &fsx))
+ perror_exit("%s: FS_IOC_FSSETXATTR failed", fpath);
+ }
+
free(fpath);
xclose(fd);
-
return (S_ISDIR(root->st.st_mode) && chattr.recursive) ? DIRTREE_RECURSE : 0;
}
@@ -316,8 +358,8 @@ void chattr_main(void)
if (chattr.set && (chattr.add || chattr.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.vflag))
- error_exit("need '-v', '=', '-' or '+'");
+ if (!(chattr.add || chattr.rm || chattr.set || chattr.pflag || chattr.vflag))
+ error_exit("need '-p', '-v', '=', '-', or '+'");
for (; *argv; argv++) dirtree_read(*argv, update_attr);
toys.exitval = 0; //always set success at this point.
}