mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
Kernel: Port more code to KResult and KResultOr<T>.
This commit is contained in:
parent
3079ef01ce
commit
028afabf6b
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue