static ssize_t do_ext2fs_readlink()

in fs/extfs/extfs.cpp [838:872]


static ssize_t do_ext2fs_readlink(ext2_filsys fs, const char *path, char *buf, size_t bufsize) {
    ext2_ino_t ino = string_to_inode(fs, path, 0);
    if (!ino) return -ENOENT;

    struct ext2_inode inode;
    errcode_t ret = ext2fs_read_inode(fs, ino, &inode);
    if (ret) return parse_extfs_error(fs, ino, ret);

    if (!LINUX_S_ISLNK(inode.i_mode))
        return -EINVAL;

    size_t len = bufsize - 1;
    if (inode.i_size < len)
        len = inode.i_size;

    if (is_fast_symlink(&inode)) {
        memcpy(buf, (char *)inode.i_block, len);
    } else {
        ext2_file_t file;
        unsigned int got;
        ret = ext2fs_file_open(fs, ino, 0, &file);
        if (ret) return parse_extfs_error(fs, ino, ret);
        ret = ext2fs_file_read(file, buf, len, &got);
        if (ret) {
            ext2fs_file_close(file);
            return parse_extfs_error(fs, ino, ret);
        }
        ret = ext2fs_file_close(file);
        if (ret) return parse_extfs_error(fs, ino, ret);
        if (got != len) return -EINVAL;
    }
    buf[len] = 0;

    return (len + 1);
}