diff options
Diffstat (limited to 'lib/mlibc/options/posix/generic/posix_stdlib.cpp')
-rw-r--r-- | lib/mlibc/options/posix/generic/posix_stdlib.cpp | 513 |
1 files changed, 0 insertions, 513 deletions
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); -} |