1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 13:28:11 +00:00

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); 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() void Device::close()

View file

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

View file

@ -86,7 +86,7 @@ public:
ByteBuffer& generator_cache() { return m_generator_cache; } 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); void set_socket_role(SocketRole);

View file

@ -34,6 +34,19 @@ public:
new (&m_storage) T(move(value)); 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() ~KResultOr()
{ {
if (!m_is_error) if (!m_is_error)

View file

@ -126,14 +126,10 @@ void init_ksyms()
void load_ksyms() void load_ksyms()
{ {
int error; auto result = VFS::the().open("/kernel.map", 0, 0, *VFS::the().root_inode());
auto descriptor = VFS::the().open("/kernel.map", error, 0, 0, *VFS::the().root_inode()); ASSERT(!result.is_error());
if (!descriptor) { auto descriptor = result.value();
kprintf("Failed to open /kernel.map\n"); auto buffer = descriptor->read_entire_file(*current);
} else { ASSERT(buffer);
auto buffer = descriptor->read_entire_file(*current); load_ksyms_from_data(buffer);
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; 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()); ASSERT(!is_connected());
if (address_size != sizeof(sockaddr_un)) { if (address_size != sizeof(sockaddr_un))
error = -EINVAL; return KResult(-EINVAL);
return false; if (address->sa_family != AF_LOCAL)
} return KResult(-EINVAL);
if (address->sa_family != AF_LOCAL) {
error = -EINVAL;
return false;
}
const sockaddr_un& local_address = *reinterpret_cast<const sockaddr_un*>(address); const sockaddr_un& local_address = *reinterpret_cast<const sockaddr_un*>(address);
char safe_address[sizeof(local_address.sun_path) + 1]; 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); kprintf("%s(%u) LocalSocket{%p} bind(%s)\n", current->name().characters(), current->pid(), this, safe_address);
#endif #endif
m_file = VFS::the().open(safe_address, error, O_CREAT | O_EXCL, S_IFSOCK | 0666, current->cwd_inode()); auto result = VFS::the().open(safe_address, O_CREAT | O_EXCL, S_IFSOCK | 0666, current->cwd_inode());
if (!m_file) { if (result.is_error()) {
if (error == -EEXIST) if (result.error() == -EEXIST)
error = -EADDRINUSE; return KResult(-EADDRINUSE);
return false; return result.error();
} }
m_file = move(result.value());
ASSERT(m_file->inode()); ASSERT(m_file->inode());
m_file->inode()->bind_socket(*this); m_file->inode()->bind_socket(*this);
m_address = local_address; m_address = local_address;
m_bound = true; 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); ASSERT(!m_bound);
if (address_size != sizeof(sockaddr_un)) { if (address_size != sizeof(sockaddr_un))
error = -EINVAL; return KResult(-EINVAL);
return false; if (address->sa_family != AF_LOCAL)
} return KResult(-EINVAL);
if (address->sa_family != AF_LOCAL) {
error = -EINVAL;
return false;
}
const sockaddr_un& local_address = *reinterpret_cast<const sockaddr_un*>(address); const sockaddr_un& local_address = *reinterpret_cast<const sockaddr_un*>(address);
char safe_address[sizeof(local_address.sun_path) + 1]; 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); kprintf("%s(%u) LocalSocket{%p} connect(%s)\n", current->name().characters(), current->pid(), this, safe_address);
#endif #endif
m_file = VFS::the().open(safe_address, error, 0, 0, current->cwd_inode()); auto descriptor_or_error = VFS::the().open(safe_address, 0, 0, current->cwd_inode());
if (!m_file) { if (descriptor_or_error.is_error())
error = -ECONNREFUSED; return KResult(-ECONNREFUSED);
return false; m_file = move(descriptor_or_error.value());
}
ASSERT(m_file->inode()); ASSERT(m_file->inode());
if (!m_file->inode()->socket()) { if (!m_file->inode()->socket())
error = -ECONNREFUSED; return KResult(-ECONNREFUSED);
return false;
}
m_address = local_address; m_address = local_address;
auto peer = m_file->inode()->socket(); auto peer = m_file->inode()->socket();
#ifdef DEBUG_LOCAL_SOCKET auto result = peer->queue_connection_from(*this);
kprintf("Queueing up connection\n"); if (result.is_error())
#endif return result;
if (!peer->queue_connection_from(*this, error))
return false;
#ifdef DEBUG_LOCAL_SOCKET return current->wait_for_connect(*this);
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;
} }
void LocalSocket::attach_fd(SocketRole role) void LocalSocket::attach_fd(SocketRole role)

