diff options
Diffstat (limited to 'lib/mlibc/options/glibc/generic')
-rw-r--r-- | lib/mlibc/options/glibc/generic/err.cpp | 64 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/error.cpp | 65 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/execinfo.cpp | 17 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/getopt-stubs.cpp | 253 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/glibc-assert.cpp | 14 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/glibc-signal.cpp | 14 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/gshadow.cpp | 7 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/malloc.cpp | 6 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/personality.cpp | 15 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/printf.cpp | 7 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/resolv-stubs.cpp | 36 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/shadow-stubs.cpp | 217 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/stdio_ext-stubs.cpp | 64 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/string.cpp | 32 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/sys-io.cpp | 25 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/sys-ioctl.cpp | 21 | ||||
-rw-r--r-- | lib/mlibc/options/glibc/generic/sys-timex.cpp | 17 |
17 files changed, 874 insertions, 0 deletions
diff --git a/lib/mlibc/options/glibc/generic/err.cpp b/lib/mlibc/options/glibc/generic/err.cpp new file mode 100644 index 0000000..042c1d8 --- /dev/null +++ b/lib/mlibc/options/glibc/generic/err.cpp @@ -0,0 +1,64 @@ +#include <err.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +// va_list + +void vwarn(const char *fmt, va_list params) { + fprintf(stderr, "%s: ", program_invocation_short_name); + if (fmt) { + vfprintf(stderr, fmt, params); + fwrite(": ", 1, 2, stderr); + } + perror(NULL); +} + +void vwarnx(const char *fmt, va_list params) { + fprintf(stderr, "%s: ", program_invocation_short_name); + if (fmt) { + vfprintf(stderr, fmt, params); + } + putc('\n', stderr); +} + +__attribute__((__noreturn__)) void verr(int status, const char *fmt, va_list params) { + vwarn(fmt, params); + exit(status); +} + +__attribute__((__noreturn__)) void verrx(int status, const char *fmt, va_list params) { + vwarnx(fmt, params); + exit(status); +} + +// variadic + +void warn(const char *fmt, ...) { + va_list params; + va_start(params, fmt); + vwarn(fmt, params); + va_end(params); +} + +void warnx(const char *fmt, ...) { + va_list params; + va_start(params, fmt); + vwarnx(fmt, params); + va_end(params); +} + +__attribute__((__noreturn__)) void err(int status, const char *fmt, ...) { + va_list params; + va_start(params, fmt); + verr(status, fmt, params); + va_end(params); +} + +__attribute__((__noreturn__)) void errx(int status, const char *fmt, ...) { + va_list params; + va_start(params, fmt); + verrx(status, fmt, params); + va_end(params); +} diff --git a/lib/mlibc/options/glibc/generic/error.cpp b/lib/mlibc/options/glibc/generic/error.cpp new file mode 100644 index 0000000..45203b2 --- /dev/null +++ b/lib/mlibc/options/glibc/generic/error.cpp @@ -0,0 +1,65 @@ +#include <stdio.h> +#include <stdarg.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <error.h> + +unsigned int error_message_count = 0; +int error_one_per_line = 0; +void (*error_print_progname)(void) = NULL; + +void error(int status, int errnum, const char *format, ...) { + va_list args; + va_start(args, format); + + error_message_count++; + + fflush(stdout); + if(error_print_progname) { + error_print_progname(); + } else { + fprintf(stderr, "%s: ", program_invocation_name); + } + vfprintf(stderr, format, args); + va_end(args); + + if(errnum) { + fprintf(stderr, ": %s\n", strerror(errnum)); + } + + if(status) { + exit(status); + } +} + +void error_at_line(int status, int errnum, const char *filename, unsigned int linenum, const char *format, ...) { + va_list args; + va_start(args, format); + + static bool first_call = true; + static unsigned int last_line = 0; + if(!(last_line == linenum && error_one_per_line && !first_call)) { + first_call = false; + last_line = linenum; + error_message_count++; + + fflush(stdout); + if(error_print_progname) { + error_print_progname(); + } else { + fprintf(stderr, "%s:", program_invocation_name); + } + fprintf(stderr, "%s:%u: ", filename, linenum); + vfprintf(stderr, format, args); + + if(errnum) { + fprintf(stderr, ": %s\n", strerror(errnum)); + } + } + va_end(args); + + if(status) { + exit(status); + } +} diff --git a/lib/mlibc/options/glibc/generic/execinfo.cpp b/lib/mlibc/options/glibc/generic/execinfo.cpp new file mode 100644 index 0000000..3474615 --- /dev/null +++ b/lib/mlibc/options/glibc/generic/execinfo.cpp @@ -0,0 +1,17 @@ +#include <execinfo.h> +#include <bits/ensure.h> + +int backtrace(void **, int) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +char **backtrace_symbols(void *const *, int) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +void backtrace_symbols_fd(void *const *, int, int) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} diff --git a/lib/mlibc/options/glibc/generic/getopt-stubs.cpp b/lib/mlibc/options/glibc/generic/getopt-stubs.cpp new file mode 100644 index 0000000..d13d4eb --- /dev/null +++ b/lib/mlibc/options/glibc/generic/getopt-stubs.cpp @@ -0,0 +1,253 @@ +#include <assert.h> +#include <bits/ensure.h> +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <frg/optional.hpp> +#include <mlibc/debug.hpp> + +char *optarg; +int optind = 1; +int opterr = 1; +int optopt; + +namespace { + +int __optpos = 1; + +enum GetoptMode { + Short, + Long, + LongOnly, +}; + +int getopt_common(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex, enum GetoptMode mode) { + auto longopt_consume = [&](const char *arg, char *s, int k, bool colon) -> frg::optional<int> { + // Consume the option and its argument. + if(longopts[k].has_arg == required_argument) { + if(s) { + // Consume the long option and its argument. + optarg = s + 1; + optind++; + }else if(argv[optind + 1]) { + // Consume the long option. + optind++; + + // Consume the option's argument. + optarg = argv[optind]; + optind++; + }else{ + /* If an error was detected, and the first character of optstring is not a colon, + and the external variable opterr is nonzero (which is the default), + getopt() prints an error message. */ + if(!colon && opterr) + fprintf(stderr, "--%s requires an argument.\n", arg); + /* If the first character of optstring is a colon (':'), then getopt() + returns ':' instead of '?' to indicate a missing option argument. */ + return colon ? ':' : '?'; + } + }else if(longopts[k].has_arg == optional_argument) { + if(s) { + // Consume the long option and its argument. + optarg = s + 1; + optind++; + }else{ + // Consume the long option. + optarg = nullptr; + optind++; + } + }else{ + __ensure(longopts[k].has_arg == no_argument); + + // Consume the long option. + optind++; + } + + return frg::null_opt; + }; + + bool colon = optstring[0] == ':'; + bool stop_at_first_nonarg = (optstring[0] == '+' || getenv("POSIXLY_CORRECT")); + + // glibc extension: Setting optind to zero causes a full reset. + // TODO: Should we really reset opterr and the other flags? + if(!optind +#if __MLIBC_BSD_OPTION + || optreset +#endif //__MLIBC_BSD_OPTION + ) { + optarg = nullptr; + optind = 1; + opterr = 1; + optopt = 0; + __optpos = 1; +#if __MLIBC_BSD_OPTION + optreset = 0; +#endif //__MLIBC_BSD_OPTION + } + + auto isOptionArg = [](char *arg){ + // If the first character of arg '-', and the arg is not exactly + // equal to "-" or "--", then the arg is an option argument. + return arg[0] == '-' && strcmp(arg, "-") && strcmp(arg, "--"); + }; + + while(optind < argc) { + char *arg = argv[optind]; + if(!isOptionArg(arg)) { + if(stop_at_first_nonarg) { + return -1; + } + + bool further_options = false; + int skip = optind; + + for(; skip < argc; ++skip) { + if(isOptionArg(argv[skip])) { + further_options = true; + break; + } + } + + if(further_options) { + optind += skip - optind; + continue; + } else { + optarg = nullptr; + return -1; + } + } + + if(arg[1] == '-') { + arg += 2; + + // Determine the end of the option name (vs. the start of the argument). + auto s = strchr(arg, '='); + size_t n = s ? (s - arg) : strlen(arg); + + int k = -1; + for(int i = 0; longopts[i].name; i++) { + if(strncmp(arg, longopts[i].name, n) || longopts[i].name[n]) + continue; + + if(k >= 0) { + if(opterr) + fprintf(stderr, "Multiple option declaration detected: %s\n", arg); + return '?'; + } + k = i; + } + + if(k == -1) { + if(opterr) + fprintf(stderr, "--%s is not a valid option.\n", arg); + return '?'; + } + + if(longindex) + *longindex = k; + + if(auto r = longopt_consume(arg, s, k, colon); r) + return r.value(); + + if(!longopts[k].flag) { + return longopts[k].val; + }else{ + *longopts[k].flag = longopts[k].val; + return 0; + } + }else{ + /* handle short options, i.e. options with only one dash prefixed; e.g. `program -s` */ + unsigned int i = __optpos; + while(true) { + if(mode == GetoptMode::LongOnly) { + const char *lo_arg = &arg[1]; + auto s = strchr(lo_arg, '='); + size_t n = s ? (s - lo_arg) : strlen(lo_arg); + int k = -1; + + for(int longopt = 0; longopts[longopt].name; longopt++) { + if(strncmp(lo_arg, longopts[longopt].name, n) || longopts[longopt].name[n]) + continue; + + if(k >= 0) { + if(opterr) + fprintf(stderr, "Multiple option declaration detected: %s\n", arg); + return '?'; + } + + k = longopt; + } + + if(k != -1) { + if(auto r = longopt_consume(lo_arg, s, k, colon); r) + return r.value(); + + if(!longopts[k].flag) { + return longopts[k].val; + }else{ + *longopts[k].flag = longopts[k].val; + return 0; + } + } + } + + auto opt = strchr(optstring, arg[i]); + if(opt) { + if(opt[1] == ':') { + bool required = (opt[2] != ':'); + + if(arg[i+1]) { + optarg = arg + i + 1; + } else if(optind + 1 < argc && argv[optind + 1] && (required || argv[optind + 1][0] != '-')) { + /* there is an argument to this short option, separated by a space */ + optarg = argv[optind + 1]; + optind++; + __optpos = 1; + } else if(!required) { + optarg = nullptr; + } else { + __optpos = 1; + optopt = arg[i]; + return colon ? ':' : '?'; + } + optind++; + } else { + if(arg[i+1]) { + __optpos++; + } else if(arg[i]) { + optind++; + } else { + return -1; + } + } + + return arg[i]; + } else { + /* If getopt() does not recognize an option character, it prints an error message to stderr, + stores the character in optopt, and returns '?'. The calling program may prevent + the error message by setting opterr to 0. */ + optopt = arg[1]; + if(opterr) + fprintf(stderr, "%s is not a valid option.\n", arg); + return '?'; + } + } + } + } + return -1; +} + +} + +int getopt_long(int argc, char * const argv[], const char *optstring, + const struct option *longopts, int *longindex) { + return getopt_common(argc, argv, optstring, longopts, longindex, GetoptMode::Long); +} + +int getopt_long_only(int argc, char * const argv[], const char *optstring, + const struct option *longopts, int *longindex) { + return getopt_common(argc, argv, optstring, longopts, longindex, GetoptMode::LongOnly); +} diff --git a/lib/mlibc/options/glibc/generic/glibc-assert.cpp b/lib/mlibc/options/glibc/generic/glibc-assert.cpp new file mode 100644 index 0000000..77cd498 --- /dev/null +++ b/lib/mlibc/options/glibc/generic/glibc-assert.cpp @@ -0,0 +1,14 @@ +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <bits/ensure.h> + +[[gnu::noreturn]] void __assert_fail_perror(int errno, const char *file, unsigned int line, + const char *function) { + char *errormsg = strerror(errno); + fprintf(stderr, "In function %s, file %s:%d: Errno '%s' failed!\n", + function, file, line, errormsg); + abort(); +} diff --git a/lib/mlibc/options/glibc/generic/glibc-signal.cpp b/lib/mlibc/options/glibc/generic/glibc-signal.cpp new file mode 100644 index 0000000..41bc455 --- /dev/null +++ b/lib/mlibc/options/glibc/generic/glibc-signal.cpp @@ -0,0 +1,14 @@ +#include <errno.h> +#include <signal.h> +#include <bits/ensure.h> +#include <mlibc/debug.hpp> +#include <mlibc/glibc-sysdeps.hpp> + +int tgkill(int tgid, int tid, int sig) { + MLIBC_CHECK_OR_ENOSYS(mlibc::sys_tgkill, -1); + if(int e = mlibc::sys_tgkill(tgid, tid, sig); e) { + errno = e; + return -1; + } + return 0; +} diff --git a/lib/mlibc/options/glibc/generic/gshadow.cpp b/lib/mlibc/options/glibc/generic/gshadow.cpp new file mode 100644 index 0000000..f93a47d --- /dev/null +++ b/lib/mlibc/options/glibc/generic/gshadow.cpp @@ -0,0 +1,7 @@ +#include <gshadow.h> +#include <bits/ensure.h> + +int getsgnam_r(const char *, struct sgrp *, char *, size_t, struct sgrp **) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} diff --git a/lib/mlibc/options/glibc/generic/malloc.cpp b/lib/mlibc/options/glibc/generic/malloc.cpp new file mode 100644 index 0000000..b5a4daf --- /dev/null +++ b/lib/mlibc/options/glibc/generic/malloc.cpp @@ -0,0 +1,6 @@ +#include <bits/glibc/glibc_malloc.h> +#include <mlibc/allocator.hpp> + +size_t malloc_usable_size(void *p) { + return getAllocator().get_size(p); +} diff --git a/lib/mlibc/options/glibc/generic/personality.cpp b/lib/mlibc/options/glibc/generic/personality.cpp new file mode 100644 index 0000000..3bfd9aa --- /dev/null +++ b/lib/mlibc/options/glibc/generic/personality.cpp @@ -0,0 +1,15 @@ +#include <bits/ensure.h> +#include <errno.h> +#include <mlibc/glibc-sysdeps.hpp> +#include <sys/personality.h> + +int personality(unsigned long persona) { + int out = 0; + auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_personality, -1); + + if(int e = sysdep(persona, &out); e) { + errno = e; + return -1; + } + return out; +} diff --git a/lib/mlibc/options/glibc/generic/printf.cpp b/lib/mlibc/options/glibc/generic/printf.cpp new file mode 100644 index 0000000..4abb00d --- /dev/null +++ b/lib/mlibc/options/glibc/generic/printf.cpp @@ -0,0 +1,7 @@ +#include <bits/ensure.h> +#include <printf.h> + +size_t parse_printf_format(const char * __restrict, size_t, int * __restrict) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} diff --git a/lib/mlibc/options/glibc/generic/resolv-stubs.cpp b/lib/mlibc/options/glibc/generic/resolv-stubs.cpp new file mode 100644 index 0000000..7c0723e --- /dev/null +++ b/lib/mlibc/options/glibc/generic/resolv-stubs.cpp @@ -0,0 +1,36 @@ +#include <resolv.h> +#include <bits/ensure.h> +#include <mlibc/debug.hpp> + +int dn_expand(const unsigned char *, const unsigned char *, + const unsigned char *, char *, int) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +int res_query(const char *, int, int, unsigned char *, int) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +int res_init() { + mlibc::infoLogger() << "mlibc: res_init is a stub!" << frg::endlog; + return 0; +} + +int res_ninit(res_state) { + mlibc::infoLogger() << "mlibc: res_ninit is a stub!" << frg::endlog; + return 0; +} + +void res_nclose(res_state) { + mlibc::infoLogger() << "mlibc: res_nclose is a stub!" << frg::endlog; + return; +} + +/* This is completely unused, and exists purely to satisfy broken apps. */ + +struct __res_state *__res_state() { + static struct __res_state res; + return &res; +} diff --git a/lib/mlibc/options/glibc/generic/shadow-stubs.cpp b/lib/mlibc/options/glibc/generic/shadow-stubs.cpp new file mode 100644 index 0000000..9ce6584 --- /dev/null +++ b/lib/mlibc/options/glibc/generic/shadow-stubs.cpp @@ -0,0 +1,217 @@ +#include <shadow.h> +#include <errno.h> +#include <limits.h> +#include <pthread.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> + +#include <bits/ensure.h> +#include <mlibc/debug.hpp> + +/* + * The code in this file is largely based on or taken from musl. + * This includes: + * - xatol + * - __parsespent + * - cleanup + * - getspnam_r + * - getspnam + */ +#define NUM(n) ((n) == -1 ? 0 : -1), ((n) == -1 ? 0 : (n)) + +int putspent(const struct spwd *sp, FILE *f) { + auto str = [] (char *s) { + return ((s) ? (s) : ""); + }; + return fprintf(f, "%s:%s:%.*d:%.*d:%.*d:%.*d:%.*d:%.*d:%.*u\n", + str(sp->sp_namp), str(sp->sp_pwdp), NUM(sp->sp_lstchg), + NUM(sp->sp_min), NUM(sp->sp_max), NUM(sp->sp_warn), + NUM(sp->sp_inact), NUM(sp->sp_expire), NUM((int)sp->sp_flag)) < 0 ? -1 : 0; +} +#undef NUM + +static long xatol(char **s) { + long x; + if(**s == ':' || **s == '\n') { + return -1; + } + for(x = 0; (unsigned int)**s - '0' < 10U; ++*s) { + x = 10 * x + (**s - '0'); + } + return x; +} + +static int __parsespent(char *s, struct spwd *sp) { + sp->sp_namp = s; + if(!(s = strchr(s, ':'))) { + return -1; + } + *s = 0; + + sp->sp_pwdp = ++s; + if(!(s = strchr(s, ':'))) { + return -1; + } + *s = 0; + + s++; + sp->sp_lstchg = xatol(&s); + if(*s != ':') { + return -1; + } + + s++; + sp->sp_min = xatol(&s); + if(*s != ':') { + return -1; + } + + s++; + sp->sp_max = xatol(&s); + if(*s != ':') { + return -1; + } + + s++; + sp->sp_warn = xatol(&s); + if(*s != ':') { + return -1; + } + + s++; + sp->sp_inact = xatol(&s); + if(*s != ':') { + return -1; + } + + s++; + sp->sp_expire = xatol(&s); + if(*s != ':') { + return -1; + } + + s++; + sp->sp_flag = xatol(&s); + if(*s != '\n') { + return -1; + } + return 0; +} + +static void cleanup(void *p) { + fclose((FILE *)p); +} + +int getspnam_r(const char *name, struct spwd *sp, char *buf, size_t size, struct spwd **res) { + char path[20 + NAME_MAX]; + FILE *f = 0; + int rv = 0; + int fd; + size_t k, l = strlen(name); + int skip = 0; + int cs; + int orig_errno = errno; + + *res = 0; + + /* Disallow potentially-malicious user names */ + if(*name=='.' || strchr(name, '/') || !l) { + return errno = EINVAL; + } + + /* Buffer size must at least be able to hold name, plus some.. */ + if(size < l + 100) { + return errno = ERANGE; + } + + /* Protect against truncation */ + if(snprintf(path, sizeof path, "/etc/tcb/%s/shadow", name) >= (int)sizeof path) { + return errno = EINVAL; + } + + fd = open(path, O_RDONLY|O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC); + if(fd >= 0) { + struct stat st = {}; + errno = EINVAL; + if(fstat(fd, &st) || !S_ISREG(st.st_mode) || !(f = fdopen(fd, "rb"))) { + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + close(fd); + pthread_setcancelstate(cs, 0); + return errno; + } + } else { + if(errno != ENOENT && errno != ENOTDIR) { + return errno; + } + f = fopen("/etc/shadow", "rbe"); + if(!f) { + if(errno != ENOENT && errno != ENOTDIR) { + return errno; + } + return 0; + } + } + + pthread_cleanup_push(cleanup, f); + while(fgets(buf, size, f) && (k = strlen(buf)) > 0) { + if(skip || strncmp(name, buf, l) || buf[l] != ':') { + skip = buf[k - 1] != '\n'; + continue; + } + if(buf[k - 1] != '\n') { + rv = ERANGE; + break; + } + + if(__parsespent(buf, sp) < 0) { + continue; + } + *res = sp; + break; + } + pthread_cleanup_pop(1); + errno = rv ? rv : orig_errno; + return rv; +} + +int lckpwdf(void) { + mlibc::infoLogger() << "mlibc: lckpwdf is unimplemented like musl" << frg::endlog; + return 0; +} + +int ulckpwdf(void) { + mlibc::infoLogger() << "mlibc: ulckpwdf is unimplemented like musl" << frg::endlog; + return 0; +} + +// Musl defines LINE_LIM to 256 +#define LINE_LIM 256 + +struct spwd *getspnam(const char *name) { + static struct spwd sp; + static char *line; + struct spwd *res; + int e; + int orig_errno = errno; + + if(!line) { + line = (char *)malloc(LINE_LIM); + } + if(!line) { + return 0; + } + e = getspnam_r(name, &sp, line, LINE_LIM, &res); + errno = e ? e : orig_errno; + return res; +} + +struct spwd *fgetspent(FILE *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +void endspent(void) { + mlibc::infoLogger() << "mlibc: endspent is a stub" << frg::endlog; +} diff --git a/lib/mlibc/options/glibc/generic/stdio_ext-stubs.cpp b/lib/mlibc/options/glibc/generic/stdio_ext-stubs.cpp new file mode 100644 index 0000000..b9b61fc --- /dev/null +++ b/lib/mlibc/options/glibc/generic/stdio_ext-stubs.cpp @@ -0,0 +1,64 @@ + +#include <stdio_ext.h> +#include <bits/ensure.h> +#include <mlibc/debug.hpp> + +size_t __fbufsize(FILE *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +size_t __fpending(FILE *file_base) { + __ensure(file_base->__dirty_end >= file_base->__dirty_begin); + return file_base->__dirty_end - file_base->__dirty_begin; +} + +int __flbf(FILE *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} +int __freadable(FILE *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} +int __fwritable(FILE *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +int __freading(FILE *file_base) { + return file_base->__io_mode == 0; +} + +int __fwriting(FILE *file_base) { + return file_base->__io_mode == 1; +} + +int __fsetlocking(FILE *, int) { + mlibc::infoLogger() << "mlibc: __fsetlocking() is a no-op" << frg::endlog; + return FSETLOCKING_INTERNAL; +} + +void _flushlbf(void) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +// The following functions are defined by musl. + +size_t __freadahead(FILE *file_base) { + if(file_base->__io_mode != 0) { + mlibc::infoLogger() << "mlibc: __freadahead() called but file is not open for reading" << frg::endlog; + return 0; + } + return file_base->__valid_limit - file_base->__offset; +} +const char *__freadptr(FILE *, size_t *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} +void __fseterr(FILE *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + diff --git a/lib/mlibc/options/glibc/generic/string.cpp b/lib/mlibc/options/glibc/generic/string.cpp new file mode 100644 index 0000000..19f77c7 --- /dev/null +++ b/lib/mlibc/options/glibc/generic/string.cpp @@ -0,0 +1,32 @@ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include <type_traits> +#include <string.h> + +/* This is a bit of a weird detail of the GNU implementation and C's lack of + * overloading and strictness: GNU takes const char * and returns a char * so + * that it autocasts to your desired constness, this function never actually + * modifies the string. + */ +char *__mlibc_gnu_basename_c(const char *path) { + char *basename_component = strrchr(path, '/'); + if (!basename_component) { + return const_cast<char *>(path); + } + return basename_component + 1; +} + + +/* GNU exposes these overloads, and as a result, we should probably have them + * checked, to make sure we actually match expectations. + */ +static_assert( + std::is_same_v<decltype(basename((const char *)nullptr)), const char*>, + "C++ overloads broken" +); + +static_assert( + std::is_same_v<decltype(basename((char *)nullptr)), char*>, + "C++ overloads broken" +); diff --git a/lib/mlibc/options/glibc/generic/sys-io.cpp b/lib/mlibc/options/glibc/generic/sys-io.cpp new file mode 100644 index 0000000..fbd9070 --- /dev/null +++ b/lib/mlibc/options/glibc/generic/sys-io.cpp @@ -0,0 +1,25 @@ +#include <errno.h> +#include <sys/io.h> + +#include <bits/ensure.h> +#include <mlibc/glibc-sysdeps.hpp> + +int ioperm(unsigned long int from, unsigned long int num, int turn_on) { + auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_ioperm, -1); + + if(int e = sysdep(from, num, turn_on); e) { + errno = e; + return -1; + } + return 0; +} + +int iopl(int level) { + auto sysdep = MLIBC_CHECK_OR_ENOSYS(mlibc::sys_iopl, -1); + + if(int e = sysdep(level); e) { + errno = e; + return -1; + } + return 0; +} diff --git a/lib/mlibc/options/glibc/generic/sys-ioctl.cpp b/lib/mlibc/options/glibc/generic/sys-ioctl.cpp new file mode 100644 index 0000000..021d2a3 --- /dev/null +++ b/lib/mlibc/options/glibc/generic/sys-ioctl.cpp @@ -0,0 +1,21 @@ + +#include <errno.h> +#include <sys/ioctl.h> + +#include <bits/ensure.h> +#include <mlibc/debug.hpp> +#include <mlibc/glibc-sysdeps.hpp> + +int ioctl(int fd, unsigned long request, ...) { + va_list args; + va_start(args, request); + int result; + MLIBC_CHECK_OR_ENOSYS(mlibc::sys_ioctl, -1); + void *arg = va_arg(args, void *); + if(int e = mlibc::sys_ioctl(fd, request, arg, &result); e) { + errno = e; + return -1; + } + return result; +} + diff --git a/lib/mlibc/options/glibc/generic/sys-timex.cpp b/lib/mlibc/options/glibc/generic/sys-timex.cpp new file mode 100644 index 0000000..6173399 --- /dev/null +++ b/lib/mlibc/options/glibc/generic/sys-timex.cpp @@ -0,0 +1,17 @@ +#include <bits/ensure.h> +#include <sys/timex.h> + +int adjtimex(struct timex *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +int clock_adjtime(clockid_t, struct timex *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} + +int ntp_adjtime(struct timex *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); +} |