diff options
Diffstat (limited to 'lib/mlibc/options/posix/generic')
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(¤t_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, ¤t_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, ¤t_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, ¤t_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, ¤t_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; -} |