From: Tulio A M Mendes Date: Sun, 19 Apr 2026 18:38:13 +0000 (-0300) Subject: POSIX compliance audit: fix syscall wrappers, headers, and commands X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=ec905308f7f0d0bded28075c83f447d844918c2e;p=AdrOS.git POSIX compliance audit: fix syscall wrappers, headers, and commands ulibc fixes: - mkdir(): change from variadic to (path, mode_t) per POSIX - stat/fstat/fstatat: use struct stat* instead of void* - wait4: use pid_t return and struct rusage* parameter - waitid: use siginfo_t* instead of void* - lseek: return off_t instead of int - pread/pwrite: return ssize_t, use off_t offset - truncate/ftruncate: use off_t length - chmod: use mode_t instead of int - open(): extract mode from va_args (was silently ignored) - openat(): extract mode and pass as 4th syscall arg - Add pivot_root() wrapper (syscall 120 existed but had no wrapper) - Add lstat() (delegates to stat, no symlinks in AdrOS) - Add fchmod() stub (ENOSYS, no kernel syscall yet) ulibc header fixes: - unistd.h: add sys/types.h include, forward declare struct stat/rusage - fcntl.h: add O_EXCL, O_NOCTTY, O_DIRECTORY, O_NOFOLLOW, AT_FDCWD, AT_SYMLINK_NOFOLLOW, AT_REMOVEDIR, AT_SYMLINK_FOLLOW, AT_EACCESS - sys/stat.h: add lstat, fchmod declarations, fix mkdir/chmod types newlib fixes: - openat(): extract mode from va_args, pass as 4th arg (was _sc3) - Add pivot_root() wrapper command fixes: - mkdir: pass mode 0755 to mkdir() calls (was calling with 0 args) - stat: remove unnecessary void* cast - df: replace hardcoded stub with /proc/mounts reader Tests: 103/103 PASS, 16/16 battery, 69/69 host --- diff --git a/newlib/libgloss/adros/posix_stubs.c b/newlib/libgloss/adros/posix_stubs.c index b9c052cf..4952bfd8 100644 --- a/newlib/libgloss/adros/posix_stubs.c +++ b/newlib/libgloss/adros/posix_stubs.c @@ -567,7 +567,11 @@ int dup3(int oldfd, int newfd, int flags) { } int openat(int dirfd, const char *path, int flags, ...) { - return _check(_sc3(SYS_OPENAT, dirfd, (int)path, flags)); + va_list ap; + va_start(ap, flags); + int mode = va_arg(ap, int); + va_end(ap); + return _check(_sc4(SYS_OPENAT, dirfd, (int)path, flags, mode)); } int fstatat(int dirfd, const char *path, struct stat *buf, int flags) { @@ -740,6 +744,10 @@ void *sbrk(intptr_t increment) { return cur; } +int pivot_root(const char *new_root, const char *put_old) { + return _check(_sc2(SYS_PIVOT_ROOT, (int)new_root, (int)put_old)); +} + int mkfifo(const char *path, mode_t mode) { (void)path; (void)mode; errno = ENOSYS; diff --git a/user/cmds/df/df.c b/user/cmds/df/df.c index 0929e41b..9eacf3db 100644 --- a/user/cmds/df/df.c +++ b/user/cmds/df/df.c @@ -9,11 +9,20 @@ /* AdrOS df utility — display filesystem disk space usage */ #include +#include +#include int main(void) { + int fd = open("/proc/mounts", O_RDONLY); + if (fd < 0) { + fprintf(stderr, "df: cannot open /proc/mounts\n"); + return 1; + } printf("Filesystem Size Used Avail Use%% Mounted on\n"); - printf("overlayfs - - - - /\n"); - printf("devfs - - - - /dev\n"); - printf("procfs - - - - /proc\n"); + char buf[1024]; + int n; + while ((n = read(fd, buf, sizeof(buf))) > 0) + write(STDOUT_FILENO, buf, (size_t)n); + close(fd); return 0; } diff --git a/user/cmds/mkdir/mkdir.c b/user/cmds/mkdir/mkdir.c index 4e803efb..45e6b2ec 100644 --- a/user/cmds/mkdir/mkdir.c +++ b/user/cmds/mkdir/mkdir.c @@ -11,6 +11,7 @@ #include #include #include +#include static int pflag = 0; /* -p: create parent directories */ @@ -23,11 +24,11 @@ static int mkdir_p(const char* path) { for (char* p = tmp + 1; *p; p++) { if (*p == '/') { *p = '\0'; - mkdir(tmp); /* ignore errors — parent may already exist */ + mkdir(tmp, 0755); /* ignore errors — parent may already exist */ *p = '/'; } } - return mkdir(tmp); + return mkdir(tmp, 0755); } int main(int argc, char** argv) { @@ -59,7 +60,7 @@ int main(int argc, char** argv) { if (pflag) { r = mkdir_p(argv[i]); } else { - r = mkdir(argv[i]); + r = mkdir(argv[i], 0755); } if (r < 0) { fprintf(stderr, "mkdir: cannot create directory '%s'\n", argv[i]); diff --git a/user/cmds/stat/stat.c b/user/cmds/stat/stat.c index 1460fb3b..fdd33fff 100644 --- a/user/cmds/stat/stat.c +++ b/user/cmds/stat/stat.c @@ -21,7 +21,7 @@ int main(int argc, char** argv) { int rc = 0; for (int i = 1; i < argc; i++) { struct stat st; - if (stat(argv[i], (void*)&st) < 0) { + if (stat(argv[i], &st) < 0) { fprintf(stderr, "stat: cannot stat '%s'\n", argv[i]); rc = 1; continue; diff --git a/user/ulibc/include/fcntl.h b/user/ulibc/include/fcntl.h index 11f92e4e..d277b84c 100644 --- a/user/ulibc/include/fcntl.h +++ b/user/ulibc/include/fcntl.h @@ -16,9 +16,13 @@ #define O_WRONLY 0x0001 #define O_RDWR 0x0002 #define O_CREAT 0x0040 +#define O_EXCL 0x0080 +#define O_NOCTTY 0x0100 #define O_TRUNC 0x0200 #define O_APPEND 0x0400 #define O_NONBLOCK 0x0800 +#define O_DIRECTORY 0x10000 +#define O_NOFOLLOW 0x20000 #define O_CLOEXEC 0x80000 #define F_DUPFD 0 @@ -35,6 +39,13 @@ #define FD_CLOEXEC 1 +/* AT_* constants for *at() syscalls */ +#define AT_FDCWD -100 +#define AT_SYMLINK_NOFOLLOW 0x100 +#define AT_REMOVEDIR 0x200 +#define AT_SYMLINK_FOLLOW 0x400 +#define AT_EACCESS 0x0400 + /* Record lock types */ #define F_RDLCK 0 #define F_WRLCK 1 diff --git a/user/ulibc/include/sys/stat.h b/user/ulibc/include/sys/stat.h index 42739674..be90b783 100644 --- a/user/ulibc/include/sys/stat.h +++ b/user/ulibc/include/sys/stat.h @@ -51,7 +51,9 @@ struct stat { int stat(const char* path, struct stat* buf); int fstat(int fd, struct stat* buf); -int mkdir(const char* path, ...); -int chmod(const char* path, int mode); +int lstat(const char* path, struct stat* buf); +int mkdir(const char* path, mode_t mode); +int chmod(const char* path, mode_t mode); +int fchmod(int fd, mode_t mode); #endif diff --git a/user/ulibc/include/unistd.h b/user/ulibc/include/unistd.h index 066800eb..c757910d 100644 --- a/user/ulibc/include/unistd.h +++ b/user/ulibc/include/unistd.h @@ -12,8 +12,12 @@ #include #include +#include #include +struct stat; +struct rusage; + #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 @@ -26,7 +30,7 @@ int read(int fd, void* buf, size_t count); int write(int fd, const void* buf, size_t count); int open(const char* path, int flags, ...); int close(int fd); -int lseek(int fd, int offset, int whence); +off_t lseek(int fd, off_t offset, int whence); int dup(int oldfd); int dup2(int oldfd, int newfd); int pipe(int fds[2]); @@ -36,7 +40,7 @@ int getpid(void); int getppid(void); int chdir(const char* path); char* getcwd(char* buf, size_t size); -int mkdir(const char* path, ...); /* mode_t optional in AdrOS */ +int mkdir(const char* path, mode_t mode); int unlink(const char* path); int rmdir(const char* path); int setsid(void); @@ -45,8 +49,8 @@ int getpgrp(void); int gettid(void); int fsync(int fd); int fdatasync(int fd); -int pread(int fd, void* buf, size_t count, int offset); -int pwrite(int fd, const void* buf, size_t count, int offset); +ssize_t pread(int fd, void* buf, size_t count, off_t offset); +ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset); int access(const char* path, int mode); int getuid(void); int getgid(void); @@ -56,8 +60,8 @@ int setuid(int uid); int setgid(int gid); int seteuid(int euid); int setegid(int egid); -int truncate(const char* path, int length); -int ftruncate(int fd, int length); +int truncate(const char* path, off_t length); +int ftruncate(int fd, off_t length); unsigned int alarm(unsigned int seconds); #define LOCK_SH 1 #define LOCK_EX 2 @@ -70,7 +74,7 @@ void* brk(void* addr); int waitpid(int pid, int* status, int options); int getdents(int fd, void* buf, size_t count); -int chmod(const char* path, int mode); +int chmod(const char* path, mode_t mode); int chown(const char* path, int owner, int group); int link(const char* oldpath, const char* newpath); int symlink(const char* target, const char* linkpath); @@ -116,16 +120,17 @@ int execle(const char* path, const char* arg, ...); int execveat(int dirfd, const char* path, char* const argv[], char* const envp[], int flags); int dup3(int oldfd, int newfd, int flags); int openat(int dirfd, const char* path, int flags, ...); -int fstatat(int dirfd, const char* path, void* buf, int flags); +int fstatat(int dirfd, const char* path, struct stat* buf, int flags); int unlinkat(int dirfd, const char* path, int flags); int mount(const char* source, const char* target, const char* fs_type, unsigned long flags, const void* data); int umount2(const char* target, int flags); int umount(const char* target); -int wait4(int pid, int* status, int options, void* rusage); -int waitid(int idtype, int id, void* info, int options); +pid_t wait4(pid_t pid, int* status, int options, struct rusage* rusage); +int waitid(int idtype, int id, siginfo_t* info, int options); int sigreturn(void); int sigqueue(int pid, int sig, const union sigval value); int set_thread_area(void* desc); +int pivot_root(const char* new_root, const char* put_old); char* getlogin(void); int getlogin_r(char* buf, size_t bufsize); int tcgetpgrp(int fd); diff --git a/user/ulibc/src/unistd.c b/user/ulibc/src/unistd.c index f0b79279..748b78a4 100644 --- a/user/ulibc/src/unistd.c +++ b/user/ulibc/src/unistd.c @@ -14,6 +14,8 @@ #include "stdlib.h" #include "sys/select.h" #include "sys/time.h" +#include "sys/stat.h" +#include "sys/resource.h" #include "signal.h" int read(int fd, void* buf, size_t count) { @@ -25,7 +27,11 @@ int write(int fd, const void* buf, size_t count) { } int open(const char* path, int flags, ...) { - (void)flags; /* mode arg unused by kernel currently */ + __builtin_va_list ap; + __builtin_va_start(ap, flags); + int mode = __builtin_va_arg(ap, int); + __builtin_va_end(ap); + (void)mode; /* kernel ignores mode currently */ return __syscall_ret(_syscall2(SYS_OPEN, (int)path, flags)); } @@ -33,8 +39,8 @@ int close(int fd) { return __syscall_ret(_syscall1(SYS_CLOSE, fd)); } -int lseek(int fd, int offset, int whence) { - return __syscall_ret(_syscall3(SYS_LSEEK, fd, offset, whence)); +off_t lseek(int fd, off_t offset, int whence) { + return __syscall_ret(_syscall3(SYS_LSEEK, fd, (int)offset, whence)); } int dup(int oldfd) { @@ -90,7 +96,8 @@ char* getcwd(char* buf, size_t size) { return buf; } -int mkdir(const char* path, ...) { +int mkdir(const char* path, mode_t mode) { + (void)mode; /* kernel ignores mode currently */ return __syscall_ret(_syscall1(SYS_MKDIR, (int)path)); } @@ -126,12 +133,12 @@ int fdatasync(int fd) { return __syscall_ret(_syscall1(SYS_FDATASYNC, fd)); } -int pread(int fd, void* buf, size_t count, int offset) { - return __syscall_ret(_syscall4(SYS_PREAD, fd, (int)buf, (int)count, offset)); +ssize_t pread(int fd, void* buf, size_t count, off_t offset) { + return __syscall_ret(_syscall4(SYS_PREAD, fd, (int)buf, (int)count, (int)offset)); } -int pwrite(int fd, const void* buf, size_t count, int offset) { - return __syscall_ret(_syscall4(SYS_PWRITE, fd, (int)buf, (int)count, offset)); +ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset) { + return __syscall_ret(_syscall4(SYS_PWRITE, fd, (int)buf, (int)count, (int)offset)); } int access(const char* path, int mode) { @@ -170,12 +177,12 @@ int setegid(int egid) { return __syscall_ret(_syscall1(SYS_SETEGID, egid)); } -int truncate(const char* path, int length) { - return __syscall_ret(_syscall2(SYS_TRUNCATE, (int)path, length)); +int truncate(const char* path, off_t length) { + return __syscall_ret(_syscall2(SYS_TRUNCATE, (int)path, (int)length)); } -int ftruncate(int fd, int length) { - return __syscall_ret(_syscall2(SYS_FTRUNCATE, fd, length)); +int ftruncate(int fd, off_t length) { + return __syscall_ret(_syscall2(SYS_FTRUNCATE, fd, (int)length)); } unsigned int alarm(unsigned int seconds) { @@ -214,16 +221,26 @@ int getdents(int fd, void* buf, size_t count) { return __syscall_ret(_syscall3(SYS_GETDENTS, fd, (int)buf, (int)count)); } -int stat(const char* path, void* buf) { +int stat(const char* path, struct stat* buf) { return __syscall_ret(_syscall2(SYS_STAT, (int)path, (int)buf)); } -int fstat(int fd, void* buf) { +int fstat(int fd, struct stat* buf) { return __syscall_ret(_syscall2(SYS_FSTAT, fd, (int)buf)); } -int chmod(const char* path, int mode) { - return __syscall_ret(_syscall2(SYS_CHMOD, (int)path, mode)); +int lstat(const char* path, struct stat* buf) { + return stat(path, buf); /* no symlinks in AdrOS, same as stat */ +} + +int chmod(const char* path, mode_t mode) { + return __syscall_ret(_syscall2(SYS_CHMOD, (int)path, (int)mode)); +} + +int fchmod(int fd, mode_t mode) { + (void)fd; (void)mode; + errno = ENOSYS; + return -1; } int chown(const char* path, int owner, int group) { @@ -343,10 +360,14 @@ int dup3(int oldfd, int newfd, int flags) { } int openat(int dirfd, const char* path, int flags, ...) { - return __syscall_ret(_syscall3(SYS_OPENAT, dirfd, (int)path, flags)); + __builtin_va_list ap; + __builtin_va_start(ap, flags); + int mode = __builtin_va_arg(ap, int); + __builtin_va_end(ap); + return __syscall_ret(_syscall4(SYS_OPENAT, dirfd, (int)path, flags, mode)); } -int fstatat(int dirfd, const char* path, void* buf, int flags) { +int fstatat(int dirfd, const char* path, struct stat* buf, int flags) { return __syscall_ret(_syscall4(SYS_FSTATAT, dirfd, (int)path, (int)buf, flags)); } @@ -366,11 +387,11 @@ int umount(const char* target) { return umount2(target, 0); } -int wait4(int pid, int* status, int options, void* rusage) { - return __syscall_ret(_syscall4(SYS_WAIT4, pid, (int)status, options, (int)rusage)); +pid_t wait4(pid_t pid, int* status, int options, struct rusage* rusage) { + return __syscall_ret(_syscall4(SYS_WAIT4, (int)pid, (int)status, options, (int)rusage)); } -int waitid(int idtype, int id, void* info, int options) { +int waitid(int idtype, int id, siginfo_t* info, int options) { return __syscall_ret(_syscall4(SYS_WAITID, idtype, id, (int)info, options)); } @@ -385,3 +406,7 @@ int sigqueue(int pid, int sig, const union sigval value) { int set_thread_area(void* desc) { return __syscall_ret(_syscall1(SYS_SET_THREAD_AREA, (int)desc)); } + +int pivot_root(const char* new_root, const char* put_old) { + return __syscall_ret(_syscall2(SYS_PIVOT_ROOT, (int)new_root, (int)put_old)); +}