static int do_ext2fs_link()

in fs/extfs/extfs.cpp [480:530]


static int do_ext2fs_link(ext2_filsys fs, const char *src, const char *dest) {
    errcode_t ret = 0;
    ext2_ino_t parent, ino;

    DEFER(LOG_DEBUG("link ", VALUE(src), VALUE(dest), VALUE(parent), VALUE(ino), VALUE(ret)));

    ino = string_to_inode(fs, dest, 0);
    if (ino) {
        return -(ret = EEXIST);
    }
    parent = get_parent_dir_ino(fs, dest);
    if (parent == 0) {
        return -(ret = ENOTDIR);
    }
    char *filename = get_filename(dest);
    if (filename == nullptr) {
        return -(ret = EISDIR);
    }
    ino = string_to_inode(fs, src, 0);
    if (ino == 0) {
        return -(ret = ENOENT);
    }

    struct ext2_inode_large inode;
    memset(&inode, 0, sizeof(inode));
    ret = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, sizeof(inode));
    if (ret) return parse_extfs_error(fs, ino, ret);

    inode.i_links_count++;
    // update_ctime
    ret = update_xtime(fs, ino, (struct ext2_inode *)&inode, EXT_CTIME);
    if (ret) return ret;

    ret = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, sizeof(inode));
    if (ret) return parse_extfs_error(fs, ino, ret);

    ret = ext2fs_link(fs, parent, filename, ino, ext2_file_type(inode.i_mode));
    if (ret == EXT2_ET_DIR_NO_SPACE) {
        ret = ext2fs_expand_dir(fs, parent);
        if (ret) return parse_extfs_error(fs, parent, ret);

        ret = ext2fs_link(fs, parent, filename, ino, ext2_file_type(inode.i_mode));
    }
    if (ret) return parse_extfs_error(fs, parent, ret);

    // update_mtime
    ret = update_xtime(fs, parent, nullptr, EXT_CTIME | EXT_MTIME);
    if (ret) return ret;

    return 0;
}