From: David Given Date: Thu, 21 Jan 2016 20:37:35 +0000 (+0100) Subject: Move struct _uzistat into its own structure, shared between the kernel and X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=9ad0ca8733067d80828d8f235ef732c3b0caceda;p=FUZIX.git Move struct _uzistat into its own structure, shared between the kernel and userspace. stcpy() now copies this safely (avoiding compiler packing gotchas). --- diff --git a/Kernel/include/kernel.h b/Kernel/include/kernel.h index 84af6d41..7804828d 100644 --- a/Kernel/include/kernel.h +++ b/Kernel/include/kernel.h @@ -174,21 +174,6 @@ typedef struct dinode { blkno_t i_addr[20]; } dinode; /* Exactly 64 bytes long! */ -struct stat /* Really only used by libc */ -{ - int16_t st_dev; - uint16_t st_ino; - uint16_t st_mode; - uint16_t st_nlink; - uint16_t st_uid; - uint16_t st_gid; - uint16_t st_rdev; - off_t st_size; - uint32_t st_atime; /* Break in 2038 */ - uint32_t st_mtime; - uint32_t st_ctime; -}; - /* We use the Linux one for compatibility. There's no real Unix 'standard' for such things */ diff --git a/Kernel/include/userstructs.h b/Kernel/include/userstructs.h new file mode 100644 index 00000000..6401de97 --- /dev/null +++ b/Kernel/include/userstructs.h @@ -0,0 +1,29 @@ +#ifndef _USERSTRUCTURES_H +#define _USERSTRUCTURES_H + +/* Structures shared between kernel and user space. + * + * Only use explicitly sized types here --- otherwise differing compiler + * flags between kernel code and user code can pack them differently. + */ + +struct _uzistat +{ + /* Do not change this without also changing stcpy() in syscall_fs.c. */ + + int16_t st_dev; + uint16_t st_ino; + uint16_t st_mode; + uint16_t st_nlink; + uint16_t st_uid; + uint16_t st_gid; + uint16_t st_rdev; + uint32_t st_size; + uint32_t st_atime; /* Breaks in 2038 */ + uint32_t st_mtime; + uint32_t st_ctime; + uint32_t st_timeh; /* Time high bytes */ +}; + +#endif + diff --git a/Kernel/syscall_fs.c b/Kernel/syscall_fs.c index 2c8056a7..c4dd91a7 100644 --- a/Kernel/syscall_fs.c +++ b/Kernel/syscall_fs.c @@ -2,6 +2,7 @@ #include #include #include +#include void updoff(void) { @@ -134,9 +135,17 @@ arg_t _fstat(void) /* Utility for stat and fstat */ int stcpy(inoptr ino, char *buf) { - int err = uput((char *) &(ino->c_dev), buf, 12); - err |= uput((char *) &(ino->c_node.i_addr[0]), buf + 12, 2); - err |= uput((char *) &(ino->c_node.i_size), buf + 14, 16); + /* Copying the structure a member at a time is too expensive. Instead we + * copy sequential runs of identical types (the only members which the + * compiler guarantees are next to each other). */ + + uint32_t zero = 0; + struct _uzistat* st = (struct _uzistat*) buf; + int err = uput(&ino->c_dev, &st->st_dev, 2 * sizeof(uint16_t)); + err |= uput(&ino->c_node.i_mode, &st->st_mode, 4 * sizeof(uint16_t)); + err |= uput(&ino->c_node.i_addr[0], &st->st_rdev, 1 * sizeof(uint16_t)); + err |= uput(&ino->c_node.i_size, &st->st_size, 4 * sizeof(uint32_t)); + err |= uput(&zero, &st->st_timeh, 1 * sizeof(uint32_t)); return err; } diff --git a/Library/include/syscalls.h b/Library/include/syscalls.h index 3adde780..96f56a8e 100644 --- a/Library/include/syscalls.h +++ b/Library/include/syscalls.h @@ -10,25 +10,12 @@ #endif #include +/* TODO: make this less nasty. */ +#include "../../Kernel/include/userstructs.h" + extern int errno; extern int syscall(int callno, ...); -struct _uzistat -{ - int16_t st_dev; - uint16_t st_ino; - uint16_t st_mode; - uint16_t st_nlink; - uint16_t st_uid; - uint16_t st_gid; - uint16_t st_rdev; - uint32_t st_size; - uint32_t st_atime; - uint32_t st_mtime; - uint32_t st_ctime; - uint32_t st_timeh; /* Time high bytes */ -}; - struct _uzisysinfoblk { uint8_t infosize; /* For expandability */ uint8_t banks; /* Banks in our 64K (and thus pagesize) */