commit 72cbcd3a31b00414f9e5285e70c85149b6ff8925
parent fcdbc7b4c2d76638fb33772f4756c7231a40b8f5
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 7 Feb 2021 10:07:48 -0500
rt: add stat wrapper
Diffstat:
6 files changed, 239 insertions(+), 76 deletions(-)
diff --git a/rt/+linux/arch+aarch64.ha b/rt/+linux/arch+aarch64.ha
@@ -0,0 +1,18 @@
+export type st = struct {
+ dev: dev_t,
+ ino: ino_t,
+ mode: mode_t,
+ nlink: nlink_t,
+ uid: uid_t,
+ gid: gid_t,
+ rdev: dev_t,
+ __pad0: u64,
+ sz: i64,
+ blksz: i64,
+ __pad1: int,
+ blocks: i64,
+ atime: timespec,
+ mtime: timespec,
+ ctime: timespec,
+ __pad2: [2]uint,
+};
diff --git a/rt/+linux/arch+x86_64.ha b/rt/+linux/arch+x86_64.ha
@@ -0,0 +1,17 @@
+export type st = struct {
+ dev: dev_t,
+ ino: ino_t,
+ nlink: nlink_t,
+ mode: mode_t,
+ uid: uid_t,
+ gid: gid_t,
+ __pad0: uint,
+ rdev: dev_t,
+ sz: i64,
+ blksz: i64,
+ blocks: i64,
+ atime: timespec,
+ mtime: timespec,
+ ctime: timespec,
+ __pad1: [3]i64,
+};
diff --git a/rt/+linux/errno.ha b/rt/+linux/errno.ha
@@ -6,8 +6,8 @@ export fn wrap_errno(err: int) errno = err: errno;
// Checks the return value from a Linux syscall and, if found to be in error,
// returns the appropriate error. Otherwise, returns the original value.
-export fn wrap_return(r: size) (errno | size) = {
- if (r > -4096z) {
+export fn wrap_return(r: u64) (errno | size) = {
+ if (r > -4096u64) {
return (-(r: i64)): int: errno;
};
return r;
diff --git a/rt/+linux/stat.ha b/rt/+linux/stat.ha
@@ -0,0 +1,57 @@
+fn mkdev(major: u32, minor: u32) dev_t =
+ ((major: u64 & 0xFFFFF000u64) << 32u64) |
+ ((major: u64 & 0x00000FFFu64) << 8u64) |
+ ((minor: u64 & 0xFFFFFF00u64) << 12u64) |
+ (minor: u64 & 0x000000FFu64);
+
+fn fstatat_statx(
+ dirfd: int,
+ path: *const char,
+ flags: int,
+ mask: uint,
+ statbuf: *stx,
+) (void | errno) = match (wrap_return(syscall5(
+ SYS_statx, dirfd: u64, path: uintptr: u64, flags: u64,
+ mask: u64, statbuf: uintptr: u64))) {
+ err: errno => err,
+ size => void,
+};
+
+export fn fstatat(
+ dirfd: int,
+ path: *const char,
+ statbuf: *st,
+ flags: int,
+) (errno | void) = {
+ let statxbuf = stx { ... };
+ match (fstatat_statx(dirfd, path, flags, STATX_BASIC_STATS, &statxbuf)) {
+ err: errno => return err,
+ void => void,
+ };
+ statbuf.dev = mkdev(statxbuf.dev_major, statxbuf.dev_minor);
+ statbuf.ino = statxbuf.ino;
+ statbuf.mode = statxbuf.mode;
+ statbuf.nlink = statxbuf.nlink;
+ statbuf.uid = statxbuf.uid;
+ statbuf.gid = statxbuf.gid;
+ statbuf.rdev = mkdev(statxbuf.dev_major, statxbuf.dev_minor);
+ statbuf.sz = statxbuf.sz: i64;
+ statbuf.blksz = statxbuf.blksize: i64;
+ statbuf.blocks = statxbuf.blocks: i64;
+ statbuf.atime.tv_sec = statxbuf.atime.tv_sec;
+ statbuf.atime.tv_nsec = statxbuf.atime.tv_nsec: i64;
+ statbuf.mtime.tv_sec = statxbuf.mtime.tv_sec;
+ statbuf.mtime.tv_nsec = statxbuf.mtime.tv_nsec: i64;
+ statbuf.ctime.tv_sec = statxbuf.ctime.tv_sec;
+ statbuf.ctime.tv_nsec = statxbuf.ctime.tv_nsec: i64;
+ return void;
+};
+
+export fn stat(path: *const char, statbuf: *st) (errno | void) =
+ fstatat(AT_FDCWD, path, statbuf, 0);
+
+export fn fstat(fd: int, statbuf: *st) (errno | void) =
+ fstatat(fd, "", statbuf, AT_EMPTY_PATH);
+
+export fn lstat(path: *const char, statbuf: *st) (errno | void) =
+ fstatat(AT_FDCWD, path, statbuf, AT_SYMLINK_NOFOLLOW);
diff --git a/rt/+linux/syscalls.ha b/rt/+linux/syscalls.ha
@@ -17,8 +17,6 @@ export fn open(path: *const char, flags: int, mode: uint) size = {
path: uintptr: u64, flags: u64, mode: u64): size;
};
-export def AT_FDCWD: int = -100;
-
export fn close(fd: int) int = syscall1(SYS_close, fd: u64): int;
export fn getpid() int = syscall0(SYS_getpid): int;
@@ -31,78 +29,6 @@ export @noreturn fn exit(status: int) void = syscall1(SYS_exit, status: u64);
export fn kill(pid: int, signal: int) int =
syscall2(SYS_kill, pid: u64, signal: u64): int;
-export def SIGHUP: int = 1;
-export def SIGINT: int = 2;
-export def SIGQUIT: int = 3;
-export def SIGILL: int = 4;
-export def SIGTRAP: int = 5;
-export def SIGABRT: int = 6;
-export def SIGBUS: int = 7;
-export def SIGFPE: int = 8;
-export def SIGKILL: int = 9;
-export def SIGUSR1: int = 10;
-export def SIGSEGV: int = 11;
-export def SIGUSR2: int = 12;
-export def SIGPIPE: int = 13;
-export def SIGALRM: int = 14;
-export def SIGTERM: int = 15;
-export def SIGSTKFLT: int = 16;
-export def SIGCHLD: int = 17;
-export def SIGCONT: int = 18;
-export def SIGSTOP: int = 19;
-export def SIGTSTP: int = 20;
-export def SIGTTIN: int = 21;
-export def SIGTTOU: int = 22;
-export def SIGURG: int = 23;
-export def SIGXCPU: int = 24;
-export def SIGXFSZ: int = 25;
-export def SIGVTALRM: int = 26;
-export def SIGPROF: int = 27;
-export def SIGWINCH: int = 28;
-export def SIGIO: int = 29;
-export def SIGPOLL: int = 29;
-export def SIGPWR: int = 30;
-export def SIGSYS: int = 31;
-
-export def MAP_SHARED: uint = 0x01u;
-export def MAP_PRIVATE: uint = 0x02u;
-export def MAP_SHARED_VALIDATE: uint = 0x03u;
-export def MAP_FIXED: uint = 0x10u;
-export def MAP_ANON: uint = 0x20u;
-export def MAP_NORESERVE: uint = 0x4000u;
-export def MAP_GROWSDOWN: uint = 0x0100u;
-export def MAP_DENYWRITE: uint = 0x0800u;
-export def MAP_EXECUTABLE: uint = 0x1000u;
-export def MAP_LOCKED: uint = 0x2000u;
-export def MAP_POPULATE: uint = 0x8000u;
-export def MAP_NONBLOCK: uint = 0x10000u;
-export def MAP_STACK: uint = 0x20000u;
-export def MAP_HUGETLB: uint = 0x40000u;
-export def MAP_SYNC: uint = 0x80000u;
-export def MAP_FIXED_NOREPLACE: uint = 0x100000u;
-export def MAP_FILE: uint = 0u;
-export def MAP_HUGE_SHIFT: uint = 26u;
-export def MAP_HUGE_MASK: uint = 0x3fu;
-export def MAP_HUGE_64KB: uint = 16u << 26u;
-export def MAP_HUGE_512KB: uint = 19u << 26u;
-export def MAP_HUGE_1MB: uint = 20u << 26u;
-export def MAP_HUGE_2MB: uint = 21u << 26u;
-export def MAP_HUGE_8MB: uint = 23u << 26u;
-export def MAP_HUGE_16MB: uint = 24u << 26u;
-export def MAP_HUGE_32MB: uint = 25u << 26u;
-export def MAP_HUGE_256MB: uint = 28u << 26u;
-export def MAP_HUGE_512MB: uint = 29u << 26u;
-export def MAP_HUGE_1GB: uint = 30u << 26u;
-export def MAP_HUGE_2GB: uint = 31u << 26u;
-export def MAP_HUGE_16GB: uint = 34u << 26u;
-
-export def PROT_NONE: uint = 0u;
-export def PROT_READ: uint = 1u;
-export def PROT_WRITE: uint = 2u;
-export def PROT_EXEC: uint = 4u;
-export def PROT_GROWSDOWN: uint = 0x01000000u;
-export def PROT_GROWSUP: uint = 0x02000000u;
-
export fn mmap(
addr: nullable *void,
length: size,
diff --git a/rt/+linux/types.ha b/rt/+linux/types.ha
@@ -0,0 +1,145 @@
+export type dev_t = u64;
+export type ino_t = u64;
+export type nlink_t = u64;
+export type mode_t = uint;
+export type uid_t = uint;
+export type gid_t = uint;
+export type time_t = i64;
+export type suseconds_t = i64;
+
+export type timeval = struct {
+ tv_sec: time_t,
+ tv_usec: suseconds_t,
+};
+
+export type timespec = struct {
+ tv_sec: time_t,
+ tv_nsec: i64,
+};
+
+export def AT_FDCWD: int = -100;
+export def AT_SYMLINK_NOFOLLOW: int = 0x100;
+export def AT_REMOVEDIR: int = 0x200;
+export def AT_SYMLINK_FOLLOW: int = 0x400;
+export def AT_EACCESS: int = 0x200;
+export def AT_NO_AUTOMOUNT: int = 0x800;
+export def AT_EMPTY_PATH: int = 0x1000;
+export def AT_STATX_SYNC_TYPE: int = 0x6000;
+export def AT_STATX_SYNC_AS_STAT: int = 0x0000;
+export def AT_STATX_FORCE_SYNC: int = 0x2000;
+export def AT_STATX_DONT_SYNC: int = 0x4000;
+export def AT_RECURSIVE: int = 0x8000;
+
+type statx_timestamp = struct {
+ tv_sec: i64,
+ tv_nsec: u32,
+};
+
+type stx = struct {
+ mask: u32,
+ blksize: u32,
+ attributes: u64,
+ nlink: u32,
+ uid: u32,
+ gid: u32,
+ mode: u16,
+ ino: u64,
+ sz: u64,
+ blocks: u64,
+ attr_mask: u64,
+ atime: statx_timestamp,
+ btime: statx_timestamp,
+ ctime: statx_timestamp,
+ mtime: statx_timestamp,
+ rdev_major: u32,
+ rdev_minor: u32,
+ dev_major: u32,
+ dev_minor: u32,
+};
+
+def STATX_TYPE: uint = 0x00000001u;
+def STATX_MODE: uint = 0x00000002u;
+def STATX_NLINK: uint = 0x00000004u;
+def STATX_UID: uint = 0x00000008u;
+def STATX_GID: uint = 0x00000010u;
+def STATX_ATIME: uint = 0x00000020u;
+def STATX_MTIME: uint = 0x00000040u;
+def STATX_CTIME: uint = 0x00000080u;
+def STATX_INO: uint = 0x00000100u;
+def STATX_SIZE: uint = 0x00000200u;
+def STATX_BLOCKS: uint = 0x00000400u;
+def STATX_BASIC_STATS: uint = 0x000007FFu;
+def STATX_BTIME: uint = 0x00000800u;
+def STATX_MNT_ID: uint = 0x00001000u;
+
+export def SIGHUP: int = 1;
+export def SIGINT: int = 2;
+export def SIGQUIT: int = 3;
+export def SIGILL: int = 4;
+export def SIGTRAP: int = 5;
+export def SIGABRT: int = 6;
+export def SIGBUS: int = 7;
+export def SIGFPE: int = 8;
+export def SIGKILL: int = 9;
+export def SIGUSR1: int = 10;
+export def SIGSEGV: int = 11;
+export def SIGUSR2: int = 12;
+export def SIGPIPE: int = 13;
+export def SIGALRM: int = 14;
+export def SIGTERM: int = 15;
+export def SIGSTKFLT: int = 16;
+export def SIGCHLD: int = 17;
+export def SIGCONT: int = 18;
+export def SIGSTOP: int = 19;
+export def SIGTSTP: int = 20;
+export def SIGTTIN: int = 21;
+export def SIGTTOU: int = 22;
+export def SIGURG: int = 23;
+export def SIGXCPU: int = 24;
+export def SIGXFSZ: int = 25;
+export def SIGVTALRM: int = 26;
+export def SIGPROF: int = 27;
+export def SIGWINCH: int = 28;
+export def SIGIO: int = 29;
+export def SIGPOLL: int = 29;
+export def SIGPWR: int = 30;
+export def SIGSYS: int = 31;
+
+export def MAP_SHARED: uint = 0x01u;
+export def MAP_PRIVATE: uint = 0x02u;
+export def MAP_SHARED_VALIDATE: uint = 0x03u;
+export def MAP_FIXED: uint = 0x10u;
+export def MAP_ANON: uint = 0x20u;
+export def MAP_NORESERVE: uint = 0x4000u;
+export def MAP_GROWSDOWN: uint = 0x0100u;
+export def MAP_DENYWRITE: uint = 0x0800u;
+export def MAP_EXECUTABLE: uint = 0x1000u;
+export def MAP_LOCKED: uint = 0x2000u;
+export def MAP_POPULATE: uint = 0x8000u;
+export def MAP_NONBLOCK: uint = 0x10000u;
+export def MAP_STACK: uint = 0x20000u;
+export def MAP_HUGETLB: uint = 0x40000u;
+export def MAP_SYNC: uint = 0x80000u;
+export def MAP_FIXED_NOREPLACE: uint = 0x100000u;
+export def MAP_FILE: uint = 0u;
+export def MAP_HUGE_SHIFT: uint = 26u;
+export def MAP_HUGE_MASK: uint = 0x3fu;
+export def MAP_HUGE_64KB: uint = 16u << 26u;
+export def MAP_HUGE_512KB: uint = 19u << 26u;
+export def MAP_HUGE_1MB: uint = 20u << 26u;
+export def MAP_HUGE_2MB: uint = 21u << 26u;
+export def MAP_HUGE_8MB: uint = 23u << 26u;
+export def MAP_HUGE_16MB: uint = 24u << 26u;
+export def MAP_HUGE_32MB: uint = 25u << 26u;
+export def MAP_HUGE_256MB: uint = 28u << 26u;
+export def MAP_HUGE_512MB: uint = 29u << 26u;
+export def MAP_HUGE_1GB: uint = 30u << 26u;
+export def MAP_HUGE_2GB: uint = 31u << 26u;
+export def MAP_HUGE_16GB: uint = 34u << 26u;
+
+export def PROT_NONE: uint = 0u;
+export def PROT_READ: uint = 1u;
+export def PROT_WRITE: uint = 2u;
+export def PROT_EXEC: uint = 4u;
+export def PROT_GROWSDOWN: uint = 0x01000000u;
+export def PROT_GROWSUP: uint = 0x02000000u;