mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 12:32:43 +00:00 
			
		
		
		
	Kernel+LibC: Turn errno codes into a strongly typed enum
..and allow implicit creation of KResult and KResultOr from ErrnoCode. This means that kernel functions that return those types can finally do "return EINVAL;" and it will just work. There's a handful of functions that still deal with signed integers that should be converted to return KResults.
This commit is contained in:
		
							parent
							
								
									e279b45aed
								
							
						
					
					
						commit
						19d3f8cab7
					
				
					 48 changed files with 591 additions and 506 deletions
				
			
		|  | @ -83,7 +83,7 @@ Kernel::KResultOr<size_t> Console::write(Kernel::FileDescription&, size_t, const | ||||||
|         return (ssize_t)bytes_count; |         return (ssize_t)bytes_count; | ||||||
|     }); |     }); | ||||||
|     if (nread < 0) |     if (nread < 0) | ||||||
|         return Kernel::KResult(nread); |         return Kernel::KResult((ErrnoCode)-nread); | ||||||
|     return (size_t)nread; |     return (size_t)nread; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -179,12 +179,12 @@ KResultOr<Region*> BXVGADevice::mmap(Process& process, FileDescription&, Virtual | ||||||
| { | { | ||||||
|     REQUIRE_PROMISE(video); |     REQUIRE_PROMISE(video); | ||||||
|     if (!shared) |     if (!shared) | ||||||
|         return KResult(-ENODEV); |         return ENODEV; | ||||||
|     ASSERT(offset == 0); |     ASSERT(offset == 0); | ||||||
|     ASSERT(size == framebuffer_size_in_bytes()); |     ASSERT(size == framebuffer_size_in_bytes()); | ||||||
|     auto vmobject = AnonymousVMObject::create_for_physical_range(m_framebuffer_address, framebuffer_size_in_bytes()); |     auto vmobject = AnonymousVMObject::create_for_physical_range(m_framebuffer_address, framebuffer_size_in_bytes()); | ||||||
|     if (!vmobject) |     if (!vmobject) | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     return process.allocate_region_with_vmobject( |     return process.allocate_region_with_vmobject( | ||||||
|         preferred_vaddr, |         preferred_vaddr, | ||||||
|         framebuffer_size_in_bytes(), |         framebuffer_size_in_bytes(), | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ KResultOr<size_t> FullDevice::read(FileDescription&, size_t, UserOrKernelBuffer& | ||||||
| { | { | ||||||
|     ssize_t count = min(static_cast<size_t>(PAGE_SIZE), size); |     ssize_t count = min(static_cast<size_t>(PAGE_SIZE), size); | ||||||
|     if (!buffer.memset(0, count)) |     if (!buffer.memset(0, count)) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     return count; |     return count; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -58,7 +58,7 @@ KResultOr<size_t> FullDevice::write(FileDescription&, size_t, const UserOrKernel | ||||||
| { | { | ||||||
|     if (size == 0) |     if (size == 0) | ||||||
|         return 0; |         return 0; | ||||||
|     return KResult(-ENOSPC); |     return ENOSPC; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -386,7 +386,7 @@ KResultOr<size_t> KeyboardDevice::read(FileDescription&, size_t, UserOrKernelBuf | ||||||
|             return (ssize_t)data_bytes; |             return (ssize_t)data_bytes; | ||||||
|         }); |         }); | ||||||
|         if (n < 0) |         if (n < 0) | ||||||
|             return KResult(n); |             return KResult((ErrnoCode)-n); | ||||||
|         ASSERT((size_t)n == sizeof(Event)); |         ASSERT((size_t)n == sizeof(Event)); | ||||||
|         nread += sizeof(Event); |         nread += sizeof(Event); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -55,12 +55,12 @@ KResultOr<Region*> MBVGADevice::mmap(Process& process, FileDescription&, Virtual | ||||||
| { | { | ||||||
|     REQUIRE_PROMISE(video); |     REQUIRE_PROMISE(video); | ||||||
|     if (!shared) |     if (!shared) | ||||||
|         return KResult(-ENODEV); |         return ENODEV; | ||||||
|     ASSERT(offset == 0); |     ASSERT(offset == 0); | ||||||
|     ASSERT(size == framebuffer_size_in_bytes()); |     ASSERT(size == framebuffer_size_in_bytes()); | ||||||
|     auto vmobject = AnonymousVMObject::create_for_physical_range(m_framebuffer_address, framebuffer_size_in_bytes()); |     auto vmobject = AnonymousVMObject::create_for_physical_range(m_framebuffer_address, framebuffer_size_in_bytes()); | ||||||
|     if (!vmobject) |     if (!vmobject) | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     return process.allocate_region_with_vmobject( |     return process.allocate_region_with_vmobject( | ||||||
|         preferred_vaddr, |         preferred_vaddr, | ||||||
|         framebuffer_size_in_bytes(), |         framebuffer_size_in_bytes(), | ||||||
|  |  | ||||||
|  | @ -288,7 +288,7 @@ KResultOr<size_t> PS2MouseDevice::read(FileDescription&, size_t, UserOrKernelBuf | ||||||
| #endif | #endif | ||||||
|         size_t bytes_read_from_packet = min(remaining_space_in_buffer, sizeof(MousePacket)); |         size_t bytes_read_from_packet = min(remaining_space_in_buffer, sizeof(MousePacket)); | ||||||
|         if (!buffer.write(&packet, nread, bytes_read_from_packet)) |         if (!buffer.write(&packet, nread, bytes_read_from_packet)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         nread += bytes_read_from_packet; |         nread += bytes_read_from_packet; | ||||||
|         remaining_space_in_buffer -= bytes_read_from_packet; |         remaining_space_in_buffer -= bytes_read_from_packet; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ KResultOr<size_t> RandomDevice::read(FileDescription&, size_t, UserOrKernelBuffe | ||||||
|         return (ssize_t)data_size; |         return (ssize_t)data_size; | ||||||
|     }); |     }); | ||||||
|     if (!success) |     if (!success) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     return size; |     return size; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -236,11 +236,11 @@ KResultOr<size_t> SB16::write(FileDescription&, size_t, const UserOrKernelBuffer | ||||||
|     if (!m_dma_region) { |     if (!m_dma_region) { | ||||||
|         auto page = MM.allocate_supervisor_physical_page(); |         auto page = MM.allocate_supervisor_physical_page(); | ||||||
|         if (!page) |         if (!page) | ||||||
|             return KResult(-ENOMEM); |             return ENOMEM; | ||||||
|         auto vmobject = AnonymousVMObject::create_with_physical_page(*page); |         auto vmobject = AnonymousVMObject::create_with_physical_page(*page); | ||||||
|         m_dma_region = MM.allocate_kernel_region_with_vmobject(*vmobject, PAGE_SIZE, "SB16 DMA buffer", Region::Access::Write); |         m_dma_region = MM.allocate_kernel_region_with_vmobject(*vmobject, PAGE_SIZE, "SB16 DMA buffer", Region::Access::Write); | ||||||
|         if (!m_dma_region) |         if (!m_dma_region) | ||||||
|             return KResult(-ENOMEM); |             return ENOMEM; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| #ifdef SB16_DEBUG | #ifdef SB16_DEBUG | ||||||
|  | @ -249,7 +249,7 @@ KResultOr<size_t> SB16::write(FileDescription&, size_t, const UserOrKernelBuffer | ||||||
|     ASSERT(length <= PAGE_SIZE); |     ASSERT(length <= PAGE_SIZE); | ||||||
|     const int BLOCK_SIZE = 32 * 1024; |     const int BLOCK_SIZE = 32 * 1024; | ||||||
|     if (length > BLOCK_SIZE) { |     if (length > BLOCK_SIZE) { | ||||||
|         return KResult(-ENOSPC); |         return ENOSPC; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     u8 mode = (u8)SampleFormat::Signed | (u8)SampleFormat::Stereo; |     u8 mode = (u8)SampleFormat::Signed | (u8)SampleFormat::Stereo; | ||||||
|  | @ -257,7 +257,7 @@ KResultOr<size_t> SB16::write(FileDescription&, size_t, const UserOrKernelBuffer | ||||||
|     const int sample_rate = 44100; |     const int sample_rate = 44100; | ||||||
|     set_sample_rate(sample_rate); |     set_sample_rate(sample_rate); | ||||||
|     if (!data.read(m_dma_region->vaddr().as_ptr(), length)) |     if (!data.read(m_dma_region->vaddr().as_ptr(), length)) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     dma_start(length); |     dma_start(length); | ||||||
| 
 | 
 | ||||||
|     // 16-bit single-cycle output.
 |     // 16-bit single-cycle output.
 | ||||||
|  |  | ||||||
|  | @ -59,7 +59,7 @@ KResultOr<size_t> SerialDevice::read(FileDescription&, size_t, UserOrKernelBuffe | ||||||
|         return (ssize_t)data_size; |         return (ssize_t)data_size; | ||||||
|     }); |     }); | ||||||
|     if (nwritten < 0) |     if (nwritten < 0) | ||||||
|         return KResult(nwritten); |         return KResult((ErrnoCode)-nwritten); | ||||||
| 
 | 
 | ||||||
|     return size; |     return size; | ||||||
| } | } | ||||||
|  | @ -83,7 +83,7 @@ KResultOr<size_t> SerialDevice::write(FileDescription&, size_t, const UserOrKern | ||||||
|         return (ssize_t)data_size; |         return (ssize_t)data_size; | ||||||
|     }); |     }); | ||||||
|     if (nread < 0) |     if (nread < 0) | ||||||
|         return KResult(nread); |         return KResult((ErrnoCode)-nread); | ||||||
|     return (size_t)nread; |     return (size_t)nread; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -48,7 +48,7 @@ KResultOr<size_t> ZeroDevice::read(FileDescription&, size_t, UserOrKernelBuffer& | ||||||
| { | { | ||||||
|     ssize_t count = min(static_cast<size_t>(PAGE_SIZE), size); |     ssize_t count = min(static_cast<size_t>(PAGE_SIZE), size); | ||||||
|     if (!buffer.memset(0, count)) |     if (!buffer.memset(0, count)) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     return count; |     return count; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -42,10 +42,10 @@ AnonymousFile::~AnonymousFile() | ||||||
| KResultOr<Region*> AnonymousFile::mmap(Process& process, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared) | KResultOr<Region*> AnonymousFile::mmap(Process& process, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared) | ||||||
| { | { | ||||||
|     if (offset != 0) |     if (offset != 0) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     if (size != m_vmobject->size()) |     if (size != m_vmobject->size()) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     return process.allocate_region_with_vmobject(preferred_vaddr, size, m_vmobject, offset, {}, prot, shared); |     return process.allocate_region_with_vmobject(preferred_vaddr, size, m_vmobject, offset, {}, prot, shared); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -46,8 +46,8 @@ private: | ||||||
|     virtual String absolute_path(const FileDescription&) const override { return ":anonymous-file:"; } |     virtual String absolute_path(const FileDescription&) const override { return ":anonymous-file:"; } | ||||||
|     virtual bool can_read(const FileDescription&, size_t) const override { return false; } |     virtual bool can_read(const FileDescription&, size_t) const override { return false; } | ||||||
|     virtual bool can_write(const FileDescription&, size_t) const override { return false; } |     virtual bool can_write(const FileDescription&, size_t) const override { return false; } | ||||||
|     virtual KResultOr<size_t> read(FileDescription&, size_t, UserOrKernelBuffer&, size_t) override { return KResult(-ENOTSUP); } |     virtual KResultOr<size_t> read(FileDescription&, size_t, UserOrKernelBuffer&, size_t) override { return ENOTSUP; } | ||||||
|     virtual KResultOr<size_t> write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) override { return KResult(-ENOTSUP); } |     virtual KResultOr<size_t> write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) override { return ENOTSUP; } | ||||||
| 
 | 
 | ||||||
|     explicit AnonymousFile(NonnullRefPtr<AnonymousVMObject>); |     explicit AnonymousFile(NonnullRefPtr<AnonymousVMObject>); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -169,7 +169,7 @@ KResult BlockBasedFS::write_block(unsigned index, const UserOrKernelBuffer& data | ||||||
|             return result; |             return result; | ||||||
|     } |     } | ||||||
|     if (!data.read(entry.data + offset, count)) |     if (!data.read(entry.data + offset, count)) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
| 
 | 
 | ||||||
|     cache().mark_dirty(entry); |     cache().mark_dirty(entry); | ||||||
|     entry.has_data = true; |     entry.has_data = true; | ||||||
|  | @ -261,7 +261,7 @@ KResult BlockBasedFS::read_block(unsigned index, UserOrKernelBuffer* buffer, siz | ||||||
|         entry.has_data = true; |         entry.has_data = true; | ||||||
|     } |     } | ||||||
|     if (buffer && !buffer->write(entry.data + offset, count)) |     if (buffer && !buffer->write(entry.data + offset, count)) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -269,7 +269,7 @@ KResult BlockBasedFS::read_blocks(unsigned index, unsigned count, UserOrKernelBu | ||||||
| { | { | ||||||
|     ASSERT(m_logical_block_size); |     ASSERT(m_logical_block_size); | ||||||
|     if (!count) |     if (!count) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     if (count == 1) |     if (count == 1) | ||||||
|         return read_block(index, &buffer, block_size(), 0, allow_cache); |         return read_block(index, &buffer, block_size(), 0, allow_cache); | ||||||
|     auto out = buffer; |     auto out = buffer; | ||||||
|  |  | ||||||
|  | @ -124,17 +124,17 @@ ssize_t DevFSInode::write_bytes(off_t, ssize_t, const UserOrKernelBuffer&, FileD | ||||||
| 
 | 
 | ||||||
| KResultOr<NonnullRefPtr<Inode>> DevFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t) | KResultOr<NonnullRefPtr<Inode>> DevFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t) | ||||||
| { | { | ||||||
|     return KResult(-EROFS); |     return EROFS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult DevFSInode::add_child(Inode&, const StringView&, mode_t) | KResult DevFSInode::add_child(Inode&, const StringView&, mode_t) | ||||||
| { | { | ||||||
|     return KResult(-EROFS); |     return EROFS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult DevFSInode::remove_child(const StringView&) | KResult DevFSInode::remove_child(const StringView&) | ||||||
| { | { | ||||||
|     return KResult(-EROFS); |     return EROFS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResultOr<size_t> DevFSInode::directory_entry_count() const | KResultOr<size_t> DevFSInode::directory_entry_count() const | ||||||
|  | @ -144,17 +144,17 @@ KResultOr<size_t> DevFSInode::directory_entry_count() const | ||||||
| 
 | 
 | ||||||
| KResult DevFSInode::chmod(mode_t) | KResult DevFSInode::chmod(mode_t) | ||||||
| { | { | ||||||
|     return KResult(-EPERM); |     return EPERM; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult DevFSInode::chown(uid_t, gid_t) | KResult DevFSInode::chown(uid_t, gid_t) | ||||||
| { | { | ||||||
|     return KResult(-EPERM); |     return EPERM; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult DevFSInode::truncate(u64) | KResult DevFSInode::truncate(u64) | ||||||
| { | { | ||||||
|     return KResult(-EPERM); |     return EPERM; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| String DevFSLinkInode::name() const | String DevFSLinkInode::name() const | ||||||
|  | @ -221,7 +221,7 @@ InodeMetadata DevFSDirectoryInode::metadata() const | ||||||
| KResult DevFSDirectoryInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const | KResult DevFSDirectoryInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
|     return KResult(-EINVAL); |     return EINVAL; | ||||||
| } | } | ||||||
| RefPtr<Inode> DevFSDirectoryInode::lookup(StringView) | RefPtr<Inode> DevFSDirectoryInode::lookup(StringView) | ||||||
| { | { | ||||||
|  | @ -288,10 +288,10 @@ KResultOr<NonnullRefPtr<Inode>> DevFSRootDirectoryInode::create_child(const Stri | ||||||
|     if (metadata.is_directory()) { |     if (metadata.is_directory()) { | ||||||
|         for (auto& folder : m_subfolders) { |         for (auto& folder : m_subfolders) { | ||||||
|             if (folder.name() == name) |             if (folder.name() == name) | ||||||
|                 return KResult(-EEXIST); |                 return EEXIST; | ||||||
|         } |         } | ||||||
|         if (name != "pts") |         if (name != "pts") | ||||||
|             return KResult(-EROFS); |             return EROFS; | ||||||
|         auto new_directory_inode = adopt(*new DevFSPtsDirectoryInode(m_parent_fs)); |         auto new_directory_inode = adopt(*new DevFSPtsDirectoryInode(m_parent_fs)); | ||||||
|         m_subfolders.append(new_directory_inode); |         m_subfolders.append(new_directory_inode); | ||||||
|         m_parent_fs.m_nodes.append(new_directory_inode); |         m_parent_fs.m_nodes.append(new_directory_inode); | ||||||
|  | @ -300,7 +300,7 @@ KResultOr<NonnullRefPtr<Inode>> DevFSRootDirectoryInode::create_child(const Stri | ||||||
|     if (metadata.is_symlink()) { |     if (metadata.is_symlink()) { | ||||||
|         for (auto& link : m_links) { |         for (auto& link : m_links) { | ||||||
|             if (link.name() == name) |             if (link.name() == name) | ||||||
|                 return KResult(-EEXIST); |                 return EEXIST; | ||||||
|         } |         } | ||||||
|         dbgln("DevFS: Success on create new symlink"); |         dbgln("DevFS: Success on create new symlink"); | ||||||
|         auto new_link_inode = adopt(*new DevFSLinkInode(m_parent_fs, name)); |         auto new_link_inode = adopt(*new DevFSLinkInode(m_parent_fs, name)); | ||||||
|  | @ -308,7 +308,7 @@ KResultOr<NonnullRefPtr<Inode>> DevFSRootDirectoryInode::create_child(const Stri | ||||||
|         m_parent_fs.m_nodes.append(new_link_inode); |         m_parent_fs.m_nodes.append(new_link_inode); | ||||||
|         return new_link_inode; |         return new_link_inode; | ||||||
|     } |     } | ||||||
|     return KResult(-EROFS); |     return EROFS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DevFSRootDirectoryInode::~DevFSRootDirectoryInode() | DevFSRootDirectoryInode::~DevFSRootDirectoryInode() | ||||||
|  |  | ||||||
|  | @ -143,7 +143,7 @@ InodeMetadata DevPtsFSInode::metadata() const | ||||||
| KResult DevPtsFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const | KResult DevPtsFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const | ||||||
| { | { | ||||||
|     if (identifier().index() > 1) |     if (identifier().index() > 1) | ||||||
|         return KResult(-ENOTDIR); |         return ENOTDIR; | ||||||
| 
 | 
 | ||||||
|     callback({ ".", identifier(), 0 }); |     callback({ ".", identifier(), 0 }); | ||||||
|     callback({ "..", identifier(), 0 }); |     callback({ "..", identifier(), 0 }); | ||||||
|  | @ -187,27 +187,27 @@ void DevPtsFSInode::flush_metadata() | ||||||
| 
 | 
 | ||||||
| KResult DevPtsFSInode::add_child(Inode&, const StringView&, mode_t) | KResult DevPtsFSInode::add_child(Inode&, const StringView&, mode_t) | ||||||
| { | { | ||||||
|     return KResult(-EROFS); |     return EROFS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResultOr<NonnullRefPtr<Inode>> DevPtsFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t) | KResultOr<NonnullRefPtr<Inode>> DevPtsFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t) | ||||||
| { | { | ||||||
|     return KResult(-EROFS); |     return EROFS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult DevPtsFSInode::remove_child(const StringView&) | KResult DevPtsFSInode::remove_child(const StringView&) | ||||||
| { | { | ||||||
|     return KResult(-EROFS); |     return EROFS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult DevPtsFSInode::chmod(mode_t) | KResult DevPtsFSInode::chmod(mode_t) | ||||||
| { | { | ||||||
|     return KResult(-EPERM); |     return EPERM; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult DevPtsFSInode::chown(uid_t, gid_t) | KResult DevPtsFSInode::chown(uid_t, gid_t) | ||||||
| { | { | ||||||
|     return KResult(-EPERM); |     return EPERM; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -233,7 +233,7 @@ Ext2FS::BlockListShape Ext2FS::compute_block_list_shape(unsigned blocks) const | ||||||
|     return {}; |     return {}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2inode, const Vector<BlockIndex>& blocks) | KResult Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2inode, const Vector<BlockIndex>& blocks) | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
| 
 | 
 | ||||||
|  | @ -241,7 +241,7 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in | ||||||
|         e2inode.i_blocks = 0; |         e2inode.i_blocks = 0; | ||||||
|         memset(e2inode.i_block, 0, sizeof(e2inode.i_block)); |         memset(e2inode.i_block, 0, sizeof(e2inode.i_block)); | ||||||
|         write_ext2_inode(inode_index, e2inode); |         write_ext2_inode(inode_index, e2inode); | ||||||
|         return true; |         return KSuccess; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // NOTE: There is a mismatch between i_blocks and blocks.size() since i_blocks includes meta blocks and blocks.size() does not.
 |     // NOTE: There is a mismatch between i_blocks and blocks.size() since i_blocks includes meta blocks and blocks.size() does not.
 | ||||||
|  | @ -279,7 +279,7 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!remaining_blocks) |     if (!remaining_blocks) | ||||||
|         return true; |         return KSuccess; | ||||||
| 
 | 
 | ||||||
|     const unsigned entries_per_block = EXT2_ADDR_PER_BLOCK(&super_block()); |     const unsigned entries_per_block = EXT2_ADDR_PER_BLOCK(&super_block()); | ||||||
| 
 | 
 | ||||||
|  | @ -315,12 +315,13 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in | ||||||
|         stream.fill_to_end(0); |         stream.fill_to_end(0); | ||||||
| 
 | 
 | ||||||
|         auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data()); |         auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data()); | ||||||
|         int err = write_block(e2inode.i_block[EXT2_IND_BLOCK], buffer, stream.size()); |         auto result = write_block(e2inode.i_block[EXT2_IND_BLOCK], buffer, stream.size()); | ||||||
|         ASSERT(err >= 0); |         if (result.is_error()) | ||||||
|  |             return result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!remaining_blocks) |     if (!remaining_blocks) | ||||||
|         return true; |         return KSuccess; | ||||||
| 
 | 
 | ||||||
|     bool dind_block_dirty = false; |     bool dind_block_dirty = false; | ||||||
| 
 | 
 | ||||||
|  | @ -356,9 +357,8 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in | ||||||
|             auto buffer = UserOrKernelBuffer::for_kernel_buffer(dind_block_contents.data()); |             auto buffer = UserOrKernelBuffer::for_kernel_buffer(dind_block_contents.data()); | ||||||
|             auto result = read_block(e2inode.i_block[EXT2_DIND_BLOCK], &buffer, block_size()); |             auto result = read_block(e2inode.i_block[EXT2_DIND_BLOCK], &buffer, block_size()); | ||||||
|             if (result.is_error()) { |             if (result.is_error()) { | ||||||
|                 // FIXME: Propagate the error
 |  | ||||||
|                 dbgln("Ext2FS: write_block_list_for_inode had error: {}", result.error()); |                 dbgln("Ext2FS: write_block_list_for_inode had error: {}", result.error()); | ||||||
|                 return false; |                 return result; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         auto* dind_block_as_pointers = (unsigned*)dind_block_contents.data(); |         auto* dind_block_as_pointers = (unsigned*)dind_block_contents.data(); | ||||||
|  | @ -384,9 +384,8 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in | ||||||
|                 auto buffer = UserOrKernelBuffer::for_kernel_buffer(ind_block_contents.data()); |                 auto buffer = UserOrKernelBuffer::for_kernel_buffer(ind_block_contents.data()); | ||||||
|                 auto result = read_block(indirect_block_index, &buffer, block_size()); |                 auto result = read_block(indirect_block_index, &buffer, block_size()); | ||||||
|                 if (result.is_error()) { |                 if (result.is_error()) { | ||||||
|                     // FIXME: Propagate the error
 |  | ||||||
|                     dbgln("Ext2FS: write_block_list_for_inode had error: {}", result.error()); |                     dbgln("Ext2FS: write_block_list_for_inode had error: {}", result.error()); | ||||||
|                     return false; |                     return result; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             auto* ind_block_as_pointers = (unsigned*)ind_block_contents.data(); |             auto* ind_block_as_pointers = (unsigned*)ind_block_contents.data(); | ||||||
|  | @ -432,7 +431,7 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!remaining_blocks) |     if (!remaining_blocks) | ||||||
|         return true; |         return KSuccess; | ||||||
| 
 | 
 | ||||||
|     // FIXME: Implement!
 |     // FIXME: Implement!
 | ||||||
|     dbgln("we don't know how to write tind ext2fs blocks yet!"); |     dbgln("we don't know how to write tind ext2fs blocks yet!"); | ||||||
|  | @ -799,7 +798,7 @@ KResult Ext2FSInode::resize(u64 new_size) | ||||||
|     if (blocks_needed_after > blocks_needed_before) { |     if (blocks_needed_after > blocks_needed_before) { | ||||||
|         u32 additional_blocks_needed = blocks_needed_after - blocks_needed_before; |         u32 additional_blocks_needed = blocks_needed_after - blocks_needed_before; | ||||||
|         if (additional_blocks_needed > fs().super_block().s_free_blocks_count) |         if (additional_blocks_needed > fs().super_block().s_free_blocks_count) | ||||||
|             return KResult(-ENOSPC); |             return ENOSPC; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Vector<Ext2FS::BlockIndex> block_list; |     Vector<Ext2FS::BlockIndex> block_list; | ||||||
|  | @ -825,9 +824,9 @@ KResult Ext2FSInode::resize(u64 new_size) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     int err = fs().write_block_list_for_inode(index(), m_raw_inode, block_list); |     auto result = fs().write_block_list_for_inode(index(), m_raw_inode, block_list); | ||||||
|     if (err < 0) |     if (result.is_error()) | ||||||
|         return KResult(err); |         return result; | ||||||
| 
 | 
 | ||||||
|     m_raw_inode.i_size = new_size; |     m_raw_inode.i_size = new_size; | ||||||
|     set_metadata_dirty(true); |     set_metadata_dirty(true); | ||||||
|  | @ -844,7 +843,7 @@ KResult Ext2FSInode::resize(u64 new_size) | ||||||
|         while (bytes_to_clear) { |         while (bytes_to_clear) { | ||||||
|             auto nwritten = write_bytes(clear_from, min(sizeof(zero_buffer), bytes_to_clear), UserOrKernelBuffer::for_kernel_buffer(zero_buffer), nullptr); |             auto nwritten = write_bytes(clear_from, min(sizeof(zero_buffer), bytes_to_clear), UserOrKernelBuffer::for_kernel_buffer(zero_buffer), nullptr); | ||||||
|             if (nwritten < 0) |             if (nwritten < 0) | ||||||
|                 return KResult(-nwritten); |                 return KResult((ErrnoCode)-nwritten); | ||||||
|             ASSERT(nwritten != 0); |             ASSERT(nwritten != 0); | ||||||
|             bytes_to_clear -= nwritten; |             bytes_to_clear -= nwritten; | ||||||
|             clear_from += nwritten; |             clear_from += nwritten; | ||||||
|  | @ -1056,7 +1055,7 @@ KResult Ext2FSInode::add_child(Inode& child, const StringView& name, mode_t mode | ||||||
|     ASSERT(is_directory()); |     ASSERT(is_directory()); | ||||||
| 
 | 
 | ||||||
|     if (name.length() > EXT2_NAME_LEN) |     if (name.length() > EXT2_NAME_LEN) | ||||||
|         return KResult(-ENAMETOOLONG); |         return ENAMETOOLONG; | ||||||
| 
 | 
 | ||||||
| #ifdef EXT2_DEBUG | #ifdef EXT2_DEBUG | ||||||
|     dbgln("Ext2FSInode::add_child: Adding inode {} with name '{}' and mode {:o} to directory {}", child.index(), name, mode, index()); |     dbgln("Ext2FSInode::add_child: Adding inode {} with name '{}' and mode {:o} to directory {}", child.index(), name, mode, index()); | ||||||
|  | @ -1078,7 +1077,7 @@ KResult Ext2FSInode::add_child(Inode& child, const StringView& name, mode_t mode | ||||||
| 
 | 
 | ||||||
|     if (name_already_exists) { |     if (name_already_exists) { | ||||||
|         dbgln("Ext2FSInode::add_child: Name '{}' already exists in inode {}", name, index()); |         dbgln("Ext2FSInode::add_child: Name '{}' already exists in inode {}", name, index()); | ||||||
|         return KResult(-EEXIST); |         return EEXIST; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     result = child.increment_link_count(); |     result = child.increment_link_count(); | ||||||
|  | @ -1104,7 +1103,7 @@ KResult Ext2FSInode::remove_child(const StringView& name) | ||||||
| 
 | 
 | ||||||
|     auto it = m_lookup_cache.find(name); |     auto it = m_lookup_cache.find(name); | ||||||
|     if (it == m_lookup_cache.end()) |     if (it == m_lookup_cache.end()) | ||||||
|         return KResult(-ENOENT); |         return ENOENT; | ||||||
|     auto child_inode_index = (*it).value; |     auto child_inode_index = (*it).value; | ||||||
| 
 | 
 | ||||||
|     InodeIdentifier child_id { fsid(), child_inode_index }; |     InodeIdentifier child_id { fsid(), child_inode_index }; | ||||||
|  | @ -1125,7 +1124,7 @@ KResult Ext2FSInode::remove_child(const StringView& name) | ||||||
|     bool success = write_directory(entries); |     bool success = write_directory(entries); | ||||||
|     if (!success) { |     if (!success) { | ||||||
|         // FIXME: Plumb error from write_directory().
 |         // FIXME: Plumb error from write_directory().
 | ||||||
|         return KResult(-EIO); |         return EIO; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     m_lookup_cache.remove(name); |     m_lookup_cache.remove(name); | ||||||
|  | @ -1487,10 +1486,10 @@ KResultOr<NonnullRefPtr<Inode>> Ext2FS::create_inode(InodeIdentifier parent_id, | ||||||
|     ASSERT(parent_inode); |     ASSERT(parent_inode); | ||||||
| 
 | 
 | ||||||
|     if (static_cast<const Ext2FSInode&>(*parent_inode).m_raw_inode.i_links_count == 0) |     if (static_cast<const Ext2FSInode&>(*parent_inode).m_raw_inode.i_links_count == 0) | ||||||
|         return KResult(-ENOENT); |         return ENOENT; | ||||||
| 
 | 
 | ||||||
|     if (name.length() > EXT2_NAME_LEN) |     if (name.length() > EXT2_NAME_LEN) | ||||||
|         return KResult(-ENAMETOOLONG); |         return ENAMETOOLONG; | ||||||
| 
 | 
 | ||||||
| #ifdef EXT2_DEBUG | #ifdef EXT2_DEBUG | ||||||
|     dbgln("Ext2FS: Adding inode '{}' (mode {:o}) to parent directory {}", name, mode, parent_inode->index()); |     dbgln("Ext2FS: Adding inode '{}' (mode {:o}) to parent directory {}", name, mode, parent_inode->index()); | ||||||
|  | @ -1499,14 +1498,14 @@ KResultOr<NonnullRefPtr<Inode>> Ext2FS::create_inode(InodeIdentifier parent_id, | ||||||
|     size_t needed_blocks = ceil_div(static_cast<size_t>(size), block_size()); |     size_t needed_blocks = ceil_div(static_cast<size_t>(size), block_size()); | ||||||
|     if ((size_t)needed_blocks > super_block().s_free_blocks_count) { |     if ((size_t)needed_blocks > super_block().s_free_blocks_count) { | ||||||
|         dbgln("Ext2FS: create_inode: not enough free blocks"); |         dbgln("Ext2FS: create_inode: not enough free blocks"); | ||||||
|         return KResult(-ENOSPC); |         return ENOSPC; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // NOTE: This doesn't commit the inode allocation just yet!
 |     // NOTE: This doesn't commit the inode allocation just yet!
 | ||||||
|     auto inode_id = find_a_free_inode(0, size); |     auto inode_id = find_a_free_inode(0, size); | ||||||
|     if (!inode_id) { |     if (!inode_id) { | ||||||
|         klog() << "Ext2FS: create_inode: allocate_inode failed"; |         klog() << "Ext2FS: create_inode: allocate_inode failed"; | ||||||
|         return KResult(-ENOSPC); |         return ENOSPC; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto blocks = allocate_blocks(group_index_from_inode(inode_id), needed_blocks); |     auto blocks = allocate_blocks(group_index_from_inode(inode_id), needed_blocks); | ||||||
|  | @ -1537,8 +1536,9 @@ KResultOr<NonnullRefPtr<Inode>> Ext2FS::create_inode(InodeIdentifier parent_id, | ||||||
|     else if (is_block_device(mode)) |     else if (is_block_device(mode)) | ||||||
|         e2inode.i_block[1] = dev; |         e2inode.i_block[1] = dev; | ||||||
| 
 | 
 | ||||||
|     success = write_block_list_for_inode(inode_id, e2inode, blocks); |     auto result = write_block_list_for_inode(inode_id, e2inode, blocks); | ||||||
|     ASSERT(success); |     if (result.is_error()) | ||||||
|  |         return result; | ||||||
| 
 | 
 | ||||||
| #ifdef EXT2_DEBUG | #ifdef EXT2_DEBUG | ||||||
|     dbgln("Ext2FS: writing initial metadata for inode {}", inode_id); |     dbgln("Ext2FS: writing initial metadata for inode {}", inode_id); | ||||||
|  | @ -1554,8 +1554,9 @@ KResultOr<NonnullRefPtr<Inode>> Ext2FS::create_inode(InodeIdentifier parent_id, | ||||||
|     // If we've already computed a block list, no sense in throwing it away.
 |     // If we've already computed a block list, no sense in throwing it away.
 | ||||||
|     static_cast<Ext2FSInode&>(*inode).m_block_list = move(blocks); |     static_cast<Ext2FSInode&>(*inode).m_block_list = move(blocks); | ||||||
| 
 | 
 | ||||||
|     auto result = parent_inode->add_child(*inode, name, mode); |     result = parent_inode->add_child(*inode, name, mode); | ||||||
|     ASSERT(result.is_success()); |     if (result.is_error()) | ||||||
|  |         return result; | ||||||
| 
 | 
 | ||||||
|     return inode.release_nonnull(); |     return inode.release_nonnull(); | ||||||
| } | } | ||||||
|  | @ -1632,9 +1633,9 @@ KResult Ext2FSInode::increment_link_count() | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
|     if (fs().is_readonly()) |     if (fs().is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
|     if (m_raw_inode.i_links_count == max_link_count) |     if (m_raw_inode.i_links_count == max_link_count) | ||||||
|         return KResult(-EMLINK); |         return EMLINK; | ||||||
|     ++m_raw_inode.i_links_count; |     ++m_raw_inode.i_links_count; | ||||||
|     set_metadata_dirty(true); |     set_metadata_dirty(true); | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
|  | @ -1644,7 +1645,7 @@ KResult Ext2FSInode::decrement_link_count() | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
|     if (fs().is_readonly()) |     if (fs().is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
|     ASSERT(m_raw_inode.i_links_count); |     ASSERT(m_raw_inode.i_links_count); | ||||||
|     --m_raw_inode.i_links_count; |     --m_raw_inode.i_links_count; | ||||||
|     if (ref_count() == 1 && m_raw_inode.i_links_count == 0) |     if (ref_count() == 1 && m_raw_inode.i_links_count == 0) | ||||||
|  | @ -1730,7 +1731,7 @@ KResult Ext2FS::prepare_to_unmount() const | ||||||
| 
 | 
 | ||||||
|     for (auto& it : m_inode_cache) { |     for (auto& it : m_inode_cache) { | ||||||
|         if (it.value->ref_count() > 1) |         if (it.value->ref_count() > 1) | ||||||
|             return KResult(-EBUSY); |             return EBUSY; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     m_inode_cache.clear(); |     m_inode_cache.clear(); | ||||||
|  |  | ||||||
|  | @ -148,7 +148,7 @@ private: | ||||||
| 
 | 
 | ||||||
|     Vector<BlockIndex> block_list_for_inode_impl(const ext2_inode&, bool include_block_list_blocks = false) const; |     Vector<BlockIndex> block_list_for_inode_impl(const ext2_inode&, bool include_block_list_blocks = false) const; | ||||||
|     Vector<BlockIndex> block_list_for_inode(const ext2_inode&, bool include_block_list_blocks = false) const; |     Vector<BlockIndex> block_list_for_inode(const ext2_inode&, bool include_block_list_blocks = false) const; | ||||||
|     bool write_block_list_for_inode(InodeIndex, ext2_inode&, const Vector<BlockIndex>&); |     KResult write_block_list_for_inode(InodeIndex, ext2_inode&, const Vector<BlockIndex>&); | ||||||
| 
 | 
 | ||||||
|     bool get_inode_allocation_state(InodeIndex) const; |     bool get_inode_allocation_state(InodeIndex) const; | ||||||
|     bool set_inode_allocation_state(InodeIndex, bool); |     bool set_inode_allocation_state(InodeIndex, bool); | ||||||
|  |  | ||||||
|  | @ -61,7 +61,7 @@ int File::ioctl(FileDescription&, unsigned, FlatPtr) | ||||||
| 
 | 
 | ||||||
| KResultOr<Region*> File::mmap(Process&, FileDescription&, VirtualAddress, size_t, size_t, int, bool) | KResultOr<Region*> File::mmap(Process&, FileDescription&, VirtualAddress, size_t, size_t, int, bool) | ||||||
| { | { | ||||||
|     return KResult(-ENODEV); |     return ENODEV; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -115,13 +115,13 @@ public: | ||||||
|     virtual KResultOr<size_t> write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) = 0; |     virtual KResultOr<size_t> write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) = 0; | ||||||
|     virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg); |     virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg); | ||||||
|     virtual KResultOr<Region*> mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared); |     virtual KResultOr<Region*> mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared); | ||||||
|     virtual KResult stat(::stat&) const { return KResult(-EBADF); } |     virtual KResult stat(::stat&) const { return EBADF; } | ||||||
| 
 | 
 | ||||||
|     virtual String absolute_path(const FileDescription&) const = 0; |     virtual String absolute_path(const FileDescription&) const = 0; | ||||||
| 
 | 
 | ||||||
|     virtual KResult truncate(u64) { return KResult(-EINVAL); } |     virtual KResult truncate(u64) { return EINVAL; } | ||||||
|     virtual KResult chown(FileDescription&, uid_t, gid_t) { return KResult(-EBADF); } |     virtual KResult chown(FileDescription&, uid_t, gid_t) { return EBADF; } | ||||||
|     virtual KResult chmod(FileDescription&, mode_t) { return KResult(-EBADF); } |     virtual KResult chmod(FileDescription&, mode_t) { return EBADF; } | ||||||
| 
 | 
 | ||||||
|     virtual const char* class_name() const = 0; |     virtual const char* class_name() const = 0; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -82,7 +82,7 @@ KResultOr<NonnullOwnPtr<KBuffer>> Inode::read_entire(FileDescription* descriptio | ||||||
|         auto buf = UserOrKernelBuffer::for_kernel_buffer(buffer); |         auto buf = UserOrKernelBuffer::for_kernel_buffer(buffer); | ||||||
|         nread = read_bytes(offset, sizeof(buffer), buf, description); |         nread = read_bytes(offset, sizeof(buffer), buf, description); | ||||||
|         if (nread < 0) |         if (nread < 0) | ||||||
|             return KResult(nread); |             return KResult((ErrnoCode)-nread); | ||||||
|         ASSERT(nread <= (ssize_t)sizeof(buffer)); |         ASSERT(nread <= (ssize_t)sizeof(buffer)); | ||||||
|         if (nread <= 0) |         if (nread <= 0) | ||||||
|             break; |             break; | ||||||
|  | @ -93,12 +93,12 @@ KResultOr<NonnullOwnPtr<KBuffer>> Inode::read_entire(FileDescription* descriptio | ||||||
|     } |     } | ||||||
|     if (nread < 0) { |     if (nread < 0) { | ||||||
|         klog() << "Inode::read_entire: ERROR: " << nread; |         klog() << "Inode::read_entire: ERROR: " << nread; | ||||||
|         return KResult(nread); |         return KResult((ErrnoCode)-nread); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto entire_file = builder.build(); |     auto entire_file = builder.build(); | ||||||
|     if (!entire_file) |     if (!entire_file) | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     return entire_file.release_nonnull(); |     return entire_file.release_nonnull(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -168,12 +168,12 @@ int Inode::set_mtime(time_t) | ||||||
| 
 | 
 | ||||||
| KResult Inode::increment_link_count() | KResult Inode::increment_link_count() | ||||||
| { | { | ||||||
|     return KResult(-ENOTIMPL); |     return ENOTIMPL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult Inode::decrement_link_count() | KResult Inode::decrement_link_count() | ||||||
| { | { | ||||||
|     return KResult(-ENOTIMPL); |     return ENOTIMPL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Inode::set_shared_vmobject(SharedInodeVMObject& vmobject) | void Inode::set_shared_vmobject(SharedInodeVMObject& vmobject) | ||||||
|  | @ -271,7 +271,7 @@ KResult Inode::prepare_to_write_data() | ||||||
|     //        We should funnel everything through an interface at the VFS layer so this can happen from a single place.
 |     //        We should funnel everything through an interface at the VFS layer so this can happen from a single place.
 | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
|     if (fs().is_readonly()) |     if (fs().is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
|     auto metadata = this->metadata(); |     auto metadata = this->metadata(); | ||||||
|     if (metadata.is_setuid() || metadata.is_setgid()) { |     if (metadata.is_setuid() || metadata.is_setgid()) { | ||||||
|         dbgln("Inode::prepare_to_write_data(): Stripping SUID/SGID bits from {}", identifier()); |         dbgln("Inode::prepare_to_write_data(): Stripping SUID/SGID bits from {}", identifier()); | ||||||
|  |  | ||||||
|  | @ -52,7 +52,7 @@ KResultOr<size_t> InodeFile::read(FileDescription& description, size_t offset, U | ||||||
|         evaluate_block_conditions(); |         evaluate_block_conditions(); | ||||||
|     } |     } | ||||||
|     if (nread < 0) |     if (nread < 0) | ||||||
|         return KResult(nread); |         return KResult((ErrnoCode)-nread); | ||||||
|     return nread; |     return nread; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -65,7 +65,7 @@ KResultOr<size_t> InodeFile::write(FileDescription& description, size_t offset, | ||||||
|         evaluate_block_conditions(); |         evaluate_block_conditions(); | ||||||
|     } |     } | ||||||
|     if (nwritten < 0) |     if (nwritten < 0) | ||||||
|         return KResult(nwritten); |         return KResult((ErrnoCode)-nwritten); | ||||||
|     return nwritten; |     return nwritten; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -78,7 +78,7 @@ KResultOr<Region*> InodeFile::mmap(Process& process, FileDescription& descriptio | ||||||
|     else |     else | ||||||
|         vmobject = PrivateInodeVMObject::create_with_inode(inode()); |         vmobject = PrivateInodeVMObject::create_with_inode(inode()); | ||||||
|     if (!vmobject) |     if (!vmobject) | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     return process.allocate_region_with_vmobject(preferred_vaddr, size, *vmobject, offset, description.absolute_path(), prot, shared); |     return process.allocate_region_with_vmobject(preferred_vaddr, size, *vmobject, offset, description.absolute_path(), prot, shared); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -95,8 +95,8 @@ KResult InodeFile::truncate(u64 size) | ||||||
|     if (truncate_result.is_error()) |     if (truncate_result.is_error()) | ||||||
|         return truncate_result; |         return truncate_result; | ||||||
|     int mtime_result = m_inode->set_mtime(kgettimeofday().tv_sec); |     int mtime_result = m_inode->set_mtime(kgettimeofday().tv_sec); | ||||||
|     if (mtime_result != 0) |     if (mtime_result < 0) | ||||||
|         return KResult(mtime_result); |         return KResult((ErrnoCode)-mtime_result); | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -106,7 +106,7 @@ struct InodeMetadata { | ||||||
|     KResult stat(stat& buffer) const |     KResult stat(stat& buffer) const | ||||||
|     { |     { | ||||||
|         if (!is_valid()) |         if (!is_valid()) | ||||||
|             return KResult(-EIO); |             return EIO; | ||||||
|         buffer.st_rdev = encoded_device(major_device, minor_device); |         buffer.st_rdev = encoded_device(major_device, minor_device); | ||||||
|         buffer.st_ino = inode.index(); |         buffer.st_ino = inode.index(); | ||||||
|         buffer.st_mode = mode; |         buffer.st_mode = mode; | ||||||
|  |  | ||||||
|  | @ -77,14 +77,14 @@ KResultOr<size_t> InodeWatcher::read(FileDescription&, size_t, UserOrKernelBuffe | ||||||
|         return (ssize_t)data_bytes; |         return (ssize_t)data_bytes; | ||||||
|     }); |     }); | ||||||
|     if (nwritten < 0) |     if (nwritten < 0) | ||||||
|         return KResult(nwritten); |         return KResult((ErrnoCode)-nwritten); | ||||||
|     evaluate_block_conditions(); |     evaluate_block_conditions(); | ||||||
|     return bytes_to_write; |     return bytes_to_write; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResultOr<size_t> InodeWatcher::write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) | KResultOr<size_t> InodeWatcher::write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) | ||||||
| { | { | ||||||
|     return KResult(-EIO); |     return EIO; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| String InodeWatcher::absolute_path(const FileDescription&) const | String InodeWatcher::absolute_path(const FileDescription&) const | ||||||
|  |  | ||||||
|  | @ -532,7 +532,7 @@ KResult Plan9FS::post_message(Message& message, RefPtr<ReceiveCompletion> comple | ||||||
|         if (!description.can_write()) { |         if (!description.can_write()) { | ||||||
|             auto unblock_flags = Thread::FileBlocker::BlockFlags::None; |             auto unblock_flags = Thread::FileBlocker::BlockFlags::None; | ||||||
|             if (Thread::current()->block<Thread::WriteBlocker>({}, description, unblock_flags).was_interrupted()) |             if (Thread::current()->block<Thread::WriteBlocker>({}, description, unblock_flags).was_interrupted()) | ||||||
|                 return KResult(-EINTR); |                 return EINTR; | ||||||
|         } |         } | ||||||
|         auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(const_cast<u8*>(data)); |         auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(const_cast<u8*>(data)); | ||||||
|         auto nwritten_or_error = description.write(data_buffer, size); |         auto nwritten_or_error = description.write(data_buffer, size); | ||||||
|  | @ -553,7 +553,7 @@ KResult Plan9FS::do_read(u8* data, size_t size) | ||||||
|         if (!description.can_read()) { |         if (!description.can_read()) { | ||||||
|             auto unblock_flags = Thread::FileBlocker::BlockFlags::None; |             auto unblock_flags = Thread::FileBlocker::BlockFlags::None; | ||||||
|             if (Thread::current()->block<Thread::ReadBlocker>({}, description, unblock_flags).was_interrupted()) |             if (Thread::current()->block<Thread::ReadBlocker>({}, description, unblock_flags).was_interrupted()) | ||||||
|                 return KResult(-EINTR); |                 return EINTR; | ||||||
|         } |         } | ||||||
|         auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(data); |         auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(data); | ||||||
|         auto nread_or_error = description.read(data_buffer, size); |         auto nread_or_error = description.read(data_buffer, size); | ||||||
|  | @ -561,7 +561,7 @@ KResult Plan9FS::do_read(u8* data, size_t size) | ||||||
|             return nread_or_error.error(); |             return nread_or_error.error(); | ||||||
|         auto nread = nread_or_error.value(); |         auto nread = nread_or_error.value(); | ||||||
|         if (nread == 0) |         if (nread == 0) | ||||||
|             return KResult(-EIO); |             return EIO; | ||||||
|         data += nread; |         data += nread; | ||||||
|         size -= nread; |         size -= nread; | ||||||
|     } |     } | ||||||
|  | @ -582,7 +582,7 @@ KResult Plan9FS::read_and_dispatch_one_message() | ||||||
| 
 | 
 | ||||||
|     auto buffer = KBuffer::try_create_with_size(header.size, Region::Access::Read | Region::Access::Write); |     auto buffer = KBuffer::try_create_with_size(header.size, Region::Access::Read | Region::Access::Write); | ||||||
|     if (!buffer) |     if (!buffer) | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     // Copy the already read header into the buffer.
 |     // Copy the already read header into the buffer.
 | ||||||
|     memcpy(buffer->data(), &header, sizeof(header)); |     memcpy(buffer->data(), &header, sizeof(header)); | ||||||
|     result = do_read(buffer->data() + sizeof(header), header.size - sizeof(header)); |     result = do_read(buffer->data() + sizeof(header), header.size - sizeof(header)); | ||||||
|  | @ -622,11 +622,11 @@ KResult Plan9FS::post_message_and_wait_for_a_reply(Message& message) | ||||||
|     if (result.is_error()) |     if (result.is_error()) | ||||||
|         return result; |         return result; | ||||||
|     if (Thread::current()->block<Plan9FS::Blocker>({}, *this, message, completion).was_interrupted()) |     if (Thread::current()->block<Plan9FS::Blocker>({}, *this, message, completion).was_interrupted()) | ||||||
|         return KResult(-EINTR); |         return EINTR; | ||||||
| 
 | 
 | ||||||
|     if (completion->result.is_error()) { |     if (completion->result.is_error()) { | ||||||
|         dbgln("Plan9FS: Message was aborted with error {}", completion->result.error()); |         dbgln("Plan9FS: Message was aborted with error {}", completion->result.error()); | ||||||
|         return KResult(-EIO); |         return EIO; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto reply_type = message.type(); |     auto reply_type = message.type(); | ||||||
|  | @ -635,7 +635,7 @@ KResult Plan9FS::post_message_and_wait_for_a_reply(Message& message) | ||||||
|         // Contains a numerical Linux errno; hopefully our errno numbers match.
 |         // Contains a numerical Linux errno; hopefully our errno numbers match.
 | ||||||
|         u32 error_code; |         u32 error_code; | ||||||
|         message >> error_code; |         message >> error_code; | ||||||
|         return KResult(-error_code); |         return KResult((ErrnoCode)error_code); | ||||||
|     } else if (reply_type == Message::Type::Rerror) { |     } else if (reply_type == Message::Type::Rerror) { | ||||||
|         // Contains an error message. We could attempt to parse it, but for now
 |         // Contains an error message. We could attempt to parse it, but for now
 | ||||||
|         // we simply return -EIO instead. In 9P200.u, it can also contain a
 |         // we simply return -EIO instead. In 9P200.u, it can also contain a
 | ||||||
|  | @ -643,12 +643,12 @@ KResult Plan9FS::post_message_and_wait_for_a_reply(Message& message) | ||||||
|         StringView error_name; |         StringView error_name; | ||||||
|         message >> error_name; |         message >> error_name; | ||||||
|         dbgln("Plan9FS: Received error name {}", error_name); |         dbgln("Plan9FS: Received error name {}", error_name); | ||||||
|         return KResult(-EIO); |         return EIO; | ||||||
|     } else if ((u8)reply_type != (u8)request_type + 1) { |     } else if ((u8)reply_type != (u8)request_type + 1) { | ||||||
|         // Other than those error messages. we only expect the matching reply
 |         // Other than those error messages. we only expect the matching reply
 | ||||||
|         // message type.
 |         // message type.
 | ||||||
|         dbgln("Plan9FS: Received unexpected message type {} in response to {}", (u8)reply_type, (u8)request_type); |         dbgln("Plan9FS: Received unexpected message type {} in response to {}", (u8)reply_type, (u8)request_type); | ||||||
|         return KResult(-EIO); |         return EIO; | ||||||
|     } else { |     } else { | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     } |     } | ||||||
|  | @ -944,7 +944,7 @@ KResult Plan9FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEnt | ||||||
|         return result; |         return result; | ||||||
|     } else { |     } else { | ||||||
|         // TODO
 |         // TODO
 | ||||||
|         return KResult(-ENOTIMPL); |         return ENOTIMPL; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -964,31 +964,31 @@ RefPtr<Inode> Plan9FSInode::lookup(StringView name) | ||||||
| KResultOr<NonnullRefPtr<Inode>> Plan9FSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t) | KResultOr<NonnullRefPtr<Inode>> Plan9FSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t) | ||||||
| { | { | ||||||
|     // TODO
 |     // TODO
 | ||||||
|     return KResult(-ENOTIMPL); |     return ENOTIMPL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult Plan9FSInode::add_child(Inode&, const StringView&, mode_t) | KResult Plan9FSInode::add_child(Inode&, const StringView&, mode_t) | ||||||
| { | { | ||||||
|     // TODO
 |     // TODO
 | ||||||
|     return KResult(-ENOTIMPL); |     return ENOTIMPL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult Plan9FSInode::remove_child(const StringView&) | KResult Plan9FSInode::remove_child(const StringView&) | ||||||
| { | { | ||||||
|     // TODO
 |     // TODO
 | ||||||
|     return KResult(-ENOTIMPL); |     return ENOTIMPL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult Plan9FSInode::chmod(mode_t) | KResult Plan9FSInode::chmod(mode_t) | ||||||
| { | { | ||||||
|     // TODO
 |     // TODO
 | ||||||
|     return KResult(-ENOTIMPL); |     return ENOTIMPL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult Plan9FSInode::chown(uid_t, gid_t) | KResult Plan9FSInode::chown(uid_t, gid_t) | ||||||
| { | { | ||||||
|     // TODO
 |     // TODO
 | ||||||
|     return KResult(-ENOTIMPL); |     return ENOTIMPL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult Plan9FSInode::truncate(u64 new_size) | KResult Plan9FSInode::truncate(u64 new_size) | ||||||
|  |  | ||||||
|  | @ -1073,14 +1073,14 @@ KResult ProcFSInode::refresh_data(FileDescription& description) const | ||||||
|     } |     } | ||||||
|     KBufferBuilder builder(buffer, true); |     KBufferBuilder builder(buffer, true); | ||||||
|     if (!read_callback(identifier(), builder)) |     if (!read_callback(identifier(), builder)) | ||||||
|         return KResult(-ENOENT); |         return ENOENT; | ||||||
|     // We don't use builder.build() here, which would steal our buffer
 |     // We don't use builder.build() here, which would steal our buffer
 | ||||||
|     // and turn it into an OwnPtr. Instead, just flush to the buffer so
 |     // and turn it into an OwnPtr. Instead, just flush to the buffer so
 | ||||||
|     // that we can read all the data that was written.
 |     // that we can read all the data that was written.
 | ||||||
|     if (!builder.flush()) |     if (!builder.flush()) | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     if (!buffer) |     if (!buffer) | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1220,7 +1220,7 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     if (!Kernel::is_directory(identifier())) |     if (!Kernel::is_directory(identifier())) | ||||||
|         return KResult(-ENOTDIR); |         return ENOTDIR; | ||||||
| 
 | 
 | ||||||
|     auto proc_file_type = to_proc_file_type(identifier()); |     auto proc_file_type = to_proc_file_type(identifier()); | ||||||
|     auto parent_id = to_parent_id(identifier()); |     auto parent_id = to_parent_id(identifier()); | ||||||
|  | @ -1263,7 +1263,7 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr | ||||||
|         auto pid = to_pid(identifier()); |         auto pid = to_pid(identifier()); | ||||||
|         auto process = Process::from_pid(pid); |         auto process = Process::from_pid(pid); | ||||||
|         if (!process) |         if (!process) | ||||||
|             return KResult(-ENOENT); |             return ENOENT; | ||||||
|         for (auto& entry : fs().m_entries) { |         for (auto& entry : fs().m_entries) { | ||||||
|             if (entry.proc_file_type > __FI_PID_Start && entry.proc_file_type < __FI_PID_End) { |             if (entry.proc_file_type > __FI_PID_Start && entry.proc_file_type < __FI_PID_End) { | ||||||
|                 if (entry.proc_file_type == FI_PID_exe && !process->executable()) |                 if (entry.proc_file_type == FI_PID_exe && !process->executable()) | ||||||
|  | @ -1278,7 +1278,7 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr | ||||||
|         auto pid = to_pid(identifier()); |         auto pid = to_pid(identifier()); | ||||||
|         auto process = Process::from_pid(pid); |         auto process = Process::from_pid(pid); | ||||||
|         if (!process) |         if (!process) | ||||||
|             return KResult(-ENOENT); |             return ENOENT; | ||||||
|         for (int i = 0; i < process->max_open_file_descriptors(); ++i) { |         for (int i = 0; i < process->max_open_file_descriptors(); ++i) { | ||||||
|             auto description = process->file_description(i); |             auto description = process->file_description(i); | ||||||
|             if (!description) |             if (!description) | ||||||
|  | @ -1293,7 +1293,7 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr | ||||||
|         auto pid = to_pid(identifier()); |         auto pid = to_pid(identifier()); | ||||||
|         auto process = Process::from_pid(pid); |         auto process = Process::from_pid(pid); | ||||||
|         if (!process) |         if (!process) | ||||||
|             return KResult(-ENOENT); |             return ENOENT; | ||||||
|         process->for_each_thread([&](Thread& thread) -> IterationDecision { |         process->for_each_thread([&](Thread& thread) -> IterationDecision { | ||||||
|             int tid = thread.tid().value(); |             int tid = thread.tid().value(); | ||||||
|             char name[16]; |             char name[16]; | ||||||
|  | @ -1478,7 +1478,7 @@ KResultOr<NonnullRefPtr<Custody>> ProcFSInode::resolve_as_link(Custody& base, Re | ||||||
|     auto proc_file_type = to_proc_file_type(identifier()); |     auto proc_file_type = to_proc_file_type(identifier()); | ||||||
|     auto process = Process::from_pid(pid); |     auto process = Process::from_pid(pid); | ||||||
|     if (!process) |     if (!process) | ||||||
|         return KResult(-ENOENT); |         return ENOENT; | ||||||
| 
 | 
 | ||||||
|     if (to_proc_parent_directory(identifier()) == PDI_PID_fd) { |     if (to_proc_parent_directory(identifier()) == PDI_PID_fd) { | ||||||
|         if (out_parent) |         if (out_parent) | ||||||
|  | @ -1486,7 +1486,7 @@ KResultOr<NonnullRefPtr<Custody>> ProcFSInode::resolve_as_link(Custody& base, Re | ||||||
|         int fd = to_fd(identifier()); |         int fd = to_fd(identifier()); | ||||||
|         auto description = process->file_description(fd); |         auto description = process->file_description(fd); | ||||||
|         if (!description) |         if (!description) | ||||||
|             return KResult(-ENOENT); |             return ENOENT; | ||||||
|         auto proxy_inode = ProcFSProxyInode::create(const_cast<ProcFS&>(fs()), *description); |         auto proxy_inode = ProcFSProxyInode::create(const_cast<ProcFS&>(fs()), *description); | ||||||
|         return Custody::create(&base, "", proxy_inode, base.mount_flags()); |         return Custody::create(&base, "", proxy_inode, base.mount_flags()); | ||||||
|     } |     } | ||||||
|  | @ -1511,7 +1511,7 @@ KResultOr<NonnullRefPtr<Custody>> ProcFSInode::resolve_as_link(Custody& base, Re | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!res) |     if (!res) | ||||||
|         return KResult(-ENOENT); |         return ENOENT; | ||||||
| 
 | 
 | ||||||
|     return *res; |     return *res; | ||||||
| } | } | ||||||
|  | @ -1559,21 +1559,21 @@ InodeMetadata ProcFSProxyInode::metadata() const | ||||||
| KResultOr<NonnullRefPtr<Inode>> ProcFSProxyInode::create_child(const String& name, mode_t mode, dev_t dev, uid_t uid, gid_t gid) | KResultOr<NonnullRefPtr<Inode>> ProcFSProxyInode::create_child(const String& name, mode_t mode, dev_t dev, uid_t uid, gid_t gid) | ||||||
| { | { | ||||||
|     if (!m_fd->inode()) |     if (!m_fd->inode()) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     return m_fd->inode()->create_child(name, mode, dev, uid, gid); |     return m_fd->inode()->create_child(name, mode, dev, uid, gid); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult ProcFSProxyInode::add_child(Inode& child, const StringView& name, mode_t mode) | KResult ProcFSProxyInode::add_child(Inode& child, const StringView& name, mode_t mode) | ||||||
| { | { | ||||||
|     if (!m_fd->inode()) |     if (!m_fd->inode()) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     return m_fd->inode()->add_child(child, name, mode); |     return m_fd->inode()->add_child(child, name, mode); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult ProcFSProxyInode::remove_child(const StringView& name) | KResult ProcFSProxyInode::remove_child(const StringView& name) | ||||||
| { | { | ||||||
|     if (!m_fd->inode()) |     if (!m_fd->inode()) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     return m_fd->inode()->remove_child(name); |     return m_fd->inode()->remove_child(name); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1587,23 +1587,23 @@ RefPtr<Inode> ProcFSProxyInode::lookup(StringView name) | ||||||
| KResultOr<size_t> ProcFSProxyInode::directory_entry_count() const | KResultOr<size_t> ProcFSProxyInode::directory_entry_count() const | ||||||
| { | { | ||||||
|     if (!m_fd->inode()) |     if (!m_fd->inode()) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     return m_fd->inode()->directory_entry_count(); |     return m_fd->inode()->directory_entry_count(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResultOr<NonnullRefPtr<Inode>> ProcFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t) | KResultOr<NonnullRefPtr<Inode>> ProcFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t) | ||||||
| { | { | ||||||
|     return KResult(-EPERM); |     return EPERM; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult ProcFSInode::add_child(Inode&, const StringView&, mode_t) | KResult ProcFSInode::add_child(Inode&, const StringView&, mode_t) | ||||||
| { | { | ||||||
|     return KResult(-EPERM); |     return EPERM; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResult ProcFSInode::remove_child([[maybe_unused]] const StringView& name) | KResult ProcFSInode::remove_child([[maybe_unused]] const StringView& name) | ||||||
| { | { | ||||||
|     return KResult(-EPERM); |     return EPERM; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResultOr<size_t> ProcFSInode::directory_entry_count() const | KResultOr<size_t> ProcFSInode::directory_entry_count() const | ||||||
|  | @ -1623,7 +1623,7 @@ KResultOr<size_t> ProcFSInode::directory_entry_count() const | ||||||
| 
 | 
 | ||||||
| KResult ProcFSInode::chmod(mode_t) | KResult ProcFSInode::chmod(mode_t) | ||||||
| { | { | ||||||
|     return KResult(-EPERM); |     return EPERM; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ProcFS::ProcFS() | ProcFS::ProcFS() | ||||||
|  | @ -1673,6 +1673,6 @@ ProcFS::ProcFSDirectoryEntry* ProcFS::get_directory_entry(InodeIdentifier identi | ||||||
| 
 | 
 | ||||||
| KResult ProcFSInode::chown(uid_t, gid_t) | KResult ProcFSInode::chown(uid_t, gid_t) | ||||||
| { | { | ||||||
|     return KResult(-EPERM); |     return EPERM; | ||||||
| } | } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -139,8 +139,8 @@ private: | ||||||
|     virtual KResult add_child(Inode&, const StringView& name, mode_t) override; |     virtual KResult add_child(Inode&, const StringView& name, mode_t) override; | ||||||
|     virtual KResult remove_child(const StringView& name) override; |     virtual KResult remove_child(const StringView& name) override; | ||||||
|     virtual KResultOr<size_t> directory_entry_count() const override; |     virtual KResultOr<size_t> directory_entry_count() const override; | ||||||
|     virtual KResult chmod(mode_t) override { return KResult(-EINVAL); } |     virtual KResult chmod(mode_t) override { return EINVAL; } | ||||||
|     virtual KResult chown(uid_t, gid_t) override { return KResult(-EINVAL); } |     virtual KResult chown(uid_t, gid_t) override { return EINVAL; } | ||||||
|     virtual KResultOr<NonnullRefPtr<Custody>> resolve_as_link(Custody&, RefPtr<Custody>*, int, int) const override { ASSERT_NOT_REACHED(); } |     virtual KResultOr<NonnullRefPtr<Custody>> resolve_as_link(Custody&, RefPtr<Custody>*, int, int) const override { ASSERT_NOT_REACHED(); } | ||||||
|     virtual FileDescription* preopen_fd() override { return m_fd; } |     virtual FileDescription* preopen_fd() override { return m_fd; } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -134,7 +134,7 @@ KResult TmpFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry | ||||||
|     LOCKER(m_lock, Lock::Mode::Shared); |     LOCKER(m_lock, Lock::Mode::Shared); | ||||||
| 
 | 
 | ||||||
|     if (!is_directory()) |     if (!is_directory()) | ||||||
|         return KResult(-ENOTDIR); |         return ENOTDIR; | ||||||
| 
 | 
 | ||||||
|     callback({ ".", identifier(), 0 }); |     callback({ ".", identifier(), 0 }); | ||||||
|     callback({ "..", m_parent, 0 }); |     callback({ "..", m_parent, 0 }); | ||||||
|  | @ -278,7 +278,7 @@ KResultOr<NonnullRefPtr<Inode>> TmpFSInode::create_child(const String& name, mod | ||||||
| 
 | 
 | ||||||
|     // TODO: Support creating devices on TmpFS.
 |     // TODO: Support creating devices on TmpFS.
 | ||||||
|     if (dev != 0) |     if (dev != 0) | ||||||
|         return KResult(-ENOTSUP); |         return ENOTSUP; | ||||||
| 
 | 
 | ||||||
|     struct timeval now; |     struct timeval now; | ||||||
|     kgettimeofday(now); |     kgettimeofday(now); | ||||||
|  | @ -305,7 +305,7 @@ KResult TmpFSInode::add_child(Inode& child, const StringView& name, mode_t) | ||||||
|     ASSERT(child.fsid() == fsid()); |     ASSERT(child.fsid() == fsid()); | ||||||
| 
 | 
 | ||||||
|     if (name.length() > NAME_MAX) |     if (name.length() > NAME_MAX) | ||||||
|         return KResult(-ENAMETOOLONG); |         return ENAMETOOLONG; | ||||||
| 
 | 
 | ||||||
|     m_children.set(name, { name, static_cast<TmpFSInode&>(child) }); |     m_children.set(name, { name, static_cast<TmpFSInode&>(child) }); | ||||||
|     did_add_child(child.identifier()); |     did_add_child(child.identifier()); | ||||||
|  | @ -322,7 +322,7 @@ KResult TmpFSInode::remove_child(const StringView& name) | ||||||
| 
 | 
 | ||||||
|     auto it = m_children.find(name); |     auto it = m_children.find(name); | ||||||
|     if (it == m_children.end()) |     if (it == m_children.end()) | ||||||
|         return KResult(-ENOENT); |         return ENOENT; | ||||||
|     auto child_id = it->value.inode->identifier(); |     auto child_id = it->value.inode->identifier(); | ||||||
|     m_children.remove(it); |     m_children.remove(it); | ||||||
|     did_remove_child(child_id); |     did_remove_child(child_id); | ||||||
|  | @ -339,7 +339,7 @@ KResult TmpFSInode::truncate(u64 size) | ||||||
|     else if (!m_content) { |     else if (!m_content) { | ||||||
|         m_content = KBuffer::try_create_with_size(size); |         m_content = KBuffer::try_create_with_size(size); | ||||||
|         if (!m_content) |         if (!m_content) | ||||||
|             return KResult(-ENOMEM); |             return ENOMEM; | ||||||
|     } else if (static_cast<size_t>(size) < m_content->capacity()) { |     } else if (static_cast<size_t>(size) < m_content->capacity()) { | ||||||
|         size_t prev_size = m_metadata.size; |         size_t prev_size = m_metadata.size; | ||||||
|         m_content->set_size(size); |         m_content->set_size(size); | ||||||
|  | @ -349,7 +349,7 @@ KResult TmpFSInode::truncate(u64 size) | ||||||
|         size_t prev_size = m_metadata.size; |         size_t prev_size = m_metadata.size; | ||||||
|         auto tmp = KBuffer::try_create_with_size(size); |         auto tmp = KBuffer::try_create_with_size(size); | ||||||
|         if (!tmp) |         if (!tmp) | ||||||
|             return KResult(-ENOMEM); |             return ENOMEM; | ||||||
|         memcpy(tmp->data(), m_content->data(), prev_size); |         memcpy(tmp->data(), m_content->data(), prev_size); | ||||||
|         m_content = move(tmp); |         m_content = move(tmp); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -107,7 +107,7 @@ KResult VFS::remount(Custody& mount_point, int new_flags) | ||||||
| 
 | 
 | ||||||
|     Mount* mount = find_mount_for_guest(mount_point.inode()); |     Mount* mount = find_mount_for_guest(mount_point.inode()); | ||||||
|     if (!mount) |     if (!mount) | ||||||
|         return KResult(-ENODEV); |         return ENODEV; | ||||||
| 
 | 
 | ||||||
|     mount->set_flags(new_flags); |     mount->set_flags(new_flags); | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
|  | @ -133,7 +133,7 @@ KResult VFS::unmount(Inode& guest_inode) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     dbg() << "VFS: Nothing mounted on inode " << guest_inode.identifier(); |     dbg() << "VFS: Nothing mounted on inode " << guest_inode.identifier(); | ||||||
|     return KResult(-ENODEV); |     return ENODEV; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool VFS::mount_root(FS& file_system) | bool VFS::mount_root(FS& file_system) | ||||||
|  | @ -230,16 +230,16 @@ KResult VFS::utime(StringView path, Custody& base, time_t atime, time_t mtime) | ||||||
|     auto& inode = custody.inode(); |     auto& inode = custody.inode(); | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if (!current_process->is_superuser() && inode.metadata().uid != current_process->euid()) |     if (!current_process->is_superuser() && inode.metadata().uid != current_process->euid()) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
|     if (custody.is_readonly()) |     if (custody.is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     int error = inode.set_atime(atime); |     int error = inode.set_atime(atime); | ||||||
|     if (error) |     if (error < 0) | ||||||
|         return KResult(error); |         return KResult((ErrnoCode)-error); | ||||||
|     error = inode.set_mtime(mtime); |     error = inode.set_mtime(mtime); | ||||||
|     if (error) |     if (error < 0) | ||||||
|         return KResult(error); |         return KResult((ErrnoCode)-error); | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -254,20 +254,20 @@ KResultOr<InodeMetadata> VFS::lookup_metadata(StringView path, Custody& base, in | ||||||
| KResultOr<NonnullRefPtr<FileDescription>> VFS::open(StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> owner) | KResultOr<NonnullRefPtr<FileDescription>> VFS::open(StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> owner) | ||||||
| { | { | ||||||
|     if ((options & O_CREAT) && (options & O_DIRECTORY)) |     if ((options & O_CREAT) && (options & O_DIRECTORY)) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     RefPtr<Custody> parent_custody; |     RefPtr<Custody> parent_custody; | ||||||
|     auto custody_or_error = resolve_path(path, base, &parent_custody, options); |     auto custody_or_error = resolve_path(path, base, &parent_custody, options); | ||||||
|     if (options & O_CREAT) { |     if (options & O_CREAT) { | ||||||
|         if (!parent_custody) |         if (!parent_custody) | ||||||
|             return KResult(-ENOENT); |             return ENOENT; | ||||||
|         if (custody_or_error.is_error()) { |         if (custody_or_error.is_error()) { | ||||||
|             if (custody_or_error.error() != -ENOENT) |             if (custody_or_error.error() != -ENOENT) | ||||||
|                 return custody_or_error.error(); |                 return custody_or_error.error(); | ||||||
|             return create(path, options, mode, *parent_custody, move(owner)); |             return create(path, options, mode, *parent_custody, move(owner)); | ||||||
|         } |         } | ||||||
|         if (options & O_EXCL) |         if (options & O_EXCL) | ||||||
|             return KResult(-EEXIST); |             return EEXIST; | ||||||
|     } |     } | ||||||
|     if (custody_or_error.is_error()) |     if (custody_or_error.is_error()) | ||||||
|         return custody_or_error.error(); |         return custody_or_error.error(); | ||||||
|  | @ -277,24 +277,24 @@ KResultOr<NonnullRefPtr<FileDescription>> VFS::open(StringView path, int options | ||||||
|     auto metadata = inode.metadata(); |     auto metadata = inode.metadata(); | ||||||
| 
 | 
 | ||||||
|     if ((options & O_DIRECTORY) && !metadata.is_directory()) |     if ((options & O_DIRECTORY) && !metadata.is_directory()) | ||||||
|         return KResult(-ENOTDIR); |         return ENOTDIR; | ||||||
| 
 | 
 | ||||||
|     bool should_truncate_file = false; |     bool should_truncate_file = false; | ||||||
| 
 | 
 | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if ((options & O_RDONLY) && !metadata.may_read(*current_process)) |     if ((options & O_RDONLY) && !metadata.may_read(*current_process)) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
| 
 | 
 | ||||||
|     if (options & O_WRONLY) { |     if (options & O_WRONLY) { | ||||||
|         if (!metadata.may_write(*current_process)) |         if (!metadata.may_write(*current_process)) | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|         if (metadata.is_directory()) |         if (metadata.is_directory()) | ||||||
|             return KResult(-EISDIR); |             return EISDIR; | ||||||
|         should_truncate_file = options & O_TRUNC; |         should_truncate_file = options & O_TRUNC; | ||||||
|     } |     } | ||||||
|     if (options & O_EXEC) { |     if (options & O_EXEC) { | ||||||
|         if (!metadata.may_execute(*current_process) || (custody.mount_flags() & MS_NOEXEC)) |         if (!metadata.may_execute(*current_process) || (custody.mount_flags() & MS_NOEXEC)) | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (auto preopen_fd = inode.preopen_fd()) |     if (auto preopen_fd = inode.preopen_fd()) | ||||||
|  | @ -321,15 +321,15 @@ KResultOr<NonnullRefPtr<FileDescription>> VFS::open(StringView path, int options | ||||||
|             description->set_original_inode({}, inode); |             description->set_original_inode({}, inode); | ||||||
|             return description; |             return description; | ||||||
|         } |         } | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (metadata.is_device()) { |     if (metadata.is_device()) { | ||||||
|         if (custody.mount_flags() & MS_NODEV) |         if (custody.mount_flags() & MS_NODEV) | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|         auto device = Device::get_device(metadata.major_device, metadata.minor_device); |         auto device = Device::get_device(metadata.major_device, metadata.minor_device); | ||||||
|         if (device == nullptr) { |         if (device == nullptr) { | ||||||
|             return KResult(-ENODEV); |             return ENODEV; | ||||||
|         } |         } | ||||||
|         auto descriptor_or_error = device->open(options); |         auto descriptor_or_error = device->open(options); | ||||||
|         if (descriptor_or_error.is_error()) |         if (descriptor_or_error.is_error()) | ||||||
|  | @ -341,7 +341,7 @@ KResultOr<NonnullRefPtr<FileDescription>> VFS::open(StringView path, int options | ||||||
|     // Check for read-only FS. Do this after handling preopen FD and devices,
 |     // Check for read-only FS. Do this after handling preopen FD and devices,
 | ||||||
|     // but before modifying the inode in any way.
 |     // but before modifying the inode in any way.
 | ||||||
|     if ((options & O_WRONLY) && custody.is_readonly()) |     if ((options & O_WRONLY) && custody.is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     if (should_truncate_file) { |     if (should_truncate_file) { | ||||||
|         KResult result = inode.truncate(0); |         KResult result = inode.truncate(0); | ||||||
|  | @ -360,22 +360,22 @@ KResultOr<NonnullRefPtr<FileDescription>> VFS::open(StringView path, int options | ||||||
| KResult VFS::mknod(StringView path, mode_t mode, dev_t dev, Custody& base) | KResult VFS::mknod(StringView path, mode_t mode, dev_t dev, Custody& base) | ||||||
| { | { | ||||||
|     if (!is_regular_file(mode) && !is_block_device(mode) && !is_character_device(mode) && !is_fifo(mode) && !is_socket(mode)) |     if (!is_regular_file(mode) && !is_block_device(mode) && !is_character_device(mode) && !is_fifo(mode) && !is_socket(mode)) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     RefPtr<Custody> parent_custody; |     RefPtr<Custody> parent_custody; | ||||||
|     auto existing_file_or_error = resolve_path(path, base, &parent_custody); |     auto existing_file_or_error = resolve_path(path, base, &parent_custody); | ||||||
|     if (!existing_file_or_error.is_error()) |     if (!existing_file_or_error.is_error()) | ||||||
|         return KResult(-EEXIST); |         return EEXIST; | ||||||
|     if (!parent_custody) |     if (!parent_custody) | ||||||
|         return KResult(-ENOENT); |         return ENOENT; | ||||||
|     if (existing_file_or_error.error() != -ENOENT) |     if (existing_file_or_error.error() != -ENOENT) | ||||||
|         return existing_file_or_error.error(); |         return existing_file_or_error.error(); | ||||||
|     auto& parent_inode = parent_custody->inode(); |     auto& parent_inode = parent_custody->inode(); | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if (!parent_inode.metadata().may_write(*current_process)) |     if (!parent_inode.metadata().may_write(*current_process)) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
|     if (parent_custody->is_readonly()) |     if (parent_custody->is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     LexicalPath p(path); |     LexicalPath p(path); | ||||||
|     dbgln("VFS::mknod: '{}' mode={} dev={} in {}", p.basename(), mode, dev, parent_inode.identifier()); |     dbgln("VFS::mknod: '{}' mode={} dev={} in {}", p.basename(), mode, dev, parent_inode.identifier()); | ||||||
|  | @ -396,9 +396,9 @@ KResultOr<NonnullRefPtr<FileDescription>> VFS::create(StringView path, int optio | ||||||
|     auto& parent_inode = parent_custody.inode(); |     auto& parent_inode = parent_custody.inode(); | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if (!parent_inode.metadata().may_write(*current_process)) |     if (!parent_inode.metadata().may_write(*current_process)) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
|     if (parent_custody.is_readonly()) |     if (parent_custody.is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     LexicalPath p(path); |     LexicalPath p(path); | ||||||
| #ifdef VFS_DEBUG | #ifdef VFS_DEBUG | ||||||
|  | @ -431,18 +431,18 @@ KResult VFS::mkdir(StringView path, mode_t mode, Custody& base) | ||||||
|     RefPtr<Custody> parent_custody; |     RefPtr<Custody> parent_custody; | ||||||
|     auto result = resolve_path(path, base, &parent_custody); |     auto result = resolve_path(path, base, &parent_custody); | ||||||
|     if (!result.is_error()) |     if (!result.is_error()) | ||||||
|         return KResult(-EEXIST); |         return EEXIST; | ||||||
|     if (!parent_custody) |     if (!parent_custody) | ||||||
|         return KResult(-ENOENT); |         return ENOENT; | ||||||
|     if (result.error() != -ENOENT) |     if (result.error() != -ENOENT) | ||||||
|         return result.error(); |         return result.error(); | ||||||
| 
 | 
 | ||||||
|     auto& parent_inode = parent_custody->inode(); |     auto& parent_inode = parent_custody->inode(); | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if (!parent_inode.metadata().may_write(*current_process)) |     if (!parent_inode.metadata().may_write(*current_process)) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
|     if (parent_custody->is_readonly()) |     if (parent_custody->is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     LexicalPath p(path); |     LexicalPath p(path); | ||||||
| #ifdef VFS_DEBUG | #ifdef VFS_DEBUG | ||||||
|  | @ -462,17 +462,17 @@ KResult VFS::access(StringView path, int mode, Custody& base) | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if (mode & R_OK) { |     if (mode & R_OK) { | ||||||
|         if (!metadata.may_read(*current_process)) |         if (!metadata.may_read(*current_process)) | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|     } |     } | ||||||
|     if (mode & W_OK) { |     if (mode & W_OK) { | ||||||
|         if (!metadata.may_write(*current_process)) |         if (!metadata.may_write(*current_process)) | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|         if (custody.is_readonly()) |         if (custody.is_readonly()) | ||||||
|             return KResult(-EROFS); |             return EROFS; | ||||||
|     } |     } | ||||||
|     if (mode & X_OK) { |     if (mode & X_OK) { | ||||||
|         if (!metadata.may_execute(*current_process)) |         if (!metadata.may_execute(*current_process)) | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|     } |     } | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
| } | } | ||||||
|  | @ -485,9 +485,9 @@ KResultOr<NonnullRefPtr<Custody>> VFS::open_directory(StringView path, Custody& | ||||||
|     auto& custody = *inode_or_error.value(); |     auto& custody = *inode_or_error.value(); | ||||||
|     auto& inode = custody.inode(); |     auto& inode = custody.inode(); | ||||||
|     if (!inode.is_directory()) |     if (!inode.is_directory()) | ||||||
|         return KResult(-ENOTDIR); |         return ENOTDIR; | ||||||
|     if (!inode.metadata().may_execute(*Process::current())) |     if (!inode.metadata().may_execute(*Process::current())) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
|     return custody; |     return custody; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -497,9 +497,9 @@ KResult VFS::chmod(Custody& custody, mode_t mode) | ||||||
| 
 | 
 | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if (current_process->euid() != inode.metadata().uid && !current_process->is_superuser()) |     if (current_process->euid() != inode.metadata().uid && !current_process->is_superuser()) | ||||||
|         return KResult(-EPERM); |         return EPERM; | ||||||
|     if (custody.is_readonly()) |     if (custody.is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     // Only change the permission bits.
 |     // Only change the permission bits.
 | ||||||
|     mode = (inode.mode() & ~07777u) | (mode & 07777u); |     mode = (inode.mode() & ~07777u) | (mode & 07777u); | ||||||
|  | @ -535,27 +535,27 @@ KResult VFS::rename(StringView old_path, StringView new_path, Custody& base) | ||||||
|     auto& new_parent_inode = new_parent_custody->inode(); |     auto& new_parent_inode = new_parent_custody->inode(); | ||||||
| 
 | 
 | ||||||
|     if (&old_parent_inode.fs() != &new_parent_inode.fs()) |     if (&old_parent_inode.fs() != &new_parent_inode.fs()) | ||||||
|         return KResult(-EXDEV); |         return EXDEV; | ||||||
| 
 | 
 | ||||||
|     for (auto* new_ancestor = new_parent_custody.ptr(); new_ancestor; new_ancestor = new_ancestor->parent()) { |     for (auto* new_ancestor = new_parent_custody.ptr(); new_ancestor; new_ancestor = new_ancestor->parent()) { | ||||||
|         if (&old_inode == &new_ancestor->inode()) |         if (&old_inode == &new_ancestor->inode()) | ||||||
|             return KResult(-EDIRINTOSELF); |             return EDIRINTOSELF; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if (!new_parent_inode.metadata().may_write(*current_process)) |     if (!new_parent_inode.metadata().may_write(*current_process)) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
| 
 | 
 | ||||||
|     if (!old_parent_inode.metadata().may_write(*current_process)) |     if (!old_parent_inode.metadata().may_write(*current_process)) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
| 
 | 
 | ||||||
|     if (old_parent_inode.metadata().is_sticky()) { |     if (old_parent_inode.metadata().is_sticky()) { | ||||||
|         if (!current_process->is_superuser() && old_inode.metadata().uid != current_process->euid()) |         if (!current_process->is_superuser() && old_inode.metadata().uid != current_process->euid()) | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (old_parent_custody->is_readonly() || new_parent_custody->is_readonly()) |     if (old_parent_custody->is_readonly() || new_parent_custody->is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     auto new_basename = LexicalPath(new_path).basename(); |     auto new_basename = LexicalPath(new_path).basename(); | ||||||
| 
 | 
 | ||||||
|  | @ -567,10 +567,10 @@ KResult VFS::rename(StringView old_path, StringView new_path, Custody& base) | ||||||
|             return KSuccess; |             return KSuccess; | ||||||
|         if (new_parent_inode.metadata().is_sticky()) { |         if (new_parent_inode.metadata().is_sticky()) { | ||||||
|             if (!current_process->is_superuser() && new_inode.metadata().uid != current_process->euid()) |             if (!current_process->is_superuser() && new_inode.metadata().uid != current_process->euid()) | ||||||
|                 return KResult(-EACCES); |                 return EACCES; | ||||||
|         } |         } | ||||||
|         if (new_inode.is_directory() && !old_inode.is_directory()) |         if (new_inode.is_directory() && !old_inode.is_directory()) | ||||||
|             return KResult(-EISDIR); |             return EISDIR; | ||||||
|         auto result = new_parent_inode.remove_child(new_basename); |         auto result = new_parent_inode.remove_child(new_basename); | ||||||
|         if (result.is_error()) |         if (result.is_error()) | ||||||
|             return result; |             return result; | ||||||
|  | @ -594,24 +594,24 @@ KResult VFS::chown(Custody& custody, uid_t a_uid, gid_t a_gid) | ||||||
| 
 | 
 | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if (current_process->euid() != metadata.uid && !current_process->is_superuser()) |     if (current_process->euid() != metadata.uid && !current_process->is_superuser()) | ||||||
|         return KResult(-EPERM); |         return EPERM; | ||||||
| 
 | 
 | ||||||
|     uid_t new_uid = metadata.uid; |     uid_t new_uid = metadata.uid; | ||||||
|     gid_t new_gid = metadata.gid; |     gid_t new_gid = metadata.gid; | ||||||
| 
 | 
 | ||||||
|     if (a_uid != (uid_t)-1) { |     if (a_uid != (uid_t)-1) { | ||||||
|         if (current_process->euid() != a_uid && !current_process->is_superuser()) |         if (current_process->euid() != a_uid && !current_process->is_superuser()) | ||||||
|             return KResult(-EPERM); |             return EPERM; | ||||||
|         new_uid = a_uid; |         new_uid = a_uid; | ||||||
|     } |     } | ||||||
|     if (a_gid != (gid_t)-1) { |     if (a_gid != (gid_t)-1) { | ||||||
|         if (!current_process->in_group(a_gid) && !current_process->is_superuser()) |         if (!current_process->in_group(a_gid) && !current_process->is_superuser()) | ||||||
|             return KResult(-EPERM); |             return EPERM; | ||||||
|         new_gid = a_gid; |         new_gid = a_gid; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (custody.is_readonly()) |     if (custody.is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     dbgln("VFS::chown(): inode {} <- uid={} gid={}", inode.identifier(), new_uid, new_gid); |     dbgln("VFS::chown(): inode {} <- uid={} gid={}", inode.identifier(), new_uid, new_gid); | ||||||
| 
 | 
 | ||||||
|  | @ -662,27 +662,27 @@ KResult VFS::link(StringView old_path, StringView new_path, Custody& base) | ||||||
|     RefPtr<Custody> parent_custody; |     RefPtr<Custody> parent_custody; | ||||||
|     auto new_custody_or_error = resolve_path(new_path, base, &parent_custody); |     auto new_custody_or_error = resolve_path(new_path, base, &parent_custody); | ||||||
|     if (!new_custody_or_error.is_error()) |     if (!new_custody_or_error.is_error()) | ||||||
|         return KResult(-EEXIST); |         return EEXIST; | ||||||
| 
 | 
 | ||||||
|     if (!parent_custody) |     if (!parent_custody) | ||||||
|         return KResult(-ENOENT); |         return ENOENT; | ||||||
| 
 | 
 | ||||||
|     auto& parent_inode = parent_custody->inode(); |     auto& parent_inode = parent_custody->inode(); | ||||||
| 
 | 
 | ||||||
|     if (parent_inode.fsid() != old_inode.fsid()) |     if (parent_inode.fsid() != old_inode.fsid()) | ||||||
|         return KResult(-EXDEV); |         return EXDEV; | ||||||
| 
 | 
 | ||||||
|     if (!parent_inode.metadata().may_write(*Process::current())) |     if (!parent_inode.metadata().may_write(*Process::current())) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
| 
 | 
 | ||||||
|     if (old_inode.is_directory()) |     if (old_inode.is_directory()) | ||||||
|         return KResult(-EPERM); |         return EPERM; | ||||||
| 
 | 
 | ||||||
|     if (parent_custody->is_readonly()) |     if (parent_custody->is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     if (!hard_link_allowed(old_inode)) |     if (!hard_link_allowed(old_inode)) | ||||||
|         return KResult(-EPERM); |         return EPERM; | ||||||
| 
 | 
 | ||||||
|     return parent_inode.add_child(old_inode, LexicalPath(new_path).basename(), old_inode.mode()); |     return parent_inode.add_child(old_inode, LexicalPath(new_path).basename(), old_inode.mode()); | ||||||
| } | } | ||||||
|  | @ -697,7 +697,7 @@ KResult VFS::unlink(StringView path, Custody& base) | ||||||
|     auto& inode = custody.inode(); |     auto& inode = custody.inode(); | ||||||
| 
 | 
 | ||||||
|     if (inode.is_directory()) |     if (inode.is_directory()) | ||||||
|         return KResult(-EISDIR); |         return EISDIR; | ||||||
| 
 | 
 | ||||||
|     // We have just checked that the inode is not a directory, and thus it's not
 |     // We have just checked that the inode is not a directory, and thus it's not
 | ||||||
|     // the root. So it should have a parent. Note that this would be invalidated
 |     // the root. So it should have a parent. Note that this would be invalidated
 | ||||||
|  | @ -707,15 +707,15 @@ KResult VFS::unlink(StringView path, Custody& base) | ||||||
|     auto& parent_inode = parent_custody->inode(); |     auto& parent_inode = parent_custody->inode(); | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if (!parent_inode.metadata().may_write(*current_process)) |     if (!parent_inode.metadata().may_write(*current_process)) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
| 
 | 
 | ||||||
|     if (parent_inode.metadata().is_sticky()) { |     if (parent_inode.metadata().is_sticky()) { | ||||||
|         if (!current_process->is_superuser() && inode.metadata().uid != current_process->euid()) |         if (!current_process->is_superuser() && inode.metadata().uid != current_process->euid()) | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (parent_custody->is_readonly()) |     if (parent_custody->is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     auto result = parent_inode.remove_child(LexicalPath(path).basename()); |     auto result = parent_inode.remove_child(LexicalPath(path).basename()); | ||||||
|     if (result.is_error()) |     if (result.is_error()) | ||||||
|  | @ -729,17 +729,17 @@ KResult VFS::symlink(StringView target, StringView linkpath, Custody& base) | ||||||
|     RefPtr<Custody> parent_custody; |     RefPtr<Custody> parent_custody; | ||||||
|     auto existing_custody_or_error = resolve_path(linkpath, base, &parent_custody); |     auto existing_custody_or_error = resolve_path(linkpath, base, &parent_custody); | ||||||
|     if (!existing_custody_or_error.is_error()) |     if (!existing_custody_or_error.is_error()) | ||||||
|         return KResult(-EEXIST); |         return EEXIST; | ||||||
|     if (!parent_custody) |     if (!parent_custody) | ||||||
|         return KResult(-ENOENT); |         return ENOENT; | ||||||
|     if (existing_custody_or_error.error() != -ENOENT) |     if (existing_custody_or_error.error() != -ENOENT) | ||||||
|         return existing_custody_or_error.error(); |         return existing_custody_or_error.error(); | ||||||
|     auto& parent_inode = parent_custody->inode(); |     auto& parent_inode = parent_custody->inode(); | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if (!parent_inode.metadata().may_write(*current_process)) |     if (!parent_inode.metadata().may_write(*current_process)) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
|     if (parent_custody->is_readonly()) |     if (parent_custody->is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     LexicalPath p(linkpath); |     LexicalPath p(linkpath); | ||||||
|     dbgln("VFS::symlink: '{}' (-> '{}') in {}", p.basename(), target, parent_inode.identifier()); |     dbgln("VFS::symlink: '{}' (-> '{}') in {}", p.basename(), target, parent_inode.identifier()); | ||||||
|  | @ -750,7 +750,7 @@ KResult VFS::symlink(StringView target, StringView linkpath, Custody& base) | ||||||
|     auto target_buffer = UserOrKernelBuffer::for_kernel_buffer(const_cast<u8*>((const u8*)target.characters_without_null_termination())); |     auto target_buffer = UserOrKernelBuffer::for_kernel_buffer(const_cast<u8*>((const u8*)target.characters_without_null_termination())); | ||||||
|     ssize_t nwritten = inode->write_bytes(0, target.length(), target_buffer, nullptr); |     ssize_t nwritten = inode->write_bytes(0, target.length(), target_buffer, nullptr); | ||||||
|     if (nwritten < 0) |     if (nwritten < 0) | ||||||
|         return KResult(nwritten); |         return KResult((ErrnoCode)-nwritten); | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -768,20 +768,20 @@ KResult VFS::rmdir(StringView path, Custody& base) | ||||||
|     // FIXME: We should return ENOTEMPTY if the last component of the path is ".."
 |     // FIXME: We should return ENOTEMPTY if the last component of the path is ".."
 | ||||||
| 
 | 
 | ||||||
|     if (!inode.is_directory()) |     if (!inode.is_directory()) | ||||||
|         return KResult(-ENOTDIR); |         return ENOTDIR; | ||||||
| 
 | 
 | ||||||
|     if (!parent_custody) |     if (!parent_custody) | ||||||
|         return KResult(-EBUSY); |         return EBUSY; | ||||||
| 
 | 
 | ||||||
|     auto& parent_inode = parent_custody->inode(); |     auto& parent_inode = parent_custody->inode(); | ||||||
|     auto parent_metadata = parent_inode.metadata(); |     auto parent_metadata = parent_inode.metadata(); | ||||||
| 
 | 
 | ||||||
|     if (!parent_metadata.may_write(*Process::current())) |     if (!parent_metadata.may_write(*Process::current())) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
| 
 | 
 | ||||||
|     if (parent_metadata.is_sticky()) { |     if (parent_metadata.is_sticky()) { | ||||||
|         if (!Process::current()->is_superuser() && inode.metadata().uid != Process::current()->euid()) |         if (!Process::current()->is_superuser() && inode.metadata().uid != Process::current()->euid()) | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     KResultOr<size_t> dir_count_result = inode.directory_entry_count(); |     KResultOr<size_t> dir_count_result = inode.directory_entry_count(); | ||||||
|  | @ -789,10 +789,10 @@ KResult VFS::rmdir(StringView path, Custody& base) | ||||||
|         return dir_count_result.result(); |         return dir_count_result.result(); | ||||||
| 
 | 
 | ||||||
|     if (dir_count_result.value() != 2) |     if (dir_count_result.value() != 2) | ||||||
|         return KResult(-ENOTEMPTY); |         return ENOTEMPTY; | ||||||
| 
 | 
 | ||||||
|     if (custody.is_readonly()) |     if (custody.is_readonly()) | ||||||
|         return KResult(-EROFS); |         return EROFS; | ||||||
| 
 | 
 | ||||||
|     auto result = inode.remove_child("."); |     auto result = inode.remove_child("."); | ||||||
|     if (result.is_error()) |     if (result.is_error()) | ||||||
|  | @ -882,27 +882,27 @@ KResult VFS::validate_path_against_process_veil(StringView path, int options) | ||||||
| 
 | 
 | ||||||
|     // FIXME: Figure out a nicer way to do this.
 |     // FIXME: Figure out a nicer way to do this.
 | ||||||
|     if (String(path).contains("/..")) |     if (String(path).contains("/..")) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     auto* unveiled_path = find_matching_unveiled_path(path); |     auto* unveiled_path = find_matching_unveiled_path(path); | ||||||
|     if (!unveiled_path) { |     if (!unveiled_path) { | ||||||
|         dbgln("Rejecting path '{}' since it hasn't been unveiled.", path); |         dbgln("Rejecting path '{}' since it hasn't been unveiled.", path); | ||||||
|         dump_backtrace(); |         dump_backtrace(); | ||||||
|         return KResult(-ENOENT); |         return ENOENT; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (options & O_CREAT) { |     if (options & O_CREAT) { | ||||||
|         if (!(unveiled_path->permissions() & UnveilAccess::CreateOrRemove)) { |         if (!(unveiled_path->permissions() & UnveilAccess::CreateOrRemove)) { | ||||||
|             dbgln("Rejecting path '{}' since it hasn't been unveiled with 'c' permission.", path); |             dbgln("Rejecting path '{}' since it hasn't been unveiled with 'c' permission.", path); | ||||||
|             dump_backtrace(); |             dump_backtrace(); | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if (options & O_UNLINK_INTERNAL) { |     if (options & O_UNLINK_INTERNAL) { | ||||||
|         if (!(unveiled_path->permissions() & UnveilAccess::CreateOrRemove)) { |         if (!(unveiled_path->permissions() & UnveilAccess::CreateOrRemove)) { | ||||||
|             dbgln("Rejecting path '{}' for unlink since it hasn't been unveiled with 'c' permission.", path); |             dbgln("Rejecting path '{}' for unlink since it hasn't been unveiled with 'c' permission.", path); | ||||||
|             dump_backtrace(); |             dump_backtrace(); | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|         } |         } | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     } |     } | ||||||
|  | @ -911,13 +911,13 @@ KResult VFS::validate_path_against_process_veil(StringView path, int options) | ||||||
|             if (!(unveiled_path->permissions() & (UnveilAccess::Read | UnveilAccess::Browse))) { |             if (!(unveiled_path->permissions() & (UnveilAccess::Read | UnveilAccess::Browse))) { | ||||||
|                 dbgln("Rejecting path '{}' since it hasn't been unveiled with 'r' or 'b' permissions.", path); |                 dbgln("Rejecting path '{}' since it hasn't been unveiled with 'r' or 'b' permissions.", path); | ||||||
|                 dump_backtrace(); |                 dump_backtrace(); | ||||||
|                 return KResult(-EACCES); |                 return EACCES; | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             if (!(unveiled_path->permissions() & UnveilAccess::Read)) { |             if (!(unveiled_path->permissions() & UnveilAccess::Read)) { | ||||||
|                 dbgln("Rejecting path '{}' since it hasn't been unveiled with 'r' permission.", path); |                 dbgln("Rejecting path '{}' since it hasn't been unveiled with 'r' permission.", path); | ||||||
|                 dump_backtrace(); |                 dump_backtrace(); | ||||||
|                 return KResult(-EACCES); |                 return EACCES; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -925,14 +925,14 @@ KResult VFS::validate_path_against_process_veil(StringView path, int options) | ||||||
|         if (!(unveiled_path->permissions() & UnveilAccess::Write)) { |         if (!(unveiled_path->permissions() & UnveilAccess::Write)) { | ||||||
|             dbgln("Rejecting path '{}' since it hasn't been unveiled with 'w' permission.", path); |             dbgln("Rejecting path '{}' since it hasn't been unveiled with 'w' permission.", path); | ||||||
|             dump_backtrace(); |             dump_backtrace(); | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if (options & O_EXEC) { |     if (options & O_EXEC) { | ||||||
|         if (!(unveiled_path->permissions() & UnveilAccess::Execute)) { |         if (!(unveiled_path->permissions() & UnveilAccess::Execute)) { | ||||||
|             dbgln("Rejecting path '{}' since it hasn't been unveiled with 'x' permission.", path); |             dbgln("Rejecting path '{}' since it hasn't been unveiled with 'x' permission.", path); | ||||||
|             dump_backtrace(); |             dump_backtrace(); | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
|  | @ -970,10 +970,10 @@ static bool safe_to_follow_symlink(const Inode& inode, const InodeMetadata& pare | ||||||
| KResultOr<NonnullRefPtr<Custody>> VFS::resolve_path_without_veil(StringView path, Custody& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level) | KResultOr<NonnullRefPtr<Custody>> VFS::resolve_path_without_veil(StringView path, Custody& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level) | ||||||
| { | { | ||||||
|     if (symlink_recursion_level >= symlink_recursion_limit) |     if (symlink_recursion_level >= symlink_recursion_limit) | ||||||
|         return KResult(-ELOOP); |         return ELOOP; | ||||||
| 
 | 
 | ||||||
|     if (path.is_empty()) |     if (path.is_empty()) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     auto parts = path.split_view('/', true); |     auto parts = path.split_view('/', true); | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|  | @ -985,10 +985,10 @@ KResultOr<NonnullRefPtr<Custody>> VFS::resolve_path_without_veil(StringView path | ||||||
|         Custody& parent = custody; |         Custody& parent = custody; | ||||||
|         auto parent_metadata = parent.inode().metadata(); |         auto parent_metadata = parent.inode().metadata(); | ||||||
|         if (!parent_metadata.is_directory()) |         if (!parent_metadata.is_directory()) | ||||||
|             return KResult(-ENOTDIR); |             return ENOTDIR; | ||||||
|         // Ensure the current user is allowed to resolve paths inside this directory.
 |         // Ensure the current user is allowed to resolve paths inside this directory.
 | ||||||
|         if (!parent_metadata.may_execute(*current_process)) |         if (!parent_metadata.may_execute(*current_process)) | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
| 
 | 
 | ||||||
|         auto& part = parts[i]; |         auto& part = parts[i]; | ||||||
|         bool have_more_parts = i + 1 < parts.size(); |         bool have_more_parts = i + 1 < parts.size(); | ||||||
|  | @ -1011,7 +1011,7 @@ KResultOr<NonnullRefPtr<Custody>> VFS::resolve_path_without_veil(StringView path | ||||||
|                 // does not exist yet.
 |                 // does not exist yet.
 | ||||||
|                 *out_parent = have_more_parts ? nullptr : &parent; |                 *out_parent = have_more_parts ? nullptr : &parent; | ||||||
|             } |             } | ||||||
|             return KResult(-ENOENT); |             return ENOENT; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         int mount_flags_for_child = parent.mount_flags(); |         int mount_flags_for_child = parent.mount_flags(); | ||||||
|  | @ -1028,13 +1028,13 @@ KResultOr<NonnullRefPtr<Custody>> VFS::resolve_path_without_veil(StringView path | ||||||
|         if (child_inode->metadata().is_symlink()) { |         if (child_inode->metadata().is_symlink()) { | ||||||
|             if (!have_more_parts) { |             if (!have_more_parts) { | ||||||
|                 if (options & O_NOFOLLOW) |                 if (options & O_NOFOLLOW) | ||||||
|                     return KResult(-ELOOP); |                     return ELOOP; | ||||||
|                 if (options & O_NOFOLLOW_NOERROR) |                 if (options & O_NOFOLLOW_NOERROR) | ||||||
|                     break; |                     break; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (!safe_to_follow_symlink(*child_inode, parent_metadata)) |             if (!safe_to_follow_symlink(*child_inode, parent_metadata)) | ||||||
|                 return KResult(-EACCES); |                 return EACCES; | ||||||
| 
 | 
 | ||||||
|             auto symlink_target = child_inode->resolve_as_link(parent, out_parent, options, symlink_recursion_level + 1); |             auto symlink_target = child_inode->resolve_as_link(parent, out_parent, options, symlink_recursion_level + 1); | ||||||
|             if (symlink_target.is_error() || !have_more_parts) |             if (symlink_target.is_error() || !have_more_parts) | ||||||
|  |  | ||||||
|  | @ -27,6 +27,8 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <AK/Assertions.h> | #include <AK/Assertions.h> | ||||||
|  | #include <AK/Platform.h> | ||||||
|  | #include <AK/StdLibExtras.h> | ||||||
| #include <LibC/errno_numbers.h> | #include <LibC/errno_numbers.h> | ||||||
| 
 | 
 | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
|  | @ -37,10 +39,9 @@ enum KSuccessTag { | ||||||
| 
 | 
 | ||||||
| class [[nodiscard]] KResult { | class [[nodiscard]] KResult { | ||||||
| public: | public: | ||||||
|     ALWAYS_INLINE explicit KResult(int negative_e) |     KResult(ErrnoCode error) | ||||||
|         : m_error(negative_e) |         : m_error(-error) | ||||||
|     { |     { | ||||||
|         ASSERT(negative_e <= 0); |  | ||||||
|     } |     } | ||||||
|     KResult(KSuccessTag) |     KResult(KSuccessTag) | ||||||
|         : m_error(0) |         : m_error(0) | ||||||
|  | @ -69,6 +70,12 @@ public: | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     KResultOr(ErrnoCode error) | ||||||
|  |         : m_error(error) | ||||||
|  |         , m_is_error(true) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     ALWAYS_INLINE KResultOr(T&& value) |     ALWAYS_INLINE KResultOr(T&& value) | ||||||
|     { |     { | ||||||
|         new (&m_storage) T(move(value)); |         new (&m_storage) T(move(value)); | ||||||
|  |  | ||||||
|  | @ -61,7 +61,7 @@ KResultOr<NonnullRefPtr<Socket>> IPv4Socket::create(int type, int protocol) | ||||||
|         return UDPSocket::create(protocol); |         return UDPSocket::create(protocol); | ||||||
|     if (type == SOCK_RAW) |     if (type == SOCK_RAW) | ||||||
|         return adopt(*new IPv4Socket(type, protocol)); |         return adopt(*new IPv4Socket(type, protocol)); | ||||||
|     return KResult(-EINVAL); |     return EINVAL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| IPv4Socket::IPv4Socket(int type, int protocol) | IPv4Socket::IPv4Socket(int type, int protocol) | ||||||
|  | @ -102,20 +102,20 @@ KResult IPv4Socket::bind(Userspace<const sockaddr*> user_address, socklen_t addr | ||||||
| { | { | ||||||
|     ASSERT(setup_state() == SetupState::Unstarted); |     ASSERT(setup_state() == SetupState::Unstarted); | ||||||
|     if (address_size != sizeof(sockaddr_in)) |     if (address_size != sizeof(sockaddr_in)) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     sockaddr_in address; |     sockaddr_in address; | ||||||
|     if (!copy_from_user(&address, user_address, sizeof(sockaddr_in))) |     if (!copy_from_user(&address, user_address, sizeof(sockaddr_in))) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
| 
 | 
 | ||||||
|     if (address.sin_family != AF_INET) |     if (address.sin_family != AF_INET) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     auto requested_local_port = ntohs(address.sin_port); |     auto requested_local_port = ntohs(address.sin_port); | ||||||
|     if (!Process::current()->is_superuser()) { |     if (!Process::current()->is_superuser()) { | ||||||
|         if (requested_local_port < 1024) { |         if (requested_local_port < 1024) { | ||||||
|             dbgln("UID {} attempted to bind {} to port {}", Process::current()->uid(), class_name(), requested_local_port); |             dbgln("UID {} attempted to bind {} to port {}", Process::current()->uid(), class_name(), requested_local_port); | ||||||
|             return KResult(-EACCES); |             return EACCES; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -134,7 +134,7 @@ KResult IPv4Socket::listen(size_t backlog) | ||||||
|     LOCKER(lock()); |     LOCKER(lock()); | ||||||
|     int rc = allocate_local_port_if_needed(); |     int rc = allocate_local_port_if_needed(); | ||||||
|     if (rc < 0) |     if (rc < 0) | ||||||
|         return KResult(-EADDRINUSE); |         return EADDRINUSE; | ||||||
| 
 | 
 | ||||||
|     set_backlog(backlog); |     set_backlog(backlog); | ||||||
|     m_role = Role::Listener; |     m_role = Role::Listener; | ||||||
|  | @ -150,19 +150,19 @@ KResult IPv4Socket::listen(size_t backlog) | ||||||
| KResult IPv4Socket::connect(FileDescription& description, Userspace<const sockaddr*> address, socklen_t address_size, ShouldBlock should_block) | KResult IPv4Socket::connect(FileDescription& description, Userspace<const sockaddr*> address, socklen_t address_size, ShouldBlock should_block) | ||||||
| { | { | ||||||
|     if (address_size != sizeof(sockaddr_in)) |     if (address_size != sizeof(sockaddr_in)) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     u16 sa_family_copy; |     u16 sa_family_copy; | ||||||
|     auto* user_address = reinterpret_cast<const sockaddr*>(address.unsafe_userspace_ptr()); |     auto* user_address = reinterpret_cast<const sockaddr*>(address.unsafe_userspace_ptr()); | ||||||
|     if (!copy_from_user(&sa_family_copy, &user_address->sa_family, sizeof(u16))) |     if (!copy_from_user(&sa_family_copy, &user_address->sa_family, sizeof(u16))) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     if (sa_family_copy != AF_INET) |     if (sa_family_copy != AF_INET) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     if (m_role == Role::Connected) |     if (m_role == Role::Connected) | ||||||
|         return KResult(-EISCONN); |         return EISCONN; | ||||||
| 
 | 
 | ||||||
|     sockaddr_in safe_address; |     sockaddr_in safe_address; | ||||||
|     if (!copy_from_user(&safe_address, (const sockaddr_in*)user_address, sizeof(sockaddr_in))) |     if (!copy_from_user(&safe_address, (const sockaddr_in*)user_address, sizeof(sockaddr_in))) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
| 
 | 
 | ||||||
|     m_peer_address = IPv4Address((const u8*)&safe_address.sin_addr.s_addr); |     m_peer_address = IPv4Address((const u8*)&safe_address.sin_addr.s_addr); | ||||||
|     m_peer_port = ntohs(safe_address.sin_port); |     m_peer_port = ntohs(safe_address.sin_port); | ||||||
|  | @ -200,16 +200,16 @@ KResultOr<size_t> IPv4Socket::sendto(FileDescription&, const UserOrKernelBuffer& | ||||||
|     LOCKER(lock()); |     LOCKER(lock()); | ||||||
| 
 | 
 | ||||||
|     if (addr && addr_length != sizeof(sockaddr_in)) |     if (addr && addr_length != sizeof(sockaddr_in)) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     if (addr) { |     if (addr) { | ||||||
|         sockaddr_in ia; |         sockaddr_in ia; | ||||||
|         if (!copy_from_user(&ia, Userspace<const sockaddr_in*>(addr.ptr()))) |         if (!copy_from_user(&ia, Userspace<const sockaddr_in*>(addr.ptr()))) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
| 
 | 
 | ||||||
|         if (ia.sin_family != AF_INET) { |         if (ia.sin_family != AF_INET) { | ||||||
|             klog() << "sendto: Bad address family: " << ia.sin_family << " is not AF_INET!"; |             klog() << "sendto: Bad address family: " << ia.sin_family << " is not AF_INET!"; | ||||||
|             return KResult(-EAFNOSUPPORT); |             return EAFNOSUPPORT; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         m_peer_address = IPv4Address((const u8*)&ia.sin_addr.s_addr); |         m_peer_address = IPv4Address((const u8*)&ia.sin_addr.s_addr); | ||||||
|  | @ -218,7 +218,7 @@ KResultOr<size_t> IPv4Socket::sendto(FileDescription&, const UserOrKernelBuffer& | ||||||
| 
 | 
 | ||||||
|     auto routing_decision = route_to(m_peer_address, m_local_address, bound_interface()); |     auto routing_decision = route_to(m_peer_address, m_local_address, bound_interface()); | ||||||
|     if (routing_decision.is_zero()) |     if (routing_decision.is_zero()) | ||||||
|         return KResult(-EHOSTUNREACH); |         return EHOSTUNREACH; | ||||||
| 
 | 
 | ||||||
|     if (m_local_address.to_u32() == 0) |     if (m_local_address.to_u32() == 0) | ||||||
|         m_local_address = routing_decision.adapter->ipv4_address(); |         m_local_address = routing_decision.adapter->ipv4_address(); | ||||||
|  | @ -234,7 +234,7 @@ KResultOr<size_t> IPv4Socket::sendto(FileDescription&, const UserOrKernelBuffer& | ||||||
|     if (type() == SOCK_RAW) { |     if (type() == SOCK_RAW) { | ||||||
|         int err = routing_decision.adapter->send_ipv4(routing_decision.next_hop, m_peer_address, (IPv4Protocol)protocol(), data, data_length, m_ttl); |         int err = routing_decision.adapter->send_ipv4(routing_decision.next_hop, m_peer_address, (IPv4Protocol)protocol(), data, data_length, m_ttl); | ||||||
|         if (err < 0) |         if (err < 0) | ||||||
|             return KResult(err); |             return KResult((ErrnoCode)-err); | ||||||
|         return data_length; |         return data_length; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -251,7 +251,7 @@ KResultOr<size_t> IPv4Socket::receive_byte_buffered(FileDescription& description | ||||||
|         if (protocol_is_disconnected()) |         if (protocol_is_disconnected()) | ||||||
|             return 0; |             return 0; | ||||||
|         if (!description.is_blocking()) |         if (!description.is_blocking()) | ||||||
|             return KResult(-EAGAIN); |             return EAGAIN; | ||||||
| 
 | 
 | ||||||
|         locker.unlock(); |         locker.unlock(); | ||||||
|         auto unblocked_flags = Thread::FileDescriptionBlocker::BlockFlags::None; |         auto unblocked_flags = Thread::FileDescriptionBlocker::BlockFlags::None; | ||||||
|  | @ -260,10 +260,10 @@ KResultOr<size_t> IPv4Socket::receive_byte_buffered(FileDescription& description | ||||||
| 
 | 
 | ||||||
|         if (!((u32)unblocked_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Read)) { |         if (!((u32)unblocked_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Read)) { | ||||||
|             if (res.was_interrupted()) |             if (res.was_interrupted()) | ||||||
|                 return KResult(-EINTR); |                 return EINTR; | ||||||
| 
 | 
 | ||||||
|             // Unblocked due to timeout.
 |             // Unblocked due to timeout.
 | ||||||
|             return KResult(-EAGAIN); |             return EAGAIN; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -287,7 +287,7 @@ KResultOr<size_t> IPv4Socket::receive_packet_buffered(FileDescription& descripti | ||||||
|             if (protocol_is_disconnected()) |             if (protocol_is_disconnected()) | ||||||
|                 return 0; |                 return 0; | ||||||
|             if (!description.is_blocking()) |             if (!description.is_blocking()) | ||||||
|                 return KResult(-EAGAIN); |                 return EAGAIN; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!m_receive_queue.is_empty()) { |         if (!m_receive_queue.is_empty()) { | ||||||
|  | @ -311,10 +311,10 @@ KResultOr<size_t> IPv4Socket::receive_packet_buffered(FileDescription& descripti | ||||||
| 
 | 
 | ||||||
|         if (!((u32)unblocked_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Read)) { |         if (!((u32)unblocked_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Read)) { | ||||||
|             if (res.was_interrupted()) |             if (res.was_interrupted()) | ||||||
|                 return KResult(-EINTR); |                 return EINTR; | ||||||
| 
 | 
 | ||||||
|             // Unblocked due to timeout.
 |             // Unblocked due to timeout.
 | ||||||
|             return KResult(-EAGAIN); |             return EAGAIN; | ||||||
|         } |         } | ||||||
|         ASSERT(m_can_read); |         ASSERT(m_can_read); | ||||||
|         ASSERT(!m_receive_queue.is_empty()); |         ASSERT(!m_receive_queue.is_empty()); | ||||||
|  | @ -339,18 +339,18 @@ KResultOr<size_t> IPv4Socket::receive_packet_buffered(FileDescription& descripti | ||||||
|         out_addr.sin_family = AF_INET; |         out_addr.sin_family = AF_INET; | ||||||
|         Userspace<sockaddr_in*> dest_addr = addr.ptr(); |         Userspace<sockaddr_in*> dest_addr = addr.ptr(); | ||||||
|         if (!copy_to_user(dest_addr, &out_addr)) |         if (!copy_to_user(dest_addr, &out_addr)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
| 
 | 
 | ||||||
|         socklen_t out_length = sizeof(sockaddr_in); |         socklen_t out_length = sizeof(sockaddr_in); | ||||||
|         ASSERT(addr_length); |         ASSERT(addr_length); | ||||||
|         if (!copy_to_user(addr_length, &out_length)) |         if (!copy_to_user(addr_length, &out_length)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (type() == SOCK_RAW) { |     if (type() == SOCK_RAW) { | ||||||
|         size_t bytes_written = min(packet.data.value().size(), buffer_length); |         size_t bytes_written = min(packet.data.value().size(), buffer_length); | ||||||
|         if (!buffer.write(packet.data.value().data(), bytes_written)) |         if (!buffer.write(packet.data.value().data(), bytes_written)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         return bytes_written; |         return bytes_written; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -362,9 +362,9 @@ KResultOr<size_t> IPv4Socket::recvfrom(FileDescription& description, UserOrKerne | ||||||
|     if (user_addr_length) { |     if (user_addr_length) { | ||||||
|         socklen_t addr_length; |         socklen_t addr_length; | ||||||
|         if (!copy_from_user(&addr_length, user_addr_length.unsafe_userspace_ptr())) |         if (!copy_from_user(&addr_length, user_addr_length.unsafe_userspace_ptr())) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         if (addr_length < sizeof(sockaddr_in)) |         if (addr_length < sizeof(sockaddr_in)) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| #ifdef IPV4_SOCKET_DEBUG | #ifdef IPV4_SOCKET_DEBUG | ||||||
|  | @ -464,17 +464,17 @@ KResult IPv4Socket::setsockopt(int level, int option, Userspace<const void*> use | ||||||
|     switch (option) { |     switch (option) { | ||||||
|     case IP_TTL: { |     case IP_TTL: { | ||||||
|         if (user_value_size < sizeof(int)) |         if (user_value_size < sizeof(int)) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         int value; |         int value; | ||||||
|         if (!copy_from_user(&value, static_ptr_cast<const int*>(user_value))) |         if (!copy_from_user(&value, static_ptr_cast<const int*>(user_value))) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         if (value < 0 || value > 255) |         if (value < 0 || value > 255) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         m_ttl = value; |         m_ttl = value; | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     } |     } | ||||||
|     default: |     default: | ||||||
|         return KResult(-ENOPROTOOPT); |         return ENOPROTOOPT; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -485,20 +485,20 @@ KResult IPv4Socket::getsockopt(FileDescription& description, int level, int opti | ||||||
| 
 | 
 | ||||||
|     socklen_t size; |     socklen_t size; | ||||||
|     if (!copy_from_user(&size, value_size.unsafe_userspace_ptr())) |     if (!copy_from_user(&size, value_size.unsafe_userspace_ptr())) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
| 
 | 
 | ||||||
|     switch (option) { |     switch (option) { | ||||||
|     case IP_TTL: |     case IP_TTL: | ||||||
|         if (size < sizeof(int)) |         if (size < sizeof(int)) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         if (!copy_to_user(static_ptr_cast<int*>(value), (int*)&m_ttl)) |         if (!copy_to_user(static_ptr_cast<int*>(value), (int*)&m_ttl)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         size = sizeof(int); |         size = sizeof(int); | ||||||
|         if (!copy_to_user(value_size, &size)) |         if (!copy_to_user(value_size, &size)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     default: |     default: | ||||||
|         return KResult(-ENOPROTOOPT); |         return ENOPROTOOPT; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -102,14 +102,14 @@ KResult LocalSocket::bind(Userspace<const sockaddr*> user_address, socklen_t add | ||||||
| { | { | ||||||
|     ASSERT(setup_state() == SetupState::Unstarted); |     ASSERT(setup_state() == SetupState::Unstarted); | ||||||
|     if (address_size != sizeof(sockaddr_un)) |     if (address_size != sizeof(sockaddr_un)) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     sockaddr_un address; |     sockaddr_un address; | ||||||
|     if (!copy_from_user(&address, user_address, sizeof(sockaddr_un))) |     if (!copy_from_user(&address, user_address, sizeof(sockaddr_un))) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
| 
 | 
 | ||||||
|     if (address.sun_family != AF_LOCAL) |     if (address.sun_family != AF_LOCAL) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     auto path = String(address.sun_path, strnlen(address.sun_path, sizeof(address.sun_path))); |     auto path = String(address.sun_path, strnlen(address.sun_path, sizeof(address.sun_path))); | ||||||
| 
 | 
 | ||||||
|  | @ -122,7 +122,7 @@ KResult LocalSocket::bind(Userspace<const sockaddr*> user_address, socklen_t add | ||||||
|     auto result = VFS::the().open(path, O_CREAT | O_EXCL | O_NOFOLLOW_NOERROR, mode, Process::current()->current_directory(), owner); |     auto result = VFS::the().open(path, O_CREAT | O_EXCL | O_NOFOLLOW_NOERROR, mode, Process::current()->current_directory(), owner); | ||||||
|     if (result.is_error()) { |     if (result.is_error()) { | ||||||
|         if (result.error() == -EEXIST) |         if (result.error() == -EEXIST) | ||||||
|             return KResult(-EADDRINUSE); |             return EADDRINUSE; | ||||||
|         return result.error(); |         return result.error(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -130,7 +130,7 @@ KResult LocalSocket::bind(Userspace<const sockaddr*> user_address, socklen_t add | ||||||
| 
 | 
 | ||||||
|     ASSERT(file->inode()); |     ASSERT(file->inode()); | ||||||
|     if (!file->inode()->bind_socket(*this)) |     if (!file->inode()->bind_socket(*this)) | ||||||
|         return KResult(-EADDRINUSE); |         return EADDRINUSE; | ||||||
| 
 | 
 | ||||||
|     m_file = move(file); |     m_file = move(file); | ||||||
| 
 | 
 | ||||||
|  | @ -143,20 +143,20 @@ KResult LocalSocket::connect(FileDescription& description, Userspace<const socka | ||||||
| { | { | ||||||
|     ASSERT(!m_bound); |     ASSERT(!m_bound); | ||||||
|     if (address_size != sizeof(sockaddr_un)) |     if (address_size != sizeof(sockaddr_un)) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     u16 sa_family_copy; |     u16 sa_family_copy; | ||||||
|     auto* user_address = reinterpret_cast<const sockaddr*>(address.unsafe_userspace_ptr()); |     auto* user_address = reinterpret_cast<const sockaddr*>(address.unsafe_userspace_ptr()); | ||||||
|     if (!copy_from_user(&sa_family_copy, &user_address->sa_family, sizeof(u16))) |     if (!copy_from_user(&sa_family_copy, &user_address->sa_family, sizeof(u16))) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     if (sa_family_copy != AF_LOCAL) |     if (sa_family_copy != AF_LOCAL) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     if (is_connected()) |     if (is_connected()) | ||||||
|         return KResult(-EISCONN); |         return EISCONN; | ||||||
| 
 | 
 | ||||||
|     const auto& local_address = *reinterpret_cast<const sockaddr_un*>(user_address); |     const auto& local_address = *reinterpret_cast<const sockaddr_un*>(user_address); | ||||||
|     char safe_address[sizeof(local_address.sun_path) + 1] = { 0 }; |     char safe_address[sizeof(local_address.sun_path) + 1] = { 0 }; | ||||||
|     if (!copy_from_user(&safe_address[0], &local_address.sun_path[0], sizeof(safe_address) - 1)) |     if (!copy_from_user(&safe_address[0], &local_address.sun_path[0], sizeof(safe_address) - 1)) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     safe_address[sizeof(safe_address) - 1] = '\0'; |     safe_address[sizeof(safe_address) - 1] = '\0'; | ||||||
| 
 | 
 | ||||||
| #ifdef DEBUG_LOCAL_SOCKET | #ifdef DEBUG_LOCAL_SOCKET | ||||||
|  | @ -165,13 +165,13 @@ KResult LocalSocket::connect(FileDescription& description, Userspace<const socka | ||||||
| 
 | 
 | ||||||
|     auto description_or_error = VFS::the().open(safe_address, O_RDWR, 0, Process::current()->current_directory()); |     auto description_or_error = VFS::the().open(safe_address, O_RDWR, 0, Process::current()->current_directory()); | ||||||
|     if (description_or_error.is_error()) |     if (description_or_error.is_error()) | ||||||
|         return KResult(-ECONNREFUSED); |         return ECONNREFUSED; | ||||||
| 
 | 
 | ||||||
|     m_file = move(description_or_error.value()); |     m_file = move(description_or_error.value()); | ||||||
| 
 | 
 | ||||||
|     ASSERT(m_file->inode()); |     ASSERT(m_file->inode()); | ||||||
|     if (!m_file->inode()->socket()) |     if (!m_file->inode()->socket()) | ||||||
|         return KResult(-ECONNREFUSED); |         return ECONNREFUSED; | ||||||
| 
 | 
 | ||||||
|     m_address.sun_family = sa_family_copy; |     m_address.sun_family = sa_family_copy; | ||||||
|     memcpy(m_address.sun_path, safe_address, sizeof(m_address.sun_path)); |     memcpy(m_address.sun_path, safe_address, sizeof(m_address.sun_path)); | ||||||
|  | @ -194,7 +194,7 @@ KResult LocalSocket::connect(FileDescription& description, Userspace<const socka | ||||||
|     auto unblock_flags = Thread::FileDescriptionBlocker::BlockFlags::None; |     auto unblock_flags = Thread::FileDescriptionBlocker::BlockFlags::None; | ||||||
|     if (Thread::current()->block<Thread::ConnectBlocker>({}, description, unblock_flags).was_interrupted()) { |     if (Thread::current()->block<Thread::ConnectBlocker>({}, description, unblock_flags).was_interrupted()) { | ||||||
|         set_connect_side_role(Role::None); |         set_connect_side_role(Role::None); | ||||||
|         return KResult(-EINTR); |         return EINTR; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| #ifdef DEBUG_LOCAL_SOCKET | #ifdef DEBUG_LOCAL_SOCKET | ||||||
|  | @ -203,7 +203,7 @@ KResult LocalSocket::connect(FileDescription& description, Userspace<const socka | ||||||
| 
 | 
 | ||||||
|     if (!((u32)unblock_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Connect)) { |     if (!((u32)unblock_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Connect)) { | ||||||
|         set_connect_side_role(Role::None); |         set_connect_side_role(Role::None); | ||||||
|         return KResult(-ECONNREFUSED); |         return ECONNREFUSED; | ||||||
|     } |     } | ||||||
|     set_connect_side_role(Role::Connected); |     set_connect_side_role(Role::Connected); | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
|  | @ -213,7 +213,7 @@ KResult LocalSocket::listen(size_t backlog) | ||||||
| { | { | ||||||
|     LOCKER(lock()); |     LOCKER(lock()); | ||||||
|     if (type() != SOCK_STREAM) |     if (type() != SOCK_STREAM) | ||||||
|         return KResult(-EOPNOTSUPP); |         return EOPNOTSUPP; | ||||||
|     set_backlog(backlog); |     set_backlog(backlog); | ||||||
|     auto previous_role = m_role; |     auto previous_role = m_role; | ||||||
|     m_role = Role::Listener; |     m_role = Role::Listener; | ||||||
|  | @ -286,10 +286,10 @@ bool LocalSocket::can_write(const FileDescription& description, size_t) const | ||||||
| KResultOr<size_t> LocalSocket::sendto(FileDescription& description, const UserOrKernelBuffer& data, size_t data_size, int, Userspace<const sockaddr*>, socklen_t) | KResultOr<size_t> LocalSocket::sendto(FileDescription& description, const UserOrKernelBuffer& data, size_t data_size, int, Userspace<const sockaddr*>, socklen_t) | ||||||
| { | { | ||||||
|     if (!has_attached_peer(description)) |     if (!has_attached_peer(description)) | ||||||
|         return KResult(-EPIPE); |         return EPIPE; | ||||||
|     auto* socket_buffer = send_buffer_for(description); |     auto* socket_buffer = send_buffer_for(description); | ||||||
|     if (!socket_buffer) |     if (!socket_buffer) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     ssize_t nwritten = socket_buffer->write(data, data_size); |     ssize_t nwritten = socket_buffer->write(data, data_size); | ||||||
|     if (nwritten > 0) |     if (nwritten > 0) | ||||||
|         Thread::current()->did_unix_socket_write(nwritten); |         Thread::current()->did_unix_socket_write(nwritten); | ||||||
|  | @ -320,17 +320,17 @@ KResultOr<size_t> LocalSocket::recvfrom(FileDescription& description, UserOrKern | ||||||
| { | { | ||||||
|     auto* socket_buffer = receive_buffer_for(description); |     auto* socket_buffer = receive_buffer_for(description); | ||||||
|     if (!socket_buffer) |     if (!socket_buffer) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     if (!description.is_blocking()) { |     if (!description.is_blocking()) { | ||||||
|         if (socket_buffer->is_empty()) { |         if (socket_buffer->is_empty()) { | ||||||
|             if (!has_attached_peer(description)) |             if (!has_attached_peer(description)) | ||||||
|                 return 0; |                 return 0; | ||||||
|             return KResult(-EAGAIN); |             return EAGAIN; | ||||||
|         } |         } | ||||||
|     } else if (!can_read(description, 0)) { |     } else if (!can_read(description, 0)) { | ||||||
|         auto unblock_flags = Thread::FileDescriptionBlocker::BlockFlags::None; |         auto unblock_flags = Thread::FileDescriptionBlocker::BlockFlags::None; | ||||||
|         if (Thread::current()->block<Thread::ReadBlocker>({}, description, unblock_flags).was_interrupted()) |         if (Thread::current()->block<Thread::ReadBlocker>({}, description, unblock_flags).was_interrupted()) | ||||||
|             return KResult(-EINTR); |             return EINTR; | ||||||
|     } |     } | ||||||
|     if (!has_attached_peer(description) && socket_buffer->is_empty()) |     if (!has_attached_peer(description) && socket_buffer->is_empty()) | ||||||
|         return 0; |         return 0; | ||||||
|  | @ -380,31 +380,31 @@ KResult LocalSocket::getsockopt(FileDescription& description, int level, int opt | ||||||
| 
 | 
 | ||||||
|     socklen_t size; |     socklen_t size; | ||||||
|     if (!copy_from_user(&size, value_size.unsafe_userspace_ptr())) |     if (!copy_from_user(&size, value_size.unsafe_userspace_ptr())) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
| 
 | 
 | ||||||
|     switch (option) { |     switch (option) { | ||||||
|     case SO_PEERCRED: { |     case SO_PEERCRED: { | ||||||
|         if (size < sizeof(ucred)) |         if (size < sizeof(ucred)) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         switch (role(description)) { |         switch (role(description)) { | ||||||
|         case Role::Accepted: |         case Role::Accepted: | ||||||
|             if (!copy_to_user(static_ptr_cast<ucred*>(value), &m_origin)) |             if (!copy_to_user(static_ptr_cast<ucred*>(value), &m_origin)) | ||||||
|                 return KResult(-EFAULT); |                 return EFAULT; | ||||||
|             size = sizeof(ucred); |             size = sizeof(ucred); | ||||||
|             if (!copy_to_user(value_size, &size)) |             if (!copy_to_user(value_size, &size)) | ||||||
|                 return KResult(-EFAULT); |                 return EFAULT; | ||||||
|             return KSuccess; |             return KSuccess; | ||||||
|         case Role::Connected: |         case Role::Connected: | ||||||
|             if (!copy_to_user(static_ptr_cast<ucred*>(value), &m_acceptor)) |             if (!copy_to_user(static_ptr_cast<ucred*>(value), &m_acceptor)) | ||||||
|                 return KResult(-EFAULT); |                 return EFAULT; | ||||||
|             size = sizeof(ucred); |             size = sizeof(ucred); | ||||||
|             if (!copy_to_user(value_size, &size)) |             if (!copy_to_user(value_size, &size)) | ||||||
|                 return KResult(-EFAULT); |                 return EFAULT; | ||||||
|             return KSuccess; |             return KSuccess; | ||||||
|         case Role::Connecting: |         case Role::Connecting: | ||||||
|             return KResult(-ENOTCONN); |             return ENOTCONN; | ||||||
|         default: |         default: | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  | @ -429,7 +429,7 @@ KResult LocalSocket::chown(FileDescription&, uid_t uid, gid_t gid) | ||||||
| 
 | 
 | ||||||
|     auto current_process = Process::current(); |     auto current_process = Process::current(); | ||||||
|     if (!current_process->is_superuser() && (current_process->euid() != uid || !current_process->in_group(gid))) |     if (!current_process->is_superuser() && (current_process->euid() != uid || !current_process->in_group(gid))) | ||||||
|         return KResult(-EPERM); |         return EPERM; | ||||||
| 
 | 
 | ||||||
|     m_prebind_uid = uid; |     m_prebind_uid = uid; | ||||||
|     m_prebind_gid = gid; |     m_prebind_gid = gid; | ||||||
|  | @ -461,11 +461,11 @@ KResult LocalSocket::sendfd(const FileDescription& socket_description, FileDescr | ||||||
|     LOCKER(lock()); |     LOCKER(lock()); | ||||||
|     auto role = this->role(socket_description); |     auto role = this->role(socket_description); | ||||||
|     if (role != Role::Connected && role != Role::Accepted) |     if (role != Role::Connected && role != Role::Accepted) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     auto& queue = sendfd_queue_for(socket_description); |     auto& queue = sendfd_queue_for(socket_description); | ||||||
|     // FIXME: Figure out how we should limit this properly.
 |     // FIXME: Figure out how we should limit this properly.
 | ||||||
|     if (queue.size() > 16) |     if (queue.size() > 16) | ||||||
|         return KResult(-EBUSY); |         return EBUSY; | ||||||
|     queue.append(move(passing_description)); |     queue.append(move(passing_description)); | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
| } | } | ||||||
|  | @ -475,11 +475,11 @@ KResultOr<NonnullRefPtr<FileDescription>> LocalSocket::recvfd(const FileDescript | ||||||
|     LOCKER(lock()); |     LOCKER(lock()); | ||||||
|     auto role = this->role(socket_description); |     auto role = this->role(socket_description); | ||||||
|     if (role != Role::Connected && role != Role::Accepted) |     if (role != Role::Connected && role != Role::Accepted) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     auto& queue = recvfd_queue_for(socket_description); |     auto& queue = recvfd_queue_for(socket_description); | ||||||
|     if (queue.is_empty()) { |     if (queue.is_empty()) { | ||||||
|         // FIXME: Figure out the perfect error code for this.
 |         // FIXME: Figure out the perfect error code for this.
 | ||||||
|         return KResult(-EAGAIN); |         return EAGAIN; | ||||||
|     } |     } | ||||||
|     return queue.take_first(); |     return queue.take_first(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ KResultOr<NonnullRefPtr<Socket>> Socket::create(int domain, int type, int protoc | ||||||
|     case AF_INET: |     case AF_INET: | ||||||
|         return IPv4Socket::create(type & SOCK_TYPE_MASK, protocol); |         return IPv4Socket::create(type & SOCK_TYPE_MASK, protocol); | ||||||
|     default: |     default: | ||||||
|         return KResult(-EAFNOSUPPORT); |         return EAFNOSUPPORT; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -99,7 +99,7 @@ KResult Socket::queue_connection_from(NonnullRefPtr<Socket> peer) | ||||||
| #endif | #endif | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
|     if (m_pending.size() >= m_backlog) |     if (m_pending.size() >= m_backlog) | ||||||
|         return KResult(-ECONNREFUSED); |         return ECONNREFUSED; | ||||||
|     m_pending.append(peer); |     m_pending.append(peer); | ||||||
|     evaluate_block_conditions(); |     evaluate_block_conditions(); | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
|  | @ -111,26 +111,26 @@ KResult Socket::setsockopt(int level, int option, Userspace<const void*> user_va | ||||||
|     switch (option) { |     switch (option) { | ||||||
|     case SO_SNDTIMEO: |     case SO_SNDTIMEO: | ||||||
|         if (user_value_size != sizeof(timeval)) |         if (user_value_size != sizeof(timeval)) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         if (!copy_from_user(&m_send_timeout, static_ptr_cast<const timeval*>(user_value))) |         if (!copy_from_user(&m_send_timeout, static_ptr_cast<const timeval*>(user_value))) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     case SO_RCVTIMEO: |     case SO_RCVTIMEO: | ||||||
|         if (user_value_size != sizeof(timeval)) |         if (user_value_size != sizeof(timeval)) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         if (!copy_from_user(&m_receive_timeout, static_ptr_cast<const timeval*>(user_value))) |         if (!copy_from_user(&m_receive_timeout, static_ptr_cast<const timeval*>(user_value))) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     case SO_BINDTODEVICE: { |     case SO_BINDTODEVICE: { | ||||||
|         if (user_value_size != IFNAMSIZ) |         if (user_value_size != IFNAMSIZ) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         auto user_string = static_ptr_cast<const char*>(user_value); |         auto user_string = static_ptr_cast<const char*>(user_value); | ||||||
|         auto ifname = copy_string_from_user(user_string, user_value_size); |         auto ifname = copy_string_from_user(user_string, user_value_size); | ||||||
|         if (ifname.is_null()) |         if (ifname.is_null()) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         auto device = NetworkAdapter::lookup_by_name(ifname); |         auto device = NetworkAdapter::lookup_by_name(ifname); | ||||||
|         if (!device) |         if (!device) | ||||||
|             return KResult(-ENODEV); |             return ENODEV; | ||||||
|         m_bound_interface = device; |         m_bound_interface = device; | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     } |     } | ||||||
|  | @ -139,18 +139,18 @@ KResult Socket::setsockopt(int level, int option, Userspace<const void*> user_va | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     case SO_TIMESTAMP: |     case SO_TIMESTAMP: | ||||||
|         if (user_value_size != sizeof(int)) |         if (user_value_size != sizeof(int)) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         if (!copy_from_user(&m_timestamp, static_ptr_cast<const int*>(user_value))) |         if (!copy_from_user(&m_timestamp, static_ptr_cast<const int*>(user_value))) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         if (m_timestamp && (domain() != AF_INET || type() == SOCK_STREAM)) { |         if (m_timestamp && (domain() != AF_INET || type() == SOCK_STREAM)) { | ||||||
|             // FIXME: Support SO_TIMESTAMP for more protocols?
 |             // FIXME: Support SO_TIMESTAMP for more protocols?
 | ||||||
|             m_timestamp = 0; |             m_timestamp = 0; | ||||||
|             return KResult(-ENOTSUP); |             return ENOTSUP; | ||||||
|         } |         } | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     default: |     default: | ||||||
|         dbgln("setsockopt({}) at SOL_SOCKET not implemented.", option); |         dbgln("setsockopt({}) at SOL_SOCKET not implemented.", option); | ||||||
|         return KResult(-ENOPROTOOPT); |         return ENOPROTOOPT; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -158,76 +158,76 @@ KResult Socket::getsockopt(FileDescription&, int level, int option, Userspace<vo | ||||||
| { | { | ||||||
|     socklen_t size; |     socklen_t size; | ||||||
|     if (!copy_from_user(&size, value_size.unsafe_userspace_ptr())) |     if (!copy_from_user(&size, value_size.unsafe_userspace_ptr())) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
| 
 | 
 | ||||||
|     // FIXME: Add TCP_NODELAY, IPPROTO_TCP and IPPROTO_IP (used in OpenSSH)
 |     // FIXME: Add TCP_NODELAY, IPPROTO_TCP and IPPROTO_IP (used in OpenSSH)
 | ||||||
|     if (level != SOL_SOCKET) { |     if (level != SOL_SOCKET) { | ||||||
|         // Not sure if this is the correct error code, but it's only temporary until other levels are implemented.
 |         // Not sure if this is the correct error code, but it's only temporary until other levels are implemented.
 | ||||||
|         return KResult(-ENOPROTOOPT); |         return ENOPROTOOPT; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     switch (option) { |     switch (option) { | ||||||
|     case SO_SNDTIMEO: |     case SO_SNDTIMEO: | ||||||
|         if (size < sizeof(timeval)) |         if (size < sizeof(timeval)) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         if (!copy_to_user(static_ptr_cast<timeval*>(value), &m_send_timeout)) |         if (!copy_to_user(static_ptr_cast<timeval*>(value), &m_send_timeout)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         size = sizeof(timeval); |         size = sizeof(timeval); | ||||||
|         if (!copy_to_user(value_size, &size)) |         if (!copy_to_user(value_size, &size)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     case SO_RCVTIMEO: |     case SO_RCVTIMEO: | ||||||
|         if (size < sizeof(timeval)) |         if (size < sizeof(timeval)) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         if (!copy_to_user(static_ptr_cast<timeval*>(value), &m_receive_timeout)) |         if (!copy_to_user(static_ptr_cast<timeval*>(value), &m_receive_timeout)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         size = sizeof(timeval); |         size = sizeof(timeval); | ||||||
|         if (!copy_to_user(value_size, &size)) |         if (!copy_to_user(value_size, &size)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     case SO_ERROR: { |     case SO_ERROR: { | ||||||
|         if (size < sizeof(int)) |         if (size < sizeof(int)) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         dbgln("getsockopt(SO_ERROR): FIXME!"); |         dbgln("getsockopt(SO_ERROR): FIXME!"); | ||||||
|         int errno = 0; |         int errno = 0; | ||||||
|         if (!copy_to_user(static_ptr_cast<int*>(value), &errno)) |         if (!copy_to_user(static_ptr_cast<int*>(value), &errno)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         size = sizeof(int); |         size = sizeof(int); | ||||||
|         if (!copy_to_user(value_size, &size)) |         if (!copy_to_user(value_size, &size)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     } |     } | ||||||
|     case SO_BINDTODEVICE: |     case SO_BINDTODEVICE: | ||||||
|         if (size < IFNAMSIZ) |         if (size < IFNAMSIZ) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         if (m_bound_interface) { |         if (m_bound_interface) { | ||||||
|             const auto& name = m_bound_interface->name(); |             const auto& name = m_bound_interface->name(); | ||||||
|             auto length = name.length() + 1; |             auto length = name.length() + 1; | ||||||
|             if (!copy_to_user(static_ptr_cast<char*>(value), name.characters(), length)) |             if (!copy_to_user(static_ptr_cast<char*>(value), name.characters(), length)) | ||||||
|                 return KResult(-EFAULT); |                 return EFAULT; | ||||||
|             size = length; |             size = length; | ||||||
|             if (!copy_to_user(value_size, &size)) |             if (!copy_to_user(value_size, &size)) | ||||||
|                 return KResult(-EFAULT); |                 return EFAULT; | ||||||
|             return KSuccess; |             return KSuccess; | ||||||
|         } else { |         } else { | ||||||
|             size = 0; |             size = 0; | ||||||
|             if (!copy_to_user(value_size, &size)) |             if (!copy_to_user(value_size, &size)) | ||||||
|                 return KResult(-EFAULT); |                 return EFAULT; | ||||||
| 
 | 
 | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         } |         } | ||||||
|     case SO_TIMESTAMP: |     case SO_TIMESTAMP: | ||||||
|         if (size < sizeof(int)) |         if (size < sizeof(int)) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         if (!copy_to_user(static_ptr_cast<int*>(value), &m_timestamp)) |         if (!copy_to_user(static_ptr_cast<int*>(value), &m_timestamp)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         size = sizeof(int); |         size = sizeof(int); | ||||||
|         if (!copy_to_user(value_size, &size)) |         if (!copy_to_user(value_size, &size)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     default: |     default: | ||||||
|         dbgln("setsockopt({}) at SOL_SOCKET not implemented.", option); |         dbgln("setsockopt({}) at SOL_SOCKET not implemented.", option); | ||||||
|         return KResult(-ENOPROTOOPT); |         return ENOPROTOOPT; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -250,9 +250,9 @@ KResult Socket::shutdown(int how) | ||||||
| { | { | ||||||
|     LOCKER(lock()); |     LOCKER(lock()); | ||||||
|     if (type() == SOCK_STREAM && !is_connected()) |     if (type() == SOCK_STREAM && !is_connected()) | ||||||
|         return KResult(-ENOTCONN); |         return ENOTCONN; | ||||||
|     if (m_role == Role::Listener) |     if (m_role == Role::Listener) | ||||||
|         return KResult(-ENOTCONN); |         return ENOTCONN; | ||||||
|     if (!m_shut_down_for_writing && (how & SHUT_WR)) |     if (!m_shut_down_for_writing && (how & SHUT_WR)) | ||||||
|         shut_down_for_writing(); |         shut_down_for_writing(); | ||||||
|     if (!m_shut_down_for_reading && (how & SHUT_RD)) |     if (!m_shut_down_for_reading && (how & SHUT_RD)) | ||||||
|  |  | ||||||
|  | @ -177,7 +177,7 @@ KResultOr<size_t> TCPSocket::protocol_receive(ReadonlyBytes raw_ipv4_packet, Use | ||||||
| #endif | #endif | ||||||
|     ASSERT(buffer_size >= payload_size); |     ASSERT(buffer_size >= payload_size); | ||||||
|     if (!buffer.write(tcp_packet.payload(), payload_size)) |     if (!buffer.write(tcp_packet.payload(), payload_size)) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     return payload_size; |     return payload_size; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -185,7 +185,7 @@ KResultOr<size_t> TCPSocket::protocol_send(const UserOrKernelBuffer& data, size_ | ||||||
| { | { | ||||||
|     int err = send_tcp_packet(TCPFlags::PUSH | TCPFlags::ACK, &data, data_length); |     int err = send_tcp_packet(TCPFlags::PUSH | TCPFlags::ACK, &data, data_length); | ||||||
|     if (err < 0) |     if (err < 0) | ||||||
|         return KResult(err); |         return KResult((ErrnoCode)-err); | ||||||
|     return data_length; |     return data_length; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -354,7 +354,7 @@ KResult TCPSocket::protocol_bind() | ||||||
|     if (has_specific_local_address() && !m_adapter) { |     if (has_specific_local_address() && !m_adapter) { | ||||||
|         m_adapter = NetworkAdapter::from_ipv4_address(local_address()); |         m_adapter = NetworkAdapter::from_ipv4_address(local_address()); | ||||||
|         if (!m_adapter) |         if (!m_adapter) | ||||||
|             return KResult(-EADDRNOTAVAIL); |             return EADDRNOTAVAIL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
|  | @ -364,7 +364,7 @@ KResult TCPSocket::protocol_listen() | ||||||
| { | { | ||||||
|     LOCKER(sockets_by_tuple().lock()); |     LOCKER(sockets_by_tuple().lock()); | ||||||
|     if (sockets_by_tuple().resource().contains(tuple())) |     if (sockets_by_tuple().resource().contains(tuple())) | ||||||
|         return KResult(-EADDRINUSE); |         return EADDRINUSE; | ||||||
|     sockets_by_tuple().resource().set(tuple(), this); |     sockets_by_tuple().resource().set(tuple(), this); | ||||||
|     set_direction(Direction::Passive); |     set_direction(Direction::Passive); | ||||||
|     set_state(State::Listen); |     set_state(State::Listen); | ||||||
|  | @ -378,7 +378,7 @@ KResult TCPSocket::protocol_connect(FileDescription& description, ShouldBlock sh | ||||||
| 
 | 
 | ||||||
|     auto routing_decision = route_to(peer_address(), local_address()); |     auto routing_decision = route_to(peer_address(), local_address()); | ||||||
|     if (routing_decision.is_zero()) |     if (routing_decision.is_zero()) | ||||||
|         return KResult(-EHOSTUNREACH); |         return EHOSTUNREACH; | ||||||
|     if (!has_specific_local_address()) |     if (!has_specific_local_address()) | ||||||
|         set_local_address(routing_decision.adapter->ipv4_address()); |         set_local_address(routing_decision.adapter->ipv4_address()); | ||||||
| 
 | 
 | ||||||
|  | @ -390,7 +390,7 @@ KResult TCPSocket::protocol_connect(FileDescription& description, ShouldBlock sh | ||||||
|     set_setup_state(SetupState::InProgress); |     set_setup_state(SetupState::InProgress); | ||||||
|     int err = send_tcp_packet(TCPFlags::SYN); |     int err = send_tcp_packet(TCPFlags::SYN); | ||||||
|     if (err < 0) |     if (err < 0) | ||||||
|         return KResult(err); |         return KResult((ErrnoCode)-err); | ||||||
|     m_state = State::SynSent; |     m_state = State::SynSent; | ||||||
|     m_role = Role::Connecting; |     m_role = Role::Connecting; | ||||||
|     m_direction = Direction::Outgoing; |     m_direction = Direction::Outgoing; | ||||||
|  | @ -401,17 +401,17 @@ KResult TCPSocket::protocol_connect(FileDescription& description, ShouldBlock sh | ||||||
|         locker.unlock(); |         locker.unlock(); | ||||||
|         auto unblock_flags = Thread::FileBlocker::BlockFlags::None; |         auto unblock_flags = Thread::FileBlocker::BlockFlags::None; | ||||||
|         if (Thread::current()->block<Thread::ConnectBlocker>({}, description, unblock_flags).was_interrupted()) |         if (Thread::current()->block<Thread::ConnectBlocker>({}, description, unblock_flags).was_interrupted()) | ||||||
|             return KResult(-EINTR); |             return EINTR; | ||||||
|         locker.lock(); |         locker.lock(); | ||||||
|         ASSERT(setup_state() == SetupState::Completed); |         ASSERT(setup_state() == SetupState::Completed); | ||||||
|         if (has_error()) { // TODO: check unblock_flags
 |         if (has_error()) { // TODO: check unblock_flags
 | ||||||
|             m_role = Role::None; |             m_role = Role::None; | ||||||
|             return KResult(-ECONNREFUSED); |             return ECONNREFUSED; | ||||||
|         } |         } | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return KResult(-EINPROGRESS); |     return EINPROGRESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int TCPSocket::protocol_allocate_local_port() | int TCPSocket::protocol_allocate_local_port() | ||||||
|  |  | ||||||
|  | @ -86,7 +86,7 @@ KResultOr<size_t> UDPSocket::protocol_receive(ReadonlyBytes raw_ipv4_packet, Use | ||||||
|     ASSERT(udp_packet.length() >= sizeof(UDPPacket)); // FIXME: This should be rejected earlier.
 |     ASSERT(udp_packet.length() >= sizeof(UDPPacket)); // FIXME: This should be rejected earlier.
 | ||||||
|     ASSERT(buffer_size >= (udp_packet.length() - sizeof(UDPPacket))); |     ASSERT(buffer_size >= (udp_packet.length() - sizeof(UDPPacket))); | ||||||
|     if (!buffer.write(udp_packet.payload(), udp_packet.length() - sizeof(UDPPacket))) |     if (!buffer.write(udp_packet.payload(), udp_packet.length() - sizeof(UDPPacket))) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     return udp_packet.length() - sizeof(UDPPacket); |     return udp_packet.length() - sizeof(UDPPacket); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -94,7 +94,7 @@ KResultOr<size_t> UDPSocket::protocol_send(const UserOrKernelBuffer& data, size_ | ||||||
| { | { | ||||||
|     auto routing_decision = route_to(peer_address(), local_address(), bound_interface()); |     auto routing_decision = route_to(peer_address(), local_address(), bound_interface()); | ||||||
|     if (routing_decision.is_zero()) |     if (routing_decision.is_zero()) | ||||||
|         return KResult(-EHOSTUNREACH); |         return EHOSTUNREACH; | ||||||
|     const size_t buffer_size = sizeof(UDPPacket) + data_length; |     const size_t buffer_size = sizeof(UDPPacket) + data_length; | ||||||
| 
 | 
 | ||||||
|     alignas(UDPPacket) u8 buffer[buffer_size]; |     alignas(UDPPacket) u8 buffer[buffer_size]; | ||||||
|  | @ -105,7 +105,7 @@ KResultOr<size_t> UDPSocket::protocol_send(const UserOrKernelBuffer& data, size_ | ||||||
|     udp_packet.set_destination_port(peer_port()); |     udp_packet.set_destination_port(peer_port()); | ||||||
|     udp_packet.set_length(buffer_size); |     udp_packet.set_length(buffer_size); | ||||||
|     if (!data.read(udp_packet.payload(), data_length)) |     if (!data.read(udp_packet.payload(), data_length)) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
| 
 | 
 | ||||||
|     routing_decision.adapter->send_ipv4(routing_decision.next_hop, peer_address(), IPv4Protocol::UDP, UserOrKernelBuffer::for_kernel_buffer(buffer), buffer_size, ttl()); |     routing_decision.adapter->send_ipv4(routing_decision.next_hop, peer_address(), IPv4Protocol::UDP, UserOrKernelBuffer::for_kernel_buffer(buffer), buffer_size, ttl()); | ||||||
|     return data_length; |     return data_length; | ||||||
|  | @ -146,7 +146,7 @@ KResult UDPSocket::protocol_bind() | ||||||
| { | { | ||||||
|     LOCKER(sockets_by_port().lock()); |     LOCKER(sockets_by_port().lock()); | ||||||
|     if (sockets_by_port().resource().contains(local_port())) |     if (sockets_by_port().resource().contains(local_port())) | ||||||
|         return KResult(-EADDRINUSE); |         return EADDRINUSE; | ||||||
|     sockets_by_port().resource().set(local_port(), this); |     sockets_by_port().resource().set(local_port(), this); | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -51,7 +51,7 @@ KResult PerformanceEventBuffer::append(int type, FlatPtr arg1, FlatPtr arg2) | ||||||
| KResult PerformanceEventBuffer::append_with_eip_and_ebp(u32 eip, u32 ebp, int type, FlatPtr arg1, FlatPtr arg2) | KResult PerformanceEventBuffer::append_with_eip_and_ebp(u32 eip, u32 ebp, int type, FlatPtr arg1, FlatPtr arg2) | ||||||
| { | { | ||||||
|     if (count() >= capacity()) |     if (count() >= capacity()) | ||||||
|         return KResult(-ENOBUFS); |         return ENOBUFS; | ||||||
| 
 | 
 | ||||||
|     PerformanceEvent event; |     PerformanceEvent event; | ||||||
|     event.type = type; |     event.type = type; | ||||||
|  | @ -67,7 +67,7 @@ KResult PerformanceEventBuffer::append_with_eip_and_ebp(u32 eip, u32 ebp, int ty | ||||||
|         event.data.free.ptr = arg1; |         event.data.free.ptr = arg1; | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto current_thread = Thread::current(); |     auto current_thread = Thread::current(); | ||||||
|  |  | ||||||
|  | @ -148,10 +148,10 @@ KResultOr<Region*> Process::allocate_region(const Range& range, const String& na | ||||||
|     ASSERT(range.is_valid()); |     ASSERT(range.is_valid()); | ||||||
|     auto vmobject = AnonymousVMObject::create_with_size(range.size(), strategy); |     auto vmobject = AnonymousVMObject::create_with_size(range.size(), strategy); | ||||||
|     if (!vmobject) |     if (!vmobject) | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     auto region = Region::create_user_accessible(this, range, vmobject.release_nonnull(), 0, name, prot_to_region_access_flags(prot)); |     auto region = Region::create_user_accessible(this, range, vmobject.release_nonnull(), 0, name, prot_to_region_access_flags(prot)); | ||||||
|     if (!region->map(page_directory())) |     if (!region->map(page_directory())) | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     return &add_region(move(region)); |     return &add_region(move(region)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -159,7 +159,7 @@ KResultOr<Region*> Process::allocate_region(VirtualAddress vaddr, size_t size, c | ||||||
| { | { | ||||||
|     auto range = allocate_range(vaddr, size); |     auto range = allocate_range(vaddr, size); | ||||||
|     if (!range.is_valid()) |     if (!range.is_valid()) | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     return allocate_region(range, name, prot, strategy); |     return allocate_region(range, name, prot, strategy); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -169,21 +169,21 @@ KResultOr<Region*> Process::allocate_region_with_vmobject(const Range& range, No | ||||||
|     size_t end_in_vmobject = offset_in_vmobject + range.size(); |     size_t end_in_vmobject = offset_in_vmobject + range.size(); | ||||||
|     if (end_in_vmobject <= offset_in_vmobject) { |     if (end_in_vmobject <= offset_in_vmobject) { | ||||||
|         dbgln("allocate_region_with_vmobject: Overflow (offset + size)"); |         dbgln("allocate_region_with_vmobject: Overflow (offset + size)"); | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     } |     } | ||||||
|     if (offset_in_vmobject >= vmobject->size()) { |     if (offset_in_vmobject >= vmobject->size()) { | ||||||
|         dbgln("allocate_region_with_vmobject: Attempt to allocate a region with an offset past the end of its VMObject."); |         dbgln("allocate_region_with_vmobject: Attempt to allocate a region with an offset past the end of its VMObject."); | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     } |     } | ||||||
|     if (end_in_vmobject > vmobject->size()) { |     if (end_in_vmobject > vmobject->size()) { | ||||||
|         dbgln("allocate_region_with_vmobject: Attempt to allocate a region with an end past the end of its VMObject."); |         dbgln("allocate_region_with_vmobject: Attempt to allocate a region with an end past the end of its VMObject."); | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     } |     } | ||||||
|     offset_in_vmobject &= PAGE_MASK; |     offset_in_vmobject &= PAGE_MASK; | ||||||
|     auto& region = add_region(Region::create_user_accessible(this, range, move(vmobject), offset_in_vmobject, name, prot_to_region_access_flags(prot), true, shared)); |     auto& region = add_region(Region::create_user_accessible(this, range, move(vmobject), offset_in_vmobject, name, prot_to_region_access_flags(prot), true, shared)); | ||||||
|     if (!region.map(page_directory())) { |     if (!region.map(page_directory())) { | ||||||
|         // FIXME: What is an appropriate error code here, really?
 |         // FIXME: What is an appropriate error code here, really?
 | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     } |     } | ||||||
|     return ®ion; |     return ®ion; | ||||||
| } | } | ||||||
|  | @ -192,7 +192,7 @@ KResultOr<Region*> Process::allocate_region_with_vmobject(VirtualAddress vaddr, | ||||||
| { | { | ||||||
|     auto range = allocate_range(vaddr, size); |     auto range = allocate_range(vaddr, size); | ||||||
|     if (!range.is_valid()) |     if (!range.is_valid()) | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     return allocate_region_with_vmobject(range, move(vmobject), offset_in_vmobject, name, prot, shared); |     return allocate_region_with_vmobject(range, move(vmobject), offset_in_vmobject, name, prot, shared); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -573,12 +573,12 @@ Custody& Process::current_directory() | ||||||
| KResultOr<String> Process::get_syscall_path_argument(const char* user_path, size_t path_length) const | KResultOr<String> Process::get_syscall_path_argument(const char* user_path, size_t path_length) const | ||||||
| { | { | ||||||
|     if (path_length == 0) |     if (path_length == 0) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     if (path_length > PATH_MAX) |     if (path_length > PATH_MAX) | ||||||
|         return KResult(-ENAMETOOLONG); |         return ENAMETOOLONG; | ||||||
|     auto copied_string = copy_string_from_user(user_path, path_length); |     auto copied_string = copy_string_from_user(user_path, path_length); | ||||||
|     if (copied_string.is_null()) |     if (copied_string.is_null()) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     return copied_string; |     return copied_string; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -819,7 +819,7 @@ KResult Process::send_signal(u8 signal, Process* sender) | ||||||
|         receiver_thread->send_signal(signal, sender); |         receiver_thread->send_signal(signal, sender); | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     } |     } | ||||||
|     return KResult(-ESRCH); |     return ESRCH; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RefPtr<Thread> Process::create_kernel_thread(void (*entry)(void*), void* entry_data, u32 priority, const String& name, u32 affinity, bool joinable) | RefPtr<Thread> Process::create_kernel_thread(void (*entry)(void*), void* entry_data, u32 priority, const String& name, u32 affinity, bool joinable) | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P | ||||||
|     ScopedSpinLock scheduler_lock(g_scheduler_lock); |     ScopedSpinLock scheduler_lock(g_scheduler_lock); | ||||||
|     if (params.request == PT_TRACE_ME) { |     if (params.request == PT_TRACE_ME) { | ||||||
|         if (Process::current()->tracer()) |         if (Process::current()->tracer()) | ||||||
|             return KResult(-EBUSY); |             return EBUSY; | ||||||
| 
 | 
 | ||||||
|         caller.set_wait_for_tracer_at_next_execve(true); |         caller.set_wait_for_tracer_at_next_execve(true); | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|  | @ -49,23 +49,23 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P | ||||||
|     // long it is not the main thread. Alternatively, if this is desired, then the
 |     // long it is not the main thread. Alternatively, if this is desired, then the
 | ||||||
|     // bug is that this prevents PT_ATTACH to the main thread from another thread.
 |     // bug is that this prevents PT_ATTACH to the main thread from another thread.
 | ||||||
|     if (params.tid == caller.pid().value()) |     if (params.tid == caller.pid().value()) | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
| 
 | 
 | ||||||
|     auto peer = Thread::from_tid(params.tid); |     auto peer = Thread::from_tid(params.tid); | ||||||
|     if (!peer) |     if (!peer) | ||||||
|         return KResult(-ESRCH); |         return ESRCH; | ||||||
| 
 | 
 | ||||||
|     if ((peer->process().uid() != caller.euid()) |     if ((peer->process().uid() != caller.euid()) | ||||||
|         || (peer->process().uid() != peer->process().euid())) // Disallow tracing setuid processes
 |         || (peer->process().uid() != peer->process().euid())) // Disallow tracing setuid processes
 | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
| 
 | 
 | ||||||
|     if (!peer->process().is_dumpable()) |     if (!peer->process().is_dumpable()) | ||||||
|         return KResult(-EACCES); |         return EACCES; | ||||||
| 
 | 
 | ||||||
|     auto& peer_process = peer->process(); |     auto& peer_process = peer->process(); | ||||||
|     if (params.request == PT_ATTACH) { |     if (params.request == PT_ATTACH) { | ||||||
|         if (peer_process.tracer()) { |         if (peer_process.tracer()) { | ||||||
|             return KResult(-EBUSY); |             return EBUSY; | ||||||
|         } |         } | ||||||
|         peer_process.start_tracing_from(caller.pid()); |         peer_process.start_tracing_from(caller.pid()); | ||||||
|         ScopedSpinLock lock(peer->get_lock()); |         ScopedSpinLock lock(peer->get_lock()); | ||||||
|  | @ -78,13 +78,13 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P | ||||||
|     auto* tracer = peer_process.tracer(); |     auto* tracer = peer_process.tracer(); | ||||||
| 
 | 
 | ||||||
|     if (!tracer) |     if (!tracer) | ||||||
|         return KResult(-EPERM); |         return EPERM; | ||||||
| 
 | 
 | ||||||
|     if (tracer->tracer_pid() != caller.pid()) |     if (tracer->tracer_pid() != caller.pid()) | ||||||
|         return KResult(-EBUSY); |         return EBUSY; | ||||||
| 
 | 
 | ||||||
|     if (peer->state() == Thread::State::Running) |     if (peer->state() == Thread::State::Running) | ||||||
|         return KResult(-EBUSY); |         return EBUSY; | ||||||
| 
 | 
 | ||||||
|     scheduler_lock.unlock(); |     scheduler_lock.unlock(); | ||||||
| 
 | 
 | ||||||
|  | @ -105,25 +105,25 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P | ||||||
| 
 | 
 | ||||||
|     case PT_GETREGS: { |     case PT_GETREGS: { | ||||||
|         if (!tracer->has_regs()) |         if (!tracer->has_regs()) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
|         auto* regs = reinterpret_cast<PtraceRegisters*>(params.addr); |         auto* regs = reinterpret_cast<PtraceRegisters*>(params.addr); | ||||||
|         if (!copy_to_user(regs, &tracer->regs())) |         if (!copy_to_user(regs, &tracer->regs())) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     case PT_SETREGS: { |     case PT_SETREGS: { | ||||||
|         if (!tracer->has_regs()) |         if (!tracer->has_regs()) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
| 
 | 
 | ||||||
|         PtraceRegisters regs; |         PtraceRegisters regs; | ||||||
|         if (!copy_from_user(®s, (const PtraceRegisters*)params.addr)) |         if (!copy_from_user(®s, (const PtraceRegisters*)params.addr)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
| 
 | 
 | ||||||
|         auto& peer_saved_registers = peer->get_register_dump_from_stack(); |         auto& peer_saved_registers = peer->get_register_dump_from_stack(); | ||||||
|         // Verify that the saved registers are in usermode context
 |         // Verify that the saved registers are in usermode context
 | ||||||
|         if ((peer_saved_registers.cs & 0x03) != 3) |         if ((peer_saved_registers.cs & 0x03) != 3) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
| 
 | 
 | ||||||
|         tracer->set_regs(regs); |         tracer->set_regs(regs); | ||||||
|         copy_ptrace_registers_into_kernel_registers(peer_saved_registers, regs); |         copy_ptrace_registers_into_kernel_registers(peer_saved_registers, regs); | ||||||
|  | @ -133,24 +133,24 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P | ||||||
|     case PT_PEEK: { |     case PT_PEEK: { | ||||||
|         Kernel::Syscall::SC_ptrace_peek_params peek_params; |         Kernel::Syscall::SC_ptrace_peek_params peek_params; | ||||||
|         if (!copy_from_user(&peek_params, reinterpret_cast<Kernel::Syscall::SC_ptrace_peek_params*>(params.addr))) |         if (!copy_from_user(&peek_params, reinterpret_cast<Kernel::Syscall::SC_ptrace_peek_params*>(params.addr))) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         if (!is_user_address(VirtualAddress { peek_params.address })) |         if (!is_user_address(VirtualAddress { peek_params.address })) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         auto result = peer->process().peek_user_data(Userspace<const u32*> { (FlatPtr)peek_params.address }); |         auto result = peer->process().peek_user_data(Userspace<const u32*> { (FlatPtr)peek_params.address }); | ||||||
|         if (result.is_error()) |         if (result.is_error()) | ||||||
|             return result.error(); |             return result.error(); | ||||||
|         if (!copy_to_user(peek_params.out_data, &result.value())) |         if (!copy_to_user(peek_params.out_data, &result.value())) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     case PT_POKE: |     case PT_POKE: | ||||||
|         if (!is_user_address(VirtualAddress { params.addr })) |         if (!is_user_address(VirtualAddress { params.addr })) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         return peer->process().poke_user_data(Userspace<u32*> { (FlatPtr)params.addr }, params.data); |         return peer->process().poke_user_data(Userspace<u32*> { (FlatPtr)params.addr }, params.data); | ||||||
| 
 | 
 | ||||||
|     default: |     default: | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
|  |  | ||||||
|  | @ -73,13 +73,13 @@ KResultOr<size_t> StorageDevice::read(FileDescription&, size_t offset, UserOrKer | ||||||
|         auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index, whole_blocks, outbuf, whole_blocks * block_size()); |         auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index, whole_blocks, outbuf, whole_blocks * block_size()); | ||||||
|         auto result = read_request->wait(); |         auto result = read_request->wait(); | ||||||
|         if (result.wait_result().was_interrupted()) |         if (result.wait_result().was_interrupted()) | ||||||
|             return KResult(-EINTR); |             return EINTR; | ||||||
|         switch (result.request_result()) { |         switch (result.request_result()) { | ||||||
|         case AsyncDeviceRequest::Failure: |         case AsyncDeviceRequest::Failure: | ||||||
|         case AsyncDeviceRequest::Cancelled: |         case AsyncDeviceRequest::Cancelled: | ||||||
|             return KResult(-EIO); |             return EIO; | ||||||
|         case AsyncDeviceRequest::MemoryFault: |         case AsyncDeviceRequest::MemoryFault: | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         default: |         default: | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  | @ -93,12 +93,12 @@ KResultOr<size_t> StorageDevice::read(FileDescription&, size_t offset, UserOrKer | ||||||
|         auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index + whole_blocks, 1, data_buffer, block_size()); |         auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index + whole_blocks, 1, data_buffer, block_size()); | ||||||
|         auto result = read_request->wait(); |         auto result = read_request->wait(); | ||||||
|         if (result.wait_result().was_interrupted()) |         if (result.wait_result().was_interrupted()) | ||||||
|             return KResult(-EINTR); |             return EINTR; | ||||||
|         switch (result.request_result()) { |         switch (result.request_result()) { | ||||||
|         case AsyncDeviceRequest::Failure: |         case AsyncDeviceRequest::Failure: | ||||||
|             return pos; |             return pos; | ||||||
|         case AsyncDeviceRequest::Cancelled: |         case AsyncDeviceRequest::Cancelled: | ||||||
|             return KResult(-EIO); |             return EIO; | ||||||
|         case AsyncDeviceRequest::MemoryFault: |         case AsyncDeviceRequest::MemoryFault: | ||||||
|             // This should never happen, we're writing to a kernel buffer!
 |             // This should never happen, we're writing to a kernel buffer!
 | ||||||
|             ASSERT_NOT_REACHED(); |             ASSERT_NOT_REACHED(); | ||||||
|  | @ -106,7 +106,7 @@ KResultOr<size_t> StorageDevice::read(FileDescription&, size_t offset, UserOrKer | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         if (!outbuf.write(data.data(), pos, remaining)) |         if (!outbuf.write(data.data(), pos, remaining)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return pos + remaining; |     return pos + remaining; | ||||||
|  | @ -140,13 +140,13 @@ KResultOr<size_t> StorageDevice::write(FileDescription&, size_t offset, const Us | ||||||
|         auto write_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index, whole_blocks, inbuf, whole_blocks * block_size()); |         auto write_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index, whole_blocks, inbuf, whole_blocks * block_size()); | ||||||
|         auto result = write_request->wait(); |         auto result = write_request->wait(); | ||||||
|         if (result.wait_result().was_interrupted()) |         if (result.wait_result().was_interrupted()) | ||||||
|             return KResult(-EINTR); |             return EINTR; | ||||||
|         switch (result.request_result()) { |         switch (result.request_result()) { | ||||||
|         case AsyncDeviceRequest::Failure: |         case AsyncDeviceRequest::Failure: | ||||||
|         case AsyncDeviceRequest::Cancelled: |         case AsyncDeviceRequest::Cancelled: | ||||||
|             return KResult(-EIO); |             return EIO; | ||||||
|         case AsyncDeviceRequest::MemoryFault: |         case AsyncDeviceRequest::MemoryFault: | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
|         default: |         default: | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  | @ -165,12 +165,12 @@ KResultOr<size_t> StorageDevice::write(FileDescription&, size_t offset, const Us | ||||||
|             auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index + whole_blocks, 1, data_buffer, block_size()); |             auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index + whole_blocks, 1, data_buffer, block_size()); | ||||||
|             auto result = read_request->wait(); |             auto result = read_request->wait(); | ||||||
|             if (result.wait_result().was_interrupted()) |             if (result.wait_result().was_interrupted()) | ||||||
|                 return KResult(-EINTR); |                 return EINTR; | ||||||
|             switch (result.request_result()) { |             switch (result.request_result()) { | ||||||
|             case AsyncDeviceRequest::Failure: |             case AsyncDeviceRequest::Failure: | ||||||
|                 return pos; |                 return pos; | ||||||
|             case AsyncDeviceRequest::Cancelled: |             case AsyncDeviceRequest::Cancelled: | ||||||
|                 return KResult(-EIO); |                 return EIO; | ||||||
|             case AsyncDeviceRequest::MemoryFault: |             case AsyncDeviceRequest::MemoryFault: | ||||||
|                 // This should never happen, we're writing to a kernel buffer!
 |                 // This should never happen, we're writing to a kernel buffer!
 | ||||||
|                 ASSERT_NOT_REACHED(); |                 ASSERT_NOT_REACHED(); | ||||||
|  | @ -180,18 +180,18 @@ KResultOr<size_t> StorageDevice::write(FileDescription&, size_t offset, const Us | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!inbuf.read(data.data(), pos, remaining)) |         if (!inbuf.read(data.data(), pos, remaining)) | ||||||
|             return KResult(-EFAULT); |             return EFAULT; | ||||||
| 
 | 
 | ||||||
|         { |         { | ||||||
|             auto write_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index + whole_blocks, 1, data_buffer, block_size()); |             auto write_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index + whole_blocks, 1, data_buffer, block_size()); | ||||||
|             auto result = write_request->wait(); |             auto result = write_request->wait(); | ||||||
|             if (result.wait_result().was_interrupted()) |             if (result.wait_result().was_interrupted()) | ||||||
|                 return KResult(-EINTR); |                 return EINTR; | ||||||
|             switch (result.request_result()) { |             switch (result.request_result()) { | ||||||
|             case AsyncDeviceRequest::Failure: |             case AsyncDeviceRequest::Failure: | ||||||
|                 return pos; |                 return pos; | ||||||
|             case AsyncDeviceRequest::Cancelled: |             case AsyncDeviceRequest::Cancelled: | ||||||
|                 return KResult(-EIO); |                 return EIO; | ||||||
|             case AsyncDeviceRequest::MemoryFault: |             case AsyncDeviceRequest::MemoryFault: | ||||||
|                 // This should never happen, we're writing to a kernel buffer!
 |                 // This should never happen, we're writing to a kernel buffer!
 | ||||||
|                 ASSERT_NOT_REACHED(); |                 ASSERT_NOT_REACHED(); | ||||||
|  |  | ||||||
|  | @ -149,7 +149,7 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_ | ||||||
|     auto vmobject = SharedInodeVMObject::create_with_inode(inode); |     auto vmobject = SharedInodeVMObject::create_with_inode(inode); | ||||||
|     if (vmobject->writable_mappings()) { |     if (vmobject->writable_mappings()) { | ||||||
|         dbgln("Refusing to execute a write-mapped program"); |         dbgln("Refusing to execute a write-mapped program"); | ||||||
|         return KResult(-ETXTBSY); |         return ETXTBSY; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     size_t executable_size = inode.size(); |     size_t executable_size = inode.size(); | ||||||
|  | @ -157,13 +157,13 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_ | ||||||
|     auto executable_region = MM.allocate_kernel_region_with_vmobject(*vmobject, PAGE_ROUND_UP(executable_size), "ELF loading", Region::Access::Read); |     auto executable_region = MM.allocate_kernel_region_with_vmobject(*vmobject, PAGE_ROUND_UP(executable_size), "ELF loading", Region::Access::Read); | ||||||
|     if (!executable_region) { |     if (!executable_region) { | ||||||
|         dbgln("Could not allocate memory for ELF loading"); |         dbgln("Could not allocate memory for ELF loading"); | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto elf_image = ELF::Image(executable_region->vaddr().as_ptr(), executable_size); |     auto elf_image = ELF::Image(executable_region->vaddr().as_ptr(), executable_size); | ||||||
| 
 | 
 | ||||||
|     if (!elf_image.is_valid()) |     if (!elf_image.is_valid()) | ||||||
|         return KResult(-ENOEXEC); |         return ENOEXEC; | ||||||
| 
 | 
 | ||||||
|     Region* master_tls_region { nullptr }; |     Region* master_tls_region { nullptr }; | ||||||
|     size_t master_tls_size = 0; |     size_t master_tls_size = 0; | ||||||
|  | @ -181,7 +181,7 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_ | ||||||
| 
 | 
 | ||||||
|             if (!elf_image.is_within_image(program_header.raw_data(), program_header.size_in_image())) { |             if (!elf_image.is_within_image(program_header.raw_data(), program_header.size_in_image())) { | ||||||
|                 dbgln("Shenanigans! ELF PT_TLS header sneaks outside of executable."); |                 dbgln("Shenanigans! ELF PT_TLS header sneaks outside of executable."); | ||||||
|                 ph_load_result = KResult(-ENOEXEC); |                 ph_load_result = ENOEXEC; | ||||||
|                 return IterationDecision::Break; |                 return IterationDecision::Break; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -195,7 +195,7 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_ | ||||||
|             master_tls_alignment = program_header.alignment(); |             master_tls_alignment = program_header.alignment(); | ||||||
| 
 | 
 | ||||||
|             if (!copy_to_user(master_tls_region->vaddr().as_ptr(), program_header.raw_data(), program_header.size_in_image())) { |             if (!copy_to_user(master_tls_region->vaddr().as_ptr(), program_header.raw_data(), program_header.size_in_image())) { | ||||||
|                 ph_load_result = KResult(-EFAULT); |                 ph_load_result = EFAULT; | ||||||
|                 return IterationDecision::Break; |                 return IterationDecision::Break; | ||||||
|             } |             } | ||||||
|             return IterationDecision::Continue; |             return IterationDecision::Continue; | ||||||
|  | @ -210,7 +210,7 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_ | ||||||
| 
 | 
 | ||||||
|             if (!elf_image.is_within_image(program_header.raw_data(), program_header.size_in_image())) { |             if (!elf_image.is_within_image(program_header.raw_data(), program_header.size_in_image())) { | ||||||
|                 dbgln("Shenanigans! Writable ELF PT_LOAD header sneaks outside of executable."); |                 dbgln("Shenanigans! Writable ELF PT_LOAD header sneaks outside of executable."); | ||||||
|                 ph_load_result = KResult(-ENOEXEC); |                 ph_load_result = ENOEXEC; | ||||||
|                 return IterationDecision::Break; |                 return IterationDecision::Break; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -236,7 +236,7 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_ | ||||||
|             auto page_offset = program_header.vaddr(); |             auto page_offset = program_header.vaddr(); | ||||||
|             page_offset.mask(~PAGE_MASK); |             page_offset.mask(~PAGE_MASK); | ||||||
|             if (!copy_to_user((u8*)region_or_error.value()->vaddr().as_ptr() + page_offset.get(), program_header.raw_data(), program_header.size_in_image())) { |             if (!copy_to_user((u8*)region_or_error.value()->vaddr().as_ptr() + page_offset.get(), program_header.raw_data(), program_header.size_in_image())) { | ||||||
|                 ph_load_result = KResult(-EFAULT); |                 ph_load_result = EFAULT; | ||||||
|                 return IterationDecision::Break; |                 return IterationDecision::Break; | ||||||
|             } |             } | ||||||
|             return IterationDecision::Continue; |             return IterationDecision::Continue; | ||||||
|  | @ -269,7 +269,7 @@ KResultOr<Process::LoadResult> Process::load_elf_object(FileDescription& object_ | ||||||
| 
 | 
 | ||||||
|     if (!elf_image.entry().offset(load_offset).get()) { |     if (!elf_image.entry().offset(load_offset).get()) { | ||||||
|         dbgln("do_exec: Failure loading program, entry pointer is invalid! {})", elf_image.entry().offset(load_offset)); |         dbgln("do_exec: Failure loading program, entry pointer is invalid! {})", elf_image.entry().offset(load_offset)); | ||||||
|         return KResult(-ENOEXEC); |         return ENOEXEC; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto stack_region_or_error = allocate_region(VirtualAddress(), Thread::default_userspace_stack_size, "Stack (Main thread)", PROT_READ | PROT_WRITE, AllocationStrategy::Reserve); |     auto stack_region_or_error = allocate_region(VirtualAddress(), Thread::default_userspace_stack_size, "Stack (Main thread)", PROT_READ | PROT_WRITE, AllocationStrategy::Reserve); | ||||||
|  | @ -299,7 +299,7 @@ KResultOr<Process::LoadResult> Process::load(NonnullRefPtr<FileDescription> main | ||||||
|     { |     { | ||||||
|         auto page_directory = PageDirectory::create_for_userspace(*this); |         auto page_directory = PageDirectory::create_for_userspace(*this); | ||||||
|         if (!page_directory) |         if (!page_directory) | ||||||
|             return KResult(-ENOMEM); |             return ENOMEM; | ||||||
| 
 | 
 | ||||||
|         // Need to make sure we don't swap contexts in the middle
 |         // Need to make sure we don't swap contexts in the middle
 | ||||||
|         ScopedCritical critical; |         ScopedCritical critical; | ||||||
|  | @ -366,12 +366,12 @@ static KResultOr<RequiredLoadRange> get_required_load_range(FileDescription& pro | ||||||
|     auto region = MM.allocate_kernel_region_with_vmobject(*vmobject, PAGE_ROUND_UP(executable_size), "ELF memory range calculation", Region::Access::Read); |     auto region = MM.allocate_kernel_region_with_vmobject(*vmobject, PAGE_ROUND_UP(executable_size), "ELF memory range calculation", Region::Access::Read); | ||||||
|     if (!region) { |     if (!region) { | ||||||
|         dbgln("Could not allocate memory for ELF"); |         dbgln("Could not allocate memory for ELF"); | ||||||
|         return KResult(-ENOMEM); |         return ENOMEM; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto elf_image = ELF::Image(region->vaddr().as_ptr(), executable_size); |     auto elf_image = ELF::Image(region->vaddr().as_ptr(), executable_size); | ||||||
|     if (!elf_image.is_valid()) { |     if (!elf_image.is_valid()) { | ||||||
|         return -EINVAL; |         return EINVAL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     RequiredLoadRange range {}; |     RequiredLoadRange range {}; | ||||||
|  | @ -688,7 +688,7 @@ static KResultOr<Vector<String>> find_shebang_interpreter_for_executable(const c | ||||||
|             return interpreter_words; |             return interpreter_words; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return KResult(-ENOEXEC); |     return ENOEXEC; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResultOr<RefPtr<FileDescription>> Process::find_elf_interpreter_for_executable(const String& path, const Elf32_Ehdr& main_program_header, int nread, size_t file_size) | KResultOr<RefPtr<FileDescription>> Process::find_elf_interpreter_for_executable(const String& path, const Elf32_Ehdr& main_program_header, int nread, size_t file_size) | ||||||
|  | @ -698,7 +698,7 @@ KResultOr<RefPtr<FileDescription>> Process::find_elf_interpreter_for_executable( | ||||||
|     String interpreter_path; |     String interpreter_path; | ||||||
|     if (!ELF::validate_program_headers(main_program_header, file_size, (const u8*)&main_program_header, nread, &interpreter_path)) { |     if (!ELF::validate_program_headers(main_program_header, file_size, (const u8*)&main_program_header, nread, &interpreter_path)) { | ||||||
|         dbgln("exec({}): File has invalid ELF Program headers", path); |         dbgln("exec({}): File has invalid ELF Program headers", path); | ||||||
|         return KResult(-ENOEXEC); |         return ENOEXEC; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!interpreter_path.is_empty()) { |     if (!interpreter_path.is_empty()) { | ||||||
|  | @ -719,34 +719,34 @@ KResultOr<RefPtr<FileDescription>> Process::find_elf_interpreter_for_executable( | ||||||
|         // Validate the program interpreter as a valid elf binary.
 |         // Validate the program interpreter as a valid elf binary.
 | ||||||
|         // If your program interpreter is a #! file or something, it's time to stop playing games :)
 |         // If your program interpreter is a #! file or something, it's time to stop playing games :)
 | ||||||
|         if (interp_metadata.size < (int)sizeof(Elf32_Ehdr)) |         if (interp_metadata.size < (int)sizeof(Elf32_Ehdr)) | ||||||
|             return KResult(-ENOEXEC); |             return ENOEXEC; | ||||||
| 
 | 
 | ||||||
|         char first_page[PAGE_SIZE] = {}; |         char first_page[PAGE_SIZE] = {}; | ||||||
|         auto first_page_buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)&first_page); |         auto first_page_buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)&first_page); | ||||||
|         auto nread_or_error = interpreter_description->read(first_page_buffer, sizeof(first_page)); |         auto nread_or_error = interpreter_description->read(first_page_buffer, sizeof(first_page)); | ||||||
|         if (nread_or_error.is_error()) |         if (nread_or_error.is_error()) | ||||||
|             return KResult(-ENOEXEC); |             return ENOEXEC; | ||||||
|         nread = nread_or_error.value(); |         nread = nread_or_error.value(); | ||||||
| 
 | 
 | ||||||
|         if (nread < (int)sizeof(Elf32_Ehdr)) |         if (nread < (int)sizeof(Elf32_Ehdr)) | ||||||
|             return KResult(-ENOEXEC); |             return ENOEXEC; | ||||||
| 
 | 
 | ||||||
|         auto elf_header = (Elf32_Ehdr*)first_page; |         auto elf_header = (Elf32_Ehdr*)first_page; | ||||||
|         if (!ELF::validate_elf_header(*elf_header, interp_metadata.size)) { |         if (!ELF::validate_elf_header(*elf_header, interp_metadata.size)) { | ||||||
|             dbgln("exec({}): Interpreter ({}) has invalid ELF header", path, interpreter_description->absolute_path()); |             dbgln("exec({}): Interpreter ({}) has invalid ELF header", path, interpreter_description->absolute_path()); | ||||||
|             return KResult(-ENOEXEC); |             return ENOEXEC; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Not using KResultOr here because we'll want to do the same thing in userspace in the RTLD
 |         // Not using KResultOr here because we'll want to do the same thing in userspace in the RTLD
 | ||||||
|         String interpreter_interpreter_path; |         String interpreter_interpreter_path; | ||||||
|         if (!ELF::validate_program_headers(*elf_header, interp_metadata.size, (u8*)first_page, nread, &interpreter_interpreter_path)) { |         if (!ELF::validate_program_headers(*elf_header, interp_metadata.size, (u8*)first_page, nread, &interpreter_interpreter_path)) { | ||||||
|             dbgln("exec({}): Interpreter ({}) has invalid ELF Program headers", path, interpreter_description->absolute_path()); |             dbgln("exec({}): Interpreter ({}) has invalid ELF Program headers", path, interpreter_description->absolute_path()); | ||||||
|             return KResult(-ENOEXEC); |             return ENOEXEC; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!interpreter_interpreter_path.is_empty()) { |         if (!interpreter_interpreter_path.is_empty()) { | ||||||
|             dbgln("exec({}): Interpreter ({}) has its own interpreter ({})! No thank you!", path, interpreter_description->absolute_path(), interpreter_interpreter_path); |             dbgln("exec({}): Interpreter ({}) has its own interpreter ({})! No thank you!", path, interpreter_description->absolute_path(), interpreter_interpreter_path); | ||||||
|             return KResult(-ELOOP); |             return ELOOP; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return interpreter_description; |         return interpreter_description; | ||||||
|  | @ -754,7 +754,7 @@ KResultOr<RefPtr<FileDescription>> Process::find_elf_interpreter_for_executable( | ||||||
| 
 | 
 | ||||||
|     if (main_program_header.e_type == ET_REL) { |     if (main_program_header.e_type == ET_REL) { | ||||||
|         // We can't exec an ET_REL, that's just an object file from the compiler
 |         // We can't exec an ET_REL, that's just an object file from the compiler
 | ||||||
|         return KResult(-ENOEXEC); |         return ENOEXEC; | ||||||
|     } |     } | ||||||
|     if (main_program_header.e_type == ET_DYN) { |     if (main_program_header.e_type == ET_DYN) { | ||||||
|         // If it's ET_DYN with no PT_INTERP, then it's a dynamic executable responsible
 |         // If it's ET_DYN with no PT_INTERP, then it's a dynamic executable responsible
 | ||||||
|  | @ -817,12 +817,12 @@ int Process::exec(String path, Vector<String> arguments, Vector<String> environm | ||||||
|     // #2) ELF32 for i386
 |     // #2) ELF32 for i386
 | ||||||
| 
 | 
 | ||||||
|     if (nread_or_error.value() < (int)sizeof(Elf32_Ehdr)) |     if (nread_or_error.value() < (int)sizeof(Elf32_Ehdr)) | ||||||
|         return KResult(-ENOEXEC); |         return ENOEXEC; | ||||||
|     auto main_program_header = (Elf32_Ehdr*)first_page; |     auto main_program_header = (Elf32_Ehdr*)first_page; | ||||||
| 
 | 
 | ||||||
|     if (!ELF::validate_elf_header(*main_program_header, metadata.size)) { |     if (!ELF::validate_elf_header(*main_program_header, metadata.size)) { | ||||||
|         dbgln("exec({}): File has invalid ELF header", path); |         dbgln("exec({}): File has invalid ELF header", path); | ||||||
|         return KResult(-ENOEXEC); |         return ENOEXEC; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto elf_result = find_elf_interpreter_for_executable(path, *main_program_header, nread_or_error.value(), metadata.size); |     auto elf_result = find_elf_interpreter_for_executable(path, *main_program_header, nread_or_error.value(), metadata.size); | ||||||
|  |  | ||||||
|  | @ -33,10 +33,10 @@ KResult Process::do_kill(Process& process, int signal) | ||||||
|     // FIXME: Allow sending SIGCONT to everyone in the process group.
 |     // FIXME: Allow sending SIGCONT to everyone in the process group.
 | ||||||
|     // FIXME: Should setuid processes have some special treatment here?
 |     // FIXME: Should setuid processes have some special treatment here?
 | ||||||
|     if (!is_superuser() && m_euid != process.m_uid && m_uid != process.m_uid) |     if (!is_superuser() && m_euid != process.m_uid && m_uid != process.m_uid) | ||||||
|         return KResult(-EPERM); |         return EPERM; | ||||||
|     if (process.is_kernel_process() && signal == SIGKILL) { |     if (process.is_kernel_process() && signal == SIGKILL) { | ||||||
|         klog() << "attempted to send SIGKILL to kernel process " << process.name().characters() << "(" << process.pid().value() << ")"; |         klog() << "attempted to send SIGKILL to kernel process " << process.name().characters() << "(" << process.pid().value() << ")"; | ||||||
|         return KResult(-EPERM); |         return EPERM; | ||||||
|     } |     } | ||||||
|     if (signal != 0) |     if (signal != 0) | ||||||
|         return process.send_signal(signal, this); |         return process.send_signal(signal, this); | ||||||
|  | @ -72,7 +72,7 @@ KResult Process::do_killpg(ProcessGroupID pgrp, int signal) | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     if (group_was_empty) |     if (group_was_empty) | ||||||
|         return KResult(-ESRCH); |         return ESRCH; | ||||||
|     if (any_succeeded) |     if (any_succeeded) | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     return error; |     return error; | ||||||
|  |  | ||||||
|  | @ -42,7 +42,7 @@ int Process::sys$ptrace(Userspace<const Syscall::SC_ptrace_params*> user_params) | ||||||
|     if (!copy_from_user(¶ms, user_params)) |     if (!copy_from_user(¶ms, user_params)) | ||||||
|         return -EFAULT; |         return -EFAULT; | ||||||
|     auto result = Ptrace::handle_syscall(params, *this); |     auto result = Ptrace::handle_syscall(params, *this); | ||||||
|     return result.is_error() ? result.error() : result.value(); |     return result.is_error() ? result.error().error() : result.value(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -64,7 +64,7 @@ KResultOr<u32> Process::peek_user_data(Userspace<const u32*> address) | ||||||
|     ProcessPagingScope scope(*this); |     ProcessPagingScope scope(*this); | ||||||
|     if (!copy_from_user(&result, address)) { |     if (!copy_from_user(&result, address)) { | ||||||
|         dbgln("Invalid address for peek_user_data: {}", address.ptr()); |         dbgln("Invalid address for peek_user_data: {}", address.ptr()); | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return result; |     return result; | ||||||
|  | @ -75,7 +75,7 @@ KResult Process::poke_user_data(Userspace<u32*> address, u32 data) | ||||||
|     Range range = { VirtualAddress(address), sizeof(u32) }; |     Range range = { VirtualAddress(address), sizeof(u32) }; | ||||||
|     auto* region = find_region_containing(range); |     auto* region = find_region_containing(range); | ||||||
|     if (!region) |     if (!region) | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     ProcessPagingScope scope(*this); |     ProcessPagingScope scope(*this); | ||||||
|     if (region->is_shared()) { |     if (region->is_shared()) { | ||||||
|         // If the region is shared, we change its vmobject to a PrivateInodeVMObject
 |         // If the region is shared, we change its vmobject to a PrivateInodeVMObject
 | ||||||
|  | @ -98,7 +98,7 @@ KResult Process::poke_user_data(Userspace<u32*> address, u32 data) | ||||||
| 
 | 
 | ||||||
|     if (!copy_to_user(address, &data)) { |     if (!copy_to_user(address, &data)) { | ||||||
|         dbgln("poke_user_data: Bad address {:p}", address.ptr()); |         dbgln("poke_user_data: Bad address {:p}", address.ptr()); | ||||||
|         return KResult(-EFAULT); |         return EFAULT; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
|  |  | ||||||
|  | @ -38,12 +38,12 @@ KResultOr<siginfo_t> Process::do_waitid(idtype_t idtype, int id, int options) | ||||||
|     case P_PGID: |     case P_PGID: | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         return KResult(-EINVAL); |         return EINVAL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     KResultOr<siginfo_t> result = KResult(KSuccess); |     KResultOr<siginfo_t> result = KResult(KSuccess); | ||||||
|     if (Thread::current()->block<Thread::WaitBlocker>({}, options, idtype, id, result).was_interrupted()) |     if (Thread::current()->block<Thread::WaitBlocker>({}, options, idtype, id, result).was_interrupted()) | ||||||
|         return KResult(-EINTR); |         return EINTR; | ||||||
|     ASSERT(!result.is_error() || (options & WNOHANG) || result.error() != KSuccess); |     ASSERT(!result.is_error() || (options & WNOHANG) || result.error() != KSuccess); | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -75,7 +75,7 @@ KResultOr<size_t> MasterPTY::read(FileDescription&, size_t, UserOrKernelBuffer& | ||||||
| KResultOr<size_t> MasterPTY::write(FileDescription&, size_t, const UserOrKernelBuffer& buffer, size_t size) | KResultOr<size_t> MasterPTY::write(FileDescription&, size_t, const UserOrKernelBuffer& buffer, size_t size) | ||||||
| { | { | ||||||
|     if (!m_slave) |     if (!m_slave) | ||||||
|         return KResult(-EIO); |         return EIO; | ||||||
|     m_slave->on_master_write(buffer, size); |     m_slave->on_master_write(buffer, size); | ||||||
|     return size; |     return size; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -59,7 +59,7 @@ KResultOr<NonnullRefPtr<FileDescription>> PTYMultiplexer::open(int options) | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
|     if (m_freelist.is_empty()) |     if (m_freelist.is_empty()) | ||||||
|         return KResult(-EBUSY); |         return EBUSY; | ||||||
|     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)); | ||||||
| #ifdef PTMX_DEBUG | #ifdef PTMX_DEBUG | ||||||
|  |  | ||||||
|  | @ -58,7 +58,7 @@ KResultOr<size_t> TTY::read(FileDescription&, size_t, UserOrKernelBuffer& buffer | ||||||
|     if (Process::current()->pgid() != pgid()) { |     if (Process::current()->pgid() != pgid()) { | ||||||
|         // FIXME: Should we propagate this error path somehow?
 |         // FIXME: Should we propagate this error path somehow?
 | ||||||
|         [[maybe_unused]] auto rc = Process::current()->send_signal(SIGTTIN, nullptr); |         [[maybe_unused]] auto rc = Process::current()->send_signal(SIGTTIN, nullptr); | ||||||
|         return KResult(-EINTR); |         return EINTR; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (m_input_buffer.size() < static_cast<size_t>(size)) |     if (m_input_buffer.size() < static_cast<size_t>(size)) | ||||||
|  | @ -95,7 +95,7 @@ KResultOr<size_t> TTY::read(FileDescription&, size_t, UserOrKernelBuffer& buffer | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|     if (nwritten < 0) |     if (nwritten < 0) | ||||||
|         return KResult(nwritten); |         return KResult((ErrnoCode)-nwritten); | ||||||
|     if (nwritten > 0 || need_evaluate_block_conditions) |     if (nwritten > 0 || need_evaluate_block_conditions) | ||||||
|         evaluate_block_conditions(); |         evaluate_block_conditions(); | ||||||
|     return (size_t)nwritten; |     return (size_t)nwritten; | ||||||
|  | @ -105,7 +105,7 @@ KResultOr<size_t> TTY::write(FileDescription&, size_t, const UserOrKernelBuffer& | ||||||
| { | { | ||||||
|     if (m_termios.c_lflag & TOSTOP && Process::current()->pgid() != pgid()) { |     if (m_termios.c_lflag & TOSTOP && Process::current()->pgid() != pgid()) { | ||||||
|         [[maybe_unused]] auto rc = Process::current()->send_signal(SIGTTOU, nullptr); |         [[maybe_unused]] auto rc = Process::current()->send_signal(SIGTTOU, nullptr); | ||||||
|         return KResult(-EINTR); |         return EINTR; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     on_tty_write(buffer, size); |     on_tty_write(buffer, size); | ||||||
|  |  | ||||||
|  | @ -748,11 +748,11 @@ public: | ||||||
|     KResult try_join(AddBlockerHandler add_blocker) |     KResult try_join(AddBlockerHandler add_blocker) | ||||||
|     { |     { | ||||||
|         if (Thread::current() == this) |         if (Thread::current() == this) | ||||||
|             return KResult(-EDEADLK); |             return EDEADLK; | ||||||
| 
 | 
 | ||||||
|         ScopedSpinLock lock(m_lock); |         ScopedSpinLock lock(m_lock); | ||||||
|         if (!m_is_joinable || state() == Dead) |         if (!m_is_joinable || state() == Dead) | ||||||
|             return KResult(-EINVAL); |             return EINVAL; | ||||||
| 
 | 
 | ||||||
|         add_blocker(); |         add_blocker(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -611,7 +611,7 @@ Thread::WaitBlocker::WaitBlocker(int wait_options, idtype_t id_type, pid_t id, K | ||||||
|     case P_PID: { |     case P_PID: { | ||||||
|         m_waitee = Process::from_pid(m_waitee_id); |         m_waitee = Process::from_pid(m_waitee_id); | ||||||
|         if (!m_waitee || m_waitee->ppid() != Process::current()->pid()) { |         if (!m_waitee || m_waitee->ppid() != Process::current()->pid()) { | ||||||
|             m_result = KResult(-ECHILD); |             m_result = ECHILD; | ||||||
|             m_error = true; |             m_error = true; | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  | @ -620,7 +620,7 @@ Thread::WaitBlocker::WaitBlocker(int wait_options, idtype_t id_type, pid_t id, K | ||||||
|     case P_PGID: { |     case P_PGID: { | ||||||
|         m_waitee_group = ProcessGroup::from_pgid(m_waitee_id); |         m_waitee_group = ProcessGroup::from_pgid(m_waitee_id); | ||||||
|         if (!m_waitee_group) { |         if (!m_waitee_group) { | ||||||
|             m_result = KResult(-ECHILD); |             m_result = ECHILD; | ||||||
|             m_error = true; |             m_error = true; | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  | @ -670,7 +670,7 @@ void Thread::WaitBlocker::do_was_disowned() | ||||||
| { | { | ||||||
|     ASSERT(!m_did_unblock); |     ASSERT(!m_did_unblock); | ||||||
|     m_did_unblock = true; |     m_did_unblock = true; | ||||||
|     m_result = KResult(-ECHILD); |     m_result = ECHILD; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Thread::WaitBlocker::do_set_result(const siginfo_t& result) | void Thread::WaitBlocker::do_set_result(const siginfo_t& result) | ||||||
|  |  | ||||||
|  | @ -26,78 +26,155 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #define EPERM 1 | enum ErrnoCode { | ||||||
| #define ENOENT 2 |     EPERM = 1, | ||||||
| #define ESRCH 3 | #define EPERM EPERM | ||||||
| #define EINTR 4 |     ENOENT, | ||||||
| #define EIO 5 | #define ENOENT ENOENT | ||||||
| #define ENXIO 6 |     ESRCH, | ||||||
| #define E2BIG 7 | #define ESRCH ESRCH | ||||||
| #define ENOEXEC 8 |     EINTR, | ||||||
| #define EBADF 9 | #define EINTR EINTR | ||||||
| #define ECHILD 10 |     EIO, | ||||||
| #define EAGAIN 11 | #define EIO EIO | ||||||
| #define ENOMEM 12 |     ENXIO, | ||||||
| #define EACCES 13 | #define ENXIO ENXIO | ||||||
| #define EFAULT 14 |     E2BIG, | ||||||
| #define ENOTBLK 15 | #define E2BIG E2BIG | ||||||
| #define EBUSY 16 |     ENOEXEC, | ||||||
| #define EEXIST 17 | #define ENOEXEC ENOEXEC | ||||||
| #define EXDEV 18 |     EBADF, | ||||||
| #define ENODEV 19 | #define EBADF EBADF | ||||||
| #define ENOTDIR 20 |     ECHILD, | ||||||
| #define EISDIR 21 | #define ECHILD ECHILD | ||||||
| #define EINVAL 22 |     EAGAIN, | ||||||
| #define ENFILE 23 | #define EAGAIN EAGAIN | ||||||
| #define EMFILE 24 |     ENOMEM, | ||||||
| #define ENOTTY 25 | #define ENOMEM ENOMEM | ||||||
| #define ETXTBSY 26 |     EACCES, | ||||||
| #define EFBIG 27 | #define EACCES EACCES | ||||||
| #define ENOSPC 28 |     EFAULT, | ||||||
| #define ESPIPE 29 | #define EFAULT EFAULT | ||||||
| #define EROFS 30 |     ENOTBLK, | ||||||
| #define EMLINK 31 | #define ENOTBLK ENOTBLK | ||||||
| #define EPIPE 32 |     EBUSY, | ||||||
| #define ERANGE 33 | #define EBUSY EBUSY | ||||||
| #define ENAMETOOLONG 34 |     EEXIST, | ||||||
| #define ELOOP 35 | #define EEXIST EEXIST | ||||||
| #define EOVERFLOW 36 |     EXDEV, | ||||||
| #define EOPNOTSUPP 37 | #define EXDEV EXDEV | ||||||
| #define ENOSYS 38 |     ENODEV, | ||||||
| #define ENOTIMPL 39 | #define ENODEV ENODEV | ||||||
| #define EAFNOSUPPORT 40 |     ENOTDIR, | ||||||
| #define ENOTSOCK 41 | #define ENOTDIR ENOTDIR | ||||||
| #define EADDRINUSE 42 |     EISDIR, | ||||||
| #define EWHYTHO 43 | #define EISDIR EISDIR | ||||||
| #define ENOTEMPTY 44 |     EINVAL, | ||||||
| #define EDOM 45 | #define EINVAL EINVAL | ||||||
| #define ECONNREFUSED 46 |     ENFILE, | ||||||
| #define EADDRNOTAVAIL 47 | #define ENFILE ENFILE | ||||||
| #define EISCONN 48 |     EMFILE, | ||||||
| #define ECONNABORTED 49 | #define EMFILE EMFILE | ||||||
| #define EALREADY 50 |     ENOTTY, | ||||||
| #define ECONNRESET 51 | #define ENOTTY ENOTTY | ||||||
| #define EDESTADDRREQ 52 |     ETXTBSY, | ||||||
| #define EHOSTUNREACH 53 | #define ETXTBSY ETXTBSY | ||||||
| #define EILSEQ 54 |     EFBIG, | ||||||
| #define EMSGSIZE 55 | #define EFBIG EFBIG | ||||||
| #define ENETDOWN 56 |     ENOSPC, | ||||||
| #define ENETUNREACH 57 | #define ENOSPC ENOSPC | ||||||
| #define ENETRESET 58 |     ESPIPE, | ||||||
| #define ENOBUFS 59 | #define ESPIPE ESPIPE | ||||||
| #define ENOLCK 60 |     EROFS, | ||||||
| #define ENOMSG 61 | #define EROFS EROFS | ||||||
| #define ENOPROTOOPT 62 |     EMLINK, | ||||||
| #define ENOTCONN 63 | #define EMLINK EMLINK | ||||||
| #define EWOULDBLOCK 64 |     EPIPE, | ||||||
| #define EPROTONOSUPPORT 65 | #define EPIPE EPIPE | ||||||
| #define EDEADLK 66 |     ERANGE, | ||||||
| #define ETIMEDOUT 67 | #define ERANGE ERANGE | ||||||
| #define EPROTOTYPE 68 |     ENAMETOOLONG, | ||||||
| #define EINPROGRESS 69 | #define ENAMETOOLONG ENAMETOOLONG | ||||||
| #define ENOTHREAD 70 |     ELOOP, | ||||||
| #define EPROTO 71 | #define ELOOP ELOOP | ||||||
| #define ENOTSUP 72 |     EOVERFLOW, | ||||||
| #define EPFNOSUPPORT 73 | #define EOVERFLOW EOVERFLOW | ||||||
| #define EDIRINTOSELF 74 |     EOPNOTSUPP, | ||||||
| #define EMAXERRNO 75 | #define EOPNOTSUPP EOPNOTSUPP | ||||||
|  |     ENOSYS, | ||||||
|  | #define ENOSYS ENOSYS | ||||||
|  |     ENOTIMPL, | ||||||
|  | #define ENOTIMPL ENOTIMPL | ||||||
|  |     EAFNOSUPPORT, | ||||||
|  | #define EAFNOSUPPORT EAFNOSUPPORT | ||||||
|  |     ENOTSOCK, | ||||||
|  | #define ENOTSOCK ENOTSOCK | ||||||
|  |     EADDRINUSE, | ||||||
|  | #define EADDRINUSE EADDRINUSE | ||||||
|  |     EWHYTHO, | ||||||
|  | #define EWHYTHO EWHYTHO | ||||||
|  |     ENOTEMPTY, | ||||||
|  | #define ENOTEMPTY ENOTEMPTY | ||||||
|  |     EDOM, | ||||||
|  | #define EDOM EDOM | ||||||
|  |     ECONNREFUSED, | ||||||
|  | #define ECONNREFUSED ECONNREFUSED | ||||||
|  |     EADDRNOTAVAIL, | ||||||
|  | #define EADDRNOTAVAIL EADDRNOTAVAIL | ||||||
|  |     EISCONN, | ||||||
|  | #define EISCONN EISCONN | ||||||
|  |     ECONNABORTED, | ||||||
|  | #define ECONNABORTED ECONNABORTED | ||||||
|  |     EALREADY, | ||||||
|  | #define EALREADY EALREADY | ||||||
|  |     ECONNRESET, | ||||||
|  | #define ECONNRESET ECONNRESET | ||||||
|  |     EDESTADDRREQ, | ||||||
|  | #define EDESTADDRREQ EDESTADDRREQ | ||||||
|  |     EHOSTUNREACH, | ||||||
|  | #define EHOSTUNREACH EHOSTUNREACH | ||||||
|  |     EILSEQ, | ||||||
|  | #define EILSEQ EILSEQ | ||||||
|  |     EMSGSIZE, | ||||||
|  | #define EMSGSIZE EMSGSIZE | ||||||
|  |     ENETDOWN, | ||||||
|  | #define ENETDOWN ENETDOWN | ||||||
|  |     ENETUNREACH, | ||||||
|  | #define ENETUNREACH ENETUNREACH | ||||||
|  |     ENETRESET, | ||||||
|  | #define ENETRESET ENETRESET | ||||||
|  |     ENOBUFS, | ||||||
|  | #define ENOBUFS ENOBUFS | ||||||
|  |     ENOLCK, | ||||||
|  | #define ENOLCK ENOLCK | ||||||
|  |     ENOMSG, | ||||||
|  | #define ENOMSG ENOMSG | ||||||
|  |     ENOPROTOOPT, | ||||||
|  | #define ENOPROTOOPT ENOPROTOOPT | ||||||
|  |     ENOTCONN, | ||||||
|  | #define ENOTCONN ENOTCONN | ||||||
|  |     EWOULDBLOCK, | ||||||
|  | #define EWOULDBLOCK EWOULDBLOCK | ||||||
|  |     EPROTONOSUPPORT, | ||||||
|  | #define EPROTONOSUPPORT EPROTONOSUPPORT | ||||||
|  |     EDEADLK, | ||||||
|  | #define EDEADLK EDEADLK | ||||||
|  |     ETIMEDOUT, | ||||||
|  | #define ETIMEDOUT ETIMEDOUT | ||||||
|  |     EPROTOTYPE, | ||||||
|  | #define EPROTOTYPE EPROTOTYPE | ||||||
|  |     EINPROGRESS, | ||||||
|  | #define EINPROGRESS EINPROGRESS | ||||||
|  |     ENOTHREAD, | ||||||
|  | #define ENOTHREAD ENOTHREAD | ||||||
|  |     EPROTO, | ||||||
|  | #define EPROTO EPROTO | ||||||
|  |     ENOTSUP, | ||||||
|  | #define ENOTSUP ENOTSUP | ||||||
|  |     EPFNOSUPPORT, | ||||||
|  | #define EPFNOSUPPORT EPFNOSUPPORT | ||||||
|  |     EDIRINTOSELF, | ||||||
|  | #define EDIRINTOSELF EDIRINTOSELF | ||||||
|  |     EMAXERRNO, | ||||||
|  | #define EMAXERRNO EMAXERRNO | ||||||
|  | }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling