commit bbe5632fb90e548f8b312a049c5bae6701c553b9
parent 0794f2d0ac9547f111cf61f46581c4677c89fb8b
Author: Mallory Adams <malloryadams@fastmail.com>
Date: Sun, 9 Jun 2024 20:18:14 -0400
NetBSD: add os::shm_open()
- Update rt/+netbsd/syscallno.ha with NetBSD 10.0 syscalls
- Add fstatvfs1 syscall
- Add unlink syscall
- Fix whitespace and comments in rt/+netbsd/types.ha
Signed-off-by: Mallory Adams <malloryadams@fastmail.com>
Diffstat:
7 files changed, 369 insertions(+), 41 deletions(-)
diff --git a/makefiles/netbsd.aarch64.mk b/makefiles/netbsd.aarch64.mk
@@ -129,8 +129,8 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
-$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
+os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/shm.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
+$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/os.td.tmp -N os $(os_ha)
diff --git a/makefiles/netbsd.riscv64.mk b/makefiles/netbsd.riscv64.mk
@@ -129,8 +129,8 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
-$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
+os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/shm.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
+$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/os.td.tmp -N os $(os_ha)
diff --git a/makefiles/netbsd.x86_64.mk b/makefiles/netbsd.x86_64.mk
@@ -129,8 +129,8 @@ $(HARECACHE)/types_c.ssa: $(types_c_ha) $(HARECACHE)/encoding_utf8.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/types_c.td.tmp -N types::c $(types_c_ha)
-os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
-$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
+os_ha = os/+netbsd/dirfdfs.ha os/+netbsd/exit.ha os/+netbsd/fs.ha os/+netbsd/platform_environ.ha os/+netbsd/shm.ha os/+netbsd/status.ha os/+netbsd/stdfd.ha os/environ.ha os/os.ha
+$(HARECACHE)/os.ssa: $(os_ha) $(HARECACHE)/bufio.td $(HARECACHE)/bytes.td $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/path.td $(HARECACHE)/rt.td $(HARECACHE)/strings.td $(HARECACHE)/time.td $(HARECACHE)/types_c.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/os.td.tmp -N os $(os_ha)
diff --git a/os/+netbsd/shm.ha b/os/+netbsd/shm.ha
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+
+use bytes;
+use errors;
+use fs;
+use io;
+use path;
+use rt;
+use strings;
+
+fn shm_check_fs() bool = {
+ match (open(rt::SHMFS_DIR_PATH,
+ fs::flag::DIRECTORY | fs::flag::RDONLY)) {
+ case fs::error =>
+ return false;
+ case let fd: io::file =>
+ defer io::close(fd)!;
+
+ let sv = rt::statvfs{...};
+ let st = rt::st{...};
+
+ if (rt::fstatvfs1(fd, &sv, rt::MNT_NOWAIT) is rt::errno)
+ return false;
+
+ if (strings::fromutf8(sv.f_fstypename)! == rt::MOUNT_SHMFS)
+ return false;
+
+ if (rt::fstat(fd, &st) is rt::errno)
+ return false;
+
+ if ((st.mode & rt::SHMFS_DIR_MODE) != rt::SHMFS_DIR_MODE)
+ return false;
+
+ return true;
+ };
+};
+
+fn shm_get_path(name: const str) (str | fs::error) = {
+ if (!shm_check_fs())
+ return errors::errno(rt::ENOTSUP): fs::error;
+
+ // The name may start with a slash character.
+ if (strings::hasprefix(name, '/')) {
+ name = strings::sub(name, 1);
+ };
+
+ // We may disallow other slashes (implementation-defined behaviour).
+ if (strings::contains(name, '/'))
+ return errors::errno(rt::EINVAL): fs::error;
+
+ const _path = strings::concat(
+ rt::SHMFS_DIR_PATH, "/", rt::SHMFS_OBJ_PREFIX, name);
+
+ if (len(_path) > path::MAX)
+ return errors::errno(rt::ENAMETOOLONG): fs::error;
+
+ return _path;
+};
+
+// Opens (or creates, given [[fs::flag::CREATE]]) a global shared memory file
+// with the given name, suitable for use with [[io::mmap]] to establish shared
+// memory areas with other processes using the same name.
+//
+// The name must not contain any forward slashes (one is permissible at the
+// start, e.g. "/example") and cannot be "." or "..".
+//
+// The "oflag" parameter, if provided, must include either [[fs::flag::RDONLY]]
+// or [[fs::flag::RDWR]], and may optionally add [[fs::flag::CREATE]],
+// [[fs::flag::EXCL]], and/or [[fs::flag::TRUNC]], which are supported on all
+// POSIX-compatible platforms. Other platforms may support additional
+// non-standard flags; consult the shm_open(3) manual for your target system for
+// details.
+//
+// The new file descriptor always has CLOEXEC set regardless of the provided
+// flags. If creating a new shared memory object, set its initial size with
+// [[io::trunc]] before mapping it with [[io::mmap]].
+//
+// Call [[shm_unlink]] to remove the global shared memory object.
+export fn shm_open(
+ name: str,
+ oflag: fs::flag = fs::flag::CREATE | fs::flag::RDWR,
+ mode: fs::mode = 0o600,
+) (io::file | fs::error) = {
+ const _path = shm_get_path(name)?;
+
+ const oflag = fsflags_to_bsd(oflag)? | rt::O_CLOEXEC | rt::O_NOFOLLOW;
+
+ match (rt::open(_path, oflag, mode)) {
+ case let fd: int =>
+ return fd: io::file;
+ case let err: rt::errno =>
+ return errors::errno(err): fs::error;
+ };
+};
+
+// Removes the shared memory object with the given name. Processes which already
+// hold a reference to the file may continue to use the memory associated with
+// it. Once all processes have unmapped the associated shared memory object, or
+// exited, the memory is released.
+export fn shm_unlink(name: str) (void | fs::error) = {
+ const _path = shm_get_path(name)?;
+
+ match (rt::unlink(_path)) {
+ case void =>
+ void;
+ case let err: rt::errno =>
+ return errors::errno(err): fs::error;
+ };
+};
+
+@test fn shm_open() void = {
+ const name = "/vizzini";
+ const value = "inconceivable";
+ def length = 13;
+
+ const fd = shm_open(name)!;
+ defer shm_unlink(name)!;
+ io::trunc(fd, length)!;
+ io::write(fd, strings::toutf8(value))!;
+
+ {
+ const fd = shm_open(name, fs::flag::RDONLY, 0o600)!;
+
+ let b: [length]u8 = [0...];
+ io::read(fd, b)!;
+ assert(strings::fromutf8(b)! == value);
+ };
+};
+
+@test fn shm_get_path() void = {
+ assert(shm_get_path("/ab/c") is fs::error);
+ assert(shm_get_path("abc"): str == "/var/shm/.shmobj_abc");
+ assert(shm_get_path("/abc"): str == "/var/shm/.shmobj_abc");
+};
diff --git a/rt/+netbsd/syscallno.ha b/rt/+netbsd/syscallno.ha
@@ -116,6 +116,8 @@ export def SYS_compat_50_settimeofday: u64 = 122;
export def SYS_fchown: u64 = 123;
export def SYS_fchmod: u64 = 124;
export def SYS_compat_43_orecvfrom: u64 = 125;
+export def SYS_setreuid: u64 = 126;
+export def SYS_setregid: u64 = 127;
export def SYS_rename: u64 = 128;
export def SYS_compat_43_otruncate: u64 = 129;
export def SYS_compat_43_oftruncate: u64 = 130;
@@ -147,6 +149,9 @@ export def SYS_compat_09_ogetdomainname: u64 = 162;
export def SYS_compat_09_osetdomainname: u64 = 163;
export def SYS_compat_09_ouname: u64 = 164;
export def SYS_sysarch: u64 = 165;
+export def SYS___futex: u64 = 166;
+export def SYS___futex_set_robust_list: u64 = 167;
+export def SYS___futex_get_robust_list: u64 = 168;
export def SYS_compat_10_osemsys: u64 = 169;
export def SYS_compat_10_omsgsys: u64 = 170;
export def SYS_compat_10_oshmsys: u64 = 171;
@@ -154,6 +159,9 @@ export def SYS_pread: u64 = 173;
export def SYS_pwrite: u64 = 174;
export def SYS_compat_30_ntp_gettime: u64 = 175;
export def SYS_ntp_adjtime: u64 = 176;
+export def SYS_timerfd_create: u64 = 177;
+export def SYS_timerfd_settime: u64 = 178;
+export def SYS_timerfd_gettime: u64 = 179;
export def SYS_setgid: u64 = 181;
export def SYS_setegid: u64 = 182;
export def SYS_seteuid: u64 = 183;
@@ -231,6 +239,7 @@ export def SYS_mq_send: u64 = 263;
export def SYS_mq_receive: u64 = 264;
export def SYS_compat_50_mq_timedsend: u64 = 265;
export def SYS_compat_50_mq_timedreceive: u64 = 266;
+export def SYS_eventfd: u64 = 267;
export def SYS___posix_rename: u64 = 270;
export def SYS_swapctl: u64 = 271;
export def SYS_compat_30_getdents: u64 = 272;
@@ -305,9 +314,9 @@ export def SYS_sched_yield: u64 = 350;
export def SYS__sched_protect: u64 = 351;
export def SYS_fsync_range: u64 = 354;
export def SYS_uuidgen: u64 = 355;
-export def SYS_getvfsstat: u64 = 356;
-export def SYS_statvfs1: u64 = 357;
-export def SYS_fstatvfs1: u64 = 358;
+export def SYS_compat_90_getvfsstat: u64 = 356;
+export def SYS_compat_90_statvfs1: u64 = 357;
+export def SYS_compat_90_fstatvfs1: u64 = 358;
export def SYS_compat_30_fhstatvfs1: u64 = 359;
export def SYS_extattrctl: u64 = 360;
export def SYS_extattr_set_file: u64 = 361;
@@ -345,7 +354,7 @@ export def SYS_compat_50___ntp_gettime30: u64 = 393;
export def SYS___socket30: u64 = 394;
export def SYS___getfh30: u64 = 395;
export def SYS___fhopen40: u64 = 396;
-export def SYS___fhstatvfs140: u64 = 397;
+export def SYS_compat_90_fhstatvfs1: u64 = 397;
export def SYS_compat_50___fhstat40: u64 = 398;
export def SYS_aio_cancel: u64 = 399;
export def SYS_aio_error: u64 = 400;
@@ -427,5 +436,20 @@ export def SYS_posix_fallocate: u64 = 479;
export def SYS_fdiscard: u64 = 480;
export def SYS_wait6: u64 = 481;
export def SYS_clock_getcpuclockid2: u64 = 482;
-export def SYS_MAXSYSCALL: u64 = 483;
-export def SYS_NSYSENT: u64 = 512;
+export def SYS___getvfsstat90: u64 = 483;
+export def SYS___statvfs190: u64 = 484;
+export def SYS___fstatvfs190: u64 = 485;
+export def SYS___fhstatvfs190: u64 = 486;
+export def SYS___acl_get_link: u64 = 487;
+export def SYS___acl_set_link: u64 = 488;
+export def SYS___acl_delete_link: u64 = 489;
+export def SYS___acl_aclcheck_link: u64 = 490;
+export def SYS___acl_get_file: u64 = 491;
+export def SYS___acl_set_file: u64 = 492;
+export def SYS___acl_get_fd: u64 = 493;
+export def SYS___acl_set_fd: u64 = 494;
+export def SYS___acl_delete_file: u64 = 495;
+export def SYS___acl_delete_fd: u64 = 496;
+export def SYS___acl_aclcheck_file: u64 = 497;
+export def SYS___acl_aclcheck_fd: u64 = 498;
+export def SYS_lpathconf: u64 = 499;
diff --git a/rt/+netbsd/syscalls.ha b/rt/+netbsd/syscalls.ha
@@ -79,6 +79,11 @@ export fn fstatat(fd: int, path: path, _stat: *st, flag: int) (void | errno) = {
_stat.flags = sb.st_flags;
};
+export fn fstatvfs1(fd: int, _statvfs: *statvfs, flag: int) (void | errno) = {
+ wrap_return(syscall3(SYS___fstatvfs190, fd: u64,
+ _statvfs: uintptr: u64, flag: u64))?;
+};
+
export fn futimens(fd: int, ts: *[2]timespec) (void | errno) = {
wrap_return(syscall2(SYS_futimens,
fd: u64, ts: uintptr: u64))?;
@@ -150,6 +155,11 @@ export fn sysctl(name: []const u32, oldp: nullable *opaque, oldlenp: nullable *s
newp: uintptr: u64, newlen: u64))?;
};
+export fn unlink(path: path) (void | errno) = {
+ let path = kpath(path)?;
+ wrap_return(syscall1(SYS_unlink, path: uintptr: u64))?;
+};
+
export fn unlinkat(dirfd: int, path: path, flags: int) (void | errno) = {
let path = kpath(path)?;
wrap_return(syscall3(SYS_unlinkat,
diff --git a/rt/+netbsd/types.ha b/rt/+netbsd/types.ha
@@ -138,11 +138,85 @@ export type stat = struct {
st_spare: [2]u32,
};
+export type fsid_t = struct {
+ __fsid_val: [2]u32,
+};
+
+export def VFS_NAMELEN: int = 32;
+export def VFS_MNAMELEN: int = 1024;
+
+export type statvfs = struct {
+ // copy of mount exported flags
+ f_flag: u64,
+ // file system block size
+ f_bsize: u64,
+ // fundamental file system block size
+ f_frsize: u64,
+ // optimal file system block size
+ f_iosize: u64,
+
+ // The following are in units of f_frsize
+
+ // number of blocks in file system,
+ f_blocks: u64,
+ // free blocks avail in file system
+ f_bfree: u64,
+ // free blocks avail to non-root
+ f_bavail: u64,
+ // blocks reserved for root
+ f_bresvd: u64,
+
+ // total file nodes in file system
+ f_files: u64,
+ // free file nodes in file system
+ f_ffree: u64,
+ // free file nodes avail to non-root
+ f_favail: u64,
+ // file nodes reserved for root
+ f_fresvd: u64,
+
+ // count of sync reads since mount
+ f_syncreads: u64,
+ // count of sync writes since mount
+ f_syncwrites: u64,
+
+ // count of async reads since mount
+ f_asyncreads: u64,
+ // count of async writes since mount
+ f_asyncwrites: u64,
+
+ // NetBSD compatible fsid
+ f_fsidx: fsid_t,
+ // Posix compatible fsid
+ f_fsid: u64,
+ // maximum filename length
+ f_namemax: u64,
+ // user that mounted the file system
+ f_owner: uid_t,
+ __pad0: u32,
+
+ // spare space
+ f_spare: [4]u64,
+
+ // fs type name
+ f_fstypename: [VFS_NAMELEN]u8,
+ // directory on which mounted
+ f_mntonname: [VFS_MNAMELEN]u8,
+ // mounted file system
+ f_mntfromname: [VFS_MNAMELEN]u8,
+ // disk label name if avail
+ f_mntfromlabel: [VFS_MNAMELEN]u8,
+};
+
export type dirent = struct {
- d_fileno: ino_t, // file number of entry
- d_reclen: u16, // length of this record
- d_namlen: u16, // length of d_name
- d_type: u8, // file type, see below
+ // file number of entry
+ d_fileno: ino_t,
+ // length of this record
+ d_reclen: u16,
+ // length of d_name
+ d_namlen: u16,
+ // file type, see below
+ d_type: u8,
d_name: [NAME_MAX + 1]u8,
};
@@ -274,22 +348,38 @@ export type ptmget = struct {
};
export type rusage = struct {
- ru_utime: timeval, // user time used
- ru_stime: timeval, // system time used
- ru_maxrss: i64, // max resident set size
- ru_ixrss: i64, // integral shared memory size
- ru_idrss: i64, // integral unshared data "
- ru_isrss: i64, // integral unshared stack "
- ru_minflt: i64, // page reclaims
- ru_majflt: i64, // page faults
- ru_nswap: i64, // swaps
- ru_inblock: i64, // block input operations
- ru_oublock: i64, // block output operations
- ru_msgsnd: i64, // messages sent
- ru_msgrcv: i64, // messages received
- ru_nsignals: i64, // signals received
- ru_nvcsw: i64, // voluntary context switches
- ru_nivcsw: i64, // involuntary "
+ // user time used
+ ru_utime: timeval,
+ // system time used
+ ru_stime: timeval,
+ // max resident set size
+ ru_maxrss: i64,
+ // integral shared memory size
+ ru_ixrss: i64,
+ // integral unshared data "
+ ru_idrss: i64,
+ // integral unshared stack "
+ ru_isrss: i64,
+ // page reclaims
+ ru_minflt: i64,
+ // page faults
+ ru_majflt: i64,
+ // swaps
+ ru_nswap: i64,
+ // block input operations
+ ru_inblock: i64,
+ // block output operations
+ ru_oublock: i64,
+ // messages sent
+ ru_msgsnd: i64,
+ // messages received
+ ru_msgrcv: i64,
+ // signals received
+ ru_nsignals: i64,
+ // voluntary context switches
+ ru_nvcsw: i64,
+ // involuntary "
+ ru_nivcsw: i64,
};
export def DT_UNKNOWN: u8 = 0;
@@ -324,6 +414,7 @@ export def O_EXEC: int = 0x00040000;
export def O_TTY_INIT: int = 0x00080000;
export def O_CLOEXEC: int = 0x00400000;
export def O_DSYNC: int = 0x01000000;
+export def O_RSYNC: int = 0x00020000;
export def AT_FDCWD: int = -100;
export def AT_EACCESS: int = 0x0100;
@@ -332,13 +423,63 @@ export def AT_SYMLINK_FOLLOW: int = 0x0400;
export def AT_REMOVEDIR: int = 0x0800;
export def AT_RESOLVE_BENEATH: int = 0x2000;
-export def S_IFIFO: mode_t = 0o010000;
-export def S_IFCHR: mode_t = 0o020000;
-export def S_IFDIR: mode_t = 0o040000;
-export def S_IFBLK: mode_t = 0o060000;
-export def S_IFREG: mode_t = 0o100000;
-export def S_IFLNK: mode_t = 0o120000;
-export def S_IFSOCK: mode_t = 0o140000;
+// set user id on execution
+export def S_ISUID: u64 = 0o004000;
+// set group id on execution
+export def S_ISGID: u64 = 0o002000;
+// sticky bit
+export def S_ISTXT: u64 = 0o001000;
+// RWX mask for owner
+export def S_IRWXU: u64 = 0o000700;
+// R for owner
+export def S_IRUSR: u64 = 0o000400;
+// W for owner
+export def S_IWUSR: u64 = 0o000200;
+// X for owner
+export def S_IXUSR: u64 = 0o000100;
+export def S_IREAD: u64 = S_IRUSR;
+export def S_IWRITE: u64 = S_IWUSR;
+export def S_IEXEC: u64 = S_IXUSR;
+// RWX mask for group
+export def S_IRWXG: u64 = 0o000070;
+// R for group
+export def S_IRGRP: u64 = 0o000040;
+// W for group
+export def S_IWGRP: u64 = 0o000020;
+// X for group
+export def S_IXGRP: u64 = 0o000010;
+// RWX mask for other
+export def S_IRWXO: u64 = 0o000007;
+// R for other
+export def S_IROTH: u64 = 0o000004;
+// W for other
+export def S_IWOTH: u64 = 0o000002;
+// X for other
+export def S_IXOTH: u64 = 0o000001;
+// type of file mask
+export def S_IFMT: u64 = 0o170000;
+// named pipe (fifo)
+export def S_IFIFO: u64 = 0o010000;
+// character special
+export def S_IFCHR: u64 = 0o020000;
+// directory
+export def S_IFDIR: u64 = 0o040000;
+// block special
+export def S_IFBLK: u64 = 0o060000;
+// regular
+export def S_IFREG: u64 = 0o100000;
+// symbolic link
+export def S_IFLNK: u64 = 0o120000;
+// save swapped text even after use
+export def S_ISVTX: u64 = 0o001000;
+// socket
+export def S_IFSOCK: u64 = 0o140000;
+// whiteout
+export def S_IFWHT: u64 = 0o160000;
+// Archive state 1, ls -l shows 'a'
+export def S_ARCH1: u64 = 0o200000;
+// Archive state 2, ls -l shows 'A'
+export def S_ARCH2: u64 = 0o400000;
export def MAP_SHARED: uint = 0x0001;
export def MAP_PRIVATE: uint = 0x0002;
@@ -492,10 +633,28 @@ export def RLIMIT_NPTS: int = 11;
export def RLIMIT_SWAP: int = 12;
export def RLIMIT_KQUEUES: int = 13;
export def RLIMIT_UMTXP: int = 14;
-export def RLIMIT_NTHR: int = 11; // number of threads
+// number of threads
+export def RLIMIT_NTHR: int = 11;
export def SHUT_RD: int = 0;
export def SHUT_WR: int = 1;
export def SHUT_RDWR: int = 2;
-export def NODEV: int = -1; // non-existent device
+// non-existent device
+export def NODEV: int = -1;
+
+// synchronously wait for I/O to complete
+export def MNT_WAIT: int = 1;
+// start all I/O, but do not wait for it
+export def MNT_NOWAIT: int = 2;
+// push data not written by filesystem syncer
+export def MNT_LAZY: int = 3;
+
+// Efficient memory file-system
+export def MOUNT_TMPFS = "tmpfs";
+export def MOUNT_SHMFS = MOUNT_TMPFS;
+
+// Shared memory objects are supported using tmpfs.
+export def SHMFS_DIR_PATH = "/var/shm";
+export def SHMFS_DIR_MODE = (S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO);
+export def SHMFS_OBJ_PREFIX = ".shmobj_";