Skip to content

Commit

Permalink
acl support added
Browse files Browse the repository at this point in the history
  • Loading branch information
ph0llux committed Nov 24, 2023
1 parent 7db94aa commit 83faad8
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 11 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ rand = "0.8.5"
base64 = "0.21.0"
time = { version = "0.3.21" }
itertools = "0.11"
posix-acl = "1.1.0"
redb = "1.0.5"
#encryption
pkcs5 = { version = "0.7.1", features = [ "pbes2", "alloc" ] }
rust-argon2 = "2.0"
Expand All @@ -47,7 +49,6 @@ sha3 = "0.10.8"
crc32fast = "1.3.2"
#signing
ed25519-dalek = { version = "2.0", features = [ "rand_core", "digest" ] }
redb = "1.0.5"
# optional deps for features
serde = { version = "1.0", features = ["derive"], optional = true }
log = { version = "0.4.6", optional = true }
Expand Down
6 changes: 5 additions & 1 deletion src/lib/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,8 @@ pub const PRELOADED_CHUNK_MAP_TABLE: TableDefinition<u64, u64> = TableDefinition

// - Encryption parameters
pub(crate) const SCRYPT_DERIVED_KEY_LENGTH_AES_128: usize = 16; // in bytes
pub(crate) const SCRYPT_DERIVED_KEY_LENGTH_AES_256: usize = 32; // in bytes
pub(crate) const SCRYPT_DERIVED_KEY_LENGTH_AES_256: usize = 32; // in bytes

// Unix ACLs
pub(crate) const ACL_PREFIX: &str = "acl";
pub(crate) const ACL_DEFAULT_PREFIX: &str = "acl::d";
69 changes: 67 additions & 2 deletions src/lib/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ use crate::{
ZffError,
ZffErrorKind,
ObjectEncoder,
CompressionAlgorithm
CompressionAlgorithm,
constants::*,
};

