pxar: Include symlink target in DirectoryEntry

This allows to read the target path of a symbolic link in the
Decoder::read_directory_entry() function and stores it in the DirectoryEntry.
By this the Decoder::read_link() function becomes obsolete and is therefore
removed.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
Christian Ebner 2020-01-17 11:21:44 +01:00 committed by Dietmar Maurer
parent 138910bcd4
commit a8aff3535d
2 changed files with 11 additions and 28 deletions

View File

@ -31,6 +31,8 @@ pub struct DirectoryEntry {
pub xattr: PxarAttributes, pub xattr: PxarAttributes,
/// Payload size /// Payload size
pub size: u64, pub size: u64,
/// Target path for symbolic links
pub target: Option<PathBuf>,
} }
/// Trait to create ReadSeek Decoder trait objects. /// Trait to create ReadSeek Decoder trait objects.
@ -78,6 +80,7 @@ impl Decoder {
entry, entry,
xattr, xattr,
size, size,
target: None,
}) })
} }
@ -135,6 +138,10 @@ impl Decoder {
PXAR_PAYLOAD => header.size - HEADER_SIZE, PXAR_PAYLOAD => header.size - HEADER_SIZE,
_ => 0, _ => 0,
}; };
let target = match header.htype {
PXAR_SYMLINK => Some(self.inner.read_link(header.size)?),
_ => None,
};
Ok(DirectoryEntry { Ok(DirectoryEntry {
start: entry_start, start: entry_start,
@ -143,6 +150,7 @@ impl Decoder {
entry, entry,
xattr, xattr,
size, size,
target,
}) })
} }
@ -370,26 +378,4 @@ impl Decoder {
Ok(data) Ok(data)
} }
/// Read the target of a hardlink in the archive.
pub fn read_link(&mut self, offset: u64) -> Result<(PathBuf, PxarEntry), Error> {
self.seek(SeekFrom::Start(offset))?;
let mut header: PxarHeader = self.inner.read_item()?;
if header.htype != PXAR_FILENAME {
bail!("Expected PXAR_FILENAME, encountered 0x{:x?}", header.htype);
}
let _filename = self.inner.read_filename(header.size)?;
header = self.inner.read_item()?;
check_ca_header::<PxarEntry>(&header, PXAR_ENTRY)?;
let entry: PxarEntry = self.inner.read_item()?;
header = self.inner.read_item()?;
if header.htype != PXAR_SYMLINK {
bail!("Expected PXAR_SYMLINK, encountered 0x{:x?}", header.htype);
}
let target = self.inner.read_link(header.size)?;
Ok((target, entry))
}
} }

View File

@ -7,7 +7,7 @@ use std::convert::TryFrom;
use std::ffi::{CStr, CString, OsStr}; use std::ffi::{CStr, CString, OsStr};
use std::fs::File; use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
use std::os::unix::ffi::{OsStrExt, OsStringExt}; use std::os::unix::ffi::OsStrExt;
use std::path::Path; use std::path::Path;
use std::sync::Mutex; use std::sync::Mutex;
@ -445,11 +445,8 @@ impl Session {
extern "C" fn readlink(req: Request, inode: u64) { extern "C" fn readlink(req: Request, inode: u64) {
Self::run_in_context(req, inode, |ctx| { Self::run_in_context(req, inode, |ctx| {
let (target, _) = ctx let target = ctx.entry.target.as_ref().ok_or_else(|| libc::EIO)?;
.decoder let link = CString::new(target.as_os_str().as_bytes()).map_err(|_| libc::EIO)?;
.read_link(ctx.ino_offset)
.map_err(|_| libc::EIO)?;
let link = CString::new(target.into_os_string().into_vec()).map_err(|_| libc::EIO)?;
let _ret = unsafe { fuse_reply_readlink(req, link.as_ptr()) }; let _ret = unsafe { fuse_reply_readlink(req, link.as_ptr()) };
Ok(()) Ok(())