Skip to content

Commit

Permalink
chunked: Add AppendFile syscall
Browse files Browse the repository at this point in the history
  • Loading branch information
robin-nitrokey committed Nov 23, 2023
1 parent a059198 commit 1d73418
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 2 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased][]

- Add `ManageExtension`: Factory reset the entire device or the state of a given client ([#11][])
- `ChunkedExtension`: Add `PartialReadFile` syscall.
- `ChunkedExtension`: Add `AppendFile` and `PartialReadFile` syscalls.

[#11]: https://github.com/trussed-dev/trussed-staging/pull/11

Expand Down
70 changes: 70 additions & 0 deletions src/streaming/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub enum ChunkedRequest {
WriteChunk(request::WriteChunk),
AbortChunkedWrite(request::AbortChunkedWrite),
PartialReadFile(request::PartialReadFile),
AppendFile(request::AppendFile),
}

#[derive(Debug, Deserialize, Serialize)]
Expand All @@ -102,6 +103,7 @@ pub enum ChunkedReply {
WriteChunk(reply::WriteChunk),
AbortChunkedWrite(reply::AbortChunkedWrite),
PartialReadFile(reply::PartialReadFile),
AppendFile(reply::AppendFile),
}

mod request {
Expand Down Expand Up @@ -292,6 +294,29 @@ mod request {
Self::PartialReadFile(request)
}
}

#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct AppendFile {
pub location: Location,
pub path: PathBuf,
pub data: Message,
}

impl TryFrom<ChunkedRequest> for AppendFile {
type Error = Error;
fn try_from(request: ChunkedRequest) -> Result<Self, Self::Error> {
match request {
ChunkedRequest::AppendFile(request) => Ok(request),
_ => Err(Error::InternalError),
}
}
}

impl From<AppendFile> for ChunkedRequest {
fn from(request: AppendFile) -> Self {
Self::AppendFile(request)
}
}
}

mod reply {
Expand Down Expand Up @@ -468,6 +493,27 @@ mod reply {
Self::PartialReadFile(reply)
}
}

#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct AppendFile {
pub file_length: usize,
}

impl TryFrom<ChunkedReply> for AppendFile {
type Error = Error;
fn try_from(reply: ChunkedReply) -> Result<Self, Self::Error> {
match reply {
ChunkedReply::AppendFile(reply) => Ok(reply),
_ => Err(Error::InternalError),
}
}
}

impl From<AppendFile> for ChunkedReply {
fn from(reply: AppendFile) -> Self {
Self::AppendFile(reply)
}
}
}

impl ExtensionImpl<ChunkedExtension> for super::StagingBackend {
Expand Down Expand Up @@ -562,6 +608,16 @@ impl ExtensionImpl<ChunkedExtension> for super::StagingBackend {
)?;
Ok(reply::PartialReadFile { data, file_length }.into())
}
ChunkedRequest::AppendFile(request) => {
let file_length = store::append_file(
store,
client_id,
&request.path,
request.location,
&request.data,
)?;
Ok(reply::AppendFile { file_length }.into())
}
#[cfg(feature = "encrypted-chunked")]
ChunkedRequest::StartEncryptedChunkedWrite(request) => {
clear_chunked_state(store, client_id, backend_ctx)?;
Expand Down Expand Up @@ -914,6 +970,20 @@ pub trait ChunkedClient: ExtensionClient<ChunkedExtension> + FilesystemClient {
length,
})
}

/// Append data to an existing file and return the size of the file after the write.
fn append_file(
&mut self,
location: Location,
path: PathBuf,
data: Message,
) -> ChunkedResult<'_, reply::AppendFile, Self> {
self.extension(request::AppendFile {
location,
path,
data,
})
}
}

impl<C: ExtensionClient<ChunkedExtension> + FilesystemClient> ChunkedClient for C {}
32 changes: 31 additions & 1 deletion src/streaming/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 or MIT

use littlefs2::driver::Storage as LfsStorage;
use littlefs2::fs::{File, Filesystem};
use littlefs2::fs::{File, Filesystem, OpenOptions};
use littlefs2::io::{SeekFrom, Write};

use trussed::config::MAX_MESSAGE_LENGTH;
Expand Down Expand Up @@ -310,3 +310,33 @@ pub fn partial_read_file(
data.truncate(length);
Ok((data, file_length))
}

fn fs_append_file<Storage: LfsStorage>(
fs: &Filesystem<Storage>,
path: &Path,
data: &[u8],
) -> Result<usize, Error> {
OpenOptions::new()
.write(true)
.append(true)
.open_and_then(fs, path, |file| {
file.write_all(data)?;
file.len()
})
.map_err(|_| Error::FilesystemWriteFailure)
}

pub fn append_file(
store: impl Store,
client_id: &Path,
path: &PathBuf,
location: Location,
data: &[u8],
) -> Result<usize, Error> {
let path = actual_path(client_id, path)?;
match location {
Location::Internal => fs_append_file(store.ifs(), &path, data),
Location::External => fs_append_file(store.efs(), &path, data),
Location::Volatile => fs_append_file(store.vfs(), &path, data),
}
}

0 comments on commit 1d73418

Please sign in to comment.