View file

@ -10,8 +10,8 @@ public:
static Retained<LocalSocket> create(int type); static Retained<LocalSocket> create(int type);
virtual ~LocalSocket() override; virtual ~LocalSocket() override;
virtual bool bind(const sockaddr*, socklen_t, int& error) override; virtual KResult bind(const sockaddr*, socklen_t) override;
virtual bool connect(const sockaddr*, socklen_t, int& error) override; virtual KResult connect(const sockaddr*, socklen_t) override;
virtual bool get_address(sockaddr*, socklen_t*) override; virtual bool get_address(sockaddr*, socklen_t*) override;
virtual void attach_fd(SocketRole) override; virtual void attach_fd(SocketRole) override;
virtual void detach_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); LOCKER(m_lock);
if (m_freelist.is_empty()) { if (m_freelist.is_empty())
error = -EBUSY; return KResult(-EBUSY);
return nullptr;
}
auto master_index = m_freelist.take_last(); auto master_index = m_freelist.take_last();
auto master = adopt(*new MasterPTY(master_index)); auto master = adopt(*new MasterPTY(master_index));
dbgprintf("PTYMultiplexer::open: Vending master %u\n", 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) void PTYMultiplexer::notify_master_destroyed(Badge<MasterPTY>, unsigned index)

View file

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

View file

@ -236,7 +236,7 @@ public:
void* sys$get_shared_buffer(int shared_buffer_id); void* sys$get_shared_buffer(int shared_buffer_id);
int sys$release_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(); static void initialize();
@ -349,7 +349,7 @@ private:
struct FileDescriptorAndFlags { struct FileDescriptorAndFlags {
operator bool() const { return !!descriptor; } operator bool() const { return !!descriptor; }
void clear() { descriptor = nullptr; flags = 0; } 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; RetainPtr<FileDescriptor> descriptor;
dword flags { 0 }; dword flags { 0 };
}; };

View file

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

View file

@ -6,12 +6,13 @@
#include <AK/HashTable.h> #include <AK/HashTable.h>
#include <AK/Vector.h> #include <AK/Vector.h>
#include <Kernel/UnixTypes.h> #include <Kernel/UnixTypes.h>
#include <Kernel/KResult.h>
enum class SocketRole { None, Listener, Accepted, Connected }; enum class SocketRole { None, Listener, Accepted, Connected };
class Socket : public Retainable<Socket> { class Socket : public Retainable<Socket> {
public: 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(); virtual ~Socket();
int domain() const { return m_domain; } int domain() const { return m_domain; }
@ -21,10 +22,10 @@ public:
bool can_accept() const { return !m_pending.is_empty(); } bool can_accept() const { return !m_pending.is_empty(); }
RetainPtr<Socket> accept(); RetainPtr<Socket> accept();
bool is_connected() const { return m_connected; } 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 KResult bind(const sockaddr*, socklen_t) = 0;
virtual bool connect(const sockaddr*, socklen_t, int& error) = 0; virtual KResult connect(const sockaddr*, socklen_t) = 0;
virtual bool get_address(sockaddr*, socklen_t*) = 0; virtual bool get_address(sockaddr*, socklen_t*) = 0;
virtual bool is_local() const { return false; } virtual bool is_local() const { return false; }
virtual void attach_fd(SocketRole) = 0; virtual void attach_fd(SocketRole) = 0;
@ -39,7 +40,7 @@ public:
protected: protected:
Socket(int domain, int type, int protocol); Socket(int domain, int type, int protocol);
bool queue_connection_from(Socket&, int& error); KResult queue_connection_from(Socket&);
private: private:
Lock m_lock; 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. // FIXME: Respect options.
(void) options; (void)options;
(void) error;
return FileDescriptor::create(move(device)); return FileDescriptor::create(move(device));
} }
KResult VFS::utime(const String& path, Inode& base, time_t atime, time_t mtime) KResult VFS::utime(const String& path, Inode& base, time_t atime, time_t mtime)
{ {
int error; auto descriptor_or_error = VFS::the().open(move(path), 0, 0, base);
auto descriptor = VFS::the().open(move(path), error, 0, 0, base); if (descriptor_or_error.is_error())
if (!descriptor) return descriptor_or_error.error();
return KResult(error); auto& inode = *descriptor_or_error.value()->inode();
auto& inode = *descriptor->inode();
if (inode.fs().is_readonly()) if (inode.fs().is_readonly())
return KResult(-EROFS); return KResult(-EROFS);
if (inode.metadata().uid != current->euid()) if (inode.metadata().uid != current->euid())
return KResult(-EACCES); return KResult(-EACCES);
error = inode.set_atime(atime);
int error = inode.set_atime(atime);
if (error) if (error)
return KResult(error); return KResult(error);
error = inode.set_mtime(mtime); 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); 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_or_error = resolve_path_to_inode(path, base, nullptr, options);
auto inode = get_inode(inode_id);
if (options & O_CREAT) { if (options & O_CREAT) {
if (!inode) if (inode_or_error.is_error())
return create(path, error, options, mode, base); return create(path, options, mode, base);
else if (options & O_EXCL) { if (options & O_EXCL)
error = -EEXIST; return KResult(-EEXIST);
return nullptr;
}
} }
if (!inode) if (inode_or_error.is_error())
return nullptr; 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, // NOTE: Read permission is a bit weird, since O_RDONLY == 0,
// so we check if (NOT write_only OR read_and_write) // so we check if (NOT write_only OR read_and_write)
if (!(options & O_WRONLY) || (options & O_RDWR)) { if (!(options & O_WRONLY) || (options & O_RDWR)) {
if (!metadata.may_read(*current)) { if (!metadata.may_read(*current))
error = -EACCES; return KResult(-EACCES);
return nullptr;
}
} }
if ((options & O_WRONLY) || (options & O_RDWR)) { if ((options & O_WRONLY) || (options & O_RDWR)) {
if (!metadata.may_write(*current)) { if (!metadata.may_write(*current))
error = -EACCES; return KResult(-EACCES);
return nullptr; if (metadata.is_directory())
} return KResult(-EISDIR);
if (metadata.is_directory()) {
error = -EISDIR;
return nullptr;
}
} }
if (metadata.is_device()) { if (metadata.is_device()) {
auto it = m_devices.find(encoded_device(metadata.major_device, metadata.minor_device)); auto it = m_devices.find(encoded_device(metadata.major_device, metadata.minor_device));
if (it == m_devices.end()) { if (it == m_devices.end()) {
kprintf("VFS::open: no such device %u,%u\n", metadata.major_device, metadata.minor_device); kprintf("VFS::open: no such device %u,%u\n", metadata.major_device, metadata.minor_device);
error = -ENODEV; return KResult(-ENODEV);
return nullptr;
} }
auto descriptor = (*it).value->open(error, options); auto descriptor = (*it).value->open(options);
descriptor->set_original_inode(Badge<VFS>(), move(inode)); ASSERT(!descriptor.is_error());
descriptor.value()->set_original_inode(Badge<VFS>(), *inode_or_error.value());
return descriptor; 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; (void)options;
error = -EWHYTHO;
if (!is_socket(mode) && !is_fifo(mode) && !is_block_device(mode) && !is_character_device(mode)) { 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.) // 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; RetainPtr<Inode> parent_inode;
auto existing_file = resolve_path_to_inode(path, base, error, &parent_inode); auto existing_file_or_error = resolve_path_to_inode(path, base, &parent_inode);
if (existing_file) { if (!existing_file_or_error.is_error())
error = -EEXIST; return KResult(-EEXIST);
return nullptr; if (!parent_inode)
} return KResult(-ENOENT);
if (!parent_inode) { if (existing_file_or_error.error() != -ENOENT)
error = -ENOENT; return existing_file_or_error.error();
return nullptr; if (!parent_inode->metadata().may_write(*current))
} return KResult(-EACCES);
if (error != -ENOENT) {
return nullptr;
}
if (!parent_inode->metadata().may_write(*current)) {
error = -EACCES;
return nullptr;
}
FileSystemPath p(path); FileSystemPath p(path);
dbgprintf("VFS::create_file: '%s' in %u:%u\n", p.basename().characters(), parent_inode->fsid(), parent_inode->index()); 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); auto new_file = parent_inode->fs().create_inode(parent_inode->identifier(), p.basename(), mode, 0, error);
if (!new_file) if (!new_file)
return nullptr; return KResult(error);
error = 0;
return FileDescriptor::create(move(new_file)); return FileDescriptor::create(move(new_file));
} }

View file

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