diff options
author | Marvin Borner | 2020-04-16 19:06:33 +0200 |
---|---|---|
committer | Marvin Borner | 2020-04-16 19:06:33 +0200 |
commit | 4014a36377ff69f6433e7b0af2144bc3a7d29ca7 (patch) | |
tree | 9440ac3749d406c6df9917d4bb3a19de6ea99655 /src/kernel/fs/ext2/ext2.c | |
parent | fc26e84ef8c6255926811fe639e3e466b756e581 (diff) |
Many fix attempts for the divide by zero exception
Diffstat (limited to 'src/kernel/fs/ext2/ext2.c')
-rw-r--r-- | src/kernel/fs/ext2/ext2.c | 790 |
1 files changed, 0 insertions, 790 deletions
diff --git a/src/kernel/fs/ext2/ext2.c b/src/kernel/fs/ext2/ext2.c deleted file mode 100644 index b14d726..0000000 --- a/src/kernel/fs/ext2/ext2.c +++ /dev/null @@ -1,790 +0,0 @@ -#include <stddef.h> -#include <stdint.h> -#include <kernel/system.h> -#include <kernel/lib/stdlib.h> -#include <kernel/lib/stdio.h> -#include <kernel/lib/lib.h> -#include <kernel/memory/alloc.h> -#include <kernel/fs/ext2/ext2.h> - -uint32_t ext2_file_size(vfs_node_t *node) -{ - ext2_fs_t *ext2fs = node->device; - inode_t *inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, inode, node->inode_num); - uint32_t ret = inode->size; - kfree(inode); - return ret; -} - -void ext2_mkdir(vfs_node_t *parent, char *name, uint16_t permission) -{ - ext2_fs_t *ext2fs = parent->device; - uint32_t inode_idx = alloc_inode(ext2fs); - inode_t *inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, inode, inode_idx); - inode->permission = EXT2_S_IFDIR; - inode->permission |= 0xFFF & permission; - inode->atime = 0; - inode->ctime = 0; - inode->dtime = 0; - inode->gid = 0; - inode->userid = 0; - inode->f_block_addr = 0; - inode->num_sectors = 0; - inode->size = ext2fs->block_size; - inode->hard_links = 2; - inode->flags = 0; - inode->file_acl = 0; - inode->dir_acl = 0; - inode->generation = 0; - inode->os_specific1 = 0; - memset(inode->blocks, 0, sizeof(inode->blocks)); - memset(inode->os_specific2, 0, 12); - alloc_inode_block(ext2fs, inode, inode_idx, 0); - write_inode_metadata(ext2fs, inode, inode_idx); - ext2_create_entry(parent, name, inode_idx); - - inode_t *p_inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, p_inode, parent->inode_num); - p_inode->hard_links++; - write_inode_metadata(ext2fs, p_inode, parent->inode_num); - rewrite_bgds(ext2fs); -} - -void ext2_mkfile(vfs_node_t *parent, char *name, uint16_t permission) -{ - ext2_fs_t *ext2fs = parent->device; - uint32_t inode_idx = alloc_inode(ext2fs); - inode_t *inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, inode, inode_idx); - inode->permission = EXT2_S_IFREG; - inode->permission |= 0xFFF & permission; - inode->atime = 0; - inode->ctime = 0; - inode->dtime = 0; - inode->gid = 0; - inode->userid = 0; - inode->f_block_addr = 0; - inode->num_sectors = 0; - inode->size = ext2fs->block_size; - inode->hard_links = 2; - inode->flags = 0; - inode->file_acl = 0; - inode->dir_acl = 0; - inode->generation = 0; - inode->os_specific1 = 0; - memset(inode->blocks, 0, sizeof(inode->blocks)); - memset(inode->os_specific2, 0, 12); - alloc_inode_block(ext2fs, inode, inode_idx, 0); - write_inode_metadata(ext2fs, inode, inode_idx); - ext2_create_entry(parent, name, inode_idx); - - inode_t *p_inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, p_inode, parent->inode_num); - p_inode->hard_links++; - write_inode_metadata(ext2fs, p_inode, parent->inode_num); - rewrite_bgds(ext2fs); -} - -void ext2_unlink(vfs_node_t *parent, char *name) -{ - ext2_fs_t *ext2fs = parent->device; - ext2_remove_entry(parent, name); - - inode_t *p_inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, p_inode, parent->inode_num); - p_inode->hard_links--; - write_inode_metadata(ext2fs, p_inode, parent->inode_num); - rewrite_bgds(ext2fs); -} - -char **ext2_listdir(vfs_node_t *parent) -{ - ext2_fs_t *ext2fs = parent->device; - inode_t *p_inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, p_inode, parent->inode_num); - uint32_t curr_offset = 0; - uint32_t block_offset = 0; - uint32_t in_block_offset = 0; - int size = 0, cap = 10; - char **ret = kmalloc(sizeof(char *) * cap); - char *block_buf = read_inode_block(ext2fs, p_inode, block_offset); - while (curr_offset < p_inode->size) { - if (in_block_offset >= ext2fs->block_size) { - block_offset++; - in_block_offset = 0; - block_buf = read_inode_block(ext2fs, p_inode, block_offset); - } - if (size + 1 == cap) { - ret = krealloc(ret, sizeof(char *) * cap * 2); - cap = cap * 2; - } - - direntry_t *curr_dir = (direntry_t *)(block_buf + in_block_offset); - if (curr_dir->inode != 0) { - char *temp = kcalloc(curr_dir->name_len + 1, 1); - memcpy(temp, curr_dir->name, curr_dir->name_len); - ret[size++] = temp; - } - uint32_t expected_size = - ((sizeof(direntry_t) + curr_dir->name_len) & 0xfffffffc) + 0x4; - uint32_t real_size = curr_dir->size; - if (real_size != expected_size) { - break; - } - in_block_offset += curr_dir->size; - curr_offset += curr_dir->size; - } - ret[size] = NULL; - return ret; -} - -vfs_node_t *vfsnode_from_direntry(ext2_fs_t *ext2fs, direntry_t *dir, inode_t *inode) -{ - vfs_node_t *ret = kcalloc(sizeof(vfs_node_t), 1); - - ret->device = (void *)ext2fs; - ret->inode_num = dir->inode; - memcpy(ret->name, dir->name, dir->name_len); - - ret->uid = inode->userid; - ret->uid = inode->gid; - ret->size = inode->size; - ret->mask = inode->permission & 0xFFF; - ret->nlink = inode->hard_links; - - ret->flags = 0; - if ((inode->permission & EXT2_S_IFREG) == EXT2_S_IFREG) { - ret->flags |= FS_FILE; - ret->read = ext2_read; - ret->write = ext2_write; - ret->unlink = ext2_unlink; - ret->get_file_size = ext2_file_size; - } - if ((inode->permission & EXT2_S_IFDIR) == EXT2_S_IFDIR) { - ret->flags |= FS_DIRECTORY; - ret->mkdir = ext2_mkdir; - ret->finddir = ext2_finddir; - ret->unlink = ext2_unlink; - ret->create = ext2_mkfile; - ret->listdir = ext2_listdir; - ret->read = ext2_read; - ret->write = ext2_write; - } - if ((inode->permission & EXT2_S_IFBLK) == EXT2_S_IFBLK) { - ret->flags |= FS_BLOCKDEVICE; - } - if ((inode->permission & EXT2_S_IFCHR) == EXT2_S_IFCHR) { - ret->flags |= FS_CHARDEVICE; - } - if ((inode->permission & EXT2_S_IFIFO) == EXT2_S_IFIFO) { - ret->flags |= FS_PIPE; - } - if ((inode->permission & EXT2_S_IFLNK) == EXT2_S_IFLNK) { - ret->flags |= FS_SYMLINK; - } - - ret->access_time = inode->atime; - ret->modified_time = inode->mtime; - ret->create_time = inode->ctime; - - ret->chmod = ext2_chmod; - ret->open = ext2_open; - ret->close = ext2_close; - return ret; -} - -vfs_node_t *ext2_finddir(vfs_node_t *parent, char *name) -{ - ext2_fs_t *ext2fs = parent->device; - inode_t *p_inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, p_inode, parent->inode_num); - uint32_t expected_size; - uint32_t real_size; - uint32_t curr_offset = 0; - uint32_t block_offset = 0; - uint32_t in_block_offset = 0; - char *block_buf = read_inode_block(ext2fs, p_inode, block_offset); - while (curr_offset < p_inode->size) { - if (in_block_offset >= ext2fs->block_size) { - block_offset++; - in_block_offset = 0; - block_buf = read_inode_block(ext2fs, p_inode, block_offset); - } - - direntry_t *curr_dir = (direntry_t *)(block_buf + in_block_offset); - char *temp = kcalloc(curr_dir->name_len + 1, 1); - memcpy(temp, curr_dir->name, curr_dir->name_len); - if (curr_dir->inode != 0 && !strcmp(temp, name)) { - inode_t *inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, inode, curr_dir->inode); - return vfsnode_from_direntry(ext2fs, curr_dir, inode); - } - if (((sizeof(direntry_t) + curr_dir->name_len) & 0x00000003) != 0) - expected_size = - ((sizeof(direntry_t) + curr_dir->name_len) & 0xfffffffc) + 0x4; - else - expected_size = ((sizeof(direntry_t) + curr_dir->name_len) & 0xfffffffc); - real_size = curr_dir->size; - if (real_size != expected_size) { - break; - } - in_block_offset += curr_dir->size; - curr_offset += curr_dir->size; - } - return NULL; -} - -void ext2_create_entry(vfs_node_t *parent, char *entry_name, uint32_t entry_inode) -{ - ext2_fs_t *ext2fs = parent->device; - inode_t *p_inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, p_inode, parent->inode_num); - uint32_t curr_offset = 0; - uint32_t block_offset = 0; - uint32_t in_block_offset = 0; - uint32_t found = 0; - uint32_t entry_name_len = strlen(entry_name); - char *check = kcalloc(entry_name_len + 1, 1); - char *block_buf = read_inode_block(ext2fs, p_inode, block_offset); - - while (curr_offset < p_inode->size) { - if (in_block_offset >= ext2fs->block_size) { - block_offset++; - in_block_offset = 0; - block_buf = read_inode_block(ext2fs, p_inode, block_offset); - } - direntry_t *curr_dir = (direntry_t *)(block_buf + in_block_offset); - if (curr_dir->name_len == entry_name_len) { - memcpy(check, curr_dir->name, entry_name_len); - if (curr_dir->inode != 0 && !strcmp(entry_name, check)) { - log("Entry by the same name %s already exist\n", check); - return; - } - } - if (found) { - curr_dir->inode = entry_inode; - curr_dir->size = - (uint32_t)block_buf + ext2fs->block_size - (uint32_t)curr_dir; - curr_dir->name_len = strlen(entry_name); - curr_dir->type = 0; - memcpy(curr_dir->name, entry_name, strlen(entry_name)); - write_inode_block(ext2fs, p_inode, block_offset, block_buf); - in_block_offset += curr_dir->size; - if (in_block_offset >= ext2fs->block_size) { - block_offset++; - in_block_offset = 0; - block_buf = read_inode_block(ext2fs, p_inode, block_offset); - } - curr_dir = (direntry_t *)(block_buf + in_block_offset); - memset(curr_dir, 0, sizeof(direntry_t)); - write_inode_block(ext2fs, p_inode, block_offset, block_buf); - return; - } - uint32_t expected_size = - ((sizeof(direntry_t) + curr_dir->name_len) & 0xfffffffc) + 0x4; - uint32_t real_size = curr_dir->size; - if (real_size != expected_size) { - found = 1; - curr_dir->size = expected_size; - in_block_offset += expected_size; - curr_offset += expected_size; - continue; - } - in_block_offset += curr_dir->size; - curr_offset += curr_dir->size; - } -} - -void ext2_remove_entry(vfs_node_t *parent, char *entry_name) -{ - ext2_fs_t *ext2fs = parent->device; - inode_t *p_inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, p_inode, parent->inode_num); - uint32_t curr_offset = 0; - uint32_t block_offset = 0; - uint32_t in_block_offset = 0; - uint32_t entry_name_len = strlen(entry_name); - char *check = kcalloc(entry_name_len + 1, 1); - char *block_buf = read_inode_block(ext2fs, p_inode, block_offset); - while (curr_offset < p_inode->size) { - if (in_block_offset >= ext2fs->block_size) { - block_offset++; - in_block_offset = 0; - block_buf = read_inode_block(ext2fs, p_inode, block_offset); - } - direntry_t *curr_dir = (direntry_t *)(block_buf + in_block_offset); - if (curr_dir->name_len == entry_name_len) { - memcpy(check, curr_dir->name, entry_name_len); - if (curr_dir->inode != 0 && !strcmp(entry_name, check)) { - curr_dir->inode = 0; - write_inode_block(ext2fs, p_inode, block_offset, block_buf); - return; - } - } - uint32_t expected_size = - ((sizeof(direntry_t) + curr_dir->name_len) & 0xfffffffc) + 0x4; - uint32_t real_size = curr_dir->size; - if (real_size != expected_size) - return; - in_block_offset += curr_dir->size; - curr_offset += curr_dir->size; - } -} - -void ext2_chmod(vfs_node_t *file, uint32_t mode) -{ - ext2_fs_t *ext2fs = file->device; - inode_t *inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, inode, file->inode_num); - inode->permission = (inode->permission & 0xFFFFF000) | mode; - write_inode_metadata(ext2fs, inode, file->inode_num); -} - -uint32_t ext2_read(vfs_node_t *file, uint32_t offset, uint32_t size, char *buf) -{ - ext2_fs_t *ext2fs = file->device; - inode_t *inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, inode, file->inode_num); - read_inode_filedata(ext2fs, inode, offset, size, buf); - return size; -} - -uint32_t ext2_write(vfs_node_t *file, uint32_t offset, uint32_t size, char *buf) -{ - ext2_fs_t *ext2fs = file->device; - inode_t *inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, inode, file->inode_num); - write_inode_filedata(ext2fs, inode, file->inode_num, offset, size, buf); - return size; -} - -void ext2_open(vfs_node_t *file, uint32_t flags) -{ - ext2_fs_t *ext2fs = file->device; - if (flags & O_TRUNC) { - inode_t *inode = kmalloc(sizeof(inode_t)); - read_inode_metadata(ext2fs, inode, file->inode_num); - inode->size = 0; - write_inode_metadata(ext2fs, inode, file->inode_num); - } -} - -void ext2_close() -{ - return; -} - -void read_inode_metadata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx) -{ - uint32_t group = inode_idx / ext2fs->inodes_per_group; - uint32_t inode_table_block = ext2fs->bgds[group].inode_table; - uint32_t idx_in_group = inode_idx - group * ext2fs->inodes_per_group; - uint32_t block_offset = (idx_in_group - 1) * ext2fs->sb->inode_size / ext2fs->block_size; - uint32_t offset_in_block = - (idx_in_group - 1) - block_offset * (ext2fs->block_size / ext2fs->sb->inode_size); - char *block_buf = kmalloc(ext2fs->block_size); - read_disk_block(ext2fs, inode_table_block + block_offset, block_buf); - memcpy(inode, block_buf + offset_in_block * ext2fs->sb->inode_size, ext2fs->sb->inode_size); - kfree(block_buf); -} - -void write_inode_metadata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx) -{ - uint32_t group = inode_idx / ext2fs->inodes_per_group; - uint32_t inode_table_block = ext2fs->bgds[group].inode_table; - uint32_t block_offset = (inode_idx - 1) * ext2fs->sb->inode_size / ext2fs->block_size; - uint32_t offset_in_block = - (inode_idx - 1) - block_offset * (ext2fs->block_size / ext2fs->sb->inode_size); - char *block_buf = kmalloc(ext2fs->block_size); - read_disk_block(ext2fs, inode_table_block + block_offset, block_buf); - memcpy(block_buf + offset_in_block * ext2fs->sb->inode_size, inode, ext2fs->sb->inode_size); - write_disk_block(ext2fs, inode_table_block + block_offset, block_buf); - kfree(block_buf); -} - -uint32_t read_inode_filedata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t offset, uint32_t size, - char *buf) -{ - uint32_t end_offset = (inode->size >= offset + size) ? (offset + size) : (inode->size); - uint32_t start_block = offset / ext2fs->block_size; - uint32_t end_block = end_offset / ext2fs->block_size; - uint32_t start_off = offset % ext2fs->block_size; - uint32_t end_size = end_offset - end_block * ext2fs->block_size; - - uint32_t i = start_block; - uint32_t curr_off = 0; - while (i <= end_block) { - uint32_t left = 0, right = ext2fs->block_size - 1; - char *block_buf = read_inode_block(ext2fs, inode, i); - if (i == start_block) - left = start_off; - if (i == end_block) - right = end_size - 1; - memcpy(buf + curr_off, block_buf + left, (right - left + 1)); - curr_off = curr_off + (right - left + 1); - kfree(block_buf); - i++; - } - return end_offset - offset; -} - -void write_inode_filedata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx, uint32_t offset, - uint32_t size, char *buf) -{ - if (offset + size > inode->size) { - inode->size = offset + size; - write_inode_metadata(ext2fs, inode, inode_idx); - } - uint32_t end_offset = (inode->size >= offset + size) ? (offset + size) : (inode->size); - uint32_t start_block = offset / ext2fs->block_size; - uint32_t end_block = end_offset / ext2fs->block_size; - uint32_t start_off = offset % ext2fs->block_size; - uint32_t end_size = end_offset - end_block * ext2fs->block_size; - - uint32_t i = start_block; - uint32_t curr_off = 0; - while (i <= end_block) { - uint32_t left = 0, right = ext2fs->block_size; - char *block_buf = read_inode_block(ext2fs, inode, i); - - if (i == start_block) - left = start_off; - if (i == end_block) - right = end_size - 1; - memcpy(block_buf + left, buf + curr_off, (right - left + 1)); - curr_off = curr_off + (right - left + 1); - write_inode_block(ext2fs, inode, i, block_buf); - kfree(block_buf); - i++; - } -} - -char *read_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t iblock) -{ - char *buf = kmalloc(ext2fs->block_size); - uint32_t disk_block = get_disk_block_number(ext2fs, inode, iblock); - read_disk_block(ext2fs, disk_block, buf); - return buf; -} - -void write_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t iblock, char *buf) -{ - uint32_t disk_block = get_disk_block_number(ext2fs, inode, iblock); - write_disk_block(ext2fs, disk_block, buf); -} - -void read_disk_block(ext2_fs_t *ext2fs, uint32_t block, char *buf) -{ - vfs_read(ext2fs->disk_device, ext2fs->block_size * block, ext2fs->block_size, buf); -} - -void write_disk_block(ext2_fs_t *ext2fs, uint32_t block, char *buf) -{ - vfs_write(ext2fs->disk_device, ext2fs->block_size * block, ext2fs->block_size, buf); -} - -void rewrite_bgds(ext2_fs_t *ext2fs) -{ - for (uint32_t i = 0; i < ext2fs->bgd_blocks; i++) - write_disk_block(ext2fs, 2, (void *)ext2fs->bgds + i * ext2fs->block_size); -} - -void rewrite_superblock(ext2_fs_t *ext2fs) -{ - write_disk_block(ext2fs, 1, (void *)ext2fs->sb); -} - -int alloc_inode_metadata_block(uint32_t *block_ptr, ext2_fs_t *ext2fs, inode_t *inode, - uint32_t inode_idx, char *buffer, unsigned int block_overwrite) -{ - if (!(*block_ptr)) { - unsigned int block_no = ext2_alloc_block(ext2fs); - if (!block_no) - return 0; - *block_ptr = block_no; - if (buffer) - write_disk_block(ext2fs, block_overwrite, (void *)buffer); - else - write_inode_metadata(ext2fs, inode, inode_idx); - return 1; - } - return 0; -} - -uint32_t get_disk_block_number(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_block) -{ - unsigned int p = ext2fs->block_size / 4; - int a, b, c, d, e, f, g; - uint32_t *tmp = kmalloc(ext2fs->block_size); - uint32_t ret = -1; - a = inode_block - EXT2_DIRECT_BLOCKS; - if (a < 0) { - ret = inode->blocks[inode_block]; - goto done; - } - b = a - p; - if (b < 0) { - read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS], (void *)tmp); - ret = tmp[a]; - goto done; - } - c = b - p * p; - if (c < 0) { - c = b / p; - d = b - c * p; - read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS + 1], (void *)tmp); - read_disk_block(ext2fs, tmp[c], (void *)tmp); - ret = tmp[d]; - goto done; - } - d = c - p * p * p; - if (d < 0) { - e = c / (p * p); - f = (c - e * p * p) / p; - g = (c - e * p * p - f * p); - read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS + 2], (void *)tmp); - read_disk_block(ext2fs, tmp[e], (void *)tmp); - read_disk_block(ext2fs, tmp[f], (void *)tmp); - ret = tmp[g]; - goto done; - } -done: - kfree(tmp); - return ret; -} - -void set_disk_block_number(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx, - uint32_t inode_block, uint32_t disk_block) -{ - unsigned int p = ext2fs->block_size / 4; - int a, b, c, d, e, f, g; - int iblock = inode_block; - uint32_t *tmp = kmalloc(ext2fs->block_size); - - a = iblock - EXT2_DIRECT_BLOCKS; - if (a <= 0) { - inode->blocks[inode_block] = disk_block; - goto done; - } - b = a - p; - if (b <= 0) { - alloc_inode_metadata_block(&(inode->blocks[EXT2_DIRECT_BLOCKS]), ext2fs, inode, - inode_idx, NULL, 0); - read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS], (void *)tmp); - ((unsigned int *)tmp)[a] = disk_block; - write_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS], (void *)tmp); - tmp[a] = disk_block; - goto done; - } - c = b - p * p; - if (c <= 0) { - c = b / p; - d = b - c * p; - alloc_inode_metadata_block(&(inode->blocks[EXT2_DIRECT_BLOCKS + 1]), ext2fs, inode, - inode_idx, NULL, 0); - read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS + 1], (void *)tmp); - alloc_inode_metadata_block(&(tmp[c]), ext2fs, inode, inode_idx, (void *)tmp, - inode->blocks[EXT2_DIRECT_BLOCKS + 1]); - unsigned int temp = tmp[c]; - read_disk_block(ext2fs, temp, (void *)tmp); - tmp[d] = disk_block; - write_disk_block(ext2fs, temp, (void *)tmp); - goto done; - } - d = c - p * p * p; - if (d <= 0) { - e = c / (p * p); - f = (c - e * p * p) / p; - g = (c - e * p * p - f * p); - alloc_inode_metadata_block(&(inode->blocks[EXT2_DIRECT_BLOCKS + 2]), ext2fs, inode, - inode_idx, NULL, 0); - read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS + 2], (void *)tmp); - alloc_inode_metadata_block(&(tmp[e]), ext2fs, inode, inode_idx, (void *)tmp, - inode->blocks[EXT2_DIRECT_BLOCKS + 2]); - unsigned int temp = tmp[e]; - read_disk_block(ext2fs, tmp[e], (void *)tmp); - alloc_inode_metadata_block(&(tmp[f]), ext2fs, inode, inode_idx, (void *)tmp, temp); - temp = tmp[f]; - read_disk_block(ext2fs, tmp[f], (void *)tmp); - tmp[g] = disk_block; - write_disk_block(ext2fs, temp, (void *)tmp); - goto done; - } -done: - kfree(tmp); -} - -uint32_t ext2_alloc_block(ext2_fs_t *ext2fs) -{ - uint32_t *buf = kcalloc(ext2fs->block_size, 1); - for (uint32_t i = 0; i < ext2fs->total_groups; i++) { - if (!ext2fs->bgds[i].free_blocks) - continue; - - uint32_t bitmap_block = ext2fs->bgds[i].block_bitmap; - read_disk_block(ext2fs, bitmap_block, (void *)buf); - for (uint32_t j = 0; j < ext2fs->block_size / 4; j++) { - uint32_t sub_bitmap = buf[j]; - if (sub_bitmap == 0xFFFFFFFF) - continue; - for (uint32_t k = 0; k < 32; k++) { - uint32_t free = !((sub_bitmap >> k) & 0x1); - if (free) { - uint32_t mask = (0x1 << k); - buf[j] = buf[j] | mask; - write_disk_block(ext2fs, bitmap_block, (void *)buf); - ext2fs->bgds[i].free_blocks--; - rewrite_bgds(ext2fs); - return i * ext2fs->blocks_per_group + j * 32 + k; - } - } - } - } - panic("We're out of blocks!\n"); - return (uint32_t)-1; -} - -void ext2_free_block(ext2_fs_t *ext2fs, uint32_t block) -{ - uint32_t *buf = kcalloc(ext2fs->block_size, 1); - uint32_t group_idx = block / ext2fs->blocks_per_group; - uint32_t sub_bitmap_idx = (block - (ext2fs->blocks_per_group * group_idx)) / 4; - uint32_t idx = (block - (ext2fs->blocks_per_group * group_idx)) % 4; - - uint32_t bitmap_block = ext2fs->bgds[group_idx].block_bitmap; - read_disk_block(ext2fs, bitmap_block, (void *)buf); - - uint32_t mask = ~(0x1 << idx); - buf[sub_bitmap_idx] = buf[sub_bitmap_idx] & mask; - - write_disk_block(ext2fs, bitmap_block, (void *)buf); - - ext2fs->bgds[group_idx].free_blocks++; - rewrite_bgds(ext2fs); -} - -void alloc_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx, uint32_t block) -{ - uint32_t ret = ext2_alloc_block(ext2fs); - set_disk_block_number(ext2fs, inode, inode_idx, block, ret); - inode->num_sectors = (block + 1) * (ext2fs->block_size / 512); - write_inode_metadata(ext2fs, inode, inode_idx); -} - -void free_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx, uint32_t block) -{ - uint32_t ret = get_disk_block_number(ext2fs, inode, block); - ext2_free_block(ext2fs, ret); - set_disk_block_number(ext2fs, inode, inode_idx, ret, 0); - write_inode_metadata(ext2fs, inode, inode_idx); -} - -uint32_t alloc_inode(ext2_fs_t *ext2fs) -{ - uint32_t *buf = kcalloc(ext2fs->block_size, 1); - for (uint32_t i = 0; i < ext2fs->total_groups; i++) { - if (!ext2fs->bgds[i].free_inodes) - continue; - - uint32_t bitmap_block = ext2fs->bgds[i].inode_bitmap; - read_disk_block(ext2fs, bitmap_block, (void *)buf); - for (uint32_t j = 0; j < ext2fs->block_size / 4; j++) { - uint32_t sub_bitmap = buf[j]; - if (sub_bitmap == 0xFFFFFFFF) - continue; - for (uint32_t k = 0; k < 32; k++) { - uint32_t free = !((sub_bitmap >> k) & 0x1); - if (free) { - uint32_t mask = (0x1 << k); - buf[j] = buf[j] | mask; - write_disk_block(ext2fs, bitmap_block, (void *)buf); - ext2fs->bgds[i].free_inodes--; - rewrite_bgds(ext2fs); - return i * ext2fs->inodes_per_group + j * 32 + k; - } - } - } - } - panic("We're out of inodes!\n"); - return (uint32_t)-1; -} - -void free_inode(ext2_fs_t *ext2fs, uint32_t inode) -{ - uint32_t *buf = kcalloc(ext2fs->block_size, 1); - uint32_t group_idx = inode / ext2fs->inodes_per_group; - uint32_t sub_bitmap_idx = (inode - (ext2fs->inodes_per_group * group_idx)) / 4; - uint32_t idx = (inode - (ext2fs->inodes_per_group * group_idx)) % 4; - - uint32_t bitmap_block = ext2fs->bgds[group_idx].inode_bitmap; - read_disk_block(ext2fs, bitmap_block, (void *)buf); - - uint32_t mask = ~(0x1 << idx); - buf[sub_bitmap_idx] = buf[sub_bitmap_idx] & mask; - - write_disk_block(ext2fs, bitmap_block, (void *)buf); - - ext2fs->bgds[group_idx].free_inodes++; - rewrite_bgds(ext2fs); -} - -vfs_node_t *get_ext2_root(ext2_fs_t *ext2fs, inode_t *inode) -{ - vfs_node_t *ext2root = kcalloc(sizeof(vfs_node_t), 1); - strcpy(ext2root->name, "/"); - ext2root->device = ext2fs; - ext2root->mask = inode->permission; - ext2root->inode_num = ROOT_INODE_NUMBER; - - ext2root->access_time = inode->atime; - ext2root->modified_time = inode->mtime; - ext2root->create_time = inode->ctime; - - ext2root->flags |= FS_DIRECTORY; - ext2root->read = NULL; - ext2root->write = NULL; - ext2root->chmod = ext2_chmod; - ext2root->open = ext2_open; - ext2root->close = ext2_close; - ext2root->read = ext2_read; - ext2root->write = ext2_write; - ext2root->mkdir = ext2_mkdir; - ext2root->create = ext2_mkfile; - ext2root->listdir = ext2_listdir; - ext2root->finddir = ext2_finddir; - ext2root->unlink = ext2_unlink; - return ext2root; -} - -void ext2_init(char *device_path, char *mountpoint) -{ - ext2_fs_t *ext2fs = kcalloc(sizeof(ext2_fs_t), 1); - ext2fs->disk_device = file_open(device_path, 0); - ext2fs->sb = kmalloc(SUPERBLOCK_SIZE); - ext2fs->block_size = 1024; - read_disk_block(ext2fs, 1, (void *)ext2fs->sb); - log("%x", ext2fs->sb->ext2_magic); - ext2fs->block_size = (1024 << ext2fs->sb->log2block_size); - ext2fs->blocks_per_group = ext2fs->sb->blocks_per_group; - ext2fs->inodes_per_group = ext2fs->sb->inodes_per_group; - - ext2fs->total_groups = ext2fs->sb->total_blocks / - ext2fs->blocks_per_group; // REMEMBER: Zero Division Exception - if (ext2fs->blocks_per_group * ext2fs->total_groups < ext2fs->total_groups) - ext2fs->total_groups++; - - ext2fs->bgd_blocks = (ext2fs->total_groups * sizeof(bgd_t)) / ext2fs->block_size; - if (ext2fs->bgd_blocks * ext2fs->block_size < ext2fs->total_groups * sizeof(bgd_t)) - ext2fs->bgd_blocks++; - - ext2fs->bgds = kcalloc(sizeof(bgd_t), ext2fs->bgd_blocks * ext2fs->block_size); - for (uint32_t i = 0; i < ext2fs->bgd_blocks; i++) { - read_disk_block(ext2fs, 2, (void *)ext2fs->bgds + i * ext2fs->block_size); - } - - inode_t *root_inode = kcalloc(sizeof(inode_t), 1); - read_inode_metadata(ext2fs, root_inode, ROOT_INODE_NUMBER); - vfs_mount(mountpoint, get_ext2_root(ext2fs, root_inode)); -} |