Commit a58223c3 authored by Simon McVittie's avatar Simon McVittie

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's avatarSimon McVittie <smcv@collabora.com>
parent 79058b6d
......@@ -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)
......
......@@ -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 )
{
......
// 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 ) );
}
// 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 );
......@@ -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;
}
......@@ -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);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment