diff options
Diffstat (limited to 'src/write.rs')
-rw-r--r-- | src/write.rs | 261 |
1 files changed, 131 insertions, 130 deletions
diff --git a/src/write.rs b/src/write.rs index 2eb7984..fb15ed1 100644 --- a/src/write.rs +++ b/src/write.rs @@ -1,27 +1,27 @@ use std::cell::RefCell; use std::collections::{BTreeMap, HashMap}; -use std::ffi::{CStr, CString, OsStr, OsString}; +use std::ffi::{CString, OsString}; use std::io::Read; use std::path::{Path, PathBuf}; +use std::sync::{Mutex, RwLock}; use std::time::SystemTime; -use bindings::*; use super::*; use super::SquashfsError; -use thiserror::Error; use walkdir::{DirEntry, WalkDir}; -pub mod BlockFlags { - pub const DontCompress: u32 = super::SQFS_BLK_FLAGS_SQFS_BLK_DONT_COMPRESS; - pub const BlockAlign: u32 = super::SQFS_BLK_FLAGS_SQFS_BLK_ALIGN; - pub const DontFragment: u32 = super::SQFS_BLK_FLAGS_SQFS_BLK_DONT_FRAGMENT; - pub const DontDeduplicate: u32 = super::SQFS_BLK_FLAGS_SQFS_BLK_DONT_DEDUPLICATE; - pub const IgnoreSparse: u32 = super::SQFS_BLK_FLAGS_SQFS_BLK_IGNORE_SPARSE; - pub const DontHash: u32 = super::SQFS_BLK_FLAGS_SQFS_BLK_DONT_HASH; +#[repr(u32)] +pub enum BlockFlags { + DontCompress = super::SQFS_BLK_FLAGS_SQFS_BLK_DONT_COMPRESS, + BlockAlign = super::SQFS_BLK_FLAGS_SQFS_BLK_ALIGN, + DontFragment = super::SQFS_BLK_FLAGS_SQFS_BLK_DONT_FRAGMENT, + DontDeduplicate = super::SQFS_BLK_FLAGS_SQFS_BLK_DONT_DEDUPLICATE, + IgnoreSparse = super::SQFS_BLK_FLAGS_SQFS_BLK_IGNORE_SPARSE, + DontHash = super::SQFS_BLK_FLAGS_SQFS_BLK_DONT_HASH, } pub enum SourceData { - File(Box<dyn Read>), - Dir(Box<dyn Iterator<Item=(OsString, u32)>>), + File(Box<dyn Read + Sync + Send>), + Dir(Box<dyn Iterator<Item=(OsString, u32)> + Sync + Send>), Symlink(OsString), BlockDev(u32, u32), CharDev(u32, u32), @@ -41,18 +41,13 @@ pub struct Source { fn file_xattrs(path: &Path) -> Result<HashMap<OsString, Vec<u8>>> { xattr::list(path)?.map(|attr| { - match xattr::get(path, attr.clone()) { - Err(e) => panic!(), // TODO Panics - Ok(None) => panic!(), //Err(anyhow!("Couldn't retrieve xattr \"{:?}\" reported to be present", attr)), - Ok(Some(value)) => Ok((attr, value)) - } + let value = xattr::get(path, attr.clone()).map_err(|e| SquashfsError::Xattr(path.to_path_buf(), e))? + .expect(&format!("Could not retrieve xattr {:?} reported to be present", attr)); + Ok((attr, value)) }).collect() } fn copy_metadata(src: &ManagedPointer<sqfs_inode_generic_t>, dst: &mut ManagedPointer<sqfs_inode_generic_t>) -> Result<()> { - fn nlink_ref(inode: &ManagedPointer<sqfs_inode_generic_t>) -> Option<&u32> { - unimplemented!(); - } let (src_base, dst_base) = unsafe { (&(***src).base, &mut (***dst).base) }; dst_base.mode = src_base.mode; dst_base.uid_idx = src_base.uid_idx; @@ -77,63 +72,56 @@ impl Source { } // TODO Handle hard links - fn to_inode(&self, link_count: u32) -> Result<ManagedPointer<sqfs_inode_generic_t>> { - fn create_inode(kind: SQFS_INODE_TYPE, extra: usize) -> ManagedPointer<sqfs_inode_generic_t> { + unsafe fn to_inode(&self, link_count: u32) -> Result<ManagedPointer<sqfs_inode_generic_t>> { + unsafe fn create_inode(kind: SQFS_INODE_TYPE, extra: usize) -> ManagedPointer<sqfs_inode_generic_t> { use std::alloc::{alloc, Layout}; use std::mem::{align_of, size_of}; - unsafe { - let layout = Layout::from_size_align_unchecked(size_of::<sqfs_inode_generic_t>() + extra, align_of::<sqfs_inode_generic_t>()); - let ret = alloc(layout) as *mut sqfs_inode_generic_t; - (*ret).base.type_ = kind as u16; - ManagedPointer::new(ret, rust_dealloc) - } + let layout = Layout::from_size_align_unchecked(size_of::<sqfs_inode_generic_t>() + extra, align_of::<sqfs_inode_generic_t>()); + let ret = alloc(layout) as *mut sqfs_inode_generic_t; + (*ret).base.type_ = kind as u16; + ManagedPointer::new(ret, rust_dealloc) } - let ret = unsafe { - match &self.data { - SourceData::File(_) => { - let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_FILE, 0); - ret - }, - SourceData::Dir(_) => { - let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_DIR, 0); - (**ret).data.dir.nlink = link_count; - ret - }, - SourceData::Symlink(dest_os) => { - let dest = os_to_string(&dest_os)?.into_bytes(); - let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_SLINK, dest.len()); - let mut data = &mut (**ret).data.slink; - data.nlink = link_count; - data.target_size = dest.len() as u32; - let dest_field = std::mem::transmute::<_, &mut [u8]>((**ret).extra.as_mut_slice(dest.len())); - dest_field.copy_from_slice(dest.as_slice()); - ret - }, - SourceData::BlockDev(maj, min) => { - let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_BDEV, 0); - let mut data = &mut (**ret).data.dev; - data.nlink = link_count; - data.devno = Self::devno(*maj, *min); - ret - }, - SourceData::CharDev(maj, min) => { - let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_CDEV, 0); - let mut data = &mut (**ret).data.dev; - data.nlink = link_count; - data.devno = Self::devno(*maj, *min); - ret - }, - SourceData::Fifo => { - let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_FIFO, 0); - (**ret).data.ipc.nlink = link_count; - ret - }, - SourceData::Socket => { - let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_SOCKET, 0); - (**ret).data.ipc.nlink = link_count; - ret - }, - } + let ret = match &self.data { + SourceData::File(_) => create_inode(SQFS_INODE_TYPE_SQFS_INODE_FILE, 0), + SourceData::Dir(_) => { + let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_DIR, 0); + (**ret).data.dir.nlink = link_count; + ret + }, + SourceData::Symlink(dest_os) => { + let dest = os_to_string(&dest_os)?.into_bytes(); + let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_SLINK, dest.len()); + let mut data = &mut (**ret).data.slink; + data.nlink = link_count; + data.target_size = dest.len() as u32; + let dest_field = std::mem::transmute::<_, &mut [u8]>((**ret).extra.as_mut_slice(dest.len())); + dest_field.copy_from_slice(dest.as_slice()); + ret + }, + SourceData::BlockDev(maj, min) => { + let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_BDEV, 0); + let mut data = &mut (**ret).data.dev; + data.nlink = link_count; + data.devno = Self::devno(*maj, *min); + ret + }, + SourceData::CharDev(maj, min) => { + let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_CDEV, 0); + let mut data = &mut (**ret).data.dev; + data.nlink = link_count; + data.devno = Self::devno(*maj, *min); + ret + }, + SourceData::Fifo => { + let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_FIFO, 0); + (**ret).data.ipc.nlink = link_count; + ret + }, + SourceData::Socket => { + let mut ret = create_inode(SQFS_INODE_TYPE_SQFS_INODE_SOCKET, 0); + (**ret).data.ipc.nlink = link_count; + ret + }, }; Ok(ret) } @@ -141,7 +129,7 @@ impl Source { struct IntermediateNode { inode: Box<ManagedPointer<sqfs_inode_generic_t>>, - dir_children: Option<Box<dyn Iterator<Item=(OsString, u32)>>>, + dir_children: Option<Box<dyn Iterator<Item=(OsString, u32)> + Sync + Send>>, pos: u64, } @@ -152,25 +140,26 @@ pub struct SourceFile { pub struct Writer { outfile: ManagedPointer<sqfs_file_t>, - compressor_config: sqfs_compressor_config_t, + #[allow(dead_code)] compressor_config: sqfs_compressor_config_t, // Referenced by `compressor` compressor: ManagedPointer<sqfs_compressor_t>, superblock: sqfs_super_t, - block_writer: ManagedPointer<sqfs_block_writer_t>, - block_processor: ManagedPointer<sqfs_block_processor_t>, + #[allow(dead_code)] block_writer: ManagedPointer<sqfs_block_writer_t>, // Referenced by `block_processor` + block_processor: Mutex<ManagedPointer<sqfs_block_processor_t>>, frag_table: ManagedPointer<sqfs_frag_table_t>, - id_table: ManagedPointer<sqfs_id_table_t>, - xattr_writer: ManagedPointer<sqfs_xattr_writer_t>, + id_table: Mutex<ManagedPointer<sqfs_id_table_t>>, + xattr_writer: Mutex<ManagedPointer<sqfs_xattr_writer_t>>, inode_writer: ManagedPointer<sqfs_meta_writer_t>, dirent_writer: ManagedPointer<sqfs_meta_writer_t>, dir_writer: ManagedPointer<sqfs_dir_writer_t>, - nodes: Vec<RefCell<IntermediateNode>>, + nodes: Mutex<Vec<RefCell<IntermediateNode>>>, + finished: RwLock<bool>, } impl Writer { pub fn open<T: AsRef<Path>>(path: T) -> Result<Self> { let cpath = CString::new(os_to_string(path.as_ref().as_os_str())?)?; let block_size = SQFS_DEFAULT_BLOCK_SIZE as u64; - let num_workers = 4; // TODO Get from core count + let num_workers = num_cpus::get() as u32; let compressor_id = SQFS_COMPRESSOR_SQFS_COMP_ZSTD; let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_secs() as u32; let outfile = sfs_init_check_null(&|| unsafe { @@ -191,15 +180,15 @@ impl Writer { let block_writer = sfs_init_check_null(&|| unsafe { sqfs_block_writer_create(*outfile, 4096, 0) }, "Couldn't create block writer", sfs_destroy)?; - let block_processor = sfs_init_check_null(&|| unsafe { + let block_processor = Mutex::new(sfs_init_check_null(&|| unsafe { sqfs_block_processor_create(block_size, *compressor, num_workers, 10 * num_workers as u64, *block_writer, *frag_table) - }, "Couldn't create block processor", sfs_destroy)?; - let id_table = sfs_init_check_null(&|| unsafe { + }, "Couldn't create block processor", sfs_destroy)?); + let id_table = Mutex::new(sfs_init_check_null(&|| unsafe { sqfs_id_table_create(0) - }, "Couldn't create ID table", sfs_destroy)?; - let xattr_writer = sfs_init_check_null(&|| unsafe { + }, "Couldn't create ID table", sfs_destroy)?); + let xattr_writer = Mutex::new(sfs_init_check_null(&|| unsafe { sqfs_xattr_writer_create(0) - }, "Couldn't create xattr writer", sfs_destroy)?; + }, "Couldn't create xattr writer", sfs_destroy)?); let inode_writer = sfs_init_check_null(&|| unsafe { sqfs_meta_writer_create(*outfile, *compressor, 0) }, "Couldn't create inode metadata writer", sfs_destroy)?; @@ -226,7 +215,8 @@ impl Writer { inode_writer: inode_writer, dirent_writer: dirent_writer, dir_writer: dir_writer, - nodes: vec![], + nodes: Mutex::new(vec![]), + finished: RwLock::new(false), }) } @@ -257,64 +247,70 @@ impl Writer { unsafe { (**self.outfile).get_size.expect("Superblock doesn't provide get_size")(*self.outfile) } } - // TODO Minimize unsafe blocks pub fn add(&mut self, mut source: Source) -> Result<u32> { + let finished = self.finished.read().expect("Poisoned lock"); + if *finished { Err(SquashfsError::Finished)?; } let flags = source.flags; let nlink = 1; // TODO Handle hard links - let mut inode = match source.data { - SourceData::File(ref mut reader) => { - let mut ret = Box::new(ManagedPointer::null(libc_free)); - unsafe { - sfs_check(sqfs_block_processor_begin_file(*self.block_processor, &mut **ret, ptr::null_mut(), flags), "Couldn't begin writing file")?; + let mut inode = unsafe { + match source.data { + SourceData::File(ref mut reader) => { + let mut ret = Box::new(ManagedPointer::null(libc_free)); + let block_processor = self.block_processor.lock().expect("Poisoned lock"); + sfs_check(sqfs_block_processor_begin_file(**block_processor, &mut **ret, ptr::null_mut(), flags), "Couldn't begin writing file")?; let mut buf = vec![0; BLOCK_BUF_SIZE]; loop { let rdsize = reader.read(&mut buf)? as u64; if rdsize == 0 { break; } - sfs_check(sqfs_block_processor_append(*self.block_processor, &buf as &[u8] as *const [u8] as *const libc::c_void, rdsize), "Couldn't write file data block")?; + sfs_check(sqfs_block_processor_append(**block_processor, &buf as &[u8] as *const [u8] as *const libc::c_void, rdsize), "Couldn't write file data block")?; } - sfs_check(sqfs_block_processor_end_file(*self.block_processor), "Couldn't finish writing file")?; - } - ret - }, - _ => Box::new(source.to_inode(nlink)?), + sfs_check(sqfs_block_processor_end_file(**block_processor), "Couldn't finish writing file")?; + ret + }, + _ => Box::new(source.to_inode(nlink)?), + } }; unsafe { - sfs_check(sqfs_xattr_writer_begin(*self.xattr_writer, 0), "Couldn't start writing xattrs")?; + let xattr_writer = self.xattr_writer.lock().expect("Poisoned lock"); + sfs_check(sqfs_xattr_writer_begin(**xattr_writer, 0), "Couldn't start writing xattrs")?; for (key, value) in &source.xattrs { let ckey = CString::new(os_to_string(key)?)?; - sfs_check(sqfs_xattr_writer_add(*self.xattr_writer, ckey.as_ptr() as *const i8, value.as_ptr() as *const libc::c_void, value.len() as u64), "Couldn't add xattr")?; + sfs_check(sqfs_xattr_writer_add(**xattr_writer, ckey.as_ptr() as *const i8, value.as_ptr() as *const libc::c_void, value.len() as u64), "Couldn't add xattr")?; } - let xattr_idx = unsafe { sfs_init(&|x| sqfs_xattr_writer_end(*self.xattr_writer, x), "Couldn't finish writing xattrs")? }; + let xattr_idx = sfs_init(&|x| sqfs_xattr_writer_end(**xattr_writer, x), "Couldn't finish writing xattrs")?; let mut base = &mut (***inode).base; base.mode = source.mode; sqfs_inode_set_xattr_index(**inode, xattr_idx); - sfs_check(sqfs_id_table_id_to_index(*self.id_table, source.uid, &mut base.uid_idx), "Couldn't set inode UID")?; - sfs_check(sqfs_id_table_id_to_index(*self.id_table, source.gid, &mut base.gid_idx), "Couldn't set inode GID")?; + let id_table = self.id_table.lock().expect("Poisoned lock"); + sfs_check(sqfs_id_table_id_to_index(**id_table, source.uid, &mut base.uid_idx), "Couldn't set inode UID")?; + sfs_check(sqfs_id_table_id_to_index(**id_table, source.gid, &mut base.gid_idx), "Couldn't set inode GID")?; base.mod_time = source.modified; - base.inode_number = self.nodes.len() as u32 + 1; } let dir_children = match source.data { SourceData::Dir(children) => Some(children), _ => None, }; - self.nodes.push(RefCell::new(IntermediateNode { inode: inode, dir_children: dir_children, pos: 0 })); - Ok(self.nodes.len() as u32) + let mut nodes = self.nodes.lock().expect("Poisoned lock"); + unsafe { (***inode).base.inode_number = nodes.len() as u32 + 1; } + nodes.push(RefCell::new(IntermediateNode { inode: inode, dir_children: dir_children, pos: 0 })); + Ok(nodes.len() as u32) } pub fn finish(&mut self) -> Result<()> { + *self.finished.write().expect("Poisoned lock") = true; + let nodes = self.nodes.lock().expect("Poisoned lock"); unsafe { - sfs_check(sqfs_block_processor_finish(*self.block_processor), "Failed finishing block processing")?; + sfs_check(sqfs_block_processor_finish(**self.block_processor.lock().expect("Poisoned lock")), "Failed finishing block processing")?; self.superblock.inode_table_start = self.outfile_size(); - for raw_node in &self.nodes { + for raw_node in &*nodes { let mut node = raw_node.borrow_mut(); - // TODO Handle extended inodes properly let id = (***node.inode).base.inode_number; if let Some(children) = node.dir_children.take() { sfs_check(sqfs_dir_writer_begin(*self.dir_writer, 0), "Couldn't start writing directory")?; // For each child, need: name, ID, reference, mode - for (name, child_id) in children { // TODO Check that children are sorted + for (name, child_id) in children { // On disk children need to be sorted -- I think the library takes care of this if child_id >= id { Err(SquashfsError::WriteOrder(id, child_id))?; } - let child_node = &self.nodes[child_id as usize - 1].borrow(); + let child_node = &nodes[child_id as usize - 1].borrow(); let child = child_node.inode.as_ref(); let child_ref = child_node.pos; sfs_check(sqfs_dir_writer_add_entry(*self.dir_writer, CString::new(os_to_string(&name)?)?.as_ptr(), child_id, child_ref, Self::mode_from_inode(&child)), "Couldn't add directory entry")?; @@ -323,7 +319,7 @@ impl Writer { let mut ret = Box::new(sfs_init_check_null(&|| { sqfs_dir_writer_create_inode(*self.dir_writer, 0, 0, 0) // TODO Populate the parent inode number (how?) }, "Couldn't get inode for directory", libc_free)?); - copy_metadata(&*node.inode, &mut ret); + copy_metadata(&*node.inode, &mut ret)?; node.inode = ret; } let (mut block, mut offset) = (0, 0); @@ -332,46 +328,49 @@ impl Writer { sfs_check(sqfs_meta_writer_write_inode(*self.inode_writer, **node.inode), "Couldn't write inode")?; } - let root_ref = self.nodes.last().ok_or(SquashfsError::Empty)?.borrow().pos; + let root_ref = nodes.last().ok_or(SquashfsError::Empty)?.borrow().pos; self.superblock.root_inode_ref = root_ref; sfs_check(sqfs_meta_writer_flush(*self.inode_writer), "Couldn't flush inodes")?; sfs_check(sqfs_meta_writer_flush(*self.dirent_writer), "Couldn't flush directory entries")?; self.superblock.directory_table_start = self.outfile_size(); sfs_check(sqfs_meta_write_write_to_file(*self.dirent_writer), "Couldn't write directory entries")?; - self.superblock.inode_count = self.nodes.len() as u32; + self.superblock.inode_count = nodes.len() as u32; sfs_check(sqfs_frag_table_write(*self.frag_table, *self.outfile, &mut self.superblock, *self.compressor), "Couldn't write fragment table")?; - sfs_check(sqfs_dir_writer_write_export_table(*self.dir_writer, *self.outfile, *self.compressor, self.nodes.len() as u32, root_ref, &mut self.superblock), "Couldn't write export table")?; - sfs_check(sqfs_id_table_write(*self.id_table, *self.outfile, &mut self.superblock, *self.compressor), "Couldn't write ID table")?; - sfs_check(sqfs_xattr_writer_flush(*self.xattr_writer, *self.outfile, &mut self.superblock, *self.compressor), "Couldn't write xattr table")?; + sfs_check(sqfs_dir_writer_write_export_table(*self.dir_writer, *self.outfile, *self.compressor, nodes.len() as u32, root_ref, &mut self.superblock), "Couldn't write export table")?; + sfs_check(sqfs_id_table_write(**self.id_table.lock().expect("Poisoned lock"), *self.outfile, &mut self.superblock, *self.compressor), "Couldn't write ID table")?; + sfs_check(sqfs_xattr_writer_flush(**self.xattr_writer.lock().expect("Poisoned lock"), *self.outfile, &mut self.superblock, *self.compressor), "Couldn't write xattr table")?; self.superblock.bytes_used = self.outfile_size(); sfs_check(sqfs_super_write(&self.superblock, *self.outfile), "Couldn't rewrite archive superblock")?; let padding: Vec<u8> = vec![0; PAD_TO - self.outfile_size() as usize % PAD_TO]; - sfs_check((**self.outfile).write_at.expect("File does not provide write_at")(*self.outfile, self.outfile_size(), &padding as &[u8] as *const [u8] as *const libc::c_void, padding.len() as u64), "Couldn't pad file"); + sfs_check((**self.outfile).write_at.expect("File does not provide write_at")(*self.outfile, self.outfile_size(), &padding as &[u8] as *const [u8] as *const libc::c_void, padding.len() as u64), "Couldn't pad file")?; } Ok(()) } } +unsafe impl Sync for Writer { } +unsafe impl Send for Writer { } + pub struct TreeProcessor { root: PathBuf, - writer: RefCell<Writer>, - childmap: RefCell<HashMap<PathBuf, BTreeMap<OsString, u32>>>, + writer: Mutex<Writer>, + childmap: Mutex<HashMap<PathBuf, BTreeMap<OsString, u32>>>, } impl TreeProcessor { pub fn new<P: AsRef<Path>>(writer: Writer, root: P) -> Result<Self> { - Ok(Self { root: root.as_ref().to_path_buf(), writer: RefCell::new(writer), childmap: RefCell::new(HashMap::new()) }) + Ok(Self { root: root.as_ref().to_path_buf(), writer: Mutex::new(writer), childmap: Mutex::new(HashMap::new()) }) } pub fn add(&self, mut source: SourceFile) -> Result<u32> { - let mut childmap = self.childmap.borrow_mut(); + let mut childmap = self.childmap.lock().expect("Poisoned lock"); if let SourceData::Dir(children) = &mut source.content.data { // Pull in any last-minute additions made by the user let mut new_children = childmap.remove(&source.path).unwrap_or(BTreeMap::new()); new_children.extend(children); source.content.data = SourceData::Dir(Box::new(new_children.into_iter())); } - let id = self.writer.borrow_mut().add(source.content)?; + let id = self.writer.lock().expect("Poisoned lock").add(source.content)?; if let Some(parent) = source.path.parent() { childmap.entry(parent.to_path_buf()).or_insert(BTreeMap::new()).insert(source.path.file_name().expect("Path from walkdir has no file name").to_os_string(), id); } @@ -379,16 +378,14 @@ impl TreeProcessor { } pub fn finish(&self) -> Result<()> { - self.writer.borrow_mut().finish() + self.writer.lock().expect("Poisoned lock").finish() } fn make_source(&self, entry: DirEntry) -> Result<Source> { - // TODO Consider adding Unix-specific functionality with graceful degradation - // TODO Catch all errors except add() and continue let metadata = entry.metadata().unwrap(); let mtime = metadata.modified()?.duration_since(SystemTime::UNIX_EPOCH)?.as_secs() as u32; let data = if metadata.file_type().is_dir() { - SourceData::Dir(Box::new(self.childmap.borrow_mut().remove(&entry.path().to_path_buf()).unwrap_or(BTreeMap::new()).into_iter())) + SourceData::Dir(Box::new(self.childmap.lock().expect("Poisoned lock").remove(&entry.path().to_path_buf()).unwrap_or(BTreeMap::new()).into_iter())) } else if metadata.file_type().is_file() { SourceData::File(Box::new(std::fs::File::open(entry.path())?)) @@ -404,6 +401,10 @@ impl TreeProcessor { use std::os::linux::fs::MetadataExt; Source { data: data, xattrs: file_xattrs(entry.path())?, uid: metadata.st_uid(), gid: metadata.st_gid(), mode: (metadata.st_mode() & !S_IFMT) as u16, modified: mtime, flags: 0 } } + else if cfg!(unix) { + use std::os::unix::fs::MetadataExt; + Source { data: data, xattrs: HashMap::new(), uid: metadata.uid(), gid: metadata.gid(), mode: (metadata.mode() & 0x1ff) as u16, modified: mtime, flags: 0 } + } else { Source { data: data, xattrs: HashMap::new(), uid: 0, gid: 0, mode: 0x1ff, modified: mtime, flags: 0 } }; |