diff --git a/src/catar/encoder.rs b/src/catar/encoder.rs index c1d4c078..447b323a 100644 --- a/src/catar/encoder.rs +++ b/src/catar/encoder.rs @@ -139,11 +139,37 @@ impl <'a, W: Write> CaTarEncoder<'a, W> { fn read_chattr(&self, fd: RawFd, entry: &mut CaFormatEntry) -> Result<(), Error> { - if let Some(fs_attr) = read_chattr(fd)? { - let flags = ca_feature_flags_from_chattr(fs_attr); - entry.flags = entry.flags | flags; + let mut attr: usize = 0; + + let res = unsafe { read_attr_fd(fd, &mut attr)}; + if let Err(err) = res { + if let nix::Error::Sys(errno) = err { + if errno_is_unsupported(errno) { return Ok(()) }; + } + bail!("read_attr_fd failed for {:?} - {}", self.current_path, err); } + let flags = ca_feature_flags_from_chattr(attr as u32); + entry.flags = entry.flags | flags; + + Ok(()) + } + + fn read_fat_attr(&self, fd: RawFd, entry: &mut CaFormatEntry) -> Result<(), Error> { + + let mut attr: u32 = 0; + + let res = unsafe { read_fat_attr_fd(fd, &mut attr)}; + if let Err(err) = res { + if let nix::Error::Sys(errno) = err { + if errno_is_unsupported(errno) { return Ok(()) }; + } + bail!("read_fat_attr_fd failed for {:?} - {}", self.current_path, err); + } + + let flags = ca_feature_flags_from_fat_attr(attr); + entry.flags = entry.flags | flags; + Ok(()) } @@ -207,6 +233,7 @@ impl <'a, W: Write> CaTarEncoder<'a, W> { let mut dir_entry = self.create_entry(&dir_stat)?; self.read_chattr(rawfd, &mut dir_entry)?; + self.read_fat_attr(rawfd, &mut dir_entry)?; self.write_entry(dir_entry)?; @@ -324,6 +351,7 @@ impl <'a, W: Write> CaTarEncoder<'a, W> { let mut entry = self.create_entry(&stat)?; self.read_chattr(filefd, &mut entry)?; + self.read_fat_attr(filefd, &mut entry)?; self.write_entry(entry)?; @@ -401,17 +429,6 @@ use nix::{convert_ioctl_res, request_code_read, ioc}; /// read Linux file system attributes (see man chattr) nix::ioctl_read!(read_attr_fd, b'f', 1, usize); -fn read_chattr(rawfd: RawFd) -> Result, Error> { - - let mut attr: usize = 0; - - let res = unsafe { read_attr_fd(rawfd, &mut attr)}; - if let Err(err) = res { - if let nix::Error::Sys(errno) = err { - if errno_is_unsupported(errno) { return Ok(None) }; - } - bail!("read_attr_fd failed - {}", err); - } - - Ok(Some(attr as u32)) -} +// /usr/include/linux/msdos_fs.h: #define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) +// read FAT file system attributes +nix::ioctl_read!(read_fat_attr_fd, b'r', 0x10, u32); diff --git a/src/catar/format_definition.rs b/src/catar/format_definition.rs index 6534510f..fb764c90 100644 --- a/src/catar/format_definition.rs +++ b/src/catar/format_definition.rs @@ -161,3 +161,27 @@ pub fn ca_feature_flags_from_chattr(attr: u32) -> u64 { 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 +}