feat: implement utime libc function, SYS_UTIME syscall, filesystem support (ext2 only)

This commit is contained in:
2026-08-09 11:16:59 +02:00
parent 771c3a5a98
commit 1c498ffa6a
15 changed files with 158 additions and 30 deletions
+82 -25
View File
@@ -118,6 +118,7 @@ static inline long _zos_syscall4(long nr, long a1, long a2, long a3, long a4) {
#define SYS_DUPHANDLE 98
#define SYS_KILL 62
#define SYS_STAT 152
#define SYS_UTIME 167
/* ========================================================================
errno
@@ -2019,10 +2020,15 @@ done:
fcntl.h / unistd.h POSIX-style file I/O
======================================================================== */
/* fd position tracking for POSIX read/write (MontaukOS uses explicit offsets) */
#define _FD_POS_MAX 64
/* fd position tracking for POSIX read/write (MontaukOS uses explicit offsets).
OPEN_MAX is part of the userspace ABI and matches the kernel handle table. */
#define _FD_POS_MAX OPEN_MAX
static unsigned long _fd_pos[_FD_POS_MAX];
static int _fd_pos_valid(int fd) {
return fd >= 0 && fd < _FD_POS_MAX;
}
int access(const char *path, int mode) {
if (path == NULL) {
errno = EINVAL;
@@ -2069,7 +2075,12 @@ int open(const char *path, int flags, ...) {
h = (int)_zos_syscall1(SYS_FCREATE, (long)path);
}
if (h >= 0 && h < _FD_POS_MAX) {
if (h >= _FD_POS_MAX) {
_zos_syscall1(SYS_CLOSE, (long)h);
errno = EMFILE;
return -1;
}
if (h >= 0) {
_fd_pos[h] = 0;
if (flags & O_APPEND) {
_fd_pos[h] = (unsigned long)_zos_syscall1(SYS_GETSIZE, (long)h);
@@ -2110,9 +2121,14 @@ int read(int fd, void *buf, size_t count) {
return (int)i;
}
unsigned long pos = (fd >= 0 && fd < _FD_POS_MAX) ? _fd_pos[fd] : 0;
if (!_fd_pos_valid(fd)) {
errno = EBADF;
return -1;
}
unsigned long pos = _fd_pos[fd];
int ret = (int)_zos_syscall4(SYS_READ, (long)fd, (long)buf, (long)pos, (long)count);
if (ret > 0 && fd >= 0 && fd < _FD_POS_MAX)
if (ret > 0)
_fd_pos[fd] += (unsigned long)ret;
return ret;
}
@@ -2127,9 +2143,14 @@ int write(int fd, const void *buf, size_t count) {
return (int)count;
}
unsigned long pos = (fd >= 0 && fd < _FD_POS_MAX) ? _fd_pos[fd] : 0;
if (!_fd_pos_valid(fd)) {
errno = EBADF;
return -1;
}
unsigned long pos = _fd_pos[fd];
int ret = (int)_zos_syscall4(SYS_FWRITE, (long)fd, (long)buf, (long)pos, (long)count);
if (ret > 0 && fd >= 0 && fd < _FD_POS_MAX)
if (ret > 0)
_fd_pos[fd] += (unsigned long)ret;
return ret;
}
@@ -2184,20 +2205,37 @@ int ftruncate(int fd, long length) {
* offset is genuinely left alone.
*/
ssize_t pread(int fd, void *buf, size_t count, off_t offset) {
if (buf == NULL || offset < 0) return -1;
if (!_fd_pos_valid(fd)) {
errno = EBADF;
return -1;
}
if (buf == NULL || offset < 0) {
errno = EINVAL;
return -1;
}
return (ssize_t)_zos_syscall4(SYS_READ, (long)fd, (long)buf,
(long)offset, (long)count);
}
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) {
if (buf == NULL || offset < 0) return -1;
if (!_fd_pos_valid(fd)) {
errno = EBADF;
return -1;
}
if (buf == NULL || offset < 0) {
errno = EINVAL;
return -1;
}
return (ssize_t)_zos_syscall4(SYS_FWRITE, (long)fd, (long)buf,
(long)offset, (long)count);
}
int close(int fd) {
if (fd >= 0 && fd < _FD_POS_MAX)
_fd_pos[fd] = 0;
if (!_fd_pos_valid(fd)) {
errno = EBADF;
return -1;
}
_fd_pos[fd] = 0;
if ((int)_zos_syscall1(SYS_CLOSE, (long)fd) < 0) {
errno = EBADF;
return -1;
@@ -2206,7 +2244,12 @@ int close(int fd) {
}
long lseek(int fd, long offset, int whence) {
unsigned long pos = (fd >= 0 && fd < _FD_POS_MAX) ? _fd_pos[fd] : 0;
if (!_fd_pos_valid(fd)) {
errno = EBADF;
return -1;
}
unsigned long pos = _fd_pos[fd];
unsigned long newpos;
switch (whence) {
case 0: /* SEEK_SET */
@@ -2219,10 +2262,10 @@ long lseek(int fd, long offset, int whence) {
newpos = (unsigned long)_zos_syscall1(SYS_GETSIZE, (long)fd) + (unsigned long)offset;
break;
default:
errno = EINVAL;
return -1;
}
if (fd >= 0 && fd < _FD_POS_MAX)
_fd_pos[fd] = newpos;
_fd_pos[fd] = newpos;
return (long)newpos;
}
@@ -3322,12 +3365,21 @@ int fchmod(int fd, mode_t mode) {
}
int utime(const char *path, const struct utimbuf *times) {
(void)times;
if (path == NULL) {
errno = EINVAL;
return -1;
}
return 0; /* file times cannot be set through the VFS */
long result = _zos_syscall4(SYS_UTIME, (long)path,
times != NULL ? (long)times->actime : 0,
times != NULL ? (long)times->modtime : 0,
times == NULL);
if (result == 0) return 0;
if (result == -2) errno = ENOTSUP;
else if (result == -3) errno = EOVERFLOW;
else if (result == -4) errno = EIO;
else errno = ENOENT;
return -1;
}
void *bsearch(const void *key, const void *base, size_t nmemb, size_t size,
@@ -3740,7 +3792,7 @@ pid_t getpid(void) {
allocation usually land there. The oldfd == newfd form (the common
validity probe) is handled exactly. */
int dup2(int oldfd, int newfd) {
if (oldfd < 0 || newfd < 0) {
if (!_fd_pos_valid(oldfd) || !_fd_pos_valid(newfd)) {
errno = EBADF;
return -1;
}
@@ -3764,9 +3816,7 @@ int dup2(int oldfd, int newfd) {
errno = EBUSY;
return -1;
}
if (h < _FD_POS_MAX) {
_fd_pos[h] = (oldfd < _FD_POS_MAX) ? _fd_pos[oldfd] : 0;
}
_fd_pos[h] = _fd_pos[oldfd];
return newfd;
}
@@ -3812,7 +3862,7 @@ int getpagesize(void) {
long sysconf(int name) {
switch (name) {
case 4: /* _SC_OPEN_MAX */
return 64;
return OPEN_MAX;
case 30: /* _SC_PAGESIZE */
return 4096;
case 84: /* _SC_NPROCESSORS_ONLN */
@@ -4066,14 +4116,21 @@ pid_t wait(int *status) {
}
int dup(int fd) {
if (!_fd_pos_valid(fd)) {
errno = EBADF;
return -1;
}
int h = (int)_zos_syscall1(SYS_DUPHANDLE, (long)fd);
if (h < 0) {
errno = EBADF;
return -1;
}
if (h < _FD_POS_MAX) {
_fd_pos[h] = (fd >= 0 && fd < _FD_POS_MAX) ? _fd_pos[fd] : 0;
if (!_fd_pos_valid(h)) {
_zos_syscall1(SYS_CLOSE, (long)h);
errno = EMFILE;
return -1;
}
_fd_pos[h] = _fd_pos[fd];
return h;
}
@@ -4089,7 +4146,7 @@ int fileno(FILE *stream) {
}
FILE *fdopen(int fd, const char *mode) {
if (fd < 0 || mode == NULL) {
if (!_fd_pos_valid(fd) || mode == NULL) {
errno = EBADF;
return NULL;
}
@@ -4099,7 +4156,7 @@ FILE *fdopen(int fd, const char *mode) {
return NULL;
}
f->handle = fd;
f->pos = (fd < _FD_POS_MAX) ? _fd_pos[fd] : 0;
f->pos = _fd_pos[fd];
f->size = (unsigned long)_zos_syscall1(SYS_GETSIZE, (long)fd);
f->eof = 0;
f->error = 0;