Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClientFilestore: make dat optional #34

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,4 @@ features = ["serde-extensions", "virt"]
rustdoc-args = ["--cfg", "docsrs"]

[patch.crates-io]
littlefs2 = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "ebd27e49ca321089d01d8c9b169c4aeb58ceeeca" }
littlefs2 = { git = "https://github.com/sosthene-nitrokey/littlefs2.git", rev = "2b45a7559ff44260c6dd693e4cb61f54ae5efc53" }
2 changes: 1 addition & 1 deletion src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ pub mod request {
ReadDirFirst:
- location: Location
- dir: PathBuf
- not_before_filename: Option<PathBuf>
- not_before: Option<(PathBuf, bool)>

ReadDirNext:

Expand Down
25 changes: 24 additions & 1 deletion src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,9 @@ pub trait FilesystemClient: PollClient {
self.request(request::DebugDumpStore {})
}

/// Open a directory for iteration with `read_dir_next`
///
/// For optimization, not_before_filename can be passed to begin the iteration at that file.
fn read_dir_first(
&mut self,
location: Location,
Expand All @@ -607,7 +610,27 @@ pub trait FilesystemClient: PollClient {
self.request(request::ReadDirFirst {
location,
dir,
not_before_filename,
not_before: not_before_filename.map(|p| (p, true)),
})
}

/// Open a directory for iteration with `read_dir_next`
///
/// For optimization, not_before_filename can be passed to begin the iteration after the first file that is "alphabetically" before the original file
///
/// <div class="warning">
/// The notion used here for "alphabetical" does not correspond to the order of iteration yielded by littlefs. This function should be used with caution. If `not_before_filename` was yielded from a previous use of read_dir, it can lead to entries being repeated.
/// </div>
fn read_dir_first_alphabetical(
&mut self,
location: Location,
dir: PathBuf,
not_before_filename: Option<PathBuf>,
) -> ClientResult<'_, reply::ReadDirFirst, Self> {
self.request(request::ReadDirFirst {
location,
dir,
not_before: not_before_filename.map(|p| (p, false)),
})
}

Expand Down
10 changes: 9 additions & 1 deletion src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ impl<P: Platform> ServiceResources<P> {
ClientFilestore::new(client_id, self.platform.store())
}

/// Get access to the filestore for the client without the `dat` intermediary
pub fn raw_filestore(&mut self, client_id: PathBuf) -> ClientFilestore<P::S> {
ClientFilestore::new_raw(client_id, self.platform.store())
}

pub fn trussed_filestore(&mut self) -> ClientFilestore<P::S> {
ClientFilestore::new(PathBuf::from("trussed"), self.platform.store())
}
Expand Down Expand Up @@ -404,7 +409,10 @@ impl<P: Platform> ServiceResources<P> {
let maybe_entry = match filestore.read_dir_first(
&request.dir,
request.location,
request.not_before_filename.as_deref(),
request
.not_before
.as_ref()
.map(|(path, require_equal)| (&**path, *require_equal)),
)? {
Some((entry, read_dir_state)) => {
ctx.read_dir_state = Some(read_dir_state);
Expand Down
43 changes: 30 additions & 13 deletions src/store/filestore.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::cmp::Ordering;

use crate::{
error::{Error, Result},
// service::ReadDirState,
Expand Down Expand Up @@ -27,19 +29,29 @@ use littlefs2::{
path::{Path, PathBuf},
};

pub type ClientId = PathBuf;

pub struct ClientFilestore<S>
where
S: Store,
{
client_id: ClientId,
base: PathBuf,
store: S,
}

impl<S: Store> ClientFilestore<S> {
pub fn new(client_id: ClientId, store: S) -> Self {
Self { client_id, store }
/// Create a filestore that stores files in `<client_id>/dat/<file_path>`
pub fn new(client_id: PathBuf, store: S) -> Self {
let mut base = client_id;
base.push(path!("dat"));
Self { base, store }
}

/// Create a filestore that stores files in `<client_id>/<file_path>`
///
/// Unlike [`ClientFilestore::new`](), it does not have the `dat` intermediary.
/// It is meant to be used by custom backends to save space in case the `dat` folder is not used and only wastes a littlefs block.
pub fn new_raw(client_id: PathBuf, store: S) -> Self {
let base = client_id;
Self { base, store }
}

/// Client files are store below `/<client_id>/dat/`.
Expand All @@ -49,9 +61,7 @@ impl<S: Store> ClientFilestore<S> {
return Err(Error::InvalidPath);
}

let mut path = PathBuf::new();
path.push(&self.client_id);
path.push(path!("dat"));
let mut path = self.base.clone();
path.push(client_path);
Ok(path)
}
Expand Down Expand Up @@ -109,7 +119,7 @@ pub trait Filestore {
&mut self,
dir: &Path,
location: Location,
not_before: Option<&Path>,
not_before: Option<(&Path, bool)>,
) -> Result<Option<(DirEntry, ReadDirState)>>;

/// Continue iterating over entries of a directory.
Expand Down Expand Up @@ -145,7 +155,7 @@ impl<S: Store> ClientFilestore<S> {
&mut self,
clients_dir: &Path,
location: Location,
not_before: Option<&Path>,
not_before: Option<(&Path, bool)>,
) -> Result<Option<(DirEntry, ReadDirState)>> {
let fs = self.store.fs(location);
let dir = self.actual_path(clients_dir)?;
Expand All @@ -163,8 +173,15 @@ impl<S: Store> ClientFilestore<S> {
.map(|(i, entry)| (i, entry.unwrap()))
// if there is a "not_before" entry, skip all entries before it.
.find(|(_, entry)| {
if let Some(not_before) = not_before {
entry.file_name() == not_before.as_ref()
if let Some((not_before, require_equal)) = not_before {
if require_equal {
entry.file_name() == not_before
} else {
match entry.file_name().cmp_str(not_before) {
Ordering::Less => false,
Ordering::Equal | Ordering::Greater => true,
}
}
} else {
true
}
Expand Down Expand Up @@ -429,7 +446,7 @@ impl<S: Store> Filestore for ClientFilestore<S> {
&mut self,
clients_dir: &Path,
location: Location,
not_before: Option<&Path>,
not_before: Option<(&Path, bool)>,
) -> Result<Option<(DirEntry, ReadDirState)>> {
self.read_dir_first_impl(clients_dir, location, not_before)
}
Expand Down
Loading
Loading