src/pxar/fuse.rs: impl getattr callback for fuse

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
Christian Ebner 2019-09-06 11:38:28 +02:00 committed by Dietmar Maurer
parent ec04ea81f2
commit d21ae955a6
1 changed files with 46 additions and 7 deletions

View File

@ -3,9 +3,10 @@
//! Allows to mount the archive as read-only filesystem to inspect its contents.
use std::ffi::{CString, OsStr};
use std::convert::TryFrom;
use std::fs::File;
use std::io::BufReader;
use std::os::unix::ffi::OsStrExt;
use std::io::{BufReader, Read, Seek};
use std::path::Path;
use std::sync::Mutex;
@ -14,7 +15,7 @@ use libc;
use libc::{c_char, c_int, c_void, size_t};
use super::decoder::Decoder;
use super::format_definition::PxarGoodbyeItem;
use super::format_definition::{PxarAttributes, PxarGoodbyeItem};
/// Node ID of the root i-node
///
@ -53,7 +54,7 @@ extern "C" {
fn fuse_session_loop(session: ConstPtr) -> c_int;
fn fuse_session_loop_mt_31(session: ConstPtr, clone_fd: c_int) -> c_int;
fn fuse_session_destroy(session: ConstPtr);
// fn fuse_reply_attr(req: Request, attr: *const libc::stat, timeout: f64) -> c_int;
fn fuse_reply_attr(req: Request, attr: Option<&libc::stat>, timeout: f64) -> c_int;
fn fuse_reply_err(req: Request, errno: c_int) -> c_int;
fn fuse_req_userdata(req: Request) -> MutPtr;
}
@ -314,11 +315,49 @@ extern "C" fn lookup(req: Request, parent: u64, _name: StrPtr) {
});
}
extern "C" fn getattr(req: Request, inode: u64, _fileinfo: MutPtr) {
run_in_context(req, inode, |_decoder, _ino_offset| {
// code goes here
/// Get attr and xattr from the decoder and update stat according to the fuse
/// implementation before returning
fn stat<R, F>(decoder: &mut Decoder<R, F>, offset: u64) -> Result<(libc::stat, PxarAttributes), i32>
where
R: Read + Seek,
F: Fn(&Path) -> Result<(), Error>,
{
let (entry, xattr, payload_size) = decoder.attributes(offset).map_err(|_| libc::EIO)?;
let inode = if offset == decoder.root_end_offset() - GOODBYE_ITEM_SIZE {
FUSE_ROOT_ID
} else {
offset
};
let nlink = match (entry.mode as u32) & libc::S_IFMT {
libc::S_IFDIR => 2,
_ => 1,
};
let time = i64::try_from(entry.mtime).map_err(|_| libc::EIO)? / 1_000_000_000;
Err(libc::ENOENT)
let mut attr: libc::stat = unsafe { std::mem::zeroed() };
attr.st_ino = inode;
attr.st_nlink = nlink;
attr.st_mode = u32::try_from(entry.mode).map_err(|_| libc::EIO)?;
attr.st_size = i64::try_from(payload_size).map_err(|_| libc::EIO)?;
attr.st_uid = entry.uid;
attr.st_gid = entry.gid;
attr.st_atime = time;
attr.st_mtime = time;
attr.st_ctime = time;
Ok((attr, xattr))
}
extern "C" fn getattr(req: Request, inode: u64, _fileinfo: MutPtr) {
run_in_context(req, inode, |mut decoder, ino_offset| {
let (attr, _) = stat(&mut decoder, ino_offset)?;
let _res = unsafe {
// Since fs is read-only, the timeout can be max.
let timeout = std::f64::MAX;
fuse_reply_attr(req, Some(&attr), timeout)
};
Ok(())
});
}