diff --git a/kernel/include/kernel/OpenFileDescriptorSet.h b/kernel/include/kernel/OpenFileDescriptorSet.h index b0882ac8..9bc33399 100644 --- a/kernel/include/kernel/OpenFileDescriptorSet.h +++ b/kernel/include/kernel/OpenFileDescriptorSet.h @@ -50,27 +50,45 @@ namespace Kernel BAN::ErrorOr file_of(int) const; BAN::ErrorOr path_of(int) const; BAN::ErrorOr> inode_of(int); - BAN::ErrorOr flags_of(int) const; + BAN::ErrorOr status_flags_of(int) const; private: struct OpenFileDescription : public BAN::RefCounted { - OpenFileDescription(VirtualFileSystem::File file, off_t offset, int flags) + OpenFileDescription(VirtualFileSystem::File file, off_t offset, int status_flags) : file(BAN::move(file)) , offset(offset) - , flags(flags) + , status_flags(status_flags) { } - BAN::RefPtr inode() const { return file.inode; } - BAN::StringView path() const { return file.canonical_path.sv(); } - VirtualFileSystem::File file; off_t offset { 0 }; - int flags { 0 }; + int status_flags; friend class BAN::RefPtr; }; + struct OpenFile + { + OpenFile() = default; + OpenFile(BAN::RefPtr description, int descriptor_flags) + : description(BAN::move(description)) + , descriptor_flags(descriptor_flags) + { } + + BAN::RefPtr inode() const { ASSERT(description); return description->file.inode; } + BAN::StringView path() const { ASSERT(description); return description->file.canonical_path.sv(); } + + int& status_flags() { ASSERT(description); return description->status_flags; } + const int& status_flags() const { ASSERT(description); return description->status_flags; } + + off_t& offset() { ASSERT(description); return description->offset; } + const off_t& offset() const { ASSERT(description); return description->offset; } + + BAN::RefPtr description; + int descriptor_flags { 0 }; + }; + BAN::ErrorOr validate_fd(int) const; BAN::ErrorOr get_free_fd() const; BAN::ErrorOr get_free_fd_pair(int fds[2]) const; @@ -78,7 +96,7 @@ namespace Kernel private: const Credentials& m_credentials; - BAN::Array, OPEN_MAX> m_open_files; + BAN::Array m_open_files; }; } diff --git a/kernel/kernel/OpenFileDescriptorSet.cpp b/kernel/kernel/OpenFileDescriptorSet.cpp index b834b00a..81486da0 100644 --- a/kernel/kernel/OpenFileDescriptorSet.cpp +++ b/kernel/kernel/OpenFileDescriptorSet.cpp @@ -36,26 +36,14 @@ namespace Kernel if (other.validate_fd(fd).is_error()) continue; - auto& open_file = other.m_open_files[fd]; + auto& open_file = m_open_files[fd]; + open_file.description = other.m_open_files[fd].description; + open_file.descriptor_flags = other.m_open_files[fd].descriptor_flags; - VirtualFileSystem::File temp_file; - temp_file.inode = open_file->inode(); - TRY(temp_file.canonical_path.append(open_file->path())); - - auto result = BAN::RefPtr::create(BAN::move(temp_file), open_file->offset, open_file->flags); - - if (result.is_error()) + if (open_file.path() == ""_sv) { - close_all(); - return result.error(); - } - - m_open_files[fd] = result.release_value(); - - if (m_open_files[fd]->path() == ""_sv) - { - ASSERT(m_open_files[fd]->inode()->is_pipe()); - static_cast(m_open_files[fd]->inode().ptr())->clone_writing(); + ASSERT(open_file.inode()->is_pipe()); + static_cast(open_file.inode().ptr())->clone_writing(); } } @@ -78,8 +66,10 @@ namespace Kernel if ((flags & O_TRUNC) && (flags & O_WRONLY) && file.inode->mode().ifreg()) TRY(file.inode->truncate(0)); + constexpr int status_mask = O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC | O_ACCMODE; int fd = TRY(get_free_fd()); - m_open_files[fd] = TRY(BAN::RefPtr::create(BAN::move(file), 0, flags)); + m_open_files[fd].description = TRY(BAN::RefPtr::create(BAN::move(file), 0, flags & status_mask)); + m_open_files[fd].descriptor_flags = flags & O_CLOEXEC; return fd; } @@ -110,11 +100,12 @@ namespace Kernel return BAN::Error::from_errno(EPROTOTYPE); } - int extra_flags = 0; + int status_flags = 0; + int descriptor_flags = 0; if (type & SOCK_NONBLOCK) - extra_flags |= O_NONBLOCK; + status_flags |= O_NONBLOCK; if (type & SOCK_CLOEXEC) - extra_flags |= O_CLOEXEC; + descriptor_flags |= O_CLOEXEC; type &= ~(SOCK_NONBLOCK | SOCK_CLOEXEC); Socket::Type sock_type; @@ -144,7 +135,8 @@ namespace Kernel auto socket = TRY(NetworkManager::get().create_socket(sock_domain, sock_type, 0777, m_credentials.euid(), m_credentials.egid())); int fd = TRY(get_free_fd()); - m_open_files[fd] = TRY(BAN::RefPtr::create(VirtualFileSystem::File(socket, ""_sv), 0, O_RDWR | extra_flags)); + m_open_files[fd].description = TRY(BAN::RefPtr::create(VirtualFileSystem::File(socket, ""_sv), 0, O_RDWR | status_flags)); + m_open_files[fd].descriptor_flags = descriptor_flags; return fd; } @@ -153,8 +145,10 @@ namespace Kernel TRY(get_free_fd_pair(fds)); auto pipe = TRY(Pipe::create(m_credentials)); - m_open_files[fds[0]] = TRY(BAN::RefPtr::create(VirtualFileSystem::File(pipe, ""_sv), 0, O_RDONLY)); - m_open_files[fds[1]] = TRY(BAN::RefPtr::create(VirtualFileSystem::File(pipe, ""_sv), 0, O_WRONLY)); + m_open_files[fds[0]].description = TRY(BAN::RefPtr::create(VirtualFileSystem::File(pipe, ""_sv), 0, O_RDONLY)); + m_open_files[fds[0]].descriptor_flags = 0; + m_open_files[fds[1]].description = TRY(BAN::RefPtr::create(VirtualFileSystem::File(pipe, ""_sv), 0, O_WRONLY)); + m_open_files[fds[1]].descriptor_flags = 0; return {}; } @@ -170,13 +164,13 @@ namespace Kernel (void)close(fildes2); - m_open_files[fildes2] = m_open_files[fildes]; - m_open_files[fildes2]->flags &= ~O_CLOEXEC; + m_open_files[fildes2].description = m_open_files[fildes].description; + m_open_files[fildes2].descriptor_flags = 0; - if (m_open_files[fildes2]->path() == ""_sv) + if (m_open_files[fildes2].path() == ""_sv) { - ASSERT(m_open_files[fildes2]->inode()->is_pipe()); - static_cast(m_open_files[fildes2]->inode().ptr())->clone_writing(); + ASSERT(m_open_files[fildes2].inode()->is_pipe()); + static_cast(m_open_files[fildes2].inode().ptr())->clone_writing(); } return fildes; @@ -193,32 +187,30 @@ namespace Kernel { const int new_fd = TRY(get_free_fd()); - auto new_file = TRY(BAN::RefPtr::create( - TRY(m_open_files[fd]->file.clone()), - m_open_files[fd]->offset, - m_open_files[fd]->flags | (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0) - )); - - if (new_file->path() == ""_sv) + m_open_files[new_fd].description = m_open_files[fd].description; + m_open_files[new_fd].descriptor_flags = (cmd == F_DUPFD_CLOEXEC) ? O_CLOEXEC : 0; + if (m_open_files[new_fd].path() == ""_sv) { - ASSERT(new_file->inode()->is_pipe()); - static_cast(new_file->inode().ptr())->clone_writing(); + ASSERT(m_open_files[new_fd].inode()->is_pipe()); + static_cast(m_open_files[new_fd].inode().ptr())->clone_writing(); } - m_open_files[new_fd] = BAN::move(new_file); return new_fd; } case F_GETFD: - return m_open_files[fd]->flags & FD_CLOEXEC; + return m_open_files[fd].descriptor_flags; case F_SETFD: - m_open_files[fd]->flags &= ~FD_CLOEXEC; - m_open_files[fd]->flags |= extra & FD_CLOEXEC; + if (extra & FD_CLOEXEC) + m_open_files[fd].descriptor_flags |= O_CLOEXEC; + else + m_open_files[fd].descriptor_flags &= ~O_CLOEXEC; return 0; case F_GETFL: - return m_open_files[fd]->flags & ~(O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC | O_ACCMODE); + return m_open_files[fd].status_flags(); case F_SETFL: - m_open_files[fd]->flags &= ~O_NONBLOCK; - m_open_files[fd]->flags |= extra & O_NONBLOCK; + extra &= O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC; + m_open_files[fd].status_flags() &= ~O_ACCMODE; + m_open_files[fd].status_flags() |= extra; return 0; default: break; @@ -239,10 +231,10 @@ namespace Kernel base_offset = 0; break; case SEEK_CUR: - base_offset = m_open_files[fd]->offset; + base_offset = m_open_files[fd].offset(); break; case SEEK_END: - base_offset = m_open_files[fd]->inode()->size(); + base_offset = m_open_files[fd].inode()->size(); break; default: return BAN::Error::from_errno(EINVAL); @@ -252,7 +244,7 @@ namespace Kernel if (new_offset < 0) return BAN::Error::from_errno(EINVAL); - m_open_files[fd]->offset = new_offset; + m_open_files[fd].offset() = new_offset; return new_offset; } @@ -260,26 +252,27 @@ namespace Kernel BAN::ErrorOr OpenFileDescriptorSet::tell(int fd) const { TRY(validate_fd(fd)); - return m_open_files[fd]->offset; + return m_open_files[fd].offset(); } BAN::ErrorOr OpenFileDescriptorSet::truncate(int fd, off_t length) { TRY(validate_fd(fd)); - return m_open_files[fd]->inode()->truncate(length); + return m_open_files[fd].inode()->truncate(length); } BAN::ErrorOr OpenFileDescriptorSet::close(int fd) { TRY(validate_fd(fd)); - if (m_open_files[fd]->path() == ""_sv) + if (m_open_files[fd].path() == ""_sv) { - ASSERT(m_open_files[fd]->inode()->is_pipe()); - static_cast(m_open_files[fd]->inode().ptr())->close_writing(); + ASSERT(m_open_files[fd].inode()->is_pipe()); + static_cast(m_open_files[fd].inode().ptr())->close_writing(); } - m_open_files[fd].clear(); + m_open_files[fd].description.clear(); + m_open_files[fd].descriptor_flags = 0; return {}; } @@ -296,7 +289,7 @@ namespace Kernel { if (validate_fd(fd).is_error()) continue; - if (m_open_files[fd]->flags & O_CLOEXEC) + if (m_open_files[fd].descriptor_flags & O_CLOEXEC) (void)close(fd); } } @@ -305,12 +298,12 @@ namespace Kernel { TRY(validate_fd(fd)); auto& open_file = m_open_files[fd]; - if (!(open_file->flags & O_RDONLY)) + if (!(open_file.status_flags() & O_RDONLY)) return BAN::Error::from_errno(EBADF); - if ((open_file->flags & O_NONBLOCK) && !open_file->inode()->can_read()) + if ((open_file.status_flags() & O_NONBLOCK) && !open_file.inode()->can_read()) return 0; - size_t nread = TRY(open_file->inode()->read(open_file->offset, buffer)); - open_file->offset += nread; + size_t nread = TRY(open_file.inode()->read(open_file.offset(), buffer)); + open_file.offset() += nread; return nread; } @@ -318,14 +311,14 @@ namespace Kernel { TRY(validate_fd(fd)); auto& open_file = m_open_files[fd]; - if (!(open_file->flags & O_WRONLY)) + if (!(open_file.status_flags() & O_WRONLY)) return BAN::Error::from_errno(EBADF); - if ((open_file->flags & O_NONBLOCK) && !open_file->inode()->can_write()) + if ((open_file.status_flags() & O_NONBLOCK) && !open_file.inode()->can_write()) return 0; - if (open_file->flags & O_APPEND) - open_file->offset = open_file->inode()->size(); - size_t nwrite = TRY(open_file->inode()->write(open_file->offset, buffer)); - open_file->offset += nwrite; + if (open_file.status_flags() & O_APPEND) + open_file.offset() = open_file.inode()->size(); + size_t nwrite = TRY(open_file.inode()->write(open_file.offset(), buffer)); + open_file.offset() += nwrite; return nwrite; } @@ -333,11 +326,11 @@ namespace Kernel { TRY(validate_fd(fd)); auto& open_file = m_open_files[fd]; - if (!(open_file->flags & O_RDONLY)) + if (!(open_file.status_flags() & O_RDONLY)) return BAN::Error::from_errno(EACCES); for (;;) { - auto ret = open_file->inode()->list_next_inodes(open_file->offset++, list, list_len); + auto ret = open_file.inode()->list_next_inodes(open_file.offset()++, list, list_len); if (ret.is_error() && ret.error().get_error_code() == ENODATA) continue; return ret; @@ -347,32 +340,32 @@ namespace Kernel BAN::ErrorOr OpenFileDescriptorSet::file_of(int fd) const { TRY(validate_fd(fd)); - return TRY(m_open_files[fd]->file.clone()); + return TRY(m_open_files[fd].description->file.clone()); } BAN::ErrorOr OpenFileDescriptorSet::path_of(int fd) const { TRY(validate_fd(fd)); - return m_open_files[fd]->path(); + return m_open_files[fd].path(); } BAN::ErrorOr> OpenFileDescriptorSet::inode_of(int fd) { TRY(validate_fd(fd)); - return m_open_files[fd]->inode(); + return m_open_files[fd].inode(); } - BAN::ErrorOr OpenFileDescriptorSet::flags_of(int fd) const + BAN::ErrorOr OpenFileDescriptorSet::status_flags_of(int fd) const { TRY(validate_fd(fd)); - return m_open_files[fd]->flags; + return m_open_files[fd].status_flags(); } BAN::ErrorOr OpenFileDescriptorSet::validate_fd(int fd) const { if (fd < 0 || fd >= (int)m_open_files.size()) return BAN::Error::from_errno(EBADF); - if (!m_open_files[fd]) + if (!m_open_files[fd].description) return BAN::Error::from_errno(EBADF); return {}; } @@ -380,7 +373,7 @@ namespace Kernel BAN::ErrorOr OpenFileDescriptorSet::get_free_fd() const { for (int fd = 0; fd < (int)m_open_files.size(); fd++) - if (!m_open_files[fd]) + if (!m_open_files[fd].description) return fd; return BAN::Error::from_errno(EMFILE); } @@ -390,7 +383,7 @@ namespace Kernel size_t found = 0; for (int fd = 0; fd < (int)m_open_files.size(); fd++) { - if (!m_open_files[fd]) + if (!m_open_files[fd].description) fds[found++] = fd; if (found == 2) return {}; diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index a1c9d154..6d4db907 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -441,8 +441,8 @@ namespace Kernel if (fd == AT_FDCWD) return TRY(m_working_directory.clone()); - int flags = TRY(m_open_file_descriptors.flags_of(fd)); - if (!(flags & O_RDONLY) && !(flags & O_SEARCH)) + const auto status_flags = TRY(m_open_file_descriptors.status_flags_of(fd)); + if (!(status_flags & O_RDONLY) && !(status_flags & O_SEARCH)) return BAN::Error::from_errno(EBADF); return TRY(m_open_file_descriptors.file_of(fd)); @@ -514,8 +514,8 @@ namespace Kernel auto working_directory = TRY(m_working_directory.clone()); - OpenFileDescriptorSet open_file_descriptors(m_credentials); - TRY(open_file_descriptors.clone_from(m_open_file_descriptors)); + auto open_file_descriptors = TRY(BAN::UniqPtr::create(m_credentials)); + TRY(open_file_descriptors->clone_from(m_open_file_descriptors)); BAN::Vector> mapped_regions; TRY(mapped_regions.reserve(m_mapped_regions.size())); @@ -526,7 +526,7 @@ namespace Kernel forked->m_controlling_terminal = m_controlling_terminal; forked->m_working_directory = BAN::move(working_directory); forked->m_page_table = BAN::move(page_table); - forked->m_open_file_descriptors = BAN::move(open_file_descriptors); + forked->m_open_file_descriptors = BAN::move(*open_file_descriptors); forked->m_mapped_regions = BAN::move(mapped_regions); forked->m_is_userspace = m_is_userspace; forked->m_userspace_info = m_userspace_info; @@ -1320,8 +1320,8 @@ namespace Kernel if (!inode->mode().ifsock()) return BAN::Error::from_errno(ENOTSOCK); - auto flags = TRY(m_open_file_descriptors.flags_of(arguments->socket)); - if ((flags & O_NONBLOCK) && !inode->can_write()) + const auto status_flags = TRY(m_open_file_descriptors.status_flags_of(arguments->socket)); + if ((status_flags & O_NONBLOCK) && !inode->can_write()) return BAN::Error::from_errno(EAGAIN); BAN::ConstByteSpan message { reinterpret_cast(arguments->message), arguments->length }; @@ -1348,8 +1348,8 @@ namespace Kernel if (!inode->mode().ifsock()) return BAN::Error::from_errno(ENOTSOCK); - auto flags = TRY(m_open_file_descriptors.flags_of(arguments->socket)); - if ((flags & O_NONBLOCK) && !inode->can_read()) + const auto status_flags = TRY(m_open_file_descriptors.status_flags_of(arguments->socket)); + if ((status_flags & O_NONBLOCK) && !inode->can_read()) return BAN::Error::from_errno(EAGAIN); BAN::ByteSpan buffer { reinterpret_cast(arguments->buffer), arguments->length }; @@ -1697,11 +1697,11 @@ namespace Kernel auto inode = TRY(m_open_file_descriptors.inode_of(args->fildes)); - auto inode_flags = TRY(m_open_file_descriptors.flags_of(args->fildes)); - if (!(inode_flags & O_RDONLY)) + const auto status_flags = TRY(m_open_file_descriptors.status_flags_of(args->fildes)); + if (!(status_flags & O_RDONLY)) return BAN::Error::from_errno(EACCES); if (region_type == MemoryRegion::Type::SHARED) - if ((args->prot & PROT_WRITE) && !(inode_flags & O_WRONLY)) + if ((args->prot & PROT_WRITE) && !(status_flags & O_WRONLY)) return BAN::Error::from_errno(EACCES); BAN::UniqPtr memory_region;