X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=lwext4%2Fext4.c;h=0cdf045afcff648175034de89e8574107fc5fd17;hb=2a7a75f8f98d051f8d2b7b78d31649e943329fa6;hp=107f55c525667b9a745beea386368e79a99b44c7;hpb=92053fed4a3c6e17c0c1c7596353c8c5465bdf1f;p=lwext4.git diff --git a/lwext4/ext4.c b/lwext4/ext4.c index 107f55c..0cdf045 100644 --- a/lwext4/ext4.c +++ b/lwext4/ext4.c @@ -44,6 +44,7 @@ #include "ext4_inode.h" #include "ext4_super.h" #include "ext4_dir_idx.h" +#include "ext4_xattr.h" #include "ext4.h" #include @@ -180,7 +181,7 @@ static int ext4_has_children(bool *has_children, struct ext4_inode_ref *enode) static int ext4_link(struct ext4_mountpoint *mp, struct ext4_inode_ref *parent, struct ext4_inode_ref *child, const char *name, - uint32_t name_len) + uint32_t name_len, bool rename) { /* Check maximum name length */ if (name_len > EXT4_DIRECTORY_FILENAME_LEN) @@ -196,7 +197,7 @@ static int ext4_link(struct ext4_mountpoint *mp, struct ext4_inode_ref *parent, */ if (ext4_inode_is_type(&mp->fs.sb, child->inode, EXT4_INODE_MODE_DIRECTORY) && - ext4_inode_get_links_count(child->inode) == 0) { + !rename) { rc = ext4_dir_add_entry(child, ".", strlen("."), child); if (rc != EOK) { ext4_dir_remove_entry(parent, name, strlen(name)); @@ -231,6 +232,10 @@ static int ext4_link(struct ext4_mountpoint *mp, struct ext4_inode_ref *parent, child->dirty = true; parent->dirty = true; } else { + /* + * In case we want to rename a directory, + * we reset the original '..' pointer. + */ if (ext4_inode_is_type(&mp->fs.sb, child->inode, EXT4_INODE_MODE_DIRECTORY)) { int has_flag_index = @@ -263,7 +268,8 @@ static int ext4_link(struct ext4_mountpoint *mp, struct ext4_inode_ref *parent, ext4_fs_inode_links_count_inc(parent); parent->dirty = true; - } else { + } + if (!rename) { ext4_fs_inode_links_count_inc(child); child->dirty = true; } @@ -445,18 +451,25 @@ int ext4_umount(const char *mount_point) return ext4_block_fini(mp->fs.bdev); } +static struct ext4_mountpoint *ext4_get_mount(const char *path) +{ + int i; + for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) { + + if (!_mp[i].mounted) + continue; + + if (!strncmp(_mp[i].name, path, strlen(_mp[i].name))) + return &_mp[i]; + } + return 0; +} + int ext4_mount_point_stats(const char *mount_point, struct ext4_mount_stats *stats) { - uint32_t i; - struct ext4_mountpoint *mp = 0; + struct ext4_mountpoint *mp = ext4_get_mount(mount_point); - for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) { - if (!strcmp(_mp[i].name, mount_point)) { - mp = &_mp[i]; - break; - } - } if (!mp) return ENOENT; @@ -498,20 +511,6 @@ int ext4_mount_setup_locks(const char *mount_point, /********************************FILE OPERATIONS*****************************/ -static struct ext4_mountpoint *ext4_get_mount(const char *path) -{ - int i; - for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) { - - if (!_mp[i].mounted) - continue; - - if (!strncmp(_mp[i].name, path, strlen(_mp[i].name))) - return &_mp[i]; - } - return 0; -} - static int ext4_path_check(const char *path, bool *is_goal) { int i; @@ -632,6 +631,9 @@ static int ext4_generic_open2(ext4_file *f, const char *path, int flags, r = ext4_dir_find_entry(&result, &ref, path, len); if (r != EOK) { + /*Destroy last result*/ + ext4_dir_destroy_result(&ref, &result); + if (r != ENOENT) break; @@ -647,11 +649,9 @@ static int ext4_generic_open2(ext4_file *f, const char *path, int flags, if (r != EOK) break; - /*Destroy last result*/ - ext4_dir_destroy_result(&ref, &result); /*Link with root dir.*/ - r = ext4_link(mp, &ref, &child_ref, path, len); + r = ext4_link(mp, &ref, &child_ref, path, len, false); if (r != EOK) { /*Fail. Free new inode.*/ ext4_fs_free_inode(&child_ref); @@ -731,6 +731,7 @@ static int ext4_generic_open2(ext4_file *f, const char *path, int flags, if (f->flags & O_APPEND) f->fpos = f->fsize; + } r = ext4_fs_put_inode_ref(&ref); @@ -758,7 +759,8 @@ 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 rename) { bool is_goal = false; uint8_t inode_type = EXT4_DIRENTRY_DIR; @@ -799,14 +801,19 @@ static int __ext4_create_hardlink(const char *path, r = ext4_dir_find_entry(&result, &ref, path, len); if (r != EOK) { + /*Destroy last result*/ + ext4_dir_destroy_result(&ref, &result); + if (r != ENOENT || !is_goal) break; + /*Link with root dir.*/ + r = ext4_link(mp, &ref, child_ref, path, len, rename); + break; + } else if (r == EOK && is_goal) { /*Destroy last result*/ ext4_dir_destroy_result(&ref, &result); - - /*Link with root dir.*/ - r = ext4_link(mp, &ref, child_ref, path, len); + r = EEXIST; break; } @@ -850,10 +857,10 @@ static int __ext4_create_hardlink(const char *path, return r; } -static int __ext4_remove_hardlink(const char *path, - uint32_t name_off, - struct ext4_inode_ref *parent_ref, - struct ext4_inode_ref *child_ref) +static int ext4_remove_orig_reference(const char *path, + uint32_t name_off, + struct ext4_inode_ref *parent_ref, + struct ext4_inode_ref *child_ref) { bool is_goal; int r; @@ -868,11 +875,16 @@ static int __ext4_remove_hardlink(const char *path, len = ext4_path_check(path, &is_goal); - /*Unlink from parent*/ - r = ext4_unlink(mp, parent_ref, child_ref, path, len); + /* Remove entry from parent directory */ + r = ext4_dir_remove_entry(parent_ref, path, len); if (r != EOK) goto Finish; + if (ext4_inode_is_type(&mp->fs.sb, child_ref->inode, + EXT4_INODE_MODE_DIRECTORY)) { + ext4_fs_inode_links_count_dec(parent_ref); + parent_ref->dirty = true; + } Finish: return r; } @@ -913,7 +925,14 @@ int ext4_flink(const char *path, const char *hardlink_path) child_loaded = true; - r = __ext4_create_hardlink(hardlink_path, &child_ref); + /* Creating hardlink for directory is not allowed. */ + if (ext4_inode_is_type(&mp->fs.sb, child_ref.inode, + EXT4_INODE_MODE_DIRECTORY)) { + r = EINVAL; + goto Finish; + } + + r = __ext4_create_hardlink(hardlink_path, &child_ref, false); Finish: if (child_loaded) @@ -962,11 +981,12 @@ int ext4_frename(const char *path, const char *new_path) child_loaded = true; - r = __ext4_create_hardlink(new_path, &child_ref); + r = __ext4_create_hardlink(new_path, &child_ref, true); if (r != EOK) goto Finish; - r = __ext4_remove_hardlink(path, name_off, &parent_ref, &child_ref); + r = ext4_remove_orig_reference(path, name_off, + &parent_ref, &child_ref); if (r != EOK) goto Finish; @@ -2155,7 +2175,10 @@ int ext4_dir_open(ext4_dir *d, const char *path) return r; } -int ext4_dir_close(ext4_dir *d) { return ext4_fclose(&d->f); } +int ext4_dir_close(ext4_dir *d) +{ + return ext4_fclose(&d->f); +} const ext4_direntry *ext4_dir_entry_next(ext4_dir *d) { @@ -2200,6 +2223,11 @@ Finish: return de; } +void ext4_dir_entry_rewind(ext4_dir *d) +{ + d->next_off = 0; +} + /** * @} */