Compare commits

...

2 Commits

Author SHA1 Message Date
Bananymous 25a47f0df3 LibC: Implement ungetc()
I didn't really test this, but I think this implementation does what it
needs to :)
2024-08-12 19:14:55 +03:00
Bananymous 39be57424c Kernel: Fix SYS_SEEK with SEEK_END
I was subtracting the offset from file end when I should have added it.
2024-08-12 19:13:27 +03:00
2 changed files with 36 additions and 11 deletions

View File

@ -217,23 +217,23 @@ namespace Kernel
{ {
TRY(validate_fd(fd)); TRY(validate_fd(fd));
off_t new_offset = 0; off_t base_offset;
switch (whence) switch (whence)
{ {
case SEEK_SET:
base_offset = 0;
break;
case SEEK_CUR: case SEEK_CUR:
new_offset = m_open_files[fd]->offset + offset; base_offset = m_open_files[fd]->offset;
break; break;
case SEEK_END: case SEEK_END:
new_offset = m_open_files[fd]->inode->size() - offset; base_offset = m_open_files[fd]->inode->size();
break;
case SEEK_SET:
new_offset = offset;
break; break;
default: default:
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
} }
const off_t new_offset = base_offset + offset;
if (new_offset < 0) if (new_offset < 0)
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);

View File

@ -23,6 +23,8 @@ struct FILE
int pid { -1 }; int pid { -1 };
int unget_char { EOF };
unsigned char inline_buffer_storage[BUFSIZ] {}; unsigned char inline_buffer_storage[BUFSIZ] {};
unsigned char* buffer = inline_buffer_storage; unsigned char* buffer = inline_buffer_storage;
uint32_t buffer_size = BUFSIZ; uint32_t buffer_size = BUFSIZ;
@ -149,6 +151,8 @@ int fflush(FILE* file)
ScopeLock _(file); ScopeLock _(file);
file->unget_char = EOF;
if (file->buffer_index == 0) if (file->buffer_index == 0)
return 0; return 0;
@ -282,9 +286,16 @@ size_t fread(void* buffer, size_t size, size_t nitems, FILE* file)
size_t target = size * nitems; size_t target = size * nitems;
size_t nread = 0; size_t nread = 0;
if (file->unget_char != EOF)
{
*static_cast<unsigned char*>(buffer) = file->unget_char;
file->unget_char = EOF;
nread++;
}
while (nread < target) while (nread < target)
{ {
ssize_t ret = syscall(SYS_READ, file->fd, (uint8_t*)buffer + nread, target - nread); ssize_t ret = syscall(SYS_READ, file->fd, static_cast<unsigned char*>(buffer) + nread, target - nread);
if (ret < 0) if (ret < 0)
file->error = true; file->error = true;
@ -350,6 +361,7 @@ 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;
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;
@ -373,7 +385,7 @@ off_t ftello(FILE* file)
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; return ret - (file->unget_char != EOF);
} }
int ftrylockfile(FILE*) int ftrylockfile(FILE*)
@ -413,6 +425,13 @@ int getc_unlocked(FILE* file)
if (file->eof) if (file->eof)
return EOF; return EOF;
if (file->unget_char != EOF)
{
int ch = file->unget_char;
file->unget_char = EOF;
return (unsigned char)ch;
}
unsigned char c; unsigned char c;
long ret = syscall(SYS_READ, file->fd, &c, 1); long ret = syscall(SYS_READ, file->fd, &c, 1);
@ -749,8 +768,14 @@ char* tmpnam(char* storage)
int ungetc(int c, FILE* stream) int ungetc(int c, FILE* stream)
{ {
dwarnln("FIXME: ungetc({}, {})", c, stream); if (c == EOF)
ASSERT_NOT_REACHED(); return EOF;
ScopeLock _(stream);
if (stream->unget_char != EOF)
return EOF;
stream->unget_char = c;
stream->eof = false;
return (unsigned char)c;
} }
int vfprintf(FILE* file, const char* format, va_list arguments) int vfprintf(FILE* file, const char* format, va_list arguments)