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