Compare commits
	
		
			5 Commits
		
	
	
		
			609067cefa
			...
			82978da5e3
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
								 | 
						82978da5e3 | |
| 
							
							
								
								 | 
						80ce9d546a | |
| 
							
							
								
								 | 
						34775633b2 | |
| 
							
							
								
								 | 
						03b5c8e76e | |
| 
							
							
								
								 | 
						766b8cd62e | 
| 
						 | 
					@ -14,6 +14,7 @@ asm_syscall_handler:
 | 
				
			||||||
	pushl %edi
 | 
						pushl %edi
 | 
				
			||||||
	pushl %esi
 | 
						pushl %esi
 | 
				
			||||||
	pushl %ebp
 | 
						pushl %ebp
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# align stack
 | 
						# align stack
 | 
				
			||||||
	movl %esp, %ebp
 | 
						movl %esp, %ebp
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,7 @@
 | 
				
			||||||
isr_stub:
 | 
					isr_stub:
 | 
				
			||||||
	push_userspace
 | 
						push_userspace
 | 
				
			||||||
	load_kernel_segments
 | 
						load_kernel_segments
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	movl %cr0, %eax; pushl %eax
 | 
						movl %cr0, %eax; pushl %eax
 | 
				
			||||||
	movl %cr2, %eax; pushl %eax
 | 
						movl %cr2, %eax; pushl %eax
 | 
				
			||||||
| 
						 | 
					@ -58,6 +59,7 @@ isr_stub:
 | 
				
			||||||
irq_stub:
 | 
					irq_stub:
 | 
				
			||||||
	push_userspace
 | 
						push_userspace
 | 
				
			||||||
	load_kernel_segments
 | 
						load_kernel_segments
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	movl 40(%esp), %eax # interrupt number
 | 
						movl 40(%esp), %eax # interrupt number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,6 +81,7 @@ irq_stub:
 | 
				
			||||||
asm_yield_handler:
 | 
					asm_yield_handler:
 | 
				
			||||||
	# This can only be called from kernel, so no segment saving is needed
 | 
						# This can only be called from kernel, so no segment saving is needed
 | 
				
			||||||
	pushal
 | 
						pushal
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	movl %esp,     %eax # interrupt registers ptr
 | 
						movl %esp,     %eax # interrupt registers ptr
 | 
				
			||||||
	leal 32(%esp), %ebx # interrupt stack ptr
 | 
						leal 32(%esp), %ebx # interrupt stack ptr
 | 
				
			||||||
| 
						 | 
					@ -101,6 +104,7 @@ asm_yield_handler:
 | 
				
			||||||
asm_ipi_handler:
 | 
					asm_ipi_handler:
 | 
				
			||||||
	push_userspace
 | 
						push_userspace
 | 
				
			||||||
	load_kernel_segments
 | 
						load_kernel_segments
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	movl %esp, %ebp
 | 
						movl %esp, %ebp
 | 
				
			||||||
	subl $15, %esp
 | 
						subl $15, %esp
 | 
				
			||||||
| 
						 | 
					@ -118,6 +122,7 @@ asm_ipi_handler:
 | 
				
			||||||
asm_timer_handler:
 | 
					asm_timer_handler:
 | 
				
			||||||
	push_userspace
 | 
						push_userspace
 | 
				
			||||||
	load_kernel_segments
 | 
						load_kernel_segments
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	movl %esp, %ebp
 | 
						movl %esp, %ebp
 | 
				
			||||||
	subl $15, %esp
 | 
						subl $15, %esp
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@ asm_syscall_handler:
 | 
				
			||||||
	pushq %r13
 | 
						pushq %r13
 | 
				
			||||||
	pushq %r14
 | 
						pushq %r14
 | 
				
			||||||
	pushq %r15
 | 
						pushq %r15
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	movq %rsi, %r8
 | 
						movq %rsi, %r8
 | 
				
			||||||
	movq %rdi, %r9
 | 
						movq %rdi, %r9
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
isr_stub:
 | 
					isr_stub:
 | 
				
			||||||
	pushaq
 | 
						pushaq
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
	movq %cr0, %rax; pushq %rax
 | 
						movq %cr0, %rax; pushq %rax
 | 
				
			||||||
	movq %cr2, %rax; pushq %rax
 | 
						movq %cr2, %rax; pushq %rax
 | 
				
			||||||
	movq %cr3, %rax; pushq %rax
 | 
						movq %cr3, %rax; pushq %rax
 | 
				
			||||||
| 
						 | 
					@ -55,6 +55,7 @@ isr_stub:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
irq_stub:
 | 
					irq_stub:
 | 
				
			||||||
	pushaq
 | 
						pushaq
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
	movq 120(%rsp), %rdi	# irq number
 | 
						movq 120(%rsp), %rdi	# irq number
 | 
				
			||||||
	call cpp_irq_handler
 | 
						call cpp_irq_handler
 | 
				
			||||||
	popaq
 | 
						popaq
 | 
				
			||||||
| 
						 | 
					@ -64,6 +65,7 @@ irq_stub:
 | 
				
			||||||
.global asm_yield_handler
 | 
					.global asm_yield_handler
 | 
				
			||||||
asm_yield_handler:
 | 
					asm_yield_handler:
 | 
				
			||||||
	pushaq
 | 
						pushaq
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
	leaq 120(%rsp), %rdi # interrupt stack ptr
 | 
						leaq 120(%rsp), %rdi # interrupt stack ptr
 | 
				
			||||||
	movq     %rsp,  %rsi # interrupt register ptr
 | 
						movq     %rsp,  %rsi # interrupt register ptr
 | 
				
			||||||
	call cpp_yield_handler
 | 
						call cpp_yield_handler
 | 
				
			||||||
| 
						 | 
					@ -73,6 +75,7 @@ asm_yield_handler:
 | 
				
			||||||
.global asm_ipi_handler
 | 
					.global asm_ipi_handler
 | 
				
			||||||
asm_ipi_handler:
 | 
					asm_ipi_handler:
 | 
				
			||||||
	pushaq
 | 
						pushaq
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
	call cpp_ipi_handler
 | 
						call cpp_ipi_handler
 | 
				
			||||||
	popaq
 | 
						popaq
 | 
				
			||||||
	iretq
 | 
						iretq
 | 
				
			||||||
| 
						 | 
					@ -80,6 +83,7 @@ asm_ipi_handler:
 | 
				
			||||||
.global asm_timer_handler
 | 
					.global asm_timer_handler
 | 
				
			||||||
