# -*- coding: utf-8 -*- # Copyright (C) 2012 Anaconda, Inc # SPDX-License-Identifier: BSD-3-Clause from __future__ import absolute_import, division, print_function, unicode_literals from collections import OrderedDict from genericpath import exists from logging import getLogger import sys from ...auxlib.decorators import memoize from ..compat import iteritems, scandir log = getLogger(__name__) @memoize def linux_get_libc_version(): """ If on linux, returns (libc_family, version), otherwise (None, None). """ if not sys.platform.startswith('linux'): return None, None from os import confstr, confstr_names, readlink # Python 2.7 does not have either of these keys in confstr_names, so provide # hard-coded defaults and assert if the key is in confstr_names but differs. # These are defined by POSIX anyway so should never change. confstr_names_fallback = OrderedDict([('CS_GNU_LIBC_VERSION', 2), ('CS_GNU_LIBPTHREAD_VERSION', 3)]) val = None for k, v in iteritems(confstr_names_fallback): assert k not in confstr_names or confstr_names[k] == v, ( "confstr_names_fallback for %s is %s yet in confstr_names it is %s" "" % (k, confstr_names_fallback[k], confstr_names[k]) ) try: val = str(confstr(v)) except Exception: # pragma: no cover pass else: if val: break if not val: # pragma: no cover # Weird, play it safe and assume glibc 2.5 family, version = 'glibc', '2.5' log.warning("Failed to detect libc family and version, assuming %s/%s", family, version) return family, version family, version = val.split(' ') # NPTL is just the name of the threading library, even though the # version refers to that of uClibc. readlink() can help to try to # figure out a better name instead. if family == 'NPTL': # pragma: no cover for clib in (entry.path for entry in scandir("/lib") if entry.name[:7] == "libc.so"): clib = readlink(clib) if exists(clib): if clib.startswith('libuClibc'): if version.startswith('0.'): family = 'uClibc' else: family = 'uClibc-ng' return family, version # This could be some other C library; it is unlikely though. family = 'uClibc' log.warning("Failed to detect non-glibc family, assuming %s (%s)", family, version) return family, version return family, version