From bd5969fc876a10b18613302db7087ef3c40f18e1 Mon Sep 17 00:00:00 2001
From: Ian Moffett <ian@osmora.org>
Date: Thu, 7 Mar 2024 17:28:00 -0500
Subject: lib: Add mlibc

Signed-off-by: Ian Moffett <ian@osmora.org>
---
 lib/mlibc/options/linux/generic/capabilities.cpp   |  19 ++++
 lib/mlibc/options/linux/generic/cpuset.cpp         |  71 ++++++++++++
 lib/mlibc/options/linux/generic/ifaddrs.cpp        |  15 +++
 lib/mlibc/options/linux/generic/linux-unistd.cpp   |  33 ++++++
 lib/mlibc/options/linux/generic/malloc.cpp         |   7 ++
 lib/mlibc/options/linux/generic/mntent-stubs.cpp   |  98 +++++++++++++++++
 lib/mlibc/options/linux/generic/module.cpp         |  24 ++++
 lib/mlibc/options/linux/generic/pty-stubs.cpp      | 101 +++++++++++++++++
 lib/mlibc/options/linux/generic/sched.cpp          |  50 +++++++++
 lib/mlibc/options/linux/generic/sys-epoll.cpp      |  58 ++++++++++
 lib/mlibc/options/linux/generic/sys-eventfd.cpp    |  45 ++++++++
 lib/mlibc/options/linux/generic/sys-fsuid.cpp      |  12 ++
 .../options/linux/generic/sys-inotify-stubs.cpp    |  47 ++++++++
 lib/mlibc/options/linux/generic/sys-klog.cpp       |  16 +++
 lib/mlibc/options/linux/generic/sys-mount.cpp      |  29 +++++
 .../options/linux/generic/sys-prctl-stubs.cpp      |  25 +++++
 .../options/linux/generic/sys-ptrace-stubs.cpp     |  36 ++++++
 lib/mlibc/options/linux/generic/sys-quota.cpp      |   7 ++
 .../options/linux/generic/sys-random-stubs.cpp     |  21 ++++
 lib/mlibc/options/linux/generic/sys-reboot.cpp     |  13 +++
 .../options/linux/generic/sys-sendfile-stubs.cpp   |   9 ++
 lib/mlibc/options/linux/generic/sys-signalfd.cpp   |  17 +++
 .../options/linux/generic/sys-statfs-stubs.cpp     |  26 +++++
 lib/mlibc/options/linux/generic/sys-swap.cpp       |  24 ++++
 lib/mlibc/options/linux/generic/sys-sysinfo.cpp    |  15 +++
 lib/mlibc/options/linux/generic/sys-timerfd.cpp    |  33 ++++++
 lib/mlibc/options/linux/generic/sys-xattr.cpp      | 122 +++++++++++++++++++++
 lib/mlibc/options/linux/generic/utmp-stubs.cpp     | 116 ++++++++++++++++++++
 lib/mlibc/options/linux/generic/utmpx.cpp          |  45 ++++++++
 29 files changed, 1134 insertions(+)
 create mode 100644 lib/mlibc/options/linux/generic/capabilities.cpp
 create mode 100644 lib/mlibc/options/linux/generic/cpuset.cpp
 create mode 100644 lib/mlibc/options/linux/generic/ifaddrs.cpp
 create mode 100644 lib/mlibc/options/linux/generic/linux-unistd.cpp
 create mode 100644 lib/mlibc/options/linux/generic/malloc.cpp
 create mode 100644 lib/mlibc/options/linux/generic/mntent-stubs.cpp
 create mode 100644 lib/mlibc/options/linux/generic/module.cpp
 create mode 100644 lib/mlibc/options/linux/generic/pty-stubs.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sched.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-epoll.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-eventfd.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-fsuid.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-inotify-stubs.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-klog.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-mount.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-prctl-stubs.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-ptrace-stubs.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-quota.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-random-stubs.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-reboot.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-sendfile-stubs.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-signalfd.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-statfs-stubs.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-swap.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-sysinfo.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-timerfd.cpp
 create mode 100644 lib/mlibc/options/linux/generic/sys-xattr.cpp
 create mode 100644 lib/mlibc/options/linux/generic/utmp-stubs.cpp
 create mode 100644 lib/mlibc/options/linux/generic/utmpx.cpp

(limited to 'lib/mlibc/options/linux/generic')

diff --git a/lib/mlibc/options/linux/generic/capabilities.cpp b/lib/mlibc/options/linux/generic/capabilities.cpp
new file mode 100644
index 0000000..871822a
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/capabilities.cpp
@@ -0,0 +1,19 @@
+#include <mlibc/debug.hpp>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int capset(void *, void *) {
+	mlibc::infoLogger() << "mlibc: capset is a no-op!" << frg::endlog;
+	return 0;
+}
+
+int capget(void *, void *) {
+	mlibc::infoLogger() << "mlibc: capget is a no-op!" << frg::endlog;
+	return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib/mlibc/options/linux/generic/cpuset.cpp b/lib/mlibc/options/linux/generic/cpuset.cpp
new file mode 100644
index 0000000..d0292b7
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/cpuset.cpp
@@ -0,0 +1,71 @@
+#include <limits.h>
+#include <sched.h>
+#include <stdlib.h>
+#include <string.h>
+
+cpu_set_t *__mlibc_cpu_alloc(int num_cpus) {
+	return reinterpret_cast<cpu_set_t *>(calloc(1, CPU_ALLOC_SIZE(num_cpus)));
+}
+
+#define CPU_MASK_BITS (CHAR_BIT * sizeof(__cpu_mask))
+
+size_t __mlibc_cpu_alloc_size(int num_cpus) {
+	/* calculate the (unaligned) remainder that doesn't neatly fit in one __cpu_mask; 0 or 1 */
+	size_t remainder = ((num_cpus % CPU_MASK_BITS) + CPU_MASK_BITS - 1) / CPU_MASK_BITS;
+	return sizeof(__cpu_mask) * (num_cpus / CPU_MASK_BITS + remainder);
+}
+
+void __mlibc_cpu_zero(const size_t setsize, cpu_set_t *set) {
+	memset(set, 0, CPU_ALLOC_SIZE(setsize));
+}
+
+void __mlibc_cpu_set(const int cpu, const size_t setsize, cpu_set_t *set) {
+	if(cpu >= static_cast<int>(setsize * CHAR_BIT)) {
+		return;
+	}
+
+	unsigned char *ptr = reinterpret_cast<unsigned char *>(set);
+	size_t off = cpu / CHAR_BIT;
+	size_t mask = 1 << (cpu % CHAR_BIT);
+
+	ptr[off] |= mask;
+}
+
+void __mlibc_cpu_clear(const int cpu, const size_t setsize, cpu_set_t *set) {
+	if(cpu >= static_cast<int>(setsize * CHAR_BIT)) {
+		return;
+	}
+
+	unsigned char *ptr = reinterpret_cast<unsigned char *>(set);
+	size_t off = cpu / CHAR_BIT;
+	size_t mask = 1 << (cpu % CHAR_BIT);
+
+	ptr[off] &= ~mask;
+}
+
+
+int __mlibc_cpu_isset(const int cpu, const size_t setsize, const cpu_set_t *set) {
+	if(cpu >= static_cast<int>(setsize * CHAR_BIT)) {
+		return false;
+	}
+
+	const unsigned char *ptr = reinterpret_cast<const unsigned char *>(set);
+	size_t off = cpu / CHAR_BIT;
+	size_t mask = 1 << (cpu % CHAR_BIT);
+
+	return (ptr[off] & mask);
+}
+
+int __mlibc_cpu_count(const size_t setsize, const cpu_set_t *set) {
+	size_t count = 0;
+	const unsigned char *ptr = reinterpret_cast<const unsigned char *>(set);
+
+	for(size_t i = 0; i < setsize; i++) {
+		for(size_t bit = 0; bit < CHAR_BIT; bit++) {
+			if((1 << bit) & ptr[i])
+				count++;
+		}
+	}
+
+	return count;
+}
diff --git a/lib/mlibc/options/linux/generic/ifaddrs.cpp b/lib/mlibc/options/linux/generic/ifaddrs.cpp
new file mode 100644
index 0000000..67dfbc6
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/ifaddrs.cpp
@@ -0,0 +1,15 @@
+#include <bits/ensure.h>
+#include <mlibc/debug.hpp>
+#include <ifaddrs.h>
+#include <errno.h>
+
+int getifaddrs(struct ifaddrs **) {
+	mlibc::infoLogger() << "mlibc: getifaddrs fails unconditionally!" << frg::endlog;
+	errno = ENOSYS;
+	return -1;
+}
+
+void freeifaddrs(struct ifaddrs *) {
+	mlibc::infoLogger() << "mlibc: freeifaddrs is a stub!" << frg::endlog;
+	return;
+}
diff --git a/lib/mlibc/options/linux/generic/linux-unistd.cpp b/lib/mlibc/options/linux/generic/linux-unistd.cpp
new file mode 100644
index 0000000..ec13f72
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/linux-unistd.cpp
@@ -0,0 +1,33 @@
+#include <bits/linux/linux_unistd.h>
+#include <bits/ensure.h>
+
+#include <errno.h>
+#include <mlibc/posix-sysdeps.hpp>
+#include <unistd.h>
+
+int dup3(int oldfd, int newfd, int flags) {
+	if(oldfd == newfd) {
+		errno = EINVAL;
+		return -1;
+	}
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_dup2, -1);
+	if(int e = mlibc::sys_dup2(oldfd, flags, newfd); e) {
+		errno = e;
+		return -1;
+	}
+	return newfd;
+}
+
+int vhangup(void) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
+
+int getdtablesize(void){
+	return sysconf(_SC_OPEN_MAX);
+}
+
+int syncfs(int) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
diff --git a/lib/mlibc/options/linux/generic/malloc.cpp b/lib/mlibc/options/linux/generic/malloc.cpp
new file mode 100644
index 0000000..065de6c
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/malloc.cpp
@@ -0,0 +1,7 @@
+#include <bits/ensure.h>
+#include <malloc.h>
+
+void *memalign(size_t, size_t) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
diff --git a/lib/mlibc/options/linux/generic/mntent-stubs.cpp b/lib/mlibc/options/linux/generic/mntent-stubs.cpp
new file mode 100644
index 0000000..35c0e92
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/mntent-stubs.cpp
@@ -0,0 +1,98 @@
+
+#include <errno.h>
+#include <mntent.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <bits/ensure.h>
+
+namespace {
+
+char *internal_buf;
+size_t internal_bufsize;
+
+}
+
+#define SENTINEL (char *)&internal_buf
+
+FILE *setmntent(const char *name, const char *mode) {
+	return fopen(name, mode);
+}
+
+struct mntent *getmntent(FILE *f) {
+	static struct mntent mnt;
+	return getmntent_r(f, &mnt, SENTINEL, 0);
+}
+
+int addmntent(FILE *f, const struct mntent *mnt) {
+	if(fseek(f, 0, SEEK_END)) {
+		return 1;
+	}
+	return fprintf(f, "%s\t%s\t%s\t%s\t%d\t%d\n",
+		mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, mnt->mnt_opts,
+		mnt->mnt_freq, mnt->mnt_passno) < 0;
+}
+
+int endmntent(FILE *f) {
+	if(f) {
+		fclose(f);
+	}
+	return 1;
+}
+
+char *hasmntopt(const struct mntent *mnt, const char *opt) {
+	return strstr(mnt->mnt_opts, opt);
+}
+
+/* Adapted from musl */
+struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen) {
+	int n[8];
+	bool use_internal = (linebuf == SENTINEL);
+	int len;
+	size_t i;
+
+	mnt->mnt_freq = 0;
+	mnt->mnt_passno = 0;
+
+	do {
+		if(use_internal) {
+			getline(&internal_buf, &internal_bufsize, f);
+			linebuf = internal_buf;
+		} else {
+			fgets(linebuf, buflen, f);
+		}
+		if(feof(f) || ferror(f)) {
+			return 0;
+		}
+		if(!strchr(linebuf, '\n')) {
+			fscanf(f, "%*[^\n]%*[\n]");
+			errno = ERANGE;
+			return 0;
+		}
+
+		len = strlen(linebuf);
+		if(len > INT_MAX) {
+			continue;
+		}
+
+		for(i = 0; i < sizeof n / sizeof *n; i++) {
+			n[i] = len;
+		}
+
+		sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
+			n, n + 1, n + 2, n + 3, n + 4, n + 5, n + 6, n + 7,
+			&mnt->mnt_freq, &mnt->mnt_passno);
+	} while(linebuf[n[0]] == '#' || n[1] == len);
+
+	linebuf[n[1]] = 0;
+	linebuf[n[3]] = 0;
+	linebuf[n[5]] = 0;
+	linebuf[n[7]] = 0;
+
+	mnt->mnt_fsname = linebuf + n[0];
+	mnt->mnt_dir = linebuf + n[2];
+	mnt->mnt_type = linebuf + n[4];
+	mnt->mnt_opts = linebuf + n[6];
+
+	return mnt;
+}
diff --git a/lib/mlibc/options/linux/generic/module.cpp b/lib/mlibc/options/linux/generic/module.cpp
new file mode 100644
index 0000000..53b6dc8
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/module.cpp
@@ -0,0 +1,24 @@
+#include <errno.h>
+#include <module.h>
+
+#include <bits/ensure.h>
+#include <mlibc/debug.hpp>
+#include <mlibc/linux-sysdeps.hpp>
+
+int init_module(void *module, unsigned long length, const char *args) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_init_module, -1);
+	if(int e = mlibc::sys_init_module(module, length, args); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
+int delete_module(const char *name, unsigned flags) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_delete_module, -1);
+	if(int e = mlibc::sys_delete_module(name, flags); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
diff --git a/lib/mlibc/options/linux/generic/pty-stubs.cpp b/lib/mlibc/options/linux/generic/pty-stubs.cpp
new file mode 100644
index 0000000..8d95027
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/pty-stubs.cpp
@@ -0,0 +1,101 @@
+
+#include <asm/ioctls.h>
+#include <bits/ensure.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pty.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <mlibc/debug.hpp>
+#include <mlibc/linux-sysdeps.hpp>
+
+int openpty(int *mfd, int *sfd, char *name, const struct termios *ios, const struct winsize *win) {
+	int ptmx_fd;
+	if(int e = mlibc::sys_open("/dev/ptmx", O_RDWR | O_NOCTTY, 0, &ptmx_fd); e) {
+		errno = e;
+		goto fail;
+	}
+
+	char spath[32];
+	if(!name)
+		name = spath;
+	if(ptsname_r(ptmx_fd, name, 32))
+		goto fail;
+
+	int pts_fd;
+	unlockpt(ptmx_fd);
+	if(int e = mlibc::sys_open(name, O_RDWR | O_NOCTTY, 0, &pts_fd); e) {
+		errno = e;
+		goto fail;
+	}
+
+	if(ios)
+		tcsetattr(ptmx_fd, TCSAFLUSH, ios);
+
+	if(win)
+		ioctl(ptmx_fd, TIOCSWINSZ, (void*)win);
+
+	*mfd = ptmx_fd;
+	*sfd = pts_fd;
+	return 0;
+
+fail:
+	mlibc::sys_close(ptmx_fd);
+	return -1;
+}
+
+int login_tty(int fd) {
+	if(setsid() == -1)
+		return -1;
+	if(ioctl(fd, TIOCSCTTY, 0))
+		return -1;
+
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_dup2, -1);
+	if(int e = mlibc::sys_dup2(fd, 0, STDIN_FILENO); e) {
+		errno = e;
+		return -1;
+	}
+	if(int e = mlibc::sys_dup2(fd, 0, STDOUT_FILENO); e) {
+		errno = e;
+		return -1;
+	}
+	if(int e = mlibc::sys_dup2(fd, 0, STDERR_FILENO); e) {
+		errno = e;
+		return -1;
+	}
+
+	if(int e = mlibc::sys_close(fd); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
+int forkpty(int *mfd, char *name, const struct termios *ios, const struct winsize *win) {
+	int sfd;
+	if(openpty(mfd, &sfd, name, ios, win))
+		return -1;
+
+	pid_t child;
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fork, -1);
+	if(int e = mlibc::sys_fork(&child); e) {
+		errno = e;
+		return -1;
+	}
+
+	if(!child) {
+		if(login_tty(sfd))
+			mlibc::panicLogger() << "mlibc: TTY login fail in forkpty() child" << frg::endlog;
+	}else{
+		if(int e = mlibc::sys_close(sfd); e) {
+			errno = e;
+			return -1;
+		}
+	}
+
+	return child;
+}
+
diff --git a/lib/mlibc/options/linux/generic/sched.cpp b/lib/mlibc/options/linux/generic/sched.cpp
new file mode 100644
index 0000000..760a9f5
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sched.cpp
@@ -0,0 +1,50 @@
+#include <bits/ensure.h>
+#include <errno.h>
+#include <sched.h>
+
+#include <mlibc/linux-sysdeps.hpp>
+#include <mlibc/posix-sysdeps.hpp>
+
+int sched_getcpu(void) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getcpu, -1);
+	int cpu;
+	if(int e = mlibc::sys_getcpu(&cpu); e) {
+		errno = e;
+		return -1;
+	}
+	return cpu;
+}
+
+int setns(int, int) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
+
+int sched_getscheduler(pid_t) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
+
+int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getaffinity, -1);
+	if(int e = mlibc::sys_getaffinity(pid, cpusetsize, mask); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
+int unshare(int) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
+
+int sched_setaffinity(pid_t, size_t, const cpu_set_t *) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
+
+int clone(int (*)(void *), void *, int, void *, ...) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
diff --git a/lib/mlibc/options/linux/generic/sys-epoll.cpp b/lib/mlibc/options/linux/generic/sys-epoll.cpp
new file mode 100644
index 0000000..799d1a9
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-epoll.cpp
@@ -0,0 +1,58 @@
+
+#include <errno.h>
+#include <sys/epoll.h>
+
+#include <bits/ensure.h>
+#include <mlibc/linux-sysdeps.hpp>
+#include <stddef.h>
+
+int epoll_create(int) {
+	int fd;
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_epoll_create, -1);
+	if(int e = mlibc::sys_epoll_create(0, &fd); e) {
+		errno = e;
+		return -1;
+	}
+	return fd;
+}
+
+int epoll_pwait(int epfd, struct epoll_event *evnts, int n, int timeout,
+		const sigset_t *sigmask) {
+	int raised;
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_epoll_pwait, -1);
+	if(int e = mlibc::sys_epoll_pwait(epfd, evnts, n, timeout, sigmask, &raised)) {
+		errno = e;
+		return -1;
+	}
+	return raised;
+}
+
+int epoll_create1(int flags) {
+	int fd;
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_epoll_create, -1);
+	if(int e = mlibc::sys_epoll_create(flags, &fd); e) {
+		errno = e;
+		return -1;
+	}
+	return fd;
+}
+
+int epoll_ctl(int epfd, int mode, int fd, struct epoll_event *ev) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_epoll_ctl, -1);
+	if(int e = mlibc::sys_epoll_ctl(epfd, mode, fd, ev); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
+int epoll_wait(int epfd, struct epoll_event *evnts, int n, int timeout) {
+	int raised;
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_epoll_pwait, -1);
+	if(int e = mlibc::sys_epoll_pwait(epfd, evnts, n, timeout, NULL, &raised)) {
+		errno = e;
+		return -1;
+	}
+	return raised;
+}
+
diff --git a/lib/mlibc/options/linux/generic/sys-eventfd.cpp b/lib/mlibc/options/linux/generic/sys-eventfd.cpp
new file mode 100644
index 0000000..1d83d8c
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-eventfd.cpp
@@ -0,0 +1,45 @@
+#include <sys/eventfd.h>
+#include <errno.h>
+
+#include <bits/ensure.h>
+#include <mlibc/linux-sysdeps.hpp>
+
+int eventfd(unsigned int initval, int flags) {
+	int fd = 0;
+
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_eventfd_create, -1);
+	if (int e = mlibc::sys_eventfd_create(initval, flags, &fd); e) {
+		errno = e;
+		return -1;
+	}
+
+	return fd;
+}
+
+int eventfd_read(int fd, eventfd_t *value) {
+	ssize_t bytes_read;
+	if (int e = mlibc::sys_read(fd, value, 8, &bytes_read); e) {
+		errno = e;
+		return -1;
+	}
+
+	if (bytes_read != 8) {
+		return -1;
+	}
+
+	return 0;
+}
+
+int eventfd_write(int fd, eventfd_t value) {
+	ssize_t bytes_written;
+	if (int e = mlibc::sys_write(fd, &value, 8, &bytes_written); e) {
+		errno = e;
+		return -1;
+	}
+
+	if (bytes_written != 8) {
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/lib/mlibc/options/linux/generic/sys-fsuid.cpp b/lib/mlibc/options/linux/generic/sys-fsuid.cpp
new file mode 100644
index 0000000..653456c
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-fsuid.cpp
@@ -0,0 +1,12 @@
+#include <bits/ensure.h>
+#include <sys/fsuid.h>
+
+int setfsuid(uid_t) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
+
+int setfsgid(gid_t) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
diff --git a/lib/mlibc/options/linux/generic/sys-inotify-stubs.cpp b/lib/mlibc/options/linux/generic/sys-inotify-stubs.cpp
new file mode 100644
index 0000000..0bc25c9
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-inotify-stubs.cpp
@@ -0,0 +1,47 @@
+
+#include <errno.h>
+#include <sys/inotify.h>
+
+#include <bits/ensure.h>
+#include <mlibc/debug.hpp>
+#include <mlibc/linux-sysdeps.hpp>
+
+int inotify_init(void) {
+	int fd;
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_inotify_create, -1);
+	if(int e = mlibc::sys_inotify_create(0, &fd); e) {
+		errno = e;
+		return -1;
+	}
+	return fd;
+}
+
+int inotify_init1(int flags) {
+	int fd;
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_inotify_create, -1);
+	if(int e = mlibc::sys_inotify_create(flags, &fd); e) {
+		errno = e;
+		return -1;
+	}
+	return fd;
+}
+
+int inotify_add_watch(int ifd, const char *path, uint32_t mask) {
+	int wd;
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_inotify_add_watch, -1);
+	if(int e = mlibc::sys_inotify_add_watch(ifd, path, mask, &wd); e) {
+		errno = e;
+		return -1;
+	}
+	return wd;
+}
+
+int inotify_rm_watch(int ifd, int wd) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_inotify_rm_watch, -1);
+	if(int e = mlibc::sys_inotify_rm_watch(ifd, wd); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
diff --git a/lib/mlibc/options/linux/generic/sys-klog.cpp b/lib/mlibc/options/linux/generic/sys-klog.cpp
new file mode 100644
index 0000000..059e292
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-klog.cpp
@@ -0,0 +1,16 @@
+#include <errno.h>
+#include <sys/klog.h>
+
+#include <bits/ensure.h>
+
+#include <mlibc/linux-sysdeps.hpp>
+
+int klogctl(int type, char *bufp, int len) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_klogctl, -1);
+	int out;
+	if (int e = mlibc::sys_klogctl(type, bufp, len, &out); e) {
+		errno = e;
+		return -1;
+	}
+	return out;
+}
diff --git a/lib/mlibc/options/linux/generic/sys-mount.cpp b/lib/mlibc/options/linux/generic/sys-mount.cpp
new file mode 100644
index 0000000..4783183
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-mount.cpp
@@ -0,0 +1,29 @@
+
+#include <errno.h>
+#include <sys/mount.h>
+
+#include <bits/ensure.h>
+#include <mlibc/linux-sysdeps.hpp>
+
+int mount(const char *source, const char *target,
+		const char *fstype, unsigned long flags, const void *data) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_mount, -1);
+	if(int e = mlibc::sys_mount(source, target, fstype, flags, data); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
+int umount(const char *target) {
+	return umount2(target, 0);
+}
+
+int umount2(const char *target, int flags) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_umount2, -1);
+	if(int e = mlibc::sys_umount2(target, flags); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
diff --git a/lib/mlibc/options/linux/generic/sys-prctl-stubs.cpp b/lib/mlibc/options/linux/generic/sys-prctl-stubs.cpp
new file mode 100644
index 0000000..5280332
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-prctl-stubs.cpp
@@ -0,0 +1,25 @@
+
+#include <stdarg.h>
+#include <errno.h>
+#include <bits/ensure.h>
+#include <sys/prctl.h>
+
+#include <mlibc/debug.hpp>
+
+#include "mlibc/linux-sysdeps.hpp"
+
+int prctl(int op, ...) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_prctl, -1);
+
+	int val;
+	va_list ap;
+	va_start(ap, op);
+	if(int e = mlibc::sys_prctl(op, ap, &val); e) {
+		errno = e;
+		return -1;
+	}
+	va_end(ap);
+
+	return val;
+}
+
diff --git a/lib/mlibc/options/linux/generic/sys-ptrace-stubs.cpp b/lib/mlibc/options/linux/generic/sys-ptrace-stubs.cpp
new file mode 100644
index 0000000..8c836c5
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-ptrace-stubs.cpp
@@ -0,0 +1,36 @@
+
+#include <sys/ptrace.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include <bits/ensure.h>
+#include <mlibc/debug.hpp>
+#include <mlibc/linux-sysdeps.hpp>
+
+long ptrace(int req, ...) {
+	va_list ap;
+
+	va_start(ap, req);
+	auto pid = va_arg(ap, pid_t);
+	auto addr = va_arg(ap, void *);
+	auto data = va_arg(ap, void *);
+	va_end(ap);
+
+	long ret;
+	if(req > 0 && req < 4) {
+		data = &ret;
+	}
+
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_ptrace, -1);
+	long out;
+	if(int e = mlibc::sys_ptrace(req, pid, addr, data, &out); e) {
+		errno = e;
+		return -1;
+	} else if(req > 0 && req < 4) {
+		errno = 0;
+		return ret;
+	}
+
+	return out;
+}
+
diff --git a/lib/mlibc/options/linux/generic/sys-quota.cpp b/lib/mlibc/options/linux/generic/sys-quota.cpp
new file mode 100644
index 0000000..27c0e6d
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-quota.cpp
@@ -0,0 +1,7 @@
+#include <bits/ensure.h>
+#include <sys/quota.h>
+
+int quotactl(int, const char *, int, caddr_t) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
diff --git a/lib/mlibc/options/linux/generic/sys-random-stubs.cpp b/lib/mlibc/options/linux/generic/sys-random-stubs.cpp
new file mode 100644
index 0000000..5e5057f
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-random-stubs.cpp
@@ -0,0 +1,21 @@
+
+#include <sys/random.h>
+#include <bits/ensure.h>
+
+#include <mlibc/debug.hpp>
+#include <mlibc/posix-sysdeps.hpp>
+
+#include <errno.h>
+
+ssize_t getrandom(void *buffer, size_t max_size, unsigned int flags) {
+	if(flags & ~(GRND_RANDOM | GRND_NONBLOCK)) {
+		errno = EINVAL;
+		return -1;
+	}
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getentropy, -1);
+	if(int e = mlibc::sys_getentropy(buffer, max_size); e) {
+		errno = e;
+		return -1;
+	}
+	return max_size;
+}
diff --git a/lib/mlibc/options/linux/generic/sys-reboot.cpp b/lib/mlibc/options/linux/generic/sys-reboot.cpp
new file mode 100644
index 0000000..c9b503f
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-reboot.cpp
@@ -0,0 +1,13 @@
+#include <errno.h>
+#include <sys/reboot.h>
+#include <bits/ensure.h>
+#include <mlibc/linux-sysdeps.hpp>
+
+int reboot(int what) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_reboot, -1);
+	if (int e = mlibc::sys_reboot(what); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
diff --git a/lib/mlibc/options/linux/generic/sys-sendfile-stubs.cpp b/lib/mlibc/options/linux/generic/sys-sendfile-stubs.cpp
new file mode 100644
index 0000000..25cd0a0
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-sendfile-stubs.cpp
@@ -0,0 +1,9 @@
+
+#include <sys/sendfile.h>
+#include <bits/ensure.h>
+
+ssize_t sendfile(int, int, off_t *, size_t) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
+
diff --git a/lib/mlibc/options/linux/generic/sys-signalfd.cpp b/lib/mlibc/options/linux/generic/sys-signalfd.cpp
new file mode 100644
index 0000000..28cfea0
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-signalfd.cpp
@@ -0,0 +1,17 @@
+
+#include <errno.h>
+#include <sys/signalfd.h>
+
+#include <bits/ensure.h>
+#include <mlibc/linux-sysdeps.hpp>
+
+int signalfd(int fd, const sigset_t *mask, int flags) {
+	__ensure(fd == -1);
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_signalfd_create, -1);
+	if(int e = mlibc::sys_signalfd_create(mask, flags, &fd); e) {
+		errno = e;
+		return -1;
+	}
+	return fd;
+}
+
diff --git a/lib/mlibc/options/linux/generic/sys-statfs-stubs.cpp b/lib/mlibc/options/linux/generic/sys-statfs-stubs.cpp
new file mode 100644
index 0000000..6152ef2
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-statfs-stubs.cpp
@@ -0,0 +1,26 @@
+
+#include <errno.h>
+#include <sys/statfs.h>
+#include <bits/ensure.h>
+
+#include <mlibc/debug.hpp>
+#include <mlibc/linux-sysdeps.hpp>
+
+int statfs(const char *path, struct statfs *buf) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_statfs, -1);
+	if(int e = mlibc::sys_statfs(path, buf); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
+int fstatfs(int fd, struct statfs *buf) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fstatfs, -1);
+	if (int e = mlibc::sys_fstatfs(fd, buf); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
diff --git a/lib/mlibc/options/linux/generic/sys-swap.cpp b/lib/mlibc/options/linux/generic/sys-swap.cpp
new file mode 100644
index 0000000..44ddf98
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-swap.cpp
@@ -0,0 +1,24 @@
+#include <errno.h>
+#include <sys/swap.h>
+
+#include <bits/ensure.h>
+#include <mlibc/debug.hpp>
+#include <mlibc/linux-sysdeps.hpp>
+
+int swapon(const char *path, int flags) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_swapon, -1);
+	if(int e = mlibc::sys_swapon(path, flags); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
+int swapoff(const char *path) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_swapoff, -1);
+	if(int e = mlibc::sys_swapoff(path); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
diff --git a/lib/mlibc/options/linux/generic/sys-sysinfo.cpp b/lib/mlibc/options/linux/generic/sys-sysinfo.cpp
new file mode 100644
index 0000000..950c38a
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-sysinfo.cpp
@@ -0,0 +1,15 @@
+#include <errno.h>
+#include <sys/sysinfo.h>
+
+#include <bits/ensure.h>
+#include <mlibc/debug.hpp>
+#include <mlibc/linux-sysdeps.hpp>
+
+int sysinfo(struct sysinfo *info) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_sysinfo, -1);
+	if(int e = mlibc::sys_sysinfo(info); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
diff --git a/lib/mlibc/options/linux/generic/sys-timerfd.cpp b/lib/mlibc/options/linux/generic/sys-timerfd.cpp
new file mode 100644
index 0000000..80bca1b
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-timerfd.cpp
@@ -0,0 +1,33 @@
+
+#include <errno.h>
+#include <sys/timerfd.h>
+
+#include <bits/ensure.h>
+#include <mlibc/debug.hpp>
+#include <mlibc/linux-sysdeps.hpp>
+
+int timerfd_create(int clockid, int flags) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_timerfd_create, -1);
+	int fd;
+	if(int e = mlibc::sys_timerfd_create(clockid, flags, &fd); e) {
+		errno = e;
+		return -1;
+	}
+	return fd;
+}
+
+int timerfd_settime(int fd, int flags, const struct itimerspec *value,
+		struct itimerspec *oldvalue) {
+	MLIBC_CHECK_OR_ENOSYS(mlibc::sys_timerfd_settime, -1);
+	if(int e = mlibc::sys_timerfd_settime(fd, flags, value, oldvalue); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
+int timerfd_gettime(int, struct itimerspec *) {
+	__ensure(!"Not implemented");
+	__builtin_unreachable();
+}
+
diff --git a/lib/mlibc/options/linux/generic/sys-xattr.cpp b/lib/mlibc/options/linux/generic/sys-xattr.cpp
new file mode 100644
index 0000000..c8d598f
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/sys-xattr.cpp
@@ -0,0 +1,122 @@
+#include <errno.h>
+#include <sys/xattr.h>
+
+#include <mlibc/linux-sysdeps.hpp>
+#include <bits/ensure.h>
+
+int setxattr(const char *path, const char *name, const void *val, size_t size,
+		int flags) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setxattr, -1);
+
+	if (int e = sysdep(path, name, val, size, flags); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
+int lsetxattr(const char *path, const char *name, const void *val, size_t size,
+		int flags) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_lsetxattr, -1);
+
+	if (int e = sysdep(path, name, val, size, flags); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
+int fsetxattr(int fd, const char *name, const void *val, size_t size,
+		int flags) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fsetxattr, -1);
+
+	if (int e = sysdep(fd, name, val, size, flags); e) {
+		errno = e;
+		return -1;
+	}
+	return 0;
+}
+
+ssize_t getxattr(const char *path, const char *name, void *val, size_t size) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getxattr, -1);
+
+	ssize_t nread;
+	if (int e = sysdep(path, name, val, size, &nread); e) {
+		errno = e;
+		return -1;
+	}
+
+	return nread;
+}
+
+ssize_t lgetxattr(const char *path, const char *name, void *val, size_t size) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_lgetxattr, -1);
+
+	ssize_t nread;
+	if (int e = sysdep(path, name, val, size, &nread); e) {
+		errno = e;
+		return -1;
+	}
+
+	return nread;
+}
+
+ssize_t fgetxattr(int fd, const char *name, void *val, size_t size) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fgetxattr, -1);
+
+	ssize_t nread;
+	if (int e = sysdep(fd, name, val, size, &nread); e) {
+		errno = e;
+		return -1;
+	}
+
+	return nread;
+}
+
+int removexattr(const char *path, const char *name) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_removexattr, -1);
+	return sysdep(path, name);
+}
+
+int lremovexattr(const char *path, const char *name) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_lremovexattr, -1);
+	return sysdep(path, name);
+}
+
+int fremovexattr(int fd, const char *name) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fremovexattr, -1);
+	return sysdep(fd, name);
+}
+
+ssize_t listxattr(const char *path, char *list, size_t size) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_listxattr, -1);
+
+	ssize_t nread;
+	if (int e = sysdep(path, list, size, &nread); e) {
+		errno = e;
+		return -1;
+	}
+	return nread;
+}
+
+ssize_t llistxattr(const char *path, char *list, size_t size) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_llistxattr, -1);
+
+	ssize_t nread;
+	if (int e = sysdep(path, list, size, &nread); e) {
+		errno = e;
+		return -1;
+	}
+	return nread;
+}
+
+ssize_t flistxattr(int fd, char *list, size_t size) {
+	auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_flistxattr, -1);
+
+	ssize_t nread;
+	if (int e = sysdep(fd, list, size, &nread); e) {
+		errno = e;
+		return -1;
+	}
+	return nread;
+}
diff --git a/lib/mlibc/options/linux/generic/utmp-stubs.cpp b/lib/mlibc/options/linux/generic/utmp-stubs.cpp
new file mode 100644
index 0000000..658dfd3
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/utmp-stubs.cpp
@@ -0,0 +1,116 @@
+#include <utmp.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <bits/ensure.h>
+#include <mlibc/debug.hpp>
+
+/*
+ * The code in this file is largely based on glibc.
+ * This includes:
+ * - setutent
+ * - read_last_entry
+ * - getutent
+ * - getutent_r
+ * - endutent
+ */
+static int fd = -1;
+static off_t offset;
+
+static struct utmp last_entry;
+
+void setutent(void) {
+	if(fd < 0) {
+		fd = open("/run/utmp", O_RDONLY | O_LARGEFILE | O_CLOEXEC);
+		if(fd == -1) {
+			return;
+		}
+	}
+
+	lseek(fd, 0, SEEK_SET);
+	offset = 0;
+}
+
+static ssize_t read_last_entry(void) {
+	struct utmp buf;
+	ssize_t bytes_read = pread(fd, &buf, sizeof(buf), offset);
+
+	if(bytes_read < 0) {
+		return -1;
+	} else if(bytes_read != sizeof(buf)) {
+		// EOF
+		return 0;
+	} else {
+		last_entry = buf;
+		offset += sizeof(buf);
+		return 1;
+	}
+}
+
+struct utmp *getutent(void) {
+	struct utmp *result;
+	static struct utmp *buf;
+	if(buf == NULL) {
+		buf = (struct utmp *)malloc(sizeof(struct utmp));
+		if(buf == NULL) {
+			return NULL;
+		}
+	}
+
+	if(getutent_r(buf, &result) < 0) {
+		return NULL;
+	}
+	return result;
+}
+
+int getutent_r(struct utmp *buf, struct utmp **res) {
+	int saved_errno = errno;
+
+	if(fd < 0) {
+		setutent();
+	}
+
+	ssize_t bytes_read = read_last_entry();
+
+	if(bytes_read <= 0) {
+		if(bytes_read == 0) {
+			errno = saved_errno;
+			*res = NULL;
+			return -1;
+		}
+	}
+
+	memcpy(buf, &last_entry, sizeof(struct utmp));
+	*res = buf;
+
+	return 0;
+}
+
+void endutent(void) {
+	if(fd >= 0) {
+		close(fd);
+		fd = -1;
+	}
+}
+
+struct utmp *pututline(const struct utmp *) {
+	mlibc::infoLogger() << "\e[31mmlibc: pututline() is a stub!\e[39m" << frg::endlog;
+	return NULL;
+}
+
+struct utmp *getutline(const struct utmp *) {
+	mlibc::infoLogger() << "\e[31mmlibc: getutline() is a stub!\e[39m" << frg::endlog;
+	return NULL;
+}
+
+int utmpname(const char *) {
+	mlibc::infoLogger() << "\e[31mmlibc: utmpname() is a stub!\e[39m" << frg::endlog;
+	return -1;
+}
+
+struct utmp *getutid(const struct utmp *) {
+	mlibc::infoLogger() << "\e[31mmlibc: getutid() is a stub!\e[39m" << frg::endlog;
+	return NULL;
+}
diff --git a/lib/mlibc/options/linux/generic/utmpx.cpp b/lib/mlibc/options/linux/generic/utmpx.cpp
new file mode 100644
index 0000000..4742567
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/utmpx.cpp
@@ -0,0 +1,45 @@
+#include <bits/ensure.h>
+#include <stddef.h>
+#include <errno.h>
+#include <utmpx.h>
+#include <mlibc/debug.hpp>
+
+void updwtmpx(const char *, const struct utmpx *) {
+	// Empty as musl does
+	mlibc::infoLogger() << "\e[31mmlibc: updwtmpx() is a stub\e[39m" << frg::endlog;
+}
+
+void endutxent(void) {
+	// Empty as musl does
+	mlibc::infoLogger() << "\e[31mmlibc: endutxent() is a stub\e[39m" << frg::endlog;
+}
+
+void setutxent(void) {
+	// Empty as musl does
+	mlibc::infoLogger() << "\e[31mmlibc: setutxent() is a stub\e[39m" << frg::endlog;
+}
+
+struct utmpx *getutxent(void) {
+	// return NULL as musl does
+	mlibc::infoLogger() << "\e[31mmlibc: getutxent() is a stub\e[39m" << frg::endlog;
+	return NULL;
+}
+
+struct utmpx *pututxline(const struct utmpx *) {
+	// return NULL as musl does
+	mlibc::infoLogger() << "\e[31mmlibc: pututxline() is a stub\e[39m" << frg::endlog;
+	return NULL;
+}
+
+int utmpxname(const char *) {
+	// return -1 as musl does
+	mlibc::infoLogger() << "\e[31mmlibc: utmpxname() is a stub\e[39m" << frg::endlog;
+	errno = ENOSYS;
+	return -1;
+}
+
+struct utmpx *getutxid(const struct utmpx *) {
+	// return NULL as musl does
+	mlibc::infoLogger() << "\e[31mmlibc: getutxid() is a stub\e[39m" << frg::endlog;
+	return NULL;
+}
-- 
cgit v1.2.3