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

refactor(virtualfs): implement overlayfs #137

Merged
merged 1 commit into from
Feb 14, 2025
Merged
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions virtualfs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ futures.workspace = true
chrono.workspace = true
getset.workspace = true
cfg-if.workspace = true
async-recursion.workspace = true
4 changes: 4 additions & 0 deletions virtualfs/lib/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ pub enum VfsError {
#[error("io error: {0}")]
Io(#[from] io::Error),

/// Overlay filesystem requires at least one layer
#[error("overlay filesystem requires at least one layer")]
OverlayFileSystemRequiresAtLeastOneLayer,

/// Custom error.
#[error(transparent)]
Custom(#[from] AnyError),
Expand Down
76 changes: 26 additions & 50 deletions virtualfs/lib/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub trait VirtualFileSystem {
/// * `Ok(true)` if the path exists
/// * `Ok(false)` if the path does not exist
/// * `Err` if the check operation fails
async fn exists(&self, path: impl AsRef<Path> + Send + Sync) -> VfsResult<bool>;
async fn exists(&self, path: &Path) -> VfsResult<bool>;

/// Creates a new empty file at the specified path.
///
Expand All @@ -45,12 +45,7 @@ pub trait VirtualFileSystem {
/// Returns an error if:
/// - The parent directory doesn't exist
/// - The file already exists and `exists_ok` is false
/// - Insufficient permissions
async fn create_file(
&self,
path: impl AsRef<Path> + Send + Sync,
exists_ok: bool,
) -> VfsResult<()>;
async fn create_file(&self, path: &Path, exists_ok: bool) -> VfsResult<()>;

/// Creates a new directory at the specified path.
///
Expand All @@ -63,8 +58,7 @@ pub trait VirtualFileSystem {
/// Returns an error if:
/// - The parent directory doesn't exist
/// - A file or directory already exists at the path
/// - Insufficient permissions
async fn create_directory(&self, path: impl AsRef<Path> + Send + Sync) -> VfsResult<()>;
async fn create_directory(&self, path: &Path) -> VfsResult<()>;

/// Creates a symbolic link at the specified path pointing to the target.
///
Expand All @@ -79,12 +73,7 @@ pub trait VirtualFileSystem {
/// - The parent directory doesn't exist
/// - A file or directory already exists at the path
/// - The target is invalid
/// - Insufficient permissions
async fn create_symlink(
&self,
path: impl AsRef<Path> + Send + Sync,
target: impl AsRef<Path> + Send + Sync,
) -> VfsResult<()>;
async fn create_symlink(&self, path: &Path, target: &Path) -> VfsResult<()>;

/// Reads data from a file starting at the specified offset.
///
Expand All @@ -103,10 +92,9 @@ pub trait VirtualFileSystem {
/// Returns an error if:
/// - The file doesn't exist
/// - The offset is beyond the end of the file
/// - Insufficient permissions
async fn read_file(
&self,
path: impl AsRef<Path> + Send + Sync,
path: &Path,
offset: u64,
length: u64,
) -> VfsResult<Pin<Box<dyn AsyncRead + Send + Sync + 'static>>>;
Expand All @@ -126,10 +114,9 @@ pub trait VirtualFileSystem {
/// Returns an error if:
/// - The path doesn't exist
/// - The path is not a directory
/// - Insufficient permissions
async fn read_directory(
&self,
path: impl AsRef<Path> + Send + Sync,
path: &Path,
) -> VfsResult<Box<dyn Iterator<Item = PathSegment> + Send + Sync + 'static>>;

/// Reads the target of a symbolic link.
Expand All @@ -141,7 +128,7 @@ pub trait VirtualFileSystem {
/// ## Returns
///
/// Returns the target path of the symlink.
async fn read_symlink(&self, path: impl AsRef<Path> + Send + Sync) -> VfsResult<PathBuf>;
async fn read_symlink(&self, path: &Path) -> VfsResult<PathBuf>;

/// Gets the metadata of a file or directory.
///
Expand All @@ -152,7 +139,21 @@ pub trait VirtualFileSystem {
/// ## Returns
///
/// Returns the metadata of the file or directory.
async fn get_metadata(&self, path: impl AsRef<Path> + Send + Sync) -> VfsResult<Metadata>;
async fn get_metadata(&self, path: &Path) -> VfsResult<Metadata>;

/// Sets the metadata of a file or directory.
///
/// ## Arguments
///
/// * `path` - The path of the file or directory to set metadata for
/// * `metadata` - The new metadata for the file or directory
///
/// ## Errors
///
/// Returns an error if:
/// - The path doesn't exist
/// - The path is not a file or directory
async fn set_metadata(&self, path: &Path, metadata: Metadata) -> VfsResult<()>;

/// Writes data to a file starting at the specified offset.
///
Expand All @@ -167,13 +168,11 @@ pub trait VirtualFileSystem {
/// Returns an error if:
/// - The file doesn't exist
/// - The offset is invalid
/// - Insufficient permissions
/// - The filesystem is read-only
async fn write_file(
&self,
path: impl AsRef<Path> + Send + Sync,
path: &Path,
offset: u64,
data: impl AsyncRead + Send + Sync + 'static,
data: Pin<Box<dyn AsyncRead + Send + Sync + 'static>>,
) -> VfsResult<()>;

/// Removes a file from the filesystem.
Expand All @@ -187,24 +186,7 @@ pub trait VirtualFileSystem {
/// Returns an error if:
/// - The path doesn't exist
/// - The path is a directory (use `remove_directory` instead)
/// - Insufficient permissions
/// - The filesystem is read-only
async fn remove(&self, path: impl AsRef<Path> + Send + Sync) -> VfsResult<()>;

/// Removes a directory and all its contents from the filesystem.
///
/// ## Arguments
///
/// * `path` - The path of the directory to remove
///
/// ## Errors
///
/// Returns an error if:
/// - The path doesn't exist
/// - The path is not a directory
/// - Insufficient permissions
/// - The filesystem is read-only
async fn remove_directory(&self, path: impl AsRef<Path> + Send + Sync) -> VfsResult<()>;
async fn remove(&self, path: &Path) -> VfsResult<()>;

/// Renames (moves) a file or directory to a new location.
///
Expand All @@ -219,11 +201,5 @@ pub trait VirtualFileSystem {
/// - The source path doesn't exist
/// - The destination path already exists
/// - The parent directory of the destination doesn't exist
/// - Insufficient permissions
/// - The filesystem is read-only
async fn rename(
&self,
old_path: impl AsRef<Path> + Send + Sync,
new_path: impl AsRef<Path> + Send + Sync,
) -> VfsResult<()>;
async fn rename(&self, old_path: &Path, new_path: &Path) -> VfsResult<()>;
}
Loading