mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
fs: check if directory is empty on unlink
This commit is contained in:
@@ -1646,6 +1646,36 @@ static int ext2_unlink(vnode_t *vnode, vnode_t *child, char *name, cred_t *cred)
|
||||
ext2node_t *node = (ext2node_t *)vnode;
|
||||
ext2fs_t *fs = (ext2fs_t *)vnode->vfs;
|
||||
|
||||
// check if its actually empty (readcount > 2, asserted 2 for . and ..)
|
||||
if (child->type == V_TYPE_DIR) {
|
||||
size_t readcount;
|
||||
dent_t *dents = alloc(sizeof(dent_t) * 3);
|
||||
if (dents == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
int err = ext2_getdents(child, dents, 3, 0, &readcount);
|
||||
if (err) {
|
||||
free(dents);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (readcount > 2) {
|
||||
free(dents);
|
||||
return ENOTEMPTY;
|
||||
}
|
||||
|
||||
// if any of the dot entries is missing, mark filesystem as unclean and return not empty as we cant really be sure
|
||||
if (readcount != 2 ||
|
||||
strcmp(dents[0].d_name, "..") == 0 || strcmp(dents[0].d_name, ".") != 0 ||
|
||||
strcmp(dents[0].d_name, "..") == 0 || strcmp(dents[0].d_name, ".") != 0) {
|
||||
ASSERT_UNCLEAN(fs, !"missing dot dent");
|
||||
free(dents);
|
||||
return ENOTEMPTY;
|
||||
}
|
||||
|
||||
free(dents);
|
||||
}
|
||||
|
||||
int inode = 0;
|
||||
int err = removedent(fs, node, name, &inode);
|
||||
if (err)
|
||||
|
||||
@@ -263,6 +263,14 @@ static int tmpfs_unlink(vnode_t *node, vnode_t *child, char *name, cred_t *cred)
|
||||
tmpfsnode_t *unlinktmpnode = r;
|
||||
__assert(child == unlinknode);
|
||||
|
||||
if (unlinknode->type == V_TYPE_DIR) {
|
||||
// check if directory is empty
|
||||
HASHTABLE_FOREACH(&unlinktmpnode->children) {
|
||||
if (memcmp(entry->key, ".", 1) && memcmp(entry->key, "..", 2))
|
||||
return ENOTEMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
err = hashtable_remove(&tmpnode->children, name, namelen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
Reference in New Issue
Block a user