From a58223c3be648aeeafda303462e5a648f327b350 Mon Sep 17 00:00:00 2001 From: Simon McVittie <smcv@collabora.com> Date: Fri, 3 Jul 2020 15:16:26 +0100 Subject: [PATCH] utils: Move library_cmp_by_name to its own translation unit This will let us unit-test it more easily. While I'm moving it, re-indent it in libcapsule's coding style (4 rather than 2 space indents). Signed-off-by: Simon McVittie <smcv@collabora.com> --- Makefile.am | 6 ++- utils/capture-libs.c | 96 +-------------------------------------- utils/library-cmp.c | 104 +++++++++++++++++++++++++++++++++++++++++++ utils/library-cmp.h | 24 ++++++++++ utils/utils.c | 25 +++++++++++ utils/utils.h | 2 + 6 files changed, 162 insertions(+), 95 deletions(-) create mode 100644 utils/library-cmp.c create mode 100644 utils/library-cmp.h diff --git a/Makefile.am b/Makefile.am index cd08fd013..06dcf2b0e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -106,7 +106,11 @@ capsule_elf_dump_LDADD = utils/libutils.la -ldl capsule_elf_dump_CFLAGS = $(AM_CFLAGS) capsule_elf_dump_LDFLAGS = $(AM_LDFLAGS) $(tools_ldflags) -capsule_capture_libs_SOURCES = utils/capture-libs.c utils/tools.c utils/tools.h +capsule_capture_libs_SOURCES = utils/capture-libs.c \ + utils/library-cmp.c \ + utils/library-cmp.h \ + utils/tools.c \ + utils/tools.h capsule_capture_libs_LDADD = utils/libld.la capsule_capture_libs_LDFLAGS = $(AM_LDFLAGS) $(tools_ldflags) diff --git a/utils/capture-libs.c b/utils/capture-libs.c index 7ae394f34..c2d092709 100644 --- a/utils/capture-libs.c +++ b/utils/capture-libs.c @@ -32,6 +32,7 @@ #include "debug.h" #include "ld-libs.h" +#include "library-cmp.h" #include "tools.h" #include "utils.h" @@ -137,19 +138,6 @@ static int dest_fd = -1; #define strstarts(str, start) \ (strncmp( str, start, strlen( start ) ) == 0) -/* Equivalent to GNU basename(3) from string.h, but not POSIX - * basename(3) from libgen.h. */ -static const char *my_basename (const char *path) -{ - const char *ret = strrchr( path, '/' ); - - if( ret == NULL ) - return path; - - assert( ret[0] == '/' ); - return ret + 1; -} - static bool resolve_ld_so ( const char *prefix, char path[PATH_MAX], const char **within_prefix, @@ -334,86 +322,6 @@ static bool capture_patterns( const char * const *patterns, capture_flags flags, int *code, char **message ); -/* - * library_cmp_by_name: - * @soname: The library we are interested in, used in debug logging - * @left_path: The path to the "left" instance of the library - * @left_from: Arbitrary description of the container/provider/sysroot - * where we found @left_path, used in debug logging - * @right_path: The path to the "right" instance of the library - * @right_from: Arbitrary description of the container/provider/sysroot - * where we found @right_path, used in debug logging - * - * Attempt to determine whether @left_path is older than, newer than or - * the same as than @right_path by inspecting their filenames. - * - * Return a strcmp-style result: negative if left < right, - * positive if left > right, zero if left == right or if left and right - * are non-comparable. - */ -static int -library_cmp_by_name( const char *soname, - const char *left_path, - const char *left_from, - const char *right_path, - const char *right_from ) -{ - _capsule_autofree char *left_realpath = NULL; - _capsule_autofree char *right_realpath = NULL; - const char *left_basename; - const char *right_basename; - - // This might look redundant when our arguments come from the ld_libs, - // but resolve_symlink_prefixed() doesn't chase symlinks if the - // prefix is '/' or empty. - left_realpath = realpath( left_path, NULL ); - right_realpath = realpath( right_path, NULL ); - left_basename = my_basename( left_realpath ); - right_basename = my_basename( right_realpath ); - - DEBUG( DEBUG_TOOL, - "Comparing %s \"%s\" from \"%s\" with " - "\"%s\" from \"%s\"", - soname, left_basename, left_from, right_basename, right_from ); - - if( strcmp( left_basename, right_basename ) == 0 ) - { - DEBUG( DEBUG_TOOL, - "Name of %s \"%s\" from \"%s\" compares the same as " - "\"%s\" from \"%s\"", - soname, left_basename, left_from, right_basename, right_from ); - return 0; - } - - if( strcmp( soname, left_basename ) == 0 ) - { - /* In some distributions (Debian, Ubuntu, Manjaro) - * libgcc_s.so.1 is a plain file, not a symlink to a - * version-suffixed version. We cannot know just from the name - * whether that's older or newer, so assume equal. The caller is - * responsible for figuring out which one to prefer. */ - DEBUG( DEBUG_TOOL, - "Unversioned %s \"%s\" from \"%s\" cannot be compared with " - "\"%s\" from \"%s\"", - soname, left_basename, left_from, - right_basename, right_from ); - return 0; - } - - if( strcmp( soname, right_basename ) == 0 ) - { - /* The same, but the other way round */ - DEBUG( DEBUG_TOOL, - "%s \"%s\" from \"%s\" cannot be compared with " - "unversioned \"%s\" from \"%s\"", - soname, left_basename, left_from, - right_basename, right_from ); - return 0; - } - - return ( strverscmp( left_basename, right_basename ) ); -} - static bool capture_one( const char *soname, capture_flags flags, int *code, char **message ) @@ -478,7 +386,7 @@ capture_one( const char *soname, capture_flags flags, break; } - needed_basename = my_basename( needed_name ); + needed_basename = _capsule_basename( needed_name ); if( !option_glibc ) { diff --git a/utils/library-cmp.c b/utils/library-cmp.c new file mode 100644 index 000000000..d7644525b --- /dev/null +++ b/utils/library-cmp.c @@ -0,0 +1,104 @@ +// Copyright © 2020 Collabora Ltd + +// This file is part of libcapsule. + +// libcapsule 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. + +// libcapsule 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 libcapsule. If not, see <http://www.gnu.org/licenses/>. + +#include "library-cmp.h" + +#include <stdio.h> +#include <string.h> + +#include "debug.h" +#include "utils.h" + +/* + * library_cmp_by_name: + * @soname: The library we are interested in, used in debug logging + * @left_path: The path to the "left" instance of the library + * @left_from: Arbitrary description of the container/provider/sysroot + * where we found @left_path, used in debug logging + * @right_path: The path to the "right" instance of the library + * @right_from: Arbitrary description of the container/provider/sysroot + * where we found @right_path, used in debug logging + * + * Attempt to determine whether @left_path is older than, newer than or + * the same as than @right_path by inspecting their filenames. + * + * Return a strcmp-style result: negative if left < right, + * positive if left > right, zero if left == right or if left and right + * are non-comparable. + */ +int +library_cmp_by_name( const char *soname, + const char *left_path, + const char *left_from, + const char *right_path, + const char *right_from ) +{ + _capsule_autofree char *left_realpath = NULL; + _capsule_autofree char *right_realpath = NULL; + const char *left_basename; + const char *right_basename; + + // This might look redundant when our arguments come from the ld_libs, + // but resolve_symlink_prefixed() doesn't chase symlinks if the + // prefix is '/' or empty. + left_realpath = realpath( left_path, NULL ); + right_realpath = realpath( right_path, NULL ); + left_basename = _capsule_basename( left_realpath ); + right_basename = _capsule_basename( right_realpath ); + + DEBUG( DEBUG_TOOL, + "Comparing %s \"%s\" from \"%s\" with " + "\"%s\" from \"%s\"", + soname, left_basename, left_from, right_basename, right_from ); + + if( strcmp( left_basename, right_basename ) == 0 ) + { + DEBUG( DEBUG_TOOL, + "Name of %s \"%s\" from \"%s\" compares the same as " + "\"%s\" from \"%s\"", + soname, left_basename, left_from, right_basename, right_from ); + return 0; + } + + if( strcmp( soname, left_basename ) == 0 ) + { + /* In some distributions (Debian, Ubuntu, Manjaro) + * libgcc_s.so.1 is a plain file, not a symlink to a + * version-suffixed version. We cannot know just from the name + * whether that's older or newer, so assume equal. The caller is + * responsible for figuring out which one to prefer. */ + DEBUG( DEBUG_TOOL, + "Unversioned %s \"%s\" from \"%s\" cannot be compared with " + "\"%s\" from \"%s\"", + soname, left_basename, left_from, + right_basename, right_from ); + return 0; + } + + if( strcmp( soname, right_basename ) == 0 ) + { + /* The same, but the other way round */ + DEBUG( DEBUG_TOOL, + "%s \"%s\" from \"%s\" cannot be compared with " + "unversioned \"%s\" from \"%s\"", + soname, left_basename, left_from, + right_basename, right_from ); + return 0; + } + + return ( strverscmp( left_basename, right_basename ) ); +} diff --git a/utils/library-cmp.h b/utils/library-cmp.h new file mode 100644 index 000000000..4233a85be --- /dev/null +++ b/utils/library-cmp.h @@ -0,0 +1,24 @@ +// Copyright © 2020 Collabora Ltd + +// This file is part of libcapsule. + +// libcapsule 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. + +// libcapsule 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 libcapsule. If not, see <http://www.gnu.org/licenses/>. + +#pragma once + +int library_cmp_by_name( const char *soname, + const char *container_path, + const char *container_root, + const char *provider_path, + const char *provider_root ); diff --git a/utils/utils.c b/utils/utils.c index 7da3b69be..267f4a19a 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -680,3 +680,28 @@ _capsule_set_error( int *code_dest, char **message_dest, va_end( ap ); } } + +/* + * _capsule_basename: + * @path: A path + * + * Return the part of @path after the last directory separator, or @path + * if there is no directory separator at all, or an empty string if @path + * ends with a directory separator. + * + * Equivalent to GNU basename(3) from string.h, but not POSIX + * basename(3) from libgen.h. + * + * Returns: (transfer none): A pointer into @path + */ +const char * +_capsule_basename (const char *path) +{ + const char *ret = strrchr( path, '/' ); + + if( ret == NULL ) + return path; + + assert( ret[0] == '/' ); + return ret + 1; +} diff --git a/utils/utils.h b/utils/utils.h index e14af8665..34a533f6e 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -230,3 +230,5 @@ _capsule_clear( void *pp ) #ifndef static_assert # define static_assert(expr, message) _Static_assert(expr, message) #endif + +const char *_capsule_basename (const char *path); -- GitLab