Kernel/LibC: move file offset back to kernel
This makes keeping track of offsets easier and more proper
This commit is contained in:
		
							parent
							
								
									f33e78882e
								
							
						
					
					
						commit
						4a4a3bf184
					
				|  | @ -25,7 +25,7 @@ namespace LibELF | |||
| 
 | ||||
| 			TRY(data.resize(st.st_size)); | ||||
| 
 | ||||
| 			TRY(Kernel::Process::current().read(fd, data.data(), 0, data.size())); | ||||
| 			TRY(Kernel::Process::current().read(fd, data.data(), data.size())); | ||||
| 
 | ||||
| 			elf = new ELF(BAN::move(data)); | ||||
| 			ASSERT(elf); | ||||
|  |  | |||
|  | @ -42,10 +42,13 @@ namespace Kernel | |||
| 
 | ||||
| 		BAN::ErrorOr<int> open(BAN::StringView, int); | ||||
| 		BAN::ErrorOr<void> close(int fd); | ||||
| 		BAN::ErrorOr<size_t> read(int fd, void* buffer, size_t offset, size_t count); | ||||
| 		BAN::ErrorOr<size_t> write(int fd, const void* buffer, size_t offset, size_t count); | ||||
| 		BAN::ErrorOr<size_t> read(int fd, void* buffer, size_t count); | ||||
| 		BAN::ErrorOr<size_t> write(int fd, const void* buffer, size_t count); | ||||
| 		BAN::ErrorOr<void> creat(BAN::StringView name, mode_t); | ||||
| 
 | ||||
| 		BAN::ErrorOr<void> seek(int fd, off_t offset, int whence); | ||||
| 		BAN::ErrorOr<off_t> tell(int fd); | ||||
| 
 | ||||
| 		BAN::ErrorOr<void> fstat(int fd, struct stat*); | ||||
| 		BAN::ErrorOr<void> stat(BAN::StringView path, struct stat*); | ||||
| 
 | ||||
|  | @ -77,7 +80,8 @@ namespace Kernel | |||
| 		{ | ||||
| 			BAN::RefPtr<Inode> inode; | ||||
| 			BAN::String path; | ||||
| 			uint8_t flags = 0; | ||||
| 			off_t offset { 0 }; | ||||
| 			uint8_t flags { 0 }; | ||||
| 		}; | ||||
| 
 | ||||
| 		BAN::ErrorOr<void> validate_fd(int); | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ | |||
| #define SYS_OPEN 6 | ||||
| #define SYS_ALLOC 7 | ||||
| #define SYS_FREE 8 | ||||
| #define SYS_SEEK 9 | ||||
| #define SYS_TELL 10 | ||||
| 
 | ||||
| #include <kernel/Attributes.h> | ||||
| #include <stdint.h> | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ namespace Kernel | |||
| 
 | ||||
| 		BAN::Vector<uint8_t> file_data; | ||||
| 		TRY(file_data.resize(st.st_size)); | ||||
| 		TRY(Process::current().read(fd, file_data.data(), 0, st.st_size)); | ||||
| 		TRY(Process::current().read(fd, file_data.data(), st.st_size)); | ||||
| 
 | ||||
| 		if (file_data.size() < 4) | ||||
| 			return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include <LibELF/Values.h> | ||||
| 
 | ||||
