From 791532b0ce833614910d1d405c0238938408bd6b Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Thu, 6 Jun 2013 11:06:55 +0200 Subject: dracut-install: install libs also from one dir above some HW has different flavors of basic libs $ ldconfig -p|fgrep libc.so libc.so.6 (libc6,64bit, hwcap: 0x0000001000000000, OS ABI: Linux 2.6.32) => /lib64/power6/libc.so.6 libc.so.6 (libc6,64bit, hwcap: 0x0000000000000200, OS ABI: Linux 2.6.32) => /lib64/power6x/libc.so.6 libc.so.6 (libc6,64bit, OS ABI: Linux 2.6.32) => /lib64/libc.so.6 because setting LD_HWCAP_MASK=0 does not work, we have to workaround this. $ LD_TRACE_LOADED_OBJECTS=1 LD_HWCAP_MASK=0 /lib64/ld64.so.1 /bin/sh | fgrep libc.so libc.so.6 => /lib64/power6/libc.so.6 (0x000000804e260000) Now we try to install the same library from one directory above the one we installed also. --- install/dracut-install.c | 89 ++++++++++++++++++++++++++++++++++++---------- install/util.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ install/util.h | 2 ++ 3 files changed, 164 insertions(+), 19 deletions(-) diff --git a/install/dracut-install.c b/install/dracut-install.c index a1c64619..6b9c613b 100644 --- a/install/dracut-install.c +++ b/install/dracut-install.c @@ -254,6 +254,72 @@ static int cp(const char *src, const char *dst) return ret; } +static int library_install(const char *src, const char *lib) +{ + _cleanup_free_ char *p = NULL; + _cleanup_free_ char *pdir = NULL, *ppdir = NULL, *clib = NULL; + char *q; + int r, ret = 0; + + p = strdup(lib); + + r = dracut_install(p, p, false, false, true); + if (r != 0) + log_error("ERROR: failed to install '%s' for '%s'", p, src); + else + log_debug("Lib install: '%s'", p); + ret += r; + + /* also install lib.so for lib.so.* files */ + q = strstr(p, ".so."); + if (q) { + q[3] = '\0'; + + /* ignore errors for base lib symlink */ + if (dracut_install(p, p, false, false, true) == 0) + log_debug("Lib install: '%s'", p); + } + + /* Also try to install the same library from one directory above. + This fixes the case, where only the HWCAP lib would be installed + # ldconfig -p|fgrep libc.so + libc.so.6 (libc6,64bit, hwcap: 0x0000001000000000, OS ABI: Linux 2.6.32) => /lib64/power6/libc.so.6 + libc.so.6 (libc6,64bit, hwcap: 0x0000000000000200, OS ABI: Linux 2.6.32) => /lib64/power6x/libc.so.6 + libc.so.6 (libc6,64bit, OS ABI: Linux 2.6.32) => /lib64/libc.so.6 + */ + + free(p); + p = strdup(lib); + + pdir = dirname(p); + if (!pdir) + return ret; + + pdir = strdup(pdir); + ppdir = dirname(pdir); + if (!ppdir) + return ret; + + ppdir = strdup(ppdir); + + strcpy(p, lib); + + clib = strjoin(ppdir, "/", basename(p), NULL); + if (dracut_install(clib, clib, false, false, true) == 0) + log_debug("Lib install: '%s'", clib); + /* also install lib.so for lib.so.* files */ + q = strstr(clib, ".so."); + if (q) { + q[3] = '\0'; + + /* ignore errors for base lib symlink */ + if (dracut_install(clib, clib, false, false, true) == 0) + log_debug("Lib install: '%s'", p); + } + + return ret; +} + static int resolve_deps(const char *src) { int ret = 0; @@ -325,28 +391,13 @@ static int resolve_deps(const char *src) if (strstr(buf, destrootdir)) break; - p = strstr(buf, "/"); + p = strchr(buf, '/'); if (p) { - int r; for (q = p; *q && *q != ' ' && *q != '\n'; q++) ; *q = '\0'; - r = dracut_install(p, p, false, false, true); - if (r != 0) - log_error("ERROR: failed to install '%s' for '%s'", p, src); - else - log_debug("Lib install: '%s'", p); - ret += r; - - /* also install lib.so for lib.so.* files */ - q = strstr(p, ".so."); - if (q) { - q += 3; - *q = '\0'; - - /* ignore errors for base lib symlink */ - if (dracut_install(p, p, false, false, true) == 0) - log_debug("Lib install: '%s'", p); - } + + ret += library_install(src, p); + } } diff --git a/install/util.c b/install/util.c index 0247184b..9aa131f8 100644 --- a/install/util.c +++ b/install/util.c @@ -185,3 +185,95 @@ static const char *const log_level_table[] = { }; DEFINE_STRING_TABLE_LOOKUP(log_level, int); + +char *strnappend(const char *s, const char *suffix, size_t b) { + size_t a; + char *r; + + if (!s && !suffix) + return strdup(""); + + if (!s) + return strndup(suffix, b); + + if (!suffix) + return strdup(s); + + assert(s); + assert(suffix); + + a = strlen(s); + if (b > ((size_t) -1) - a) + return NULL; + + r = new(char, a+b+1); + if (!r) + return NULL; + + memcpy(r, s, a); + memcpy(r+a, suffix, b); + r[a+b] = 0; + + return r; +} + +char *strappend(const char *s, const char *suffix) { + return strnappend(s, suffix, suffix ? strlen(suffix) : 0); +} + +char *strjoin(const char *x, ...) { + va_list ap; + size_t l; + char *r, *p; + + va_start(ap, x); + + if (x) { + l = strlen(x); + + for (;;) { + const char *t; + size_t n; + + t = va_arg(ap, const char *); + if (!t) + break; + + n = strlen(t); + if (n > ((size_t) -1) - l) { + va_end(ap); + return NULL; + } + + l += n; + } + } else + l = 0; + + va_end(ap); + + r = new(char, l+1); + if (!r) + return NULL; + + if (x) { + p = stpcpy(r, x); + + va_start(ap, x); + + for (;;) { + const char *t; + + t = va_arg(ap, const char *); + if (!t) + break; + + p = stpcpy(p, t); + } + + va_end(ap); + } else + r[0] = 0; + + return r; +} diff --git a/install/util.h b/install/util.h index e86b2f2a..3d7c2320 100644 --- a/install/util.h +++ b/install/util.h @@ -560,4 +560,6 @@ bool in_initrd(void); void warn_melody(void); +char *strjoin(const char *x, ...) _sentinel_; + #endif -- cgit v1.2.3