- Added Linux-compatible file metadata syscalls (stat, lstat, fstat, newfstatat) - Implemented access control checks with faccessat and related flag definitions - Added file persistence operations (fsync, fdatasync, truncate, ftruncate) - Integrated clock syscalls (gettimeofday, clock_gettime, clock_getres) - Added process identity queries (getpid, getppid, gettid, getuid, getgid) - Changed exit mechanism from exit(60) to exit_group(231) for consistency - Updated crt0.S with Linux x86-64 exit_group ABI compatibility - Extended fcntl.h with AT_SYMLINK_NOFOLLOW and AT_EACCESS constants - Added complete syscalls implementation in user/libc.c and runtime/posix.c - Implemented kernel-side syscall handlers in process.c with proper validation - Added systest utility to verify file metadata, persistence and identity calls - Updated Makefile dependencies to track user header changes - Enhanced README documentation for newmaster
parent
2d052429ca
commit
ee69e75f4f
26 changed files with 667 additions and 66 deletions
@ -1,8 +1,40 @@ |
||||
#ifndef TYPEPHP_OS_USER_SYS_STAT_H |
||||
#define TYPEPHP_OS_USER_SYS_STAT_H |
||||
|
||||
typedef unsigned int mode_t; |
||||
#include <sys/types.h> |
||||
#include <time.h> |
||||
|
||||
struct stat { |
||||
dev_t st_dev; |
||||
ino_t st_ino; |
||||
nlink_t st_nlink; |
||||
mode_t st_mode; |
||||
uid_t st_uid; |
||||
gid_t st_gid; |
||||
int __pad0; |
||||
dev_t st_rdev; |
||||
off_t st_size; |
||||
blksize_t st_blksize; |
||||
blkcnt_t st_blocks; |
||||
struct timespec st_atim; |
||||
struct timespec st_mtim; |
||||
struct timespec st_ctim; |
||||
long __reserved[3]; |
||||
}; |
||||
|
||||
#define S_IFMT 0170000 |
||||
#define S_IFREG 0100000 |
||||
#define S_IFDIR 0040000 |
||||
#define S_IFCHR 0020000 |
||||
|
||||
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) |
||||
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) |
||||
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) |
||||
|
||||
int mkdir(const char *path, mode_t mode); |
||||
int stat(const char *path, struct stat *value); |
||||
int lstat(const char *path, struct stat *value); |
||||
int fstat(int fd, struct stat *value); |
||||
int fstatat(int directory_fd, const char *path, struct stat *value, int flags); |
||||
|
||||
#endif |
||||
|
||||
@ -0,0 +1,13 @@ |
||||
#ifndef TYPEPHP_OS_USER_SYS_TIME_H |
||||
#define TYPEPHP_OS_USER_SYS_TIME_H |
||||
|
||||
#include <sys/types.h> |
||||
|
||||
struct timeval { |
||||
time_t tv_sec; |
||||
long tv_usec; |
||||
}; |
||||
|
||||
int gettimeofday(struct timeval *value, void *timezone); |
||||
|
||||
#endif |
||||
@ -0,0 +1,20 @@ |
||||
#ifndef TYPEPHP_OS_USER_SYS_TYPES_H |
||||
#define TYPEPHP_OS_USER_SYS_TYPES_H |
||||
|
||||
/* Linux x86-64 ABI-compatible scalar types. Keeping this layout stable makes
|
||||
* the userspace boundary suitable for a future glibc port. */ |
||||
typedef unsigned long dev_t; |
||||
typedef unsigned long ino_t; |
||||
typedef unsigned long nlink_t; |
||||
typedef unsigned int mode_t; |
||||
typedef unsigned int uid_t; |
||||
typedef unsigned int gid_t; |
||||
typedef int pid_t; |
||||
typedef long off_t; |
||||
typedef long blksize_t; |
||||
typedef long blkcnt_t; |
||||
typedef long ssize_t; |
||||
typedef long time_t; |
||||
typedef int clockid_t; |
||||
|
||||
#endif |
||||
@ -1,8 +1,18 @@ |
||||
#ifndef TYPEPHP_OS_USER_TIME_H |
||||
#define TYPEPHP_OS_USER_TIME_H |
||||
|
||||
typedef long time_t; |
||||
#include <sys/types.h> |
||||
|
||||
#define CLOCK_REALTIME 0 |
||||
#define CLOCK_MONOTONIC 1 |
||||
|
||||
struct timespec { |
||||
time_t tv_sec; |
||||
long tv_nsec; |
||||
}; |
||||
|
||||
time_t time(time_t *result); |
||||
int clock_gettime(clockid_t clock_id, struct timespec *value); |
||||
int clock_getres(clockid_t clock_id, struct timespec *value); |
||||
|
||||
#endif |
||||
|
||||
@ -0,0 +1,73 @@ |
||||
#include <fcntl.h> |
||||
#include <stddef.h> |
||||
#include <sys/stat.h> |
||||
#include <sys/time.h> |
||||
#include <time.h> |
||||
#include <unistd.h> |
||||
|
||||
_Static_assert(sizeof(struct stat) == 144, "Linux x86-64 stat ABI changed"); |
||||
|
||||
static int fail(const char *operation) |
||||
{ |
||||
size_t length = 0; |
||||
while (operation[length] != '\0') { |
||||
++length; |
||||
} |
||||
(void) write(STDERR_FILENO, "systest: ", sizeof("systest: ") - 1); |
||||
(void) write(STDERR_FILENO, operation, length); |
||||
(void) write(STDERR_FILENO, " failed\n", sizeof(" failed\n") - 1); |
||||
return 1; |
||||
} |
||||
|
||||
int main(int argc, char **argv) |
||||
{ |
||||
static const char path[] = "/SYS.TMP"; |
||||
static const char payload[] = "abcdef"; |
||||
struct stat info; |
||||
struct timeval wall; |
||||
struct timespec realtime; |
||||
struct timespec monotonic; |
||||
struct timespec resolution; |
||||
int fd; |
||||
(void) argc; |
||||
(void) argv; |
||||
|
||||
if (stat("/HELLO.TXT", &info) != 0 || !S_ISREG(info.st_mode) |
||||
|| info.st_size <= 0 || access("/HELLO.TXT", R_OK) != 0) { |
||||
return fail("stat/access"); |
||||
} |
||||
if (fstatat(AT_FDCWD, "/HELLO.TXT", &info, AT_SYMLINK_NOFOLLOW) != 0 |
||||
|| faccessat(AT_FDCWD, "/HELLO.TXT", R_OK, 0) != 0) { |
||||
return fail("*at metadata"); |
||||
} |
||||
|
||||
(void) unlink(path); |
||||
fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0666); |
||||
if (fd < 0 || write(fd, payload, sizeof(payload) - 1) != sizeof(payload) - 1 |
||||
|| fsync(fd) != 0 || ftruncate(fd, 3) != 0 |
||||
|| fstat(fd, &info) != 0 || info.st_size != 3 |
||||
|| fdatasync(fd) != 0 || close(fd) != 0) { |
||||
return fail("descriptor persistence"); |
||||
} |
||||
if (truncate(path, 1) != 0 || lstat(path, &info) != 0 |
||||
|| info.st_size != 1 || unlink(path) != 0) { |
||||
return fail("path truncate"); |
||||
} |
||||
|
||||
if (getpid() != 2 || gettid() != 2 || getppid() != 1 |
||||
|| getuid() != 0 || geteuid() != 0 || getgid() != 0 || getegid() != 0) { |
||||
return fail("single-task identity"); |
||||
} |
||||
if (gettimeofday(&wall, NULL) != 0 || wall.tv_sec <= 0 |
||||
|| clock_gettime(CLOCK_REALTIME, &realtime) != 0 |
||||
|| clock_gettime(CLOCK_MONOTONIC, &monotonic) != 0 |
||||
|| clock_getres(CLOCK_MONOTONIC, &resolution) != 0 |
||||
|| realtime.tv_sec <= 0 || monotonic.tv_sec <= 0 |
||||
|| resolution.tv_sec != 1 || resolution.tv_nsec != 0) { |
||||
return fail("clock ABI"); |
||||
} |
||||
|
||||
(void) write(STDOUT_FILENO, "basic syscalls: OK\n", |
||||
sizeof("basic syscalls: OK\n") - 1); |
||||
return 0; |
||||
} |
||||
Loading…
Reference in new issue