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 <c.ebner@proxmox.com>
This commit is contained in:
Christian Ebner 2019-06-06 13:37:07 +02:00 committed by Dietmar Maurer
parent 1f319e766e
commit e993db91cd
2 changed files with 243 additions and 65 deletions

View File

@ -50,7 +50,10 @@ pub struct Encoder<'a, W: Write> {
all_file_systems: bool, all_file_systems: bool,
root_st_dev: u64, root_st_dev: u64,
verbose: bool, verbose: bool,
// Flags set by the user
feature_flags: u64, feature_flags: u64,
// Flags signaling features supported by the filesystem
fs_feature_flags: u64,
hardlinks: HashMap<HardLinkInfo, (PathBuf, u64)>, hardlinks: HashMap<HardLinkInfo, (PathBuf, u64)>,
} }
@ -94,6 +97,8 @@ impl <'a, W: Write> Encoder<'a, W> {
bail!("backup virtual file systems is disabled!"); bail!("backup virtual file systems is disabled!");
} }
let fs_feature_flags = feature_flags_from_magic(magic);
let mut me = Self { let mut me = Self {
base_path: path, base_path: path,
relative_path: PathBuf::new(), relative_path: PathBuf::new(),
@ -105,6 +110,7 @@ impl <'a, W: Write> Encoder<'a, W> {
root_st_dev: stat.st_dev, root_st_dev: stat.st_dev,
verbose, verbose,
feature_flags, feature_flags,
fs_feature_flags,
hardlinks: HashMap::new(), 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 /// True if all of the given feature flags are set in the Encoder, false otherwise
fn has_features(&self, feature_flags: u64) -> bool { 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 /// 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 { 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<CaFormatXAttr>, Option<CaFormatFCaps>), Error> { fn read_xattrs(&self, fd: RawFd, stat: &FileStat) -> Result<(Vec<CaFormatXAttr>, Option<CaFormatFCaps>), Error> {
@ -568,6 +574,11 @@ impl <'a, W: Write> Encoder<'a, W> {
self.read_chattr(rawfd, &mut dir_entry)?; self.read_chattr(rawfd, &mut dir_entry)?;
self.read_fat_attr(rawfd, magic, &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 (xattrs, fcaps) = self.read_xattrs(rawfd, &dir_stat)?;
let acl_access = self.read_acl(rawfd, &dir_stat, acl::ACL_TYPE_ACCESS)?; 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)?; let acl_default = self.read_acl(rawfd, &dir_stat, acl::ACL_TYPE_DEFAULT)?;
@ -933,35 +944,6 @@ fn detect_fs_type(fd: RawFd) -> Result<i64, Error> {
Ok(fs_stat.f_type) 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)] #[inline(always)]
pub fn is_temporary_file_system(magic: i64) -> bool { pub fn is_temporary_file_system(magic: i64) -> bool {
magic == RAMFS_MAGIC || magic == TMPFS_MAGIC magic == RAMFS_MAGIC || magic == TMPFS_MAGIC

View File

@ -115,40 +115,6 @@ pub const CA_FORMAT_EXCLUDE_SUBMOUNTS: u64 = 0x4000000000000000;
/// Exclude entries with chattr flag NODUMP /// Exclude entries with chattr flag NODUMP
pub const CA_FORMAT_EXCLUDE_NODUMP: u64 = 0x8000000000000000; 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(Debug)]
#[derive(Endian)] #[derive(Endian)]
#[repr(C)] #[repr(C)]
@ -415,3 +381,233 @@ pub fn ca_feature_flags_from_fat_attr(attr: u32) -> u64 {
flags 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
},
}
}