Added ext2 subdirectory support (#6)
* updated ext2-test rule * added strtok * added ext2 subdirectory support * reverted partition numbers * simplified parsing * reworked parsing logic * reverted qloader2.cfg
diff --git a/src/fs/ext2fs.c b/src/fs/ext2fs.c
index 7fc58244..b703e922 100644
--- a/src/fs/ext2fs.c
+++ b/src/fs/ext2fs.c
@@ -200,32 +200,61 @@ static int ext2fs_get_inode(struct ext2fs_inode *ret, uint64_t drive, struct par
return 0;
}
-static int ext2fs_parse_dirent(struct ext2fs_dir_entry *dir, struct ext2fs_file_handle *fd, const char *filename) {
- uint64_t offset = fd->root_inode.i_blocks[0] * fd->block_size;
+static int ext2fs_parse_dirent(struct ext2fs_dir_entry *dir, struct ext2fs_file_handle *fd, struct ext2fs_superblock *sb, const char *path) {
+ int path_len = strlen(path);
- while (offset < fd->root_inode.i_size + offset) {
- // preliminary read
- read_partition(fd->drive, &fd->part, dir, offset, sizeof(struct ext2fs_dir_entry));
+ char *cpy = path;
- // name read
- char* name = balloc(dir->name_len);
- read_partition(fd->drive, &fd->part, name, offset + sizeof(struct ext2fs_dir_entry), dir->name_len);
+ if (*cpy = '/')
+ cpy++;
- int r = strncmp(filename, name, dir->name_len);
+ int token_count;
+ for (int i = 0; i < path_len; i++) {
+ if (cpy[i] == '/')
+ token_count++;
+ }
+
+ const char *delimiter = "/";
+ char *token;
+ struct ext2fs_inode *current = &fd->root_inode;
+
+ for (int i = 0; i < (token_count + 1); i++) {
+ token = strtok(cpy, delimiter);
+
+ uint64_t offset = current->i_blocks[0] * fd->block_size;
+
+ while (offset < current->i_size + offset) {
+ // preliminary read
+ read_partition(fd->drive, &fd->part, dir, offset, sizeof(struct ext2fs_dir_entry));
- brewind(dir->name_len);
+ // name read
+ char* name = balloc(dir->name_len);
+ read_partition(fd->drive, &fd->part, name, offset + sizeof(struct ext2fs_dir_entry), dir->name_len);
- if (!r) {
- return 0;
+ int r = strncmp(token, name, dir->name_len);
+
+ brewind(dir->name_len);
+
+ if (!r) {
+ if (i == token_count)
+ return 0;
+ else
+ break;
+ }
+
+ offset += dir->rec_len;
}
- offset += dir->rec_len;
+ cpy = NULL;
+
+ // update the current inode
+ ext2fs_get_inode(current, fd->drive, &fd->part, dir->inode, sb);
}
return 1;
}
-int ext2fs_open(struct ext2fs_file_handle *ret, int drive, int partition, const char* filename) {
+int ext2fs_open(struct ext2fs_file_handle *ret, int drive, int partition, const char *path) {
get_part(&ret->part, drive, partition);
ret->drive = drive;
@@ -238,14 +267,14 @@ int ext2fs_open(struct ext2fs_file_handle *ret, int drive, int partition, const
ext2fs_get_inode(&ret->root_inode, drive, &ret->part, 2, &sb);
struct ext2fs_dir_entry entry;
- ext2fs_parse_dirent(&entry, ret, filename);
+ ext2fs_parse_dirent(&entry, ret, &sb, path);
ext2fs_get_inode(&ret->inode, drive, &ret->part, entry.inode, &sb);
ret->size = ret->inode.i_size;
return 0;
}
-int ext2fs_read(struct ext2fs_file_handle *file, void* buf, uint64_t loc, uint64_t count) {
+int ext2fs_read(struct ext2fs_file_handle *file, void *buf, uint64_t loc, uint64_t count) {
// TODO: add support for the indirect block pointers
for (uint64_t progress = 0; progress < count;) {
diff --git a/src/fs/ext2fs.h b/src/fs/ext2fs.h
index 71fd291d..2faf8e30 100644
--- a/src/fs/ext2fs.h
+++ b/src/fs/ext2fs.h
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <stddef.h>
+#include <stdbool.h>
#include <drivers/disk.h>
#include <lib/libc.h>
#include <lib/blib.h>
@@ -61,7 +62,7 @@ struct ext2fs_file_handle {
int ext2fs_check_signature(int drive, int partition);
-int ext2fs_open(struct ext2fs_file_handle *ret, int drive, int partition, const char* filename);
-int ext2fs_read(struct ext2fs_file_handle *file, void* buf, uint64_t loc, uint64_t count);
+int ext2fs_open(struct ext2fs_file_handle *ret, int drive, int partition, const char *path);
+int ext2fs_read(struct ext2fs_file_handle *file, void *buf, uint64_t loc, uint64_t count);
#endif
diff --git a/src/lib/libc.c b/src/lib/libc.c
index 28674fca..f6ee8b32 100644
--- a/src/lib/libc.c
+++ b/src/lib/libc.c
@@ -111,3 +111,36 @@ size_t strlen(const char *str) {
return len;
}
+
+char *strtok(char *str, const char *delimiter) {
+ static char* buffer;
+
+ if (str != NULL) {
+ buffer = str;
+ }
+
+ if (buffer[0] == '\0') {
+ return NULL;
+ }
+
+ char* ret = buffer;
+
+ for (char* b = buffer; *b != '\0'; b++) {
+ for (const char* d = delimiter; *d != '\0'; d++) {
+ if(*b == *d) {
+ *b = '\0';
+ buffer = b + 1;
+
+ // Skip the beginning delimiters
+ if (b == ret) {
+ ret++;
+ continue;
+ }
+
+ return ret;
+ }
+ }
+ }
+
+ return ret;
+}
diff --git a/src/lib/libc.h b/src/lib/libc.h
index 9699f4ae..2035ac41 100644
--- a/src/lib/libc.h
+++ b/src/lib/libc.h
@@ -13,5 +13,6 @@ char *strncpy(char *, const char *, size_t);
size_t strlen(const char *);
int strcmp(const char *, const char *);
int strncmp(const char *, const char *, size_t);
+char *strtok(char *str, const char *delimiter);
#endif
