Kernel/LibC: Implement readlink and readlinkat
This commit is contained in:
		
							parent
							
								
									a3a287f5ca
								
							
						
					
					
						commit
						447da99f0b
					
				|  | @ -101,6 +101,9 @@ namespace Kernel | |||
| 		BAN::ErrorOr<long> sys_create(const char*, mode_t); | ||||
| 		BAN::ErrorOr<long> sys_create_dir(const char*, mode_t); | ||||
| 		BAN::ErrorOr<long> sys_unlink(const char*); | ||||
| 		BAN::ErrorOr<long> readlink_impl(BAN::StringView absolute_path, char* buffer, size_t bufsize); | ||||
| 		BAN::ErrorOr<long> sys_readlink(const char* path, char* buffer, size_t bufsize); | ||||
| 		BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize); | ||||
| 
 | ||||
| 		BAN::ErrorOr<long> sys_chmod(const char*, mode_t); | ||||
| 
 | ||||
|  |  | |||
|  | @ -782,6 +782,47 @@ namespace Kernel | |||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<long> Process::readlink_impl(BAN::StringView absolute_path, char* buffer, size_t bufsize) | ||||
| 	{ | ||||
| 		auto inode = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_NOFOLLOW | O_RDONLY)).inode; | ||||
| 		 | ||||
| 		// FIXME: no allocation needed
 | ||||
| 		auto link_target = TRY(inode->link_target()); | ||||
| 
 | ||||
| 		size_t byte_count = BAN::Math::min<size_t>(link_target.size(), bufsize); | ||||
| 		memcpy(buffer, link_target.data(), byte_count); | ||||
| 
 | ||||
| 		return byte_count; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<long> Process::sys_readlink(const char* path, char* buffer, size_t bufsize) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		validate_string_access(path); | ||||
| 		validate_pointer_access(buffer, bufsize); | ||||
| 
 | ||||
| 		auto absolute_path = TRY(absolute_path_of(path)); | ||||
| 
 | ||||
| 		return readlink_impl(absolute_path.sv(), buffer, bufsize); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<long> Process::sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		validate_string_access(path); | ||||
| 		validate_pointer_access(buffer, bufsize); | ||||
| 
 | ||||
| 		// FIXME: handle O_SEARCH in fd
 | ||||
| 		auto parent_path = TRY(m_open_file_descriptors.path_of(fd)); | ||||
| 
 | ||||
| 		BAN::String absolute_path; | ||||
| 		TRY(absolute_path.append(parent_path)); | ||||
| 		TRY(absolute_path.push_back('/')); | ||||
| 		TRY(absolute_path.append(path)); | ||||
| 
 | ||||
| 		return readlink_impl(absolute_path.sv(), buffer, bufsize); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<long> Process::sys_chmod(const char* path, mode_t mode) | ||||
| 	{ | ||||
| 		if (mode & S_IFMASK) | ||||
|  |  | |||
|  | @ -211,6 +211,12 @@ namespace Kernel | |||
| 		case SYS_UNLINK: | ||||
| 			ret = Process::current().sys_unlink((const char*)arg1); | ||||
| 			break; | ||||
| 		case SYS_READLINK: | ||||
| 			ret = Process::current().sys_readlink((const char*)arg1, (char*)arg2, (size_t)arg3); | ||||
| 			break; | ||||
| 		case SYS_READLINKAT: | ||||
| 			ret = Process::current().sys_readlinkat((int)arg1, (const char*)arg2, (char*)arg3, (size_t)arg4); | ||||
| 			break; | ||||
| 		default: | ||||
| 			dwarnln("Unknown syscall {}", syscall); | ||||
| 			break; | ||||
|  |  | |||
|  | @ -59,6 +59,8 @@ __BEGIN_DECLS | |||
| #define SYS_CREATE 56 // creat, mkfifo
 | ||||
| #define SYS_CREATE_DIR 57 // mkdir
 | ||||
| #define SYS_UNLINK 58 | ||||
| #define SYS_READLINK 59 | ||||
| #define SYS_READLINKAT 60 | ||||
| 
 | ||||
| __END_DECLS | ||||
| 
 | ||||
|  |  | |||
|  | @ -78,6 +78,16 @@ ssize_t write(int fildes, const void* buf, size_t nbyte) | |||
| 	return syscall(SYS_WRITE, fildes, buf, nbyte); | ||||
| } | ||||
| 
 | ||||
| ssize_t readlink(const char* __restrict path, char* __restrict buf, size_t bufsize) | ||||
| { | ||||
| 	return syscall(SYS_READLINK, path, buf, bufsize); | ||||
| } | ||||
| 
 | ||||
| ssize_t readlinkat(int fd, const char* __restrict path, char* __restrict buf, size_t bufsize) | ||||
| { | ||||
| 	return syscall(SYS_READLINKAT, fd, path, buf, bufsize); | ||||
| } | ||||
| 
 | ||||
| int dup(int fildes) | ||||
| { | ||||
| 	return syscall(SYS_DUP, fildes); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue