summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarald Hoyer <harald@redhat.com>2013-06-06 11:06:55 +0200
committerHarald Hoyer <harald@redhat.com>2013-06-06 11:06:55 +0200
commit791532b0ce833614910d1d405c0238938408bd6b (patch)
tree87c5b2b1e2baf063f7622811ad75ddae0a4546d2
parentad4502441632690954df4ccb05149eba3e4f7b2f (diff)
downloaddracut-791532b0ce833614910d1d405c0238938408bd6b.tar.gz
dracut-791532b0ce833614910d1d405c0238938408bd6b.tar.bz2
dracut-791532b0ce833614910d1d405c0238938408bd6b.zip
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.
-rw-r--r--install/dracut-install.c89
-rw-r--r--install/util.c92
-rw-r--r--install/util.h2
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