From e993db91cdfe2dc1ce599d4047f7f9d7e4daaf75 Mon Sep 17 00:00:00 2001 From: Christian Ebner Date: Thu, 6 Jun 2019 13:37:07 +0200 Subject: [PATCH] pxar: introduce fs_feature_flags obtained from filesystem magic in Encoder Not all filesystems support features such as xattrs,acl,... and trying to get them is rather expensive. By getting the supported features based on the filesystem magic and masking the user set feature flags, unsupported features are excluded rather inexpensively while encoding the archive. Signed-off-by: Christian Ebner --- src/pxar/encoder.rs | 44 ++---- src/pxar/format_definition.rs | 264 +++++++++++++++++++++++++++++----- 2 files changed, 243 insertions(+), 65 deletions(-) diff --git a/src/pxar/encoder.rs b/src/pxar/encoder.rs index c77acb6e..16548e87 100644 --- a/src/pxar/encoder.rs +++ b/src/pxar/encoder.rs @@ -50,7 +50,10 @@ pub struct Encoder<'a, W: Write> { all_file_systems: bool, root_st_dev: u64, verbose: bool, + // Flags set by the user feature_flags: u64, + // Flags signaling features supported by the filesystem + fs_feature_flags: u64, hardlinks: HashMap, } @@ -94,6 +97,8 @@ impl <'a, W: Write> Encoder<'a, W> { bail!("backup virtual file systems is disabled!"); } + let fs_feature_flags = feature_flags_from_magic(magic); + let mut me = Self { base_path: path, relative_path: PathBuf::new(), @@ -105,6 +110,7 @@ impl <'a, W: Write> Encoder<'a, W> { root_st_dev: stat.st_dev, verbose, feature_flags, + fs_feature_flags, hardlinks: HashMap::new(), }; @@ -223,12 +229,12 @@ impl <'a, W: Write> Encoder<'a, W> { /// True if all of the given feature flags are set in the Encoder, false otherwise fn has_features(&self, feature_flags: u64) -> bool { - (self.feature_flags & feature_flags) == feature_flags + (self.feature_flags & self.fs_feature_flags & feature_flags) == feature_flags } /// True if at least one of the given feature flags is set in the Encoder, false otherwise fn has_some_features(&self, feature_flags: u64) -> bool { - (self.feature_flags & feature_flags) != 0 + (self.feature_flags & self.fs_feature_flags & feature_flags) != 0 } fn read_xattrs(&self, fd: RawFd, stat: &FileStat) -> Result<(Vec, Option), Error> { @@ -568,6 +574,11 @@ impl <'a, W: Write> Encoder<'a, W> { self.read_chattr(rawfd, &mut dir_entry)?; self.read_fat_attr(rawfd, magic, &mut dir_entry)?; + + // for each node in the directory tree, the filesystem features are + // checked based on the fs magic number. + self.fs_feature_flags = feature_flags_from_magic(magic); + let (xattrs, fcaps) = self.read_xattrs(rawfd, &dir_stat)?; let acl_access = self.read_acl(rawfd, &dir_stat, acl::ACL_TYPE_ACCESS)?; let acl_default = self.read_acl(rawfd, &dir_stat, acl::ACL_TYPE_DEFAULT)?; @@ -933,35 +944,6 @@ fn detect_fs_type(fd: RawFd) -> Result { Ok(fs_stat.f_type) } - -// from /usr/include/linux/magic.h -// and from casync util.h -pub const BINFMTFS_MAGIC: i64 = 0x42494e4d; -pub const CGROUP2_SUPER_MAGIC: i64 = 0x63677270; -pub const CGROUP_SUPER_MAGIC: i64 = 0x0027e0eb; -pub const CONFIGFS_MAGIC: i64 = 0x62656570; -pub const DEBUGFS_MAGIC: i64 = 0x64626720; -pub const DEVPTS_SUPER_MAGIC: i64 = 0x00001cd1; -pub const EFIVARFS_MAGIC: i64 = 0xde5e81e4; -pub const FUSE_CTL_SUPER_MAGIC: i64 = 0x65735543; -pub const HUGETLBFS_MAGIC: i64 = 0x958458f6; -pub const MQUEUE_MAGIC: i64 = 0x19800202; -pub const NFSD_MAGIC: i64 = 0x6e667364; -pub const PROC_SUPER_MAGIC: i64 = 0x00009fa0; -pub const PSTOREFS_MAGIC: i64 = 0x6165676C; -pub const RPCAUTH_GSSMAGIC: i64 = 0x67596969; -pub const SECURITYFS_MAGIC: i64 = 0x73636673; -pub const SELINUX_MAGIC: i64 = 0xf97cff8c; -pub const SMACK_MAGIC: i64 = 0x43415d53; -pub const RAMFS_MAGIC: i64 = 0x858458f6; -pub const TMPFS_MAGIC: i64 = 0x01021994; -pub const SYSFS_MAGIC: i64 = 0x62656572; -pub const MSDOS_SUPER_MAGIC: i64 = 0x00004d44; -pub const FUSE_SUPER_MAGIC: i64 = 0x65735546; -pub const EXT4_SUPER_MAGIC: i64 = 0x0000EF53; -pub const XFS_SUPER_MAGIC: i64 = 0x58465342; - - #[inline(always)] pub fn is_temporary_file_system(magic: i64) -> bool { magic == RAMFS_MAGIC || magic == TMPFS_MAGIC diff --git a/src/pxar/format_definition.rs b/src/pxar/format_definition.rs index 9896244d..f71f302e 100644 --- a/src/pxar/format_definition.rs +++ b/src/pxar/format_definition.rs @@ -115,40 +115,6 @@ pub const CA_FORMAT_EXCLUDE_SUBMOUNTS: u64 = 0x4000000000000000; /// Exclude entries with chattr flag NODUMP pub const CA_FORMAT_EXCLUDE_NODUMP: u64 = 0x8000000000000000; -/// Default feature flags for encoder/decoder -pub const CA_FORMAT_DEFAULT: u64 = -CA_FORMAT_WITH_32BIT_UIDS | -CA_FORMAT_WITH_USER_NAMES | -CA_FORMAT_WITH_NSEC_TIME| -CA_FORMAT_WITH_SYMLINKS| -CA_FORMAT_WITH_DEVICE_NODES| -CA_FORMAT_WITH_FIFOS| -CA_FORMAT_WITH_SOCKETS| -CA_FORMAT_WITH_FLAG_HIDDEN| -CA_FORMAT_WITH_FLAG_SYSTEM| -CA_FORMAT_WITH_FLAG_ARCHIVE| -CA_FORMAT_WITH_FLAG_APPEND| -CA_FORMAT_WITH_FLAG_NOATIME| -CA_FORMAT_WITH_FLAG_COMPR| -CA_FORMAT_WITH_FLAG_NOCOW| -//CA_FORMAT_WITH_FLAG_NODUMP| -CA_FORMAT_WITH_FLAG_DIRSYNC| -CA_FORMAT_WITH_FLAG_IMMUTABLE| -CA_FORMAT_WITH_FLAG_SYNC| -CA_FORMAT_WITH_FLAG_NOCOMP| -CA_FORMAT_WITH_FLAG_PROJINHERIT| -CA_FORMAT_WITH_SUBVOLUME| -CA_FORMAT_WITH_SUBVOLUME_RO| -CA_FORMAT_WITH_XATTRS| -CA_FORMAT_WITH_ACL| -CA_FORMAT_WITH_SELINUX| -CA_FORMAT_WITH_FCAPS| -CA_FORMAT_WITH_QUOTA_PROJID | - -CA_FORMAT_EXCLUDE_NODUMP| -CA_FORMAT_EXCLUDE_FILE| -CA_FORMAT_SHA512_256; - #[derive(Debug)] #[derive(Endian)] #[repr(C)] @@ -415,3 +381,233 @@ pub fn ca_feature_flags_from_fat_attr(attr: u32) -> u64 { flags } + +// from /usr/include/linux/magic.h +// and from casync util.h +pub const BINFMTFS_MAGIC: i64 = 0x42494e4d; +pub const CGROUP2_SUPER_MAGIC: i64 = 0x63677270; +pub const CGROUP_SUPER_MAGIC: i64 = 0x0027e0eb; +pub const CONFIGFS_MAGIC: i64 = 0x62656570; +pub const DEBUGFS_MAGIC: i64 = 0x64626720; +pub const DEVPTS_SUPER_MAGIC: i64 = 0x00001cd1; +pub const EFIVARFS_MAGIC: i64 = 0xde5e81e4; +pub const FUSE_CTL_SUPER_MAGIC: i64 = 0x65735543; +pub const HUGETLBFS_MAGIC: i64 = 0x958458f6; +pub const MQUEUE_MAGIC: i64 = 0x19800202; +pub const NFSD_MAGIC: i64 = 0x6e667364; +pub const PROC_SUPER_MAGIC: i64 = 0x00009fa0; +pub const PSTOREFS_MAGIC: i64 = 0x6165676C; +pub const RPCAUTH_GSSMAGIC: i64 = 0x67596969; +pub const SECURITYFS_MAGIC: i64 = 0x73636673; +pub const SELINUX_MAGIC: i64 = 0xf97cff8c; +pub const SMACK_MAGIC: i64 = 0x43415d53; +pub const RAMFS_MAGIC: i64 = 0x858458f6; +pub const TMPFS_MAGIC: i64 = 0x01021994; +pub const SYSFS_MAGIC: i64 = 0x62656572; +pub const MSDOS_SUPER_MAGIC: i64 = 0x00004d44; +pub const BTRFS_SUPER_MAGIC: i64 = 0x9123683E; +pub const FUSE_SUPER_MAGIC: i64 = 0x65735546; +pub const EXT4_SUPER_MAGIC: i64 = 0x0000EF53; +pub const XFS_SUPER_MAGIC: i64 = 0x58465342; + +/// Definitions of typical feature flags for the *pxar* encoder/decoder. +/// By this expensive syscalls for unsupported features are avoided. + +/// All chattr file attributes +pub const CA_FORMAT_WITH_CHATTR: u64 = + CA_FORMAT_WITH_FLAG_APPEND| + CA_FORMAT_WITH_FLAG_NOATIME| + CA_FORMAT_WITH_FLAG_COMPR| + CA_FORMAT_WITH_FLAG_NOCOW| + CA_FORMAT_WITH_FLAG_NODUMP| + CA_FORMAT_WITH_FLAG_DIRSYNC| + CA_FORMAT_WITH_FLAG_IMMUTABLE| + CA_FORMAT_WITH_FLAG_SYNC| + CA_FORMAT_WITH_FLAG_NOCOMP| + CA_FORMAT_WITH_FLAG_PROJINHERIT; + +/// All FAT file attributes +pub const CA_FORMAT_WITH_FAT_ATTRS: u64 = + CA_FORMAT_WITH_FLAG_HIDDEN| + CA_FORMAT_WITH_FLAG_SYSTEM| + CA_FORMAT_WITH_FLAG_ARCHIVE; + +/// All bits that may also be exposed via fuse +pub const CA_FORMAT_WITH_FUSE: u64 = + CA_FORMAT_WITH_16BIT_UIDS| + CA_FORMAT_WITH_32BIT_UIDS| + CA_FORMAT_WITH_SEC_TIME| + CA_FORMAT_WITH_USEC_TIME| + CA_FORMAT_WITH_NSEC_TIME| + CA_FORMAT_WITH_2SEC_TIME| + CA_FORMAT_WITH_READ_ONLY| + CA_FORMAT_WITH_PERMISSIONS| + CA_FORMAT_WITH_SYMLINKS| + CA_FORMAT_WITH_DEVICE_NODES| + CA_FORMAT_WITH_FIFOS| + CA_FORMAT_WITH_SOCKETS| + CA_FORMAT_WITH_FAT_ATTRS| + CA_FORMAT_WITH_CHATTR| + CA_FORMAT_WITH_XATTRS; + +/// Default feature flags for encoder/decoder +pub const CA_FORMAT_DEFAULT: u64 = + CA_FORMAT_WITH_32BIT_UIDS| + CA_FORMAT_WITH_USER_NAMES| + CA_FORMAT_WITH_NSEC_TIME| + CA_FORMAT_WITH_SYMLINKS| + CA_FORMAT_WITH_DEVICE_NODES| + CA_FORMAT_WITH_FIFOS| + CA_FORMAT_WITH_SOCKETS| + CA_FORMAT_WITH_FLAG_HIDDEN| + CA_FORMAT_WITH_FLAG_SYSTEM| + CA_FORMAT_WITH_FLAG_ARCHIVE| + CA_FORMAT_WITH_FLAG_APPEND| + CA_FORMAT_WITH_FLAG_NOATIME| + CA_FORMAT_WITH_FLAG_COMPR| + CA_FORMAT_WITH_FLAG_NOCOW| + //CA_FORMAT_WITH_FLAG_NODUMP| + CA_FORMAT_WITH_FLAG_DIRSYNC| + CA_FORMAT_WITH_FLAG_IMMUTABLE| + CA_FORMAT_WITH_FLAG_SYNC| + CA_FORMAT_WITH_FLAG_NOCOMP| + CA_FORMAT_WITH_FLAG_PROJINHERIT| + CA_FORMAT_WITH_SUBVOLUME| + CA_FORMAT_WITH_SUBVOLUME_RO| + CA_FORMAT_WITH_XATTRS| + CA_FORMAT_WITH_ACL| + CA_FORMAT_WITH_SELINUX| + CA_FORMAT_WITH_FCAPS| + CA_FORMAT_WITH_QUOTA_PROJID| + CA_FORMAT_EXCLUDE_NODUMP| + CA_FORMAT_EXCLUDE_FILE| + CA_FORMAT_SHA512_256; + +/// Return the supported *pxar* feature flags based on the magic number of the filesystem. +pub fn feature_flags_from_magic(magic: i64) -> u64 { + match magic { + MSDOS_SUPER_MAGIC => { + CA_FORMAT_WITH_2SEC_TIME| + CA_FORMAT_WITH_READ_ONLY| + CA_FORMAT_WITH_FAT_ATTRS + }, + EXT4_SUPER_MAGIC => { + CA_FORMAT_WITH_16BIT_UIDS| + CA_FORMAT_WITH_32BIT_UIDS| + CA_FORMAT_WITH_USER_NAMES| + CA_FORMAT_WITH_SEC_TIME| + CA_FORMAT_WITH_USEC_TIME| + CA_FORMAT_WITH_NSEC_TIME| + CA_FORMAT_WITH_2SEC_TIME| + CA_FORMAT_WITH_READ_ONLY| + CA_FORMAT_WITH_PERMISSIONS| + CA_FORMAT_WITH_SYMLINKS| + CA_FORMAT_WITH_DEVICE_NODES| + CA_FORMAT_WITH_FIFOS| + CA_FORMAT_WITH_SOCKETS| + CA_FORMAT_WITH_FLAG_APPEND| + CA_FORMAT_WITH_FLAG_NOATIME| + CA_FORMAT_WITH_FLAG_NODUMP| + CA_FORMAT_WITH_FLAG_DIRSYNC| + CA_FORMAT_WITH_FLAG_IMMUTABLE| + CA_FORMAT_WITH_FLAG_SYNC| + CA_FORMAT_WITH_XATTRS| + CA_FORMAT_WITH_ACL| + CA_FORMAT_WITH_SELINUX| + CA_FORMAT_WITH_FCAPS| + CA_FORMAT_WITH_QUOTA_PROJID + }, + XFS_SUPER_MAGIC => { + CA_FORMAT_WITH_16BIT_UIDS| + CA_FORMAT_WITH_32BIT_UIDS| + CA_FORMAT_WITH_USER_NAMES| + CA_FORMAT_WITH_SEC_TIME| + CA_FORMAT_WITH_USEC_TIME| + CA_FORMAT_WITH_NSEC_TIME| + CA_FORMAT_WITH_2SEC_TIME| + CA_FORMAT_WITH_READ_ONLY| + CA_FORMAT_WITH_PERMISSIONS| + CA_FORMAT_WITH_SYMLINKS| + CA_FORMAT_WITH_DEVICE_NODES| + CA_FORMAT_WITH_FIFOS| + CA_FORMAT_WITH_SOCKETS| + CA_FORMAT_WITH_FLAG_APPEND| + CA_FORMAT_WITH_FLAG_NOATIME| + CA_FORMAT_WITH_FLAG_NODUMP| + CA_FORMAT_WITH_FLAG_IMMUTABLE| + CA_FORMAT_WITH_FLAG_SYNC| + CA_FORMAT_WITH_XATTRS| + CA_FORMAT_WITH_ACL| + CA_FORMAT_WITH_SELINUX| + CA_FORMAT_WITH_FCAPS| + CA_FORMAT_WITH_QUOTA_PROJID + }, + BTRFS_SUPER_MAGIC => { + CA_FORMAT_WITH_16BIT_UIDS| + CA_FORMAT_WITH_32BIT_UIDS| + CA_FORMAT_WITH_USER_NAMES| + CA_FORMAT_WITH_SEC_TIME| + CA_FORMAT_WITH_USEC_TIME| + CA_FORMAT_WITH_NSEC_TIME| + CA_FORMAT_WITH_2SEC_TIME| + CA_FORMAT_WITH_READ_ONLY| + CA_FORMAT_WITH_PERMISSIONS| + CA_FORMAT_WITH_SYMLINKS| + CA_FORMAT_WITH_DEVICE_NODES| + CA_FORMAT_WITH_FIFOS| + CA_FORMAT_WITH_SOCKETS| + CA_FORMAT_WITH_FLAG_APPEND| + CA_FORMAT_WITH_FLAG_NOATIME| + CA_FORMAT_WITH_FLAG_COMPR| + CA_FORMAT_WITH_FLAG_NOCOW| + CA_FORMAT_WITH_FLAG_NODUMP| + CA_FORMAT_WITH_FLAG_DIRSYNC| + CA_FORMAT_WITH_FLAG_IMMUTABLE| + CA_FORMAT_WITH_FLAG_SYNC| + CA_FORMAT_WITH_FLAG_NOCOMP| + CA_FORMAT_WITH_XATTRS| + CA_FORMAT_WITH_ACL| + CA_FORMAT_WITH_SELINUX| + CA_FORMAT_WITH_SUBVOLUME| + CA_FORMAT_WITH_SUBVOLUME_RO| + CA_FORMAT_WITH_FCAPS + }, + TMPFS_MAGIC => { + CA_FORMAT_WITH_16BIT_UIDS| + CA_FORMAT_WITH_32BIT_UIDS| + CA_FORMAT_WITH_USER_NAMES| + CA_FORMAT_WITH_SEC_TIME| + CA_FORMAT_WITH_USEC_TIME| + CA_FORMAT_WITH_NSEC_TIME| + CA_FORMAT_WITH_2SEC_TIME| + CA_FORMAT_WITH_READ_ONLY| + CA_FORMAT_WITH_PERMISSIONS| + CA_FORMAT_WITH_SYMLINKS| + CA_FORMAT_WITH_DEVICE_NODES| + CA_FORMAT_WITH_FIFOS| + CA_FORMAT_WITH_SOCKETS| + CA_FORMAT_WITH_ACL| + CA_FORMAT_WITH_SELINUX + }, + FUSE_SUPER_MAGIC => { + // FUSE mounts are special as the supported feature set is not clear + // a priori. + CA_FORMAT_WITH_FUSE + }, + _ => { + CA_FORMAT_WITH_16BIT_UIDS| + CA_FORMAT_WITH_32BIT_UIDS| + CA_FORMAT_WITH_USER_NAMES| + CA_FORMAT_WITH_SEC_TIME| + CA_FORMAT_WITH_USEC_TIME| + CA_FORMAT_WITH_NSEC_TIME| + CA_FORMAT_WITH_2SEC_TIME| + CA_FORMAT_WITH_READ_ONLY| + CA_FORMAT_WITH_PERMISSIONS| + CA_FORMAT_WITH_SYMLINKS| + CA_FORMAT_WITH_DEVICE_NODES| + CA_FORMAT_WITH_FIFOS| + CA_FORMAT_WITH_SOCKETS + }, + } +}