Kernel: Symlinks are now working
We still have to implement loop or depth detection
This commit is contained in:
		
							parent
							
								
									efb3271588
								
							
						
					
					
						commit
						7bbdee6cc4
					
				|  | @ -25,7 +25,7 @@ namespace Kernel | ||||||
| 			BAN::RefPtr<Inode> inode; | 			BAN::RefPtr<Inode> inode; | ||||||
| 			BAN::String canonical_path; | 			BAN::String canonical_path; | ||||||
| 		}; | 		}; | ||||||
| 		BAN::ErrorOr<File> file_from_absolute_path(BAN::StringView, bool follow_links); | 		BAN::ErrorOr<File> file_from_absolute_path(BAN::StringView, bool follow_link); | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
| 		VirtualFileSystem() = default; | 		VirtualFileSystem() = default; | ||||||
|  | @ -39,7 +39,7 @@ namespace Kernel | ||||||
| 		MountPoint* mount_from_root_inode(BAN::RefPtr<Inode>); | 		MountPoint* mount_from_root_inode(BAN::RefPtr<Inode>); | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
| 		RecursiveSpinLock				m_lock; | 		SpinLock						m_lock; | ||||||
| 		FileSystem*						m_root_fs = nullptr; | 		FileSystem*						m_root_fs = nullptr; | ||||||
| 		BAN::Vector<MountPoint>			m_mount_points; | 		BAN::Vector<MountPoint>			m_mount_points; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  | @ -82,7 +82,7 @@ namespace Kernel | ||||||
| 		return nullptr; | 		return nullptr; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_absolute_path(BAN::StringView path, bool follow_links) | 	BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_absolute_path(BAN::StringView path, bool follow_link) | ||||||
| 	{ | 	{ | ||||||
| 		LockGuard _(m_lock); | 		LockGuard _(m_lock); | ||||||
| 
 | 
 | ||||||
|  | @ -93,13 +93,22 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 		BAN::String canonical_path; | 		BAN::String canonical_path; | ||||||
| 
 | 
 | ||||||
| 		const auto path_parts = TRY(path.split('/')); | 		BAN::Vector<BAN::String> path_parts; | ||||||
| 
 | 
 | ||||||
| 		for (auto path_part : path_parts) |  | ||||||
| 		{ | 		{ | ||||||
|  | 			auto temp = TRY(path.split('/')); | ||||||
|  | 			for (size_t i = 0; i < temp.size(); i++) | ||||||
|  | 				TRY(path_parts.push_back(temp[temp.size() - i - 1])); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		while (!path_parts.empty()) | ||||||
|  | 		{ | ||||||
|  | 			const auto& path_part = path_parts.back(); | ||||||
|  | 			auto orig = inode; | ||||||
|  | 
 | ||||||
| 			if (path_part.empty() || path_part == "."sv) | 			if (path_part.empty() || path_part == "."sv) | ||||||
| 			{ | 			{ | ||||||
| 				continue; | 
 | ||||||
| 			} | 			} | ||||||
| 			else if (path_part == ".."sv) | 			else if (path_part == ".."sv) | ||||||
| 			{ | 			{ | ||||||
|  | @ -119,32 +128,42 @@ namespace Kernel | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				inode = TRY(inode->read_directory_inode(path_part)); | 				inode = TRY(inode->read_directory_inode(path_part)); | ||||||
| 				TRY(canonical_path.push_back('/')); |  | ||||||
| 				TRY(canonical_path.append(path_part)); |  | ||||||
| 
 | 
 | ||||||
| 				if (auto* mount_point = mount_from_host_inode(inode)) | 				if (auto* mount_point = mount_from_host_inode(inode)) | ||||||
| 					inode = mount_point->target->root_inode(); | 					inode = mount_point->target->root_inode(); | ||||||
| 
 | 
 | ||||||
| 				if (follow_links && inode->mode().iflnk()) | 				TRY(canonical_path.push_back('/')); | ||||||
|  | 				TRY(canonical_path.append(path_part)); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			path_parts.pop_back(); | ||||||
|  | 
 | ||||||
|  | 			if (inode->mode().iflnk() && (follow_link || !path_parts.empty())) | ||||||
|  | 			{ | ||||||
|  | 				auto target = TRY(inode->link_target()); | ||||||
|  | 				if (target.empty()) | ||||||
|  | 					return BAN::Error::from_errno(ENOENT); | ||||||
|  | 				 | ||||||
|  | 				if (target.front() == '/') | ||||||
| 				{ | 				{ | ||||||
| 					auto target = TRY(inode->link_target()); | 					inode = root_inode(); | ||||||
| 					if (target.empty()) | 					canonical_path.clear(); | ||||||
| 						return BAN::Error::from_errno(ENOENT); | 
 | ||||||
| 					if (target.front() == '/') | 					auto temp = TRY(target.sv().split('/')); | ||||||
| 					{ | 					for (size_t i = 0; i < temp.size(); i++) | ||||||
| 						File file = TRY(file_from_absolute_path(target, follow_links)); | 						TRY(path_parts.emplace_back(temp[temp.size() - i - 1])); | ||||||
| 						inode = file.inode; | 				} | ||||||
| 						canonical_path = BAN::move(file.canonical_path); | 				else | ||||||
| 					} | 				{ | ||||||
| 					else | 					inode = orig; | ||||||
| 					{ | 
 | ||||||
| 						while (canonical_path.back() != '/') | 					while (canonical_path.back() != '/') | ||||||
| 							canonical_path.pop_back(); | 						canonical_path.pop_back(); | ||||||
| 						TRY(canonical_path.append(target)); | 					canonical_path.pop_back(); | ||||||
| 						File file = TRY(file_from_absolute_path(canonical_path, follow_links)); | 
 | ||||||
| 						inode = file.inode; | 					auto new_parts = TRY(target.sv().split('/')); | ||||||
| 						canonical_path = BAN::move(file.canonical_path); | 					for (size_t i = 0; i < new_parts.size(); i++) | ||||||
| 					} | 						TRY(path_parts.emplace_back(new_parts[new_parts.size() - i - 1])); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -296,7 +296,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<int> Process::open(BAN::StringView path, int flags) | 	BAN::ErrorOr<int> Process::open(BAN::StringView path, int flags) | ||||||
| 	{ | 	{ | ||||||
| 		if (flags & ~O_RDWR) | 		if (flags & ~(O_RDONLY | O_WRONLY | O_NOFOLLOW)) | ||||||
| 			return BAN::Error::from_errno(ENOTSUP); | 			return BAN::Error::from_errno(ENOTSUP); | ||||||
| 
 | 
 | ||||||
| 		BAN::String absolute_path = TRY(absolute_path_of(path)); | 		BAN::String absolute_path = TRY(absolute_path_of(path)); | ||||||
|  | @ -468,7 +468,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 	BAN::ErrorOr<void> Process::stat(BAN::StringView path, struct stat* out) | 	BAN::ErrorOr<void> Process::stat(BAN::StringView path, struct stat* out) | ||||||
| 	{ | 	{ | ||||||
| 		int fd = TRY(open(path, O_RDONLY)); | 		int fd = TRY(open(path, O_RDONLY | O_NOFOLLOW)); | ||||||
| 		auto ret = fstat(fd, out); | 		auto ret = fstat(fd, out); | ||||||
| 		MUST(close(fd)); | 		MUST(close(fd)); | ||||||
| 		return ret; | 		return ret; | ||||||
|  |  | ||||||
|  | @ -41,6 +41,7 @@ namespace Kernel | ||||||
| 			mode.ifdir() ? 'd' : | 			mode.ifdir() ? 'd' : | ||||||
| 			mode.ifblk() ? 'b' : | 			mode.ifblk() ? 'b' : | ||||||
| 			mode.ifchr() ? 'c' : | 			mode.ifchr() ? 'c' : | ||||||
|  | 			mode.iflnk() ? 'l' : | ||||||
| 							'-'; | 							'-'; | ||||||
| 
 | 
 | ||||||
| 		buffer[1] = (mode.mode & Inode::Mode::IRUSR) ? 'r' : '-'; | 		buffer[1] = (mode.mode & Inode::Mode::IRUSR) ? 'r' : '-'; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue