Kernel/LibC: Add support for creating hardlinks
This commit is contained in:
parent
12abe81c6d
commit
713daf6cd3
|
@ -36,6 +36,7 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override;
|
||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override;
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
|
||||
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||
|
|
|
@ -95,6 +95,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<size_t> list_next_inodes(off_t, struct dirent* list, size_t list_size);
|
||||
BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t);
|
||||
BAN::ErrorOr<void> create_directory(BAN::StringView, mode_t, uid_t, gid_t);
|
||||
BAN::ErrorOr<void> link_inode(BAN::StringView, BAN::RefPtr<Inode>);
|
||||
BAN::ErrorOr<void> unlink(BAN::StringView);
|
||||
|
||||
// Link API
|
||||
|
@ -131,6 +132,7 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
// Link API
|
||||
|
|
|
@ -110,6 +110,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> sys_write(int fd, const void* buffer, size_t count);
|
||||
BAN::ErrorOr<long> sys_access(const char* path, int amode);
|
||||
BAN::ErrorOr<long> sys_create_dir(const char*, mode_t);
|
||||
BAN::ErrorOr<long> sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag);
|
||||
BAN::ErrorOr<long> sys_unlink(const char*);
|
||||
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
|
||||
|
||||
|
|
|
@ -518,6 +518,23 @@ done:
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::link_inode_impl(BAN::StringView name, BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
ASSERT(this->mode().ifdir());
|
||||
ASSERT(!inode->mode().ifdir());
|
||||
|
||||
if (&m_fs != inode->filesystem())
|
||||
return BAN::Error::from_errno(EXDEV);
|
||||
|
||||
if (!find_inode_impl(name).is_error())
|
||||
return BAN::Error::from_errno(EEXIST);
|
||||
|
||||
auto ext2_inode = static_cast<Ext2Inode*>(inode.ptr());
|
||||
TRY(link_inode_to_directory(*ext2_inode, name));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::link_inode_to_directory(Ext2Inode& inode, BAN::StringView name)
|
||||
{
|
||||
if (!this->mode().ifdir())
|
||||
|
|
|
@ -93,6 +93,16 @@ namespace Kernel
|
|||
return create_directory_impl(name, mode, uid, gid);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::link_inode(BAN::StringView name, BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
if (!this->mode().ifdir())
|
||||
return BAN::Error::from_errno(ENOTDIR);
|
||||
if (inode->mode().ifdir())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
return link_inode_impl(name, inode);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::unlink(BAN::StringView name)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
|
|
@ -1042,6 +1042,40 @@ namespace Kernel
|
|||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_string_access(path1));
|
||||
TRY(validate_string_access(path2));
|
||||
|
||||
auto inode = TRY(find_file(fd1, path1, flag)).inode;
|
||||
if (inode->mode().ifdir())
|
||||
return BAN::Error::from_errno(EISDIR);
|
||||
|
||||
auto parent = TRY(find_parent(fd2, path2));
|
||||
|
||||
BAN::RefPtr<Inode> parent_inode;
|
||||
BAN::StringView file_name;
|
||||
|
||||
BAN::StringView path2_sv = path2;
|
||||
if (auto index = path2_sv.rfind('/'); index.has_value())
|
||||
{
|
||||
parent_inode = TRY(VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, path2_sv.substring(0, index.value()), O_EXEC | O_WRONLY)).inode;
|
||||
file_name = path2_sv.substring(index.value() + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent_inode = parent.inode;
|
||||
file_name = path2_sv;
|
||||
if (!parent_inode->can_access(m_credentials, O_WRONLY))
|
||||
return BAN::Error::from_errno(EACCES);
|
||||
}
|
||||
|
||||
ASSERT(parent_inode->mode().ifdir());
|
||||
TRY(parent_inode->link_inode(file_name, inode));
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_unlink(const char* path)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
|
|
|
@ -90,6 +90,7 @@ __BEGIN_DECLS
|
|||
O(SYS_PTSNAME, ptsname) \
|
||||
O(SYS_FSYNC, fsync) \
|
||||
O(SYS_SYMLINKAT, symlinkat) \
|
||||
O(SYS_HARDLINKAT, hardlinkat) \
|
||||
|
||||
enum Syscall
|
||||
{
|
||||
|
|
|
@ -630,3 +630,13 @@ int symlinkat(const char* path1, int fd, const char* path2)
|
|||
{
|
||||
return syscall(SYS_SYMLINKAT, path1, fd, path2);
|
||||
}
|
||||
|
||||
int link(const char* path1, const char* path2)
|
||||
{
|
||||
return linkat(AT_FDCWD, path1, AT_FDCWD, path2, 0);
|
||||
}
|
||||
|
||||
int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag)
|
||||
{
|
||||
return syscall(SYS_HARDLINKAT, fd1, path1, fd2, path2, flag);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue