Skip to content

Implement core filesystem syscalls#90

Draft
apet2929 wants to merge 24 commits intomainfrom
feat/Write
Draft

Implement core filesystem syscalls#90
apet2929 wants to merge 24 commits intomainfrom
feat/Write

Conversation

@apet2929
Copy link
Copy Markdown
Collaborator

@apet2929 apet2929 commented Apr 6, 2026

Implements the following syscalls: sys_open, sys_close, sys_read, sys_write, and sys_stat for files and directories.
Creates a basic architecture to implement the syscalls.

Essentially, to accommodate the Unix "everything is a file" approach, we store a global array of structs containing information about different kinds of file descriptors- files, directories, tcp streams, and stdio for now. Because they may store different data, I created a union to represent each of their internal mappings and state. For example, for the File FD, I store its internal fd given to us by the switch, as well as a seek offset, since the switch doesn't handle that for us.

Comment thread packages/lib/include/megaton/__priv/nn/fs/fs_bcat.h Outdated
#include <megaton/__priv/nn/fs.h>


#define BOTWTOOLKIT_TCP_SEND2 // todo: replace with BOTWTOOLKIT_TCP_SEND (double check this)
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Using tcp to send debug information (for now). Probably need to have a discussion about debug logging and how we want to handle that for the library. Should we write to a debug file, now that we can? Should we log to tcp? Is there a particular format we want to use for debug info?

Comment thread packages/lib/include/megaton/fs.h Outdated
Comment thread packages/lib/include/megaton/fs.h Outdated
Comment thread packages/lib/src/fs.cpp Outdated
result = nn::fs::CreateFile(name, 0);
if(result.IsFailure()) {
botw::tcp::sendf("Library sys_open: nn::fs::CreateFile failed! Exit code=%d\n", result.GetInnerValueForDebug());
return -1;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Need to look like how to manifest these errors in rust
for example there should be some other sys call to get last error ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I didn't see any syscall like that, could be wrong. I agree we definitely should find out how to pass these errors to Rust. I'll make an issue for it.

Comment thread packages/lib/include/megaton/__priv/nn/fs/fs_bcat.h Outdated
Comment thread packages/lib/include/megaton/fs.h Outdated
Comment thread packages/lib/src/fs.cpp Outdated
Comment thread packages/lib/src/fs.cpp Outdated
}
}
botw::tcp::sendf("Unable to allocate FD - FDList is full!\n");
return 0;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

returning stdin in case of error seems like a bad idea

Comment thread packages/lib/src/fs.cpp Outdated
}

FileDescriptor insertIntoFDList(FD fd) {
for(FileDescriptor i = 3; i < NUM_FDS; i++) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not thread safe!
Also this is not very efficient, but it might be fine for now as we are prototyping. if we have time at the end this would need fixing

Comment thread packages/lib/src/fs.cpp

int32_t stat_dir(nn::fs::DirectoryHandle handle, const char* name, FileAttr* stat) {
nn::Result result;
// TODO: What values should these have?
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

look at the unix documentation for these values, there are some optional fields and it should tell you how to fill those

Comment thread packages/lib/src/fs.cpp Outdated

extern "C" isize sys_read(FileDescriptor fd, u8* buf, usize len) {
botw::tcp::sendf("Library: sys_read called! fd=%d len=%d\n", fd, len);
FD outerFD = FDList[fd];
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

needs bounds check / null check on untrusted parameters
(a good reason why writing this in Rust would be easier :p)

Comment thread packages/lib/src/fs.cpp
return 0;
}
case FileDescriptorType::DIR: {
nn::fs::DirectoryHandle dh = nn::fs::DirectoryHandle { outer_fd.get_internal_fd() };
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nn::fs::DirectoryHandle dh { outer_fd.get_internal_fd() };

Comment thread packages/lib/src/fs.cpp
result = nn::fs::DeleteFile(name);
if(result.IsFailure()){
botw::tcp::sendf("Library: sys_unlink: nn::fs::DeleteFile failed with %d!\n", result.GetInnerValueForDebug());
return -1;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

errno instead of -1

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.

4 participants