diff --git a/kernel/console/psf.c b/kernel/console/psf.c index 6aa1a913..fea8d635 100644 --- a/kernel/console/psf.c +++ b/kernel/console/psf.c @@ -10,7 +10,8 @@ static struct font* load_psf1(file_description* desc) { struct psf1_header header; - if (file_description_read(desc, &header, sizeof(struct psf1_header)) != + if (file_description_read_to_end(desc, &header, + sizeof(struct psf1_header)) != sizeof(struct psf1_header)) { return ERR_PTR(-EINVAL); } @@ -31,7 +32,7 @@ static struct font* load_psf1(file_description* desc) { kfree(font); return ERR_PTR(-ENOMEM); } - if ((size_t)file_description_read(desc, font->glyphs, buf_size) != + if ((size_t)file_description_read_to_end(desc, font->glyphs, buf_size) != buf_size) { kfree(font->glyphs); kfree(font); @@ -43,7 +44,7 @@ static struct font* load_psf1(file_description* desc) { for (size_t i = 0; i < num_glyphs; ++i) { for (;;) { uint16_t uc; - if (file_description_read(desc, &uc, sizeof(uint16_t)) != + if (file_description_read_to_end(desc, &uc, sizeof(uint16_t)) != sizeof(uint16_t)) { kfree(font->glyphs); kfree(font); @@ -65,7 +66,8 @@ static struct font* load_psf1(file_description* desc) { static struct font* load_psf2(file_description* desc) { struct psf2_header header; - if (file_description_read(desc, &header, sizeof(struct psf2_header)) != + if (file_description_read_to_end(desc, &header, + sizeof(struct psf2_header)) != sizeof(struct psf2_header)) return ERR_PTR(-EINVAL); if (header.magic != PSF2_MAGIC || header.version != 0 || @@ -91,7 +93,7 @@ static struct font* load_psf2(file_description* desc) { kfree(font); return ERR_PTR(-ENOMEM); } - if ((size_t)file_description_read(desc, font->glyphs, buf_size) != + if ((size_t)file_description_read_to_end(desc, font->glyphs, buf_size) != buf_size) { kfree(font->glyphs); kfree(font); @@ -103,7 +105,7 @@ static struct font* load_psf2(file_description* desc) { for (size_t i = 0; i < header.numglyph; ++i) { for (;;) { uint8_t uc; - if (file_description_read(desc, &uc, sizeof(uint8_t)) != + if (file_description_read_to_end(desc, &uc, sizeof(uint8_t)) != sizeof(uint8_t)) { kfree(font->glyphs); kfree(font); diff --git a/kernel/exec.c b/kernel/exec.c index c779ff98..901be676 100644 --- a/kernel/exec.c +++ b/kernel/exec.c @@ -191,7 +191,8 @@ static int execve(const char* pathname, string_vec* argv, string_vec* envp) { ret = -ENOMEM; goto fail_exe; } - ssize_t nread = file_description_read(desc, exe_buf, stat.st_size); + + ssize_t nread = file_description_read_to_end(desc, exe_buf, stat.st_size); file_description_close(desc); desc = NULL; if (IS_ERR(nread)) { diff --git a/kernel/fs/fs.c b/kernel/fs/fs.c index 95170b65..aa78b82f 100644 --- a/kernel/fs/fs.c +++ b/kernel/fs/fs.c @@ -176,6 +176,21 @@ ssize_t file_description_read(file_description* desc, void* buffer, return inode->fops->read(desc, buffer, count); } +NODISCARD ssize_t file_description_read_to_end(file_description* desc, + void* buffer, size_t count) { + size_t cursor = 0; + while (cursor < count) { + ssize_t nread = file_description_read( + desc, (unsigned char*)buffer + cursor, count - cursor); + if (IS_ERR(nread)) + return nread; + if (nread == 0) + break; + cursor += nread; + } + return cursor; +} + ssize_t file_description_write(file_description* desc, const void* buffer, size_t count) { struct inode* inode = desc->inode; @@ -188,6 +203,21 @@ ssize_t file_description_write(file_description* desc, const void* buffer, return inode->fops->write(desc, buffer, count); } +ssize_t file_description_write_all(file_description* desc, const void* buffer, + size_t count) { + size_t cursor = 0; + while (cursor < count) { + ssize_t nwritten = file_description_write( + desc, (unsigned char*)buffer + cursor, count - cursor); + if (IS_ERR(nwritten)) + return nwritten; + if (nwritten == 0) + break; + cursor += nwritten; + } + return cursor; +} + void* file_description_mmap(file_description* desc, size_t length, off_t offset, int flags) { struct inode* inode = desc->inode; diff --git a/kernel/fs/fs.h b/kernel/fs/fs.h index 4454515a..15cd3f3d 100644 --- a/kernel/fs/fs.h +++ b/kernel/fs/fs.h @@ -84,8 +84,12 @@ NODISCARD int inode_stat(struct inode*, struct stat* buf); int file_description_close(file_description*); NODISCARD ssize_t file_description_read(file_description*, void* buffer, size_t count); +NODISCARD ssize_t file_description_read_to_end(file_description*, void* buffer, + size_t count); NODISCARD ssize_t file_description_write(file_description*, const void* buffer, size_t count); +NODISCARD ssize_t file_description_write_all(file_description*, + const void* buffer, size_t count); NODISCARD void* file_description_mmap(file_description*, size_t length, off_t offset, int flags); NODISCARD int file_description_truncate(file_description*, off_t length); diff --git a/kernel/fs/initrd.c b/kernel/fs/initrd.c index bd0cf887..822fac8a 100644 --- a/kernel/fs/initrd.c +++ b/kernel/fs/initrd.c @@ -72,12 +72,10 @@ void initrd_populate_root_fs(uintptr_t phys_addr, size_t size) { const unsigned char* file_content = (const unsigned char*)(cursor + sizeof(struct cpio_odc_header) + name_size); - for (size_t count = 0; count < file_size;) { - ssize_t nwritten = file_description_write( - desc, file_content + count, file_size - count); - ASSERT_OK(nwritten); - count += nwritten; - } + ssize_t nwritten = + file_description_write_all(desc, file_content, file_size); + ASSERT_OK(nwritten); + ASSERT((size_t)nwritten == file_size); ASSERT_OK(file_description_close(desc)); } diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index 03c07ff3..e384dbbe 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -174,19 +174,11 @@ static struct path* follow_symlink(const struct path* parent, return ERR_CAST(desc); char target[SYMLINK_MAX]; - size_t target_len = 0; - while (target_len < SYMLINK_MAX) { - ssize_t nread = file_description_read(desc, target + target_len, - SYMLINK_MAX - target_len); - if (IS_ERR(nread)) { - file_description_close(desc); - return ERR_PTR(nread); - } - if (nread == 0) - break; - target_len += nread; - } + ssize_t target_len = + file_description_read_to_end(desc, target, SYMLINK_MAX); file_description_close(desc); + if (IS_ERR(target_len)) + return ERR_PTR(target_len); char* pathname = kmalloc(target_len + 1 + strlen(rest_pathname) + 1); if (!pathname) diff --git a/kernel/syscall/fs.c b/kernel/syscall/fs.c index d2d284b8..b5541e0d 100644 --- a/kernel/syscall/fs.c +++ b/kernel/syscall/fs.c @@ -79,22 +79,14 @@ ssize_t sys_readlink(const char* user_pathname, char* user_buf, size_t bufsiz) { bufsiz = MIN(bufsiz, SYMLINK_MAX); char buf[SYMLINK_MAX]; - size_t buf_len = 0; - while (buf_len < bufsiz) { - ssize_t nread = file_description_read(desc, buf + buf_len, bufsiz); - if (IS_ERR(nread)) { - file_description_close(desc); - return nread; - } - if (nread == 0) - break; - buf_len += nread; - } + ssize_t nread = file_description_read_to_end(desc, buf, bufsiz); file_description_close(desc); + if (IS_ERR(nread)) + return nread; - if (!copy_to_user(user_buf, buf, buf_len)) + if (!copy_to_user(user_buf, buf, nread)) return -EFAULT; - return buf_len; + return nread; } ssize_t sys_write(int fd, const void* user_buf, size_t count) { @@ -169,7 +161,7 @@ int sys_symlink(const char* user_target, const char* user_linkpath) { file_description* desc = inode_open(inode, O_WRONLY, 0); if (IS_ERR(desc)) return PTR_ERR(desc); - rc = file_description_write(desc, target, target_len); + rc = file_description_write_all(desc, target, target_len); file_description_close(desc); inode_unref(inode);