diff options
author | Ben Bridle <ben@derelict.engineering> | 2024-12-16 18:09:46 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2024-12-16 18:09:46 +1300 |
commit | 9612c307f00c4313d73fe0c3a86c05c8d8cd514e (patch) | |
tree | d6a37206f6e8d0ce48c0c311398cf2f7b14dccc8 | |
parent | 3533aced8b3fc4d6c1ec22c35f805ae966d8a7cb (diff) | |
download | bedrock-nds-9612c307f00c4313d73fe0c3a86c05c8d8cd514e.zip |
-rw-r--r-- | arm9/source/devices/file.c | 88 | ||||
-rw-r--r-- | arm9/source/devices/file.h | 2 |
2 files changed, 59 insertions, 31 deletions
diff --git a/arm9/source/devices/file.c b/arm9/source/devices/file.c index 1b10862..dcc987d 100644 --- a/arm9/source/devices/file.c +++ b/arm9/source/devices/file.c @@ -1,6 +1,7 @@ #include "nds.h" #include "fat.h" #include "file.h" +#include <sys/stat.h> static bool FS_ENABLE = false; static u8 buffer[255]; @@ -14,34 +15,10 @@ bool filesystem_enabled() { return FS_ENABLE; } -void fs_close(FileDevice *fs) { - fclose(fs->file); - fs->file = NULL; - closedir(fs->dir); - fs->dir = NULL; - fs->open = false; - fs->success = false; - fs->is_dir = false; - fs->child_is_dir = false; - pb_clear(&fs->path); - pb_clear(&fs->child_path); - fs->pointer = 0; - fs->length = 0; - fs->child = NULL; - fs->dir_i = 0; - fs->at_root = false; -} - -void fs_clear(FileDevice *fs) { - pb_clear(&fs->entry); - pb_clear(&fs->action); -} - -void fs_open_entry(FileDevice* fs, u8 *path) { - fs->success = false; +bool is_valid_path(u8 *path) { // Prevent non-absolute paths from being opened. if (path[0] != '/') { - return; + return false; } // Remove trailing slash if any, without removing leading slash. for (int i=2; i<255; i++) { @@ -58,18 +35,46 @@ void fs_open_entry(FileDevice* fs, u8 *path) { if (path[i+1]=='.') { // Check for '.' components. if (path[i+2]=='/' || path[i+2]==0) { - return; + return false; } // Check for '..' components. if (path[i+2]=='.' && (path[i+3]=='/' || path[i+3]==0)) { - return; + return false; } } } else if (path[i] == 0) { break; } } + return true; +} + +void fs_close(FileDevice *fs) { + fclose(fs->file); + fs->file = NULL; + closedir(fs->dir); + fs->dir = NULL; + fs->open = false; + fs->success = false; + fs->is_dir = false; + fs->child_is_dir = false; + pb_clear(&fs->path); + pb_clear(&fs->child_path); + fs->pointer = 0; + fs->length = 0; + fs->child = NULL; + fs->dir_i = 0; + fs->at_root = false; +} +void fs_clear(FileDevice *fs) { + pb_clear(&fs->entry); + pb_clear(&fs->action); +} + +void fs_open_entry(FileDevice* fs, u8 *path) { + fs->success = false; + if (!is_valid_path(path)) return; DIR *tmpdir = opendir((char*) path); if (tmpdir) { @@ -138,8 +143,11 @@ void fs_select_child(FileDevice *fs, u32 pointer) { void fs_push_entry(FileDevice *fs, u8 byte) { if (pb_push_byte(&fs->entry, byte)) { fs_close(fs); - if (pb_is_terminated(&fs->entry) && fs->entry.mem[0] != 0) { - fs_open_entry(fs, &fs->entry.mem[0]); + if (fs->entry.mem[0] != 0) { + fs->success = false; + if (pb_is_terminated(&fs->entry)) { + fs_open_entry(fs, fs->entry.mem); + } } fs_clear(fs); } @@ -147,15 +155,20 @@ void fs_push_entry(FileDevice *fs, u8 byte) { void fs_push_action(FileDevice *fs, u8 byte) { if (pb_push_byte(&fs->action, byte)) { - if (!pb_is_terminated(&fs->action)) return; + fs->success = false; bool action = fs->action.mem[0] != 0; if (fs->open) { if (action) { + if (!pb_is_terminated(&fs->action)) return; + if (!is_valid_path(fs->action.mem)) return; fs->success = rename((char*) fs->path.mem, (char*) fs->action.mem); } else { // TODO: DELETE } } else if (action) { + if (!pb_is_terminated(&fs->action)) return; + if (!is_valid_path(fs->action.mem)) return; + create_parents(fs->action.mem); FILE *tmpfile = fopen((char*) fs->action.mem, "w"); fs->success = tmpfile != NULL; fclose(tmpfile); @@ -165,6 +178,19 @@ void fs_push_action(FileDevice *fs, u8 byte) { } } +// Recursively create parent directories. +void create_parents(u8 *path) { + // Iterate over characters left-to-right. + for (u8 *p=path+1; *p; p++) { + if (*p == '/') { + *p = 0; + mkdir((char*) path, 0777); + *p = '/'; + } + } + return; +} + u8 fs_read_byte(FileDevice *fs) { return fgetc(fs->file); diff --git a/arm9/source/devices/file.h b/arm9/source/devices/file.h index efff684..f295e89 100644 --- a/arm9/source/devices/file.h +++ b/arm9/source/devices/file.h @@ -35,6 +35,8 @@ void init_filesystem(); bool filesystem_enabled(); + void create_parents(u8 *path); + void fs_push_entry(FileDevice *fs, u8 byte); void fs_push_action(FileDevice *fs, u8 byte); bool fs_push_byte(PathBuf *buf, u8 byte); |