turn pxar::flags into bitflags, pxar::Flags

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2020-06-10 11:03:42 +02:00
parent d4f2397d4c
commit 5444fa940b
10 changed files with 380 additions and 367 deletions

View File

@ -25,7 +25,7 @@ use crate::backup::catalog::{self, DirEntryAttribute};
// FIXME: Remove looku_self() calls by putting Directory into the dir stack // FIXME: Remove looku_self() calls by putting Directory into the dir stack
use crate::pxar::dir_stack::PxarDirStack; use crate::pxar::dir_stack::PxarDirStack;
use crate::pxar::flags; use crate::pxar::Flags;
use crate::pxar::fuse::{Accessor, FileEntry}; use crate::pxar::fuse::{Accessor, FileEntry};
use crate::pxar::metadata; use crate::pxar::metadata;
@ -977,7 +977,7 @@ impl Shell {
let pxar_dir_stack = PxarDirStack::new(rootdir, root_meta); let pxar_dir_stack = PxarDirStack::new(rootdir, root_meta);
let mut extractor = ExtractorState::new( let mut extractor = ExtractorState::new(
flags::DEFAULT, Flags::DEFAULT,
&mut self.catalog, &mut self.catalog,
dir_stack, dir_stack,
pxar_dir_stack, pxar_dir_stack,
@ -1010,14 +1010,14 @@ struct ExtractorState<'a> {
pxar_dir_stack: PxarDirStack, pxar_dir_stack: PxarDirStack,
catalog: &'a mut CatalogReader, catalog: &'a mut CatalogReader,
feature_flags: u64, feature_flags: Flags,
match_list: &'a [MatchEntry], match_list: &'a [MatchEntry],
accessor: &'a Accessor, accessor: &'a Accessor,
} }
impl<'a> ExtractorState<'a> { impl<'a> ExtractorState<'a> {
pub fn new( pub fn new(
feature_flags: u64, feature_flags: Flags,
catalog: &'a mut CatalogReader, catalog: &'a mut CatalogReader,
dir_stack: Vec<PathStackEntry>, dir_stack: Vec<PathStackEntry>,
pxar_dir_stack: PxarDirStack, pxar_dir_stack: PxarDirStack,
@ -1198,7 +1198,7 @@ impl<'a> ExtractorState<'a> {
} }
metadata::apply_with_path( metadata::apply_with_path(
flags::DEFAULT, Flags::DEFAULT,
entry.metadata(), entry.metadata(),
file.as_raw_fd(), file.as_raw_fd(),
entry.file_name(), entry.file_name(),

View File

@ -1255,7 +1255,7 @@ async fn restore(param: Value) -> Result<Value, Error> {
pxar::decoder::Decoder::from_std(reader)?, pxar::decoder::Decoder::from_std(reader)?,
Path::new(target), Path::new(target),
&[], &[],
proxmox_backup::pxar::flags::DEFAULT, proxmox_backup::pxar::Flags::DEFAULT,
allow_existing_dirs, allow_existing_dirs,
|path| { |path| {
if verbose { if verbose {

View File

@ -15,12 +15,12 @@ use proxmox::api::cli::*;
use proxmox::api::api; use proxmox::api::api;
use proxmox_backup::tools; 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<R: std::io::Read>( fn extract_archive_from_reader<R: std::io::Read>(
reader: &mut R, reader: &mut R,
target: &str, target: &str,
feature_flags: u64, feature_flags: Flags,
allow_existing_dirs: bool, allow_existing_dirs: bool,
verbose: bool, verbose: bool,
match_list: &[MatchEntry], match_list: &[MatchEntry],
@ -120,24 +120,24 @@ fn extract_archive(
no_fifos: bool, no_fifos: bool,
no_sockets: bool, no_sockets: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut feature_flags = flags::DEFAULT; let mut feature_flags = Flags::DEFAULT;
if no_xattrs { if no_xattrs {
feature_flags ^= flags::WITH_XATTRS; feature_flags ^= Flags::WITH_XATTRS;
} }
if no_fcaps { if no_fcaps {
feature_flags ^= flags::WITH_FCAPS; feature_flags ^= Flags::WITH_FCAPS;
} }
if no_acls { if no_acls {
feature_flags ^= flags::WITH_ACL; feature_flags ^= Flags::WITH_ACL;
} }
if no_device_nodes { if no_device_nodes {
feature_flags ^= flags::WITH_DEVICE_NODES; feature_flags ^= Flags::WITH_DEVICE_NODES;
} }
if no_fifos { if no_fifos {
feature_flags ^= flags::WITH_FIFOS; feature_flags ^= Flags::WITH_FIFOS;
} }
if no_sockets { if no_sockets {
feature_flags ^= flags::WITH_SOCKETS; feature_flags ^= Flags::WITH_SOCKETS;
} }
let pattern = pattern.unwrap_or_else(Vec::new); let pattern = pattern.unwrap_or_else(Vec::new);
@ -308,24 +308,24 @@ fn create_archive(
.open(archive)?; .open(archive)?;
let writer = std::io::BufWriter::with_capacity(1024 * 1024, file); 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 { if no_xattrs {
feature_flags ^= flags::WITH_XATTRS; feature_flags ^= Flags::WITH_XATTRS;
} }
if no_fcaps { if no_fcaps {
feature_flags ^= flags::WITH_FCAPS; feature_flags ^= Flags::WITH_FCAPS;
} }
if no_acls { if no_acls {
feature_flags ^= flags::WITH_ACL; feature_flags ^= Flags::WITH_ACL;
} }
if no_device_nodes { if no_device_nodes {
feature_flags ^= flags::WITH_DEVICE_NODES; feature_flags ^= Flags::WITH_DEVICE_NODES;
} }
if no_fifos { if no_fifos {
feature_flags ^= flags::WITH_FIFOS; feature_flags ^= Flags::WITH_FIFOS;
} }
if no_sockets { if no_sockets {
feature_flags ^= flags::WITH_SOCKETS; feature_flags ^= Flags::WITH_SOCKETS;
} }
let writer = pxar::encoder::sync::StandardWriter::new(writer); let writer = pxar::encoder::sync::StandardWriter::new(writer);

View File

@ -67,7 +67,7 @@ impl PxarBackupStream {
dir, dir,
writer, writer,
patterns, patterns,
crate::pxar::flags::DEFAULT, crate::pxar::Flags::DEFAULT,
device_set, device_set,
skip_lost_and_found, skip_lost_and_found,
|_| Ok(()), |_| Ok(()),

View File

@ -20,7 +20,7 @@ use proxmox::sys::error::SysError;
use proxmox::tools::fd::RawFdNum; use proxmox::tools::fd::RawFdNum;
use crate::pxar::catalog::BackupCatalogWriter; use crate::pxar::catalog::BackupCatalogWriter;
use crate::pxar::flags; use crate::pxar::Flags;
use crate::pxar::tools::assert_single_path_component; use crate::pxar::tools::assert_single_path_component;
use crate::tools::{acl, fs, xattr, Fd}; use crate::tools::{acl, fs, xattr, Fd};
@ -86,9 +86,8 @@ struct HardLinkInfo {
} }
struct Archiver<'a, 'b> { struct Archiver<'a, 'b> {
/// FIXME: use bitflags!() for feature_flags feature_flags: Flags,
feature_flags: u64, fs_feature_flags: Flags,
fs_feature_flags: u64,
fs_magic: i64, fs_magic: i64,
patterns: &'a [MatchEntry], patterns: &'a [MatchEntry],
callback: &'a mut dyn FnMut(&Path) -> Result<(), Error>, callback: &'a mut dyn FnMut(&Path) -> Result<(), Error>,
@ -107,7 +106,7 @@ pub fn create_archive<T, F>(
source_dir: Dir, source_dir: Dir,
mut writer: T, mut writer: T,
mut patterns: Vec<MatchEntry>, mut patterns: Vec<MatchEntry>,
feature_flags: u64, feature_flags: Flags,
mut device_set: Option<HashSet<u64>>, mut device_set: Option<HashSet<u64>>,
skip_lost_and_found: bool, skip_lost_and_found: bool,
mut callback: F, mut callback: F,
@ -123,7 +122,7 @@ where
bail!("refusing to backup a virtual file system"); 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 stat = nix::sys::stat::fstat(source_dir.as_raw_fd())?;
let metadata = get_metadata( let metadata = get_metadata(
@ -176,7 +175,9 @@ struct FileListEntry {
} }
impl<'a, 'b> Archiver<'a, 'b> { 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 self.feature_flags & self.fs_feature_flags
} }
@ -447,7 +448,7 @@ impl<'a, 'b> Archiver<'a, 'b> {
let mut skip_contents = false; let mut skip_contents = false;
if old_st_dev != stat.st_dev { if old_st_dev != stat.st_dev {
self.fs_magic = detect_fs_type(dir.as_raw_fd())?; 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; self.current_st_dev = stat.st_dev;
if is_virtual_file_system(self.fs_magic) { 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<Metadata, Error> { fn get_metadata(fd: RawFd, stat: &FileStat, flags: Flags, fs_magic: i64) -> Result<Metadata, Error> {
// required for some of these // required for some of these
let proc_path = Path::new("/proc/self/fd/").join(fd.to_string()); 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> { fn get_fcaps(meta: &mut Metadata, fd: RawFd, flags: Flags) -> Result<(), Error> {
if 0 == (flags & flags::WITH_FCAPS) { if flags.contains(Flags::WITH_FCAPS) {
return Ok(()); return Ok(());
} }
@ -564,9 +565,9 @@ fn get_xattr_fcaps_acl(
meta: &mut Metadata, meta: &mut Metadata,
fd: RawFd, fd: RawFd,
proc_path: &Path, proc_path: &Path,
flags: u64, flags: Flags,
) -> Result<(), Error> { ) -> Result<(), Error> {
if 0 == (flags & flags::WITH_XATTRS) { if flags.contains(Flags::WITH_XATTRS) {
return Ok(()); 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), 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(()) 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), 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(()) Ok(())
} }
@ -648,14 +649,14 @@ fn get_fat_attr(metadata: &mut Metadata, fd: RawFd, fs_magic: i64) -> Result<(),
fn get_quota_project_id( fn get_quota_project_id(
metadata: &mut Metadata, metadata: &mut Metadata,
fd: RawFd, fd: RawFd,
flags: u64, flags: Flags,
magic: i64, magic: i64,
) -> Result<(), Error> { ) -> Result<(), Error> {
if !(metadata.is_dir() || metadata.is_regular_file()) { if !(metadata.is_dir() || metadata.is_regular_file()) {
return Ok(()); return Ok(());
} }
if 0 == (flags & flags::WITH_QUOTA_PROJID) { if flags.contains(Flags::WITH_QUOTA_PROJID) {
return Ok(()); return Ok(());
} }
@ -689,8 +690,8 @@ fn get_quota_project_id(
Ok(()) Ok(())
} }
fn get_acl(metadata: &mut Metadata, proc_path: &Path, flags: u64) -> Result<(), Error> { fn get_acl(metadata: &mut Metadata, proc_path: &Path, flags: Flags) -> Result<(), Error> {
if 0 == (flags & flags::WITH_ACL) { if flags.contains(Flags::WITH_ACL) {
return Ok(()); return Ok(());
} }

View File

@ -20,20 +20,19 @@ use proxmox::c_result;
use proxmox::tools::fs::{create_path, CreateOptions}; use proxmox::tools::fs::{create_path, CreateOptions};
use crate::pxar::dir_stack::PxarDirStack; use crate::pxar::dir_stack::PxarDirStack;
use crate::pxar::flags; use crate::pxar::Flags;
use crate::pxar::metadata; use crate::pxar::metadata;
struct Extractor<'a> { struct Extractor<'a> {
/// FIXME: use bitflags!() for feature_flags feature_flags: Flags,
feature_flags: u64,
allow_existing_dirs: bool, allow_existing_dirs: bool,
callback: &'a mut dyn FnMut(&Path), callback: &'a mut dyn FnMut(&Path),
dir_stack: PxarDirStack, dir_stack: PxarDirStack,
} }
impl<'a> Extractor<'a> { impl<'a> Extractor<'a> {
fn with_flag(&self, flag: u64) -> bool { fn contains_flags(&self, flag: Flags) -> bool {
flag == (self.feature_flags & flag) self.feature_flags.contains(flag)
} }
} }
@ -41,7 +40,7 @@ pub fn extract_archive<T, F>(
mut decoder: pxar::decoder::Decoder<T>, mut decoder: pxar::decoder::Decoder<T>,
destination: &Path, destination: &Path,
match_list: &[MatchEntry], match_list: &[MatchEntry],
feature_flags: u64, feature_flags: Flags,
allow_existing_dirs: bool, allow_existing_dirs: bool,
mut callback: F, mut callback: F,
) -> Result<(), Error> ) -> Result<(), Error>
@ -164,7 +163,7 @@ where
extractor.extract_hardlink(&file_name, metadata, link.as_os_str()) extractor.extract_hardlink(&file_name, metadata, link.as_os_str())
} }
(true, EntryKind::Device(dev)) => { (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.callback(entry.path());
extractor.extract_device(&file_name, metadata, dev) extractor.extract_device(&file_name, metadata, dev)
} else { } else {
@ -172,7 +171,7 @@ where
} }
} }
(true, EntryKind::Fifo) => { (true, EntryKind::Fifo) => {
if extractor.with_flag(flags::WITH_FIFOS) { if extractor.contains_flags(Flags::WITH_FIFOS) {
extractor.callback(entry.path()); extractor.callback(entry.path());
extractor.extract_special(&file_name, metadata, 0) extractor.extract_special(&file_name, metadata, 0)
} else { } else {
@ -180,7 +179,7 @@ where
} }
} }
(true, EntryKind::Socket) => { (true, EntryKind::Socket) => {
if extractor.with_flag(flags::WITH_SOCKETS) { if extractor.contains_flags(Flags::WITH_SOCKETS) {
extractor.callback(entry.path()); extractor.callback(entry.path());
extractor.extract_special(&file_name, metadata, 0) extractor.extract_special(&file_name, metadata, 0)
} else { } else {

View File

@ -3,317 +3,332 @@
//! Flags for known supported features for a given filesystem can be derived //! Flags for known supported features for a given filesystem can be derived
//! from the superblocks magic number. //! from the superblocks magic number.
// FIXME: use bitflags!() here! use bitflags::bitflags;
/// FAT-style 2s time granularity bitflags! {
pub const WITH_2SEC_TIME: u64 = 0x40; pub struct Flags: u64 {
/// Preserve read only flag of files /// FAT-style 2s time granularity
pub const WITH_READ_ONLY: u64 = 0x80; const WITH_2SEC_TIME = 0x40;
/// Preserve unix permissions /// Preserve read only flag of files
pub const WITH_PERMISSIONS: u64 = 0x100; const WITH_READ_ONLY = 0x80;
/// Include symbolik links /// Preserve unix permissions
pub const WITH_SYMLINKS: u64 = 0x200; const WITH_PERMISSIONS = 0x100;
/// Include device nodes /// Include symbolik links
pub const WITH_DEVICE_NODES: u64 = 0x400; const WITH_SYMLINKS = 0x200;
/// Include FIFOs /// Include device nodes
pub const WITH_FIFOS: u64 = 0x800; const WITH_DEVICE_NODES = 0x400;
/// Include Sockets /// Include FIFOs
pub const WITH_SOCKETS: u64 = 0x1000; const WITH_FIFOS = 0x800;
/// Include Sockets
const WITH_SOCKETS = 0x1000;
/// Preserve DOS file flag `HIDDEN` /// Preserve DOS file flag `HIDDEN`
pub const WITH_FLAG_HIDDEN: u64 = 0x2000; const WITH_FLAG_HIDDEN = 0x2000;
/// Preserve DOS file flag `SYSTEM` /// Preserve DOS file flag `SYSTEM`
pub const WITH_FLAG_SYSTEM: u64 = 0x4000; const WITH_FLAG_SYSTEM = 0x4000;
/// Preserve DOS file flag `ARCHIVE` /// Preserve DOS file flag `ARCHIVE`
pub const WITH_FLAG_ARCHIVE: u64 = 0x8000; const WITH_FLAG_ARCHIVE = 0x8000;
// chattr() flags // chattr() flags
/// Linux file attribute `APPEND` /// Linux file attribute `APPEND`
pub const WITH_FLAG_APPEND: u64 = 0x10000; const WITH_FLAG_APPEND = 0x10000;
/// Linux file attribute `NOATIME` /// Linux file attribute `NOATIME`
pub const WITH_FLAG_NOATIME: u64 = 0x20000; const WITH_FLAG_NOATIME = 0x20000;
/// Linux file attribute `COMPR` /// Linux file attribute `COMPR`
pub const WITH_FLAG_COMPR: u64 = 0x40000; const WITH_FLAG_COMPR = 0x40000;
/// Linux file attribute `NOCOW` /// Linux file attribute `NOCOW`
pub const WITH_FLAG_NOCOW: u64 = 0x80000; const WITH_FLAG_NOCOW = 0x80000;
/// Linux file attribute `NODUMP` /// Linux file attribute `NODUMP`
pub const WITH_FLAG_NODUMP: u64 = 0x0010_0000; const WITH_FLAG_NODUMP = 0x0010_0000;
/// Linux file attribute `DIRSYNC` /// Linux file attribute `DIRSYNC`
pub const WITH_FLAG_DIRSYNC: u64 = 0x0020_0000; const WITH_FLAG_DIRSYNC = 0x0020_0000;
/// Linux file attribute `IMMUTABLE` /// Linux file attribute `IMMUTABLE`
pub const WITH_FLAG_IMMUTABLE: u64 = 0x0040_0000; const WITH_FLAG_IMMUTABLE = 0x0040_0000;
/// Linux file attribute `SYNC` /// Linux file attribute `SYNC`
pub const WITH_FLAG_SYNC: u64 = 0x0080_0000; const WITH_FLAG_SYNC = 0x0080_0000;
/// Linux file attribute `NOCOMP` /// Linux file attribute `NOCOMP`
pub const WITH_FLAG_NOCOMP: u64 = 0x0100_0000; const WITH_FLAG_NOCOMP = 0x0100_0000;
/// Linux file attribute `PROJINHERIT` /// Linux file attribute `PROJINHERIT`
pub const WITH_FLAG_PROJINHERIT: u64 = 0x0200_0000; const WITH_FLAG_PROJINHERIT = 0x0200_0000;
/// Preserve BTRFS subvolume flag /// Preserve BTRFS subvolume flag
pub const WITH_SUBVOLUME: u64 = 0x0400_0000; const WITH_SUBVOLUME = 0x0400_0000;
/// Preserve BTRFS read-only subvolume flag /// Preserve BTRFS read-only subvolume flag
pub const WITH_SUBVOLUME_RO: u64 = 0x0800_0000; const WITH_SUBVOLUME_RO = 0x0800_0000;
/// Preserve Extended Attribute metadata /// Preserve Extended Attribute metadata
pub const WITH_XATTRS: u64 = 0x1000_0000; const WITH_XATTRS = 0x1000_0000;
/// Preserve Access Control List metadata /// Preserve Access Control List metadata
pub const WITH_ACL: u64 = 0x2000_0000; const WITH_ACL = 0x2000_0000;
/// Preserve SELinux security context /// Preserve SELinux security context
pub const WITH_SELINUX: u64 = 0x4000_0000; const WITH_SELINUX = 0x4000_0000;
/// Preserve "security.capability" xattr /// Preserve "security.capability" xattr
pub const WITH_FCAPS: u64 = 0x8000_0000; const WITH_FCAPS = 0x8000_0000;
/// Preserve XFS/ext4/ZFS project quota ID /// Preserve XFS/ext4/ZFS project quota ID
pub const WITH_QUOTA_PROJID: u64 = 0x0001_0000_0000; const WITH_QUOTA_PROJID = 0x0001_0000_0000;
/// Support ".pxarexclude" files /// Support ".pxarexclude" files
pub const EXCLUDE_FILE: u64 = 0x1000_0000_0000_0000; const EXCLUDE_FILE = 0x1000_0000_0000_0000;
/// Exclude submounts /// Exclude submounts
pub const EXCLUDE_SUBMOUNTS: u64 = 0x4000_0000_0000_0000; const EXCLUDE_SUBMOUNTS = 0x4000_0000_0000_0000;
/// Exclude entries with chattr flag NODUMP /// Exclude entries with chattr flag NODUMP
pub const EXCLUDE_NODUMP: u64 = 0x8000_0000_0000_0000; const EXCLUDE_NODUMP = 0x8000_0000_0000_0000;
/// Definitions of typical feature flags for the *pxar* encoder/decoder. // Definitions of typical feature flags for the *pxar* encoder/decoder.
/// By this expensive syscalls for unsupported features are avoided. // By this expensive syscalls for unsupported features are avoided.
/// All chattr file attributes /// All chattr file attributes
pub const WITH_CHATTR: u64 = const WITH_CHATTR =
WITH_FLAG_APPEND| Flags::WITH_FLAG_APPEND.bits() |
WITH_FLAG_NOATIME| Flags::WITH_FLAG_NOATIME.bits() |
WITH_FLAG_COMPR| Flags::WITH_FLAG_COMPR.bits() |
WITH_FLAG_NOCOW| Flags::WITH_FLAG_NOCOW.bits() |
WITH_FLAG_NODUMP| Flags::WITH_FLAG_NODUMP.bits() |
WITH_FLAG_DIRSYNC| Flags::WITH_FLAG_DIRSYNC.bits() |
WITH_FLAG_IMMUTABLE| Flags::WITH_FLAG_IMMUTABLE.bits() |
WITH_FLAG_SYNC| Flags::WITH_FLAG_SYNC.bits() |
WITH_FLAG_NOCOMP| Flags::WITH_FLAG_NOCOMP.bits() |
WITH_FLAG_PROJINHERIT; Flags::WITH_FLAG_PROJINHERIT.bits();
/// All FAT file attributes /// All FAT file attributes
pub const WITH_FAT_ATTRS: u64 = const WITH_FAT_ATTRS =
WITH_FLAG_HIDDEN| Flags::WITH_FLAG_HIDDEN.bits() |
WITH_FLAG_SYSTEM| Flags::WITH_FLAG_SYSTEM.bits() |
WITH_FLAG_ARCHIVE; Flags::WITH_FLAG_ARCHIVE.bits();
/// All bits that may also be exposed via fuse /// All bits that may also be exposed via fuse
pub const WITH_FUSE: u64 = const WITH_FUSE =
WITH_2SEC_TIME| Flags::WITH_2SEC_TIME.bits() |
WITH_READ_ONLY| Flags::WITH_READ_ONLY.bits() |
WITH_PERMISSIONS| Flags::WITH_PERMISSIONS.bits() |
WITH_SYMLINKS| Flags::WITH_SYMLINKS.bits() |
WITH_DEVICE_NODES| Flags::WITH_DEVICE_NODES.bits() |
WITH_FIFOS| Flags::WITH_FIFOS.bits() |
WITH_SOCKETS| Flags::WITH_SOCKETS.bits() |
WITH_FAT_ATTRS| Flags::WITH_FAT_ATTRS.bits() |
WITH_CHATTR| Flags::WITH_CHATTR.bits() |
WITH_XATTRS; Flags::WITH_XATTRS.bits();
/// Default feature flags for encoder/decoder /// Default feature flags for encoder/decoder
pub const DEFAULT: u64 = const DEFAULT =
WITH_SYMLINKS| Flags::WITH_SYMLINKS.bits() |
WITH_DEVICE_NODES| Flags::WITH_DEVICE_NODES.bits() |
WITH_FIFOS| Flags::WITH_FIFOS.bits() |
WITH_SOCKETS| Flags::WITH_SOCKETS.bits() |
WITH_FLAG_HIDDEN| Flags::WITH_FLAG_HIDDEN.bits() |
WITH_FLAG_SYSTEM| Flags::WITH_FLAG_SYSTEM.bits() |
WITH_FLAG_ARCHIVE| Flags::WITH_FLAG_ARCHIVE.bits() |
WITH_FLAG_APPEND| Flags::WITH_FLAG_APPEND.bits() |
WITH_FLAG_NOATIME| Flags::WITH_FLAG_NOATIME.bits() |
WITH_FLAG_COMPR| Flags::WITH_FLAG_COMPR.bits() |
WITH_FLAG_NOCOW| Flags::WITH_FLAG_NOCOW.bits() |
//WITH_FLAG_NODUMP| //WITH_FLAG_NODUMP.bits() |
WITH_FLAG_DIRSYNC| Flags::WITH_FLAG_DIRSYNC.bits() |
WITH_FLAG_IMMUTABLE| Flags::WITH_FLAG_IMMUTABLE.bits() |
WITH_FLAG_SYNC| Flags::WITH_FLAG_SYNC.bits() |
WITH_FLAG_NOCOMP| Flags::WITH_FLAG_NOCOMP.bits() |
WITH_FLAG_PROJINHERIT| Flags::WITH_FLAG_PROJINHERIT.bits() |
WITH_SUBVOLUME| Flags::WITH_SUBVOLUME.bits() |
WITH_SUBVOLUME_RO| Flags::WITH_SUBVOLUME_RO.bits() |
WITH_XATTRS| Flags::WITH_XATTRS.bits() |
WITH_ACL| Flags::WITH_ACL.bits() |
WITH_SELINUX| Flags::WITH_SELINUX.bits() |
WITH_FCAPS| Flags::WITH_FCAPS.bits() |
WITH_QUOTA_PROJID| Flags::WITH_QUOTA_PROJID.bits() |
EXCLUDE_NODUMP| Flags::EXCLUDE_NODUMP.bits() |
EXCLUDE_FILE; Flags::EXCLUDE_FILE.bits();
}
}
// form /usr/include/linux/fs.h impl Default for Flags {
const FS_APPEND_FL: u32 = 0x0000_0020; fn default() -> Flags {
const FS_NOATIME_FL: u32 = 0x0000_0080; Flags::DEFAULT
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;
static CHATTR_MAP: [(u64, u32); 10] = [ impl Flags {
( WITH_FLAG_APPEND, FS_APPEND_FL ), /// Get a set of feature flags from file attributes.
( WITH_FLAG_NOATIME, FS_NOATIME_FL ), pub fn from_chattr(attr: u32) -> Flags {
( WITH_FLAG_COMPR, FS_COMPR_FL ), // form /usr/include/linux/fs.h
( WITH_FLAG_NOCOW, FS_NOCOW_FL ), const FS_APPEND_FL: u32 = 0x0000_0020;
( WITH_FLAG_NODUMP, FS_NODUMP_FL ), const FS_NOATIME_FL: u32 = 0x0000_0080;
( WITH_FLAG_DIRSYNC, FS_DIRSYNC_FL ), const FS_COMPR_FL: u32 = 0x0000_0004;
( WITH_FLAG_IMMUTABLE, FS_IMMUTABLE_FL ), const FS_NOCOW_FL: u32 = 0x0080_0000;
( WITH_FLAG_SYNC, FS_SYNC_FL ), const FS_NODUMP_FL: u32 = 0x0000_0040;
( WITH_FLAG_NOCOMP, FS_NOCOMP_FL ), const FS_DIRSYNC_FL: u32 = 0x0001_0000;
( WITH_FLAG_PROJINHERIT, FS_PROJINHERIT_FL ), 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 { for (fe_flag, fs_flag) in &CHATTR_MAP {
if (attr & fs_flag) != 0 { flags |= fe_flag; } if (attr & fs_flag) != 0 {
flags |= *fe_flag;
}
} }
flags flags
} }
// from /usr/include/linux/msdos_fs.h /// Get a set of feature flags from FAT attributes.
const ATTR_HIDDEN: u32 = 2; pub fn from_fat_attr(attr: u32) -> Flags {
const ATTR_SYS: u32 = 4; // from /usr/include/linux/msdos_fs.h
const ATTR_ARCH: u32 = 32; const ATTR_HIDDEN: u32 = 2;
const ATTR_SYS: u32 = 4;
const ATTR_ARCH: u32 = 32;
static FAT_ATTR_MAP: [(u64, u32); 3] = [ const FAT_ATTR_MAP: [(Flags, u32); 3] = [
( WITH_FLAG_HIDDEN, ATTR_HIDDEN ), ( Flags::WITH_FLAG_HIDDEN, ATTR_HIDDEN ),
( WITH_FLAG_SYSTEM, ATTR_SYS ), ( Flags::WITH_FLAG_SYSTEM, ATTR_SYS ),
( WITH_FLAG_ARCHIVE, ATTR_ARCH ), ( 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 { for (fe_flag, fs_flag) in &FAT_ATTR_MAP {
if (attr & fs_flag) != 0 { flags |= fe_flag; } if (attr & fs_flag) != 0 {
flags |= *fe_flag;
}
} }
flags flags
} }
/// Return the supported *pxar* feature flags based on the magic number of the filesystem.
/// Return the supported *pxar* feature flags based on the magic number of the filesystem. pub fn from_magic(magic: i64) -> Flags {
pub fn feature_flags_from_magic(magic: i64) -> u64 {
use proxmox::sys::linux::magic::*; use proxmox::sys::linux::magic::*;
match magic { match magic {
MSDOS_SUPER_MAGIC => { MSDOS_SUPER_MAGIC => {
WITH_2SEC_TIME| Flags::WITH_2SEC_TIME |
WITH_READ_ONLY| Flags::WITH_READ_ONLY |
WITH_FAT_ATTRS Flags::WITH_FAT_ATTRS
}, },
EXT4_SUPER_MAGIC => { EXT4_SUPER_MAGIC => {
WITH_2SEC_TIME| Flags::WITH_2SEC_TIME |
WITH_READ_ONLY| Flags::WITH_READ_ONLY |
WITH_PERMISSIONS| Flags::WITH_PERMISSIONS |
WITH_SYMLINKS| Flags::WITH_SYMLINKS |
WITH_DEVICE_NODES| Flags::WITH_DEVICE_NODES |
WITH_FIFOS| Flags::WITH_FIFOS |
WITH_SOCKETS| Flags::WITH_SOCKETS |
WITH_FLAG_APPEND| Flags::WITH_FLAG_APPEND |
WITH_FLAG_NOATIME| Flags::WITH_FLAG_NOATIME |
WITH_FLAG_NODUMP| Flags::WITH_FLAG_NODUMP |
WITH_FLAG_DIRSYNC| Flags::WITH_FLAG_DIRSYNC |
WITH_FLAG_IMMUTABLE| Flags::WITH_FLAG_IMMUTABLE |
WITH_FLAG_SYNC| Flags::WITH_FLAG_SYNC |
WITH_XATTRS| Flags::WITH_XATTRS |
WITH_ACL| Flags::WITH_ACL |
WITH_SELINUX| Flags::WITH_SELINUX |
WITH_FCAPS| Flags::WITH_FCAPS |
WITH_QUOTA_PROJID Flags::WITH_QUOTA_PROJID
}, },
XFS_SUPER_MAGIC => { XFS_SUPER_MAGIC => {
WITH_2SEC_TIME| Flags::WITH_2SEC_TIME |
WITH_READ_ONLY| Flags::WITH_READ_ONLY |
WITH_PERMISSIONS| Flags::WITH_PERMISSIONS |
WITH_SYMLINKS| Flags::WITH_SYMLINKS |
WITH_DEVICE_NODES| Flags::WITH_DEVICE_NODES |
WITH_FIFOS| Flags::WITH_FIFOS |
WITH_SOCKETS| Flags::WITH_SOCKETS |
WITH_FLAG_APPEND| Flags::WITH_FLAG_APPEND |
WITH_FLAG_NOATIME| Flags::WITH_FLAG_NOATIME |
WITH_FLAG_NODUMP| Flags::WITH_FLAG_NODUMP |
WITH_FLAG_IMMUTABLE| Flags::WITH_FLAG_IMMUTABLE |
WITH_FLAG_SYNC| Flags::WITH_FLAG_SYNC |
WITH_XATTRS| Flags::WITH_XATTRS |
WITH_ACL| Flags::WITH_ACL |
WITH_SELINUX| Flags::WITH_SELINUX |
WITH_FCAPS| Flags::WITH_FCAPS |
WITH_QUOTA_PROJID Flags::WITH_QUOTA_PROJID
}, },
ZFS_SUPER_MAGIC => { ZFS_SUPER_MAGIC => {
WITH_2SEC_TIME| Flags::WITH_2SEC_TIME |
WITH_READ_ONLY| Flags::WITH_READ_ONLY |
WITH_PERMISSIONS| Flags::WITH_PERMISSIONS |
WITH_SYMLINKS| Flags::WITH_SYMLINKS |
WITH_DEVICE_NODES| Flags::WITH_DEVICE_NODES |
WITH_FIFOS| Flags::WITH_FIFOS |
WITH_SOCKETS| Flags::WITH_SOCKETS |
WITH_FLAG_APPEND| Flags::WITH_FLAG_APPEND |
WITH_FLAG_NOATIME| Flags::WITH_FLAG_NOATIME |
WITH_FLAG_NODUMP| Flags::WITH_FLAG_NODUMP |
WITH_FLAG_DIRSYNC| Flags::WITH_FLAG_DIRSYNC |
WITH_FLAG_IMMUTABLE| Flags::WITH_FLAG_IMMUTABLE |
WITH_FLAG_SYNC| Flags::WITH_FLAG_SYNC |
WITH_XATTRS| Flags::WITH_XATTRS |
WITH_ACL| Flags::WITH_ACL |
WITH_SELINUX| Flags::WITH_SELINUX |
WITH_FCAPS| Flags::WITH_FCAPS |
WITH_QUOTA_PROJID Flags::WITH_QUOTA_PROJID
}, },
BTRFS_SUPER_MAGIC => { BTRFS_SUPER_MAGIC => {
WITH_2SEC_TIME| Flags::WITH_2SEC_TIME |
WITH_READ_ONLY| Flags::WITH_READ_ONLY |
WITH_PERMISSIONS| Flags::WITH_PERMISSIONS |
WITH_SYMLINKS| Flags::WITH_SYMLINKS |
WITH_DEVICE_NODES| Flags::WITH_DEVICE_NODES |
WITH_FIFOS| Flags::WITH_FIFOS |
WITH_SOCKETS| Flags::WITH_SOCKETS |
WITH_FLAG_APPEND| Flags::WITH_FLAG_APPEND |
WITH_FLAG_NOATIME| Flags::WITH_FLAG_NOATIME |
WITH_FLAG_COMPR| Flags::WITH_FLAG_COMPR |
WITH_FLAG_NOCOW| Flags::WITH_FLAG_NOCOW |
WITH_FLAG_NODUMP| Flags::WITH_FLAG_NODUMP |
WITH_FLAG_DIRSYNC| Flags::WITH_FLAG_DIRSYNC |
WITH_FLAG_IMMUTABLE| Flags::WITH_FLAG_IMMUTABLE |
WITH_FLAG_SYNC| Flags::WITH_FLAG_SYNC |
WITH_FLAG_NOCOMP| Flags::WITH_FLAG_NOCOMP |
WITH_XATTRS| Flags::WITH_XATTRS |
WITH_ACL| Flags::WITH_ACL |
WITH_SELINUX| Flags::WITH_SELINUX |
WITH_SUBVOLUME| Flags::WITH_SUBVOLUME |
WITH_SUBVOLUME_RO| Flags::WITH_SUBVOLUME_RO |
WITH_FCAPS Flags::WITH_FCAPS
}, },
TMPFS_MAGIC => { TMPFS_MAGIC => {
WITH_2SEC_TIME| Flags::WITH_2SEC_TIME |
WITH_READ_ONLY| Flags::WITH_READ_ONLY |
WITH_PERMISSIONS| Flags::WITH_PERMISSIONS |
WITH_SYMLINKS| Flags::WITH_SYMLINKS |
WITH_DEVICE_NODES| Flags::WITH_DEVICE_NODES |
WITH_FIFOS| Flags::WITH_FIFOS |
WITH_SOCKETS| Flags::WITH_SOCKETS |
WITH_ACL| Flags::WITH_ACL |
WITH_SELINUX Flags::WITH_SELINUX
}, },
// FUSE mounts are special as the supported feature set // FUSE mounts are special as the supported feature set
// is not clear a priori. // is not clear a priori.
FUSE_SUPER_MAGIC => { FUSE_SUPER_MAGIC => {
WITH_FUSE Flags::WITH_FUSE
}, },
_ => { _ => {
WITH_2SEC_TIME| Flags::WITH_2SEC_TIME |
WITH_READ_ONLY| Flags::WITH_READ_ONLY |
WITH_PERMISSIONS| Flags::WITH_PERMISSIONS |
WITH_SYMLINKS| Flags::WITH_SYMLINKS |
WITH_DEVICE_NODES| Flags::WITH_DEVICE_NODES |
WITH_FIFOS| Flags::WITH_FIFOS |
WITH_SOCKETS Flags::WITH_SOCKETS
}, },
} }
}
} }

View File

@ -14,7 +14,7 @@ use proxmox::sys::error::SysError;
use proxmox::tools::fd::RawFdNum; use proxmox::tools::fd::RawFdNum;
use proxmox::{c_result, c_try}; use proxmox::{c_result, c_try};
use crate::pxar::flags; use crate::pxar::Flags;
use crate::pxar::tools::perms_from_metadata; use crate::pxar::tools::perms_from_metadata;
use crate::tools::{acl, fs, xattr}; use crate::tools::{acl, fs, xattr};
@ -22,10 +22,6 @@ use crate::tools::{acl, fs, xattr};
// utility functions // utility functions
// //
fn flags_contain(flags: u64, test_flag: u64) -> bool {
0 != (flags & test_flag)
}
fn allow_notsupp<E: SysError>(err: E) -> Result<(), E> { fn allow_notsupp<E: SysError>(err: E) -> Result<(), E> {
if err.is_errno(Errno::EOPNOTSUPP) { if err.is_errno(Errno::EOPNOTSUPP) {
Ok(()) Ok(())
@ -70,7 +66,7 @@ fn nsec_to_update_timespec(mtime_nsec: u64) -> [libc::timespec; 2] {
// //
pub fn apply_at( pub fn apply_at(
flags: u64, flags: Flags,
metadata: &Metadata, metadata: &Metadata,
parent: RawFd, parent: RawFd,
file_name: &CStr, file_name: &CStr,
@ -86,7 +82,7 @@ pub fn apply_at(
} }
pub fn apply_with_path<T: AsRef<Path>>( pub fn apply_with_path<T: AsRef<Path>>(
flags: u64, flags: Flags,
metadata: &Metadata, metadata: &Metadata,
fd: RawFd, fd: RawFd,
file_name: T, file_name: T,
@ -99,7 +95,7 @@ pub fn apply_with_path<T: AsRef<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 = CString::new(format!("/proc/self/fd/{}", fd)).unwrap();
let c_proc_path = c_proc_path.as_ptr(); 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( fn add_fcaps(
flags: u64, flags: Flags,
c_proc_path: *const libc::c_char, c_proc_path: *const libc::c_char,
metadata: &Metadata, metadata: &Metadata,
skip_xattrs: &mut bool, skip_xattrs: &mut bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
if *skip_xattrs || !flags_contain(flags, flags::WITH_FCAPS) { if *skip_xattrs || !flags.contains(Flags::WITH_FCAPS) {
return Ok(()); return Ok(());
} }
let fcaps = match metadata.fcaps.as_ref() { let fcaps = match metadata.fcaps.as_ref() {
@ -185,12 +181,12 @@ fn add_fcaps(
} }
fn apply_xattrs( fn apply_xattrs(
flags: u64, flags: Flags,
c_proc_path: *const libc::c_char, c_proc_path: *const libc::c_char,
metadata: &Metadata, metadata: &Metadata,
skip_xattrs: &mut bool, skip_xattrs: &mut bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
if *skip_xattrs || !flags_contain(flags, flags::WITH_XATTRS) { if *skip_xattrs || !flags.contains(Flags::WITH_XATTRS) {
return Ok(()); return Ok(());
} }
@ -221,11 +217,11 @@ fn apply_xattrs(
} }
fn apply_acls( fn apply_acls(
flags: u64, flags: Flags,
c_proc_path: *const libc::c_char, c_proc_path: *const libc::c_char,
metadata: &Metadata, metadata: &Metadata,
) -> Result<(), Error> { ) -> 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(()); return Ok(());
} }
@ -309,8 +305,8 @@ fn apply_acls(
Ok(()) Ok(())
} }
fn apply_quota_project_id(flags: u64, fd: RawFd, metadata: &Metadata) -> Result<(), Error> { fn apply_quota_project_id(flags: Flags, fd: RawFd, metadata: &Metadata) -> Result<(), Error> {
if !flags_contain(flags, flags::WITH_QUOTA_PROJID) { if !flags.contains(Flags::WITH_QUOTA_PROJID) {
return Ok(()); return Ok(());
} }

View File

@ -52,10 +52,12 @@ pub(crate) mod create;
pub(crate) mod dir_stack; pub(crate) mod dir_stack;
pub(crate) mod extract; pub(crate) mod extract;
pub(crate) mod metadata; pub(crate) mod metadata;
pub mod flags;
pub mod fuse; pub mod fuse;
pub(crate) mod tools; pub(crate) mod tools;
mod flags;
pub use flags::Flags;
pub use create::create_archive; pub use create::create_archive;
pub use extract::extract_archive; pub use extract::extract_archive;

View File

@ -29,7 +29,7 @@ fn run_test(dir_name: &str) -> Result<(), Error> {
dir, dir,
writer, writer,
Vec::new(), Vec::new(),
flags::DEFAULT, Flags::DEFAULT,
None, None,
false, false,
|_| Ok(()), |_| Ok(()),