From: Wolfgang Bumiller Date: Wed, 10 Jun 2020 09:03:42 +0000 (+0200) Subject: turn pxar::flags into bitflags, pxar::Flags X-Git-Tag: v0.3.0~118 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=5444fa940ba7764766b264e81fad2d0c40892e84;p=proxmox-backup.git turn pxar::flags into bitflags, pxar::Flags Signed-off-by: Wolfgang Bumiller --- diff --git a/src/backup/catalog_shell.rs b/src/backup/catalog_shell.rs index 86bf1fc4..87fede0c 100644 --- a/src/backup/catalog_shell.rs +++ b/src/backup/catalog_shell.rs @@ -25,7 +25,7 @@ use crate::backup::catalog::{self, DirEntryAttribute}; // FIXME: Remove looku_self() calls by putting Directory into the dir stack use crate::pxar::dir_stack::PxarDirStack; -use crate::pxar::flags; +use crate::pxar::Flags; use crate::pxar::fuse::{Accessor, FileEntry}; use crate::pxar::metadata; @@ -977,7 +977,7 @@ impl Shell { let pxar_dir_stack = PxarDirStack::new(rootdir, root_meta); let mut extractor = ExtractorState::new( - flags::DEFAULT, + Flags::DEFAULT, &mut self.catalog, dir_stack, pxar_dir_stack, @@ -1010,14 +1010,14 @@ struct ExtractorState<'a> { pxar_dir_stack: PxarDirStack, catalog: &'a mut CatalogReader, - feature_flags: u64, + feature_flags: Flags, match_list: &'a [MatchEntry], accessor: &'a Accessor, } impl<'a> ExtractorState<'a> { pub fn new( - feature_flags: u64, + feature_flags: Flags, catalog: &'a mut CatalogReader, dir_stack: Vec, pxar_dir_stack: PxarDirStack, @@ -1198,7 +1198,7 @@ impl<'a> ExtractorState<'a> { } metadata::apply_with_path( - flags::DEFAULT, + Flags::DEFAULT, entry.metadata(), file.as_raw_fd(), entry.file_name(), diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs index 29ee562b..123ab2b5 100644 --- a/src/bin/proxmox-backup-client.rs +++ b/src/bin/proxmox-backup-client.rs @@ -1255,7 +1255,7 @@ async fn restore(param: Value) -> Result { pxar::decoder::Decoder::from_std(reader)?, Path::new(target), &[], - proxmox_backup::pxar::flags::DEFAULT, + proxmox_backup::pxar::Flags::DEFAULT, allow_existing_dirs, |path| { if verbose { diff --git a/src/bin/pxar.rs b/src/bin/pxar.rs index 13677305..ecd61f11 100644 --- a/src/bin/pxar.rs +++ b/src/bin/pxar.rs @@ -15,12 +15,12 @@ use proxmox::api::cli::*; use proxmox::api::api; use proxmox_backup::tools; -use proxmox_backup::pxar::{flags, fuse, format_single_line_entry, ENCODER_MAX_ENTRIES}; +use proxmox_backup::pxar::{fuse, format_single_line_entry, ENCODER_MAX_ENTRIES, Flags}; fn extract_archive_from_reader( reader: &mut R, target: &str, - feature_flags: u64, + feature_flags: Flags, allow_existing_dirs: bool, verbose: bool, match_list: &[MatchEntry], @@ -120,24 +120,24 @@ fn extract_archive( no_fifos: bool, no_sockets: bool, ) -> Result<(), Error> { - let mut feature_flags = flags::DEFAULT; + let mut feature_flags = Flags::DEFAULT; if no_xattrs { - feature_flags ^= flags::WITH_XATTRS; + feature_flags ^= Flags::WITH_XATTRS; } if no_fcaps { - feature_flags ^= flags::WITH_FCAPS; + feature_flags ^= Flags::WITH_FCAPS; } if no_acls { - feature_flags ^= flags::WITH_ACL; + feature_flags ^= Flags::WITH_ACL; } if no_device_nodes { - feature_flags ^= flags::WITH_DEVICE_NODES; + feature_flags ^= Flags::WITH_DEVICE_NODES; } if no_fifos { - feature_flags ^= flags::WITH_FIFOS; + feature_flags ^= Flags::WITH_FIFOS; } if no_sockets { - feature_flags ^= flags::WITH_SOCKETS; + feature_flags ^= Flags::WITH_SOCKETS; } let pattern = pattern.unwrap_or_else(Vec::new); @@ -308,24 +308,24 @@ fn create_archive( .open(archive)?; let writer = std::io::BufWriter::with_capacity(1024 * 1024, file); - let mut feature_flags = flags::DEFAULT; + let mut feature_flags = Flags::DEFAULT; if no_xattrs { - feature_flags ^= flags::WITH_XATTRS; + feature_flags ^= Flags::WITH_XATTRS; } if no_fcaps { - feature_flags ^= flags::WITH_FCAPS; + feature_flags ^= Flags::WITH_FCAPS; } if no_acls { - feature_flags ^= flags::WITH_ACL; + feature_flags ^= Flags::WITH_ACL; } if no_device_nodes { - feature_flags ^= flags::WITH_DEVICE_NODES; + feature_flags ^= Flags::WITH_DEVICE_NODES; } if no_fifos { - feature_flags ^= flags::WITH_FIFOS; + feature_flags ^= Flags::WITH_FIFOS; } if no_sockets { - feature_flags ^= flags::WITH_SOCKETS; + feature_flags ^= Flags::WITH_SOCKETS; } let writer = pxar::encoder::sync::StandardWriter::new(writer); diff --git a/src/client/pxar_backup_stream.rs b/src/client/pxar_backup_stream.rs index 11f5d924..7ccca4f0 100644 --- a/src/client/pxar_backup_stream.rs +++ b/src/client/pxar_backup_stream.rs @@ -67,7 +67,7 @@ impl PxarBackupStream { dir, writer, patterns, - crate::pxar::flags::DEFAULT, + crate::pxar::Flags::DEFAULT, device_set, skip_lost_and_found, |_| Ok(()), diff --git a/src/pxar/create.rs b/src/pxar/create.rs index 2e403229..90b1d00c 100644 --- a/src/pxar/create.rs +++ b/src/pxar/create.rs @@ -20,7 +20,7 @@ use proxmox::sys::error::SysError; use proxmox::tools::fd::RawFdNum; use crate::pxar::catalog::BackupCatalogWriter; -use crate::pxar::flags; +use crate::pxar::Flags; use crate::pxar::tools::assert_single_path_component; use crate::tools::{acl, fs, xattr, Fd}; @@ -86,9 +86,8 @@ struct HardLinkInfo { } struct Archiver<'a, 'b> { - /// FIXME: use bitflags!() for feature_flags - feature_flags: u64, - fs_feature_flags: u64, + feature_flags: Flags, + fs_feature_flags: Flags, fs_magic: i64, patterns: &'a [MatchEntry], callback: &'a mut dyn FnMut(&Path) -> Result<(), Error>, @@ -107,7 +106,7 @@ pub fn create_archive( source_dir: Dir, mut writer: T, mut patterns: Vec, - feature_flags: u64, + feature_flags: Flags, mut device_set: Option>, skip_lost_and_found: bool, mut callback: F, @@ -123,7 +122,7 @@ where bail!("refusing to backup a virtual file system"); } - let fs_feature_flags = flags::feature_flags_from_magic(fs_magic); + let fs_feature_flags = Flags::from_magic(fs_magic); let stat = nix::sys::stat::fstat(source_dir.as_raw_fd())?; let metadata = get_metadata( @@ -176,7 +175,9 @@ struct FileListEntry { } impl<'a, 'b> Archiver<'a, 'b> { - fn flags(&self) -> u64 { + /// Get the currently effective feature flags. (Requested flags masked by the file system + /// feature flags). + fn flags(&self) -> Flags { self.feature_flags & self.fs_feature_flags } @@ -447,7 +448,7 @@ impl<'a, 'b> Archiver<'a, 'b> { let mut skip_contents = false; if old_st_dev != stat.st_dev { self.fs_magic = detect_fs_type(dir.as_raw_fd())?; - self.fs_feature_flags = flags::feature_flags_from_magic(self.fs_magic); + self.fs_feature_flags = Flags::from_magic(self.fs_magic); self.current_st_dev = stat.st_dev; if is_virtual_file_system(self.fs_magic) { @@ -511,7 +512,7 @@ impl<'a, 'b> Archiver<'a, 'b> { } } -fn get_metadata(fd: RawFd, stat: &FileStat, flags: u64, fs_magic: i64) -> Result { +fn get_metadata(fd: RawFd, stat: &FileStat, flags: Flags, fs_magic: i64) -> Result { // required for some of these let proc_path = Path::new("/proc/self/fd/").join(fd.to_string()); @@ -543,8 +544,8 @@ fn errno_is_unsupported(errno: Errno) -> bool { } } -fn get_fcaps(meta: &mut Metadata, fd: RawFd, flags: u64) -> Result<(), Error> { - if 0 == (flags & flags::WITH_FCAPS) { +fn get_fcaps(meta: &mut Metadata, fd: RawFd, flags: Flags) -> Result<(), Error> { + if flags.contains(Flags::WITH_FCAPS) { return Ok(()); } @@ -564,9 +565,9 @@ fn get_xattr_fcaps_acl( meta: &mut Metadata, fd: RawFd, proc_path: &Path, - flags: u64, + flags: Flags, ) -> Result<(), Error> { - if 0 == (flags & flags::WITH_XATTRS) { + if flags.contains(Flags::WITH_XATTRS) { return Ok(()); } @@ -617,7 +618,7 @@ fn get_chattr(metadata: &mut Metadata, fd: RawFd) -> Result<(), Error> { Err(err) => bail!("failed to read file attributes: {}", err), } - metadata.stat.flags |= flags::feature_flags_from_chattr(attr as u32); + metadata.stat.flags |= Flags::from_chattr(attr as u32).bits(); Ok(()) } @@ -639,7 +640,7 @@ fn get_fat_attr(metadata: &mut Metadata, fd: RawFd, fs_magic: i64) -> Result<(), Err(err) => bail!("failed to read fat attributes: {}", err), } - metadata.stat.flags |= flags::feature_flags_from_fat_attr(attr); + metadata.stat.flags |= Flags::from_fat_attr(attr).bits(); Ok(()) } @@ -648,14 +649,14 @@ fn get_fat_attr(metadata: &mut Metadata, fd: RawFd, fs_magic: i64) -> Result<(), fn get_quota_project_id( metadata: &mut Metadata, fd: RawFd, - flags: u64, + flags: Flags, magic: i64, ) -> Result<(), Error> { if !(metadata.is_dir() || metadata.is_regular_file()) { return Ok(()); } - if 0 == (flags & flags::WITH_QUOTA_PROJID) { + if flags.contains(Flags::WITH_QUOTA_PROJID) { return Ok(()); } @@ -689,8 +690,8 @@ fn get_quota_project_id( Ok(()) } -fn get_acl(metadata: &mut Metadata, proc_path: &Path, flags: u64) -> Result<(), Error> { - if 0 == (flags & flags::WITH_ACL) { +fn get_acl(metadata: &mut Metadata, proc_path: &Path, flags: Flags) -> Result<(), Error> { + if flags.contains(Flags::WITH_ACL) { return Ok(()); } diff --git a/src/pxar/extract.rs b/src/pxar/extract.rs index 52ed4c8c..2905b7de 100644 --- a/src/pxar/extract.rs +++ b/src/pxar/extract.rs @@ -20,20 +20,19 @@ use proxmox::c_result; use proxmox::tools::fs::{create_path, CreateOptions}; use crate::pxar::dir_stack::PxarDirStack; -use crate::pxar::flags; +use crate::pxar::Flags; use crate::pxar::metadata; struct Extractor<'a> { - /// FIXME: use bitflags!() for feature_flags - feature_flags: u64, + feature_flags: Flags, allow_existing_dirs: bool, callback: &'a mut dyn FnMut(&Path), dir_stack: PxarDirStack, } impl<'a> Extractor<'a> { - fn with_flag(&self, flag: u64) -> bool { - flag == (self.feature_flags & flag) + fn contains_flags(&self, flag: Flags) -> bool { + self.feature_flags.contains(flag) } } @@ -41,7 +40,7 @@ pub fn extract_archive( mut decoder: pxar::decoder::Decoder, destination: &Path, match_list: &[MatchEntry], - feature_flags: u64, + feature_flags: Flags, allow_existing_dirs: bool, mut callback: F, ) -> Result<(), Error> @@ -164,7 +163,7 @@ where extractor.extract_hardlink(&file_name, metadata, link.as_os_str()) } (true, EntryKind::Device(dev)) => { - if extractor.with_flag(flags::WITH_DEVICE_NODES) { + if extractor.contains_flags(Flags::WITH_DEVICE_NODES) { extractor.callback(entry.path()); extractor.extract_device(&file_name, metadata, dev) } else { @@ -172,7 +171,7 @@ where } } (true, EntryKind::Fifo) => { - if extractor.with_flag(flags::WITH_FIFOS) { + if extractor.contains_flags(Flags::WITH_FIFOS) { extractor.callback(entry.path()); extractor.extract_special(&file_name, metadata, 0) } else { @@ -180,7 +179,7 @@ where } } (true, EntryKind::Socket) => { - if extractor.with_flag(flags::WITH_SOCKETS) { + if extractor.contains_flags(Flags::WITH_SOCKETS) { extractor.callback(entry.path()); extractor.extract_special(&file_name, metadata, 0) } else { diff --git a/src/pxar/flags.rs b/src/pxar/flags.rs index 7395beef..2e81d251 100644 --- a/src/pxar/flags.rs +++ b/src/pxar/flags.rs @@ -3,317 +3,332 @@ //! Flags for known supported features for a given filesystem can be derived //! from the superblocks magic number. -// FIXME: use bitflags!() here! +use bitflags::bitflags; -/// FAT-style 2s time granularity -pub const WITH_2SEC_TIME: u64 = 0x40; -/// Preserve read only flag of files -pub const WITH_READ_ONLY: u64 = 0x80; -/// Preserve unix permissions -pub const WITH_PERMISSIONS: u64 = 0x100; -/// Include symbolik links -pub const WITH_SYMLINKS: u64 = 0x200; -/// Include device nodes -pub const WITH_DEVICE_NODES: u64 = 0x400; -/// Include FIFOs -pub const WITH_FIFOS: u64 = 0x800; -/// Include Sockets -pub const WITH_SOCKETS: u64 = 0x1000; +bitflags! { + pub struct Flags: u64 { + /// FAT-style 2s time granularity + const WITH_2SEC_TIME = 0x40; + /// Preserve read only flag of files + const WITH_READ_ONLY = 0x80; + /// Preserve unix permissions + const WITH_PERMISSIONS = 0x100; + /// Include symbolik links + const WITH_SYMLINKS = 0x200; + /// Include device nodes + const WITH_DEVICE_NODES = 0x400; + /// Include FIFOs + const WITH_FIFOS = 0x800; + /// Include Sockets + const WITH_SOCKETS = 0x1000; -/// Preserve DOS file flag `HIDDEN` -pub const WITH_FLAG_HIDDEN: u64 = 0x2000; -/// Preserve DOS file flag `SYSTEM` -pub const WITH_FLAG_SYSTEM: u64 = 0x4000; -/// Preserve DOS file flag `ARCHIVE` -pub const WITH_FLAG_ARCHIVE: u64 = 0x8000; + /// Preserve DOS file flag `HIDDEN` + const WITH_FLAG_HIDDEN = 0x2000; + /// Preserve DOS file flag `SYSTEM` + const WITH_FLAG_SYSTEM = 0x4000; + /// Preserve DOS file flag `ARCHIVE` + const WITH_FLAG_ARCHIVE = 0x8000; -// chattr() flags -/// Linux file attribute `APPEND` -pub const WITH_FLAG_APPEND: u64 = 0x10000; -/// Linux file attribute `NOATIME` -pub const WITH_FLAG_NOATIME: u64 = 0x20000; -/// Linux file attribute `COMPR` -pub const WITH_FLAG_COMPR: u64 = 0x40000; -/// Linux file attribute `NOCOW` -pub const WITH_FLAG_NOCOW: u64 = 0x80000; -/// Linux file attribute `NODUMP` -pub const WITH_FLAG_NODUMP: u64 = 0x0010_0000; -/// Linux file attribute `DIRSYNC` -pub const WITH_FLAG_DIRSYNC: u64 = 0x0020_0000; -/// Linux file attribute `IMMUTABLE` -pub const WITH_FLAG_IMMUTABLE: u64 = 0x0040_0000; -/// Linux file attribute `SYNC` -pub const WITH_FLAG_SYNC: u64 = 0x0080_0000; -/// Linux file attribute `NOCOMP` -pub const WITH_FLAG_NOCOMP: u64 = 0x0100_0000; -/// Linux file attribute `PROJINHERIT` -pub const WITH_FLAG_PROJINHERIT: u64 = 0x0200_0000; + // chattr() flags + /// Linux file attribute `APPEND` + const WITH_FLAG_APPEND = 0x10000; + /// Linux file attribute `NOATIME` + const WITH_FLAG_NOATIME = 0x20000; + /// Linux file attribute `COMPR` + const WITH_FLAG_COMPR = 0x40000; + /// Linux file attribute `NOCOW` + const WITH_FLAG_NOCOW = 0x80000; + /// Linux file attribute `NODUMP` + const WITH_FLAG_NODUMP = 0x0010_0000; + /// Linux file attribute `DIRSYNC` + const WITH_FLAG_DIRSYNC = 0x0020_0000; + /// Linux file attribute `IMMUTABLE` + const WITH_FLAG_IMMUTABLE = 0x0040_0000; + /// Linux file attribute `SYNC` + const WITH_FLAG_SYNC = 0x0080_0000; + /// Linux file attribute `NOCOMP` + const WITH_FLAG_NOCOMP = 0x0100_0000; + /// Linux file attribute `PROJINHERIT` + const WITH_FLAG_PROJINHERIT = 0x0200_0000; -/// Preserve BTRFS subvolume flag -pub const WITH_SUBVOLUME: u64 = 0x0400_0000; -/// Preserve BTRFS read-only subvolume flag -pub const WITH_SUBVOLUME_RO: u64 = 0x0800_0000; + /// Preserve BTRFS subvolume flag + const WITH_SUBVOLUME = 0x0400_0000; + /// Preserve BTRFS read-only subvolume flag + const WITH_SUBVOLUME_RO = 0x0800_0000; -/// Preserve Extended Attribute metadata -pub const WITH_XATTRS: u64 = 0x1000_0000; -/// Preserve Access Control List metadata -pub const WITH_ACL: u64 = 0x2000_0000; -/// Preserve SELinux security context -pub const WITH_SELINUX: u64 = 0x4000_0000; -/// Preserve "security.capability" xattr -pub const WITH_FCAPS: u64 = 0x8000_0000; + /// Preserve Extended Attribute metadata + const WITH_XATTRS = 0x1000_0000; + /// Preserve Access Control List metadata + const WITH_ACL = 0x2000_0000; + /// Preserve SELinux security context + const WITH_SELINUX = 0x4000_0000; + /// Preserve "security.capability" xattr + const WITH_FCAPS = 0x8000_0000; -/// Preserve XFS/ext4/ZFS project quota ID -pub const WITH_QUOTA_PROJID: u64 = 0x0001_0000_0000; + /// Preserve XFS/ext4/ZFS project quota ID + const WITH_QUOTA_PROJID = 0x0001_0000_0000; -/// Support ".pxarexclude" files -pub const EXCLUDE_FILE: u64 = 0x1000_0000_0000_0000; -/// Exclude submounts -pub const EXCLUDE_SUBMOUNTS: u64 = 0x4000_0000_0000_0000; -/// Exclude entries with chattr flag NODUMP -pub const EXCLUDE_NODUMP: u64 = 0x8000_0000_0000_0000; + /// Support ".pxarexclude" files + const EXCLUDE_FILE = 0x1000_0000_0000_0000; + /// Exclude submounts + const EXCLUDE_SUBMOUNTS = 0x4000_0000_0000_0000; + /// Exclude entries with chattr flag NODUMP + const EXCLUDE_NODUMP = 0x8000_0000_0000_0000; -/// Definitions of typical feature flags for the *pxar* encoder/decoder. -/// By this expensive syscalls for unsupported features are avoided. + // 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 WITH_CHATTR: u64 = - WITH_FLAG_APPEND| - WITH_FLAG_NOATIME| - WITH_FLAG_COMPR| - WITH_FLAG_NOCOW| - WITH_FLAG_NODUMP| - WITH_FLAG_DIRSYNC| - WITH_FLAG_IMMUTABLE| - WITH_FLAG_SYNC| - WITH_FLAG_NOCOMP| - WITH_FLAG_PROJINHERIT; + /// All chattr file attributes + const WITH_CHATTR = + Flags::WITH_FLAG_APPEND.bits() | + Flags::WITH_FLAG_NOATIME.bits() | + Flags::WITH_FLAG_COMPR.bits() | + Flags::WITH_FLAG_NOCOW.bits() | + Flags::WITH_FLAG_NODUMP.bits() | + Flags::WITH_FLAG_DIRSYNC.bits() | + Flags::WITH_FLAG_IMMUTABLE.bits() | + Flags::WITH_FLAG_SYNC.bits() | + Flags::WITH_FLAG_NOCOMP.bits() | + Flags::WITH_FLAG_PROJINHERIT.bits(); -/// All FAT file attributes -pub const WITH_FAT_ATTRS: u64 = - WITH_FLAG_HIDDEN| - WITH_FLAG_SYSTEM| - WITH_FLAG_ARCHIVE; + /// All FAT file attributes + const WITH_FAT_ATTRS = + Flags::WITH_FLAG_HIDDEN.bits() | + Flags::WITH_FLAG_SYSTEM.bits() | + Flags::WITH_FLAG_ARCHIVE.bits(); -/// All bits that may also be exposed via fuse -pub const WITH_FUSE: u64 = - WITH_2SEC_TIME| - WITH_READ_ONLY| - WITH_PERMISSIONS| - WITH_SYMLINKS| - WITH_DEVICE_NODES| - WITH_FIFOS| - WITH_SOCKETS| - WITH_FAT_ATTRS| - WITH_CHATTR| - WITH_XATTRS; + /// All bits that may also be exposed via fuse + const WITH_FUSE = + Flags::WITH_2SEC_TIME.bits() | + Flags::WITH_READ_ONLY.bits() | + Flags::WITH_PERMISSIONS.bits() | + Flags::WITH_SYMLINKS.bits() | + Flags::WITH_DEVICE_NODES.bits() | + Flags::WITH_FIFOS.bits() | + Flags::WITH_SOCKETS.bits() | + Flags::WITH_FAT_ATTRS.bits() | + Flags::WITH_CHATTR.bits() | + Flags::WITH_XATTRS.bits(); -/// Default feature flags for encoder/decoder -pub const DEFAULT: u64 = - WITH_SYMLINKS| - WITH_DEVICE_NODES| - WITH_FIFOS| - WITH_SOCKETS| - WITH_FLAG_HIDDEN| - WITH_FLAG_SYSTEM| - WITH_FLAG_ARCHIVE| - WITH_FLAG_APPEND| - WITH_FLAG_NOATIME| - WITH_FLAG_COMPR| - WITH_FLAG_NOCOW| - //WITH_FLAG_NODUMP| - WITH_FLAG_DIRSYNC| - WITH_FLAG_IMMUTABLE| - WITH_FLAG_SYNC| - WITH_FLAG_NOCOMP| - WITH_FLAG_PROJINHERIT| - WITH_SUBVOLUME| - WITH_SUBVOLUME_RO| - WITH_XATTRS| - WITH_ACL| - WITH_SELINUX| - WITH_FCAPS| - WITH_QUOTA_PROJID| - EXCLUDE_NODUMP| - EXCLUDE_FILE; + /// Default feature flags for encoder/decoder + const DEFAULT = + Flags::WITH_SYMLINKS.bits() | + Flags::WITH_DEVICE_NODES.bits() | + Flags::WITH_FIFOS.bits() | + Flags::WITH_SOCKETS.bits() | + Flags::WITH_FLAG_HIDDEN.bits() | + Flags::WITH_FLAG_SYSTEM.bits() | + Flags::WITH_FLAG_ARCHIVE.bits() | + Flags::WITH_FLAG_APPEND.bits() | + Flags::WITH_FLAG_NOATIME.bits() | + Flags::WITH_FLAG_COMPR.bits() | + Flags::WITH_FLAG_NOCOW.bits() | + //WITH_FLAG_NODUMP.bits() | + Flags::WITH_FLAG_DIRSYNC.bits() | + Flags::WITH_FLAG_IMMUTABLE.bits() | + Flags::WITH_FLAG_SYNC.bits() | + Flags::WITH_FLAG_NOCOMP.bits() | + Flags::WITH_FLAG_PROJINHERIT.bits() | + Flags::WITH_SUBVOLUME.bits() | + Flags::WITH_SUBVOLUME_RO.bits() | + Flags::WITH_XATTRS.bits() | + Flags::WITH_ACL.bits() | + Flags::WITH_SELINUX.bits() | + Flags::WITH_FCAPS.bits() | + Flags::WITH_QUOTA_PROJID.bits() | + Flags::EXCLUDE_NODUMP.bits() | + Flags::EXCLUDE_FILE.bits(); + } +} -// form /usr/include/linux/fs.h -const FS_APPEND_FL: u32 = 0x0000_0020; -const FS_NOATIME_FL: u32 = 0x0000_0080; -const FS_COMPR_FL: u32 = 0x0000_0004; -const FS_NOCOW_FL: u32 = 0x0080_0000; -const FS_NODUMP_FL: u32 = 0x0000_0040; -const FS_DIRSYNC_FL: u32 = 0x0001_0000; -const FS_IMMUTABLE_FL: u32 = 0x0000_0010; -const FS_SYNC_FL: u32 = 0x0000_0008; -const FS_NOCOMP_FL: u32 = 0x0000_0400; -const FS_PROJINHERIT_FL: u32 = 0x2000_0000; +impl Default for Flags { + fn default() -> Flags { + Flags::DEFAULT + } +} -static CHATTR_MAP: [(u64, u32); 10] = [ - ( WITH_FLAG_APPEND, FS_APPEND_FL ), - ( WITH_FLAG_NOATIME, FS_NOATIME_FL ), - ( WITH_FLAG_COMPR, FS_COMPR_FL ), - ( WITH_FLAG_NOCOW, FS_NOCOW_FL ), - ( WITH_FLAG_NODUMP, FS_NODUMP_FL ), - ( WITH_FLAG_DIRSYNC, FS_DIRSYNC_FL ), - ( WITH_FLAG_IMMUTABLE, FS_IMMUTABLE_FL ), - ( WITH_FLAG_SYNC, FS_SYNC_FL ), - ( WITH_FLAG_NOCOMP, FS_NOCOMP_FL ), - ( WITH_FLAG_PROJINHERIT, FS_PROJINHERIT_FL ), -]; +impl Flags { + /// Get a set of feature flags from file attributes. + pub fn from_chattr(attr: u32) -> Flags { + // form /usr/include/linux/fs.h + const FS_APPEND_FL: u32 = 0x0000_0020; + const FS_NOATIME_FL: u32 = 0x0000_0080; + const FS_COMPR_FL: u32 = 0x0000_0004; + const FS_NOCOW_FL: u32 = 0x0080_0000; + const FS_NODUMP_FL: u32 = 0x0000_0040; + const FS_DIRSYNC_FL: u32 = 0x0001_0000; + const FS_IMMUTABLE_FL: u32 = 0x0000_0010; + const FS_SYNC_FL: u32 = 0x0000_0008; + const FS_NOCOMP_FL: u32 = 0x0000_0400; + const FS_PROJINHERIT_FL: u32 = 0x2000_0000; -pub fn feature_flags_from_chattr(attr: u32) -> u64 { + const CHATTR_MAP: [(Flags, u32); 10] = [ + ( Flags::WITH_FLAG_APPEND, FS_APPEND_FL ), + ( Flags::WITH_FLAG_NOATIME, FS_NOATIME_FL ), + ( Flags::WITH_FLAG_COMPR, FS_COMPR_FL ), + ( Flags::WITH_FLAG_NOCOW, FS_NOCOW_FL ), + ( Flags::WITH_FLAG_NODUMP, FS_NODUMP_FL ), + ( Flags::WITH_FLAG_DIRSYNC, FS_DIRSYNC_FL ), + ( Flags::WITH_FLAG_IMMUTABLE, FS_IMMUTABLE_FL ), + ( Flags::WITH_FLAG_SYNC, FS_SYNC_FL ), + ( Flags::WITH_FLAG_NOCOMP, FS_NOCOMP_FL ), + ( Flags::WITH_FLAG_PROJINHERIT, FS_PROJINHERIT_FL ), + ]; - let mut flags = 0u64; + let mut flags = Flags::empty(); - for (fe_flag, fs_flag) in &CHATTR_MAP { - if (attr & fs_flag) != 0 { flags |= fe_flag; } - } + for (fe_flag, fs_flag) in &CHATTR_MAP { + if (attr & fs_flag) != 0 { + flags |= *fe_flag; + } + } - flags -} + flags + } -// from /usr/include/linux/msdos_fs.h -const ATTR_HIDDEN: u32 = 2; -const ATTR_SYS: u32 = 4; -const ATTR_ARCH: u32 = 32; + /// Get a set of feature flags from FAT attributes. + pub fn from_fat_attr(attr: u32) -> Flags { + // from /usr/include/linux/msdos_fs.h + const ATTR_HIDDEN: u32 = 2; + const ATTR_SYS: u32 = 4; + const ATTR_ARCH: u32 = 32; -static FAT_ATTR_MAP: [(u64, u32); 3] = [ - ( WITH_FLAG_HIDDEN, ATTR_HIDDEN ), - ( WITH_FLAG_SYSTEM, ATTR_SYS ), - ( WITH_FLAG_ARCHIVE, ATTR_ARCH ), -]; + const FAT_ATTR_MAP: [(Flags, u32); 3] = [ + ( Flags::WITH_FLAG_HIDDEN, ATTR_HIDDEN ), + ( Flags::WITH_FLAG_SYSTEM, ATTR_SYS ), + ( Flags::WITH_FLAG_ARCHIVE, ATTR_ARCH ), + ]; -pub fn feature_flags_from_fat_attr(attr: u32) -> u64 { + let mut flags = Flags::empty(); - let mut flags = 0u64; + for (fe_flag, fs_flag) in &FAT_ATTR_MAP { + if (attr & fs_flag) != 0 { + flags |= *fe_flag; + } + } - for (fe_flag, fs_flag) in &FAT_ATTR_MAP { - if (attr & fs_flag) != 0 { flags |= fe_flag; } + flags } - flags -} - - -/// Return the supported *pxar* feature flags based on the magic number of the filesystem. -pub fn feature_flags_from_magic(magic: i64) -> u64 { - use proxmox::sys::linux::magic::*; - match magic { - MSDOS_SUPER_MAGIC => { - WITH_2SEC_TIME| - WITH_READ_ONLY| - WITH_FAT_ATTRS - }, - EXT4_SUPER_MAGIC => { - WITH_2SEC_TIME| - WITH_READ_ONLY| - WITH_PERMISSIONS| - WITH_SYMLINKS| - WITH_DEVICE_NODES| - WITH_FIFOS| - WITH_SOCKETS| - WITH_FLAG_APPEND| - WITH_FLAG_NOATIME| - WITH_FLAG_NODUMP| - WITH_FLAG_DIRSYNC| - WITH_FLAG_IMMUTABLE| - WITH_FLAG_SYNC| - WITH_XATTRS| - WITH_ACL| - WITH_SELINUX| - WITH_FCAPS| - WITH_QUOTA_PROJID - }, - XFS_SUPER_MAGIC => { - WITH_2SEC_TIME| - WITH_READ_ONLY| - WITH_PERMISSIONS| - WITH_SYMLINKS| - WITH_DEVICE_NODES| - WITH_FIFOS| - WITH_SOCKETS| - WITH_FLAG_APPEND| - WITH_FLAG_NOATIME| - WITH_FLAG_NODUMP| - WITH_FLAG_IMMUTABLE| - WITH_FLAG_SYNC| - WITH_XATTRS| - WITH_ACL| - WITH_SELINUX| - WITH_FCAPS| - WITH_QUOTA_PROJID - }, - ZFS_SUPER_MAGIC => { - WITH_2SEC_TIME| - WITH_READ_ONLY| - WITH_PERMISSIONS| - WITH_SYMLINKS| - WITH_DEVICE_NODES| - WITH_FIFOS| - WITH_SOCKETS| - WITH_FLAG_APPEND| - WITH_FLAG_NOATIME| - WITH_FLAG_NODUMP| - WITH_FLAG_DIRSYNC| - WITH_FLAG_IMMUTABLE| - WITH_FLAG_SYNC| - WITH_XATTRS| - WITH_ACL| - WITH_SELINUX| - WITH_FCAPS| - WITH_QUOTA_PROJID - }, - BTRFS_SUPER_MAGIC => { - WITH_2SEC_TIME| - WITH_READ_ONLY| - WITH_PERMISSIONS| - WITH_SYMLINKS| - WITH_DEVICE_NODES| - WITH_FIFOS| - WITH_SOCKETS| - WITH_FLAG_APPEND| - WITH_FLAG_NOATIME| - WITH_FLAG_COMPR| - WITH_FLAG_NOCOW| - WITH_FLAG_NODUMP| - WITH_FLAG_DIRSYNC| - WITH_FLAG_IMMUTABLE| - WITH_FLAG_SYNC| - WITH_FLAG_NOCOMP| - WITH_XATTRS| - WITH_ACL| - WITH_SELINUX| - WITH_SUBVOLUME| - WITH_SUBVOLUME_RO| - WITH_FCAPS - }, - TMPFS_MAGIC => { - WITH_2SEC_TIME| - WITH_READ_ONLY| - WITH_PERMISSIONS| - WITH_SYMLINKS| - WITH_DEVICE_NODES| - WITH_FIFOS| - WITH_SOCKETS| - WITH_ACL| - WITH_SELINUX - }, - // FUSE mounts are special as the supported feature set - // is not clear a priori. - FUSE_SUPER_MAGIC => { - WITH_FUSE - }, - _ => { - WITH_2SEC_TIME| - WITH_READ_ONLY| - WITH_PERMISSIONS| - WITH_SYMLINKS| - WITH_DEVICE_NODES| - WITH_FIFOS| - WITH_SOCKETS - }, + /// Return the supported *pxar* feature flags based on the magic number of the filesystem. + pub fn from_magic(magic: i64) -> Flags { + use proxmox::sys::linux::magic::*; + match magic { + MSDOS_SUPER_MAGIC => { + Flags::WITH_2SEC_TIME | + Flags::WITH_READ_ONLY | + Flags::WITH_FAT_ATTRS + }, + EXT4_SUPER_MAGIC => { + Flags::WITH_2SEC_TIME | + Flags::WITH_READ_ONLY | + Flags::WITH_PERMISSIONS | + Flags::WITH_SYMLINKS | + Flags::WITH_DEVICE_NODES | + Flags::WITH_FIFOS | + Flags::WITH_SOCKETS | + Flags::WITH_FLAG_APPEND | + Flags::WITH_FLAG_NOATIME | + Flags::WITH_FLAG_NODUMP | + Flags::WITH_FLAG_DIRSYNC | + Flags::WITH_FLAG_IMMUTABLE | + Flags::WITH_FLAG_SYNC | + Flags::WITH_XATTRS | + Flags::WITH_ACL | + Flags::WITH_SELINUX | + Flags::WITH_FCAPS | + Flags::WITH_QUOTA_PROJID + }, + XFS_SUPER_MAGIC => { + Flags::WITH_2SEC_TIME | + Flags::WITH_READ_ONLY | + Flags::WITH_PERMISSIONS | + Flags::WITH_SYMLINKS | + Flags::WITH_DEVICE_NODES | + Flags::WITH_FIFOS | + Flags::WITH_SOCKETS | + Flags::WITH_FLAG_APPEND | + Flags::WITH_FLAG_NOATIME | + Flags::WITH_FLAG_NODUMP | + Flags::WITH_FLAG_IMMUTABLE | + Flags::WITH_FLAG_SYNC | + Flags::WITH_XATTRS | + Flags::WITH_ACL | + Flags::WITH_SELINUX | + Flags::WITH_FCAPS | + Flags::WITH_QUOTA_PROJID + }, + ZFS_SUPER_MAGIC => { + Flags::WITH_2SEC_TIME | + Flags::WITH_READ_ONLY | + Flags::WITH_PERMISSIONS | + Flags::WITH_SYMLINKS | + Flags::WITH_DEVICE_NODES | + Flags::WITH_FIFOS | + Flags::WITH_SOCKETS | + Flags::WITH_FLAG_APPEND | + Flags::WITH_FLAG_NOATIME | + Flags::WITH_FLAG_NODUMP | + Flags::WITH_FLAG_DIRSYNC | + Flags::WITH_FLAG_IMMUTABLE | + Flags::WITH_FLAG_SYNC | + Flags::WITH_XATTRS | + Flags::WITH_ACL | + Flags::WITH_SELINUX | + Flags::WITH_FCAPS | + Flags::WITH_QUOTA_PROJID + }, + BTRFS_SUPER_MAGIC => { + Flags::WITH_2SEC_TIME | + Flags::WITH_READ_ONLY | + Flags::WITH_PERMISSIONS | + Flags::WITH_SYMLINKS | + Flags::WITH_DEVICE_NODES | + Flags::WITH_FIFOS | + Flags::WITH_SOCKETS | + Flags::WITH_FLAG_APPEND | + Flags::WITH_FLAG_NOATIME | + Flags::WITH_FLAG_COMPR | + Flags::WITH_FLAG_NOCOW | + Flags::WITH_FLAG_NODUMP | + Flags::WITH_FLAG_DIRSYNC | + Flags::WITH_FLAG_IMMUTABLE | + Flags::WITH_FLAG_SYNC | + Flags::WITH_FLAG_NOCOMP | + Flags::WITH_XATTRS | + Flags::WITH_ACL | + Flags::WITH_SELINUX | + Flags::WITH_SUBVOLUME | + Flags::WITH_SUBVOLUME_RO | + Flags::WITH_FCAPS + }, + TMPFS_MAGIC => { + Flags::WITH_2SEC_TIME | + Flags::WITH_READ_ONLY | + Flags::WITH_PERMISSIONS | + Flags::WITH_SYMLINKS | + Flags::WITH_DEVICE_NODES | + Flags::WITH_FIFOS | + Flags::WITH_SOCKETS | + Flags::WITH_ACL | + Flags::WITH_SELINUX + }, + // FUSE mounts are special as the supported feature set + // is not clear a priori. + FUSE_SUPER_MAGIC => { + Flags::WITH_FUSE + }, + _ => { + Flags::WITH_2SEC_TIME | + Flags::WITH_READ_ONLY | + Flags::WITH_PERMISSIONS | + Flags::WITH_SYMLINKS | + Flags::WITH_DEVICE_NODES | + Flags::WITH_FIFOS | + Flags::WITH_SOCKETS + }, + } } } diff --git a/src/pxar/metadata.rs b/src/pxar/metadata.rs index e611ba26..24bdcd97 100644 --- a/src/pxar/metadata.rs +++ b/src/pxar/metadata.rs @@ -14,7 +14,7 @@ use proxmox::sys::error::SysError; use proxmox::tools::fd::RawFdNum; use proxmox::{c_result, c_try}; -use crate::pxar::flags; +use crate::pxar::Flags; use crate::pxar::tools::perms_from_metadata; use crate::tools::{acl, fs, xattr}; @@ -22,10 +22,6 @@ use crate::tools::{acl, fs, xattr}; // utility functions // -fn flags_contain(flags: u64, test_flag: u64) -> bool { - 0 != (flags & test_flag) -} - fn allow_notsupp(err: E) -> Result<(), E> { if err.is_errno(Errno::EOPNOTSUPP) { Ok(()) @@ -70,7 +66,7 @@ fn nsec_to_update_timespec(mtime_nsec: u64) -> [libc::timespec; 2] { // pub fn apply_at( - flags: u64, + flags: Flags, metadata: &Metadata, parent: RawFd, file_name: &CStr, @@ -86,7 +82,7 @@ pub fn apply_at( } pub fn apply_with_path>( - flags: u64, + flags: Flags, metadata: &Metadata, fd: RawFd, file_name: T, @@ -99,7 +95,7 @@ pub fn apply_with_path>( ) } -pub fn apply(flags: u64, metadata: &Metadata, fd: RawFd, file_name: &CStr) -> Result<(), Error> { +pub fn apply(flags: Flags, metadata: &Metadata, fd: RawFd, file_name: &CStr) -> Result<(), Error> { let c_proc_path = CString::new(format!("/proc/self/fd/{}", fd)).unwrap(); let c_proc_path = c_proc_path.as_ptr(); @@ -156,12 +152,12 @@ pub fn apply(flags: u64, metadata: &Metadata, fd: RawFd, file_name: &CStr) -> Re } fn add_fcaps( - flags: u64, + flags: Flags, c_proc_path: *const libc::c_char, metadata: &Metadata, skip_xattrs: &mut bool, ) -> Result<(), Error> { - if *skip_xattrs || !flags_contain(flags, flags::WITH_FCAPS) { + if *skip_xattrs || !flags.contains(Flags::WITH_FCAPS) { return Ok(()); } let fcaps = match metadata.fcaps.as_ref() { @@ -185,12 +181,12 @@ fn add_fcaps( } fn apply_xattrs( - flags: u64, + flags: Flags, c_proc_path: *const libc::c_char, metadata: &Metadata, skip_xattrs: &mut bool, ) -> Result<(), Error> { - if *skip_xattrs || !flags_contain(flags, flags::WITH_XATTRS) { + if *skip_xattrs || !flags.contains(Flags::WITH_XATTRS) { return Ok(()); } @@ -221,11 +217,11 @@ fn apply_xattrs( } fn apply_acls( - flags: u64, + flags: Flags, c_proc_path: *const libc::c_char, metadata: &Metadata, ) -> Result<(), Error> { - if !flags_contain(flags, flags::WITH_ACL) || metadata.acl.is_empty() { + if !flags.contains(Flags::WITH_ACL) || metadata.acl.is_empty() { return Ok(()); } @@ -309,8 +305,8 @@ fn apply_acls( Ok(()) } -fn apply_quota_project_id(flags: u64, fd: RawFd, metadata: &Metadata) -> Result<(), Error> { - if !flags_contain(flags, flags::WITH_QUOTA_PROJID) { +fn apply_quota_project_id(flags: Flags, fd: RawFd, metadata: &Metadata) -> Result<(), Error> { + if !flags.contains(Flags::WITH_QUOTA_PROJID) { return Ok(()); } diff --git a/src/pxar/mod.rs b/src/pxar/mod.rs index 571d6c21..6e910667 100644 --- a/src/pxar/mod.rs +++ b/src/pxar/mod.rs @@ -52,10 +52,12 @@ pub(crate) mod create; pub(crate) mod dir_stack; pub(crate) mod extract; pub(crate) mod metadata; -pub mod flags; pub mod fuse; pub(crate) mod tools; +mod flags; +pub use flags::Flags; + pub use create::create_archive; pub use extract::extract_archive; diff --git a/tests/catar.rs b/tests/catar.rs index e5b2c4cb..a6acf9af 100644 --- a/tests/catar.rs +++ b/tests/catar.rs @@ -29,7 +29,7 @@ fn run_test(dir_name: &str) -> Result<(), Error> { dir, writer, Vec::new(), - flags::DEFAULT, + Flags::DEFAULT, None, false, |_| Ok(()),