summaryrefslogtreecommitdiff
path: root/fs/ext2.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext2.c')
-rw-r--r--fs/ext2.c763
1 files changed, 0 insertions, 763 deletions
diff --git a/fs/ext2.c b/fs/ext2.c
deleted file mode 100644
index bd0fb07..0000000
--- a/fs/ext2.c
+++ /dev/null
@@ -1,763 +0,0 @@
-#include <assert.h>
-#include <fs/ext2.h>
-#include <fs/vfs.h>
-#include <stdint.h>
-#include <string.h>
-
-#define EXT2_SUPERBLOCK_SECTOR 2
-#define EXT2_ROOT_INODE 2
-
-#define BLOCKS_REQUIRED(_a, _b) ((_a) / (_b) + (((_a) % (_b)) != 0))
-
-superblock_t *superblock;
-uint32_t block_byte_size;
-uint32_t inode_size;
-uint32_t inodes_per_block;
-
-#define BLOCK_SIZE (block_byte_size)
-
-void ext2_close(vfs_fd_t *fd) {
- return; // There is nothing to clear
-}
-
-int read_inode(int inode_num, unsigned char *data, uint64_t size,
- uint64_t offset, uint64_t *file_size);
-
-struct BLOCK_CACHE {
- uint32_t block_num;
- uint8_t block[1024];
-};
-
-#define NUM_BLOCK_CACHE 30
-struct BLOCK_CACHE cache[NUM_BLOCK_CACHE] = {0};
-uint8_t last_taken_cache = 0;
-
-void cached_read_block(uint32_t block, void *address, size_t size,
- size_t offset) {
- int free_found = -1;
- for (int i = 0; i < NUM_BLOCK_CACHE; i++) {
- if (cache[i].block_num == block) {
- memcpy(address, cache[i].block + offset, size);
- return;
- }
- if (0 == cache[i].block_num)
- free_found = i;
- }
-
- if (-1 == free_found) {
- free_found = last_taken_cache;
- last_taken_cache++;
- if (last_taken_cache >= NUM_BLOCK_CACHE)
- last_taken_cache = 0;
- }
-
- struct BLOCK_CACHE *c = &cache[free_found];
- c->block_num = block;
- read_lba(block * block_byte_size / 512, c->block, 1024, 0);
- return cached_read_block(block, address, size, offset);
-}
-
-void ext2_read_block(uint32_t block, void *address, size_t size,
- size_t offset) {
- cached_read_block(block, address, size, offset);
-}
-
-void ext2_write_block(uint32_t block, void *address, size_t size,
- size_t offset) {
- // Invalidate a old cache
- for (int i = 0; i < NUM_BLOCK_CACHE; i++) {
- if (cache[i].block_num == block) {
- cache[i].block_num = 0;
- break;
- }
- }
- write_lba(block * block_byte_size / 512, address, size, offset);
-}
-
-void write_group_descriptor(uint32_t group_index, bgdt_t *block_group) {
- int starting_block = (1024 == block_byte_size) ? 2 : 1;
- ext2_write_block(starting_block, block_group, sizeof(bgdt_t),
- group_index * sizeof(bgdt_t));
-}
-
-void get_group_descriptor(uint32_t group_index, bgdt_t *block_group) {
- int starting_block = (1024 == block_byte_size) ? 2 : 1;
- ext2_read_block(starting_block, block_group, sizeof(bgdt_t),
- group_index * sizeof(bgdt_t));
-}
-
-uint32_t num_block_groups(void) {
- // Determining the Number of Block Groups
-
- // From the Superblock, extract the size of each block, the total
- // number of inodes, the total number of blocks, the number of blocks
- // per block group, and the number of inodes in each block group. From
- // this information we can infer the number of block groups there are
- // by:
-
- // Rounding up the total number of blocks divided by the number of
- // blocks per block group
- uint32_t num_blocks = superblock->num_blocks;
- uint32_t num_blocks_in_group = superblock->num_blocks_in_group;
- uint32_t b = num_blocks / num_blocks_in_group;
- if (num_blocks % num_blocks_in_group != 0)
- b++;
-
- // Rounding up the total number of inodes divided by the number of
- // inodes per block group
- uint32_t num_inodes = superblock->num_inodes;
- uint32_t num_inodes_in_group = superblock->num_inodes_in_group;
- uint32_t i = num_inodes / num_inodes_in_group;
- if (num_inodes % num_inodes_in_group != 0)
- i++;
- // Both (and check them against each other)
- assert(i == b);
- return i;
-}
-
-void ext2_block_containing_inode(uint32_t inode_index, uint32_t *block_index,
- uint32_t *offset) {
- assert(0 != inode_index);
- bgdt_t block_group;
- get_group_descriptor((inode_index - 1) / superblock->num_inodes_in_group,
- &block_group);
-
- uint64_t full_offset =
- ((inode_index - 1) % superblock->num_inodes_in_group) * inode_size;
- *block_index = block_group.starting_inode_table +
- (full_offset >> (superblock->block_size + 10));
- *offset = full_offset & (block_byte_size - 1);
-}
-
-int ext2_last_inode_read = -1;
-inode_t ext2_last_inode;
-
-void ext2_get_inode_header(int inode_index, inode_t *data) {
- // Very simple cache. If the inode_index is a inode already read then
- // just copy the old data.
- if (ext2_last_inode_read == inode_index) {
- memcpy(data, &ext2_last_inode, sizeof(inode_t));
- return;
- }
- uint32_t block_index;
- uint32_t block_offset;
- ext2_block_containing_inode(inode_index, &block_index, &block_offset);
-
- uint8_t mem_block[inode_size];
- ext2_read_block(block_index, mem_block, inode_size, block_offset);
-
- memcpy(data, mem_block, inode_size);
- memcpy(&ext2_last_inode, mem_block, sizeof(inode_t));
- ext2_last_inode_read = inode_index;
-}
-
-void ext2_write_inode(int inode_index, inode_t *data) {
- if (ext2_last_inode_read == inode_index)
- ext2_last_inode_read = -1; // Invalidate the cache
- uint32_t block_index;
- uint32_t block_offset;
- ext2_block_containing_inode(inode_index, &block_index, &block_offset);
-
- uint8_t mem_block[inode_size];
- memcpy(mem_block, data, inode_size);
- ext2_write_block(block_index, mem_block, inode_size, block_offset);
-}
-
-int ext2_get_inode_in_directory(int dir_inode, char *file,
- direntry_header_t *entry) {
- // FIXME: Allocate sufficent size each time
- unsigned char *data = kmalloc(block_byte_size * 5);
- ASSERT_BUT_FIXME_PROPOGATE(
- -1 != read_inode(dir_inode, data, block_byte_size * 5, 0, 0));
-
- direntry_header_t *dir;
- unsigned char *data_p = data;
- for (; (dir = (direntry_header_t *)data_p)->inode; data_p += dir->size) {
- if (0 == dir->size)
- break;
- if (0 == dir->name_length)
- continue;
- if (0 ==
- memcmp(data_p + sizeof(direntry_header_t), file, dir->name_length)) {
- if (strlen(file) > dir->name_length)
- continue;
- if (entry)
- memcpy(entry, data_p, sizeof(direntry_header_t));
- return dir->inode;
- }
- }
- return 0;
-}
-
-int ext2_read_dir(int dir_inode, unsigned char *buffer, size_t len,
- size_t offset) {
- unsigned char data[block_byte_size];
- read_inode(dir_inode, data, block_byte_size, 0, 0);
-
- direntry_header_t *dir;
- struct dirent tmp_entry;
- size_t n_dir = 0;
- int rc = 0;
- unsigned char *data_p = data;
- for (; (dir = (direntry_header_t *)data_p)->inode && len > 0;
- data_p += dir->size, n_dir++) {
- if (0 == dir->size)
- break;
- if (0 == dir->name_length)
- continue;
- if (n_dir < (offset / sizeof(struct dirent)))
- continue;
-
- memcpy(tmp_entry.d_name, data_p + sizeof(direntry_header_t),
- dir->name_length);
- tmp_entry.d_name[dir->name_length] = '\0';
- uint8_t *p = (uint8_t *)&tmp_entry;
- size_t l = sizeof(struct dirent);
-
- l = (len < l) ? len : l;
- memcpy(buffer, p, l);
- len -= l;
- rc += l;
- }
- return rc;
-}
-
-uint32_t ext2_find_inode(const char *file) {
- int cur_path_inode = EXT2_ROOT_INODE;
-
- if (*file == '/' && *(file + 1) == '\0')
- return cur_path_inode;
-
- char *str = copy_and_allocate_string(file);
- char *orig_str = str;
-
- char *start;
- for (;;) {
- int final = 0;
- start = str + 1;
- str++;
-
- for (; '/' != *str && '\0' != *str; str++)
- ;
- if ('\0' == *str)
- final = 1;
-
- *str = '\0';
-
- direntry_header_t a;
- if (0 == (cur_path_inode =
- ext2_get_inode_in_directory(cur_path_inode, start, &a))) {
- kfree(orig_str);
- return 0;
- }
-
- if (final)
- break;
-
- // The expected returned entry is a directory
- if (TYPE_INDICATOR_DIRECTORY != a.type_indicator) {
- kfree(orig_str);
- kprintf("FAILED\n");
- return 0;
- }
- }
- kfree(orig_str);
- return cur_path_inode;
-}
-
-uint32_t get_singly_block_index(uint32_t singly_block_ptr, uint32_t i) {
- uint8_t block[block_byte_size];
- ext2_read_block(singly_block_ptr, block, block_byte_size, 0);
- uint32_t index = *(uint32_t *)(block + (i * (32 / 8)));
- return index;
-}
-
-int get_block(inode_t *inode, uint32_t i) {
- if (i < 12)
- return inode->block_pointers[i];
-
- i -= 12;
- uint32_t singly_block_size = block_byte_size / (32 / 8);
- uint32_t double_block_size = (singly_block_size * singly_block_size);
- if (i < singly_block_size) {
- return get_singly_block_index(inode->single_indirect_block_pointer, i);
- } else if (i < double_block_size) {
- i -= singly_block_size;
- uint32_t singly_entry = get_singly_block_index(
- inode->double_indirect_block_pointer, i / singly_block_size);
- uint32_t offset_in_entry = i % singly_block_size;
- int block = get_singly_block_index(singly_entry, offset_in_entry);
- return block;
- }
- assert(0);
- return 0;
-}
-
-int get_free_block(int allocate) {
- bgdt_t block_group;
- uint8_t bitmap[BLOCK_SIZE];
- assert(0 < superblock->num_blocks_unallocated);
- for (uint32_t g = 0; g < num_block_groups(); g++) {
- get_group_descriptor(g, &block_group);
-
- if (block_group.num_unallocated_blocks_in_group == 0) {
- kprintf("skip\n");
- continue;
- }
-
- ext2_read_block(block_group.block_usage_bitmap, bitmap, BLOCK_SIZE, 0);
- for (uint32_t i = 0; i < superblock->num_blocks_in_group; i++) {
- if (!(bitmap[i >> 3] & (1 << (i % 8)))) {
- if (allocate) {
- bitmap[i >> 3] |= (1 << (i % 8));
- ext2_write_block(block_group.block_usage_bitmap, bitmap, BLOCK_SIZE,
- 0);
- block_group.num_unallocated_blocks_in_group--;
- write_group_descriptor(g, &block_group);
- superblock->num_blocks_unallocated--;
- write_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE,
- 0);
- }
- return i + g * superblock->num_blocks_in_group + 1;
- }
- }
- }
- return -1;
-}
-
-int get_free_inode(int allocate) {
- bgdt_t block_group;
- assert(0 < superblock->num_inodes_unallocated);
- for (uint32_t g = 0; g < num_block_groups(); g++) {
- get_group_descriptor(g, &block_group);
-
- if (0 == block_group.num_unallocated_inodes_in_group)
- continue;
-
- uint8_t bitmap[BLOCK_SIZE];
- ext2_read_block(block_group.inode_usage_bitmap, bitmap, BLOCK_SIZE, 0);
- for (uint32_t i = 0; i < superblock->num_inodes_in_group; i++) {
- if (!(bitmap[i / 8] & (1 << (i % 8)))) {
- if (allocate) {
- bitmap[i / 8] |= (1 << (i % 8));
- ext2_write_block(block_group.inode_usage_bitmap, bitmap, BLOCK_SIZE,
- 0);
- block_group.num_unallocated_inodes_in_group--;
- write_group_descriptor(g, &block_group);
- superblock->num_inodes_unallocated--;
- write_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE,
- 0);
- }
- return i + g * superblock->num_inodes_in_group + 1;
- }
- }
- }
- return -1;
-}
-
-int write_inode(int inode_num, unsigned char *data, uint64_t size,
- uint64_t offset, uint64_t *file_size, int append) {
- (void)file_size;
- uint8_t inode_buffer[inode_size];
- ext2_get_inode_header(inode_num, (inode_t *)inode_buffer);
- inode_t *inode = (inode_t *)inode_buffer;
-
- uint64_t fsize = (uint64_t)(((uint64_t)inode->_upper_32size << 32) |
- (uint64_t)inode->low_32size);
- if (append)
- offset = fsize;
-
- uint32_t block_start = offset / block_byte_size;
- uint32_t block_offset = offset % block_byte_size;
-
- int num_blocks_used = inode->num_disk_sectors / (BLOCK_SIZE / SECTOR_SIZE);
-
- if (size + offset > fsize)
- fsize = size + offset;
-
- int num_blocks_required = BLOCKS_REQUIRED(fsize, BLOCK_SIZE);
-
- for (int i = num_blocks_used; i < num_blocks_required; i++) {
- if (i > 12)
- assert(0);
- int b = get_free_block(1 /*true*/);
- assert(-1 != b);
- inode->block_pointers[i] = b;
- }
-
- inode->num_disk_sectors = num_blocks_required * (BLOCK_SIZE / SECTOR_SIZE);
-
- int bytes_written = 0;
- for (int i = block_start; size; i++) {
- uint32_t block = get_block(inode, i);
- if (0 == block) {
- kprintf("block_not_found\n");
- break;
- }
-
- int write_len = ((size + block_offset) > block_byte_size)
- ? (block_byte_size - block_offset)
- : size;
- ext2_write_block(block, data + bytes_written, write_len, block_offset);
- block_offset = 0;
- bytes_written += write_len;
- size -= write_len;
- }
- inode->low_32size = fsize;
- inode->_upper_32size = (fsize >> 32);
- ext2_write_inode(inode_num, inode);
- return bytes_written;
-}
-
-int read_inode(int inode_num, unsigned char *data, uint64_t size,
- uint64_t offset, uint64_t *file_size) {
- // TODO: Fail if size is lower than the size of the file being read, and
- // return the size of the file the callers is trying to read.
- uint8_t inode_buffer[inode_size];
- ext2_get_inode_header(inode_num, (inode_t *)inode_buffer);
- inode_t *inode = (inode_t *)inode_buffer;
-
- uint64_t fsize = (uint64_t)(((uint64_t)inode->_upper_32size << 32) |
- (uint64_t)inode->low_32size);
-
- if (file_size)
- *file_size = fsize;
-
- if (size > fsize - offset)
- size -= ((size + offset) - fsize);
-
- if (size == 0)
- return 0;
-
- if (offset > fsize)
- return 0;
-
- uint32_t block_start = offset / block_byte_size;
- uint32_t block_offset = offset % block_byte_size;
-
- int bytes_read = 0;
- for (int i = block_start; size; i++) {
- uint32_t block = get_block(inode, i);
- if (0 == block) {
- klog("Filesystem EXT2: Unable to find block", LOG_WARN);
- return -1;
- }
-
- int read_len = ((size + block_offset) > block_byte_size)
- ? (block_byte_size - block_offset)
- : size;
- ext2_read_block(block, data + bytes_read, read_len, block_offset);
- block_offset = 0;
- bytes_read += read_len;
- size -= read_len;
- }
- return bytes_read;
-}
-
-size_t ext2_read_file_offset(const char *file, unsigned char *data,
- uint64_t size, uint64_t offset,
- uint64_t *file_size) {
- // TODO: Fail if the file does not exist.
- uint32_t inode = ext2_find_inode(file);
- return read_inode(inode, data, size, offset, file_size);
-}
-
-size_t ext2_read_file(const char *file, unsigned char *data, size_t size,
- uint64_t *file_size) {
- return ext2_read_file_offset(file, data, size, 0, file_size);
-}
-
-int resolve_link(int inode_num) {
- uint8_t tmp[inode_size];
- inode_t *inode = (inode_t *)tmp;
- uint64_t inode_size =
- (((uint64_t)inode->_upper_32size) << 32) & inode->low_32size;
- assert(inode_size <= 60);
- ext2_get_inode_header(inode_num, inode);
- char *path = (char *)(tmp + (10 * 4));
- path--;
- *path = '/';
- return ext2_find_inode(path);
-}
-
-int ext2_write(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
- uint64_t file_size;
- int rc;
- int inode_num = fd->inode->inode_num;
- assert(fd->inode->type != FS_TYPE_DIRECTORY);
- if (fd->inode->type == FS_TYPE_LINK) {
- inode_num = resolve_link(inode_num);
- }
- rc = write_inode(inode_num, buffer, len, offset, &file_size, 0);
- return rc;
-}
-
-int ext2_read(uint8_t *buffer, uint64_t offset, uint64_t len, vfs_fd_t *fd) {
- uint64_t file_size;
- int rc;
- int inode_num = fd->inode->inode_num;
- if (fd->inode->type == FS_TYPE_DIRECTORY) {
- rc = ext2_read_dir(inode_num, buffer, len, offset);
- return rc;
- }
- if (fd->inode->type == FS_TYPE_LINK) {
- inode_num = resolve_link(inode_num);
- }
- rc = read_inode(inode_num, buffer, len, offset, &file_size);
- return rc;
-}
-
-int ext2_truncate(vfs_fd_t *fd, size_t length) {
- // TODO: Blocks that are no longer used should be freed.
- char inode_buffer[inode_size];
- inode_t *ext2_inode = (inode_t *)inode_buffer;
-
- ext2_get_inode_header(fd->inode->inode_num, ext2_inode);
-
- // FIXME: ftruncate should support 64 bit lengths
- ext2_inode->_upper_32size = 0;
- ext2_inode->low_32size = length;
-
- ext2_write_inode(fd->inode->inode_num, ext2_inode);
- return 0;
-}
-
-vfs_inode_t *ext2_open(const char *path) {
- uint32_t inode_num = ext2_find_inode(path);
- if (0 == inode_num)
- return NULL;
-
- inode_t ext2_inode[inode_size];
- ext2_get_inode_header(inode_num, ext2_inode);
- uint64_t file_size =
- ((uint64_t)(ext2_inode->_upper_32size) << 32) | ext2_inode->low_32size;
-
- uint8_t type;
- switch ((ext2_inode->types_permissions / 0x1000)) {
- case 0xA:
- type = FS_TYPE_LINK;
- break;
- case 0x4:
- type = FS_TYPE_DIRECTORY;
- break;
- default:
- type = FS_TYPE_FILE;
- break;
- }
-
- return vfs_create_inode(inode_num, type, 1 /*has_data*/, 1 /*can_write*/,
- 1 /*is_open*/, NULL /*internal_object*/, file_size,
- ext2_open, ext2_create_file, ext2_read, ext2_write,
- ext2_close, ext2_create_directory,
- NULL /*get_vm_object*/, ext2_truncate /*truncate*/);
-}
-
-uint64_t end_of_last_entry_position(int dir_inode, uint64_t *entry_offset,
- direntry_header_t *meta) {
- // FIXME: Allocate sufficent size each time
- unsigned char data[block_byte_size * 5];
- uint64_t file_size = 0;
- read_inode(dir_inode, data, block_byte_size * 5, 0, &file_size);
- assert(block_byte_size * 5 > file_size);
-
- direntry_header_t *dir;
- unsigned char *data_p = data;
- uint64_t pos = 0;
- uint64_t prev = pos;
- for (; pos < file_size && (dir = (direntry_header_t *)data_p)->size;
- data_p += dir->size, prev = pos, pos += dir->size)
- ;
- if (entry_offset)
- *entry_offset = prev;
- if (meta)
- memcpy(meta, ((char *)data) + prev, sizeof(direntry_header_t));
- return pos;
-}
-
-void ext2_create_entry(int directory_inode, direntry_header_t entry_header,
- const char *name) {
- uint64_t entry_offset = 0;
- direntry_header_t meta;
- end_of_last_entry_position(directory_inode, &entry_offset, &meta);
-
- uint32_t padding_in_use = block_byte_size - entry_offset;
-
- // assert(padding_in_use == meta.size);
- assert(padding_in_use >=
- (sizeof(direntry_header_t) + entry_header.name_length));
-
- // Modify the entry to have its real size
- meta.size = sizeof(direntry_header_t) + meta.name_length;
- meta.size += (4 - (meta.size % 4));
- write_inode(directory_inode, (unsigned char *)&meta,
- sizeof(direntry_header_t), entry_offset, NULL, 0);
-
- // Create new entry
- uint32_t new_entry_offset = entry_offset + meta.size;
- entry_header.size = (sizeof(direntry_header_t) + entry_header.name_length);
- entry_header.size += (4 - (entry_header.size % 4));
-
- uint32_t length_till_next_block = 1024 - (new_entry_offset % 1024);
- if (0 == length_till_next_block)
- length_till_next_block = 1024;
- assert(entry_header.size < length_till_next_block);
- entry_header.size = length_till_next_block;
-
- uint8_t buffer[entry_header.size];
- memset(buffer, 0, entry_header.size);
- memcpy(buffer, &entry_header, sizeof(entry_header));
- memcpy(buffer + sizeof(entry_header), name, entry_header.name_length);
- write_inode(directory_inode, (unsigned char *)buffer, entry_header.size,
- new_entry_offset, NULL, 0);
-}
-
-int ext2_find_parent(char *path, uint32_t *parent_inode, char **filename) {
- char *e = path;
- for (; *e; e++)
- ;
- for (; *e != '/'; e--)
- ;
- *e = '\0';
- *filename = e + 1;
- if (*path == '\0') {
- *parent_inode = EXT2_ROOT_INODE;
- return 1;
- } else {
- int r = ext2_find_inode(path);
- if (0 == r)
- return 0;
- *parent_inode = r;
- return 1;
- }
- return 0;
-}
-
-int ext2_create_directory(const char *path, int mode) {
- (void)mode;
- // Check if the directory already exists
- uint32_t inode_num = ext2_find_inode(path);
- if (0 != inode_num) {
- klog("ext2_create_directory: Directory already exists", LOG_WARN);
- return inode_num;
- }
-
- uint32_t parent_inode;
- // Get the parent directory
- char path_buffer[strlen(path) + 1];
- char *filename;
- strcpy(path_buffer, path);
- if (!ext2_find_parent(path_buffer, &parent_inode, &filename)) {
- klog("ext2_create_file: Parent does not exist", LOG_WARN);
- return -1;
- }
-
- int new_file_inode = get_free_inode(1);
- if (-1 == new_file_inode) {
- klog("ext2_create_file: Unable to find free inode", LOG_WARN);
- return -1;
- }
- assert(0 != new_file_inode);
-
- direntry_header_t entry_header;
- entry_header.inode = new_file_inode;
- entry_header.name_length = strlen(filename);
- entry_header.type_indicator = TYPE_INDICATOR_DIRECTORY;
- entry_header.size = sizeof(entry_header) + entry_header.name_length;
-
- ext2_create_entry(parent_inode, entry_header, filename);
- // Create the inode header
- uint8_t inode_buffer[inode_size];
- inode_t *new_inode = (inode_t *)inode_buffer;
- memset(inode_buffer, 0, inode_size);
- new_inode->types_permissions = DIRECTORY;
- new_inode->num_hard_links = 2; // 2 since the directory references
- // itself with the "." entry
- ext2_write_inode(new_file_inode, new_inode);
-
- // Populate the new directory with "." and ".."
- {
- // "."
- direntry_header_t child_entry_header;
- child_entry_header.inode = new_file_inode;
- child_entry_header.name_length = 1;
- child_entry_header.type_indicator = TYPE_INDICATOR_DIRECTORY;
- child_entry_header.size = sizeof(entry_header) + entry_header.name_length;
- ext2_create_entry(new_file_inode, child_entry_header, ".");
- // ".."
- child_entry_header.inode = parent_inode;
- child_entry_header.name_length = 2;
- child_entry_header.type_indicator = TYPE_INDICATOR_DIRECTORY;
- child_entry_header.size = sizeof(entry_header) + entry_header.name_length;
- ext2_create_entry(new_file_inode, child_entry_header, "..");
- }
- return new_file_inode;
-}
-
-int ext2_create_file(const char *path, int mode) {
- // Check if the file already exists
- uint32_t inode_num = ext2_find_inode(path);
- if (0 != inode_num) {
- klog("ext2_create_file: File already exists", LOG_WARN);
- return inode_num;
- }
-
- uint32_t parent_inode;
- // Get the parent directory
- char path_buffer[strlen(path) + 1];
- char *filename;
- strcpy(path_buffer, path);
- if (!ext2_find_parent(path_buffer, &parent_inode, &filename)) {
- klog("ext2_create_file: Parent does not exist", LOG_WARN);
- return -1;
- }
-
- int new_file_inode = get_free_inode(1);
- if (-1 == new_file_inode) {
- klog("ext2_create_file: Unable to find free inode", LOG_WARN);
- return -1;
- }
- assert(0 != new_file_inode);
-
- direntry_header_t entry_header;
- entry_header.inode = new_file_inode;
- entry_header.name_length = strlen(filename);
- entry_header.type_indicator = TYPE_INDICATOR_REGULAR;
- entry_header.size = sizeof(entry_header) + entry_header.name_length;
-
- ext2_create_entry(parent_inode, entry_header, filename);
- // Create the inode header
- uint8_t inode_buffer[inode_size];
- inode_t *new_inode = (inode_t *)inode_buffer;
- memset(inode_buffer, 0, inode_size);
- new_inode->types_permissions = 0x8000;
- new_inode->num_hard_links = 1;
- ext2_write_inode(new_file_inode, new_inode);
- return new_file_inode;
-}
-
-vfs_inode_t *ext2_mount(void) {
- parse_superblock();
- return vfs_create_inode(0 /*inode_num*/, 0 /*type*/, 0 /*has_data*/,
- 0 /*can_write*/, 0 /*is_open*/,
- NULL /*internal_object*/, 0 /*file_size*/, ext2_open,
- ext2_create_file, ext2_read, ext2_write, ext2_close,
- ext2_create_directory, NULL /*get_vm_object*/,
- ext2_truncate /*truncate*/);
-}
-
-void parse_superblock(void) {
- superblock = ksbrk(2 * SECTOR_SIZE);
- read_lba(EXT2_SUPERBLOCK_SECTOR, (void *)superblock, 2 * SECTOR_SIZE, 0);
- block_byte_size = 1024 << superblock->block_size;
-
- if (0xEF53 != superblock->ext2_signature) {
- klog("Incorrect ext2 signature in superblock.", LOG_ERROR);
- for (;;)
- ; // TODO: Fail properly
- }
-
- if (1 <= superblock->major_version)
- inode_size = ((ext_superblock_t *)superblock)->inode_size;
-
- inodes_per_block = block_byte_size / inode_size;
-}