Kernel: Port more code to KResult and KResultOr<T>.

This commit is contained in:
Andreas Kling 2019-03-06 22:14:31 +01:00
parent 3079ef01ce
commit 028afabf6b
15 changed files with 155 additions and 198 deletions

View file

@ -13,9 +13,9 @@ Device::~Device()
VFS::the().unregister_device(*this);
}
RetainPtr<FileDescriptor> Device::open(int& error, int options)
KResultOr<Retained<FileDescriptor>> Device::open(int options)
{
return VFS::the().open(*this, error, options);
return VFS::the().open(*this, options);
}
void Device::close()

View file

@ -13,7 +13,7 @@ public:
InodeMetadata metadata() const { return { }; }
virtual RetainPtr<FileDescriptor> open(int& error, int options);
virtual KResultOr<Retained<FileDescriptor>> open(int options);
virtual void close();
virtual bool can_read(Process&) const = 0;

View file

@ -86,7 +86,7 @@ public:
ByteBuffer& generator_cache() { return m_generator_cache; }
void set_original_inode(Badge<VFS>, RetainPtr<Inode>&& inode) { m_inode = move(inode); }
void set_original_inode(Badge<VFS>, Retained<Inode>&& inode) { m_inode = move(inode); }
void set_socket_role(SocketRole);

View file

@ -34,6 +34,19 @@ public:
new (&m_storage) T(move(value));
}
template<typename U>
KResultOr(U&& value)
{
new (&m_storage) T(move(value));
}
KResultOr(KResultOr&& other)
{
new (&m_storage) T(move(other.value()));
other.m_is_error = true;
other.m_error = KSuccess;
}
~KResultOr()
{
if (!m_is_error)

View file

@ -126,14 +126,10 @@ void init_ksyms()
void load_ksyms()
{
int error;
auto descriptor = VFS::the().open("/kernel.map", error, 0, 0, *VFS::the().root_inode());
if (!descriptor) {
kprintf("Failed to open /kernel.map\n");
} else {
auto buffer = descriptor->read_entire_file(*current);
ASSERT(buffer);
load_ksyms_from_data(buffer);
}
auto result = VFS::the().open("/kernel.map", 0, 0, *VFS::the().root_inode());
ASSERT(!result.is_error());
auto descriptor = result.value();
auto buffer = descriptor->read_entire_file(*current);
ASSERT(buffer);
load_ksyms_from_data(buffer);
}

View file

@ -33,17 +33,13 @@ bool LocalSocket::get_address(sockaddr* address, socklen_t* address_size)
return true;
}
bool LocalSocket::bind(const sockaddr* address, socklen_t address_size, int& error)
KResult LocalSocket::bind(const sockaddr* address, socklen_t address_size)
{
ASSERT(!is_connected());
if (address_size != sizeof(sockaddr_un)) {
error = -EINVAL;
return false;
}
if (address->sa_family != AF_LOCAL) {
error = -EINVAL;
return false;
}
if (address_size != sizeof(sockaddr_un))
return KResult(-EINVAL);
if (address->sa_family != AF_LOCAL)
return KResult(-EINVAL);
const sockaddr_un& local_address = *reinterpret_cast<const sockaddr_un*>(address);
char safe_address[sizeof(local_address.sun_path) + 1];
@ -53,32 +49,29 @@ bool LocalSocket::bind(const sockaddr* address, socklen_t address_size, int& err
kprintf("%s(%u) LocalSocket{%p} bind(%s)\n", current->name().characters(), current->pid(), this, safe_address);
#endif
m_file = VFS::the().open(safe_address, error, O_CREAT | O_EXCL, S_IFSOCK | 0666, current->cwd_inode());
if (!m_file) {
if (error == -EEXIST)
error = -EADDRINUSE;
return false;
auto result = VFS::the().open(safe_address, O_CREAT | O_EXCL, S_IFSOCK | 0666, current->cwd_inode());
if (result.is_error()) {
if (result.error() == -EEXIST)
return KResult(-EADDRINUSE);
return result.error();
}
m_file = move(result.value());
ASSERT(m_file->inode());
m_file->inode()->bind_socket(*this);
m_address = local_address;
m_bound = true;
return true;
return KSuccess;
}
bool LocalSocket::connect(const sockaddr* address, socklen_t address_size, int& error)
KResult LocalSocket::connect(const sockaddr* address, socklen_t address_size)
{
ASSERT(!m_bound);
if (address_size != sizeof(sockaddr_un)) {
error = -EINVAL;
return false;
}
if (address->sa_family != AF_LOCAL) {
error = -EINVAL;
return false;
}
if (address_size != sizeof(sockaddr_un))
return KResult(-EINVAL);
if (address->sa_family != AF_LOCAL)
return KResult(-EINVAL);
const sockaddr_un& local_address = *reinterpret_cast<const sockaddr_un*>(address);
char safe_address[sizeof(local_address.sun_path) + 1];
@ -88,36 +81,23 @@ bool LocalSocket::connect(const sockaddr* address, socklen_t address_size, int&
kprintf("%s(%u) LocalSocket{%p} connect(%s)\n", current->name().characters(), current->pid(), this, safe_address);
#endif
m_file = VFS::the().open(safe_address, error, 0, 0, current->cwd_inode());
if (!m_file) {
error = -ECONNREFUSED;
return false;
}
auto descriptor_or_error = VFS::the().open(safe_address, 0, 0, current->cwd_inode());
if (descriptor_or_error.is_error())
return KResult(-ECONNREFUSED);
m_file = move(descriptor_or_error.value());
ASSERT(m_file->inode());
if (!m_file->inode()->socket()) {
error = -ECONNREFUSED;
return false;
}
if (!m_file->inode()->socket())
return KResult(-ECONNREFUSED);
m_address = local_address;
auto peer = m_file->inode()->socket();
#ifdef DEBUG_LOCAL_SOCKET
kprintf("Queueing up connection\n");
#endif
if (!peer->queue_connection_from(*this, error))
return false;
auto result = peer->queue_connection_from(*this);
if (result.is_error())
return result;
#ifdef DEBUG_LOCAL_SOCKET
kprintf("Waiting for connect...\n");
#endif
if (!current->wait_for_connect(*this, error))
return false;
#ifdef DEBUG_LOCAL_SOCKET
kprintf("CONNECTED!\n");
#endif
return true;
return current->wait_for_connect(*this);
}
void LocalSocket::attach_fd(SocketRole role)

View file

@ -10,8 +10,8 @@ public:
static Retained<LocalSocket> create(int type);
virtual ~LocalSocket() override;
virtual bool bind(const sockaddr*, socklen_t, int& error) override;
virtual bool connect(const sockaddr*, socklen_t, int& error) override;
virtual KResult bind(const sockaddr*, socklen_t) override;
virtual KResult connect(const sockaddr*, socklen_t) override;
virtual bool get_address(sockaddr*, socklen_t*) override;
virtual void attach_fd(SocketRole) override;
virtual void detach_fd(SocketRole) override;

View file

@ -26,17 +26,15 @@ PTYMultiplexer::~PTYMultiplexer()
{
}
RetainPtr<FileDescriptor> PTYMultiplexer::open(int& error, int options)
KResultOr<Retained<FileDescriptor>> PTYMultiplexer::open(int options)
{
LOCKER(m_lock);
if (m_freelist.is_empty()) {
error = -EBUSY;
return nullptr;
}
if (m_freelist.is_empty())
return KResult(-EBUSY);
auto master_index = m_freelist.take_last();
auto master = adopt(*new MasterPTY(master_index));
dbgprintf("PTYMultiplexer::open: Vending master %u\n", master->index());
return VFS::the().open(move(master), error, options);
return VFS::the().open(move(master), options);
}
void PTYMultiplexer::notify_master_destroyed(Badge<MasterPTY>, unsigned index)

View file

@ -15,7 +15,7 @@ public:
static PTYMultiplexer& the();
// ^CharacterDevice
virtual RetainPtr<FileDescriptor> open(int& error, int options) override;
virtual KResultOr<Retained<FileDescriptor>> open(int options) override;
virtual ssize_t read(Process&, byte*, ssize_t) override { return 0; }
virtual ssize_t write(Process&, const byte*, ssize_t) override { return 0; }
virtual bool can_read(Process&) const override { return true; }

View file

@ -293,12 +293,10 @@ int Process::do_exec(String path, Vector<String> arguments, Vector<String> envir
if (parts.is_empty())
return -ENOENT;
int error;
auto descriptor = VFS::the().open(path, error, 0, 0, cwd_inode());
if (!descriptor) {
ASSERT(error != 0);
return error;
}
auto result = VFS::the().open(path, 0, 0, cwd_inode());
if (result.is_error())
return result.error();
auto descriptor = result.value();
if (!descriptor->metadata().may_execute(m_euid, m_gids))
return -EACCES;
@ -644,10 +642,9 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t ppid, RingLevel ring
} else {
m_fds.resize(m_max_open_file_descriptors);
auto& device_to_use_as_tty = tty ? (CharacterDevice&)*tty : NullDevice::the();
int error;
m_fds[0].set(device_to_use_as_tty.open(error, O_RDONLY));
m_fds[1].set(device_to_use_as_tty.open(error, O_WRONLY));
m_fds[2].set(device_to_use_as_tty.open(error, O_WRONLY));
m_fds[0].set(*device_to_use_as_tty.open(O_RDONLY).value());
m_fds[1].set(*device_to_use_as_tty.open(O_WRONLY).value());
m_fds[2].set(*device_to_use_as_tty.open(O_WRONLY).value());
}
if (fork_parent)
@ -1306,7 +1303,7 @@ int Process::sys$fcntl(int fd, int cmd, dword arg)
}
if (new_fd == -1)
return -EMFILE;
m_fds[new_fd].set(descriptor);
m_fds[new_fd].set(*descriptor);
break;
}
case F_GETFD:
@ -1359,10 +1356,10 @@ int Process::sys$readlink(const char* path, char* buffer, ssize_t size)
if (!validate_write(buffer, size))
return -EFAULT;
int error;
auto descriptor = VFS::the().open(path, error, O_RDONLY | O_NOFOLLOW_NOERROR, 0, cwd_inode());
if (!descriptor)
return error;
auto result = VFS::the().open(path, O_RDONLY | O_NOFOLLOW_NOERROR, 0, cwd_inode());
if (result.is_error())
return result.error();
auto descriptor = result.value();
if (!descriptor->metadata().is_symlink())
return -EINVAL;
@ -1422,10 +1419,11 @@ int Process::sys$open(const char* path, int options, mode_t mode)
return -EFAULT;
if (number_of_open_file_descriptors() >= m_max_open_file_descriptors)
return -EMFILE;
int error = -EWHYTHO;
auto descriptor = VFS::the().open(path, error, options, mode & ~umask(), cwd_inode());
if (!descriptor)
return error;
auto result = VFS::the().open(path, options, mode & ~umask(), cwd_inode());
if (result.is_error())
return result.error();
auto descriptor = result.value();
if (options & O_DIRECTORY && !descriptor->is_directory())
return -ENOTDIR; // FIXME: This should be handled by VFS::open.
if (options & O_NONBLOCK)
@ -1952,7 +1950,7 @@ int Process::sys$dup(int old_fd)
if (!m_fds[new_fd])
break;
}
m_fds[new_fd].set(descriptor);
m_fds[new_fd].set(*descriptor);
return new_fd;
}
@ -1963,7 +1961,7 @@ int Process::sys$dup2(int old_fd, int new_fd)
return -EBADF;
if (number_of_open_file_descriptors() == m_max_open_file_descriptors)
return -EMFILE;
m_fds[new_fd].set(descriptor);
m_fds[new_fd].set(*descriptor);
return new_fd;
}
@ -2400,11 +2398,10 @@ int Process::sys$socket(int domain, int type, int protocol)
if (!m_fds[fd])
break;
}
int error;
auto socket = Socket::create(domain, type, protocol, error);
if (!socket)
return error;
auto descriptor = FileDescriptor::create(move(socket));
auto result = Socket::create(domain, type, protocol);
if (result.is_error())
return result.error();
auto descriptor = FileDescriptor::create(*result.value());
unsigned flags = 0;
if (type & SOCK_CLOEXEC)
flags |= FD_CLOEXEC;
@ -2424,10 +2421,7 @@ int Process::sys$bind(int sockfd, const sockaddr* address, socklen_t address_len
if (!descriptor->is_socket())
return -ENOTSOCK;
auto& socket = *descriptor->socket();
int error;
if (!socket.bind(address, address_length, error))
return error;
return 0;
return socket.bind(address, address_length);
}
int Process::sys$listen(int sockfd, int backlog)
@ -2438,9 +2432,9 @@ int Process::sys$listen(int sockfd, int backlog)
if (!descriptor->is_socket())
return -ENOTSOCK;
auto& socket = *descriptor->socket();
int error;
if (!socket.listen(backlog, error))
return error;
auto result = socket.listen(backlog);
if (result.is_error())
return result;
descriptor->set_socket_role(SocketRole::Listener);
return 0;
}
@ -2497,26 +2491,24 @@ int Process::sys$connect(int sockfd, const sockaddr* address, socklen_t address_
if (!descriptor->is_socket())
return -ENOTSOCK;
auto& socket = *descriptor->socket();
int error;
if (!socket.connect(address, address_size, error))
return error;
auto result = socket.connect(address, address_size);
if (result.is_error())
return result;
descriptor->set_socket_role(SocketRole::Connected);
return 0;
}
bool Process::wait_for_connect(Socket& socket, int& error)
KResult Process::wait_for_connect(Socket& socket)
{
if (socket.is_connected())
return true;
return KSuccess;
m_blocked_connecting_socket = socket;
block(BlockedConnect);
Scheduler::yield();
m_blocked_connecting_socket = nullptr;
if (!socket.is_connected()) {
error = -ECONNREFUSED;
return false;
}
return true;
if (!socket.is_connected())
return KResult(-ECONNREFUSED);
return KSuccess;
}
struct SharedBuffer {

View file

@ -236,7 +236,7 @@ public:
void* sys$get_shared_buffer(int shared_buffer_id);
int sys$release_shared_buffer(int shared_buffer_id);
bool wait_for_connect(Socket&, int& error);
KResult wait_for_connect(Socket&);
static void initialize();
@ -349,7 +349,7 @@ private:
struct FileDescriptorAndFlags {
operator bool() const { return !!descriptor; }
void clear() { descriptor = nullptr; flags = 0; }
void set(RetainPtr<FileDescriptor>&& d, dword f = 0) { descriptor = move(d); flags = f; }
void set(Retained<FileDescriptor>&& d, dword f = 0) { descriptor = move(d); flags = f; }
RetainPtr<FileDescriptor> descriptor;
dword flags { 0 };
};

View file

@ -4,15 +4,14 @@
#include <Kernel/Process.h>
#include <LibC/errno_numbers.h>
RetainPtr<Socket> Socket::create(int domain, int type, int protocol, int& error)
KResultOr<Retained<Socket>> Socket::create(int domain, int type, int protocol)
{
(void)protocol;
switch (domain) {
case AF_LOCAL:
return LocalSocket::create(type & SOCK_TYPE_MASK);
default:
error = EAFNOSUPPORT;
return nullptr;
return KResult(-EAFNOSUPPORT);
}
}
@ -28,16 +27,14 @@ Socket::~Socket()
{
}
bool Socket::listen(int backlog, int& error)
KResult Socket::listen(int backlog)
{
LOCKER(m_lock);
if (m_type != SOCK_STREAM) {
error = -EOPNOTSUPP;
return false;
}
if (m_type != SOCK_STREAM)
return KResult(-EOPNOTSUPP);
m_backlog = backlog;
kprintf("Socket{%p} listening with backlog=%d\n", this, m_backlog);
return true;
return KSuccess;
}
RetainPtr<Socket> Socket::accept()
@ -52,13 +49,11 @@ RetainPtr<Socket> Socket::accept()
return client;
}
bool Socket::queue_connection_from(Socket& peer, int& error)
KResult Socket::queue_connection_from(Socket& peer)
{
LOCKER(m_lock);
if (m_pending.size() >= m_backlog) {
error = -ECONNREFUSED;
return false;
}
if (m_pending.size() >= m_backlog)
return KResult(-ECONNREFUSED);
m_pending.append(peer);
return true;
return KSuccess;
}

View file

@ -6,12 +6,13 @@
#include <AK/HashTable.h>
#include <AK/Vector.h>
#include <Kernel/UnixTypes.h>
#include <Kernel/KResult.h>
enum class SocketRole { None, Listener, Accepted, Connected };
class Socket : public Retainable<Socket> {
public:
static RetainPtr<Socket> create(int domain, int type, int protocol, int& error);
static KResultOr<Retained<Socket>> create(int domain, int type, int protocol);
virtual ~Socket();
int domain() const { return m_domain; }
@ -21,10 +22,10 @@ public:
bool can_accept() const { return !m_pending.is_empty(); }
RetainPtr<Socket> accept();
bool is_connected() const { return m_connected; }
bool listen(int backlog, int& error);
KResult listen(int backlog);
virtual bool bind(const sockaddr*, socklen_t, int& error) = 0;
virtual bool connect(const sockaddr*, socklen_t, int& error) = 0;
virtual KResult bind(const sockaddr*, socklen_t) = 0;
virtual KResult connect(const sockaddr*, socklen_t) = 0;
virtual bool get_address(sockaddr*, socklen_t*) = 0;
virtual bool is_local() const { return false; }
virtual void attach_fd(SocketRole) = 0;
@ -39,7 +40,7 @@ public:
protected:
Socket(int domain, int type, int protocol);
bool queue_connection_from(Socket&, int& error);
KResult queue_connection_from(Socket&);
private:
Lock m_lock;

View file

@ -123,26 +123,25 @@ void VFS::traverse_directory_inode(Inode& dir_inode, Function<bool(const FS::Dir
});
}
RetainPtr<FileDescriptor> VFS::open(RetainPtr<Device>&& device, int& error, int options)
KResultOr<Retained<FileDescriptor>> VFS::open(RetainPtr<Device>&& device, int options)
{
// FIXME: Respect options.
(void) options;
(void) error;
(void)options;
return FileDescriptor::create(move(device));
}
KResult VFS::utime(const String& path, Inode& base, time_t atime, time_t mtime)
{
int error;
auto descriptor = VFS::the().open(move(path), error, 0, 0, base);
if (!descriptor)
return KResult(error);
auto& inode = *descriptor->inode();
auto descriptor_or_error = VFS::the().open(move(path), 0, 0, base);
if (descriptor_or_error.is_error())
return descriptor_or_error.error();
auto& inode = *descriptor_or_error.value()->inode();
if (inode.fs().is_readonly())
return KResult(-EROFS);
if (inode.metadata().uid != current->euid())
return KResult(-EACCES);
error = inode.set_atime(atime);
int error = inode.set_atime(atime);
if (error)
return KResult(error);
error = inode.set_mtime(mtime);
@ -159,60 +158,50 @@ KResult VFS::stat(const String& path, int options, Inode& base, struct stat& sta
return FileDescriptor::create(inode_or_error.value().ptr())->fstat(statbuf);
}
RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options, mode_t mode, Inode& base)
KResultOr<Retained<FileDescriptor>> VFS::open(const String& path, int options, mode_t mode, Inode& base)
{
auto inode_id = old_resolve_path(path, base.identifier(), error, options);
auto inode = get_inode(inode_id);
auto inode_or_error = resolve_path_to_inode(path, base, nullptr, options);
if (options & O_CREAT) {
if (!inode)
return create(path, error, options, mode, base);
else if (options & O_EXCL) {
error = -EEXIST;
return nullptr;
}
if (inode_or_error.is_error())
return create(path, options, mode, base);
if (options & O_EXCL)
return KResult(-EEXIST);
}
if (!inode)
return nullptr;
if (inode_or_error.is_error())
return inode_or_error.error();
auto metadata = inode->metadata();
auto metadata = inode_or_error.value()->metadata();
// NOTE: Read permission is a bit weird, since O_RDONLY == 0,
// so we check if (NOT write_only OR read_and_write)
if (!(options & O_WRONLY) || (options & O_RDWR)) {
if (!metadata.may_read(*current)) {
error = -EACCES;
return nullptr;
}
if (!metadata.may_read(*current))
return KResult(-EACCES);
}
if ((options & O_WRONLY) || (options & O_RDWR)) {
if (!metadata.may_write(*current)) {
error = -EACCES;
return nullptr;
}
if (metadata.is_directory()) {
error = -EISDIR;
return nullptr;
}
if (!metadata.may_write(*current))
return KResult(-EACCES);
if (metadata.is_directory())
return KResult(-EISDIR);
}
if (metadata.is_device()) {
auto it = m_devices.find(encoded_device(metadata.major_device, metadata.minor_device));
if (it == m_devices.end()) {
kprintf("VFS::open: no such device %u,%u\n", metadata.major_device, metadata.minor_device);
error = -ENODEV;
return nullptr;
return KResult(-ENODEV);
}
auto descriptor = (*it).value->open(error, options);
descriptor->set_original_inode(Badge<VFS>(), move(inode));
auto descriptor = (*it).value->open(options);
ASSERT(!descriptor.is_error());
descriptor.value()->set_original_inode(Badge<VFS>(), *inode_or_error.value());
return descriptor;
}
return FileDescriptor::create(move(inode));
return FileDescriptor::create(*inode_or_error.value());
}
RetainPtr<FileDescriptor> VFS::create(const String& path, int& error, int options, mode_t mode, Inode& base)
KResultOr<Retained<FileDescriptor>> VFS::create(const String& path, int options, mode_t mode, Inode& base)
{
(void) options;
error = -EWHYTHO;
(void)options;
if (!is_socket(mode) && !is_fifo(mode) && !is_block_device(mode) && !is_character_device(mode)) {
// Turn it into a regular file. (This feels rather hackish.)
@ -220,30 +209,23 @@ RetainPtr<FileDescriptor> VFS::create(const String& path, int& error, int option
}
RetainPtr<Inode> parent_inode;
auto existing_file = resolve_path_to_inode(path, base, error, &parent_inode);
if (existing_file) {
error = -EEXIST;
return nullptr;
}
if (!parent_inode) {
error = -ENOENT;
return nullptr;
}
if (error != -ENOENT) {
return nullptr;
}
if (!parent_inode->metadata().may_write(*current)) {
error = -EACCES;
return nullptr;
}
auto existing_file_or_error = resolve_path_to_inode(path, base, &parent_inode);
if (!existing_file_or_error.is_error())
return KResult(-EEXIST);
if (!parent_inode)
return KResult(-ENOENT);
if (existing_file_or_error.error() != -ENOENT)
return existing_file_or_error.error();
if (!parent_inode->metadata().may_write(*current))
return KResult(-EACCES);
FileSystemPath p(path);
dbgprintf("VFS::create_file: '%s' in %u:%u\n", p.basename().characters(), parent_inode->fsid(), parent_inode->index());
int error;
auto new_file = parent_inode->fs().create_inode(parent_inode->identifier(), p.basename(), mode, 0, error);
if (!new_file)
return nullptr;
return KResult(error);
error = 0;
return FileDescriptor::create(move(new_file));
}

View file

@ -62,9 +62,9 @@ public:
bool mount_root(RetainPtr<FS>&&);
bool mount(RetainPtr<FS>&&, const String& path);
RetainPtr<FileDescriptor> open(RetainPtr<Device>&&, int& error, int options);
RetainPtr<FileDescriptor> open(const String& path, int& error, int options, mode_t mode, Inode& base);
RetainPtr<FileDescriptor> create(const String& path, int& error, int options, mode_t mode, Inode& base);
KResultOr<Retained<FileDescriptor>> open(RetainPtr<Device>&&, int options);
KResultOr<Retained<FileDescriptor>> open(const String& path, int options, mode_t mode, Inode& base);
KResultOr<Retained<FileDescriptor>> create(const String& path, int options, mode_t mode, Inode& base);
KResult mkdir(const String& path, mode_t mode, Inode& base);
KResult link(const String& old_path, const String& new_path, Inode& base);
KResult unlink(const String& path, Inode& base);