sketchy incorrect unlink and truncate on open

This commit is contained in:
Kevin Lange 2015-02-12 21:43:20 -08:00
parent e64eb6c90c
commit a9f5727a8b

View File

@ -531,6 +531,12 @@ static int allocate_inode_block(ext2_fs_t * this, ext2_inodetable_t * inode, uns
unsigned int t = (block + 1) * (this->block_size / 512);
if (inode->blocks < t) {
debug_print(NOTICE, "Setting inode->blocks to %d = (%d fs blocks)", t, t / (this->block_size / 512));
if (t == 496) {
debug_print(WARNING, "Oh hello, this is a breakpoint of sorts.");
debug_print(WARNING, "block = %d -> %d", block, block_no);
debug_print(WARNING, "block+1 = %d -> %d", block+1, get_block_number(this, inode, block+1));
}
inode->blocks = t;
}
write_inode(this, inode, inode_no);
@ -913,6 +919,8 @@ static int chmod_ext2(fs_node_t * node, int mode) {
write_inode(this, inode, node->inode);
ext2_sync(this);
return 0;
}
@ -1022,7 +1030,7 @@ static ext2_dir_t * direntry_ext2(ext2_fs_t * this, ext2_inodetable_t * inode, u
while (total_offset < inode->size && dir_index <= index) {
ext2_dir_t *d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset);
if (dir_index == index) {
if (d_ent->inode != 0 && dir_index == index) {
ext2_dir_t *out = malloc(d_ent->rec_len);
memcpy(out, d_ent, d_ent->rec_len);
free(block);
@ -1031,7 +1039,10 @@ static ext2_dir_t * direntry_ext2(ext2_fs_t * this, ext2_inodetable_t * inode, u
dir_offset += d_ent->rec_len;
total_offset += d_ent->rec_len;
dir_index++;
if (d_ent->inode) {
dir_index++;
}
if (dir_offset >= this->block_size) {
block_nr++;
@ -1068,7 +1079,7 @@ static fs_node_t * finddir_ext2(fs_node_t *node, char *name) {
}
ext2_dir_t *d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset);
if (strlen(name) != d_ent->name_len) {
if (d_ent->inode == 0 || strlen(name) != d_ent->name_len) {
dir_offset += d_ent->rec_len;
total_offset += d_ent->rec_len;
@ -1109,6 +1120,61 @@ static fs_node_t * finddir_ext2(fs_node_t *node, char *name) {
return outnode;
}
static void unlink_ext2(fs_node_t * node, char * name) {
/* XXX this is a very bad implementation */
ext2_fs_t * this = (ext2_fs_t *)node->device;
ext2_inodetable_t *inode = read_inode(this,node->inode);
assert(inode->mode & EXT2_S_IFDIR);
uint8_t * block = malloc(this->block_size);
ext2_dir_t *direntry = NULL;
uint8_t block_nr = 0;
inode_read_block(this, inode, block_nr, block);
uint32_t dir_offset = 0;
uint32_t total_offset = 0;
while (total_offset < inode->size) {
if (dir_offset >= this->block_size) {
block_nr++;
dir_offset -= this->block_size;
inode_read_block(this, inode, block_nr, block);
}
ext2_dir_t *d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset);
if (d_ent->inode == 0 || strlen(name) != d_ent->name_len) {
dir_offset += d_ent->rec_len;
total_offset += d_ent->rec_len;
continue;
}
char *dname = malloc(sizeof(char) * (d_ent->name_len + 1));
memcpy(dname, &(d_ent->name), d_ent->name_len);
dname[d_ent->name_len] = '\0';
if (!strcmp(dname, name)) {
free(dname);
direntry = d_ent;
break;
}
free(dname);
dir_offset += d_ent->rec_len;
total_offset += d_ent->rec_len;
}
free(inode);
if (!direntry) {
free(block);
return;
}
direntry->inode = 0;
inode_write_block(this, inode, node->inode, block_nr, block);
free(block);
ext2_sync(this);
}
static void refresh_inode(ext2_fs_t * this, ext2_inodetable_t * inodet, uint32_t inode) {
uint32_t group = inode / this->inodes_per_group;
@ -1233,7 +1299,14 @@ static uint32_t write_ext2(fs_node_t *node, uint32_t offset, uint32_t size, uint
}
static void open_ext2(fs_node_t *node, unsigned int flags) {
/* Nothing to do here */
ext2_fs_t * this = node->device;
if (flags & O_TRUNC) {
/* Uh, herp */
ext2_inodetable_t * inode = read_inode(this,node->inode);
inode->size = 0;
write_inode(this, inode, node->inode);
}
}
static void close_ext2(fs_node_t *node) {
@ -1297,6 +1370,7 @@ static uint32_t node_from_file(ext2_fs_t * this, ext2_inodetable_t *inode, ext2_
fnode->mkdir = mkdir_ext2;
fnode->readdir = readdir_ext2;
fnode->finddir = finddir_ext2;
fnode->unlink = unlink_ext2;
fnode->write = NULL;
}
if ((inode->mode & EXT2_S_IFBLK) == EXT2_S_IFBLK) {
@ -1388,6 +1462,7 @@ static uint32_t ext2_root(ext2_fs_t * this, ext2_inodetable_t *inode, fs_node_t
fnode->ioctl = NULL;
fnode->create = create_ext2;
fnode->mkdir = mkdir_ext2;
fnode->unlink = unlink_ext2;
return 1;
}