fix: check dirs and hamtshards supported

this is probably being overly strict but at least there will not be any
misunderstandings.
This commit is contained in:
Joonas Koivunen 2020-06-17 12:19:25 +03:00
parent d589e90160
commit 1d50a5195c
3 changed files with 49 additions and 40 deletions

View File

@ -7,6 +7,16 @@ use std::fmt;
mod sharded_lookup;
pub use sharded_lookup::{Cache, LookupError, ShardError, ShardedLookup};
mod dir;
pub(crate) use dir::{check_directory_supported, UnexpectedDirectoryProperties};
pub(crate) fn check_hamtshard_supported(
mut flat: FlatUnixFs<'_>,
) -> Result<FlatUnixFs<'_>, ShardError> {
ShardedLookup::check_supported(&mut flat)?;
Ok(flat)
}
/// Resolves a single path segment on `dag-pb` or UnixFS directories (normal, sharded).
///
/// The third parameter can always be substituted with a None but when repeatedly resolving over
@ -30,20 +40,7 @@ pub fn resolve<'needle>(
return Ok(ShardedLookup::lookup_or_start(hamt, needle, cache)?)
}
Ok(flat) if flat.data.Type == UnixFsType::Directory => {
if flat.data.filesize.is_some()
|| !flat.data.blocksizes.is_empty()
|| flat.data.hashType.is_some()
|| flat.data.fanout.is_some()
{
return Err(ResolveError::UnexpectedDirProperties {
filesize: flat.data.filesize,
blocksizes: flat.data.blocksizes,
hash_type: flat.data.hashType,
fanout: flat.data.fanout,
});
}
flat.links
check_directory_supported(flat)?.links
}
Err(ParsingFailed::InvalidUnixFs(_, PBNode { Links: links, .. }))
| Err(ParsingFailed::NoData(PBNode { Links: links, .. })) => links,
@ -103,16 +100,7 @@ pub enum ResolveError {
UnexpectedType(UnexpectedNodeType),
/// A directory had unsupported properties. These are not encountered during walking sharded
/// directories.
UnexpectedDirProperties {
/// filesize is a property of Files
filesize: Option<u64>,
/// blocksizes is a property of Files
blocksizes: Vec<u64>,
/// hash_type is a property of HAMT Shards
hash_type: Option<u64>,
/// fanout is a property of HAMT shards
fanout: Option<u64>,
},
UnexpectedDirProperties(UnexpectedDirectoryProperties),
/// Failed to read the block as a dag-pb node. Failure to read an inner UnixFS node is ignored
/// and links of the outer dag-pb are processed.
Read(quick_protobuf::Error),
@ -120,23 +108,18 @@ pub enum ResolveError {
Lookup(LookupError),
}
impl From<UnexpectedDirectoryProperties> for ResolveError {
fn from(e: UnexpectedDirectoryProperties) -> Self {
ResolveError::UnexpectedDirProperties(e)
}
}
impl fmt::Display for ResolveError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
use ResolveError::*;
match self {
UnexpectedType(ut) => write!(
fmt,
"unexpected type for UnixFs: {:?}",
ut
),
UnexpectedDirProperties { filesize, blocksizes, hash_type, fanout } => write!(
fmt,
"unexpected directory properties: filesize={:?}, {} blocksizes, hash_type={:?}, fanout={:?}",
filesize,
blocksizes.len(),
hash_type,
fanout
),
UnexpectedType(ut) => write!(fmt, "unexpected type for UnixFs: {:?}", ut),
UnexpectedDirProperties(udp) => write!(fmt, "unexpected directory properties: {}", udp),
Read(e) => write!(fmt, "parsing failed: {}", e),
Lookup(e) => write!(fmt, "{}", e),
}

View File

@ -137,7 +137,7 @@ impl<'needle> ShardedLookup<'needle> {
/// Takes the validated object as mutable reference to move data out of it in case of error.
///
/// Returns an error if we don't support the properties on the HAMTShard-typed node
fn check_supported(hamt: &mut FlatUnixFs<'_>) -> Result<(), ShardError> {
pub(crate) fn check_supported(hamt: &mut FlatUnixFs<'_>) -> Result<(), ShardError> {
assert_eq!(hamt.data.Type, UnixFsType::HAMTShard);
if hamt.data.fanout != Some(256) || hamt.data.hashType != Some(34) {

View File

@ -1,10 +1,12 @@
#![allow(unused, dead_code)]
use crate::dir::{
check_directory_supported, check_hamtshard_supported, ShardError, UnexpectedDirectoryProperties,
};
use crate::file::visit::{Cache, FileVisit, IdleFileVisit};
use crate::file::{FileError, FileReadFailed};
use crate::pb::{FlatUnixFs, PBLink, PBNode, ParsingFailed, UnixFsType};
use crate::Metadata;
use crate::{InvalidCidInLink, UnexpectedNodeType};
use crate::{InvalidCidInLink, Metadata, UnexpectedNodeType};
use cid::Cid;
use either::Either;
use std::borrow::Cow;
@ -155,6 +157,8 @@ impl Walker {
match flat.data.Type {
UnixFsType::Directory => {
let flat = crate::dir::check_directory_supported(flat)?;
let (cid, name, depth) = self.next.expect("validated at start and this method");
match self.current.as_mut() {
Some(current) => current.as_directory(cid, &name, depth, metadata),
@ -196,6 +200,8 @@ impl Walker {
Ok(ContinuedWalk::Directory(Item::from(state)))
}
UnixFsType::HAMTShard => {
let flat = crate::dir::check_hamtshard_supported(flat)?;
// TODO: the first hamtshard must have metadata!
let (cid, name, depth) = self.next.expect("validated at start and this method");
@ -736,6 +742,12 @@ pub enum Error {
/// A file has invalid structure
File(FileError),
/// Directory has unsupported structure
UnsupportedDirectory(UnexpectedDirectoryProperties),
/// HAMTSharded directory has unsupported properties
UnsupportedHAMTShard(ShardError),
}
impl From<ParsingFailed<'_>> for Error {
@ -767,6 +779,18 @@ impl From<FileReadFailed> for Error {
}
}
impl From<UnexpectedDirectoryProperties> for Error {
fn from(e: UnexpectedDirectoryProperties) -> Self {
Error::UnsupportedDirectory(e)
}
}
impl From<ShardError> for Error {
fn from(e: ShardError) -> Self {
Error::UnsupportedHAMTShard(e)
}
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
use Error::*;
@ -779,6 +803,8 @@ impl fmt::Display for Error {
EmptyDagPbNode => write!(fmt, "failed to parse the inner UnixFs: no data"),
InvalidCid(e) => write!(fmt, "link contained an invalid Cid: {}", e),
File(e) => write!(fmt, "invalid file: {}", e),
UnsupportedDirectory(udp) => write!(fmt, "unsupported directory: {}", udp),
UnsupportedHAMTShard(se) => write!(fmt, "unsupported hamtshard: {}", se),
}
}
}