diff --git a/lwext4/ext4.c b/lwext4/ext4.c index e22b64f..77e6e51 100644 --- a/lwext4/ext4.c +++ b/lwext4/ext4.c @@ -758,7 +758,7 @@ static int ext4_generic_open(ext4_file *f, const char *path, const char *flags, } static int __ext4_create_hardlink(const char *path, - struct ext4_inode_ref *child_ref) + struct ext4_inode_ref *child_ref) { bool is_goal = false; uint8_t inode_type = EXT4_DIRECTORY_FILETYPE_DIR; @@ -810,9 +810,9 @@ static int __ext4_create_hardlink(const char *path, break; } - next_inode = ext4_dir_entry_ll_get_inode(result.dentry); + next_inode = result.dentry->inode; inode_type = - ext4_dir_entry_ll_get_inode_type(&mp->fs.sb, result.dentry); + ext4_dir_entry_ll_get_inode_type(&mp->fs.sb, result.dentry); r = ext4_dir_destroy_result(&ref, &result); if (r != EOK) @@ -850,85 +850,93 @@ static int __ext4_create_hardlink(const char *path, return r; } -static int __ext4_get_inode_ref_remove_hardlink(const char *path, - struct ext4_inode_ref *child) +static int __ext4_remove_hardlink(const char *path, + uint32_t name_off, + struct ext4_inode_ref *parent_ref, + struct ext4_inode_ref *child_ref) { - ext4_file f; - uint32_t parent_inode; - uint32_t name_off; bool is_goal; int r; int len; - struct ext4_inode_ref parent; struct ext4_mountpoint *mp = ext4_get_mount(path); if (!mp) return ENOENT; - r = ext4_generic_open2(&f, path, O_RDONLY, - EXT4_DIRECTORY_FILETYPE_UNKNOWN, &parent_inode, - &name_off); - if (r != EOK) - return r; - - /*Load parent*/ - r = ext4_fs_get_inode_ref(&mp->fs, parent_inode, &parent); - if (r != EOK) { - return r; - } - - /*We have file to unlink. Load it.*/ - r = ext4_fs_get_inode_ref(&mp->fs, f.inode, child); - if (r != EOK) { - ext4_fs_put_inode_ref(&parent); - return r; - } - - if (r != EOK) - goto Finish; - /*Set path*/ path += name_off; len = ext4_path_check(path, &is_goal); /*Unlink from parent*/ - r = ext4_unlink(mp, &parent, child, path, len); + r = ext4_unlink(mp, parent_ref, child_ref, path, len); if (r != EOK) goto Finish; Finish: if (r != EOK) - ext4_fs_put_inode_ref(child); + ext4_fs_put_inode_ref(child_ref); - ext4_fs_put_inode_ref(&parent); + ext4_fs_put_inode_ref(parent_ref); return r; } int ext4_frename(const char *path, const char *new_path) { int r; + ext4_file f; + uint32_t name_off; + bool parent_loaded = false, child_loaded = false; + uint32_t parent_inode, child_inode; struct ext4_mountpoint *mp = ext4_get_mount(path); - struct ext4_inode_ref inode_ref; + struct ext4_inode_ref child_ref, parent_ref; if (!mp) return ENOENT; EXT4_MP_LOCK(mp); - r = __ext4_get_inode_ref_remove_hardlink(path, &inode_ref); + r = ext4_generic_open2(&f, path, O_RDONLY, + EXT4_DIRECTORY_FILETYPE_UNKNOWN, + &parent_inode, &name_off); if (r != EOK) goto Finish; - r = __ext4_create_hardlink(new_path, &inode_ref); + child_inode = f.inode; + ext4_fclose(&f); + + /*Load parent*/ + r = ext4_fs_get_inode_ref(&mp->fs, parent_inode, &parent_ref); if (r != EOK) - r = __ext4_create_hardlink(path, &inode_ref); + goto Finish; - ext4_fs_put_inode_ref(&inode_ref); + parent_loaded = true; + + /*We have file to unlink. Load it.*/ + r = ext4_fs_get_inode_ref(&mp->fs, child_inode, &child_ref); + if (r != EOK) + goto Finish; + + child_loaded = true; + + r = __ext4_create_hardlink(new_path, &child_ref); + if (r != EOK) + goto Finish; + + r = __ext4_remove_hardlink(path, name_off, &parent_ref, &child_ref); + if (r != EOK) + goto Finish; Finish: + if (parent_loaded) + ext4_fs_put_inode_ref(&parent_ref); + + if (child_loaded) + ext4_fs_put_inode_ref(&child_ref); + EXT4_MP_UNLOCK(mp); return r; + } /****************************************************************************/