#[cfg(target_family = "unix")]
Expand All @@ -51,6 +52,9 @@ use crate::{
use time::{OffsetDateTime};
use crc32fast::{Hasher as CRC32Hasher};

#[cfg(target_family = "unix")]
use posix_acl::{PosixACL, Qualifier, ACLEntry};

// returns the buffer with the read bytes and the number of bytes which was read.
pub(crate) fn buffer_chunk<R>(
input: &mut R,
Expand Down Expand Up @@ -266,7 +270,11 @@ fn get_time_from_metadata(metadata: &Metadata) -> HashMap<&str, u64> {
timestamps
}

fn get_file_header(metadata: &Metadata, path: &Path, current_file_number: u64, parent_file_number: u64) -> Result<FileHeader> {
fn get_file_header(
metadata: &Metadata,
path: &Path,
current_file_number: u64,
parent_file_number: u64) -> Result<FileHeader> {
let filetype = if metadata.file_type().is_dir() {
FileType::Directory
} else if metadata.file_type().is_file() {
Expand All @@ -293,6 +301,22 @@ fn get_file_header(metadata: &Metadata, path: &Path, current_file_number: u64, p
Ok(file_header)
}

#[cfg(target_family = "unix")]
pub(crate) fn add_posix_acls_to_metadata_ext(metadata_ext_map: &mut HashMap<String, String>, acl: &PosixACL, default_acls: Option<&PosixACL>) {
for entry in acl.entries() {
if let Some((key, value)) = gen_acl_key_value(false, &entry) {
metadata_ext_map.insert(key, value);
}
};
if let Some(default_acls) = default_acls {
for entry in default_acls.entries() {
if let Some((key, value)) = gen_acl_key_value(false, &entry) {
metadata_ext_map.insert(key, value);
}
};
}
}

// returns ...
// ... None, if there is no other hardlink available to this file or if there is another hardlink available to this file, but this is the first of the hardlinked files, you've read.
// ... Some(filenumber), if there is another hardlink available and already was read.
Expand Down Expand Up @@ -328,4 +352,45 @@ pub(crate) fn check_same_byte(vec: &[u8]) -> bool {
} else {
true // Empty vector is considered to have the same byte on every position
}
}

#[cfg(target_family = "unix")]
fn gen_acl_key_value(default: bool, entry: &ACLEntry) -> Option<(String, String)> {
let key = match entry.qual {
Qualifier::User(uid) => gen_acl_key_uid(default, uid),
Qualifier::Group(gid) => gen_acl_key_gid(default, gid),
Qualifier::Mask => gen_acl_mask(default),
_ => return None, // ignoring UserObj, GroupObj and Other while this is always figured by the "mode" key
};
return Some((key, entry.perm.to_string()))
}

#[cfg(target_family = "unix")]
fn gen_acl_key_uid(default: bool, uid: u32) -> String {
let start = if default {
ACL_PREFIX
} else {
ACL_DEFAULT_PREFIX
};
format!("{start}:user:{uid}")
}

#[cfg(target_family = "unix")]
fn gen_acl_key_gid(default: bool, gid: u32) -> String {
let start = if default {
ACL_PREFIX
} else {
ACL_DEFAULT_PREFIX
};
format!("{start}:group:{gid}")
}

#[cfg(target_family = "unix")]
fn gen_acl_mask(default: bool) -> String {
let start = if default {
ACL_PREFIX
} else {
ACL_DEFAULT_PREFIX
};
format!("{start}:mask")
}
56 changes: 49 additions & 7 deletions src/lib/io/zffwriter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,13 @@ use super::{
ObjectEncoderInformation,
};
#[cfg(target_family = "unix")]
use super::{
add_to_hardlink_map,
};
use super::*;

// - external
use ed25519_dalek::{SigningKey};

#[cfg(feature = "log")]
use log::{error, warn, debug};
use log::{error, warn, debug, info};

/// Defines the output for a [ZffWriter].
/// This enum determine, that the [ZffWriter] will extend or build a new Zff container.
Expand Down Expand Up @@ -341,6 +339,10 @@ impl<R: Read> ZffWriter<R> {
chunk_number: u64,
object_encoder: &mut Vec<ObjectEncoderInformation<R>>) -> Result<()> {
for (logical_object_header, input_files) in logical_objects {
#[cfg(feature = "log")]
info!("Collecting files and folders for logical object {} using following paths: {:?}",
logical_object_header.object_number, input_files);

let lobj = Self::setup_logical_object(
logical_object_header,
input_files,
Expand Down Expand Up @@ -404,6 +406,15 @@ impl<R: Read> ZffWriter<R> {
Err(_) => continue,
};

// check acls on unix systems
#[cfg(target_family = "unix")]
if let Ok(acl) = PosixACL::read_acl(&path) {
add_posix_acls_to_metadata_ext(
&mut file_header.metadata_ext,
&acl,
PosixACL::read_default_acl(&path).ok().as_ref());
}

//test if file is readable and exists.
// allow unused variables if the cfg feature log is not set.
#[allow(unused_variables)]
Expand Down Expand Up @@ -461,6 +472,15 @@ impl<R: Read> ZffWriter<R> {
Ok(file_header) => file_header,
Err(_) => continue,
};
// check acls on unix systems
#[cfg(target_family = "unix")]
if let Ok(acl) = PosixACL::read_acl(&current_dir) {
add_posix_acls_to_metadata_ext(
&mut file_header.metadata_ext,
&acl,
PosixACL::read_default_acl(&current_dir).ok().as_ref());
}

file_header.metadata_ext.insert(METADATA_EXT_KEY_UNACCESSABLE_FILE.to_string(), current_dir.to_string_lossy().to_string());
files.push((current_dir.clone(), file_header));

Expand All @@ -477,10 +497,19 @@ impl<R: Read> ZffWriter<R> {
directory_children.get_mut(&dir_parent_file_number).unwrap().push(dir_current_file_number);
};
parent_file_number = dir_current_file_number;
let file_header = match get_file_header(&metadata, &current_dir, dir_current_file_number, dir_parent_file_number) {
let mut file_header = match get_file_header(&metadata, &current_dir, dir_current_file_number, dir_parent_file_number) {
Ok(file_header) => file_header,
Err(_) => continue,
};

#[cfg(target_family = "unix")]
if let Ok(acl) = PosixACL::read_acl(&current_dir) {
add_posix_acls_to_metadata_ext(
&mut file_header.metadata_ext,
&acl,
PosixACL::read_default_acl(&current_dir).ok().as_ref());
}

#[cfg(target_family = "unix")]
add_to_hardlink_map(&mut hardlink_map, &metadata, dir_current_file_number);
files.push((current_dir.clone(), file_header));
Expand Down Expand Up @@ -532,6 +561,14 @@ impl<R: Read> ZffWriter<R> {
Err(_) => continue,
};

#[cfg(target_family = "unix")]
if let Ok(acl) = PosixACL::read_acl(&path) {
add_posix_acls_to_metadata_ext(
&mut file_header.metadata_ext,
&acl,
PosixACL::read_default_acl(&path).ok().as_ref());
}

//test if file is readable and exists.
// allow unused variables if the cfg feature log is not set.
#[allow(unused_variables)]
Expand Down Expand Up @@ -645,8 +682,11 @@ impl<R: Read> ZffWriter<R> {

//write the object header
if !self.current_object_encoder.written_object_header {
self.object_header_segment_numbers.insert(self.current_object_encoder.obj_number(), self.current_segment_no);
segment_footer.add_object_header_offset(self.current_object_encoder.obj_number(), seek_value + written_bytes);
let object_number = self.current_object_encoder.obj_number();
self.object_header_segment_numbers.insert(object_number, self.current_segment_no);
segment_footer.add_object_header_offset(object_number, seek_value + written_bytes);
#[cfg(feature = "log")]
debug!("Writing object {object_number}");
written_bytes += output.write(&self.current_object_encoder.get_encoded_header())? as u64;
self.current_object_encoder.written_object_header = true;
};
Expand Down Expand Up @@ -837,6 +877,8 @@ impl<R: Read> ZffWriter<R> {
};
current_offset = match self.write_next_segment(&mut output_file, seek_value, &mut chunk_map, extend) {
Ok(written_bytes) => {
#[cfg(feature = "log")]
info!("Segment {} was written successfully.", segment_filename.display());
//adds the seek value to the written bytes
extend = false;
current_offset = seek_value + written_bytes;
Expand Down

0 comments on commit 83faad8

Please sign in to comment.