asm_timer_handler:
 | 
					asm_timer_handler:
 | 
				
			||||||
	pushaq
 | 
						pushaq
 | 
				
			||||||
 | 
						cld
 | 
				
			||||||
	call cpp_timer_handler
 | 
						call cpp_timer_handler
 | 
				
			||||||
	popaq
 | 
						popaq
 | 
				
			||||||
	iretq
 | 
						iretq
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -283,16 +283,14 @@ namespace Kernel::ACPI::AML
 | 
				
			||||||
		switch (opcode)
 | 
							switch (opcode)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			case AML::Byte::PackageOp:
 | 
								case AML::Byte::PackageOp:
 | 
				
			||||||
 | 
									if (context.aml_data.empty())
 | 
				
			||||||
 | 
										return BAN::Error::from_errno(ENODATA);
 | 
				
			||||||
				num_elements = context.aml_data[0];
 | 
									num_elements = context.aml_data[0];
 | 
				
			||||||
				context.aml_data = context.aml_data.slice(1);
 | 
									context.aml_data = context.aml_data.slice(1);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case AML::Byte::VarPackageOp:
 | 
								case AML::Byte::VarPackageOp:
 | 
				
			||||||
			{
 | 
									num_elements = TRY(convert_node(TRY(parse_node(context)), ConvInteger, sizeof(uint64_t))).as.integer.value;
 | 
				
			||||||
				auto node = TRY(parse_node(context));
 | 
					 | 
				
			||||||
				node = TRY(convert_node(BAN::move(node), ConvInteger, sizeof(uint64_t)));
 | 
					 | 
				
			||||||
				num_elements = node.as.integer.value;
 | 
					 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				ASSERT_NOT_REACHED();
 | 
									ASSERT_NOT_REACHED();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1868,10 +1866,13 @@ namespace Kernel::ACPI::AML
 | 
				
			||||||
		ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::NotifyOp);
 | 
							ASSERT(static_cast<AML::Byte>(context.aml_data[0]) == AML::Byte::NotifyOp);
 | 
				
			||||||
		context.aml_data = context.aml_data.slice(1);
 | 
							context.aml_data = context.aml_data.slice(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto object = TRY(parse_super_name(context, true));
 | 
							auto [obj_path, obj_ref] = TRY(parse_super_name(context, true));
 | 
				
			||||||
		auto value = TRY(convert_node(TRY(parse_node(context)), ConvInteger, sizeof(uint64_t)));
 | 
							auto value = TRY(convert_node(TRY(parse_node(context)), ConvInteger, sizeof(uint64_t)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dwarnln("TODO: handle notify({}, {})", object.elem2->node, value);
 | 
							if (obj_ref == nullptr)
 | 
				
			||||||
 | 
								return {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							dwarnln("TODO: handle notify({}, {})", obj_ref->node, value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return {};
 | 
							return {};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -692,9 +692,7 @@ namespace Kernel
 | 
				
			||||||
		if (options & ~(WCONTINUED | WNOHANG | WUNTRACED))
 | 
							if (options & ~(WCONTINUED | WNOHANG | WUNTRACED))
 | 
				
			||||||
			return BAN::Error::from_errno(EINVAL);
 | 
								return BAN::Error::from_errno(EINVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// FIXME: support options stopped processes
 | 
							// FIXME: Add WCONTINUED and WUNTRACED when stopped/continued processes are added
 | 
				
			||||||
		if (options & ~(WCONTINUED | WUNTRACED))
 | 
					 | 
				
			||||||
			return BAN::Error::from_errno(ENOTSUP);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const auto pid_matches =
 | 
							const auto pid_matches =
 | 
				
			||||||
			[&](const ChildExitStatus& child)
 | 
								[&](const ChildExitStatus& child)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -270,7 +270,9 @@ namespace Kernel
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (!m_disk_cache.has_value())
 | 
								if (!m_disk_cache.has_value())
 | 
				
			||||||
				return BAN::Error::from_errno(EIO);
 | 
									return BAN::Error::from_errno(EIO);
 | 
				
			||||||
			return m_disk_cache->write_to_cache(lba, buffer, true);
 | 
								for (size_t i = 0; i < sector_count; i++)
 | 
				
			||||||
 | 
									TRY(m_disk_cache->write_to_cache(lba + i, buffer.slice(i * sector_size(), sector_size()), true));
 | 
				
			||||||
 | 
								return {};
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!m_disk_cache.has_value())
 | 
							if (!m_disk_cache.has_value())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,22 +17,20 @@ struct FILE
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
	mode_t mode;
 | 
						mode_t mode;
 | 
				
			||||||
	int buffer_type;
 | 
					 | 
				
			||||||
	bool eof;
 | 
						bool eof;
 | 
				
			||||||
	bool error;
 | 
						bool error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int pid;
 | 
						int pid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int unget_char;
 | 
						unsigned char inline_buffer[BUFSIZ];
 | 
				
			||||||
 | 
						unsigned char* buffer;
 | 
				
			||||||
 | 
						uint32_t buffer_rd_size; // 0 write buffer
 | 
				
			||||||
 | 
						uint32_t buffer_size;
 | 
				
			||||||
 | 
						uint32_t buffer_idx;
 | 
				
			||||||
 | 
						int buffer_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned char inline_buffer_storage[BUFSIZ];
 | 
						unsigned char unget_buffer[12];
 | 
				
			||||||
	unsigned char* write_buffer;
 | 
						uint32_t unget_buf_idx;
 | 
				
			||||||
	uint32_t wr_buf_size;
 | 
					 | 
				
			||||||
	uint32_t wr_buf_index;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	unsigned char read_buffer[BUFSIZ];
 | 
					 | 
				
			||||||
	uint32_t rd_buf_size;
 | 
					 | 
				
			||||||
	uint32_t rd_buf_index;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ScopeLock
 | 
					struct ScopeLock
 | 
				
			||||||
| 
						 | 
					@ -48,7 +46,7 @@ struct ScopeLock
 | 
				
			||||||
		funlockfile(m_file);
 | 
							funlockfile(m_file);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FILE* m_file;
 | 
						FILE* const m_file;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static FILE s_files[FOPEN_MAX];
 | 
					static FILE s_files[FOPEN_MAX];
 | 
				
			||||||
| 
						 | 
					@ -60,18 +58,31 @@ FILE* stddbg = &s_files[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void init_closed_file(FILE* file)
 | 
					static void init_closed_file(FILE* file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	file->fd           = -1;
 | 
						file->fd             = -1;
 | 
				
			||||||
	file->mode         = 0;
 | 
						file->mode           = 0;
 | 
				
			||||||
	file->buffer_type  = _IOLBF;
 | 
						file->eof            = false;
 | 
				
			||||||
	file->eof          = false;
 | 
						file->error          = false;
 | 
				
			||||||
	file->error        = false;
 | 
						file->pid            = -1;
 | 
				
			||||||
	file->pid          = -1;
 | 
						file->buffer         = file->inline_buffer;
 | 
				
			||||||
	file->unget_char   = EOF;
 | 
						file->buffer_size    = sizeof(file->inline_buffer);
 | 
				
			||||||
	file->write_buffer       = file->inline_buffer_storage;
 | 
						file->buffer_idx     = 0;
 | 
				
			||||||
	file->wr_buf_size  = BUFSIZ;
 | 
						file->buffer_type    = _IOFBF;
 | 
				
			||||||
	file->wr_buf_index = 0;
 | 
						file->buffer_rd_size = 0;
 | 
				
			||||||
	file->rd_buf_size  = 0;
 | 
						file->unget_buf_idx  = 0;
 | 
				
			||||||
	file->rd_buf_index = 0;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int drop_read_buffer(FILE* file)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (file->buffer_rd_size == 0)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						ASSERT(file->buffer_idx != 0);
 | 
				
			||||||
 | 
						if (file->buffer_idx == 1)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						if (syscall(SYS_SEEK, file->fd, file->buffer_idx - 1, SEEK_CUR) == -1)
 | 
				
			||||||
 | 
							return EOF;
 | 
				
			||||||
 | 
						file->buffer_rd_size = 0;
 | 
				
			||||||
 | 
						file->buffer_idx = 0;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void _init_stdio()
 | 
					void _init_stdio()
 | 
				
			||||||
| 
						 | 
					@ -79,18 +90,21 @@ void _init_stdio()
 | 
				
			||||||
	for (size_t i = 0; i < FOPEN_MAX; i++)
 | 
						for (size_t i = 0; i < FOPEN_MAX; i++)
 | 
				
			||||||
		init_closed_file(&s_files[i]);
 | 
							init_closed_file(&s_files[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s_files[STDIN_FILENO].fd   = STDIN_FILENO;
 | 
						s_files[STDIN_FILENO].fd          = STDIN_FILENO;
 | 
				
			||||||
	s_files[STDIN_FILENO].mode = O_RDONLY;
 | 
						s_files[STDIN_FILENO].mode        = O_RDONLY;
 | 
				
			||||||
 | 
						s_files[STDIN_FILENO].buffer_type = _IOLBF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s_files[STDOUT_FILENO].fd   = STDOUT_FILENO;
 | 
						s_files[STDOUT_FILENO].fd          = STDOUT_FILENO;
 | 
				
			||||||
	s_files[STDOUT_FILENO].mode = O_WRONLY;
 | 
						s_files[STDOUT_FILENO].mode        = O_WRONLY;
 | 
				
			||||||
 | 
						s_files[STDOUT_FILENO].buffer_type = _IOLBF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s_files[STDERR_FILENO].fd   = STDERR_FILENO;
 | 
						s_files[STDERR_FILENO].fd          = STDERR_FILENO;
 | 
				
			||||||
	s_files[STDERR_FILENO].mode = O_WRONLY;
 | 
						s_files[STDERR_FILENO].mode        = O_WRONLY;
 | 
				
			||||||
	s_files[STDERR_FILENO].buffer_type = _IONBF;
 | 
						s_files[STDERR_FILENO].buffer_type = _IONBF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s_files[STDDBG_FILENO].fd   = STDDBG_FILENO;
 | 
						s_files[STDDBG_FILENO].fd          = STDDBG_FILENO;
 | 
				
			||||||
	s_files[STDDBG_FILENO].mode = O_WRONLY;
 | 
						s_files[STDDBG_FILENO].mode        = O_WRONLY;
 | 
				
			||||||
 | 
						s_files[STDDBG_FILENO].buffer_type = _IOLBF;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void clearerr(FILE* file)
 | 
					void clearerr(FILE* file)
 | 
				
			||||||
| 
						 | 
					@ -120,10 +134,12 @@ int dprintf(int fildes, const char* __restrict format, ...)
 | 
				
			||||||
int fclose(FILE* file)
 | 
					int fclose(FILE* file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ScopeLock _(file);
 | 
						ScopeLock _(file);
 | 
				
			||||||
	(void)fflush(file);
 | 
						if (fflush(file) == EOF)
 | 
				
			||||||
	int ret = (close(file->fd) == -1) ? EOF : 0;
 | 
							return EOF;
 | 
				
			||||||
 | 
						if (close(file->fd) == -1)
 | 
				
			||||||
 | 
							return EOF;
 | 
				
			||||||
	init_closed_file(file);
 | 
						init_closed_file(file);
 | 
				
			||||||
	return ret;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static mode_t parse_mode_string(const char* mode_str)
 | 
					static mode_t parse_mode_string(const char* mode_str)
 | 
				
			||||||
| 
						 | 
					@ -162,9 +178,9 @@ FILE* fdopen(int fd, const char* mode_str)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		s_files[i].fd = fd;
 | 
							s_files[i].fd = fd;
 | 
				
			||||||
		s_files[i].mode = mode & O_ACCMODE;
 | 
							s_files[i].mode = mode & O_ACCMODE;
 | 
				
			||||||
		ASSERT(s_files[i].write_buffer == s_files[i].inline_buffer_storage);
 | 
							ASSERT(s_files[i].buffer == s_files[i].inline_buffer);
 | 
				
			||||||
		ASSERT(s_files[i].wr_buf_size == BUFSIZ);
 | 
							ASSERT(s_files[i].buffer_size == BUFSIZ);
 | 
				
			||||||
		ASSERT(s_files[i].rd_buf_size == 0);
 | 
							ASSERT(s_files[i].buffer_idx == 0);
 | 
				
			||||||
		return &s_files[i];
 | 
							return &s_files[i];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -186,27 +202,41 @@ int fflush(FILE* file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (file == nullptr)
 | 
						if (file == nullptr)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							int ret = 0;
 | 
				
			||||||
		for (int i = 0; i < FOPEN_MAX; i++)
 | 
							for (int i = 0; i < FOPEN_MAX; i++)
 | 
				
			||||||
			if (s_files[i].fd != -1)
 | 
								if (s_files[i].fd != -1)
 | 
				
			||||||
				if (int ret = fflush(&s_files[i]); ret != 0)
 | 
									if (int err = fflush(&s_files[i]); err != 0)
 | 
				
			||||||
					return ret;
 | 
										ret = err;
 | 
				
			||||||
		return 0;
 | 
							return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ScopeLock _(file);
 | 
						ScopeLock _(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	file->unget_char = EOF;
 | 
						if (file->fd == -1)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (file->wr_buf_index == 0)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (syscall(SYS_WRITE, file->fd, file->write_buffer, file->wr_buf_index) < 0)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		file->error = true;
 | 
							errno = EBADF;
 | 
				
			||||||
		return EOF;
 | 
							return EOF;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	file->wr_buf_index = 0;
 | 
						file->unget_buf_idx = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (file->buffer_rd_size)
 | 
				
			||||||
 | 
							return drop_read_buffer(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t written = 0;
 | 
				
			||||||
 | 
						while (written < file->buffer_idx)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ssize_t nwrite = write(file->fd, file->buffer + written, file->buffer_idx - written);
 | 
				
			||||||
 | 
							if (nwrite < 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								file->error = true;
 | 
				
			||||||
 | 
								return EOF;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							written += nwrite;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file->buffer_idx = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -254,8 +284,11 @@ char* fgets(char* str, int size, FILE* file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int fileno(FILE* fp)
 | 
					int fileno(FILE* fp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (fp == nullptr)
 | 
						if (fp->fd == -1)
 | 
				
			||||||
		return EBADF;
 | 
						{
 | 
				
			||||||
 | 
							errno = EBADF;
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return fp->fd;
 | 
						return fp->fd;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -285,9 +318,8 @@ FILE* fopen(const char* pathname, const char* mode_str)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		s_files[i].fd = fd;
 | 
							s_files[i].fd = fd;
 | 
				
			||||||
		s_files[i].mode = mode & O_ACCMODE;
 | 
							s_files[i].mode = mode & O_ACCMODE;
 | 
				
			||||||
		ASSERT(s_files[i].write_buffer == s_files[i].inline_buffer_storage);
 | 
							ASSERT(s_files[i].buffer == s_files[i].inline_buffer);
 | 
				
			||||||
		ASSERT(s_files[i].wr_buf_size == BUFSIZ);
 | 
							ASSERT(s_files[i].buffer_size == BUFSIZ);
 | 
				
			||||||
		ASSERT(s_files[i].rd_buf_size == 0);
 | 
					 | 
				
			||||||
		return &s_files[i];
 | 
							return &s_files[i];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -334,12 +366,13 @@ size_t fread(void* buffer, size_t size, size_t nitems, FILE* file)
 | 
				
			||||||
	if (target == 0)
 | 
						if (target == 0)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned char* ubuffer = static_cast<unsigned char*>(buffer);
 | 
				
			||||||
	while (nread < target)
 | 
						while (nread < target)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int ch = getc_unlocked(file);
 | 
							int ch = getc_unlocked(file);
 | 
				
			||||||
		if (ch == EOF)
 | 
							if (ch == EOF)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		static_cast<unsigned char*>(buffer)[nread++] = ch;
 | 
							ubuffer[nread++] = ch;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nread / size;
 | 
						return nread / size;
 | 
				
			||||||
| 
						 | 
					@ -395,13 +428,12 @@ int fseek(FILE* file, long offset, int whence)
 | 
				
			||||||
int fseeko(FILE* file, off_t offset, int whence)
 | 
					int fseeko(FILE* file, off_t offset, int whence)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ScopeLock _(file);
 | 
						ScopeLock _(file);
 | 
				
			||||||
	file->unget_char = EOF;
 | 
						if (fflush(file) == EOF)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
	long ret = syscall(SYS_SEEK, file->fd, offset, whence);
 | 
						long ret = syscall(SYS_SEEK, file->fd, offset, whence);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	file->eof = false;
 | 
						file->eof = false;
 | 
				
			||||||
	file->rd_buf_size = 0;
 | 
					 | 
				
			||||||
	file->rd_buf_index = 0;
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -418,10 +450,12 @@ long ftell(FILE* file)
 | 
				
			||||||
off_t ftello(FILE* file)
 | 
					off_t ftello(FILE* file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ScopeLock _(file);
 | 
						ScopeLock _(file);
 | 
				
			||||||
 | 
						if (fflush(file) == EOF)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
	long ret = syscall(SYS_TELL, file->fd);
 | 
						long ret = syscall(SYS_TELL, file->fd);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	return ret - (file->unget_char != EOF) - (file->rd_buf_size - file->rd_buf_index);
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ftrylockfile(FILE*)
 | 
					int ftrylockfile(FILE*)
 | 
				
			||||||
| 
						 | 
					@ -458,38 +492,65 @@ int getchar(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int getc_unlocked(FILE* file)
 | 
					int getc_unlocked(FILE* file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (file->fd == -1 || !(file->mode & O_RDONLY))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							errno = EBADF;
 | 
				
			||||||
 | 
							return EOF;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (file->eof)
 | 
						if (file->eof)
 | 
				
			||||||
		return EOF;
 | 
							return EOF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (file->unget_char != EOF)
 | 
						// read characters from ungetc
 | 
				
			||||||
 | 
						if (file->unget_buf_idx)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int ch = file->unget_char;
 | 
							file->unget_buf_idx--;
 | 
				
			||||||
		file->unget_char = EOF;
 | 
							unsigned char ch = file->unget_buffer[file->unget_buf_idx];
 | 
				
			||||||
		return (unsigned char)ch;
 | 
							if (fseeko(file, 1, SEEK_CUR) == -1)
 | 
				
			||||||
 | 
								return EOF;
 | 
				
			||||||
 | 
							return ch;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (file->rd_buf_index < file->rd_buf_size)
 | 
						// read from unbuffered file
 | 
				
			||||||
		return file->read_buffer[file->rd_buf_index++];
 | 
						if (file->buffer_type == _IONBF)
 | 
				
			||||||
	file->rd_buf_size = 0;
 | 
					 | 
				
			||||||
	file->rd_buf_index = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ssize_t nread = read(file->fd, file->read_buffer, sizeof(file->read_buffer));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (nread < 0)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		file->error = true;
 | 
							unsigned char ch;
 | 
				
			||||||
 | 
							if (ssize_t nread = read(file->fd, &ch, 1); nread <= 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								((nread == 0) ? file->eof : file->error) = true;
 | 
				
			||||||
 | 
								return EOF;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return ch;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// flush writable data
 | 
				
			||||||
 | 
						if (file->buffer_rd_size == 0 && file->buffer_idx)
 | 
				
			||||||
 | 
							if (fflush(file) == EOF)
 | 
				
			||||||
 | 
								return EOF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// buffered read
 | 
				
			||||||
 | 
						if (file->buffer_idx < file->buffer_rd_size)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							unsigned char ch = file->buffer[file->buffer_idx];
 | 
				
			||||||
 | 
							file->buffer_idx++;
 | 
				
			||||||
 | 
							return ch;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (drop_read_buffer(file) == EOF)
 | 
				
			||||||
 | 
							return EOF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// read into buffer
 | 
				
			||||||
 | 
						ssize_t nread = read(file->fd, file->buffer, file->buffer_size);
 | 
				
			||||||
 | 
						if (nread <= 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							((nread == 0) ? file->eof : file->error) = true;
 | 
				
			||||||
		return EOF;
 | 
							return EOF;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (fseeko(file, 1 - nread, SEEK_CUR) == -1)
 | 
				
			||||||
	if (nread == 0)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		file->eof = true;
 | 
					 | 
				
			||||||
		return EOF;
 | 
							return EOF;
 | 
				
			||||||
	}
 | 
						file->buffer_rd_size = nread;
 | 
				
			||||||
 | 
						file->buffer_idx = 1;
 | 
				
			||||||
	file->rd_buf_size = nread;
 | 
						return file->buffer[0];
 | 
				
			||||||
	file->rd_buf_index = 1;
 | 
					 | 
				
			||||||
	return file->read_buffer[0];
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int getchar_unlocked(void)
 | 
					int getchar_unlocked(void)
 | 
				
			||||||
| 
						 | 
					@ -502,11 +563,11 @@ char* gets(char* buffer)
 | 
				
			||||||
	if (stdin->eof)
 | 
						if (stdin->eof)
 | 
				
			||||||
		return nullptr;
 | 
							return nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned char* ubuffer = (unsigned char*)buffer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int first = fgetc(stdin);
 | 
						int first = fgetc(stdin);
 | 
				
			||||||
	if (first == EOF)
 | 
						if (first == EOF)
 | 
				
			||||||
		return nullptr;
 | 
							return nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned char* ubuffer = reinterpret_cast<unsigned char*>(buffer);
 | 
				
			||||||
	*ubuffer++ = first;
 | 
						*ubuffer++ = first;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (;;)
 | 
						for (;;)
 | 
				
			||||||
| 
						 | 
					@ -602,9 +663,8 @@ FILE* popen(const char* command, const char* mode_str)
 | 
				
			||||||
		s_files[i].fd = read ? fds[0] : fds[1];
 | 
							s_files[i].fd = read ? fds[0] : fds[1];
 | 
				
			||||||
		s_files[i].mode = (unsigned)(read ? O_RDONLY : O_WRONLY);
 | 
							s_files[i].mode = (unsigned)(read ? O_RDONLY : O_WRONLY);
 | 
				
			||||||
		s_files[i].pid = pid;
 | 
							s_files[i].pid = pid;
 | 
				
			||||||
		ASSERT(s_files[i].write_buffer == s_files[i].inline_buffer_storage);
 | 
							ASSERT(s_files[i].buffer == s_files[i].inline_buffer);
 | 
				
			||||||
		ASSERT(s_files[i].wr_buf_size == BUFSIZ);
 | 
							ASSERT(s_files[i].buffer_size == BUFSIZ);
 | 
				
			||||||
		ASSERT(s_files[i].rd_buf_size == 0);
 | 
					 | 
				
			||||||
		return &s_files[i];
 | 
							return &s_files[i];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -633,8 +693,29 @@ int putchar(int c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int putc_unlocked(int c, FILE* file)
 | 
					int putc_unlocked(int c, FILE* file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	file->write_buffer[file->wr_buf_index++] = c;
 | 
						if (file->fd == -1 || !(file->mode & O_WRONLY))
 | 
				
			||||||
	if (file->buffer_type == _IONBF || (file->buffer_type == _IOLBF && c == '\n') || file->wr_buf_index >= file->wr_buf_size)
 | 
						{
 | 
				
			||||||
 | 
							errno = EBADF;
 | 
				
			||||||
 | 
							return EOF;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file->unget_buf_idx = 0;
 | 
				
			||||||
 | 
						if (file->buffer_rd_size && drop_read_buffer(file) == EOF)
 | 
				
			||||||
 | 
							return EOF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (file->buffer_type == _IONBF)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ssize_t nwrite = write(file->fd, &c, 1);
 | 
				
			||||||
 | 
							if (nwrite == -1)
 | 
				
			||||||
 | 
								file->error = true;
 | 
				
			||||||
 | 
							if (nwrite <= 0)
 | 
				
			||||||
 | 
								return EOF;
 | 
				
			||||||
 | 
							return (unsigned char)c;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file->buffer[file->buffer_idx] = c;
 | 
				
			||||||
 | 
						file->buffer_idx++;
 | 
				
			||||||
 | 
						if ((file->buffer_type == _IOLBF && c == '\n') || file->buffer_idx >= file->buffer_size)
 | 
				
			||||||
		if (fflush(file) == EOF)
 | 
							if (fflush(file) == EOF)
 | 
				
			||||||
			return EOF;
 | 
								return EOF;
 | 
				
			||||||
	return (unsigned char)c;
 | 
						return (unsigned char)c;
 | 
				
			||||||
| 
						 | 
					@ -746,15 +827,21 @@ int setvbuf(FILE* file, char* buffer, int type, size_t size)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buffer == nullptr)
 | 
						if (size == 0)
 | 
				
			||||||
 | 
							type = _IONBF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned char* ubuffer = reinterpret_cast<unsigned char*>(buffer);
 | 
				
			||||||
 | 
						if (ubuffer == nullptr)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		buffer = reinterpret_cast<char*>(file->inline_buffer_storage);
 | 
							ubuffer = file->inline_buffer;
 | 
				
			||||||
		size = BAN::Math::min<size_t>(size, BUFSIZ);
 | 
							size = BAN::Math::min<size_t>(size, sizeof(file->inline_buffer));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ASSERT(file->buffer_rd_size == 0);
 | 
				
			||||||
 | 
						ASSERT(file->buffer_idx == 0);
 | 
				
			||||||
	file->buffer_type = type;
 | 
						file->buffer_type = type;
 | 
				
			||||||
	file->wr_buf_size = size;
 | 
						file->buffer_size = size;
 | 
				
			||||||
	file->write_buffer = reinterpret_cast<unsigned char*>(buffer);
 | 
						file->buffer      = ubuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -789,8 +876,10 @@ int sscanf(const char* s, const char* format, ...)
 | 
				
			||||||
// TODO
 | 
					// TODO
 | 
				
			||||||
char* tempnam(const char*, const char*);
 | 
					char* tempnam(const char*, const char*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO
 | 
					FILE* tmpfile(void)
 | 
				
			||||||
FILE* tmpfile(void);
 | 
					{
 | 
				
			||||||
 | 
						ASSERT_NOT_REACHED();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char* tmpnam(char* storage)
 | 
					char* tmpnam(char* storage)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -810,11 +899,23 @@ char* tmpnam(char* storage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ungetc_unlocked(int c, FILE* stream)
 | 
					int ungetc_unlocked(int c, FILE* stream)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (c == EOF)
 | 
						if (stream->fd == -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							errno = EBADF;
 | 
				
			||||||
		return EOF;
 | 
							return EOF;
 | 
				
			||||||
	if (stream->unget_char != EOF)
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (c == EOF || stream->unget_buf_idx >= sizeof(stream->unget_buffer))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							errno = EINVAL;
 | 
				
			||||||
		return EOF;
 | 
							return EOF;
 | 
				
			||||||
	stream->unget_char = c;
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fseeko(stream, -1, SEEK_CUR) == -1)
 | 
				
			||||||
 | 
							return EOF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stream->unget_buffer[stream->unget_buf_idx] = c;
 | 
				
			||||||
 | 
						stream->unget_buf_idx++;
 | 
				
			||||||
	stream->eof = false;
 | 
						stream->eof = false;
 | 
				
			||||||
	return (unsigned char)c;
 | 
						return (unsigned char)c;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -961,8 +1062,3 @@ int vsscanf(const char* s, const char* format, va_list arguments)
 | 
				
			||||||
		}, &s
 | 
							}, &s
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
FILE* tmpfile(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ASSERT_NOT_REACHED();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue