aboutsummaryrefslogtreecommitdiffstats
path: root/pseudo_wrappers.c
diff options
context:
space:
mode:
authorPeter Seebach <peter.seebach@windriver.com>2011-06-09 10:53:32 -0500
committerPeter Seebach <peter.seebach@windriver.com>2011-06-09 10:53:32 -0500
commitc2f7c5ad8ef0f9c94a2a8382c109c8c6e16c8b18 (patch)
tree75f4147dfe46e532872c047344e7e6f0ff4858ee /pseudo_wrappers.c
parent1d3e67cb168c3459e67a0b29f071ca30ed17dadc (diff)
downloadpseudo-c2f7c5ad8ef0f9c94a2a8382c109c8c6e16c8b18.tar.gz
pseudo-c2f7c5ad8ef0f9c94a2a8382c109c8c6e16c8b18.tar.bz2
pseudo-c2f7c5ad8ef0f9c94a2a8382c109c8c6e16c8b18.zip
Fix realpath(name, NULL) when PSEUDO_DISABLED=1
On some Linux systems, dlsym("realpath", RTLD_NEXT) prefers for reasons of its own to give a symbol that is also known as old_realpath, which fails and yields EINVAL when called with a null pointer as the second argument. This can be avoided, on some systems, by using dlvsym() to request the GLIBC_2.3 version of the symbol. The wrapper logic is enhanced to allow for specifying versions, although this currently only works for Linux (Darwin has no dlvsym, apparently?). The test case is a trivial program which calls realpath(name, NULL) run with PSEUDO_DISABLED=1.
Diffstat (limited to 'pseudo_wrappers.c')
-rw-r--r--pseudo_wrappers.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/pseudo_wrappers.c b/pseudo_wrappers.c
index 600a918..07a4429 100644
--- a/pseudo_wrappers.c
+++ b/pseudo_wrappers.c
@@ -90,6 +90,42 @@ pseudo_reinit_libpseudo(void) {
_libpseudo_init();
}
+static void
+pseudo_init_one_wrapper(pseudo_function *func) {
+ int (*f)(void);
+ char *e;
+ if (*func->real != NULL) {
+ /* already initialized */
+ return;
+ }
+ dlerror();
+
+#if PSEUDO_PORT_LINUX
+ if (func->version)
+ f = dlvsym(RTLD_NEXT, func->name, func->version);
+ /* fall through to the general case, if that failed */
+ if (!f)
+#endif
+ f = dlsym(RTLD_NEXT, func->name);
+ if (f) {
+ *func->real = f;
+ } else {
+ e = dlerror();
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ char *s = func->name;
+ s += strlen(s) - 2;
+ /* *at() don't have to exist */
+ if (!strcmp(s, "at")) {
+ continue;
+ }
+#else
+ if (e != NULL) {
+ pseudo_diag("No real function for %s: %s\n", func->name, e);
+ }
+#endif
+ }
+}
+
void
pseudo_init_wrappers(void) {
int i;
@@ -103,29 +139,7 @@ pseudo_init_wrappers(void) {
*/
if (!done) {
for (i = 0; pseudo_functions[i].name; ++i) {
- if (*pseudo_functions[i].real == NULL) {
- int (*f)(void);
- char *e;
- dlerror();
- f = dlsym(RTLD_NEXT, pseudo_functions[i].name);
- if (f) {
- *pseudo_functions[i].real = f;
- } else {
- e = dlerror();
-#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
- char *s = pseudo_functions[i].name;
- s += strlen(s) - 2;
- /* *at() don't have to exist */
- if (!strcmp(s, "at")) {
- continue;
- }
-#else
- if (e != NULL) {
- pseudo_diag("No real function for %s: %s\n", pseudo_functions[i].name, e);
- }
-#endif
- }
- }
+ pseudo_init_one_wrapper(&pseudo_functions[i]);
}
done = 1;
}