Skip to content

feat: implement & test write#366

Open
Sl1mb0 wants to merge 1 commit intotm/open-atfrom
tm/posix-write
Open

feat: implement & test write#366
Sl1mb0 wants to merge 1 commit intotm/open-atfrom
tm/posix-write

Conversation

@Sl1mb0
Copy link
Contributor

@Sl1mb0 Sl1mb0 commented Feb 10, 2026

  • feat: implement write (3rd time's the charm)

@Sl1mb0 Sl1mb0 changed the base branch from main to tm/open-at February 10, 2026 22:38
@Sl1mb0 Sl1mb0 requested a review from Copilot February 11, 2026 01:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Implements write support for the in-memory VFS (VfsCtxView), replacing the previous ReadOnly trap and adding a suite of unit tests validating POSIX-like behaviors around writing.

Changes:

  • Implement HostDescriptor::write for regular files, including file extension, zero-fill gaps, and memory-limit enforcement via the limiter.
  • Add comprehensive unit tests for write covering success cases, offsets, EOF extension, directory errors, permission errors, and insufficient-memory behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

let node = Arc::clone(&desc.node);
let offset = offset as usize;
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

offset is a Filesize (WASI type) but is cast with offset as usize. On 32-bit hosts or when guests pass offsets > usize::MAX, this truncates and can write to the wrong location rather than returning an error. Please use a fallible conversion (usize::try_from(offset)) and trap with an appropriate error code when it doesn’t fit.

Suggested change
let offset = offset as usize;
let offset = usize::try_from(offset)
.map_err(|_| FsError::trap(ErrorCode::Overflow))?;

Copilot uses AI. Check for mistakes.
match &mut guard.kind {
VfsNodeKind::File { content } => {
let current_len = content.len();
let write_end = offset.saturating_add(buffer_len);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

write_end = offset.saturating_add(buffer_len) hides arithmetic overflow. If offset + buffer_len overflows usize, this will silently clamp to usize::MAX, potentially attempting an enormous Vec::resize or producing incorrect accounting. Prefer checked_add and return an error when the requested end offset can’t be represented.

Suggested change
let write_end = offset.saturating_add(buffer_len);
let write_end = offset
.checked_add(buffer_len)
.ok_or_else(|| FsError::trap(ErrorCode::InsufficientMemory))?;

Copilot uses AI. Check for mistakes.
Comment on lines +661 to +667
// Extend the file with zeros if writing past the current end
// Per POSIX: Writing past EOF extends the file
if offset > current_len {
content.resize(offset, 0);
}

// Ensure we have enough capacity for the write
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The file extension logic does two resizes (resize(offset, 0) and later resize(write_end, 0)). Since write_end is already known, this can be simplified to a single resize to write_end (which also zero-fills any gap) to reduce reallocations and keep the control flow simpler.

Suggested change
// Extend the file with zeros if writing past the current end
// Per POSIX: Writing past EOF extends the file
if offset > current_len {
content.resize(offset, 0);
}
// Ensure we have enough capacity for the write
// Extend the file with zeros if writing past the current end.
// A single resize to write_end is sufficient: Vec::resize zero-fills
// any newly allocated region, including any gap between the previous
// end-of-file and the write offset, matching POSIX semantics.

Copilot uses AI. Check for mistakes.
@Sl1mb0 Sl1mb0 force-pushed the tm/open-at branch 7 times, most recently from 2a96695 to 1f00b30 Compare February 12, 2026 12:29
@Sl1mb0 Sl1mb0 closed this Feb 15, 2026
@Sl1mb0 Sl1mb0 reopened this Feb 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant