aboutsummaryrefslogtreecommitdiff
path: root/lib/mlibc/options/posix/generic
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mlibc/options/posix/generic')
-rw-r--r--lib/mlibc/options/posix/generic/arpa-inet-stubs.cpp220
-rw-r--r--lib/mlibc/options/posix/generic/dirent-stubs.cpp180
-rw-r--r--lib/mlibc/options/posix/generic/dlfcn-stubs.cpp64
-rw-r--r--lib/mlibc/options/posix/generic/fcntl-stubs.cpp108
-rw-r--r--lib/mlibc/options/posix/generic/ftw-stubs.cpp18
-rw-r--r--lib/mlibc/options/posix/generic/grp-stubs.cpp316
-rw-r--r--lib/mlibc/options/posix/generic/langinfo-stubs.cpp15
-rw-r--r--lib/mlibc/options/posix/generic/libgen-stubs.cpp51
-rw-r--r--lib/mlibc/options/posix/generic/lookup.cpp512
-rw-r--r--lib/mlibc/options/posix/generic/mqueue.cpp22
-rw-r--r--lib/mlibc/options/posix/generic/net-if-stubs.cpp40
-rw-r--r--lib/mlibc/options/posix/generic/netdb-stubs.cpp486
-rw-r--r--lib/mlibc/options/posix/generic/poll.cpp31
-rw-r--r--lib/mlibc/options/posix/generic/posix-file-io.cpp275
-rw-r--r--lib/mlibc/options/posix/generic/posix_ctype.cpp136
-rw-r--r--lib/mlibc/options/posix/generic/posix_locale.cpp37
-rw-r--r--lib/mlibc/options/posix/generic/posix_signal.cpp151
-rw-r--r--lib/mlibc/options/posix/generic/posix_stdio.cpp209
-rw-r--r--lib/mlibc/options/posix/generic/posix_stdlib.cpp513
-rw-r--r--lib/mlibc/options/posix/generic/posix_string.cpp174
-rw-r--r--lib/mlibc/options/posix/generic/posix_time.cpp32
-rw-r--r--lib/mlibc/options/posix/generic/pthread-stubs.cpp1426
-rw-r--r--lib/mlibc/options/posix/generic/pwd-stubs.cpp284
-rw-r--r--lib/mlibc/options/posix/generic/resolv_conf.cpp42
-rw-r--r--lib/mlibc/options/posix/generic/sched-stubs.cpp50
-rw-r--r--lib/mlibc/options/posix/generic/search.cpp151
-rw-r--r--lib/mlibc/options/posix/generic/semaphore-stubs.cpp114
-rw-r--r--lib/mlibc/options/posix/generic/services.cpp222
-rw-r--r--lib/mlibc/options/posix/generic/spawn-stubs.cpp376
-rw-r--r--lib/mlibc/options/posix/generic/strings-stubs.cpp107
-rw-r--r--lib/mlibc/options/posix/generic/sys-file-stubs.cpp16
-rw-r--r--lib/mlibc/options/posix/generic/sys-ipc.cpp8
-rw-r--r--lib/mlibc/options/posix/generic/sys-mman-stubs.cpp177
-rw-r--r--lib/mlibc/options/posix/generic/sys-msg.cpp23
-rw-r--r--lib/mlibc/options/posix/generic/sys-resource-stubs.cpp57
-rw-r--r--lib/mlibc/options/posix/generic/sys-select-stubs.cpp58
-rw-r--r--lib/mlibc/options/posix/generic/sys-sem.cpp51
-rw-r--r--lib/mlibc/options/posix/generic/sys-shm.cpp24
-rw-r--r--lib/mlibc/options/posix/generic/sys-socket-stubs.cpp225
-rw-r--r--lib/mlibc/options/posix/generic/sys-stat-stubs.cpp155
-rw-r--r--lib/mlibc/options/posix/generic/sys-statvfs-stubs.cpp24
-rw-r--r--lib/mlibc/options/posix/generic/sys-time-stubs.cpp107
-rw-r--r--lib/mlibc/options/posix/generic/sys-times.cpp19
-rw-r--r--lib/mlibc/options/posix/generic/sys-uio.cpp67
-rw-r--r--lib/mlibc/options/posix/generic/sys-utsname.cpp24
-rw-r--r--lib/mlibc/options/posix/generic/sys-wait-stubs.cpp52
-rw-r--r--lib/mlibc/options/posix/generic/syslog-stubs.cpp152
-rw-r--r--lib/mlibc/options/posix/generic/termios-stubs.cpp103
-rw-r--r--lib/mlibc/options/posix/generic/time.cpp505
-rw-r--r--lib/mlibc/options/posix/generic/ucontext-stubs.cpp19
-rw-r--r--lib/mlibc/options/posix/generic/unistd-stubs.cpp1227
-rw-r--r--lib/mlibc/options/posix/generic/utime-stubs.cpp31
-rw-r--r--lib/mlibc/options/posix/generic/wordexp-stubs.cpp342
53 files changed, 0 insertions, 9828 deletions
diff --git a/lib/mlibc/options/posix/generic/arpa-inet-stubs.cpp b/lib/mlibc/options/posix/generic/arpa-inet-stubs.cpp
deleted file mode 100644
index 0bc9727..0000000
--- a/lib/mlibc/options/posix/generic/arpa-inet-stubs.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-
-#include <arpa/inet.h>
-#include <bits/ensure.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <mlibc/bitutil.hpp>
-#include <mlibc/debug.hpp>
-
-const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
-const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
-
-uint32_t htonl(uint32_t x) {
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- return mlibc::bit_util<uint32_t>::byteswap(x);
-#else
- return x;
-#endif
-}
-uint16_t htons(uint16_t x) {
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- return mlibc::bit_util<uint16_t>::byteswap(x);
-#else
- return x;
-#endif
-}
-uint32_t ntohl(uint32_t x) {
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- return mlibc::bit_util<uint32_t>::byteswap(x);
-#else
- return x;
-#endif
-}
-uint16_t ntohs(uint16_t x) {
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- return mlibc::bit_util<uint16_t>::byteswap(x);
-#else
- return x;
-#endif
-}
-
-// ----------------------------------------------------------------------------
-// IPv4 address manipulation.
-// ----------------------------------------------------------------------------
-in_addr_t inet_addr(const char *p) {
- struct in_addr a;
- if(!inet_aton(p, &a))
- return -1;
- return a.s_addr;
-}
-char *inet_ntoa(struct in_addr addr) {
- // string: xxx.yyy.zzz.aaa
- // 4 * 3 + 3 + 1 = 12 + 4 = 16
- thread_local static char buffer[16];
- uint32_t proper = htonl(addr.s_addr);
- snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d",
- (proper >> 24) & 0xff, ((proper >> 16) & 0xff),
- (proper >> 8) & 0xff, proper & 0xff);
- return buffer;
-}
-int inet_aton(const char *string, struct in_addr *dest) {
- int array[4];
- int i = 0;
- char *end;
-
- for (; i < 4; i++) {
- array[i] = strtoul(string, &end, 0);
- if (*end && *end != '.')
- return 0;
- if (!*end)
- break;
- string = end + 1;
- }
-
- switch (i) {
- case 0:
- dest->s_addr = htonl(array[0]);
- break;
- case 1:
- if (array[0] > 255 || array[1] > 0xffffff)
- return 0;
- dest->s_addr = htonl((array[0] << 24) | array[1]);
- break;
- case 2:
- if (array[0] > 255 || array[1] > 255 ||
- array[2] > 0xffff)
- return 0;
- dest->s_addr = htonl((array[0] << 24) | (array[1] << 16) |
- array[2]);
- break;
- case 3:
- if (array[0] > 255 || array[1] > 255 ||
- array[2] > 255 || array[3] > 255)
- return 0;
- dest->s_addr = htonl((array[0] << 24) | (array[1] << 16) |
- (array[2] << 8) | array[3]);
- break;
- }
-
- return 1;
-}
-
-// ----------------------------------------------------------------------------
-// Generic IP address manipulation.
-// ----------------------------------------------------------------------------
-const char *inet_ntop(int af, const void *__restrict src, char *__restrict dst,
- socklen_t size) {
- switch (af) {
- case AF_INET: {
- auto source = reinterpret_cast<const struct in_addr*>(src);
- if (snprintf(dst, size, "%d.%d.%d.%d",
- source->s_addr & 0xff,
- (source->s_addr & 0xffff) >> 8,
- (source->s_addr & 0xffffff) >> 16,
- source->s_addr >> 24) < (int)size)
- return dst;
- break;
- }
- case AF_INET6: {
- auto source = reinterpret_cast<const struct in6_addr*>(src);
- size_t cur_zeroes_off = 0;
- size_t cur_zeroes_len = 0;
- size_t max_zeroes_off = 0;
- size_t max_zeroes_len = 0;
-
- /* we look for the largest block of zeroed quartet(s) */
- for(size_t i = 0; i < 8; i++) {
- auto ptr = source->s6_addr + (i * 2);
- if(!ptr[0] && !ptr[1]) {
- cur_zeroes_len++;
- if(max_zeroes_len < cur_zeroes_len) {
- max_zeroes_len = cur_zeroes_len;
- max_zeroes_off = cur_zeroes_off;
- }
- } else {
- /* advance the offset to the next quartet to check */
- cur_zeroes_len = 0;
- cur_zeroes_off = i + 1;
- }
- }
-
- size_t off = 0;
- for(size_t i = 0; i < 8; i++) {
- auto ptr = source->s6_addr + (i * 2);
-
- /* if we are at the beginning of the largest block of zeroed quartets, place "::" */
- if(i == max_zeroes_off && max_zeroes_len >= 2) {
- if(off < size) {
- dst[off++] = ':';
- }
- if(off < size) {
- dst[off++] = ':';
- }
- i += max_zeroes_len - 1;
-
- continue;
- }
-
- /* place a colon if we're not at the beginning of the string and it is not already there */
- if(off && dst[off - 1] != ':') {
- if(off < size) {
- dst[off++] = ':';
- }
- }
-
- off += snprintf(dst + off, size - off, "%x", ptr[0] << 8 | ptr[1]);
- }
-
- dst[off] = 0;
-
- return dst;
- }
- default:
- errno = EAFNOSUPPORT;
- return NULL;
- }
-
- errno = ENOSPC;
- return NULL;
-}
-int inet_pton(int af, const char *__restrict src, void *__restrict dst) {
- switch (af) {
- case AF_INET: {
- uint8_t array[4] = {};
- for (int i = 0; i < 4; i++) {
- char *end;
- long int value = strtol(src, &end, 10);
- if (value > 255)
- return 0;
- if (*end != '\0' && *end != '.')
- return 0;
- src = end + 1;
- array[i] = value;
- }
- auto addr = reinterpret_cast<struct in_addr*>(dst);
- memcpy(&addr->s_addr, array, 4);
- break;
- }
- case AF_INET6:
- mlibc::infoLogger() << "inet_pton: ipv6 is not implemented!" << frg::endlog;
- /* fallthrough */
- default:
- errno = EAFNOSUPPORT;
- return -1;
- }
-
- return 1;
-}
-
-struct in_addr inet_makeaddr(in_addr_t, in_addr_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-in_addr_t inet_netof(struct in_addr) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/dirent-stubs.cpp b/lib/mlibc/options/posix/generic/dirent-stubs.cpp
deleted file mode 100644
index 1352585..0000000
--- a/lib/mlibc/options/posix/generic/dirent-stubs.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-
-#include <errno.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-
-#include <bits/ensure.h>
-#include <frg/allocation.hpp>
-#include <mlibc/allocator.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-#include <mlibc/debug.hpp>
-
-// Code taken from musl
-int alphasort(const struct dirent **a, const struct dirent **b) {
- return strcoll((*a)->d_name, (*b)->d_name);
-}
-
-int closedir(DIR *dir) {
- // TODO: Deallocate the dir structure.
- close(dir->__handle);
- return 0;
-}
-int dirfd(DIR *dir) {
- return dir->__handle;
-}
-DIR *fdopendir(int fd) {
- struct stat st;
-
- if(fstat(fd, &st) < 0) {
- return nullptr;
- }
- // Musl implements this, but O_PATH is only declared on the linux abi
- /*if(fcntl(fd, F_GETFL) & O_PATH) {
- errno = EBADF;
- return nullptr;
- }*/
- if(!S_ISDIR(st.st_mode)) {
- errno = ENOTDIR;
- return nullptr;
- }
- auto dir = frg::construct<__mlibc_dir_struct>(getAllocator());
- __ensure(dir);
- dir->__ent_next = 0;
- dir->__ent_limit = 0;
- int flags = fcntl(fd, F_GETFD);
- fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
- dir->__handle = fd;
- return dir;
-}
-DIR *opendir(const char *path) {
- auto dir = frg::construct<__mlibc_dir_struct>(getAllocator());
- __ensure(dir);
- dir->__ent_next = 0;
- dir->__ent_limit = 0;
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_open_dir, nullptr);
- if(int e = mlibc::sys_open_dir(path, &dir->__handle); e) {
- errno = e;
- frg::destruct(getAllocator(), dir);
- return nullptr;
- }else{
- return dir;
- }
-}
-struct dirent *readdir(DIR *dir) {
- __ensure(dir->__ent_next <= dir->__ent_limit);
- if(dir->__ent_next == dir->__ent_limit) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_read_entries, nullptr);
- if(int e = mlibc::sys_read_entries(dir->__handle, dir->__ent_buffer, 2048, &dir->__ent_limit); e)
- __ensure(!"mlibc::sys_read_entries() failed");
- dir->__ent_next = 0;
- if(!dir->__ent_limit)
- return nullptr;
- }
-
- auto entp = reinterpret_cast<struct dirent *>(dir->__ent_buffer + dir->__ent_next);
- // We only copy as many bytes as we need to avoid buffer-overflows.
- memcpy(&dir->__current, entp, offsetof(struct dirent, d_name) + strlen(entp->d_name) + 1);
- dir->__ent_next += entp->d_reclen;
- return &dir->__current;
-}
-int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result) {
- if(!mlibc::sys_read_entries) {
- MLIBC_MISSING_SYSDEP();
- return ENOSYS;
- }
-
- __ensure(dir->__ent_next <= dir->__ent_limit);
- if(dir->__ent_next == dir->__ent_limit) {
- if(int e = mlibc::sys_read_entries(dir->__handle, dir->__ent_buffer, 2048, &dir->__ent_limit); e)
- __ensure(!"mlibc::sys_read_entries() failed");
- dir->__ent_next = 0;
- if(!dir->__ent_limit) {
- *result = NULL;
- return 0;
- }
- }
-
- auto entp = reinterpret_cast<struct dirent *>(dir->__ent_buffer + dir->__ent_next);
- // We only copy as many bytes as we need to avoid buffer-overflows.
- memcpy(entry, entp, offsetof(struct dirent, d_name) + strlen(entp->d_name) + 1);
- dir->__ent_next += entp->d_reclen;
- *result = entry;
- return 0;
-}
-
-void rewinddir(DIR *dir) {
- lseek(dir->__handle, 0, SEEK_SET);
- dir->__ent_next = 0;
-}
-
-int scandir(const char *path, struct dirent ***res, int (*select)(const struct dirent *),
- int (*compare)(const struct dirent **, const struct dirent **)) {
- DIR *dir = opendir(path);
- if (!dir)
- return -1; // errno will be set by opendir()
-
- // we should save the errno
- int old_errno = errno;
- errno = 0;
-
- struct dirent *dir_ent;
- struct dirent **array = nullptr, **tmp = nullptr;
- int length = 0;
- int count = 0;
- while((dir_ent = readdir(dir)) && !errno) {
- if(select && !select(dir_ent))
- continue;
-
- if(count >= length) {
- length = 2*length + 1;
- tmp = static_cast<struct dirent**>(realloc(array,
- length * sizeof(struct dirent*)));
- // we need to check the call actually goes through
- // before we overwrite array so that we can
- // deallocate the already written entries should realloc()
- // have failed
- if(!tmp)
- break;
- array = tmp;
- }
- array[count] = static_cast<struct dirent*>(malloc(dir_ent->d_reclen));
- if(!array[count])
- break;
-
- memcpy(array[count], dir_ent, dir_ent->d_reclen);
- count++;
- }
-
- if(errno) {
- if(array)
- while(count-- > 0)
- free(array[count]);
- free(array);
- return -1;
- }
-
- // from here we can set the old errno back
- errno = old_errno;
-
- if(compare)
- qsort(array, count, sizeof(struct dirent*),
- (int (*)(const void *, const void *)) compare);
- *res = array;
- return count;
-}
-void seekdir(DIR *, long) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-long telldir(DIR *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int versionsort(const struct dirent **a, const struct dirent **b) {
- return strverscmp((*a)->d_name, (*b)->d_name);
-}
diff --git a/lib/mlibc/options/posix/generic/dlfcn-stubs.cpp b/lib/mlibc/options/posix/generic/dlfcn-stubs.cpp
deleted file mode 100644
index fc9fd84..0000000
--- a/lib/mlibc/options/posix/generic/dlfcn-stubs.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-
-#include <bits/ensure.h>
-#include <dlfcn.h>
-
-#include <mlibc/debug.hpp>
-
-struct __dlapi_symbol {
- const char *file;
- void *base;
- const char *symbol;
- void *address;
-};
-
-extern "C" const char *__dlapi_error();
-extern "C" void *__dlapi_open(const char *, int, void *);
-extern "C" void *__dlapi_resolve(void *, const char *, void *);
-extern "C" int __dlapi_reverse(const void *, __dlapi_symbol *);
-extern "C" int __dlapi_close(void *);
-
-int dlclose(void *handle) {
- return __dlapi_close(handle);
-}
-
-char *dlerror(void) {
- return const_cast<char *>(__dlapi_error());
-}
-
-[[gnu::noinline]]
-void *dlopen(const char *file, int flags) {
- auto ra = __builtin_extract_return_addr(__builtin_return_address(0));
- return __dlapi_open(file, flags, ra);
-}
-
-[[gnu::noinline]]
-void *dlsym(void *__restrict handle, const char *__restrict string) {
- auto ra = __builtin_extract_return_addr(__builtin_return_address(0));
- return __dlapi_resolve(handle, string, ra);
-}
-
-[[gnu::noinline]]
-void *dlvsym(void *__restrict handle, const char *__restrict string, const char *__restrict version) {
- mlibc::infoLogger() << "mlibc: dlvsym ignores version " << version << frg::endlog;
- auto ra = __builtin_extract_return_addr(__builtin_return_address(0));
- return __dlapi_resolve(handle, string, ra);
-}
-
-//gnu extensions
-int dladdr(const void *ptr, Dl_info *out) {
- __dlapi_symbol info;
- if(__dlapi_reverse(ptr, &info))
- return 0;
-
- out->dli_fname = info.file;
- out->dli_fbase = info.base;
- out->dli_sname = info.symbol;
- out->dli_saddr = info.address;
- return 1;
-}
-
-int dlinfo(void *, int, void *) {
- __ensure(!"dlinfo() not implemented");
- __builtin_unreachable();
-}
-
diff --git a/lib/mlibc/options/posix/generic/fcntl-stubs.cpp b/lib/mlibc/options/posix/generic/fcntl-stubs.cpp
deleted file mode 100644
index 66e2d12..0000000
--- a/lib/mlibc/options/posix/generic/fcntl-stubs.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-
-#include <errno.h>
-#include <bits/ensure.h>
-#include <fcntl.h>
-#include <stdarg.h>
-
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-int creat(const char *pathname, mode_t mode) {
- return open(pathname, O_CREAT|O_WRONLY|O_TRUNC, mode);
-}
-
-int fallocate(int, int, off_t, off_t) {
- mlibc::infoLogger() << "mlibc: fallocate() is a no-op" << frg::endlog;
- errno = ENOSYS;
- return -1;
-}
-
-int fcntl(int fd, int command, ...) {
- va_list args;
- va_start(args, command);
- int result;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fcntl, -1);
- if(int e = mlibc::sys_fcntl(fd, command, args, &result); e) {
- errno = e;
- return -1;
- }
- va_end(args);
- return result;
-}
-
-int openat(int dirfd, const char *pathname, int flags, ...) {
- va_list args;
- va_start(args, flags);
- mode_t mode = 0;
- int fd;
-
- if((flags & (O_CREAT | O_TMPFILE)))
- mode = va_arg(args, mode_t);
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_openat, -1);
- if(int e = mlibc::sys_openat(dirfd, pathname, flags, mode, &fd); e) {
- errno = e;
- return -1;
- }
- va_end(args);
- return fd;
-}
-
-int posix_fadvise(int fd, off_t offset, off_t length, int advice) {
- if(!mlibc::sys_fadvise) {
- mlibc::infoLogger() << "mlibc: fadvise() ignored due to missing sysdep" << frg::endlog;
- return 0;
- }
-
- // posix_fadvise() returns an error instead of setting errno.
- return mlibc::sys_fadvise(fd, offset, length, advice);
-}
-
-int posix_fallocate(int fd, off_t offset, off_t size) {
- // posix_fallocate() returns an error instead of setting errno.
- if(!mlibc::sys_fallocate) {
- MLIBC_MISSING_SYSDEP();
- return ENOSYS;
- }
- return mlibc::sys_fallocate(fd, offset, size);
-}
-
-// This is a linux extension
-int name_to_handle_at(int, const char *, struct file_handle *, int *, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int open_by_handle_at(int, struct file_handle *, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-ssize_t splice(int, off_t *, int, off_t *, size_t, unsigned int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-ssize_t vmsplice(int, const struct iovec *, size_t, unsigned int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int open(const char *pathname, int flags, ...) {
- mode_t mode = 0;
-
- if ((flags & O_CREAT) || (flags & O_TMPFILE)) {
- va_list args;
- va_start(args, flags);
- mode = va_arg(args, mode_t);
- va_end(args);
- }
-
- int fd;
- if(int e = mlibc::sys_open(pathname, flags, mode, &fd); e) {
- errno = e;
- return -1;
- }
- return fd;
-}
-
diff --git a/lib/mlibc/options/posix/generic/ftw-stubs.cpp b/lib/mlibc/options/posix/generic/ftw-stubs.cpp
deleted file mode 100644
index 2d93995..0000000
--- a/lib/mlibc/options/posix/generic/ftw-stubs.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#include <ftw.h>
-
-#include <bits/ensure.h>
-
-int ftw(const char *, int (*fn)(const char *, const struct stat *, int), int) {
- (void)fn;
- __ensure(!"ftw() not implemented");
- __builtin_unreachable();
-}
-
-int nftw(const char *, int (*fn)(const char *, const struct stat *, int, struct FTW *),
- int, int) {
- (void)fn;
- __ensure(!"nftw() not implemented");
- __builtin_unreachable();
-}
-
diff --git a/lib/mlibc/options/posix/generic/grp-stubs.cpp b/lib/mlibc/options/posix/generic/grp-stubs.cpp
deleted file mode 100644
index f8b2813..0000000
--- a/lib/mlibc/options/posix/generic/grp-stubs.cpp
+++ /dev/null
@@ -1,316 +0,0 @@
-
-#include <grp.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <bits/ensure.h>
-
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-namespace {
- FILE *global_file;
-
- bool open_global_file() {
- if(!global_file) {
- global_file = fopen("/etc/group", "r");
- if(!global_file) {
- errno = EIO;
- return false;
- }
- }
-
- return true;
- }
-
- void close_global_file() {
- if(global_file) {
- fclose(global_file);
- global_file = nullptr;
- }
- }
-
- template<typename F>
- void walk_segments(frg::string_view line, char delimiter, F fn) {
- size_t s = 0;
- while(true) {
- size_t d = line.find_first(delimiter, s);
- if(d == size_t(-1))
- break;
- auto chunk = line.sub_string(s, d - s);
- fn(chunk);
- s = d + 1;
- }
- if(line[s]) {
- auto chunk = line.sub_string(s, line.size() - s);
-
- if (chunk.size() > 0) {
- // Remove trailing newline
- if (chunk[chunk.size() - 1] == '\n')
- chunk = chunk.sub_string(0, chunk.size() - 1);
-
- fn(chunk);
- }
- }
- }
-
- bool extract_entry(frg::string_view line, group *entry) {
- frg::string_view segments[5];
-
- // Parse the line into 3 or 4 segments (depending if the group has members or not)
- int n = 0;
- walk_segments(line, ':', [&] (frg::string_view s) {
- __ensure(n < 4);
- segments[n++] = s;
- });
-
- if(n < 3) // n can be 3 when there are no members in the group
- return false;
-
- // TODO: Handle strndup() and malloc() failure.
- auto name = strndup(segments[0].data(), segments[0].size());
- __ensure(name);
-
- auto passwd = strndup(segments[1].data(), segments[1].size());
-
- auto gid = segments[2].to_number<int>();
- if(!gid)
- return false;
-
- size_t n_members = 0;
- walk_segments(segments[3], ',', [&] (frg::string_view) {
- n_members++;
- });
-
- auto members = reinterpret_cast<char **>(malloc(sizeof(char *) * (n_members + 1)));
- __ensure(members);
- size_t k = 0;
- walk_segments(segments[3], ',', [&] (frg::string_view m) {
- members[k] = strndup(m.data(), m.size());
- __ensure(members[k]);
- k++;
- });
- members[k] = nullptr;
-
- entry->gr_name = name;
- entry->gr_passwd = passwd;
- entry->gr_gid = *gid;
- entry->gr_mem = members;
- return true;
- }
-
- void clear_entry(group *entry) {
- free(entry->gr_name);
- if(entry->gr_mem) {
- for(size_t i = 0; entry->gr_mem[i]; i++)
- free(entry->gr_mem[i]);
- free(entry->gr_mem);
- }
- entry->gr_name = nullptr;
- entry->gr_mem = nullptr;
- }
-
- template<typename C>
- int walk_file(struct group *entry, C cond) {
- auto file = fopen("/etc/group", "r");
- if(!file) {
- return EIO;
- }
-
- char line[512];
- while(fgets(line, 512, file)) {
- if(!extract_entry(line, entry))
- continue;
- if(cond(entry)) {
- fclose(file);
- return 0;
- }
- }
-
- int err = ESRCH;
- if(ferror(file)) {
- err = EIO;
- }
-
- fclose(file);
- return err;
- }
-
- int copy_to_buffer(struct group *grp, char *buffer, size_t size) {
- // Adjust to correct alignment so that we can put gr_mem first in buffer
- uintptr_t mask = sizeof(char *) - 1;
- size_t offset = (reinterpret_cast<uintptr_t>(buffer) % sizeof(char *) + mask) & ~mask;
- if (size < offset)
- return ERANGE;
-
- buffer += offset;
- size -= offset;
-
- // Calculate the amount of space we need
- size_t nmemb, required_size = 0;
- for (nmemb = 0; grp->gr_mem[nmemb] != nullptr; nmemb++) {
- // One for the string's null terminator and one for the pointer in gr_mem
- required_size += strlen(grp->gr_mem[nmemb]) + 1 + sizeof(char *);
- }
-
- // One for null terminator of gr_name, plus sizeof(char *) for nullptr terminator of gr_mem
- required_size += strlen(grp->gr_name) + 1 + sizeof(char *);
- if (size < required_size)
- return ERANGE;
-
- // Put the gr_mem array first in the buffer as we are guaranteed
- // that the pointer is aligned correctly
- char *string_data = buffer + (nmemb + 1) * sizeof(char *);
-
- for (size_t i = 0; i < nmemb; i++) {
- reinterpret_cast<char **>(buffer)[i] = string_data;
- string_data = stpcpy(string_data, grp->gr_mem[i]) + 1;
- free(grp->gr_mem[i]);
- }
-
- reinterpret_cast<char **>(buffer)[nmemb] = nullptr;
- free(grp->gr_mem);
- grp->gr_mem = reinterpret_cast<char **>(buffer);
-
- char *gr_name = stpcpy(string_data, grp->gr_name) + 1;
- free(grp->gr_name);
- grp->gr_name = string_data;
-
- __ensure(gr_name <= buffer + size);
- return 0;
- }
-}
-
-void endgrent(void) {
- close_global_file();
-}
-
-struct group *getgrent(void) {
- static group entry;
- char line[512];
-
- if(!open_global_file()) {
- return nullptr;
- }
-
- if(fgets(line, 512, global_file)) {
- clear_entry(&entry);
- if(!extract_entry(line, &entry)) {
- errno = EINVAL;
- return nullptr;
- }
- return &entry;
- }
-
- if(ferror(global_file)) {
- errno = EIO;
- }
-
- return nullptr;
-}
-
-struct group *getgrgid(gid_t gid) {
- static group entry;
-
- int err = walk_file(&entry, [&] (group *entry) {
- return entry->gr_gid == gid;
- });
-
- if (err) {
- errno = err;
- return nullptr;
- }
-
- return &entry;
-}
-
-int getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t size, struct group **result) {
- *result = nullptr;
- int err = walk_file(grp, [&] (group *entry) {
- return entry->gr_gid == gid;
- });
-
- if (err) {
- return err;
- }
-
- err = copy_to_buffer(grp, buffer, size);
- if (err) {
- return err;
- }
-
- *result = grp;
- return 0;
-}
-
-struct group *getgrnam(const char *name) {
- static group entry;
-
- int err = walk_file(&entry, [&] (group *entry) {
- return !strcmp(entry->gr_name, name);
- });
-
- if (err) {
- errno = err;
- return nullptr;
- }
-
- return &entry;
-}
-
-int getgrnam_r(const char *name, struct group *grp, char *buffer, size_t size, struct group **result) {
- *result = nullptr;
-
- int err = walk_file(grp, [&] (group *entry) {
- return !strcmp(entry->gr_name, name);
- });
-
- if (err) {
- return err;
- }
-
- err = copy_to_buffer(grp, buffer, size);
- if (err) {
- return err;
- }
-
- *result = grp;
- return 0;
-}
-
-void setgrent(void) {
- if(!open_global_file()) {
- return;
- }
- rewind(global_file);
-}
-
-int setgroups(size_t size, const gid_t *list) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setgroups, -1);
- if(int e = mlibc::sys_setgroups(size, list); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int initgroups(const char *, gid_t) {
- mlibc::infoLogger() << "mlibc: initgroups is a stub" << frg::endlog;
- return 0;
-}
-
-int putgrent(const struct group *, FILE *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-struct group *fgetgrent(FILE *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int getgrouplist(const char *, gid_t, gid_t *, int *) {
- mlibc::infoLogger() << "mlibc: getgrouplist is a stub" << frg::endlog;
- return 0;
-}
diff --git a/lib/mlibc/options/posix/generic/langinfo-stubs.cpp b/lib/mlibc/options/posix/generic/langinfo-stubs.cpp
deleted file mode 100644
index b239cbd..0000000
--- a/lib/mlibc/options/posix/generic/langinfo-stubs.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-
-#include <langinfo.h>
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-#include <mlibc/locale.hpp>
-
-char *nl_langinfo(nl_item item) {
- return mlibc::nl_langinfo(item);
-}
-
-char *nl_langinfo_l(nl_item, locale_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
diff --git a/lib/mlibc/options/posix/generic/libgen-stubs.cpp b/lib/mlibc/options/posix/generic/libgen-stubs.cpp
deleted file mode 100644
index ff80349..0000000
--- a/lib/mlibc/options/posix/generic/libgen-stubs.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-
-#include <bits/ensure.h>
-#include <libgen.h>
-#include <string.h>
-
-#include <mlibc/debug.hpp>
-
-// Adopted from musl's code.
-char *basename(char *s) {
- // This empty string behavior is specified by POSIX.
- if (!s || !*s)
- return const_cast<char *>(".");
-
- // Delete trailing slashes.
- // Note that we do not delete the slash at index zero.
- auto i = strlen(s) - 1;
- for(; i && s[i] == '/'; i--)
- s[i] = 0;
-
- // Find the last non-trailing slash.
- for(; i && s[i - 1] != '/'; i--)
- ;
- return s + i;
-}
-
-char *dirname(char *s) {
- if (!s || !(*s))
- return const_cast<char *>(".");
-
- auto i = strlen(s) - 1;
-
- // Skip trailing slashes.
- for (; s[i] == '/'; i--)
- if(!i) // Path only consists of slashes.
- return const_cast<char *>("/");
-
- // Skip the last non-slash path component.
- for (; s[i] != '/'; i--)
- if(!i) // Path only contains a single component.
- return const_cast<char *>(".");
-
- // Skip slashes.
- for (; s[i] == '/'; i--)
- if(!i) // Path is entry in root directory.
- return const_cast<char *>("/");
-
- s[i+1] = 0;
-
- return s;
-}
-
diff --git a/lib/mlibc/options/posix/generic/lookup.cpp b/lib/mlibc/options/posix/generic/lookup.cpp
deleted file mode 100644
index f877fe5..0000000
--- a/lib/mlibc/options/posix/generic/lookup.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-#include <mlibc/lookup.hpp>
-#include <mlibc/resolv_conf.hpp>
-#include <mlibc/debug.hpp>
-#include <bits/ensure.h>
-
-#include <frg/string.hpp>
-#include <mlibc/allocator.hpp>
-#include <string.h>
-#include <errno.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <ctype.h>
-
-namespace mlibc {
-
-namespace {
- constexpr unsigned int RECORD_A = 1;
- constexpr unsigned int RECORD_CNAME = 5;
- constexpr unsigned int RECORD_PTR = 12;
-}
-
-static frg::string<MemoryAllocator> read_dns_name(char *buf, char *&it) {
- frg::string<MemoryAllocator> res{getAllocator()};
- while (true) {
- char code = *it++;
- if ((code & 0xC0) == 0xC0) {
- // pointer
- uint8_t offset = ((code & 0x3F) << 8) | *it++;
- auto offset_it = buf + offset;
- return res + read_dns_name(buf, offset_it);
- } else if (!(code & 0xC0)) {
- if (!code)
- break;
-
- for (int i = 0; i < code; i++)
- res += (*it++);
-
- if (*it)
- res += '.';
- } else {
- break;
- }
- }
-
- return res;
-}
-
-int lookup_name_dns(struct lookup_result &buf, const char *name,
- frg::string<MemoryAllocator> &canon_name) {
- frg::string<MemoryAllocator> request{getAllocator()};
-
- int num_q = 1;
- struct dns_header header;
- header.identification = htons(123);
- header.flags = htons(0x100);
- header.no_q = htons(num_q);
- header.no_ans = htons(0);
- header.no_auths = htons(0);
- header.no_additional = htons(0);
-
- request.resize(sizeof(header));
- memcpy(request.data(), &header, sizeof(header));
-
- const char *end = name;
- while (*end != '\0') {
- end = strchrnul(name, '.');
- size_t length = end - name;
- frg::string_view substring{name, length};
- name += length + 1;
- request += char(length);
- request += substring;
- }
-
- request += char(0);
- // set question type to fetch A records
- request += 0;
- request += 1;
- // set CLASS to IN
- request += 0;
- request += 1;
-
- struct sockaddr_in sin = {};
- sin.sin_family = AF_INET;
- // TODO(geert): we could probably make this use the service lookup
- // for dns
- sin.sin_port = htons(53);
-
- auto nameserver = get_nameserver();
- if (!inet_aton(nameserver ? nameserver->name.data() : "127.0.0.1", &sin.sin_addr)) {
- mlibc::infoLogger() << "lookup_name_dns(): inet_aton() failed!" << frg::endlog;
- return -EAI_SYSTEM;
- }
-
- int fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (fd < 0) {
- mlibc::infoLogger() << "lookup_name_dns(): socket() failed" << frg::endlog;
- return -EAI_SYSTEM;
- }
-
- size_t sent = sendto(fd, request.data(), request.size(), 0,
- (struct sockaddr*)&sin, sizeof(sin));
- if (sent != request.size()) {
- mlibc::infoLogger() << "lookup_name_dns(): sendto() failed to send everything" << frg::endlog;
- return -EAI_SYSTEM;
- }
-
- char response[256];
- ssize_t rlen;
- int num_ans = 0;
- while ((rlen = recvfrom(fd, response, 256, 0, NULL, NULL)) >= 0) {
- if ((size_t)rlen < sizeof(struct dns_header))
- continue;
- auto response_header = reinterpret_cast<struct dns_header*>(response);
- if (response_header->identification != header.identification)
- return -EAI_FAIL;
-
- auto it = response + sizeof(struct dns_header);
- for (int i = 0; i < ntohs(response_header->no_q); i++) {
- auto dns_name = read_dns_name(response, it);
- (void) dns_name;
- it += 4;
- }
-
- for (int i = 0; i < ntohs(response_header->no_ans); i++) {
- struct dns_addr_buf buffer;
- auto dns_name = read_dns_name(response, it);
-
- uint16_t rr_type = (it[0] << 8) | it[1];
- uint16_t rr_class = (it[2] << 8) | it[3];
- uint16_t rr_length = (it[8] << 8) | it[9];
- it += 10;
- (void)rr_class;
-
- switch (rr_type) {
- case RECORD_A:
- memcpy(buffer.addr, it, rr_length);
- it += rr_length;
- buffer.family = AF_INET;
- buffer.name = std::move(dns_name);
- buf.buf.push(std::move(buffer));
- break;
- case RECORD_CNAME:
- canon_name = read_dns_name(response, it);
- buf.aliases.push(std::move(dns_name));
- break;
- default:
- mlibc::infoLogger() << "lookup_name_dns: unknown rr type "
- << rr_type << frg::endlog;
- break;
- }
- }
- num_ans += ntohs(response_header->no_ans);
-
- if (num_ans >= num_q)
- break;
- }
-
- close(fd);
- return buf.buf.size();
-}
-
-int lookup_addr_dns(frg::span<char> name, frg::array<uint8_t, 16> &addr, int family) {
- frg::string<MemoryAllocator> request{getAllocator()};
-
- int num_q = 1;
- struct dns_header header;
- header.identification = htons(123);
- header.flags = htons(0x100);
- header.no_q = htons(num_q);
- header.no_ans = htons(0);
- header.no_auths = htons(0);
- header.no_additional = htons(0);
-
- request.resize(sizeof(header));
- memcpy(request.data(), &header, sizeof(header));
-
- char addr_str[64];
- if(!inet_ntop(family, addr.data(), addr_str, sizeof(addr_str))) {
- switch(errno) {
- case EAFNOSUPPORT:
- return -EAI_FAMILY;
- case ENOSPC:
- return -EAI_OVERFLOW;
- default:
- return -EAI_FAIL;
- }
- }
- frg::string<MemoryAllocator> req_str{getAllocator(), addr_str};
- req_str += ".in-addr.arpa";
-
- frg::string_view req_view{req_str.data(), req_str.size()};
- size_t ptr = 0;
- do {
- size_t next = req_view.find_first('.', ptr);
- size_t length = next != (size_t)-1 ? next - ptr : req_view.size() - ptr;
- frg::string_view substring = req_view.sub_string(ptr, length);
- request += char(length);
- request += substring;
- ptr = next + 1;
- } while(ptr != 0);
-
- request += char(0);
- // set question type to fetch PTR records
- request += 0;
- request += 12;
- // set CLASS to IN
- request += 0;
- request += 1;
-
-
- struct sockaddr_in sin = {};
- sin.sin_family = AF_INET;
- // TODO(geert): we could probably make this use the service lookup
- // for dns
- sin.sin_port = htons(53);
-
- auto nameserver = get_nameserver();
- if (!inet_aton(nameserver ? nameserver->name.data() : "127.0.0.1", &sin.sin_addr)) {
- mlibc::infoLogger() << "lookup_name_dns(): inet_aton() failed!" << frg::endlog;
- return -EAI_SYSTEM;
- }
-
- int fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (fd < 0) {
- mlibc::infoLogger() << "lookup_name_dns(): socket() failed" << frg::endlog;
- return -EAI_SYSTEM;
- }
-
- size_t sent = sendto(fd, request.data(), request.size(), 0,
- (struct sockaddr*)&sin, sizeof(sin));
- if (sent != request.size()) {
- mlibc::infoLogger() << "lookup_name_dns(): sendto() failed to send everything" << frg::endlog;
- return -EAI_SYSTEM;
- }
-
- char response[256];
- ssize_t rlen;
- int num_ans = 0;
- while ((rlen = recvfrom(fd, response, 256, 0, NULL, NULL)) >= 0) {
- if ((size_t)rlen < sizeof(struct dns_header))
- continue;
- auto response_header = reinterpret_cast<struct dns_header*>(response);
- if (response_header->identification != header.identification)
- return -EAI_FAIL;
-
- auto it = response + sizeof(struct dns_header);
- for (int i = 0; i < ntohs(response_header->no_q); i++) {
- auto dns_name = read_dns_name(response, it);
- (void) dns_name;
- it += 4;
- }
-
- for (int i = 0; i < ntohs(response_header->no_ans); i++) {
- struct dns_addr_buf buffer;
- auto dns_name = read_dns_name(response, it);
-
- uint16_t rr_type = (it[0] << 8) | it[1];
- uint16_t rr_class = (it[2] << 8) | it[3];
- uint16_t rr_length = (it[8] << 8) | it[9];
- it += 10;
- (void)rr_class;
- (void)rr_length;
-
- (void)dns_name;
-
- switch (rr_type) {
- case RECORD_PTR: {
- auto ptr_name = read_dns_name(response, it);
- if (ptr_name.size() >= name.size())
- return -EAI_OVERFLOW;
- std::copy(ptr_name.begin(), ptr_name.end(), name.data());
- name.data()[ptr_name.size()] = '\0';
- return 1;
- }
- default:
- mlibc::infoLogger() << "lookup_addr_dns: unknown rr type "
- << rr_type << frg::endlog;
- break;
- }
- num_ans += ntohs(response_header->no_ans);
-
- if (num_ans >= num_q)
- break;
- }
- }
-
- close(fd);
- return 0;
-}
-
-int lookup_name_hosts(struct lookup_result &buf, const char *name,
- frg::string<MemoryAllocator> &canon_name) {
- auto file = fopen("/etc/hosts", "r");
- if (!file) {
- switch (errno) {
- case ENOENT:
- case ENOTDIR:
- case EACCES:
- return -EAI_SERVICE;
- default:
- return -EAI_SYSTEM;
- }
- }
-
- char line[128];
- int name_length = strlen(name);
- while (fgets(line, 128, file)) {
- char *pos;
- // same way to deal with comments as in services.cpp
- if ((pos = strchr(line, '#'))) {
- *pos++ = '\n';
- *pos = '\0';
- }
-
- for(pos = line + 1; (pos = strstr(pos, name)) &&
- (!isspace(pos[-1]) || !isspace(pos[name_length])); pos++);
- if (!pos)
- continue;
-
- for (pos = line; !isspace(*pos); pos++);
- *pos = '\0';
-
- // TODO(geert): we assume ipv4 for now
- struct in_addr addr;
- if (!inet_aton(line, &addr))
- continue;
-
- pos++;
- for(; *pos && isspace(*pos); pos++);
- char *end;
- for(end = pos; *end && !isspace(*end); end++);
-
- struct dns_addr_buf buffer;
- memcpy(buffer.addr, &addr, 4);
- buffer.family = AF_INET;
- buffer.name = frg::string<MemoryAllocator>{pos,
- static_cast<size_t>(end - pos), getAllocator()};
- canon_name = buffer.name;
-
- buf.buf.push(std::move(buffer));
-
- pos = end;
- while (pos[1]) {
- for (; *pos && isspace(*pos); pos++);
- for (end = pos; *end && !isspace(*end); end++);
- auto name = frg::string<MemoryAllocator>{pos,
- static_cast<size_t>(end - pos), getAllocator()};
- buf.aliases.push(std::move(name));
- pos = end;
- }
- }
-
- fclose(file);
- return buf.buf.size();
-}
-
-int lookup_addr_hosts(frg::span<char> name, frg::array<uint8_t, 16> &addr, int family) {
- auto file = fopen("/etc/hosts", "r");
- if (!file) {
- switch (errno) {
- case ENOENT:
- case ENOTDIR:
- case EACCES:
- return -EAI_SERVICE;
- default:
- return -EAI_SYSTEM;
- }
- }
-
- // Buffer to hold ASCII version of address
- char addr_str[64];
- if(!inet_ntop(family, addr.data(), addr_str, sizeof(addr_str))) {
- switch(errno) {
- case EAFNOSUPPORT:
- return -EAI_FAMILY;
- case ENOSPC:
- return -EAI_OVERFLOW;
- default:
- return -EAI_FAIL;
- }
- }
- int addr_str_len = strlen(addr_str);
-
- char line[128];
- while (fgets(line, 128, file)) {
- char *pos;
- // same way to deal with comments as in services.cpp
- if ((pos = strchr(line, '#'))) {
- *pos++ = '\n';
- *pos = '\0';
- }
- if (strncmp(line, addr_str, addr_str_len))
- continue;
-
- for (pos = line + addr_str_len + 1; isspace(*pos); pos++);
- char *begin = pos;
- for (; !isspace(*pos); pos++);
- char *end = pos;
-
- size_t size = end - begin;
- if (size >= name.size())
- return -EAI_OVERFLOW;
- std::copy(begin, end, name.data());
- name.data()[size] = '\0';
- return 1;
- }
- return 0;
-}
-
-int lookup_name_null(struct lookup_result &buf, int flags, int family) {
- if (flags & AI_PASSIVE) {
- if (family != AF_INET6) {
- struct dns_addr_buf addr_buf;
- addr_buf.family = AF_INET;
-
- in_addr_t addr = INADDR_ANY;
- memcpy(&addr_buf.addr, &addr, 4);
-
- buf.buf.push_back(addr_buf);
- }
- if (family != AF_INET) {
- struct dns_addr_buf addr_buf;
- addr_buf.family = AF_INET6;
-
- struct in6_addr addr = IN6ADDR_ANY_INIT;
- memcpy(&addr_buf.addr, &addr, 16);
-
- buf.buf.push_back(addr_buf);
- }
- } else {
- if (family != AF_INET6) {
- struct dns_addr_buf addr_buf;
- addr_buf.family = AF_INET;
-
- in_addr_t addr = INADDR_LOOPBACK;
- memcpy(&addr_buf.addr, &addr, 4);
-
- buf.buf.push_back(addr_buf);
- }
- if (family != AF_INET) {
- struct dns_addr_buf addr_buf;
- addr_buf.family = AF_INET6;
-
- struct in6_addr addr = IN6ADDR_LOOPBACK_INIT;
- memcpy(&addr_buf.addr, &addr, 16);
-
- buf.buf.push_back(addr_buf);
- }
- }
- return buf.buf.size();
-}
-
-int lookup_name_ip(struct lookup_result &buf, const char *name, int family) {
- if (family == AF_INET) {
- in_addr_t addr = 0;
- int res = inet_pton(AF_INET, name, &addr);
-
- if (res <= 0)
- return -EAI_NONAME;
-
- struct dns_addr_buf addr_buf;
- addr_buf.family = AF_INET;
- memcpy(&addr_buf.addr, &addr, 4);
-
- buf.buf.push_back(addr_buf);
- return 1;
- }
-
- if (family == AF_INET6) {
- struct in6_addr addr{0};
- int res = inet_pton(AF_INET6, name, &addr);
-
- if (res <= 0)
- return -EAI_NONAME;
-
- struct dns_addr_buf addr_buf;
- addr_buf.family = AF_INET6;
- memcpy(&addr_buf.addr, &addr, 16);
-
- buf.buf.push_back(addr_buf);
- return 1;
- }
-
- // If no family was specified we try ipv4 and then ipv6.
- in_addr_t addr4 = 0;
- int res = inet_pton(AF_INET, name, &addr4);
-
- if (res > 0) {
- struct dns_addr_buf addr_buf;
- addr_buf.family = AF_INET;
- memcpy(&addr_buf.addr, &addr4, 4);
-
- buf.buf.push_back(addr_buf);
- return 1;
- }
-
- struct in6_addr addr6{0};
- res = inet_pton(AF_INET6, name, &addr6);
-
- if (res <= 0)
- return -EAI_NONAME;
-
- struct dns_addr_buf addr_buf;
- addr_buf.family = AF_INET6;
- memcpy(&addr_buf.addr, &addr6, 16);
-
- buf.buf.push_back(addr_buf);
- return 1;
-}
-
-} // namespace mlibc
diff --git a/lib/mlibc/options/posix/generic/mqueue.cpp b/lib/mlibc/options/posix/generic/mqueue.cpp
deleted file mode 100644
index d635419..0000000
--- a/lib/mlibc/options/posix/generic/mqueue.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <mqueue.h>
-#include <bits/ensure.h>
-
-int mq_getattr(mqd_t, struct mq_attr *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int mq_setattr(mqd_t, const struct mq_attr *__restrict__, struct mq_attr *__restrict__) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int mq_unlink(const char *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-mqd_t mq_open(const char *, int, ...) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/net-if-stubs.cpp b/lib/mlibc/options/posix/generic/net-if-stubs.cpp
deleted file mode 100644
index 6a65a5c..0000000
--- a/lib/mlibc/options/posix/generic/net-if-stubs.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <errno.h>
-#include <net/if.h>
-#include <stdlib.h>
-
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-void if_freenameindex(struct if_nameindex *) {
- mlibc::infoLogger() << "mlibc: if_freenameindex is a no-op" << frg::endlog;
-}
-
-char *if_indextoname(unsigned int index, char *name) {
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_if_indextoname, NULL);
-
- if(int e = sysdep(index, name); e) {
- errno = e;
- return NULL;
- }
-
- return name;
-}
-
-struct if_nameindex *if_nameindex(void) {
- mlibc::infoLogger() << "mlibc: if_nameindex() is a no-op" << frg::endlog;
- errno = ENOSYS;
- return NULL;
-}
-
-unsigned int if_nametoindex(const char *name) {
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_if_nametoindex, 0);
- unsigned int ret = 0;
-
- if(int e = sysdep(name, &ret); e) {
- errno = e;
- return 0;
- }
-
- return ret;
-}
diff --git a/lib/mlibc/options/posix/generic/netdb-stubs.cpp b/lib/mlibc/options/posix/generic/netdb-stubs.cpp
deleted file mode 100644
index 455444b..0000000
--- a/lib/mlibc/options/posix/generic/netdb-stubs.cpp
+++ /dev/null
@@ -1,486 +0,0 @@
-#include <netdb.h>
-#include <bits/ensure.h>
-
-#include <mlibc/debug.hpp>
-#include <mlibc/lookup.hpp>
-#include <mlibc/allocator.hpp>
-#include <mlibc/services.hpp>
-#include <frg/vector.hpp>
-#include <frg/array.hpp>
-#include <frg/span.hpp>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <errno.h>
-
-__thread int __mlibc_h_errno;
-
-// This function is from musl
-int *__h_errno_location(void) {
- return &__mlibc_h_errno;
-}
-
-void endhostent(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void endnetent(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void endprotoent(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void endservent(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void freeaddrinfo(struct addrinfo *ptr) {
- if (ptr) {
- auto buf = (struct mlibc::ai_buf*) ptr - offsetof(struct mlibc::ai_buf, ai);
- // this string was allocated by a frg::string
- getAllocator().free(ptr->ai_canonname);
- free(buf);
- }
-}
-
-const char *gai_strerror(int code) {
- static thread_local char buffer[128];
- snprintf(buffer, sizeof(buffer), "Unknown error (%d)", code);
- return buffer;
-}
-
-int getaddrinfo(const char *__restrict node, const char *__restrict service,
- const struct addrinfo *__restrict hints, struct addrinfo **__restrict res) {
- if (!node && !service)
- return EAI_NONAME;
-
- int socktype = 0, protocol = 0, family = AF_UNSPEC, flags = AI_V4MAPPED | AI_ADDRCONFIG;
- if (hints) {
- socktype = hints->ai_socktype;
- protocol = hints->ai_protocol;
- family = hints->ai_family;
- flags = hints->ai_flags;
-
- int mask = AI_V4MAPPED | AI_ADDRCONFIG | AI_NUMERICHOST | AI_PASSIVE |
- AI_CANONNAME | AI_ALL | AI_NUMERICSERV;
- if ((flags & mask) != flags)
- return EAI_BADFLAGS;
-
- if (family != AF_INET && family != AF_INET6 && family != AF_UNSPEC)
- return EAI_FAMILY;
- }
-
- mlibc::service_result serv_buf{getAllocator()};
- int serv_count = mlibc::lookup_serv_by_name(serv_buf, service, protocol, socktype, flags);
- if (serv_count < 0)
- return -serv_count;
-
- struct mlibc::lookup_result addr_buf;
- int addr_count = 1;
- frg::string<MemoryAllocator> canon{getAllocator()};
- if (node) {
- if ((addr_count = mlibc::lookup_name_ip(addr_buf, node, family)) <= 0) {
- if (flags & AI_NUMERICHOST)
- addr_count = -EAI_NONAME;
- else if ((addr_count = mlibc::lookup_name_hosts(addr_buf, node, canon)) <= 0)
- addr_count = mlibc::lookup_name_dns(addr_buf, node, canon);
- else
- addr_count = 1;
- }
-
- if (addr_count < 0)
- return -addr_count;
- if (!addr_count)
- return EAI_NONAME;
- } else {
- /* There is no node specified */
- if (flags & AI_NUMERICHOST)
- return EAI_NONAME;
- addr_count = lookup_name_null(addr_buf, flags, family);
- }
-
- auto out = (struct mlibc::ai_buf *) calloc(serv_count * addr_count,
- sizeof(struct mlibc::ai_buf));
-
- if (node && !canon.size())
- canon = frg::string<MemoryAllocator>{node, getAllocator()};
-
- for (int i = 0, k = 0; i < addr_count; i++) {
- for (int j = 0; j < serv_count; j++, k++) {
- out[i].ai.ai_family = addr_buf.buf[i].family;
- out[i].ai.ai_socktype = serv_buf[j].socktype;
- out[i].ai.ai_protocol = serv_buf[j].protocol;
- out[i].ai.ai_flags = flags;
- out[i].ai.ai_addr = (struct sockaddr *) &out[i].sa;
- if (canon.size())
- out[i].ai.ai_canonname = canon.data();
- else
- out[i].ai.ai_canonname = NULL;
- out[i].ai.ai_next = NULL;
- switch (addr_buf.buf[i].family) {
- case AF_INET:
- out[i].ai.ai_addrlen = sizeof(struct sockaddr_in);
- out[i].sa.sin.sin_port = htons(serv_buf[j].port);
- out[i].sa.sin.sin_family = AF_INET;
- memcpy(&out[i].sa.sin.sin_addr, addr_buf.buf[i].addr, 4);
- break;
- case AF_INET6:
- out[i].ai.ai_addrlen = sizeof(struct sockaddr_in6);
- out[i].sa.sin6.sin6_family = htons(serv_buf[j].port);
- out[i].sa.sin6.sin6_family = AF_INET6;
- memcpy(&out[i].sa.sin6.sin6_addr, addr_buf.buf[i].addr, 16);
- break;
- }
- }
- }
- if (canon.size())
- canon.detach();
-
- *res = &out[0].ai;
- return 0;
-}
-
-struct hostent *gethostent(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int getnameinfo(const struct sockaddr *__restrict addr, socklen_t addr_len,
- char *__restrict host, socklen_t host_len, char *__restrict serv,
- socklen_t serv_len, int flags) {
- frg::array<uint8_t, 16> addr_array;
- int family = addr->sa_family;
-
- switch(family) {
- case AF_INET: {
- if (addr_len < sizeof(struct sockaddr_in))
- return EAI_FAMILY;
- auto sockaddr = reinterpret_cast<const struct sockaddr_in*>(addr);
- memcpy(addr_array.data(), reinterpret_cast<const char*>(&sockaddr->sin_addr), 4);
- break;
- }
- case AF_INET6: {
- mlibc::infoLogger() << "getnameinfo(): ipv6 is not fully supported in this function" << frg::endlog;
- if (addr_len < sizeof(struct sockaddr_in6))
- return EAI_FAMILY;
- auto sockaddr = reinterpret_cast<const struct sockaddr_in6*>(addr);
- memcpy(addr_array.data(), reinterpret_cast<const char*>(&sockaddr->sin6_addr), 16);
- break;
- }
- default:
- return EAI_FAMILY;
- }
-
- if (host && host_len) {
- frg::span<char> host_span{host, host_len};
- int res = 0;
- if (!(flags & NI_NUMERICHOST))
- res = mlibc::lookup_addr_hosts(host_span, addr_array, family);
- if (!(flags & NI_NUMERICHOST) && !res)
- res = mlibc::lookup_addr_dns(host_span, addr_array, family);
-
- if (!res) {
- if (flags & NI_NAMEREQD)
- return EAI_NONAME;
- if(!inet_ntop(family, addr_array.data(), host, host_len)) {
- switch(errno) {
- case EAFNOSUPPORT:
- return EAI_FAMILY;
- case ENOSPC:
- return EAI_OVERFLOW;
- default:
- return EAI_FAIL;
- }
- }
- }
-
- if (res < 0)
- return -res;
- }
-
- if (serv && serv_len) {
- __ensure("getnameinfo(): not implemented service resolution yet!");
- __builtin_unreachable();
- }
-
- return 0;
-}
-
-struct netent *getnetbyaddr(uint32_t, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-struct netent *getnetbyname(const char *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-struct netent *getnetent(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-struct hostent *gethostbyname(const char *name) {
- if (!name) {
- h_errno = HOST_NOT_FOUND;
- return NULL;
- }
-
- struct mlibc::lookup_result buf;
- frg::string<MemoryAllocator> canon{getAllocator()};
- int ret = 0;
- if ((ret = mlibc::lookup_name_hosts(buf, name, canon)) <= 0)
- ret = mlibc::lookup_name_dns(buf, name, canon);
- if (ret <= 0) {
- h_errno = HOST_NOT_FOUND;
- return NULL;
- }
-
- static struct hostent h;
- if (h.h_name) {
- getAllocator().free(h.h_name);
- for (int i = 0; h.h_aliases[i] != NULL; i++)
- getAllocator().free(h.h_aliases[i]);
- free(h.h_aliases);
-
- if (h.h_addr_list) {
- for (int i = 0; h.h_addr_list[i] != NULL; i++)
- free(h.h_addr_list[i]);
- free(h.h_addr_list);
- }
- }
- h = {};
-
- if (!canon.size())
- canon = frg::string<MemoryAllocator>{name, getAllocator()};
-
- h.h_name = canon.data();
-
- h.h_aliases = reinterpret_cast<char**>(malloc((buf.aliases.size() + 1)
- * sizeof(char*)));
- int alias_pos = 0;
- for (auto &buf_name : buf.aliases) {
- h.h_aliases[alias_pos] = buf_name.data();
- buf_name.detach();
- alias_pos++;
- }
- h.h_aliases[alias_pos] = NULL;
- canon.detach();
-
- // just pick the first family as the one for all addresses...??
- h.h_addrtype = buf.buf[0].family;
- if (h.h_addrtype != AF_INET && h.h_addrtype != AF_INET6) {
- // this is not allowed per spec
- h_errno = NO_DATA;
- return NULL;
- }
-
- // can only be AF_INET or AF_INET6
- h.h_length = h.h_addrtype == AF_INET ? 4 : 16;
- h.h_addr_list = reinterpret_cast<char**>(malloc((ret + 1) * sizeof(char*)));
- int addr_pos = 0;
- for (int i = 0; i < ret; i++) {
- if (buf.buf[i].family != h.h_addrtype)
- continue;
- h.h_addr_list[addr_pos] = reinterpret_cast<char*>(malloc(h.h_length));
- memcpy(h.h_addr_list[addr_pos], buf.buf[i].addr, h.h_length);
- addr_pos++;
- }
- h.h_addr_list[addr_pos] = NULL;
-
- return &h;
-}
-
-struct hostent *gethostbyname2(const char *, int) {
- __ensure(!"gethostbyname2() not implemented");
- __builtin_unreachable();
-}
-
-struct hostent *gethostbyaddr(const void *, socklen_t, int) {
- __ensure(!"gethostbyaddr() not implemented");
- __builtin_unreachable();
-}
-
-int gethostbyaddr_r(const void *__restrict, socklen_t, int, struct hostent *__restrict,
- char *__restrict, size_t, struct hostent **__restrict, int *__restrict) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int gethostbyname_r(const char *__restrict, struct hostent *__restrict, char *__restrict, size_t,
- struct hostent **__restrict, int *__restrict) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-struct protoent *getprotobyname(const char *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-struct protoent *getprotobynumber(int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-struct protoent *getprotoent(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-struct servent *getservbyname(const char *name, const char *proto) {
- int iproto = -1;
- if (proto &&(!strncmp(proto, "tcp", 3) || !strncmp(proto, "TCP", 3)))
- iproto = IPPROTO_TCP;
- else if (proto && (!strncmp(proto, "udp", 3) || !strncmp(proto, "UDP", 3)))
- iproto = IPPROTO_UDP;
-
- static struct servent ret;
- if (ret.s_name) {
- free(ret.s_name);
- ret.s_name = nullptr;
-
- for (char **alias = ret.s_aliases; *alias != NULL; alias++) {
- free(*alias);
- *alias = nullptr;
- }
-
- free(ret.s_proto);
- ret.s_proto = nullptr;
- }
-
- mlibc::service_result serv_buf{getAllocator()};
- int count = mlibc::lookup_serv_by_name(serv_buf, name, iproto,
- 0, 0);
- if (count <= 0)
- return NULL;
-
- ret.s_name = serv_buf[0].name.data();
- serv_buf[0].name.detach();
- // Sanity check.
- if (strncmp(name, serv_buf[0].name.data(), serv_buf[0].name.size()))
- return NULL;
-
- ret.s_aliases = reinterpret_cast<char**>(malloc((serv_buf[0].aliases.size() + 1) * sizeof(char*)));
- int alias_pos = 0;
- for (auto &buf_name : serv_buf[0].aliases) {
- ret.s_aliases[alias_pos] = buf_name.data();
- buf_name.detach();
- alias_pos++;
- }
- ret.s_aliases[alias_pos] = NULL;
-
- ret.s_port = htons(serv_buf[0].port);
-
- auto proto_string = frg::string<MemoryAllocator>(getAllocator());
- if (!proto) {
- if (serv_buf[0].protocol == IPPROTO_TCP)
- proto_string = frg::string<MemoryAllocator>("tcp", getAllocator());
- else if (serv_buf[0].protocol == IPPROTO_UDP)
- proto_string = frg::string<MemoryAllocator>("udp", getAllocator());
- else
- return NULL;
- } else {
- proto_string = frg::string<MemoryAllocator>(proto, getAllocator());
- }
- ret.s_proto = proto_string.data();
- proto_string.detach();
-
- return &ret;
-}
-
-struct servent *getservbyport(int port, const char *proto) {
- int iproto = -1;
- if (proto && (!strncmp(proto, "tcp", 3) || !strncmp(proto, "TCP", 3)))
- iproto = IPPROTO_TCP;
- else if (proto && (!strncmp(proto, "udp", 3) || !strncmp(proto, "UDP", 3)))
- iproto = IPPROTO_UDP;
-
- static struct servent ret;
- if (ret.s_name) {
- free(ret.s_name);
- ret.s_name = nullptr;
-
- for (char **alias = ret.s_aliases; *alias != NULL; alias++) {
- free(*alias);
- *alias = nullptr;
- }
-
- free(ret.s_proto);
- ret.s_proto = nullptr;
- }
-
- mlibc::service_result serv_buf{getAllocator()};
- int count = mlibc::lookup_serv_by_port(serv_buf, iproto, ntohs(port));
- if (count <= 0)
- return NULL;
-
- ret.s_name = serv_buf[0].name.data();
- serv_buf[0].name.detach();
-
- ret.s_aliases = reinterpret_cast<char**>(malloc((serv_buf[0].aliases.size() + 1) * sizeof(char*)));
- int alias_pos = 0;
- for (auto &buf_name : serv_buf[0].aliases) {
- ret.s_aliases[alias_pos] = buf_name.data();
- buf_name.detach();
- alias_pos++;
- }
- ret.s_aliases[alias_pos] = NULL;
-
- ret.s_port = port;
-
- auto proto_string = frg::string<MemoryAllocator>(getAllocator());
- if (!proto) {
- if (serv_buf[0].protocol == IPPROTO_TCP)
- proto_string = frg::string<MemoryAllocator>("tcp", getAllocator());
- else if (serv_buf[0].protocol == IPPROTO_UDP)
- proto_string = frg::string<MemoryAllocator>("udp", getAllocator());
- else
- return NULL;
- } else {
- proto_string = frg::string<MemoryAllocator>(proto, getAllocator());
- }
- ret.s_proto = proto_string.data();
- proto_string.detach();
-
- return &ret;
-}
-
-struct servent *getservent(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void sethostent(int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void setnetent(int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void setprotoent(int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void setservent(int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-const char *hstrerror(int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/poll.cpp b/lib/mlibc/options/posix/generic/poll.cpp
deleted file mode 100644
index c34e25e..0000000
--- a/lib/mlibc/options/posix/generic/poll.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-
-#include <errno.h>
-#include <poll.h>
-
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-int poll(struct pollfd *fds, nfds_t count, int timeout) {
- int num_events;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_poll, -1);
- if(int e = mlibc::sys_poll(fds, count, timeout, &num_events); e) {
- errno = e;
- return -1;
- }
- return num_events;
-}
-
-#if __MLIBC_LINUX_OPTION
-int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts, const sigset_t *sigmask) {
- sigset_t origmask;
- int timeout = (timeout_ts == NULL) ? -1 : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
-
- sigprocmask(SIG_SETMASK, sigmask, &origmask);
- int ready = poll(fds, nfds, timeout);
- sigprocmask(SIG_SETMASK, &origmask, NULL);
-
- return ready;
-}
-#endif // __MLIBC_LINUX_OPTION
-
diff --git a/lib/mlibc/options/posix/generic/posix-file-io.cpp b/lib/mlibc/options/posix/generic/posix-file-io.cpp
deleted file mode 100644
index 1a4f38b..0000000
--- a/lib/mlibc/options/posix/generic/posix-file-io.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-#include <mlibc/posix-file-io.hpp>
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-#include <errno.h>
-
-namespace mlibc {
-
-int mem_file::reopen(const char *, const char *) {
- mlibc::panicLogger() << "mlibc: freopen() on a mem_file stream is unimplemented!" << frg::endlog;
- return -1;
-}
-
-int mem_file::determine_type(stream_type *type) {
- *type = stream_type::file_like;
- return 0;
-}
-
-int mem_file::determine_bufmode(buffer_mode *mode) {
- *mode = buffer_mode::no_buffer;
- return 0;
-}
-
-memstream_mem_file::memstream_mem_file(char **ptr, size_t *sizeloc, int flags, void (*do_dispose)(abstract_file *))
-: mem_file{flags, do_dispose}, _bufloc{ptr}, _sizeloc{sizeloc} { }
-
-
-int memstream_mem_file::close() {
- _update_ptrs();
- _buf.detach();
-
- return 0;
-}
-
-int memstream_mem_file::io_read(char *buffer, size_t max_size, size_t *actual_size) {
- if ((_pos >= 0 && _pos >= _max_size) || !max_size) {
- *actual_size = 0;
- return 0;
- }
-
- size_t bytes_read = std::min(size_t(_max_size - _pos), max_size);
- memcpy(buffer, _buffer().data() + _pos, bytes_read);
- _pos += bytes_read;
- *actual_size = bytes_read;
- return 0;
-}
-
-int memstream_mem_file::io_write(const char *buffer, size_t max_size, size_t *actual_size) {
- if (_pos + max_size >= _buffer_size()) {
- _buf.resize(_pos + max_size + 1, '\0');
- _update_ptrs();
- }
-
- size_t bytes_write = std::min(static_cast<size_t>(_buffer_size() - _pos), max_size);
- memcpy(_buffer().data() + _pos, buffer, bytes_write);
- _pos += max_size;
- *actual_size = max_size;
-
- return 0;
-}
-
-int memstream_mem_file::io_seek(off_t offset, int whence, off_t *new_offset) {
- switch (whence) {
- case SEEK_SET:
- _pos = offset;
- if (_pos >= 0 && size_t(_pos) >= _buffer_size()) {
- _buf.resize(_pos + 1, '\0');
- _update_ptrs();
- }
- *new_offset = _pos;
- break;
- case SEEK_CUR:
- _pos += offset;
- if (_pos >= 0 && size_t(_pos) >= _buffer_size()) {
- _buf.resize(_pos + 1, '\0');
- _update_ptrs();
- }
- *new_offset = _pos;
- break;
- case SEEK_END:
- _pos = _buffer_size() ? _buffer_size() - 1 + offset : _buffer_size() + offset;
- _buf.resize(_pos + 1, '\0');
- _update_ptrs();
- *new_offset = _pos;
- break;
- default:
- return EINVAL;
- }
- return 0;
-}
-
-void memstream_mem_file::_update_ptrs() {
- *_bufloc = _buf.data();
- *_sizeloc = _buf.size() - 1;
-}
-
-fmemopen_mem_file::fmemopen_mem_file(void *in_buf, size_t size, int flags, void (*do_dispose)(abstract_file *))
-: mem_file{flags, do_dispose}, _inBuffer{in_buf}, _inBufferSize{size} {
- if(!_inBuffer) {
- _inBuffer = getAllocator().allocate(size);
- _needsDeallocation = true;
- }
-
- if(_flags & O_APPEND) {
- // the initial seek-size for append is zero if buf was NULL, or the first '\0' found, or the size
- _max_size = (_needsDeallocation) ? 0 : strnlen(reinterpret_cast<char *>(_inBuffer), _inBufferSize);
- _pos = _max_size;
- } else if((_flags & O_WRONLY || _flags & O_RDWR) && _flags & O_CREAT && _flags & O_TRUNC) {
- // modes: "w", "w+"
- _max_size = 0;
- } else {
- _max_size = size;
- }
-}
-
-int fmemopen_mem_file::close() {
- if(_needsDeallocation) {
- getAllocator().free(_inBuffer);
- }
-
- return 0;
-}
-
-int fmemopen_mem_file::io_read(char *buffer, size_t max_size, size_t *actual_size) {
- if ((_pos >= 0 && _pos >= _max_size) || !max_size) {
- *actual_size = 0;
- return 0;
- }
-
- size_t bytes_read = std::min(size_t(_max_size - _pos), max_size);
- memcpy(buffer, _buffer().data() + _pos, bytes_read);
- _pos += bytes_read;
- *actual_size = bytes_read;
- return 0;
-}
-
-int fmemopen_mem_file::io_write(const char *buffer, size_t max_size, size_t *actual_size) {
- off_t bytes_write = std::min(static_cast<size_t>(_buffer_size() - _pos), max_size);
- memcpy(_buffer().data() + _pos, buffer, bytes_write);
- _pos += bytes_write;
- *actual_size = bytes_write;
-
- if(_pos > _max_size) {
- _max_size = _pos;
- }
-
- // upon flushing, we need to put a null byte at the current position or at the end of the buffer
- size_t null = _pos;
- // a special case is if the mode is set to updating ('+'), then it always goes at the end
- if(null >= _buffer_size() || _flags & O_RDWR) {
- null = _buffer_size() - 1;
- }
-
- if(_buffer_size()) {
- _buffer()[null] = '\0';
- }
-
- return 0;
-}
-
-int fmemopen_mem_file::io_seek(off_t offset, int whence, off_t *new_offset) {
- switch (whence) {
- case SEEK_SET:
- if(offset < 0 || size_t(offset) > _buffer_size()) {
- return EINVAL;
- }
- _pos = offset;
- *new_offset = _pos;
- break;
- case SEEK_CUR:
- // seeking to negative positions or positions larger than the buffer is disallowed in fmemopen(3)
- if((_pos + offset) < 0 || size_t(_pos + offset) > _buffer_size()) {
- return EINVAL;
- }
- _pos += offset;
- *new_offset = _pos;
- break;
- case SEEK_END:
- if((_max_size + offset) < 0 || size_t(_max_size + offset) > _buffer_size()) {
- return EINVAL;
- }
- _pos = _max_size + offset;
- *new_offset = _pos;
- break;
- default:
- return EINVAL;
- }
- return 0;
-}
-
-int cookie_file::close() {
- if(!_funcs.close) {
- return 0;
- }
-
- return _funcs.close(_cookie);
-}
-
-int cookie_file::reopen(const char *, const char *) {
- mlibc::panicLogger() << "mlibc: freopen() on a cookie_file stream is unimplemented!" << frg::endlog;
- return -1;
-}
-
-int cookie_file::determine_type(stream_type *type) {
- *type = stream_type::file_like;
- return 0;
-}
-
-int cookie_file::determine_bufmode(buffer_mode *mode) {
- *mode = buffer_mode::no_buffer;
- return 0;
-}
-
-int cookie_file::io_read(char *buffer, size_t max_size, size_t *actual_size) {
- if(!_funcs.read) {
- return EOF;
- }
-
- *actual_size = _funcs.read(_cookie, buffer, max_size);
-
- return 0;
-}
-
-int cookie_file::io_write(const char *buffer, size_t max_size, size_t *actual_size) {
- if(!_funcs.write) {
- return 0;
- }
-
- *actual_size = _funcs.write(_cookie, buffer, max_size);
-
- return 0;
-}
-
-int cookie_file::io_seek(off_t offset, int whence, off_t *new_offset) {
- if(!_funcs.seek) {
- return ENOTSUP;
- }
-
- *new_offset = offset;
-
- return _funcs.seek(_cookie, new_offset, whence);
-}
-
-} // namespace mlibc
-
-FILE *fdopen(int fd, const char *mode) {
- int flags = mlibc::fd_file::parse_modestring(mode);
-
- flags &= ~O_TRUNC; // 'w' should not truncate the file
-
- if (flags & O_APPEND) {
- int cur_flags = fcntl(fd, F_GETFL, 0);
- if (cur_flags < 0) {
- errno = EINVAL;
- return nullptr;
- } else if (!(cur_flags & O_APPEND)) {
- if (fcntl(fd, F_SETFL, cur_flags | O_APPEND)) {
- errno = EINVAL;
- return nullptr;
- }
- }
- }
-
- if (flags & O_CLOEXEC) {
- if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
- errno = EINVAL;
- return nullptr;
- }
- }
-
- // TODO: We may need to activate line buffered mode for terminals.
-
- return frg::construct<mlibc::fd_file>(getAllocator(), fd,
- mlibc::file_dispose_cb<mlibc::fd_file>);
-}
diff --git a/lib/mlibc/options/posix/generic/posix_ctype.cpp b/lib/mlibc/options/posix/generic/posix_ctype.cpp
deleted file mode 100644
index 19f129f..0000000
--- a/lib/mlibc/options/posix/generic/posix_ctype.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <ctype.h>
-#include <wctype.h>
-
-#include <bits/ensure.h>
-
-int isalnum_l(int c, locale_t) {
- return isalnum(c);
-}
-
-int isalpha_l(int c, locale_t) {
- return isalpha(c);
-}
-
-int isblank_l(int c, locale_t) {
- return isblank(c);
-}
-
-int iscntrl_l(int c, locale_t) {
- return iscntrl(c);
-}
-
-int isdigit_l(int c, locale_t) {
- return isdigit(c);
-}
-
-int isgraph_l(int c, locale_t) {
- return isgraph(c);
-}
-
-int islower_l(int c, locale_t) {
- return islower(c);
-}
-
-int isprint_l(int c, locale_t) {
- return isprint(c);
-}
-
-int ispunct_l(int c, locale_t) {
- return ispunct(c);
-}
-
-int isspace_l(int c, locale_t) {
- return isspace(c);
-}
-
-int isupper_l(int c, locale_t) {
- return isupper(c);
-}
-
-int isxdigit_l(int c, locale_t) {
- return isxdigit(c);
-}
-
-int isascii_l(int c, locale_t) {
- return isascii(c);
-}
-
-int tolower_l(int c, locale_t) {
- return tolower(c);
-}
-
-int toupper_l(int c, locale_t) {
- return toupper(c);
-}
-
-int iswalnum_l(wint_t c, locale_t) {
- return iswalnum(c);
-}
-
-int iswblank_l(wint_t c, locale_t) {
- return iswblank(c);
-}
-
-int iswcntrl_l(wint_t c, locale_t) {
- return iswcntrl(c);
-}
-
-int iswdigit_l(wint_t c, locale_t) {
- return iswdigit(c);
-}
-
-int iswgraph_l(wint_t c, locale_t) {
- return iswgraph(c);
-}
-
-int iswlower_l(wint_t c, locale_t) {
- return iswlower(c);
-}
-
-int iswprint_l(wint_t c, locale_t) {
- return iswprint(c);
-}
-
-int iswpunct_l(wint_t c, locale_t) {
- return iswpunct(c);
-}
-
-int iswspace_l(wint_t c, locale_t) {
- return iswspace(c);
-}
-
-int iswupper_l(wint_t c, locale_t) {
- return iswupper(c);
-}
-
-int iswxdigit_l(wint_t c, locale_t) {
- return iswxdigit(c);
-}
-
-int iswalpha_l(wint_t c, locale_t) {
- return iswalpha(c);
-}
-
-wctype_t wctype_l(const char* p, locale_t) {
- return wctype(p);
-}
-
-int iswctype_l(wint_t w, wctype_t t, locale_t) {
- return iswctype(w, t);
-}
-
-wint_t towlower_l(wint_t c, locale_t) {
- return towlower(c);
-}
-
-wint_t towupper_l(wint_t c, locale_t) {
- return towupper(c);
-}
-
-wctrans_t wctrans_l(const char* c, locale_t) {
- return wctrans(c);
-}
-
-wint_t towctrans_l(wint_t c, wctrans_t desc, locale_t) {
- return towctrans(c, desc);
-}
diff --git a/lib/mlibc/options/posix/generic/posix_locale.cpp b/lib/mlibc/options/posix/generic/posix_locale.cpp
deleted file mode 100644
index bd8710a..0000000
--- a/lib/mlibc/options/posix/generic/posix_locale.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <bits/posix/posix_locale.h>
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-
-namespace {
-
-bool newlocale_seen = false;
-bool uselocale_seen = false;
-
-}
-
-locale_t newlocale(int, const char *, locale_t) {
- // Due to all of the locale functions being stubs, the locale will not be used
- if(!newlocale_seen) {
- mlibc::infoLogger() << "mlibc: newlocale() is a no-op" << frg::endlog;
- newlocale_seen = true;
- }
- return nullptr;
-}
-
-void freelocale(locale_t) {
- mlibc::infoLogger() << "mlibc: freelocale() is a no-op" << frg::endlog;
- return;
-}
-
-locale_t uselocale(locale_t) {
- if(!uselocale_seen) {
- mlibc::infoLogger() << "mlibc: uselocale() is a no-op" << frg::endlog;
- uselocale_seen = true;
- }
- return nullptr;
-}
-
-locale_t duplocale(locale_t) {
- mlibc::infoLogger() << "mlibc: duplocale() is a no-op" << frg::endlog;
- return nullptr;
-}
diff --git a/lib/mlibc/options/posix/generic/posix_signal.cpp b/lib/mlibc/options/posix/generic/posix_signal.cpp
deleted file mode 100644
index eef3ef3..0000000
--- a/lib/mlibc/options/posix/generic/posix_signal.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-
-#include <errno.h>
-#include <signal.h>
-#include <unistd.h>
-#include <bits/ensure.h>
-
-#include <mlibc/posix-sysdeps.hpp>
-#include <mlibc/tcb.hpp>
-
-int sigsuspend(const sigset_t *sigmask) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_sigsuspend, -1);
-
- // This is guaranteed to return an error (EINTR most probably)
- errno = mlibc::sys_sigsuspend(sigmask);
- return -1;
-}
-
-int pthread_sigmask(int how, const sigset_t *__restrict set, sigset_t *__restrict retrieve) {
- if(!mlibc::sys_sigprocmask) {
- MLIBC_MISSING_SYSDEP();
- return ENOSYS;
- }
- if(int e = mlibc::sys_sigprocmask(how, set, retrieve); e) {
- return e;
- }
- return 0;
-}
-
-int pthread_kill(pthread_t thread, int sig) {
- auto tcb = reinterpret_cast<Tcb *>(thread);
- auto pid = getpid();
-
- if(!mlibc::sys_tgkill) {
- MLIBC_MISSING_SYSDEP();
- return ENOSYS;
- }
-
- if(int e = mlibc::sys_tgkill(pid, tcb->tid, sig); e) {
- return e;
- }
-
- return 0;
-}
-
-int sigaction(int signum, const struct sigaction *__restrict act, struct sigaction *__restrict oldact) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_sigaction, -1);
- if(int e = mlibc::sys_sigaction(signum, act, oldact); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int siginterrupt(int sig, int flag) {
- int ret;
- struct sigaction act;
-
- sigaction(sig, NULL, &act);
- if (flag)
- act.sa_flags &= ~SA_RESTART;
- else
- act.sa_flags |= SA_RESTART;
-
- ret = sigaction(sig, &act, NULL);
- return ret;
-}
-
-int kill(pid_t pid, int number) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_kill, -1);
- if(int e = mlibc::sys_kill(pid, number); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int killpg(pid_t pgrp, int sig) {
- if(pgrp > 1) {
- return kill(-pgrp, sig);
- }
-
- errno = EINVAL;
- return -1;
-}
-
-int sigtimedwait(const sigset_t *__restrict set, siginfo_t *__restrict info, const struct timespec *__restrict timeout) {
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_sigtimedwait, -1);
-
- int signo;
-
- if (int e = sysdep(set, info, timeout, &signo)) {
- errno = e;
- return -1;
- }
-
- return signo;
-}
-
-int sigwaitinfo(const sigset_t *__restrict set, siginfo_t *__restrict info) {
- // NOTE: This assumes the sysdep behavior noted in mlibc/posix-sysdeps.hpp
- return sigtimedwait(set, info, nullptr);
-}
-
-int sigwait(const sigset_t *__restrict set, int *__restrict sig) {
- if (int e = sigwaitinfo(set, nullptr); e < 0) {
- return e;
- } else {
- if (sig)
- *sig = e;
-
- return 0;
- }
-}
-
-int sigpending(sigset_t *set) {
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_sigpending, -1);
-
- if(int e = sysdep(set)) {
- errno = e;
- return -1;
- }
-
- return 0;
-}
-
-int sigaltstack(const stack_t *__restrict ss, stack_t *__restrict oss) {
- if (ss && ss->ss_size < MINSIGSTKSZ && !(ss->ss_flags & SS_DISABLE)) {
- errno = ENOMEM;
- return -1;
- }
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_sigaltstack, -1);
- if (int e = mlibc::sys_sigaltstack(ss, oss); e) {
- errno = e;
- return -1;
- }
-
- return 0;
-}
-
-#if __MLIBC_GLIBC_OPTION
-int sigisemptyset(const sigset_t *set) {
- return !(*set);
-}
-#endif // __MLIBC_GLIBC_OPTION
-
-int sigqueue(pid_t, int, const union sigval) {
- __ensure(!"sigqueue() not implemented");
- __builtin_unreachable();
-}
-
diff --git a/lib/mlibc/options/posix/generic/posix_stdio.cpp b/lib/mlibc/options/posix/generic/posix_stdio.cpp
deleted file mode 100644
index fc77a54..0000000
--- a/lib/mlibc/options/posix/generic/posix_stdio.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <bits/ensure.h>
-#include <mlibc/ansi-sysdeps.hpp>
-#include <mlibc/debug.hpp>
-#include <mlibc/file-io.hpp>
-#include <mlibc/posix-file-io.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-struct popen_file : mlibc::fd_file {
- popen_file(int fd, void (*do_dispose)(abstract_file *) = nullptr)
- : fd_file(fd, do_dispose) {}
-
- pid_t get_popen_pid() {
- return _popen_pid;
- }
-
- void set_popen_pid(pid_t new_pid) {
- _popen_pid = new_pid;
- }
-
-private:
- // Underlying PID in case of popen()
- pid_t _popen_pid;
-};
-
-FILE *fmemopen(void *buf, size_t size, const char *__restrict mode) {
- int flags = mlibc::fd_file::parse_modestring(mode);
-
- return frg::construct<mlibc::fmemopen_mem_file>(getAllocator(), buf, size, flags,
- mlibc::file_dispose_cb<mlibc::mem_file>);
-}
-
-int pclose(FILE *stream) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_waitpid, -1);
-
- auto file = static_cast<popen_file *>(stream);
-
- int status;
- pid_t pid = file->get_popen_pid();
-
- fclose(file);
-
- if (mlibc::sys_waitpid(pid, &status, 0, NULL, &pid) != 0) {
- errno = ECHILD;
- return -1;
- }
-
- return status;
-}
-
-FILE *popen(const char *command, const char *typestr) {
- bool is_write;
- pid_t child;
- FILE *ret = nullptr;
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fork && mlibc::sys_dup2 && mlibc::sys_execve &&
- mlibc::sys_sigprocmask && mlibc::sys_sigaction && mlibc::sys_pipe, nullptr);
-
- if (typestr == NULL) {
- errno = EINVAL;
- return nullptr;
- }
-
- if (strstr(typestr, "w") != NULL) {
- is_write = true;
- } else if (strstr(typestr, "r") != NULL) {
- is_write = false;
- } else {
- errno = EINVAL;
- return nullptr;
- }
-
- bool cloexec = false;
- if (strstr(typestr, "e") != NULL) {
- // Set FD_CLOEXEC on the new file descriptor
- cloexec = true;
- }
-
- int fds[2];
- if (int e = mlibc::sys_pipe(fds, 0)) {
- errno = e;
- return nullptr;
- }
-
- struct sigaction new_sa, old_int, old_quit;
- sigset_t new_mask, old_mask;
-
- new_sa.sa_handler = SIG_IGN;
- new_sa.sa_flags = 0;
- sigemptyset(&new_sa.sa_mask);
- mlibc::sys_sigaction(SIGINT, &new_sa, &old_int);
- mlibc::sys_sigaction(SIGQUIT, &new_sa, &old_quit);
-
- sigemptyset(&new_mask);
- sigaddset(&new_mask, SIGCHLD);
- mlibc::sys_sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
-
- int parent_end = is_write ? 1 : 0;
- int child_end = is_write ? 0 : 1;
-
- if (int e = mlibc::sys_fork(&child)) {
- errno = e;
- mlibc::sys_close(fds[0]);
- mlibc::sys_close(fds[1]);
- } else if (!child) {
- // For the child
- mlibc::sys_sigaction(SIGINT, &old_int, nullptr);
- mlibc::sys_sigaction(SIGQUIT, &old_quit, nullptr);
- mlibc::sys_sigprocmask(SIG_SETMASK, &old_mask, nullptr);
-
- mlibc::sys_close(fds[parent_end]);
-
- if (mlibc::sys_dup2(fds[child_end], 0, is_write ? 0 : 1)) {
- __ensure(!"sys_dup2() failed in popen()");
- }
- mlibc::sys_close(fds[child_end]);
-
- const char *args[] = {
- "sh", "-c", command, nullptr
- };
-
- mlibc::sys_execve("/bin/sh", const_cast<char **>(args), environ);
- _Exit(127);
- } else {
- // For the parent
- mlibc::sys_close(fds[child_end]);
-
- ret = frg::construct<popen_file>(
- getAllocator(),
- fds[parent_end],
- mlibc::file_dispose_cb<popen_file>
- );
- __ensure(ret);
-
- auto file = static_cast<popen_file *>(ret);
-
- file->set_popen_pid(child);
-
- if (cloexec == true) {
- fcntl(file->fd(), F_SETFD, O_CLOEXEC);
- }
- }
-
- mlibc::sys_sigaction(SIGINT, &old_int, nullptr);
- mlibc::sys_sigaction(SIGQUIT, &old_quit, nullptr);
- mlibc::sys_sigprocmask(SIG_SETMASK, &old_mask, nullptr);
-
- return ret;
-}
-
-FILE *open_memstream(char **buf, size_t *sizeloc) {
- return frg::construct<mlibc::memstream_mem_file>(getAllocator(), buf, sizeloc, O_RDWR,
- mlibc::file_dispose_cb<mlibc::mem_file>);
-}
-
-int fseeko(FILE *file_base, off_t offset, int whence) {
- auto file = static_cast<mlibc::abstract_file *>(file_base);
- if(int e = file->seek(offset, whence); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-off_t ftello(FILE *file_base) {
- auto file = static_cast<mlibc::abstract_file *>(file_base);
- off_t current_offset;
- if(int e = file->tell(&current_offset); e) {
- errno = e;
- return -1;
- }
- return current_offset;
-}
-
-int dprintf(int fd, const char *format, ...) {
- va_list args;
- va_start(args, format);
- int result = vdprintf(fd, format, args);
- va_end(args);
- return result;
-}
-
-int vdprintf(int fd, const char *format, __builtin_va_list args) {
- mlibc::fd_file file{fd};
- int ret = vfprintf(&file, format, args);
- file.flush();
- return ret;
-}
-
-char *fgetln(FILE *, size_t *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-FILE *fopencookie(void *cookie, const char *__restrict mode, cookie_io_functions_t funcs) {
- int flags = mlibc::fd_file::parse_modestring(mode);
-
- return frg::construct<mlibc::cookie_file>(getAllocator(), cookie, flags, funcs,
- mlibc::file_dispose_cb<mlibc::cookie_file>);
-}
diff --git a/lib/mlibc/options/posix/generic/posix_stdlib.cpp b/lib/mlibc/options/posix/generic/posix_stdlib.cpp
deleted file mode 100644
index 4010998..0000000
--- a/lib/mlibc/options/posix/generic/posix_stdlib.cpp
+++ /dev/null
@@ -1,513 +0,0 @@
-
-#include <abi-bits/fcntl.h>
-#include <bits/ensure.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-
-#include <frg/small_vector.hpp>
-#include <mlibc/allocator.hpp>
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-#include <mlibc/rtdl-config.hpp>
-
-namespace {
- constexpr bool debugPathResolution = false;
-}
-
-// Borrowed from musl
-static uint32_t init[] = {
-0x00000000,0x5851f42d,0xc0b18ccf,0xcbb5f646,
-0xc7033129,0x30705b04,0x20fd5db4,0x9a8b7f78,
-0x502959d8,0xab894868,0x6c0356a7,0x88cdb7ff,
-0xb477d43f,0x70a3a52b,0xa8e4baf1,0xfd8341fc,
-0x8ae16fd9,0x742d2f7a,0x0d1f0796,0x76035e09,
-0x40f7702c,0x6fa72ca5,0xaaa84157,0x58a0df74,
-0xc74a0364,0xae533cc4,0x04185faf,0x6de3b115,
-0x0cab8628,0xf043bfa4,0x398150e9,0x37521657};
-
-static int n = 31;
-static int i = 3;
-static int j = 0;
-static uint32_t *x = init + 1;
-
-
-static uint32_t lcg31(uint32_t x) {
- return (1103515245 * x + 12345) & 0x7fffffff;
-}
-
-static uint64_t lcg64(uint64_t x) {
- return 6364136223846793005ull * x + 1;
-}
-
-static void *savestate(void) {
- x[-1] = (n << 16) | (i << 8) | j;
- return x - 1;
-}
-
-static void loadstate(uint32_t *state) {
- x = state + 1;
- n = x[-1] >> 16;
- i = (x[-1] >> 8) & 0xff;
- j = x[-1] & 0xff;
-}
-
-long random(void) {
- long k;
-
- if(n == 0) {
- k = x[0] = lcg31(x[0]);
- return k;
- }
- x[i] += x[j];
- k = x[i] >> 1;
- if(++i == n)
- i = 0;
- if(++j == n)
- j = 0;
-
- return k;
-}
-
-double drand48(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void srand48(long int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-// Borrowed from musl
-void srandom(unsigned int seed) {
- int k;
- uint64_t s = seed;
-
- if(n == 0) {
- x[0] = s;
- return;
- }
- i = n == 31 || n == 7 ? 3 : 1;
- j = 0;
- for(k = 0; k < n; k++) {
- s = lcg64(s);
- x[k] = s >> 32;
- }
- // Make sure x contains at least one odd number
- x[0] |= 1;
-}
-
-char *initstate(unsigned int seed, char *state, size_t size) {
- void *old;
-
- if(size < 8)
- return 0;
- old = savestate();
- if(size < 32)
- n = 0;
- else if(size < 64)
- n = 7;
- else if(size < 128)
- n = 15;
- else if(size < 256)
- n = 31;
- else
- n = 63;
- x = (uint32_t *)state + 1;
- srandom(seed);
- savestate();
- return (char *)old;
-}
-
-char *setstate(char *state) {
- void *old;
-
- old = savestate();
- loadstate((uint32_t *)state);
- return (char *)old;
-}
-
-// ----------------------------------------------------------------------------
-// Path handling.
-// ----------------------------------------------------------------------------
-
-
-int mkostemps(char *pattern, int suffixlen, int flags) {
- auto n = strlen(pattern);
- if(n < (6 + static_cast<size_t>(suffixlen))) {
- errno = EINVAL;
- return -1;
- }
-
- flags &= ~O_WRONLY;
-
- for(size_t i = 0; i < 6; i++) {
- if(pattern[n - (6 + suffixlen) + i] == 'X')
- continue;
- errno = EINVAL;
- return -1;
- }
-
- // TODO: Do an exponential search.
- for(size_t i = 0; i < 999999; i++) {
- char sfx = pattern[n - suffixlen];
- __ensure(sprintf(pattern + (n - (6 + suffixlen)), "%06zu", i) == 6);
- pattern[n - suffixlen] = sfx;
-
- int fd;
- if(int e = mlibc::sys_open(pattern, O_RDWR | O_CREAT | O_EXCL | flags, S_IRUSR | S_IWUSR, &fd); !e) {
- return fd;
- }else if(e != EEXIST) {
- errno = e;
- return -1;
- }
- }
-
- errno = EEXIST;
- return -1;
-}
-
-int mkostemp(char *pattern, int flags) {
- return mkostemps(pattern, flags, 0);
-}
-
-int mkstemp(char *path) {
- return mkostemp(path, 0);
-}
-
-int mkstemps(char *pattern, int suffixlen) {
- return mkostemps(pattern, suffixlen, 0);
-}
-
-char *mkdtemp(char *pattern) {
- mlibc::infoLogger() << "mlibc mkdtemp(" << pattern << ") called" << frg::endlog;
- auto n = strlen(pattern);
- __ensure(n >= 6);
- if(n < 6) {
- errno = EINVAL;
- return NULL;
- }
- for(size_t i = 0; i < 6; i++) {
- if(pattern[n - 6 + i] == 'X')
- continue;
- errno = EINVAL;
- return NULL;
- }
-
- // TODO: Do an exponential search.
- for(size_t i = 0; i < 999999; i++) {
- __ensure(sprintf(pattern + (n - 6), "%06zu", i) == 6);
- if(int e = mlibc::sys_mkdir(pattern, S_IRWXU); !e) {
- return pattern;
- }else if(e != EEXIST) {
- errno = e;
- return NULL;
- }
- }
-
- errno = EEXIST;
- return NULL;
-}
-
-char *realpath(const char *path, char *out) {
- if(debugPathResolution)
- mlibc::infoLogger() << "mlibc realpath(): Called on '" << path << "'" << frg::endlog;
- frg::string_view path_view{path};
-
- // In case of the root, the string only contains the null-terminator.
- frg::small_vector<char, PATH_MAX, MemoryAllocator> resolv{getAllocator()};
- size_t ps;
-
- // If the path is relative, we have to preprend the working directory.
- if(path[0] == '/') {
- resolv.push_back(0);
- ps = 1;
- }else{
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getcwd, nullptr);
-
- // Try to getcwd() until the buffer is large enough.
- resolv.resize(128);
- while(true) {
- int e = mlibc::sys_getcwd(resolv.data(), resolv.size());
- if(e == ERANGE) {
- resolv.resize(2 * resolv.size());
- }else if(!e) {
- break;
- }else{
- errno = e;
- return nullptr;
- }
- }
- frg::string_view cwd_view{resolv.data()};
- if(cwd_view == "/") {
- // Restore our invariant that we only store the null-terminator for the root.
- resolv.resize(1);
- resolv[0] = 0;
- }else{
- resolv.resize(cwd_view.size() + 1);
- }
- ps = 0;
- }
-
- // Contains unresolved links as a relative path compared to resolv.
- frg::small_vector<char, PATH_MAX, MemoryAllocator> lnk{getAllocator()};
- size_t ls = 0;
-
- auto process_segment = [&] (frg::string_view s_view) -> int {
- if(debugPathResolution)
- mlibc::infoLogger() << "mlibc realpath(): resolv is '" << resolv.data() << "'"
- << ", segment is " << s_view.data()
- << ", size: " << s_view.size() << frg::endlog;
-
- if(!s_view.size() || s_view == ".") {
- // Keep resolv invariant.
- return 0;
- }else if(s_view == "..") {
- // Remove a single segment from resolv.
- if(resolv.size() > 1) {
- auto slash = strrchr(resolv.data(), '/');
- __ensure(slash); // We never remove the leading sla.
- resolv.resize((slash - resolv.data()) + 1);
- *slash = 0; // Replace the slash by a null-terminator.
- }
- return 0;
- }
-
- // Append the segment to resolv.
- auto rsz = resolv.size();
- resolv[rsz - 1] = '/'; // Replace null-terminator by a slash.
- resolv.resize(rsz + s_view.size() + 1);
- memcpy(resolv.data() + rsz, s_view.data(), s_view.size());
- resolv[rsz + s_view.size()] = 0;
-
- // stat() the path to (1) see if it exists and (2) see if it is a link.
- if(!mlibc::sys_stat) {
- MLIBC_MISSING_SYSDEP();
- return ENOSYS;
- }
- if(debugPathResolution)
- mlibc::infoLogger() << "mlibc realpath(): stat()ing '"
- << resolv.data() << "'" << frg::endlog;
- struct stat st;
- if(int e = mlibc::sys_stat(mlibc::fsfd_target::path,
- -1, resolv.data(), AT_SYMLINK_NOFOLLOW, &st); e)
- return e;
-
- if(S_ISLNK(st.st_mode)) {
- if(debugPathResolution) {
- mlibc::infoLogger() << "mlibc realpath(): Encountered symlink '"
- << resolv.data() << "'" << frg::endlog;
- }
-
- if(!mlibc::sys_readlink) {
- MLIBC_MISSING_SYSDEP();
- return ENOSYS;
- }
-
- ssize_t sz = 0;
- char path[512];
-
- if (int e = mlibc::sys_readlink(resolv.data(), path, 512, &sz); e)
- return e;
-
- if(debugPathResolution) {
- mlibc::infoLogger() << "mlibc realpath(): Symlink resolves to '"
- << frg::string_view{path, static_cast<size_t>(sz)} << "'" << frg::endlog;
- }
-
- if (path[0] == '/') {
- // Absolute path, replace resolv
- resolv.resize(sz);
- strncpy(resolv.data(), path, sz - 1);
- resolv.data()[sz - 1] = 0;
-
- if(debugPathResolution) {
- mlibc::infoLogger() << "mlibc realpath(): Symlink is absolute, resolv: '"
- << resolv.data() << "'" << frg::endlog;
- }
- } else {
- // Relative path, revert changes to resolv, prepend to lnk
- resolv.resize(rsz);
- resolv[rsz - 1] = 0;
-
- auto lsz = lnk.size();
- lnk.resize((lsz - ls) + sz + 1);
- memmove(lnk.data() + sz, lnk.data() + ls, lsz - ls);
- memcpy(lnk.data(), path, sz);
- lnk[(lsz - ls) + sz] = 0;
-
- ls = 0;
-
- if(debugPathResolution) {
- mlibc::infoLogger() << "mlibc realpath(): Symlink is relative, resolv: '"
- << resolv.data() << "' lnk: '"
- << frg::string_view{lnk.data(), lnk.size()} << "'" << frg::endlog;
- }
- }
- }
-
- return 0;
- };
-
- // Each iteration of this outer loop consumes segment of the input path.
- // This design avoids copying the input path into lnk;
- // the latter could often involve additional allocations.
- while(ps < path_view.size()) {
- frg::string_view ps_view;
- if(auto slash = strchr(path + ps, '/'); slash) {
- ps_view = frg::string_view{path + ps, static_cast<size_t>(slash - (path + ps))};
- }else{
- ps_view = frg::string_view{path + ps, strlen(path) - ps};
- }
- ps += ps_view.size() + 1;
-
- // Handle one segment from the input path.
- if(int e = process_segment(ps_view); e) {
- errno = e;
- return nullptr;
- }
-
- // This inner loop consumes segments of lnk.
- while(ls < lnk.size()) {
- frg::string_view ls_view;
- if(auto slash = strchr(lnk.data() + ls, '/'); slash) {
- ls_view = frg::string_view{lnk.data() + ls, static_cast<size_t>(slash - (lnk.data() + ls))};
- }else{
- ls_view = frg::string_view{lnk.data() + ls, strlen(lnk.data()) - ls};
- }
- ls += ls_view.size() + 1;
-
- // Handle one segment from the link
- if(int e = process_segment(ls_view); e) {
- errno = e;
- return nullptr;
- }
- }
-
- // All of lnk was consumed, reset it
- lnk.resize(0);
- ls = 0;
- }
-
- if(resolv.size() == 1) {
- resolv.resize(0);
- resolv.push_back('/');
- resolv.push_back(0);
- }
-
- if(debugPathResolution)
- mlibc::infoLogger() << "mlibc realpath(): Returns '" << resolv.data() << "'" << frg::endlog;
-
- if(resolv.size() > PATH_MAX) {
- errno = ENAMETOOLONG;
- return nullptr;
- }
-
- if(!out)
- out = reinterpret_cast<char *>(getAllocator().allocate(resolv.size()));
- strcpy(out, resolv.data());
- return out;
-}
-
-// ----------------------------------------------------------------------------
-// Pseudoterminals
-// ----------------------------------------------------------------------------
-
-int ptsname_r(int fd, char *buffer, size_t length) {
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_ptsname, ENOSYS);
-
- if(int e = sysdep(fd, buffer, length); e)
- return e;
-
- return 0;
-}
-
-char *ptsname(int fd) {
- static char buffer[128];
-
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_ptsname, NULL);
-
- if(int e = sysdep(fd, buffer, 128); e) {
- errno = e;
- return NULL;
- }
-
- return buffer;
-}
-
-int posix_openpt(int flags) {
- int fd;
- if(int e = mlibc::sys_open("/dev/ptmx", flags, 0, &fd); e) {
- errno = e;
- return -1;
- }
-
- return fd;
-}
-
-int unlockpt(int fd) {
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_unlockpt, -1);
-
- if(int e = sysdep(fd); e) {
- errno = e;
- return -1;
- }
-
- return 0;
-}
-
-int grantpt(int) {
- return 0;
-}
-
-double strtod_l(const char *__restrict__ nptr, char ** __restrict__ endptr, locale_t) {
- mlibc::infoLogger() << "mlibc: strtod_l ignores locale!" << frg::endlog;
- return strtod(nptr, endptr);
-}
-
-long double strtold_l(const char *__restrict__, char ** __restrict__, locale_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-float strtof_l(const char *__restrict__ nptr, char **__restrict__ endptr, locale_t) {
- mlibc::infoLogger() << "mlibc: strtof_l ignores locales" << frg::endlog;
- return strtof(nptr, endptr);
-}
-
-int strcoll_l(const char *, const char *, locale_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int getloadavg(double *, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-char *secure_getenv(const char *name) {
- if (mlibc::rtdlConfig().secureRequired)
- return NULL;
- else
- return getenv(name);
-}
-
-void *reallocarray(void *ptr, size_t m, size_t n) {
- if(n && m > -1 / n) {
- errno = ENOMEM;
- return 0;
- }
-
- return realloc(ptr, m * n);
-}
-
-char *canonicalize_file_name(const char *name) {
- return realpath(name, NULL);
-}
diff --git a/lib/mlibc/options/posix/generic/posix_string.cpp b/lib/mlibc/options/posix/generic/posix_string.cpp
deleted file mode 100644
index d0bc7b5..0000000
--- a/lib/mlibc/options/posix/generic/posix_string.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <bits/ensure.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <signal.h>
-
-#include <mlibc/debug.hpp>
-
-char *strdup(const char *string) {
- auto num_bytes = strlen(string);
-
- char *new_string = (char *)malloc(num_bytes + 1);
- if(!new_string) // TODO: set errno
- return nullptr;
-
- memcpy(new_string, string, num_bytes);
- new_string[num_bytes] = 0;
- return new_string;
-}
-
-char *strndup(const char *string, size_t max_size) {
- auto num_bytes = strnlen(string, max_size);
- char *new_string = (char *)malloc(num_bytes + 1);
- if(!new_string) // TODO: set errno
- return nullptr;
-
- memcpy(new_string, string, num_bytes);
- new_string[num_bytes] = 0;
- return new_string;
-}
-
-char *stpcpy(char *__restrict dest, const char *__restrict src) {
- auto n = strlen(src);
- memcpy(dest, src, n + 1);
- return dest + n;
-}
-
-char *stpncpy(char *__restrict dest, const char *__restrict src, size_t n) {
- size_t nulls, copied, srcLen = strlen(src);
- if (n >= srcLen) {
- nulls = n - srcLen;
- copied = srcLen;
- } else {
- nulls = 0;
- copied = n;
- }
-
- memcpy(dest, src, copied);
- memset(dest + srcLen, 0, nulls);
- return dest + n - nulls;
-}
-
-size_t strnlen(const char *s, size_t n) {
- size_t len = 0;
- while(len < n && s[len])
- ++len;
- return len;
-}
-
-char *strsep(char **m, const char *del) {
- __ensure(m);
-
- auto tok = *m;
- if(!tok)
- return nullptr;
-
- // Replace the following delimiter by a null-terminator.
- // After this loop: *p is null iff we reached the end of the string.
- auto p = tok;
- while(*p && !strchr(del, *p))
- p++;
-
- if(*p) {
- *p = 0;
- *m = p + 1;
- }else{
- *m = nullptr;
- }
- return tok;
-}
-
-char *strsignal(int sig) {
- #define CASE_FOR(sigconst) case sigconst: s = #sigconst; break;
- const char *s;
- switch(sig) {
- CASE_FOR(SIGABRT)
- CASE_FOR(SIGFPE)
- CASE_FOR(SIGILL)
- CASE_FOR(SIGINT)
- CASE_FOR(SIGSEGV)
- CASE_FOR(SIGTERM)
- CASE_FOR(SIGPROF)
- CASE_FOR(SIGIO)
- CASE_FOR(SIGPWR)
- CASE_FOR(SIGALRM)
- CASE_FOR(SIGBUS)
- CASE_FOR(SIGCHLD)
- CASE_FOR(SIGCONT)
- CASE_FOR(SIGHUP)
- CASE_FOR(SIGKILL)
- CASE_FOR(SIGPIPE)
- CASE_FOR(SIGQUIT)
- CASE_FOR(SIGSTOP)
- CASE_FOR(SIGTSTP)
- CASE_FOR(SIGTTIN)
- CASE_FOR(SIGTTOU)
- CASE_FOR(SIGUSR1)
- CASE_FOR(SIGUSR2)
- CASE_FOR(SIGSYS)
- CASE_FOR(SIGTRAP)
- CASE_FOR(SIGURG)
- CASE_FOR(SIGVTALRM)
- CASE_FOR(SIGXCPU)
- CASE_FOR(SIGXFSZ)
- CASE_FOR(SIGWINCH)
- default:
- mlibc::infoLogger() << "mlibc: Unknown signal number " << sig << frg::endlog;
- s = "Unknown signal number";
- }
- return const_cast<char *>(s);
-}
-
-char *strcasestr(const char *s, const char *pattern) {
- size_t plen = strlen(pattern);
- const char *p = s;
- while(*p) {
- // Need strncasecmp() to avoid checking past the end of a successful match.
- if(!strncasecmp(p, pattern, plen))
- return const_cast<char *>(p);
- ++p;
- }
- return nullptr;
-}
-
-void *memccpy(void *__restrict, const void *__restrict, int, size_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-// This implementation was taken from musl
-void *memrchr(const void *m, int c, size_t n) {
- const unsigned char *s = (const unsigned char *)m;
- c = (unsigned char)c;
- while(n--) {
- if(s[n] == c)
- return (void *)(s + n);
- }
- return 0;
-}
-
-// BSD extensions.
-// Taken from musl
-size_t strlcpy(char *d, const char *s, size_t n) {
- char *d0 = d;
-
- if(!n--)
- goto finish;
- for(; n && (*d=*s); n--, s++, d++);
- *d = 0;
-finish:
- return d-d0 + strlen(s);
-}
-
-size_t strlcat(char *d, const char *s, size_t n) {
- size_t l = strnlen(d, n);
- if(l == n) {
- return l + strlen(s);
- }
- return l + strlcpy(d + l, s, n - l);
-}
diff --git a/lib/mlibc/options/posix/generic/posix_time.cpp b/lib/mlibc/options/posix/generic/posix_time.cpp
deleted file mode 100644
index d93ebbc..0000000
--- a/lib/mlibc/options/posix/generic/posix_time.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include <bits/posix/posix_time.h>
-#include <bits/ensure.h>
-#include <mlibc/posix-sysdeps.hpp>
-#include <errno.h>
-
-int utimes(const char *filename, const struct timeval times[2]) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_utimensat, -1);
- struct timespec time[2];
- if(times == nullptr) {
- time[0].tv_sec = UTIME_NOW;
- time[0].tv_nsec = UTIME_NOW;
- time[1].tv_sec = UTIME_NOW;
- time[1].tv_nsec = UTIME_NOW;
- } else {
- time[0].tv_sec = times[0].tv_sec;
- time[0].tv_nsec = times[0].tv_usec * 1000;
- time[1].tv_sec = times[1].tv_sec;
- time[1].tv_nsec = times[1].tv_usec * 1000;
- }
-
- if (int e = mlibc::sys_utimensat(AT_FDCWD, filename, time, 0); e) {
- errno = e;
- return -1;
- }
-
- return 0;
-}
-
-int futimes(int, const struct timeval[2]) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/pthread-stubs.cpp b/lib/mlibc/options/posix/generic/pthread-stubs.cpp
deleted file mode 100644
index 9720bc2..0000000
--- a/lib/mlibc/options/posix/generic/pthread-stubs.cpp
+++ /dev/null
@@ -1,1426 +0,0 @@
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <errno.h>
-#include <inttypes.h>
-
-#include <bits/ensure.h>
-#include <frg/allocation.hpp>
-#include <frg/array.hpp>
-#include <mlibc/allocator.hpp>
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-#include <mlibc/thread.hpp>
-#include <mlibc/tcb.hpp>
-#include <mlibc/tid.hpp>
-#include <mlibc/threads.hpp>
-
-static bool enableTrace = false;
-
-struct ScopeTrace {
- ScopeTrace(const char *file, int line, const char *function)
- : _file(file), _line(line), _function(function) {
- if(!enableTrace)
- return;
- mlibc::infoLogger() << "trace: Enter scope "
- << _file << ":" << _line << " (in function "
- << _function << ")" << frg::endlog;
- }
-
- ~ScopeTrace() {
- if(!enableTrace)
- return;
- mlibc::infoLogger() << "trace: Exit scope" << frg::endlog;
- }
-
-private:
- const char *_file;
- int _line;
- const char *_function;
-};
-
-#define SCOPE_TRACE() ScopeTrace(__FILE__, __LINE__, __FUNCTION__)
-
-static constexpr unsigned int mutexRecursive = 1;
-static constexpr unsigned int mutexErrorCheck = 2;
-
-// TODO: either use uint32_t or determine the bit based on sizeof(int).
-static constexpr unsigned int mutex_owner_mask = (static_cast<uint32_t>(1) << 30) - 1;
-static constexpr unsigned int mutex_waiters_bit = static_cast<uint32_t>(1) << 31;
-
-// Only valid for the internal __mlibc_m mutex of wrlocks.
-static constexpr unsigned int mutex_excl_bit = static_cast<uint32_t>(1) << 30;
-
-static constexpr unsigned int rc_count_mask = (static_cast<uint32_t>(1) << 31) - 1;
-static constexpr unsigned int rc_waiters_bit = static_cast<uint32_t>(1) << 31;
-
-static constexpr size_t default_stacksize = 0x200000;
-static constexpr size_t default_guardsize = 4096;
-
-// ----------------------------------------------------------------------------
-// pthread_attr and pthread functions.
-// ----------------------------------------------------------------------------
-
-// pthread_attr functions.
-int pthread_attr_init(pthread_attr_t *attr) {
- *attr = pthread_attr_t{};
- attr->__mlibc_stacksize = default_stacksize;
- attr->__mlibc_guardsize = default_guardsize;
- attr->__mlibc_detachstate = PTHREAD_CREATE_JOINABLE;
- return 0;
-}
-
-int pthread_attr_destroy(pthread_attr_t *) {
- return 0;
-}
-
-int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) {
- *detachstate = attr->__mlibc_detachstate;
- return 0;
-}
-int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) {
- if (detachstate != PTHREAD_CREATE_DETACHED &&
- detachstate != PTHREAD_CREATE_JOINABLE)
- return EINVAL;
-
- attr->__mlibc_detachstate = detachstate;
- return 0;
-}
-
-int pthread_attr_getstacksize(const pthread_attr_t *__restrict attr, size_t *__restrict stacksize) {
- *stacksize = attr->__mlibc_stacksize;
- return 0;
-}
-
-int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) {
- if (stacksize < PTHREAD_STACK_MIN)
- return EINVAL;
- attr->__mlibc_stacksize = stacksize;
- return 0;
-}
-
-int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) {
- *stackaddr = attr->__mlibc_stackaddr;
- return 0;
-}
-int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) {
- attr->__mlibc_stackaddr = stackaddr;
- return 0;
-}
-
-int pthread_attr_getstack(const pthread_attr_t *attr, void **stackaddr, size_t *stacksize) {
- *stackaddr = attr->__mlibc_stackaddr;
- *stacksize = attr->__mlibc_stacksize;
- return 0;
-}
-int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize) {
- if (stacksize < PTHREAD_STACK_MIN)
- return EINVAL;
- attr->__mlibc_stacksize = stacksize;
- attr->__mlibc_stackaddr = stackaddr;
- return 0;
-}
-
-int pthread_attr_getguardsize(const pthread_attr_t *__restrict attr, size_t *__restrict guardsize) {
- *guardsize = attr->__mlibc_guardsize;
- return 0;
-}
-int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) {
- attr->__mlibc_guardsize = guardsize;
- return 0;
-}
-
-int pthread_attr_getscope(const pthread_attr_t *attr, int *scope) {
- *scope = attr->__mlibc_scope;
- return 0;
-}
-int pthread_attr_setscope(pthread_attr_t *attr, int scope) {
- if (scope != PTHREAD_SCOPE_SYSTEM &&
- scope != PTHREAD_SCOPE_PROCESS)
- return EINVAL;
- if (scope == PTHREAD_SCOPE_PROCESS)
- return ENOTSUP;
- attr->__mlibc_scope = scope;
- return 0;
-}
-
-int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched) {
- *inheritsched = attr->__mlibc_inheritsched;
- return 0;
-}
-int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched) {
- if (inheritsched != PTHREAD_INHERIT_SCHED &&
- inheritsched != PTHREAD_EXPLICIT_SCHED)
- return EINVAL;
- attr->__mlibc_inheritsched = inheritsched;
- return 0;
-}
-
-int pthread_attr_getschedparam(const pthread_attr_t *__restrict attr, struct sched_param *__restrict schedparam) {
- *schedparam = attr->__mlibc_schedparam;
- return 0;
-}
-int pthread_attr_setschedparam(pthread_attr_t *__restrict attr, const struct sched_param *__restrict schedparam) {
- // TODO: this is supposed to return EINVAL for when the schedparam doesn't make sense
- // for the given schedpolicy.
- attr->__mlibc_schedparam = *schedparam;
- return 0;
-}
-
-int pthread_attr_getschedpolicy(const pthread_attr_t *__restrict attr, int *__restrict policy) {
- *policy = attr->__mlibc_schedpolicy;
- return 0;
-}
-int pthread_attr_setschedpolicy(pthread_attr_t *__restrict attr, int policy) {
- if (policy != SCHED_FIFO && policy != SCHED_RR &&
- policy != SCHED_OTHER)
- return EINVAL;
- attr->__mlibc_schedpolicy = policy;
- return 0;
-}
-
-#if __MLIBC_LINUX_OPTION
-int pthread_attr_getaffinity_np(const pthread_attr_t *__restrict attr,
- size_t cpusetsize, cpu_set_t *__restrict cpusetp) {
- if (!attr)
- return EINVAL;
-
- if (!attr->__mlibc_cpuset) {
- memset(cpusetp, -1, cpusetsize);
- return 0;
- }
-
- for (size_t cnt = cpusetsize; cnt < attr->__mlibc_cpusetsize; cnt++)
- if (reinterpret_cast<char*>(attr->__mlibc_cpuset)[cnt] != '\0')
- return ERANGE;
-
- auto p = memcpy(cpusetp, attr->__mlibc_cpuset,
- std::min(cpusetsize, attr->__mlibc_cpusetsize));
- if (cpusetsize > attr->__mlibc_cpusetsize)
- memset(p, '\0', cpusetsize - attr->__mlibc_cpusetsize);
-
- return 0;
-}
-
-int pthread_attr_setaffinity_np(pthread_attr_t *__restrict attr,
- size_t cpusetsize, const cpu_set_t *__restrict cpusetp) {
- if (!attr)
- return EINVAL;
-
- if (!cpusetp || !cpusetsize) {
- attr->__mlibc_cpuset = NULL;
- attr->__mlibc_cpusetsize = 0;
- return 0;
- }
-
- if (attr->__mlibc_cpusetsize != cpusetsize) {
- auto newp = realloc(attr->__mlibc_cpuset, cpusetsize);
- if (!newp)
- return ENOMEM;
-
- attr->__mlibc_cpuset = static_cast<cpu_set_t*>(newp);
- attr->__mlibc_cpusetsize = cpusetsize;
- }
-
- memcpy(attr->__mlibc_cpuset, cpusetp, cpusetsize);
- return 0;
-}
-
-int pthread_attr_getsigmask_np(const pthread_attr_t *__restrict attr,
- sigset_t *__restrict sigmask) {
- if (!attr)
- return EINVAL;
-
- if (!attr->__mlibc_sigmaskset) {
- sigemptyset(sigmask);
- return PTHREAD_ATTR_NO_SIGMASK_NP;
- }
-
- *sigmask = attr->__mlibc_sigmask;
-
- return 0;
-}
-int pthread_attr_setsigmask_np(pthread_attr_t *__restrict attr,
- const sigset_t *__restrict sigmask) {
- if (!attr)
- return EINVAL;
-
- if (!sigmask) {
- attr->__mlibc_sigmaskset = 0;
- return 0;
- }
-
- attr->__mlibc_sigmask = *sigmask;
- attr->__mlibc_sigmaskset = 1;
-
- // Filter out internally used signals.
- sigdelset(&attr->__mlibc_sigmask, SIGCANCEL);
-
- return 0;
-}
-
-namespace {
- void get_own_stackinfo(void **stack_addr, size_t *stack_size) {
- auto fp = fopen("/proc/self/maps", "r");
- if (!fp) {
- mlibc::infoLogger() << "mlibc pthreads: /proc/self/maps does not exist! Producing incorrect"
- " stack results!" << frg::endlog;
- return;
- }
-
- char line[256];
- auto sp = mlibc::get_sp();
- while (fgets(line, 256, fp)) {
- uintptr_t from, to;
- if(sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
- continue;
- if (sp < to && sp > from) {
- // We need to return the lowest byte of the stack.
- *stack_addr = reinterpret_cast<void*>(from);
- *stack_size = to - from;
- fclose(fp);
- return;
- }
- }
-
- fclose(fp);
- }
-}
-
-int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr) {
- auto tcb = reinterpret_cast<Tcb*>(thread);
- *attr = pthread_attr_t{};
-
- if (!tcb->stackAddr || !tcb->stackSize) {
- get_own_stackinfo(&attr->__mlibc_stackaddr, &attr->__mlibc_stacksize);
- } else {
- attr->__mlibc_stacksize = tcb->stackSize;
- attr->__mlibc_stackaddr = tcb->stackAddr;
- }
-
- attr->__mlibc_guardsize = tcb->guardSize;
- attr->__mlibc_detachstate = tcb->isJoinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED;
- mlibc::infoLogger() << "pthread_getattr_np(): Implementation is incomplete!" << frg::endlog;
- return 0;
-}
-
-int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *mask) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getthreadaffinity, ENOSYS);
- return mlibc::sys_getthreadaffinity(reinterpret_cast<Tcb*>(thread)->tid, cpusetsize, mask);
-}
-
-int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *mask) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setthreadaffinity, ENOSYS);
- return mlibc::sys_setthreadaffinity(reinterpret_cast<Tcb*>(thread)->tid, cpusetsize, mask);
-}
-#endif // __MLIBC_LINUX_OPTION
-
-extern "C" Tcb *__rtdl_allocateTcb();
-
-// pthread functions.
-int pthread_create(pthread_t *__restrict thread, const pthread_attr_t *__restrict attrp,
- void *(*entry) (void *), void *__restrict user_arg) {
- return mlibc::thread_create(thread, attrp, reinterpret_cast<void *>(entry), user_arg, false);
-}
-
-pthread_t pthread_self(void) {
- return reinterpret_cast<pthread_t>(mlibc::get_current_tcb());
-}
-
-int pthread_equal(pthread_t t1, pthread_t t2) {
- if(t1 == t2)
- return 1;
- return 0;
-}
-
-namespace {
- struct key_global_info {
- bool in_use;
-
- void (*dtor)(void *);
- uint64_t generation;
- };
-
- constinit frg::array<
- key_global_info,
- PTHREAD_KEYS_MAX
- > key_globals_{};
-
- FutexLock key_mutex_;
-}
-
-namespace mlibc {
- __attribute__ ((__noreturn__)) void do_exit() {
- sys_thread_exit();
- __builtin_unreachable();
- }
-}
-
-__attribute__ ((__noreturn__)) void pthread_exit(void *ret_val) {
- auto self = mlibc::get_current_tcb();
-
- if (__atomic_load_n(&self->cancelBits, __ATOMIC_RELAXED) & tcbExitingBit)
- mlibc::do_exit();
-
- __atomic_fetch_or(&self->cancelBits, tcbExitingBit, __ATOMIC_RELAXED);
-
- auto hand = self->cleanupEnd;
- while (hand) {
- auto old = hand;
- hand->func(hand->arg);
- hand = hand->prev;
- frg::destruct(getAllocator(), old);
- }
-
- for (size_t j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++) {
- for (size_t i = 0; i < PTHREAD_KEYS_MAX; i++) {
- if (auto v = pthread_getspecific(i)) {
- key_mutex_.lock();
- auto dtor = key_globals_[i].dtor;
- key_mutex_.unlock();
-
- if (dtor) {
- dtor(v);
- (*self->localKeys)[i].value = nullptr;
- }
- }
- }
- }
-
- self->returnValue.voidPtr = ret_val;
- __atomic_store_n(&self->didExit, 1, __ATOMIC_RELEASE);
- mlibc::sys_futex_wake(&self->didExit);
-
- // TODO: clean up thread resources when we are detached.
-
- // TODO: do exit(0) when we're the only thread instead
- mlibc::do_exit();
-}
-
-int pthread_join(pthread_t thread, void **ret) {
- return mlibc::thread_join(thread, ret);
-}
-
-int pthread_detach(pthread_t thread) {
- auto tcb = reinterpret_cast<Tcb*>(thread);
- if (!__atomic_load_n(&tcb->isJoinable, __ATOMIC_RELAXED))
- return EINVAL;
-
- int expected = 1;
- if(!__atomic_compare_exchange_n(&tcb->isJoinable, &expected, 0, false, __ATOMIC_RELEASE,
- __ATOMIC_RELAXED))
- return EINVAL;
-
- return 0;
-}
-
-void pthread_cleanup_push(void (*func) (void *), void *arg) {
- auto self = mlibc::get_current_tcb();
-
- auto hand = frg::construct<Tcb::CleanupHandler>(getAllocator());
- hand->func = func;
- hand->arg = arg;
- hand->next = nullptr;
- hand->prev = self->cleanupEnd;
-
- if (self->cleanupEnd)
- self->cleanupEnd->next = hand;
-
- self->cleanupEnd = hand;
-
- if (!self->cleanupBegin)
- self->cleanupBegin = self->cleanupEnd;
-}
-
-void pthread_cleanup_pop(int execute) {
- auto self = mlibc::get_current_tcb();
-
- auto hand = self->cleanupEnd;
-
- if (self->cleanupEnd)
- self->cleanupEnd = self->cleanupEnd->prev;
- if (self->cleanupEnd)
- self->cleanupEnd->next = nullptr;
-
- if (execute)
- hand->func(hand->arg);
-
- frg::destruct(getAllocator(), hand);
-}
-
-int pthread_setname_np(pthread_t thread, const char *name) {
- auto tcb = reinterpret_cast<Tcb*>(thread);
-
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_thread_setname, ENOSYS);
- if(int e = sysdep(tcb, name); e) {
- return e;
- }
-
- return 0;
-}
-
-int pthread_getname_np(pthread_t thread, char *name, size_t size) {
- auto tcb = reinterpret_cast<Tcb*>(thread);
-
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_thread_getname, ENOSYS);
- if(int e = sysdep(tcb, name, size); e) {
- return e;
- }
-
- return 0;
-}
-
-int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param) {
- auto tcb = reinterpret_cast<Tcb*>(thread);
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setschedparam, ENOSYS);
- if(int e = mlibc::sys_setschedparam(tcb, policy, param); e) {
- return e;
- }
-
- return 0;
-}
-
-int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param) {
- auto tcb = reinterpret_cast<Tcb*>(thread);
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getschedparam, ENOSYS);
- if(int e = mlibc::sys_getschedparam(tcb, policy, param); e) {
- return e;
- }
-
- return 0;
-}
-
-//pthread cancel functions
-
-extern "C" void __mlibc_do_cancel() {
- //TODO(geert): for now the same as pthread_exit()
- pthread_exit(PTHREAD_CANCELED);
-}
-
-namespace {
-
- void sigcancel_handler(int signal, siginfo_t *info, void *ucontext) {
- ucontext_t *uctx = static_cast<ucontext_t*>(ucontext);
- // The function could be called from other signals, or from another
- // process, in which case we should do nothing.
- if (signal != SIGCANCEL || info->si_pid != getpid() ||
- info->si_code != SI_TKILL)
- return;
-
- auto tcb = reinterpret_cast<Tcb*>(mlibc::get_current_tcb());
- int old_value = tcb->cancelBits;
-
- /*
- * When a thread is marked with deferred cancellation and performs a blocking syscall,
- * the spec mandates that the syscall can get interrupted before it has caused any side
- * effects (e.g. before a read() has read any bytes from disk). If the syscall has
- * already caused side effects it should return its partial work, and set the program
- * counter just after the syscall. If the syscall hasn't caused any side effects, it
- * should fail with EINTR and set the program counter to the syscall instruction.
- *
- * cancellable_syscall:
- * test whether_a_cancel_is_queued
- * je cancel
- * syscall
- * end_cancellable_syscall
- *
- * The mlibc::sys_before_cancellable_syscall sysdep should return 1 when the
- * program counter is between the 'canellable_syscall' and 'end_cancellable_syscall' label.
- */
- if (!(old_value & tcbCancelAsyncBit) &&
- mlibc::sys_before_cancellable_syscall && !mlibc::sys_before_cancellable_syscall(uctx))
- return;
-
- int bitmask = tcbCancelTriggerBit | tcbCancelingBit;
- while (1) {
- int new_value = old_value | bitmask;
-
- // Check if we are already cancelled or exiting
- if (old_value == new_value || old_value & tcbExitingBit)
- return;
-
- int current_value = old_value;
- if (__atomic_compare_exchange_n(&tcb->cancelBits, &current_value,
- new_value, true,__ATOMIC_RELAXED, __ATOMIC_RELAXED)) {
- tcb->returnValue.voidPtr = PTHREAD_CANCELED;
-
- // Perform cancellation
- __mlibc_do_cancel();
-
- break;
- }
-
- old_value = current_value;
- }
- }
-}
-
-namespace mlibc {
-namespace {
-
-struct PthreadSignalInstaller {
- PthreadSignalInstaller() {
- struct sigaction sa;
- sa.sa_sigaction = sigcancel_handler;
- sa.sa_flags = SA_SIGINFO;
- auto e = ENOSYS;
- if(sys_sigaction)
- e = sys_sigaction(SIGCANCEL, &sa, NULL);
- // Opt-out of cancellation support.
- if(e == ENOSYS)
- return;
- __ensure(!e);
- }
-};
-
-PthreadSignalInstaller pthread_signal_installer;
-
-} // anonymous namespace
-} // namespace mlibc
-
-int pthread_setcanceltype(int type, int *oldtype) {
- if (type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS)
- return EINVAL;
-
- auto self = reinterpret_cast<Tcb *>(mlibc::get_current_tcb());
- int old_value = self->cancelBits;
- while (1) {
- int new_value = old_value & ~tcbCancelAsyncBit;
- if (type == PTHREAD_CANCEL_ASYNCHRONOUS)
- new_value |= tcbCancelAsyncBit;
-
- if (oldtype)
- *oldtype = ((old_value & tcbCancelAsyncBit)
- ? PTHREAD_CANCEL_ASYNCHRONOUS
- : PTHREAD_CANCEL_DEFERRED);
-
- // Avoid unecessary atomic op.
- if (old_value == new_value)
- break;
-
- int current_value = old_value;
- if (__atomic_compare_exchange_n(&self->cancelBits, &current_value,
- new_value, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) {
-
- if (mlibc::tcb_async_cancelled(new_value))
- __mlibc_do_cancel();
-
- break;
- }
-
- old_value = current_value;
- }
-
- return 0;
-}
-int pthread_setcancelstate(int state, int *oldstate) {
- if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)
- return EINVAL;
-
- auto self = reinterpret_cast<Tcb *>(mlibc::get_current_tcb());
- int old_value = self->cancelBits;
- while (1) {
- int new_value = old_value & ~tcbCancelEnableBit;
- if (state == PTHREAD_CANCEL_ENABLE)
- new_value |= tcbCancelEnableBit;
-
- if (oldstate)
- *oldstate = ((old_value & tcbCancelEnableBit)
- ? PTHREAD_CANCEL_ENABLE
- : PTHREAD_CANCEL_DISABLE);
-
- // Avoid unecessary atomic op.
- if (old_value == new_value)
- break;
-
- int current_value = old_value;
- if (__atomic_compare_exchange_n(&self->cancelBits, &current_value,
- new_value, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) {
-
- if (mlibc::tcb_async_cancelled(new_value))
- __mlibc_do_cancel();
-
- sigset_t set = {};
- sigaddset(&set, SIGCANCEL);
- if (new_value & PTHREAD_CANCEL_ENABLE)
- sigprocmask(SIG_UNBLOCK, &set, NULL);
- else
- sigprocmask(SIG_BLOCK, &set, NULL);
- break;
- }
-
- old_value = current_value;
- }
-
- return 0;
-}
-void pthread_testcancel(void) {
- auto self = reinterpret_cast<Tcb *>(mlibc::get_current_tcb());
- int value = self->cancelBits;
- if ((value & tcbCancelEnableBit) && (value & tcbCancelTriggerBit)) {
- __mlibc_do_cancel();
- __builtin_unreachable();
- }
-}
-int pthread_cancel(pthread_t thread) {
- if (!mlibc::sys_tgkill) {
- MLIBC_MISSING_SYSDEP();
- return ENOSYS;
- }
-
- auto tcb = reinterpret_cast<Tcb *>(thread);
- // Check if the TCB is valid, somewhat..
- if (tcb->selfPointer != tcb)
- return ESRCH;
-
- int old_value = __atomic_load_n(&tcb->cancelBits, __ATOMIC_RELAXED);
- while (1) {
- int bitmask = tcbCancelTriggerBit;
-
- int new_value = old_value | bitmask;
- if (old_value == new_value)
- break;
-
- int current_value = old_value;
- if (__atomic_compare_exchange_n(&tcb->cancelBits, &current_value,
- new_value, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) {
- if (mlibc::tcb_cancel_enabled(new_value)) {
- pid_t pid = getpid();
-
- int res = mlibc::sys_tgkill(pid, tcb->tid, SIGCANCEL);
-
- current_value = __atomic_load_n(&tcb->cancelBits, __ATOMIC_RELAXED);
-
- // If we can't find the thread anymore, it's possible that it exited between
- // us setting the cancel trigger bit, and us sending the signal. Check the
- // cancelBits for tcbExitingBit to confirm that.
- // XXX(qookie): This will be an use-after-free once we start freeing TCBs on
- // exit. Perhaps the TCB should be refcounted.
- if (!(res == ESRCH && (current_value & tcbExitingBit)))
- return res;
- }
-
- break;
- }
-
- old_value = current_value;
- }
-
- return 0;
-}
-
-int pthread_atfork(void (*prepare) (void), void (*parent) (void), void (*child) (void)) {
- auto self = mlibc::get_current_tcb();
-
- auto hand = frg::construct<Tcb::AtforkHandler>(getAllocator());
- if (!hand)
- return -1;
-
- hand->prepare = prepare;
- hand->parent = parent;
- hand->child = child;
- hand->next = nullptr;
- hand->prev = self->atforkEnd;
-
- if (self->atforkEnd)
- self->atforkEnd->next = hand;
-
- self->atforkEnd = hand;
-
- if (!self->atforkBegin)
- self->atforkBegin = self->atforkEnd;
-
- return 0;
-}
-
-// ----------------------------------------------------------------------------
-// pthread_key functions.
-// ----------------------------------------------------------------------------
-
-int pthread_key_create(pthread_key_t *out, void (*destructor)(void *)) {
- SCOPE_TRACE();
-
- auto g = frg::guard(&key_mutex_);
-
- pthread_key_t key = PTHREAD_KEYS_MAX;
- for (size_t i = 0; i < PTHREAD_KEYS_MAX; i++) {
- if (!key_globals_[i].in_use) {
- key = i;
- break;
- }
- }
-
- if (key == PTHREAD_KEYS_MAX)
- return EAGAIN;
-
- key_globals_[key].in_use = true;
- key_globals_[key].dtor = destructor;
-
- *out = key;
-
- return 0;
-}
-
-int pthread_key_delete(pthread_key_t key) {
- SCOPE_TRACE();
-
- auto g = frg::guard(&key_mutex_);
-
- if (key >= PTHREAD_KEYS_MAX || !key_globals_[key].in_use)
- return EINVAL;
-
- key_globals_[key].in_use = false;
- key_globals_[key].dtor = nullptr;
- key_globals_[key].generation++;
-
- return 0;
-}
-
-void *pthread_getspecific(pthread_key_t key) {
- SCOPE_TRACE();
-
- auto self = mlibc::get_current_tcb();
- auto g = frg::guard(&key_mutex_);
-
- if (key >= PTHREAD_KEYS_MAX || !key_globals_[key].in_use)
- return nullptr;
-
- if (key_globals_[key].generation > (*self->localKeys)[key].generation) {
- (*self->localKeys)[key].value = nullptr;
- (*self->localKeys)[key].generation = key_globals_[key].generation;
- }
-
- return (*self->localKeys)[key].value;
-}
-
-int pthread_setspecific(pthread_key_t key, const void *value) {
- SCOPE_TRACE();
-
- auto self = mlibc::get_current_tcb();
- auto g = frg::guard(&key_mutex_);
-
- if (key >= PTHREAD_KEYS_MAX || !key_globals_[key].in_use)
- return EINVAL;
-
- (*self->localKeys)[key].value = const_cast<void *>(value);
- (*self->localKeys)[key].generation = key_globals_[key].generation;
-
- return 0;
-}
-
-// ----------------------------------------------------------------------------
-// pthread_once functions.
-// ----------------------------------------------------------------------------
-
-static constexpr unsigned int onceComplete = 1;
-static constexpr unsigned int onceLocked = 2;
-
-int pthread_once(pthread_once_t *once, void (*function) (void)) {
- SCOPE_TRACE();
-
- auto expected = __atomic_load_n(&once->__mlibc_done, __ATOMIC_ACQUIRE);
-
- // fast path: the function was already run.
- while(!(expected & onceComplete)) {
- if(!expected) {
- // try to acquire the mutex.
- if(!__atomic_compare_exchange_n(&once->__mlibc_done,
- &expected, onceLocked, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE))
- continue;
-
- function();
-
- // unlock the mutex.
- __atomic_exchange_n(&once->__mlibc_done, onceComplete, __ATOMIC_RELEASE);
- if(int e = mlibc::sys_futex_wake((int *)&once->__mlibc_done); e)
- __ensure(!"sys_futex_wake() failed");
- return 0;
- }else{
- // a different thread is currently running the initializer.
- __ensure(expected == onceLocked);
- if(int e = mlibc::sys_futex_wait((int *)&once->__mlibc_done, onceLocked, nullptr); e)
- __ensure(!"sys_futex_wait() failed");
- expected = __atomic_load_n(&once->__mlibc_done, __ATOMIC_ACQUIRE);
- }
- }
-
- return 0;
-}
-
-// ----------------------------------------------------------------------------
-// pthread_mutexattr and pthread_mutex functions.
-// ----------------------------------------------------------------------------
-
-// pthread_mutexattr functions
-int pthread_mutexattr_init(pthread_mutexattr_t *attr) {
- SCOPE_TRACE();
- return mlibc::thread_mutexattr_init(attr);
-}
-
-int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) {
- SCOPE_TRACE();
- return mlibc::thread_mutexattr_destroy(attr);
-}
-
-int pthread_mutexattr_gettype(const pthread_mutexattr_t *__restrict attr, int *__restrict type) {
- return mlibc::thread_mutexattr_gettype(attr, type);
-}
-
-int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) {
- return mlibc::thread_mutexattr_settype(attr, type);
-}
-
-int pthread_mutexattr_getrobust(const pthread_mutexattr_t *__restrict attr,
- int *__restrict robust) {
- *robust = attr->__mlibc_robust;
- return 0;
-}
-int pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robust) {
- if (robust != PTHREAD_MUTEX_STALLED && robust != PTHREAD_MUTEX_ROBUST)
- return EINVAL;
-
- attr->__mlibc_robust = robust;
- return 0;
-}
-
-int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared) {
- *pshared = attr->__mlibc_pshared;
- return 0;
-}
-int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) {
- if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
- return EINVAL;
-
- attr->__mlibc_pshared = pshared;
- return 0;
-}
-
-int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *__restrict attr,
- int *__restrict protocol) {
- *protocol = attr->__mlibc_protocol;
- return 0;
-}
-
-int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol) {
- if (protocol != PTHREAD_PRIO_NONE && protocol != PTHREAD_PRIO_INHERIT
- && protocol != PTHREAD_PRIO_PROTECT)
- return EINVAL;
-
- attr->__mlibc_protocol = protocol;
- return 0;
-}
-
-int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict attr,
- int *__restrict prioceiling) {
- (void)attr;
- (void)prioceiling;
- return EINVAL;
-}
-
-int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling) {
- (void)attr;
- (void)prioceiling;
- return EINVAL;
-}
-
-// pthread_mutex functions
-int pthread_mutex_init(pthread_mutex_t *__restrict mutex,
- const pthread_mutexattr_t *__restrict attr) {
- SCOPE_TRACE();
-
- return mlibc::thread_mutex_init(mutex, attr);
-}
-
-int pthread_mutex_destroy(pthread_mutex_t *mutex) {
- return mlibc::thread_mutex_destroy(mutex);
-}
-
-int pthread_mutex_lock(pthread_mutex_t *mutex) {
- SCOPE_TRACE();
-
- return mlibc::thread_mutex_lock(mutex);
-}
-
-int pthread_mutex_trylock(pthread_mutex_t *mutex) {
- SCOPE_TRACE();
-
- unsigned int this_tid = mlibc::this_tid();
- unsigned int expected = __atomic_load_n(&mutex->__mlibc_state, __ATOMIC_RELAXED);
- if(!expected) {
- // Try to take the mutex here.
- if(__atomic_compare_exchange_n(&mutex->__mlibc_state,
- &expected, this_tid, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) {
- __ensure(!mutex->__mlibc_recursion);
- mutex->__mlibc_recursion = 1;
- return 0;
- }
- } else {
- // If this (recursive) mutex is already owned by us, increment the recursion level.
- if((expected & mutex_owner_mask) == this_tid) {
- if(!(mutex->__mlibc_flags & mutexRecursive)) {
- return EBUSY;
- }
- ++mutex->__mlibc_recursion;
- return 0;
- }
- }
-
- return EBUSY;
-}
-
-int pthread_mutex_timedlock(pthread_mutex_t *__restrict,
- const struct timespec *__restrict) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int pthread_mutex_unlock(pthread_mutex_t *mutex) {
- SCOPE_TRACE();
-
- return mlibc::thread_mutex_unlock(mutex);
-}
-
-int pthread_mutex_consistent(pthread_mutex_t *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-// ----------------------------------------------------------------------------
-// pthread_condattr and pthread_cond functions.
-// ----------------------------------------------------------------------------
-
-int pthread_condattr_init(pthread_condattr_t *attr) {
- attr->__mlibc_pshared = PTHREAD_PROCESS_PRIVATE;
- attr->__mlibc_clock = CLOCK_REALTIME;
- return 0;
-}
-
-int pthread_condattr_destroy(pthread_condattr_t *attr) {
- memset(attr, 0, sizeof(*attr));
- return 0;
-}
-
-int pthread_condattr_getclock(const pthread_condattr_t *__restrict attr,
- clockid_t *__restrict clock) {
- *clock = attr->__mlibc_clock;
- return 0;
-}
-
-int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock) {
- if (clock != CLOCK_REALTIME && clock != CLOCK_MONOTONIC
- && clock != CLOCK_MONOTONIC_RAW && clock != CLOCK_REALTIME_COARSE
- && clock != CLOCK_MONOTONIC_COARSE && clock != CLOCK_BOOTTIME)
- return EINVAL;
-
- attr->__mlibc_clock = clock;
- return 0;
-}
-
-int pthread_condattr_getpshared(const pthread_condattr_t *__restrict attr,
- int *__restrict pshared) {
- *pshared = attr->__mlibc_pshared;
- return 0;
-}
-
-int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared) {
- if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
- return EINVAL;
-
- attr->__mlibc_pshared = pshared;
- return 0;
-}
-
-int pthread_cond_init(pthread_cond_t *__restrict cond, const pthread_condattr_t *__restrict attr) {
- SCOPE_TRACE();
-
- return mlibc::thread_cond_init(cond, attr);
-}
-
-int pthread_cond_destroy(pthread_cond_t *cond) {
- SCOPE_TRACE();
-
- return mlibc::thread_cond_destroy(cond);
-}
-
-int pthread_cond_wait(pthread_cond_t *__restrict cond, pthread_mutex_t *__restrict mutex) {
- return pthread_cond_timedwait(cond, mutex, nullptr);
-}
-
-int pthread_cond_timedwait(pthread_cond_t *__restrict cond, pthread_mutex_t *__restrict mutex,
- const struct timespec *__restrict abstime) {
- return mlibc::thread_cond_timedwait(cond, mutex, abstime);
-}
-
-int pthread_cond_signal(pthread_cond_t *cond) {
- SCOPE_TRACE();
-
- return pthread_cond_broadcast(cond);
-}
-
-int pthread_cond_broadcast(pthread_cond_t *cond) {
- SCOPE_TRACE();
-
- return mlibc::thread_cond_broadcast(cond);
-}
-
-// ----------------------------------------------------------------------------
-// pthread_barrierattr and pthread_barrier functions.
-// ----------------------------------------------------------------------------
-
-int pthread_barrierattr_init(pthread_barrierattr_t *attr) {
- attr->__mlibc_pshared = PTHREAD_PROCESS_PRIVATE;
- return 0;
-}
-
-int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr,
- int *__restrict pshared) {
- *pshared = attr->__mlibc_pshared;
- return 0;
-}
-
-int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) {
- if (pshared != PTHREAD_PROCESS_SHARED && pshared != PTHREAD_PROCESS_PRIVATE)
- return EINVAL;
-
- attr->__mlibc_pshared = pshared;
- return 0;
-}
-
-int pthread_barrierattr_destroy(pthread_barrierattr_t *) {
- return 0;
-}
-
-int pthread_barrier_init(pthread_barrier_t *__restrict barrier,
- const pthread_barrierattr_t *__restrict attr, unsigned count) {
- if (count == 0)
- return EINVAL;
-
- barrier->__mlibc_waiting = 0;
- barrier->__mlibc_inside = 0;
- barrier->__mlibc_seq = 0;
- barrier->__mlibc_count = count;
-
- // Since we don't implement these yet, set a flag to error later.
- auto pshared = attr ? attr->__mlibc_pshared : PTHREAD_PROCESS_PRIVATE;
- barrier->__mlibc_flags = pshared;
-
- return 0;
-}
-
-int pthread_barrier_destroy(pthread_barrier_t *barrier) {
- // Wait until there are no threads still using the barrier.
- unsigned inside = 0;
- do {
- unsigned expected = __atomic_load_n(&barrier->__mlibc_inside, __ATOMIC_RELAXED);
- if (expected == 0)
- break;
-
- int e = mlibc::sys_futex_wait((int *)&barrier->__mlibc_inside, expected, nullptr);
- if (e != 0 && e != EAGAIN && e != EINTR)
- mlibc::panicLogger() << "mlibc: sys_futex_wait() returned error " << e << frg::endlog;
- } while (inside > 0);
-
- memset(barrier, 0, sizeof *barrier);
- return 0;
-}
-
-int pthread_barrier_wait(pthread_barrier_t *barrier) {
- if (barrier->__mlibc_flags != 0) {
- mlibc::panicLogger() << "mlibc: pthread_barrier_t flags were non-zero"
- << frg::endlog;
- }
-
- // inside is incremented on entry and decremented on exit.
- // This is used to synchronise with pthread_barrier_destroy, to ensure that a thread doesn't pass
- // the barrier and immediately destroy its state while other threads still rely on it.
-
- __atomic_fetch_add(&barrier->__mlibc_inside, 1, __ATOMIC_ACQUIRE);
-
- auto leave = [&](){
- unsigned inside = __atomic_sub_fetch(&barrier->__mlibc_inside, 1, __ATOMIC_RELEASE);
- if (inside == 0)
- mlibc::sys_futex_wake((int *)&barrier->__mlibc_inside);
- };
-
- unsigned seq = __atomic_load_n(&barrier->__mlibc_seq, __ATOMIC_ACQUIRE);
-
- while (true) {
- unsigned expected = __atomic_load_n(&barrier->__mlibc_waiting, __ATOMIC_RELAXED);
- bool swapped = __atomic_compare_exchange_n(&barrier->__mlibc_waiting, &expected, expected + 1, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
-
- if (swapped) {
- if (expected + 1 == barrier->__mlibc_count) {
- // We were the last thread to hit the barrier. Reset waiters and wake the others.
- __atomic_fetch_add(&barrier->__mlibc_seq, 1, __ATOMIC_ACQUIRE);
- __atomic_store_n(&barrier->__mlibc_waiting, 0, __ATOMIC_RELEASE);
-
- mlibc::sys_futex_wake((int *)&barrier->__mlibc_seq);
-
- leave();
- return PTHREAD_BARRIER_SERIAL_THREAD;
- }
-
- while (true) {
- int e = mlibc::sys_futex_wait((int *)&barrier->__mlibc_seq, seq, nullptr);
- if (e != 0 && e != EAGAIN && e != EINTR)
- mlibc::panicLogger() << "mlibc: sys_futex_wait() returned error " << e << frg::endlog;
-
- unsigned newSeq = __atomic_load_n(&barrier->__mlibc_seq, __ATOMIC_ACQUIRE);
- if (newSeq > seq) {
- leave();
- return 0;
- }
- }
- }
- }
-}
-
-// ----------------------------------------------------------------------------
-// pthread_rwlock functions.
-// ----------------------------------------------------------------------------
-
-namespace {
- void rwlock_m_lock(pthread_rwlock_t *rw, bool excl) {
- unsigned int m_expected = __atomic_load_n(&rw->__mlibc_m, __ATOMIC_RELAXED);
- while(true) {
- if(m_expected) {
- __ensure(m_expected & mutex_owner_mask);
-
- // Try to set the waiters bit.
- if(!(m_expected & mutex_waiters_bit)) {
- unsigned int desired = m_expected | mutex_waiters_bit;
- if(!__atomic_compare_exchange_n(&rw->__mlibc_m,
- &m_expected, desired, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED))
- continue;
- }
-
- // Wait on the futex.
- mlibc::sys_futex_wait((int *)&rw->__mlibc_m, m_expected | mutex_waiters_bit, nullptr);
-
- // Opportunistically try to take the lock after we wake up.
- m_expected = 0;
- }else{
- // Try to lock the mutex.
- unsigned int desired = 1;
- if(excl)
- desired |= mutex_excl_bit;
- if(__atomic_compare_exchange_n(&rw->__mlibc_m,
- &m_expected, desired, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
- break;
- }
- }
- }
-
- int rwlock_m_trylock(pthread_rwlock_t *rw, bool excl) {
- unsigned int m_expected = __atomic_load_n(&rw->__mlibc_m, __ATOMIC_RELAXED);
- if(!m_expected) {
- // Try to lock the mutex.
- unsigned int desired = 1;
- if(excl)
- desired |= mutex_excl_bit;
- if(__atomic_compare_exchange_n(&rw->__mlibc_m,
- &m_expected, desired, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
- return 0;
- }
-
- __ensure(m_expected & mutex_owner_mask);
-
- // POSIX says that this function should never block but also that
- // readers should not be blocked by readers. We implement this by returning EAGAIN
- // (and not EBUSY) if a reader would block a reader.
- if(!excl && !(m_expected & mutex_excl_bit))
- return EAGAIN;
-
- return EBUSY;
- }
-
- void rwlock_m_unlock(pthread_rwlock_t *rw) {
- auto m = __atomic_exchange_n(&rw->__mlibc_m, 0, __ATOMIC_RELEASE);
- if(m & mutex_waiters_bit)
- mlibc::sys_futex_wake((int *)&rw->__mlibc_m);
- }
-}
-
-int pthread_rwlockattr_init(pthread_rwlockattr_t *attr) {
- attr->__mlibc_pshared = PTHREAD_PROCESS_PRIVATE;
- return 0;
-}
-
-int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *__restrict attr,
- int *__restrict pshared) {
- *pshared = attr->__mlibc_pshared;
- return 0;
-}
-
-int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared) {
- if (pshared != PTHREAD_PROCESS_SHARED && pshared != PTHREAD_PROCESS_PRIVATE)
- return EINVAL;
-
- attr->__mlibc_pshared = pshared;
- return 0;
-}
-
-int pthread_rwlockattr_destroy(pthread_rwlockattr_t *) {
- return 0;
-}
-
-int pthread_rwlock_init(pthread_rwlock_t *__restrict rw, const pthread_rwlockattr_t *__restrict attr) {
- SCOPE_TRACE();
- rw->__mlibc_m = 0;
- rw->__mlibc_rc = 0;
-
- // Since we don't implement this yet, set a flag to error later.
- auto pshared = attr ? attr->__mlibc_pshared : PTHREAD_PROCESS_PRIVATE;
- rw->__mlibc_flags = pshared;
- return 0;
-}
-
-int pthread_rwlock_destroy(pthread_rwlock_t *rw) {
- __ensure(!rw->__mlibc_m);
- __ensure(!rw->__mlibc_rc);
- return 0;
-}
-
-int pthread_rwlock_trywrlock(pthread_rwlock_t *rw) {
- SCOPE_TRACE();
-
- if (rw->__mlibc_flags != 0) {
- mlibc::panicLogger() << "mlibc: pthread_rwlock_t flags were non-zero"
- << frg::endlog;
- }
-
- // Take the __mlibc_m mutex.
- // Will be released in pthread_rwlock_unlock().
- if(int e = rwlock_m_trylock(rw, true))
- return e;
-
- // Check that there are no readers.
- unsigned int rc_expected = __atomic_load_n(&rw->__mlibc_rc, __ATOMIC_ACQUIRE);
- if(rc_expected) {
- rwlock_m_unlock(rw);
- return EBUSY;
- }
-
- return 0;
-}
-
-int pthread_rwlock_wrlock(pthread_rwlock_t *rw) {
- SCOPE_TRACE();
-
- if (rw->__mlibc_flags != 0) {
- mlibc::panicLogger() << "mlibc: pthread_rwlock_t flags were non-zero"
- << frg::endlog;
- }
-
- // Take the __mlibc_m mutex.
- // Will be released in pthread_rwlock_unlock().
- rwlock_m_lock(rw, true);
-
- // Now wait until there are no more readers.
- unsigned int rc_expected = __atomic_load_n(&rw->__mlibc_rc, __ATOMIC_ACQUIRE);
- while(true) {
- if(!rc_expected)
- break;
-
- __ensure(rc_expected & rc_count_mask);
-
- // Try to set the waiters bit.
- if(!(rc_expected & rc_waiters_bit)) {
- unsigned int desired = rc_expected | rc_count_mask;
- if(!__atomic_compare_exchange_n(&rw->__mlibc_rc,
- &rc_expected, desired, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE))
- continue;
- }
-
- // Wait on the futex.
- mlibc::sys_futex_wait((int *)&rw->__mlibc_rc, rc_expected | rc_waiters_bit, nullptr);
-
- // Re-check the reader counter.
- rc_expected = __atomic_load_n(&rw->__mlibc_rc, __ATOMIC_ACQUIRE);
- }
-
- return 0;
-}
-
-int pthread_rwlock_tryrdlock(pthread_rwlock_t *rw) {
- SCOPE_TRACE();
-
- if (rw->__mlibc_flags != 0) {
- mlibc::panicLogger() << "mlibc: pthread_rwlock_t flags were non-zero"
- << frg::endlog;
- }
-
- // Increment the reader count while holding the __mlibc_m mutex.
- if(int e = rwlock_m_trylock(rw, false); e)
- return e;
- __atomic_fetch_add(&rw->__mlibc_rc, 1, __ATOMIC_ACQUIRE);
- rwlock_m_unlock(rw);
-
- return 0;
-}
-
-int pthread_rwlock_rdlock(pthread_rwlock_t *rw) {
- SCOPE_TRACE();
-
- if (rw->__mlibc_flags != 0) {
- mlibc::panicLogger() << "mlibc: pthread_rwlock_t flags were non-zero"
- << frg::endlog;
- }
-
- // Increment the reader count while holding the __mlibc_m mutex.
- rwlock_m_lock(rw, false);
- __atomic_fetch_add(&rw->__mlibc_rc, 1, __ATOMIC_ACQUIRE);
- rwlock_m_unlock(rw);
-
- return 0;
-}
-
-int pthread_rwlock_unlock(pthread_rwlock_t *rw) {
- SCOPE_TRACE();
-
- unsigned int rc_expected = __atomic_load_n(&rw->__mlibc_rc, __ATOMIC_RELAXED);
- if(!rc_expected) {
- // We are doing a write-unlock.
- rwlock_m_unlock(rw);
- return 0;
- }else{
- // We are doing a read-unlock.
- while(true) {
- unsigned int count = rc_expected & rc_count_mask;
- __ensure(count);
-
- // Try to decrement the count.
- if(count == 1 && (rc_expected & rc_waiters_bit)) {
- unsigned int desired = 0;
- if(!__atomic_compare_exchange_n(&rw->__mlibc_rc,
- &rc_expected, desired, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED))
- continue;
-
- // Wake the futex.
- mlibc::sys_futex_wake((int *)&rw->__mlibc_rc);
- break;
- }else{
- unsigned int desired = (rc_expected & ~rc_count_mask) | (count - 1);
- if(!__atomic_compare_exchange_n(&rw->__mlibc_rc,
- &rc_expected, desired, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED))
- continue;
- break;
- }
- }
-
- return 0;
- }
-}
-
-int pthread_getcpuclockid(pthread_t, clockid_t *) {
- mlibc::infoLogger() << "mlibc: pthread_getcpuclockid() always returns ENOENT"
- << frg::endlog;
- return ENOENT;
-}
diff --git a/lib/mlibc/options/posix/generic/pwd-stubs.cpp b/lib/mlibc/options/posix/generic/pwd-stubs.cpp
deleted file mode 100644
index 5d8f618..0000000
--- a/lib/mlibc/options/posix/generic/pwd-stubs.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-
-#include <errno.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <bits/ensure.h>
-
-#include <mlibc/debug.hpp>
-
-namespace {
- FILE *global_file; // Used by setpwent/getpwent/endpwent.
-
- bool open_global_file() {
- if(!global_file) {
- global_file = fopen("/etc/passwd", "r");
- if(!global_file) {
- errno = EIO;
- return false;
- }
- }
-
- return true;
- }
-
- void close_global_file() {
- if(global_file) {
- fclose(global_file);
- global_file = nullptr;
- }
- }
-
- bool extract_entry(frg::string_view line, passwd *entry) {
- frg::string_view segments[8];
-
- // Parse the line into 7 or 8 segments.
- size_t s = 0;
- int n;
- for(n = 0; n < 7; n++) {
- size_t d = line.find_first(':', s);
- if(d == size_t(-1))
- break;
- segments[n] = line.sub_string(s, d - s);
- s = d + 1;
- }
- if(line.find_first(':', s) != size_t(-1))
- return false;
- segments[n] = line.sub_string(s, line.size() - s);
- n++;
-
- if(n < 7)
- return false;
-
- // TODO: Handle strndup() failure.
- auto name = strndup(segments[0].data(), segments[0].size());
- __ensure(name);
-
- auto passwd = strndup(segments[1].data(), segments[1].size());
- __ensure(passwd);
-
- auto uid = segments[2].to_number<int>();
- if(!uid)
- return false;
- auto gid = segments[3].to_number<int>();
- if(!gid)
- return false;
-
- auto real_name = strndup(segments[4].data(), segments[4].size());
- __ensure(real_name);
- auto dir = strndup(segments[5].data(), segments[5].size());
- __ensure(dir);
- auto shell = strndup(segments[6].data(), segments[6].size());
- __ensure(shell);
-
- // Chop the newline off the end of shell
- __ensure(strlen(shell) > 0);
- shell[strlen(shell) - 1] = '\0';
-
- entry->pw_name = name;
- entry->pw_passwd = passwd;
- entry->pw_uid = *uid;
- entry->pw_gid = *gid;
- entry->pw_dir = dir;
- entry->pw_shell = shell;
- entry->pw_gecos = real_name;
- return true;
- }
-
- void copy_to_buffer(passwd *pwd, char *buffer, size_t size) {
- char *pw_dir = stpcpy(buffer, pwd->pw_name) + 1;
- free(pwd->pw_name);
- pwd->pw_name = buffer;
-
- char *pw_shell = stpcpy(pw_dir, pwd->pw_dir) + 1;
- free(pwd->pw_dir);
- pwd->pw_dir = pw_dir;
-
- char *pw_passwd = stpcpy(pw_shell, pwd->pw_shell) + 1;
- free(pwd->pw_shell);
- pwd->pw_shell = pw_shell;
-
- char *end = stpcpy(pw_passwd, pwd->pw_passwd);
- __ensure(end <= buffer + size);
- free(pwd->pw_passwd);
- pwd->pw_passwd = pw_passwd;
- }
-
- void clear_entry(passwd *entry) {
- free(entry->pw_name);
- free(entry->pw_dir);
- free(entry->pw_passwd);
- free(entry->pw_shell);
- entry->pw_name = nullptr;
- entry->pw_dir = nullptr;
- entry->pw_passwd = nullptr;
- entry->pw_shell = nullptr;
- }
-}
-
-struct passwd *getpwent(void) {
- static passwd entry;
- char line[NSS_BUFLEN_PASSWD];
-
- if(!open_global_file()) {
- return nullptr;
- }
-
- if (fgets(line, NSS_BUFLEN_PASSWD, global_file)) {
- clear_entry(&entry);
- if(!extract_entry(line, &entry)) {
- errno = EINVAL; // I suppose this can be a valid errno?
- return nullptr;
- }
- return &entry;
- }
-
- if(ferror(global_file)) {
- errno = EIO;
- }
-
- return nullptr;
-}
-
-struct passwd *getpwnam(const char *name) {
- static passwd entry;
- auto file = fopen("/etc/passwd", "r");
- if(!file)
- return nullptr;
-
- char line[NSS_BUFLEN_PASSWD];
- while(fgets(line, NSS_BUFLEN_PASSWD, file)) {
- clear_entry(&entry);
- if(!extract_entry(line, &entry))
- continue;
- if(!strcmp(entry.pw_name, name)) {
- fclose(file);
- return &entry;
- }
- }
-
- int err = errno;
- if(ferror(file)) {
- err = EIO;
- }
-
- fclose(file);
- errno = err;
- return nullptr;
-}
-
-int getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t size, struct passwd **result) {
- *result = nullptr;
- auto file = fopen("/etc/passwd", "r");
- if(!file) {
- return EIO;
- }
-
- char line[NSS_BUFLEN_PASSWD];
- while(fgets(line, NSS_BUFLEN_PASSWD, file)) {
- if(!extract_entry(line, pwd))
- continue;
- if(!strcmp(pwd->pw_name, name)) {
- fclose(file);
-
- size_t required_size = strlen(pwd->pw_name) + strlen(pwd->pw_dir)
- + strlen(pwd->pw_shell) + strlen(pwd->pw_passwd) + 4;
- if (size < required_size)
- return ERANGE;
-
- copy_to_buffer(pwd, buffer, size);
- *result = pwd;
- return 0;
- }
- }
-
- int ret = 0;
- if(ferror(file)) {
- ret = EIO;
- }
-
- fclose(file);
- return ret;
-}
-
-struct passwd *getpwuid(uid_t uid) {
- static passwd entry;
- auto file = fopen("/etc/passwd", "r");
- if(!file)
- return nullptr;
-
- char line[NSS_BUFLEN_PASSWD];
- while(fgets(line, NSS_BUFLEN_PASSWD, file)) {
- clear_entry(&entry);
- if(!extract_entry(line, &entry))
- continue;
- if(entry.pw_uid == uid) {
- fclose(file);
- return &entry;
- }
- }
-
- int err = ESRCH;
- if(ferror(file)) {
- err = EIO;
- }
-
- fclose(file);
- errno = err;
- return nullptr;
-}
-
-int getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t size, struct passwd **result) {
- *result = nullptr;
- auto file = fopen("/etc/passwd", "r");
- if(!file) {
- return EIO;
- }
-
- char line[NSS_BUFLEN_PASSWD];
- while(fgets(line, NSS_BUFLEN_PASSWD, file)) {
- if(!extract_entry(line, pwd))
- continue;
- if(pwd->pw_uid == uid) {
- fclose(file);
-
- size_t required_size = strlen(pwd->pw_name) + strlen(pwd->pw_dir)
- + strlen(pwd->pw_shell) + + strlen(pwd->pw_passwd) + 4;
- if (size < required_size)
- return ERANGE;
-
- copy_to_buffer(pwd, buffer, size);
- *result = pwd;
- return 0;
- }
- }
-
- int ret = 0;
- if(ferror(file)) {
- ret = EIO;
- }
-
- fclose(file);
- return ret;
-}
-
-void setpwent(void) {
- if(!open_global_file()) {
- return;
- }
- rewind(global_file);
-}
-
-void endpwent(void) {
- close_global_file();
-}
-
-int putpwent(const struct passwd *, FILE *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-struct passwd *fgetpwent(FILE *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/resolv_conf.cpp b/lib/mlibc/options/posix/generic/resolv_conf.cpp
deleted file mode 100644
index a5c3aa7..0000000
--- a/lib/mlibc/options/posix/generic/resolv_conf.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <mlibc/resolv_conf.hpp>
-#include <mlibc/allocator.hpp>
-#include <stdio.h>
-#include <ctype.h>
-
-namespace mlibc {
-
-frg::optional<struct nameserver_data> get_nameserver() {
- auto file = fopen("/etc/resolv.conf", "r");
- if (!file)
- return frg::null_opt;
-
- char line[128];
- struct nameserver_data ret;
- while (fgets(line, 128, file)) {
- char *pos;
- if (!strchr(line, '\n') && !feof(file)) {
- // skip truncated lines
- for (int c = getc(file); c != '\n' && c != EOF; c = getc(file));
- continue;
- }
-
- // TODO(geert): resolv.conf can actually have multiple nameservers
- // but we just pick the first one for now
- if (!strncmp(line, "nameserver", 10) && isspace(line[10])) {
- char *end;
- for (pos = line + 11; isspace(*pos); pos++);
- for (end = pos; *end && !isspace(*end); end++);
- *end = '\0';
- ret.name = frg::string<MemoryAllocator>(
- pos, end - pos, getAllocator());
- break;
- }
- }
-
- fclose(file);
- if(ret.name.empty())
- return frg::null_opt;
- return ret;
-}
-
-} // namespace mlibc
diff --git a/lib/mlibc/options/posix/generic/sched-stubs.cpp b/lib/mlibc/options/posix/generic/sched-stubs.cpp
deleted file mode 100644
index 9d75d50..0000000
--- a/lib/mlibc/options/posix/generic/sched-stubs.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-
-#include <bits/ensure.h>
-#include <errno.h>
-#include <limits.h>
-#include <sched.h>
-
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-int sched_yield(void) {
- if(mlibc::sys_yield) {
- mlibc::sys_yield();
- }else{
- // Missing sched_yield() is not an error.
- MLIBC_MISSING_SYSDEP();
- }
- return 0;
-}
-
-int sched_get_priority_max(int policy) {
- int res = 0;
-
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_get_max_priority, -1);
- if(int e = sysdep(policy, &res); e) {
- errno = e;
- return -1;
- }
- return res;
-}
-
-int sched_get_priority_min(int policy) {
- int res = 0;
-
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_get_min_priority, -1);
- if(int e = sysdep(policy, &res); e) {
- errno = e;
- return -1;
- }
- return res;
-}
-
-int sched_setscheduler(pid_t, int, const struct sched_param *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int sched_getparam(pid_t, struct sched_param *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/search.cpp b/lib/mlibc/options/posix/generic/search.cpp
deleted file mode 100644
index e6f8c1d..0000000
--- a/lib/mlibc/options/posix/generic/search.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-
-#include <bits/ensure.h>
-#include <search.h>
-#include <stddef.h>
-#include <new>
-#include <mlibc/allocator.hpp>
-#include <frg/stack.hpp>
-#include <stdlib.h>
-
-struct node {
- const void *key;
- void *a[2];
- int h;
-};
-
-namespace {
- int height(struct node *node) {
- return node ? node->h : 0;
- }
-
- int rotate(struct node **nodep, int side) {
- struct node *node = *nodep;
- struct node *x = static_cast<struct node *>(node->a[side]);
- struct node *y = static_cast<struct node *>(x->a[!side]);
- struct node *z = static_cast<struct node *>(x->a[side]);
-
- int height_node = node->h;
- int height_y = height(y);
- if (height_y > height(z)) {
- // Perform double rotation
- node->a[side] = y->a[!side];
- x->a[!side] = y->a[side];
- y->a[!side] = node;
- y->a[side] = x;
- node->h = height_y;
- x->h = height_y;
- y->h = height_y + 1;
- } else {
- // Perform single rotation
- node->a[side] = y;
- x->a[!side] = node;
- node->h = height_y + 1;
- x->h = height_y + 2;
- y = x;
-
- }
- *nodep = y;
- return y->h - height_node;
- }
-
- int balance_tree(struct node **nodep) {
- struct node *node = *nodep;
- int height_a = height(static_cast<struct node *>(node->a[0]));
- int height_b = height(static_cast<struct node *>(node->a[1]));
- if (height_a - height_b < 2) {
- int old = node->h;
- node->h = height_a < height_b ? height_b + 1 : height_a + 1;
- return node->h - old;
- }
-
- return rotate(nodep, height_a < height_b);
- }
-}
-
-void *tsearch(const void *key, void **rootp, int(*compar)(const void *, const void *)) {
- if (!rootp)
- return NULL;
-
- struct node *n = static_cast<struct node *>(*rootp);
- frg::stack<struct node **, MemoryAllocator> nodes(getAllocator());
- nodes.push(reinterpret_cast<struct node **>(rootp));
- int c = 0;
- for (;;) {
- if (!n)
- break;
- c = compar(key, n->key);
- if (!c)
- return n;
- nodes.push(reinterpret_cast<struct node **>(&n->a[c > 0]));
- n = static_cast<struct node *>(n->a[c > 0]);
- }
-
- struct node *insert = static_cast<struct node*>(malloc(sizeof(struct node)));
- if (!insert)
- return NULL;
- insert->key = key;
- insert->a[0] = insert->a[1] = NULL;
- insert->h = 1;
-
- (*nodes.top()) = insert;
- nodes.pop();
- while(nodes.size() && balance_tree(nodes.top())) nodes.pop();
- return insert;
-}
-
-// This implementation is taken from musl
-void *tfind(const void *key, void *const *rootp, int (*compar)(const void *, const void *)) {
- if(!rootp)
- return 0;
-
- struct node *n = (struct node *)*rootp;
- for(;;) {
- if(!n)
- break;
- int c = compar(key, n->key);
- if(!c)
- break;
- n = (struct node *)n->a[c > 0];
- }
- return n;
-}
-
-void *tdelete(const void *, void **, int(*compar)(const void *, const void *)) {
- (void)compar;
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void twalk(const void *, void (*action)(const void *, VISIT, int)) {
- (void)action;
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void tdestroy(void *, void (*free_node)(void *)) {
- (void)free_node;
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void *lsearch(const void *key, void *base, size_t *nelp, size_t width,
- int (*compar)(const void *, const void *)) {
- (void)key;
- (void)base;
- (void)nelp;
- (void)width;
- (void)compar;
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void *lfind(const void *key, const void *base, size_t *nelp,
- size_t width, int (*compar)(const void *, const void *)) {
- (void)key;
- (void)base;
- (void)nelp;
- (void)width;
- (void)compar;
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/semaphore-stubs.cpp b/lib/mlibc/options/posix/generic/semaphore-stubs.cpp
deleted file mode 100644
index d41eccb..0000000
--- a/lib/mlibc/options/posix/generic/semaphore-stubs.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-#include <semaphore.h>
-#include <errno.h>
-
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-#include <mlibc/ansi-sysdeps.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-static constexpr unsigned int semaphoreHasWaiters = static_cast<uint32_t>(1 << 31);
-static constexpr unsigned int semaphoreCountMask = static_cast<uint32_t>(1 << 31) - 1;
-
-int sem_init(sem_t *sem, int pshared, unsigned int initial_count) {
- if (pshared) {
- mlibc::infoLogger() << "mlibc: shared semaphores are unsuppored" << frg::endlog;
- errno = ENOSYS;
- return -1;
- }
-
- if (initial_count > SEM_VALUE_MAX) {
- errno = EINVAL;
- return -1;
- }
-
- sem->__mlibc_count = initial_count;
-
- return 0;
-}
-
-int sem_destroy(sem_t *) {
- return 0;
-}
-
-int sem_wait(sem_t *sem) {
- unsigned int state = 0;
-
- while (1) {
- if (!(state & semaphoreCountMask)) {
- if (__atomic_compare_exchange_n(&sem->__mlibc_count, &state, semaphoreHasWaiters,
- false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) {
- int e = mlibc::sys_futex_wait((int *)&sem->__mlibc_count, state, nullptr);
- if (e == 0 || e == EAGAIN) {
- continue;
- } else if (e == EINTR) {
- errno = EINTR;
- return -1;
- } else {
- mlibc::panicLogger() << "sys_futex_wait() failed with error code " << e << frg::endlog;
- }
- }
- } else {
- unsigned int desired = (state - 1);
- if (__atomic_compare_exchange_n(&sem->__mlibc_count, &state, desired, false,
- __ATOMIC_RELAXED, __ATOMIC_RELAXED))
- return 0;
- }
- }
-}
-
-int sem_timedwait(sem_t *sem, const struct timespec *) {
- mlibc::infoLogger() << "\e[31mmlibc: sem_timedwait is implemented as sem_wait\e[0m" << frg::endlog;
- return sem_wait(sem);
-}
-
-int sem_post(sem_t *sem) {
- auto old_count = __atomic_load_n(&sem->__mlibc_count, __ATOMIC_RELAXED) & semaphoreCountMask;
-
- if (old_count + 1 > SEM_VALUE_MAX) {
- errno = EOVERFLOW;
- return -1;
- }
-
- auto state = __atomic_exchange_n(&sem->__mlibc_count, old_count + 1, __ATOMIC_RELEASE);
-
- if (state & semaphoreHasWaiters)
- if (int e = mlibc::sys_futex_wake((int *)&sem->__mlibc_count); e)
- __ensure(!"sys_futex_wake() failed");
-
- return 0;
-}
-
-sem_t *sem_open(const char *, int, ...) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int sem_close(sem_t *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int sem_getvalue(sem_t *, int *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int sem_unlink(const char *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int sem_trywait(sem_t *sem) {
- while (true) {
- auto state = __atomic_load_n(&sem->__mlibc_count, __ATOMIC_ACQUIRE);
-
- if (state & semaphoreHasWaiters) {
- return EAGAIN;
- }
-
- auto desired = state - 1;
- if (__atomic_compare_exchange_n(&sem->__mlibc_count, &state, desired, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED)) {
- return 0;
- }
- }
-}
diff --git a/lib/mlibc/options/posix/generic/services.cpp b/lib/mlibc/options/posix/generic/services.cpp
deleted file mode 100644
index 8ae0656..0000000
--- a/lib/mlibc/options/posix/generic/services.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-#include <mlibc/services.hpp>
-#include <netdb.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <mlibc/debug.hpp>
-
-namespace mlibc {
-
-static int parse_rest(service_buf &buf, char *end, int proto) {
- if (!strncmp(end, "/udp", 4)) {
- if (proto == IPPROTO_TCP && proto != -1)
- return 0;
- buf.protocol = IPPROTO_UDP;
- buf.socktype = SOCK_DGRAM;
- } else if (!strncmp(end, "/tcp", 4)) {
- if (proto == IPPROTO_UDP && proto != -1)
- return 0;
- buf.protocol = IPPROTO_TCP;
- buf.socktype = SOCK_STREAM;
- } else {
- return 0;
- }
-
- //TODO(geert): also parse aliases.
-
- return 1;
-}
-
-static int lookup_serv_file_port(service_result &buf, int proto, int port) {
- auto file = fopen(_PATH_SERVICES, "r");
- if (!file) {
- switch (errno) {
- case ENOENT:
- case ENOTDIR:
- case EACCES:
- return -EAI_SERVICE;
- default:
- return -EAI_SYSTEM;
- }
- }
-
- char line_buf[129] = {0};
- char *line = line_buf + 1;
- while(fgets(line, 128, file)) {
- int name_length = 0;
- char *pos;
- // easy way to handle comments, just move the end of the line
- // to the beginning of the comment
- if ((pos = strchr(line, '#'))) {
- *pos++ = '\n';
- *pos = '\0';
- }
-
- char *end = NULL;
- for (pos = line; *pos; pos++) {
- for (; isalpha(*pos); pos++);
- int rport = strtoul(pos, &end, 10);
- if (rport != port || rport > 65535) {
- pos = end;
- continue;
- }
-
- // We have found the port, time to rewind to the start
- // of the line.
- for (; pos[-1]; pos--)
- if(!isspace(pos[-1]))
- name_length++;
- break;
- }
-
- if (!pos)
- continue;
-
- if (!name_length)
- continue;
-
- auto name = frg::string<MemoryAllocator>(pos, name_length,
- getAllocator());
-
- struct service_buf sbuf = {};
- sbuf.port = port;
- sbuf.name = std::move(name);
- if (!parse_rest(sbuf, end, proto))
- continue;
- buf.push_back(std::move(sbuf));
- }
-
- fclose(file);
- return buf.size();
-}
-
-static int lookup_serv_file_name(service_result &buf, const char *name,
- int proto) {
- auto file = fopen(_PATH_SERVICES, "r");
- if (!file) {
- switch (errno) {
- case ENOENT:
- case ENOTDIR:
- case EACCES:
- return -EAI_SERVICE;
- default:
- return -EAI_SYSTEM;
- }
- }
-
- char line[128];
- int name_length = strlen(name);
- while(fgets(line, 128, file)) {
- char *pos;
- // easy way to handle comments, just move the end of the line
- // to the beginning of the comment
- if ((pos = strchr(line, '#'))) {
- *pos++ = '\n';
- *pos = '\0';
- }
-
- for (pos = line; (pos = strstr(pos, name)); pos++) {
- // the name must start and end with a space
- if (pos > line && !isspace(pos[-1]))
- continue;
- if (pos[name_length] && !isspace(pos[name_length]))
- continue;
- break;
- }
- if (!pos)
- continue;
-
- // Skip the name at the beginning of the line.
- for(pos = line; *pos && !isspace(*pos); pos++)
- ;
-
- char *end = NULL;
- int port = strtoul(pos, &end, 10);
- if (port > 65535 || end == pos)
- continue;
-
- struct service_buf sbuf;
- sbuf.port = port;
- sbuf.name = frg::string<MemoryAllocator>(name, getAllocator());
- if (!parse_rest(sbuf, end, proto))
- continue;
-
- buf.push_back(sbuf);
-
- }
-
- fclose(file);
- return buf.size();
-}
-
-
-// This function returns a negative error code, since a positive
-// return code means success.
-int lookup_serv_by_name(service_result &buf, const char *name, int proto,
- int socktype, int flags) {
- switch(socktype) {
- case SOCK_STREAM:
- if (!proto)
- proto = IPPROTO_TCP;
- else if (proto != IPPROTO_TCP)
- return -EAI_SERVICE;
- break;
- case SOCK_DGRAM:
- if (!proto)
- proto = IPPROTO_UDP;
- else if (proto != IPPROTO_UDP)
- return -EAI_SERVICE;
- break;
- case 0:
- break;
- default:
- if (name)
- return -EAI_SERVICE;
- buf[0].port = 0;
- buf[0].socktype = socktype;
- buf[0].protocol = proto;
- return 1;
- }
-
- char *end = nullptr;
- unsigned int port = 0;
- int count = 0;
-
- if (name) {
- if (!*name)
- return -EAI_SERVICE;
- port = strtoul(name, &end, 10);
- }
- // The end pointer is a null pointer so the name was a port
- // or the name was not specified.
- if (!end || !*end) {
- if (proto != IPPROTO_UDP) {
- buf[count].port = port;
- buf[count].protocol = IPPROTO_TCP;
- buf[count].socktype = SOCK_STREAM;
- count++;
- }
- if (proto != IPPROTO_TCP) {
- buf[count].port = port;
- buf[count].protocol = IPPROTO_UDP;
- buf[count].socktype = SOCK_DGRAM;
- count++;
- }
- return count;
- }
-
- if (flags & AI_NUMERICSERV)
- return -EAI_NONAME;
-
- return lookup_serv_file_name(buf, name, proto);
-}
-
-int lookup_serv_by_port(service_result &buf, int proto, int port) {
- return lookup_serv_file_port(buf, proto, port);
-}
-
-} // namespace mlibc
diff --git a/lib/mlibc/options/posix/generic/spawn-stubs.cpp b/lib/mlibc/options/posix/generic/spawn-stubs.cpp
deleted file mode 100644
index cf7edfc..0000000
--- a/lib/mlibc/options/posix/generic/spawn-stubs.cpp
+++ /dev/null
@@ -1,376 +0,0 @@
-
-#include <spawn.h>
-#include <errno.h>
-#include <pthread.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <limits.h>
-#include <sched.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/wait.h>
-
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-
-/*
- * Musl places this in a seperate header called fdop.h
- * This header isn't present in glibc, or on my host, so I
- * include it's contents here
- */
-
-#define FDOP_CLOSE 1
-#define FDOP_DUP2 2
-#define FDOP_OPEN 3
-#define FDOP_CHDIR 4
-#define FDOP_FCHDIR 5
-
-struct fdop {
- struct fdop *next, *prev;
- int cmd, fd, srcfd, oflag;
- mode_t mode;
- char path[];
-};
-
-/*
- * This posix_spawn implementation is taken from musl
- */
-
-static unsigned long handler_set[NSIG / (8 * sizeof(long))];
-
-static void __get_handler_set(sigset_t *set) {
- memcpy(set, handler_set, sizeof handler_set);
-}
-
-struct args {
- int p[2];
- sigset_t oldmask;
- const char *path;
- const posix_spawn_file_actions_t *fa;
- const posix_spawnattr_t *__restrict attr;
- char *const *argv, *const *envp;
-};
-
-static int child(void *args_vp) {
- int i, ret;
- struct sigaction sa = {};
- struct args *args = (struct args *)args_vp;
- int p = args->p[1];
- const posix_spawn_file_actions_t *fa = args->fa;
- const posix_spawnattr_t *__restrict attr = args->attr;
- sigset_t hset;
- bool use_execvpe = false;
-
- if(attr->__fn)
- use_execvpe = true;
-
- close(args->p[0]);
-
- /* All signal dispositions must be either SIG_DFL or SIG_IGN
- * before signals are unblocked. Otherwise a signal handler
- * from the parent might get run in the child while sharing
- * memory, with unpredictable and dangerous results. To
- * reduce overhead, sigaction has tracked for us which signals
- * potentially have a signal handler. */
- __get_handler_set(&hset);
- for(i = 1; i < NSIG; i++) {
- if((attr->__flags & POSIX_SPAWN_SETSIGDEF) && sigismember(&attr->__def, i)) {
- sa.sa_handler = SIG_DFL;
- } else if(sigismember(&hset, i)) {
- if (i - 32 < 3) {
- sa.sa_handler = SIG_IGN;
- } else {;
- sigaction(i, 0, &sa);
- if(sa.sa_handler == SIG_IGN)
- continue;
- sa.sa_handler = SIG_DFL;
- }
- } else {
- continue;
- }
- sigaction(i, &sa, 0);
- }
-
- if(attr->__flags & POSIX_SPAWN_SETSID) {
- if((ret = setsid()) < 0)
- goto fail;
- }
-
- if(attr->__flags & POSIX_SPAWN_SETPGROUP) {
- mlibc::infoLogger() << "mlibc: posix_spawn: ignoring SETPGROUP" << frg::endlog;
- //if((ret = setpgid(0, attr->__pgrp)))
- // goto fail;
- }
-
- if(attr->__flags & POSIX_SPAWN_RESETIDS) {
- if((ret = setgid(getgid())) || (ret = setuid(getuid())) )
- goto fail;
- }
-
- if(fa && fa->__actions) {
- struct fdop *op;
- int fd;
- for(op = (struct fdop *)fa->__actions; op->next; op = op->next);
- for(; op; op = op->prev) {
- /* It's possible that a file operation would clobber
- * the pipe fd used for synchronizing with the
- * parent. To avoid that, we dup the pipe onto
- * an unoccupied fd. */
- if(op->fd == p) {
- ret = dup(p);
- if(ret < 0)
- goto fail;
- close(p);
- p = ret;
- }
- switch(op->cmd) {
- case FDOP_CLOSE:
- close(op->fd);
- break;
- case FDOP_DUP2:
- fd = op->srcfd;
- if(fd == p) {
- ret = -EBADF;
- goto fail;
- }
- if(fd != op->fd) {
- if((ret = dup2(fd, op->fd)) < 0)
- goto fail;
- } else {
- ret = fcntl(fd, F_GETFD);
- ret = fcntl(fd, F_SETFD, ret & ~FD_CLOEXEC);
- if(ret < 0)
- goto fail;
- }
- break;
- case FDOP_OPEN:
- fd = open(op->path, op->oflag, op->mode);
- if((ret = fd) < 0)
- goto fail;
- if(fd != op->fd) {
- if((ret = dup2(fd, op->fd)) < 0)
- goto fail;
- close(fd);
- }
- break;
- case FDOP_CHDIR:
- ret = chdir(op->path);
- if(ret < 0)
- goto fail;
- break;
- case FDOP_FCHDIR:
- ret = fchdir(op->fd);
- if(ret < 0)
- goto fail;
- break;
- }
- }
- }
-
- /* Close-on-exec flag may have been lost if we moved the pipe
- * to a different fd. */
- fcntl(p, F_SETFD, FD_CLOEXEC);
-
- pthread_sigmask(SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK)
- ? &attr->__mask : &args->oldmask, 0);
-
- if(use_execvpe)
- execvpe(args->path, args->argv, args->envp);
- else
- execve(args->path, args->argv, args->envp);
- ret = -errno;
-
-fail:
- /* Since sizeof errno < PIPE_BUF, the write is atomic. */
- ret = -ret;
- if(ret)
- while(write(p, &ret, sizeof ret) < 0);
- _exit(127);
-}
-
-int posix_spawn(pid_t *__restrict res, const char *__restrict path,
- const posix_spawn_file_actions_t *file_actions,
- const posix_spawnattr_t *__restrict attrs,
- char *const argv[], char *const envp[]) {
- pid_t pid;
- int ec = 0, cs;
- struct args args;
- const posix_spawnattr_t empty_attr = {};
- sigset_t full_sigset;
- sigfillset(&full_sigset);
-
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
-
- args.path = path;
- args.fa = file_actions;
- args.attr = attrs ? attrs : &empty_attr;
- args.argv = argv;
- args.envp = envp;
- pthread_sigmask(SIG_BLOCK, &full_sigset, &args.oldmask);
-
- /* The lock guards both against seeing a SIGABRT disposition change
- * by abort and against leaking the pipe fd to fork-without-exec. */
- //LOCK(__abort_lock);
-
- if(pipe2(args.p, O_CLOEXEC)) {
- //UNLOCK(__abort_lock);
- ec = errno;
- goto fail;
- }
-
- /* Mlibc change: We use fork + execve, as clone is not implemented.
- * This yields the same result in the end. */
- //pid = clone(child, stack + sizeof stack, CLONE_VM | CLONE_VFORK | SIGCHLD, &args);
- pid = fork();
- if(!pid) {
- child(&args);
- }
- close(args.p[1]);
- //UNLOCK(__abort_lock);
-
- if(pid > 0) {
- if(read(args.p[0], &ec, sizeof ec) != sizeof ec)
- ec = 0;
- else
- waitpid(pid, 0, 0);
- } else {
- ec = -pid;
- }
-
- close(args.p[0]);
-
- if(!ec && res)
- *res = pid;
-
-fail:
- pthread_sigmask(SIG_SETMASK, &args.oldmask, 0);
- pthread_setcancelstate(cs, 0);
-
- return ec;
-}
-
-int posix_spawnattr_init(posix_spawnattr_t *attr) {
- *attr = (posix_spawnattr_t){};
- return 0;
-}
-
-int posix_spawnattr_destroy(posix_spawnattr_t *) {
- return 0;
-}
-
-int posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags) {
- const unsigned all_flags =
- POSIX_SPAWN_RESETIDS |
- POSIX_SPAWN_SETPGROUP |
- POSIX_SPAWN_SETSIGDEF |
- POSIX_SPAWN_SETSIGMASK |
- POSIX_SPAWN_SETSCHEDPARAM |
- POSIX_SPAWN_SETSCHEDULER |
- POSIX_SPAWN_USEVFORK |
- POSIX_SPAWN_SETSID;
- if(flags & ~all_flags)
- return EINVAL;
- attr->__flags = flags;
- return 0;
-}
-
-int posix_spawnattr_setsigdefault(posix_spawnattr_t *__restrict attr,
- const sigset_t *__restrict sigdefault) {
- attr->__def = *sigdefault;
- return 0;
-}
-
-int posix_spawnattr_setschedparam(posix_spawnattr_t *__restrict,
- const struct sched_param *__restrict) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int posix_spawnattr_setsigmask(posix_spawnattr_t *__restrict attr,
- const sigset_t *__restrict sigmask) {
- attr->__mask = *sigmask;
- return 0;
-}
-
-int posix_spawnattr_setpgroup(posix_spawnattr_t *attr, pid_t pgroup) {
- attr->__pgrp = pgroup;
- return 0;
-}
-
-int posix_spawn_file_actions_init(posix_spawn_file_actions_t *file_actions) {
- file_actions->__actions = 0;
- return 0;
-}
-
-int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *file_actions) {
- struct fdop *op = (struct fdop *)file_actions->__actions, *next;
- while(op) {
- next = op->next;
- free(op);
- op = next;
- }
- return 0;
-}
-
-int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *file_actions,
- int fildes, int newfildes) {
- struct fdop *op = (struct fdop *)malloc(sizeof *op);
- if(!op)
- return ENOMEM;
- op->cmd = FDOP_DUP2;
- op->srcfd = fildes;
- op->fd = newfildes;
- if((op->next = (struct fdop *)file_actions->__actions))
- op->next->prev = op;
- op->prev = 0;
- file_actions->__actions = op;
- return 0;
-}
-
-int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *file_actions,
- int fildes) {
- struct fdop *op = (struct fdop *)malloc(sizeof *op);
- if(!op)
- return ENOMEM;
- op->cmd = FDOP_CLOSE;
- op->fd = fildes;
- if((op->next = (struct fdop *)file_actions->__actions))
- op->next->prev = op;
- op->prev = 0;
- file_actions->__actions = op;
- return 0;
-}
-
-int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *__restrict file_actions,
- int fildes, const char *__restrict path, int oflag, mode_t mode) {
- struct fdop *op = (struct fdop *)malloc(sizeof *op + strlen(path) + 1);
- if(!op)
- return ENOMEM;
- op->cmd = FDOP_OPEN;
- op->fd = fildes;
- op->oflag = oflag;
- op->mode = mode;
- strcpy(op->path, path);
- if((op->next = (struct fdop *)file_actions->__actions))
- op->next->prev = op;
- op->prev = 0;
- file_actions->__actions = op;
- return 0;
-}
-
-int posix_spawnp(pid_t *__restrict pid, const char *__restrict file,
- const posix_spawn_file_actions_t *file_actions,
- const posix_spawnattr_t *__restrict attrp,
- char *const argv[], char *const envp[]) {
- posix_spawnattr_t spawnp_attr = {};
- if(attrp)
- spawnp_attr = *attrp;
- spawnp_attr.__fn = (void *)execvpe;
- return posix_spawn(pid, file, file_actions, &spawnp_attr, argv, envp);
-}
-
diff --git a/lib/mlibc/options/posix/generic/strings-stubs.cpp b/lib/mlibc/options/posix/generic/strings-stubs.cpp
deleted file mode 100644
index 524c424..0000000
--- a/lib/mlibc/options/posix/generic/strings-stubs.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-
-#include <strings.h>
-#include <string.h>
-
-#include <ctype.h>
-#include <bits/ensure.h>
-#include <mlibc/strings.hpp>
-
-char *index (const char *s, int c) {
- return strchr(s, c);
-}
-
-char *rindex(const char *s, int c) {
- return strrchr(s, c);
-}
-
-namespace {
-
- template<typename T>
- int ffs_generic(T i) {
- //Non-portably assume a byte has 8 bits; fine in all plausible cases.
- for(size_t b = 0; b < sizeof(T) * 8;)
- if(i & (static_cast<T>(0x1) << b++))
- return b;
-
- return 0;
- }
-
-}
-
-// On RISC-V, __builtin_ffs just calls into ffs, so we can't use it here.
-#if defined(__has_builtin) && !defined(__riscv)
-# if __has_builtin(__builtin_ffs)
-# define __mlibc_ffs __builtin_ffs
-# endif
-# if __has_builtin(__builtin_ffsl)
-# define __mlibc_ffsl __builtin_ffsl
-# endif
-# if __has_builtin(__builtin_ffsll)
-# define __mlibc_ffsll __builtin_ffsll
-# endif
-#endif
-
-int ffs(int i) {
-#ifdef __mlibc_ffs
- return __mlibc_ffs(i);
-#else
- return ffs_generic<int>(i);
-#endif
-}
-
-/*
- Both ffsl() and ffsll() are glibc extensions
- defined in string.h. They are however implemented
- here because of similarity in logic and
- shared code.
-*/
-
-int ffsl(long i) {
-#ifdef __mlibc_ffsl
- return __mlibc_ffsl(i);
-#else
- return ffs_generic<long>(i);
-#endif
-}
-
-int ffsll(long long i) {
-#ifdef __mlibc_ffsll
- return __mlibc_ffsll(i);
-#else
- return ffs_generic<long long>(i);
-#endif
-}
-
-int strcasecmp(const char *a, const char *b) {
- size_t i = 0;
- while(true) {
- unsigned char a_byte = tolower(a[i]);
- unsigned char b_byte = tolower(b[i]);
- if(!a_byte && !b_byte)
- return 0;
- // If only one char is null, one of the following cases applies.
- if(a_byte < b_byte)
- return -1;
- if(a_byte > b_byte)
- return 1;
- i++;
- }
-}
-
-int strncasecmp(const char *a, const char *b, size_t size) {
- return mlibc::strncasecmp(a, b, size);
-}
-
-// Marked as obsolete in posix 2008 but used by at least tracker
-int bcmp(const void *s1, const void *s2, size_t n) {
- return memcmp(s1, s2, n);
-}
-
-void bcopy(const void *s1, void *s2, size_t n) {
- memmove(s2, s1, n);
-}
-
-void bzero(void *s, size_t n) {
- memset(s, 0, n);
-}
-
diff --git a/lib/mlibc/options/posix/generic/sys-file-stubs.cpp b/lib/mlibc/options/posix/generic/sys-file-stubs.cpp
deleted file mode 100644
index e1cc9ab..0000000
--- a/lib/mlibc/options/posix/generic/sys-file-stubs.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-
-#include <sys/file.h>
-#include <mlibc/posix-sysdeps.hpp>
-#include <errno.h>
-
-#include <bits/ensure.h>
-
-int flock(int fd, int opt) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_flock, -1);
- if(int e = mlibc::sys_flock(fd, opt); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
diff --git a/lib/mlibc/options/posix/generic/sys-ipc.cpp b/lib/mlibc/options/posix/generic/sys-ipc.cpp
deleted file mode 100644
index b9e0d3d..0000000
--- a/lib/mlibc/options/posix/generic/sys-ipc.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <sys/ipc.h>
-
-#include <bits/ensure.h>
-
-key_t ftok(const char *, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/sys-mman-stubs.cpp b/lib/mlibc/options/posix/generic/sys-mman-stubs.cpp
deleted file mode 100644
index 9383976..0000000
--- a/lib/mlibc/options/posix/generic/sys-mman-stubs.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-
-#include <errno.h>
-#include <limits.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <bits/ensure.h>
-
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-int mprotect(void *pointer, size_t size, int prot) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_vm_protect, -1);
- if(int e = mlibc::sys_vm_protect(pointer, size, prot); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int mlock(const void *addr, size_t len) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_mlock, -1);
- if(int e = mlibc::sys_mlock(addr, len); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int mlockall(int flags) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_mlockall, -1);
- if(int e = mlibc::sys_mlockall(flags); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int munlock(const void *addr, size_t len) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_munlock, -1);
- if(int e = mlibc::sys_munlock(addr, len); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int munlockall(void) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_munlockall, -1);
- if(int e = mlibc::sys_munlockall(); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-
-int posix_madvise(void *, size_t, int) {
- mlibc::infoLogger() << "\e[31m" "mlibc: posix_madvise() fails unconditionally" "\e[39m"
- << frg::endlog;
- return ENOSYS;
-}
-
-int msync(void *addr, size_t length, int flags) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_msync, -1);
- if(int e = mlibc::sys_msync(addr, length, flags); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-void *mremap(void *pointer, size_t size, size_t new_size, int flags, ...) {
- __ensure(flags == MREMAP_MAYMOVE);
-
- void *window;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_vm_remap, (void *)-1);
- if(int e = mlibc::sys_vm_remap(pointer, size, new_size, &window); e) {
- errno = e;
- return (void *)-1;
- }
- return window;
-}
-
-int remap_file_pages(void *, size_t, int, size_t, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void *mmap(void *hint, size_t size, int prot, int flags, int fd, off_t offset) {
- void *window;
- if(int e = mlibc::sys_vm_map(hint, size, prot, flags, fd, offset, &window); e) {
- errno = e;
- return (void *)-1;
- }
- return window;
-}
-
-int munmap(void *pointer, size_t size) {
- if(int e = mlibc::sys_vm_unmap(pointer, size); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-// The implementation of shm_open and shm_unlink is taken from musl.
-namespace {
- char *shm_mapname(const char *name, char *buf) {
- char *p;
- while(*name == '/')
- name++;
- if(*(p = strchrnul(name, '/')) || p == name ||
- (p - name <= 2 && name[0] == '.' && p[-1] == '.')) {
- errno = EINVAL;
- return 0;
- }
- if(p - name > NAME_MAX) {
- errno = ENAMETOOLONG;
- return 0;
- }
- memcpy(buf, "/dev/shm/", 9);
- memcpy(buf + 9, name, p - name + 1);
- return buf;
- }
-}
-
-int shm_open(const char *name, int flags, mode_t mode) {
- int cs;
- char buf[NAME_MAX + 10];
- if(!(name = shm_mapname(name, buf)))
- return -1;
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
- int fd = open(name, flags | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK, mode);
- pthread_setcancelstate(cs, 0);
- return fd;
-}
-
-int shm_unlink(const char *name) {
- char buf[NAME_MAX + 10];
- if(!(name = shm_mapname(name, buf)))
- return -1;
- return unlink(name);
-}
-
-#if __MLIBC_LINUX_OPTION
-int memfd_create(const char *name, unsigned int flags) {
- int ret = -1;
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_memfd_create, -1);
- if(int e = mlibc::sys_memfd_create(name, flags, &ret)) {
- errno = e;
- return -1;
- }
-
- return ret;
-}
-
-int madvise(void *addr, size_t length, int advice) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_madvise, -1);
- if(int e = mlibc::sys_madvise(addr, length, advice)) {
- errno = e;
- return -1;
- }
-
- return 0;
-}
-
-int mincore(void *addr, size_t length, unsigned char *vec) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_munlockall, -1);
- if(int e = mlibc::sys_mincore(addr, length, vec); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-#endif /* __MLIBC_LINUX_OPTION */
diff --git a/lib/mlibc/options/posix/generic/sys-msg.cpp b/lib/mlibc/options/posix/generic/sys-msg.cpp
deleted file mode 100644
index 95f067e..0000000
--- a/lib/mlibc/options/posix/generic/sys-msg.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-
-#include <bits/ensure.h>
-#include <sys/msg.h>
-
-int msgget(key_t, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int msgctl(int, int, struct msqid_ds *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-ssize_t msgrcv(int, void *, size_t, long, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int msgsnd(int, const void *, size_t, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/sys-resource-stubs.cpp b/lib/mlibc/options/posix/generic/sys-resource-stubs.cpp
deleted file mode 100644
index 597de4d..0000000
--- a/lib/mlibc/options/posix/generic/sys-resource-stubs.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-
-#include <errno.h>
-#include <sys/resource.h>
-
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-int getpriority(int which, id_t who) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getpriority, -1);
- int value = 0;
- if(int e = mlibc::sys_getpriority(which, who, &value); e) {
- errno = e;
- }
- return value;
-}
-
-int setpriority(int which, id_t who, int prio) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setpriority, -1);
- if(int e = mlibc::sys_setpriority(which, who, prio); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int getrusage(int scope, struct rusage *usage) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getrusage, -1);
- if(int e = mlibc::sys_getrusage(scope, usage); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int getrlimit(int resource, struct rlimit *limit) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getrlimit, -1);
- if(int e = mlibc::sys_getrlimit(resource, limit); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int setrlimit(int resource, const struct rlimit *limit) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setrlimit, -1);
- if(int e = mlibc::sys_setrlimit(resource, limit); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int prlimit(pid_t, int, const struct rlimit *, struct rlimit *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/sys-select-stubs.cpp b/lib/mlibc/options/posix/generic/sys-select-stubs.cpp
deleted file mode 100644
index e8ff927..0000000
--- a/lib/mlibc/options/posix/generic/sys-select-stubs.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-
-#include <string.h>
-#include <sys/select.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <bits/ensure.h>
-#include <mlibc-config.h>
-
-#include <mlibc/posix-sysdeps.hpp>
-
-void __FD_CLR(int fd, fd_set *set) {
- __ensure(fd < FD_SETSIZE);
- set->__mlibc_elems[fd / 8] &= ~(1 << (fd % 8));
-}
-int __FD_ISSET(int fd, fd_set *set) {
- __ensure(fd < FD_SETSIZE);
- return set->__mlibc_elems[fd / 8] & (1 << (fd % 8));
-}
-void __FD_SET(int fd, fd_set *set) {
- __ensure(fd < FD_SETSIZE);
- set->__mlibc_elems[fd / 8] |= 1 << (fd % 8);
-}
-void __FD_ZERO(fd_set *set) {
- memset(set->__mlibc_elems, 0, sizeof(fd_set));
-}
-
-int select(int num_fds, fd_set *__restrict read_set, fd_set *__restrict write_set,
- fd_set *__restrict except_set, struct timeval *__restrict timeout) {
- int num_events = 0;
- struct timespec timeouts = {};
- struct timespec *timeout_ptr = NULL;
- if (timeout) {
- timeouts.tv_sec = timeout->tv_sec;
- timeouts.tv_nsec = timeout->tv_usec * 1000;
- timeout_ptr = &timeouts;
- }
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_pselect, -1);
- if(int e = mlibc::sys_pselect(num_fds, read_set, write_set, except_set,
- timeout_ptr, NULL, &num_events); e) {
- errno = e;
- return -1;
- }
- return num_events;
-}
-
-int pselect(int num_fds, fd_set *read_set, fd_set *write_set, fd_set *except_set,
- const struct timespec *timeout, const sigset_t *sigmask) {
- int num_events = 0;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_pselect, -1);
- if(int e = mlibc::sys_pselect(num_fds, read_set, write_set, except_set,
- timeout, sigmask, &num_events); e) {
- errno = e;
- return -1;
- }
- return num_events;
-}
diff --git a/lib/mlibc/options/posix/generic/sys-sem.cpp b/lib/mlibc/options/posix/generic/sys-sem.cpp
deleted file mode 100644
index ac3df69..0000000
--- a/lib/mlibc/options/posix/generic/sys-sem.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-
-#include <bits/ensure.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/sem.h>
-
-#include <mlibc/posix-sysdeps.hpp>
-
-int semget(key_t key, int n, int fl) {
- if(n > USHRT_MAX) {
- errno = EINVAL;
- return -1;
- }
-
- int id = 0;
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_semget, -1);
- if(int e = sysdep(key, n, fl, &id); e) {
- errno = e;
- return -1;
- }
- return id;
-}
-
-int semop(int, struct sembuf *, size_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-union semun {
- int val;
- struct semid_ds *buf;
- unsigned short *array;
-};
-
-int semctl(int id, int num, int cmd, ...) {
- union semun semun;
- int ret = 0;
-
- va_list ap;
- va_start(ap, cmd);
- semun = va_arg(ap, union semun);
- va_end(ap);
-
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_semctl, -1);
- if(int e = sysdep(id, num, cmd, semun.buf, &ret); e) {
- errno = e;
- return -1;
- }
-
- return ret;
-}
diff --git a/lib/mlibc/options/posix/generic/sys-shm.cpp b/lib/mlibc/options/posix/generic/sys-shm.cpp
deleted file mode 100644
index 3af7e90..0000000
--- a/lib/mlibc/options/posix/generic/sys-shm.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <sys/shm.h>
-
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-
-void *shmat(int, const void *, int) {
- __ensure(!"Function is not implemented");
- __builtin_unreachable();
-}
-
-int shmctl(int, int, struct shmid_ds *) {
- __ensure(!"Function is not implemented");
- __builtin_unreachable();
-}
-
-int shmdt(const void *) {
- __ensure(!"Function is not implemented");
- __builtin_unreachable();
-}
-
-int shmget(key_t, size_t, int) {
- mlibc::infoLogger() << "mlibc: shmget() is a no-op!" << frg::endlog;
- return -1;
-}
diff --git a/lib/mlibc/options/posix/generic/sys-socket-stubs.cpp b/lib/mlibc/options/posix/generic/sys-socket-stubs.cpp
deleted file mode 100644
index 037a994..0000000
--- a/lib/mlibc/options/posix/generic/sys-socket-stubs.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <sys/socket.h>
-
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-int accept(int fd, struct sockaddr *__restrict addr_ptr, socklen_t *__restrict addr_length) {
- int newfd;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_accept, -1);
- if(int e = mlibc::sys_accept(fd, &newfd, addr_ptr, addr_length, 0); e) {
- errno = e;
- return -1;
- }
- return newfd;
-}
-
-int accept4(int fd, struct sockaddr *__restrict addr_ptr, socklen_t *__restrict addr_length, int flags) {
- int newfd;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_accept, -1);
- if(int e = mlibc::sys_accept(fd, &newfd, addr_ptr, addr_length, flags); e) {
- errno = e;
- return -1;
- }
-
- return newfd;
-}
-
-int bind(int fd, const struct sockaddr *addr_ptr, socklen_t addr_len) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_bind, -1);
- if(int e = mlibc::sys_bind(fd, addr_ptr, addr_len); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int connect(int fd, const struct sockaddr *addr_ptr, socklen_t addr_len) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_connect, -1);
- if(int e = mlibc::sys_connect(fd, addr_ptr, addr_len); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int getpeername(int fd, struct sockaddr *addr_ptr, socklen_t *__restrict addr_length) {
- socklen_t actual_length;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_peername, -1);
- if(int e = mlibc::sys_peername(fd, addr_ptr, *addr_length, &actual_length); e) {
- errno = e;
- return -1;
- }
- *addr_length = actual_length;
- return 0;
-}
-
-int getsockname(int fd, struct sockaddr *__restrict addr_ptr, socklen_t *__restrict addr_length) {
- socklen_t actual_length;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_sockname, -1);
- if(int e = mlibc::sys_sockname(fd, addr_ptr, *addr_length, &actual_length); e) {
- errno = e;
- return -1;
- }
- *addr_length = actual_length;
- return 0;
-}
-
-int getsockopt(int fd, int layer, int number,
- void *__restrict buffer, socklen_t *__restrict size) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getsockopt, -1);
- return mlibc::sys_getsockopt(fd, layer, number, buffer, size);
-}
-
-int listen(int fd, int backlog) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_listen, -1);
- if(int e = mlibc::sys_listen(fd, backlog); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-ssize_t recv(int sockfd, void *__restrict buf, size_t len, int flags) {
- return recvfrom(sockfd, buf, len, flags, NULL, NULL);
-}
-
-ssize_t recvfrom(int sockfd, void *__restrict buf, size_t len, int flags,
- struct sockaddr *__restrict src_addr, socklen_t *__restrict addrlen) {
- if(mlibc::sys_recvfrom) {
- ssize_t length;
- if(int e = mlibc::sys_recvfrom(sockfd, buf, len, flags, src_addr, addrlen, &length); e) {
- errno = e;
- return -1;
- }
- return length;
- }
-
- struct iovec iov = {};
- iov.iov_base = buf;
- iov.iov_len = len;
-
- struct msghdr hdr = {};
- hdr.msg_name = src_addr;
- if (addrlen) {
- hdr.msg_namelen = *addrlen;
- }
- hdr.msg_iov = &iov;
- hdr.msg_iovlen = 1;
-
- int ret = recvmsg(sockfd, &hdr, flags);
- if (ret < 0)
- return ret;
-
- if(addrlen)
- *addrlen = hdr.msg_namelen;
- return ret;
-}
-
-ssize_t recvmsg(int fd, struct msghdr *hdr, int flags) {
- ssize_t length;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_msg_recv, -1);
- if(int e = mlibc::sys_msg_recv(fd, hdr, flags, &length); e) {
- errno = e;
- return -1;
- }
- return length;
-}
-
-int recvmmsg(int, struct mmsghdr *, unsigned int, int, struct timespec *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-ssize_t send(int fd, const void *buffer, size_t size, int flags) {
- return sendto(fd, buffer, size, flags, nullptr, 0);
-}
-
-ssize_t sendto(int fd, const void *buffer, size_t size, int flags,
- const struct sockaddr *sock_addr, socklen_t addr_length) {
- if(mlibc::sys_sendto) {
- ssize_t length;
- if(int e = mlibc::sys_sendto(fd, buffer, size, flags, sock_addr, addr_length, &length); e) {
- errno = e;
- return -1;
- }
- return length;
- }
-
- struct iovec iov = {};
- iov.iov_base = const_cast<void *>(buffer);
- iov.iov_len = size;
-
- struct msghdr hdr = {};
- hdr.msg_name = const_cast<struct sockaddr *>(sock_addr);
- hdr.msg_namelen = addr_length;
- hdr.msg_iov = &iov;
- hdr.msg_iovlen = 1;
-
- return sendmsg(fd, &hdr, flags);
-}
-
-ssize_t sendmsg(int fd, const struct msghdr *hdr, int flags) {
- if(hdr->msg_iovlen > IOV_MAX)
- return EMSGSIZE;
-
- ssize_t length;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_msg_send, -1);
- if(int e = mlibc::sys_msg_send(fd, hdr, flags, &length); e) {
- errno = e;
- return -1;
- }
- return length;
-}
-
-int sendmmsg(int, struct mmsghdr *, unsigned int, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int setsockopt(int fd, int layer, int number,
- const void *buffer, socklen_t size) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setsockopt, -1);
- return mlibc::sys_setsockopt(fd, layer, number, buffer, size);
-}
-
-int shutdown(int sockfd, int how) {
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_shutdown, -1);
- if(int e = sysdep(sockfd, how); e) {
- errno = e;
- return -1;
- }
-
- return 0;
-}
-
-int sockatmark(int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int socket(int family, int type, int protocol) {
- int fd;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_socket, -1);
- if(int e = mlibc::sys_socket(family, type, protocol, &fd); e) {
- errno = e;
- return -1;
- }
- return fd;
-}
-
-int socketpair(int domain, int type, int protocol, int sv[2]) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_socketpair, -1);
- if(int e = mlibc::sys_socketpair(domain, type, protocol, sv); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-// connectpair() is provided by the platform
-
diff --git a/lib/mlibc/options/posix/generic/sys-stat-stubs.cpp b/lib/mlibc/options/posix/generic/sys-stat-stubs.cpp
deleted file mode 100644
index 2eca445..0000000
--- a/lib/mlibc/options/posix/generic/sys-stat-stubs.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-
-#include <errno.h>
-#include <bits/ensure.h>
-#include <sys/stat.h>
-
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-int chmod(const char *pathname, mode_t mode) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_chmod, -1);
- if(int e = mlibc::sys_chmod(pathname, mode); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int fchmod(int fd, mode_t mode) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fchmod, -1);
- if(int e = mlibc::sys_fchmod(fd, mode); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fchmodat, -1);
- if(int e = mlibc::sys_fchmodat(dirfd, pathname, mode, flags); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int fstatat(int dirfd, const char *path, struct stat *result, int flags) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_stat, -1);
- if(int e = mlibc::sys_stat(mlibc::fsfd_target::fd_path, dirfd, path, flags, result); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int futimens(int fd, const struct timespec times[2]) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_utimensat, -1);
-
- if (int e = mlibc::sys_utimensat(fd, nullptr, times, 0); e) {
- errno = e;
- return -1;
- }
-
- return 0;
-}
-
-int mkdir(const char *path, mode_t mode) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_mkdir, -1);
- if(int e = mlibc::sys_mkdir(path, mode); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int mkdirat(int dirfd, const char *path, mode_t mode) {
- mlibc::infoLogger() << "\e[31mmlibc: mkdirat() ignores its mode\e[39m" << frg::endlog;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_mkdirat, -1);
- if(int e = mlibc::sys_mkdirat(dirfd, path, mode); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int mkfifo(const char *path, mode_t mode) {
- return mkfifoat(AT_FDCWD, path, mode);
-}
-
-int mkfifoat(int dirfd, const char *path, mode_t mode) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_mkfifoat, -1);
- if (int e = mlibc::sys_mkfifoat(dirfd, path, mode); e) {
- errno = e;
- return -1;
- }
-
- return 0;
-}
-
-int mknod(const char *path, mode_t mode, dev_t dev) {
- return mknodat(AT_FDCWD, path, mode, dev);
-}
-
-int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_mknodat, -1);
- if (int e = mlibc::sys_mknodat(dirfd, path, mode, dev); e) {
- errno = e;
- return -1;
- }
-
- return 0;
-}
-
-mode_t umask(mode_t mode) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_umask, -1);
- mode_t old;
- if (int e = mlibc::sys_umask(mode, &old); e) {
- errno = e;
- return -1;
- }
- return old;
-}
-
-int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) {
- if(pathname == nullptr) {
- errno = EINVAL;
- return -1;
- }
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_utimensat, -1);
- if (int e = mlibc::sys_utimensat(dirfd, pathname, times, flags); e) {
- errno = e;
- return -1;
- }
-
- return 0;
-}
-
-int stat(const char *path, struct stat *result) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_stat, -1);
- if(int e = mlibc::sys_stat(mlibc::fsfd_target::path, -1, path, 0, result); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int lstat(const char *path, struct stat *result) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_stat, -1);
- if(int e = mlibc::sys_stat(mlibc::fsfd_target::path,
- -1, path, AT_SYMLINK_NOFOLLOW, result); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int fstat(int fd, struct stat *result) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_stat, -1);
- if(int e = mlibc::sys_stat(mlibc::fsfd_target::fd, fd, "", 0, result); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
diff --git a/lib/mlibc/options/posix/generic/sys-statvfs-stubs.cpp b/lib/mlibc/options/posix/generic/sys-statvfs-stubs.cpp
deleted file mode 100644
index c02cc39..0000000
--- a/lib/mlibc/options/posix/generic/sys-statvfs-stubs.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <errno.h>
-#include <sys/statvfs.h>
-
-#include <bits/ensure.h>
-#include <mlibc/posix-sysdeps.hpp>
-
-int statvfs(const char *path, struct statvfs *out) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_statvfs, -1);
- if(int e = mlibc::sys_statvfs(path, out); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int fstatvfs(int fd, struct statvfs *out) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fstatvfs, -1);
- if(int e = mlibc::sys_fstatvfs(fd, out); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
diff --git a/lib/mlibc/options/posix/generic/sys-time-stubs.cpp b/lib/mlibc/options/posix/generic/sys-time-stubs.cpp
deleted file mode 100644
index 5cc0fe5..0000000
--- a/lib/mlibc/options/posix/generic/sys-time-stubs.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-
-#include <errno.h>
-#include <sys/time.h>
-#include <time.h>
-
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-
-int gettimeofday(struct timeval *__restrict result, void *__restrict unused) {
- (void)unused; // Linux just ignores gettimeofday().
-
- if(result) {
- long nanos;
- if(int e = mlibc::sys_clock_get(CLOCK_REALTIME, &result->tv_sec, &nanos); e) {
- errno = e;
- return -1;
- }
- result->tv_usec = nanos / 1000;
- }
- return 0;
-}
-
-int settimeofday(const struct timeval *, const struct timezone *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void timeradd(const struct timeval *a, const struct timeval *b, struct timeval *res) {
- res->tv_sec = a->tv_sec + b->tv_sec;
- res->tv_usec = a->tv_usec + b->tv_usec;
- while(res->tv_usec > 999999) {
- res->tv_usec -= 1000000;
- res->tv_sec += 1;
- }
-}
-
-void timersub(const struct timeval *a, const struct timeval *b, struct timeval *res) {
- res->tv_sec = a->tv_sec - b->tv_sec;
- res->tv_usec = a->tv_usec - b->tv_usec;
- while(res->tv_usec < 0) {
- res->tv_usec += 1000000;
- res->tv_sec -= 1;
- }
-}
-
-void timerclear(struct timeval *tvp) {
- tvp->tv_sec = 0;
- tvp->tv_usec = 0;
-}
-
-int timerisset(struct timeval *tvp) {
- if(tvp->tv_sec != 0 || tvp->tv_usec != 0) {
- return 1;
- }
- return 0;
-}
-
-int getitimer(int which, struct itimerval *curr_value) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getitimer, -1);
- if(int e = mlibc::sys_getitimer(which, curr_value); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setitimer, -1);
- if(int e = mlibc::sys_setitimer(which, new_value, old_value); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int timer_create(clockid_t clk, struct sigevent *__restrict evp, timer_t *__restrict res) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_timer_create, -1);
- if(int e = mlibc::sys_timer_create(clk, evp, res); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int timer_settime(timer_t t, int flags, const struct itimerspec *__restrict val, struct itimerspec *__restrict old) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_timer_settime, -1);
- if(int e = mlibc::sys_timer_settime(t, flags, val, old); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int timer_gettime(timer_t, struct itimerspec *) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int timer_delete(timer_t t) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_timer_delete, -1);
- if(int e = mlibc::sys_timer_delete(t); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
diff --git a/lib/mlibc/options/posix/generic/sys-times.cpp b/lib/mlibc/options/posix/generic/sys-times.cpp
deleted file mode 100644
index 61b6e25..0000000
--- a/lib/mlibc/options/posix/generic/sys-times.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-
-#include <errno.h>
-#include <sys/times.h>
-
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-#include <internal-config.h>
-#include <mlibc/posix-sysdeps.hpp>
-
-clock_t times(struct tms *tms) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_times, -1);
- clock_t ret;
- if(int e = mlibc::sys_times(tms, &ret); e) {
- errno = e;
- return -1;
- }
- return ret;
-}
-
diff --git a/lib/mlibc/options/posix/generic/sys-uio.cpp b/lib/mlibc/options/posix/generic/sys-uio.cpp
deleted file mode 100644
index 0f14bc0..0000000
--- a/lib/mlibc/options/posix/generic/sys-uio.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-
-#include <sys/uio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include <frg/vector.hpp>
-#include <mlibc/allocator.hpp>
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-#include <bits/ensure.h>
-
-ssize_t readv(int fd, const struct iovec *iovs, int iovc) {
- ssize_t read_bytes = 0;
-
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_readv, -1);
-
- if (int e = sysdep(fd, iovs, iovc, &read_bytes); e) {
- errno = e;
- return -1;
- }
-
- return read_bytes;
-}
-
-ssize_t writev(int fd, const struct iovec *iovs, int iovc) {
- __ensure(iovc);
-
- ssize_t written = 0;
- size_t bytes = 0;
- for(int i = 0; i < iovc; i++) {
- if(SSIZE_MAX - bytes < iovs[i].iov_len) {
- errno = EINVAL;
- return -1;
- }
- bytes += iovs[i].iov_len;
- }
- frg::vector<char, MemoryAllocator> buffer{getAllocator()};
- buffer.resize(bytes);
-
- size_t to_copy = bytes;
- char *bp = buffer.data();
- for(int i = 0; i < iovc; i++) {
- size_t copy = frg::min(iovs[i].iov_len, to_copy);
-
- bp = (char *)mempcpy((void *)bp, (void *)iovs[i].iov_base, copy);
-
- to_copy -= copy;
- if(to_copy == 0)
- break;
- }
-
- written = write(fd, buffer.data(), bytes);
- return written;
-}
-
-ssize_t preadv(int, const struct iovec *, int, off_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-ssize_t pwritev(int, const struct iovec *, int, off_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/sys-utsname.cpp b/lib/mlibc/options/posix/generic/sys-utsname.cpp
deleted file mode 100644
index 3176574..0000000
--- a/lib/mlibc/options/posix/generic/sys-utsname.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-
-#include <string.h>
-#include <sys/utsname.h>
-#include <errno.h>
-
-#include <bits/ensure.h>
-#include <mlibc/debug.hpp>
-#include <internal-config.h>
-#include <mlibc/posix-sysdeps.hpp>
-
-int uname(struct utsname *p) {
- if (p == NULL) {
- errno = EFAULT;
- return -1;
- }
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_uname, -1);
- if(int e = mlibc::sys_uname(p); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
diff --git a/lib/mlibc/options/posix/generic/sys-wait-stubs.cpp b/lib/mlibc/options/posix/generic/sys-wait-stubs.cpp
deleted file mode 100644
index 6e7cc78..0000000
--- a/lib/mlibc/options/posix/generic/sys-wait-stubs.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-
-#include <errno.h>
-#include <sys/wait.h>
-#include <bits/ensure.h>
-
-#include <mlibc/ansi-sysdeps.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-#include <mlibc/debug.hpp>
-
-int waitid(idtype_t idtype, id_t id, siginfo_t *info, int options) {
- auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_waitid, -1);
- if(int e = sysdep(idtype, id, info, options); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-pid_t waitpid(pid_t pid, int *status, int flags) {
- pid_t ret;
- int tmp_status = 0;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_waitpid, -1);
- if(int e = mlibc::sys_waitpid(pid, &tmp_status, flags, NULL, &ret); e) {
- errno = e;
- return -1;
- }
- if(status) {
- *status = tmp_status;
- }
- return ret;
-}
-
-pid_t wait(int *status) {
- return waitpid(-1, status, 0);
-}
-
-pid_t wait3(int *status, int options, struct rusage *rusage) {
- (void) rusage;
- mlibc::infoLogger() << "\e[31mmlibc: wait3() is not implemented correctly\e[39m"
- << frg::endlog;
- return waitpid(-1, status, options);
-}
-
-pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru) {
- pid_t ret;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_waitpid, -1);
- if(int e = mlibc::sys_waitpid(pid, status, options, ru, &ret); e) {
- errno = e;
- return -1;
- }
- return ret;
-}
diff --git a/lib/mlibc/options/posix/generic/syslog-stubs.cpp b/lib/mlibc/options/posix/generic/syslog-stubs.cpp
deleted file mode 100644
index 6a80ff9..0000000
--- a/lib/mlibc/options/posix/generic/syslog-stubs.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-
-#include <syslog.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <time.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <bits/ensure.h>
-
-#include <frg/mutex.hpp>
-#include <mlibc/lock.hpp>
-#include <mlibc/debug.hpp>
-
-// This syslog implementation is largely taken from musl
-
-static char log_ident[32];
-static int log_options;
-static int log_facility = LOG_USER;
-static int log_fd = -1;
-static int log_opt;
-static int log_mask = 0xff;
-
-static int use_mlibc_logger = 0;
-static FutexLock __syslog_lock;
-
-static const struct sockaddr_un log_addr {AF_UNIX, "/dev/log"};
-
-void closelog(void) {
- frg::unique_lock<FutexLock> holder { __syslog_lock };
- close(log_fd);
- log_fd = -1;
-}
-
-static void __openlog() {
- log_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if(log_fd >= 0) {
- int ret = connect(log_fd, (const sockaddr *)&log_addr, sizeof log_addr);
- if(ret) {
- mlibc::infoLogger() << "\e[31mmlibc: syslog: connect returned an error, falling back to infoLogger\e[39m" << frg::endlog;
- use_mlibc_logger = 1;
- }
- }
-}
-
-void openlog(const char *ident, int options, int facility) {
- frg::unique_lock<FutexLock> holder { __syslog_lock };
- if(ident) {
- size_t n = strnlen(ident, sizeof log_ident - 1);
- memcpy(log_ident, ident, n);
- log_ident[n] = 0;
- } else {
- log_ident[0] = 0;
- }
- log_options = options;
- log_facility = facility;
-
- if((options & LOG_NDELAY) && log_fd < 0)
- __openlog();
-}
-
-int setlogmask(int mask) {
- int old_mask = log_mask;
-
- log_mask = mask;
-
- return old_mask;
-}
-
-static void _vsyslog(int priority, const char *message, va_list ap) {
- auto is_lost_conn = [] (int e) {
- return e == ECONNREFUSED || e == ECONNRESET || e == ENOTCONN || e == EPIPE;
- };
-
- if(!(priority & log_mask)) {
- return;
- }
-
- char timebuf[16];
- time_t now;
- struct tm tm;
- char buf[1024];
- int errno_save = errno;
- int pid;
- int l, l2;
- int hlen;
- int fd;
-
- if(log_fd < 0)
- __openlog();
-
- if(use_mlibc_logger) {
- vsnprintf(buf, sizeof buf, message, ap);
- mlibc::infoLogger() << "mlibc: syslog: " << buf << frg::endlog;
- return;
- }
-
- if(!(priority & LOG_FACMASK))
- priority |= log_facility;
-
- now = time(NULL);
- gmtime_r(&now, &tm);
- strftime(timebuf, sizeof timebuf, "%b %e %T", &tm);
-
- pid = (log_opt & LOG_PID) ? getpid() : 0;
- l = snprintf(buf, sizeof buf, "<%d>%s %n%s%s%.0d%s: ",
- priority, timebuf, &hlen, log_ident, "[" + !pid, pid, "]" + !pid);
- errno = errno_save;
- l2 = vsnprintf(buf + l, sizeof buf - l, message, ap);
- if(l2 >= 0) {
- if(l2 >= (long int)(sizeof buf - l))
- l = sizeof buf - 1;
- else
- l += l2;
- if(buf[l - 1] != '\n')
- buf[l++] = '\n';
- if(send(log_fd, buf, l, 0) < 0 && (!is_lost_conn(errno)
- || connect(log_fd, (const sockaddr *)&log_addr, sizeof log_addr) < 0
- || send(log_fd, buf, l, 0) < 0)
- && (log_opt & LOG_CONS)) {
- fd = open("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
- if(fd >= 0) {
- dprintf(fd, "%.*s", l - hlen, buf + hlen);
- close(fd);
- }
- }
- if(log_opt & LOG_PERROR)
- dprintf(STDERR_FILENO, "%.*s", l - hlen, buf + hlen);
- }
-}
-
-void syslog(int priority, const char *format, ...) {
- va_list ap;
- va_start(ap, format);
- vsyslog(priority, format, ap);
- va_end(ap);
-}
-
-void vsyslog(int priority, const char *message, va_list ap) {
- int cs;
- if(!(log_mask & LOG_MASK(priority & 7)) || (priority & ~0x3ff)) {
- mlibc::infoLogger() << "\e[31mmlibc: syslog: log_mask or priority out of range, not printing anything\e[39m" << frg::endlog;
- return;
- }
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
- frg::unique_lock<FutexLock> lock(__syslog_lock);
- _vsyslog(priority, message, ap);
- pthread_setcancelstate(cs, 0);
-}
diff --git a/lib/mlibc/options/posix/generic/termios-stubs.cpp b/lib/mlibc/options/posix/generic/termios-stubs.cpp
deleted file mode 100644
index 631456a..0000000
--- a/lib/mlibc/options/posix/generic/termios-stubs.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-
-#include <errno.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-
-#include <bits/ensure.h>
-#include <mlibc/posix-sysdeps.hpp>
-
-speed_t cfgetispeed(const struct termios *tios) {
- return tios->c_cflag & CBAUD;
-}
-
-speed_t cfgetospeed(const struct termios *tios) {
- return tios->c_cflag & CBAUD;
-}
-
-int cfsetispeed(struct termios *termios, speed_t speed) {
- return speed ? cfsetospeed(termios, speed) : 0;
-}
-
-int cfsetospeed(struct termios *termios, speed_t speed) {
- if(speed & ~CBAUD) {
- errno = EINVAL;
- return -1;
- }
-
- termios->c_cflag &= ~CBAUD;
- termios->c_cflag |= speed;
-
- return 0;
-}
-
-void cfmakeraw(struct termios *t) {
- t->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
- t->c_oflag &= ~OPOST;
- t->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
- t->c_cflag &= ~(CSIZE | PARENB);
- t->c_cflag |= CS8;
- t->c_cc[VMIN] = 1;
- t->c_cc[VTIME] = 0;
-}
-
-int tcdrain(int fd) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_tcdrain, -1);
- if(int e = mlibc::sys_tcdrain(fd); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int tcflow(int fd, int action) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_tcflow, -1);
- if(int e = mlibc::sys_tcflow(fd, action); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int tcflush(int fd, int queue_selector) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_tcflush, -1);
- if(int e = mlibc::sys_tcflush(fd, queue_selector); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int tcgetattr(int fd, struct termios *attr) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_tcgetattr, -1);
- if(int e = mlibc::sys_tcgetattr(fd, attr); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-pid_t tcgetsid(int fd) {
- int sid;
- if(ioctl(fd, TIOCGSID, &sid) < 0) {
- return -1;
- }
- return sid;
-}
-
-int tcsendbreak(int, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int tcsetattr(int fd, int opts, const struct termios *attr) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_tcsetattr, -1);
- if(int e = mlibc::sys_tcsetattr(fd, opts, attr); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
diff --git a/lib/mlibc/options/posix/generic/time.cpp b/lib/mlibc/options/posix/generic/time.cpp
deleted file mode 100644
index 14193af..0000000
--- a/lib/mlibc/options/posix/generic/time.cpp
+++ /dev/null
@@ -1,505 +0,0 @@
-#include <ctype.h>
-#include <langinfo.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#include <bits/ensure.h>
-#include <mlibc/strings.hpp>
-
-namespace {
-
-int month_to_day(int month) {
- switch(month){
- case 0: return 0;
- case 1: return 31;
- case 2: return 59;
- case 3: return 90;
- case 4: return 120;
- case 5: return 151;
- case 6: return 181;
- case 7: return 212;
- case 8: return 243;
- case 9: return 273;
- case 10: return 304;
- case 11: return 334;
- }
- return -1;
-}
-
-int is_leapyear(int year) {
- return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
-}
-
-int month_and_year_to_day_in_year(int month, int year){
- int day = month_to_day(month);
- if(is_leapyear(year) && month < 2)
- return day + 1;
-
- return day;
-}
-
-int target_determination(int month) {
- switch(month){
- case 0: return 3;
- case 1: return 14;
- case 2: return 14;
- case 3: return 4;
- case 4: return 9;
- case 5: return 6;
- case 6: return 11;
- case 7: return 8;
- case 8: return 5;
- case 9: return 10;
- case 10: return 7;
- case 11: return 12;
- }
-
- return -1;
-}
-
-int doom_determination(int full_year) {
- int century = full_year / 100;
- int anchor = 2 + 5 * (century % 4) % 7;
-
- int year = full_year % 100;
-
- if(year % 2)
- year += 11;
-
- year /= 2;
-
- if(year % 2)
- year += 11;
-
- return 7 - (year % 7) + anchor;
-}
-
-//Determine day of week through the doomsday algorithm.
-int day_determination(int day, int month, int year) {
- int doom = doom_determination(year);
- bool leap = is_leapyear(year);
-
- int target = target_determination(month);
- if(leap && month < 2)
- target++;
-
- int doom_dif = (day - target) % 7;
- return (doom + doom_dif) % 7;
-}
-
-struct strptime_internal_state {
- bool has_century;
- bool has_year;
- bool has_month;
- bool has_day_of_month;
- bool has_day_of_year;
- bool has_day_of_week;
-
- bool full_year_given;
-
- int century;
-
- size_t format_index;
- size_t input_index;
-};
-
-char *strptime_internal(const char *__restrict input, const char *__restrict format,
- struct tm *__restrict tm, struct strptime_internal_state *__restrict state) {
- auto matchLanginfoItem = [&] (int start, size_t num, int &dest, bool &flag) -> bool {
- for(size_t i = start; i < (start + num); i++) {
- const char *mon = nl_langinfo(i);
- size_t len = strlen(mon);
- if(mlibc::strncasecmp(&input[state->input_index], mon, len))
- continue;
- state->input_index += len;
- dest = i - start;
- flag = true;
- return true;
- }
- return false;
- };
-
- auto matchNumericRange = [&] (int start, int end, int &dest, bool *flag) -> bool {
- int product = 0, n = 0;
- sscanf(&input[state->input_index], "%d%n", &product, &n);
- if(n == 0 || 2 < n)
- return false;
- if(product < start || product > end)
- return false;
- state->input_index += n;
- dest = product;
- if(flag) *flag = true;
- return true;
- };
-
- while(isspace(input[state->input_index]))
- state->input_index++;
-
- if(input[state->input_index] == '\0')
- return NULL;
-
- while(format[state->format_index] != '\0'){
- if(format[state->format_index] != '%'){
- if(isspace(format[state->format_index])){
- while(isspace(input[state->input_index++]));
- state->input_index--;
- }
- else {
- if(format[state->format_index] != input[state->input_index++])
- return NULL;
- }
- state->format_index++;
- continue;
- }
- state->format_index++;
- switch(format[state->format_index]){
- case '%':
- if(input[state->input_index++] != '%')
- return NULL;
- break;
- case 'a':
- case 'A': {
- if (!matchLanginfoItem(DAY_1, 7, tm->tm_wday, state->has_day_of_week) && \
- !matchLanginfoItem(ABDAY_1, 7, tm->tm_wday, state->has_day_of_week))
- return NULL;
- break;
- }
- case 'b':
- case 'B':
- case 'h': {
- if (!matchLanginfoItem(MON_1, 12, tm->tm_mon, state->has_month) && \
- !matchLanginfoItem(ABMON_1, 12, tm->tm_mon, state->has_month))
- return NULL;
- break;
- }
- case 'c':
- __ensure(!"strptime() %c directive unimplemented.");
- __builtin_unreachable();
- break;
- case 'C': {
- int product = 0, n = 0;
- sscanf(&input[state->input_index], "%d%n", &product, &n);
- if(n == 0 || 2 < n)
- return NULL;
- state->input_index += n;
- state->century = product;
- state->has_century = true;
- break;
- }
- case 'd': //`%d` and `%e` are equivalent
- case 'e': {
- if(!matchNumericRange(1, 31, tm->tm_mday, &state->has_day_of_month))
- return NULL;
- break;
- }
- case 'D': { //equivalent to `%m/%d/%y`
- size_t pre_fi = state->format_index;
- state->format_index = 0;
-
- char *result = strptime_internal(input, "%m/%d/%y", tm, state);
- if(result == NULL)
- return NULL;
-
- state->format_index = pre_fi;
- break;
- }
- case 'H': {
- if(!matchNumericRange(0, 23, tm->tm_hour, nullptr))
- return NULL;
- break;
- }
- case 'I': {
- if(!matchNumericRange(1, 12, tm->tm_hour, nullptr))
- return NULL;
- break;
- }
- case 'j': {
- if(!matchNumericRange(1, 366, tm->tm_yday, &state->has_day_of_year))
- return NULL;
- tm->tm_yday--;
- break;
- }
- case 'm': {
- if(!matchNumericRange(1, 12, tm->tm_mon, &state->has_month))
- return NULL;
- tm->tm_mon--;
- break;
- }
- case 'M': {
- if(!matchNumericRange(0, 59, tm->tm_min, nullptr))
- return NULL;
- break;
- }
- case 'n':
- case 't': {
- size_t n = 0;
- while(isspace(input[state->input_index++]))
- n++;
- if(n == 0)
- return NULL;
- state->input_index--;
- break;
- }
- case 'p': {
- const char *meridian_str = nl_langinfo(AM_STR);
- size_t len = strlen(meridian_str);
- if (!mlibc::strncasecmp(&input[state->input_index], meridian_str, len)) {
- tm->tm_hour %= 12;
- state->input_index += len;
- break;
- }
- meridian_str = nl_langinfo(PM_STR);
- len = strlen(meridian_str);
- if (!mlibc::strncasecmp(&input[state->input_index], meridian_str, len)) {
- tm->tm_hour %= 12;
- tm->tm_hour += 12;
- state->input_index += len;
- break;
- }
- break;
- }
- case 'r': { //equivalent to `%I:%M:%S %p`
- size_t pre_fi = state->format_index;
- state->format_index = 0;
-
- char *result = strptime_internal(input, "%I:%M:%S %p", tm, state);
- if(result == NULL)
- return NULL;
-
- state->format_index = pre_fi;
- break;
- }
- case 'R': { //equivalent to `%H:%M`
- size_t pre_fi = state->format_index;
- state->format_index = 0;
-
- char *result = strptime_internal(input, "%H:%M", tm, state);
- if(result == NULL)
- return NULL;
-
- state->format_index = pre_fi;
- break;
- }
- case 'S': {
- if(!matchNumericRange(0, 60, tm->tm_sec, nullptr))
- return NULL;
- break;
- }
- case 'T': { //equivalent to `%H:%M:%S`
- size_t pre_fi = state->format_index;
- state->format_index = 0;
-
- char *result = strptime_internal(input, "%H:%M:%S", tm, state);
- if(result == NULL)
- return NULL;
-
- state->format_index = pre_fi;
- break;
- }
- case 'U':
- __ensure(!"strptime() %U directive unimplemented.");
- __builtin_unreachable();
- break;
- case 'w': {
- int product = 0, n = 0;
- sscanf(&input[state->input_index], "%d%n", &product, &n);
- if(n == 0 || 1 < n)
- return NULL;
- state->input_index += n;
- tm->tm_wday = product;
- state->has_day_of_week = true;
- break;
- }
- case 'W':
- __ensure(!"strptime() %W directive unimplemented.");
- __builtin_unreachable();
- break;
- case 'x':
- __ensure(!"strptime() %x directive unimplemented.");
- __builtin_unreachable();
- break;
- case 'X':
- __ensure(!"strptime() %X directive unimplemented.");
- __builtin_unreachable();
- break;
- case 'y': {
- int product = 0, n = 0;
- sscanf(&input[state->input_index], "%d%n", &product, &n);
- if(n == 0 || 2 < n)
- return NULL;
- if(product < 69)
- product += 100;
- state->input_index += n;
- tm->tm_year = product;
- state->has_year = true;
- break;
- }
- case 'Y': {
- int product = 0, n = 0;
- sscanf(&input[state->input_index], "%d%n", &product, &n);
- if(n == 0 || 4 < n)
- return NULL;
- state->input_index += n;
- tm->tm_year = product - 1900;
- state->has_year = true;
- state->has_century = true;
- state->full_year_given = true;
- state->century = product / 100;
- break;
- }
- case 'F': { //GNU extensions
- //equivalent to `%Y-%m-%d`
- size_t pre_fi = state->format_index;
- state->format_index = 0;
-
- char *result = strptime_internal(input, "%Y-%m-%d", tm, state);
- if(result == NULL)
- return NULL;
-
- state->format_index = pre_fi;
- break;
- }
- case 'g':
- __ensure(!"strptime() %g directive unimplemented.");
- __builtin_unreachable();
- break;
- case 'G':
- __ensure(!"strptime() %G directive unimplemented.");
- __builtin_unreachable();
- break;
- case 'u': {
- if(!matchNumericRange(1, 7, tm->tm_wday, nullptr))
- return NULL;
- tm->tm_wday--;
- break;
- }
- case 'V':
- __ensure(!"strptime() %V directive unimplemented.");
- __builtin_unreachable();
- break;
- case 'z':
- __ensure(!"strptime() %z directive unimplemented.");
- __builtin_unreachable();
- break;
- case 'Z':
- __ensure(!"strptime() %Z directive unimplemented.");
- __builtin_unreachable();
- break;
- case 's': //end of GNU extensions
- __ensure(!"strptime() %s directive unimplemented.");
- __builtin_unreachable();
- break;
- case 'E': { //locale-dependent date & time representation
- __ensure(!"strptime() %E* directives unimplemented.");
- __builtin_unreachable();
- /*
- state->format_index++;
- switch(format[state->format_index]){
- case 'c':
- break;
- case 'C':
- break;
- case 'x':
- break;
- case 'X':
- break;
- case 'y':
- break;
- case 'Y':
- break;
- default:
- return NULL;
- }
- */
- }
- case 'O': { //locale-dependent numeric symbols
- __ensure(!"strptime() %O* directives unimplemented.");
- __builtin_unreachable();
- /*
- state->format_index++;
- switch(format[state->format_index]){
- case 'd':
- case 'e':
- break;
- case 'H':
- break;
- case 'I':
- break;
- case 'm':
- break;
- case 'M':
- break;
- case 'S':
- break;
- case 'U':
- break;
- case 'w':
- break;
- case 'W':
- break;
- case 'y':
- break;
- default:
- return NULL;
- }
- */
- }
- default:
- return NULL;
- }
- state->format_index++;
- }
-
- return (char*)input + state->input_index;
-}
-
-} //anonymous namespace
-
-char *strptime(const char *__restrict s, const char *__restrict format, struct tm *__restrict tm){
- struct strptime_internal_state state = {};
-
- char *result = strptime_internal(s, format, tm, &state);
-
- if(result == NULL)
- return NULL;
-
- if(state.has_century && !state.full_year_given){
- int full_year = state.century * 100;
-
- if(state.has_year){
- //Compensate for default century-adjustment of `%j` operand
- if(tm->tm_year >= 100)
- full_year += tm->tm_year - 100;
- else
- full_year += tm->tm_year;
- }
-
- tm->tm_year = full_year - 1900;
-
- state.has_year = true;
- }
-
- if(state.has_month && !state.has_day_of_year){
- int day = 0;
- if(state.has_year)
- day = month_and_year_to_day_in_year(tm->tm_mon, tm->tm_year);
- else
- day = month_to_day(tm->tm_mon);
-
- tm->tm_yday = day + tm->tm_mday - 1;
- state.has_day_of_year = true;
- }
-
- if(state.has_year && !state.has_day_of_week){
- if(!state.has_month && !state.has_day_of_month){
- tm->tm_wday = day_determination(0, 0, tm->tm_year + 1900);
- }
- else if(state.has_month && state.has_day_of_month){
- tm->tm_wday = day_determination(tm->tm_mday, tm->tm_mon, tm->tm_year + 1900);
- }
- state.has_day_of_week = true;
- }
-
- return result;
-}
diff --git a/lib/mlibc/options/posix/generic/ucontext-stubs.cpp b/lib/mlibc/options/posix/generic/ucontext-stubs.cpp
deleted file mode 100644
index 9413a78..0000000
--- a/lib/mlibc/options/posix/generic/ucontext-stubs.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <ucontext.h>
-#include <bits/ensure.h>
-
-int getcontext(ucontext_t *) {
- __ensure(!"Not implemented!");
- __builtin_unreachable();
-}
-int setcontext(const ucontext_t *) {
- __ensure(!"Not implemented!");
- __builtin_unreachable();
-}
-void makecontext(ucontext_t *, void (*)(), int, ...) {
- __ensure(!"Not implemented!");
- __builtin_unreachable();
-}
-int swapcontext(ucontext_t *, const ucontext_t *) {
- __ensure(!"Not implemented!");
- __builtin_unreachable();
-}
diff --git a/lib/mlibc/options/posix/generic/unistd-stubs.cpp b/lib/mlibc/options/posix/generic/unistd-stubs.cpp
deleted file mode 100644
index 39cf76a..0000000
--- a/lib/mlibc/options/posix/generic/unistd-stubs.cpp
+++ /dev/null
@@ -1,1227 +0,0 @@
-#include <stdio.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/resource.h>
-#include <unistd.h>
-#include <limits.h>
-#include <termios.h>
-#include <pwd.h>
-#include <sys/ioctl.h>
-
-#include <bits/ensure.h>
-#include <mlibc/allocator.hpp>
-#include <mlibc/arch-defs.hpp>
-#include <mlibc/debug.hpp>
-#include <mlibc/posix-sysdeps.hpp>
-#include <mlibc/bsd-sysdeps.hpp>
-#include <mlibc/thread.hpp>
-
-namespace {
-
-constexpr bool logExecvpeTries = false;
-
-}
-
-unsigned int alarm(unsigned int seconds) {
- struct itimerval it = {}, old = {};
- it.it_value.tv_sec = seconds;
- setitimer(ITIMER_REAL, &it, &old);
- return old.it_value.tv_sec + !! old.it_value.tv_usec;
-}
-
-int chdir(const char *path) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_chdir, -1);
- if(int e = mlibc::sys_chdir(path); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int fchdir(int fd) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fchdir, -1);
- if(int e = mlibc::sys_fchdir(fd); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int chown(const char *path, uid_t uid, gid_t gid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fchownat, -1);
- if(int e = mlibc::sys_fchownat(AT_FDCWD, path, uid, gid, 0); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-ssize_t confstr(int name, char *buf, size_t len) {
- const char *str = "";
- if (name == _CS_PATH) {
- str = "/bin:/usr/bin";
- } else if(name == _CS_GNU_LIBPTHREAD_VERSION) {
- // We are not glibc, so we can return 0 here.
- return 0;
- } else if(name == _CS_GNU_LIBC_VERSION) {
- // We are not glibc, so we can return 0 here.
- return 0;
- } else {
- mlibc::infoLogger() << "\e[31mmlibc: confstr() request " << name << " is unimplemented\e[39m"
- << frg::endlog;
- __ensure(!"Not implemented");
- }
-
- return snprintf(buf, len, "%s", str) + 1;
-}
-
-void _exit(int status) {
- mlibc::sys_exit(status);
-}
-
-int execl(const char *path, const char *arg0, ...) {
- // TODO: It's a stupid idea to limit the number of arguments here.
- char *argv[16];
- argv[0] = const_cast<char *>(arg0);
-
- va_list args;
- int n = 1;
- va_start(args, arg0);
- while(true) {
- __ensure(n < 15);
- auto argn = va_arg(args, const char *);
- argv[n++] = const_cast<char *>(argn);
- if(!argn)
- break;
- }
- va_end(args);
- argv[n] = nullptr;
-
- return execve(path, argv, environ);
-}
-
-// This function is taken from musl.
-int execle(const char *path, const char *arg0, ...) {
- int argc;
- va_list ap;
- va_start(ap, arg0);
- for(argc = 1; va_arg(ap, const char *); argc++);
- va_end(ap);
-
- int i;
- char *argv[argc + 1];
- char **envp;
- va_start(ap, arg0);
- argv[0] = (char *)argv;
- for(i = 1; i <= argc; i++)
- argv[i] = va_arg(ap, char *);
- envp = va_arg(ap, char **);
- va_end(ap);
- return execve(path, argv, envp);
-}
-
-// This function is taken from musl
-int execlp(const char *file, const char *argv0, ...) {
- int argc;
- va_list ap;
- va_start(ap, argv0);
- for(argc = 1; va_arg(ap, const char *); argc++);
- va_end(ap);
- {
- int i;
- char *argv[argc + 1];
- va_start(ap, argv0);
- argv[0] = (char *)argv0;
- for(i = 1; i < argc; i++)
- argv[i] = va_arg(ap, char *);
- argv[i] = NULL;
- va_end(ap);
- return execvp(file, argv);
- }
-}
-
-int execv(const char *path, char *const argv[]) {
- return execve(path, argv, environ);
-}
-
-int execvp(const char *file, char *const argv[]) {
- return execvpe(file, argv, environ);
-}
-
-int execvpe(const char *file, char *const argv[], char *const envp[]) {
- char *null_list[] = {
- nullptr
- };
-
- if(!argv)
- argv = null_list;
- if(!envp)
- envp = null_list;
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_execve, -1);
-
- if(strchr(file, '/')) {
- int e = mlibc::sys_execve(file, argv, envp);
- __ensure(e && "sys_execve() is supposed to never return with success");
- errno = e;
- return -1;
- }
-
- frg::string_view dirs;
- if(const char *pv = getenv("PATH"); pv) {
- dirs = pv;
- }else{
- dirs = "/bin:/usr/bin";
- }
-
- size_t p = 0;
- int res = ENOENT;
- while(p < dirs.size()) {
- size_t s; // Offset of next colon or end of string.
- if(size_t cs = dirs.find_first(':', p); cs != size_t(-1)) {
- s = cs;
- }else{
- s = dirs.size();
- }
-
- frg::string<MemoryAllocator> path{getAllocator()};
- path += dirs.sub_string(p, s - p);
- path += "/";
- path += file;
-
- if(logExecvpeTries)
- mlibc::infoLogger() << "mlibc: execvpe() tries '" << path.data() << "'" << frg::endlog;
-
- int e = mlibc::sys_execve(path.data(), argv, envp);
- __ensure(e && "sys_execve() is supposed to never return with success");
- switch(e) {
- case ENOENT:
- case ENOTDIR:
- break;
- case EACCES:
- res = EACCES;
- break;
- default:
- errno = e;
- return -1;
- }
-
- p = s + 1;
- }
-
- errno = res;
- return -1;
-}
-
-int faccessat(int dirfd, const char *pathname, int mode, int flags) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_faccessat, -1);
- if(int e = mlibc::sys_faccessat(dirfd, pathname, mode, flags); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int fchown(int fd, uid_t uid, gid_t gid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fchownat, -1);
- if(int e = mlibc::sys_fchownat(fd, "", uid, gid, AT_EMPTY_PATH); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int fchownat(int fd, const char *path, uid_t uid, gid_t gid, int flags) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fchownat, -1);
- if(int e = mlibc::sys_fchownat(fd, path, uid, gid, flags); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int fdatasync(int fd) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fdatasync, -1);
- if(int e = mlibc::sys_fdatasync(fd); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int fexecve(int, char *const [], char *const []) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-long fpathconf(int, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int fsync(int fd) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fsync, -1);
- if(auto e = mlibc::sys_fsync(fd); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int ftruncate(int fd, off_t size) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_ftruncate, -1);
- if(int e = mlibc::sys_ftruncate(fd, size); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-char *getcwd(char *buffer, size_t size) {
- if (buffer) {
- if (size == 0) {
- errno = EINVAL;
- return NULL;
- }
- } else if (!buffer) {
- if (size == 0)
- size = PATH_MAX;
-
- buffer = (char *)malloc(size);
- }
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getcwd, nullptr);
- if(int e = mlibc::sys_getcwd(buffer, size); e) {
- errno = e;
- return NULL;
- }
-
- return buffer;
-}
-
-int getgroups(int size, gid_t list[]) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getgroups, -1);
- int ret;
- if(int e = mlibc::sys_getgroups(size, list, &ret); e) {
- errno = e;
- return -1;
- }
- return ret;
-}
-
-long gethostid(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int gethostname(char *buffer, size_t bufsize) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_gethostname, -1);
- if(auto e = mlibc::sys_gethostname(buffer, bufsize); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int sethostname(const char *buffer, size_t bufsize) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_sethostname, -1);
- if(auto e = mlibc::sys_sethostname(buffer, bufsize); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-// Code taken from musl
-char *getlogin(void) {
- return getenv("LOGNAME");
-}
-
-int getlogin_r(char *, size_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-// optarg and optind are provided to us by the GLIBC part of the mlibc.
-
-static char *scan = NULL; /* Private scan pointer. */
-
-int getopt(int argc, char *const argv[], const char *optstring) {
- char c;
- char *place;
-
- optarg = NULL;
-
- if (!scan || *scan == '\0') {
- if (optind == 0)
- optind++;
-
- if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
- return EOF;
- if (argv[optind][1] == '-' && argv[optind][2] == '\0') {
- optind++;
- return EOF;
- }
-
- scan = argv[optind]+1;
- optind++;
- }
-
- c = *scan++;
- place = strchr(optstring, c);
-
- if (!place || c == ':') {
- fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
- return '?';
- }
-
- place++;
- if (*place == ':') {
- if (*scan != '\0') {
- optarg = scan;
- scan = NULL;
- } else if( optind < argc ) {
- optarg = argv[optind];
- optind++;
- } else {
- fprintf(stderr, "%s: option requires argument -%c\n", argv[0], c);
- return ':';
- }
- }
-
- return c;
-}
-
-pid_t getpgid(pid_t pid) {
- pid_t pgid;
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getpgid, -1);
- if(int e = mlibc::sys_getpgid(pid, &pgid); e) {
- errno = e;
- return -1;
- }
- return pgid;
-}
-
-pid_t getpgrp(void) {
- return getpgid(0);
-}
-
-pid_t getsid(pid_t pid) {
- if(!mlibc::sys_getsid) {
- MLIBC_MISSING_SYSDEP();
- return -1;
- }
- pid_t sid;
- if(int e = mlibc::sys_getsid(pid, &sid); e) {
- errno = e;
- return -1;
- }
- return sid;
-}
-
-int lchown(const char *path, uid_t uid, gid_t gid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fchownat, -1);
- if(int e = mlibc::sys_fchownat(AT_FDCWD, path, uid, gid, AT_SYMLINK_NOFOLLOW); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int link(const char *old_path, const char *new_path) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_link, -1);
- if(int e = mlibc::sys_link(old_path, new_path); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int linkat(int olddirfd, const char *old_path, int newdirfd, const char *new_path, int flags) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_linkat, -1);
- if(int e = mlibc::sys_linkat(olddirfd, old_path, newdirfd, new_path, flags); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-// Code take from musl
-int lockf(int fd, int op, off_t size) {
- struct flock l = {
- .l_type = F_WRLCK,
- .l_whence = SEEK_CUR,
- .l_start = 0,
- .l_len = size,
- .l_pid = 0,
- };
-
- switch(op) {
- case F_TEST:
- l.l_type = F_RDLCK;
- if(fcntl(fd, F_GETLK, &l) < 0)
- return -1;
- if(l.l_type == F_UNLCK || l.l_pid == getpid())
- return 0;
- errno = EACCES;
- return -1;
- case F_ULOCK:
- l.l_type = F_UNLCK;
- [[fallthrough]];
- case F_TLOCK:
- return fcntl(fd, F_SETLK, &l);
- case F_LOCK:
- return fcntl(fd, F_SETLKW, &l);
- }
-
- errno = EINVAL;
- return -1;
-}
-
-int nice(int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-long pathconf(const char *, int name) {
- switch (name) {
- case _PC_NAME_MAX:
- return NAME_MAX;
- default:
- mlibc::infoLogger() << "missing pathconf() entry " << name << frg::endlog;
- errno = EINVAL;
- return -1;
- }
-}
-
-int pause(void) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_pause, -1);
- if(int e = mlibc::sys_pause(); e) {
- errno = e;
- return -1;
- }
- __ensure(!"There is no successful completion return value for pause");
- __builtin_unreachable();
-}
-
-int pipe(int *fds) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_pipe, -1);
- if(int e = mlibc::sys_pipe(fds, 0); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int pipe2(int *fds, int flags) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_pipe, -1);
- if(int e = mlibc::sys_pipe(fds, flags); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-ssize_t pread(int fd, void *buf, size_t n, off_t off) {
- ssize_t num_read;
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_pread, -1);
- if(int e = mlibc::sys_pread(fd, buf, n, off, &num_read); e) {
- errno = e;
- return -1;
- }
- return num_read;
-}
-
-ssize_t pwrite(int fd, const void *buf, size_t n, off_t off) {
- ssize_t num_written;
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_pwrite, -1);
- if(int e = mlibc::sys_pwrite(fd, buf, n, off, &num_written); e) {
- errno = e;
- return -1;
- }
- return num_written;
-}
-
-ssize_t readlink(const char *__restrict path, char *__restrict buffer, size_t max_size) {
- ssize_t length;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_readlink, -1);
- if(int e = mlibc::sys_readlink(path, buffer, max_size, &length); e) {
- errno = e;
- return -1;
- }
- return length;
-}
-
-ssize_t readlinkat(int, const char *__restrict, char *__restrict, size_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int rmdir(const char *path) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_rmdir, -1);
- if(int e = mlibc::sys_rmdir(path); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int setegid(gid_t egid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setegid, 0);
- if(int e = mlibc::sys_setegid(egid); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int seteuid(uid_t euid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_seteuid, 0);
- if(int e = mlibc::sys_seteuid(euid); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int setgid(gid_t gid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setgid, 0);
- if(int e = mlibc::sys_setgid(gid); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int setpgid(pid_t pid, pid_t pgid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setpgid, -1);
- if(int e = mlibc::sys_setpgid(pid, pgid); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-pid_t setpgrp(void) {
- return setpgid(0, 0);
-}
-
-int setregid(gid_t rgid, gid_t egid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setregid, -1);
- if(int e = mlibc::sys_setregid(rgid, egid); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int setreuid(uid_t ruid, uid_t euid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setreuid, -1);
- if(int e = mlibc::sys_setreuid(ruid, euid); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-pid_t setsid(void) {
- if(!mlibc::sys_setsid) {
- MLIBC_MISSING_SYSDEP();
- return -1;
- }
- pid_t sid;
- if(int e = mlibc::sys_setsid(&sid); e) {
- errno = e;
- return -1;
- }
- return sid;
-}
-
-int setuid(uid_t uid) {
- if(!mlibc::sys_setuid) {
- MLIBC_MISSING_SYSDEP();
- mlibc::infoLogger() << "mlibc: missing sysdep sys_setuid(). Returning 0" << frg::endlog;
- return 0;
- }
- if(int e = mlibc::sys_setuid(uid); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-void swab(const void *__restrict, void *__restrict, ssize_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int symlink(const char *target_path, const char *link_path) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_symlink, -1);
- if(int e = mlibc::sys_symlink(target_path, link_path); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int symlinkat(const char *target_path, int dirfd, const char *link_path) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_symlinkat, -1);
- if(int e = mlibc::sys_symlinkat(target_path, dirfd, link_path); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-void sync(void) {
- if(!mlibc::sys_sync) {
- MLIBC_MISSING_SYSDEP();
- } else {
- mlibc::sys_sync();
- }
-}
-
-long sysconf(int number) {
- if(mlibc::sys_sysconf) {
- long ret = 0;
-
- int e = mlibc::sys_sysconf(number, &ret);
-
- if(e && e != EINVAL) {
- errno = e;
- return -1;
- }
-
- if(e != EINVAL) {
- return ret;
- }
- }
-
- /* default return values, if not overriden by sysdep */
- switch(number) {
- case _SC_ARG_MAX:
- // On linux, it is defined to 2097152 in most cases, so define it to be 2097152
- return 2097152;
- case _SC_PAGE_SIZE:
- return mlibc::page_size;
- case _SC_OPEN_MAX:
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_OPEN_MAX) returns fallback value 256\e[39m" << frg::endlog;
- return 256;
- case _SC_PHYS_PAGES:
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_PHYS_PAGES) returns fallback value 1024\e[39m" << frg::endlog;
- return 1024;
- case _SC_NPROCESSORS_ONLN:
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_NPROCESSORS_ONLN) returns fallback value 1\e[39m" << frg::endlog;
- return 1;
- case _SC_GETPW_R_SIZE_MAX:
- return NSS_BUFLEN_PASSWD;
- case _SC_GETGR_R_SIZE_MAX:
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_GETGR_R_SIZE_MAX) returns fallback value 1024\e[39m" << frg::endlog;
- return 1024;
- case _SC_CHILD_MAX:
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_CHILD_MAX) returns fallback value 25\e[39m" << frg::endlog;
- // On linux, it is defined to 25 in most cases, so define it to be 25
- return 25;
- case _SC_JOB_CONTROL:
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_JOB_CONTROL) returns fallback value 1\e[39m" << frg::endlog;
- // If 1, job control is supported
- return 1;
- case _SC_CLK_TCK:
- // TODO: This should be obsolete?
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_CLK_TCK) is obsolete and returns arbitrary value 1000000\e[39m" << frg::endlog;
- return 1000000;
- case _SC_NGROUPS_MAX:
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_NGROUPS_MAX) returns fallback value 65536\e[39m" << frg::endlog;
- // On linux, it is defined to 65536 in most cases, so define it to be 65536
- return 65536;
- case _SC_RE_DUP_MAX:
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_RE_DUP_MAX) returns fallback value RE_DUP_MAX\e[39m" << frg::endlog;
- return RE_DUP_MAX;
- case _SC_LINE_MAX:
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_LINE_MAX) returns fallback value 2048\e[39m" << frg::endlog;
- // Linux defines it as 2048.
- return 2048;
- case _SC_XOPEN_CRYPT:
-#if __MLIBC_CRYPT_OPTION
- return _XOPEN_CRYPT;
-#else
- return -1;
-#endif /* __MLIBC_CRYPT_OPTION */
- case _SC_NPROCESSORS_CONF:
- // TODO: actually return a proper value for _SC_NPROCESSORS_CONF
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_NPROCESSORS_CONF) unconditionally returns fallback value 1\e[39m" << frg::endlog;
- return 1;
- case _SC_HOST_NAME_MAX:
- mlibc::infoLogger() << "\e[31mmlibc: sysconf(_SC_HOST_NAME_MAX) unconditionally returns fallback value 256\e[39m" << frg::endlog;
- return 256;
- default:
- mlibc::infoLogger() << "\e[31mmlibc: sysconf() call is not implemented, number: " << number << "\e[39m" << frg::endlog;
- errno = EINVAL;
- return -1;
- }
-}
-
-pid_t tcgetpgrp(int fd) {
- int pgrp;
- if(ioctl(fd, TIOCGPGRP, &pgrp) < 0) {
- return -1;
- }
- return pgrp;
-}
-
-int tcsetpgrp(int fd, pid_t pgrp) {
- return ioctl(fd, TIOCSPGRP, &pgrp);
-}
-
-int truncate(const char *, off_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-char *ttyname(int fd) {
- const size_t size = 128;
- static thread_local char buf[size];
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_ttyname, nullptr);
- if(int e = mlibc::sys_ttyname(fd, buf, size); e) {
- errno = e;
- return nullptr;
- }
- return buf;
-}
-
-int ttyname_r(int fd, char *buf, size_t size) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_ttyname, -1);
- if(int e = mlibc::sys_ttyname(fd, buf, size); e) {
- return e;
- }
- return 0;
-}
-
-int unlink(const char *path) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_unlinkat, -1);
- if(int e = mlibc::sys_unlinkat(AT_FDCWD, path, 0); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int unlinkat(int fd, const char *path, int flags) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_unlinkat, -1);
- if(int e = mlibc::sys_unlinkat(fd, path, flags); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int getpagesize() {
- return mlibc::page_size;
-}
-
-// Code taken from musl
-// GLIBC extension for stdin/stdout
-char *getpass(const char *prompt) {
- int fdin, fdout;
- struct termios s, t;
- ssize_t l;
- static char password[128];
-
- if((fdin = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0) {
- fdin = STDIN_FILENO;
- fdout = STDOUT_FILENO;
- } else {
- fdout = fdin;
- }
-
- tcgetattr(fdin, &t);
- s = t;
- t.c_lflag &= ~(ECHO | ISIG);
- t.c_lflag |= ICANON;
- t.c_iflag &= ~(INLCR | IGNCR);
- t.c_iflag |= ICRNL;
- tcsetattr(fdin, TCSAFLUSH, &t);
- tcdrain(fdin);
-
- dprintf(fdout, "%s", prompt);
-
- l = read(fdin, password, sizeof password);
- if(l >= 0) {
- if((l > 0 && password[l - 1] == '\n') || l == sizeof password)
- l--;
- password[l] = 0;
- }
-
- tcsetattr(fdin, TCSAFLUSH, &s);
-
- dprintf(fdout, "\n");
- if(fdin != STDIN_FILENO) {
- close(fdin);
- }
-
- return l < 0 ? 0 : password;
-}
-
-char *get_current_dir_name(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-// This is a Linux extension
-pid_t gettid(void) {
- if(!mlibc::sys_gettid) {
- MLIBC_MISSING_SYSDEP();
- __ensure(!"Cannot continue without sys_gettid()");
- }
- return mlibc::sys_gettid();
-}
-
-int getentropy(void *buffer, size_t length) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getentropy, -1);
- if(length > 256) {
- errno = EIO;
- return -1;
- }
- if(int e = mlibc::sys_getentropy(buffer, length); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-ssize_t write(int fd, const void *buf, size_t count) {
- ssize_t bytes_written;
- if(int e = mlibc::sys_write(fd, buf, count, &bytes_written); e) {
- errno = e;
- return (ssize_t)-1;
- }
- return bytes_written;
-}
-
-ssize_t read(int fd, void *buf, size_t count) {
- ssize_t bytes_read;
- if(int e = mlibc::sys_read(fd, buf, count, &bytes_read); e) {
- errno = e;
- return (ssize_t)-1;
- }
- return bytes_read;
-}
-
-off_t lseek(int fd, off_t offset, int whence) {
- off_t new_offset;
- if(int e = mlibc::sys_seek(fd, offset, whence, &new_offset); e) {
- errno = e;
- return (off_t)-1;
- }
- return new_offset;
-}
-
-off64_t lseek64(int fd, off64_t offset, int whence) {
- off64_t new_offset;
- if(int e = mlibc::sys_seek(fd, offset, whence, &new_offset); e) {
- errno = e;
- return (off64_t)-1;
- }
- return new_offset;
-}
-
-int close(int fd) {
- return mlibc::sys_close(fd);
-}
-
-unsigned int sleep(unsigned int secs) {
- time_t seconds = secs;
- long nanos = 0;
- if(!mlibc::sys_sleep) {
- MLIBC_MISSING_SYSDEP();
- __ensure(!"Cannot continue without sys_sleep()");
- }
- mlibc::sys_sleep(&seconds, &nanos);
- return seconds;
-}
-
-// In contrast to sleep() this functions returns 0/-1 on success/failure.
-int usleep(useconds_t usecs) {
- time_t seconds = 0;
- long nanos = usecs * 1000;
- if(!mlibc::sys_sleep) {
- MLIBC_MISSING_SYSDEP();
- __ensure(!"Cannot continue without sys_sleep()");
- }
- return mlibc::sys_sleep(&seconds, &nanos);
-}
-
-int dup(int fd) {
- int newfd;
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_dup, -1);
- if(int e = mlibc::sys_dup(fd, 0, &newfd); e) {
- errno = e;
- return -1;
- }
- return newfd;
-}
-
-int dup2(int fd, int newfd) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_dup2, -1);
- if(int e = mlibc::sys_dup2(fd, 0, newfd); e) {
- errno = e;
- return -1;
- }
- return newfd;
-}
-
-pid_t fork(void) {
- auto self = mlibc::get_current_tcb();
- pid_t child;
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fork, -1);
-
- auto hand = self->atforkEnd;
- while (hand) {
- if (hand->prepare)
- hand->prepare();
-
- hand = hand->prev;
- }
-
- if(int e = mlibc::sys_fork(&child); e) {
- errno = e;
- return -1;
- }
-
- hand = self->atforkBegin;
- while (hand) {
- if (!child) {
- if (hand->child)
- hand->child();
- } else {
- if (hand->parent)
- hand->parent();
- }
- hand = hand->next;
- }
-
- return child;
-}
-
-pid_t vfork(void) {
- pid_t child;
- /*
- * Fork handlers established using pthread_atfork(3) are not
- * called when a multithreaded program employing the NPTL
- * threading library calls vfork(). Fork handlers are called
- * in this case in a program using the LinuxThreads threading
- * library. (See pthreads(7) for a description of Linux
- * threading libraries.)
- * - vfork(2), release 5.13 of the Linux man-pages project
- *
- * as a result, we call sys_fork instead of running atforks
- */
-
- /* deferring to fork as implementing vfork correctly requires assembly
- * to handle not mucking up the stack
- */
- if(!mlibc::sys_fork) {
- MLIBC_MISSING_SYSDEP();
- errno = ENOSYS;
- return -1;
- }
-
- if(int e = mlibc::sys_fork(&child); e) {
- errno = e;
- return -1;
- }
-
- return child;
-}
-
-int execve(const char *path, char *const argv[], char *const envp[]) {
- char *null_list[] = {
- nullptr
- };
-
- if(!argv)
- argv = null_list;
- if(!envp)
- envp = null_list;
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_execve, -1);
- int e = mlibc::sys_execve(path, argv, envp);
- __ensure(e && "sys_execve() is expected to fail if it returns");
- errno = e;
- return -1;
-}
-
-gid_t getgid(void) {
- if(!mlibc::sys_getgid) {
- MLIBC_MISSING_SYSDEP();
- __ensure(!"Cannot continue without sys_getgid()");
- }
- return mlibc::sys_getgid();
-}
-
-gid_t getegid(void) {
- if(!mlibc::sys_getegid) {
- MLIBC_MISSING_SYSDEP();
- __ensure(!"Cannot continue without sys_getegid()");
- }
- return mlibc::sys_getegid();
-}
-
-uid_t getuid(void) {
- if(!mlibc::sys_getuid) {
- MLIBC_MISSING_SYSDEP();
- __ensure(!"Cannot continue without sys_getuid()");
- }
- return mlibc::sys_getuid();
-}
-
-uid_t geteuid(void) {
- if(!mlibc::sys_geteuid) {
- MLIBC_MISSING_SYSDEP();
- __ensure(!"Cannot continue without sys_geteuid()");
- }
- return mlibc::sys_geteuid();
-}
-
-pid_t getpid(void) {
- if(!mlibc::sys_getpid) {
- MLIBC_MISSING_SYSDEP();
- __ensure(!"Cannot continue without sys_getpid()");
- }
- return mlibc::sys_getpid();
-}
-
-pid_t getppid(void) {
- if(!mlibc::sys_getppid) {
- MLIBC_MISSING_SYSDEP();
- __ensure(!"Cannot continue without sys_getppid()");
- }
- return mlibc::sys_getppid();
-}
-
-int access(const char *path, int mode) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_access, -1);
- if(int e = mlibc::sys_access(path, mode); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-char *getusershell(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void setusershell(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-void endusershell(void) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int isatty(int fd) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_isatty, 0);
- if(int e = mlibc::sys_isatty(fd); e) {
- errno = e;
- return 0;
- }
- return 1;
-}
-
-int chroot(const char *ptr) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_chroot, -1);
- if(int e = mlibc::sys_chroot(ptr); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int daemon(int, int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-char *ctermid(char *s) {
- return s ? strcpy(s, "/dev/tty") : const_cast<char *>("/dev/tty");
-}
-
-int setresuid(uid_t ruid, uid_t euid, uid_t suid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setresuid, -1);
- if(int e = mlibc::sys_setresuid(ruid, euid, suid); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int setresgid(gid_t rgid, gid_t egid, gid_t sgid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setresgid, -1);
- if(int e = mlibc::sys_setresgid(rgid, egid, sgid); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int getdomainname(char *, size_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int setdomainname(const char *, size_t) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-
-int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getresuid, -1);
- if(int e = mlibc::sys_getresuid(ruid, euid, suid); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_getresgid, -1);
- if(int e = mlibc::sys_getresgid(rgid, egid, sgid); e) {
- errno = e;
- return -1;
- }
- return 0;
-}
-
-#if __MLIBC_CRYPT_OPTION
-void encrypt(char[64], int) {
- __ensure(!"Not implemented");
- __builtin_unreachable();
-}
-#endif
-
-#if __MLIBC_BSD_OPTION
-void *sbrk(intptr_t increment) {
- if(increment) {
- errno = ENOMEM;
- return (void *)-1;
- }
-
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_brk, (void *)-1);
- void *out;
- if(int e = mlibc::sys_brk(&out); e) {
- errno = e;
- return (void *)-1;
- }
- return out;
-}
-#endif
diff --git a/lib/mlibc/options/posix/generic/utime-stubs.cpp b/lib/mlibc/options/posix/generic/utime-stubs.cpp
deleted file mode 100644
index f78729f..0000000
--- a/lib/mlibc/options/posix/generic/utime-stubs.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-
-#include <utime.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <bits/ensure.h>
-#include <mlibc/posix-sysdeps.hpp>
-
-int utime(const char *filename, const struct utimbuf *times) {
- MLIBC_CHECK_OR_ENOSYS(mlibc::sys_utimensat, -1);
- struct timespec time[2];
- if(times) {
- time[0].tv_sec = times->actime;
- time[0].tv_nsec = 0;
- time[1].tv_sec = times->modtime;
- time[1].tv_nsec = 0;
- } else {
- time[0].tv_sec = UTIME_NOW;
- time[0].tv_nsec = UTIME_NOW;
- time[1].tv_sec = UTIME_NOW;
- time[1].tv_nsec = UTIME_NOW;
- }
-
- if (int e = mlibc::sys_utimensat(AT_FDCWD, filename, time, 0); e) {
- errno = e;
- return -1;
- }
-
- return 0;
-}
-
diff --git a/lib/mlibc/options/posix/generic/wordexp-stubs.cpp b/lib/mlibc/options/posix/generic/wordexp-stubs.cpp
deleted file mode 100644
index 8443527..0000000
--- a/lib/mlibc/options/posix/generic/wordexp-stubs.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * code taken from OPNSense, with modifications
- *
- * Copyright (c) 2002 Tim J. Robbins.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <wordexp.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <stdint.h>
-
-#define SHELL_PATH "/bin/sh"
-#define SHELL_NAME "sh"
-
-static size_t we_read_fully(int fd, char *buffer, size_t len) {
- size_t done = 0;
-
- do {
- ssize_t nread = read(fd, buffer + done, len - done);
- if(nread == -1 && errno == EINTR)
- continue;
- if(nread <= 0)
- break;
- done += nread;
- } while (done != len);
-
- return done;
-}
-
-static int we_askshell(const char *words, wordexp_t *we, int flags) {
- int pdes[2]; /* pipe to child */
- char bbuf[9]; /* buffer for byte count */
- char wbuf[9]; /* buffer for word count */
- size_t nwords = 0; /* number of words from child */
- size_t nbytes = 0; /* number of bytes from child */
- size_t sofs = 0; /* offset into we->we_strings */
- size_t vofs = 0; /* offset into we->we_wordv */
- pid_t pid; /* PID of child */
- pid_t wpid; /* waitpid return value */
- int status; /* child exit status */
- int error; /* our return value */
- int serrno; /* errno to return */
- char *np, *p; /* handy pointers */
- char *nstrings; /* temporary for realloc() */
- char **new_wordv; /* temporary for realloc() */
- sigset_t newsigblock;
- sigset_t oldsigblock;
- const char *ifs = getenv("IFS");
-
- serrno = errno;
-
- if(pipe2(pdes, O_CLOEXEC) < 0)
- return WRDE_NOSPACE;
-
- (void)sigemptyset(&newsigblock);
- (void)sigaddset(&newsigblock, SIGCHLD);
- (void)sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock);
-
- if((pid = fork()) < 0) {
- serrno = errno;
- close(pdes[0]);
- close(pdes[1]);
- (void)sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
- errno = serrno;
- return WRDE_NOSPACE;
- } else if(pid == 0) {
- /*
- * We are the child; make /bin/sh expand `words'.
- */
- (void)sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
- if((pdes[1] != STDOUT_FILENO ? dup2(pdes[1], STDOUT_FILENO) : fcntl(pdes[1], F_SETFD, 0)) < 0)
- _exit(1);
-
- execl(SHELL_PATH, SHELL_NAME, flags & WRDE_UNDEF ? "-u" : "+u",
- "-c", "IFS=$1;eval \"$2\";eval \"set -- $3\";IFS=;a=\"$*\";"
- "printf '%08x' \"$#\" \"${#a}\";printf '%s\\0' \"$@\"", "",
- ifs != NULL ? ifs : " \t\n",
- flags & WRDE_SHOWERR ? "" : "exec 2>/dev/null",
- words,
- (char *)NULL);
- _exit(1);
- }
-
- /*
- * We are the parent; read the output of the shell wordexp function,
- * which is a 32-bit hexadecimal word count, a 32-bit hexadecimal
- * byte count (not including terminating null bytes), followed by
- * the expanded words separated by nulls.
- */
- close(pdes[1]);
- if(we_read_fully(pdes[0], wbuf, 8) != 8 || we_read_fully(pdes[0], bbuf, 8) != 8) {
- error = flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX;
- serrno = errno;
- goto cleanup;
- }
- wbuf[8] = bbuf[8] = '\0';
- nwords = strtol(wbuf, NULL, 16);
- nbytes = strtol(bbuf, NULL, 16) + nwords;
-
- /*
- * Allocate or reallocate (when flags & WRDE_APPEND) the word vector
- * and string storage buffers for the expanded words we're about to
- * read from the child.
- */
- sofs = we->we_nbytes;
- vofs = we->we_wordc;
- if((flags & (WRDE_DOOFFS|WRDE_APPEND)) == (WRDE_DOOFFS | WRDE_APPEND))
- vofs += we->we_offs;
- we->we_wordc += nwords;
- we->we_nbytes += nbytes;
-
- if((new_wordv = (char **) realloc(we->we_wordv, (we->we_wordc + 1 + (flags & WRDE_DOOFFS ? we->we_offs : 0)) * sizeof(char *))) == NULL) {
- error = WRDE_NOSPACE;
- goto cleanup;
- }
-
- we->we_wordv = new_wordv;
-
- if((nstrings = (char *) realloc(we->we_strings, we->we_nbytes)) == NULL) {
- error = WRDE_NOSPACE;
- goto cleanup;
- }
-
- for(size_t i = 0; i < vofs; i++) {
- if(we->we_wordv[i] != NULL)
- we->we_wordv[i] += nstrings - we->we_strings;
- }
- we->we_strings = nstrings;
-
- if(we_read_fully(pdes[0], we->we_strings + sofs, nbytes) != nbytes) {
- error = flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX;
- serrno = errno;
- goto cleanup;
- }
-
- error = 0;
-cleanup:
- close(pdes[0]);
-
- do {
- wpid = waitpid(pid, &status, 0);
- } while(wpid < 0 && errno == EINTR);
-
- (void)sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
-
- if(error != 0) {
- errno = serrno;
- return error;
- }
-
- if(wpid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
- return flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX;
-
- /*
- * Break the null-terminated expanded word strings out into
- * the vector.
- */
- if(vofs == 0 && flags & WRDE_DOOFFS) {
- while (vofs < we->we_offs)
- we->we_wordv[vofs++] = NULL;
- }
-
- p = we->we_strings + sofs;
- while (nwords-- != 0) {
- we->we_wordv[vofs++] = p;
- if((np = (char *) memchr(p, '\0', nbytes)) == NULL)
- return WRDE_NOSPACE;
-
- nbytes -= np - p + 1;
- p = np + 1;
- }
-
- we->we_wordv[vofs] = NULL;
- return 0;
-}
-
-/*
- * we_check --
- * Check that the string contains none of the following unquoted
- * special characters: <newline> |&;<>(){}
- * or command substitutions when WRDE_NOCMD is set in flags.
- */
-static int we_check(const char *words, int flags)
-{
- char c;
- int dquote, level, quote, squote;
-
- quote = squote = dquote = 0;
- while ((c = *words++) != '\0') {
- switch (c) {
- case '\\': {
- if(squote == 0)
- quote ^= 1;
- continue;
- }
- case '\'': {
- if(quote + dquote == 0)
- squote ^= 1;
- break;
- }
- case '"': {
- if(quote + squote == 0)
- dquote ^= 1;
- break;
- }
- case '`': {
- if(quote + squote == 0 && flags & WRDE_NOCMD)
- return WRDE_CMDSUB;
- while ((c = *words++) != '\0' && c != '`')
- if(c == '\\' && (c = *words++) == '\0')
- break;
- if(c == '\0')
- return WRDE_SYNTAX;
- break;
- }
- case '|':
- case '&':
- case ';':
- case '<':
- case '>':
- case '{':
- case '}':
- case '(':
- case ')':
- case '\n': {
- if(quote + squote + dquote == 0)
- return WRDE_BADCHAR;
- break;
- }
- case '$': {
- if((c = *words++) == '\0')
- break;
- else if(quote + squote == 0 && c == '(') {
- if(flags & WRDE_NOCMD && *words != '(')
- return WRDE_CMDSUB;
- level = 1;
- while ((c = *words++) != '\0') {
- if(c == '\\') {
- if((c = *words++) == '\0')
- break;
- } else if(c == '(')
- level++;
- else if(c == ')' && --level == 0)
- break;
- }
- if(c == '\0' || level != 0)
- return WRDE_SYNTAX;
- } else if(quote + squote == 0 && c == '{') {
- level = 1;
- while ((c = *words++) != '\0') {
- if(c == '\\') {
- if((c = *words++) == '\0')
- break;
- } else if(c == '{')
- level++;
- else if(c == '}' && --level == 0)
- break;
- }
- if(c == '\0' || level != 0)
- return WRDE_SYNTAX;
- } else
- --words;
- break;
- }
- default: {
- break;
- }
- }
- quote = 0;
- }
-
- if(quote + squote + dquote != 0)
- return WRDE_SYNTAX;
-
- return 0;
-}
-
-int wordexp(const char * __restrict words, wordexp_t * __restrict we, int flags) {
- int error;
-
- if(flags & WRDE_REUSE)
- wordfree(we);
-
- if((flags & WRDE_APPEND) == 0) {
- we->we_wordc = 0;
- we->we_wordv = NULL;
- we->we_strings = NULL;
- we->we_nbytes = 0;
- }
-
- if((error = we_check(words, flags)) != 0) {
- wordfree(we);
- return error;
- }
-
- if((error = we_askshell(words, we, flags)) != 0) {
- wordfree(we);
- return error;
- }
-
- return 0;
-}
-
-void wordfree(wordexp_t *we) {
- if (we == NULL)
- return;
- free(we->we_wordv);
- free(we->we_strings);
- we->we_wordv = NULL;
- we->we_strings = NULL;
- we->we_nbytes = 0;
- we->we_wordc = 0;
-}