in fs/extfs/extfs.cpp [532:580]
static int do_ext2fs_symlink(ext2_filsys fs, const char *src, const char *dest) {
ext2_ino_t parent, ino;
errcode_t ret = 0;
DEFER(LOG_DEBUG("symlink ", 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);
}
/* Create symlink */
ret = ext2fs_symlink(fs, parent, 0, filename, src);
if (ret == EXT2_ET_DIR_NO_SPACE) {
ret = ext2fs_expand_dir(fs, parent);
if (ret) return parse_extfs_error(fs, parent, ret);
ret = ext2fs_symlink(fs, parent, 0, filename, src);
}
if (ret) return parse_extfs_error(fs, parent, ret);
/* Update parent dir's mtime */
ret = update_xtime(fs, parent, nullptr, EXT_CTIME | EXT_MTIME);
if (ret) return ret;
/* Still have to update the uid/gid of the symlink */
ino = string_to_inode(fs, dest, 0);
if (ino == 0) {
return -(ret = ENOTDIR);
}
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);
ret = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, sizeof(inode));
if (ret) return parse_extfs_error(fs, ino, ret);
return 0;
}