aboutsummaryrefslogtreecommitdiffstats
path: root/pseudo_util.c
diff options
context:
space:
mode:
authorPeter Seebach <peter.seebach@windriver.com>2011-03-25 12:38:43 -0500
committerPeter Seebach <peter.seebach@windriver.com>2011-03-25 12:38:43 -0500
commit29e8b8a4cd8f7383c3d851b6255272f1c2a5d286 (patch)
treec9619032a670d06124ef45c392484f4a04f7d0f0 /pseudo_util.c
parent96d8e7ce8b483e5cafd0449b9735e4714f41f20b (diff)
downloadpseudo-29e8b8a4cd8f7383c3d851b6255272f1c2a5d286.tar.gz
pseudo-29e8b8a4cd8f7383c3d851b6255272f1c2a5d286.tar.bz2
pseudo-29e8b8a4cd8f7383c3d851b6255272f1c2a5d286.zip
Merge in ports work
This is a spiffied-up rebase of a bunch of intermediate changes, presented as a whole because it is, surprisingly, less confusing that way. The basic idea is to separate the guts code into categories ranging from generic stuff that can be the same everywhere and specific variants. The big scary one is the Darwin support, which actually seems to run okay on 64-bit OS X 10.6. (No other variants were tested.) The other example given is support for the old clone() syscall on RHEL 4, which affects some wrlinux use cases. There's a few minor cleanup bits here, such as a function with inconsistent calling conventions, but nothing really exciting.
Diffstat (limited to 'pseudo_util.c')
-rw-r--r--pseudo_util.c255
1 files changed, 190 insertions, 65 deletions
diff --git a/pseudo_util.c b/pseudo_util.c
index 704655e..d19bd0c 100644
--- a/pseudo_util.c
+++ b/pseudo_util.c
@@ -204,7 +204,7 @@ static ssize_t pseudo_sys_max_pathlen = -1;
* libc.so -- this forces rebuilds of the library when the C library
* changes. The problem is that the pseudo binary may be
* a prebuilt, in which case it doesn't know about CHECKSUM, so it
- * has to determine whether a given LD_PRELOAD contains libpseudo.so
+ * has to determine whether a given PRELINK_LIBRARIES contains libpseudo.so
* or libpseudoCHECKSUM.so, without prior knowledge... Fancy!
*
* We search for anything matching libpseudo*.so, where * is any
@@ -213,9 +213,13 @@ static ssize_t pseudo_sys_max_pathlen = -1;
* the end of the string or a space after it.
*/
static char *libpseudo_name = "libpseudo.so";
-static char *libpseudo_pattern = "(^|=| )libpseudo[^ ]*\\.so($| )";
+/* this used to look for a "libpseudo*.so", but it turns out you can
+ * specify a path even on Linux.
+ */
+static char *libpseudo_pattern = "(^|=| )[^ ]*libpseudo[^ ]*\\.so($| )";
static regex_t libpseudo_regex;
static int libpseudo_regex_compiled = 0;
+
/* Okay, so, there's a funny story behind this. On one of the systems
* we need to run on, /usr/bin/find happens to provide its own
* definitions of regcomp and regexec which are INCOMPATIBLE with the
@@ -226,8 +230,13 @@ static int libpseudo_regex_compiled = 0;
* no one called us from a program with incompatible variants.
*
*/
+#if PSEUDO_PORT_LINUX
static int (*real_regcomp)(regex_t *__restrict __preg, const char *__restrict __pattern, int __cflags);
static int (*real_regexec)(const regex_t *__restrict __preg, const char *__restrict __string, size_t __nmatch, regmatch_t __pmatch[__restrict_arr], int __eflags);
+#else
+#define real_regcomp regcomp
+#define real_regexec regexec
+#endif /* PSEUDO_PORT_LINUX */
static int
libpseudo_regex_init(void) {
@@ -235,20 +244,22 @@ libpseudo_regex_init(void) {
if (libpseudo_regex_compiled)
return 0;
+#if PSEUDO_PORT_LINUX
real_regcomp = dlsym(RTLD_NEXT, "regcomp");
if (!real_regcomp)
real_regcomp = regcomp;
real_regexec = dlsym(RTLD_NEXT, "regexec");
if (!real_regexec)
real_regexec = regexec;
+#endif
rc = (*real_regcomp)(&libpseudo_regex, libpseudo_pattern, REG_EXTENDED);
if (rc == 0)
libpseudo_regex_compiled = 1;
return rc;
}
-/* given a space-separated list of files, ala LD_PRELOAD, return that
- * list without any variants of libpseudo*.so.
+/* given a space-or-colon-separated list of files, ala PRELINK_LIBRARIES,
+ # return that list without any variants of libpseudo*.so.
*/
static char *
without_libpseudo(char *list) {
@@ -259,7 +270,7 @@ without_libpseudo(char *list) {
if (libpseudo_regex_init())
return NULL;
- if (list[0] == '=' || list[0] == ' ')
+ if (list[0] == '=' || list[0] == PSEUDO_LINKPATH_SEPARATOR[0])
skip_start = 1;
if ((*real_regexec)(&libpseudo_regex, list, 1, pmatch, 0)) {
@@ -282,20 +293,42 @@ without_libpseudo(char *list) {
}
static char *
-with_libpseudo(char *list) {
+with_libpseudo(char *list, char *libdir_path) {
regmatch_t pmatch[1];
+
if (libpseudo_regex_init())
return NULL;
if ((*real_regexec)(&libpseudo_regex, list, 1, pmatch, 0)) {
+ size_t len;
+#if PSEUDO_PORT_DARWIN
+ /* <%s:%s/%s\0> */
+ len = strlen(list) + 1 + strlen(libdir_path) + 1 + strlen(libpseudo_name) + 1;
+#else
+ /* suppress warning */
+ (void) libdir_path;
/* <%s %s\0> */
- size_t len = strlen(list) + 1 + strlen(libpseudo_name) + 1;
+ len = strlen(list) + 1 + strlen(libpseudo_name) + 1;
+#endif
char *new = malloc(len);
- if (new)
- snprintf(new, len, "%s %s", list,
+ if (new) {
+ /* insert space only if there were previous bits */
+ /* on Darwin, we have to provide the full path to
+ * libpseudo
+ */
+#if PSEUDO_PORT_DARWIN
+ snprintf(new, len, "%s%s%s/%s", list,
+ *list ? PSEUDO_LINKPATH_SEPARATOR : "",
+ libdir_path ? libdir_path : "",
libpseudo_name);
+#else
+ snprintf(new, len, "%s%s%s", list,
+ *list ? PSEUDO_LINKPATH_SEPARATOR : "",
+ libpseudo_name);
+#endif
+ }
return new;
} else {
- return list;
+ return strdup(list);
}
}
@@ -399,7 +432,7 @@ pseudo_append_element(char **pnewpath, char **proot, size_t *pallocated, char **
static int link_recursion = 0;
size_t curlen, allocated;
char *newpath, *current, *root;
- struct stat64 buf;
+ struct stat buf;
if (!pnewpath || !*pnewpath ||
!pcurrent || !*pcurrent ||
!proot || !*proot ||
@@ -461,7 +494,7 @@ pseudo_append_element(char **pnewpath, char **proot, size_t *pallocated, char **
/* if lstat fails, that's fine -- nonexistent files aren't symlinks */
if (!leave_this) {
int is_link;
- is_link = (lstat64(newpath, &buf) != -1) && S_ISLNK(buf.st_mode);
+ is_link = (lstat(newpath, &buf) != -1) && S_ISLNK(buf.st_mode);
if (link_recursion >= PSEUDO_MAX_LINK_RECURSION && is_link) {
pseudo_diag("link recursion too deep, not expanding path '%s'.\n", newpath);
is_link = 0;
@@ -621,17 +654,19 @@ pseudo_fix_path(const char *base, const char *path, size_t rootlen, size_t basel
* we don't try to fix the library path.
*/
void pseudo_dropenv() {
- char * ld_preload = getenv("LD_PRELOAD");
+ char *ld_preload = getenv(PRELINK_LIBRARIES);
if (ld_preload) {
ld_preload = without_libpseudo(ld_preload);
if (!ld_preload) {
- pseudo_diag("fatal: can't allocate new LD_PRELOAD variable.\n");
+ pseudo_diag("fatal: can't allocate new %s variable.\n", PRELINK_LIBRARIES);
+ }
+ if (ld_preload && strlen(ld_preload)) {
+ pseudo_diag("ld_preload without: <%s>\n", ld_preload);
+ setenv(PRELINK_LIBRARIES, ld_preload, 1);
+ } else {
+ unsetenv(PRELINK_LIBRARIES);
}
- if (ld_preload && strlen(ld_preload))
- setenv("LD_PRELOAD", ld_preload, 1);
- else
- unsetenv("LD_PRELOAD");
}
}
@@ -650,15 +685,15 @@ pseudo_dropenvp(char * const *envp) {
j = 0;
for (i = 0; envp[i]; ++i) {
- if (STARTSWITH(envp[i], "LD_PRELOAD=")) {
+ if (STARTSWITH(envp[i], PRELINK_LIBRARIES "=")) {
char *new_val = without_libpseudo(envp[i]);
if (!new_val) {
pseudo_diag("fatal: can't allocate new environment variable.\n");
return 0;
} else {
/* don't keep an empty value; if the whole string is
- * LD_PRELOAD=, we just drop it. */
- if (strcmp(new_val, "LD_PRELOAD=")) {
+ * PRELINK_LIRBARIES=, we just drop it. */
+ if (strcmp(new_val, PRELINK_LIBRARIES "=")) {
new_envp[j++] = new_val;
}
}
@@ -690,40 +725,58 @@ pseudo_setupenv() {
i++;
}
- char * ld_preload = getenv("LD_PRELOAD");
- if (ld_preload) {
- ld_preload = with_libpseudo(ld_preload);
- if (!ld_preload) {
- pseudo_diag("fatal: can't allocate new LD_PRELOAD variable.\n");
- }
- setenv("LD_PRELOAD", ld_preload, 1);
- } else {
- setenv("LD_PRELOAD", libpseudo_name, 1);
- }
-
- const char *ld_library_path = getenv("LD_LIBRARY_PATH");
- char * libdir_path = pseudo_libdir_path(NULL);
+ const char *ld_library_path = getenv(PRELINK_PATH);
+ char *libdir_path = pseudo_libdir_path(NULL);
if (!ld_library_path) {
size_t len = strlen(libdir_path) + 1 + (strlen(libdir_path) + 2) + 1;
char *newenv = malloc(len);
if (!newenv) {
- pseudo_diag("fatal: can't allocate new LD_LIBRARY_PATH variable.\n");
+ pseudo_diag("fatal: can't allocate new %s variable.\n", PRELINK_PATH);
}
snprintf(newenv, len, "%s:%s64", libdir_path, libdir_path);
- setenv("LD_LIBRARY_PATH", newenv, 1);
+ setenv(PRELINK_PATH, newenv, 1);
} else if (!strstr(ld_library_path, libdir_path)) {
size_t len = strlen(ld_library_path) + 1 + strlen(libdir_path) + 1 + (strlen(libdir_path) + 2) + 1;
char *newenv = malloc(len);
if (!newenv) {
- pseudo_diag("fatal: can't allocate new LD_LIBRARY_PATH variable.\n");
+ pseudo_diag("fatal: can't allocate new %s variable.\n", PRELINK_PATH);
}
snprintf(newenv, len, "%s:%s:%s64", ld_library_path, libdir_path, libdir_path);
- setenv("LD_LIBRARY_PATH", newenv, 1);
+ setenv(PRELINK_PATH, newenv, 1);
} else {
/* nothing to do, ld_library_path exists and contains
* our preferred path */
}
+
+ char *ld_preload = getenv(PRELINK_LIBRARIES);
+ if (ld_preload) {
+ ld_preload = with_libpseudo(ld_preload, libdir_path);
+ if (!ld_preload) {
+ pseudo_diag("fatal: can't allocate new %s variable.\n", PRELINK_LIBRARIES);
+ }
+ setenv(PRELINK_LIBRARIES, ld_preload, 1);
+ free(ld_preload);
+ } else {
+ ld_preload = with_libpseudo("", libdir_path);
+ if (!ld_preload) {
+ pseudo_diag("fatal: can't allocate new %s variable.\n", PRELINK_LIBRARIES);
+ }
+ setenv(PRELINK_LIBRARIES, ld_preload, 1);
+ free(ld_preload);
+ }
+
+ /* we kept libdir path until now because with_libpseudo might
+ * need it
+ */
free(libdir_path);
+
+
+#if PSEUDO_PORT_DARWIN
+ char *force_flat = getenv("DYLD_FORCE_FLAT_NAMESPACE");
+ if (!force_flat) {
+ setenv("DYLD_FORCE_FLAT_NAMESPACE", "1", 1);
+ }
+#endif
}
/* add pseudo stuff to the environment.
@@ -751,10 +804,10 @@ pseudo_setupenvp(char * const *envp) {
free(pseudo_get_localstatedir());
for (i = 0; envp[i]; ++i) {
- if (STARTSWITH(envp[i], "LD_PRELOAD=")) {
+ if (STARTSWITH(envp[i], PRELINK_LIBRARIES "=")) {
ld_preload = envp[i];
}
- if (STARTSWITH(envp[i], "LD_LIBRARY_PATH=")) {
+ if (STARTSWITH(envp[i], PRELINK_PATH "=")) {
ld_library_path = envp[i];
}
++env_count;
@@ -773,33 +826,20 @@ pseudo_setupenvp(char * const *envp) {
return NULL;
}
- if (ld_preload) {
- ld_preload = with_libpseudo(ld_preload);
- if (!ld_preload) {
- pseudo_diag("fatal: can't allocate new LD_PRELOAD variable.\n");
- }
- new_envp[j++] = ld_preload;
- } else {
- size_t len = strlen("LD_PRELOAD=") + strlen(libpseudo_name) + 1;
- char *newenv = malloc(len);
- snprintf(newenv, len, "LD_PRELOAD=%s", libpseudo_name);
- new_envp[j++] = newenv;
- }
-
char *libdir_path = pseudo_libdir_path(NULL);
if (!ld_library_path) {
- size_t len = strlen("LD_LIBRARY_PATH=") + strlen(libdir_path) + 1 + (strlen(libdir_path) + 2) + 1;
+ size_t len = strlen(PRELINK_PATH "=") + strlen(libdir_path) + 1 + (strlen(libdir_path) + 2) + 1;
char *newenv = malloc(len);
if (!newenv) {
- pseudo_diag("fatal: can't allocate new LD_LIBRARY_PATH variable.\n");
+ pseudo_diag("fatal: can't allocate new %s variable.\n", PRELINK_PATH);
}
- snprintf(newenv, len, "LD_LIBRARY_PATH=%s:%s64", libdir_path, libdir_path);
+ snprintf(newenv, len, PRELINK_PATH "=%s:%s64", libdir_path, libdir_path);
new_envp[j++] = newenv;
} else if (!strstr(ld_library_path, libdir_path)) {
size_t len = strlen(ld_library_path) + 1 + strlen(libdir_path) + 1 + (strlen(libdir_path) + 2) + 1;
char *newenv = malloc(len);
if (!newenv) {
- pseudo_diag("fatal: can't allocate new LD_LIBRARY_PATH variable.\n");
+ pseudo_diag("fatal: can't allocate new %s variable.\n", PRELINK_PATH);
}
snprintf(newenv, len, "%s:%s:%s64", ld_library_path, libdir_path, libdir_path);
new_envp[j++] = newenv;
@@ -807,11 +847,27 @@ pseudo_setupenvp(char * const *envp) {
/* keep old value */
new_envp[j++] = ld_library_path;
}
+
+ if (ld_preload) {
+ ld_preload = with_libpseudo(ld_preload, libdir_path);
+ if (!ld_preload) {
+ pseudo_diag("fatal: can't allocate new %s variable.\n", PRELINK_LIBRARIES);
+ }
+ new_envp[j++] = ld_preload;
+ } else {
+ ld_preload = with_libpseudo("", libdir_path);
+ size_t len = strlen(PRELINK_LIBRARIES "=") + strlen(ld_preload) + 1;
+ char *newenv = malloc(len);
+ snprintf(newenv, len, PRELINK_LIBRARIES "=%s", ld_preload);
+ new_envp[j++] = newenv;
+ free(ld_preload);
+ }
+
free(libdir_path);
for (i = 0; envp[i]; ++i) {
- if (STARTSWITH(envp[i], "LD_PRELOAD=")) continue;
- if (STARTSWITH(envp[i], "LD_LIBRARY_PATH=")) continue;
+ if (STARTSWITH(envp[i], PRELINK_LIBRARIES "=")) continue;
+ if (STARTSWITH(envp[i], PRELINK_PATH "=")) continue;
new_envp[j++] = envp[i];
}
@@ -892,7 +948,7 @@ pseudo_prefix_path(char *file) {
char *
pseudo_bindir_path(char *file) {
char * rc;
- char * bindir = pseudo_get_bindir(NULL);
+ char * bindir = pseudo_get_bindir();
if (!bindir) {
pseudo_diag("You must set the PSEUDO_BINDIR environment variable to run pseudo.\n");
@@ -909,7 +965,7 @@ pseudo_bindir_path(char *file) {
char *
pseudo_libdir_path(char *file) {
char * rc;
- char * libdir = pseudo_get_libdir(NULL);
+ char * libdir = pseudo_get_libdir();
if (!libdir) {
pseudo_diag("You must set the PSEUDO_LIBDIR environment variable to run pseudo.\n");
@@ -926,7 +982,7 @@ pseudo_libdir_path(char *file) {
char *
pseudo_localstatedir_path(char *file) {
char * rc;
- char * localstatedir = pseudo_get_localstatedir(NULL);
+ char * localstatedir = pseudo_get_localstatedir();
if (!localstatedir) {
pseudo_diag("You must set the PSEUDO_LOCALSTATEDIR environment variable to run pseudo.\n");
@@ -996,7 +1052,7 @@ pseudo_get_prefix(char *pathname) {
}
char *
-pseudo_get_bindir() {
+pseudo_get_bindir(void) {
char *s = pseudo_get_value("PSEUDO_BINDIR");
if (!s) {
char *pseudo_bindir = pseudo_prefix_path(PSEUDO_BINDIR);;
@@ -1009,15 +1065,19 @@ pseudo_get_bindir() {
}
char *
-pseudo_get_libdir() {
+pseudo_get_libdir(void) {
char *s = pseudo_get_value("PSEUDO_LIBDIR");
if (!s) {
- char *pseudo_libdir = pseudo_prefix_path(PSEUDO_LIBDIR);
+ char *pseudo_libdir;
+ pseudo_libdir = pseudo_prefix_path(PSEUDO_LIBDIR);
if (pseudo_libdir) {
pseudo_set_value("PSEUDO_LIBDIR", pseudo_libdir);
s = pseudo_libdir;
}
}
+#if PSEUDO_PORT_DARWIN
+ /* on Darwin, we need lib64, because dyld won't search */
+#else
/* If we somehow got lib64 in there, clean it down to just lib... */
if (s) {
size_t len = strlen(s);
@@ -1026,6 +1086,7 @@ pseudo_get_libdir() {
pseudo_set_value("PSEUDO_LIBDIR", s);
}
}
+#endif
return s;
}
@@ -1144,6 +1205,23 @@ pseudo_access_fopen(const char *mode) {
* - /etc/<file>
*/
+#if PSEUDO_PORT_DARWIN
+/* on Darwin, you can't just use /etc/passwd for system lookups,
+ * you have to use the real library calls because they know about
+ * Directory Services. So...
+ *
+ * We make up fake fds and FILE * objects that can't possibly be
+ * valid.
+ */
+int pseudo_host_etc_passwd_fd = -3;
+int pseudo_host_etc_group_fd = -4;
+static FILE pseudo_fake_passwd_file;
+static FILE pseudo_fake_group_file;
+FILE *pseudo_host_etc_passwd_file = &pseudo_fake_passwd_file;
+FILE *pseudo_host_etc_group_file = &pseudo_fake_group_file;
+
+#endif
+
int
pseudo_etc_file(const char *file, char *realname, int flags, char **search_dirs, int dircount) {
char filename[pseudo_path_max()];
@@ -1181,6 +1259,15 @@ pseudo_etc_file(const char *file, char *realname, int flags, char **search_dirs,
} else {
pseudo_debug(2, "pseudo_etc_file: no search dirs.\n");
}
+#if PSEUDO_PORT_DARWIN
+ if (!strcmp("passwd", file)) {
+ pseudo_debug(2, "Darwin hackery: pseudo_etc_passwd returning magic passwd fd\n");
+ return pseudo_host_etc_passwd_fd;
+ } else if (!strcmp("group", file)) {
+ pseudo_debug(2, "Darwin hackery: pseudo_etc_passwd returning magic group fd\n");
+ return pseudo_host_etc_group_fd;
+ }
+#endif
snprintf(filename, pseudo_path_max(), "/etc/%s", file);
pseudo_debug(2, "falling back on <%s> for <%s>\n",
filename, file);
@@ -1200,7 +1287,11 @@ pseudo_logfile(char *defname) {
char *pseudo_path;
char *filename = pseudo_get_value("PSEUDO_DEBUG_FILE");
char *s;
+#if PSEUDO_PORT_LINUX
extern char *program_invocation_short_name; /* glibcism */
+#else
+ char *program_invocation_short_name = "unknown";
+#endif
int fd;
if (!filename) {
@@ -1288,3 +1379,37 @@ pseudo_logfile(char *defname) {
else
return 0;
}
+
+void
+pseudo_stat32_from64(struct stat *buf32, const struct stat64 *buf) {
+ buf32->st_dev = buf->st_dev;
+ buf32->st_ino = buf->st_ino;
+ buf32->st_mode = buf->st_mode;
+ buf32->st_nlink = buf->st_nlink;
+ buf32->st_uid = buf->st_uid;
+ buf32->st_gid = buf->st_gid;
+ buf32->st_rdev = buf->st_rdev;
+ buf32->st_size = buf->st_size;
+ buf32->st_blksize = buf->st_blksize;
+ buf32->st_blocks = buf->st_blocks;
+ buf32->st_atime = buf->st_atime;
+ buf32->st_mtime = buf->st_mtime;
+ buf32->st_ctime = buf->st_ctime;
+}
+
+void
+pseudo_stat64_from32(struct stat64 *buf64, const struct stat *buf) {
+ buf64->st_dev = buf->st_dev;
+ buf64->st_ino = buf->st_ino;
+ buf64->st_mode = buf->st_mode;
+ buf64->st_nlink = buf->st_nlink;
+ buf64->st_uid = buf->st_uid;
+ buf64->st_gid = buf->st_gid;
+ buf64->st_rdev = buf->st_rdev;
+ buf64->st_size = buf->st_size;
+ buf64->st_blksize = buf->st_blksize;
+ buf64->st_blocks = buf->st_blocks;
+ buf64->st_atime = buf->st_atime;
+ buf64->st_mtime = buf->st_mtime;
+ buf64->st_ctime = buf->st_ctime;
+}