| #include <fcntl.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| namespace Kernel | ||||
| { | ||||
|  | @ -210,6 +211,7 @@ namespace Kernel | |||
| 		auto& open_file_description = m_open_files[fd]; | ||||
| 		open_file_description.inode = file.inode; | ||||
| 		open_file_description.path = BAN::move(file.canonical_path); | ||||
| 		open_file_description.offset = 0; | ||||
| 		open_file_description.flags = flags; | ||||
| 
 | ||||
| 		return fd; | ||||
|  | @ -224,7 +226,7 @@ namespace Kernel | |||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> Process::read(int fd, void* buffer, size_t offset, size_t count) | ||||
| 	BAN::ErrorOr<size_t> Process::read(int fd, void* buffer, size_t count) | ||||
| 	{ | ||||
| 		OpenFileDescription open_fd_copy; | ||||
| 
 | ||||
|  | @ -236,10 +238,19 @@ namespace Kernel | |||
| 
 | ||||
| 		if (!(open_fd_copy.flags & O_RDONLY)) | ||||
| 			return BAN::Error::from_errno(EBADF); | ||||
| 		return TRY(open_fd_copy.inode->read(offset, buffer, count)); | ||||
| 
 | ||||
| 		size_t nread = TRY(open_fd_copy.inode->read(open_fd_copy.offset, buffer, count)); | ||||
| 
 | ||||
| 		{ | ||||
| 			LockGuard _(m_lock); | ||||
| 			MUST(validate_fd(fd)); | ||||
| 			open_file_description(fd).offset += nread; | ||||
| 		} | ||||
| 
 | ||||
| 		return nread; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> Process::write(int fd, const void* buffer, size_t offset, size_t count) | ||||
| 	BAN::ErrorOr<size_t> Process::write(int fd, const void* buffer, size_t count) | ||||
| 	{ | ||||
| 		OpenFileDescription open_fd_copy; | ||||
| 
 | ||||
|  | @ -251,7 +262,54 @@ namespace Kernel | |||
| 
 | ||||
| 		if (!(open_fd_copy.flags & O_WRONLY)) | ||||
| 			return BAN::Error::from_errno(EBADF); | ||||
| 		return TRY(open_fd_copy.inode->write(offset, buffer, count)); | ||||
| 
 | ||||
| 		size_t nwrite = TRY(open_fd_copy.inode->write(open_fd_copy.offset, buffer, count)); | ||||
| 
 | ||||
| 		{ | ||||
| 			LockGuard _(m_lock); | ||||
| 			MUST(validate_fd(fd)); | ||||
| 			open_file_description(fd).offset += nwrite; | ||||
| 		} | ||||
| 
 | ||||
| 		return nwrite; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> Process::seek(int fd, off_t offset, int whence) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		TRY(validate_fd(fd)); | ||||
| 
 | ||||
| 		auto& open_fd = open_file_description(fd); | ||||
| 
 | ||||
| 		off_t new_offset = 0; | ||||
| 
 | ||||
| 		switch (whence) | ||||
| 		{ | ||||
| 			case SEEK_CUR: | ||||
| 				new_offset = open_fd.offset + offset; | ||||
| 				break; | ||||
| 			case SEEK_END: | ||||
| 				new_offset = open_fd.inode->size() - offset; | ||||
| 				break; | ||||
| 			case SEEK_SET: | ||||
| 				new_offset = offset; | ||||
| 				break; | ||||
| 			default: | ||||
| 				return BAN::Error::from_errno(EINVAL); | ||||
| 		} | ||||
| 
 | ||||
| 		if (new_offset < 0) | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		open_fd.offset = new_offset; | ||||
| 
 | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<off_t> Process::tell(int fd) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		TRY(validate_fd(fd)); | ||||
| 		return open_file_description(fd).offset; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> Process::creat(BAN::StringView path, mode_t mode) | ||||
|  |  | |||
|  | @ -22,14 +22,14 @@ namespace Kernel | |||
| 	static void TTY_PRINT(Args&&... args) | ||||
| 	{ | ||||
| 		BAN::String message = BAN::String::formatted(BAN::forward<Args>(args)...); | ||||
| 		MUST(Process::current().write(STDOUT_FILENO, message.data(), 0, message.size())); | ||||
| 		MUST(Process::current().write(STDOUT_FILENO, message.data(), message.size())); | ||||
| 	} | ||||
| 
 | ||||
| 	template<typename... Args> | ||||
| 	static void TTY_PRINTLN(Args&&... args) | ||||
| 	{ | ||||
| 		TTY_PRINT(BAN::forward<Args>(args)...); | ||||
| 		MUST(Process::current().write(STDOUT_FILENO, "\n", 0, 1)); | ||||
| 		MUST(Process::current().write(STDOUT_FILENO, "\n", 1)); | ||||
| 	} | ||||
| 
 | ||||
| 	static auto s_default_prompt = "\\[\e[32m\\]user\\[\e[m\\]:\\[\e[34m\\]\\w\\[\e[m\\]# "sv; | ||||
|  | @ -112,7 +112,7 @@ namespace Kernel | |||
| 
 | ||||
| 	void Shell::run() | ||||
| 	{ | ||||
| 		auto getch = [this] { uint8_t ch; MUST(Process::current().read(STDIN_FILENO, &ch, 0, 1)); return ch; }; | ||||
| 		auto getch = [this] { uint8_t ch; MUST(Process::current().read(STDIN_FILENO, &ch, 1)); return ch; }; | ||||
| 
 | ||||
| 		MUST(m_buffer.push_back(""sv)); | ||||
| 
 | ||||
|  | @ -130,7 +130,7 @@ namespace Kernel | |||
| 					while ((current.back() & 0xC0) == 0x80) | ||||
| 						current.pop_back(); | ||||
| 					current.pop_back(); | ||||
| 					MUST(Process::current().write(STDOUT_FILENO, "\b \b", 0, 3)); | ||||
| 					MUST(Process::current().write(STDOUT_FILENO, "\b \b", 3)); | ||||
| 				} | ||||
| 				continue; | ||||
| 			} | ||||
|  | @ -171,7 +171,7 @@ namespace Kernel | |||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			MUST(Process::current().write(STDOUT_FILENO, &ch, 0, 1)); | ||||
| 			MUST(Process::current().write(STDOUT_FILENO, &ch, 1)); | ||||
| 
 | ||||
| 			if (ch != '\n') | ||||
| 			{ | ||||
|  | @ -556,12 +556,8 @@ argument_done: | |||
| 			BAN::ScopeGuard buffer_guard([buffer] { delete[] buffer; }); | ||||
| 			ASSERT(buffer); | ||||
| 
 | ||||
| 			size_t offset = 0; | ||||
| 			while (size_t n_read = TRY(Process::current().read(fd, buffer, offset, buffer_size))) | ||||
| 			{ | ||||
| 			while (size_t n_read = TRY(Process::current().read(fd, buffer, buffer_size))) | ||||
| 				TTY_PRINT("{}", BAN::StringView(buffer, n_read)); | ||||
| 				offset += n_read; | ||||
| 			} | ||||
| 			TTY_PRINTLN(""); | ||||
| 		} | ||||
| 		else if (arguments.front() == "stat") | ||||
|  | @ -639,7 +635,7 @@ argument_done: | |||
| 
 | ||||
| 				while (true) | ||||
| 				{ | ||||
| 					size_t n_read = TRY(Process::current().read(fd, buffer, total_read, buffer_size)); | ||||
| 					size_t n_read = TRY(Process::current().read(fd, buffer, buffer_size)); | ||||
| 					if (n_read == 0) | ||||
| 						break; | ||||
| 					for (size_t j = 0; j < n_read; j++) | ||||
|  |  | |||
|  | @ -10,17 +10,17 @@ namespace Kernel | |||
| 		Process::current().exit(); | ||||
| 	} | ||||
| 
 | ||||
| 	long sys_read(int fd, void* buffer, size_t offset, size_t size) | ||||
| 	long sys_read(int fd, void* buffer, size_t size) | ||||
| 	{ | ||||
| 		auto res = Process::current().read(fd, buffer, offset, size); | ||||
| 		auto res = Process::current().read(fd, buffer, size); | ||||
| 		if (res.is_error()) | ||||
| 			return -res.error().get_error_code(); | ||||
| 		return res.value(); | ||||
| 	} | ||||
| 
 | ||||
| 	long sys_write(int fd, const void* buffer, size_t offset, size_t size) | ||||
| 	long sys_write(int fd, const void* buffer, size_t size) | ||||
| 	{ | ||||
| 		auto res = Process::current().write(fd, buffer, offset, size); | ||||
| 		auto res = Process::current().write(fd, buffer, size); | ||||
| 		if (res.is_error()) | ||||
| 			return -res.error().get_error_code(); | ||||
| 		return res.value(); | ||||
|  | @ -60,12 +60,32 @@ namespace Kernel | |||
| 		Process::current().free(ptr); | ||||
| 	} | ||||
| 
 | ||||
| 	long sys_seek(int fd, long offset, int whence) | ||||
| 	{ | ||||
| 		auto res = Process::current().seek(fd, offset, whence); | ||||
| 		if (res.is_error()) | ||||
| 			return -res.error().get_error_code(); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	long sys_tell(int fd) | ||||
| 	{ | ||||
| 		auto res = Process::current().tell(fd); | ||||
| 		if (res.is_error()) | ||||
| 			return -res.error().get_error_code(); | ||||
| 		return res.value(); | ||||
| 	} | ||||
| 
 | ||||
| 	extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5) | ||||
| 	{ | ||||
| 		Thread::current().set_in_syscall(true); | ||||
| 
 | ||||
| 		asm volatile("sti"); | ||||
| 
 | ||||
| 		(void)arg1; | ||||
| 		(void)arg2; | ||||
| 		(void)arg3; | ||||
| 		(void)arg4; | ||||
| 		(void)arg5; | ||||
| 
 | ||||
| 		long ret = 0; | ||||
|  | @ -75,10 +95,10 @@ namespace Kernel | |||
| 			sys_exit(); | ||||
| 			break; | ||||
| 		case SYS_READ: | ||||
| 			ret = sys_read((int)arg1, (void*)arg2, (size_t)arg3, (size_t)arg4); | ||||
| 			ret = sys_read((int)arg1, (void*)arg2, (size_t)arg3); | ||||
| 			break; | ||||
| 		case SYS_WRITE: | ||||
| 			ret = sys_write((int)arg1, (const void*)arg2, (size_t)arg3, (size_t)arg4); | ||||
| 			ret = sys_write((int)arg1, (const void*)arg2, (size_t)arg3); | ||||
| 			break; | ||||
| 		case SYS_TERMID: | ||||
| 			sys_termid((char*)arg1); | ||||
|  | @ -95,6 +115,12 @@ namespace Kernel | |||
| 		case SYS_FREE: | ||||
| 			sys_free((void*)arg1); | ||||
| 			break; | ||||
| 		case SYS_SEEK: | ||||
| 			ret = sys_seek((int)arg1, (long)arg2, (int)arg3); | ||||
| 			break; | ||||
| 		case SYS_TELL: | ||||
| 			ret = sys_tell((int)arg1); | ||||
| 			break; | ||||
| 		default: | ||||
| 			Kernel::panic("Unknown syscall {}", syscall); | ||||
| 		} | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ namespace Kernel | |||
| 				while (true) | ||||
| 				{ | ||||
| 					Input::KeyEvent event; | ||||
| 					ASSERT(MUST(Process::current().read(fd, &event, 0, sizeof(event))) == sizeof(event)); | ||||
| 					ASSERT(MUST(Process::current().read(fd, &event, sizeof(event))) == sizeof(event)); | ||||
| 					TTY::current()->on_key(event); | ||||
| 				} | ||||
| 			}, nullptr | ||||
|  |  | |||
|  | @ -10,7 +10,6 @@ | |||
| struct FILE | ||||
| { | ||||
| 	int fd			{ -1 }; | ||||
| 	off_t offset	{ 0 }; | ||||
| 	bool eof		{ false }; | ||||
| 	bool error		{ false }; | ||||
| 
 | ||||
|  | @ -77,7 +76,7 @@ int fflush(FILE* file) | |||
| 	if (file->buffer_index == 0) | ||||
| 		return 0; | ||||
| 	 | ||||
| 	if (syscall(SYS_WRITE, file->fd, file->buffer, file->offset, file->buffer_index) < 0) | ||||
| 	if (syscall(SYS_WRITE, file->fd, file->buffer, file->buffer_index) < 0) | ||||
| 	{ | ||||
| 		file->error = true; | ||||
| 		return EOF; | ||||
|  | @ -93,7 +92,7 @@ int fgetc(FILE* file) | |||
| 		return EOF; | ||||
| 	 | ||||
| 	unsigned char c; | ||||
| 	long ret = syscall(SYS_READ, file->fd, &c, file->offset, 1); | ||||
| 	long ret = syscall(SYS_READ, file->fd, &c, 1); | ||||
| 
 | ||||
| 	if (ret < 0) | ||||
| 	{ | ||||
|  | @ -107,13 +106,15 @@ int fgetc(FILE* file) | |||
| 		return EOF; | ||||
| 	} | ||||
| 
 | ||||
| 	file->offset++; | ||||
| 	return c; | ||||
| } | ||||
| 
 | ||||
| int fgetpos(FILE* file, fpos_t* pos) | ||||
| { | ||||
| 	*pos = file->offset; | ||||
| 	off_t offset = ftello(file); | ||||
| 	if (offset == -1) | ||||
| 		return -1; | ||||
| 	*pos = offset; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -214,7 +215,6 @@ int fprintf(FILE* file, const char* format, ...) | |||
| int fputc(int c, FILE* file) | ||||
| { | ||||
| 	file->buffer[file->buffer_index++] = c; | ||||
| 	file->offset++; | ||||
| 	if (c == '\n' || file->buffer_index == sizeof(file->buffer)) | ||||
| 		if (fflush(file) == EOF) | ||||
| 			return EOF; | ||||
|  | @ -236,15 +236,14 @@ size_t fread(void* buffer, size_t size, size_t nitems, FILE* file) | |||
| { | ||||
| 	if (file->eof || nitems * size == 0) | ||||
| 		return 0; | ||||
| 	long ret = syscall(SYS_READ, file->fd, buffer, file->offset, size * nitems); | ||||
| 	long ret = syscall(SYS_READ, file->fd, buffer, size * nitems); | ||||
| 	if (ret < 0) | ||||
| 	{ | ||||
| 		file->error = true; | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (ret < size * nitems) | ||||
| 	if (ret == 0) | ||||
| 		file->eof = true; | ||||
| 	file->offset += ret; | ||||
| 	return ret / size; | ||||
| } | ||||
| 
 | ||||
|  | @ -261,29 +260,11 @@ int fseek(FILE* file, long offset, int whence) | |||
| 
 | ||||
| int fseeko(FILE* file, off_t offset, int whence) | ||||
| { | ||||
| 	if (offset < 0) | ||||
| 	{ | ||||
| 		errno = EINVAL; | ||||
| 	long ret = syscall(SYS_SEEK, file->fd, offset, whence); | ||||
| 	if (ret < 0) | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (whence == SEEK_CUR && offset <= file->offset) | ||||
| 		file->offset += offset; | ||||
| 	else if (whence == SEEK_SET) | ||||
| 		file->offset = offset; | ||||
| 	else if (whence == SEEK_END) | ||||
| 	{ | ||||
| 		errno = ENOTSUP; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		errno = EINVAL; | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	 | ||||
| 	file->eof = false; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -299,7 +280,10 @@ long ftell(FILE* file) | |||
| 
 | ||||
| off_t ftello(FILE* file) | ||||
| { | ||||
| 	return file->offset; | ||||
| 	long ret = syscall(SYS_TELL, file->fd); | ||||
| 	if (ret < 0) | ||||
| 		return -1; | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| // TODO
 | ||||
|  |  | |||
|  | @ -76,6 +76,20 @@ long syscall(long syscall, ...) | |||
| 			ret = Kernel::syscall(SYS_FREE, (uintptr_t)ptr); | ||||
| 			break; | ||||
| 		} | ||||
| 		case SYS_SEEK: | ||||
| 		{ | ||||
| 			int fd = va_arg(args, int); | ||||
| 			off_t offset = va_arg(args, off_t); | ||||
| 			int whence = va_arg(args, int); | ||||
| 			ret = Kernel::syscall(SYS_SEEK, fd, offset, whence); | ||||
| 			break; | ||||
| 		} | ||||
| 		case SYS_TELL: | ||||
| 		{ | ||||
| 			int fd = va_arg(args, int); | ||||
| 			ret = Kernel::syscall(SYS_TELL, fd); | ||||
| 			break; | ||||
| 		} | ||||
| 		default: | ||||
| 			puts("LibC: Unhandeled syscall"); | ||||
| 			ret = -ENOSYS; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue