Skip to content
Open
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
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ jobs:
- name: Install iperf3
run: |
sudo apt install -y iperf3
- name: Install diod
run: |
sudo apt install -y diod
- uses: Swatinem/rust-cache@v2
- name: Cache custom out directories
uses: actions/cache@v5
Expand Down Expand Up @@ -90,6 +93,9 @@ jobs:
uses: taiki-e/install-action@v2
with:
tool: nextest@${{ env.NEXTEST_VERSION }}
- name: Install diod
run: |
sudo apt install -y diod
- name: Set up tun
run: |
sudo ./litebox_platform_linux_userland/scripts/tun-setup.sh
Expand Down
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.

3 changes: 3 additions & 0 deletions litebox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ enforce_singleton_litebox_instance = []

[lints]
workspace = true

[dev-dependencies]
tempfile = "3"
24 changes: 24 additions & 0 deletions litebox/src/fs/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub enum OpenError {
AlreadyExists,
#[error("error when truncating: {0}")]
TruncateError(#[from] TruncateError),
#[error("I/O error")]
Io,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we interpret Io error as network failure instead of the file or directory not exist?

#[error(transparent)]
PathError(#[from] PathError),
}
Expand All @@ -44,6 +46,8 @@ pub enum ReadError {
NotAFile,
#[error("file not open for reading")]
NotForReading,
#[error("I/O error")]
Io,
}

/// Possible errors from [`FileSystem::write`]
Expand All @@ -56,6 +60,8 @@ pub enum WriteError {
NotAFile,
#[error("file not open for writing")]
NotForWriting,
#[error("I/O error")]
Io,
}

/// Possible errors from [`FileSystem::seek`]
Expand All @@ -70,6 +76,8 @@ pub enum SeekError {
InvalidOffset,
#[error("non-seekable file")]
NonSeekable,
#[error("I/O error")]
Io,
}

/// Possible errors from [`FileSystem::truncate`]
Expand All @@ -83,6 +91,8 @@ pub enum TruncateError {
NotForWriting,
#[error("file descriptor points to a terminal device")]
IsTerminalDevice,
#[error("I/O error")]
Io,
}

/// Possible errors from [`FileSystem::chmod`]
Expand All @@ -96,6 +106,8 @@ pub enum ChmodError {
NotTheOwner,
#[error("the named file resides on a read-only filesystem")]
ReadOnlyFileSystem,
#[error("I/O error")]
Io,
#[error(transparent)]
PathError(#[from] PathError),
}
Expand All @@ -111,6 +123,8 @@ pub enum ChownError {
NotTheOwner,
#[error("the named file resides on a read-only filesystem")]
ReadOnlyFileSystem,
#[error("I/O error")]
Io,
#[error(transparent)]
PathError(#[from] PathError),
}
Expand All @@ -125,6 +139,8 @@ pub enum UnlinkError {
IsADirectory,
#[error("the named file resides on a read-only filesystem")]
ReadOnlyFileSystem,
#[error("I/O error")]
Io,
#[error(transparent)]
PathError(#[from] PathError),
}
Expand All @@ -139,6 +155,8 @@ pub enum MkdirError {
AlreadyExists,
#[error("the named file resides on a read-only filesystem")]
ReadOnlyFileSystem,
#[error("I/O error")]
Io,
#[error(transparent)]
PathError(#[from] PathError),
}
Expand All @@ -159,6 +177,8 @@ pub enum RmdirError {
NotADirectory,
#[error("the named file resides on a read-only filesystem")]
ReadOnlyFileSystem,
#[error("I/O error")]
Io,
#[error(transparent)]
PathError(#[from] PathError),
}
Expand All @@ -171,6 +191,8 @@ pub enum ReadDirError {
ClosedFd,
#[error("fd does not point to a directory")]
NotADirectory,
#[error("I/O error")]
Io,
}

/// Possible errors from [`FileSystem::file_status`]
Expand All @@ -179,6 +201,8 @@ pub enum ReadDirError {
pub enum FileStatusError {
#[error("fd has been closed already")]
ClosedFd,
#[error("I/O error")]
Io,
#[error(transparent)]
PathError(#[from] PathError),
}
Expand Down
23 changes: 22 additions & 1 deletion litebox/src/fs/layered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ impl<Platform: sync::RawSyncPrimitivesProvider, Upper: super::FileSystem, Lower:
match self.lower.file_status(path) {
Ok(stat) => Ok(stat.file_type),
Err(FileStatusError::ClosedFd) => unreachable!(),
Err(FileStatusError::Io) => Err(PathError::NoSuchFileOrDirectory),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Io is a pretty general erorr name. Why would it imply NoSuchFileOrDirectory?

Err(FileStatusError::PathError(e)) => Err(e),
}
}
Expand Down Expand Up @@ -132,6 +133,7 @@ impl<Platform: sync::RawSyncPrimitivesProvider, Upper: super::FileSystem, Lower:
// perfectly fine, just fallthrough to next place in the loop
}
MkdirError::ReadOnlyFileSystem
| MkdirError::Io
| MkdirError::NoWritePerms
| MkdirError::PathError(
PathError::ComponentNotADirectory
Expand Down Expand Up @@ -199,6 +201,7 @@ impl<Platform: sync::RawSyncPrimitivesProvider, Upper: super::FileSystem, Lower:
Ok(fd) => fd,
Err(e) => match e {
OpenError::AccessNotAllowed => return Err(MigrationError::NoReadPerms),
OpenError::Io => return Err(MigrationError::Io),
OpenError::NoWritePerms
| OpenError::ReadOnlyFileSystem
| OpenError::AlreadyExists
Expand Down Expand Up @@ -255,6 +258,7 @@ impl<Platform: sync::RawSyncPrimitivesProvider, Upper: super::FileSystem, Lower:
return Err(MigrationError::NotAFile);
}
ReadError::ClosedFd | ReadError::NotForReading => unreachable!(),
ReadError::Io => return Err(MigrationError::Io),
},
}
}
Expand Down Expand Up @@ -419,6 +423,8 @@ pub enum MigrationError {
NotAFile,
#[error("no read access permissions")]
NoReadPerms,
#[error("I/O error")]
Io,
#[error(transparent)]
PathError(#[from] PathError),
}
Expand Down Expand Up @@ -525,14 +531,16 @@ impl<
}
Err(e) => match &e {
OpenError::AccessNotAllowed
| OpenError::Io
| OpenError::NoWritePerms
| OpenError::ReadOnlyFileSystem
| OpenError::AlreadyExists
| OpenError::TruncateError(
TruncateError::IsDirectory
| TruncateError::NotForWriting
| TruncateError::IsTerminalDevice
| TruncateError::ClosedFd,
| TruncateError::ClosedFd
| TruncateError::Io,
)
| OpenError::PathError(
PathError::ComponentNotADirectory
Expand Down Expand Up @@ -816,6 +824,7 @@ impl<
Ok(()) => {}
Err(MigrationError::NoReadPerms) => unimplemented!(),
Err(MigrationError::NotAFile) => return Err(WriteError::NotAFile),
Err(MigrationError::Io) => return Err(WriteError::Io),
Err(MigrationError::PathError(_e)) => unreachable!(),
}
// As a sanity check, in debug mode, confirm that it is now an upper file
Expand Down Expand Up @@ -905,6 +914,7 @@ impl<

Ok(())
}
Err(TruncateError::Io) => Err(TruncateError::Io),
}
} else {
// The lower level truncate will correctly identify dir/file and handle
Expand All @@ -924,6 +934,7 @@ impl<
Ok(()) => return Ok(()),
Err(e) => match e {
ChmodError::NotTheOwner
| ChmodError::Io
| ChmodError::ReadOnlyFileSystem
| ChmodError::PathError(
PathError::ComponentNotADirectory
Expand All @@ -944,6 +955,7 @@ impl<
Ok(()) => {}
Err(MigrationError::NoReadPerms) => unimplemented!(),
Err(MigrationError::NotAFile) => unimplemented!(),
Err(MigrationError::Io) => return Err(ChmodError::Io),
Err(MigrationError::PathError(_e)) => unreachable!(),
}
// Since it has been migrated, we can just re-trigger, causing it to apply to the
Expand All @@ -962,6 +974,7 @@ impl<
Ok(()) => return Ok(()),
Err(e) => match e {
ChownError::NotTheOwner
| ChownError::Io
| ChownError::ReadOnlyFileSystem
| ChownError::PathError(
PathError::ComponentNotADirectory
Expand All @@ -982,6 +995,7 @@ impl<
Ok(()) => {}
Err(MigrationError::NoReadPerms) => unimplemented!(),
Err(MigrationError::NotAFile) => unimplemented!(),
Err(MigrationError::Io) => return Err(ChownError::Io),
Err(MigrationError::PathError(_e)) => unreachable!(),
}
// Since it has been migrated, we can just re-trigger, causing it to apply to the
Expand All @@ -1005,6 +1019,7 @@ impl<
}
Err(e) => match e {
UnlinkError::NoWritePerms
| UnlinkError::Io
| UnlinkError::IsADirectory
| UnlinkError::ReadOnlyFileSystem
| UnlinkError::PathError(
Expand Down Expand Up @@ -1054,6 +1069,7 @@ impl<
}
Err(e) => match e {
MkdirError::NoWritePerms
| MkdirError::Io
| MkdirError::AlreadyExists
| MkdirError::ReadOnlyFileSystem
| MkdirError::PathError(
Expand Down Expand Up @@ -1099,6 +1115,7 @@ impl<
}
OpenError::PathError(pe) => return Err(pe.into()),
OpenError::AccessNotAllowed => todo!(),
OpenError::Io => return Err(RmdirError::Io),
OpenError::ReadOnlyFileSystem => {
return Err(RmdirError::ReadOnlyFileSystem);
}
Expand All @@ -1112,6 +1129,7 @@ impl<
let entries = match self.read_dir(&dir_fd) {
Ok(entries) => entries,
Err(ReadDirError::ClosedFd | ReadDirError::NotADirectory) => unreachable!(),
Err(ReadDirError::Io) => return Err(RmdirError::Io),
};
self.close(&dir_fd).expect("close dir fd failed");
// "." and ".." are always present; anything more => not empty.
Expand All @@ -1135,6 +1153,7 @@ impl<
) => unreachable!(),
RmdirError::Busy
| RmdirError::NoWritePerms
| RmdirError::Io
| RmdirError::PathError(PathError::NoSearchPerms { .. }) => return Err(e),
}
}
Expand All @@ -1161,6 +1180,7 @@ impl<
) => unreachable!(),
RmdirError::Busy
| RmdirError::NoWritePerms
| RmdirError::Io
| RmdirError::PathError(PathError::NoSearchPerms { .. }) => return Err(e),
}
}
Expand Down Expand Up @@ -1278,6 +1298,7 @@ impl<
// None of these can be handled by lower level, just quit out early
return Err(e);
}
FileStatusError::Io => return Err(e),
FileStatusError::PathError(
PathError::NoSuchFileOrDirectory | PathError::MissingComponent,
) => {
Expand Down
Loading