[Rpm-maint] [PATCH 3/3] Add new helper to search for dependencies in the libraries
Alexey Gladkov
gladkov.alexey at gmail.com
Mon Nov 22 13:50:56 UTC 2010
The helper generates depends not on all files, but only for
those which are found in certain directories. Helpers checks the
configuration of ldconfig, standart directories %_libdir and /%lib,
and directories in the RPM_FINDPROV_LIB_PATH variable.
Signed-off-by: Alexey Gladkov <gladkov.alexey at gmail.com>
---
Makefile.am | 4 +
fileattrs/elf.attr | 3 +-
fileattrs/elflib.attr | 3 +
scripts/Makefile.am | 4 +-
scripts/libdeps.in | 28 +++++
tools/dump_ld_config.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 329 insertions(+), 3 deletions(-)
create mode 100644 fileattrs/elflib.attr
create mode 100755 scripts/libdeps.in
create mode 100644 tools/dump_ld_config.c
diff --git a/Makefile.am b/Makefile.am
index d5be498..5ad84d4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -159,6 +159,10 @@ elfdeps_LDADD += @WITH_LIBELF_LIB@ @WITH_POPT_LIB@
endif
endif
+rpmlibexec_PROGRAMS += dump_ld_config
+dump_ld_config_SOURCES = tools/dump_ld_config.c
+dump_ld_config_LDADD =
+
rpmlibexec_PROGRAMS += javadeps
javadeps_SOURCES = tools/javadeps.c
javadeps_LDADD =
diff --git a/fileattrs/elf.attr b/fileattrs/elf.attr
index fba180b..7a82abe 100644
--- a/fileattrs/elf.attr
+++ b/fileattrs/elf.attr
@@ -1,4 +1,3 @@
-%__elf_provides %{_rpmconfigdir}/elfdeps --provides %{?__filter_GLIBC_PRIVATE:--filter-private}
%__elf_requires %{_rpmconfigdir}/elfdeps --requires %{?__filter_GLIBC_PRIVATE:--filter-private}
-%__elf_magic ^ELF (32|64)-bit.*$
+%__elf_magic ^ELF (32|64)-bit.* shared object, .*$
%__elf_flags exeonly
diff --git a/fileattrs/elflib.attr b/fileattrs/elflib.attr
new file mode 100644
index 0000000..f95db9d
--- /dev/null
+++ b/fileattrs/elflib.attr
@@ -0,0 +1,3 @@
+%__elflib_provides %{_rpmconfigdir}/libdeps --provides %{?__filter_GLIBC_PRIVATE:--filter-private}
+%__elflib_requires %{_rpmconfigdir}/libdeps --requires %{?__filter_GLIBC_PRIVATE:--filter-private}
+%__elflib_magic ^ELF (32|64)-bit.* shared object, .*$
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index a080991..3a03a8e 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -34,9 +34,11 @@ rpmconfig_SCRIPTS = \
pkgconfigdeps.sh libtooldeps.sh \
ocaml-find-requires.sh ocaml-find-provides.sh \
fontconfig.prov desktop-file.prov script.req \
- rpmdb_loadcvt rpm2cpio.sh tcl.req tgpg
+ rpmdb_loadcvt rpm2cpio.sh tcl.req tgpg libdeps
rpmconfig_DATA = \
rpm.daily rpm.log \
macros.perl macros.php macros.python
+libdeps: libdeps.in
+ @$(SED) -e "s,[@]RPMCONFIGDIR[@],$(rpmconfigdir),g" <$< >$@
diff --git a/scripts/libdeps.in b/scripts/libdeps.in
new file mode 100755
index 0000000..c8f73e7
--- /dev/null
+++ b/scripts/libdeps.in
@@ -0,0 +1,28 @@
+#!/bin/sh -efu
+
+ld_config='@RPMCONFIGDIR@/dump_ld_config'
+
+get_paths() {
+ [ -z "${RPM_FINDPROV_LIB_PATH-}" ] || echo "${RPM_FINDPROV_LIB_PATH-}"
+ [ -z "${RPM_BUILD_ROOT-}" ] || "$ld_config" '' "$RPM_BUILD_ROOT"
+ [ -n "${RPM_LIBDIR-}" ] || RPM_LIBDIR="$(rpm --eval '%_libdir')"
+ [ -n "${RPM_LIB-}" ] || RPM_LIB="$(rpm --eval '/%_lib')"
+ echo "$RPM_LIBDIR"
+ echo "$RPM_LIB"
+ "$ld_config"
+}
+
+RPM_FINDPROV_LIB_PATH="$(IFS="$IFS:"; echo '' $(get_paths) '')"
+echo "RPM_FINDPROV_LIB_PATH=$RPM_FINDPROV_LIB_PATH" >&2
+
+while read fn; do
+ found=
+ for path in $RPM_FINDPROV_LIB_PATH; do
+ if [ -z "${fn##${RPM_BUILD_ROOT-}$path/*}" ]; then
+ found=1
+ break
+ fi
+ done
+ [ -z "$found" ] ||
+ printf '%s\n' "$fn"
+done |@RPMCONFIGDIR@/elfdeps "$@"
diff --git a/tools/dump_ld_config.c b/tools/dump_ld_config.c
new file mode 100644
index 0000000..ca5431e
--- /dev/null
+++ b/tools/dump_ld_config.c
@@ -0,0 +1,290 @@
+
+/*
+ Dump dynamic linker configuration.
+
+ Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ This file is based on part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj at suse.de>, 1999.
+ Modified by Dmitry V. Levin <ldv at altlinux.org>, 2004, 2006.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <error.h>
+#include <ctype.h>
+#include <glob.h>
+#include <sys/stat.h>
+
+void *
+xmalloc(size_t size)
+{
+ void *r = malloc(size);
+
+ if (!r)
+ error(EXIT_FAILURE, errno, "malloc");
+ return r;
+}
+
+void *
+xrealloc(void *ptr, size_t size)
+{
+ void *r = realloc(ptr, size);
+
+ if (!r)
+ error(EXIT_FAILURE, errno, "realloc");
+ return r;
+}
+
+char *
+xstrdup(const char *s)
+{
+ size_t len = strlen(s);
+ char *r = xmalloc(len + 1);
+
+ memcpy(r, s, len + 1);
+ return r;
+}
+
+/* List of directories to handle. */
+struct dir_entry
+{
+ struct dir_entry *next;
+ const char *name;
+};
+
+static struct dir_entry *path_list_head, *path_list_tail;
+static const char *prefix;
+
+static void
+path_list_add(const char *path)
+{
+ if (path[0] != '/')
+ return;
+
+ struct dir_entry *e;
+
+#ifndef KEEP_DUPLICATES
+ for (e = path_list_head; e; e = e->next)
+ if (!strcmp(path, e->name))
+ return;
+#endif
+
+ char *newp = NULL;
+
+ if (prefix)
+ {
+ newp = xmalloc(strlen(prefix) + strlen(path) + 1);
+ strcpy(newp, prefix);
+ strcat(newp, path);
+ path = newp;
+ }
+
+ struct stat buf;
+
+ if (stat(path, &buf))
+ {
+ free(newp);
+ return;
+ }
+
+ e = xmalloc(sizeof(*e));
+
+ e->next = 0;
+ e->name = xstrdup(prefix ? (path + strlen(prefix)) : path);
+ if (!path_list_head)
+ path_list_head = e;
+ if (path_list_tail)
+ path_list_tail->next = e;
+ path_list_tail = e;
+
+ free(newp);
+}
+
+static void
+parse_path_line(char *line)
+{
+ /* Skip leading space characters */
+ while (isspace(*line))
+ ++line;
+
+ /* Search for an '=' sign. */
+ char *equal_sign = strchr(line, '=');
+
+ if (equal_sign)
+ *equal_sign = '\0';
+
+ int i = strlen(line) - 1;
+
+ /* Remove trailing space characters */
+ for (; i >= 0 && isspace(line[i]); --i)
+ line[i] = '\0';
+
+ /* Remove trailing slashes */
+ for (; i > 0 && line[i] == '/'; --i)
+ line[i] = '\0';
+
+ if (line[0] == '/')
+ path_list_add(line);
+}
+
+static void parse_file(const char *filename);
+
+static void
+parse_include_pattern(const char *filename, const char *pattern)
+{
+ char *newp = NULL, *p;
+
+ if (prefix)
+ {
+ if (pattern[0] == '/')
+ {
+ newp = xmalloc(strlen(prefix) + strlen(pattern) + 1);
+ strcpy(newp, prefix);
+ strcat(newp, pattern);
+ pattern = newp;
+ } else if ((p = strrchr(filename, '/')))
+ {
+ size_t preflen = strlen(prefix);
+ size_t patlen = strlen(pattern) + 1;
+
+ newp = xmalloc(p - filename + 1 + preflen + patlen);
+ memcpy(newp, prefix, preflen);
+ memcpy(newp + preflen, filename, p - filename + 1);
+ memcpy(newp + (p - filename + 1 + preflen), pattern,
+ patlen);
+ pattern = newp;
+ }
+ } else
+ {
+ if (pattern[0] != '/' && (p = strrchr(filename, '/')))
+ {
+ size_t patlen = strlen(pattern) + 1;
+
+ newp = xmalloc(p - filename + 1 + patlen);
+ memcpy(newp, filename, p - filename + 1);
+ memcpy(newp + (p - filename + 1), pattern, patlen);
+ pattern = newp;
+ }
+ }
+
+ glob_t gl;
+
+ if (glob(pattern, 0, NULL, &gl) == 0)
+ {
+ size_t i;
+
+ for (i = 0; i < gl.gl_pathc; ++i)
+ parse_file(gl.gl_pathv[i]);
+ globfree(&gl);
+ }
+
+ free(newp);
+}
+
+static void
+parse_include_line(const char *filename, char *line)
+{
+ char *arg;
+
+ while ((arg = strsep(&line, " \t")) != NULL)
+ if (arg[0] != '\0')
+ parse_include_pattern(filename, arg);
+}
+
+static void
+parse_file(const char *filename)
+{
+ FILE *fp = fopen(filename, "r");
+
+ if (fp == NULL)
+ return;
+
+ char *line = 0;
+ size_t linesize = 0;
+
+ while (getline(&line, &linesize, fp) > 0)
+ {
+ char *p = strchr(line, '\n');
+
+ if (p)
+ *p = '\0';
+
+ /* Because the file format does not know any form of quoting we
+ can search forward for the next '#' character and if found
+ make it terminating the line. */
+ p = strchr(line, '#');
+ if (p)
+ *p = '\0';
+
+ /* Skip leading whitespace characters. */
+ for (p = line; isspace(*p); ++p)
+ ;
+
+ /* If the line is blank it is ignored. */
+ if (p[0] == '\0')
+ continue;
+
+ if (!strncmp(p, "include", 7) && isblank(p[7]))
+ parse_include_line(filename, p + 8);
+ else
+ parse_path_line(p);
+ }
+ free(line);
+ fclose(fp);
+}
+
+int
+main(int ac, char **av)
+{
+ const char *fname = "/etc/ld.so.conf";
+
+ if (ac > 3)
+ return 1;
+ if (ac > 2)
+ {
+ int len = strlen(av[2]) - 1;
+
+ /* Remove trailing slashes */
+ for (; len > 0 && av[2][len] == '/'; --len)
+ av[2][len] = '\0';
+ if (len < 1 || av[2][0] != '/')
+ return 1;
+ prefix = av[2];
+ }
+ if (ac > 1 && av[1][0])
+ fname = av[1];
+
+ parse_file(fname);
+
+#if defined(SLIBDIR) && defined(LIBDIR)
+ /* Always add the standard search paths. */
+ path_list_add(SLIBDIR);
+ if (strcmp(SLIBDIR, LIBDIR))
+ path_list_add(LIBDIR);
+#endif
+
+ struct dir_entry *e;
+
+ for (e = path_list_head; e; e = e->next)
+ puts(e->name);
+ return 0;
+}
--
1.7.3.2
More information about the Rpm-maint
mailing list