Kernel: Rework processes and VFS so we don't expose inodes
Everything is now done through a file descriptor.
This commit is contained in:
		
							parent
							
								
									32c3aca52f
								
							
						
					
					
						commit
						e55860eb6b
					
				|  | @ -123,15 +123,22 @@ namespace Kernel | ||||||
| 	class Ext2Inode : public Inode | 	class Ext2Inode : public Inode | ||||||
| 	{ | 	{ | ||||||
| 	public: | 	public: | ||||||
|  | 		virtual ino_t ino() const override { return m_index; }; | ||||||
|  | 		virtual mode_t mode() const override { return m_inode.mode; } | ||||||
|  | 		virtual nlink_t nlink() const override { return m_inode.links_count; } | ||||||
| 		virtual uid_t uid() const override { return m_inode.uid; } | 		virtual uid_t uid() const override { return m_inode.uid; } | ||||||
| 		virtual gid_t gid() const override { return m_inode.gid; } | 		virtual gid_t gid() const override { return m_inode.gid; } | ||||||
| 		virtual size_t size() const override { return m_inode.size; } | 		virtual off_t size() const override { return m_inode.size; } | ||||||
| 
 | 		virtual timespec atime() const override { return timespec { .tv_sec = m_inode.atime, .tv_nsec = 0 }; } | ||||||
| 		virtual mode_t mode() const override { return m_inode.mode; } | 		virtual timespec mtime() const override { return timespec { .tv_sec = m_inode.mtime, .tv_nsec = 0 }; } | ||||||
|  | 		virtual timespec ctime() const override { return timespec { .tv_sec = m_inode.ctime, .tv_nsec = 0 }; } | ||||||
|  | 		virtual blksize_t blksize() const override; | ||||||
|  | 		virtual blkcnt_t blocks() const override; | ||||||
| 
 | 
 | ||||||
| 		virtual BAN::StringView name() const override { return m_name; } | 		virtual BAN::StringView name() const override { return m_name; } | ||||||
| 
 | 
 | ||||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override; | 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override; | ||||||
|  | 		virtual BAN::ErrorOr<BAN::Vector<BAN::String>> read_directory_entries_impl(size_t) override; | ||||||
| 
 | 
 | ||||||
| 		virtual BAN::ErrorOr<void> create_file(BAN::StringView, mode_t) override; | 		virtual BAN::ErrorOr<void> create_file(BAN::StringView, mode_t) override; | ||||||
| 
 | 
 | ||||||
|  | @ -139,8 +146,7 @@ namespace Kernel | ||||||
| 		virtual bool operator==(const Inode& other) const override; | 		virtual bool operator==(const Inode& other) const override; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		virtual BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes_impl() override; | 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> read_directory_inode_impl(BAN::StringView) override; | ||||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find_impl(BAN::StringView) override; |  | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
| 		BAN::ErrorOr<uint32_t> data_block_index(uint32_t); | 		BAN::ErrorOr<uint32_t> data_block_index(uint32_t); | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include <BAN/Vector.h> | #include <BAN/Vector.h> | ||||||
| 
 | 
 | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
|  | #include <time.h> | ||||||
| 
 | 
 | ||||||
| namespace Kernel | namespace Kernel | ||||||
| { | { | ||||||
|  | @ -43,27 +44,32 @@ namespace Kernel | ||||||
| 		bool ifdir() const { return mode() & Mode::IFDIR; } | 		bool ifdir() const { return mode() & Mode::IFDIR; } | ||||||
| 		bool ifreg() const { return mode() & Mode::IFREG; } | 		bool ifreg() const { return mode() & Mode::IFREG; } | ||||||
| 
 | 
 | ||||||
|  | 		virtual ino_t ino() const = 0; | ||||||
|  | 		virtual mode_t mode() const = 0; | ||||||
|  | 		virtual nlink_t nlink() const = 0; | ||||||
| 		virtual uid_t uid() const = 0; | 		virtual uid_t uid() const = 0; | ||||||
| 		virtual gid_t gid() const = 0; | 		virtual gid_t gid() const = 0; | ||||||
| 		virtual size_t size() const = 0; | 		virtual off_t size() const = 0; | ||||||
| 
 | 		virtual timespec atime() const = 0;	 | ||||||
| 		virtual mode_t mode() const = 0; | 		virtual timespec mtime() const = 0; | ||||||
|  | 		virtual timespec ctime() const = 0; | ||||||
|  | 		virtual blksize_t blksize() const = 0; | ||||||
|  | 		virtual blkcnt_t blocks() const = 0; | ||||||
| 
 | 
 | ||||||
| 		virtual BAN::StringView name() const = 0; | 		virtual BAN::StringView name() const = 0; | ||||||
| 
 | 
 | ||||||
| 		BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes(); | 		BAN::ErrorOr<BAN::RefPtr<Inode>> read_directory_inode(BAN::StringView); | ||||||
| 		BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find(BAN::StringView); | 		BAN::ErrorOr<BAN::Vector<BAN::String>> read_directory_entries(size_t); | ||||||
| 
 | 
 | ||||||
| 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) = 0; | 		virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) = 0; | ||||||
| 
 |  | ||||||
| 		virtual BAN::ErrorOr<void> create_file(BAN::StringView, mode_t) = 0; | 		virtual BAN::ErrorOr<void> create_file(BAN::StringView, mode_t) = 0; | ||||||
| 
 | 
 | ||||||
| 		virtual Type type() const = 0; | 		virtual Type type() const = 0; | ||||||
| 		virtual bool operator==(const Inode&) const = 0; | 		virtual bool operator==(const Inode&) const = 0; | ||||||
| 
 | 
 | ||||||
| 	protected: | 	protected: | ||||||
| 		virtual BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> directory_inodes_impl() = 0; | 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> read_directory_inode_impl(BAN::StringView) = 0; | ||||||
| 		virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find_impl(BAN::StringView) = 0; | 		virtual BAN::ErrorOr<BAN::Vector<BAN::String>> read_directory_entries_impl(size_t) = 0; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | @ -7,6 +7,8 @@ | ||||||
| #include <kernel/SpinLock.h> | #include <kernel/SpinLock.h> | ||||||
| #include <kernel/Thread.h> | #include <kernel/Thread.h> | ||||||
| 
 | 
 | ||||||
|  | #include <sys/stat.h> | ||||||
|  | 
 | ||||||
| namespace Kernel | namespace Kernel | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  | @ -32,11 +34,14 @@ namespace Kernel | ||||||
| 		BAN::ErrorOr<size_t> read(int, void*, size_t); | 		BAN::ErrorOr<size_t> read(int, void*, size_t); | ||||||
| 		BAN::ErrorOr<void> creat(BAN::StringView, mode_t); | 		BAN::ErrorOr<void> creat(BAN::StringView, mode_t); | ||||||
| 
 | 
 | ||||||
|  | 		BAN::ErrorOr<void> fstat(int, stat*); | ||||||
|  | 		BAN::ErrorOr<void> stat(BAN::StringView, stat*); | ||||||
|  | 
 | ||||||
|  | 		BAN::ErrorOr<BAN::Vector<BAN::String>> read_directory_entries(int); | ||||||
|  | 
 | ||||||
| 		BAN::String working_directory() const; | 		BAN::String working_directory() const; | ||||||
| 		BAN::ErrorOr<void> set_working_directory(BAN::StringView); | 		BAN::ErrorOr<void> set_working_directory(BAN::StringView); | ||||||
| 
 | 
 | ||||||
| 		Inode& inode_for_fd(int); |  | ||||||
| 
 |  | ||||||
| 		static BAN::RefPtr<Process> current() { return Thread::current()->process(); } | 		static BAN::RefPtr<Process> current() { return Thread::current()->process(); } | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
|  | @ -51,8 +56,6 @@ namespace Kernel | ||||||
| 			BAN::String path; | 			BAN::String path; | ||||||
| 			size_t offset = 0; | 			size_t offset = 0; | ||||||
| 			uint8_t flags = 0; | 			uint8_t flags = 0; | ||||||
| 
 |  | ||||||
| 			BAN::ErrorOr<size_t> read(void*, size_t); |  | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		BAN::ErrorOr<void> validate_fd(int); | 		BAN::ErrorOr<void> validate_fd(int); | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include <BAN/ScopeGuard.h> | #include <BAN/ScopeGuard.h> | ||||||
| #include <BAN/StringView.h> | #include <BAN/StringView.h> | ||||||
| #include <kernel/FS/Ext2.h> | #include <kernel/FS/Ext2.h> | ||||||
|  | #include <kernel/Process.h> | ||||||
| #include <kernel/RTC.h> | #include <kernel/RTC.h> | ||||||
| 
 | 
 | ||||||
| #define EXT2_DEBUG_PRINT 0 | #define EXT2_DEBUG_PRINT 0 | ||||||
|  | @ -150,6 +151,16 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	blksize_t Ext2Inode::blksize() const | ||||||
|  | 	{ | ||||||
|  | 		return m_fs.block_size(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	blkcnt_t Ext2Inode::blocks() const | ||||||
|  | 	{ | ||||||
|  | 		return m_inode.blocks / (2 << m_fs.superblock().log_block_size); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::create(Ext2FS& fs, uint32_t inode_inode, BAN::StringView name) | 	BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::create(Ext2FS& fs, uint32_t inode_inode, BAN::StringView name) | ||||||
| 	{ | 	{ | ||||||
| 		BAN::Vector<uint8_t> block_buffer; | 		BAN::Vector<uint8_t> block_buffer; | ||||||
|  | @ -273,6 +284,38 @@ namespace Kernel | ||||||
| 		return n_read; | 		return n_read; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	BAN::ErrorOr<BAN::Vector<BAN::String>> Ext2Inode::read_directory_entries_impl(size_t index) | ||||||
|  | 	{ | ||||||
|  | 		if (!ifdir()) | ||||||
|  | 			return BAN::Error::from_errno(ENOTDIR); | ||||||
|  | 		 | ||||||
|  | 		uint32_t data_block_count = blocks(); | ||||||
|  | 		if (index >= data_block_count) | ||||||
|  | 			return BAN::Vector<BAN::String>(); | ||||||
|  | 
 | ||||||
|  | 		uint32_t block_size = blksize(); | ||||||
|  | 		uint32_t block_index = TRY(data_block_index(index)); | ||||||
|  | 
 | ||||||
|  | 		BAN::Vector<uint8_t> block_buffer; | ||||||
|  | 		TRY(block_buffer.resize(block_size)); | ||||||
|  | 
 | ||||||
|  | 		m_fs.read_block(block_index, block_buffer.span()); | ||||||
|  | 
 | ||||||
|  | 		BAN::Vector<BAN::String> entries; | ||||||
|  | 
 | ||||||
|  | 		const uint8_t* block_buffer_end = block_buffer.data() + block_size; | ||||||
|  | 		const uint8_t* entry_addr = block_buffer.data(); | ||||||
|  | 		while (entry_addr < block_buffer_end) | ||||||
|  | 		{ | ||||||
|  | 			auto& entry = *(Ext2::LinkedDirectoryEntry*)entry_addr; | ||||||
|  | 			if (entry.inode) | ||||||
|  | 				TRY(entries.emplace_back(BAN::StringView(entry.name, entry.name_len))); | ||||||
|  | 			entry_addr += entry.rec_len; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return entries; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	BAN::ErrorOr<void> Ext2Inode::create_file(BAN::StringView name, mode_t mode) | 	BAN::ErrorOr<void> Ext2Inode::create_file(BAN::StringView name, mode_t mode) | ||||||
| 	{ | 	{ | ||||||
| 		if (!ifdir()) | 		if (!ifdir()) | ||||||
|  | @ -285,7 +328,7 @@ namespace Kernel | ||||||
| 		BAN::Vector<uint8_t> block_buffer; | 		BAN::Vector<uint8_t> block_buffer; | ||||||
| 		TRY(block_buffer.resize(block_size)); | 		TRY(block_buffer.resize(block_size)); | ||||||
| 
 | 
 | ||||||
| 		auto error_or = directory_find_impl(name); | 		auto error_or = read_directory_inode_impl(name); | ||||||
| 		if (!error_or.is_error()) | 		if (!error_or.is_error()) | ||||||
| 			return BAN::Error::from_errno(EEXISTS); | 			return BAN::Error::from_errno(EEXISTS); | ||||||
| 		if (error_or.error().get_error_code() != ENOENT) | 		if (error_or.error().get_error_code() != ENOENT) | ||||||
|  | @ -358,7 +401,7 @@ namespace Kernel | ||||||
| 		return {}; | 		return {}; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::directory_find_impl(BAN::StringView file_name) | 	BAN::ErrorOr<BAN::RefPtr<Inode>> Ext2Inode::read_directory_inode_impl(BAN::StringView file_name) | ||||||
| 	{ | 	{ | ||||||
| 		if (!ifdir()) | 		if (!ifdir()) | ||||||
| 			return BAN::Error::from_errno(ENOTDIR); | 			return BAN::Error::from_errno(ENOTDIR); | ||||||
|  | @ -367,7 +410,7 @@ namespace Kernel | ||||||
| 		BAN::Vector<uint8_t> block_buffer; | 		BAN::Vector<uint8_t> block_buffer; | ||||||
| 		TRY(block_buffer.resize(block_size)); | 		TRY(block_buffer.resize(block_size)); | ||||||
| 
 | 
 | ||||||
| 		uint32_t data_block_count = m_inode.blocks / (2 << m_fs.superblock().log_block_size); | 		uint32_t data_block_count = blocks(); | ||||||
| 
 | 
 | ||||||
| 		for (uint32_t i = 0; i < data_block_count; i++) | 		for (uint32_t i = 0; i < data_block_count; i++) | ||||||
| 		{ | 		{ | ||||||
|  | @ -390,42 +433,6 @@ namespace Kernel | ||||||
| 		return BAN::Error::from_errno(ENOENT); | 		return BAN::Error::from_errno(ENOENT); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> Ext2Inode::directory_inodes_impl() |  | ||||||
| 	{ |  | ||||||
| 		if (!ifdir()) |  | ||||||
| 			return BAN::Error::from_errno(ENOTDIR); |  | ||||||
| 
 |  | ||||||
| 		uint32_t block_size = m_fs.block_size(); |  | ||||||
| 		BAN::Vector<uint8_t> block_buffer; |  | ||||||
| 		TRY(block_buffer.resize(block_size)); |  | ||||||
| 
 |  | ||||||
| 		uint32_t data_block_count = m_inode.blocks / (2 << m_fs.superblock().log_block_size); |  | ||||||
| 		 |  | ||||||
| 		BAN::Vector<BAN::RefPtr<Inode>> inodes; |  | ||||||
| 
 |  | ||||||
| 		for (uint32_t i = 0; i < data_block_count; i++) |  | ||||||
| 		{ |  | ||||||
| 			uint32_t block_index = TRY(data_block_index(i)); |  | ||||||
| 			m_fs.read_block(block_index, block_buffer.span()); |  | ||||||
| 			 |  | ||||||
| 			const uint8_t* block_buffer_end = block_buffer.data() + block_size; |  | ||||||
| 			const uint8_t* entry_addr = block_buffer.data(); |  | ||||||
| 			while (entry_addr < block_buffer_end) |  | ||||||
| 			{ |  | ||||||
| 				const auto& entry = *(const Ext2::LinkedDirectoryEntry*)entry_addr; |  | ||||||
| 				if (entry.inode) |  | ||||||
| 				{ |  | ||||||
| 					BAN::StringView entry_name(entry.name, entry.name_len); |  | ||||||
| 					auto inode = TRY(Ext2Inode::create(m_fs, entry.inode, entry_name)); |  | ||||||
| 					TRY(inodes.push_back(inode)); |  | ||||||
| 				} |  | ||||||
| 				entry_addr += entry.rec_len; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		return inodes; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	bool Ext2Inode::operator==(const Inode& other) const | 	bool Ext2Inode::operator==(const Inode& other) const | ||||||
| 	{ | 	{ | ||||||
| 		if (type() != other.type()) | 		if (type() != other.type()) | ||||||
|  |  | ||||||
|  | @ -5,23 +5,22 @@ | ||||||
| namespace Kernel | namespace Kernel | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| 	 | 	BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::read_directory_inode(BAN::StringView name) | ||||||
| 	BAN::ErrorOr<BAN::Vector<BAN::RefPtr<Inode>>> Inode::directory_inodes() |  | ||||||
| 	{ |  | ||||||
| 		for (const auto& mount : VirtualFileSystem::get().mount_points()) |  | ||||||
| 			if (*mount.inode == *this) |  | ||||||
| 				return mount.target->root_inode()->directory_inodes_impl(); |  | ||||||
| 		return directory_inodes_impl(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::directory_find(BAN::StringView name) |  | ||||||
| 	{ | 	{ | ||||||
| 		if (name == ".."sv) | 		if (name == ".."sv) | ||||||
| 			return directory_find_impl(name); | 			return read_directory_inode_impl(name); | ||||||
| 		for (const auto& mount : VirtualFileSystem::get().mount_points()) | 		for (const auto& mount : VirtualFileSystem::get().mount_points()) | ||||||
| 			if (*mount.inode == *this) | 			if (*mount.inode == *this) | ||||||
| 				return mount.target->root_inode()->directory_find_impl(name); | 				return mount.target->root_inode()->read_directory_inode_impl(name); | ||||||
| 		return directory_find_impl(name); | 		return read_directory_inode_impl(name); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	BAN::ErrorOr<BAN::Vector<BAN::String>> Inode::read_directory_entries(size_t index) | ||||||
|  | 	{ | ||||||
|  | 		for (const auto& mount : VirtualFileSystem::get().mount_points()) | ||||||
|  | 			if (*mount.inode == *this) | ||||||
|  | 				return mount.target->root_inode()->read_directory_entries_impl(index); | ||||||
|  | 		return read_directory_entries_impl(index); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | @ -117,11 +117,9 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<void> VirtualFileSystem::mount_test() | 	BAN::ErrorOr<void> VirtualFileSystem::mount_test() | ||||||
| 	{ | 	{ | ||||||
| 		auto mount = TRY(root_inode()->directory_find("mnt"sv)); | 		auto mount = TRY(root_inode()->read_directory_inode("mnt"sv)); | ||||||
| 		if (!mount->ifdir()) | 		if (!mount->ifdir()) | ||||||
| 			return BAN::Error::from_errno(ENOTDIR); | 			return BAN::Error::from_errno(ENOTDIR); | ||||||
| 		if (TRY(mount->directory_inodes()).size() > 2) |  | ||||||
| 			return BAN::Error::from_errno(ENOTEMPTY); |  | ||||||
| 
 | 
 | ||||||
| 		for (auto* controller : m_storage_controllers) | 		for (auto* controller : m_storage_controllers) | ||||||
| 		{ | 		{ | ||||||
|  | @ -159,7 +157,7 @@ namespace Kernel | ||||||
| 			} | 			} | ||||||
| 			else if (path_parts[i] == ".."sv) | 			else if (path_parts[i] == ".."sv) | ||||||
| 			{ | 			{ | ||||||
| 				inode = TRY(inode->directory_find(path_parts[i])); | 				inode = TRY(inode->read_directory_inode(path_parts[i])); | ||||||
| 				path_parts.remove(i); | 				path_parts.remove(i); | ||||||
| 				if (i > 0) | 				if (i > 0) | ||||||
| 				{ | 				{ | ||||||
|  | @ -169,7 +167,7 @@ namespace Kernel | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				inode = TRY(inode->directory_find(path_parts[i]));	 | 				inode = TRY(inode->read_directory_inode(path_parts[i]));	 | ||||||
| 				i++; | 				i++; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -40,10 +40,12 @@ namespace Kernel | ||||||
| 		int fd = TRY(Process::current()->open(path, O_RDONLY)); | 		int fd = TRY(Process::current()->open(path, O_RDONLY)); | ||||||
| 		BAN::ScopeGuard _([fd] { MUST(Process::current()->close(fd)); }); | 		BAN::ScopeGuard _([fd] { MUST(Process::current()->close(fd)); }); | ||||||
| 
 | 
 | ||||||
| 		size_t file_size = Process::current()->inode_for_fd(fd).size(); | 		stat st; | ||||||
|  | 		TRY(Process::current()->fstat(fd, &st)); | ||||||
|  | 
 | ||||||
| 		BAN::Vector<uint8_t> file_data; | 		BAN::Vector<uint8_t> file_data; | ||||||
| 		TRY(file_data.resize(file_size)); | 		TRY(file_data.resize(st.st_size)); | ||||||
| 		TRY(Process::current()->read(fd, file_data.data(), file_size)); | 		TRY(Process::current()->read(fd, file_data.data(), st.st_size)); | ||||||
| 
 | 
 | ||||||
| 		if (file_data.size() < 4) | 		if (file_data.size() < 4) | ||||||
| 			return BAN::Error::from_c_string("Font file is too small"); | 			return BAN::Error::from_c_string("Font file is too small"); | ||||||
|  |  | ||||||
|  | @ -36,7 +36,10 @@ namespace Kernel | ||||||
| 	void Process::on_thread_exit(Thread& thread) | 	void Process::on_thread_exit(Thread& thread) | ||||||
| 	{ | 	{ | ||||||
| 		LockGuard _(m_lock); | 		LockGuard _(m_lock); | ||||||
| 		(void)thread; | 		dprintln("thread {} exit", thread.tid()); | ||||||
|  | 		for (size_t i = 0; i < m_threads.size(); i++) | ||||||
|  | 			if (m_threads[i].ptr() == &thread) | ||||||
|  | 				m_threads.remove(i); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<int> Process::open(BAN::StringView path, int flags) | 	BAN::ErrorOr<int> Process::open(BAN::StringView path, int flags) | ||||||
|  | @ -63,7 +66,6 @@ namespace Kernel | ||||||
| 	BAN::ErrorOr<void> Process::close(int fd) | 	BAN::ErrorOr<void> Process::close(int fd) | ||||||
| 	{ | 	{ | ||||||
| 		LockGuard _(m_lock); | 		LockGuard _(m_lock); | ||||||
| 
 |  | ||||||
| 		TRY(validate_fd(fd)); | 		TRY(validate_fd(fd)); | ||||||
| 		auto& open_file_description = this->open_file_description(fd); | 		auto& open_file_description = this->open_file_description(fd); | ||||||
| 		open_file_description.inode = nullptr; | 		open_file_description.inode = nullptr; | ||||||
|  | @ -73,19 +75,18 @@ namespace Kernel | ||||||
| 	BAN::ErrorOr<size_t> Process::read(int fd, void* buffer, size_t count) | 	BAN::ErrorOr<size_t> Process::read(int fd, void* buffer, size_t count) | ||||||
| 	{ | 	{ | ||||||
| 		LockGuard _(m_lock); | 		LockGuard _(m_lock); | ||||||
| 
 |  | ||||||
| 		TRY(validate_fd(fd)); | 		TRY(validate_fd(fd)); | ||||||
| 		auto& open_file_description = this->open_file_description(fd); | 		auto& open_fd = open_file_description(fd); | ||||||
| 		if (open_file_description.offset >= open_file_description.inode->size()) | 		if (!(open_fd.flags & O_RDONLY)) | ||||||
| 			return 0; | 			return BAN::Error::from_errno(EBADF); | ||||||
| 		size_t n_read = TRY(open_file_description.read(buffer, count)); | 		size_t n_read = TRY(open_fd.inode->read(open_fd.offset, buffer, count)); | ||||||
|  | 		open_fd.offset += n_read; | ||||||
| 		return n_read; | 		return n_read; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<void> Process::creat(BAN::StringView path, mode_t mode) | 	BAN::ErrorOr<void> Process::creat(BAN::StringView path, mode_t mode) | ||||||
| 	{ | 	{ | ||||||
| 		LockGuard _(m_lock); | 		LockGuard _(m_lock); | ||||||
| 
 |  | ||||||
| 		auto absolute_path = TRY(absolute_path_of(path)); | 		auto absolute_path = TRY(absolute_path_of(path)); | ||||||
| 		while (absolute_path.sv().back() != '/') | 		while (absolute_path.sv().back() != '/') | ||||||
| 			absolute_path.pop_back(); | 			absolute_path.pop_back(); | ||||||
|  | @ -96,12 +97,47 @@ namespace Kernel | ||||||
| 		return {}; | 		return {}; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Inode& Process::inode_for_fd(int fd) | 	BAN::ErrorOr<void> Process::fstat(int fd, struct stat* out) | ||||||
| 	{ | 	{ | ||||||
| 		LockGuard _(m_lock); | 		LockGuard _(m_lock); | ||||||
| 
 | 
 | ||||||
| 		MUST(validate_fd(fd)); | 		TRY(validate_fd(fd)); | ||||||
| 		return *open_file_description(fd).inode; | 		const auto& open_fd = open_file_description(fd); | ||||||
|  | 
 | ||||||
|  | 		out->st_dev = 0; | ||||||
|  | 		out->st_ino = open_fd.inode->ino(); | ||||||
|  | 		out->st_mode = open_fd.inode->mode(); | ||||||
|  | 		out->st_nlink = open_fd.inode->nlink(); | ||||||
|  | 		out->st_uid = open_fd.inode->uid(); | ||||||
|  | 		out->st_gid = open_fd.inode->gid(); | ||||||
|  | 		out->st_rdev = 0; | ||||||
|  | 		out->st_size = open_fd.inode->size(); | ||||||
|  | 		out->st_atim = open_fd.inode->atime(); | ||||||
|  | 		out->st_mtim = open_fd.inode->mtime(); | ||||||
|  | 		out->st_ctim = open_fd.inode->ctime(); | ||||||
|  | 		out->st_blksize = open_fd.inode->blksize(); | ||||||
|  | 		out->st_blocks = open_fd.inode->blocks(); | ||||||
|  | 
 | ||||||
|  | 		return {}; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	BAN::ErrorOr<void> Process::stat(BAN::StringView path, struct stat* out) | ||||||
|  | 	{ | ||||||
|  | 		LockGuard _(m_lock); | ||||||
|  | 		int fd = TRY(open(path, O_RDONLY)); | ||||||
|  | 		auto ret = fstat(fd, out); | ||||||
|  | 		MUST(close(fd)); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	BAN::ErrorOr<BAN::Vector<BAN::String>> Process::read_directory_entries(int fd) | ||||||
|  | 	{ | ||||||
|  | 		LockGuard _(m_lock); | ||||||
|  | 		TRY(validate_fd(fd)); | ||||||
|  | 		auto& open_fd = open_file_description(fd); | ||||||
|  | 		auto result = TRY(open_fd.inode->read_directory_entries(open_fd.offset)); | ||||||
|  | 		open_fd.offset++; | ||||||
|  | 		return result; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	BAN::String Process::working_directory() const | 	BAN::String Process::working_directory() const | ||||||
|  | @ -142,19 +178,9 @@ namespace Kernel | ||||||
| 		return absolute_path; | 		return absolute_path; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<size_t> Process::OpenFileDescription::read(void* buffer, size_t count) |  | ||||||
| 	{ |  | ||||||
| 		if (!(flags & O_RDONLY)) |  | ||||||
| 			return BAN::Error::from_errno(EBADF); |  | ||||||
| 		size_t n_read = TRY(inode->read(offset, buffer, count)); |  | ||||||
| 		offset += n_read; |  | ||||||
| 		return n_read; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	BAN::ErrorOr<void> Process::validate_fd(int fd) | 	BAN::ErrorOr<void> Process::validate_fd(int fd) | ||||||
| 	{ | 	{ | ||||||
| 		LockGuard _(m_lock); | 		LockGuard _(m_lock); | ||||||
| 
 |  | ||||||
| 		if (fd < 0 || m_open_files.size() <= (size_t)fd || !m_open_files[fd].inode) | 		if (fd < 0 || m_open_files.size() <= (size_t)fd || !m_open_files[fd].inode) | ||||||
| 			return BAN::Error::from_errno(EBADF); | 			return BAN::Error::from_errno(EBADF); | ||||||
| 		return {}; | 		return {}; | ||||||
|  |  | ||||||
|  | @ -356,14 +356,6 @@ argument_done: | ||||||
| 			if (arguments.size() > 2) | 			if (arguments.size() > 2) | ||||||
| 				return BAN::Error::from_c_string("usage: 'ls [path]'"); | 				return BAN::Error::from_c_string("usage: 'ls [path]'"); | ||||||
| 
 | 
 | ||||||
| 			BAN::String path = (arguments.size() == 2) ? arguments[1] : Process::current()->working_directory(); |  | ||||||
| 
 |  | ||||||
| 			int fd = TRY(Process::current()->open(path, O_RDONLY)); |  | ||||||
| 			BAN::ScopeGuard _([fd] { MUST(Process::current()->close(fd)); }); |  | ||||||
| 
 |  | ||||||
| 			auto& directory = Process::current()->inode_for_fd(fd); |  | ||||||
| 			auto inodes = TRY(directory.directory_inodes()); |  | ||||||
| 
 |  | ||||||
| 			auto mode_string = [](mode_t mode) | 			auto mode_string = [](mode_t mode) | ||||||
| 			{ | 			{ | ||||||
| 				static char buffer[11] {}; | 				static char buffer[11] {}; | ||||||
|  | @ -380,12 +372,40 @@ argument_done: | ||||||
| 				return (const char*)buffer; | 				return (const char*)buffer; | ||||||
| 			}; | 			}; | ||||||
| 
 | 
 | ||||||
| 			for (auto& inode : inodes) | 			BAN::String path = (arguments.size() == 2) ? arguments[1] : Process::current()->working_directory(); | ||||||
| 				if (inode->ifdir()) | 
 | ||||||
| 					TTY_PRINTLN("  {} {7} \e[34m{}\e[m", mode_string(inode->mode()), inode->size(), inode->name()); | 			int fd = TRY(Process::current()->open(path, O_RDONLY)); | ||||||
| 			for (auto& inode : inodes) | 			BAN::ScopeGuard _([fd] { MUST(Process::current()->close(fd)); }); | ||||||
| 				if (!inode->ifdir()) | 
 | ||||||
| 					TTY_PRINTLN("  {} {7} {}", mode_string(inode->mode()), inode->size(), inode->name()); | 			BAN::Vector<BAN::String> all_entries; | ||||||
|  | 
 | ||||||
|  | 			BAN::Vector<BAN::String> entries; | ||||||
|  | 			while (!(entries = TRY(Process::current()->read_directory_entries(fd))).empty()) | ||||||
|  | 			{ | ||||||
|  | 				TRY(all_entries.reserve(all_entries.size() + entries.size())); | ||||||
|  | 				for (auto& entry : entries) | ||||||
|  | 					TRY(all_entries.push_back(entry)); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			BAN::String entry_prefix; | ||||||
|  | 			TRY(entry_prefix.append(path)); | ||||||
|  | 			TRY(entry_prefix.push_back('/')); | ||||||
|  | 			for (const auto& entry : all_entries) | ||||||
|  | 			{ | ||||||
|  | 				stat st; | ||||||
|  | 
 | ||||||
|  | 				BAN::String entry_path; | ||||||
|  | 				TRY(entry_path.append(entry_prefix)); | ||||||
|  | 				TRY(entry_path.append(entry)); | ||||||
|  | 				TRY(Process::current()->stat(entry_path, &st)); | ||||||
|  | 
 | ||||||
|  | 				const char* color = | ||||||
|  | 					(st.st_mode & Inode::Mode::IFDIR) ? "34" : | ||||||
|  | 					(st.st_mode & Inode::Mode::IXUSR) ? "32" : | ||||||
|  | 														""; | ||||||
|  | 				 | ||||||
|  | 				TTY_PRINTLN("  {} {7} \e[{}m{}\e[m", mode_string(st.st_mode), st.st_size, color, entry); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		else if (arguments.front() == "cat") | 		else if (arguments.front() == "cat") | ||||||
| 		{ | 		{ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue