diff options
author | A. Wilcox <awilcox@wilcox-tech.com> | 2018-09-21 21:30:18 +0000 |
---|---|---|
committer | A. Wilcox <awilcox@wilcox-tech.com> | 2018-09-21 21:30:18 +0000 |
commit | e7fd895295db6291319af09ffaa3b6d93180788c (patch) | |
tree | 6ad80501db199c916e8fc2ed5648bf694a257675 | |
parent | 938c8095e7456fbcdf4ce261bdb6dfa3a8e41b80 (diff) | |
parent | 9bc7c737b311fcbba71af11884b7f9111dba57ba (diff) | |
download | gcompat-e7fd895295db6291319af09ffaa3b6d93180788c.tar.gz gcompat-e7fd895295db6291319af09ffaa3b6d93180788c.tar.bz2 gcompat-e7fd895295db6291319af09ffaa3b6d93180788c.tar.xz gcompat-e7fd895295db6291319af09ffaa3b6d93180788c.zip |
Merge branch 'patch-3' into 'master'
Add some more functions (notably __cxa_thread_atexit_impl and realpath) and run clang-format
See merge request !3
-rw-r--r-- | CHANGELOG.rst | 30 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | libgcompat/ctype.c | 1 | ||||
-rw-r--r-- | libgcompat/cxx_thread.c | 56 | ||||
-rw-r--r-- | libgcompat/gnulib.c | 16 | ||||
-rw-r--r-- | libgcompat/internal.c | 3 | ||||
-rw-r--r-- | libgcompat/math.c | 13 | ||||
-rw-r--r-- | libgcompat/readlink.c | 3 | ||||
-rw-r--r-- | libgcompat/realpath.c | 51 | ||||
-rw-r--r-- | libgcompat/resolv.c | 2 | ||||
-rw-r--r-- | libgcompat/socket.c | 2 | ||||
-rw-r--r-- | libgcompat/stdlib.c | 3 | ||||
-rw-r--r-- | libgcompat/string.c | 9 | ||||
-rw-r--r-- | libgcompat/unistd.c | 9 |
14 files changed, 177 insertions, 24 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ee9851d..edc96f5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,17 @@ Build system * Allow building against libucontext. +ctype +----- + +* Add __ctype_b. + + +cxx_thread +---------- + +* Add __cxa_thread_atexit_impl. + math ---- @@ -24,6 +35,14 @@ math * Add most __*_finite functions, courtesy of Elizabeth Myers. +readlink/realpath +----------------- + +* Intercept realpath as well as readlink. +* Report EIO on /proc read failure. +* Report ENOSYS on dlsym failure. + + resolv ------ @@ -36,6 +55,12 @@ socket * Add __poll_chk +stdlib +------ + +* Add secure_getenv alias to __secure_getenv. + + string ------ @@ -43,6 +68,11 @@ string * Add memfrob. * Add strfry. +unistd +------ + +* Add __open_2/__open64_2. + malloc ------ @@ -1,6 +1,8 @@ LIBGCOMPAT_INCLUDE = \ libgcompat/alias.h LIBGCOMPAT_SRC = \ + libgcompat/ctype.c \ + libgcompat/cxx_thread.c \ libgcompat/dlfcn.c \ libgcompat/error.c \ libgcompat/execinfo.c \ @@ -14,6 +16,7 @@ LIBGCOMPAT_SRC = \ libgcompat/pthread.c \ libgcompat/pwd.c \ libgcompat/readlink.c \ + libgcompat/realpath.c \ libgcompat/resolv.c \ libgcompat/resource.c \ libgcompat/setjmp.c \ diff --git a/libgcompat/ctype.c b/libgcompat/ctype.c new file mode 100644 index 0000000..1ae9877 --- /dev/null +++ b/libgcompat/ctype.c @@ -0,0 +1 @@ +const unsigned short int *__ctype_b; diff --git a/libgcompat/cxx_thread.c b/libgcompat/cxx_thread.c new file mode 100644 index 0000000..105e4c5 --- /dev/null +++ b/libgcompat/cxx_thread.c @@ -0,0 +1,56 @@ +#include <pthread.h> /* NULL, pthread_{key,once,{get,set}specific} */ +#include <stdlib.h> /* malloc, free */ + +#include "internal.h" + +struct dtor_node { + struct dtor_node *next; + void (*func)(void *); + void *obj; +}; + +static pthread_key_t key; +static pthread_once_t once = PTHREAD_ONCE_INIT; + +static void run_dtors(void *head) +{ + struct dtor_node *next, *node = head; + + while (node != NULL) { + next = node->next; + node->func(node->obj); + free(node); + node = next; + } +} + +static void create_key(void) +{ + int res = pthread_key_create(&key, run_dtors); + + GCOMPAT__assert_with_reason(res, "No key for thread_atexit list"); +} + +/** + * Register a destructor to run at thread exit. + * + * See + * https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables + */ +int __cxa_thread_atexit_impl(void (*func)(void *), void *obj, void *dso_symbol) +{ + struct dtor_node *node; + + pthread_once(&once, create_key); + + node = malloc(sizeof(*node)); + GCOMPAT__assert_with_reason(node, "No memory for thread_atexit node"); + node->next = pthread_getspecific(key); + node->func = func; + node->obj = obj; + + int res = pthread_setspecific(key, node); + GCOMPAT__assert_with_reason(!res, "Cannot update thread_atexit list"); + + return 0; +} diff --git a/libgcompat/gnulib.c b/libgcompat/gnulib.c index ccdec24..3f66963 100644 --- a/libgcompat/gnulib.c +++ b/libgcompat/gnulib.c @@ -1,16 +1,18 @@ #include <sys/select.h> #include "internal.h" -#define REASON_FD_SET_OVERFLOW \ - "Fault: Overflow in fd_set detected.\n" \ - "Description: This is caused by a programmer naively attempting to redefine FD_SETSIZE,\n" \ - " which is not allowed on POSIX platforms. The program must be either rebuilt\n" \ - " with the correct FD_SETSIZE definition, or preferably rewritten to avoid use\n" \ - " of select(2) in general. See also: poll(2).\n" \ +#define REASON_FD_SET_OVERFLOW \ + "Fault: Overflow in fd_set detected.\n" \ + "Description: This is caused by a programmer naively attempting to\n" \ + " redefine FD_SETSIZE, which is not allowed on POSIX platforms.\n" \ + " The program must either be rebuilt with the correct FD_SETSIZE\n" \ + " definition, or else be rewritten to avoid use of select(2) in \n" \ + " general. See also: poll(2).\n" \ " libgcompat believes FD_SETSIZE to be %zu.\n" unsigned long __fdelt_chk(unsigned long size) { - GCOMPAT__assert_with_reason(size < FD_SETSIZE, REASON_FD_SET_OVERFLOW, FD_SETSIZE); + GCOMPAT__assert_with_reason(size < FD_SETSIZE, REASON_FD_SET_OVERFLOW, + FD_SETSIZE); return size / (sizeof(unsigned long) << 3); } diff --git a/libgcompat/internal.c b/libgcompat/internal.c index 441b3cc..450c5e4 100644 --- a/libgcompat/internal.c +++ b/libgcompat/internal.c @@ -1,8 +1,7 @@ -#include <stdio.h> #include <stdarg.h> +#include <stdio.h> #include <stdlib.h> - void GCOMPAT__panic(const char *fmt, ...) { va_list va; diff --git a/libgcompat/math.c b/libgcompat/math.c index 83abbf4..793ff1a 100644 --- a/libgcompat/math.c +++ b/libgcompat/math.c @@ -1,8 +1,8 @@ -#define _GNU_SOURCE /* Extra maths functions */ -#include <math.h> /* Literally everything */ +#define _GNU_SOURCE /* Extra maths functions */ +#include <math.h> /* Literally everything */ -#include "alias.h" /* weak_alias */ -#include "internal.h" /* GCOMPAT__assert_with_reason */ +#include "alias.h" /* weak_alias */ +#include "internal.h" /* GCOMPAT__assert_with_reason */ /** * Multiplies the first argument x by FLT_RADIX (probably 2) to the power of y. @@ -14,7 +14,7 @@ long double scalbl(long double x, long double y) * 1) Good Enough(TM) * 2) scalbl is deprecated anyway * */ - return scalblnl(x, (long int)y); + return scalblnl(x, (long int) y); } /* @@ -144,7 +144,6 @@ int __isnan(double arg) } weak_alias(__isnan, isnan); - /** * Test for a NaN. * @@ -290,7 +289,6 @@ long double __asinl_finite(long double x) return res; } - /** * Returns the principal value of the arc tangent of x/y, expressed in radians. */ @@ -363,7 +361,6 @@ long double __atanhl_finite(long double x) return res; } - /** * Returns the hyperbolic cosine of x. */ diff --git a/libgcompat/readlink.c b/libgcompat/readlink.c index 63def96..9b3e2dd 100644 --- a/libgcompat/readlink.c +++ b/libgcompat/readlink.c @@ -1,4 +1,5 @@ #include <dlfcn.h> +#include <errno.h> #include <fcntl.h> #include <limits.h> #include <stddef.h> @@ -18,6 +19,7 @@ ssize_t readlink(const char *path, char *buf, size_t len) if (real_readlink == NULL) { real_readlink = dlsym(RTLD_NEXT, "readlink"); if (real_readlink == NULL) { + errno = ENOSYS; return -1; } } @@ -78,6 +80,7 @@ ssize_t readlink(const char *path, char *buf, size_t len) close(fd); fail: exe[0] = '\0'; + errno = EIO; return -1; } diff --git a/libgcompat/realpath.c b/libgcompat/realpath.c new file mode 100644 index 0000000..ab68cc4 --- /dev/null +++ b/libgcompat/realpath.c @@ -0,0 +1,51 @@ +#include <dlfcn.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifndef LINKER +#error LINKER must be defined +#endif + +static char *(*real_realpath)(const char *restrict, char *restrict); + +char *realpath(const char *restrict path, char *restrict resolved) +{ + if (real_realpath == NULL) { + real_realpath = dlsym(RTLD_NEXT, "realpath"); + if (real_realpath == NULL) { + errno = ENOSYS; + return NULL; + } + } + + if (!strcmp(path, "/proc/self/exe")) { + char *fixed = resolved; + + if (fixed == NULL) { + fixed = malloc(PATH_MAX); + if (fixed == NULL) { + errno = ENOMEM; + return NULL; + } + } + + /* If passed in, the buffer is at least PATH_MAX per POSIX. */ + ssize_t written = readlink(path, fixed, PATH_MAX - 1); + if (written == -1) { + /* Free the buffer iff we allocated it. */ + if (fixed != resolved) + free(fixed); + return NULL; + } + fixed[written] = '\0'; + + return fixed; + } + + return real_realpath(path, resolved); +} diff --git a/libgcompat/resolv.c b/libgcompat/resolv.c index f70d913..0b81d0c 100644 --- a/libgcompat/resolv.c +++ b/libgcompat/resolv.c @@ -42,7 +42,7 @@ int __res_nclose(res_state statp) weak_alias(__res_nclose, res_nclose); int __res_search(const char *dname, int class, int type, unsigned char *answer, - int anslen) + int anslen) { return res_search(dname, class, type, answer, anslen); } diff --git a/libgcompat/socket.c b/libgcompat/socket.c index 9919ee0..e56199e 100644 --- a/libgcompat/socket.c +++ b/libgcompat/socket.c @@ -1,6 +1,6 @@ #include <assert.h> /* assert */ +#include <poll.h> /* poll, pollfd, nfds_t */ #include <stddef.h> /* NULL */ -#include <poll.h> /* poll, pollfd, nfds_t */ #include <sys/socket.h> /* recv, recvfrom */ /** diff --git a/libgcompat/stdlib.c b/libgcompat/stdlib.c index a08f914..82f7602 100644 --- a/libgcompat/stdlib.c +++ b/libgcompat/stdlib.c @@ -5,6 +5,8 @@ #include <stdlib.h> /* getenv, realpath, strto* */ #include <unistd.h> /* get*id */ +#include "alias.h" + /** * Resolve a pathname, with buffer overflow checking. * @@ -30,6 +32,7 @@ char *__secure_getenv(const char *name) return getenv(name); } +weak_alias(__secure_getenv, secure_getenv); /** * Underlying function for strtod. diff --git a/libgcompat/string.c b/libgcompat/string.c index 9f1704b..f4e0620 100644 --- a/libgcompat/string.c +++ b/libgcompat/string.c @@ -2,10 +2,10 @@ #include <assert.h> /* assert */ #include <stddef.h> /* NULL, size_t */ #include <stdint.h> /* SIZE_MAX */ -#include <string.h> /* memcpy, strcpy, strncat, strndup */ #include <stdlib.h> /* rand_r */ -#include <unistd.h> /* getpid */ +#include <string.h> /* memcpy, strcpy, strncat, strndup */ #include <time.h> /* time */ +#include <unistd.h> /* getpid */ #include "alias.h" /* weak_alias */ @@ -189,8 +189,7 @@ size_t __strcspn_c2(const char *str, int bad, int bad2) { size_t length = 0; const char *s = str; - while(*s != bad && *s != bad2 && *s != '\0') - { + while (*s != bad && *s != bad2 && *s != '\0') { length++; s++; } @@ -285,7 +284,7 @@ char *strfry(char *s) if (!len) return s; - seed += time(NULL) ^ getpid() ^ (uintptr_t)s; + seed += time(NULL) ^ getpid() ^ (uintptr_t) s; for (i = 0; i < len - 1; ++i) { j = rand_r(&seed) % (len - i) + i; diff --git a/libgcompat/unistd.c b/libgcompat/unistd.c index e19ec8e..d2f3097 100644 --- a/libgcompat/unistd.c +++ b/libgcompat/unistd.c @@ -1,4 +1,5 @@ #include <assert.h> /* assert */ +#include <fcntl.h> /* O_CREAT */ #include <limits.h> /* NGROUPS_MAX */ #include <stddef.h> /* NULL, size_t */ #include <unistd.h> /* confstr, getcwd, getgroups, ... */ @@ -90,6 +91,14 @@ pid_t __getpgid(pid_t pid) return getpgid(pid); } +int __open_2(const char *path, int oflag) +{ + assert(!(oflag & O_CREAT)); + + return open(path, oflag); +} +alias(__open_2, __open64_2); + /** * Read from a file, with buffer overflow checking. * |