pxar: cleanup: move feature flags to src/pxar/flags.rs and omit CA_FORMAT prefix on all of them

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
Christian Ebner 2019-08-02 15:19:33 +02:00 committed by Dietmar Maurer
parent 91451c4355
commit 47651f9530
11 changed files with 378 additions and 394 deletions

View File

@ -799,7 +799,7 @@ fn restore(
if let Some(target) = target {
let feature_flags = pxar::CA_FORMAT_DEFAULT;
let feature_flags = pxar::flags::DEFAULT;
let mut decoder = pxar::SequentialDecoder::new(&mut reader, feature_flags, |path| {
if verbose {
println!("{:?}", path);

View File

@ -44,7 +44,7 @@ fn dump_archive(
let archive = tools::required_string_param(&param, "archive")?;
let verbose = param["verbose"].as_bool().unwrap_or(false);
let feature_flags = pxar::CA_FORMAT_DEFAULT;
let feature_flags = pxar::flags::DEFAULT;
if archive == "-" {
let stdin = std::io::stdin();
@ -102,24 +102,24 @@ fn extract_archive(
let empty = Vec::new();
let arg_pattern = param["pattern"].as_array().unwrap_or(&empty);
let mut feature_flags = pxar::CA_FORMAT_DEFAULT;
let mut feature_flags = pxar::flags::DEFAULT;
if no_xattrs {
feature_flags ^= pxar::CA_FORMAT_WITH_XATTRS;
feature_flags ^= pxar::flags::WITH_XATTRS;
}
if no_fcaps {
feature_flags ^= pxar::CA_FORMAT_WITH_FCAPS;
feature_flags ^= pxar::flags::WITH_FCAPS;
}
if no_acls {
feature_flags ^= pxar::CA_FORMAT_WITH_ACL;
feature_flags ^= pxar::flags::WITH_ACL;
}
if no_device_nodes {
feature_flags ^= pxar::CA_FORMAT_WITH_DEVICE_NODES;
feature_flags ^= pxar::flags::WITH_DEVICE_NODES;
}
if no_fifos {
feature_flags ^= pxar::CA_FORMAT_WITH_FIFOS;
feature_flags ^= pxar::flags::WITH_FIFOS;
}
if no_sockets {
feature_flags ^= pxar::CA_FORMAT_WITH_SOCKETS;
feature_flags ^= pxar::flags::WITH_SOCKETS;
}
let mut pattern_list = Vec::new();
@ -188,24 +188,24 @@ fn create_archive(
.open(archive)?;
let mut writer = std::io::BufWriter::with_capacity(1024*1024, file);
let mut feature_flags = pxar::CA_FORMAT_DEFAULT;
let mut feature_flags = pxar::flags::DEFAULT;
if no_xattrs {
feature_flags ^= pxar::CA_FORMAT_WITH_XATTRS;
feature_flags ^= pxar::flags::WITH_XATTRS;
}
if no_fcaps {
feature_flags ^= pxar::CA_FORMAT_WITH_FCAPS;
feature_flags ^= pxar::flags::WITH_FCAPS;
}
if no_acls {
feature_flags ^= pxar::CA_FORMAT_WITH_ACL;
feature_flags ^= pxar::flags::WITH_ACL;
}
if no_device_nodes {
feature_flags ^= pxar::CA_FORMAT_WITH_DEVICE_NODES;
feature_flags ^= pxar::flags::WITH_DEVICE_NODES;
}
if no_fifos {
feature_flags ^= pxar::CA_FORMAT_WITH_FIFOS;
feature_flags ^= pxar::flags::WITH_FIFOS;
}
if no_sockets {
feature_flags ^= pxar::CA_FORMAT_WITH_SOCKETS;
feature_flags ^= pxar::flags::WITH_SOCKETS;
}
pxar::Encoder::encode(source, &mut dir, &mut writer, devices, verbose, false, feature_flags)?;

View File

@ -49,7 +49,7 @@ impl PxarBackupStream {
let child = thread::spawn(move|| {
let mut writer = unsafe { std::fs::File::from_raw_fd(tx) };
if let Err(err) = pxar::Encoder::encode(path, &mut dir, &mut writer, device_set, verbose, skip_lost_and_found, pxar::CA_FORMAT_DEFAULT) {
if let Err(err) = pxar::Encoder::encode(path, &mut dir, &mut writer, device_set, verbose, skip_lost_and_found, pxar::flags::DEFAULT) {
let mut error = error2.lock().unwrap();
*error = Some(err.to_string());
}

View File

@ -31,7 +31,7 @@ impl PxarDecodeWriter {
let child = thread::spawn(move|| {
let mut reader = unsafe { std::fs::File::from_raw_fd(rx) };
let mut decoder = pxar::SequentialDecoder::new(&mut reader, pxar::CA_FORMAT_DEFAULT, |path| {
let mut decoder = pxar::SequentialDecoder::new(&mut reader, pxar::flags::DEFAULT, |path| {
if verbose {
println!("{:?}", path);
}

View File

@ -50,6 +50,9 @@
mod binary_search_tree;
pub use binary_search_tree::*;
pub mod flags;
pub use flags::*;
mod format_definition;
pub use format_definition::*;

View File

@ -36,7 +36,7 @@ impl <'a, R: Read + Seek, F: Fn(&Path) -> Result<(), Error>> Decoder<'a, R, F> {
let root_end = reader.seek(SeekFrom::End(0))?;
Ok(Self {
inner: SequentialDecoder::new(reader, CA_FORMAT_DEFAULT, callback),
inner: SequentialDecoder::new(reader, super::flags::DEFAULT, callback),
root_start: 0,
root_end: root_end,
})

View File

@ -6,6 +6,7 @@ use failure::*;
use endian_trait::Endian;
use std::collections::{HashSet, HashMap};
use super::flags;
use super::format_definition::*;
use super::binary_search_tree::*;
use super::helper::*;
@ -110,7 +111,7 @@ impl <'a, W: Write> Encoder<'a, W> {
bail!("backup virtual file systems is disabled!");
}
let fs_feature_flags = feature_flags_from_magic(magic);
let fs_feature_flags = flags::feature_flags_from_magic(magic);
let mut me = Self {
base_path: path,
@ -217,7 +218,7 @@ impl <'a, W: Write> Encoder<'a, W> {
bail!("read_attr_fd failed for {:?} - {}", self.full_path(), err);
}
let flags = ca_feature_flags_from_chattr(attr as u32);
let flags = flags::feature_flags_from_chattr(attr as u32);
entry.flags = entry.flags | flags;
Ok(())
@ -240,7 +241,7 @@ impl <'a, W: Write> Encoder<'a, W> {
bail!("read_fat_attr_fd failed for {:?} - {}", self.full_path(), err);
}
let flags = ca_feature_flags_from_fat_attr(attr);
let flags = flags::feature_flags_from_fat_attr(attr);
entry.flags = entry.flags | flags;
Ok(())
@ -260,7 +261,7 @@ impl <'a, W: Write> Encoder<'a, W> {
let mut xattrs = Vec::new();
let mut fcaps = None;
let flags = CA_FORMAT_WITH_XATTRS | CA_FORMAT_WITH_FCAPS;
let flags = flags::WITH_XATTRS | flags::WITH_FCAPS;
if !self.has_some_features(flags) {
return Ok((xattrs, fcaps));
}
@ -292,13 +293,13 @@ impl <'a, W: Write> Encoder<'a, W> {
};
if xattr::is_security_capability(&name) {
if self.has_features(CA_FORMAT_WITH_FCAPS) {
if self.has_features(flags::WITH_FCAPS) {
// fcaps are stored in own format within the archive
fcaps = Some(CaFormatFCaps {
data: value,
});
}
} else if self.has_features(CA_FORMAT_WITH_XATTRS) {
} else if self.has_features(flags::WITH_XATTRS) {
xattrs.push(CaFormatXAttr {
name: name.to_vec(),
value: value,
@ -318,7 +319,7 @@ impl <'a, W: Write> Encoder<'a, W> {
default: None,
};
if !self.has_features(CA_FORMAT_WITH_ACL) {
if !self.has_features(flags::WITH_ACL) {
return Ok(ret);
}
if is_symlink(&stat) {
@ -427,7 +428,7 @@ impl <'a, W: Write> Encoder<'a, W> {
if !(is_directory(&stat) || is_reg_file(&stat)) {
return Ok(None);
}
if !self.has_features(CA_FORMAT_WITH_QUOTA_PROJID) {
if !self.has_features(flags::WITH_QUOTA_PROJID) {
return Ok(None);
}
@ -598,7 +599,7 @@ impl <'a, W: Write> Encoder<'a, W> {
// 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);
self.fs_feature_flags = 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)?;
@ -815,21 +816,21 @@ impl <'a, W: Write> Encoder<'a, W> {
Err(err) => bail!("readlink {:?} failed - {}", self.full_path(), err),
}
} else if is_block_dev(&stat) || is_char_dev(&stat) {
if self.has_features(CA_FORMAT_WITH_DEVICE_NODES) {
if self.has_features(flags::WITH_DEVICE_NODES) {
self.write_filename(&filename)?;
self.encode_device(&stat)?;
} else {
eprintln!("skip device node: {:?}", self.full_path());
}
} else if is_fifo(&stat) {
if self.has_features(CA_FORMAT_WITH_FIFOS) {
if self.has_features(flags::WITH_FIFOS) {
self.write_filename(&filename)?;
self.encode_special(&stat)?;
} else {
eprintln!("skip fifo: {:?}", self.full_path());
}
} else if is_socket(&stat) {
if self.has_features(CA_FORMAT_WITH_SOCKETS) {
if self.has_features(flags::WITH_SOCKETS) {
self.write_filename(&filename)?;
self.encode_special(&stat)?;
} else {

320
src/pxar/flags.rs Normal file
View File

@ -0,0 +1,320 @@
//! Feature flags for *pxar* allow to control what is stored/restored in/from the
//! archive.
//! Flags for known supported features for a given filesystem can be derived
//! from the superblocks magic number.
/// 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;
/// 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;
// 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 = 0x100000;
/// Linux file attribute `DIRSYNC`
pub const WITH_FLAG_DIRSYNC: u64 = 0x200000;
/// Linux file attribute `IMMUTABLE`
pub const WITH_FLAG_IMMUTABLE: u64 = 0x400000;
/// Linux file attribute `SYNC`
pub const WITH_FLAG_SYNC: u64 = 0x800000;
/// Linux file attribute `NOCOMP`
pub const WITH_FLAG_NOCOMP: u64 = 0x1000000;
/// Linux file attribute `PROJINHERIT`
pub const WITH_FLAG_PROJINHERIT: u64 = 0x2000000;
/// Preserve BTRFS subvolume flag
pub const WITH_SUBVOLUME: u64 = 0x4000000;
/// Preserve BTRFS read-only subvolume flag
pub const WITH_SUBVOLUME_RO: u64 = 0x8000000;
/// Preserve Extended Attribute metadata
pub const WITH_XATTRS: u64 = 0x10000000;
/// Preserve Access Control List metadata
pub const WITH_ACL: u64 = 0x20000000;
/// Preserve SELinux security context
pub const WITH_SELINUX: u64 = 0x40000000;
/// Preserve "security.capability" xattr
pub const WITH_FCAPS: u64 = 0x80000000;
/// Preserve XFS/ext4/ZFS project quota ID
pub const WITH_QUOTA_PROJID: u64 = 0x100000000;
/// Support ".pxarexclude" files
pub const EXCLUDE_FILE: u64 = 0x1000000000000000;
/// the purpose of this flag is still unclear
pub const SHA512_256: u64 = 0x2000000000000000;
/// Exclude submounts
pub const EXCLUDE_SUBMOUNTS: u64 = 0x4000000000000000;
/// Exclude entries with chattr flag NODUMP
pub const EXCLUDE_NODUMP: u64 = 0x8000000000000000;
/// 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 FAT file attributes
pub const WITH_FAT_ATTRS: u64 =
WITH_FLAG_HIDDEN|
WITH_FLAG_SYSTEM|
WITH_FLAG_ARCHIVE;
/// 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;
/// 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|
SHA512_256;
// form /usr/include/linux/fs.h
const FS_APPEND_FL: u32 = 0x00000020;
const FS_NOATIME_FL: u32 = 0x00000080;
const FS_COMPR_FL: u32 = 0x00000004;
const FS_NOCOW_FL: u32 = 0x00800000;
const FS_NODUMP_FL: u32 = 0x00000040;
const FS_DIRSYNC_FL: u32 = 0x00010000;
const FS_IMMUTABLE_FL: u32 = 0x00000010;
const FS_SYNC_FL: u32 = 0x00000008;
const FS_NOCOMP_FL: u32 = 0x00000400;
const FS_PROJINHERIT_FL: u32 = 0x20000000;
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 ),
];
pub fn feature_flags_from_chattr(attr: u32) -> u64 {
let mut flags = 0u64;
for (fe_flag, fs_flag) in &CHATTR_MAP {
if (attr & fs_flag) != 0 { flags = flags | fe_flag; }
}
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 ),
];
pub fn feature_flags_from_fat_attr(attr: u32) -> u64 {
let mut flags = 0u64;
for (fe_flag, fs_flag) in &FAT_ATTR_MAP {
if (attr & fs_flag) != 0 { flags = flags | fe_flag; }
}
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 crate::tools::fs::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
},
}
}

View File

@ -35,80 +35,6 @@ pub const CA_FORMAT_GOODBYE: u64 = 0xdfd35c5e8327c403;
pub const CA_FORMAT_GOODBYE_TAIL_MARKER: u64 = 0x57446fa533702943;
// Feature flags
pub const CA_FORMAT_WITH_SEC_TIME: u64 = 0x8;
pub const CA_FORMAT_WITH_USEC_TIME: u64 = 0x10;
pub const CA_FORMAT_WITH_NSEC_TIME: u64 = 0x20;
/// FAT-style 2s time granularity
pub const CA_FORMAT_WITH_2SEC_TIME: u64 = 0x40;
pub const CA_FORMAT_WITH_READ_ONLY: u64 = 0x80;
pub const CA_FORMAT_WITH_PERMISSIONS: u64 = 0x100;
/// include symbolik links
pub const CA_FORMAT_WITH_SYMLINKS: u64 = 0x200;
/// include device nodes
pub const CA_FORMAT_WITH_DEVICE_NODES: u64 = 0x400;
/// include FIFOs
pub const CA_FORMAT_WITH_FIFOS: u64 = 0x800;
/// include Sockets
pub const CA_FORMAT_WITH_SOCKETS: u64 = 0x1000;
/// DOS file flag `HIDDEN`
pub const CA_FORMAT_WITH_FLAG_HIDDEN: u64 = 0x2000;
/// DOS file flag `SYSTEM`
pub const CA_FORMAT_WITH_FLAG_SYSTEM: u64 = 0x4000;
/// DOS file flag `ARCHIVE`
pub const CA_FORMAT_WITH_FLAG_ARCHIVE: u64 = 0x8000;
// chattr() flags
/// Linux file attribute `APPEND`
pub const CA_FORMAT_WITH_FLAG_APPEND: u64 = 0x10000;
/// Linux file attribute `NOATIME`
pub const CA_FORMAT_WITH_FLAG_NOATIME: u64 = 0x20000;
/// Linux file attribute `COMPR`
pub const CA_FORMAT_WITH_FLAG_COMPR: u64 = 0x40000;
/// Linux file attribute `NOCOW`
pub const CA_FORMAT_WITH_FLAG_NOCOW: u64 = 0x80000;
/// Linux file attribute `NODUMP`
pub const CA_FORMAT_WITH_FLAG_NODUMP: u64 = 0x100000;
/// Linux file attribute `DIRSYNC`
pub const CA_FORMAT_WITH_FLAG_DIRSYNC: u64 = 0x200000;
/// Linux file attribute `IMMUTABLE`
pub const CA_FORMAT_WITH_FLAG_IMMUTABLE: u64 = 0x400000;
/// Linux file attribute `SYNC`
pub const CA_FORMAT_WITH_FLAG_SYNC: u64 = 0x800000;
/// Linux file attribute `NOCOMP`
pub const CA_FORMAT_WITH_FLAG_NOCOMP: u64 = 0x1000000;
/// Linux file attribute `PROJINHERIT`
pub const CA_FORMAT_WITH_FLAG_PROJINHERIT: u64 = 0x2000000;
// Include BTRFS subvolume flag
pub const CA_FORMAT_WITH_SUBVOLUME: u64 = 0x4000000;
// Include BTRFS read-only subvolume flag
pub const CA_FORMAT_WITH_SUBVOLUME_RO: u64 = 0x8000000;
/// Include Extended Attribute metadata
pub const CA_FORMAT_WITH_XATTRS: u64 = 0x10000000;
/// Include Access Control List metadata
pub const CA_FORMAT_WITH_ACL: u64 = 0x20000000;
/// Include SELinux security context
pub const CA_FORMAT_WITH_SELINUX: u64 = 0x40000000;
/// Include "security.capability" xattr
pub const CA_FORMAT_WITH_FCAPS: u64 = 0x80000000;
/// XFS/ext4 project quota ID
pub const CA_FORMAT_WITH_QUOTA_PROJID: u64 = 0x100000000;
/// Support ".caexclude" files
pub const CA_FORMAT_EXCLUDE_FILE: u64 = 0x1000000000000000;
/// the purpose of this flag is still unclear
pub const CA_FORMAT_SHA512_256: u64 = 0x2000000000000000;
/// Exclude submounts
pub const CA_FORMAT_EXCLUDE_SUBMOUNTS: u64 = 0x4000000000000000;
/// Exclude entries with chattr flag NODUMP
pub const CA_FORMAT_EXCLUDE_NODUMP: u64 = 0x8000000000000000;
#[derive(Debug)]
#[derive(Endian)]
#[repr(C)]
@ -329,270 +255,3 @@ pub fn check_ca_header<T>(head: &CaFormatHeader, htype: u64) -> Result<(), Error
Ok(())
}
// form /usr/include/linux/fs.h
const FS_APPEND_FL: u32 = 0x00000020;
const FS_NOATIME_FL: u32 = 0x00000080;
const FS_COMPR_FL: u32 = 0x00000004;
const FS_NOCOW_FL: u32 = 0x00800000;
const FS_NODUMP_FL: u32 = 0x00000040;
const FS_DIRSYNC_FL: u32 = 0x00010000;
const FS_IMMUTABLE_FL: u32 = 0x00000010;
const FS_SYNC_FL: u32 = 0x00000008;
const FS_NOCOMP_FL: u32 = 0x00000400;
const FS_PROJINHERIT_FL: u32 = 0x20000000;
static CHATTR_MAP: [(u64, u32); 10] = [
( CA_FORMAT_WITH_FLAG_APPEND, FS_APPEND_FL ),
( CA_FORMAT_WITH_FLAG_NOATIME, FS_NOATIME_FL ),
( CA_FORMAT_WITH_FLAG_COMPR, FS_COMPR_FL ),
( CA_FORMAT_WITH_FLAG_NOCOW, FS_NOCOW_FL ),
( CA_FORMAT_WITH_FLAG_NODUMP, FS_NODUMP_FL ),
( CA_FORMAT_WITH_FLAG_DIRSYNC, FS_DIRSYNC_FL ),
( CA_FORMAT_WITH_FLAG_IMMUTABLE, FS_IMMUTABLE_FL ),
( CA_FORMAT_WITH_FLAG_SYNC, FS_SYNC_FL ),
( CA_FORMAT_WITH_FLAG_NOCOMP, FS_NOCOMP_FL ),
( CA_FORMAT_WITH_FLAG_PROJINHERIT, FS_PROJINHERIT_FL ),
];
pub fn ca_feature_flags_from_chattr(attr: u32) -> u64 {
let mut flags = 0u64;
for (ca_flag, fs_flag) in &CHATTR_MAP {
if (attr & fs_flag) != 0 { flags = flags | ca_flag; }
}
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] = [
( CA_FORMAT_WITH_FLAG_HIDDEN, ATTR_HIDDEN ),
( CA_FORMAT_WITH_FLAG_SYSTEM, ATTR_SYS ),
( CA_FORMAT_WITH_FLAG_ARCHIVE, ATTR_ARCH ),
];
pub fn ca_feature_flags_from_fat_attr(attr: u32) -> u64 {
let mut flags = 0u64;
for (ca_flag, fs_flag) in &FAT_ATTR_MAP {
if (attr & fs_flag) != 0 { flags = flags | ca_flag; }
}
flags
}
/// 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_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_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 {
use crate::tools::fs::magic::*;
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_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_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
},
ZFS_SUPER_MAGIC => {
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
},
BTRFS_SUPER_MAGIC => {
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_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_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
},
}
}

View File

@ -5,6 +5,7 @@
use failure::*;
use endian_trait::Endian;
use super::flags;
use super::format_definition::*;
use super::exclude_pattern::*;
use super::dir_buffer::*;
@ -186,63 +187,63 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
loop {
match head.htype {
CA_FORMAT_XATTR => {
if self.has_features(CA_FORMAT_WITH_XATTRS) {
if self.has_features(flags::WITH_XATTRS) {
attr.xattrs.push(self.read_xattr(size)?);
} else {
self.skip_bytes(size)?;
}
},
CA_FORMAT_FCAPS => {
if self.has_features(CA_FORMAT_WITH_FCAPS) {
if self.has_features(flags::WITH_FCAPS) {
attr.fcaps = Some(self.read_fcaps(size)?);
} else {
self.skip_bytes(size)?;
}
},
CA_FORMAT_ACL_USER => {
if self.has_features(CA_FORMAT_WITH_ACL) {
if self.has_features(flags::WITH_ACL) {
attr.acl_user.push(self.read_item::<CaFormatACLUser>()?);
} else {
self.skip_bytes(size)?;
}
},
CA_FORMAT_ACL_GROUP => {
if self.has_features(CA_FORMAT_WITH_ACL) {
if self.has_features(flags::WITH_ACL) {
attr.acl_group.push(self.read_item::<CaFormatACLGroup>()?);
} else {
self.skip_bytes(size)?;
}
},
CA_FORMAT_ACL_GROUP_OBJ => {
if self.has_features(CA_FORMAT_WITH_ACL) {
if self.has_features(flags::WITH_ACL) {
attr.acl_group_obj = Some(self.read_item::<CaFormatACLGroupObj>()?);
} else {
self.skip_bytes(size)?;
}
},
CA_FORMAT_ACL_DEFAULT => {
if self.has_features(CA_FORMAT_WITH_ACL) {
if self.has_features(flags::WITH_ACL) {
attr.acl_default = Some(self.read_item::<CaFormatACLDefault>()?);
} else {
self.skip_bytes(size)?;
}
},
CA_FORMAT_ACL_DEFAULT_USER => {
if self.has_features(CA_FORMAT_WITH_ACL) {
if self.has_features(flags::WITH_ACL) {
attr.acl_default_user.push(self.read_item::<CaFormatACLUser>()?);
} else {
self.skip_bytes(size)?;
}
},
CA_FORMAT_ACL_DEFAULT_GROUP => {
if self.has_features(CA_FORMAT_WITH_ACL) {
if self.has_features(flags::WITH_ACL) {
attr.acl_default_group.push(self.read_item::<CaFormatACLGroup>()?);
} else {
self.skip_bytes(size)?;
}
},
CA_FORMAT_QUOTA_PROJID => {
if self.has_features(CA_FORMAT_WITH_QUOTA_PROJID) {
if self.has_features(flags::WITH_QUOTA_PROJID) {
attr.quota_projid = Some(self.read_item::<CaFormatQuotaProjID>()?);
} else {
self.skip_bytes(size)?;
@ -508,7 +509,7 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
entry: &CaFormatEntry,
filename: &OsStr
) -> Result<(), Error> {
if !self.has_features(CA_FORMAT_WITH_SOCKETS) {
if !self.has_features(flags::WITH_SOCKETS) {
return Ok(());
}
if let Some(fd) = parent_fd {
@ -527,7 +528,7 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
entry: &CaFormatEntry,
filename: &OsStr
) -> Result<(), Error> {
if !self.has_features(CA_FORMAT_WITH_FIFOS) {
if !self.has_features(flags::WITH_FIFOS) {
return Ok(());
}
if let Some(fd) = parent_fd {
@ -551,7 +552,7 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
bail!("got unknown header type inside device entry {:016x}", head.htype);
}
let device: CaFormatDevice = self.read_item()?;
if !self.has_features(CA_FORMAT_WITH_DEVICE_NODES) {
if !self.has_features(flags::WITH_DEVICE_NODES) {
return Ok(());
}
if let Some(fd) = parent_fd {
@ -932,55 +933,55 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
match header.htype {
CA_FORMAT_XATTR => {
let xattr = self.read_xattr((header.size - HEADER_SIZE) as usize)?;
if verbose && self.has_features(CA_FORMAT_WITH_XATTRS) {
if verbose && self.has_features(flags::WITH_XATTRS) {
println!("XAttr: {:?}", xattr);
}
},
CA_FORMAT_FCAPS => {
let fcaps = self.read_fcaps((header.size - HEADER_SIZE) as usize)?;
if verbose && self.has_features(CA_FORMAT_WITH_FCAPS) {
if verbose && self.has_features(flags::WITH_FCAPS) {
println!("FCaps: {:?}", fcaps);
}
},
CA_FORMAT_ACL_USER => {
let user = self.read_item::<CaFormatACLUser>()?;
if verbose && self.has_features(CA_FORMAT_WITH_ACL) {
if verbose && self.has_features(flags::WITH_ACL) {
println!("ACLUser: {:?}", user);
}
},
CA_FORMAT_ACL_GROUP => {
let group = self.read_item::<CaFormatACLGroup>()?;
if verbose && self.has_features(CA_FORMAT_WITH_ACL) {
if verbose && self.has_features(flags::WITH_ACL) {
println!("ACLGroup: {:?}", group);
}
},
CA_FORMAT_ACL_GROUP_OBJ => {
let group_obj = self.read_item::<CaFormatACLGroupObj>()?;
if verbose && self.has_features(CA_FORMAT_WITH_ACL) {
if verbose && self.has_features(flags::WITH_ACL) {
println!("ACLGroupObj: {:?}", group_obj);
}
},
CA_FORMAT_ACL_DEFAULT => {
let default = self.read_item::<CaFormatACLDefault>()?;
if verbose && self.has_features(CA_FORMAT_WITH_ACL) {
if verbose && self.has_features(flags::WITH_ACL) {
println!("ACLDefault: {:?}", default);
}
},
CA_FORMAT_ACL_DEFAULT_USER => {
let default_user = self.read_item::<CaFormatACLUser>()?;
if verbose && self.has_features(CA_FORMAT_WITH_ACL) {
if verbose && self.has_features(flags::WITH_ACL) {
println!("ACLDefaultUser: {:?}", default_user);
}
},
CA_FORMAT_ACL_DEFAULT_GROUP => {
let default_group = self.read_item::<CaFormatACLGroup>()?;
if verbose && self.has_features(CA_FORMAT_WITH_ACL) {
if verbose && self.has_features(flags::WITH_ACL) {
println!("ACLDefaultGroup: {:?}", default_group);
}
},
CA_FORMAT_QUOTA_PROJID => {
let quota_projid = self.read_item::<CaFormatQuotaProjID>()?;
if verbose && self.has_features(CA_FORMAT_WITH_QUOTA_PROJID) {
if verbose && self.has_features(flags::WITH_QUOTA_PROJID) {
println!("Quota project id: {:?}", quota_projid);
}
},

View File

@ -26,7 +26,7 @@ fn run_test(dir_name: &str) -> Result<(), Error> {
let path = std::path::PathBuf::from(dir_name);
Encoder::encode(path, &mut dir, &mut writer, None, false, false, CA_FORMAT_DEFAULT)?;
Encoder::encode(path, &mut dir, &mut writer, None, false, false, flags::DEFAULT)?;
Command::new("cmp")
.arg("--verbose")