wimlib-1.14.5/ 0000755 0001750 0001750 00000000000 15137024753 010366 5 ustar 00e e wimlib-1.14.5/m4/ 0000755 0001750 0001750 00000000000 15137024753 010706 5 ustar 00e e wimlib-1.14.5/m4/lt~obsolete.m4 0000644 0001750 0001750 00000014007 15137024751 013522 0 ustar 00e e # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2025 Free
# Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 5 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
wimlib-1.14.5/m4/libtool.m4 0000644 0001750 0001750 00001166223 15137024751 012625 0 ustar 00e e # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
#
# Copyright (C) 1996-2001, 2003-2019, 2021-2025 Free Software
# Foundation, Inc.
# Written by Gordon Matzigkeit, 1996
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
m4_define([_LT_COPYING], [dnl
# Copyright (C) 2025 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions. There is NO
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# GNU Libtool is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program or library that is built
# using GNU Libtool, you may include this file under the same
# distribution terms that you use for the rest of that program.
#
# GNU Libtool 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
])
# serial 66 LT_INIT
# LT_PREREQ(VERSION)
# ------------------
# Complain and exit if this libtool version is less that VERSION.
m4_defun([LT_PREREQ],
[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
[m4_default([$3],
[m4_fatal([Libtool version $1 or higher is required],
63)])],
[$2])])
# _LT_CHECK_BUILDDIR
# ------------------
# Complain if the absolute build directory name contains unusual characters
m4_defun([_LT_CHECK_BUILDDIR],
[case `pwd` in
*\ * | *\ *)
AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
esac
])
# LT_INIT([OPTIONS])
# ------------------
AC_DEFUN([LT_INIT],
[AC_PREREQ([2.64])dnl We use AC_PATH_PROGS_FEATURE_CHECK
AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
AC_BEFORE([$0], [LT_LANG])dnl
AC_BEFORE([$0], [LT_OUTPUT])dnl
AC_BEFORE([$0], [LTDL_INIT])dnl
m4_require([_LT_CHECK_BUILDDIR])dnl
dnl Autoconf doesn't catch unexpanded LT_ macros by default:
m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
dnl unless we require an AC_DEFUNed macro:
AC_REQUIRE([LTOPTIONS_VERSION])dnl
AC_REQUIRE([LTSUGAR_VERSION])dnl
AC_REQUIRE([LTVERSION_VERSION])dnl
AC_REQUIRE([LTOBSOLETE_VERSION])dnl
m4_require([_LT_PROG_LTMAIN])dnl
_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
dnl Parse OPTIONS
_LT_SET_OPTIONS([$0], [$1])
# This can be used to rebuild libtool when needed
LIBTOOL_DEPS=$ltmain
# Always use our own libtool.
LIBTOOL='$(SHELL) $(top_builddir)/libtool'
AC_SUBST(LIBTOOL)dnl
_LT_SETUP
# Only expand once:
m4_define([LT_INIT])
])# LT_INIT
# Old names:
AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
# _LT_PREPARE_CC_BASENAME
# -----------------------
m4_defun([_LT_PREPARE_CC_BASENAME], [
# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
func_cc_basename ()
{
for cc_temp in @S|@*""; do
case $cc_temp in
compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
\-*) ;;
*) break;;
esac
done
func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
}
])# _LT_PREPARE_CC_BASENAME
# _LT_CC_BASENAME(CC)
# -------------------
# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
# but that macro is also expanded into generated libtool script, which
# arranges for $SED and $ECHO to be set by different means.
m4_defun([_LT_CC_BASENAME],
[m4_require([_LT_PREPARE_CC_BASENAME])dnl
AC_REQUIRE([_LT_DECL_SED])dnl
AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
func_cc_basename $1
cc_basename=$func_cc_basename_result
])
# _LT_FILEUTILS_DEFAULTS
# ----------------------
# It is okay to use these file commands and assume they have been set
# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'.
m4_defun([_LT_FILEUTILS_DEFAULTS],
[: ${CP="cp -f"}
: ${MV="mv -f"}
: ${RM="rm -f"}
])# _LT_FILEUTILS_DEFAULTS
# _LT_SETUP
# ---------
m4_defun([_LT_SETUP],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
dnl
_LT_DECL([], [host_alias], [0], [The host system])dnl
_LT_DECL([], [host], [0])dnl
_LT_DECL([], [host_os], [0])dnl
dnl
_LT_DECL([], [build_alias], [0], [The build system])dnl
_LT_DECL([], [build], [0])dnl
_LT_DECL([], [build_os], [0])dnl
dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([LT_PATH_LD])dnl
AC_REQUIRE([LT_PATH_NM])dnl
dnl
AC_REQUIRE([AC_PROG_LN_S])dnl
test -z "$LN_S" && LN_S="ln -s"
_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
dnl
AC_REQUIRE([LT_CMD_MAX_LEN])dnl
_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_CHECK_SHELL_FEATURES])dnl
m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
m4_require([_LT_CMD_RELOAD])dnl
m4_require([_LT_DECL_FILECMD])dnl
m4_require([_LT_CHECK_MAGIC_METHOD])dnl
m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
m4_require([_LT_CMD_OLD_ARCHIVE])dnl
m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
m4_require([_LT_WITH_SYSROOT])dnl
m4_require([_LT_CMD_TRUNCATE])dnl
_LT_CONFIG_LIBTOOL_INIT([
# See if we are running on zsh, and set the options that allow our
# commands through without removal of \ escapes INIT.
if test -n "\${ZSH_VERSION+set}"; then
setopt NO_GLOB_SUBST
fi
])
if test -n "${ZSH_VERSION+set}"; then
setopt NO_GLOB_SUBST
fi
_LT_CHECK_OBJDIR
m4_require([_LT_TAG_COMPILER])dnl
case $host_os in
aix3*)
# AIX sometimes has problems with the GCC collect2 program. For some
# reason, if we set the COLLECT_NAMES environment variable, the problems
# vanish in a puff of smoke.
if test set != "${COLLECT_NAMES+set}"; then
COLLECT_NAMES=
export COLLECT_NAMES
fi
;;
esac
# Global variables:
ofile=libtool
can_build_shared=yes
# All known linkers require a '.a' archive for static linking (except MSVC and
# ICC, which need '.lib').
libext=a
with_gnu_ld=$lt_cv_prog_gnu_ld
old_CC=$CC
old_CFLAGS=$CFLAGS
# Set sane defaults for various variables
test -z "$CC" && CC=cc
test -z "$LTCC" && LTCC=$CC
test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
test -z "$LD" && LD=ld
test -z "$ac_objext" && ac_objext=o
_LT_CC_BASENAME([$compiler])
# Only perform the check for file, if the check method requires it
test -z "$MAGIC_CMD" && MAGIC_CMD=file
case $deplibs_check_method in
file_magic*)
if test "$file_magic_cmd" = '$MAGIC_CMD'; then
_LT_PATH_MAGIC
fi
;;
esac
# Use C for the default configuration in the libtool script
LT_SUPPORTED_TAG([CC])
_LT_LANG_C_CONFIG
_LT_LANG_DEFAULT_CONFIG
_LT_CONFIG_COMMANDS
])# _LT_SETUP
# _LT_PREPARE_SED_QUOTE_VARS
# --------------------------
# Define a few sed substitution that help us do robust quoting.
m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
[# Backslashify metacharacters that are still active within
# double-quoted strings.
sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
# Same as above, but do not quote variable references.
double_quote_subst='s/\([["`\\]]\)/\\\1/g'
# Sed substitution to delay expansion of an escaped shell variable in a
# double_quote_subst'ed string.
delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
# Sed substitution to delay expansion of an escaped single quote.
delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
# Sed substitution to avoid accidental globbing in evaled expressions
no_glob_subst='s/\*/\\\*/g'
])
# _LT_PROG_LTMAIN
# ---------------
# Note that this code is called both from 'configure', and 'config.status'
# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
# 'config.status' has no value for ac_aux_dir unless we are using Automake,
# so we pass a copy along to make sure it has a sensible value anyway.
m4_defun([_LT_PROG_LTMAIN],
[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
ltmain=$ac_aux_dir/ltmain.sh
])# _LT_PROG_LTMAIN
## ------------------------------------- ##
## Accumulate code for creating libtool. ##
## ------------------------------------- ##
# So that we can recreate a full libtool script including additional
# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
# in macros and then make a single call at the end using the 'libtool'
# label.
# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
# ----------------------------------------
# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
m4_define([_LT_CONFIG_LIBTOOL_INIT],
[m4_ifval([$1],
[m4_append([_LT_OUTPUT_LIBTOOL_INIT],
[$1
])])])
# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_INIT])
# _LT_CONFIG_LIBTOOL([COMMANDS])
# ------------------------------
# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
m4_define([_LT_CONFIG_LIBTOOL],
[m4_ifval([$1],
[m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
[$1
])])])
# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
# -----------------------------------------------------
m4_defun([_LT_CONFIG_SAVE_COMMANDS],
[_LT_CONFIG_LIBTOOL([$1])
_LT_CONFIG_LIBTOOL_INIT([$2])
])
# _LT_FORMAT_COMMENT([COMMENT])
# -----------------------------
# Add leading comment marks to the start of each line, and a trailing
# full-stop to the whole comment if one is not present already.
m4_define([_LT_FORMAT_COMMENT],
[m4_ifval([$1], [
m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
[['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
)])
## ------------------------ ##
## FIXME: Eliminate VARNAME ##
## ------------------------ ##
# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
# -------------------------------------------------------------------
# CONFIGNAME is the name given to the value in the libtool script.
# VARNAME is the (base) name used in the configure script.
# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
# VARNAME. Any other value will be used directly.
m4_define([_LT_DECL],
[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
[lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
[m4_ifval([$1], [$1], [$2])])
lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
m4_ifval([$4],
[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
lt_dict_add_subkey([lt_decl_dict], [$2],
[tagged?], [m4_ifval([$5], [yes], [no])])])
])
# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
# --------------------------------------------------------
m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
# ------------------------------------------------
m4_define([lt_decl_tag_varnames],
[_lt_decl_filter([tagged?], [yes], $@)])
# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
# ---------------------------------------------------------
m4_define([_lt_decl_filter],
[m4_case([$#],
[0], [m4_fatal([$0: too few arguments: $#])],
[1], [m4_fatal([$0: too few arguments: $#: $1])],
[2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
[3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
[lt_dict_filter([lt_decl_dict], $@)])[]dnl
])
# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
# --------------------------------------------------
m4_define([lt_decl_quote_varnames],
[_lt_decl_filter([value], [1], $@)])
# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
# ---------------------------------------------------
m4_define([lt_decl_dquote_varnames],
[_lt_decl_filter([value], [2], $@)])
# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
# ---------------------------------------------------
m4_define([lt_decl_varnames_tagged],
[m4_assert([$# <= 2])dnl
_$0(m4_quote(m4_default([$1], [[, ]])),
m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
m4_define([_lt_decl_varnames_tagged],
[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
# ------------------------------------------------
m4_define([lt_decl_all_varnames],
[_$0(m4_quote(m4_default([$1], [[, ]])),
m4_if([$2], [],
m4_quote(lt_decl_varnames),
m4_quote(m4_shift($@))))[]dnl
])
m4_define([_lt_decl_all_varnames],
[lt_join($@, lt_decl_varnames_tagged([$1],
lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
])
# _LT_CONFIG_STATUS_DECLARE([VARNAME])
# ------------------------------------
# Quote a variable value, and forward it to 'config.status' so that its
# declaration there will have the same value as in 'configure'. VARNAME
# must have a single quote delimited value for this to work.
m4_define([_LT_CONFIG_STATUS_DECLARE],
[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
# _LT_CONFIG_STATUS_DECLARATIONS
# ------------------------------
# We delimit libtool config variables with single quotes, so when
# we write them to config.status, we have to be sure to quote all
# embedded single quotes properly. In configure, this macro expands
# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
#
# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`'
m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
[m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
# _LT_LIBTOOL_TAGS
# ----------------
# Output comment and list of tags supported by the script
m4_defun([_LT_LIBTOOL_TAGS],
[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
available_tags='_LT_TAGS'dnl
])
# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
# -----------------------------------
# Extract the dictionary values for VARNAME (optionally with TAG) and
# expand to a commented shell variable setting:
#
# # Some comment about what VAR is for.
# visible_name=$lt_internal_name
m4_define([_LT_LIBTOOL_DECLARE],
[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
[description])))[]dnl
m4_pushdef([_libtool_name],
m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
[0], [_libtool_name=[$]$1],
[1], [_libtool_name=$lt_[]$1],
[2], [_libtool_name=$lt_[]$1],
[_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
])
# _LT_LIBTOOL_CONFIG_VARS
# -----------------------
# Produce commented declarations of non-tagged libtool config variables
# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool'
# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
# section) are produced by _LT_LIBTOOL_TAG_VARS.
m4_defun([_LT_LIBTOOL_CONFIG_VARS],
[m4_foreach([_lt_var],
m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
[m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
# _LT_LIBTOOL_TAG_VARS(TAG)
# -------------------------
m4_define([_LT_LIBTOOL_TAG_VARS],
[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
[m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
# _LT_TAGVAR(VARNAME, [TAGNAME])
# ------------------------------
m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
# _LT_OBJECTIVE_C
# ------------------------------
m4_defun([_LT_OBJECTIVE_C], [
AC_CACHE_CHECK([for Objective C compilation],
[lt_cv_objc_compiles],
[ save_CFLAGS=$CFLAGS
CFLAGS=$OBJCFLAGS
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([#import
@interface Addition : NSObject
- (int)this:(int)a that:(int)b;
@end
@implementation Addition
- (int)this:(int)a that:(int)b
{
return a + b;
}
@end
],[])],
lt_cv_objc_compiles=yes,
lt_cv_objc_compiles=no
)
CFLAGS=$save_CFLAGS
]
)
objc_compiles=$lt_cv_objc_compiles
_LT_DECL([], [objc_compiles], [1],
[Check for compiling Objective C and C++ code])
])
m4_defun([_LT_ML64], [
AC_CACHE_CHECK([for ML64 compilation],
[lt_cv_ml64_compiles],
[ save_CFLAGS=$CFLAGS
CFLAGS=$ML64FLAGS
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([ret
],[])],
lt_cv_ml64_compiles=yes,
lt_cv_ml64_compiles=no
)
CFLAGS=$save_CFLAGS
]
)
objc_compiles=$lt_cv_objc_compiles
_LT_DECL([], [ml64_compiles], [1],
[Check for compiling ml64 code])
])
# _LT_CONFIG_COMMANDS
# -------------------
# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
# variables for single and double quote escaping we saved from calls
# to _LT_DECL, we can put quote escaped variables declarations
# into 'config.status', and then the shell code to quote escape them in
# for loops in 'config.status'. Finally, any additional code accumulated
# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
m4_defun([_LT_CONFIG_COMMANDS],
[AC_PROVIDE_IFELSE([LT_OUTPUT],
dnl If the libtool generation code has been placed in $CONFIG_LT,
dnl instead of duplicating it all over again into config.status,
dnl then we will have config.status run $CONFIG_LT later, so it
dnl needs to know what name is stored there:
[AC_CONFIG_COMMANDS([libtool],
[$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
dnl If the libtool generation code is destined for config.status,
dnl expand the accumulated commands and init code now:
[AC_CONFIG_COMMANDS([libtool],
[_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
])#_LT_CONFIG_COMMANDS
# Initialize.
m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
[
# The HP-UX ksh and POSIX shell print the target directory to stdout
# if CDPATH is set.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
sed_quote_subst='$sed_quote_subst'
double_quote_subst='$double_quote_subst'
delay_variable_subst='$delay_variable_subst'
_LT_CONFIG_STATUS_DECLARATIONS
LTCC='$LTCC'
LTCFLAGS='$LTCFLAGS'
compiler='$compiler_DEFAULT'
# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
\$[]1
_LTECHO_EOF'
}
# Quote evaled strings.
for var in lt_decl_all_varnames([[ \
]], lt_decl_quote_varnames); do
case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
*[[\\\\\\\`\\"\\\$]]*)
eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
;;
*)
eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
;;
esac
done
# Double-quote double-evaled strings.
for var in lt_decl_all_varnames([[ \
]], lt_decl_dquote_varnames); do
case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
*[[\\\\\\\`\\"\\\$]]*)
eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
;;
*)
eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
;;
esac
done
_LT_OUTPUT_LIBTOOL_INIT
])
# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
# ------------------------------------
# Generate a child script FILE with all initialization necessary to
# reuse the environment learned by the parent script, and make the
# file executable. If COMMENT is supplied, it is inserted after the
# '#!' sequence but before initialization text begins. After this
# macro, additional text can be appended to FILE to form the body of
# the child script. The macro ends with non-zero status if the
# file could not be fully written (such as if the disk is full).
m4_ifdef([AS_INIT_GENERATED],
[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
[m4_defun([_LT_GENERATED_FILE_INIT],
[m4_require([AS_PREPARE])]dnl
[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
[lt_write_fail=0
cat >$1 <<_ASEOF || lt_write_fail=1
#! $SHELL
# Generated by $as_me.
$2
SHELL=\${CONFIG_SHELL-$SHELL}
export SHELL
_ASEOF
cat >>$1 <<\_ASEOF || lt_write_fail=1
AS_SHELL_SANITIZE
_AS_PREPARE
exec AS_MESSAGE_FD>&1
_ASEOF
test 0 = "$lt_write_fail" && chmod +x $1[]dnl
m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
# LT_OUTPUT
# ---------
# This macro allows early generation of the libtool script (before
# AC_OUTPUT is called), in case it is used in configure for compilation
# tests.
AC_DEFUN([LT_OUTPUT],
[: ${CONFIG_LT=./config.lt}
AC_MSG_NOTICE([creating $CONFIG_LT])
_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
[# Run this file to recreate a libtool stub with the current configuration.])
cat >>"$CONFIG_LT" <<\_LTEOF
lt_cl_silent=false
exec AS_MESSAGE_LOG_FD>>config.log
{
echo
AS_BOX([Running $as_me.])
} >&AS_MESSAGE_LOG_FD
lt_cl_help="\
'$as_me' creates a local libtool stub from the current configuration,
for use in further configure time tests before the real libtool is
generated.
Usage: $[0] [[OPTIONS]]
-h, --help print this help, then exit
-V, --version print version number, then exit
-q, --quiet do not print progress messages
-d, --debug don't remove temporary files
Report bugs to ."
lt_cl_version="\
m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
configured by $[0], generated by m4_PACKAGE_STRING.
Copyright (C) 2025 Free Software Foundation, Inc.
This config.lt script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
while test 0 != $[#]
do
case $[1] in
--version | --v* | -V )
echo "$lt_cl_version"; exit 0 ;;
--help | --h* | -h )
echo "$lt_cl_help"; exit 0 ;;
--debug | --d* | -d )
debug=: ;;
--quiet | --q* | --silent | --s* | -q )
lt_cl_silent=: ;;
-*) AC_MSG_ERROR([unrecognized option: $[1]
Try '$[0] --help' for more information.]) ;;
*) AC_MSG_ERROR([unrecognized argument: $[1]
Try '$[0] --help' for more information.]) ;;
esac
shift
done
if $lt_cl_silent; then
exec AS_MESSAGE_FD>/dev/null
fi
_LTEOF
cat >>"$CONFIG_LT" <<_LTEOF
_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
_LTEOF
cat >>"$CONFIG_LT" <<\_LTEOF
AC_MSG_NOTICE([creating $ofile])
_LT_OUTPUT_LIBTOOL_COMMANDS
AS_EXIT(0)
_LTEOF
chmod +x "$CONFIG_LT"
# configure is writing to config.log, but config.lt does its own redirection,
# appending to config.log, which fails on DOS, as config.log is still kept
# open by configure. Here we exec the FD to /dev/null, effectively closing
# config.log, so it can be properly (re)opened and appended to by config.lt.
lt_cl_success=:
test yes = "$silent" &&
lt_config_lt_args="$lt_config_lt_args --quiet"
exec AS_MESSAGE_LOG_FD>/dev/null
$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
exec AS_MESSAGE_LOG_FD>>config.log
$lt_cl_success || AS_EXIT(1)
])# LT_OUTPUT
# _LT_CONFIG(TAG)
# ---------------
# If TAG is the built-in tag, create an initial libtool script with a
# default configuration from the untagged config vars. Otherwise add code
# to config.status for appending the configuration named by TAG from the
# matching tagged config vars.
m4_defun([_LT_CONFIG],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
_LT_CONFIG_SAVE_COMMANDS([
m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
m4_if(_LT_TAG, [C], [
# See if we are running on zsh, and set the options that allow our
# commands through without removal of \ escapes.
if test -n "${ZSH_VERSION+set}"; then
setopt NO_GLOB_SUBST
fi
cfgfile=${ofile}T
trap "$RM \"$cfgfile\"; exit 1" 1 2 15
$RM "$cfgfile"
cat <<_LT_EOF >> "$cfgfile"
#! $SHELL
# Generated automatically by $as_me ($PACKAGE) $VERSION
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
# Provide generalized library-building support services.
# Written by Gordon Matzigkeit, 1996
_LT_COPYING
_LT_LIBTOOL_TAGS
# Configured defaults for sys_lib_dlsearch_path munging.
: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
# ### BEGIN LIBTOOL CONFIG
_LT_LIBTOOL_CONFIG_VARS
_LT_LIBTOOL_TAG_VARS
# ### END LIBTOOL CONFIG
_LT_EOF
cat <<'_LT_EOF' >> "$cfgfile"
# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
_LT_PREPARE_MUNGE_PATH_LIST
_LT_PREPARE_CC_BASENAME
# ### END FUNCTIONS SHARED WITH CONFIGURE
_LT_EOF
case $host_os in
aix3*)
cat <<\_LT_EOF >> "$cfgfile"
# AIX sometimes has problems with the GCC collect2 program. For some
# reason, if we set the COLLECT_NAMES environment variable, the problems
# vanish in a puff of smoke.
if test set != "${COLLECT_NAMES+set}"; then
COLLECT_NAMES=
export COLLECT_NAMES
fi
_LT_EOF
;;
esac
_LT_PROG_LTMAIN
# We use sed instead of cat because bash on DJGPP gets confused if
# if finds mixed CR/LF and LF-only lines. Since sed operates in
# text mode, it properly converts lines to CR/LF. This bash problem
# is reportedly fixed, but why not run on old versions too?
$SED '$q' "$ltmain" >> "$cfgfile" \
|| (rm -f "$cfgfile"; exit 1)
mv -f "$cfgfile" "$ofile" ||
(rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
chmod +x "$ofile"
],
[cat <<_LT_EOF >> "$ofile"
dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
dnl in a comment (ie after a #).
# ### BEGIN LIBTOOL TAG CONFIG: $1
_LT_LIBTOOL_TAG_VARS(_LT_TAG)
# ### END LIBTOOL TAG CONFIG: $1
_LT_EOF
])dnl /m4_if
],
[m4_if([$1], [], [
PACKAGE='$PACKAGE'
VERSION='$VERSION'
RM='$RM'
ofile='$ofile'], [])
])dnl /_LT_CONFIG_SAVE_COMMANDS
])# _LT_CONFIG
# LT_SUPPORTED_TAG(TAG)
# ---------------------
# Trace this macro to discover what tags are supported by the libtool
# --tag option, using:
# autoconf --trace 'LT_SUPPORTED_TAG:$1'
AC_DEFUN([LT_SUPPORTED_TAG], [])
# C support is built-in for now
m4_define([_LT_LANG_C_enabled], [])
m4_define([_LT_TAGS], [])
# LT_LANG(LANG)
# -------------
# Enable libtool support for the given language if not already enabled.
AC_DEFUN([LT_LANG],
[AC_BEFORE([$0], [LT_OUTPUT])dnl
m4_case([$1],
[C], [_LT_LANG(C)],
[C++], [_LT_LANG(CXX)],
[Objective-C], [_LT_LANG(OBJC)],
[Objective-C++], [_LT_LANG(OBJCXX)],
[Microsoft Macro Assembler], [_LT_LANG(ML64)],
[Go], [_LT_LANG(GO)],
[Java], [_LT_LANG(GCJ)],
[Fortran 77], [_LT_LANG(F77)],
[Fortran], [_LT_LANG(FC)],
[Windows Resource], [_LT_LANG(RC)],
[m4_ifdef([_LT_LANG_]$1[_CONFIG],
[_LT_LANG($1)],
[m4_fatal([$0: unsupported language: "$1"])])])dnl
])# LT_LANG
# _LT_LANG(LANGNAME)
# ------------------
m4_defun([_LT_LANG],
[m4_ifdef([_LT_LANG_]$1[_enabled], [],
[LT_SUPPORTED_TAG([$1])dnl
m4_append([_LT_TAGS], [$1 ])dnl
m4_define([_LT_LANG_]$1[_enabled], [])dnl
_LT_LANG_$1_CONFIG($1)])dnl
])# _LT_LANG
m4_ifndef([AC_PROG_ML64], [
m4_defun([AC_PROG_ML64],
[AC_LANG_PUSH(ML64)dnl
AC_ARG_VAR([ML64], [ml64 compiler command])dnl
AC_ARG_VAR([ML64FLAGS], [ml64 compiler flags])dnl
_AC_ARG_VAR_LDFLAGS()dnl
AC_CHECK_TOOL(ML64, ml64)
if test -z "$ML64"; then
if test -n "$ac_tool_prefix"; then
AC_CHECK_PROG(ML64, [${ac_tool_prefix}ml64], [${ac_tool_prefix}ml64])
fi
fi
if test -z "$ML64"; then
AC_CHECK_PROG(ML64, ml64, ml64, false)
fi
])#m4_defun
])#m4_ifndef
m4_ifndef([AC_PROG_GO], [
############################################################
# NOTE: This macro has been submitted for inclusion into #
# GNU Autoconf as AC_PROG_GO. When it is available in #
# a released version of Autoconf we should remove this #
# macro and use it instead. #
############################################################
m4_defun([AC_PROG_GO],
[AC_LANG_PUSH(Go)dnl
AC_ARG_VAR([GOC], [Go compiler command])dnl
AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
_AC_ARG_VAR_LDFLAGS()dnl
AC_CHECK_TOOL(GOC, gccgo)
if test -z "$GOC"; then
if test -n "$ac_tool_prefix"; then
AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
fi
fi
if test -z "$GOC"; then
AC_CHECK_PROG(GOC, gccgo, gccgo, false)
fi
])#m4_defun
])#m4_ifndef
# _LT_LANG_DEFAULT_CONFIG
# -----------------------
m4_defun([_LT_LANG_DEFAULT_CONFIG],
[AC_PROVIDE_IFELSE([AC_PROG_CXX],
[LT_LANG(CXX)],
[m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
AC_PROVIDE_IFELSE([AC_PROG_F77],
[LT_LANG(F77)],
[m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
AC_PROVIDE_IFELSE([AC_PROG_FC],
[LT_LANG(FC)],
[m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
dnl pulling things in needlessly.
AC_PROVIDE_IFELSE([AC_PROG_GCJ],
[LT_LANG(GCJ)],
[AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
[LT_LANG(GCJ)],
[AC_PROVIDE_IFELSE([LT_PROG_GCJ],
[LT_LANG(GCJ)],
[m4_ifdef([AC_PROG_GCJ],
[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
m4_ifdef([A][M_PROG_GCJ],
[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
m4_ifdef([LT_PROG_GCJ],
[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
AC_PROVIDE_IFELSE([AC_PROG_GO],
[LT_LANG(GO)],
[m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
[LT_LANG(OBJC)],
[m4_define([AC_PROG_OBJC], defn([AC_PROG_OBJC])[LT_LANG(OBJC)])])
AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
[LT_LANG(OBJCXX)],
[m4_define([AC_PROG_OBJCXX], defn([AC_PROG_OBJCXX])[LT_LANG(OBJCXX)])])
AC_PROVIDE_IFELSE([AC_PROG_ML64],
[LT_LANG(ML64)],
[m4_define([AC_PROG_ML64], defn([AC_PROG_ML64])[LT_LANG(ML64)])])
AC_PROVIDE_IFELSE([LT_PROG_RC],
[LT_LANG(RC)],
[m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
])
# _LT_LANG_DEFAULT_CONFIG
# Obsolete macros:
AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
dnl AC_DEFUN([AC_LIBTOOL_F77], [])
dnl AC_DEFUN([AC_LIBTOOL_FC], [])
dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
dnl AC_DEFUN([AC_LIBTOOL_RC], [])
# _LT_TAG_COMPILER
# ----------------
m4_defun([_LT_TAG_COMPILER],
[AC_REQUIRE([AC_PROG_CC])dnl
_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
# If no C compiler was specified, use CC.
LTCC=${LTCC-"$CC"}
# If no C compiler flags were specified, use CFLAGS.
LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
# Allow CC to be a program name with arguments.
compiler=$CC
])# _LT_TAG_COMPILER
# _LT_COMPILER_BOILERPLATE
# ------------------------
# Check for compiler boilerplate output or warnings with
# the simple compiler test code.
m4_defun([_LT_COMPILER_BOILERPLATE],
[m4_require([_LT_DECL_SED])dnl
ac_outfile=conftest.$ac_objext
echo "$lt_simple_compile_test_code" >conftest.$ac_ext
eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
_lt_compiler_boilerplate=`cat conftest.err`
$RM conftest*
])# _LT_COMPILER_BOILERPLATE
# _LT_LINKER_BOILERPLATE
# ----------------------
# Check for linker boilerplate output or warnings with
# the simple link test code.
m4_defun([_LT_LINKER_BOILERPLATE],
[m4_require([_LT_DECL_SED])dnl
ac_outfile=conftest.$ac_objext
echo "$lt_simple_link_test_code" >conftest.$ac_ext
eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
_lt_linker_boilerplate=`cat conftest.err`
$RM -r conftest*
])# _LT_LINKER_BOILERPLATE
# _LT_REQUIRED_DARWIN_CHECKS
# -------------------------
m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
case $host_os in
rhapsody* | darwin*)
AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
AC_CHECK_TOOL([LIPO], [lipo], [:])
AC_CHECK_TOOL([OTOOL], [otool], [:])
AC_CHECK_TOOL([OTOOL64], [otool64], [:])
_LT_DECL([], [DSYMUTIL], [1],
[Tool to manipulate archived DWARF debug symbol files on Mac OS X])
_LT_DECL([], [NMEDIT], [1],
[Tool to change global to local symbols on Mac OS X])
_LT_DECL([], [LIPO], [1],
[Tool to manipulate fat objects and archives on Mac OS X])
_LT_DECL([], [OTOOL], [1],
[ldd/readelf like tool for Mach-O binaries on Mac OS X])
_LT_DECL([], [OTOOL64], [1],
[ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
[lt_cv_apple_cc_single_mod=no
if test -z "$LT_MULTI_MODULE"; then
# By default we will add the -single_module flag. You can override
# by either setting the environment variable LT_MULTI_MODULE
# non-empty at configure time, or by adding -multi_module to the
# link flags.
rm -rf libconftest.dylib*
echo "int foo(void){return 1;}" > conftest.c
echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
-dynamiclib -Wl,-single_module conftest.c 2>conftest.err
_lt_result=$?
# If there is a non-empty error log, and "single_module"
# appears in it, assume the flag caused a linker warning
if test -s conftest.err && $GREP single_module conftest.err; then
cat conftest.err >&AS_MESSAGE_LOG_FD
# Otherwise, if the output was created with a 0 exit code from
# the compiler, it worked.
elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
lt_cv_apple_cc_single_mod=yes
else
cat conftest.err >&AS_MESSAGE_LOG_FD
fi
rm -rf libconftest.dylib*
rm -f conftest.*
fi])
# Feature test to disable chained fixups since it is not
# compatible with '-undefined dynamic_lookup'
AC_CACHE_CHECK([for -no_fixup_chains linker flag],
[lt_cv_support_no_fixup_chains],
[ save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -Wl,-no_fixup_chains"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([],[])],
lt_cv_support_no_fixup_chains=yes,
lt_cv_support_no_fixup_chains=no
)
LDFLAGS=$save_LDFLAGS
]
)
AC_CACHE_CHECK([for -exported_symbols_list linker flag],
[lt_cv_ld_exported_symbols_list],
[lt_cv_ld_exported_symbols_list=no
save_LDFLAGS=$LDFLAGS
echo "_main" > conftest.sym
LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
[lt_cv_ld_exported_symbols_list=yes],
[lt_cv_ld_exported_symbols_list=no])
LDFLAGS=$save_LDFLAGS
])
AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
[lt_cv_ld_force_load=no
cat > conftest.c << _LT_EOF
int forced_loaded() { return 2;}
_LT_EOF
echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
$LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
$AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
$RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
cat > conftest.c << _LT_EOF
int main(void) { return 0;}
_LT_EOF
echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
_lt_result=$?
if test -s conftest.err && $GREP force_load conftest.err; then
cat conftest.err >&AS_MESSAGE_LOG_FD
elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
lt_cv_ld_force_load=yes
else
cat conftest.err >&AS_MESSAGE_LOG_FD
fi
rm -f conftest.err libconftest.a conftest conftest.c
rm -rf conftest.dSYM
])
case $host_os in
rhapsody* | darwin1.[[012]])
_lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
darwin1.*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
darwin*)
case $MACOSX_DEPLOYMENT_TARGET,$host in
10.[[012]],*|,*powerpc*-darwin[[5-8]]*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup'
if test yes = "$lt_cv_support_no_fixup_chains"; then
AS_VAR_APPEND([_lt_dar_allow_undefined], [' $wl-no_fixup_chains'])
fi
;;
esac
;;
esac
if test yes = "$lt_cv_apple_cc_single_mod"; then
_lt_dar_single_mod='$single_module'
fi
_lt_dar_needs_single_mod=no
case $host_os in
rhapsody* | darwin1.*)
_lt_dar_needs_single_mod=yes ;;
darwin*)
# When targeting Mac OS X 10.4 (darwin 8) or later,
# -single_module is the default and -multi_module is unsupported.
# The toolchain on macOS 10.14 (darwin 18) and later cannot
# target any OS version that needs -single_module.
case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
10.0,*-darwin[[567]].*|10.[[0-3]],*-darwin[[5-9]].*|10.[[0-3]],*-darwin1[[0-7]].*)
_lt_dar_needs_single_mod=yes ;;
esac
;;
esac
if test yes = "$lt_cv_ld_exported_symbols_list"; then
_lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
else
_lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
fi
if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
_lt_dsymutil='~$DSYMUTIL $lib || :'
else
_lt_dsymutil=
fi
;;
esac
])
# _LT_DARWIN_LINKER_FEATURES([TAG])
# ---------------------------------
# Checks for linker and compiler features on darwin
m4_defun([_LT_DARWIN_LINKER_FEATURES],
[
m4_require([_LT_REQUIRED_DARWIN_CHECKS])
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_automatic, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
if test yes = "$lt_cv_ld_force_load"; then
_LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
[FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes])
else
_LT_TAGVAR(whole_archive_flag_spec, $1)=''
fi
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined
case $cc_basename in
ifort*|nagfor*) _lt_dar_can_shared=yes ;;
*) _lt_dar_can_shared=$GCC ;;
esac
if test yes = "$_lt_dar_can_shared"; then
output_verbose_link_cmd=func_echo_all
_LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
_LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
_LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
m4_if([$1], [CXX],
[ if test yes = "$_lt_dar_needs_single_mod" -a yes != "$lt_cv_apple_cc_single_mod"; then
_LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs $stdlibflag -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs $stdlibflag -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
fi
],[])
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
])
# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
# ----------------------------------
# Links a minimal program and checks the executable
# for the system default hardcoded library path. In most cases,
# this is /usr/lib:/lib, but when the MPI compilers are used
# the location of the communication and MPI libs are included too.
# If we don't find anything, use the default library path according
# to the aix ld manual.
# Store the results from the different compilers for each TAGNAME.
# Allow to override them for all tags through lt_cv_aix_libpath.
m4_defun([_LT_SYS_MODULE_PATH_AIX],
[m4_require([_LT_DECL_SED])dnl
if test set = "${lt_cv_aix_libpath+set}"; then
aix_libpath=$lt_cv_aix_libpath
else
AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
[AC_LINK_IFELSE([AC_LANG_PROGRAM],[
lt_aix_libpath_sed='[
/Import File Strings/,/^$/ {
/^0/ {
s/^0 *\([^ ]*\) *$/\1/
p
}
}]'
_LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
# Check for a 64-bit object if we didn't find anything.
if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
_LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
fi],[])
if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
_LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib
fi
])
aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
fi
])# _LT_SYS_MODULE_PATH_AIX
# _LT_SHELL_INIT(ARG)
# -------------------
m4_define([_LT_SHELL_INIT],
[m4_divert_text([M4SH-INIT], [$1
])])# _LT_SHELL_INIT
# _LT_PROG_ECHO_BACKSLASH
# -----------------------
# Find how we can fake an echo command that does not interpret backslash.
# In particular, with Autoconf 2.60 or later we add some code to the start
# of the generated configure script that will find a shell with a builtin
# printf (that we can use as an echo command).
m4_defun([_LT_PROG_ECHO_BACKSLASH],
[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
AC_MSG_CHECKING([how to print strings])
# Test print first, because it will be a builtin if present.
if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
ECHO='print -r --'
elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
ECHO='printf %s\n'
else
# Use this function as a fallback that always works.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
$[]1
_LTECHO_EOF'
}
ECHO='func_fallback_echo'
fi
# func_echo_all arg...
# Invoke $ECHO with all args, space-separated.
func_echo_all ()
{
$ECHO "$*"
}
case $ECHO in
printf*) AC_MSG_RESULT([printf]) ;;
print*) AC_MSG_RESULT([print -r]) ;;
*) AC_MSG_RESULT([cat]) ;;
esac
m4_ifdef([_AS_DETECT_SUGGESTED],
[_AS_DETECT_SUGGESTED([
test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
PATH=/empty FPATH=/empty; export PATH FPATH
test "X`printf %s $ECHO`" = "X$ECHO" \
|| test "X`print -r -- $ECHO`" = "X$ECHO" )])])
_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
])# _LT_PROG_ECHO_BACKSLASH
# _LT_WITH_SYSROOT
# ----------------
AC_DEFUN([_LT_WITH_SYSROOT],
[m4_require([_LT_DECL_SED])dnl
AC_MSG_CHECKING([for sysroot])
AC_ARG_WITH([sysroot],
[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
[Search for dependent libraries within DIR (or the compiler's sysroot
if not specified).])],
[], [with_sysroot=no])
dnl lt_sysroot will always be passed unquoted. We quote it here
dnl in case the user passed a directory name.
lt_sysroot=
case $with_sysroot in #(
yes)
if test yes = "$GCC"; then
# Trim trailing / since we'll always append absolute paths and we want
# to avoid //, if only for less confusing output for the user.
lt_sysroot=`$CC --print-sysroot 2>/dev/null | $SED 's:/\+$::'`
fi
;; #(
/*)
lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
;; #(
no|'')
;; #(
*)
AC_MSG_RESULT([$with_sysroot])
AC_MSG_ERROR([The sysroot must be an absolute path.])
;;
esac
AC_MSG_RESULT([${lt_sysroot:-no}])
_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
[dependent libraries, and where our libraries should be installed.])])
# _LT_ENABLE_LOCK
# ---------------
m4_defun([_LT_ENABLE_LOCK],
[AC_ARG_ENABLE([libtool-lock],
[AS_HELP_STRING([--disable-libtool-lock],
[avoid locking (might break parallel builds)])])
test no = "$enable_libtool_lock" || enable_libtool_lock=yes
# Some flags need to be propagated to the compiler or linker for good
# libtool support.
case $host in
ia64-*-hpux*)
# Find out what ABI is being produced by ac_compile, and set mode
# options accordingly.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `$FILECMD conftest.$ac_objext` in
*ELF-32*)
HPUX_IA64_MODE=32
;;
*ELF-64*)
HPUX_IA64_MODE=64
;;
esac
fi
rm -rf conftest*
;;
*-*-irix6*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly.
echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
if test yes = "$lt_cv_prog_gnu_ld"; then
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
LD="${LD-ld} -melf32bsmip"
;;
*N32*)
LD="${LD-ld} -melf32bmipn32"
;;
*64-bit*)
LD="${LD-ld} -melf64bmip"
;;
esac
else
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
LD="${LD-ld} -32"
;;
*N32*)
LD="${LD-ld} -n32"
;;
*64-bit*)
LD="${LD-ld} -64"
;;
esac
fi
fi
rm -rf conftest*
;;
mips64*-*linux*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly.
echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
emul=elf
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
emul="${emul}32"
;;
*64-bit*)
emul="${emul}64"
;;
esac
case `$FILECMD conftest.$ac_objext` in
*MSB*)
emul="${emul}btsmip"
;;
*LSB*)
emul="${emul}ltsmip"
;;
esac
case `$FILECMD conftest.$ac_objext` in
*N32*)
emul="${emul}n32"
;;
esac
LD="${LD-ld} -m $emul"
fi
rm -rf conftest*
;;
x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
s390*-*linux*|s390*-*tpf*|sparc*-*linux*|x86_64-gnu*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly. Note that the listed cases only cover the
# situations where additional linker options are needed (such as when
# doing 32-bit compilation for a host where ld defaults to 64-bit, or
# vice versa); the common cases where no linker options are needed do
# not appear in the list.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `$FILECMD conftest.o` in
*32-bit*)
case $host in
x86_64-*kfreebsd*-gnu)
LD="${LD-ld} -m elf_i386_fbsd"
;;
x86_64-*linux*|x86_64-gnu*)
case `$FILECMD conftest.o` in
*x86-64*)
LD="${LD-ld} -m elf32_x86_64"
;;
*)
LD="${LD-ld} -m elf_i386"
;;
esac
;;
powerpc64le-*linux*)
LD="${LD-ld} -m elf32lppclinux"
;;
powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
LD="${LD-ld} -m elf_s390"
;;
sparc64-*linux*)
LD="${LD-ld} -m elf32_sparc"
;;
esac
;;
*64-bit*)
case $host in
x86_64-*kfreebsd*-gnu)
LD="${LD-ld} -m elf_x86_64_fbsd"
;;
x86_64-*linux*|x86_64-gnu*)
LD="${LD-ld} -m elf_x86_64"
;;
powerpcle-*linux*)
LD="${LD-ld} -m elf64lppc"
;;
powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
LD="${LD-ld} -m elf64_s390"
;;
sparc*-*linux*)
LD="${LD-ld} -m elf64_sparc"
;;
esac
;;
esac
fi
rm -rf conftest*
;;
*-*-sco3.2v5*)
# On SCO OpenServer 5, we need -belf to get full-featured binaries.
SAVE_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -belf"
AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
[AC_LANG_PUSH(C)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
AC_LANG_POP])
if test yes != "$lt_cv_cc_needs_belf"; then
# this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
CFLAGS=$SAVE_CFLAGS
fi
;;
*-*solaris*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `$FILECMD conftest.o` in
*64-bit*)
case $lt_cv_prog_gnu_ld in
yes*)
case $host in
i?86-*-solaris*|x86_64-*-solaris*)
LD="${LD-ld} -m elf_x86_64"
;;
sparc*-*-solaris*)
LD="${LD-ld} -m elf64_sparc"
;;
esac
# GNU ld 2.21 introduced _sol2 emulations. Use them if available.
if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
LD=${LD-ld}_sol2
fi
;;
*)
if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
LD="${LD-ld} -64"
fi
;;
esac
;;
esac
fi
rm -rf conftest*
;;
esac
need_locks=$enable_libtool_lock
])# _LT_ENABLE_LOCK
# _LT_PROG_AR
# -----------
m4_defun([_LT_PROG_AR],
[AC_CHECK_TOOLS(AR, [ar], false)
: ${AR=ar}
_LT_DECL([], [AR], [1], [The archiver])
# Use ARFLAGS variable as AR's operation code to sync the variable naming with
# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
# higher priority because that's what people were doing historically (setting
# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS
# variable obsoleted/removed.
test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
lt_ar_flags=$AR_FLAGS
_LT_DECL([], [lt_ar_flags], [1], [Flags to create an archive (by configure)])
# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override
# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}],
[Flags to create an archive])
AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
[lt_cv_ar_at_file=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
[echo conftest.$ac_objext > conftest.lst
lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
AC_TRY_EVAL([lt_ar_try])
if test 0 -eq "$ac_status"; then
# Ensure the archiver fails upon bogus file names.
rm -f conftest.$ac_objext libconftest.a
AC_TRY_EVAL([lt_ar_try])
if test 0 -ne "$ac_status"; then
lt_cv_ar_at_file=@
fi
fi
rm -f conftest.* libconftest.a
])
])
if test no = "$lt_cv_ar_at_file"; then
archiver_list_spec=
else
archiver_list_spec=$lt_cv_ar_at_file
fi
_LT_DECL([], [archiver_list_spec], [1],
[How to feed a file listing to the archiver])
])# _LT_PROG_AR
# _LT_CMD_OLD_ARCHIVE
# -------------------
m4_defun([_LT_CMD_OLD_ARCHIVE],
[_LT_PROG_AR
AC_CHECK_TOOL(STRIP, strip, :)
test -z "$STRIP" && STRIP=:
_LT_DECL([], [STRIP], [1], [A symbol stripping program])
AC_REQUIRE([AC_PROG_RANLIB])
test -z "$RANLIB" && RANLIB=:
_LT_DECL([], [RANLIB], [1],
[Commands used to install an old-style archive])
# Determine commands to create old-style static archives.
old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
old_postinstall_cmds='chmod 644 $oldlib'
old_postuninstall_cmds=
if test -n "$RANLIB"; then
old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
fi
case $host_os in
darwin*)
lock_old_archive_extraction=yes ;;
*)
lock_old_archive_extraction=no ;;
esac
_LT_DECL([], [old_postinstall_cmds], [2])
_LT_DECL([], [old_postuninstall_cmds], [2])
_LT_TAGDECL([], [old_archive_cmds], [2],
[Commands used to build an old-style archive])
_LT_DECL([], [lock_old_archive_extraction], [0],
[Whether to use a lock for old archive extraction])
])# _LT_CMD_OLD_ARCHIVE
# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
# ----------------------------------------------------------------
# Check whether the given compiler option works
AC_DEFUN([_LT_COMPILER_OPTION],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_SED])dnl
AC_CACHE_CHECK([$1], [$2],
[$2=no
m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment
# Insert the option either (1) after the last *FLAGS variable, or
# (2) before a word containing "conftest.", or (3) at the end.
# Note that $ac_compile itself does not contain backslashes and begins
# with a dollar sign (not a hyphen), so the echo should work correctly.
# The option is referenced via a variable to avoid confusing sed.
lt_compile=`echo "$ac_compile" | $SED \
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&AS_MESSAGE_LOG_FD
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
$ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.expsym
$SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
if test ! -s conftest.er2 || diff conftest.expsym conftest.er2 >/dev/null; then
$2=yes
fi
fi
$RM conftest*
])
if test yes = "[$]$2"; then
m4_if([$5], , :, [$5])
else
m4_if([$6], , :, [$6])
fi
])# _LT_COMPILER_OPTION
# Old name:
AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
# [ACTION-SUCCESS], [ACTION-FAILURE])
# ----------------------------------------------------
# Check whether the given linker option works
AC_DEFUN([_LT_LINKER_OPTION],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_SED])dnl
AC_CACHE_CHECK([$1], [$2],
[$2=no
save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS $3"
echo "$lt_simple_link_test_code" > conftest.$ac_ext
if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
# The linker can only warn and ignore the option if not recognized
# So say no if there are warnings
if test -s conftest.err; then
# Append any errors to the config.log.
cat conftest.err 1>&AS_MESSAGE_LOG_FD
$ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.expsym
$SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
if diff conftest.expsym conftest.er2 >/dev/null; then
$2=yes
fi
else
$2=yes
fi
fi
$RM -r conftest*
LDFLAGS=$save_LDFLAGS
])
if test yes = "[$]$2"; then
m4_if([$4], , :, [$4])
else
m4_if([$5], , :, [$5])
fi
])# _LT_LINKER_OPTION
# Old name:
AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
# LT_CMD_MAX_LEN
#---------------
AC_DEFUN([LT_CMD_MAX_LEN],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
# find the maximum length of command line arguments
AC_MSG_CHECKING([the maximum length of command line arguments])
AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
i=0
teststring=ABCD
case $build_os in
msdosdjgpp*)
# On DJGPP, this test can blow up pretty badly due to problems in libc
# (any single argument exceeding 2000 bytes causes a buffer overrun
# during glob expansion). Even if it were fixed, the result of this
# check would be larger than it should be.
lt_cv_sys_max_cmd_len=12288; # 12K is about right
;;
gnu* | ironclad*)
# Under GNU Hurd and Ironclad, this test is not required because there
# is no limit to the length of command line arguments.
# Libtool will interpret -1 as no limit whatsoever
lt_cv_sys_max_cmd_len=-1;
;;
cygwin* | mingw* | windows* | cegcc*)
# On Win9x/ME, this test blows up -- it succeeds, but takes
# about 5 minutes as the teststring grows exponentially.
# Worse, since 9x/ME are not pre-emptively multitasking,
# you end up with a "frozen" computer, even though with patience
# the test eventually succeeds (with a max line length of 256k).
# Instead, let's just punt: use the minimum linelength reported by
# all of the supported platforms: 8192 (on NT/2K/XP).
lt_cv_sys_max_cmd_len=8192;
;;
mint*)
# On MiNT this can take a long time and run out of memory.
lt_cv_sys_max_cmd_len=8192;
;;
amigaos*)
# On AmigaOS with pdksh, this test takes hours, literally.
# So we just punt and use a minimum line length of 8192.
lt_cv_sys_max_cmd_len=8192;
;;
darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
# This has been around since 386BSD, at least. Likely further.
if test -x /sbin/sysctl; then
lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
elif test -x /usr/sbin/sysctl; then
lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
else
lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
fi
# And add a safety zone
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
;;
interix*)
# We know the value 262144 and hardcode it with a safety zone (like BSD)
lt_cv_sys_max_cmd_len=196608
;;
os2*)
# The test takes a long time on OS/2.
lt_cv_sys_max_cmd_len=8192
;;
osf*)
# Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
# due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
# nice to cause kernel panics so lets avoid the loop below.
# First set a reasonable default.
lt_cv_sys_max_cmd_len=16384
#
if test -x /sbin/sysconfig; then
case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
*1*) lt_cv_sys_max_cmd_len=-1 ;;
esac
fi
;;
sco3.2v5*)
lt_cv_sys_max_cmd_len=102400
;;
sysv5* | sco5v6* | sysv4.2uw2*)
kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
if test -n "$kargmax"; then
lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[ ]]//'`
else
lt_cv_sys_max_cmd_len=32768
fi
;;
*)
lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
if test -n "$lt_cv_sys_max_cmd_len" && \
test undefined != "$lt_cv_sys_max_cmd_len"; then
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
else
# Make teststring a little bigger before we do anything with it.
# a 1K string should be a reasonable start.
for i in 1 2 3 4 5 6 7 8; do
teststring=$teststring$teststring
done
SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
# If test is not a shell built-in, we'll probably end up computing a
# maximum length that is only half of the actual maximum length, but
# we can't tell.
while { test X`env echo "$teststring$teststring" 2>/dev/null` \
= "X$teststring$teststring"; } >/dev/null 2>&1 &&
test 17 != "$i" # 1/2 MB should be enough
do
i=`expr $i + 1`
teststring=$teststring$teststring
done
# Only check the string length outside the loop.
lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
teststring=
# Add a significant safety factor because C++ compilers can tack on
# massive amounts of additional arguments before passing them to the
# linker. It appears as though 1/2 is a usable value.
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
fi
;;
esac
])
if test -n "$lt_cv_sys_max_cmd_len"; then
AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
else
AC_MSG_RESULT(none)
fi
max_cmd_len=$lt_cv_sys_max_cmd_len
_LT_DECL([], [max_cmd_len], [0],
[What is the maximum length of a command?])
])# LT_CMD_MAX_LEN
# Old name:
AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
# _LT_HEADER_DLFCN
# ----------------
m4_defun([_LT_HEADER_DLFCN],
[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
])# _LT_HEADER_DLFCN
# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
# ----------------------------------------------------------------
m4_defun([_LT_TRY_DLOPEN_SELF],
[m4_require([_LT_HEADER_DLFCN])dnl
if test yes = "$cross_compiling"; then :
[$4]
else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
[#line $LINENO "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
#include
#endif
#include
#ifdef RTLD_GLOBAL
# define LT_DLGLOBAL RTLD_GLOBAL
#else
# ifdef DL_GLOBAL
# define LT_DLGLOBAL DL_GLOBAL
# else
# define LT_DLGLOBAL 0
# endif
#endif
/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
find out it does not work in some platform. */
#ifndef LT_DLLAZY_OR_NOW
# ifdef RTLD_LAZY
# define LT_DLLAZY_OR_NOW RTLD_LAZY
# else
# ifdef DL_LAZY
# define LT_DLLAZY_OR_NOW DL_LAZY
# else
# ifdef RTLD_NOW
# define LT_DLLAZY_OR_NOW RTLD_NOW
# else
# ifdef DL_NOW
# define LT_DLLAZY_OR_NOW DL_NOW
# else
# define LT_DLLAZY_OR_NOW 0
# endif
# endif
# endif
# endif
#endif
/* When -fvisibility=hidden is used, assume the code has been annotated
correspondingly for the symbols needed. */
#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
int fnord (void) __attribute__((visibility("default")));
#endif
int fnord (void) { return 42; }
int main (void)
{
void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
int status = $lt_dlunknown;
if (self)
{
if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
else
{
if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
else puts (dlerror ());
}
/* dlclose (self); */
}
else
puts (dlerror ());
return status;
}]
_LT_EOF
if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then
(./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
lt_status=$?
case x$lt_status in
x$lt_dlno_uscore) $1 ;;
x$lt_dlneed_uscore) $2 ;;
x$lt_dlunknown|x*) $3 ;;
esac
else :
# compilation failed
$3
fi
fi
rm -fr conftest*
])# _LT_TRY_DLOPEN_SELF
# LT_SYS_DLOPEN_SELF
# ------------------
AC_DEFUN([LT_SYS_DLOPEN_SELF],
[m4_require([_LT_HEADER_DLFCN])dnl
if test yes != "$enable_dlopen"; then
enable_dlopen=unknown
enable_dlopen_self=unknown
enable_dlopen_self_static=unknown
else
lt_cv_dlopen=no
lt_cv_dlopen_libs=
case $host_os in
beos*)
lt_cv_dlopen=load_add_on
lt_cv_dlopen_libs=
lt_cv_dlopen_self=yes
;;
mingw* | windows* | pw32* | cegcc*)
lt_cv_dlopen=LoadLibrary
lt_cv_dlopen_libs=
;;
cygwin*)
lt_cv_dlopen=dlopen
lt_cv_dlopen_libs=
;;
darwin*)
# if libdl is installed we need to link against it
AC_CHECK_LIB([dl], [dlopen],
[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[
lt_cv_dlopen=dyld
lt_cv_dlopen_libs=
lt_cv_dlopen_self=yes
])
;;
tpf*)
# Don't try to run any link tests for TPF. We know it's impossible
# because TPF is a cross-compiler, and we know how we open DSOs.
lt_cv_dlopen=dlopen
lt_cv_dlopen_libs=
lt_cv_dlopen_self=no
;;
*)
AC_CHECK_FUNC([shl_load],
[lt_cv_dlopen=shl_load],
[AC_CHECK_LIB([dld], [shl_load],
[lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld],
[AC_CHECK_FUNC([dlopen],
[lt_cv_dlopen=dlopen],
[AC_CHECK_LIB([dl], [dlopen],
[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],
[AC_CHECK_LIB([svld], [dlopen],
[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld],
[AC_CHECK_LIB([dld], [dld_link],
[lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld])
])
])
])
])
])
;;
esac
if test no = "$lt_cv_dlopen"; then
enable_dlopen=no
else
enable_dlopen=yes
fi
case $lt_cv_dlopen in
dlopen)
save_CPPFLAGS=$CPPFLAGS
test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
save_LDFLAGS=$LDFLAGS
wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
save_LIBS=$LIBS
LIBS="$lt_cv_dlopen_libs $LIBS"
AC_CACHE_CHECK([whether a program can dlopen itself],
lt_cv_dlopen_self, [dnl
_LT_TRY_DLOPEN_SELF(
lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
])
if test yes = "$lt_cv_dlopen_self"; then
wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
lt_cv_dlopen_self_static, [dnl
_LT_TRY_DLOPEN_SELF(
lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
])
fi
CPPFLAGS=$save_CPPFLAGS
LDFLAGS=$save_LDFLAGS
LIBS=$save_LIBS
;;
esac
case $lt_cv_dlopen_self in
yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
*) enable_dlopen_self=unknown ;;
esac
case $lt_cv_dlopen_self_static in
yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
*) enable_dlopen_self_static=unknown ;;
esac
fi
_LT_DECL([dlopen_support], [enable_dlopen], [0],
[Whether dlopen is supported])
_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
[Whether dlopen of programs is supported])
_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
[Whether dlopen of statically linked programs is supported])
])# LT_SYS_DLOPEN_SELF
# Old name:
AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
# _LT_COMPILER_C_O([TAGNAME])
# ---------------------------
# Check to see if options -c and -o are simultaneously supported by compiler.
# This macro does not hard code the compiler like AC_PROG_CC_C_O.
m4_defun([_LT_COMPILER_C_O],
[m4_require([_LT_DECL_SED])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_TAG_COMPILER])dnl
AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
[_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
[_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
$RM -r conftest 2>/dev/null
mkdir conftest
cd conftest
mkdir out
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
lt_compiler_flag="-o out/conftest2.$ac_objext"
# Insert the option either (1) after the last *FLAGS variable, or
# (2) before a word containing "conftest.", or (3) at the end.
# Note that $ac_compile itself does not contain backslashes and begins
# with a dollar sign (not a hyphen), so the echo should work correctly.
lt_compile=`echo "$ac_compile" | $SED \
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&AS_MESSAGE_LOG_FD
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
$ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.expsym
$SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
if test ! -s out/conftest.er2 || diff out/conftest.expsym out/conftest.er2 >/dev/null; then
_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
fi
fi
chmod u+w . 2>&AS_MESSAGE_LOG_FD
$RM conftest*
# SGI C++ compiler will create directory out/ii_files/ for
# template instantiation
test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
$RM out/* && rmdir out
cd ..
$RM -r conftest
$RM conftest*
])
_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
[Does compiler simultaneously support -c and -o options?])
])# _LT_COMPILER_C_O
# _LT_COMPILER_FILE_LOCKS([TAGNAME])
# ----------------------------------
# Check to see if we can do hard links to lock some files if needed
m4_defun([_LT_COMPILER_FILE_LOCKS],
[m4_require([_LT_ENABLE_LOCK])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
_LT_COMPILER_C_O([$1])
hard_links=nottested
if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then
# do not overwrite the value of need_locks provided by the user
AC_MSG_CHECKING([if we can lock with hard links])
hard_links=yes
$RM conftest*
ln conftest.a conftest.b 2>/dev/null && hard_links=no
touch conftest.a
ln conftest.a conftest.b 2>&5 || hard_links=no
ln conftest.a conftest.b 2>/dev/null && hard_links=no
AC_MSG_RESULT([$hard_links])
if test no = "$hard_links"; then
AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe])
need_locks=warn
fi
else
need_locks=no
fi
_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
])# _LT_COMPILER_FILE_LOCKS
# _LT_CHECK_OBJDIR
# ----------------
m4_defun([_LT_CHECK_OBJDIR],
[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
[rm -f .libs 2>/dev/null
mkdir .libs 2>/dev/null
if test -d .libs; then
lt_cv_objdir=.libs
else
# MS-DOS does not allow filenames that begin with a dot.
lt_cv_objdir=_libs
fi
rmdir .libs 2>/dev/null])
objdir=$lt_cv_objdir
_LT_DECL([], [objdir], [0],
[The name of the directory that contains temporary libtool files])dnl
m4_pattern_allow([LT_OBJDIR])dnl
AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/",
[Define to the sub-directory where libtool stores uninstalled libraries.])
])# _LT_CHECK_OBJDIR
# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
# --------------------------------------
# Check hardcoding attributes.
m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
[AC_MSG_CHECKING([how to hardcode library paths into programs])
_LT_TAGVAR(hardcode_action, $1)=
if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
test -n "$_LT_TAGVAR(runpath_var, $1)" ||
test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then
# We can hardcode non-existent directories.
if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
# If the only mechanism to avoid hardcoding is shlibpath_var, we
# have to relink, otherwise we might link with an installed library
# when we should be linking with a yet-to-be-installed one
## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then
# Linking always hardcodes the temporary library directory.
_LT_TAGVAR(hardcode_action, $1)=relink
else
# We can link without hardcoding, and we can hardcode nonexisting dirs.
_LT_TAGVAR(hardcode_action, $1)=immediate
fi
else
# We cannot hardcode anything, or else we can only hardcode existing
# directories.
_LT_TAGVAR(hardcode_action, $1)=unsupported
fi
AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
if test relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
# Fast installation is not supported
enable_fast_install=no
elif test yes = "$shlibpath_overrides_runpath" ||
test no = "$enable_shared"; then
# Fast installation is not necessary
enable_fast_install=needless
fi
_LT_TAGDECL([], [hardcode_action], [0],
[How to hardcode a shared library path into an executable])
])# _LT_LINKER_HARDCODE_LIBPATH
# _LT_CMD_STRIPLIB
# ----------------
m4_defun([_LT_CMD_STRIPLIB],
[m4_require([_LT_DECL_EGREP])
striplib=
old_striplib=
AC_MSG_CHECKING([whether stripping libraries is possible])
if test -z "$STRIP"; then
AC_MSG_RESULT([no])
else
if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
old_striplib="$STRIP --strip-debug"
striplib="$STRIP --strip-unneeded"
AC_MSG_RESULT([yes])
else
case $host_os in
darwin*)
# FIXME - insert some real tests, host_os isn't really good enough
striplib="$STRIP -x"
old_striplib="$STRIP -S"
AC_MSG_RESULT([yes])
;;
freebsd*)
if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
old_striplib="$STRIP --strip-debug"
striplib="$STRIP --strip-unneeded"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
;;
*)
AC_MSG_RESULT([no])
;;
esac
fi
fi
_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
_LT_DECL([], [striplib], [1])
])# _LT_CMD_STRIPLIB
# _LT_PREPARE_MUNGE_PATH_LIST
# ---------------------------
# Make sure func_munge_path_list() is defined correctly.
m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
[[# func_munge_path_list VARIABLE PATH
# -----------------------------------
# VARIABLE is name of variable containing _space_ separated list of
# directories to be munged by the contents of PATH, which is string
# having a format:
# "DIR[:DIR]:"
# string "DIR[ DIR]" will be prepended to VARIABLE
# ":DIR[:DIR]"
# string "DIR[ DIR]" will be appended to VARIABLE
# "DIRP[:DIRP]::[DIRA:]DIRA"
# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
# "DIRA[ DIRA]" will be appended to VARIABLE
# "DIR[:DIR]"
# VARIABLE will be replaced by "DIR[ DIR]"
func_munge_path_list ()
{
case x@S|@2 in
x)
;;
*:)
eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\"
;;
x:*)
eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
;;
*::*)
eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\"
;;
*)
eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
;;
esac
}
]])# _LT_PREPARE_PATH_LIST
# _LT_SYS_DYNAMIC_LINKER([TAG])
# -----------------------------
# PORTME Fill in your ld.so characteristics
m4_defun([_LT_SYS_DYNAMIC_LINKER],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_OBJDUMP])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_CHECK_SHELL_FEATURES])dnl
m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
AC_MSG_CHECKING([dynamic linker characteristics])
m4_if([$1],
[], [
if test yes = "$GCC"; then
case $host_os in
darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
*) lt_awk_arg='/^libraries:/' ;;
esac
case $host_os in
mingw* | windows* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;;
*) lt_sed_strip_eq='s|=/|/|g' ;;
esac
lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
case $lt_search_path_spec in
*\;*)
# if the path contains ";" then we assume it to be the separator
# otherwise default to the standard path separator (i.e. ":") - it is
# assumed that no part of a normal pathname contains ";" but that should
# okay in the real world where ";" in dirpaths is itself problematic.
lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
;;
*)
lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
;;
esac
# Ok, now we have the path, separated by spaces, we can step through it
# and add multilib dir if necessary...
lt_tmp_lt_search_path_spec=
lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
# ...but if some path component already ends with the multilib dir we assume
# that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
case "$lt_multi_os_dir; $lt_search_path_spec " in
"/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
lt_multi_os_dir=
;;
esac
for lt_sys_path in $lt_search_path_spec; do
if test -d "$lt_sys_path$lt_multi_os_dir"; then
lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
elif test -n "$lt_multi_os_dir"; then
test -d "$lt_sys_path" && \
lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
fi
done
lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
BEGIN {RS = " "; FS = "/|\n";} {
lt_foo = "";
lt_count = 0;
for (lt_i = NF; lt_i > 0; lt_i--) {
if ($lt_i != "" && $lt_i != ".") {
if ($lt_i == "..") {
lt_count++;
} else {
if (lt_count == 0) {
lt_foo = "/" $lt_i lt_foo;
} else {
lt_count--;
}
}
}
}
if (lt_foo != "") { lt_freq[[lt_foo]]++; }
if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
}'`
# AWK program above erroneously prepends '/' to C:/dos/paths
# for these hosts.
case $host_os in
mingw* | windows* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
$SED 's|/\([[A-Za-z]]:\)|\1|g'` ;;
esac
sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
else
sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
fi])
library_names_spec=
libname_spec='lib$name'
soname_spec=
shrext_cmds=.so
postinstall_cmds=
postuninstall_cmds=
finish_cmds=
finish_eval=
shlibpath_var=
shlibpath_overrides_runpath=unknown
version_type=none
dynamic_linker="$host_os ld.so"
sys_lib_dlsearch_path_spec="/lib /usr/lib"
need_lib_prefix=unknown
hardcode_into_libs=no
# when you set need_version to no, make sure it does not cause -set_version
# flags to be left without arguments
need_version=unknown
AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
[User-defined run-time library search path.])
case $host_os in
aix3*)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
shlibpath_var=LIBPATH
# AIX 3 has no versioning support, so we append a major version to the name.
soname_spec='$libname$release$shared_ext$major'
;;
aix[[4-9]]*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
hardcode_into_libs=yes
if test ia64 = "$host_cpu"; then
# AIX 5 supports IA64
library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
else
# With GCC up to 2.95.x, collect2 would create an import file
# for dependence libraries. The import file would start with
# the line '#! .'. This would cause the generated library to
# depend on '.', always an invalid library. This was fixed in
# development snapshots of GCC prior to 3.0.
case $host_os in
aix4 | aix4.[[01]] | aix4.[[01]].*)
if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
echo ' yes '
echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
:
else
can_build_shared=no
fi
;;
esac
# Using Import Files as archive members, it is possible to support
# filename-based versioning of shared library archives on AIX. While
# this would work for both with and without runtime linking, it will
# prevent static linking of such archives. So we do filename-based
# shared library versioning with .so extension only, which is used
# when both runtime linking and shared linking is enabled.
# Unfortunately, runtime linking may impact performance, so we do
# not want this to be the default eventually. Also, we use the
# versioned .so libs for executables only if there is the -brtl
# linker flag in LDFLAGS as well, or --enable-aix-soname=svr4 only.
# To allow for filename-based versioning support, we need to create
# libNAME.so.V as an archive file, containing:
# *) an Import File, referring to the versioned filename of the
# archive as well as the shared archive member, telling the
# bitwidth (32 or 64) of that shared object, and providing the
# list of exported symbols of that shared object, eventually
# decorated with the 'weak' keyword
# *) the shared object with the F_LOADONLY flag set, to really avoid
# it being seen by the linker.
# At run time we better use the real file rather than another symlink,
# but for link time we create the symlink libNAME.so -> libNAME.so.V
case $with_aix_soname,$aix_use_runtimelinking in
# AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
# soname into executable. Probably we can add versioning support to
# collect2, so additional links can be useful in future.
aix,yes) # traditional libtool
dynamic_linker='AIX unversionable lib.so'
# If using run time linking (on AIX 4.2 or later) use lib.so
# instead of lib.a to let people know that these are not
# typical AIX shared libraries.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
;;
aix,no) # traditional AIX only
dynamic_linker='AIX lib.a[(]lib.so.V[)]'
# We preserve .a as extension for shared libraries through AIX4.2
# and later when we are not doing run time linking.
library_names_spec='$libname$release.a $libname.a'
soname_spec='$libname$release$shared_ext$major'
;;
svr4,*) # full svr4 only
dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
# We do not specify a path in Import Files, so LIBPATH fires.
shlibpath_overrides_runpath=yes
;;
*,yes) # both, prefer svr4
dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
# unpreferred sharedlib libNAME.a needs extra handling
postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
# We do not specify a path in Import Files, so LIBPATH fires.
shlibpath_overrides_runpath=yes
;;
*,no) # both, prefer aix
dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
library_names_spec='$libname$release.a $libname.a'
soname_spec='$libname$release$shared_ext$major'
# unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
;;
esac
shlibpath_var=LIBPATH
fi
;;
amigaos*)
case $host_cpu in
powerpc)
# Since July 2007 AmigaOS4 officially supports .so libraries.
# When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
;;
m68k)
library_names_spec='$libname.ixlibrary $libname.a'
# Create ${libname}_ixlibrary.a entries in /sys/libs.
finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
;;
esac
;;
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"
shlibpath_var=LIBRARY_PATH
;;
bsdi[[45]]*)
version_type=linux # correct to gnu/linux during the next big refactor
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
shlibpath_var=LD_LIBRARY_PATH
sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
# the default ld.so.conf also contains /usr/contrib/lib and
# /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
# libtool to hard-code these into programs
;;
cygwin* | mingw* | windows* | pw32* | cegcc*)
version_type=windows
shrext_cmds=.dll
need_version=no
need_lib_prefix=no
case $GCC,$cc_basename in
yes,*)
# gcc
library_names_spec='$libname.dll.a'
# DLL is installed to $(libdir)/../bin by postinstall_cmds
# If user builds GCC with multilib enabled,
# it should just install on $(libdir)
# not on $(libdir)/../bin or 32 bits dlls would override 64 bit ones.
if test xyes = x"$multilib"; then
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
$install_prog $dir/$dlname $destdir/$dlname~
chmod a+x $destdir/$dlname~
if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
eval '\''$striplib $destdir/$dlname'\'' || exit \$?;
fi'
else
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname~
chmod a+x \$dldir/$dlname~
if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
fi'
fi
postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
dlpath=$dir/\$dldll~
$RM \$dlpath'
shlibpath_overrides_runpath=yes
case $host_os in
cygwin*)
# Cygwin DLLs use 'cyg' prefix rather than 'lib'
soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
m4_if([$1], [],[
sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
;;
mingw* | windows* | cegcc*)
# MinGW DLLs use traditional 'lib' prefix
soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
;;
pw32*)
# pw32 DLLs use 'pw' prefix rather than 'lib'
library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
;;
esac
dynamic_linker='Win32 ld.exe'
;;
*,cl* | *,icl* | *,icx*)
# Native MSVC and Intel compilers
libname_spec='$name'
soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
library_names_spec='$libname.dll.lib'
case $build_os in
mingw* | windows*)
sys_lib_search_path_spec=
lt_save_ifs=$IFS
IFS=';'
for lt_path in $LIB
do
IFS=$lt_save_ifs
# Let DOS variable expansion print the short 8.3 style file name.
lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
done
IFS=$lt_save_ifs
# Convert to MSYS style.
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
;;
cygwin*)
# Convert to unix form, then to dos form, then back to unix form
# but this time dos style (no spaces!) so that the unix form looks
# like /cygdrive/c/PROGRA~1:/cygdr...
sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
;;
*)
sys_lib_search_path_spec=$LIB
if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
# It is most probably a Windows format PATH.
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
else
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
fi
# FIXME: find the short name or the path components, as spaces are
# common. (e.g. "Program Files" -> "PROGRA~1")
;;
esac
# DLL is installed to $(libdir)/../bin by postinstall_cmds
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname'
postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
dlpath=$dir/\$dldll~
$RM \$dlpath'
shlibpath_overrides_runpath=yes
dynamic_linker='Win32 link.exe'
;;
*)
# Assume MSVC and ICC wrapper
library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
dynamic_linker='Win32 ld.exe'
;;
esac
# FIXME: first we should search . and the directory the executable is in
shlibpath_var=PATH
;;
darwin* | rhapsody*)
dynamic_linker="$host_os dyld"
version_type=darwin
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
soname_spec='$libname$release$major$shared_ext'
shlibpath_overrides_runpath=yes
shlibpath_var=DYLD_LIBRARY_PATH
shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
m4_if([$1], [],[
sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
;;
dgux*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
;;
freebsd* | dragonfly* | midnightbsd*)
# DragonFly does not have aout. When/if they implement a new
# versioning mechanism, adjust this.
if test -x /usr/bin/objformat; then
objformat=`/usr/bin/objformat`
else
case $host_os in
freebsd[[23]].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
version_type=freebsd-$objformat
case $version_type in
freebsd-elf*)
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
need_version=no
need_lib_prefix=no
;;
freebsd-*)
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
need_version=yes
;;
esac
case $host_cpu in
powerpc64)
# On FreeBSD bi-arch platforms, a different variable is used for 32-bit
# binaries. See .
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE(
[[int test_pointer_size[sizeof (void *) - 5];
]])],
[shlibpath_var=LD_LIBRARY_PATH],
[shlibpath_var=LD_32_LIBRARY_PATH])
;;
*)
shlibpath_var=LD_LIBRARY_PATH
;;
esac
case $host_os in
freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[[01]]* | freebsdelf3.[[01]]*)
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
;;
freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
*) # from 4.6 on, and DragonFly
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
;;
esac
;;
haiku*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
dynamic_linker="$host_os runtime_loader"
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LIBRARY_PATH
shlibpath_overrides_runpath=no
sys_lib_search_path_spec='/boot/system/non-packaged/develop/lib /boot/system/develop/lib'
sys_lib_dlsearch_path_spec='/boot/home/config/non-packaged/lib /boot/home/config/lib /boot/system/non-packaged/lib /boot/system/lib'
hardcode_into_libs=no
;;
hpux9* | hpux10* | hpux11*)
# Give a soname corresponding to the major version so that dld.sl refuses to
# link against other versions.
version_type=sunos
need_lib_prefix=no
need_version=no
case $host_cpu in
ia64*)
shrext_cmds='.so'
hardcode_into_libs=yes
dynamic_linker="$host_os dld.so"
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
if test 32 = "$HPUX_IA64_MODE"; then
sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
sys_lib_dlsearch_path_spec=/usr/lib/hpux32
else
sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
sys_lib_dlsearch_path_spec=/usr/lib/hpux64
fi
;;
hppa*64*)
shrext_cmds='.sl'
hardcode_into_libs=yes
dynamic_linker="$host_os dld.sl"
shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
;;
*)
shrext_cmds='.sl'
dynamic_linker="$host_os dld.sl"
shlibpath_var=SHLIB_PATH
shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
;;
esac
# HP-UX runs *really* slowly unless shared libraries are mode 555, ...
postinstall_cmds='chmod 555 $lib'
# or fails outright, so override atomically:
install_override_mode=555
;;
interix[[3-9]]*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
irix5* | irix6* | nonstopux*)
case $host_os in
nonstopux*) version_type=nonstopux ;;
*)
if test yes = "$lt_cv_prog_gnu_ld"; then
version_type=linux # correct to gnu/linux during the next big refactor
else
version_type=irix
fi ;;
esac
need_lib_prefix=no
need_version=no
soname_spec='$libname$release$shared_ext$major'
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
case $host_os in
irix5* | nonstopux*)
libsuff= shlibsuff=
;;
*)
case $LD in # libtool.m4 will add one of these switches to LD
*-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
libsuff= shlibsuff= libmagic=32-bit;;
*-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
libsuff=32 shlibsuff=N32 libmagic=N32;;
*-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
libsuff=64 shlibsuff=64 libmagic=64-bit;;
*) libsuff= shlibsuff= libmagic=never-match;;
esac
;;
esac
shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
shlibpath_overrides_runpath=no
sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
hardcode_into_libs=yes
;;
*-mlibc)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
dynamic_linker='mlibc ld.so'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
# No shared lib support for Linux oldld, aout, or coff.
linux*oldld* | linux*aout* | linux*coff*)
dynamic_linker=no
;;
linux*android*)
version_type=none # Android doesn't support versioned libraries.
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext $libname$shared_ext'
soname_spec='$libname$release$shared_ext'
finish_cmds=
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
# This implies no fast_install, which is unacceptable.
# Some rework will be needed to allow for fast_install
# before this can be enabled.
hardcode_into_libs=yes
dynamic_linker='Android linker'
# -rpath works at least for libraries that are not overridden by
# libraries installed in system locations.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
;;
# This must be glibc/ELF.
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
# Some binutils ld are patched to set DT_RUNPATH
AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
[lt_cv_shlibpath_overrides_runpath=no
save_LDFLAGS=$LDFLAGS
save_libdir=$libdir
eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
[AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
[lt_cv_shlibpath_overrides_runpath=yes])])
LDFLAGS=$save_LDFLAGS
libdir=$save_libdir
])
shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
# This implies no fast_install, which is unacceptable.
# Some rework will be needed to allow for fast_install
# before this can be enabled.
hardcode_into_libs=yes
# Ideally, we could use ldconfig to report *all* directories which are
# searched for libraries, however this is still not possible. Aside from not
# being certain /sbin/ldconfig is available, command
# 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
# even though it is searched at run-time. Try to do the best guess by
# appending ld.so.conf contents (and includes) to the search path.
if test -f /etc/ld.so.conf; then
lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
fi
# We used to test for /lib/ld.so.1 and disable shared libraries on
# powerpc, because MkLinux only supported shared libraries with the
# GNU dynamic linker. Since this was broken with cross compilers,
# most powerpc-linux boxes support dynamic linking these days and
# people can always --disable-shared, the test was removed, and we
# assume the GNU/Linux dynamic linker is in use.
dynamic_linker='GNU/Linux ld.so'
;;
netbsdelf*-gnu)
version_type=linux
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
dynamic_linker='NetBSD ld.elf_so'
enable_cxx_stdlib=yes
stdlibflag=
;;
netbsd*)
version_type=sunos
need_lib_prefix=no
need_version=no
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
dynamic_linker='NetBSD (a.out) ld.so'
else
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
dynamic_linker='NetBSD ld.elf_so'
fi
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
enable_cxx_stdlib=yes
stdlibflag=
;;
newsos6)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
;;
*nto* | *qnx*)
version_type=qnx
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
dynamic_linker='ldqnx.so'
;;
openbsd*)
version_type=sunos
sys_lib_dlsearch_path_spec=/usr/lib
need_lib_prefix=no
if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
need_version=no
else
need_version=yes
fi
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
;;
os2*)
libname_spec='$name'
version_type=windows
shrext_cmds=.dll
need_version=no
need_lib_prefix=no
# OS/2 can only load a DLL with a base name of 8 characters or less.
soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
v=$($ECHO $release$versuffix | tr -d .-);
n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
$ECHO $n$v`$shared_ext'
library_names_spec='${libname}_dll.$libext'
dynamic_linker='OS/2 ld.exe'
shlibpath_var=BEGINLIBPATH
sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname~
chmod a+x \$dldir/$dlname~
if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
fi'
postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
dlpath=$dir/\$dldll~
$RM \$dlpath'
;;
osf3* | osf4* | osf5*)
version_type=osf
need_lib_prefix=no
need_version=no
soname_spec='$libname$release$shared_ext$major'
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
;;
rdos*)
dynamic_linker=no
;;
serenity*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
dynamic_linker='SerenityOS LibELF'
;;
solaris*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
# ldd complains unless libraries are executable
postinstall_cmds='chmod +x $lib'
;;
sunos4*)
version_type=sunos
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
if test yes = "$with_gnu_ld"; then
need_lib_prefix=no
fi
need_version=yes
;;
sysv4 | sysv4.3*)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
case $host_vendor in
sni)
shlibpath_overrides_runpath=no
need_lib_prefix=no
runpath_var=LD_RUN_PATH
;;
siemens)
need_lib_prefix=no
;;
motorola)
need_lib_prefix=no
need_version=no
shlibpath_overrides_runpath=no
sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
;;
esac
;;
sysv4*MP*)
if test -d /usr/nec; then
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
soname_spec='$libname$shared_ext.$major'
shlibpath_var=LD_LIBRARY_PATH
fi
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
version_type=sco
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
if test yes = "$with_gnu_ld"; then
sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
else
sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
case $host_os in
sco3.2v5*)
sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
;;
esac
fi
sys_lib_dlsearch_path_spec='/usr/lib'
;;
tpf*)
# TPF is a cross-target only. Preferred cross-host = GNU/Linux.
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
uts4*)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
;;
emscripten*)
version_type=none
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext'
soname_spec='$libname$release$shared_ext'
finish_cmds=
dynamic_linker="Emscripten linker"
_LT_COMPILER_PIC($1)='-fPIC'
_LT_TAGVAR(archive_cmds, $1)='$CC -sSIDE_MODULE=2 -shared $libobjs $deplibs $compiler_flags -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -sSIDE_MODULE=2 -shared $libobjs $deplibs $compiler_flags -o $lib -s EXPORTED_FUNCTIONS=@$output_objdir/$soname.expsym'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(no_undefined_flag, $1)=
;;
*)
dynamic_linker=no
;;
esac
AC_MSG_RESULT([$dynamic_linker])
test no = "$dynamic_linker" && can_build_shared=no
variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
if test yes = "$GCC"; then
variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
fi
if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
fi
if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
fi
# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
_LT_DECL([], [variables_saved_for_relink], [1],
[Variables whose values should be saved in libtool wrapper scripts and
restored at link time])
_LT_DECL([], [need_lib_prefix], [0],
[Do we need the "lib" prefix for modules?])
_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
_LT_DECL([], [version_type], [0], [Library versioning type])
_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
_LT_DECL([], [shlibpath_overrides_runpath], [0],
[Is shlibpath searched before the hard-coded library search path?])
_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
_LT_DECL([], [library_names_spec], [1],
[[List of archive names. First name is the real one, the rest are links.
The last name is the one that the linker finds with -lNAME]])
_LT_DECL([], [soname_spec], [1],
[[The coded name of the library, if different from the real name]])
_LT_DECL([], [install_override_mode], [1],
[Permission mode override for installation of shared libraries])
_LT_DECL([], [postinstall_cmds], [2],
[Command to use after installation of a shared archive])
_LT_DECL([], [postuninstall_cmds], [2],
[Command to use after uninstallation of a shared archive])
_LT_DECL([], [finish_cmds], [2],
[Commands used to finish a libtool library installation in a directory])
_LT_DECL([], [finish_eval], [1],
[[As "finish_cmds", except a single script fragment to be evaled but
not shown]])
_LT_DECL([], [hardcode_into_libs], [0],
[Whether we should hardcode library paths into libraries])
_LT_DECL([], [sys_lib_search_path_spec], [2],
[Compile-time system search path for libraries])
_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2],
[Detected run-time system search path for libraries])
_LT_DECL([], [configure_time_lt_sys_library_path], [2],
[Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
])# _LT_SYS_DYNAMIC_LINKER
# _LT_PATH_TOOL_PREFIX(TOOL)
# --------------------------
# find a file program that can recognize shared library
AC_DEFUN([_LT_PATH_TOOL_PREFIX],
[m4_require([_LT_DECL_EGREP])dnl
AC_MSG_CHECKING([for $1])
AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
[case $MAGIC_CMD in
[[\\/*] | ?:[\\/]*])
lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
;;
*)
lt_save_MAGIC_CMD=$MAGIC_CMD
lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
dnl $ac_dummy forces splitting on constant user-supplied paths.
dnl POSIX.2 word splitting is done only on the output of word expansions,
dnl not every word. This closes a longstanding sh security hole.
ac_dummy="m4_if([$2], , $PATH, [$2])"
for ac_dir in $ac_dummy; do
IFS=$lt_save_ifs
test -z "$ac_dir" && ac_dir=.
if test -f "$ac_dir/$1"; then
lt_cv_path_MAGIC_CMD=$ac_dir/"$1"
if test -n "$file_magic_test_file"; then
case $deplibs_check_method in
"file_magic "*)
file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
MAGIC_CMD=$lt_cv_path_MAGIC_CMD
if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
$EGREP "$file_magic_regex" > /dev/null; then
:
else
cat <<_LT_EOF 1>&2
*** Warning: the command libtool uses to detect shared libraries,
*** $file_magic_cmd, produces output that libtool cannot recognize.
*** The result is that libtool may fail to recognize shared libraries
*** as such. This will affect the creation of libtool libraries that
*** depend on shared libraries, but programs linked with such libtool
*** libraries will work regardless of this problem. Nevertheless, you
*** may want to report the problem to your system manager and/or to
*** bug-libtool@gnu.org
_LT_EOF
fi ;;
esac
fi
break
fi
done
IFS=$lt_save_ifs
MAGIC_CMD=$lt_save_MAGIC_CMD
;;
esac])
MAGIC_CMD=$lt_cv_path_MAGIC_CMD
if test -n "$MAGIC_CMD"; then
AC_MSG_RESULT($MAGIC_CMD)
else
AC_MSG_RESULT(no)
fi
_LT_DECL([], [MAGIC_CMD], [0],
[Used to examine libraries when file_magic_cmd begins with "file"])dnl
])# _LT_PATH_TOOL_PREFIX
# Old name:
AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
# _LT_PATH_MAGIC
# --------------
# find a file program that can recognize a shared library
m4_defun([_LT_PATH_MAGIC],
[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
if test -z "$lt_cv_path_MAGIC_CMD"; then
if test -n "$ac_tool_prefix"; then
_LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
else
MAGIC_CMD=:
fi
fi
])# _LT_PATH_MAGIC
# LT_PATH_LD
# ----------
# find the pathname to the GNU or non-GNU linker
AC_DEFUN([LT_PATH_LD],
[AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
AC_ARG_WITH([gnu-ld],
[AS_HELP_STRING([--with-gnu-ld],
[assume the C compiler uses GNU ld @<:@default=no@:>@])],
[test no = "$withval" || with_gnu_ld=yes],
[with_gnu_ld=no])dnl
ac_prog=ld
if test yes = "$GCC"; then
# Check if gcc -print-prog-name=ld gives a path.
AC_MSG_CHECKING([for ld used by $CC])
case $host in
*-*-mingw* | *-*-windows*)
# gcc leaves a trailing carriage return, which upsets mingw
ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
*)
ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
esac
case $ac_prog in
# Accept absolute paths.
[[\\/]]* | ?:[[\\/]]*)
re_direlt='/[[^/]][[^/]]*/\.\./'
# Canonicalize the pathname of ld
ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
done
test -z "$LD" && LD=$ac_prog
;;
"")
# If it fails, then pretend we aren't using GCC.
ac_prog=ld
;;
*)
# If it is relative, then search for the first ld in PATH.
with_gnu_ld=unknown
;;
esac
elif test yes = "$with_gnu_ld"; then
AC_MSG_CHECKING([for GNU ld])
else
AC_MSG_CHECKING([for non-GNU ld])
fi
AC_CACHE_VAL(lt_cv_path_LD,
[if test -z "$LD"; then
lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
for ac_dir in $PATH; do
IFS=$lt_save_ifs
test -z "$ac_dir" && ac_dir=.
if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
lt_cv_path_LD=$ac_dir/$ac_prog
# Check to see if the program is GNU ld. I'd rather use --version,
# but apparently some variants of GNU ld only accept -v.
# Break only if it was the GNU/non-GNU ld that we prefer.
case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i
cat conftest.i conftest.i >conftest2.i
: ${lt_DD:=$DD}
AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
cmp -s conftest.i conftest.out \
&& ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
fi])
rm -f conftest.i conftest2.i conftest.out])
])# _LT_PATH_DD
# _LT_CMD_TRUNCATE
# ----------------
# find command to truncate a binary pipe
m4_defun([_LT_CMD_TRUNCATE],
[m4_require([_LT_PATH_DD])
AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
[printf 0123456789abcdef0123456789abcdef >conftest.i
cat conftest.i conftest.i >conftest2.i
lt_cv_truncate_bin=
if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
cmp -s conftest.i conftest.out \
&& lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
fi
rm -f conftest.i conftest2.i conftest.out
test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
[Command to truncate a binary pipe])
])# _LT_CMD_TRUNCATE
# _LT_CHECK_MAGIC_METHOD
# ----------------------
# how to check for library dependencies
# -- PORTME fill in with the dynamic library characteristics
m4_defun([_LT_CHECK_MAGIC_METHOD],
[m4_require([_LT_DECL_EGREP])
m4_require([_LT_DECL_OBJDUMP])
AC_CACHE_CHECK([how to recognize dependent libraries],
lt_cv_deplibs_check_method,
[lt_cv_file_magic_cmd='$MAGIC_CMD'
lt_cv_file_magic_test_file=
lt_cv_deplibs_check_method='unknown'
# Need to set the preceding variable on all platforms that support
# interlibrary dependencies.
# 'none' -- dependencies not supported.
# 'unknown' -- same as none, but documents that we really don't know.
# 'pass_all' -- all dependencies passed with no checks.
# 'file_magic [[regex]]' -- check by looking for files in library path
# that responds to the $file_magic_cmd with a given extended regex.
# If you have 'file' or equivalent on your system and you're not sure
# whether 'pass_all' will *always* work, you probably want this one.
case $host_os in
aix[[4-9]]*)
lt_cv_deplibs_check_method=pass_all
;;
beos*)
lt_cv_deplibs_check_method=pass_all
;;
bsdi[[45]]*)
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
lt_cv_file_magic_cmd='$FILECMD -L'
lt_cv_file_magic_test_file=/shlib/libc.so
;;
cygwin*)
# func_win32_libid is a shell function defined in ltmain.sh
lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
lt_cv_file_magic_cmd='func_win32_libid'
;;
mingw* | windows* | pw32*)
# Base MSYS/MinGW do not provide the 'file' command needed by
# func_win32_libid shell function, so use a weaker test based on 'objdump',
# unless we find 'file', for example because we are cross-compiling.
if ( file / ) >/dev/null 2>&1; then
lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
lt_cv_file_magic_cmd='func_win32_libid'
else
# Keep this pattern in sync with the one in func_win32_libid.
lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64|pe-aarch64)'
lt_cv_file_magic_cmd='$OBJDUMP -f'
fi
;;
cegcc*)
# use the weaker test based on 'objdump'. See mingw*.
lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
lt_cv_file_magic_cmd='$OBJDUMP -f'
;;
darwin* | rhapsody*)
lt_cv_deplibs_check_method=pass_all
;;
freebsd* | dragonfly* | midnightbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
case $host_cpu in
i*86 )
# Not sure whether the presence of OpenBSD here was a mistake.
# Let's accept both of them until this is cleared up.
lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
lt_cv_file_magic_cmd=$FILECMD
lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
;;
esac
else
lt_cv_deplibs_check_method=pass_all
fi
;;
haiku*)
lt_cv_deplibs_check_method=pass_all
;;
hpux10.20* | hpux11*)
lt_cv_file_magic_cmd=$FILECMD
case $host_cpu in
ia64*)
lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
;;
hppa*64*)
[lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
;;
*)
lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
lt_cv_file_magic_test_file=/usr/lib/libc.sl
;;
esac
;;
interix[[3-9]]*)
# PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
;;
irix5* | irix6* | nonstopux*)
case $LD in
*-32|*"-32 ") libmagic=32-bit;;
*-n32|*"-n32 ") libmagic=N32;;
*-64|*"-64 ") libmagic=64-bit;;
*) libmagic=never-match;;
esac
lt_cv_deplibs_check_method=pass_all
;;
*-mlibc)
lt_cv_deplibs_check_method=pass_all
;;
# This must be glibc/ELF.
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
lt_cv_deplibs_check_method=pass_all
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
else
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
fi
;;
newos6*)
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
lt_cv_file_magic_cmd=$FILECMD
lt_cv_file_magic_test_file=/usr/lib/libnls.so
;;
*nto* | *qnx*)
lt_cv_deplibs_check_method=pass_all
;;
openbsd*)
if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
else
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
fi
;;
osf3* | osf4* | osf5*)
lt_cv_deplibs_check_method=pass_all
;;
rdos*)
lt_cv_deplibs_check_method=pass_all
;;
serenity*)
lt_cv_deplibs_check_method=pass_all
;;
solaris*)
lt_cv_deplibs_check_method=pass_all
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
lt_cv_deplibs_check_method=pass_all
;;
sysv4 | sysv4.3*)
case $host_vendor in
motorola)
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
;;
ncr)
lt_cv_deplibs_check_method=pass_all
;;
sequent)
lt_cv_file_magic_cmd='/bin/file'
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
;;
sni)
lt_cv_file_magic_cmd='/bin/file'
lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
lt_cv_file_magic_test_file=/lib/libc.so
;;
siemens)
lt_cv_deplibs_check_method=pass_all
;;
pc)
lt_cv_deplibs_check_method=pass_all
;;
esac
;;
tpf*)
lt_cv_deplibs_check_method=pass_all
;;
os2*)
lt_cv_deplibs_check_method=pass_all
;;
esac
])
file_magic_glob=
want_nocaseglob=no
if test "$build" = "$host"; then
case $host_os in
mingw* | windows* | pw32*)
if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
want_nocaseglob=yes
else
file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
fi
;;
esac
fi
file_magic_cmd=$lt_cv_file_magic_cmd
deplibs_check_method=$lt_cv_deplibs_check_method
test -z "$deplibs_check_method" && deplibs_check_method=unknown
_LT_DECL([], [deplibs_check_method], [1],
[Method to check whether dependent libraries are shared objects])
_LT_DECL([], [file_magic_cmd], [1],
[Command to use when deplibs_check_method = "file_magic"])
_LT_DECL([], [file_magic_glob], [1],
[How to find potential files when deplibs_check_method = "file_magic"])
_LT_DECL([], [want_nocaseglob], [1],
[Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
])# _LT_CHECK_MAGIC_METHOD
# LT_PATH_NM
# ----------
# find the pathname to a BSD- or MS-compatible name lister
AC_DEFUN([LT_PATH_NM],
[AC_REQUIRE([AC_PROG_CC])dnl
AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
[if test -n "$NM"; then
# Let the user override the test.
lt_cv_path_NM=$NM
else
lt_nm_to_check=${ac_tool_prefix}nm
if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
lt_nm_to_check="$lt_nm_to_check nm"
fi
for lt_tmp_nm in $lt_nm_to_check; do
lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
IFS=$lt_save_ifs
test -z "$ac_dir" && ac_dir=.
tmp_nm=$ac_dir/$lt_tmp_nm
if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
# Check to see if the nm accepts a BSD-compat flag.
# Adding the 'sed 1q' prevents false positives on HP-UX, which says:
# nm: unknown option "B" ignored
# Tru64's nm complains that /dev/null is an invalid object file
# MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
case $build_os in
mingw* | windows*) lt_bad_file=conftest.nm/nofile ;;
*) lt_bad_file=/dev/null ;;
esac
case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
*$lt_bad_file* | *'Invalid file or object type'*)
lt_cv_path_NM="$tmp_nm -B"
break 2
;;
*)
case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
*/dev/null*)
lt_cv_path_NM="$tmp_nm -p"
break 2
;;
*)
lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
continue # so that we can try to find one that supports BSD flags
;;
esac
;;
esac
fi
done
IFS=$lt_save_ifs
done
: ${lt_cv_path_NM=no}
fi])
if test no != "$lt_cv_path_NM"; then
NM=$lt_cv_path_NM
else
# Didn't find any BSD compatible name lister, look for dumpbin.
if test -n "$DUMPBIN"; then :
# Let the user override the test.
else
AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
*COFF*)
DUMPBIN="$DUMPBIN -symbols -headers"
;;
*)
DUMPBIN=:
;;
esac
fi
AC_SUBST([DUMPBIN])
if test : != "$DUMPBIN"; then
NM=$DUMPBIN
fi
fi
test -z "$NM" && NM=nm
AC_SUBST([NM])
_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
[lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&AS_MESSAGE_LOG_FD
(eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&AS_MESSAGE_LOG_FD
(eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
cat conftest.out >&AS_MESSAGE_LOG_FD
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
fi
rm -f conftest*])
])# LT_PATH_NM
# Old names:
AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_PROG_NM], [])
dnl AC_DEFUN([AC_PROG_NM], [])
# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
# --------------------------------
# how to determine the name of the shared library
# associated with a specific link library.
# -- PORTME fill in with the dynamic library characteristics
m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
[m4_require([_LT_DECL_EGREP])
m4_require([_LT_DECL_OBJDUMP])
m4_require([_LT_DECL_DLLTOOL])
AC_CACHE_CHECK([how to associate runtime and link libraries],
lt_cv_sharedlib_from_linklib_cmd,
[lt_cv_sharedlib_from_linklib_cmd='unknown'
case $host_os in
cygwin* | mingw* | windows* | pw32* | cegcc*)
# two different shell functions defined in ltmain.sh;
# decide which one to use based on capabilities of $DLLTOOL
case `$DLLTOOL --help 2>&1` in
*--identify-strict*)
lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
;;
*)
lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
;;
esac
;;
*)
# fallback: assume linklib IS sharedlib
lt_cv_sharedlib_from_linklib_cmd=$ECHO
;;
esac
])
sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
[Command to associate shared and link libraries])
])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
# _LT_PATH_MANIFEST_TOOL
# ----------------------
# locate the manifest tool
m4_defun([_LT_PATH_MANIFEST_TOOL],
[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_manifest_tool],
[lt_cv_path_manifest_tool=no
echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
$MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
cat conftest.err >&AS_MESSAGE_LOG_FD
if $GREP 'Manifest Tool' conftest.out > /dev/null; then
lt_cv_path_manifest_tool=yes
fi
rm -f conftest*])
if test yes != "$lt_cv_path_manifest_tool"; then
MANIFEST_TOOL=:
fi
_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
])# _LT_PATH_MANIFEST_TOOL
# _LT_DLL_DEF_P([FILE])
# ---------------------
# True iff FILE is a Windows DLL '.def' file.
# Keep in sync with func_dll_def_p in the libtool script
AC_DEFUN([_LT_DLL_DEF_P],
[dnl
test DEF = "`$SED -n dnl
-e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace
-e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments
-e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl
-e q dnl Only consider the first "real" line
$1`" dnl
])# _LT_DLL_DEF_P
# LT_LIB_M
# --------
# check for math library
AC_DEFUN([LT_LIB_M],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
LIBM=
case $host in
*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-mingw* | *-*-pw32* | *-*-darwin*)
# These system don't have libm, or don't need it
;;
*-ncr-sysv4.3*)
AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw)
AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
;;
*)
AC_CHECK_LIB(m, cos, LIBM=-lm)
;;
esac
AC_SUBST([LIBM])
])# LT_LIB_M
# Old name:
AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_CHECK_LIBM], [])
# _LT_COMPILER_NO_RTTI([TAGNAME])
# -------------------------------
m4_defun([_LT_COMPILER_NO_RTTI],
[m4_require([_LT_TAG_COMPILER])dnl
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
if test yes = "$GCC"; then
case $cc_basename in
nvcc*)
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
*)
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
esac
_LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
lt_cv_prog_compiler_rtti_exceptions,
[-fno-rtti -fno-exceptions], [],
[_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
fi
_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
[Compiler flag to turn off builtin functions])
])# _LT_COMPILER_NO_RTTI
# _LT_CMD_GLOBAL_SYMBOLS
# ----------------------
m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([LT_PATH_NM])dnl
AC_REQUIRE([LT_PATH_LD])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_TAG_COMPILER])dnl
# Check for command to grab the raw symbol name followed by C symbol from nm.
AC_MSG_CHECKING([command to parse $NM output from $compiler object])
AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
[
# These are sane defaults that work on at least a few old systems.
# [They come from Ultrix. What could be older than Ultrix?!! ;)]
# Character class describing NM global symbol codes.
symcode='[[BCDEGRST]]'
# Regexp to match symbols that can be accessed directly from C.
sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
# Define system-specific variables.
case $host_os in
aix*)
symcode='[[BCDT]]'
;;
cygwin* | mingw* | windows* | pw32* | cegcc*)
symcode='[[ABCDGISTW]]'
;;
hpux*)
if test ia64 = "$host_cpu"; then
symcode='[[ABCDEGRST]]'
fi
;;
irix* | nonstopux*)
symcode='[[BCDEGRST]]'
;;
osf*)
symcode='[[BCDEGQRST]]'
;;
solaris*)
symcode='[[BCDRT]]'
;;
sco3.2v5*)
symcode='[[DT]]'
;;
sysv4.2uw2*)
symcode='[[DT]]'
;;
sysv5* | sco5v6* | unixware* | OpenUNIX*)
symcode='[[ABDT]]'
;;
sysv4)
symcode='[[DFNSTU]]'
;;
esac
# If we're using GNU nm, then use its standard symbol codes.
case `$NM -V 2>&1` in
*GNU* | *'with BFD'*)
symcode='[[ABCDGIRSTW]]' ;;
esac
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
# Gets list of data symbols to import.
lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \([[a-zA-Z_]][[a-zA-Z0-9_]]*\)$/\1/p'"
# Adjust the below global symbol transforms to fixup imported variables.
lt_cdecl_hook=" -e 's/^I .* \([[a-zA-Z_]][[a-zA-Z0-9_]]*\)$/extern __declspec(dllimport) char \1;/p'"
lt_c_name_hook=" -e 's/^I .* \([[a-zA-Z_]][[a-zA-Z0-9_]]*\)$/ {\"\1\", (void *) 0},/p'"
lt_c_name_lib_hook="\
-e 's/^I .* \(lib[[a-zA-Z_]][[a-zA-Z0-9_]]*\)$/ {\"\1\", (void *) 0},/p'\
-e 's/^I .* \([[a-zA-Z_]][[a-zA-Z0-9_]]*\)$/ {\"lib\1\", (void *) 0},/p'"
else
# Disable hooks by default.
lt_cv_sys_global_symbol_to_import=
lt_cdecl_hook=
lt_c_name_hook=
lt_c_name_lib_hook=
fi
# Transform an extracted symbol line into a proper C declaration.
# Some systems (esp. on ia64) link data and code symbols differently,
# so use this general approach.
lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
$lt_cdecl_hook\
" -e 's/^T .* \([[a-zA-Z_]][[a-zA-Z0-9_]]*\)$/extern int \1();/p'"\
" -e 's/^$symcode$symcode* .* \([[a-zA-Z_]][[a-zA-Z0-9_]]*\)$/extern char \1;/p'"
# Transform an extracted symbol line into symbol name and symbol address
lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
$lt_c_name_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \([[a-zA-Z_]][[a-zA-Z0-9_]]*\)$/ {\"\1\", (void *) \&\1},/p'"
# Transform an extracted symbol line into symbol name with lib prefix and
# symbol address.
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
$lt_c_name_lib_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(lib[[a-zA-Z_]][[a-zA-Z0-9_]]*\)$/ {\"\1\", (void *) \&\1},/p'"\
" -e 's/^$symcode$symcode* .* \([[a-zA-Z_]][[a-zA-Z0-9_]]*\)$/ {\"lib\1\", (void *) \&\1},/p'"
# Handle CRLF in mingw tool chain
opt_cr=
case $build_os in
mingw* | windows*)
opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
;;
esac
# Try without a prefix underscore, then with it.
for ac_symprfx in "" "_"; do
# Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
symxfrm="\\1 $ac_symprfx\\2 \\2"
# Write the raw and C identifiers.
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
# Fake it for dumpbin and say T for any non-static function,
# D for any global variable and I for any imported variable.
# Also find C++ and __fastcall symbols from MSVC++ or ICC,
# which start with @ or ?. And Cygwin gawk-4.1.4-3 and newer
# treats input as binary, have to drop carriage return first.
lt_cv_sys_global_symbol_pipe="$AWK ['"\
" {sub(/\\r\$/,\"\")};"\
" {last_section=section; section=\$ 3};"\
" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
" \$ 0!~/External *\|/{next};"\
" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
" {if(hide[section]) next};"\
" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
" ' prfx=^$ac_symprfx]"
else
lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
fi
lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
# Check to see that the pipe works correctly.
pipe_works=no
rm -f conftest*
cat > conftest.$ac_ext <<_LT_EOF
#ifdef __cplusplus
extern "C" {
#endif
char nm_test_var;
void nm_test_func(void);
void nm_test_func(void){}
#ifdef __cplusplus
}
#endif
int main(void){nm_test_var='a';nm_test_func();return(0);}
_LT_EOF
if AC_TRY_EVAL(ac_compile); then
# Now try to grab the symbols.
nlist=conftest.nm
$ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD
if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then
# Try sorting and uniquifying the output.
if sort "$nlist" | uniq > "$nlist"T; then
mv -f "$nlist"T "$nlist"
else
rm -f "$nlist"T
fi
# Make sure that we snagged all the symbols we need.
if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
cat <<_LT_EOF > conftest.$ac_ext
/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
/* DATA imports from DLLs on WIN32 can't be const, because runtime
relocations are performed -- see ld's documentation on pseudo-relocs. */
# define LT@&t@_DLSYM_CONST
#elif defined __osf__
/* This system does not cope well with relocations in const data. */
# define LT@&t@_DLSYM_CONST
#else
# define LT@&t@_DLSYM_CONST const
#endif
#ifdef __cplusplus
extern "C" {
#endif
_LT_EOF
# Now generate the symbol file.
eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
cat <<_LT_EOF >> conftest.$ac_ext
/* The mapping between symbol names and symbols. */
LT@&t@_DLSYM_CONST struct {
const char *name;
void *address;
}
lt__PROGRAM__LTX_preloaded_symbols[[]] =
{
{ "@PROGRAM@", (void *) 0 },
_LT_EOF
$SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
cat <<\_LT_EOF >> conftest.$ac_ext
{0, (void *) 0}
};
/* This works around a problem in FreeBSD linker */
#ifdef FREEBSD_WORKAROUND
static const void *lt_preloaded_setup() {
return lt__PROGRAM__LTX_preloaded_symbols;
}
#endif
#ifdef __cplusplus
}
#endif
_LT_EOF
# Now try linking the two files.
mv conftest.$ac_objext conftstm.$ac_objext
lt_globsym_save_LIBS=$LIBS
lt_globsym_save_CFLAGS=$CFLAGS
LIBS=conftstm.$ac_objext
CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
pipe_works=yes
fi
LIBS=$lt_globsym_save_LIBS
CFLAGS=$lt_globsym_save_CFLAGS
else
echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
fi
else
echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
fi
else
echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
fi
else
echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
cat conftest.$ac_ext >&5
fi
rm -rf conftest* conftst*
# Do not use the global_symbol_pipe unless it works.
if test yes = "$pipe_works"; then
break
else
lt_cv_sys_global_symbol_pipe=
fi
done
])
if test -z "$lt_cv_sys_global_symbol_pipe"; then
lt_cv_sys_global_symbol_to_cdecl=
fi
if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
AC_MSG_RESULT(failed)
else
AC_MSG_RESULT(ok)
fi
# Response file support.
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
nm_file_list_spec='@'
elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
nm_file_list_spec='@'
fi
_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
[Take the output of nm and produce a listing of raw symbols and C names])
_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
[Transform the output of nm in a proper C declaration])
_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
[Transform the output of nm into a list of symbols to manually relocate])
_LT_DECL([global_symbol_to_c_name_address],
[lt_cv_sys_global_symbol_to_c_name_address], [1],
[Transform the output of nm in a C name address pair])
_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
[lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
[Transform the output of nm in a C name address pair when lib prefix is needed])
_LT_DECL([nm_interface], [lt_cv_nm_interface], [1],
[The name lister interface])
_LT_DECL([], [nm_file_list_spec], [1],
[Specify filename containing input files for $NM])
]) # _LT_CMD_GLOBAL_SYMBOLS
# _LT_COMPILER_PIC([TAGNAME])
# ---------------------------
m4_defun([_LT_COMPILER_PIC],
[m4_require([_LT_TAG_COMPILER])dnl
_LT_TAGVAR(lt_prog_compiler_wl, $1)=
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_static, $1)=
m4_if([$1], [CXX], [
# C++ specific cases for pic, static, wl, etc.
if test yes = "$GXX"; then
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
case $host_os in
aix*)
# All AIX code is PIC.
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
fi
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
m68k)
# FIXME: we need at least 68020 code to build shared libraries, but
# adding the '-m68020' flag to GCC prevents building anything better,
# like '-m68040'.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
;;
esac
;;
beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
# PIC is the default for these OSes.
;;
mingw* | windows* | cygwin* | os2* | pw32* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
# Although the cygwin gcc ignores -fPIC, still need this for old-style
# (--disable-auto-import) libraries
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
case $host_os in
os2*)
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
;;
esac
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
;;
*djgpp*)
# DJGPP does not support shared libraries at all
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
;;
haiku*)
# PIC is the default for Haiku.
# The "-static" flag exists, but is broken.
_LT_TAGVAR(lt_prog_compiler_static, $1)=
;;
interix[[3-9]]*)
# Interix 3.x gcc -fpic/-fPIC options generate broken code.
# Instead, we relocate shared libraries at runtime.
;;
sysv4*MP*)
if test -d /usr/nec; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
fi
;;
hpux*)
# PIC is the default for 64-bit PA HP-UX, but not for 32-bit
# PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
# sets the default TLS model and affects inlining.
case $host_cpu in
hppa*64*)
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
esac
;;
*qnx* | *nto*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
esac
else
case $host_os in
aix[[4-9]]*)
# All AIX code is PIC.
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
else
_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.expsym'
fi
;;
chorus*)
case $cc_basename in
cxch68*)
# Green Hills C++ Compiler
# _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
;;
esac
;;
mingw* | windows* | cygwin* | os2* | pw32* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
;;
dgux*)
case $cc_basename in
ec++*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
;;
ghcx*)
# Green Hills C++ Compiler
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
;;
*)
;;
esac
;;
freebsd* | dragonfly* | midnightbsd*)
# FreeBSD uses GNU C++
;;
hpux9* | hpux10* | hpux11*)
case $cc_basename in
CC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
if test ia64 != "$host_cpu"; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
fi
;;
aCC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
case $host_cpu in
hppa*64*|ia64*)
# +Z the default
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
;;
esac
;;
*)
;;
esac
;;
interix*)
# This is c89, which is MS Visual C++ (no shared libs)
# Anyone wants to do a port?
;;
irix5* | irix6* | nonstopux*)
case $cc_basename in
CC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
# CC pic flag -KPIC is the default.
;;
*)
;;
esac
;;
*-mlibc)
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
KCC*)
# KAI C++ Compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
ecpc* )
# old Intel C++ for x86_64, which still supported -KPIC.
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
icpc* | icpx*)
# Intel C++, used to be incompatible with GCC.
# ICC 10 doesn't accept -KPIC any more.
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
pgCC* | pgcpp*)
# Portland Group C++ compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
cxx*)
# Compaq C++
# Make sure the PIC flag is empty. It appears that all Alpha
# Linux and Compaq Tru64 Unix objects are PIC.
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
# IBM XL 8.0, 9.0 on PPC and BlueGene
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
;;
*)
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ C*)
# Sun C++ 5.9
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
;;
esac
;;
esac
;;
lynxos*)
;;
m88k*)
;;
mvs*)
case $cc_basename in
cxx*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
;;
*)
;;
esac
;;
netbsd* | netbsdelf*-gnu)
;;
*qnx* | *nto*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
osf3* | osf4* | osf5*)
case $cc_basename in
KCC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
;;
RCC*)
# Rational C++ 2.4.1
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
;;
cxx*)
# Digital/Compaq C++
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# Make sure the PIC flag is empty. It appears that all Alpha
# Linux and Compaq Tru64 Unix objects are PIC.
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
*)
;;
esac
;;
psos*)
;;
serenity*)
;;
solaris*)
case $cc_basename in
CC* | sunCC*)
# Sun C++ 4.2, 5.x and Centerline C++
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
;;
gcx*)
# Green Hills C++ Compiler
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
;;
*)
;;
esac
;;
sunos4*)
case $cc_basename in
CC*)
# Sun C++ 4.x
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
lcc*)
# Lucid
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
;;
*)
;;
esac
;;
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
case $cc_basename in
CC*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
esac
;;
tandem*)
case $cc_basename in
NCC*)
# NonStop-UX NCC 3.20
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
;;
*)
;;
esac
;;
vxworks*)
;;
*)
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
;;
esac
fi
],
[
if test yes = "$GCC"; then
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
case $host_os in
aix*)
# All AIX code is PIC.
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
fi
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
m68k)
# FIXME: we need at least 68020 code to build shared libraries, but
# adding the '-m68020' flag to GCC prevents building anything better,
# like '-m68040'.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
;;
esac
;;
beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
# PIC is the default for these OSes.
;;
mingw* | windows* | cygwin* | pw32* | os2* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
# Although the cygwin gcc ignores -fPIC, still need this for old-style
# (--disable-auto-import) libraries
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
case $host_os in
os2*)
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
;;
esac
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
;;
haiku*)
# PIC is the default for Haiku.
# The "-static" flag exists, but is broken.
_LT_TAGVAR(lt_prog_compiler_static, $1)=
;;
hpux*)
# PIC is the default for 64-bit PA HP-UX, but not for 32-bit
# PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
# sets the default TLS model and affects inlining.
case $host_cpu in
hppa*64*)
# +Z the default
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
esac
;;
interix[[3-9]]*)
# Interix 3.x gcc -fpic/-fPIC options generate broken code.
# Instead, we relocate shared libraries at runtime.
;;
msdosdjgpp*)
# Just because we use GCC doesn't mean we suddenly get shared libraries
# on systems that don't support them.
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
enable_shared=no
;;
*nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
sysv4*MP*)
if test -d /usr/nec; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
fi
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
;;
esac
case $cc_basename in
nvcc*) # Cuda Compiler Driver 2.2
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
fi
;;
esac
else
# PORTME Check for flag to pass linker flags through the system compiler.
case $host_os in
aix*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
else
_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.expsym'
fi
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
case $cc_basename in
nagfor*)
# NAG Fortran compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
esac
;;
mingw* | windows* | cygwin* | pw32* | os2* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
m4_if([$1], [GCJ], [],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
case $host_os in
os2*)
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
;;
esac
;;
hpux9* | hpux10* | hpux11*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
# not for PA HP-UX.
case $host_cpu in
hppa*64*|ia64*)
# +Z the default
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
;;
esac
# Is there a better lt_prog_compiler_static that works with the bundled CC?
_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
;;
irix5* | irix6* | nonstopux*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# PIC (with -KPIC) is the default.
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
*-mlibc)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu* | freebsd*)
case $cc_basename in
# old Intel for x86_64, which still supported -KPIC.
ecc*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
*flang* | ftn | f18* | f95*)
# Flang compiler.
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
# icc used to be incompatible with GCC.
# ICC 10 doesn't accept -KPIC any more.
icc* | ifort* | icx* | ifx*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
# Lahey Fortran 8.1.
lf95*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
;;
nagfor*)
# NAG Fortran compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
tcc*)
# Fabrice Bellard et al's Tiny C Compiler
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
# Portland Group compilers (*not* the Pentium gcc compiler,
# which looks to be a dead project)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
ccc*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# All Alpha code is PIC.
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
xl* | bgxl* | bgf* | mpixl*)
# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
;;
*)
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
# Sun Fortran 8.3 passes all unrecognized flags to the linker
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)=''
;;
*Sun\ F* | *Sun*Fortran*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
;;
*Sun\ C*)
# Sun C 5.9
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
;;
*Intel*\ [[CF]]*Compiler*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
*Portland\ Group*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
esac
;;
esac
;;
newsos6)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
*nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
;;
osf3* | osf4* | osf5*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
# All OSF/1 code is PIC.
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
rdos*)
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
serenity*)
;;
solaris*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
case $cc_basename in
f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
esac
;;
sunos4*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
sysv4 | sysv4.2uw2* | sysv4.3*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
sysv4*MP*)
if test -d /usr/nec; then
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
fi
;;
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
unicos*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
;;
uts4*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
;;
*)
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
;;
esac
fi
])
case $host_os in
# For platforms that do not support PIC, -DPIC is meaningless:
*djgpp*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)=
;;
*)
_LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
;;
esac
AC_CACHE_CHECK([for $compiler option to produce PIC],
[_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
[_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
#
# Check to make sure the PIC flag actually works.
#
if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
_LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
[_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
[$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
[case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
"" | " "*) ;;
*) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
esac],
[_LT_TAGVAR(lt_prog_compiler_pic, $1)=
_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
fi
_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
[Additional compiler flags for building library objects])
_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
[How to pass a linker flag through the compiler])
#
# Check to make sure the static flag actually works.
#
wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
_LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
$lt_tmp_static_flag,
[],
[_LT_TAGVAR(lt_prog_compiler_static, $1)=])
_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
[Compiler flag to prevent dynamic linking])
])# _LT_COMPILER_PIC
# _LT_LINKER_SHLIBS([TAGNAME])
# ----------------------------
# See if the linker supports building shared libraries.
m4_defun([_LT_LINKER_SHLIBS],
[AC_REQUIRE([LT_PATH_LD])dnl
AC_REQUIRE([LT_PATH_NM])dnl
m4_require([_LT_PATH_MANIFEST_TOOL])dnl
m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_DECL_SED])dnl
m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
m4_require([_LT_TAG_COMPILER])dnl
AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
m4_if([$1], [CXX], [
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
case $host_os in
aix[[4-9]]*)
# If we're using GNU nm, then we don't want the "-C" option.
# -C means demangle to GNU nm, but means don't demangle to AIX nm.
# Without the "-l" option, or with the "-B" option, AIX nm treats
# weak defined symbols like other global defined symbols, whereas
# GNU nm marks them as "W".
# While the 'weak' keyword is ignored in the Export File, we need
# it in the Import File for the 'aix-soname' feature, so we have
# to replace the "-B" option with "-P" for AIX nm.
if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
_LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
else
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
fi
;;
pw32*)
_LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds
;;
cygwin* | mingw* | windows* | cegcc*)
case $cc_basename in
cl* | icl* | icx* | icpx*)
# Native MSVC and Intel compilers
_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
;;
*)
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
;;
esac
;;
*)
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
;;
esac
], [
runpath_var=
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_cmds, $1)=
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(compiler_needs_object, $1)=no
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(old_archive_from_new_cmds, $1)=
_LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
_LT_TAGVAR(thread_safe_flag_spec, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
# include_expsyms should be a list of space-separated symbols to be *always*
# included in the symbol list
_LT_TAGVAR(include_expsyms, $1)=
# exclude_expsyms can be an extended regexp of symbols to exclude
# it will be wrapped by ' (' and ')$', so one must not match beginning or
# end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
# as well as any symbol that contains 'd'.
_LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
# platforms (ab)use it in PIC code, but their linkers get confused if
# the symbol is explicitly referenced. Since portable code cannot
# rely on this symbol name, it's probably fine to never include it in
# preloaded symbol tables.
# Exclude shared library initialization/finalization symbols.
dnl Note also adjust exclude_expsyms for C++ above.
extract_expsyms_cmds=
case $host_os in
cygwin* | mingw* | windows* | pw32* | cegcc*)
# FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++ or Intel C++ Compiler.
if test yes != "$GCC"; then
with_gnu_ld=no
fi
;;
interix*)
# we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
with_gnu_ld=yes
;;
esac
_LT_TAGVAR(ld_shlibs, $1)=yes
# On some targets, GNU ld is compatible enough with the native linker
# that we're better off using the native interface for both.
lt_use_gnu_ld_interface=no
if test yes = "$with_gnu_ld"; then
case $host_os in
aix*)
# The AIX port of GNU ld has always aspired to compatibility
# with the native linker. However, as the warning in the GNU ld
# block says, versions before 2.19.5* couldn't really create working
# shared libraries, regardless of the interface used.
case `$LD -v 2>&1` in
*\ \(GNU\ Binutils\)\ 2.19.5*) ;;
*\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
*\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
*)
lt_use_gnu_ld_interface=yes
;;
esac
;;
*)
lt_use_gnu_ld_interface=yes
;;
esac
fi
if test yes = "$lt_use_gnu_ld_interface"; then
# If archive_cmds runs LD, not CC, wlarc should be empty
wlarc='$wl'
# Set some defaults for GNU ld with shared library support. These
# are reset later if shared libraries are not supported. Putting them
# here allows them to be overridden if necessary.
runpath_var=LD_RUN_PATH
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
# ancient GNU ld didn't support --whole-archive et. al.
if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
_LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
else
_LT_TAGVAR(whole_archive_flag_spec, $1)=
fi
supports_anon_versioning=no
case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in
*GNU\ gold*) supports_anon_versioning=yes ;;
*\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
*\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
*\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
*\ 2.11.*) ;; # other 2.11 versions
*) supports_anon_versioning=yes ;;
esac
# See if GNU ld supports shared libraries.
case $host_os in
aix[[3-9]]*)
# On AIX/PPC, the GNU linker is very broken
if test ia64 != "$host_cpu"; then
_LT_TAGVAR(ld_shlibs, $1)=no
cat <<_LT_EOF 1>&2
*** Warning: the GNU linker, at least up to release 2.19, is reported
*** to be unable to reliably create shared libraries on AIX.
*** Therefore, libtool is disabling shared libraries support. If you
*** really care for shared libraries, you may want to install binutils
*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
*** You will then need to restart the configuration process.
_LT_EOF
fi
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)=''
;;
m68k)
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
;;
esac
;;
beos*)
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
# Joseph Beckenbach says some releases of gcc
# support --undefined. This deserves some investigation. FIXME
_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
cygwin* | mingw* | windows* | pw32* | cegcc*)
# _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
# as there is no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
_LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
_LT_TAGVAR(file_list_spec, $1)='@'
if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
# If the export-symbols file already is a .def file, use it as
# is; otherwise, prepend EXPORTS...
_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
cp $export_symbols $output_objdir/$soname.def;
else
echo EXPORTS > $output_objdir/$soname.def;
cat $export_symbols >> $output_objdir/$soname.def;
fi~
$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(link_all_deplibs, $1)=no
;;
os2*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
shrext_cmds=.dll
_LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
prefix_cmds="$SED"~
if test EXPORTS = "`$SED 1q $export_symbols`"; then
prefix_cmds="$prefix_cmds -e 1d";
fi~
prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
;;
interix[[3-9]]*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
# Instead, shared libraries are loaded at an image base (0x10000000 by
# default) and relocated if they conflict, which is a slow very memory
# consuming and fragmenting process. To avoid this, we pick a random,
# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
# time. Moving up from 0x10000000 also allows more sbrk(2) space.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
;;
*-mlibc)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
;;
gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
tmp_diet=no
if test linux-dietlibc = "$host_os"; then
case $cc_basename in
diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
esac
fi
if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
&& test no = "$tmp_diet"
then
tmp_addflag=' $pic_flag'
tmp_sharedflag='-shared'
case $cc_basename,$host_cpu in
pgcc*) # Portland Group C compiler
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
tmp_addflag=' $pic_flag'
;;
pgf77* | pgf90* | pgf95* | pgfortran*)
# Portland Group f77 and f90 compilers
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
tmp_addflag=' $pic_flag -Mnomain' ;;
ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
tmp_addflag=' -i_dynamic' ;;
efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
tmp_addflag=' -i_dynamic -nofor_main' ;;
ifc* | ifort* | ifx*) # Intel Fortran compiler
tmp_addflag=' -nofor_main' ;;
lf95*) # Lahey Fortran 8.1
_LT_TAGVAR(whole_archive_flag_spec, $1)=
tmp_sharedflag='--shared' ;;
nagfor*) # NAGFOR 5.3
tmp_sharedflag='-Wl,-shared' ;;
xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
tmp_sharedflag='-qmkshrobj'
tmp_addflag= ;;
nvcc*) # Cuda Compiler Driver 2.2
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
_LT_TAGVAR(compiler_needs_object, $1)=yes
;;
esac
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ C*) # Sun C 5.9
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
_LT_TAGVAR(compiler_needs_object, $1)=yes
tmp_sharedflag='-G' ;;
*Sun\ F*) # Sun Fortran 8.3
tmp_sharedflag='-G' ;;
esac
_LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
fi
case $cc_basename in
tcc*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
;;
xlf* | bgf* | bgxlf* | mpixlf*)
# IBM XL Fortran 10.1 on PPC cannot create shared libs itself
_LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
fi
;;
esac
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
wlarc=
else
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
fi
;;
solaris*)
if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
_LT_TAGVAR(ld_shlibs, $1)=no
cat <<_LT_EOF 1>&2
*** Warning: The releases 2.8.* of the GNU linker cannot reliably
*** create shared libraries on Solaris systems. Therefore, libtool
*** is disabling shared libraries support. We urge you to upgrade GNU
*** binutils to release 2.9.1 or newer. Another option is to modify
*** your PATH or compiler configuration so that the native linker is
*** used, and then restart.
_LT_EOF
elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
case `$LD -v 2>&1` in
*\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
_LT_TAGVAR(ld_shlibs, $1)=no
cat <<_LT_EOF 1>&2
*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
*** reliably create shared libraries on SCO systems. Therefore, libtool
*** is disabling shared libraries support. We urge you to upgrade GNU
*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
*** your PATH or compiler configuration so that the native linker is
*** used, and then restart.
_LT_EOF
;;
*)
# For security reasons, it is highly recommended that you always
# use absolute paths for naming shared libraries, and exclude the
# DT_RUNPATH tag from executables and libraries. But doing so
# requires that you compile everything twice, which is a pain.
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
sunos4*)
_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
wlarc=
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then
runpath_var=
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
fi
else
# PORTME fill in a description of your system's linker (not GNU ld)
case $host_os in
aix3*)
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
_LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
# Note: this linker hardcodes the directories in LIBPATH if there
# are no directories specified by -L.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
# Neither direct hardcoding nor static linking is supported with a
# broken collect2.
_LT_TAGVAR(hardcode_direct, $1)=unsupported
fi
;;
aix[[4-9]]*)
if test ia64 = "$host_cpu"; then
# On IA64, the linker does run time linking by default, so we don't
# have to do anything special.
aix_use_runtimelinking=no
exp_sym_flag='-Bexport'
no_entry_flag=
else
# If we're using GNU nm, then we don't want the "-C" option.
# -C means demangle to GNU nm, but means don't demangle to AIX nm.
# Without the "-l" option, or with the "-B" option, AIX nm treats
# weak defined symbols like other global defined symbols, whereas
# GNU nm marks them as "W".
# While the 'weak' keyword is ignored in the Export File, we need
# it in the Import File for the 'aix-soname' feature, so we have
# to replace the "-B" option with "-P" for AIX nm.
if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
_LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
else
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
fi
aix_use_runtimelinking=no
# Test if we are trying to use run time linking or normal
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
# have runtime linking enabled, and use it for executables.
# For shared libraries, we enable/disable runtime linking
# depending on the kind of the shared library created -
# when "with_aix_soname,aix_use_runtimelinking" is:
# "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
# "aix,yes" lib.so shared, rtl:yes, for executables
# lib.a static archive
# "both,no" lib.so.V(shr.o) shared, rtl:yes
# lib.a(lib.so.V) shared, rtl:no, for executables
# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
# lib.a(lib.so.V) shared, rtl:no
# "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
# lib.a static archive
case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
for ld_flag in $LDFLAGS; do
if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
aix_use_runtimelinking=yes
break
fi
done
if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
# With aix-soname=svr4, we create the lib.so.V shared archives only,
# so we don't have lib.a shared libs to link our executables.
# We have to force runtime linking in this case.
aix_use_runtimelinking=yes
LDFLAGS="$LDFLAGS -Wl,-brtl"
fi
;;
esac
exp_sym_flag='-bexport'
no_entry_flag='-bnoentry'
fi
# When large executables or shared objects are built, AIX ld can
# have problems creating the table of contents. If linking a library
# or program results in "error TOC overflow" add -mminimal-toc to
# CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
# enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
_LT_TAGVAR(archive_cmds, $1)=''
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='$wl-f,'
case $with_aix_soname,$aix_use_runtimelinking in
aix,*) ;; # traditional, no import file
svr4,* | *,yes) # use import file
# The Import File defines what to hardcode.
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
;;
esac
if test yes = "$GCC"; then
case $host_os in aix4.[[012]]|aix4.[[012]].*)
# We only want to do this on AIX 4.2 and lower, the check
# below for broken collect2 doesn't work under 4.3+
collect2name=`$CC -print-prog-name=collect2`
if test -f "$collect2name" &&
strings "$collect2name" | $GREP resolve_lib_name >/dev/null
then
# We have reworked collect2
:
else
# We have old collect2
_LT_TAGVAR(hardcode_direct, $1)=unsupported
# It fails to find uninstalled libraries when the uninstalled
# path is not listed in the libpath. Setting hardcode_minus_L
# to unsupported forces relinking
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=
fi
;;
esac
shared_flag='-shared'
if test yes = "$aix_use_runtimelinking"; then
shared_flag="$shared_flag "'$wl-G'
fi
# Need to ensure runtime linking is disabled for the traditional
# shared library, or the linker may eventually find shared libraries
# /with/ Import File - we do not want to mix them.
shared_flag_aix='-shared'
shared_flag_svr4='-shared $wl-G'
else
# not using gcc
if test ia64 = "$host_cpu"; then
# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
# chokes on -Wl,-G. The following line is correct:
shared_flag='-G'
else
if test yes = "$aix_use_runtimelinking"; then
shared_flag='$wl-G'
else
shared_flag='$wl-bM:SRE'
fi
shared_flag_aix='$wl-bM:SRE'
shared_flag_svr4='$wl-G'
fi
fi
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
# It seems that -bexpall does not export symbols beginning with
# underscore (_), so it is better to generate a list of symbols to export.
_LT_TAGVAR(always_export_symbols, $1)=yes
if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
# Warning - without using the other runtime loading flags (-brtl),
# -berok will link without error, but may produce a broken library.
_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
# Determine the default libpath from the value encoded in an
# empty executable.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
else
if test ia64 = "$host_cpu"; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
_LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
_LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
else
# Determine the default libpath from the value encoded in an
# empty executable.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
# Warning - without using the other run time loading flags,
# -berok will link without error, but may produce a broken library.
_LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
if test yes = "$with_gnu_ld"; then
# We only use this code for GNU lds that support --whole-archive.
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
else
# Exported symbols can be pulled into shared objects from archives
_LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
_LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
# -brtl affects multiple linker settings, -berok does not and is overridden later
compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
if test svr4 != "$with_aix_soname"; then
# This is similar to how AIX traditionally builds its shared libraries.
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
fi
if test aix != "$with_aix_soname"; then
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
else
# used by -dlpreopen to get the symbols
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
fi
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
fi
fi
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)=''
;;
m68k)
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
;;
esac
;;
bsdi[[45]]*)
_LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
;;
cygwin* | mingw* | windows* | pw32* | cegcc*)
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++ or Intel C++ Compiler.
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
case $cc_basename in
cl* | icl* | icx* | icpx*)
# Native MSVC and Intel compilers
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
# Tell ltmain to make .lib files, not .a files.
libext=lib
# Tell ltmain to make .dll files, not .so files.
shrext_cmds=.dll
# FIXME: Setting linknames here is a bad hack.
# A check exists to verify if there are linker flags, which will use
# different commands when linking.
_LT_TAGVAR(archive_cmds, $1)='$CC -Fe$output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
cp "$export_symbols" "$output_objdir/$soname.def";
echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.expsym";
else
$SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.expsym;
fi~
if test -z "$linker_flags"; then
$CC -Fe$tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.expsym" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib";
else
$CC -Fe$tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.expsym" -Wl,$linker_flags-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib";
fi~
linknames='
# The linker will not automatically build a static lib if we build a DLL.
# _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
# Don't use ranlib
_LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
_LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
lt_tool_outputfile="@TOOL_OUTPUT@"~
case $lt_outputfile in
*.exe|*.EXE) ;;
*)
lt_outputfile=$lt_outputfile.exe
lt_tool_outputfile=$lt_tool_outputfile.exe
;;
esac~
if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
$MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
$RM "$lt_outputfile.manifest";
fi'
;;
*)
# Assume MSVC and ICC wrapper
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
# Tell ltmain to make .lib files, not .a files.
libext=lib
# Tell ltmain to make .dll files, not .so files.
shrext_cmds=.dll
# FIXME: Setting linknames here is a bad hack.
_LT_TAGVAR(archive_cmds, $1)='$CC -Fe$lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
# The linker will automatically build a .lib file if we build a DLL.
_LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
# FIXME: Should let the user specify the lib program.
_LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
;;
esac
;;
darwin* | rhapsody*)
_LT_DARWIN_LINKER_FEATURES($1)
;;
dgux*)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
# FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
# support. Future versions do this automatically, but an explicit c++rt0.o
# does not break anything, and helps significantly (at the cost of a little
# extra space).
freebsd2.2*)
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
freebsd2.*)
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
# FreeBSD 3 and greater uses gcc -shared to do shared libraries.
freebsd* | dragonfly* | midnightbsd*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
hpux9*)
if test yes = "$GCC"; then
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
else
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(hardcode_direct, $1)=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
;;
hpux10*)
if test yes,no = "$GCC,$with_gnu_ld"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
fi
if test no = "$with_gnu_ld"; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
fi
;;
hpux11*)
if test yes,no = "$GCC,$with_gnu_ld"; then
case $host_cpu in
hppa*64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
;;
esac
else
case $host_cpu in
hppa*64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
;;
*)
m4_if($1, [], [
# Older versions of the 11.00 compiler do not understand -b yet
# (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
_LT_LINKER_OPTION([if $CC understands -b],
_LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
[_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
[_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
[_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
;;
esac
fi
if test no = "$with_gnu_ld"; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
case $host_cpu in
hppa*64*|ia64*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
_LT_TAGVAR(hardcode_minus_L, $1)=yes
;;
esac
fi
;;
irix5* | irix6* | nonstopux*)
if test yes = "$GCC"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
# Try to use the -exported_symbol ld option, if it does not
# work, assume that -exports_file does not work either and
# implicitly export all symbols.
# This should be the same for all languages, so no per-tag cache variable.
AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
[lt_cv_irix_exported_symbol],
[save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
AC_LINK_IFELSE(
[AC_LANG_SOURCE(
[AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
[C++], [[int foo (void) { return 0; }]],
[Fortran 77], [[
subroutine foo
end]],
[Fortran], [[
subroutine foo
end]])])],
[lt_cv_irix_exported_symbol=yes],
[lt_cv_irix_exported_symbol=no])
LDFLAGS=$save_LDFLAGS])
if test yes = "$lt_cv_irix_exported_symbol"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
fi
else
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)='no'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(inherit_rpath, $1)=yes
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
*-mlibc)
;;
linux*)
case $cc_basename in
tcc*)
# Fabrice Bellard et al's Tiny C Compiler
_LT_TAGVAR(ld_shlibs, $1)=yes
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
;;
esac
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
else
_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
newsos6)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*nto* | *qnx*)
;;
openbsd*)
if test -f /usr/libexec/ld.so; then
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
else
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
fi
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
os2*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
shrext_cmds=.dll
_LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
prefix_cmds="$SED"~
if test EXPORTS = "`$SED 1q $export_symbols`"; then
prefix_cmds="$prefix_cmds -e 1d";
fi~
prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
;;
osf3*)
if test yes = "$GCC"; then
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
else
_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)='no'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
;;
osf4* | osf5*) # as osf3* with the addition of -msym flag
if test yes = "$GCC"; then
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
else
_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.expsym; done; printf "%s\\n" "-hidden">> $lib.expsym~
$CC -shared$allow_undefined_flag $wl-input $wl$lib.expsym $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.expsym'
# Both c and cxx compiler support -rpath directly
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)='no'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
;;
serenity*)
;;
solaris*)
_LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
if test yes = "$GCC"; then
wlarc='$wl'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.expsym~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.expsym~echo "local: *; };" >> $lib.expsym~
$CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.expsym $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.expsym'
else
case `$CC -V 2>&1` in
*"Compilers 5.0"*)
wlarc=''
_LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.expsym~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.expsym~echo "local: *; };" >> $lib.expsym~
$LD -G$allow_undefined_flag -M $lib.expsym -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.expsym'
;;
*)
wlarc='$wl'
_LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.expsym~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.expsym~echo "local: *; };" >> $lib.expsym~
$CC -G$allow_undefined_flag -M $lib.expsym -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.expsym'
;;
esac
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
case $host_os in
solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
*)
# The compiler driver will combine and reorder linker options,
# but understands '-z linker_flag'. GCC discards it without '$wl',
# but is careful enough not to reorder.
# Supported since Solaris 2.6 (maybe 2.5.1?)
if test yes = "$GCC"; then
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
else
_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
fi
;;
esac
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
sunos4*)
if test sequent = "$host_vendor"; then
# Use $CC to link under sequent, because it throws in some extra .o
# files that make .init and .fini sections work.
_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
sysv4)
case $host_vendor in
sni)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
;;
siemens)
## LD is ld it makes a PLAMLIB
## CC just makes a GrossModule.
_LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
_LT_TAGVAR(hardcode_direct, $1)=no
;;
motorola)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
;;
esac
runpath_var='LD_RUN_PATH'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
sysv4.3*)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
;;
sysv4*MP*)
if test -d /usr/nec; then
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
runpath_var=LD_RUN_PATH
hardcode_runpath_var=yes
_LT_TAGVAR(ld_shlibs, $1)=yes
fi
;;
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
runpath_var='LD_RUN_PATH'
if test yes = "$GCC"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
fi
;;
sysv5* | sco3.2v5* | sco5v6*)
# Note: We CANNOT use -z defs as we might desire, because we do not
# link with -lc, and that would cause any symbols used from libc to
# always be unresolved, which means just about no library would
# ever link correctly. If we're not using GNU ld we use -z text
# though, which does catch some bad symbols but isn't as heavy-handed
# as -z defs.
_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
_LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
runpath_var='LD_RUN_PATH'
if test yes = "$GCC"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
else
_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
fi
;;
uts4*)
_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
if test sni = "$host_vendor"; then
case $host in
sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym'
;;
esac
fi
fi
])
AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
_LT_DECL([], [extract_expsyms_cmds], [2],
[The commands to extract the exported symbol list from a shared archive])
#
# Do we need to explicitly link libc?
#
case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
x|xyes)
# Assume -lc should be added
_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
if test yes,yes = "$GCC,$enable_shared"; then
case $_LT_TAGVAR(archive_cmds, $1) in
*'~'*)
# FIXME: we may have to deal with multi-command sequences.
;;
'$CC '*)
# Test whether the compiler implicitly links with -lc since on some
# systems, -lgcc has to come before -lc. If gcc already passes -lc
# to ld, don't add -lc before -lgcc.
AC_CACHE_CHECK([whether -lc should be explicitly linked in],
[lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
[$RM conftest*
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
soname=conftest
lib=conftest
libobjs=conftest.$ac_objext
deplibs=
wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
compiler_flags=-v
linker_flags=-v
verstring=
output_objdir=.
libname=conftest
lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
_LT_TAGVAR(allow_undefined_flag, $1)=
if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
then
lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
else
lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
fi
_LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
else
cat conftest.err 1>&5
fi
$RM conftest*
])
_LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
;;
esac
fi
;;
esac
_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
[Whether or not to add -lc for building shared libraries])
_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
[enable_shared_with_static_runtimes], [0],
[Whether or not to disallow shared libs when runtime libs are static])
_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
[Compiler flag to allow reflexive dlopens])
_LT_TAGDECL([], [whole_archive_flag_spec], [1],
[Compiler flag to generate shared objects directly from archives])
_LT_TAGDECL([], [compiler_needs_object], [1],
[Whether the compiler copes with passing no objects directly])
_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
[Create an old-style archive from a shared archive])
_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
[Create a temporary old-style archive to link instead of a shared archive])
_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
_LT_TAGDECL([], [archive_expsym_cmds], [2])
_LT_TAGDECL([], [module_cmds], [2],
[Commands used to build a loadable module if different from building
a shared archive.])
_LT_TAGDECL([], [module_expsym_cmds], [2])
_LT_TAGDECL([], [with_gnu_ld], [1],
[Whether we are building with GNU ld or not])
_LT_TAGDECL([], [allow_undefined_flag], [1],
[Flag that allows shared libraries with undefined symbols to be built])
_LT_TAGDECL([], [no_undefined_flag], [1],
[Flag that enforces no undefined symbols])
_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
[Flag to hardcode $libdir into a binary during linking.
This must work even if $libdir does not exist])
_LT_TAGDECL([], [hardcode_libdir_separator], [1],
[Whether we need a single "-rpath" flag with a separated argument])
_LT_TAGDECL([], [hardcode_direct], [0],
[Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
DIR into the resulting binary])
_LT_TAGDECL([], [hardcode_direct_absolute], [0],
[Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
DIR into the resulting binary and the resulting library dependency is
"absolute", i.e. impossible to change by setting $shlibpath_var if the
library is relocated])
_LT_TAGDECL([], [hardcode_minus_L], [0],
[Set to "yes" if using the -LDIR flag during linking hardcodes DIR
into the resulting binary])
_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
[Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
into the resulting binary])
_LT_TAGDECL([], [hardcode_automatic], [0],
[Set to "yes" if building a shared library automatically hardcodes DIR
into the library and all subsequent libraries and executables linked
against it])
_LT_TAGDECL([], [inherit_rpath], [0],
[Set to yes if linker adds runtime paths of dependent libraries
to runtime path list])
_LT_TAGDECL([], [link_all_deplibs], [0],
[Whether libtool must link a program against all its dependency libraries])
_LT_TAGDECL([], [always_export_symbols], [0],
[Set to "yes" if exported symbols are required])
_LT_TAGDECL([], [export_symbols_cmds], [2],
[The commands to list exported symbols])
_LT_TAGDECL([], [exclude_expsyms], [1],
[Symbols that should not be listed in the preloaded symbols])
_LT_TAGDECL([], [include_expsyms], [1],
[Symbols that must always be exported])
_LT_TAGDECL([], [prelink_cmds], [2],
[Commands necessary for linking programs (against libraries) with templates])
_LT_TAGDECL([], [postlink_cmds], [2],
[Commands necessary for finishing linking programs])
_LT_TAGDECL([], [file_list_spec], [1],
[Specify filename containing input files])
dnl FIXME: Not yet implemented
dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
dnl [Compiler flag to generate thread safe objects])
])# _LT_LINKER_SHLIBS
# _LT_LANG_C_CONFIG([TAG])
# ------------------------
# Ensure that the configuration variables for a C compiler are suitably
# defined. These variables are subsequently used by _LT_CONFIG to write
# the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_C_CONFIG],
[m4_require([_LT_DECL_EGREP])dnl
lt_save_CC=$CC
AC_LANG_PUSH(C)
# Source file extension for C test sources.
ac_ext=c
# Object file extension for compiled C test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="int some_variable = 0;"
# Code to be used in simple link tests
lt_simple_link_test_code='int main(void){return(0);}'
_LT_TAG_COMPILER
# Save the default compiler, since it gets overwritten when the other
# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
compiler_DEFAULT=$CC
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then
_LT_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
LT_SYS_DLOPEN_SELF
_LT_CMD_STRIPLIB
# Report what library types will actually be built
AC_MSG_CHECKING([if libtool supports shared libraries])
AC_MSG_RESULT([$can_build_shared])
AC_MSG_CHECKING([whether to build shared libraries])
test no = "$can_build_shared" && enable_shared=no
# On AIX, shared libraries and static libraries use the same namespace, and
# are all built from PIC.
case $host_os in
aix3*)
test yes = "$enable_shared" && enable_static=no
if test -n "$RANLIB"; then
archive_cmds="$archive_cmds~\$RANLIB \$lib"
postinstall_cmds='$RANLIB $lib'
fi
;;
aix[[4-9]]*)
if test ia64 != "$host_cpu"; then
case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
yes,aix,yes) ;; # shared object as lib.so file only
yes,svr4,*) ;; # shared object as lib.so archive member only
yes,*) enable_static=no ;; # shared object in lib.a archive as well
esac
fi
;;
esac
AC_MSG_RESULT([$enable_shared])
AC_MSG_CHECKING([whether to build static libraries])
# Make sure either enable_shared or enable_static is yes.
test yes = "$enable_shared" || enable_static=yes
AC_MSG_RESULT([$enable_static])
_LT_CONFIG($1)
fi
AC_LANG_POP
CC=$lt_save_CC
])# _LT_LANG_C_CONFIG
# _LT_LANG_CXX_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for a C++ compiler are suitably
# defined. These variables are subsequently used by _LT_CONFIG to write
# the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_CXX_CONFIG],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_DECL_EGREP])dnl
m4_require([_LT_PATH_MANIFEST_TOOL])dnl
if test -n "$CXX" && ( test no != "$CXX" &&
( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
(test g++ != "$CXX"))); then
AC_PROG_CXXCPP
else
_lt_caught_CXX_error=yes
fi
AC_LANG_PUSH(C++)
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(compiler_needs_object, $1)=no
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
# Source file extension for C++ test sources.
ac_ext=cpp
# Object file extension for compiled C++ test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# No sense in running all these tests if we already determined that
# the CXX compiler isn't working. Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test yes != "$_lt_caught_CXX_error"; then
# Code to be used in simple compile tests
lt_simple_compile_test_code="int some_variable = 0;"
# Code to be used in simple link tests
lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_LD=$LD
lt_save_GCC=$GCC
GCC=$GXX
lt_save_with_gnu_ld=$with_gnu_ld
lt_save_path_LD=$lt_cv_path_LD
if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
else
$as_unset lt_cv_prog_gnu_ld
fi
if test -n "${lt_cv_path_LDCXX+set}"; then
lt_cv_path_LD=$lt_cv_path_LDCXX
else
$as_unset lt_cv_path_LD
fi
test -z "${LDCXX+set}" || LD=$LDCXX
CC=${CXX-"c++"}
CFLAGS=$CXXFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
if test -n "$compiler"; then
# We don't want -fno-exception when compiling C++ code, so set the
# no_builtin_flag separately
if test yes = "$GXX"; then
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
else
_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
fi
if test yes = "$GXX"; then
# Set up default GNU C++ configuration
LT_PATH_LD
# Check if GNU C++ uses GNU ld as the underlying linker, since the
# archiving commands below assume that GNU ld is being used.
if test yes = "$with_gnu_ld"; then
_LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared $stdlibflag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared $stdlibflag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
# If archive_cmds runs LD, not CC, wlarc should be empty
# XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
# investigate it a little bit more. (MM)
wlarc='$wl'
# ancient GNU ld didn't support --whole-archive et. al.
if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
_LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
else
_LT_TAGVAR(whole_archive_flag_spec, $1)=
fi
else
with_gnu_ld=no
wlarc=
# A generic and very simple default shared library creation
# command for GNU C++ for the case where it uses the native
# linker, instead of GNU ld. If possible, this setting should
# overridden to take advantage of the native linker features on
# the platform it is being used on.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $stdlibflag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
fi
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP -v "^Driving:" | $GREP " [[-]]L"'
else
GXX=no
with_gnu_ld=no
wlarc=
fi
# PORTME: fill in a description of your system's C++ link characteristics
AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
_LT_TAGVAR(ld_shlibs, $1)=yes
case $host_os in
aix3*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
aix[[4-9]]*)
if test ia64 = "$host_cpu"; then
# On IA64, the linker does run time linking by default, so we don't
# have to do anything special.
aix_use_runtimelinking=no
exp_sym_flag='-Bexport'
no_entry_flag=
else
aix_use_runtimelinking=no
# Test if we are trying to use run time linking or normal
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
# have runtime linking enabled, and use it for executables.
# For shared libraries, we enable/disable runtime linking
# depending on the kind of the shared library created -
# when "with_aix_soname,aix_use_runtimelinking" is:
# "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
# "aix,yes" lib.so shared, rtl:yes, for executables
# lib.a static archive
# "both,no" lib.so.V(shr.o) shared, rtl:yes
# lib.a(lib.so.V) shared, rtl:no, for executables
# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
# lib.a(lib.so.V) shared, rtl:no
# "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
# lib.a static archive
case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
for ld_flag in $LDFLAGS; do
case $ld_flag in
*-brtl*)
aix_use_runtimelinking=yes
break
;;
esac
done
if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
# With aix-soname=svr4, we create the lib.so.V shared archives only,
# so we don't have lib.a shared libs to link our executables.
# We have to force runtime linking in this case.
aix_use_runtimelinking=yes
LDFLAGS="$LDFLAGS -Wl,-brtl"
fi
;;
esac
exp_sym_flag='-bexport'
no_entry_flag='-bnoentry'
fi
# When large executables or shared objects are built, AIX ld can
# have problems creating the table of contents. If linking a library
# or program results in "error TOC overflow" add -mminimal-toc to
# CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
# enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
_LT_TAGVAR(archive_cmds, $1)=''
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='$wl-f,'
case $with_aix_soname,$aix_use_runtimelinking in
aix,*) ;; # no import file
svr4,* | *,yes) # use import file
# The Import File defines what to hardcode.
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
;;
esac
if test yes = "$GXX"; then
case $host_os in aix4.[[012]]|aix4.[[012]].*)
# We only want to do this on AIX 4.2 and lower, the check
# below for broken collect2 doesn't work under 4.3+
collect2name=`$CC -print-prog-name=collect2`
if test -f "$collect2name" &&
strings "$collect2name" | $GREP resolve_lib_name >/dev/null
then
# We have reworked collect2
:
else
# We have old collect2
_LT_TAGVAR(hardcode_direct, $1)=unsupported
# It fails to find uninstalled libraries when the uninstalled
# path is not listed in the libpath. Setting hardcode_minus_L
# to unsupported forces relinking
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=
fi
esac
shared_flag='-shared'
if test yes = "$aix_use_runtimelinking"; then
shared_flag=$shared_flag' $wl-G'
fi
# Need to ensure runtime linking is disabled for the traditional
# shared library, or the linker may eventually find shared libraries
# /with/ Import File - we do not want to mix them.
shared_flag_aix='-shared'
shared_flag_svr4='-shared $wl-G'
else
# not using gcc
if test ia64 = "$host_cpu"; then
# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
# chokes on -Wl,-G. The following line is correct:
shared_flag='-G'
else
if test yes = "$aix_use_runtimelinking"; then
shared_flag='$wl-G'
else
shared_flag='$wl-bM:SRE'
fi
shared_flag_aix='$wl-bM:SRE'
shared_flag_svr4='$wl-G'
fi
fi
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
# It seems that -bexpall does not export symbols beginning with
# underscore (_), so it is better to generate a list of symbols to
# export.
_LT_TAGVAR(always_export_symbols, $1)=yes
if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
# Warning - without using the other runtime loading flags (-brtl),
# -berok will link without error, but may produce a broken library.
# The "-G" linker flag allows undefined symbols.
_LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
# Determine the default libpath from the value encoded in an empty
# executable.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
else
if test ia64 = "$host_cpu"; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
_LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
_LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
else
# Determine the default libpath from the value encoded in an
# empty executable.
_LT_SYS_MODULE_PATH_AIX([$1])
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
# Warning - without using the other run time loading flags,
# -berok will link without error, but may produce a broken library.
_LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
if test yes = "$with_gnu_ld"; then
# We only use this code for GNU lds that support --whole-archive.
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
else
# Exported symbols can be pulled into shared objects from archives
_LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
_LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
# -brtl affects multiple linker settings, -berok does not and is overridden later
compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
if test svr4 != "$with_aix_soname"; then
# This is similar to how AIX traditionally builds its shared
# libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
fi
if test aix != "$with_aix_soname"; then
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
else
# used by -dlpreopen to get the symbols
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
fi
_LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
fi
fi
;;
beos*)
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
# Joseph Beckenbach says some releases of gcc
# support --undefined. This deserves some investigation. FIXME
_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
chorus*)
case $cc_basename in
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
cygwin* | mingw* | windows* | pw32* | cegcc*)
case $GXX,$cc_basename in
,cl* | no,cl* | ,icl* | no,icl* | ,icx* | no,icx* | ,icpx* | no,icpx*)
# Native MSVC and Intel compilers
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
# Tell ltmain to make .lib files, not .a files.
libext=lib
# Tell ltmain to make .dll files, not .so files.
shrext_cmds=.dll
# FIXME: Setting linknames here is a bad hack.
# A check exists to verify if there are linker flags, which will use
# different commands when linking.
_LT_TAGVAR(archive_cmds, $1)='$CC -Fe$output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
cp "$export_symbols" "$output_objdir/$soname.def";
echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.expsym";
else
$SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.expsym;
fi~
if test -z "$linker_flags"; then
$CC -Fe$tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.expsym" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib";
else
$CC -Fe$tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.expsym" -Wl,$linker_flags-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib";
fi~
linknames='
# The linker will not automatically build a static lib if we build a DLL.
# _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
# Don't use ranlib
_LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
_LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
lt_tool_outputfile="@TOOL_OUTPUT@"~
case $lt_outputfile in
*.exe|*.EXE) ;;
*)
lt_outputfile=$lt_outputfile.exe
lt_tool_outputfile=$lt_tool_outputfile.exe
;;
esac~
func_to_tool_file "$lt_outputfile"~
if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
$MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
$RM "$lt_outputfile.manifest";
fi'
;;
*)
# g++
# _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
# as there is no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $stdlibflag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
# If the export-symbols file already is a .def file, use it as
# is; otherwise, prepend EXPORTS...
_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
cp $export_symbols $output_objdir/$soname.def;
else
echo EXPORTS > $output_objdir/$soname.def;
cat $export_symbols >> $output_objdir/$soname.def;
fi~
$CC -shared $stdlibflag $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
darwin* | rhapsody*)
_LT_DARWIN_LINKER_FEATURES($1)
;;
os2*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
_LT_TAGVAR(hardcode_minus_L, $1)=yes
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
shrext_cmds=.dll
_LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
prefix_cmds="$SED"~
if test EXPORTS = "`$SED 1q $export_symbols`"; then
prefix_cmds="$prefix_cmds -e 1d";
fi~
prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
;;
dgux*)
case $cc_basename in
ec++*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
ghcx*)
# Green Hills C++ Compiler
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
freebsd2.*)
# C++ shared libraries reported to be fairly broken before
# switch to ELF
_LT_TAGVAR(ld_shlibs, $1)=no
;;
freebsd-elf*)
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
;;
freebsd* | dragonfly* | midnightbsd*)
# FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
# conventions
_LT_TAGVAR(ld_shlibs, $1)=yes
;;
haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(link_all_deplibs, $1)=no
;;
hpux9*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
# but as the default
# location of the library.
case $cc_basename in
CC*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
aCC*)
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "[[-]]L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test yes = "$GXX"; then
_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $stdlibflag $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
else
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
hpux10*|hpux11*)
if test no = "$with_gnu_ld"; then
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
case $host_cpu in
hppa*64*|ia64*)
;;
*)
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
;;
esac
fi
case $host_cpu in
hppa*64*|ia64*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
*)
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
# but as the default
# location of the library.
;;
esac
case $cc_basename in
CC*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
aCC*)
case $host_cpu in
hppa*64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
esac
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " [[-]]L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test yes = "$GXX"; then
if test no = "$with_gnu_ld"; then
case $host_cpu in
hppa*64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $stdlibflag -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
ia64*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $stdlibflag $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $stdlibflag $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
;;
esac
fi
else
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
interix[[3-9]]*)
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
# Instead, shared libraries are loaded at an image base (0x10000000 by
# default) and relocated if they conflict, which is a slow very memory
# consuming and fragmenting process. To avoid this, we pick a random,
# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
# time. Moving up from 0x10000000 also allows more sbrk(2) space.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
;;
irix5* | irix6*)
case $cc_basename in
CC*)
# SGI C++
_LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
# Archives containing C++ object files must be created using
# "CC -ar", where "CC" is the IRIX C++ compiler. This is
# necessary to make sure instantiated templates are included
# in the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
;;
*)
if test yes = "$GXX"; then
if test no = "$with_gnu_ld"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $stdlibflag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
else
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $stdlibflag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
fi
fi
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
esac
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
_LT_TAGVAR(inherit_rpath, $1)=yes
;;
*-mlibc)
_LT_TAGVAR(ld_shlibs, $1)=yes
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
KCC*)
# Kuck and Associates, Inc. (KAI) C++ Compiler
# KCC will only create a shared library if the output file
# ends with ".so" (or ".sl" for HP-UX), so rename the library
# to its proper name (with version) after linking.
_LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
# Archives containing C++ object files must be created using
# "CC -Bstatic", where "CC" is the KAI C++ compiler.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
;;
icpc* | ecpc* | icpx*)
# Intel C++
with_gnu_ld=yes
# version 8.0 and above of icpc choke on multiply defined symbols
# if we add $predep_objects and $postdep_objects, however 7.1 and
# earlier do not add the objects themselves.
case `$CC -V 2>&1` in
*"Version 7."*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
;;
*) # Version 8.0 or newer
tmp_idyn=
case $host_cpu in
ia64*) tmp_idyn=' -i_dynamic';;
esac
_LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
;;
esac
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
;;
pgCC* | pgcpp*)
# Portland Group C++ compiler
case `$CC -V` in
*pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
_LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
_LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
$RANLIB $oldlib'
_LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
rm -rf $tpldir~
$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
;;
*) # Version 6 and above use weak symbols
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
;;
esac
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
;;
cxx*)
# Compaq C++
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols'
runpath_var=LD_RUN_PATH
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
;;
xl* | mpixl* | bgxl*)
# IBM XL 8.0 on PPC, with GNU ld
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
_LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
fi
;;
*)
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ C*)
# Sun C++ 5.9
_LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
_LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
_LT_TAGVAR(compiler_needs_object, $1)=yes
# Not sure whether something based on
# $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
# would be better.
output_verbose_link_cmd='func_echo_all'
# Archives containing C++ object files must be created using
# "CC -xar", where "CC" is the Sun C++ compiler. This is
# necessary to make sure instantiated templates are included
# in the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
;;
esac
;;
esac
;;
lynxos*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
m88k*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
mvs*)
case $cc_basename in
cxx*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
netbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
wlarc=
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
else
_LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
fi
output_verbose_link_cmd=func_echo_all
;;
*nto* | *qnx*)
_LT_TAGVAR(ld_shlibs, $1)=yes
;;
openbsd*)
if test -f /usr/libexec/ld.so; then
_LT_TAGVAR(hardcode_direct, $1)=yes
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
_LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
fi
output_verbose_link_cmd=func_echo_all
else
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
osf3* | osf4* | osf5*)
case $cc_basename in
KCC*)
# Kuck and Associates, Inc. (KAI) C++ Compiler
# KCC will only create a shared library if the output file
# ends with ".so" (or ".sl" for HP-UX), so rename the library
# to its proper name (with version) after linking.
_LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Archives containing C++ object files must be created using
# the KAI C++ compiler.
case $host in
osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
esac
;;
RCC*)
# Rational C++ 2.4.1
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
cxx*)
case $host in
osf3*)
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
;;
*)
_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.expsym; done~
echo "-hidden">> $lib.expsym~
$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.expsym `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
$RM $lib.expsym'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
;;
esac
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
#
# There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test yes,no = "$GXX,$with_gnu_ld"; then
_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
case $host in
osf3*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $stdlibflag $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $stdlibflag $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
;;
esac
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=:
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP -v "^Driving:" | $GREP " [[-]]L"'
else
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
fi
;;
esac
;;
psos*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
serenity*)
;;
sunos4*)
case $cc_basename in
CC*)
# Sun C++ 4.x
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
lcc*)
# Lucid
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
solaris*)
case $cc_basename in
CC* | sunCC*)
# Sun C++ 4.2, 5.x and Centerline C++
_LT_TAGVAR(archive_cmds_need_lc,$1)=yes
_LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
_LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.expsym~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.expsym~echo "local: *; };" >> $lib.expsym~
$CC -G$allow_undefined_flag $wl-M $wl$lib.expsym -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.expsym'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
case $host_os in
solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
*)
# The compiler driver will combine and reorder linker options,
# but understands '-z linker_flag'.
# Supported since Solaris 2.6 (maybe 2.5.1?)
_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
;;
esac
_LT_TAGVAR(link_all_deplibs, $1)=yes
output_verbose_link_cmd='func_echo_all'
# Archives containing C++ object files must be created using
# "CC -xar", where "CC" is the Sun C++ compiler. This is
# necessary to make sure instantiated templates are included
# in the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
;;
gcx*)
# Green Hills C++ Compiler
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
# The C++ compiler must be used to create the archive.
_LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
;;
*)
# GNU C++ compiler with Solaris linker
if test yes,no = "$GXX,$with_gnu_ld"; then
_LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
if $CC --version | $GREP -v '^2\.7' > /dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $stdlibflag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.expsym~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.expsym~echo "local: *; };" >> $lib.expsym~
$CC -shared $pic_flag $stdlibflag $wl-M $wl$lib.expsym $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.expsym'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP -v "^Driving:" | $GREP " [[-]]L"'
else
# g++ 2.7 appears to require '-G' NOT '-shared' on this
# platform.
_LT_TAGVAR(archive_cmds, $1)='$CC -G $stdlibflag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.expsym~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.expsym~echo "local: *; };" >> $lib.expsym~
$CC -G $stdlibflag $wl-M $wl$lib.expsym $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.expsym'
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP -v "^Driving:" | $GREP " [[-]]L"'
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
case $host_os in
solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
*)
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
;;
esac
fi
;;
esac
;;
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
runpath_var='LD_RUN_PATH'
case $cc_basename in
CC*)
_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
esac
;;
sysv5* | sco3.2v5* | sco5v6*)
# Note: We CANNOT use -z defs as we might desire, because we do not
# link with -lc, and that would cause any symbols used from libc to
# always be unresolved, which means just about no library would
# ever link correctly. If we're not using GNU ld we use -z text
# though, which does catch some bad symbols but isn't as heavy-handed
# as -z defs.
_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
_LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
_LT_TAGVAR(link_all_deplibs, $1)=yes
_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
runpath_var='LD_RUN_PATH'
case $cc_basename in
CC*)
_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
'"$_LT_TAGVAR(old_archive_cmds, $1)"
_LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
'"$_LT_TAGVAR(reload_cmds, $1)"
;;
*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
esac
;;
tandem*)
case $cc_basename in
NCC*)
# NonStop-UX NCC 3.20
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
;;
vxworks*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
*)
# FIXME: insert proper C++ library support
_LT_TAGVAR(ld_shlibs, $1)=no
;;
esac
AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
_LT_TAGVAR(GCC, $1)=$GXX
_LT_TAGVAR(LD, $1)=$LD
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
_LT_SYS_HIDDEN_LIBDEPS($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi # test -n "$compiler"
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
LDCXX=$LD
LD=$lt_save_LD
GCC=$lt_save_GCC
with_gnu_ld=$lt_save_with_gnu_ld
lt_cv_path_LDCXX=$lt_cv_path_LD
lt_cv_path_LD=$lt_save_path_LD
lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
fi # test yes != "$_lt_caught_CXX_error"
AC_LANG_POP
])# _LT_LANG_CXX_CONFIG
# _LT_FUNC_STRIPNAME_CNF
# ----------------------
# func_stripname_cnf prefix suffix name
# strip PREFIX and SUFFIX off of NAME.
# PREFIX and SUFFIX must not contain globbing or regex special
# characters, hashes, percent signs, but SUFFIX may contain a leading
# dot (in which case that matches only a dot).
#
# This function is identical to the (non-XSI) version of func_stripname,
# except this one can be used by m4 code that may be executed by configure,
# rather than the libtool script.
m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
AC_REQUIRE([_LT_DECL_SED])
AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
func_stripname_cnf ()
{
case @S|@2 in
.*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;;
*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;;
esac
} # func_stripname_cnf
])# _LT_FUNC_STRIPNAME_CNF
# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
# ---------------------------------
# Figure out "hidden" library dependencies from verbose
# compiler output when linking a shared library.
# Parse the compiler output and extract the necessary
# objects, libraries and library flags.
m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
# Dependencies to place before and after the object being linked:
_LT_TAGVAR(predep_objects, $1)=
_LT_TAGVAR(postdep_objects, $1)=
_LT_TAGVAR(predeps, $1)=
_LT_TAGVAR(postdeps, $1)=
_LT_TAGVAR(compiler_lib_search_path, $1)=
dnl we can't use the lt_simple_compile_test_code here,
dnl because it contains code intended for an executable,
dnl not a library. It's possible we should let each
dnl tag define a new lt_????_link_test_code variable,
dnl but it's only used here...
m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
int a;
void foo (void) { a = 0; }
_LT_EOF
], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
class Foo
{
public:
Foo (void) { a = 0; }
private:
int a;
};
_LT_EOF
], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
subroutine foo
implicit none
integer*4 a
a=0
return
end
_LT_EOF
], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
subroutine foo
implicit none
integer a
a=0
return
end
_LT_EOF
], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
public class foo {
private int a;
public void bar (void) {
a = 0;
}
};
_LT_EOF
], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
package foo
func foo() {
}
_LT_EOF
])
_lt_libdeps_save_CFLAGS=$CFLAGS
case "$CC $CFLAGS " in #(
*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
esac
dnl Parse the compiler output and extract the necessary
dnl objects, libraries and library flags.
if AC_TRY_EVAL(ac_compile); then
# Parse the compiler output and extract the necessary
# objects, libraries and library flags.
# Sentinel used to keep track of whether or not we are before
# the conftest object file.
pre_test_object_deps_done=no
if test yes = "$enable_cxx_stdlib"; then
output_verbose_link_cmd=
fi
for p in `eval "$output_verbose_link_cmd"`; do
case $prev$p in
-L* | -R* | -l* | */libclang_rt.*.a)
# Some compilers place space between "-{L,R,l}" and the path.
# Remove the space.
if test x-L = x"$p" ||
test x-R = x"$p" ||
test x-l = x"$p"; then
prev=$p
continue
fi
# Expand the sysroot to ease extracting the directories later.
if test -z "$prev"; then
case $p in
-L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
-R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
-l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
esac
fi
case $p in
=*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
esac
if test no = "$pre_test_object_deps_done"; then
case $prev in
-L | -R)
# Internal compiler library paths should come after those
# provided the user. The postdeps already come after the
# user supplied libs so there is no need to process them.
if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
_LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p
else
_LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p"
fi
;;
# The "-l" case would never come before the object being
# linked, so don't bother handling this case.
esac
else
if test -z "$_LT_TAGVAR(postdeps, $1)"; then
_LT_TAGVAR(postdeps, $1)=$prev$p
else
_LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p"
fi
fi
prev=
;;
*.lto.$objext) ;; # Ignore GCC LTO objects
*.$objext)
# This assumes that the test object file only shows up
# once in the compiler output.
if test "$p" = "conftest.$objext"; then
pre_test_object_deps_done=yes
continue
fi
if test no = "$pre_test_object_deps_done"; then
if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
_LT_TAGVAR(predep_objects, $1)=$p
else
_LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
fi
else
if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
_LT_TAGVAR(postdep_objects, $1)=$p
else
_LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
fi
fi
;;
*) ;; # Ignore the rest.
esac
done
# Clean up.
rm -f a.out a.exe
else
echo "libtool.m4: error: problem compiling $1 test program"
fi
$RM -f confest.$objext
CFLAGS=$_lt_libdeps_save_CFLAGS
# PORTME: override above test on systems where it is broken
m4_if([$1], [CXX],
[case $host_os in
interix[[3-9]]*)
# Interix 3.5 installs completely hosed .la files for C++, so rather than
# hack all around it, let's just trust "g++" to DTRT.
_LT_TAGVAR(predep_objects,$1)=
_LT_TAGVAR(postdep_objects,$1)=
_LT_TAGVAR(postdeps,$1)=
;;
esac
])
case " $_LT_TAGVAR(postdeps, $1) " in
*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
esac
_LT_TAGVAR(compiler_lib_search_dirs, $1)=
if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
_LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'`
fi
_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
[The directories searched by this compiler when creating a shared library])
_LT_TAGDECL([], [predep_objects], [1],
[Dependencies to place before and after the objects being linked to
create a shared library])
_LT_TAGDECL([], [postdep_objects], [1])
_LT_TAGDECL([], [predeps], [1])
_LT_TAGDECL([], [postdeps], [1])
_LT_TAGDECL([], [compiler_lib_search_path], [1],
[The library search path used internally by the compiler when linking
a shared library])
])# _LT_SYS_HIDDEN_LIBDEPS
# _LT_LANG_F77_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for a Fortran 77 compiler are
# suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_F77_CONFIG],
[AC_LANG_PUSH(Fortran 77)
if test -z "$F77" || test no = "$F77"; then
_lt_disable_F77=yes
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
# Source file extension for f77 test sources.
ac_ext=f
# Object file extension for compiled f77 test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# No sense in running all these tests if we already determined that
# the F77 compiler isn't working. Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test yes != "$_lt_disable_F77"; then
# Code to be used in simple compile tests
lt_simple_compile_test_code="\
subroutine t
return
end
"
# Code to be used in simple link tests
lt_simple_link_test_code="\
program t
end
"
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_GCC=$GCC
lt_save_CFLAGS=$CFLAGS
CC=${F77-"f77"}
CFLAGS=$FFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
GCC=$G77
if test -n "$compiler"; then
AC_MSG_CHECKING([if libtool supports shared libraries])
AC_MSG_RESULT([$can_build_shared])
AC_MSG_CHECKING([whether to build shared libraries])
test no = "$can_build_shared" && enable_shared=no
# On AIX, shared libraries and static libraries use the same namespace, and
# are all built from PIC.
case $host_os in
aix3*)
test yes = "$enable_shared" && enable_static=no
if test -n "$RANLIB"; then
archive_cmds="$archive_cmds~\$RANLIB \$lib"
postinstall_cmds='$RANLIB $lib'
fi
;;
aix[[4-9]]*)
if test ia64 != "$host_cpu"; then
case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
yes,aix,yes) ;; # shared object as lib.so file only
yes,svr4,*) ;; # shared object as lib.so archive member only
yes,*) enable_static=no ;; # shared object in lib.a archive as well
esac
fi
;;
esac
AC_MSG_RESULT([$enable_shared])
AC_MSG_CHECKING([whether to build static libraries])
# Make sure either enable_shared or enable_static is yes.
test yes = "$enable_shared" || enable_static=yes
AC_MSG_RESULT([$enable_static])
_LT_TAGVAR(GCC, $1)=$G77
_LT_TAGVAR(LD, $1)=$LD
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi # test -n "$compiler"
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
fi # test yes != "$_lt_disable_F77"
AC_LANG_POP
])# _LT_LANG_F77_CONFIG
# _LT_LANG_FC_CONFIG([TAG])
# -------------------------
# Ensure that the configuration variables for a Fortran compiler are
# suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_FC_CONFIG],
[AC_LANG_PUSH(Fortran)
if test -z "$FC" || test no = "$FC"; then
_lt_disable_FC=yes
fi
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no
_LT_TAGVAR(archive_expsym_cmds, $1)=
_LT_TAGVAR(export_dynamic_flag_spec, $1)=
_LT_TAGVAR(hardcode_direct, $1)=no
_LT_TAGVAR(hardcode_direct_absolute, $1)=no
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
_LT_TAGVAR(hardcode_libdir_separator, $1)=
_LT_TAGVAR(hardcode_minus_L, $1)=no
_LT_TAGVAR(hardcode_automatic, $1)=no
_LT_TAGVAR(inherit_rpath, $1)=no
_LT_TAGVAR(module_cmds, $1)=
_LT_TAGVAR(module_expsym_cmds, $1)=
_LT_TAGVAR(link_all_deplibs, $1)=unknown
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
_LT_TAGVAR(no_undefined_flag, $1)=
_LT_TAGVAR(whole_archive_flag_spec, $1)=
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
# Source file extension for fc test sources.
ac_ext=${ac_fc_srcext-f}
# Object file extension for compiled fc test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# No sense in running all these tests if we already determined that
# the FC compiler isn't working. Some variables (like enable_shared)
# are currently assumed to apply to all compilers on this platform,
# and will be corrupted by setting them based on a non-working compiler.
if test yes != "$_lt_disable_FC"; then
# Code to be used in simple compile tests
lt_simple_compile_test_code="\
subroutine t
return
end
"
# Code to be used in simple link tests
lt_simple_link_test_code="\
program t
end
"
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_GCC=$GCC
lt_save_CFLAGS=$CFLAGS
CC=${FC-"f95"}
CFLAGS=$FCFLAGS
compiler=$CC
GCC=$ac_cv_fc_compiler_gnu
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
if test -n "$compiler"; then
AC_MSG_CHECKING([if libtool supports shared libraries])
AC_MSG_RESULT([$can_build_shared])
AC_MSG_CHECKING([whether to build shared libraries])
test no = "$can_build_shared" && enable_shared=no
# On AIX, shared libraries and static libraries use the same namespace, and
# are all built from PIC.
case $host_os in
aix3*)
test yes = "$enable_shared" && enable_static=no
if test -n "$RANLIB"; then
archive_cmds="$archive_cmds~\$RANLIB \$lib"
postinstall_cmds='$RANLIB $lib'
fi
;;
aix[[4-9]]*)
if test ia64 != "$host_cpu"; then
case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
yes,aix,yes) ;; # shared object as lib.so file only
yes,svr4,*) ;; # shared object as lib.so archive member only
yes,*) enable_static=no ;; # shared object in lib.a archive as well
esac
fi
;;
esac
AC_MSG_RESULT([$enable_shared])
AC_MSG_CHECKING([whether to build static libraries])
# Make sure either enable_shared or enable_static is yes.
test yes = "$enable_shared" || enable_static=yes
AC_MSG_RESULT([$enable_static])
_LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu
_LT_TAGVAR(LD, $1)=$LD
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
_LT_SYS_HIDDEN_LIBDEPS($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_SYS_DYNAMIC_LINKER($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi # test -n "$compiler"
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
fi # test yes != "$_lt_disable_FC"
AC_LANG_POP
])# _LT_LANG_FC_CONFIG
# _LT_LANG_GCJ_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for the GNU Java Compiler compiler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_GCJ_CONFIG],
[AC_REQUIRE([LT_PROG_GCJ])dnl
AC_LANG_SAVE
# Source file extension for Java test sources.
ac_ext=java
# Object file extension for compiled Java test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="class foo {}"
# Code to be used in simple link tests
lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=yes
CC=${GCJ-"gcj"}
CFLAGS=$GCJFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_TAGVAR(LD, $1)=$LD
_LT_CC_BASENAME([$compiler])
# GCJ did not exist at the time GCC didn't implicitly link libc in.
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then
_LT_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi
AC_LANG_RESTORE
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_GCJ_CONFIG
# _LT_LANG_ML64_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for the ML64 assembler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_ML64_CONFIG],
[AC_REQUIRE([LT_PROG_ML64])dnl
AC_LANG_SAVE
# Source file extension for ML64 test sources.
ac_ext=asm
#Object file extension for compile ML64 test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="main PROC ret main ENDP"
# Code to be used in simple link tests
lt_simple_link_test_code="main PROC ret main ENDP"
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# TODO? Check for compilation issues with ML64 flags.
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=yes
CC=${ML64-"gcc"}
CFLAGS=$ML64FLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_TAGVAR(LD, $1)=$LD
_LT_CC_BASENAME([$compiler])
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then
_LT_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi
AC_LANG_RESTORE
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_ML64_CONFIG
# _LT_LANG_GO_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for the GNU Go compiler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_GO_CONFIG],
[AC_REQUIRE([LT_PROG_GO])dnl
AC_LANG_SAVE
# Source file extension for Go test sources.
ac_ext=go
# Object file extension for compiled Go test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="package main; func main() { }"
# Code to be used in simple link tests
lt_simple_link_test_code='package main; func main() { }'
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=yes
CC=${GOC-"gccgo"}
CFLAGS=$GOFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_TAGVAR(LD, $1)=$LD
_LT_CC_BASENAME([$compiler])
# Go did not exist at the time GCC didn't implicitly link libc in.
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then
_LT_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi
AC_LANG_RESTORE
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_GO_CONFIG
# _LT_LANG_OBJC_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for the GNU Objective-C compiler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_OBJC_CONFIG],
[AC_REQUIRE([LT_PROG_OBJC])dnl
AC_LANG_SAVE
# Source file extension for OBJC test sources.
ac_ext=m
# Object file extension for compiled OBJC test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="int some_variable = 0;"
# Code to be used in simple link tests
lt_simple_link_test_code='int main(void){return(0);}'
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Check for compilation issues with OBJC flags
_LT_OBJECTIVE_C
if test "yes" = "$lt_cv_gnustep_exists"; then
OBJCFLAGS="$OBJCFLAGS `gnustep-config --objc-flags`"
fi
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=yes
CC=${OBJC-"gcc"}
CFLAGS=$OBJCFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_TAGVAR(LD, $1)=$LD
_LT_CC_BASENAME([$compiler])
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then
_LT_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi
AC_LANG_RESTORE
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_OBJC_CONFIG
# _LT_LANG_OBJCXX_CONFIG([TAG])
# --------------------------
# Ensure that the configuration variables for the GNU Objective-C++ compiler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_OBJCXX_CONFIG],
[AC_REQUIRE([LT_PROG_OBJCXX])dnl
AC_LANG_SAVE
# Source file extension for OBJCXX test sources.
ac_ext=mm
# Object file extension for compiled OBJCXX test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="int some_variable = 0;"
# Code to be used in simple link tests
lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Check for compilation issues with OBJCXX flags
_LT_OBJECTIVE_C
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=yes
CC=${OBJCXX-"g++"}
CFLAGS=$OBJCXXFLAGS
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_TAGVAR(LD, $1)=$LD
_LT_CC_BASENAME([$compiler])
_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
_LT_TAGVAR(reload_flag, $1)=$reload_flag
_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then
_LT_COMPILER_NO_RTTI($1)
_LT_COMPILER_PIC($1)
_LT_COMPILER_C_O($1)
_LT_COMPILER_FILE_LOCKS($1)
_LT_LINKER_SHLIBS($1)
_LT_LINKER_HARDCODE_LIBPATH($1)
_LT_CONFIG($1)
fi
AC_LANG_RESTORE
GCC=$lt_save_GCC
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_OBJCXX_CONFIG
# _LT_LANG_RC_CONFIG([TAG])
# -------------------------
# Ensure that the configuration variables for the Windows resource compiler
# are suitably defined. These variables are subsequently used by _LT_CONFIG
# to write the compiler configuration to 'libtool'.
m4_defun([_LT_LANG_RC_CONFIG],
[AC_REQUIRE([LT_PROG_RC])dnl
AC_LANG_SAVE
# Source file extension for RC test sources.
ac_ext=rc
# Object file extension for compiled RC test sources.
objext=o
_LT_TAGVAR(objext, $1)=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
# Code to be used in simple link tests
lt_simple_link_test_code=$lt_simple_compile_test_code
# ltmain only uses $CC for tagged configurations so make sure $CC is set.
_LT_TAG_COMPILER
# save warnings/boilerplate of simple test code
_LT_COMPILER_BOILERPLATE
_LT_LINKER_BOILERPLATE
# Allow CC to be a program name with arguments.
lt_save_CC=$CC
lt_save_CFLAGS=$CFLAGS
lt_save_GCC=$GCC
GCC=
CC=${RC-"windres"}
CFLAGS=
compiler=$CC
_LT_TAGVAR(compiler, $1)=$CC
_LT_CC_BASENAME([$compiler])
_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
if test -n "$compiler"; then
:
_LT_CONFIG($1)
fi
GCC=$lt_save_GCC
AC_LANG_RESTORE
CC=$lt_save_CC
CFLAGS=$lt_save_CFLAGS
])# _LT_LANG_RC_CONFIG
# LT_PROG_ML64
# -----------
AC_DEFUN([LT_PROG_ML64],
[AC_CHECK_TOOL(ML64, ml64,)
])
# LT_PROG_OBJC
# -----------
AC_DEFUN([LT_PROG_OBJC],
[AC_CHECK_TOOL(OBJC, gcc,)
AC_CHECK_TOOL(GNUSTEP_CONFIG, gnustep-config,)
if test Xgnustep-config = X"$GNUSTEP_CONFIG"; then
test set = "${OBJCFLAGS+set}" || OBJCFLAGS="`gnustep-config --objc-flags`"
fi
AC_SUBST(OBJCFLAGS)])])[]dnl
])
# LT_PROG_OBJCXX
# -----------
AC_DEFUN([LT_PROG_OBJCXX],
[AC_CHECK_TOOL(OBJCXX, g++,)
AC_CHECK_TOOL(GNUSTEP_CONFIG, gnustep-config,)
if test Xgnustep-config = X"$GNUSTEP_CONFIG"; then
test set = "${OBJCXXFLAGS+set}" || OBJCXXFLAGS="`gnustep-config --objc-flags`"
fi
AC_SUBST(OBJCXXFLAGS)])])[]dnl
])
# LT_PROG_GCJ
# -----------
AC_DEFUN([LT_PROG_GCJ],
[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
[m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
[AC_CHECK_TOOL(GCJ, gcj,)
test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2"
AC_SUBST(GCJFLAGS)])])[]dnl
])
# Old name:
AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
# LT_PROG_GO
# ----------
AC_DEFUN([LT_PROG_GO],
[AC_CHECK_TOOL(GOC, gccgo,)
])
# LT_PROG_RC
# ----------
AC_DEFUN([LT_PROG_RC],
[AC_CHECK_TOOL(RC, windres,)
])
# Old name:
AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_RC], [])
# _LT_DECL_EGREP
# --------------
# If we don't have a new enough Autoconf to choose the best grep
# available, choose the one first in the user's PATH.
m4_defun([_LT_DECL_EGREP],
[AC_REQUIRE([AC_PROG_EGREP])dnl
AC_REQUIRE([AC_PROG_FGREP])dnl
test -z "$GREP" && GREP=grep
_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
_LT_DECL([], [EGREP], [1], [An ERE matcher])
_LT_DECL([], [FGREP], [1], [A literal string matcher])
dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
AC_SUBST([GREP])
])
# _LT_DECL_OBJDUMP
# --------------
# If we don't have a new enough Autoconf to choose the best objdump
# available, choose the one first in the user's PATH.
m4_defun([_LT_DECL_OBJDUMP],
[AC_CHECK_TOOL(OBJDUMP, objdump, false)
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
AC_SUBST([OBJDUMP])
])
# _LT_DECL_DLLTOOL
# ----------------
# Ensure DLLTOOL variable is set.
m4_defun([_LT_DECL_DLLTOOL],
[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
AC_SUBST([DLLTOOL])
])
# _LT_DECL_FILECMD
# ----------------
# Check for a file(cmd) program that can be used to detect file type and magic
m4_defun([_LT_DECL_FILECMD],
[AC_CHECK_PROG([FILECMD], [file], [file], [:])
_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types])
])# _LD_DECL_FILECMD
# _LT_DECL_SED
# ------------
# Check for a fully-functional sed program, that truncates
# as few characters as possible. Prefer GNU sed if found.
m4_defun([_LT_DECL_SED],
[AC_PROG_SED
test -z "$SED" && SED=sed
Xsed="$SED -e 1s/^X//"
_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
[Sed that helps us avoid accidentally triggering echo(1) options like -n])
])# _LT_DECL_SED
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([LT_AC_PROG_SED], [])
# _LT_CHECK_SHELL_FEATURES
# ------------------------
# Find out whether the shell is Bourne or XSI compatible,
# or has some other useful features.
m4_defun([_LT_CHECK_SHELL_FEATURES],
[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
lt_unset=unset
else
lt_unset=false
fi
_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
# test EBCDIC or ASCII
case `echo X|tr X '\101'` in
A) # ASCII based system
# \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
lt_SP2NL='tr \040 \012'
lt_NL2SP='tr \015\012 \040\040'
;;
*) # EBCDIC based system
lt_SP2NL='tr \100 \n'
lt_NL2SP='tr \r\n \100\100'
;;
esac
_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
])# _LT_CHECK_SHELL_FEATURES
# _LT_PATH_CONVERSION_FUNCTIONS
# -----------------------------
# Determine what file name conversion functions should be used by
# func_to_host_file (and, implicitly, by func_to_host_path). These are needed
# for certain cross-compile configurations and native mingw.
m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
AC_MSG_CHECKING([how to convert $build file names to $host format])
AC_CACHE_VAL(lt_cv_to_host_file_cmd,
[case $host in
*-*-mingw* )
case $build in
*-*-mingw* | *-*-windows* ) # actually msys
lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
;;
*-*-cygwin* )
lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
;;
* ) # otherwise, assume *nix
lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
;;
esac
;;
*-*-cygwin* )
case $build in
*-*-mingw* | *-*-windows* ) # actually msys
lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
;;
*-*-cygwin* )
lt_cv_to_host_file_cmd=func_convert_file_noop
;;
* ) # otherwise, assume *nix
lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
;;
esac
;;
* ) # unhandled hosts (and "normal" native builds)
lt_cv_to_host_file_cmd=func_convert_file_noop
;;
esac
])
to_host_file_cmd=$lt_cv_to_host_file_cmd
AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
[0], [convert $build file names to $host format])dnl
AC_MSG_CHECKING([how to convert $build file names to toolchain format])
AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
[#assume ordinary cross tools, or native build.
lt_cv_to_tool_file_cmd=func_convert_file_noop
case $host in
*-*-mingw* | *-*-windows* )
case $build in
*-*-mingw* | *-*-windows* ) # actually msys
lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
;;
esac
;;
esac
])
to_tool_file_cmd=$lt_cv_to_tool_file_cmd
AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
[0], [convert $build files to toolchain format])dnl
AS_CASE([$host],
[*-*-mingw* | *-*-windows* | *-*-cygwin*],
[AS_CASE([$build],
[*-*-mingw* | *-*-windows* | *-*-cygwin*],
[AC_MSG_CHECKING([whether cygpath is installed])
AC_CACHE_VAL([lt_cv_cygpath_installed],
[lt_cv_cygpath_installed=ignoring
cygpath --help &> /dev/null
_lt_result=$?
AS_IF([test 0 = "$_lt_result"],
[lt_cv_cygpath_installed=yes],
[lt_cv_cygpath_installed=no])
])
AC_MSG_RESULT([$lt_cv_cygpath_installed])
_LT_DECL([cygpath_installed], [lt_cv_cygpath_installed],
[0], [whether cygpath is installed])dnl
AS_IF([test "xyes" != "x$lt_cv_cygpath_installed"],
[
AC_MSG_CHECKING([whether to use cmd with one slash or two slashes])
AC_CACHE_VAL([lt_cv_cmd_slashes],
[
_lt_result=`cmd /c echo one-slash works. Not checked //c echo two-slashes 2>/dev/null`
AS_IF([test 0 != $?],
[AC_MSG_ERROR([Do not know how to convert paths])])
AS_CASE([$_lt_result],
[one-slash*],[lt_cv_cmd_slashes="one"],
[two-slashes*],[lt_cv_cmd_slashes="two"],
[AC_MSG_ERROR([Do not know how to convert paths])]
)
])
AC_MSG_RESULT([$lt_cv_cmd_slashes])
])
])
]
)dnl
])# _LT_PATH_CONVERSION_FUNCTIONS
wimlib-1.14.5/m4/ax_pthread.m4 0000644 0001750 0001750 00000054034 14707301127 013270 0 ustar 00e e # ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
#
# DESCRIPTION
#
# This macro figures out how to build C programs using POSIX threads. It
# sets the PTHREAD_LIBS output variable to the threads library and linker
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
# needed for multi-threaded programs (defaults to the value of CC
# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
# special cc_r/CC_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also to link with them as well. For example, you might link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threaded programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
# CXX="$PTHREAD_CXX"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
# PTHREAD_CFLAGS.
#
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
# is not found. If ACTION-IF-FOUND is not specified, the default action
# will define HAVE_PTHREAD.
#
# Please let the authors know if this macro fails on any platform, or if
# you have any other suggestions or comments. This macro was based on work
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
# grateful for the helpful feedback of numerous users.
#
# Updated for Autoconf 2.68 by Daniel Richard G.
#
# LICENSE
#
# Copyright (c) 2008 Steven G. Johnson
# Copyright (c) 2011 Daniel Richard G.
# Copyright (c) 2019 Marc Stevens
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program 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 General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see .
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 31
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_PROG_SED])
AC_LANG_PUSH([C])
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on Tru64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
ax_pthread_save_CC="$CC"
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
AC_MSG_RESULT([$ax_pthread_ok])
if test "x$ax_pthread_ok" = "xno"; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
CC="$ax_pthread_save_CC"
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items with a "," contain both
# C compiler flags (before ",") and linker flags (after ","). Other items
# starting with a "-" are C compiler flags, and remaining items are
# library names, except for "none" which indicates that we try without
# any flags at all, and "pthread-config" which is a program returning
# the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
# (Note: HP C rejects this with "bad form for `-t' option")
# -pthreads: Solaris/gcc (Note: HP C also rejects)
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads and
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
# is present but should not be used directly; and before -mthreads,
# because the compiler interprets this as "-mt" + "-hreads")
# -mthreads: Mingw32/gcc, Lynx/gcc
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case $host_os in
freebsd*)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
;;
hpux*)
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
# multi-threading and also sets -lpthread."
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
;;
openedition*)
# IBM z/OS requires a feature-test macro to be defined in order to
# enable POSIX threads at all, so give the user a hint if this is
# not set. (We don't define these ourselves, as they can affect
# other portions of the system API in unpredictable ways.)
AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
[
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
AX_PTHREAD_ZOS_MISSING
# endif
],
[AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
;;
solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (N.B.: The stubs are missing
# pthread_cleanup_push, or rather a function called by this macro,
# so we could check for that, but who knows whether they'll stub
# that too in a future libc.) So we'll check first for the
# standard Solaris way of linking pthreads (-mt -lpthread).
ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
;;
esac
# Are we compiling with Clang?
AC_CACHE_CHECK([whether $CC is Clang],
[ax_cv_PTHREAD_CLANG],
[ax_cv_PTHREAD_CLANG=no
# Note that Autoconf sets GCC=yes for Clang as well as GCC
if test "x$GCC" = "xyes"; then
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
# if defined(__clang__) && defined(__llvm__)
AX_PTHREAD_CC_IS_CLANG
# endif
],
[ax_cv_PTHREAD_CLANG=yes])
fi
])
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
# Note that for GCC and Clang -pthread generally implies -lpthread,
# except when -nostdlib is passed.
# This is problematic using libtool to build C++ shared libraries with pthread:
# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
# To solve this, first try -pthread together with -lpthread for GCC
AS_IF([test "x$GCC" = "xyes"],
[ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
AS_IF([test "x$ax_pthread_clang" = "xyes"],
[ax_pthread_flags="-pthread,-lpthread -pthread"])
# The presence of a feature test macro requesting re-entrant function
# definitions is, on some systems, a strong hint that pthreads support is
# correctly enabled
case $host_os in
darwin* | hpux* | linux* | osf* | solaris*)
ax_pthread_check_macro="_REENTRANT"
;;
aix*)
ax_pthread_check_macro="_THREAD_SAFE"
;;
*)
ax_pthread_check_macro="--"
;;
esac
AS_IF([test "x$ax_pthread_check_macro" = "x--"],
[ax_pthread_check_cond=0],
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
if test "x$ax_pthread_ok" = "xno"; then
for ax_pthread_try_flag in $ax_pthread_flags; do
case $ax_pthread_try_flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
*,*)
PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
PTHREAD_CFLAGS="$ax_pthread_try_flag"
;;
pthread-config)
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
PTHREAD_LIBS="-l$ax_pthread_try_flag"
;;
esac
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include
# if $ax_pthread_check_cond
# error "$ax_pthread_check_macro must be defined"
# endif
static void *some_global = NULL;
static void routine(void *a)
{
/* To avoid any unused-parameter or
unused-but-set-parameter warning. */
some_global = a;
}
static void *start_routine(void *a) { return a; }],
[pthread_t th; pthread_attr_t attr;
pthread_create(&th, 0, start_routine, 0);
pthread_join(th, 0);
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_cleanup_pop(0) /* ; */])],
[ax_pthread_ok=yes],
[])
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
AC_MSG_RESULT([$ax_pthread_ok])
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Clang needs special handling, because older versions handle the -pthread
# option in a rather... idiosyncratic way
if test "x$ax_pthread_clang" = "xyes"; then
# Clang takes -pthread; it has never supported any other flag
# (Note 1: This will need to be revisited if a system that Clang
# supports has POSIX threads in a separate library. This tends not
# to be the way of modern systems, but it's conceivable.)
# (Note 2: On some systems, notably Darwin, -pthread is not needed
# to get POSIX threads support; the API is always present and
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
# -pthread does define _REENTRANT, and while the Darwin headers
# ignore this macro, third-party headers might not.)
# However, older versions of Clang make a point of warning the user
# that, in an invocation where only linking and no compilation is
# taking place, the -pthread option has no effect ("argument unused
# during compilation"). They expect -pthread to be passed in only
# when source code is being compiled.
#
# Problem is, this is at odds with the way Automake and most other
# C build frameworks function, which is that the same flags used in
# compilation (CFLAGS) are also used in linking. Many systems
# supported by AX_PTHREAD require exactly this for POSIX threads
# support, and in fact it is often not straightforward to specify a
# flag that is used only in the compilation phase and not in
# linking. Such a scenario is extremely rare in practice.
#
# Even though use of the -pthread flag in linking would only print
# a warning, this can be a nuisance for well-run software projects
# that build with -Werror. So if the active version of Clang has
# this misfeature, we search for an option to squash it.
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
# Create an alternate version of $ac_link that compiles and
# links in two steps (.c -> .o, .o -> exe) instead of one
# (.c -> exe), because the warning occurs only in the second
# step
ax_pthread_save_ac_link="$ac_link"
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
ax_pthread_save_CFLAGS="$CFLAGS"
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
ac_link="$ax_pthread_save_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[ac_link="$ax_pthread_2step_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[break])
])
done
ac_link="$ax_pthread_save_ac_link"
CFLAGS="$ax_pthread_save_CFLAGS"
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
])
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
no | unknown) ;;
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
esac
fi # $ax_pthread_clang = yes
# Various other checks:
if test "x$ax_pthread_ok" = "xyes"; then
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_CACHE_CHECK([for joinable pthread attribute],
[ax_cv_PTHREAD_JOINABLE_ATTR],
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ],
[int attr = $ax_pthread_attr; return attr /* ; */])],
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
[])
done
])
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
[AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
[$ax_cv_PTHREAD_JOINABLE_ATTR],
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
ax_pthread_joinable_attr_defined=yes
])
AC_CACHE_CHECK([whether more special flags are required for pthreads],
[ax_cv_PTHREAD_SPECIAL_FLAGS],
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
case $host_os in
solaris*)
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
;;
esac
])
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
test "x$ax_pthread_special_flags_added" != "xyes"],
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
ax_pthread_special_flags_added=yes])
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
[ax_cv_PTHREAD_PRIO_INHERIT],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]],
[[int i = PTHREAD_PRIO_INHERIT;
return i;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
test "x$ax_pthread_prio_inherit_defined" != "xyes"],
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
ax_pthread_prio_inherit_defined=yes
])
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
# More AIX lossage: compile with *_r variant
if test "x$GCC" != "xyes"; then
case $host_os in
aix*)
AS_CASE(["x/$CC"],
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
[
AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
],
[
AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
]
)
])
;;
esac
fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
AC_SUBST([PTHREAD_LIBS])
AC_SUBST([PTHREAD_CFLAGS])
AC_SUBST([PTHREAD_CC])
AC_SUBST([PTHREAD_CXX])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test "x$ax_pthread_ok" = "xyes"; then
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
:
else
ax_pthread_ok=no
$2
fi
AC_LANG_POP
])dnl AX_PTHREAD
wimlib-1.14.5/m4/ltversion.m4 0000644 0001750 0001750 00000001312 15137024751 013170 0 ustar 00e e # ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004, 2011-2019, 2021-2025 Free Software Foundation,
# Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# @configure_input@
# serial 4509 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.6.0])
m4_define([LT_PACKAGE_REVISION], [2.6.0])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.6.0'
macro_revision='2.6.0'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
wimlib-1.14.5/m4/ltsugar.m4 0000644 0001750 0001750 00000010453 15137024751 012632 0 ustar 00e e # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2025 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59, which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])
wimlib-1.14.5/m4/ltoptions.m4 0000644 0001750 0001750 00000042160 15137024751 013204 0 ustar 00e e # Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2025 Free
# Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 12 ltoptions.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
# ------------------------------------------
m4_define([_LT_MANGLE_OPTION],
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
# ---------------------------------------
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
# matching handler defined, dispatch to it. Other OPTION-NAMEs are
# saved as a flag.
m4_define([_LT_SET_OPTION],
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
_LT_MANGLE_DEFUN([$1], [$2]),
[m4_warning([Unknown $1 option '$2'])])[]dnl
])
# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
# ------------------------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
m4_define([_LT_IF_OPTION],
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
# -------------------------------------------------------
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
# are set.
m4_define([_LT_UNLESS_OPTIONS],
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
[m4_define([$0_found])])])[]dnl
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
])[]dnl
])
# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
# ----------------------------------------
# OPTION-LIST is a space-separated list of Libtool options associated
# with MACRO-NAME. If any OPTION has a matching handler declared with
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
# the unknown option and exit.
m4_defun([_LT_SET_OPTIONS],
[# Set options
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[_LT_SET_OPTION([$1], _LT_Option)])
m4_if([$1],[LT_INIT],[
dnl
dnl Simply set some default values (i.e off) if boolean options were not
dnl specified:
_LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
])
_LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
])
dnl
dnl If no reference was made to various pairs of opposing options, then
dnl we run the default mode handler for the pair. For example, if neither
dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
dnl archives by default:
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
_LT_UNLESS_OPTIONS([LT_INIT], [cxx-stdlib no-cxx-stdlib], [_LT_ENABLE_CXX_STDLIB])
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
[_LT_ENABLE_FAST_INSTALL])
_LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
[_LT_WITH_AIX_SONAME([aix])])
])
])# _LT_SET_OPTIONS
## --------------------------------- ##
## Macros to handle LT_INIT options. ##
## --------------------------------- ##
# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
# -----------------------------------------
m4_define([_LT_MANGLE_DEFUN],
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
# -----------------------------------------------
m4_define([LT_OPTION_DEFINE],
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
])# LT_OPTION_DEFINE
# dlopen
# ------
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
])
AU_DEFUN([AC_LIBTOOL_DLOPEN],
[_LT_SET_OPTION([LT_INIT], [dlopen])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'dlopen' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
# win32-dll
# ---------
# Declare package support for building win32 dll's.
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
[enable_win32_dll=yes
case $host in
*-*-cygwin* | *-*-mingw* | *-*-windows* | *-*-pw32* | *-*-cegcc*)
AC_CHECK_TOOL(AS, as, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(OBJDUMP, objdump, false)
;;
esac
test -z "$AS" && AS=as
_LT_DECL([], [AS], [1], [Assembler program])dnl
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
])# win32-dll
AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
_LT_SET_OPTION([LT_INIT], [win32-dll])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'win32-dll' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
# _LT_ENABLE_SHARED([DEFAULT])
# ----------------------------
# implement the --enable-shared flag, and supports the 'shared' and
# 'disable-shared' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_SHARED],
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([shared],
[AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_shared=yes ;;
no) enable_shared=no ;;
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
_LT_DECL([build_libtool_libs], [enable_shared], [0],
[Whether or not to build shared libraries])
])# _LT_ENABLE_SHARED
LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
# Old names:
AC_DEFUN([AC_ENABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
])
AC_DEFUN([AC_DISABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], [disable-shared])
])
AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
dnl AC_DEFUN([AM_DISABLE_SHARED], [])
# _LT_ENABLE_STATIC([DEFAULT])
# ----------------------------
# implement the --enable-static flag, and support the 'static' and
# 'disable-static' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_STATIC],
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([static],
[AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_static=yes ;;
no) enable_static=no ;;
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
_LT_DECL([build_old_libs], [enable_static], [0],
[Whether or not to build static libraries])
])# _LT_ENABLE_STATIC
LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
# Old names:
AC_DEFUN([AC_ENABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
])
AC_DEFUN([AC_DISABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], [disable-static])
])
AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
dnl AC_DEFUN([AM_DISABLE_STATIC], [])
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
# ----------------------------------
# implement the --enable-fast-install flag, and support the 'fast-install'
# and 'disable-fast-install' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_FAST_INSTALL],
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([fast-install],
[AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
[optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_fast_install=yes ;;
no) enable_fast_install=no ;;
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
_LT_DECL([fast_install], [enable_fast_install], [0],
[Whether or not to optimize for fast installation])dnl
])# _LT_ENABLE_FAST_INSTALL
LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
# Old names:
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the 'fast-install' option into LT_INIT's first parameter.])
])
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the 'disable-fast-install' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
# _LT_WITH_AIX_SONAME([DEFAULT])
# ----------------------------------
# implement the --enable-aix-soname configure option, and support the
# `aix-soname=aix' and `aix-soname=both' and `aix-soname=svr4' LT_INIT options.
# DEFAULT is either `aix', `both', or `svr4'. If omitted, it defaults to `aix'.
m4_define([_LT_WITH_AIX_SONAME],
[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
shared_archive_member_spec=
case $host,$enable_shared in
power*-*-aix[[5-9]]*,yes)
AC_MSG_CHECKING([which variant of shared library versioning to provide])
AC_ARG_ENABLE([aix-soname],
[AS_HELP_STRING([--enable-aix-soname=aix|svr4|both],
[shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
[case $enableval in
aix|svr4|both)
;;
*)
AC_MSG_ERROR([Unknown argument to --enable-aix-soname])
;;
esac
lt_cv_with_aix_soname=$enable_aix_soname],
[_AC_ENABLE_IF([with], [aix-soname],
[case $withval in
aix|svr4|both)
;;
*)
AC_MSG_ERROR([Unknown argument to --with-aix-soname])
;;
esac
lt_cv_with_aix_soname=$with_aix_soname],
[AC_CACHE_VAL([lt_cv_with_aix_soname],
[lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)])
enable_aix_soname=$lt_cv_with_aix_soname])
with_aix_soname=$enable_aix_soname
AC_MSG_RESULT([$with_aix_soname])
if test aix != "$with_aix_soname"; then
# For the AIX way of multilib, we name the shared archive member
# based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
# and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
# Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
# the AIX toolchain works better with OBJECT_MODE set (default 32).
if test 64 = "${OBJECT_MODE-32}"; then
shared_archive_member_spec=shr_64
else
shared_archive_member_spec=shr
fi
fi
;;
power*-*-aix[[5-9]]*,'')
AC_MSG_WARN([for $host, specify if building shared libraries for versioning (svr4|both)])
AC_MSG_CHECKING([which variant of shared library versioning to provide])
with_aix_soname=aix
AC_MSG_RESULT([(default) $with_aix_soname])
;;
*)
AC_MSG_CHECKING([which variant of shared library versioning to provide])
with_aix_soname=aix
AC_MSG_RESULT([(default) $with_aix_soname])
;;
esac
_LT_DECL([], [shared_archive_member_spec], [0],
[Shared archive member basename, for filename based shared library versioning on AIX])dnl
])# _LT_WITH_AIX_SONAME
LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
# _LT_WITH_PIC([MODE])
# --------------------
# implement the --enable-pic flag, and support the 'pic-only' and 'no-pic'
# LT_INIT options.
# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'.
m4_define([_LT_WITH_PIC],
[AC_ARG_ENABLE([pic],
[AS_HELP_STRING([--enable-pic@<:@=PKGS@:>@],
[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
[lt_p=${PACKAGE-default}
case $enableval in
yes|no) pic_mode=$enableval ;;
*)
pic_mode=default
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for lt_pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$lt_pkg" = "X$lt_p"; then
pic_mode=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[dnl Continue to support --with-pic and --without-pic, for backward
dnl compatibility.
_AC_ENABLE_IF([with], [pic],
[lt_p=${PACKAGE-default}
case $withval in
yes|no) pic_mode=$withval ;;
*)
pic_mode=default
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for lt_pkg in $withval; do
IFS=$lt_save_ifs
if test "X$lt_pkg" = "X$lt_p"; then
pic_mode=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[pic_mode=m4_default([$1], [default])])]
)
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
])# _LT_WITH_PIC
LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
# Old name:
AU_DEFUN([AC_LIBTOOL_PICMODE],
[_LT_SET_OPTION([LT_INIT], [pic-only])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'pic-only' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
# _LT_ENABLE_CXX_STDLIB([MODE])
# --------------------
# implement the --enable-cxx-stdlib flag, and support the 'cxx-stdlib' and 'no-cxx-stdlib'
# LT_INIT options.
# MODE is either 'yes' or 'no'. If omitted, it defaults to 'no'.
m4_define([_LT_ENABLE_CXX_STDLIB],
[m4_define([_LT_ENABLE_CXX_STDLIB_DEFAULT], [m4_if($1, yes, yes, no)])dnl
stdlibflag=-nostdlib
AC_ARG_ENABLE([cxx-stdlib],
[AS_HELP_STRING([--enable-cxx-stdlib@<:@=PKGS@:>@],
[let the compiler frontend decide what standard libraries to link when building C++ shared libraries and modules @<:@default=]_LT_ENABLE_CXX_STDLIB_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_cxx_stdlib=yes ;;
no) enable_cxx_stdlib=no ;;
*)
enable_cxx_stdlib=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_cxx_stdlib=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_cxx_stdlib=]_LT_ENABLE_CXX_STDLIB_DEFAULT)
if test yes = "$enable_cxx_stdlib"; then
stdlibflag=
fi
_LT_DECL([], [enable_cxx_stdlib], [0], [Whether to let the compiler frontend decide what standard libraries to link when building C++ shared libraries and modules])dnl
_LT_DECL([], [stdlibflag], [0], [Flag used for specifying not to link standard libraries])dnl
])# _LT_ENABLE_CXX_STDLIB
LT_OPTION_DEFINE([LT_INIT], [cxx-stdlib], [_LT_ENABLE_CXX_STDLIB([yes])])
LT_OPTION_DEFINE([LT_INIT], [no-cxx-stdlib], [_LT_ENABLE_CXX_STDLIB([no])])
## ----------------- ##
## LTDL_INIT Options ##
## ----------------- ##
m4_define([_LTDL_MODE], [])
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
[m4_define([_LTDL_MODE], [nonrecursive])])
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
[m4_define([_LTDL_MODE], [recursive])])
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
[m4_define([_LTDL_MODE], [subproject])])
m4_define([_LTDL_TYPE], [])
LT_OPTION_DEFINE([LTDL_INIT], [installable],
[m4_define([_LTDL_TYPE], [installable])])
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
[m4_define([_LTDL_TYPE], [convenience])])
wimlib-1.14.5/build-aux/ 0000755 0001750 0001750 00000000000 15137024753 012260 5 ustar 00e e wimlib-1.14.5/build-aux/config.guess 0000744 0001750 0001750 00000143067 15137024752 014610 0 ustar 00e e #! /bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
timestamp='2024-07-27'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
#
# Please send patches to .
# The "shellcheck disable" line above the timestamp inhibits complaints
# about features and limitations of the classic Bourne shell that were
# superseded or lifted in POSIX. However, this script identifies a wide
# variety of pre-POSIX systems that do not have POSIX shells at all, and
# even some reasonably current systems (Solaris 10 as case-in-point) still
# have a pre-POSIX /bin/sh.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION]
Output the configuration name of the system '$me' is run on.
Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to ."
version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright 1992-2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
* )
break ;;
esac
done
if test $# != 0; then
echo "$me: too many arguments$help" >&2
exit 1
fi
# Just in case it came from the environment.
GUESS=
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.
# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still
# use 'HOST_CC' if defined, but it is deprecated.
# Portable tmp directory creation inspired by the Autoconf team.
tmp=
# shellcheck disable=SC2172
trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
set_cc_for_build() {
# prevent multiple calls if $tmp is already set
test "$tmp" && return 0
: "${TMPDIR=/tmp}"
# shellcheck disable=SC2039,SC3028
{ tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
dummy=$tmp/dummy
case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
,,) echo "int x;" > "$dummy.c"
for driver in cc gcc c17 c99 c89 ; do
if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
CC_FOR_BUILD=$driver
break
fi
done
if test x"$CC_FOR_BUILD" = x ; then
CC_FOR_BUILD=no_compiler_found
fi
;;
,,*) CC_FOR_BUILD=$CC ;;
,*,*) CC_FOR_BUILD=$HOST_CC ;;
esac
}
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
if test -f /.attbin/uname ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case $UNAME_SYSTEM in
Linux|GNU|GNU/*)
LIBC=unknown
set_cc_for_build
cat <<-EOF > "$dummy.c"
#if defined(__ANDROID__)
LIBC=android
#else
#include
#if defined(__UCLIBC__)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
#elif defined(__GLIBC__)
LIBC=gnu
#elif defined(__LLVM_LIBC__)
LIBC=llvm
#else
#include
/* First heuristic to detect musl libc. */
#ifdef __DEFINED_va_list
LIBC=musl
#endif
#endif
#endif
EOF
cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
eval "$cc_set_libc"
# Second heuristic to detect musl libc.
if [ "$LIBC" = unknown ] &&
command -v ldd >/dev/null &&
ldd --version 2>&1 | grep -q ^musl; then
LIBC=musl
fi
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
if [ "$LIBC" = unknown ]; then
LIBC=gnu
fi
;;
esac
# Note: order is significant - the case branches are not exclusive.
case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
# compatibility and a consistent mechanism for selecting the
# object file format.
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
/usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
echo unknown)`
case $UNAME_MACHINE_ARCH in
aarch64eb) machine=aarch64_be-unknown ;;
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
earmv*)
arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
machine=${arch}${endian}-unknown
;;
*) machine=$UNAME_MACHINE_ARCH-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently (or will in the future) and ABI.
case $UNAME_MACHINE_ARCH in
earm*)
os=netbsdelf
;;
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
os=netbsd
else
os=netbsdelf
fi
;;
*)
os=netbsd
;;
esac
# Determine ABI tags.
case $UNAME_MACHINE_ARCH in
earm*)
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
;;
esac
# The OS release
# Debian GNU/NetBSD machines have a different userland, and
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
case $UNAME_VERSION in
Debian*)
release='-gnu'
;;
*)
release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
GUESS=$machine-${os}${release}${abi-}
;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
;;
*:SecBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
;;
*:LibertyBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
;;
*:MidnightBSD:*:*)
GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
;;
*:ekkoBSD:*:*)
GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
;;
*:SolidBSD:*:*)
GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
;;
*:OS108:*:*)
GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
;;
macppc:MirBSD:*:*)
GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
;;
*:MirBSD:*:*)
GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
;;
*:Sortix:*:*)
GUESS=$UNAME_MACHINE-unknown-sortix
;;
*:Twizzler:*:*)
GUESS=$UNAME_MACHINE-unknown-twizzler
;;
*:Redox:*:*)
GUESS=$UNAME_MACHINE-unknown-redox
;;
mips:OSF1:*.*)
GUESS=mips-dec-osf1
;;
alpha:OSF1:*:*)
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
trap '' 0
case $UNAME_RELEASE in
*4.0)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
case $ALPHA_CPU_TYPE in
"EV4 (21064)")
UNAME_MACHINE=alpha ;;
"EV4.5 (21064)")
UNAME_MACHINE=alpha ;;
"LCA4 (21066/21068)")
UNAME_MACHINE=alpha ;;
"EV5 (21164)")
UNAME_MACHINE=alphaev5 ;;
"EV5.6 (21164A)")
UNAME_MACHINE=alphaev56 ;;
"EV5.6 (21164PC)")
UNAME_MACHINE=alphapca56 ;;
"EV5.7 (21164PC)")
UNAME_MACHINE=alphapca57 ;;
"EV6 (21264)")
UNAME_MACHINE=alphaev6 ;;
"EV6.7 (21264A)")
UNAME_MACHINE=alphaev67 ;;
"EV6.8CB (21264C)")
UNAME_MACHINE=alphaev68 ;;
"EV6.8AL (21264B)")
UNAME_MACHINE=alphaev68 ;;
"EV6.8CX (21264D)")
UNAME_MACHINE=alphaev68 ;;
"EV6.9A (21264/EV69A)")
UNAME_MACHINE=alphaev69 ;;
"EV7 (21364)")
UNAME_MACHINE=alphaev7 ;;
"EV7.9 (21364A)")
UNAME_MACHINE=alphaev79 ;;
esac
# A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
;;
Amiga*:UNIX_System_V:4.0:*)
GUESS=m68k-unknown-sysv4
;;
*:[Aa]miga[Oo][Ss]:*:*)
GUESS=$UNAME_MACHINE-unknown-amigaos
;;
*:[Mm]orph[Oo][Ss]:*:*)
GUESS=$UNAME_MACHINE-unknown-morphos
;;
*:OS/390:*:*)
GUESS=i370-ibm-openedition
;;
*:z/VM:*:*)
GUESS=s390-ibm-zvmoe
;;
*:OS400:*:*)
GUESS=powerpc-ibm-os400
;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
GUESS=arm-acorn-riscix$UNAME_RELEASE
;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
GUESS=arm-unknown-riscos
;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
GUESS=hppa1.1-hitachi-hiuxmpp
;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
case `(/bin/universe) 2>/dev/null` in
att) GUESS=pyramid-pyramid-sysv3 ;;
*) GUESS=pyramid-pyramid-bsd ;;
esac
;;
NILE*:*:*:dcosx)
GUESS=pyramid-pyramid-svr4
;;
DRS?6000:unix:4.0:6*)
GUESS=sparc-icl-nx6
;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case `/usr/bin/uname -p` in
sparc) GUESS=sparc-icl-nx7 ;;
esac
;;
s390x:SunOS:*:*)
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
;;
sun4H:SunOS:5.*:*)
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=sparc-hal-solaris2$SUN_REL
;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=sparc-sun-solaris2$SUN_REL
;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
GUESS=i386-pc-auroraux$UNAME_RELEASE
;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
set_cc_for_build
SUN_ARCH=i386
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH=x86_64
fi
fi
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=sparc-sun-solaris3$SUN_REL
;;
sun4*:SunOS:*:*)
case `/usr/bin/arch -k` in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like '4.1.3-JL'.
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
GUESS=sparc-sun-sunos$SUN_REL
;;
sun3*:SunOS:*:*)
GUESS=m68k-sun-sunos$UNAME_RELEASE
;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
case `/bin/arch` in
sun3)
GUESS=m68k-sun-sunos$UNAME_RELEASE
;;
sun4)
GUESS=sparc-sun-sunos$UNAME_RELEASE
;;
esac
;;
aushp:SunOS:*:*)
GUESS=sparc-auspex-sunos$UNAME_RELEASE
;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
# > m68000). The system name ranges from "MiNT" over "FreeMiNT"
# to the lowercase version "mint" (or "freemint"). Finally
# the system name "TOS" denotes a system which is actually not
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
GUESS=m68k-atari-mint$UNAME_RELEASE
;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
GUESS=m68k-atari-mint$UNAME_RELEASE
;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
GUESS=m68k-atari-mint$UNAME_RELEASE
;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
GUESS=m68k-milan-mint$UNAME_RELEASE
;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
GUESS=m68k-hades-mint$UNAME_RELEASE
;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
GUESS=m68k-unknown-mint$UNAME_RELEASE
;;
m68k:machten:*:*)
GUESS=m68k-apple-machten$UNAME_RELEASE
;;
powerpc:machten:*:*)
GUESS=powerpc-apple-machten$UNAME_RELEASE
;;
RISC*:Mach:*:*)
GUESS=mips-dec-mach_bsd4.3
;;
RISC*:ULTRIX:*:*)
GUESS=mips-dec-ultrix$UNAME_RELEASE
;;
VAX*:ULTRIX*:*:*)
GUESS=vax-dec-ultrix$UNAME_RELEASE
;;
2020:CLIX:*:* | 2430:CLIX:*:*)
GUESS=clipper-intergraph-clix$UNAME_RELEASE
;;
mips:*:*:UMIPS | mips:*:*:RISCos)
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#ifdef __cplusplus
#include /* for printf() prototype */
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
{ echo "$SYSTEM_NAME"; exit; }
GUESS=mips-mips-riscos$UNAME_RELEASE
;;
Motorola:PowerMAX_OS:*:*)
GUESS=powerpc-motorola-powermax
;;
Motorola:*:4.3:PL8-*)
GUESS=powerpc-harris-powermax
;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
GUESS=powerpc-harris-powermax
;;
Night_Hawk:Power_UNIX:*:*)
GUESS=powerpc-harris-powerunix
;;
m88k:CX/UX:7*:*)
GUESS=m88k-harris-cxux7
;;
m88k:*:4*:R4*)
GUESS=m88k-motorola-sysv4
;;
m88k:*:3*:R3*)
GUESS=m88k-motorola-sysv3
;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
then
if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
test "$TARGET_BINARY_INTERFACE"x = x
then
GUESS=m88k-dg-dgux$UNAME_RELEASE
else
GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
fi
else
GUESS=i586-dg-dgux$UNAME_RELEASE
fi
;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
GUESS=m88k-dolphin-sysv3
;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
GUESS=m88k-motorola-sysv3
;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
GUESS=m88k-tektronix-sysv3
;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
GUESS=m68k-tektronix-bsd
;;
*:IRIX*:*:*)
IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
GUESS=mips-sgi-irix$IRIX_REL
;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id
;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
GUESS=i386-ibm-aix
;;
ia64:AIX:*:*)
if test -x /usr/bin/oslevel ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
fi
GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#include
int
main ()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
then
GUESS=$SYSTEM_NAME
else
GUESS=rs6000-ibm-aix3.2.5
fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
GUESS=rs6000-ibm-aix3.2.4
else
GUESS=rs6000-ibm-aix3.2
fi
;;
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if test -x /usr/bin/lslpp ; then
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
fi
GUESS=$IBM_ARCH-ibm-aix$IBM_REV
;;
*:AIX:*:*)
GUESS=rs6000-ibm-aix
;;
ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
GUESS=romp-ibm-bsd4.4
;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to
;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
GUESS=rs6000-bull-bosx
;;
DPX/2?00:B.O.S.:*:*)
GUESS=m68k-bull-sysv3
;;
9000/[34]??:4.3bsd:1.*:*)
GUESS=m68k-hp-bsd
;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
GUESS=m68k-hp-bsd4.4
;;
9000/[34678]??:HP-UX:*:*)
HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
case $UNAME_MACHINE in
9000/31?) HP_ARCH=m68000 ;;
9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if test -x /usr/bin/getconf; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case $sc_cpu_version in
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case $sc_kernel_bits in
32) HP_ARCH=hppa2.0n ;;
64) HP_ARCH=hppa2.0w ;;
'') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
esac ;;
esac
fi
if test "$HP_ARCH" = ""; then
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#define _HPUX_SOURCE
#include
#include
int
main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
if test "$HP_ARCH" = hppa2.0w
then
set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
# generating 64-bit code. GNU and HP use different nomenclature:
#
# $ CC_FOR_BUILD=cc ./config.guess
# => hppa2.0w-hp-hpux11.23
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
HP_ARCH=hppa2.0w
else
HP_ARCH=hppa64
fi
fi
GUESS=$HP_ARCH-hp-hpux$HPUX_REV
;;
ia64:HP-UX:*:*)
HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
GUESS=ia64-hp-hpux$HPUX_REV
;;
3050*:HI-UX:*:*)
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#include
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
{ echo "$SYSTEM_NAME"; exit; }
GUESS=unknown-hitachi-hiuxwe2
;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
GUESS=hppa1.1-hp-bsd
;;
9000/8??:4.3bsd:*:*)
GUESS=hppa1.0-hp-bsd
;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
GUESS=hppa1.0-hp-mpeix
;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
GUESS=hppa1.1-hp-osf
;;
hp8??:OSF1:*:*)
GUESS=hppa1.0-hp-osf
;;
i*86:OSF1:*:*)
if test -x /usr/sbin/sysversion ; then
GUESS=$UNAME_MACHINE-unknown-osf1mk
else
GUESS=$UNAME_MACHINE-unknown-osf1
fi
;;
parisc*:Lites*:*:*)
GUESS=hppa1.1-hp-lites
;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
GUESS=c1-convex-bsd
;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
GUESS=c34-convex-bsd
;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
GUESS=c38-convex-bsd
;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
GUESS=c4-convex-bsd
;;
CRAY*Y-MP:*:*:*)
CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
GUESS=ymp-cray-unicos$CRAY_REL
;;
CRAY*[A-Z]90:*:*:*)
echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
GUESS=t90-cray-unicos$CRAY_REL
;;
CRAY*T3E:*:*:*)
CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
GUESS=alphaev5-cray-unicosmk$CRAY_REL
;;
CRAY*SV1:*:*:*)
CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
GUESS=sv1-cray-unicos$CRAY_REL
;;
*:UNICOS/mp:*:*)
CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
GUESS=craynv-cray-unicosmp$CRAY_REL
;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
;;
sparc*:BSD/OS:*:*)
GUESS=sparc-unknown-bsdi$UNAME_RELEASE
;;
*:BSD/OS:*:*)
GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
;;
arm:FreeBSD:*:*)
UNAME_PROCESSOR=`uname -p`
set_cc_for_build
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
else
FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
fi
;;
*:FreeBSD:*:*)
UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in
amd64)
UNAME_PROCESSOR=x86_64 ;;
i386)
UNAME_PROCESSOR=i586 ;;
esac
FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
;;
i*:CYGWIN*:*)
GUESS=$UNAME_MACHINE-pc-cygwin
;;
*:MINGW64*:*)
GUESS=$UNAME_MACHINE-pc-mingw64
;;
*:MINGW*:*)
GUESS=$UNAME_MACHINE-pc-mingw32
;;
*:MSYS*:*)
GUESS=$UNAME_MACHINE-pc-msys
;;
i*:PW*:*)
GUESS=$UNAME_MACHINE-pc-pw32
;;
*:SerenityOS:*:*)
GUESS=$UNAME_MACHINE-pc-serenity
;;
*:Interix*:*)
case $UNAME_MACHINE in
x86)
GUESS=i586-pc-interix$UNAME_RELEASE
;;
authenticamd | genuineintel | EM64T)
GUESS=x86_64-unknown-interix$UNAME_RELEASE
;;
IA64)
GUESS=ia64-unknown-interix$UNAME_RELEASE
;;
esac ;;
i*:UWIN*:*)
GUESS=$UNAME_MACHINE-pc-uwin
;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
GUESS=x86_64-pc-cygwin
;;
prep*:SunOS:5.*:*)
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=powerpcle-unknown-solaris2$SUN_REL
;;
*:GNU:*:*)
# the GNU system
GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"`
GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
;;
x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*)
GUESS="$UNAME_MACHINE-pc-managarm-mlibc"
;;
*:[Mm]anagarm:*:*)
GUESS="$UNAME_MACHINE-unknown-managarm-mlibc"
;;
*:Minix:*:*)
GUESS=$UNAME_MACHINE-unknown-minix
;;
aarch64:Linux:*:*)
set_cc_for_build
CPU=$UNAME_MACHINE
LIBCABI=$LIBC
if test "$CC_FOR_BUILD" != no_compiler_found; then
ABI=64
sed 's/^ //' << EOF > "$dummy.c"
#ifdef __ARM_EABI__
#ifdef __ARM_PCS_VFP
ABI=eabihf
#else
ABI=eabi
#endif
#endif
EOF
cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
eval "$cc_set_abi"
case $ABI in
eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;;
esac
fi
GUESS=$CPU-unknown-linux-$LIBCABI
;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
PCA57) UNAME_MACHINE=alphapca56 ;;
EV6) UNAME_MACHINE=alphaev6 ;;
EV67) UNAME_MACHINE=alphaev67 ;;
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
arm*:Linux:*:*)
set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
else
GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
fi
fi
;;
avr32*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
cris:Linux:*:*)
GUESS=$UNAME_MACHINE-axis-linux-$LIBC
;;
crisv32:Linux:*:*)
GUESS=$UNAME_MACHINE-axis-linux-$LIBC
;;
e2k:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
frv:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
hexagon:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
i*86:Linux:*:*)
GUESS=$UNAME_MACHINE-pc-linux-$LIBC
;;
ia64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
k1om:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
kvx:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
kvx:cos:*:*)
GUESS=$UNAME_MACHINE-unknown-cos
;;
kvx:mbr:*:*)
GUESS=$UNAME_MACHINE-unknown-mbr
;;
loongarch32:Linux:*:* | loongarch64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
m32r*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
m68*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
mips:Linux:*:* | mips64:Linux:*:*)
set_cc_for_build
IS_GLIBC=0
test x"${LIBC}" = xgnu && IS_GLIBC=1
sed 's/^ //' << EOF > "$dummy.c"
#undef CPU
#undef mips
#undef mipsel
#undef mips64
#undef mips64el
#if ${IS_GLIBC} && defined(_ABI64)
LIBCABI=gnuabi64
#else
#if ${IS_GLIBC} && defined(_ABIN32)
LIBCABI=gnuabin32
#else
LIBCABI=${LIBC}
#endif
#endif
#if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
CPU=mipsisa64r6
#else
#if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
CPU=mipsisa32r6
#else
#if defined(__mips64)
CPU=mips64
#else
CPU=mips
#endif
#endif
#endif
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
MIPS_ENDIAN=el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
MIPS_ENDIAN=
#else
MIPS_ENDIAN=
#endif
#endif
EOF
cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
eval "$cc_set_vars"
test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
;;
mips64el:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
openrisc*:Linux:*:*)
GUESS=or1k-unknown-linux-$LIBC
;;
or32:Linux:*:* | or1k*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
padre:Linux:*:*)
GUESS=sparc-unknown-linux-$LIBC
;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
GUESS=hppa64-unknown-linux-$LIBC
;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
*) GUESS=hppa-unknown-linux-$LIBC ;;
esac
;;
ppc64:Linux:*:*)
GUESS=powerpc64-unknown-linux-$LIBC
;;
ppc:Linux:*:*)
GUESS=powerpc-unknown-linux-$LIBC
;;
ppc64le:Linux:*:*)
GUESS=powerpc64le-unknown-linux-$LIBC
;;
ppcle:Linux:*:*)
GUESS=powerpcle-unknown-linux-$LIBC
;;
riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
s390:Linux:*:* | s390x:Linux:*:*)
GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
;;
sh64*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
sh*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
sparc:Linux:*:* | sparc64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
tile*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
vax:Linux:*:*)
GUESS=$UNAME_MACHINE-dec-linux-$LIBC
;;
x86_64:Linux:*:*)
set_cc_for_build
CPU=$UNAME_MACHINE
LIBCABI=$LIBC
if test "$CC_FOR_BUILD" != no_compiler_found; then
ABI=64
sed 's/^ //' << EOF > "$dummy.c"
#ifdef __i386__
ABI=x86
#else
#ifdef __ILP32__
ABI=x32
#endif
#endif
EOF
cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
eval "$cc_set_abi"
case $ABI in
x86) CPU=i686 ;;
x32) LIBCABI=${LIBC}x32 ;;
esac
fi
GUESS=$CPU-pc-linux-$LIBCABI
;;
xtensa*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
GUESS=i386-sequent-sysv4
;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
;;
i*86:OS/2:*:*)
# If we were able to find 'uname', then EMX Unix compatibility
# is probably installed.
GUESS=$UNAME_MACHINE-pc-os2-emx
;;
i*86:XTS-300:*:STOP)
GUESS=$UNAME_MACHINE-unknown-stop
;;
i*86:atheos:*:*)
GUESS=$UNAME_MACHINE-unknown-atheos
;;
i*86:syllable:*:*)
GUESS=$UNAME_MACHINE-pc-syllable
;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
GUESS=i386-unknown-lynxos$UNAME_RELEASE
;;
i*86:*DOS:*:*)
GUESS=$UNAME_MACHINE-pc-msdosdjgpp
;;
i*86:*:4.*:*)
UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
else
GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
fi
;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
else
GUESS=$UNAME_MACHINE-pc-sysv32
fi
;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configure will decide that
# this is a cross-build.
GUESS=i586-pc-msdosdjgpp
;;
Intel:Mach:3*:*)
GUESS=i386-pc-mach3
;;
paragon:*:*:*)
GUESS=i860-intel-osf1
;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4
fi
;;
mini*:CTIX:SYS*5:*)
# "miniframe"
GUESS=m68010-convergent-sysv
;;
mc68k:UNIX:SYSTEM5:3.51m)
GUESS=m68k-convergent-sysv
;;
M680?0:D-NIX:5.3:*)
GUESS=m68k-diab-dnix
;;
M68*:*:R3V[5678]*:*)
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
&& { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
GUESS=m68k-unknown-lynxos$UNAME_RELEASE
;;
mc68030:UNIX_System_V:4.*:*)
GUESS=m68k-atari-sysv4
;;
TSUNAMI:LynxOS:2.*:*)
GUESS=sparc-unknown-lynxos$UNAME_RELEASE
;;
rs6000:LynxOS:2.*:*)
GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
;;
SM[BE]S:UNIX_SV:*:*)
GUESS=mips-dde-sysv$UNAME_RELEASE
;;
RM*:ReliantUNIX-*:*:*)
GUESS=mips-sni-sysv4
;;
RM*:SINIX-*:*:*)
GUESS=mips-sni-sysv4
;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
GUESS=$UNAME_MACHINE-sni-sysv4
else
GUESS=ns32k-sni-sysv
fi
;;
PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort
# says
GUESS=i586-unisys-sysv4
;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes .
# How about differentiating between stratus architectures? -djm
GUESS=hppa1.1-stratus-sysv4
;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
GUESS=i860-stratus-sysv4
;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
GUESS=$UNAME_MACHINE-stratus-vos
;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
GUESS=hppa1.1-stratus-vos
;;
mc68*:A/UX:*:*)
GUESS=m68k-apple-aux$UNAME_RELEASE
;;
news*:NEWS-OS:6*:*)
GUESS=mips-sony-newsos6
;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if test -d /usr/nec; then
GUESS=mips-nec-sysv$UNAME_RELEASE
else
GUESS=mips-unknown-sysv$UNAME_RELEASE
fi
;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
GUESS=powerpc-be-beos
;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
GUESS=powerpc-apple-beos
;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
GUESS=i586-pc-beos
;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
GUESS=i586-pc-haiku
;;
ppc:Haiku:*:*) # Haiku running on Apple PowerPC
GUESS=powerpc-apple-haiku
;;
*:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat)
GUESS=$UNAME_MACHINE-unknown-haiku
;;
SX-4:SUPER-UX:*:*)
GUESS=sx4-nec-superux$UNAME_RELEASE
;;
SX-5:SUPER-UX:*:*)
GUESS=sx5-nec-superux$UNAME_RELEASE
;;
SX-6:SUPER-UX:*:*)
GUESS=sx6-nec-superux$UNAME_RELEASE
;;
SX-7:SUPER-UX:*:*)
GUESS=sx7-nec-superux$UNAME_RELEASE
;;
SX-8:SUPER-UX:*:*)
GUESS=sx8-nec-superux$UNAME_RELEASE
;;
SX-8R:SUPER-UX:*:*)
GUESS=sx8r-nec-superux$UNAME_RELEASE
;;
SX-ACE:SUPER-UX:*:*)
GUESS=sxace-nec-superux$UNAME_RELEASE
;;
Power*:Rhapsody:*:*)
GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
;;
*:Rhapsody:*:*)
GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
;;
arm64:Darwin:*:*)
GUESS=aarch64-apple-darwin$UNAME_RELEASE
;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in
unknown) UNAME_PROCESSOR=powerpc ;;
esac
if command -v xcode-select > /dev/null 2> /dev/null && \
! xcode-select --print-path > /dev/null 2> /dev/null ; then
# Avoid executing cc if there is no toolchain installed as
# cc will be a stub that puts up a graphical alert
# prompting the user to install developer tools.
CC_FOR_BUILD=no_compiler_found
else
set_cc_for_build
fi
if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_PPC >/dev/null
then
UNAME_PROCESSOR=powerpc
fi
elif test "$UNAME_PROCESSOR" = i386 ; then
# uname -m returns i386 or x86_64
UNAME_PROCESSOR=$UNAME_MACHINE
fi
GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
;;
*:QNX:*:4*)
GUESS=i386-pc-qnx
;;
NEO-*:NONSTOP_KERNEL:*:*)
GUESS=neo-tandem-nsk$UNAME_RELEASE
;;
NSE-*:NONSTOP_KERNEL:*:*)
GUESS=nse-tandem-nsk$UNAME_RELEASE
;;
NSR-*:NONSTOP_KERNEL:*:*)
GUESS=nsr-tandem-nsk$UNAME_RELEASE
;;
NSV-*:NONSTOP_KERNEL:*:*)
GUESS=nsv-tandem-nsk$UNAME_RELEASE
;;
NSX-*:NONSTOP_KERNEL:*:*)
GUESS=nsx-tandem-nsk$UNAME_RELEASE
;;
*:NonStop-UX:*:*)
GUESS=mips-compaq-nonstopux
;;
BS2000:POSIX*:*:*)
GUESS=bs2000-siemens-sysv
;;
DS/*:UNIX_System_V:*:*)
GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
if test "${cputype-}" = 386; then
UNAME_MACHINE=i386
elif test "x${cputype-}" != x; then
UNAME_MACHINE=$cputype
fi
GUESS=$UNAME_MACHINE-unknown-plan9
;;
*:TOPS-10:*:*)
GUESS=pdp10-unknown-tops10
;;
*:TENEX:*:*)
GUESS=pdp10-unknown-tenex
;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
GUESS=pdp10-dec-tops20
;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
GUESS=pdp10-xkl-tops20
;;
*:TOPS-20:*:*)
GUESS=pdp10-unknown-tops20
;;
*:ITS:*:*)
GUESS=pdp10-unknown-its
;;
SEI:*:*:SEIUX)
GUESS=mips-sei-seiux$UNAME_RELEASE
;;
*:DragonFly:*:*)
DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
case $UNAME_MACHINE in
A*) GUESS=alpha-dec-vms ;;
I*) GUESS=ia64-dec-vms ;;
V*) GUESS=vax-dec-vms ;;
esac ;;
*:XENIX:*:SysV)
GUESS=i386-pc-xenix
;;
i*86:skyos:*:*)
SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
;;
i*86:rdos:*:*)
GUESS=$UNAME_MACHINE-pc-rdos
;;
i*86:Fiwix:*:*)
GUESS=$UNAME_MACHINE-pc-fiwix
;;
*:AROS:*:*)
GUESS=$UNAME_MACHINE-unknown-aros
;;
x86_64:VMkernel:*:*)
GUESS=$UNAME_MACHINE-unknown-esx
;;
amd64:Isilon\ OneFS:*:*)
GUESS=x86_64-unknown-onefs
;;
*:Unleashed:*:*)
GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
;;
*:Ironclad:*:*)
GUESS=$UNAME_MACHINE-unknown-ironclad
;;
esac
# Do we have a guess based on uname results?
if test "x$GUESS" != x; then
echo "$GUESS"
exit
fi
# No uname command or uname output not recognized.
set_cc_for_build
cat > "$dummy.c" <
#include
#endif
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
#include
#if defined(_SIZE_T_) || defined(SIGLOST)
#include
#endif
#endif
#endif
int
main ()
{
#if defined (sony)
#if defined (MIPSEB)
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
I don't know.... */
printf ("mips-sony-bsd\n"); exit (0);
#else
#include
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
#else
""
#endif
); exit (0);
#endif
#endif
#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
if (version < 4)
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
else
printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
exit (0);
#endif
#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
printf ("ns32k-encore-mach\n"); exit (0);
#else
printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif
#if defined (__386BSD__)
printf ("i386-pc-bsd\n"); exit (0);
#endif
#if defined (sequent)
#if defined (i386)
printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif
#if defined (_SEQUENT_)
struct utsname un;
uname(&un);
if (strncmp(un.version, "V2", 2) == 0) {
printf ("i386-sequent-ptx2\n"); exit (0);
}
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
printf ("i386-sequent-ptx1\n"); exit (0);
}
printf ("i386-sequent-ptx\n"); exit (0);
#endif
#if defined (vax)
#if !defined (ultrix)
#include
#if defined (BSD)
#if BSD == 43
printf ("vax-dec-bsd4.3\n"); exit (0);
#else
#if BSD == 199006
printf ("vax-dec-bsd4.3reno\n"); exit (0);
#else
printf ("vax-dec-bsd\n"); exit (0);
#endif
#endif
#else
printf ("vax-dec-bsd\n"); exit (0);
#endif
#else
#if defined(_SIZE_T_) || defined(SIGLOST)
struct utsname un;
uname (&un);
printf ("vax-dec-ultrix%s\n", un.release); exit (0);
#else
printf ("vax-dec-ultrix\n"); exit (0);
#endif
#endif
#endif
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
#if defined(_SIZE_T_) || defined(SIGLOST)
struct utsname *un;
uname (&un);
printf ("mips-dec-ultrix%s\n", un.release); exit (0);
#else
printf ("mips-dec-ultrix\n"); exit (0);
#endif
#endif
#endif
#if defined (alliant) && defined (i860)
printf ("i860-alliant-bsd\n"); exit (0);
#endif
exit (1);
}
EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
{ echo "$SYSTEM_NAME"; exit; }
# Apollos put the system type in the environment.
test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
echo "$0: unable to guess system type" >&2
case $UNAME_MACHINE:$UNAME_SYSTEM in
mips:Linux | mips64:Linux)
# If we got here on MIPS GNU/Linux, output extra information.
cat >&2 <&2 <&2 </dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
hostinfo = `(hostinfo) 2>/dev/null`
/bin/universe = `(/bin/universe) 2>/dev/null`
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
/bin/arch = `(/bin/arch) 2>/dev/null`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
UNAME_MACHINE = "$UNAME_MACHINE"
UNAME_RELEASE = "$UNAME_RELEASE"
UNAME_SYSTEM = "$UNAME_SYSTEM"
UNAME_VERSION = "$UNAME_VERSION"
EOF
fi
exit 1
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
wimlib-1.14.5/build-aux/compile 0000744 0001750 0001750 00000017600 15137024752 013637 0 ustar 00e e #! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2025-06-18.21; # UTC
# Copyright (C) 1999-2025 Free Software Foundation, Inc.
# Written by Tom Tromey .
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to or send patches to
# .
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file unneeded_conversions
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) UNNEEDED_CONVERSIONS, no
# conversion will take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
if test -n "$MSYSTEM" && (cygpath --version) >/dev/null 2>&1; then
# MSYS2 environment.
file_conv=cygwin
else
# Original MinGW environment.
file_conv=mingw
fi
;;
MSYS*)
# Old MSYS environment, or MSYS2 with 32-bit MSYS2 shell.
file_conv=cygwin
;;
CYGWIN*)
# Cygwin environment.
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
# This is the optimization mentioned above:
# If UNNEEDED_CONVERSIONS contains $file_conv, don't convert.
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -w "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.lo | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to .
GNU Automake home page: .
General help using GNU software: .
EOF
exit $?
;;
-v | --v*)
echo "compile (GNU Automake) $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
clang-cl | *[/\\]clang-cl | clang-cl.exe | *[/\\]clang-cl.exe | \
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%Y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
wimlib-1.14.5/build-aux/install-sh 0000744 0001750 0001750 00000036122 15137024752 014265 0 ustar 00e e #!/bin/sh
# install - install a program, script, or datafile
scriptversion=2025-06-18.21; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
# Create dirs (including intermediate dirs) using mode 755.
# This is like GNU 'install' as of coreutils 8.32 (2020).
mkdir_umask=22
backupsuffix=
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-p pass -p to $cpprog.
-s $stripprog installed files.
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
By default, rm is invoked with -f; when overridden with RMPROG,
it's up to you to specify -f if you want it.
If -S is not specified, no backups are attempted.
Report bugs to .
GNU Automake home page: .
General help using GNU software: ."
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-p) cpprog="$cpprog -p";;
-s) stripcmd=$stripprog;;
-S) backupsuffix="$2"
shift;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 (GNU Automake) $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
# Don't chown directories that already exist.
if test $dstdir_status = 0; then
chowncmd=""
fi
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dstbase=`basename "$src"`
case $dst in
*/) dst=$dst$dstbase;;
*) dst=$dst/$dstbase;;
esac
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
case $dstdir in
*/) dstdirslash=$dstdir;;
*) dstdirslash=$dstdir/;;
esac
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
# The $RANDOM variable is not portable (e.g., dash). Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap '
ret=$?
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
exit $ret
' 0
# Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test
# 'mkdir -p'.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibility with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=${dstdirslash}_inst.$$_
rmtmp=${dstdirslash}_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask &&
{ test -z "$stripcmd" || {
# Create $dsttmp read-write so that cp doesn't create it read-only,
# which would cause strip to fail.
if test -z "$doit"; then
: >"$dsttmp" # No need to fork-exec 'touch'.
else
$doit touch "$dsttmp"
fi
}
} &&
$doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# If $backupsuffix is set, and the file being installed
# already exists, attempt a backup. Don't worry if it fails,
# e.g., if mv doesn't support -f.
if test -n "$backupsuffix" && test -f "$dst"; then
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
fi
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%Y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
wimlib-1.14.5/build-aux/config.rpath 0000644 0001750 0001750 00000000000 14707301127 014546 0 ustar 00e e wimlib-1.14.5/build-aux/config.sub 0000744 0001750 0001750 00000115441 15137024752 014246 0 ustar 00e e #! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268,SC2162 # see below for rationale
timestamp='2024-05-27'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
# Please send patches to .
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support. The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
# The "shellcheck disable" line above the timestamp inhibits complaints
# about features and limitations of the classic Bourne shell that were
# superseded or lifted in POSIX. However, this script identifies a wide
# variety of pre-POSIX systems that do not have POSIX shells at all, and
# even some reasonably current systems (Solaris 10 as case-in-point) still
# have a pre-POSIX /bin/sh.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to ."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
*local*)
# First pass through any local machine types.
echo "$1"
exit ;;
* )
break ;;
esac
done
case $# in
0) echo "$me: missing argument$help" >&2
exit 1;;
1) ;;
*) echo "$me: too many arguments$help" >&2
exit 1;;
esac
# Split fields of configuration type
saved_IFS=$IFS
IFS="-" read field1 field2 field3 field4 <&2
exit 1
;;
*-*-*-*)
basic_machine=$field1-$field2
basic_os=$field3-$field4
;;
*-*-*)
# Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
# parts
maybe_os=$field2-$field3
case $maybe_os in
cloudabi*-eabi* \
| kfreebsd*-gnu* \
| knetbsd*-gnu* \
| kopensolaris*-gnu* \
| linux-* \
| managarm-* \
| netbsd*-eabi* \
| netbsd*-gnu* \
| nto-qnx* \
| os2-emx* \
| rtmk-nova* \
| storm-chaos* \
| uclinux-gnu* \
| uclinux-uclibc* \
| windows-* )
basic_machine=$field1
basic_os=$maybe_os
;;
android-linux)
basic_machine=$field1-unknown
basic_os=linux-android
;;
*)
basic_machine=$field1-$field2
basic_os=$field3
;;
esac
;;
*-*)
case $field1-$field2 in
# Shorthands that happen to contain a single dash
convex-c[12] | convex-c3[248])
basic_machine=$field2-convex
basic_os=
;;
decstation-3100)
basic_machine=mips-dec
basic_os=
;;
*-*)
# Second component is usually, but not always the OS
case $field2 in
# Do not treat sunos as a manufacturer
sun*os*)
basic_machine=$field1
basic_os=$field2
;;
# Manufacturers
3100* \
| 32* \
| 3300* \
| 3600* \
| 7300* \
| acorn \
| altos* \
| apollo \
| apple \
| atari \
| att* \
| axis \
| be \
| bull \
| cbm \
| ccur \
| cisco \
| commodore \
| convergent* \
| convex* \
| cray \
| crds \
| dec* \
| delta* \
| dg \
| digital \
| dolphin \
| encore* \
| gould \
| harris \
| highlevel \
| hitachi* \
| hp \
| ibm* \
| intergraph \
| isi* \
| knuth \
| masscomp \
| microblaze* \
| mips* \
| motorola* \
| ncr* \
| news \
| next \
| ns \
| oki \
| omron* \
| pc533* \
| rebel \
| rom68k \
| rombug \
| semi \
| sequent* \
| siemens \
| sgi* \
| siemens \
| sim \
| sni \
| sony* \
| stratus \
| sun \
| sun[234]* \
| tektronix \
| tti* \
| ultra \
| unicom* \
| wec \
| winbond \
| wrs)
basic_machine=$field1-$field2
basic_os=
;;
zephyr*)
basic_machine=$field1-unknown
basic_os=$field2
;;
*)
basic_machine=$field1
basic_os=$field2
;;
esac
;;
esac
;;
*)
# Convert single-component short-hands not valid as part of
# multi-component configurations.
case $field1 in
386bsd)
basic_machine=i386-pc
basic_os=bsd
;;
a29khif)
basic_machine=a29k-amd
basic_os=udi
;;
adobe68k)
basic_machine=m68010-adobe
basic_os=scout
;;
alliant)
basic_machine=fx80-alliant
basic_os=
;;
altos | altos3068)
basic_machine=m68k-altos
basic_os=
;;
am29k)
basic_machine=a29k-none
basic_os=bsd
;;
amdahl)
basic_machine=580-amdahl
basic_os=sysv
;;
amiga)
basic_machine=m68k-unknown
basic_os=
;;
amigaos | amigados)
basic_machine=m68k-unknown
basic_os=amigaos
;;
amigaunix | amix)
basic_machine=m68k-unknown
basic_os=sysv4
;;
apollo68)
basic_machine=m68k-apollo
basic_os=sysv
;;
apollo68bsd)
basic_machine=m68k-apollo
basic_os=bsd
;;
aros)
basic_machine=i386-pc
basic_os=aros
;;
aux)
basic_machine=m68k-apple
basic_os=aux
;;
balance)
basic_machine=ns32k-sequent
basic_os=dynix
;;
blackfin)
basic_machine=bfin-unknown
basic_os=linux
;;
cegcc)
basic_machine=arm-unknown
basic_os=cegcc
;;
cray)
basic_machine=j90-cray
basic_os=unicos
;;
crds | unos)
basic_machine=m68k-crds
basic_os=
;;
da30)
basic_machine=m68k-da30
basic_os=
;;
decstation | pmax | pmin | dec3100 | decstatn)
basic_machine=mips-dec
basic_os=
;;
delta88)
basic_machine=m88k-motorola
basic_os=sysv3
;;
dicos)
basic_machine=i686-pc
basic_os=dicos
;;
djgpp)
basic_machine=i586-pc
basic_os=msdosdjgpp
;;
ebmon29k)
basic_machine=a29k-amd
basic_os=ebmon
;;
es1800 | OSE68k | ose68k | ose | OSE)
basic_machine=m68k-ericsson
basic_os=ose
;;
gmicro)
basic_machine=tron-gmicro
basic_os=sysv
;;
go32)
basic_machine=i386-pc
basic_os=go32
;;
h8300hms)
basic_machine=h8300-hitachi
basic_os=hms
;;
h8300xray)
basic_machine=h8300-hitachi
basic_os=xray
;;
h8500hms)
basic_machine=h8500-hitachi
basic_os=hms
;;
harris)
basic_machine=m88k-harris
basic_os=sysv3
;;
hp300 | hp300hpux)
basic_machine=m68k-hp
basic_os=hpux
;;
hp300bsd)
basic_machine=m68k-hp
basic_os=bsd
;;
hppaosf)
basic_machine=hppa1.1-hp
basic_os=osf
;;
hppro)
basic_machine=hppa1.1-hp
basic_os=proelf
;;
i386mach)
basic_machine=i386-mach
basic_os=mach
;;
isi68 | isi)
basic_machine=m68k-isi
basic_os=sysv
;;
m68knommu)
basic_machine=m68k-unknown
basic_os=linux
;;
magnum | m3230)
basic_machine=mips-mips
basic_os=sysv
;;
merlin)
basic_machine=ns32k-utek
basic_os=sysv
;;
mingw64)
basic_machine=x86_64-pc
basic_os=mingw64
;;
mingw32)
basic_machine=i686-pc
basic_os=mingw32
;;
mingw32ce)
basic_machine=arm-unknown
basic_os=mingw32ce
;;
monitor)
basic_machine=m68k-rom68k
basic_os=coff
;;
morphos)
basic_machine=powerpc-unknown
basic_os=morphos
;;
moxiebox)
basic_machine=moxie-unknown
basic_os=moxiebox
;;
msdos)
basic_machine=i386-pc
basic_os=msdos
;;
msys)
basic_machine=i686-pc
basic_os=msys
;;
mvs)
basic_machine=i370-ibm
basic_os=mvs
;;
nacl)
basic_machine=le32-unknown
basic_os=nacl
;;
ncr3000)
basic_machine=i486-ncr
basic_os=sysv4
;;
netbsd386)
basic_machine=i386-pc
basic_os=netbsd
;;
netwinder)
basic_machine=armv4l-rebel
basic_os=linux
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
basic_os=newsos
;;
news1000)
basic_machine=m68030-sony
basic_os=newsos
;;
necv70)
basic_machine=v70-nec
basic_os=sysv
;;
nh3000)
basic_machine=m68k-harris
basic_os=cxux
;;
nh[45]000)
basic_machine=m88k-harris
basic_os=cxux
;;
nindy960)
basic_machine=i960-intel
basic_os=nindy
;;
mon960)
basic_machine=i960-intel
basic_os=mon960
;;
nonstopux)
basic_machine=mips-compaq
basic_os=nonstopux
;;
os400)
basic_machine=powerpc-ibm
basic_os=os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
basic_os=ose
;;
os68k)
basic_machine=m68k-none
basic_os=os68k
;;
paragon)
basic_machine=i860-intel
basic_os=osf
;;
parisc)
basic_machine=hppa-unknown
basic_os=linux
;;
psp)
basic_machine=mipsallegrexel-sony
basic_os=psp
;;
pw32)
basic_machine=i586-unknown
basic_os=pw32
;;
rdos | rdos64)
basic_machine=x86_64-pc
basic_os=rdos
;;
rdos32)
basic_machine=i386-pc
basic_os=rdos
;;
rom68k)
basic_machine=m68k-rom68k
basic_os=coff
;;
sa29200)
basic_machine=a29k-amd
basic_os=udi
;;
sei)
basic_machine=mips-sei
basic_os=seiux
;;
sequent)
basic_machine=i386-sequent
basic_os=
;;
sps7)
basic_machine=m68k-bull
basic_os=sysv2
;;
st2000)
basic_machine=m68k-tandem
basic_os=
;;
stratus)
basic_machine=i860-stratus
basic_os=sysv4
;;
sun2)
basic_machine=m68000-sun
basic_os=
;;
sun2os3)
basic_machine=m68000-sun
basic_os=sunos3
;;
sun2os4)
basic_machine=m68000-sun
basic_os=sunos4
;;
sun3)
basic_machine=m68k-sun
basic_os=
;;
sun3os3)
basic_machine=m68k-sun
basic_os=sunos3
;;
sun3os4)
basic_machine=m68k-sun
basic_os=sunos4
;;
sun4)
basic_machine=sparc-sun
basic_os=
;;
sun4os3)
basic_machine=sparc-sun
basic_os=sunos3
;;
sun4os4)
basic_machine=sparc-sun
basic_os=sunos4
;;
sun4sol2)
basic_machine=sparc-sun
basic_os=solaris2
;;
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
basic_os=
;;
sv1)
basic_machine=sv1-cray
basic_os=unicos
;;
symmetry)
basic_machine=i386-sequent
basic_os=dynix
;;
t3e)
basic_machine=alphaev5-cray
basic_os=unicos
;;
t90)
basic_machine=t90-cray
basic_os=unicos
;;
toad1)
basic_machine=pdp10-xkl
basic_os=tops20
;;
tpf)
basic_machine=s390x-ibm
basic_os=tpf
;;
udi29k)
basic_machine=a29k-amd
basic_os=udi
;;
ultra3)
basic_machine=a29k-nyu
basic_os=sym1
;;
v810 | necv810)
basic_machine=v810-nec
basic_os=none
;;
vaxv)
basic_machine=vax-dec
basic_os=sysv
;;
vms)
basic_machine=vax-dec
basic_os=vms
;;
vsta)
basic_machine=i386-pc
basic_os=vsta
;;
vxworks960)
basic_machine=i960-wrs
basic_os=vxworks
;;
vxworks68)
basic_machine=m68k-wrs
basic_os=vxworks
;;
vxworks29k)
basic_machine=a29k-wrs
basic_os=vxworks
;;
xbox)
basic_machine=i686-pc
basic_os=mingw32
;;
ymp)
basic_machine=ymp-cray
basic_os=unicos
;;
*)
basic_machine=$1
basic_os=
;;
esac
;;
esac
# Decode 1-component or ad-hoc basic machines
case $basic_machine in
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
w89k)
cpu=hppa1.1
vendor=winbond
;;
op50n)
cpu=hppa1.1
vendor=oki
;;
op60c)
cpu=hppa1.1
vendor=oki
;;
ibm*)
cpu=i370
vendor=ibm
;;
orion105)
cpu=clipper
vendor=highlevel
;;
mac | mpw | mac-mpw)
cpu=m68k
vendor=apple
;;
pmac | pmac-mpw)
cpu=powerpc
vendor=apple
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
cpu=m68000
vendor=att
;;
3b*)
cpu=we32k
vendor=att
;;
bluegene*)
cpu=powerpc
vendor=ibm
basic_os=cnk
;;
decsystem10* | dec10*)
cpu=pdp10
vendor=dec
basic_os=tops10
;;
decsystem20* | dec20*)
cpu=pdp10
vendor=dec
basic_os=tops20
;;
delta | 3300 | delta-motorola | 3300-motorola | motorola-delta | motorola-3300)
cpu=m68k
vendor=motorola
;;
# This used to be dpx2*, but that gets the RS6000-based
# DPX/20 and the x86-based DPX/2-100 wrong. See
# https://oldskool.silicium.org/stations/bull_dpx20.htm
# https://www.feb-patrimoine.com/english/bull_dpx2.htm
# https://www.feb-patrimoine.com/english/unix_and_bull.htm
dpx2 | dpx2[23]00 | dpx2[23]xx)
cpu=m68k
vendor=bull
;;
dpx2100 | dpx21xx)
cpu=i386
vendor=bull
;;
dpx20)
cpu=rs6000
vendor=bull
;;
encore | umax | mmax)
cpu=ns32k
vendor=encore
;;
elxsi)
cpu=elxsi
vendor=elxsi
basic_os=${basic_os:-bsd}
;;
fx2800)
cpu=i860
vendor=alliant
;;
genix)
cpu=ns32k
vendor=ns
;;
h3050r* | hiux*)
cpu=hppa1.1
vendor=hitachi
basic_os=hiuxwe2
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
cpu=m68000
vendor=hp
;;
hp9k3[2-9][0-9])
cpu=m68k
vendor=hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
cpu=hppa1.1
vendor=hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
cpu=hppa1.1
vendor=hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
cpu=hppa1.1
vendor=hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
cpu=hppa1.1
vendor=hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
i*86v32)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv32
;;
i*86v4*)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv4
;;
i*86v)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv
;;
i*86sol2)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=solaris2
;;
j90 | j90-cray)
cpu=j90
vendor=cray
basic_os=${basic_os:-unicos}
;;
iris | iris4d)
cpu=mips
vendor=sgi
case $basic_os in
irix*)
;;
*)
basic_os=irix4
;;
esac
;;
miniframe)
cpu=m68000
vendor=convergent
;;
*mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
cpu=m68k
vendor=atari
basic_os=mint
;;
news-3600 | risc-news)
cpu=mips
vendor=sony
basic_os=newsos
;;
next | m*-next)
cpu=m68k
vendor=next
;;
np1)
cpu=np1
vendor=gould
;;
op50n-* | op60c-*)
cpu=hppa1.1
vendor=oki
basic_os=proelf
;;
pa-hitachi)
cpu=hppa1.1
vendor=hitachi
basic_os=hiuxwe2
;;
pbd)
cpu=sparc
vendor=tti
;;
pbb)
cpu=m68k
vendor=tti
;;
pc532)
cpu=ns32k
vendor=pc532
;;
pn)
cpu=pn
vendor=gould
;;
power)
cpu=power
vendor=ibm
;;
ps2)
cpu=i386
vendor=ibm
;;
rm[46]00)
cpu=mips
vendor=siemens
;;
rtpc | rtpc-*)
cpu=romp
vendor=ibm
;;
sde)
cpu=mipsisa32
vendor=sde
basic_os=${basic_os:-elf}
;;
simso-wrs)
cpu=sparclite
vendor=wrs
basic_os=vxworks
;;
tower | tower-32)
cpu=m68k
vendor=ncr
;;
vpp*|vx|vx-*)
cpu=f301
vendor=fujitsu
;;
w65)
cpu=w65
vendor=wdc
;;
w89k-*)
cpu=hppa1.1
vendor=winbond
basic_os=proelf
;;
none)
cpu=none
vendor=none
;;
leon|leon[3-9])
cpu=sparc
vendor=$basic_machine
;;
leon-*|leon[3-9]-*)
cpu=sparc
vendor=`echo "$basic_machine" | sed 's/-.*//'`
;;
*-*)
saved_IFS=$IFS
IFS="-" read cpu vendor <&2
exit 1
;;
esac
;;
esac
# Here we canonicalize certain aliases for manufacturers.
case $vendor in
digital*)
vendor=dec
;;
commodore*)
vendor=cbm
;;
*)
;;
esac
# Decode manufacturer-specific aliases for certain operating systems.
if test x"$basic_os" != x
then
# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
# set os.
obj=
case $basic_os in
gnu/linux*)
kernel=linux
os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
;;
os2-emx)
kernel=os2
os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
;;
nto-qnx*)
kernel=nto
os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
;;
*-*)
saved_IFS=$IFS
IFS="-" read kernel os <&2
fi
;;
*)
echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2
exit 1
;;
esac
case $obj in
aout* | coff* | elf* | pe*)
;;
'')
# empty is fine
;;
*)
echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2
exit 1
;;
esac
# Here we handle the constraint that a (synthetic) cpu and os are
# valid only in combination with each other and nowhere else.
case $cpu-$os in
# The "javascript-unknown-ghcjs" triple is used by GHC; we
# accept it here in order to tolerate that, but reject any
# variations.
javascript-ghcjs)
;;
javascript-* | *-ghcjs)
echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2
exit 1
;;
esac
# As a final step for OS-related things, validate the OS-kernel combination
# (given a valid OS), if there is a kernel.
case $kernel-$os-$obj in
linux-gnu*- | linux-android*- | linux-dietlibc*- | linux-llvm*- \
| linux-mlibc*- | linux-musl*- | linux-newlib*- \
| linux-relibc*- | linux-uclibc*- | linux-ohos*- )
;;
uclinux-uclibc*- | uclinux-gnu*- )
;;
managarm-mlibc*- | managarm-kernel*- )
;;
windows*-msvc*-)
;;
-dietlibc*- | -llvm*- | -mlibc*- | -musl*- | -newlib*- | -relibc*- \
| -uclibc*- )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2
exit 1
;;
-kernel*- )
echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2
exit 1
;;
*-kernel*- )
echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2
exit 1
;;
*-msvc*- )
echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2
exit 1
;;
kfreebsd*-gnu*- | knetbsd*-gnu*- | netbsd*-gnu*- | kopensolaris*-gnu*-)
;;
vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-)
;;
nto-qnx*-)
;;
os2-emx-)
;;
rtmk-nova-)
;;
*-eabi*- | *-gnueabi*-)
;;
none--*)
# None (no kernel, i.e. freestanding / bare metal),
# can be paired with an machine code file format
;;
-*-)
# Blank kernel with real OS is always fine.
;;
--*)
# Blank kernel and OS with real machine code file format is always fine.
;;
*-*-*)
echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2
exit 1
;;
esac
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
case $vendor in
unknown)
case $cpu-$os in
*-riscix*)
vendor=acorn
;;
*-sunos* | *-solaris*)
vendor=sun
;;
*-cnk* | *-aix*)
vendor=ibm
;;
*-beos*)
vendor=be
;;
*-hpux*)
vendor=hp
;;
*-mpeix*)
vendor=hp
;;
*-hiux*)
vendor=hitachi
;;
*-unos*)
vendor=crds
;;
*-dgux*)
vendor=dg
;;
*-luna*)
vendor=omron
;;
*-genix*)
vendor=ns
;;
*-clix*)
vendor=intergraph
;;
*-mvs* | *-opened*)
vendor=ibm
;;
*-os400*)
vendor=ibm
;;
s390-* | s390x-*)
vendor=ibm
;;
*-ptx*)
vendor=sequent
;;
*-tpf*)
vendor=ibm
;;
*-vxsim* | *-vxworks* | *-windiss*)
vendor=wrs
;;
*-aux*)
vendor=apple
;;
*-hms*)
vendor=hitachi
;;
*-mpw* | *-macos*)
vendor=apple
;;
*-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
vendor=atari
;;
*-vos*)
vendor=stratus
;;
esac
;;
esac
echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}"
exit
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
wimlib-1.14.5/build-aux/ar-lib 0000744 0001750 0001750 00000014501 15137024752 013352 0 ustar 00e e #! /bin/sh
# Wrapper for Microsoft lib.exe
me=ar-lib
scriptversion=2025-02-03.05; # UTC
# Copyright (C) 2010-2025 Free Software Foundation, Inc.
# Written by Peter Rosin .
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to or send patches to
# .
# func_error message
func_error ()
{
echo "$me: $1" 1>&2
exit 1
}
file_conv=
# func_file_conv build_file
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
if test -n "$MSYSTEM" && (cygpath --version) >/dev/null 2>&1; then
# MSYS2 environment.
file_conv=cygwin
else
# Original MinGW environment.
file_conv=mingw
fi
;;
MSYS*)
# Old MSYS environment, or MSYS2 with 32-bit MSYS2 shell.
file_conv=cygwin
;;
CYGWIN*)
# Cygwin environment.
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv in
mingw)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin)
file=`cygpath -w "$file" || echo "$file"`
;;
wine)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_at_file at_file operation archive
# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
# for each of them.
# When interpreting the content of the @FILE, do NOT use func_file_conv,
# since the user would need to supply preconverted file names to
# binutils ar, at least for MinGW.
func_at_file ()
{
operation=$2
archive=$3
at_file_contents=`cat "$1"`
eval set x "$at_file_contents"
shift
for member
do
$AR -NOLOGO $operation:"$member" "$archive" || exit $?
done
}
case $1 in
'')
func_error "no command. Try '$0 --help' for more information."
;;
-h | --h*)
cat <.
GNU Automake home page: .
General help using GNU software: .
EOF
exit $?
;;
-v | --v*)
echo "$me (GNU Automake) $scriptversion"
exit $?
;;
esac
if test $# -lt 3; then
func_error "you must specify a program, an action and an archive"
fi
AR=$1
shift
while :
do
if test $# -lt 2; then
func_error "you must specify a program, an action and an archive"
fi
case $1 in
-lib | -LIB \
| -ltcg | -LTCG \
| -machine* | -MACHINE* \
| -subsystem* | -SUBSYSTEM* \
| -verbose | -VERBOSE \
| -wx* | -WX* )
AR="$AR $1"
shift
;;
-nologo | -NOLOGO)
# We always invoke AR with -nologo, so don't need to add it again.
shift
;;
*)
action=$1
shift
break
;;
esac
done
orig_archive=$1
shift
func_file_conv "$orig_archive"
archive=$file
# strip leading dash in $action
action=${action#-}
delete=
extract=
list=
quick=
replace=
index=
create=
while test -n "$action"
do
case $action in
d*) delete=yes ;;
x*) extract=yes ;;
t*) list=yes ;;
q*) quick=yes ;;
r*) replace=yes ;;
s*) index=yes ;;
S*) ;; # the index is always updated implicitly
c*) create=yes ;;
u*) ;; # TODO: don't ignore the update modifier
v*) ;; # TODO: don't ignore the verbose modifier
*)
func_error "unknown action specified"
;;
esac
action=${action#?}
done
case $delete$extract$list$quick$replace,$index in
yes,* | ,yes)
;;
yesyes*)
func_error "more than one action specified"
;;
*)
func_error "no action specified"
;;
esac
if test -n "$delete"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
for member
do
case $1 in
@*)
func_at_file "${1#@}" -REMOVE "$archive"
;;
*)
func_file_conv "$1"
$AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
;;
esac
done
elif test -n "$extract"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
if test $# -gt 0; then
for member
do
case $1 in
@*)
func_at_file "${1#@}" -EXTRACT "$archive"
;;
*)
func_file_conv "$1"
$AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
;;
esac
done
else
$AR -NOLOGO -LIST "$archive" | tr -d '\r' | sed -e 's/\\/\\\\/g' \
| while read member
do
$AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
done
fi
elif test -n "$quick$replace"; then
if test ! -f "$orig_archive"; then
if test -z "$create"; then
echo "$me: creating $orig_archive"
fi
orig_archive=
else
orig_archive=$archive
fi
for member
do
case $1 in
@*)
func_file_conv "${1#@}"
set x "$@" "@$file"
;;
*)
func_file_conv "$1"
set x "$@" "$file"
;;
esac
shift
shift
done
if test -n "$orig_archive"; then
$AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
else
$AR -NOLOGO -OUT:"$archive" "$@" || exit $?
fi
elif test -n "$list"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
$AR -NOLOGO -LIST "$archive" || exit $?
fi
wimlib-1.14.5/build-aux/ltmain.sh 0000644 0001750 0001750 00001233125 15137024751 014105 0 ustar 00e e #! /usr/bin/env sh
## DO NOT EDIT - This file generated from ./build-aux/ltmain.in
## by inline-source v2019-02-19.15
# libtool (GNU libtool) 2.6.0
# Provide generalized library-building support services.
# Written by Gordon Matzigkeit , 1996
# Copyright (C) 1996-2019, 2021-2025 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions. There is NO
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# GNU Libtool is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# As a special exception to the GNU General Public License,
# if you distribute this file as part of a program or library that
# is built using GNU Libtool, you may include this file under the
# same distribution terms that you use for the rest of that program.
#
# GNU Libtool 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
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
PROGRAM=libtool
PACKAGE=libtool
VERSION=2.6.0
package_revision=2.6.0
## ------ ##
## Usage. ##
## ------ ##
# Run './libtool --help' for help with using this script from the
# command line.
## ------------------------------- ##
## User overridable command paths. ##
## ------------------------------- ##
# After configure completes, it has a better idea of some of the
# shell tools we need than the defaults used by the functions shared
# with bootstrap, so set those here where they can still be over-
# ridden by the user, but otherwise take precedence.
: ${AUTOCONF="autoconf"}
: ${AUTOMAKE="automake"}
## -------------------------- ##
## Source external libraries. ##
## -------------------------- ##
# Much of our low-level functionality needs to be sourced from external
# libraries, which are installed to $pkgauxdir.
# Set a version string for this script.
scriptversion=2019-02-19.15; # UTC
# General shell script boiler plate, and helper functions.
# Written by Gary V. Vaughan, 2004
# This is free software. There is NO warranty; not even for
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Copyright (C) 2004-2019, 2021, 2023-2024 Bootstrap Authors
#
# This file is dual licensed under the terms of the MIT license
# , and GPL version 2 or later
# . You must apply one of
# these licenses when using or redistributing this software or any of
# the files within it. See the URLs above, or the file `LICENSE`
# included in the Bootstrap distribution for the full license texts.
# Please report bugs or propose patches to:
#
## ------ ##
## Usage. ##
## ------ ##
# Evaluate this file near the top of your script to gain access to
# the functions and variables defined here:
#
# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh
#
# If you need to override any of the default environment variable
# settings, do that before evaluating this file.
## -------------------- ##
## Shell normalisation. ##
## -------------------- ##
# Some shells need a little help to be as Bourne compatible as possible.
# Before doing anything else, make sure all that help has been provided!
DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac
fi
# NLS nuisances: We save the old values in case they are required later.
_G_user_locale=
_G_safe_locale=
for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
do
eval "if test set = \"\${$_G_var+set}\"; then
save_$_G_var=\$$_G_var
$_G_var=C
export $_G_var
_G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\"
_G_safe_locale=\"$_G_var=C; \$_G_safe_locale\"
fi"
done
# These NLS vars are set unconditionally (bootstrap issue #24). Unset those
# in case the environment reset is needed later and the $save_* variant is not
# defined (see the code above).
LC_ALL=C
LANGUAGE=C
export LANGUAGE LC_ALL
# Make sure IFS has a sensible default
sp=' '
nl='
'
IFS="$sp $nl"
# There are apparently some systems that use ';' as a PATH separator!
if test "${PATH_SEPARATOR+set}" != set; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
PATH_SEPARATOR=';'
}
fi
# func_unset VAR
# --------------
# Portably unset VAR.
# In some shells, an 'unset VAR' statement leaves a non-zero return
# status if VAR is already unset, which might be problematic if the
# statement is used at the end of a function (thus poisoning its return
# value) or when 'set -e' is active (causing even a spurious abort of
# the script in this case).
func_unset ()
{
{ eval $1=; (eval unset $1) >/dev/null 2>&1 && eval unset $1 || : ; }
}
# Make sure CDPATH doesn't cause `cd` commands to output the target dir.
func_unset CDPATH
# Make sure ${,E,F}GREP behave sanely.
func_unset GREP_OPTIONS
## ------------------------- ##
## Locate command utilities. ##
## ------------------------- ##
# func_executable_p FILE
# ----------------------
# Check that FILE is an executable regular file.
func_executable_p ()
{
test -f "$1" && test -x "$1"
}
# func_path_progs PROGS_LIST CHECK_FUNC [PATH]
# --------------------------------------------
# Search for either a program that responds to --version with output
# containing "GNU", or else returned by CHECK_FUNC otherwise, by
# trying all the directories in PATH with each of the elements of
# PROGS_LIST.
#
# CHECK_FUNC should accept the path to a candidate program, and
# set $func_check_prog_result if it truncates its output less than
# $_G_path_prog_max characters.
func_path_progs ()
{
_G_progs_list=$1
_G_check_func=$2
_G_PATH=${3-"$PATH"}
_G_path_prog_max=0
_G_path_prog_found=false
_G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:}
for _G_dir in $_G_PATH; do
IFS=$_G_save_IFS
test -z "$_G_dir" && _G_dir=.
for _G_prog_name in $_G_progs_list; do
for _exeext in '' .EXE; do
_G_path_prog=$_G_dir/$_G_prog_name$_exeext
func_executable_p "$_G_path_prog" || continue
case `"$_G_path_prog" --version 2>&1` in
*GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;;
*) $_G_check_func $_G_path_prog
func_path_progs_result=$func_check_prog_result
;;
esac
$_G_path_prog_found && break 3
done
done
done
IFS=$_G_save_IFS
test -z "$func_path_progs_result" && {
echo "no acceptable sed could be found in \$PATH" >&2
exit 1
}
}
# We want to be able to use the functions in this file before configure
# has figured out where the best binaries are kept, which means we have
# to search for them ourselves - except when the results are already set
# where we skip the searches.
# Unless the user overrides by setting SED, search the path for either GNU
# sed, or the sed that truncates its output the least.
test -z "$SED" && {
_G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
for _G_i in 1 2 3 4 5 6 7; do
_G_sed_script=$_G_sed_script$nl$_G_sed_script
done
echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed
_G_sed_script=
func_check_prog_sed ()
{
_G_path_prog=$1
_G_count=0
printf 0123456789 >conftest.in
while :
do
cat conftest.in conftest.in >conftest.tmp
mv conftest.tmp conftest.in
cp conftest.in conftest.nl
echo '' >> conftest.nl
"$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break
diff conftest.out conftest.nl >/dev/null 2>&1 || break
_G_count=`expr $_G_count + 1`
if test "$_G_count" -gt "$_G_path_prog_max"; then
# Best one so far, save it but keep looking for a better one
func_check_prog_result=$_G_path_prog
_G_path_prog_max=$_G_count
fi
# 10*(2^10) chars as input seems more than enough
test 10 -lt "$_G_count" && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out
}
func_path_progs "sed gsed" func_check_prog_sed "$PATH:/usr/xpg4/bin"
rm -f conftest.sed
SED=$func_path_progs_result
}
# Unless the user overrides by setting GREP, search the path for either GNU
# grep, or the grep that truncates its output the least.
test -z "$GREP" && {
func_check_prog_grep ()
{
_G_path_prog=$1
_G_count=0
_G_path_prog_max=0
printf 0123456789 >conftest.in
while :
do
cat conftest.in conftest.in >conftest.tmp
mv conftest.tmp conftest.in
cp conftest.in conftest.nl
echo 'GREP' >> conftest.nl
"$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break
diff conftest.out conftest.nl >/dev/null 2>&1 || break
_G_count=`expr $_G_count + 1`
if test "$_G_count" -gt "$_G_path_prog_max"; then
# Best one so far, save it but keep looking for a better one
func_check_prog_result=$_G_path_prog
_G_path_prog_max=$_G_count
fi
# 10*(2^10) chars as input seems more than enough
test 10 -lt "$_G_count" && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out
}
func_path_progs "grep ggrep" func_check_prog_grep "$PATH:/usr/xpg4/bin"
GREP=$func_path_progs_result
}
## ------------------------------- ##
## User overridable command paths. ##
## ------------------------------- ##
# All uppercase variable names are used for environment variables. These
# variables can be overridden by the user before calling a script that
# uses them if a suitable command of that name is not already available
# in the command search PATH.
: ${CP="cp -f"}
: ${ECHO="printf %s\n"}
: ${EGREP="$GREP -E"}
: ${FGREP="$GREP -F"}
: ${LN_S="ln -s"}
: ${MAKE="make"}
: ${MKDIR="mkdir"}
: ${MV="mv -f"}
: ${RM="rm -f"}
: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
## -------------------- ##
## Useful sed snippets. ##
## -------------------- ##
sed_dirname='s|/[^/]*$||'
sed_basename='s|^.*/||'
# Sed substitution that helps us do robust quoting. It backslashifies
# metacharacters that are still active within double-quoted strings.
sed_quote_subst='s|\([`"$\\]\)|\\\1|g'
# Same as above, but do not quote variable references.
sed_double_quote_subst='s/\(["`\\]\)/\\\1/g'
# Sed substitution that turns a string into a regex matching for the
# string literally.
sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g'
# Sed substitution that converts a w32 file name or path
# that contains forward slashes, into one that contains
# (escaped) backslashes. A very naive implementation.
sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
# Re-'\' parameter expansions in output of sed_double_quote_subst that
# were '\'-ed in input to the same. If an odd number of '\' preceded a
# '$' in input to sed_double_quote_subst, that '$' was protected from
# expansion. Since each input '\' is now two '\'s, look for any number
# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'.
_G_bs='\\'
_G_bs2='\\\\'
_G_bs4='\\\\\\\\'
_G_dollar='\$'
sed_double_backslash="\
s/$_G_bs4/&\\
/g
s/^$_G_bs2$_G_dollar/$_G_bs&/
s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g
s/\n//g"
# require_check_ifs_backslash
# ---------------------------
# Check if we can use backslash as IFS='\' separator, and set
# $check_ifs_backshlash_broken to ':' or 'false'.
require_check_ifs_backslash=func_require_check_ifs_backslash
func_require_check_ifs_backslash ()
{
_G_save_IFS=$IFS
IFS='\'
_G_check_ifs_backshlash='a\\b'
for _G_i in $_G_check_ifs_backshlash
do
case $_G_i in
a)
check_ifs_backshlash_broken=false
;;
'')
break
;;
*)
check_ifs_backshlash_broken=:
break
;;
esac
done
IFS=$_G_save_IFS
require_check_ifs_backslash=:
}
## ----------------- ##
## Global variables. ##
## ----------------- ##
# Except for the global variables explicitly listed below, the following
# functions in the '^func_' namespace, and the '^require_' namespace
# variables initialised in the 'Resource management' section, sourcing
# this file will not pollute your global namespace with anything
# else. There's no portable way to scope variables in Bourne shell
# though, so actually running these functions will sometimes place
# results into a variable named after the function, and often use
# temporary variables in the '^_G_' namespace. If you are careful to
# avoid using those namespaces casually in your sourcing script, things
# should continue to work as you expect. And, of course, you can freely
# overwrite any of the functions or variables defined here before
# calling anything to customize them.
EXIT_SUCCESS=0
EXIT_FAILURE=1
EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing.
EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake.
# Allow overriding, eg assuming that you follow the convention of
# putting '$debug_cmd' at the start of all your functions, you can get
# bash to show function call trace with:
#
# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name
debug_cmd=${debug_cmd-":"}
exit_cmd=:
# By convention, finish your script with:
#
# exit $exit_status
#
# so that you can set exit_status to non-zero if you want to indicate
# something went wrong during execution without actually bailing out at
# the point of failure.
exit_status=$EXIT_SUCCESS
# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
# is ksh but when the shell is invoked as "sh" and the current value of
# the _XPG environment variable is not equal to 1 (one), the special
# positional parameter $0, within a function call, is the name of the
# function.
progpath=$0
# The name of this program.
progname=`$ECHO "$progpath" |$SED "$sed_basename"`
# Make sure we have an absolute progpath for reexecution:
case $progpath in
[\\/]*|[A-Za-z]:\\*) ;;
*[\\/]*)
progdir=`$ECHO "$progpath" |$SED "$sed_dirname"`
progdir=`cd "$progdir" && pwd`
progpath=$progdir/$progname
;;
*)
_G_IFS=$IFS
IFS=${PATH_SEPARATOR-:}
for progdir in $PATH; do
IFS=$_G_IFS
test -x "$progdir/$progname" && break
done
IFS=$_G_IFS
test -n "$progdir" || progdir=`pwd`
progpath=$progdir/$progname
;;
esac
## ----------------- ##
## Standard options. ##
## ----------------- ##
# The following options affect the operation of the functions defined
# below, and should be set appropriately depending on run-time para-
# meters passed on the command line.
opt_dry_run=false
opt_quiet=false
opt_verbose=false
# Categories 'all' and 'none' are always available. Append any others
# you will pass as the first argument to func_warning from your own
# code.
warning_categories=
# By default, display warnings according to 'opt_warning_types'. Set
# 'warning_func' to ':' to elide all warnings, or func_fatal_error to
# treat the next displayed warning as a fatal error.
warning_func=func_warn_and_continue
# Set to 'all' to display all warnings, 'none' to suppress all
# warnings, or a space delimited list of some subset of
# 'warning_categories' to display only the listed warnings.
opt_warning_types=all
## -------------------- ##
## Resource management. ##
## -------------------- ##
# This section contains definitions for functions that each ensure a
# particular resource (a file, or a non-empty configuration variable for
# example) is available, and if appropriate to extract default values
# from pertinent package files. Call them using their associated
# 'require_*' variable to ensure that they are executed, at most, once.
#
# It's entirely deliberate that calling these functions can set
# variables that don't obey the namespace limitations obeyed by the rest
# of this file, in order that that they be as useful as possible to
# callers.
# require_term_colors
# -------------------
# Allow display of bold text on terminals that support it.
require_term_colors=func_require_term_colors
func_require_term_colors ()
{
$debug_cmd
test -t 1 && {
# COLORTERM and USE_ANSI_COLORS environment variables take
# precedence, because most terminfo databases neglect to describe
# whether color sequences are supported.
test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"}
if test 1 = "$USE_ANSI_COLORS"; then
# Standard ANSI escape sequences
tc_reset='[0m'
tc_bold='[1m'; tc_standout='[7m'
tc_red='[31m'; tc_green='[32m'
tc_blue='[34m'; tc_cyan='[36m'
else
# Otherwise trust the terminfo database after all.
test -n "`tput sgr0 2>/dev/null`" && {
tc_reset=`tput sgr0`
test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold`
tc_standout=$tc_bold
test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso`
test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1`
test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2`
test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4`
test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5`
}
fi
}
require_term_colors=:
}
## ----------------- ##
## Function library. ##
## ----------------- ##
# This section contains a variety of useful functions to call in your
# scripts. Take note of the portable wrappers for features provided by
# some modern shells, which will fall back to slower equivalents on
# less featureful shells.
# func_append VAR VALUE
# ---------------------
# Append VALUE onto the existing contents of VAR.
# We should try to minimise forks, especially on Windows where they are
# unreasonably slow, so skip the feature probes when bash or zsh are
# being used:
if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then
: ${_G_HAVE_ARITH_OP="yes"}
: ${_G_HAVE_XSI_OPS="yes"}
# The += operator was introduced in bash 3.1
case $BASH_VERSION in
[12].* | 3.0 | 3.0*) ;;
*)
: ${_G_HAVE_PLUSEQ_OP="yes"}
;;
esac
fi
# _G_HAVE_PLUSEQ_OP
# Can be empty, in which case the shell is probed, "yes" if += is
# usable or anything else if it does not work.
test -z "$_G_HAVE_PLUSEQ_OP" \
&& (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \
&& _G_HAVE_PLUSEQ_OP=yes
if test yes = "$_G_HAVE_PLUSEQ_OP"
then
# This is an XSI compatible shell, allowing a faster implementation...
eval 'func_append ()
{
$debug_cmd
eval "$1+=\$2"
}'
else
# ...otherwise fall back to using expr, which is often a shell builtin.
func_append ()
{
$debug_cmd
eval "$1=\$$1\$2"
}
fi
# func_append_quoted VAR VALUE
# ----------------------------
# Quote VALUE and append to the end of shell variable VAR, separated
# by a space.
if test yes = "$_G_HAVE_PLUSEQ_OP"; then
eval 'func_append_quoted ()
{
$debug_cmd
func_quote_arg pretty "$2"
eval "$1+=\\ \$func_quote_arg_result"
}'
else
func_append_quoted ()
{
$debug_cmd
func_quote_arg pretty "$2"
eval "$1=\$$1\\ \$func_quote_arg_result"
}
fi
# func_append_uniq VAR VALUE
# --------------------------
# Append unique VALUE onto the existing contents of VAR, assuming
# entries are delimited by the first character of VALUE. For example:
#
# func_append_uniq options " --another-option option-argument"
#
# will only append to $options if " --another-option option-argument "
# is not already present somewhere in $options already (note spaces at
# each end implied by leading space in second argument).
func_append_uniq ()
{
$debug_cmd
eval _G_current_value='`$ECHO $'$1'`'
_G_delim=`expr "$2" : '\(.\)'`
case $_G_delim$_G_current_value$_G_delim in
*"$2$_G_delim"*) ;;
*) func_append "$@" ;;
esac
}
# func_arith TERM...
# ------------------
# Set func_arith_result to the result of evaluating TERMs.
test -z "$_G_HAVE_ARITH_OP" \
&& (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \
&& _G_HAVE_ARITH_OP=yes
if test yes = "$_G_HAVE_ARITH_OP"; then
eval 'func_arith ()
{
$debug_cmd
func_arith_result=$(( $* ))
}'
else
func_arith ()
{
$debug_cmd
func_arith_result=`expr "$@"`
}
fi
# func_basename FILE
# ------------------
# Set func_basename_result to FILE with everything up to and including
# the last / stripped.
if test yes = "$_G_HAVE_XSI_OPS"; then
# If this shell supports suffix pattern removal, then use it to avoid
# forking. Hide the definitions single quotes in case the shell chokes
# on unsupported syntax...
_b='func_basename_result=${1##*/}'
_d='case $1 in
*/*) func_dirname_result=${1%/*}$2 ;;
* ) func_dirname_result=$3 ;;
esac'
else
# ...otherwise fall back to using sed.
_b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`'
_d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"`
if test "X$func_dirname_result" = "X$1"; then
func_dirname_result=$3
else
func_append func_dirname_result "$2"
fi'
fi
eval 'func_basename ()
{
$debug_cmd
'"$_b"'
}'
# func_dirname FILE APPEND NONDIR_REPLACEMENT
# -------------------------------------------
# Compute the dirname of FILE. If nonempty, add APPEND to the result,
# otherwise set result to NONDIR_REPLACEMENT.
eval 'func_dirname ()
{
$debug_cmd
'"$_d"'
}'
# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT
# --------------------------------------------------------
# Perform func_basename and func_dirname in a single function
# call:
# dirname: Compute the dirname of FILE. If nonempty,
# add APPEND to the result, otherwise set result
# to NONDIR_REPLACEMENT.
# value returned in "$func_dirname_result"
# basename: Compute filename of FILE.
# value returned in "$func_basename_result"
# For efficiency, we do not delegate to the functions above but instead
# duplicate the functionality here.
eval 'func_dirname_and_basename ()
{
$debug_cmd
'"$_b"'
'"$_d"'
}'
# func_echo ARG...
# ----------------
# Echo program name prefixed message.
func_echo ()
{
$debug_cmd
_G_message=$*
func_echo_IFS=$IFS
IFS=$nl
for _G_line in $_G_message; do
IFS=$func_echo_IFS
$ECHO "$progname: $_G_line"
done
IFS=$func_echo_IFS
}
# func_echo_all ARG...
# --------------------
# Invoke $ECHO with all args, space-separated.
func_echo_all ()
{
$ECHO "$*"
}
# func_echo_infix_1 INFIX ARG...
# ------------------------------
# Echo program name, followed by INFIX on the first line, with any
# additional lines not showing INFIX.
func_echo_infix_1 ()
{
$debug_cmd
$require_term_colors
_G_infix=$1; shift
_G_indent=$_G_infix
_G_prefix="$progname: $_G_infix: "
_G_message=$*
# Strip color escape sequences before counting printable length
for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan"
do
test -n "$_G_tc" && {
_G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"`
_G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"`
}
done
_G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes
func_echo_infix_1_IFS=$IFS
IFS=$nl
for _G_line in $_G_message; do
IFS=$func_echo_infix_1_IFS
$ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2
_G_prefix=$_G_indent
done
IFS=$func_echo_infix_1_IFS
}
# func_error ARG...
# -----------------
# Echo program name prefixed message to standard error.
func_error ()
{
$debug_cmd
$require_term_colors
func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2
}
# func_fatal_error ARG...
# -----------------------
# Echo program name prefixed message to standard error, and exit.
func_fatal_error ()
{
$debug_cmd
func_error "$*"
exit $EXIT_FAILURE
}
# func_grep EXPRESSION FILENAME
# -----------------------------
# Check whether EXPRESSION matches any line of FILENAME, without output.
func_grep ()
{
$debug_cmd
$GREP "$1" "$2" >/dev/null 2>&1
}
# func_len STRING
# ---------------
# Set func_len_result to the length of STRING. STRING may not
# start with a hyphen.
test -z "$_G_HAVE_XSI_OPS" \
&& (eval 'x=a/b/c;
test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
&& _G_HAVE_XSI_OPS=yes
if test yes = "$_G_HAVE_XSI_OPS"; then
eval 'func_len ()
{
$debug_cmd
func_len_result=${#1}
}'
else
func_len ()
{
$debug_cmd
func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
}
fi
# func_mkdir_p DIRECTORY-PATH
# ---------------------------
# Make sure the entire path to DIRECTORY-PATH is available.
func_mkdir_p ()
{
$debug_cmd
_G_directory_path=$1
_G_dir_list=
if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then
# Protect directory names starting with '-'
case $_G_directory_path in
-*) _G_directory_path=./$_G_directory_path ;;
esac
# While some portion of DIR does not yet exist...
while test ! -d "$_G_directory_path"; do
# ...make a list in topmost first order. Use a colon delimited
# list in case some portion of path contains whitespace.
_G_dir_list=$_G_directory_path:$_G_dir_list
# If the last portion added has no slash in it, the list is done
case $_G_directory_path in */*) ;; *) break ;; esac
# ...otherwise throw away the child directory and loop
_G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"`
done
_G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'`
func_mkdir_p_IFS=$IFS; IFS=:
for _G_dir in $_G_dir_list; do
IFS=$func_mkdir_p_IFS
# mkdir can fail with a 'File exist' error if two processes
# try to create one of the directories concurrently. Don't
# stop in that case!
$MKDIR "$_G_dir" 2>/dev/null || :
done
IFS=$func_mkdir_p_IFS
# Bail out if we (or some other process) failed to create a directory.
test -d "$_G_directory_path" || \
func_fatal_error "Failed to create '$1'"
fi
}
# func_mktempdir [BASENAME]
# -------------------------
# Make a temporary directory that won't clash with other running
# libtool processes, and avoids race conditions if possible. If
# given, BASENAME is the basename for that directory.
func_mktempdir ()
{
$debug_cmd
_G_template=${TMPDIR-/tmp}/${1-$progname}
if test : = "$opt_dry_run"; then
# Return a directory name, but don't create it in dry-run mode
_G_tmpdir=$_G_template-$$
else
# If mktemp works, use that first and foremost
_G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null`
if test ! -d "$_G_tmpdir"; then
# Failing that, at least try and use $RANDOM to avoid a race
_G_tmpdir=$_G_template-${RANDOM-0}$$
func_mktempdir_umask=`umask`
umask 0077
$MKDIR "$_G_tmpdir"
umask $func_mktempdir_umask
fi
# If we're not in dry-run mode, bomb out on failure
test -d "$_G_tmpdir" || \
func_fatal_error "cannot create temporary directory '$_G_tmpdir'"
fi
$ECHO "$_G_tmpdir"
}
# func_normal_abspath PATH
# ------------------------
# Remove doubled-up and trailing slashes, "." path components,
# and cancel out any ".." path components in PATH after making
# it an absolute path.
func_normal_abspath ()
{
$debug_cmd
# These SED scripts presuppose an absolute path with a trailing slash.
_G_pathcar='s|^/\([^/]*\).*$|\1|'
_G_pathcdr='s|^/[^/]*||'
_G_removedotparts=':dotsl
s|/\./|/|g
t dotsl
s|/\.$|/|'
_G_collapseslashes='s|/\{1,\}|/|g'
_G_finalslash='s|/*$|/|'
# Start from root dir and reassemble the path.
func_normal_abspath_result=
func_normal_abspath_tpath=$1
func_normal_abspath_altnamespace=
case $func_normal_abspath_tpath in
"")
# Empty path, that just means $cwd.
func_stripname '' '/' "`pwd`"
func_normal_abspath_result=$func_stripname_result
return
;;
# The next three entries are used to spot a run of precisely
# two leading slashes without using negated character classes;
# we take advantage of case's first-match behaviour.
///*)
# Unusual form of absolute path, do nothing.
;;
//*)
# Not necessarily an ordinary path; POSIX reserves leading '//'
# and for example Cygwin uses it to access remote file shares
# over CIFS/SMB, so we conserve a leading double slash if found.
func_normal_abspath_altnamespace=/
;;
/*)
# Absolute path, do nothing.
;;
*)
# Relative path, prepend $cwd.
func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
;;
esac
# Cancel out all the simple stuff to save iterations. We also want
# the path to end with a slash for ease of parsing, so make sure
# there is one (and only one) here.
func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
-e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"`
while :; do
# Processed it all yet?
if test / = "$func_normal_abspath_tpath"; then
# If we ascended to the root using ".." the result may be empty now.
if test -z "$func_normal_abspath_result"; then
func_normal_abspath_result=/
fi
break
fi
func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
-e "$_G_pathcar"`
func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
-e "$_G_pathcdr"`
# Figure out what to do with it
case $func_normal_abspath_tcomponent in
"")
# Trailing empty path component, ignore it.
;;
..)
# Parent dir; strip last assembled component from result.
func_dirname "$func_normal_abspath_result"
func_normal_abspath_result=$func_dirname_result
;;
*)
# Actual path component, append it.
func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent"
;;
esac
done
# Restore leading double-slash if one was found on entry.
func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
}
# func_notquiet ARG...
# --------------------
# Echo program name prefixed message only when not in quiet mode.
func_notquiet ()
{
$debug_cmd
$opt_quiet || func_echo ${1+"$@"}
# A bug in bash halts the script if the last line of a function
# fails when set -e is in force, so we need another command to
# work around that:
:
}
# func_relative_path SRCDIR DSTDIR
# --------------------------------
# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR.
func_relative_path ()
{
$debug_cmd
func_relative_path_result=
func_normal_abspath "$1"
func_relative_path_tlibdir=$func_normal_abspath_result
func_normal_abspath "$2"
func_relative_path_tbindir=$func_normal_abspath_result
# Ascend the tree starting from libdir
while :; do
# check if we have found a prefix of bindir
case $func_relative_path_tbindir in
$func_relative_path_tlibdir)
# found an exact match
func_relative_path_tcancelled=
break
;;
$func_relative_path_tlibdir*)
# found a matching prefix
func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
func_relative_path_tcancelled=$func_stripname_result
if test -z "$func_relative_path_result"; then
func_relative_path_result=.
fi
break
;;
*)
func_dirname $func_relative_path_tlibdir
func_relative_path_tlibdir=$func_dirname_result
if test -z "$func_relative_path_tlibdir"; then
# Have to descend all the way to the root!
func_relative_path_result=../$func_relative_path_result
func_relative_path_tcancelled=$func_relative_path_tbindir
break
fi
func_relative_path_result=../$func_relative_path_result
;;
esac
done
# Now calculate path; take care to avoid doubling-up slashes.
func_stripname '' '/' "$func_relative_path_result"
func_relative_path_result=$func_stripname_result
func_stripname '/' '/' "$func_relative_path_tcancelled"
if test -n "$func_stripname_result"; then
func_append func_relative_path_result "/$func_stripname_result"
fi
# Normalisation. If bindir is libdir, return '.' else relative path.
if test -n "$func_relative_path_result"; then
func_stripname './' '' "$func_relative_path_result"
func_relative_path_result=$func_stripname_result
fi
test -n "$func_relative_path_result" || func_relative_path_result=.
:
}
# func_quote_portable EVAL ARG
# ----------------------------
# Internal function to portably implement func_quote_arg. Note that we still
# keep attention to performance here so we as much as possible try to avoid
# calling sed binary (so far O(N) complexity as long as func_append is O(1)).
func_quote_portable ()
{
$debug_cmd
$require_check_ifs_backslash
func_quote_portable_result=$2
# one-time-loop (easy break)
while true
do
if $1; then
func_quote_portable_result=`$ECHO "$2" | $SED \
-e "$sed_double_quote_subst" -e "$sed_double_backslash"`
break
fi
# Quote for eval.
case $func_quote_portable_result in
*[\\\`\"\$]*)
# Fallback to sed for $func_check_bs_ifs_broken=:, or when the string
# contains the shell wildcard characters.
case $check_ifs_backshlash_broken$func_quote_portable_result in
:*|*[\[\*\?]*)
func_quote_portable_result=`$ECHO "$func_quote_portable_result" \
| $SED "$sed_quote_subst"`
break
;;
esac
func_quote_portable_old_IFS=$IFS
for _G_char in '\' '`' '"' '$'
do
# STATE($1) PREV($2) SEPARATOR($3)
set start "" ""
func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy
IFS=$_G_char
for _G_part in $func_quote_portable_result
do
case $1 in
quote)
func_append func_quote_portable_result "$3$2"
set quote "$_G_part" "\\$_G_char"
;;
start)
set first "" ""
func_quote_portable_result=
;;
first)
set quote "$_G_part" ""
;;
esac
done
done
IFS=$func_quote_portable_old_IFS
;;
*) ;;
esac
break
done
func_quote_portable_unquoted_result=$func_quote_portable_result
case $func_quote_portable_result in
# double-quote args containing shell metacharacters to delay
# word splitting, command substitution and variable expansion
# for a subsequent eval.
# many bourne shells cannot handle close brackets correctly
# in scan sets, so we specify it separately.
*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
func_quote_portable_result=\"$func_quote_portable_result\"
;;
esac
}
# func_quotefast_eval ARG
# -----------------------
# Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG',
# but optimized for speed. Result is stored in $func_quotefast_eval.
if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then
printf -v _GL_test_printf_tilde %q '~'
if test '\~' = "$_GL_test_printf_tilde"; then
func_quotefast_eval ()
{
printf -v func_quotefast_eval_result %q "$1"
}
else
# Broken older Bash implementations. Make those faster too if possible.
func_quotefast_eval ()
{
case $1 in
'~'*)
func_quote_portable false "$1"
func_quotefast_eval_result=$func_quote_portable_result
;;
*)
printf -v func_quotefast_eval_result %q "$1"
;;
esac
}
fi
else
func_quotefast_eval ()
{
func_quote_portable false "$1"
func_quotefast_eval_result=$func_quote_portable_result
}
fi
# func_quote_arg MODEs ARG
# ------------------------
# Quote one ARG to be evaled later. MODEs argument may contain zero or more
# specifiers listed below separated by ',' character. This function returns two
# values:
# i) func_quote_arg_result
# double-quoted (when needed), suitable for a subsequent eval
# ii) func_quote_arg_unquoted_result
# has all characters that are still active within double
# quotes backslashified. Available only if 'unquoted' is specified.
#
# Available modes:
# ----------------
# 'eval' (default)
# - escape shell special characters
# 'expand'
# - the same as 'eval'; but do not quote variable references
# 'pretty'
# - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might
# be used later in func_quote to get output like: 'echo "a b"' instead
# of 'echo a\ b'. This is slower than default on some shells.
# 'unquoted'
# - produce also $func_quote_arg_unquoted_result which does not contain
# wrapping double-quotes.
#
# Examples for 'func_quote_arg pretty,unquoted string':
#
# string | *_result | *_unquoted_result
# ------------+-----------------------+-------------------
# " | \" | \"
# a b | "a b" | a b
# "a b" | "\"a b\"" | \"a b\"
# * | "*" | *
# z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\"
#
# Examples for 'func_quote_arg pretty,unquoted,expand string':
#
# string | *_result | *_unquoted_result
# --------------+---------------------+--------------------
# z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\"
func_quote_arg ()
{
_G_quote_expand=false
case ,$1, in
*,expand,*)
_G_quote_expand=:
;;
esac
case ,$1, in
*,pretty,*|*,expand,*|*,unquoted,*)
func_quote_portable $_G_quote_expand "$2"
func_quote_arg_result=$func_quote_portable_result
func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result
;;
*)
# Faster quote-for-eval for some shells.
func_quotefast_eval "$2"
func_quote_arg_result=$func_quotefast_eval_result
;;
esac
}
# func_quote MODEs ARGs...
# ------------------------
# Quote all ARGs to be evaled later and join them into single command. See
# func_quote_arg's description for more info.
func_quote ()
{
$debug_cmd
_G_func_quote_mode=$1 ; shift
func_quote_result=
while test 0 -lt $#; do
func_quote_arg "$_G_func_quote_mode" "$1"
if test -n "$func_quote_result"; then
func_append func_quote_result " $func_quote_arg_result"
else
func_append func_quote_result "$func_quote_arg_result"
fi
shift
done
}
# func_stripname PREFIX SUFFIX NAME
# ---------------------------------
# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result.
# PREFIX and SUFFIX must not contain globbing or regex special
# characters, hashes, percent signs, but SUFFIX may contain a leading
# dot (in which case that matches only a dot).
if test yes = "$_G_HAVE_XSI_OPS"; then
eval 'func_stripname ()
{
$debug_cmd
# pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
# positional parameters, so assign one to ordinary variable first.
func_stripname_result=$3
func_stripname_result=${func_stripname_result#"$1"}
func_stripname_result=${func_stripname_result%"$2"}
}'
else
func_stripname ()
{
$debug_cmd
case $2 in
.*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;;
*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;;
esac
}
fi
# func_show_eval CMD [FAIL_EXP]
# -----------------------------
# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is
# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
# is given, then evaluate it.
func_show_eval ()
{
$debug_cmd
_G_cmd=$1
_G_fail_exp=${2-':'}
func_quote_arg pretty,expand "$_G_cmd"
eval "func_notquiet $func_quote_arg_result"
$opt_dry_run || {
eval "$_G_cmd"
_G_status=$?
if test 0 -ne "$_G_status"; then
eval "(exit $_G_status); $_G_fail_exp"
fi
}
}
# func_show_eval_locale CMD [FAIL_EXP]
# ------------------------------------
# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is
# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
# is given, then evaluate it. Use the saved locale for evaluation.
func_show_eval_locale ()
{
$debug_cmd
_G_cmd=$1
_G_fail_exp=${2-':'}
$opt_quiet || {
func_quote_arg expand,pretty "$_G_cmd"
eval "func_echo $func_quote_arg_result"
}
$opt_dry_run || {
eval "$_G_user_locale
$_G_cmd"
_G_status=$?
eval "$_G_safe_locale"
if test 0 -ne "$_G_status"; then
eval "(exit $_G_status); $_G_fail_exp"
fi
}
}
# func_tr_sh
# ----------
# Turn $1 into a string suitable for a shell variable name.
# Result is stored in $func_tr_sh_result. All characters
# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
# if $1 begins with a digit, a '_' is prepended as well.
func_tr_sh ()
{
$debug_cmd
case $1 in
[0-9]* | *[!a-zA-Z0-9_]*)
func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'`
;;
* )
func_tr_sh_result=$1
;;
esac
}
# func_verbose ARG...
# -------------------
# Echo program name prefixed message in verbose mode only.
func_verbose ()
{
$debug_cmd
$opt_verbose && func_echo "$*"
:
}
# func_warn_and_continue ARG...
# -----------------------------
# Echo program name prefixed warning message to standard error.
func_warn_and_continue ()
{
$debug_cmd
$require_term_colors
func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2
}
# func_warning CATEGORY ARG...
# ----------------------------
# Echo program name prefixed warning message to standard error. Warning
# messages can be filtered according to CATEGORY, where this function
# elides messages where CATEGORY is not listed in the global variable
# 'opt_warning_types'.
func_warning ()
{
$debug_cmd
# CATEGORY must be in the warning_categories list!
case " $warning_categories " in
*" $1 "*) ;;
*) func_internal_error "invalid warning category '$1'" ;;
esac
_G_category=$1
shift
case " $opt_warning_types " in
*" $_G_category "*) $warning_func ${1+"$@"} ;;
esac
}
# func_sort_ver VER1 VER2
# -----------------------
# 'sort -V' is not generally available.
# Note this deviates from the version comparison in automake
# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a
# but this should suffice as we won't be specifying old
# version formats or redundant trailing .0 in bootstrap.conf.
# If we did want full compatibility then we should probably
# use m4_version_compare from autoconf.
func_sort_ver ()
{
$debug_cmd
printf '%s\n%s\n' "$1" "$2" \
| sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n
}
# func_lt_ver PREV CURR
# ---------------------
# Return true if PREV and CURR are in the correct order according to
# func_sort_ver, otherwise false. Use it like this:
#
# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..."
func_lt_ver ()
{
$debug_cmd
test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q`
}
# Local variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
# time-stamp-time-zone: "UTC"
# End:
#! /bin/sh
# A portable, pluggable option parser for Bourne shell.
# Written by Gary V. Vaughan, 2010
# This is free software. There is NO warranty; not even for
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Copyright (C) 2010-2019, 2021, 2023-2024 Bootstrap Authors
#
# This file is dual licensed under the terms of the MIT license
# , and GPL version 2 or later
# . You must apply one of
# these licenses when using or redistributing this software or any of
# the files within it. See the URLs above, or the file `LICENSE`
# included in the Bootstrap distribution for the full license texts.
# Please report bugs or propose patches to:
#
# Set a version string for this script.
scriptversion=2019-02-19.15; # UTC
## ------ ##
## Usage. ##
## ------ ##
# This file is a library for parsing options in your shell scripts along
# with assorted other useful supporting features that you can make use
# of too.
#
# For the simplest scripts you might need only:
#
# #!/bin/sh
# . relative/path/to/funclib.sh
# . relative/path/to/options-parser
# scriptversion=1.0
# func_options ${1+"$@"}
# eval set dummy "$func_options_result"; shift
# ...rest of your script...
#
# In order for the '--version' option to work, you will need to have a
# suitably formatted comment like the one at the top of this file
# starting with '# Written by ' and ending with '# Copyright'.
#
# For '-h' and '--help' to work, you will also need a one line
# description of your script's purpose in a comment directly above the
# '# Written by ' line, like the one at the top of this file.
#
# The default options also support '--debug', which will turn on shell
# execution tracing (see the comment above debug_cmd below for another
# use), and '--verbose' and the func_verbose function to allow your script
# to display verbose messages only when your user has specified
# '--verbose'.
#
# After sourcing this file, you can plug in processing for additional
# options by amending the variables from the 'Configuration' section
# below, and following the instructions in the 'Option parsing'
# section further down.
## -------------- ##
## Configuration. ##
## -------------- ##
# You should override these variables in your script after sourcing this
# file so that they reflect the customisations you have added to the
# option parser.
# The usage line for option parsing errors and the start of '-h' and
# '--help' output messages. You can embed shell variables for delayed
# expansion at the time the message is displayed, but you will need to
# quote other shell meta-characters carefully to prevent them being
# expanded when the contents are evaled.
usage='$progpath [OPTION]...'
# Short help message in response to '-h' and '--help'. Add to this or
# override it after sourcing this library to reflect the full set of
# options your script accepts.
usage_message="\
--debug enable verbose shell tracing
-W, --warnings=CATEGORY
report the warnings falling in CATEGORY [all]
-v, --verbose verbosely report processing
--version print version information and exit
-h, --help print short or long help message and exit
"
# Additional text appended to 'usage_message' in response to '--help'.
long_help_message="
Warning categories include:
'all' show all warnings
'none' turn off all the warnings
'error' warnings are treated as fatal errors"
# Help message printed before fatal option parsing errors.
fatal_help="Try '\$progname --help' for more information."
## ------------------------- ##
## Hook function management. ##
## ------------------------- ##
# This section contains functions for adding, removing, and running hooks
# in the main code. A hook is just a list of function names that can be
# run in order later on.
# func_hookable FUNC_NAME
# -----------------------
# Declare that FUNC_NAME will run hooks added with
# 'func_add_hook FUNC_NAME ...'.
func_hookable ()
{
$debug_cmd
func_append hookable_fns " $1"
}
# func_add_hook FUNC_NAME HOOK_FUNC
# ---------------------------------
# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must
# first have been declared "hookable" by a call to 'func_hookable'.
func_add_hook ()
{
$debug_cmd
case " $hookable_fns " in
*" $1 "*) ;;
*) func_fatal_error "'$1' does not accept hook functions." ;;
esac
eval func_append ${1}_hooks '" $2"'
}
# func_remove_hook FUNC_NAME HOOK_FUNC
# ------------------------------------
# Remove HOOK_FUNC from the list of hook functions to be called by
# FUNC_NAME.
func_remove_hook ()
{
$debug_cmd
eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`'
}
# func_propagate_result FUNC_NAME_A FUNC_NAME_B
# ---------------------------------------------
# If the *_result variable of FUNC_NAME_A _is set_, assign its value to
# *_result variable of FUNC_NAME_B.
func_propagate_result ()
{
$debug_cmd
func_propagate_result_result=:
if eval "test \"\${${1}_result+set}\" = set"
then
eval "${2}_result=\$${1}_result"
else
func_propagate_result_result=false
fi
}
# func_run_hooks FUNC_NAME [ARG]...
# ---------------------------------
# Run all hook functions registered to FUNC_NAME.
# It's assumed that the list of hook functions contains nothing more
# than a whitespace-delimited list of legal shell function names, and
# no effort is wasted trying to catch shell meta-characters or preserve
# whitespace.
func_run_hooks ()
{
$debug_cmd
case " $hookable_fns " in
*" $1 "*) ;;
*) func_fatal_error "'$1' does not support hook functions." ;;
esac
eval _G_hook_fns=\$$1_hooks; shift
for _G_hook in $_G_hook_fns; do
func_unset "${_G_hook}_result"
eval $_G_hook '${1+"$@"}'
func_propagate_result $_G_hook func_run_hooks
if $func_propagate_result_result; then
eval set dummy "$func_run_hooks_result"; shift
fi
done
}
## --------------- ##
## Option parsing. ##
## --------------- ##
# In order to add your own option parsing hooks, you must accept the
# full positional parameter list from your hook function. You may remove
# or edit any options that you action, and then pass back the remaining
# unprocessed options in '_result', escaped
# suitably for 'eval'.
#
# The '_result' variable is automatically unset
# before your hook gets called; for best performance, only set the
# *_result variable when necessary (i.e. don't call the 'func_quote'
# function unnecessarily because it can be an expensive operation on some
# machines).
#
# Like this:
#
# my_options_prep ()
# {
# $debug_cmd
#
# # Extend the existing usage message.
# usage_message=$usage_message'
# -s, --silent don'\''t print informational messages
# '
# # No change in '$@' (ignored completely by this hook). Leave
# # my_options_prep_result variable intact.
# }
# func_add_hook func_options_prep my_options_prep
#
#
# my_silent_option ()
# {
# $debug_cmd
#
# args_changed=false
#
# # Note that, for efficiency, we parse as many options as we can
# # recognise in a loop before passing the remainder back to the
# # caller on the first unrecognised argument we encounter.
# while test $# -gt 0; do
# opt=$1; shift
# case $opt in
# --silent|-s) opt_silent=:
# args_changed=:
# ;;
# # Separate non-argument short options:
# -s*) func_split_short_opt "$_G_opt"
# set dummy "$func_split_short_opt_name" \
# "-$func_split_short_opt_arg" ${1+"$@"}
# shift
# args_changed=:
# ;;
# *) # Make sure the first unrecognised option "$_G_opt"
# # is added back to "$@" in case we need it later,
# # if $args_changed was set to 'true'.
# set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
# esac
# done
#
# # Only call 'func_quote' here if we processed at least one argument.
# if $args_changed; then
# func_quote eval ${1+"$@"}
# my_silent_option_result=$func_quote_result
# fi
# }
# func_add_hook func_parse_options my_silent_option
#
#
# my_option_validation ()
# {
# $debug_cmd
#
# $opt_silent && $opt_verbose && func_fatal_help "\
# '--silent' and '--verbose' options are mutually exclusive."
# }
# func_add_hook func_validate_options my_option_validation
#
# You'll also need to manually amend $usage_message to reflect the extra
# options you parse. It's preferable to append if you can, so that
# multiple option parsing hooks can be added safely.
# func_options_finish [ARG]...
# ----------------------------
# Finishing the option parse loop (call 'func_options' hooks ATM).
func_options_finish ()
{
$debug_cmd
func_run_hooks func_options ${1+"$@"}
func_propagate_result func_run_hooks func_options_finish
}
# func_options [ARG]...
# ---------------------
# All the functions called inside func_options are hookable. See the
# individual implementations for details.
func_hookable func_options
func_options ()
{
$debug_cmd
_G_options_quoted=false
for my_func in options_prep parse_options validate_options options_finish
do
func_unset func_${my_func}_result
func_unset func_run_hooks_result
eval func_$my_func '${1+"$@"}'
func_propagate_result func_$my_func func_options
if $func_propagate_result_result; then
eval set dummy "$func_options_result"; shift
_G_options_quoted=:
fi
done
$_G_options_quoted || {
# As we (func_options) are top-level options-parser function and
# nobody quoted "$@" for us yet, we need to do it explicitly for
# caller.
func_quote eval ${1+"$@"}
func_options_result=$func_quote_result
}
}
# func_options_prep [ARG]...
# --------------------------
# All initialisations required before starting the option parse loop.
# Note that when calling hook functions, we pass through the list of
# positional parameters. If a hook function modifies that list, and
# needs to propagate that back to rest of this script, then the complete
# modified list must be put in 'func_run_hooks_result' before returning.
func_hookable func_options_prep
func_options_prep ()
{
$debug_cmd
# Option defaults:
opt_verbose=false
opt_warning_types=
func_run_hooks func_options_prep ${1+"$@"}
func_propagate_result func_run_hooks func_options_prep
}
# func_parse_options [ARG]...
# ---------------------------
# The main option parsing loop.
func_hookable func_parse_options
func_parse_options ()
{
$debug_cmd
_G_parse_options_requote=false
# this just eases exit handling
while test $# -gt 0; do
# Defer to hook functions for initial option parsing, so they
# get priority in the event of reusing an option name.
func_run_hooks func_parse_options ${1+"$@"}
func_propagate_result func_run_hooks func_parse_options
if $func_propagate_result_result; then
eval set dummy "$func_parse_options_result"; shift
# Even though we may have changed "$@", we passed the "$@" array
# down into the hook and it quoted it for us (because we are in
# this if-branch). No need to quote it again.
_G_parse_options_requote=false
fi
# Break out of the loop if we already parsed every option.
test $# -gt 0 || break
# We expect that one of the options parsed in this function matches
# and thus we remove _G_opt from "$@" and need to re-quote.
_G_match_parse_options=:
_G_opt=$1
shift
case $_G_opt in
--debug|-x) debug_cmd='set -x'
func_echo "enabling shell trace mode" >&2
$debug_cmd
;;
--no-warnings|--no-warning|--no-warn)
set dummy --warnings none ${1+"$@"}
shift
;;
--warnings|--warning|-W)
if test $# = 0 && func_missing_arg $_G_opt; then
_G_parse_options_requote=:
break
fi
case " $warning_categories $1" in
*" $1 "*)
# trailing space prevents matching last $1 above
func_append_uniq opt_warning_types " $1"
;;
*all)
opt_warning_types=$warning_categories
;;
*none)
opt_warning_types=none
warning_func=:
;;
*error)
opt_warning_types=$warning_categories
warning_func=func_fatal_error
;;
*)
func_fatal_error \
"unsupported warning category: '$1'"
;;
esac
shift
;;
--verbose|-v) opt_verbose=: ;;
--version) func_version ;;
-\?|-h) func_usage ;;
--help) func_help ;;
# Separate optargs to long options (plugins may need this):
--*=*) func_split_equals "$_G_opt"
set dummy "$func_split_equals_lhs" \
"$func_split_equals_rhs" ${1+"$@"}
shift
;;
# Separate optargs to short options:
-W*)
func_split_short_opt "$_G_opt"
set dummy "$func_split_short_opt_name" \
"$func_split_short_opt_arg" ${1+"$@"}
shift
;;
# Separate non-argument short options:
-\?*|-h*|-v*|-x*)
func_split_short_opt "$_G_opt"
set dummy "$func_split_short_opt_name" \
"-$func_split_short_opt_arg" ${1+"$@"}
shift
;;
--) _G_parse_options_requote=: ; break ;;
-*) func_fatal_help "unrecognised option: '$_G_opt'" ;;
*) set dummy "$_G_opt" ${1+"$@"}; shift
_G_match_parse_options=false
break
;;
esac
if $_G_match_parse_options; then
_G_parse_options_requote=:
fi
done
if $_G_parse_options_requote; then
# save modified positional parameters for caller
func_quote eval ${1+"$@"}
func_parse_options_result=$func_quote_result
fi
}
# func_validate_options [ARG]...
# ------------------------------
# Perform any sanity checks on option settings and/or unconsumed
# arguments.
func_hookable func_validate_options
func_validate_options ()
{
$debug_cmd
# Display all warnings if -W was not given.
test -n "$opt_warning_types" || opt_warning_types=" $warning_categories"
func_run_hooks func_validate_options ${1+"$@"}
func_propagate_result func_run_hooks func_validate_options
# Bail if the options were screwed!
$exit_cmd $EXIT_FAILURE
}
## ----------------- ##
## Helper functions. ##
## ----------------- ##
# This section contains the helper functions used by the rest of the
# hookable option parser framework in ascii-betical order.
# func_fatal_help ARG...
# ----------------------
# Echo program name prefixed message to standard error, followed by
# a help hint, and exit.
func_fatal_help ()
{
$debug_cmd
eval \$ECHO \""Usage: $usage"\"
eval \$ECHO \""$fatal_help"\"
func_error ${1+"$@"}
exit $EXIT_FAILURE
}
# func_help
# ---------
# Echo long help message to standard output and exit.
func_help ()
{
$debug_cmd
func_usage_message
$ECHO "$long_help_message"
exit 0
}
# func_missing_arg ARGNAME
# ------------------------
# Echo program name prefixed message to standard error and set global
# exit_cmd.
func_missing_arg ()
{
$debug_cmd
func_error "Missing argument for '$1'."
exit_cmd=exit
}
# func_split_equals STRING
# ------------------------
# Set func_split_equals_lhs and func_split_equals_rhs shell variables
# after splitting STRING at the '=' sign.
test -z "$_G_HAVE_XSI_OPS" \
&& (eval 'x=a/b/c;
test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
&& _G_HAVE_XSI_OPS=yes
if test yes = "$_G_HAVE_XSI_OPS"
then
# This is an XSI compatible shell, allowing a faster implementation...
eval 'func_split_equals ()
{
$debug_cmd
func_split_equals_lhs=${1%%=*}
func_split_equals_rhs=${1#*=}
if test "x$func_split_equals_lhs" = "x$1"; then
func_split_equals_rhs=
fi
}'
else
# ...otherwise fall back to using expr, which is often a shell builtin.
func_split_equals ()
{
$debug_cmd
func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'`
func_split_equals_rhs=
test "x$func_split_equals_lhs=" = "x$1" \
|| func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'`
}
fi #func_split_equals
# func_split_short_opt SHORTOPT
# -----------------------------
# Set func_split_short_opt_name and func_split_short_opt_arg shell
# variables after splitting SHORTOPT after the 2nd character.
if test yes = "$_G_HAVE_XSI_OPS"
then
# This is an XSI compatible shell, allowing a faster implementation...
eval 'func_split_short_opt ()
{
$debug_cmd
func_split_short_opt_arg=${1#??}
func_split_short_opt_name=${1%"$func_split_short_opt_arg"}
}'
else
# ...otherwise fall back to using expr, which is often a shell builtin.
func_split_short_opt ()
{
$debug_cmd
func_split_short_opt_name=`expr "x$1" : 'x\(-.\)'`
func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'`
}
fi #func_split_short_opt
# func_usage
# ----------
# Echo short help message to standard output and exit.
func_usage ()
{
$debug_cmd
func_usage_message
$ECHO "Run '$progname --help |${PAGER-more}' for full usage"
exit 0
}
# func_usage_message
# ------------------
# Echo short help message to standard output.
func_usage_message ()
{
$debug_cmd
eval \$ECHO \""Usage: $usage"\"
echo
$SED -n 's|^# ||
/^Written by/{
x;p;x
}
h
/^Written by/q' < "$progpath"
echo
eval \$ECHO \""$usage_message"\"
}
# func_version
# ------------
# Echo version message to standard output and exit.
# The version message is extracted from the calling file's header
# comments, with leading '# ' stripped:
# 1. First display the progname and version
# 2. Followed by the header comment line matching /^# Written by /
# 3. Then a blank line followed by the first following line matching
# /^# Copyright /
# 4. Immediately followed by any lines between the previous matches,
# except lines preceding the intervening completely blank line.
# For example, see the header comments of this file.
func_version ()
{
$debug_cmd
printf '%s\n' "$progname $scriptversion"
$SED -n '
/^# Written by /!b
s|^# ||; p; n
:fwd2blnk
/./ {
n
b fwd2blnk
}
p; n
:holdwrnt
s|^# ||
s|^# *$||
/^Copyright /!{
/./H
n
b holdwrnt
}
s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2|
G
s|\(\n\)\n*|\1|g
p; q' < "$progpath"
exit $?
}
# Local variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC"
# time-stamp-time-zone: "UTC"
# End:
# Set a version string.
scriptversion='(GNU libtool) 2.6.0'
# func_version
# ------------
# Echo version message to standard output and exit.
func_version ()
{
$debug_cmd
year=`date +%Y`
cat <
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Originally written by Gordon Matzigkeit, 1996
(See AUTHORS for complete contributor listing)
EOF
exit $?
}
# func_echo ARG...
# ----------------
# Libtool also displays the current mode in messages, so override
# funclib.sh func_echo with this custom definition.
func_echo ()
{
$debug_cmd
_G_message=$*
func_echo_IFS=$IFS
IFS=$nl
for _G_line in $_G_message; do
IFS=$func_echo_IFS
$ECHO "$progname${opt_mode+: $opt_mode}: $_G_line"
done
IFS=$func_echo_IFS
}
## ---------------- ##
## Options parsing. ##
## ---------------- ##
# Hook in the functions to make sure our own options are parsed during
# the option parsing loop.
usage='$progpath [OPTION]... [MODE-ARG]...'
# Short help message in response to '-h'.
usage_message="Options:
--config show all configuration variables
--debug enable verbose shell tracing
-n, --dry-run display commands without modifying any files
--features display basic configuration information
--finish use operation '--mode=finish'
--mode=MODE use operation mode MODE
--no-finish don't update shared library cache
--no-quiet, --no-silent print default informational messages
--no-warnings equivalent to '-Wnone'
--preserve-dup-deps don't remove duplicate dependency libraries
--quiet, --silent don't print informational messages
--reorder-cache=DIRS reorder shared library cache for preferred DIRS
--tag=TAG use configuration variables from tag TAG
-v, --verbose print more informational messages than default
--version print version information
-W, --warnings=CATEGORY report the warnings falling in CATEGORY [all]
-h, --help, --help-all print short, long, or detailed help message
"
# Additional text appended to 'usage_message' in response to '--help'.
func_help ()
{
$debug_cmd
func_usage_message
$ECHO "$long_help_message
If a TAG is supplied, it must use one of the tag names below:
Tag Name Language Name
CC C
CXX C++
OBJC Objective-C
OBJCXX Objective-C++
GCJ Java
F77 Fortran 77
FC Fortran
GO Go
RC Windows Resource
If you do not see a tag name associated with your programming language, then
you are using a compiler that $progname does not support.
MODE must be one of the following:
clean remove files from the build directory
compile compile a source file into a libtool object
execute automatically set library path, then run a program
finish complete the installation of libtool libraries
install install libraries or executables
link create a library or an executable
uninstall remove libraries from an installed directory
MODE-ARGS vary depending on the MODE. When passed as first option,
'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that.
Try '$progname --help --mode=MODE' for a more detailed description of MODE.
When reporting a bug, please describe a test case to reproduce it and
include the following information:
host-triplet: $host
shell: $SHELL
compiler: $LTCC
compiler flags: $LTCFLAGS
linker: $LD (gnu? $with_gnu_ld)
version: $progname $scriptversion
automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q`
Report bugs to .
GNU libtool home page: .
General help using GNU software: ."
exit 0
}
# func_lo2o OBJECT-NAME
# ---------------------
# Transform OBJECT-NAME from a '.lo' suffix to the platform specific
# object suffix.
lo2o=s/\\.lo\$/.$objext/
o2lo=s/\\.$objext\$/.lo/
if test yes = "$_G_HAVE_XSI_OPS"; then
eval 'func_lo2o ()
{
case $1 in
*.lo) func_lo2o_result=${1%.lo}.$objext ;;
* ) func_lo2o_result=$1 ;;
esac
}'
# func_xform LIBOBJ-OR-SOURCE
# ---------------------------
# Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise)
# suffix to a '.lo' libtool-object suffix.
eval 'func_xform ()
{
func_xform_result=${1%.*}.lo
}'
else
# ...otherwise fall back to using sed.
func_lo2o ()
{
func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"`
}
func_xform ()
{
func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'`
}
fi
# func_fatal_configuration ARG...
# -------------------------------
# Echo program name prefixed message to standard error, followed by
# a configuration failure hint, and exit.
func_fatal_configuration ()
{
func_fatal_error ${1+"$@"} \
"See the $PACKAGE documentation for more information." \
"Fatal configuration error."
}
# func_config
# -----------
# Display the configuration for all the tags in this script.
func_config ()
{
re_begincf='^# ### BEGIN LIBTOOL'
re_endcf='^# ### END LIBTOOL'
# Default configuration.
$SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
# Now print the configurations for the tags.
for tagname in $taglist; do
$SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
done
exit $?
}
# func_features
# -------------
# Display the features supported by this script.
func_features ()
{
echo "host: $host"
if test yes = "$build_libtool_libs"; then
echo "enable shared libraries"
else
echo "disable shared libraries"
fi
if test yes = "$build_old_libs"; then
echo "enable static libraries"
else
echo "disable static libraries"
fi
exit $?
}
# func_enable_tag TAGNAME
# -----------------------
# Verify that TAGNAME is valid, and either flag an error and exit, or
# enable the TAGNAME tag. We also add TAGNAME to the global $taglist
# variable here.
func_enable_tag ()
{
# Global variable:
tagname=$1
re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
sed_extractcf=/$re_begincf/,/$re_endcf/p
# Validate tagname.
case $tagname in
*[!-_A-Za-z0-9,/]*)
func_fatal_error "invalid tag name: $tagname"
;;
esac
# Don't test for the "default" C tag, as we know it's
# there but not specially marked.
case $tagname in
CC) ;;
*)
if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
taglist="$taglist $tagname"
# Evaluate the configuration. Be careful to quote the path
# and the sed script, to avoid splitting on whitespace, but
# also don't use non-portable quotes within backquotes within
# quotes we have to do it in 2 steps:
extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
eval "$extractedcf"
else
func_error "ignoring unknown tag $tagname"
fi
;;
esac
}
# func_check_version_match
# ------------------------
# Ensure that we are using m4 macros, and libtool script from the same
# release of libtool.
func_check_version_match ()
{
if test "$package_revision" != "$macro_revision"; then
if test "$VERSION" != "$macro_version"; then
if test -z "$macro_version"; then
cat >&2 <<_LT_EOF
$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
$progname: definition of this LT_INIT comes from an older release.
$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
$progname: and run autoconf again.
_LT_EOF
else
cat >&2 <<_LT_EOF
$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
$progname: and run autoconf again.
_LT_EOF
fi
else
cat >&2 <<_LT_EOF
$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision,
$progname: but the definition of this LT_INIT comes from revision $macro_revision.
$progname: You should recreate aclocal.m4 with macros from revision $package_revision
$progname: of $PACKAGE $VERSION and run autoconf again.
_LT_EOF
fi
exit $EXIT_MISMATCH
fi
}
# libtool_options_prep [ARG]...
# -----------------------------
# Preparation for options parsed by libtool.
libtool_options_prep ()
{
$debug_mode
# Option defaults:
opt_config=false
opt_dlopen=
opt_dry_run=false
opt_help=false
opt_mode=
opt_reorder_cache=false
opt_preserve_dup_deps=false
opt_quiet=false
opt_finishing=true
opt_warning=
nonopt=
preserve_args=
_G_rc_lt_options_prep=:
# Shorthand for --mode=foo, only valid as the first argument
case $1 in
clean|clea|cle|cl)
shift; set dummy --mode clean ${1+"$@"}; shift
;;
compile|compil|compi|comp|com|co|c)
shift; set dummy --mode compile ${1+"$@"}; shift
;;
execute|execut|execu|exec|exe|ex|e)
shift; set dummy --mode execute ${1+"$@"}; shift
;;
finish|finis|fini|fin|fi|f)
shift; set dummy --mode finish ${1+"$@"}; shift
;;
install|instal|insta|inst|ins|in|i)
shift; set dummy --mode install ${1+"$@"}; shift
;;
link|lin|li|l)
shift; set dummy --mode link ${1+"$@"}; shift
;;
uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
shift; set dummy --mode uninstall ${1+"$@"}; shift
;;
*)
_G_rc_lt_options_prep=false
;;
esac
if $_G_rc_lt_options_prep; then
# Pass back the list of options.
func_quote eval ${1+"$@"}
libtool_options_prep_result=$func_quote_result
fi
}
func_add_hook func_options_prep libtool_options_prep
# libtool_parse_options [ARG]...
# ---------------------------------
# Provide handling for libtool specific options.
libtool_parse_options ()
{
$debug_cmd
_G_rc_lt_parse_options=false
# Perform our own loop to consume as many options as possible in
# each iteration.
while test $# -gt 0; do
_G_match_lt_parse_options=:
_G_opt=$1
shift
case $_G_opt in
--dry-run|--dryrun|-n)
opt_dry_run=:
;;
--config) func_config ;;
--dlopen|-dlopen)
opt_dlopen="${opt_dlopen+$opt_dlopen
}$1"
shift
;;
--preserve-dup-deps)
opt_preserve_dup_deps=: ;;
--features) func_features ;;
--finish) set dummy --mode finish ${1+"$@"}; shift ;;
--help) opt_help=: ;;
--help-all) opt_help=': help-all' ;;
--mode) test $# = 0 && func_missing_arg $_G_opt && break
opt_mode=$1
case $1 in
# Valid mode arguments:
clean|compile|execute|finish|install|link|relink|uninstall) ;;
# Catch anything else as an error
*) func_error "invalid argument '$1' for $_G_opt"
exit_cmd=exit
;;
esac
shift
;;
--no-finish)
opt_finishing=false
func_append preserve_args " $_G_opt"
;;
--no-silent|--no-quiet)
opt_quiet=false
func_append preserve_args " $_G_opt"
;;
--no-warnings|--no-warning|--no-warn)
opt_warning=false
func_append preserve_args " $_G_opt"
;;
--no-verbose)
opt_verbose=false
func_append preserve_args " $_G_opt"
;;
--reorder-cache)
opt_reorder_cache=true
shared_lib_dirs=$1
if test -n "$shared_lib_dirs"; then
case $1 in
# Must begin with /:
/*) ;;
# Catch anything else as an error (relative paths)
*) func_error "invalid argument '$1' for $_G_opt"
func_error "absolute paths are required for $_G_opt"
exit_cmd=exit
;;
esac
fi
shift
;;
--silent|--quiet)
opt_quiet=:
opt_verbose=false
func_append preserve_args " $_G_opt"
;;
--tag) test $# = 0 && func_missing_arg $_G_opt && break
opt_tag=$1
func_append preserve_args " $_G_opt $1"
func_enable_tag "$1"
shift
;;
--verbose|-v) opt_quiet=false
opt_verbose=:
func_append preserve_args " $_G_opt"
;;
# An option not handled by this hook function:
*) set dummy "$_G_opt" ${1+"$@"} ; shift
_G_match_lt_parse_options=false
break
;;
esac
$_G_match_lt_parse_options && _G_rc_lt_parse_options=:
done
if $_G_rc_lt_parse_options; then
# save modified positional parameters for caller
func_quote eval ${1+"$@"}
libtool_parse_options_result=$func_quote_result
fi
}
func_add_hook func_parse_options libtool_parse_options
# func_warning ARG...
# -------------------
# Libtool warnings are not categorized, so override funclib.sh
# func_warning with this simpler definition.
func_warning ()
{
if $opt_warning; then
$debug_cmd
$warning_func ${1+"$@"}
fi
}
# libtool_validate_options [ARG]...
# ---------------------------------
# Perform any sanity checks on option settings and/or unconsumed
# arguments.
libtool_validate_options ()
{
# save first non-option argument
if test 0 -lt $#; then
nonopt=$1
shift
fi
# preserve --debug
test : = "$debug_cmd" || func_append preserve_args " --debug"
case $host_os in
# Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452
# see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788
cygwin* | mingw* | windows* | pw32* | cegcc* | solaris2* | os2* | *linux*)
# don't eliminate duplications in $postdeps and $predeps
opt_duplicate_compiler_generated_deps=:
;;
*)
opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
;;
esac
$opt_help || {
# Sanity checks first:
func_check_version_match
test yes != "$build_libtool_libs" \
&& test yes != "$build_old_libs" \
&& func_fatal_configuration "not configured to build any kind of library"
# Darwin sucks
eval std_shrext=\"$shrext_cmds\"
# Only execute mode is allowed to have -dlopen flags.
if test -n "$opt_dlopen" && test execute != "$opt_mode"; then
func_error "unrecognized option '-dlopen'"
$ECHO "$help" 1>&2
exit $EXIT_FAILURE
fi
# Change the help message to a mode-specific one.
generic_help=$help
help="Try '$progname --help --mode=$opt_mode' for more information."
}
# Pass back the unparsed argument list
func_quote eval ${1+"$@"}
libtool_validate_options_result=$func_quote_result
}
func_add_hook func_validate_options libtool_validate_options
# Process options as early as possible so that --help and --version
# can return quickly.
func_options ${1+"$@"}
eval set dummy "$func_options_result"; shift
## ----------- ##
## Main. ##
## ----------- ##
magic='%%%MAGIC variable%%%'
magic_exe='%%%MAGIC EXE variable%%%'
# Global variables.
extracted_archives=
extracted_serial=0
# If this variable is set in any of the actions, the command in it
# will be execed at the end. This prevents here-documents from being
# left over by shells.
exec_cmd=
# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
$1
_LTECHO_EOF'
}
# func_generated_by_libtool
# True iff stdin has been generated by Libtool. This function is only
# a basic sanity check; it will hardly flush out determined imposters.
func_generated_by_libtool_p ()
{
$GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
}
# func_lalib_p file
# True iff FILE is a libtool '.la' library or '.lo' object file.
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_lalib_p ()
{
test -f "$1" &&
$SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p
}
# func_lalib_unsafe_p file
# True iff FILE is a libtool '.la' library or '.lo' object file.
# This function implements the same check as func_lalib_p without
# resorting to external programs. To this end, it redirects stdin and
# closes it afterwards, without saving the original file descriptor.
# As a safety measure, use it only where a negative result would be
# fatal anyway. Works if 'file' does not exist.
func_lalib_unsafe_p ()
{
lalib_p=no
if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
for lalib_p_l in 1 2 3 4
do
read lalib_p_line
case $lalib_p_line in
\#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
esac
done
exec 0<&5 5<&-
fi
test yes = "$lalib_p"
}
# func_ltwrapper_script_p file
# True iff FILE is a libtool wrapper script
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_script_p ()
{
test -f "$1" &&
$lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p
}
# func_ltwrapper_executable_p file
# True iff FILE is a libtool wrapper executable
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_executable_p ()
{
func_ltwrapper_exec_suffix=
case $1 in
*.exe) ;;
*) func_ltwrapper_exec_suffix=.exe ;;
esac
$GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
}
# func_ltwrapper_scriptname file
# Assumes file is an ltwrapper_executable
# uses $file to determine the appropriate filename for a
# temporary ltwrapper_script.
func_ltwrapper_scriptname ()
{
func_dirname_and_basename "$1" "" "."
func_stripname '' '.exe' "$func_basename_result"
func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper
}
# func_ltwrapper_p file
# True iff FILE is a libtool wrapper script or wrapper executable
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_p ()
{
func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
}
# func_execute_cmds commands fail_cmd
# Execute tilde-delimited COMMANDS.
# If FAIL_CMD is given, eval that upon failure.
# FAIL_CMD may read-access the current command in variable CMD!
func_execute_cmds ()
{
$debug_cmd
save_ifs=$IFS; IFS='~'
for cmd in $1; do
IFS=$sp$nl
eval cmd=\"$cmd\"
IFS=$save_ifs
func_show_eval "$cmd" "${2-:}"
done
IFS=$save_ifs
}
# func_source file
# Source FILE, adding directory component if necessary.
# Note that it is not necessary on cygwin/mingw to append a dot to
# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
# behavior happens only for exec(3), not for open(2)! Also, sourcing
# 'FILE.' does not work on cygwin managed mounts.
func_source ()
{
$debug_cmd
case $1 in
*/* | *\\*) . "$1" ;;
*) . "./$1" ;;
esac
}
# func_resolve_sysroot PATH
# Replace a leading = in PATH with a sysroot. Store the result into
# func_resolve_sysroot_result
func_resolve_sysroot ()
{
func_resolve_sysroot_result=$1
case $func_resolve_sysroot_result in
=*)
func_stripname '=' '' "$func_resolve_sysroot_result"
func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
;;
esac
}
# func_replace_sysroot PATH
# If PATH begins with the sysroot, replace it with = and
# store the result into func_replace_sysroot_result.
func_replace_sysroot ()
{
case $lt_sysroot:$1 in
?*:"$lt_sysroot"*)
func_stripname "$lt_sysroot" '' "$1"
func_replace_sysroot_result='='$func_stripname_result
;;
*)
# Including no sysroot.
func_replace_sysroot_result=$1
;;
esac
}
# func_infer_tag arg
# Infer tagged configuration to use if any are available and
# if one wasn't chosen via the "--tag" command line option.
# Only attempt this if the compiler in the base compile
# command doesn't match the default compiler.
# arg is usually of the form 'gcc ...'
func_infer_tag ()
{
$debug_cmd
if test -n "$available_tags" && test -z "$tagname"; then
CC_quoted=
for arg in $CC; do
func_append_quoted CC_quoted "$arg"
done
CC_expanded=`func_echo_all $CC`
CC_quoted_expanded=`func_echo_all $CC_quoted`
case $@ in
# Blanks in the command may have been stripped by the calling shell,
# but not from the CC environment variable when configure was run.
" $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
" $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
# Blanks at the start of $base_compile will cause this to fail
# if we don't check for them as well.
*)
for z in $available_tags; do
if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
# Evaluate the configuration.
eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
CC_quoted=
for arg in $CC; do
# Double-quote args containing other shell metacharacters.
func_append_quoted CC_quoted "$arg"
done
CC_expanded=`func_echo_all $CC`
CC_quoted_expanded=`func_echo_all $CC_quoted`
case "$@ " in
" $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
" $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
# The compiler in the base compile command matches
# the one in the tagged configuration.
# Assume this is the tagged configuration we want.
tagname=$z
break
;;
esac
fi
done
# If $tagname still isn't set, then no tagged configuration
# was found and let the user know that the "--tag" command
# line option must be used.
if test -z "$tagname"; then
func_echo "unable to infer tagged configuration with compiler."
func_echo "Possible use of unsupported compiler."
func_fatal_error "specify a tag with '--tag'. For more information, try '$progname --help'."
# else
# func_verbose "using $tagname tagged configuration"
fi
;;
esac
fi
}
# func_write_libtool_object output_name pic_name nonpic_name
# Create a libtool object file (analogous to a ".la" file),
# but don't create it if we're doing a dry run.
func_write_libtool_object ()
{
write_libobj=$1
if test yes = "$build_libtool_libs"; then
write_lobj=\'$2\'
else
write_lobj=none
fi
if test yes = "$build_old_libs"; then
write_oldobj=\'$3\'
else
write_oldobj=none
fi
$opt_dry_run || {
cat >${write_libobj}T </dev/null`
if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then
func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
$SED -e "$sed_naive_backslashify"`
else
func_convert_core_file_wine_to_w32_result=
fi
fi
}
# end: func_convert_core_file_wine_to_w32
# func_convert_core_path_wine_to_w32 ARG
# Helper function used by path conversion functions when $build is *nix, and
# $host is mingw, windows, cygwin, or some other w32 environment. Relies on a
# correctly configured wine environment available, with the winepath program
# in $build's $PATH. Assumes ARG has no leading or trailing path separator
# characters.
#
# ARG is path to be converted from $build format to win32.
# Result is available in $func_convert_core_path_wine_to_w32_result.
# Unconvertible file (directory) names in ARG are skipped; if no directory names
# are convertible, then the result may be empty.
func_convert_core_path_wine_to_w32 ()
{
$debug_cmd
# unfortunately, winepath doesn't convert paths, only file names
func_convert_core_path_wine_to_w32_result=
if test -n "$1"; then
oldIFS=$IFS
IFS=:
for func_convert_core_path_wine_to_w32_f in $1; do
IFS=$oldIFS
func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
if test -n "$func_convert_core_file_wine_to_w32_result"; then
if test -z "$func_convert_core_path_wine_to_w32_result"; then
func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result
else
func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
fi
fi
done
IFS=$oldIFS
fi
}
# end: func_convert_core_path_wine_to_w32
# func_cygpath ARGS...
# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
# (2), returns the Cygwin file name or path in func_cygpath_result (input
# file name or path is assumed to be in w32 format, as previously converted
# from $build's *nix or MSYS format). In case (3), returns the w32 file name
# or path in func_cygpath_result (input file name or path is assumed to be in
# Cygwin format). Returns an empty string on error.
#
# ARGS are passed to cygpath, with the last one being the file name or path to
# be converted.
#
# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
# environment variable; do not put it in $PATH.
func_cygpath ()
{
$debug_cmd
if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
if test "$?" -ne 0; then
# on failure, ensure result is empty
func_cygpath_result=
fi
else
func_cygpath_result=
func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'"
fi
}
#end: func_cygpath
# func_convert_core_msys_to_w32 ARG
# Convert file name or path ARG from MSYS format to w32 format. Return
# result in func_convert_core_msys_to_w32_result.
func_convert_core_msys_to_w32 ()
{
$debug_cmd
# Compatibility for original MSYS
if test "Xone" = "X$lt_cv_cmd_slashes"; then
func_convert_core_msys_to_w32_result=`( cmd /c echo "$1" ) 2>/dev/null |
$SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"`
else # Assume 'lt_cv_cmd_slashes = "two"'
func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
$SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"`
fi
if test "$?" -ne 0; then
# on failure, ensure result is empty
func_convert_core_msys_to_w32_result=
fi
}
#end: func_convert_core_msys_to_w32
# func_convert_core_msys_to_w32_with_cygpath ARG
# Convert file name or path ARG with cygpath from MSYS format to w32
# format. Return result in func_convert_core_msys_to_w32_with_cygpath_result.
func_convert_core_msys_to_w32_with_cygpath ()
{
$debug_cmd
# Since MSYS2 is packaged with cygpath, call cygpath in $PATH; no need
# to use LT_CYGPATH in this case.
func_convert_core_msys_to_w32_result=`cygpath "$@" 2>/dev/null |
$SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"`
if test "$?" -ne 0; then
# on failure, ensure result is empty
func_convert_core_msys_to_w32_result=
fi
}
#end: func_convert_core_msys_to_w32_with_cygpath
# func_convert_file_check ARG1 ARG2
# Verify that ARG1 (a file name in $build format) was converted to $host
# format in ARG2. Otherwise, emit an error message, but continue (resetting
# func_to_host_file_result to ARG1).
func_convert_file_check ()
{
$debug_cmd
if test -z "$2" && test -n "$1"; then
func_error "Could not determine host file name corresponding to"
func_error " '$1'"
func_error "Continuing, but uninstalled executables may not work."
# Fallback:
func_to_host_file_result=$1
fi
}
# end func_convert_file_check
# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
# Verify that FROM_PATH (a path in $build format) was converted to $host
# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
# func_to_host_file_result to a simplistic fallback value (see below).
func_convert_path_check ()
{
$debug_cmd
if test -z "$4" && test -n "$3"; then
func_error "Could not determine the host path corresponding to"
func_error " '$3'"
func_error "Continuing, but uninstalled executables may not work."
# Fallback. This is a deliberately simplistic "conversion" and
# should not be "improved". See libtool.info.
if test "x$1" != "x$2"; then
lt_replace_pathsep_chars="s|$1|$2|g"
func_to_host_path_result=`echo "$3" |
$SED -e "$lt_replace_pathsep_chars"`
else
func_to_host_path_result=$3
fi
fi
}
# end func_convert_path_check
# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
# and appending REPL if ORIG matches BACKPAT.
func_convert_path_front_back_pathsep ()
{
$debug_cmd
case $4 in
$1 ) func_to_host_path_result=$3$func_to_host_path_result
;;
esac
case $4 in
$2 ) func_append func_to_host_path_result "$3"
;;
esac
}
# end func_convert_path_front_back_pathsep
# func_convert_delimited_path PATH ORIG_DELIMITER NEW_DELIMITER
# Replaces a delimiter for a given path.
func_convert_delimited_path ()
{
converted_path=`$ECHO "$1" | $SED "s#$2#$3#g"`
}
# end func_convert_delimited_path
##################################################
# $build to $host FILE NAME CONVERSION FUNCTIONS #
##################################################
# invoked via '$to_host_file_cmd ARG'
#
# In each case, ARG is the path to be converted from $build to $host format.
# Result will be available in $func_to_host_file_result.
# func_to_host_file ARG
# Converts the file name ARG from $build format to $host format. Return result
# in func_to_host_file_result.
func_to_host_file ()
{
$debug_cmd
$to_host_file_cmd "$1"
}
# end func_to_host_file
# func_to_tool_file ARG LAZY
# converts the file name ARG from $build format to toolchain format. Return
# result in func_to_tool_file_result. If the conversion in use is listed
# in (the comma separated) LAZY, no conversion takes place.
func_to_tool_file ()
{
$debug_cmd
case ,$2, in
*,"$to_tool_file_cmd",*)
func_to_tool_file_result=$1
;;
*)
$to_tool_file_cmd "$1"
func_to_tool_file_result=$func_to_host_file_result
;;
esac
}
# end func_to_tool_file
# func_convert_file_noop ARG
# Copy ARG to func_to_host_file_result.
func_convert_file_noop ()
{
func_to_host_file_result=$1
}
# end func_convert_file_noop
# func_convert_file_msys_to_w32 ARG
# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
# conversion to w32 is not available inside the cwrapper. Returns result in
# func_to_host_file_result.
func_convert_file_msys_to_w32 ()
{
$debug_cmd
func_to_host_file_result=$1
if test -n "$1"; then
if test "Xyes" = "X$cygpath_installed"; then
func_convert_core_msys_to_w32_with_cygpath -w "$1"
func_to_host_file_result=$func_convert_core_msys_to_w32_with_cygpath_result
else
func_convert_core_msys_to_w32 "$1"
func_to_host_file_result=$func_convert_core_msys_to_w32_result
fi
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_msys_to_w32
# func_convert_file_cygwin_to_w32 ARG
# Convert file name ARG from Cygwin to w32 format. Returns result in
# func_to_host_file_result.
func_convert_file_cygwin_to_w32 ()
{
$debug_cmd
func_to_host_file_result=$1
if test -n "$1"; then
# because $build is cygwin, we call "the" cygpath in $PATH; no need to use
# LT_CYGPATH in this case.
func_to_host_file_result=`cygpath -m "$1"`
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_cygwin_to_w32
# func_convert_file_nix_to_w32 ARG
# Convert file name ARG from *nix to w32 format. Requires a wine environment
# and a working winepath. Returns result in func_to_host_file_result.
func_convert_file_nix_to_w32 ()
{
$debug_cmd
func_to_host_file_result=$1
if test -n "$1"; then
func_convert_core_file_wine_to_w32 "$1"
func_to_host_file_result=$func_convert_core_file_wine_to_w32_result
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_nix_to_w32
# func_convert_file_msys_to_cygwin ARG
# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
# Returns result in func_to_host_file_result.
func_convert_file_msys_to_cygwin ()
{
$debug_cmd
func_to_host_file_result=$1
if test -n "$1"; then
if test "Xyes" = "X$cygpath_installed"; then
func_convert_core_msys_to_w32_with_cygpath -w "$1"
func_cygpath -u "$func_convert_core_msys_to_w32_with_cygpath_result"
else
func_convert_core_msys_to_w32 "$1"
func_cygpath -u "$func_convert_core_msys_to_w32_result"
fi
func_to_host_file_result=$func_cygpath_result
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_msys_to_cygwin
# func_convert_file_nix_to_cygwin ARG
# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed
# in a wine environment, working winepath, and LT_CYGPATH set. Returns result
# in func_to_host_file_result.
func_convert_file_nix_to_cygwin ()
{
$debug_cmd
func_to_host_file_result=$1
if test -n "$1"; then
# convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
func_convert_core_file_wine_to_w32 "$1"
func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
func_to_host_file_result=$func_cygpath_result
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_nix_to_cygwin
#############################################
# $build to $host PATH CONVERSION FUNCTIONS #
#############################################
# invoked via '$to_host_path_cmd ARG'
#
# In each case, ARG is the path to be converted from $build to $host format.
# The result will be available in $func_to_host_path_result.
#
# Path separators are also converted from $build format to $host format. If
# ARG begins or ends with a path separator character, it is preserved (but
# converted to $host format) on output.
#
# All path conversion functions are named using the following convention:
# file name conversion function : func_convert_file_X_to_Y ()
# path conversion function : func_convert_path_X_to_Y ()
# where, for any given $build/$host combination the 'X_to_Y' value is the
# same. If conversion functions are added for new $build/$host combinations,
# the two new functions must follow this pattern, or func_init_to_host_path_cmd
# will break.
# func_init_to_host_path_cmd
# Ensures that function "pointer" variable $to_host_path_cmd is set to the
# appropriate value, based on the value of $to_host_file_cmd.
to_host_path_cmd=
func_init_to_host_path_cmd ()
{
$debug_cmd
if test -z "$to_host_path_cmd"; then
func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
to_host_path_cmd=func_convert_path_$func_stripname_result
fi
}
# func_to_host_path ARG
# Converts the path ARG from $build format to $host format. Return result
# in func_to_host_path_result.
func_to_host_path ()
{
$debug_cmd
func_init_to_host_path_cmd
$to_host_path_cmd "$1"
}
# end func_to_host_path
# func_convert_path_noop ARG
# Copy ARG to func_to_host_path_result.
func_convert_path_noop ()
{
func_to_host_path_result=$1
}
# end func_convert_path_noop
# func_convert_path_msys_to_w32 ARG
# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
# conversion to w32 is not available inside the cwrapper. Returns result in
# func_to_host_path_result.
func_convert_path_msys_to_w32 ()
{
$debug_cmd
func_to_host_path_result=$1
if test -n "$1"; then
# Remove leading and trailing path separator characters from ARG. MSYS
# behavior is inconsistent here; cygpath turns them into '.;' and ';.';
# and winepath ignores them completely.
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
if test "Xyes" = "X$cygpath_installed"; then
func_convert_core_msys_to_w32_with_cygpath -w -p "$func_to_host_path_tmp1"
func_to_host_path_result=$func_convert_core_msys_to_w32_with_cygpath_result
else
func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
func_to_host_path_result=$func_convert_core_msys_to_w32_result
fi
func_convert_path_check : ";" \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
fi
}
# end func_convert_path_msys_to_w32
# func_convert_path_cygwin_to_w32 ARG
# Convert path ARG from Cygwin to w32 format. Returns result in
# func_to_host_file_result.
func_convert_path_cygwin_to_w32 ()
{
$debug_cmd
func_to_host_path_result=$1
if test -n "$1"; then
# See func_convert_path_msys_to_w32:
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
func_convert_path_check : ";" \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
fi
}
# end func_convert_path_cygwin_to_w32
# func_convert_path_nix_to_w32 ARG
# Convert path ARG from *nix to w32 format. Requires a wine environment and
# a working winepath. Returns result in func_to_host_file_result.
func_convert_path_nix_to_w32 ()
{
$debug_cmd
func_to_host_path_result=$1
if test -n "$1"; then
# See func_convert_path_msys_to_w32:
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
func_to_host_path_result=$func_convert_core_path_wine_to_w32_result
func_convert_path_check : ";" \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
fi
}
# end func_convert_path_nix_to_w32
# func_convert_path_msys_to_cygwin ARG
# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
# Returns result in func_to_host_file_result.
func_convert_path_msys_to_cygwin ()
{
$debug_cmd
func_to_host_path_result=$1
if test -n "$1"; then
# See func_convert_path_msys_to_w32:
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
if test "Xyes" = "X$cygpath_installed"; then
func_convert_core_msys_to_w32_with_cygpath -w -p "$func_to_host_path_tmp1"
func_cygpath -u -p "$func_convert_core_msys_to_w32_with_cygpath_result"
else
func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
fi
func_to_host_path_result=$func_cygpath_result
func_convert_path_check : : \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" : "$1"
fi
}
# end func_convert_path_msys_to_cygwin
# func_convert_path_nix_to_cygwin ARG
# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a
# a wine environment, working winepath, and LT_CYGPATH set. Returns result in
# func_to_host_file_result.
func_convert_path_nix_to_cygwin ()
{
$debug_cmd
func_to_host_path_result=$1
if test -n "$1"; then
# Remove leading and trailing path separator characters from
# ARG. msys behavior is inconsistent here, cygpath turns them
# into '.;' and ';.', and winepath ignores them completely.
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
func_to_host_path_result=$func_cygpath_result
func_convert_path_check : : \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" : "$1"
fi
}
# end func_convert_path_nix_to_cygwin
# func_dll_def_p FILE
# True iff FILE is a Windows DLL '.def' file.
# Keep in sync with _LT_DLL_DEF_P in libtool.m4
func_dll_def_p ()
{
$debug_cmd
func_dll_def_p_tmp=`$SED -n \
-e 's/^[ ]*//' \
-e '/^\(;.*\)*$/d' \
-e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \
-e q \
"$1"`
test DEF = "$func_dll_def_p_tmp"
}
# func_reorder_shared_lib_cache DIRS
# Reorder the shared library cache by unconfiguring previous shared library cache
# and configuring preferred search directories before previous search directories.
# Previous shared library cache: /usr/lib /usr/local/lib
# Preferred search directories: /tmp/testing
# Reordered shared library cache: /tmp/testing /usr/lib /usr/local/lib
func_reorder_shared_lib_cache ()
{
$debug_cmd
case $host_os in
openbsd*)
get_search_directories=`PATH="$PATH:/sbin" ldconfig -r | $GREP "search directories" | $SED "s#.*search directories:\ ##g"`
func_convert_delimited_path "$get_search_directories" ':' '\ '
save_search_directories=$converted_path
func_convert_delimited_path "$1" ':' '\ '
# Ensure directories exist
for dir in $converted_path; do
# Ensure each directory is an absolute path
case $dir in
/*) ;;
*) func_error "Directory '$dir' is not an absolute path"
exit $EXIT_FAILURE ;;
esac
# Ensure no trailing slashes
func_stripname '' '/' "$dir"
dir=$func_stripname_result
if test -d "$dir"; then
if test -n "$preferred_search_directories"; then
preferred_search_directories="$preferred_search_directories $dir"
else
preferred_search_directories=$dir
fi
else
func_error "Directory '$dir' does not exist"
exit $EXIT_FAILURE
fi
done
PATH="$PATH:/sbin" ldconfig -U $save_search_directories
PATH="$PATH:/sbin" ldconfig -m $preferred_search_directories $save_search_directories
get_search_directories=`PATH="$PATH:/sbin" ldconfig -r | $GREP "search directories" | $SED "s#.*search directories:\ ##g"`
func_convert_delimited_path "$get_search_directories" ':' '\ '
reordered_search_directories=$converted_path
$ECHO "Original: $save_search_directories"
$ECHO "Reordered: $reordered_search_directories"
exit $EXIT_SUCCESS
;;
*)
func_error "--reorder-cache is not supported for host_os=$host_os."
exit $EXIT_FAILURE
;;
esac
}
# end func_reorder_shared_lib_cache
# func_mode_compile arg...
func_mode_compile ()
{
$debug_cmd
# Get the compilation command and the source file.
base_compile=
srcfile=$nonopt # always keep a non-empty value in "srcfile"
suppress_opt=yes
suppress_output=
arg_mode=normal
libobj=
later=
pie_flag=
for arg
do
case $arg_mode in
arg )
# do not "continue". Instead, add this to base_compile
lastarg=$arg
arg_mode=normal
;;
target )
libobj=$arg
arg_mode=normal
continue
;;
normal )
# Accept any command-line options.
case $arg in
-o)
test -n "$libobj" && \
func_fatal_error "you cannot specify '-o' more than once"
arg_mode=target
continue
;;
-pie | -fpie | -fPIE)
func_append pie_flag " $arg"
continue
;;
-shared | -static | -prefer-pic | -prefer-non-pic)
func_append later " $arg"
continue
;;
-no-suppress)
suppress_opt=no
continue
;;
-Xcompiler)
arg_mode=arg # the next one goes into the "base_compile" arg list
continue # The current "srcfile" will either be retained or
;; # replaced later. I would guess that would be a bug.
-Wc,*)
func_stripname '-Wc,' '' "$arg"
args=$func_stripname_result
lastarg=
save_ifs=$IFS; IFS=,
for arg in $args; do
IFS=$save_ifs
func_append_quoted lastarg "$arg"
done
IFS=$save_ifs
func_stripname ' ' '' "$lastarg"
lastarg=$func_stripname_result
# Add the arguments to base_compile.
func_append base_compile " $lastarg"
continue
;;
*)
# Accept the current argument as the source file.
# The previous "srcfile" becomes the current argument.
#
lastarg=$srcfile
srcfile=$arg
;;
esac # case $arg
;;
esac # case $arg_mode
# Aesthetically quote the previous argument.
func_append_quoted base_compile "$lastarg"
done # for arg
case $arg_mode in
arg)
func_fatal_error "you must specify an argument for -Xcompile"
;;
target)
func_fatal_error "you must specify a target with '-o'"
;;
*)
# Get the name of the library object.
test -z "$libobj" && {
func_basename "$srcfile"
libobj=$func_basename_result
}
;;
esac
# Recognize several different file suffixes.
# If the user specifies -o file.o, it is replaced with file.lo
case $libobj in
*.[cCFSifmso] | \
*.ada | *.adb | *.ads | *.asm | \
*.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
*.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
func_xform "$libobj"
libobj=$func_xform_result
;;
esac
case $libobj in
*.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
*)
func_fatal_error "cannot determine name of library object from '$libobj'"
;;
esac
func_infer_tag $base_compile
for arg in $later; do
case $arg in
-shared)
test yes = "$build_libtool_libs" \
|| func_fatal_configuration "cannot build a shared library"
build_old_libs=no
continue
;;
-static)
build_libtool_libs=no
build_old_libs=yes
continue
;;
-prefer-pic)
pic_mode=yes
continue
;;
-prefer-non-pic)
pic_mode=no
continue
;;
esac
done
func_quote_arg pretty "$libobj"
test "X$libobj" != "X$func_quote_arg_result" \
&& $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \
&& func_warning "libobj name '$libobj' may not contain shell special characters."
func_dirname_and_basename "$obj" "/" ""
objname=$func_basename_result
xdir=$func_dirname_result
lobj=$xdir$objdir/$objname
test -z "$base_compile" && \
func_fatal_help "you must specify a compilation command"
# Delete any leftover library objects.
if test yes = "$build_old_libs"; then
removelist="$obj $lobj $libobj ${libobj}T"
else
removelist="$lobj $libobj ${libobj}T"
fi
# On Cygwin there's no "real" PIC flag so we must build both object types
case $host_os in
cygwin* | mingw* | windows* | pw32* | os2* | cegcc*)
pic_mode=default
;;
esac
if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then
# non-PIC code in shared libraries is not supported
pic_mode=default
fi
# Calculate the filename of the output object if compiler does
# not support -o with -c
if test no = "$compiler_c_o"; then
output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext
lockfile=$output_obj.lock
else
output_obj=
need_locks=no
lockfile=
fi
# Lock this critical section if it is needed
# We use this script file to make the link, it avoids creating a new file
if test yes = "$need_locks"; then
until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
func_echo "Waiting for $lockfile to be removed"
sleep 2
done
elif test warn = "$need_locks"; then
if test -f "$lockfile"; then
$ECHO "\
*** ERROR, $lockfile exists and contains:
`cat $lockfile 2>/dev/null`
This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support '-c' and '-o' together. If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."
$opt_dry_run || $RM $removelist
exit $EXIT_FAILURE
fi
func_append removelist " $output_obj"
$ECHO "$srcfile" > "$lockfile"
fi
$opt_dry_run || $RM $removelist
func_append removelist " $lockfile"
trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
srcfile=$func_to_tool_file_result
func_quote_arg pretty "$srcfile"
qsrcfile=$func_quote_arg_result
# Only build a PIC object if we are building libtool libraries.
if test yes = "$build_libtool_libs"; then
# Without this assignment, base_compile gets emptied.
fbsd_hideous_sh_bug=$base_compile
if test no != "$pic_mode"; then
command="$base_compile $qsrcfile $pic_flag"
else
# Don't build PIC code
command="$base_compile $qsrcfile"
fi
func_mkdir_p "$xdir$objdir"
if test -z "$output_obj"; then
# Place PIC objects in $objdir
func_append command " -o $lobj"
fi
func_show_eval_locale "$command" \
'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
if test warn = "$need_locks" &&
test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
$ECHO "\
*** ERROR, $lockfile contains:
`cat $lockfile 2>/dev/null`
but it should contain:
$srcfile
This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support '-c' and '-o' together. If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."
$opt_dry_run || $RM $removelist
exit $EXIT_FAILURE
fi
# Just move the object if needed, then go on to compile the next one
if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
func_show_eval '$MV "$output_obj" "$lobj"' \
'error=$?; $opt_dry_run || $RM $removelist; exit $error'
fi
# Allow error messages only from the first compilation.
if test yes = "$suppress_opt"; then
suppress_output=' >/dev/null 2>&1'
fi
fi
# Only build a position-dependent object if we build old libraries.
if test yes = "$build_old_libs"; then
if test yes != "$pic_mode"; then
# Don't build PIC code
command="$base_compile $qsrcfile$pie_flag"
else
command="$base_compile $qsrcfile $pic_flag"
fi
if test yes = "$compiler_c_o"; then
func_append command " -o $obj"
fi
# Suppress compiler output if we already did a PIC compilation.
func_append command "$suppress_output"
func_show_eval_locale "$command" \
'$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
if test warn = "$need_locks" &&
test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
$ECHO "\
*** ERROR, $lockfile contains:
`cat $lockfile 2>/dev/null`
but it should contain:
$srcfile
This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support '-c' and '-o' together. If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."
$opt_dry_run || $RM $removelist
exit $EXIT_FAILURE
fi
# Just move the object if needed
if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
func_show_eval '$MV "$output_obj" "$obj"' \
'error=$?; $opt_dry_run || $RM $removelist; exit $error'
fi
fi
$opt_dry_run || {
func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
# Unlock the critical section if it was locked
if test no != "$need_locks"; then
removelist=$lockfile
$RM "$lockfile"
fi
}
exit $EXIT_SUCCESS
}
$opt_help || {
test compile = "$opt_mode" && func_mode_compile ${1+"$@"}
}
func_mode_help ()
{
# We need to display help for each of the modes.
case $opt_mode in
"")
# Generic help is extracted from the usage comments
# at the start of this file.
func_help
;;
clean)
$ECHO \
"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
Remove files from the build directory.
RM is the name of the program to use to delete files associated with each FILE
(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed
to RM.
If FILE is a libtool library, object or program, all the files associated
with it are deleted. Otherwise, only FILE itself is deleted using RM."
;;
compile)
$ECHO \
"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
Compile a source file into a libtool library object.
This mode accepts the following additional options:
-o OUTPUT-FILE set the output file name to OUTPUT-FILE
-no-suppress do not suppress compiler output for multiple passes
-prefer-pic try to build PIC objects only
-prefer-non-pic try to build non-PIC objects only
-shared do not build a '.o' file suitable for static linking
-static only build a '.o' file suitable for static linking
-Wc,FLAG
-Xcompiler FLAG pass FLAG directly to the compiler
COMPILE-COMMAND is a command to be used in creating a 'standard' object file
from the given SOURCEFILE.
The output file name is determined by removing the directory component from
SOURCEFILE, then substituting the C source code suffix '.c' with the
library object suffix, '.lo'."
;;
execute)
$ECHO \
"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
Automatically set library path, then run a program.
This mode accepts the following additional options:
-dlopen FILE add the directory containing FILE to the library path
This mode sets the library path environment variable according to '-dlopen'
flags.
If any of the ARGS are libtool executable wrappers, then they are translated
into their corresponding uninstalled binary, and any of their required library
directories are added to the library path.
Then, COMMAND is executed, with ARGS as arguments."
;;
finish)
$ECHO \
"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
Complete the installation of libtool libraries.
Each LIBDIR is a directory that contains libtool libraries.
The commands that this mode executes may require superuser privileges. Use
the '--dry-run' option if you just want to see what would be executed."
;;
install)
$ECHO \
"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
Install executables or libraries.
INSTALL-COMMAND is the installation command. The first component should be
either the 'install' or 'cp' program.
The following components of INSTALL-COMMAND are treated specially:
-inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation
The rest of the components are interpreted as arguments to that command (only
BSD-compatible install options are recognized)."
;;
link)
$ECHO \
"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
Link object files or libraries together to form another library, or to
create an executable program.
LINK-COMMAND is a command using the C compiler that you would use to create
a program from several object files.
The following components of LINK-COMMAND are treated specially:
-all-static do not do any dynamic linking at all
-avoid-version do not add a version suffix if possible
-bindir BINDIR specify path to binaries directory (for systems where
libraries must be found in the PATH setting at runtime)
-dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime
-dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
-export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
-export-symbols SYMFILE
try to export only the symbols listed in SYMFILE
-export-symbols-regex REGEX
try to export only the symbols matching REGEX
-LLIBDIR search LIBDIR for required installed libraries
-lNAME OUTPUT-FILE requires the installed library libNAME
-module build a library that can dlopened
-no-fast-install disable the fast-install mode
-no-install link a not-installable executable
-no-undefined declare that a library does not refer to external symbols
-o OUTPUT-FILE create OUTPUT-FILE from the specified objects
-objectlist FILE use a list of object files found in FILE to specify objects
-os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes)
-precious-files-regex REGEX
don't remove output files matching REGEX
-release RELEASE specify package release information
-rpath LIBDIR the created library will eventually be installed in LIBDIR
-R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
-shared only do dynamic linking of libtool libraries
-shrext SUFFIX override the standard shared library file extension
-static do not do any dynamic linking of uninstalled libtool libraries
-static-libtool-libs
do not do any dynamic linking of libtool libraries
-version-info CURRENT[:REVISION[:AGE]]
specify library version info [each variable defaults to 0]
-weak LIBNAME declare that the target provides the LIBNAME interface
-Wc,FLAG
-Xcompiler FLAG pass linker-specific FLAG directly to the compiler
-Wa,FLAG
-Xassembler FLAG pass linker-specific FLAG directly to the assembler
-Wl,FLAG
-Xlinker FLAG pass linker-specific FLAG directly to the linker
-XCClinker FLAG pass link-specific FLAG to the compiler driver (CC)
All other options (arguments beginning with '-') are ignored.
Every other argument is treated as a filename. Files ending in '.la' are
treated as uninstalled libtool libraries, other files are standard or library
object files.
If the OUTPUT-FILE ends in '.la', then a libtool library is created,
only library objects ('.lo' files) may be specified, and '-rpath' is
required, except when creating a convenience library.
If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created
using 'ar' and 'ranlib', or on Windows using 'lib'.
If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file
is created, otherwise an executable program is created."
;;
uninstall)
$ECHO \
"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
Remove libraries from an installation directory.
RM is the name of the program to use to delete files associated with each FILE
(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed
to RM.
If FILE is a libtool library, all the files associated with it are deleted.
Otherwise, only FILE itself is deleted using RM."
;;
*)
func_fatal_help "invalid operation mode '$opt_mode'"
;;
esac
echo
$ECHO "Try '$progname --help' for more information about other modes."
}
# Now that we've collected a possible --mode arg, show help if necessary
if $opt_help; then
if test : = "$opt_help"; then
func_mode_help
else
{
func_help noexit
for opt_mode in compile link execute install finish uninstall clean; do
func_mode_help
done
} | $SED -n '1p; 2,$s/^Usage:/ or: /p'
{
func_help noexit
for opt_mode in compile link execute install finish uninstall clean; do
echo
func_mode_help
done
} |
$SED '1d
/^When reporting/,/^Report/{
H
d
}
$x
/information about other modes/d
/more detailed .*MODE/d
s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
fi
exit $?
fi
# If option '--reorder-cache', reorder the shared library cache and exit.
if $opt_reorder_cache; then
func_reorder_shared_lib_cache $shared_lib_dirs
fi
# func_mode_execute arg...
func_mode_execute ()
{
$debug_cmd
# The first argument is the command name.
cmd=$nonopt
test -z "$cmd" && \
func_fatal_help "you must specify a COMMAND"
# Handle -dlopen flags immediately.
for file in $opt_dlopen; do
test -f "$file" \
|| func_fatal_help "'$file' is not a file"
dir=
case $file in
*.la)
func_resolve_sysroot "$file"
file=$func_resolve_sysroot_result
# Check to see that this really is a libtool archive.
func_lalib_unsafe_p "$file" \
|| func_fatal_help "'$lib' is not a valid libtool archive"
# Read the libtool library.
dlname=
library_names=
func_source "$file"
# Skip this library if it cannot be dlopened.
if test -z "$dlname"; then
# Warn if it was a shared library.
test -n "$library_names" && \
func_warning "'$file' was not linked with '-export-dynamic'"
continue
fi
func_dirname "$file" "" "."
dir=$func_dirname_result
if test -f "$dir/$objdir/$dlname"; then
func_append dir "/$objdir"
else
if test ! -f "$dir/$dlname"; then
func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'"
fi
fi
;;
*.lo)
# Just add the directory containing the .lo file.
func_dirname "$file" "" "."
dir=$func_dirname_result
;;
*)
func_warning "'-dlopen' is ignored for non-libtool libraries and objects"
continue
;;
esac
# Get the absolute pathname.
absdir=`cd "$dir" && pwd`
test -n "$absdir" && dir=$absdir
# Now add the directory to shlibpath_var.
if eval "test -z \"\$$shlibpath_var\""; then
eval "$shlibpath_var=\"\$dir\""
else
eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
fi
done
# This variable tells wrapper scripts just to set shlibpath_var
# rather than running their programs.
libtool_execute_magic=$magic
# Check if any of the arguments is a wrapper script.
args=
for file
do
case $file in
-* | *.la | *.lo ) ;;
*)
# Do a test to see if this is really a libtool program.
if func_ltwrapper_script_p "$file"; then
func_source "$file"
# Transform arg to wrapped name.
file=$progdir/$program
elif func_ltwrapper_executable_p "$file"; then
func_ltwrapper_scriptname "$file"
func_source "$func_ltwrapper_scriptname_result"
# Transform arg to wrapped name.
file=$progdir/$program
fi
;;
esac
# Quote arguments (to preserve shell metacharacters).
func_append_quoted args "$file"
done
if $opt_dry_run; then
# Display what would be done.
if test -n "$shlibpath_var"; then
eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
echo "export $shlibpath_var"
fi
$ECHO "$cmd$args"
exit $EXIT_SUCCESS
else
if test -n "$shlibpath_var"; then
# Export the shlibpath_var.
eval "export $shlibpath_var"
fi
# Restore saved environment variables
for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
do
eval "if test \"\${save_$lt_var+set}\" = set; then
$lt_var=\$save_$lt_var; export $lt_var
else
$lt_unset $lt_var
fi"
done
# Now prepare to actually exec the command.
exec_cmd=\$cmd$args
fi
}
test execute = "$opt_mode" && func_mode_execute ${1+"$@"}
# func_mode_finish arg...
func_mode_finish ()
{
$debug_cmd
libs=
libdirs=
admincmds=
for opt in "$nonopt" ${1+"$@"}
do
if test -d "$opt"; then
func_append libdirs " $opt"
elif test -f "$opt"; then
if func_lalib_unsafe_p "$opt"; then
func_append libs " $opt"
else
func_warning "'$opt' is not a valid libtool archive"
fi
else
func_fatal_error "invalid argument '$opt'"
fi
done
if test -n "$libs"; then
if test -n "$lt_sysroot"; then
sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
else
sysroot_cmd=
fi
# Remove sysroot references
if $opt_dry_run; then
for lib in $libs; do
echo "removing references to $lt_sysroot and '=' prefixes from $lib"
done
else
tmpdir=`func_mktempdir`
for lib in $libs; do
$SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
> $tmpdir/tmp-la
mv -f $tmpdir/tmp-la $lib
done
${RM}r "$tmpdir"
fi
fi
if test -n "$finish_cmds$finish_eval" && test -n "$libdirs" && $opt_finishing; then
for libdir in $libdirs; do
if test -n "$finish_cmds"; then
# Do each command in the finish commands.
func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
'"$cmd"'"'
fi
if test -n "$finish_eval"; then
# Do the single finish_eval.
eval cmds=\"$finish_eval\"
$opt_dry_run || eval "$cmds" || func_append admincmds "
$cmds"
fi
done
fi
# Exit here if they wanted silent mode.
$opt_quiet && exit $EXIT_SUCCESS
if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
echo "----------------------------------------------------------------------"
echo "Libraries have been installed in:"
for libdir in $libdirs; do
$ECHO " $libdir"
done
if test "false" = "$opt_finishing"; then
echo
echo "NOTE: finish_cmds were not executed during testing, so you must"
echo "manually run ldconfig to add a given test directory, LIBDIR, to"
echo "the search path for generated executables."
fi
echo
echo "If you ever happen to want to link against installed libraries"
echo "in a given directory, LIBDIR, you must either use libtool, and"
echo "specify the full pathname of the library, or use the '-LLIBDIR'"
echo "flag during linking and do at least one of the following:"
if test -n "$shlibpath_var"; then
echo " - add LIBDIR to the '$shlibpath_var' environment variable"
echo " during execution"
fi
if test -n "$runpath_var"; then
echo " - add LIBDIR to the '$runpath_var' environment variable"
echo " during linking"
fi
if test -n "$hardcode_libdir_flag_spec"; then
libdir=LIBDIR
eval flag=\"$hardcode_libdir_flag_spec\"
$ECHO " - use the '$flag' linker flag"
fi
if test -n "$admincmds"; then
$ECHO " - have your system administrator run these commands:$admincmds"
fi
if test -f /etc/ld.so.conf; then
echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'"
fi
echo
echo "After a 'make install' for many GNU/Linux systems, 'ldconfig LIBDIR'"
echo "may need to be executed to help locate newly installed libraries,"
echo "but you should consult with a system administrator before updating"
echo "the shared library cache as this should be done with great care"
echo "and consideration. (See the 'Platform-specific configuration notes'"
echo "section of the documentation for more information.)"
echo
echo "See any operating system documentation about shared libraries for"
case $host in
solaris2.[6789]|solaris2.1[0-9])
echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
echo "pages."
;;
*)
echo "more information, such as the ld(1) and ld.so(8) manual pages."
;;
esac
echo "----------------------------------------------------------------------"
fi
exit $EXIT_SUCCESS
}
test finish = "$opt_mode" && func_mode_finish ${1+"$@"}
# func_mode_install arg...
func_mode_install ()
{
$debug_cmd
# There may be an optional sh(1) argument at the beginning of
# install_prog (especially on Windows NT).
if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" ||
# Allow the use of GNU shtool's install command.
case $nonopt in *shtool*) :;; *) false;; esac
then
# Aesthetically quote it.
func_quote_arg pretty "$nonopt"
install_prog="$func_quote_arg_result "
arg=$1
shift
else
install_prog=
arg=$nonopt
fi
# The real first argument should be the name of the installation program.
# Aesthetically quote it.
func_quote_arg pretty "$arg"
func_append install_prog "$func_quote_arg_result"
install_shared_prog=$install_prog
case " $install_prog " in
*[\\\ /]cp\ *) install_cp=: ;;
*) install_cp=false ;;
esac
# We need to accept at least all the BSD install flags.
dest=
files=
opts=
prev=
install_type=
isdir=false
stripme=
no_mode=:
for arg
do
arg2=
if test -n "$dest"; then
func_append files " $dest"
dest=$arg
continue
fi
case $arg in
-d) isdir=: ;;
-f)
if $install_cp; then :; else
prev=$arg
fi
;;
-g | -m | -o | -S | -t)
prev=$arg
;;
-s)
stripme=" -s"
continue
;;
-*)
;;
*)
# If the previous option needed an argument, then skip it.
if test -n "$prev"; then
if test X-m = "X$prev" && test -n "$install_override_mode"; then
arg2=$install_override_mode
no_mode=false
fi
prev=
else
dest=$arg
continue
fi
;;
esac
# Aesthetically quote the argument.
func_quote_arg pretty "$arg"
func_append install_prog " $func_quote_arg_result"
if test -n "$arg2"; then
func_quote_arg pretty "$arg2"
fi
func_append install_shared_prog " $func_quote_arg_result"
done
test -z "$install_prog" && \
func_fatal_help "you must specify an install program"
test -n "$prev" && \
func_fatal_help "the '$prev' option requires an argument"
if test -n "$install_override_mode" && $no_mode; then
if $install_cp; then :; else
func_quote_arg pretty "$install_override_mode"
func_append install_shared_prog " -m $func_quote_arg_result"
fi
fi
if test -z "$files"; then
if test -z "$dest"; then
func_fatal_help "no file or destination specified"
else
func_fatal_help "you must specify a destination"
fi
fi
# Strip any trailing slash from the destination.
func_stripname '' '/' "$dest"
dest=$func_stripname_result
# Check to see that the destination is a directory.
test -d "$dest" && isdir=:
if $isdir; then
destdir=$dest
destname=
else
func_dirname_and_basename "$dest" "" "."
destdir=$func_dirname_result
destname=$func_basename_result
# Not a directory, so check to see that there is only one file specified.
set dummy $files; shift
test "$#" -gt 1 && \
func_fatal_help "'$dest' is not a directory"
fi
case $destdir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
for file in $files; do
case $file in
*.lo) ;;
*)
func_fatal_help "'$destdir' must be an absolute directory name"
;;
esac
done
;;
esac
# This variable tells wrapper scripts just to set variables rather
# than running their programs.
libtool_install_magic=$magic
staticlibs=
future_libdirs=
current_libdirs=
for file in $files; do
# Do each installation.
case $file in
*.$libext)
# Do the static libraries later.
func_append staticlibs " $file"
;;
*.la)
func_resolve_sysroot "$file"
file=$func_resolve_sysroot_result
# Check to see that this really is a libtool archive.
func_lalib_unsafe_p "$file" \
|| func_fatal_help "'$file' is not a valid libtool archive"
library_names=
old_library=
relink_command=
func_source "$file"
# Add the libdir to current_libdirs if it is the destination.
if test "X$destdir" = "X$libdir"; then
case "$current_libdirs " in
*" $libdir "*) ;;
*) func_append current_libdirs " $libdir" ;;
esac
else
# Note the libdir as a future libdir.
case "$future_libdirs " in
*" $libdir "*) ;;
*) func_append future_libdirs " $libdir" ;;
esac
fi
func_dirname "$file" "/" ""
dir=$func_dirname_result
func_append dir "$objdir"
if test -n "$relink_command"; then
# Strip any trailing slash from the destination.
func_stripname '' '/' "$libdir"
destlibdir=$func_stripname_result
func_stripname '' '/' "$destdir"
s_destdir=$func_stripname_result
# Determine the prefix the user has applied to our future dir.
inst_prefix_dir=`$ECHO "X$s_destdir" | $Xsed -e "s%$destlibdir\$%%"`
# Don't allow the user to place us outside of our expected
# location b/c this prevents finding dependent libraries that
# are installed to the same prefix.
# At present, this check doesn't affect windows .dll's that
# are installed into $libdir/../bin (currently, that works fine)
# but it's something to keep an eye on.
test "$inst_prefix_dir" = "$destdir" && \
func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir"
if test -n "$inst_prefix_dir"; then
# Stick the inst_prefix_dir data into the link command.
relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
else
relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
fi
func_warning "relinking '$file'"
func_show_eval "$relink_command" \
'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"'
fi
# See the names of the shared library.
set dummy $library_names; shift
if test -n "$1"; then
realname=$1
shift
srcname=$realname
test -n "$relink_command" && srcname=${realname}T
# Install the shared library and build the symlinks.
func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
'exit $?'
tstripme=$stripme
case $host_os in
cygwin* | mingw* | windows* | pw32* | cegcc*)
case $realname in
*.dll.a)
tstripme=
;;
esac
;;
os2*)
case $realname in
*_dll.a)
tstripme=
;;
esac
;;
esac
if test -n "$tstripme" && test -n "$striplib"; then
func_show_eval "$striplib $destdir/$realname" 'exit $?'
fi
if test "$#" -gt 0; then
# Delete the old symlinks, and create new ones.
# Try 'ln -sf' first, because the 'ln' binary might depend on
# the symlink we replace! Solaris /bin/ln does not understand -f,
# so we also need to try rm && ln -s.
for linkname
do
test "$linkname" != "$realname" \
&& func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
done
fi
# Do each command in the postinstall commands.
lib=$destdir/$realname
func_execute_cmds "$postinstall_cmds" 'exit $?'
fi
# Install the pseudo-library for information purposes.
func_basename "$file"
name=$func_basename_result
instname=$dir/${name}i
func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
# Maybe install the static library, too.
test -n "$old_library" && func_append staticlibs " $dir/$old_library"
;;
*.lo)
# Install (i.e. copy) a libtool object.
# Figure out destination file name, if it wasn't already specified.
if test -n "$destname"; then
destfile=$destdir/$destname
else
func_basename "$file"
destfile=$func_basename_result
destfile=$destdir/$destfile
fi
# Deduce the name of the destination old-style object file.
case $destfile in
*.lo)
func_lo2o "$destfile"
staticdest=$func_lo2o_result
;;
*.$objext)
staticdest=$destfile
destfile=
;;
*)
func_fatal_help "cannot copy a libtool object to '$destfile'"
;;
esac
# Install the libtool object if requested.
test -n "$destfile" && \
func_show_eval "$install_prog $file $destfile" 'exit $?'
# Install the old object if enabled.
if test yes = "$build_old_libs"; then
# Deduce the name of the old-style object file.
func_lo2o "$file"
staticobj=$func_lo2o_result
func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
fi
exit $EXIT_SUCCESS
;;
*)
# Figure out destination file name, if it wasn't already specified.
if test -n "$destname"; then
destfile=$destdir/$destname
else
func_basename "$file"
destfile=$func_basename_result
destfile=$destdir/$destfile
fi
# If the file is missing, and there is a .exe on the end, strip it
# because it is most likely a libtool script we actually want to
# install
stripped_ext=
case $file in
*.exe)
if test ! -f "$file"; then
func_stripname '' '.exe' "$file"
file=$func_stripname_result
stripped_ext=.exe
fi
;;
esac
# Do a test to see if this is really a libtool program.
case $host in
*cygwin* | *mingw* | *windows*)
if func_ltwrapper_executable_p "$file"; then
func_ltwrapper_scriptname "$file"
wrapper=$func_ltwrapper_scriptname_result
else
func_stripname '' '.exe' "$file"
wrapper=$func_stripname_result
fi
;;
*)
wrapper=$file
;;
esac
if func_ltwrapper_script_p "$wrapper"; then
notinst_deplibs=
relink_command=
func_source "$wrapper"
# Check the variables that should have been set.
test -z "$generated_by_libtool_version" && \
func_fatal_error "invalid libtool wrapper script '$wrapper'"
finalize=:
for lib in $notinst_deplibs; do
# Check to see that each library is installed.
libdir=
if test -f "$lib"; then
func_source "$lib"
fi
libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'`
if test -n "$libdir" && test ! -f "$libfile"; then
func_warning "'$lib' has not been installed in '$libdir'"
finalize=false
fi
done
relink_command=
func_source "$wrapper"
outputname=
if test no = "$fast_install" && test -n "$relink_command"; then
$opt_dry_run || {
if $finalize; then
tmpdir=`func_mktempdir`
func_basename "$file$stripped_ext"
file=$func_basename_result
outputname=$tmpdir/$file
# Replace the output file specification.
relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
$opt_quiet || {
func_quote_arg expand,pretty "$relink_command"
eval "func_echo $func_quote_arg_result"
}
if eval "$relink_command"; then :
else
func_error "error: relink '$file' with the above command before installing it"
$opt_dry_run || ${RM}r "$tmpdir"
continue
fi
file=$outputname
else
func_warning "cannot relink '$file'"
fi
}
else
# Install the binary that we compiled earlier.
file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
fi
fi
# remove .exe since cygwin /usr/bin/install will append another
# one anyway
case $install_prog,$host in
*/usr/bin/install*,*cygwin*)
case $file:$destfile in
*.exe:*.exe)
# this is ok
;;
*.exe:*)
destfile=$destfile.exe
;;
*:*.exe)
func_stripname '' '.exe' "$destfile"
destfile=$func_stripname_result
;;
esac
;;
esac
func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
$opt_dry_run || if test -n "$outputname"; then
${RM}r "$tmpdir"
fi
;;
esac
done
for file in $staticlibs; do
func_basename "$file"
name=$func_basename_result
# Set up the ranlib parameters.
oldlib=$destdir/$name
func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
tool_oldlib=$func_to_tool_file_result
func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
if test -n "$stripme" && test -n "$old_striplib"; then
func_show_eval "$old_striplib $tool_oldlib" 'exit $?'
fi
# Do each command in the postinstall commands.
func_execute_cmds "$old_postinstall_cmds" 'exit $?'
done
test -n "$future_libdirs" && \
func_warning "remember to run '$progname --finish$future_libdirs'"
if test -n "$current_libdirs"; then
# Maybe just do a dry run.
$opt_dry_run && current_libdirs=" -n$current_libdirs"
exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs'
else
exit $EXIT_SUCCESS
fi
}
test install = "$opt_mode" && func_mode_install ${1+"$@"}
# func_generate_dlsyms outputname originator pic_p
# Extract symbols from dlprefiles and create ${outputname}S.o with
# a dlpreopen symbol table.
func_generate_dlsyms ()
{
$debug_cmd
my_outputname=$1
my_originator=$2
my_pic_p=${3-false}
my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'`
my_dlsyms=
if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
if test -n "$NM" && test -n "$global_symbol_pipe"; then
my_dlsyms=${my_outputname}S.c
else
func_error "not configured to extract global symbols from dlpreopened files"
fi
fi
if test -n "$my_dlsyms"; then
case $my_dlsyms in
"") ;;
*.c)
# Discover the nlist of each of the dlfiles.
nlist=$output_objdir/$my_outputname.nm
func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
# Parse the name list into a source file.
func_verbose "creating $output_objdir/$my_dlsyms"
$opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */
/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */
#ifdef __cplusplus
extern \"C\" {
#endif
#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
#endif
/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
/* DATA imports from DLLs on WIN32 can't be const, because runtime
relocations are performed -- see ld's documentation on pseudo-relocs. */
# define LT_DLSYM_CONST
#elif defined __osf__
/* This system does not cope well with relocations in const data. */
# define LT_DLSYM_CONST
#else
# define LT_DLSYM_CONST const
#endif
#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
/* External symbol declarations for the compiler. */\
"
if test yes = "$dlself"; then
func_verbose "generating symbol list for '$output'"
$opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
# Add our own program objects to the symbol list.
progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
for progfile in $progfiles; do
func_to_tool_file "$progfile" func_convert_file_msys_to_w32
func_verbose "extracting global C symbols from '$func_to_tool_file_result'"
$opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
done
if test -n "$exclude_expsyms"; then
$opt_dry_run || {
eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
eval '$MV "$nlist"T "$nlist"'
}
fi
if test -n "$export_symbols_regex"; then
$opt_dry_run || {
eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
eval '$MV "$nlist"T "$nlist"'
}
fi
# Prepare the list of exported symbols
if test -z "$export_symbols"; then
export_symbols=$output_objdir/$outputname.expsym
$opt_dry_run || {
$RM $export_symbols
eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
case $host in
*cygwin* | *mingw* | *windows* | *cegcc* )
eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
;;
esac
}
else
$opt_dry_run || {
eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.expsym"'
eval '$GREP -f "$output_objdir/$outputname.expsym" < "$nlist" > "$nlist"T'
eval '$MV "$nlist"T "$nlist"'
case $host in
*cygwin* | *mingw* | *windows* | *cegcc* )
eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
;;
esac
}
fi
fi
for dlprefile in $dlprefiles; do
func_verbose "extracting global C symbols from '$dlprefile'"
func_basename "$dlprefile"
name=$func_basename_result
case $host in
*cygwin* | *mingw* | *windows* | *cegcc* )
# if an import library, we need to obtain dlname
if func_win32_import_lib_p "$dlprefile"; then
func_tr_sh "$dlprefile"
eval "curr_lafile=\$libfile_$func_tr_sh_result"
dlprefile_dlbasename=
if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
# Use subshell, to avoid clobbering current variable values
dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
if test -n "$dlprefile_dlname"; then
func_basename "$dlprefile_dlname"
dlprefile_dlbasename=$func_basename_result
else
# no lafile. user explicitly requested -dlpreopen .
$sharedlib_from_linklib_cmd "$dlprefile"
dlprefile_dlbasename=$sharedlib_from_linklib_result
fi
fi
$opt_dry_run || {
if test -n "$dlprefile_dlbasename"; then
eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
else
func_warning "Could not compute DLL name from $name"
eval '$ECHO ": $name " >> "$nlist"'
fi
func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
case $host in
i[3456]86-*-mingw32*)
eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
$SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
;;
*)
eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
$SED -e '/I __imp/d' -e 's/I __nm_/D /;s/__nm_//' >> '$nlist'"
;;
esac
}
else # not an import lib
$opt_dry_run || {
eval '$ECHO ": $name " >> "$nlist"'
func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
}
fi
;;
*)
$opt_dry_run || {
eval '$ECHO ": $name " >> "$nlist"'
func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
}
;;
esac
done
$opt_dry_run || {
# Make sure we have at least an empty file.
test -f "$nlist" || : > "$nlist"
if test -n "$exclude_expsyms"; then
$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
$MV "$nlist"T "$nlist"
fi
# Try sorting and uniquifying the output.
if $GREP -v "^: " < "$nlist" |
if sort -k 3 /dev/null 2>&1; then
sort -k 3
else
sort +2
fi |
uniq > "$nlist"S; then
:
else
$GREP -v "^: " < "$nlist" > "$nlist"S
fi
if test -f "$nlist"S; then
eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
else
echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
fi
func_show_eval '$RM "${nlist}I"'
if test -n "$global_symbol_to_import"; then
eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I'
fi
echo >> "$output_objdir/$my_dlsyms" "\
/* The mapping between symbol names and symbols. */
typedef struct {
const char *name;
void *address;
} lt_dlsymlist;
extern LT_DLSYM_CONST lt_dlsymlist
lt_${my_prefix}_LTX_preloaded_symbols[];\
"
if test -s "$nlist"I; then
echo >> "$output_objdir/$my_dlsyms" "\
static void lt_syminit(void)
{
LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols;
for (; symbol->name; ++symbol)
{"
$SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms"
echo >> "$output_objdir/$my_dlsyms" "\
}
}"
fi
echo >> "$output_objdir/$my_dlsyms" "\
LT_DLSYM_CONST lt_dlsymlist
lt_${my_prefix}_LTX_preloaded_symbols[] =
{ {\"$my_originator\", (void *) 0},"
if test -s "$nlist"I; then
echo >> "$output_objdir/$my_dlsyms" "\
{\"@INIT@\", (void *) <_syminit},"
fi
case $need_lib_prefix in
no)
eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
;;
*)
eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
;;
esac
echo >> "$output_objdir/$my_dlsyms" "\
{0, (void *) 0}
};
/* This works around a problem in FreeBSD linker */
#ifdef FREEBSD_WORKAROUND
static const void *lt_preloaded_setup() {
return lt_${my_prefix}_LTX_preloaded_symbols;
}
#endif
#ifdef __cplusplus
}
#endif\
"
} # !$opt_dry_run
pic_flag_for_symtable=
case "$compile_command " in
*" -static "*) ;;
*)
case $host in
# compiling the symbol table file with pic_flag works around
# a FreeBSD bug that causes programs to crash when -lm is
# linked before any other PIC object. But we must not use
# pic_flag when linking with -static. The problem exists in
# FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
*-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
*-*-hpux*)
pic_flag_for_symtable=" $pic_flag" ;;
*)
$my_pic_p && pic_flag_for_symtable=" $pic_flag"
;;
esac
;;
esac
symtab_cflags=
for arg in $LTCFLAGS; do
case $arg in
-pie | -fpie | -fPIE) ;;
*) func_append symtab_cflags " $arg" ;;
esac
done
# Now compile the dynamic symbol file.
func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
# Clean up the generated files.
func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"'
# Transform the symbol file into the correct name.
symfileobj=$output_objdir/${my_outputname}S.$objext
case $host in
*cygwin* | *mingw* | *windows* | *cegcc* )
if test -f "$output_objdir/$my_outputname.def"; then
compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
else
compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
fi
;;
*)
compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
;;
esac
;;
*)
func_fatal_error "unknown suffix for '$my_dlsyms'"
;;
esac
else
# We keep going just in case the user didn't refer to
# lt_preloaded_symbols. The linker will fail if global_symbol_pipe
# really was required.
# Nullify the symbol file.
compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
fi
}
# func_cygming_gnu_implib_p ARG
# This predicate returns with zero status (TRUE) if
# ARG is a GNU/binutils-style import library. Returns
# with nonzero status (FALSE) otherwise.
func_cygming_gnu_implib_p ()
{
$debug_cmd
func_to_tool_file "$1" func_convert_file_msys_to_w32
func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
test -n "$func_cygming_gnu_implib_tmp"
}
# func_cygming_ms_implib_p ARG
# This predicate returns with zero status (TRUE) if
# ARG is an MS-style import library. Returns
# with nonzero status (FALSE) otherwise.
func_cygming_ms_implib_p ()
{
$debug_cmd
func_to_tool_file "$1" func_convert_file_msys_to_w32
func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
test -n "$func_cygming_ms_implib_tmp"
}
# func_win32_libid arg
# return the library type of file 'arg'
#
# Need a lot of goo to handle *both* DLLs and import libs
# Has to be a shell function in order to 'eat' the argument
# that is supplied when $file_magic_command is called.
# Despite the name, also deal with 64 bit binaries.
func_win32_libid ()
{
$debug_cmd
win32_libid_type=unknown
win32_fileres=`file -L $1 2>/dev/null`
case $win32_fileres in
*ar\ archive\ import\ library*) # definitely import
win32_libid_type="x86 archive import"
;;
*ar\ archive*) # could be an import, or static
# Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
$EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64|pe-aarch64)' >/dev/null; then
case $nm_interface in
"MS dumpbin")
if func_cygming_ms_implib_p "$1" ||
func_cygming_gnu_implib_p "$1"
then
win32_nmres=import
else
win32_nmres=
fi
;;
*)
func_to_tool_file "$1" func_convert_file_msys_to_w32
win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
$SED -n -e '
1,100{
/ I /{
s|.*|import|
p
q
}
}'`
;;
esac
case $win32_nmres in
import*) win32_libid_type="x86 archive import";;
*) win32_libid_type="x86 archive static";;
esac
fi
;;
*DLL*)
win32_libid_type="x86 DLL"
;;
*executable*) # but shell scripts are "executable" too...
case $win32_fileres in
*MS\ Windows\ PE\ Intel*)
win32_libid_type="x86 DLL"
;;
esac
;;
esac
$ECHO "$win32_libid_type"
}
# func_cygming_dll_for_implib ARG
#
# Platform-specific function to extract the
# name of the DLL associated with the specified
# import library ARG.
# Invoked by eval'ing the libtool variable
# $sharedlib_from_linklib_cmd
# Result is available in the variable
# $sharedlib_from_linklib_result
func_cygming_dll_for_implib ()
{
$debug_cmd
sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
}
# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
#
# The is the core of a fallback implementation of a
# platform-specific function to extract the name of the
# DLL associated with the specified import library LIBNAME.
#
# SECTION_NAME is either .idata$6 or .idata$7, depending
# on the platform and compiler that created the implib.
#
# Echos the name of the DLL associated with the
# specified import library.
func_cygming_dll_for_implib_fallback_core ()
{
$debug_cmd
match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
$OBJDUMP -s --section "$1" "$2" 2>/dev/null |
$SED '/^Contents of section '"$match_literal"':/{
# Place marker at beginning of archive member dllname section
s/.*/====MARK====/
p
d
}
# These lines can sometimes be longer than 43 characters, but
# are always uninteresting
/:[ ]*file format pe[i]\{,1\}-/d
/^In archive [^:]*:/d
# Ensure marker is printed
/^====MARK====/p
# Remove all lines with less than 43 characters
/^.\{43\}/!d
# From remaining lines, remove first 43 characters
s/^.\{43\}//' |
$SED -n '
# Join marker and all lines until next marker into a single line
/^====MARK====/ b para
H
$ b para
b
:para
x
s/\n//g
# Remove the marker
s/^====MARK====//
# Remove trailing dots and whitespace
s/[\. \t]*$//
# Print
/./p' |
# we now have a list, one entry per line, of the stringified
# contents of the appropriate section of all members of the
# archive that possess that section. Heuristic: eliminate
# all those that have a first or second character that is
# a '.' (that is, objdump's representation of an unprintable
# character.) This should work for all archives with less than
# 0x302f exports -- but will fail for DLLs whose name actually
# begins with a literal '.' or a single character followed by
# a '.'.
#
# Of those that remain, print the first one.
$SED -e '/^\./d;/^.\./d;q'
}
# func_cygming_dll_for_implib_fallback ARG
# Platform-specific function to extract the
# name of the DLL associated with the specified
# import library ARG.
#
# This fallback implementation is for use when $DLLTOOL
# does not support the --identify-strict option.
# Invoked by eval'ing the libtool variable
# $sharedlib_from_linklib_cmd
# Result is available in the variable
# $sharedlib_from_linklib_result
func_cygming_dll_for_implib_fallback ()
{
$debug_cmd
if func_cygming_gnu_implib_p "$1"; then
# binutils import library
sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
elif func_cygming_ms_implib_p "$1"; then
# ms-generated import library
sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
else
# unknown
sharedlib_from_linklib_result=
fi
}
# func_extract_an_archive dir oldlib
func_extract_an_archive ()
{
$debug_cmd
f_ex_an_ar_dir=$1; shift
f_ex_an_ar_oldlib=$1
if test yes = "$lock_old_archive_extraction"; then
lockfile=$f_ex_an_ar_oldlib.lock
until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
func_echo "Waiting for $lockfile to be removed"
sleep 2
done
fi
func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
'stat=$?; rm -f "$lockfile"; exit $stat'
if test yes = "$lock_old_archive_extraction"; then
$opt_dry_run || rm -f "$lockfile"
fi
if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
:
else
func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
fi
}
# func_extract_archives gentop oldlib ...
func_extract_archives ()
{
$debug_cmd
my_gentop=$1; shift
my_oldlibs=${1+"$@"}
my_oldobjs=
my_xlib=
my_xabs=
my_xdir=
for my_xlib in $my_oldlibs; do
# Extract the objects.
case $my_xlib in
[\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;;
*) my_xabs=`pwd`"/$my_xlib" ;;
esac
func_basename "$my_xlib"
my_xlib=$func_basename_result
my_xlib_u=$my_xlib
while :; do
case " $extracted_archives " in
*" $my_xlib_u "*)
func_arith $extracted_serial + 1
extracted_serial=$func_arith_result
my_xlib_u=lt$extracted_serial-$my_xlib ;;
*) break ;;
esac
done
extracted_archives="$extracted_archives $my_xlib_u"
my_xdir=$my_gentop/$my_xlib_u
func_mkdir_p "$my_xdir"
case $host in
*-darwin*)
func_verbose "Extracting $my_xabs"
# Do not bother doing anything if just a dry run
$opt_dry_run || {
darwin_orig_dir=`pwd`
cd $my_xdir || exit $?
darwin_archive=$my_xabs
darwin_curdir=`pwd`
func_basename "$darwin_archive"
darwin_base_archive=$func_basename_result
darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
if test -n "$darwin_arches"; then
darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
darwin_arch=
func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
for darwin_arch in $darwin_arches; do
func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch"
$LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive"
cd "unfat-$$/$darwin_base_archive-$darwin_arch"
func_extract_an_archive "`pwd`" "$darwin_base_archive"
cd "$darwin_curdir"
$RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive"
done # $darwin_arches
## Okay now we've a bunch of thin objects, gotta fatten them up :)
darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u`
darwin_file=
darwin_files=
for darwin_file in $darwin_filelist; do
darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
$LIPO -create -output "$darwin_file" $darwin_files
done # $darwin_filelist
$RM -rf unfat-$$
cd "$darwin_orig_dir"
else
cd $darwin_orig_dir
func_extract_an_archive "$my_xdir" "$my_xabs"
fi # $darwin_arches
} # !$opt_dry_run
;;
*)
func_extract_an_archive "$my_xdir" "$my_xabs"
;;
esac
my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
done
func_extract_archives_result=$my_oldobjs
}
# func_emit_wrapper [arg=no]
#
# Emit a libtool wrapper script on stdout.
# Don't directly open a file because we may want to
# incorporate the script contents within a cygwin/mingw/windows
# wrapper executable. Must ONLY be called from within
# func_mode_link because it depends on a number of variables
# set therein.
#
# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
# variable will take. If 'yes', then the emitted script
# will assume that the directory where it is stored is
# the $objdir directory. This is a cygwin/mingw/windows-specific
# behavior.
func_emit_wrapper ()
{
func_emit_wrapper_arg1=${1-no}
$ECHO "\
#! $SHELL
# $output - temporary wrapper script for $objdir/$outputname
# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
#
# The $output program cannot be directly executed until all the libtool
# libraries that it depends on are installed.
#
# This wrapper script should never be moved out of the build directory.
# If it is, it will not operate correctly.
# Sed substitution that helps us do robust quoting. It backslashifies
# metacharacters that are still active within double-quoted strings.
sed_quote_subst='$sed_quote_subst'
# Be Bourne compatible
if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
# Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
else
case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
fi
BIN_SH=xpg4; export BIN_SH # for Tru64
DUALCASE=1; export DUALCASE # for MKS sh
# The HP-UX ksh and POSIX shell print the target directory to stdout
# if CDPATH is set.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
relink_command=\"$relink_command\"
# This environment variable determines our operation mode.
if test \"\$libtool_install_magic\" = \"$magic\"; then
# install mode needs the following variables:
generated_by_libtool_version='$macro_version'
notinst_deplibs='$notinst_deplibs'
else
# When we are sourced in execute mode, \$file and \$ECHO are already set.
if test \"\$libtool_execute_magic\" != \"$magic\"; then
file=\"\$0\""
func_quote_arg pretty "$ECHO"
qECHO=$func_quote_arg_result
$ECHO "\
# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
\$1
_LTECHO_EOF'
}
ECHO=$qECHO
fi
# Very basic option parsing. These options are (a) specific to
# the libtool wrapper, (b) are identical between the wrapper
# /script/ and the wrapper /executable/ that is used only on
# windows platforms, and (c) all begin with the string "--lt-"
# (application programs are unlikely to have options that match
# this pattern).
#
# There are only two supported options: --lt-debug and
# --lt-dump-script. There is, deliberately, no --lt-help.
#
# The first argument to this parsing function should be the
# script's $0 value, followed by "$@".
lt_option_debug=
func_parse_lt_options ()
{
lt_script_arg0=\$0
shift
for lt_opt
do
case \"\$lt_opt\" in
--lt-debug) lt_option_debug=1 ;;
--lt-dump-script)
lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
cat \"\$lt_dump_D/\$lt_dump_F\"
exit 0
;;
--lt-*)
\$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
exit 1
;;
esac
done
# Print the debug banner immediately:
if test -n \"\$lt_option_debug\"; then
echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2
fi
}
# Used when --lt-debug. Prints its arguments to stdout
# (redirection is the responsibility of the caller)
func_lt_dump_args ()
{
lt_dump_args_N=1;
for lt_arg
do
\$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\"
lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
done
}
# Core function for launching the target application
func_exec_program_core ()
{
"
case $host in
# Backslashes separate directories on plain windows
*-*-mingw* | *-*-windows* | *-*-os2* | *-cegcc*)
$ECHO "\
if test -n \"\$lt_option_debug\"; then
\$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2
func_lt_dump_args \${1+\"\$@\"} 1>&2
fi
exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
"
;;
*)
$ECHO "\
if test -n \"\$lt_option_debug\"; then
\$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2
func_lt_dump_args \${1+\"\$@\"} 1>&2
fi
exec \"\$progdir/\$program\" \${1+\"\$@\"}
"
;;
esac
$ECHO "\
\$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
exit 1
}
# A function to encapsulate launching the target application
# Strips options in the --lt-* namespace from \$@ and
# launches target application with the remaining arguments.
func_exec_program ()
{
case \" \$* \" in
*\\ --lt-*)
for lt_wr_arg
do
case \$lt_wr_arg in
--lt-*) ;;
*) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
esac
shift
done ;;
esac
func_exec_program_core \${1+\"\$@\"}
}
# Parse options
func_parse_lt_options \"\$0\" \${1+\"\$@\"}
# Find the directory that this script lives in.
thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
test \"x\$thisdir\" = \"x\$file\" && thisdir=.
# Follow symbolic links until we get to the real thisdir.
file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
while test -n \"\$file\"; do
destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
# If there was a directory component, then change thisdir.
if test \"x\$destdir\" != \"x\$file\"; then
case \"\$destdir\" in
[\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
*) thisdir=\"\$thisdir/\$destdir\" ;;
esac
fi
file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
done
# Usually 'no', except on cygwin/mingw/windows when embedded into
# the cwrapper.
WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
# special case for '.'
if test \"\$thisdir\" = \".\"; then
thisdir=\`pwd\`
fi
# remove .libs from thisdir
case \"\$thisdir\" in
*[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
$objdir ) thisdir=. ;;
esac
fi
# Try to get the absolute directory name.
absdir=\`cd \"\$thisdir\" && pwd\`
test -n \"\$absdir\" && thisdir=\"\$absdir\"
"
if test yes = "$fast_install"; then
$ECHO "\
program=lt-'$outputname'$exeext
progdir=\"\$thisdir/$objdir\"
if test ! -f \"\$progdir/\$program\" ||
{ file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\
test \"X\$file\" != \"X\$progdir/\$program\"; }; then
file=\"\$\$-\$program\"
if test ! -d \"\$progdir\"; then
$MKDIR \"\$progdir\"
else
$RM \"\$progdir/\$file\"
fi"
$ECHO "\
# relink executable if necessary
if test -n \"\$relink_command\"; then
if relink_command_output=\`eval \$relink_command 2>&1\`; then :
else
\$ECHO \"\$relink_command_output\" >&2
$RM \"\$progdir/\$file\"
exit 1
fi
fi
$MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
{ $RM \"\$progdir/\$program\";
$MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
$RM \"\$progdir/\$file\"
fi"
else
$ECHO "\
program='$outputname'
progdir=\"\$thisdir/$objdir\"
"
fi
$ECHO "\
if test -f \"\$progdir/\$program\"; then"
# fixup the dll searchpath if we need to.
#
# Fix the DLL searchpath if we need to. Do this before prepending
# to shlibpath, because on Windows, both are PATH and uninstalled
# libraries must come first.
if test -n "$dllsearchpath"; then
$ECHO "\
# Add the dll search path components to the executable PATH
PATH=$dllsearchpath:\$PATH
"
fi
# Export our shlibpath_var if we have one.
if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
$ECHO "\
# Add our own library path to $shlibpath_var
$shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
# Some systems cannot cope with colon-terminated $shlibpath_var
# The second colon is a workaround for a bug in BeOS R4 sed
$shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
export $shlibpath_var
"
fi
$ECHO "\
if test \"\$libtool_execute_magic\" != \"$magic\"; then
# Run the actual program with our arguments.
func_exec_program \${1+\"\$@\"}
fi
else
# The program doesn't exist.
\$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2
\$ECHO \"This script is just a wrapper for \$program.\" 1>&2
\$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
exit 1
fi
fi\
"
}
# func_emit_cwrapperexe_src
# emit the source code for a wrapper executable on stdout
# Must ONLY be called from within func_mode_link because
# it depends on a number of variable set therein.
func_emit_cwrapperexe_src ()
{
cat <
#include
#if defined _WIN32 && !defined __GNUC__
# include
# include
# include
#else
# include
# include
# ifdef __CYGWIN__
# include
# endif
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
/* declarations of non-ANSI functions */
#if defined __MINGW32__
# ifdef __STRICT_ANSI__
_CRTIMP int __cdecl _putenv (const char *);
# endif
#elif defined __CYGWIN__
# ifdef __STRICT_ANSI__
char *realpath (const char *, char *);
int putenv (char *);
int setenv (const char *, const char *, int);
# endif
/* #elif defined other_platform || defined ... */
#endif
/* portability defines, excluding path handling macros */
#if defined _MSC_VER
# define setmode _setmode
# define stat _stat
# define chmod _chmod
# define getcwd _getcwd
# define putenv _putenv
# define S_IXUSR _S_IEXEC
# define MSVC_ISDIR(m)(((m) & S_IFMT) == S_IFDIR)
#elif defined __MINGW32__
# define setmode _setmode
# define stat _stat
# define chmod _chmod
# define getcwd _getcwd
# define putenv _putenv
#elif defined __CYGWIN__
# define HAVE_SETENV
# define FOPEN_WB "wb"
/* #elif defined other platforms ... */
#endif
#if defined PATH_MAX
# define LT_PATHMAX PATH_MAX
#elif defined MAXPATHLEN
# define LT_PATHMAX MAXPATHLEN
#else
# define LT_PATHMAX 1024
#endif
#ifndef S_IXOTH
# define S_IXOTH 0
#endif
#ifndef S_IXGRP
# define S_IXGRP 0
#endif
/* path handling portability macros */
#ifndef DIR_SEPARATOR
# define DIR_SEPARATOR '/'
# define PATH_SEPARATOR ':'
#endif
#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \
defined __OS2__
# define HAVE_DOS_BASED_FILE_SYSTEM
# define FOPEN_WB "wb"
# ifndef DIR_SEPARATOR_2
# define DIR_SEPARATOR_2 '\\'
# endif
# ifndef PATH_SEPARATOR_2
# define PATH_SEPARATOR_2 ';'
# endif
#endif
#ifndef DIR_SEPARATOR_2
# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
#else /* DIR_SEPARATOR_2 */
# define IS_DIR_SEPARATOR(ch) \
(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
#endif /* DIR_SEPARATOR_2 */
#ifndef PATH_SEPARATOR_2
# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
#else /* PATH_SEPARATOR_2 */
# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
#endif /* PATH_SEPARATOR_2 */
#ifndef FOPEN_WB
# define FOPEN_WB "w"
#endif
#ifndef _O_BINARY
# define _O_BINARY 0
#endif
#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
#define XFREE(stale) do { \
if (stale) { free (stale); stale = 0; } \
} while (0)
#if defined LT_DEBUGWRAPPER
static int lt_debug = 1;
#else
static int lt_debug = 0;
#endif
const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */
void *xmalloc (size_t num);
char *xstrdup (const char *string);
const char *base_name (const char *name);
char *find_executable (const char *wrapper);
char *chase_symlinks (const char *pathspec);
int make_executable (const char *path);
int check_executable (const char *path);
char *strendzap (char *str, const char *pat);
void lt_debugprintf (const char *file, int line, const char *fmt, ...);
void lt_fatal (const char *file, int line, const char *message, ...);
static const char *nonnull (const char *s);
static const char *nonempty (const char *s);
void lt_setenv (const char *name, const char *value);
char *lt_extend_str (const char *orig_value, const char *add, int to_end);
void lt_update_exe_path (const char *name, const char *value);
void lt_update_lib_path (const char *name, const char *value);
char **prepare_spawn (char **argv);
void lt_dump_script (FILE *f);
EOF
cat <= 0) && !MSVC_ISDIR (st.st_mode)
&& (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
#else
if ((stat (path, &st) >= 0) && !S_ISDIR (st.st_mode)
&& (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
#endif
return 1;
else
return 0;
}
int
make_executable (const char *path)
{
int rval = 0;
struct stat st;
lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
nonempty (path));
if ((!path) || (!*path))
return 0;
if (stat (path, &st) >= 0)
{
rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
}
return rval;
}
/* Searches for the full path of the wrapper. Returns
newly allocated full path name if found, NULL otherwise
Does not chase symlinks, even on platforms that support them.
*/
char *
find_executable (const char *wrapper)
{
int has_slash = 0;
const char *p;
const char *p_next;
/* static buffer for getcwd */
char tmp[LT_PATHMAX + 1];
size_t tmp_len;
char *concat_name;
lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
nonempty (wrapper));
if ((wrapper == NULL) || (*wrapper == '\0'))
return NULL;
/* Absolute path? */
#if defined HAVE_DOS_BASED_FILE_SYSTEM
if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
{
concat_name = xstrdup (wrapper);
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
}
else
{
#endif
if (IS_DIR_SEPARATOR (wrapper[0]))
{
concat_name = xstrdup (wrapper);
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
}
#if defined HAVE_DOS_BASED_FILE_SYSTEM
}
#endif
for (p = wrapper; *p; p++)
if (*p == '/')
{
has_slash = 1;
break;
}
if (!has_slash)
{
/* no slashes; search PATH */
const char *path = getenv ("PATH");
if (path != NULL)
{
for (p = path; *p; p = p_next)
{
const char *q;
size_t p_len;
for (q = p; *q; q++)
if (IS_PATH_SEPARATOR (*q))
break;
p_len = (size_t) (q - p);
p_next = (*q == '\0' ? q : q + 1);
if (p_len == 0)
{
/* empty path: current directory */
if (getcwd (tmp, LT_PATHMAX) == NULL)
lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
nonnull (strerror (errno)));
tmp_len = strlen (tmp);
concat_name =
XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
memcpy (concat_name, tmp, tmp_len);
concat_name[tmp_len] = '/';
strcpy (concat_name + tmp_len + 1, wrapper);
}
else
{
concat_name =
XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
memcpy (concat_name, p, p_len);
concat_name[p_len] = '/';
strcpy (concat_name + p_len + 1, wrapper);
}
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
}
}
/* not found in PATH; assume curdir */
}
/* Relative path | not found in path: prepend cwd */
if (getcwd (tmp, LT_PATHMAX) == NULL)
lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
nonnull (strerror (errno)));
tmp_len = strlen (tmp);
concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
memcpy (concat_name, tmp, tmp_len);
concat_name[tmp_len] = '/';
strcpy (concat_name + tmp_len + 1, wrapper);
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
return NULL;
}
char *
chase_symlinks (const char *pathspec)
{
#ifndef S_ISLNK
return xstrdup (pathspec);
#else
char buf[LT_PATHMAX];
struct stat s;
char *tmp_pathspec = xstrdup (pathspec);
char *p;
int has_symlinks = 0;
while (strlen (tmp_pathspec) && !has_symlinks)
{
lt_debugprintf (__FILE__, __LINE__,
"checking path component for symlinks: %s\n",
tmp_pathspec);
if (lstat (tmp_pathspec, &s) == 0)
{
if (S_ISLNK (s.st_mode) != 0)
{
has_symlinks = 1;
break;
}
/* search backwards for last DIR_SEPARATOR */
p = tmp_pathspec + strlen (tmp_pathspec) - 1;
while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
p--;
if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
{
/* no more DIR_SEPARATORS left */
break;
}
*p = '\0';
}
else
{
lt_fatal (__FILE__, __LINE__,
"error accessing file \"%s\": %s",
tmp_pathspec, nonnull (strerror (errno)));
}
}
XFREE (tmp_pathspec);
if (!has_symlinks)
{
return xstrdup (pathspec);
}
tmp_pathspec = realpath (pathspec, buf);
if (tmp_pathspec == 0)
{
lt_fatal (__FILE__, __LINE__,
"could not follow symlinks for %s", pathspec);
}
return xstrdup (tmp_pathspec);
#endif
}
char *
strendzap (char *str, const char *pat)
{
size_t len, patlen;
assert (str != NULL);
assert (pat != NULL);
len = strlen (str);
patlen = strlen (pat);
if (patlen <= len)
{
str += len - patlen;
if (STREQ (str, pat))
*str = '\0';
}
return str;
}
void
lt_debugprintf (const char *file, int line, const char *fmt, ...)
{
va_list args;
if (lt_debug)
{
(void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
va_start (args, fmt);
(void) vfprintf (stderr, fmt, args);
va_end (args);
}
}
static void
lt_error_core (int exit_status, const char *file,
int line, const char *mode,
const char *message, va_list ap)
{
fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
vfprintf (stderr, message, ap);
fprintf (stderr, ".\n");
if (exit_status >= 0)
exit (exit_status);
}
void
lt_fatal (const char *file, int line, const char *message, ...)
{
va_list ap;
va_start (ap, message);
lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
va_end (ap);
}
static const char *
nonnull (const char *s)
{
return s ? s : "(null)";
}
static const char *
nonempty (const char *s)
{
return (s && !*s) ? "(empty)" : nonnull (s);
}
void
lt_setenv (const char *name, const char *value)
{
lt_debugprintf (__FILE__, __LINE__,
"(lt_setenv) setting '%s' to '%s'\n",
nonnull (name), nonnull (value));
{
#ifdef HAVE_SETENV
/* always make a copy, for consistency with !HAVE_SETENV */
char *str = xstrdup (value);
setenv (name, str, 1);
#else
size_t len = strlen (name) + 1 + strlen (value) + 1;
char *str = XMALLOC (char, len);
sprintf (str, "%s=%s", name, value);
if (putenv (str) != EXIT_SUCCESS)
{
XFREE (str);
}
#endif
}
}
char *
lt_extend_str (const char *orig_value, const char *add, int to_end)
{
char *new_value;
if (orig_value && *orig_value)
{
size_t orig_value_len = strlen (orig_value);
size_t add_len = strlen (add);
new_value = XMALLOC (char, add_len + orig_value_len + 1);
if (to_end)
{
strcpy (new_value, orig_value);
strcpy (new_value + orig_value_len, add);
}
else
{
strcpy (new_value, add);
strcpy (new_value + add_len, orig_value);
}
}
else
{
new_value = xstrdup (add);
}
return new_value;
}
void
lt_update_exe_path (const char *name, const char *value)
{
lt_debugprintf (__FILE__, __LINE__,
"(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
nonnull (name), nonnull (value));
if (name && *name && value && *value)
{
char *new_value = lt_extend_str (getenv (name), value, 0);
/* some systems can't cope with a ':'-terminated path #' */
size_t len = strlen (new_value);
while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
{
new_value[--len] = '\0';
}
lt_setenv (name, new_value);
XFREE (new_value);
}
}
void
lt_update_lib_path (const char *name, const char *value)
{
lt_debugprintf (__FILE__, __LINE__,
"(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
nonnull (name), nonnull (value));
if (name && *name && value && *value)
{
char *new_value = lt_extend_str (getenv (name), value, 0);
lt_setenv (name, new_value);
XFREE (new_value);
}
}
EOF
case $host_os in
mingw* | windows*)
cat <<"EOF"
/* Prepares an argument vector before calling spawn().
Note that spawn() does not by itself call the command interpreter
(getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&v);
v.dwPlatformId == VER_PLATFORM_WIN32_NT;
}) ? "cmd.exe" : "command.com").
Instead it simply concatenates the arguments, separated by ' ', and calls
CreateProcess(). We must quote the arguments since Win32 CreateProcess()
interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
special way:
- Space and tab are interpreted as delimiters. They are not treated as
delimiters if they are surrounded by double quotes: "...".
- Unescaped double quotes are removed from the input. Their only effect is
that within double quotes, space and tab are treated like normal
characters.
- Backslashes not followed by double quotes are not special.
- But 2*n+1 backslashes followed by a double quote become
n backslashes followed by a double quote (n >= 0):
\" -> "
\\\" -> \"
\\\\\" -> \\"
*/
#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
char **
prepare_spawn (char **argv)
{
size_t argc;
char **new_argv;
size_t i;
/* Count number of arguments. */
for (argc = 0; argv[argc] != NULL; argc++)
;
/* Allocate new argument vector. */
new_argv = XMALLOC (char *, argc + 1);
/* Put quoted arguments into the new argument vector. */
for (i = 0; i < argc; i++)
{
const char *string = argv[i];
if (string[0] == '\0')
new_argv[i] = xstrdup ("\"\"");
else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
{
int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
size_t length;
unsigned int backslashes;
const char *s;
char *quoted_string;
char *p;
length = 0;
backslashes = 0;
if (quote_around)
length++;
for (s = string; *s != '\0'; s++)
{
char c = *s;
if (c == '"')
length += backslashes + 1;
length++;
if (c == '\\')
backslashes++;
else
backslashes = 0;
}
if (quote_around)
length += backslashes + 1;
quoted_string = XMALLOC (char, length + 1);
p = quoted_string;
backslashes = 0;
if (quote_around)
*p++ = '"';
for (s = string; *s != '\0'; s++)
{
char c = *s;
if (c == '"')
{
unsigned int j;
for (j = backslashes + 1; j > 0; j--)
*p++ = '\\';
}
*p++ = c;
if (c == '\\')
backslashes++;
else
backslashes = 0;
}
if (quote_around)
{
unsigned int j;
for (j = backslashes; j > 0; j--)
*p++ = '\\';
*p++ = '"';
}
*p = '\0';
new_argv[i] = quoted_string;
}
else
new_argv[i] = (char *) string;
}
new_argv[argc] = NULL;
return new_argv;
}
EOF
;;
esac
cat <<"EOF"
void lt_dump_script (FILE* f)
{
EOF
func_emit_wrapper yes |
$SED -n -e '
s/^\(.\{79\}\)\(..*\)/\1\
\2/
h
s/\([\\"]\)/\\\1/g
s/$/\\n/
s/\([^\n]*\).*/ fputs ("\1", f);/p
g
D'
cat <<"EOF"
}
EOF
}
# end: func_emit_cwrapperexe_src
# func_win32_import_lib_p ARG
# True if ARG is an import lib, as indicated by $file_magic_cmd
func_win32_import_lib_p ()
{
$debug_cmd
case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
*import*) : ;;
*) false ;;
esac
}
# func_suncc_cstd_abi
# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!!
# Several compiler flags select an ABI that is incompatible with the
# Cstd library. Avoid specifying it if any are in CXXFLAGS.
func_suncc_cstd_abi ()
{
$debug_cmd
case " $compile_command " in
*" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*)
suncc_use_cstd_abi=no
;;
*)
suncc_use_cstd_abi=yes
;;
esac
}
# func_mode_link arg...
func_mode_link ()
{
$debug_cmd
case $host in
*-*-cygwin* | *-*-mingw* | *-*-windows* | *-*-pw32* | *-*-os2* | *-cegcc*)
# It is impossible to link a dll without this setting, and
# we shouldn't force the makefile maintainer to figure out
# what system we are compiling for in order to pass an extra
# flag for every libtool invocation.
# allow_undefined=no
# FIXME: Unfortunately, there are problems with the above when trying
# to make a dll that has undefined symbols, in which case not
# even a static library is built. For now, we need to specify
# -no-undefined on the libtool link line when we can be certain
# that all symbols are satisfied, otherwise we get a static library.
allow_undefined=yes
;;
*)
allow_undefined=yes
;;
esac
libtool_args=$nonopt
base_compile="$nonopt $@"
compile_command=$nonopt
finalize_command=$nonopt
compile_rpath=
compile_rpath_tail=
finalize_rpath=
compile_shlibpath=
finalize_shlibpath=
convenience=
old_convenience=
deplibs=
old_deplibs=
compiler_flags=
linker_flags=
dllsearchpath=
lib_search_path=`pwd`
inst_prefix_dir=
new_inherited_linker_flags=
avoid_version=no
bindir=
dlfiles=
dlprefiles=
dlself=no
export_dynamic=no
export_symbols=
export_symbols_regex=
generated=
libobjs=
ltlibs=
module=no
no_install=no
objs=
os2dllname=
non_pic_objects=
precious_files_regex=
prefer_static_libs=no
preload=false
prev=
prevarg=
release=
rpath=
xrpath=
perm_rpath=
temp_rpath=
temp_rpath_tail=
thread_safe=no
vinfo=
vinfo_number=no
weak_libs=
rpath_arg=
single_module=$wl-single_module
func_infer_tag $base_compile
# We need to know -static, to get the right output filenames.
for arg
do
case $arg in
-shared)
test yes != "$build_libtool_libs" \
&& func_fatal_configuration "cannot build a shared library"
build_old_libs=no
break
;;
-all-static | -static | -static-libtool-libs)
case $arg in
-all-static)
if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then
func_warning "complete static linking is impossible in this configuration"
fi
if test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=yes
;;
-static)
if test -z "$pic_flag" && test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=built
;;
-static-libtool-libs)
if test -z "$pic_flag" && test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=yes
;;
esac
build_libtool_libs=no
build_old_libs=yes
break
;;
esac
done
# See if our shared archives depend on static archives.
test -n "$old_archive_from_new_cmds" && build_old_libs=yes
# Go through the arguments, transforming them on the way.
while test "$#" -gt 0; do
arg=$1
shift
func_quote_arg pretty,unquoted "$arg"
qarg=$func_quote_arg_unquoted_result
func_append libtool_args " $func_quote_arg_result"
# If the previous option needs an argument, assign it.
if test -n "$prev"; then
case $prev in
output)
func_append compile_command " @OUTPUT@"
func_append finalize_command " @OUTPUT@"
;;
esac
case $prev in
bindir)
bindir=$arg
prev=
continue
;;
dlfiles|dlprefiles)
$preload || {
# Add the symbol object into the linking commands.
func_append compile_command " @SYMFILE@"
func_append finalize_command " @SYMFILE@"
preload=:
}
case $arg in
*.la | *.lo) ;; # We handle these cases below.
force)
if test no = "$dlself"; then
dlself=needless
export_dynamic=yes
fi
prev=
continue
;;
self)
if test dlprefiles = "$prev"; then
dlself=yes
elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then
dlself=yes
else
dlself=needless
export_dynamic=yes
fi
prev=
continue
;;
*)
if test dlfiles = "$prev"; then
func_append dlfiles " $arg"
else
func_append dlprefiles " $arg"
fi
prev=
continue
;;
esac
;;
expsyms)
export_symbols=$arg
test -f "$arg" \
|| func_fatal_error "symbol file '$arg' does not exist"
prev=
continue
;;
expsyms_regex)
export_symbols_regex=$arg
prev=
continue
;;
framework)
case $host in
*-*-darwin*)
case "$deplibs " in
*" $qarg.ltframework "*) ;;
*) func_append deplibs " $qarg.ltframework" # this is fixed later
;;
esac
;;
esac
prev=
continue
;;
inst_prefix)
inst_prefix_dir=$arg
prev=
continue
;;
mllvm)
# Clang does not use LLVM to link, so we can simply discard any
# '-mllvm $arg' options when doing the link step.
prev=
continue
;;
objectlist)
if test -f "$arg"; then
save_arg=$arg
moreargs=
for fil in `cat "$save_arg"`
do
# func_append moreargs " $fil"
arg=$fil
# A libtool-controlled object.
# Check to see that this really is a libtool object.
if func_lalib_unsafe_p "$arg"; then
pic_object=
non_pic_object=
# Read the .lo file
func_source "$arg"
if test -z "$pic_object" ||
test -z "$non_pic_object" ||
test none = "$pic_object" &&
test none = "$non_pic_object"; then
func_fatal_error "cannot find name of object for '$arg'"
fi
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir=$func_dirname_result
if test none != "$pic_object"; then
# Prepend the subdirectory the object is found in.
pic_object=$xdir$pic_object
if test dlfiles = "$prev"; then
if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
func_append dlfiles " $pic_object"
prev=
continue
else
# If libtool objects are unsupported, then we need to preload.
prev=dlprefiles
fi
fi
# CHECK ME: I think I busted this. -Ossama
if test dlprefiles = "$prev"; then
# Preload the old-style object.
func_append dlprefiles " $pic_object"
prev=
fi
# A PIC object.
func_append libobjs " $pic_object"
arg=$pic_object
fi
# Non-PIC object.
if test none != "$non_pic_object"; then
# Prepend the subdirectory the object is found in.
non_pic_object=$xdir$non_pic_object
# A standard non-PIC object
func_append non_pic_objects " $non_pic_object"
if test -z "$pic_object" || test none = "$pic_object"; then
arg=$non_pic_object
fi
else
# If the PIC object exists, use it instead.
# $xdir was prepended to $pic_object above.
non_pic_object=$pic_object
func_append non_pic_objects " $non_pic_object"
fi
else
# Only an error if not doing a dry-run.
if $opt_dry_run; then
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir=$func_dirname_result
func_lo2o "$arg"
pic_object=$xdir$objdir/$func_lo2o_result
non_pic_object=$xdir$func_lo2o_result
func_append libobjs " $pic_object"
func_append non_pic_objects " $non_pic_object"
else
func_fatal_error "'$arg' is not a valid libtool object"
fi
fi
done
else
func_fatal_error "link input file '$arg' does not exist"
fi
arg=$save_arg
prev=
continue
;;
os2dllname)
os2dllname=$arg
prev=
continue
;;
precious_regex)
precious_files_regex=$arg
prev=
continue
;;
release)
release=-$arg
prev=
continue
;;
rpath | xrpath)
# We need an absolute path.
case $arg in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
func_fatal_error "argument to -rpath is not absolute: $arg"
;;
esac
if test rpath = "$prev"; then
case "$rpath " in
*" $arg "*) ;;
*) func_append rpath " $arg" ;;
esac
else
case "$xrpath " in
*" $arg "*) ;;
*) func_append xrpath " $arg" ;;
esac
fi
prev=
continue
;;
shrext)
shrext_cmds=$arg
prev=
continue
;;
weak)
func_append weak_libs " $arg"
prev=
continue
;;
xassembler)
func_append compiler_flags " -Xassembler $qarg"
prev=
func_append compile_command " -Xassembler $qarg"
func_append finalize_command " -Xassembler $qarg"
continue
;;
xcclinker)
func_append linker_flags " $qarg"
func_append compiler_flags " $qarg"
prev=
func_append compile_command " $qarg"
func_append finalize_command " $qarg"
continue
;;
xcompiler)
func_append compiler_flags " $qarg"
prev=
func_append compile_command " $qarg"
func_append finalize_command " $qarg"
continue
;;
xlinker)
func_append linker_flags "$qarg,"
# Args in the var 'compiler_flags' causes warnings in MSVC
func_cc_basename "$CC"
case $func_cc_basename_result in
cl|cl.exe) ;;
*) func_append compiler_flags " $wl$qarg" ;;
esac
prev=
func_append compile_command " $wl$qarg"
func_append finalize_command " $wl$qarg"
continue
;;
*)
eval "$prev=\"\$arg\""
prev=
continue
;;
esac
fi # test -n "$prev"
prevarg=$arg
case $arg in
-all-static)
if test -n "$link_static_flag"; then
# See comment for -static flag below, for more details.
func_append compile_command " $link_static_flag"
func_append finalize_command " $link_static_flag"
fi
continue
;;
-allow-undefined)
# FIXME: remove this flag sometime in the future.
func_fatal_error "'-allow-undefined' must not be used because it is the default"
;;
-avoid-version)
avoid_version=yes
continue
;;
-bindir)
prev=bindir
continue
;;
-dlopen)
prev=dlfiles
continue
;;
-dlpreopen)
prev=dlprefiles
continue
;;
-export-dynamic)
export_dynamic=yes
continue
;;
-export-symbols | -export-symbols-regex)
if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
func_fatal_error "more than one -exported-symbols argument is not allowed"
fi
if test X-export-symbols = "X$arg"; then
prev=expsyms
else
prev=expsyms_regex
fi
continue
;;
-framework)
prev=framework
continue
;;
-inst-prefix-dir)
prev=inst_prefix
continue
;;
# The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
# so, if we see these flags be careful not to treat them like -L
-L[A-Z][A-Z]*:*)
case $with_gcc/$host in
no/*-*-irix* | /*-*-irix*)
func_append compile_command " $arg"
func_append finalize_command " $arg"
;;
esac
continue
;;
-L*)
func_stripname "-L" '' "$arg"
if test -z "$func_stripname_result"; then
if test "$#" -gt 0; then
func_fatal_error "require no space between '-L' and '$1'"
else
func_fatal_error "need path for '-L' option"
fi
fi
func_resolve_sysroot "$func_stripname_result"
dir=$func_resolve_sysroot_result
# We need an absolute path.
case $dir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
absdir=`cd "$dir" && pwd`
test -z "$absdir" && \
func_fatal_error "cannot determine absolute directory name of '$dir'"
dir=$absdir
;;
esac
case "$deplibs " in
*" -L$dir "* | *" $arg "*)
# Will only happen for absolute or sysroot arguments
;;
*)
# Preserve sysroot, but never include relative directories
case $dir in
[\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;;
*) func_append deplibs " -L$dir" ;;
esac
func_append lib_search_path " $dir"
;;
esac
case $host in
*-*-cygwin* | *-*-mingw* | *-*-windows* | *-*-pw32* | *-*-os2* | *-cegcc*)
testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
case :$dllsearchpath: in
*":$dir:"*) ;;
::) dllsearchpath=$dir;;
*) func_append dllsearchpath ":$dir";;
esac
case :$dllsearchpath: in
*":$testbindir:"*) ;;
::) dllsearchpath=$testbindir;;
*) func_append dllsearchpath ":$testbindir";;
esac
;;
esac
continue
;;
-l*)
if test X-lc = "X$arg" || test X-lm = "X$arg"; then
case $host in
*-*-cygwin* | *-*-mingw* | *-*-windows* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
# These systems don't actually have a C or math library (as such)
continue
;;
*-*-os2*)
# These systems don't actually have a C library (as such)
test X-lc = "X$arg" && continue
;;
*-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-midnightbsd*)
# Do not include libc due to us having libc/libc_r.
test X-lc = "X$arg" && continue
;;
*-*-rhapsody* | *-*-darwin1.[012])
# Rhapsody C and math libraries are in the System framework
func_append deplibs " System.ltframework"
continue
;;
*-*-sco3.2v5* | *-*-sco5v6*)
# Causes problems with __ctype
test X-lc = "X$arg" && continue
;;
*-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
# Compiler inserts libc in the correct place for threads to work
test X-lc = "X$arg" && continue
;;
esac
elif test X-lc_r = "X$arg"; then
case $host in
*-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-midnightbsd*)
# Do not include libc_r directly, use -pthread flag.
continue
;;
esac
fi
func_append deplibs " $arg"
continue
;;
-mllvm)
prev=mllvm
continue
;;
-module)
module=yes
continue
;;
# Tru64 UNIX uses -model [arg] to determine the layout of C++
# classes, name mangling, and exception handling.
# Darwin uses the -arch flag to determine output architecture.
# -q for IBM XL C/C++ compiler.
-model|-arch|-isysroot|--sysroot|-q)
func_append compiler_flags " $arg"
func_append compile_command " $arg"
func_append finalize_command " $arg"
prev=xcompiler
continue
;;
# Solaris ld rejects as of 11.4. Refer to Oracle bug 22985199.
-pthread)
case $host in
*solaris2*) ;;
*)
case "$new_inherited_linker_flags " in
*" $arg "*) ;;
* ) func_append new_inherited_linker_flags " $arg" ;;
esac
;;
esac
continue
;;
-mt|-mthreads|-kthread|-Kthread|-pthreads|--thread-safe \
|-threads|-fopenmp|-fopenmp=*|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
func_append compiler_flags " $arg"
func_append compile_command " $arg"
func_append finalize_command " $arg"
case "$new_inherited_linker_flags " in
*" $arg "*) ;;
* ) func_append new_inherited_linker_flags " $arg" ;;
esac
continue
;;
-multi_module)
single_module=$wl-multi_module
continue
;;
-no-fast-install)
fast_install=no
continue
;;
-no-install)
case $host in
*-*-cygwin* | *-*-mingw* | *-*-windows* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
# The PATH hackery in wrapper scripts is required on Windows
# and Darwin in order for the loader to find any dlls it needs.
fast_install=no
;;
*) no_install=yes ;;
esac
continue
;;
-no-undefined)
allow_undefined=no
continue
;;
-objectlist)
prev=objectlist
continue
;;
-os2dllname)
prev=os2dllname
continue
;;
-o) prev=output ;;
-precious-files-regex)
prev=precious_regex
continue
;;
-release)
prev=release
continue
;;
-rpath)
prev=rpath
continue
;;
-R)
prev=xrpath
continue
;;
-R*)
func_stripname '-R' '' "$arg"
dir=$func_stripname_result
# We need an absolute path.
case $dir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
=*)
func_stripname '=' '' "$dir"
dir=$lt_sysroot$func_stripname_result
;;
*)
func_fatal_error "argument ($arg) to '-R' is not an absolute path: $dir"
;;
esac
case "$xrpath " in
*" $dir "*) ;;
*) func_append xrpath " $dir" ;;
esac
continue
;;
-shared)
# The effects of -shared are defined in a previous loop.
continue
;;
-shrext)
prev=shrext
continue
;;
-static | -static-libtool-libs)
# The effects of -static are defined in a previous loop.
# We used to do the same as -all-static on platforms that
# didn't have a PIC flag, but the assumption that the effects
# would be equivalent was wrong. It would break on at least
# Digital Unix and AIX.
continue
;;
-thread-safe)
thread_safe=yes
continue
;;
-version-info)
prev=vinfo
continue
;;
-version-number)
prev=vinfo
vinfo_number=yes
continue
;;
-weak)
prev=weak
continue
;;
-Wc,*)
func_stripname '-Wc,' '' "$arg"
args=$func_stripname_result
arg=
save_ifs=$IFS; IFS=,
for flag in $args; do
IFS=$save_ifs
func_quote_arg pretty "$flag"
func_append arg " $func_quote_arg_result"
func_append compiler_flags " $func_quote_arg_result"
done
IFS=$save_ifs
func_stripname ' ' '' "$arg"
arg=$func_stripname_result
;;
-Wl,--as-needed|-Wl,--no-as-needed)
deplibs="$deplibs $arg"
continue
;;
-Wl,*)
func_stripname '-Wl,' '' "$arg"
args=$func_stripname_result
arg=
save_ifs=$IFS; IFS=,
for flag in $args; do
IFS=$save_ifs
func_quote_arg pretty "$flag"
func_append arg " $wl$func_quote_arg_result"
# Args in the var 'compiler_flags' causes warnings in MSVC
func_cc_basename "$CC"
case $func_cc_basename_result in
cl|cl.exe) ;;
*) func_append compiler_flags " $wl$func_quote_arg_result" ;;
esac
func_append linker_flags "$func_quote_arg_result,"
done
IFS=$save_ifs
func_stripname ' ' '' "$arg"
arg=$func_stripname_result
;;
-Xassembler)
prev=xassembler
continue
;;
-Xcompiler)
prev=xcompiler
continue
;;
-Xlinker)
prev=xlinker
continue
;;
-XCClinker)
prev=xcclinker
continue
;;
# -msg_* for osf cc
-msg_*)
func_quote_arg pretty "$arg"
arg=$func_quote_arg_result
;;
# Flags to be passed through unchanged, with rationale:
# -64, -mips[0-9] enable 64-bit mode for the SGI compiler
# -r[0-9][0-9]* specify processor for the SGI compiler
# -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
# +DA*, +DD* enable 64-bit mode for the HP compiler
# -q* compiler args for the IBM compiler
# -m*, -t[45]*, -txscale* architecture-specific flags for GCC
# -F/path path to uninstalled frameworks, gcc on darwin
# -p, -pg, --coverage, -fprofile-* profiling flags for GCC
# -fstack-protector* stack protector flags for GCC
# @file GCC response files
# -tp=* Portland pgcc target processor selection
# --sysroot=* for sysroot support
# --target=* for target architecture support
# -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
# -specs=* GCC specs files
# -stdlib=* select c++ std lib with clang
# -fdiagnostics-color* simply affects output
# -frecord-gcc-switches used to verify flags were respected
# -fsanitize=* Clang/GCC memory and address sanitizer
# -fno-sanitize* Clang/GCC memory and address sanitizer
# -shared-libsan Link with shared sanitizer runtimes (Clang)
# -static-libsan Link with static sanitizer runtimes (Clang)
# -no-canonical-prefixes Do not expand any symbolic links
# -fuse-ld=* Linker select flags for GCC
# -static-* direct GCC to link specific libraries statically
# -fcilkplus Cilk Plus language extension features for C/C++
# -rtlib=* select c runtime lib with clang
# --unwindlib=* select unwinder library with clang
# -f{file|debug|macro|profile}-prefix-map=* needed for lto linking
# -Wa,* Pass flags directly to the assembler
# -W* Warnings, needed for lto
-64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
-t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*|--target=*| \
-O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-no-canonical-prefixes| \
-stdlib=*|-rtlib=*|--unwindlib=*| \
-specs=*|-fsanitize=*|-fno-sanitize*|-shared-libsan|-static-libsan| \
-ffile-prefix-map=*|-fdebug-prefix-map=*|-fmacro-prefix-map=*|-fprofile-prefix-map=*| \
-fdiagnostics-color*|-frecord-gcc-switches| \
-fuse-ld=*|-static-*|-fcilkplus|-W*)
func_quote_arg pretty "$arg"
arg=$func_quote_arg_result
func_append compile_command " $arg"
func_append finalize_command " $arg"
func_append compiler_flags " $arg"
continue
;;
-Z*)
if test os2 = "`expr $host : '.*\(os2\)'`"; then
# OS/2 uses -Zxxx to specify OS/2-specific options
compiler_flags="$compiler_flags $arg"
func_append compile_command " $arg"
func_append finalize_command " $arg"
case $arg in
-Zlinker | -Zstack)
prev=xcompiler
;;
esac
continue
else
# Otherwise treat like 'Some other compiler flag' below
func_quote_arg pretty "$arg"
arg=$func_quote_arg_result
fi
;;
# Some other compiler flag.
-* | +*)
func_quote_arg pretty "$arg"
arg=$func_quote_arg_result
;;
*.$objext)
# A standard object.
func_append objs " $arg"
;;
*.lo)
# A libtool-controlled object.
# Check to see that this really is a libtool object.
if func_lalib_unsafe_p "$arg"; then
pic_object=
non_pic_object=
# Read the .lo file
func_source "$arg"
if test -z "$pic_object" ||
test -z "$non_pic_object" ||
test none = "$pic_object" &&
test none = "$non_pic_object"; then
func_fatal_error "cannot find name of object for '$arg'"
fi
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir=$func_dirname_result
test none = "$pic_object" || {
# Prepend the subdirectory the object is found in.
pic_object=$xdir$pic_object
if test dlfiles = "$prev"; then
if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
func_append dlfiles " $pic_object"
prev=
continue
else
# If libtool objects are unsupported, then we need to preload.
prev=dlprefiles
fi
fi
# CHECK ME: I think I busted this. -Ossama
if test dlprefiles = "$prev"; then
# Preload the old-style object.
func_append dlprefiles " $pic_object"
prev=
fi
# A PIC object.
func_append libobjs " $pic_object"
arg=$pic_object
}
# Non-PIC object.
if test none != "$non_pic_object"; then
# Prepend the subdirectory the object is found in.
non_pic_object=$xdir$non_pic_object
# A standard non-PIC object
func_append non_pic_objects " $non_pic_object"
if test -z "$pic_object" || test none = "$pic_object"; then
arg=$non_pic_object
fi
else
# If the PIC object exists, use it instead.
# $xdir was prepended to $pic_object above.
non_pic_object=$pic_object
func_append non_pic_objects " $non_pic_object"
fi
else
# Only an error if not doing a dry-run.
if $opt_dry_run; then
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir=$func_dirname_result
func_lo2o "$arg"
pic_object=$xdir$objdir/$func_lo2o_result
non_pic_object=$xdir$func_lo2o_result
func_append libobjs " $pic_object"
func_append non_pic_objects " $non_pic_object"
else
func_fatal_error "'$arg' is not a valid libtool object"
fi
fi
;;
*.$libext)
# An archive.
func_append deplibs " $arg"
func_append old_deplibs " $arg"
continue
;;
*.la)
# A libtool-controlled library.
func_resolve_sysroot "$arg"
if test dlfiles = "$prev"; then
# This library was specified with -dlopen.
func_append dlfiles " $func_resolve_sysroot_result"
prev=
elif test dlprefiles = "$prev"; then
# The library was specified with -dlpreopen.
func_append dlprefiles " $func_resolve_sysroot_result"
prev=
else
func_append deplibs " $func_resolve_sysroot_result"
fi
continue
;;
# Some other compiler argument.
*)
# Unknown arguments in both finalize_command and compile_command need
# to be aesthetically quoted because they are evaled later.
func_quote_arg pretty "$arg"
arg=$func_quote_arg_result
;;
esac # arg
# Now actually substitute the argument into the commands.
if test -n "$arg"; then
if test -n "$rpath_arg"; then
func_append finalize_rpath " ${arg##*,}"
unset rpath_arg
else
case $arg in
-Wl,-rpath,*)
func_append finalize_rpath " ${arg##*,}";;
-Wl,-rpath)
rpath_arg=1;;
*)
func_append compile_command " $arg"
func_append finalize_command " $arg"
esac
fi
fi
done # argument parsing loop
test -n "$prev" && \
func_fatal_help "the '$prevarg' option requires an argument"
if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then
eval arg=\"$export_dynamic_flag_spec\"
func_append compile_command " $arg"
func_append finalize_command " $arg"
fi
oldlibs=
# calculate the name of the file, without its directory
func_basename "$output"
outputname=$func_basename_result
libobjs_save=$libobjs
if test -n "$shlibpath_var"; then
# get the directories listed in $shlibpath_var
eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\`
else
shlib_search_path=
fi
eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
# Definition is injected by LT_CONFIG during libtool generation.
func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH"
func_dirname "$output" "/" ""
output_objdir=$func_dirname_result$objdir
func_to_tool_file "$output_objdir/"
tool_output_objdir=$func_to_tool_file_result
# Create the object directory.
func_mkdir_p "$output_objdir"
# Determine the type of output
case $output in
"")
func_fatal_help "you must specify an output file"
;;
*.$libext) linkmode=oldlib ;;
*.lo | *.$objext) linkmode=obj ;;
*.la) linkmode=lib ;;
*) linkmode=prog ;; # Anything else should be a program.
esac
specialdeplibs=
libs=
# Find all interdependent deplibs by searching for libraries
# that are linked more than once (e.g. -la -lb -la)
for deplib in $deplibs; do
if $opt_preserve_dup_deps; then
case "$libs " in
*" $deplib "*) func_append specialdeplibs " $deplib" ;;
esac
fi
func_append libs " $deplib"
done
if test lib = "$linkmode"; then
libs="$predeps $libs $compiler_lib_search_path $postdeps"
# Compute libraries that are listed more than once in $predeps
# $postdeps and mark them as special (i.e., whose duplicates are
# not to be eliminated).
pre_post_deps=
if $opt_duplicate_compiler_generated_deps; then
for pre_post_dep in $predeps $postdeps; do
case "$pre_post_deps " in
*" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;;
esac
func_append pre_post_deps " $pre_post_dep"
done
fi
pre_post_deps=
fi
deplibs=
newdependency_libs=
newlib_search_path=
need_relink=no # whether we're linking any uninstalled libtool libraries
notinst_deplibs= # not-installed libtool libraries
notinst_path= # paths that contain not-installed libtool libraries
case $linkmode in
lib)
passes="conv dlpreopen link"
for file in $dlfiles $dlprefiles; do
case $file in
*.la) ;;
*)
func_fatal_help "libraries can '-dlopen' only libtool libraries: $file"
;;
esac
done
;;
prog)
compile_deplibs=
finalize_deplibs=
alldeplibs=false
newdlfiles=
newdlprefiles=
passes="conv scan dlopen dlpreopen link"
;;
*) passes="conv"
;;
esac
for pass in $passes; do
# The preopen pass in lib mode reverses $deplibs; put it back here
# so that -L comes before libs that need it for instance...
if test lib,link = "$linkmode,$pass"; then
## FIXME: Find the place where the list is rebuilt in the wrong
## order, and fix it there properly
tmp_deplibs=
for deplib in $deplibs; do
tmp_deplibs="$deplib $tmp_deplibs"
done
deplibs=$tmp_deplibs
fi
if test lib,link = "$linkmode,$pass" ||
test prog,scan = "$linkmode,$pass"; then
libs=$deplibs
deplibs=
fi
if test prog = "$linkmode"; then
case $pass in
dlopen) libs=$dlfiles ;;
dlpreopen) libs=$dlprefiles ;;
link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
esac
fi
if test lib,dlpreopen = "$linkmode,$pass"; then
# Collect and forward deplibs of preopened libtool libs
for lib in $dlprefiles; do
# Ignore non-libtool-libs
dependency_libs=
func_resolve_sysroot "$lib"
case $lib in
*.la) func_source "$func_resolve_sysroot_result" ;;
esac
# Collect preopened libtool deplibs, except any this library
# has declared as weak libs
for deplib in $dependency_libs; do
func_basename "$deplib"
deplib_base=$func_basename_result
case " $weak_libs " in
*" $deplib_base "*) ;;
*) func_append deplibs " $deplib" ;;
esac
done
done
libs=$dlprefiles
fi
if test dlopen = "$pass"; then
# Collect dlpreopened libraries
save_deplibs=$deplibs
deplibs=
fi
for deplib in $libs; do
lib=
found=false
case $deplib in
-Wl,--as-needed|-Wl,--no-as-needed)
if test prog,link = "$linkmode,$pass"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
deplibs="$deplib $deplibs"
fi
continue
;;
-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
|-threads|-fopenmp|-fopenmp=*|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
if test prog,link = "$linkmode,$pass"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
func_append compiler_flags " $deplib"
if test lib = "$linkmode"; then
case "$new_inherited_linker_flags " in
*" $deplib "*) ;;
* ) func_append new_inherited_linker_flags " $deplib" ;;
esac
fi
fi
continue
;;
-l*)
if test lib != "$linkmode" && test prog != "$linkmode"; then
func_warning "'-l' is ignored for archives/objects"
continue
fi
func_stripname '-l' '' "$deplib"
name=$func_stripname_result
if test lib = "$linkmode"; then
searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
else
searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
fi
for searchdir in $searchdirs; do
for search_ext in .la $std_shrext .so .a; do
# Search the libtool library
lib=$searchdir/lib$name$search_ext
if test -f "$lib"; then
if test .la = "$search_ext"; then
found=:
else
found=false
fi
break 2
fi
done
done
if $found; then
# deplib is a libtool library
# If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
# We need to do some special things here, and not later.
if test yes = "$allow_libtool_libs_with_static_runtimes"; then
case " $predeps $postdeps " in
*" $deplib "*)
if func_lalib_p "$lib"; then
library_names=
old_library=
func_source "$lib"
for l in $old_library $library_names; do
ll=$l
done
if test "X$ll" = "X$old_library"; then # only static version available
found=false
func_dirname "$lib" "" "."
ladir=$func_dirname_result
lib=$ladir/$old_library
if test prog,link = "$linkmode,$pass"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
deplibs="$deplib $deplibs"
test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
fi
continue
fi
fi
;;
*) ;;
esac
fi
else
# deplib doesn't seem to be a libtool library
if test prog,link = "$linkmode,$pass"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
deplibs="$deplib $deplibs"
test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
fi
continue
fi
;; # -l
*.ltframework)
if test prog,link = "$linkmode,$pass"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
deplibs="$deplib $deplibs"
if test lib = "$linkmode"; then
case "$new_inherited_linker_flags " in
*" $deplib "*) ;;
* ) func_append new_inherited_linker_flags " $deplib" ;;
esac
fi
fi
continue
;;
-L*)
case $linkmode in
lib)
deplibs="$deplib $deplibs"
test conv = "$pass" && continue
newdependency_libs="$deplib $newdependency_libs"
func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
func_append newlib_search_path " $func_resolve_sysroot_result"
;;
prog)
if test conv = "$pass"; then
deplibs="$deplib $deplibs"
continue
fi
if test scan = "$pass"; then
deplibs="$deplib $deplibs"
else
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
fi
func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
func_append newlib_search_path " $func_resolve_sysroot_result"
;;
*)
func_warning "'-L' is ignored for archives/objects"
;;
esac # linkmode
continue
;; # -L
-R*)
if test link = "$pass"; then
func_stripname '-R' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
dir=$func_resolve_sysroot_result
# Make sure the xrpath contains only unique directories.
case "$xrpath " in
*" $dir "*) ;;
*) func_append xrpath " $dir" ;;
esac
fi
deplibs="$deplib $deplibs"
continue
;;
*.la)
func_resolve_sysroot "$deplib"
lib=$func_resolve_sysroot_result
;;
*.$libext)
if test conv = "$pass"; then
deplibs="$deplib $deplibs"
continue
fi
case $linkmode in
lib)
# Linking convenience modules and compiler provided static libraries
# into shared libraries is allowed, but linking other static
# libraries is non-portable.
case $deplib in
*/libgcc*.$libext | */libclang_rt*.$libext)
deplibs="$deplib $deplibs"
continue
;;
esac
case " $dlpreconveniencelibs " in
*" $deplib "*) ;;
*)
valid_a_lib=false
case $deplibs_check_method in
match_pattern*)
set dummy $deplibs_check_method; shift
match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
| $EGREP "$match_pattern_regex" > /dev/null; then
valid_a_lib=:
fi
;;
pass_all)
valid_a_lib=:
;;
esac
if $valid_a_lib; then
func_warning "Linking the shared library $output against the static library $deplib is not portable!"
deplibs="$deplib $deplibs"
else
func_warning "Trying to link with static lib archive $deplib."
func_warning "I have the capability to make that library automatically link in when"
func_warning "you link to this library. But I can only do this if you have a"
func_warning "shared version of the library, which you do not appear to have"
func_warning "because the file extensions .$libext of this argument makes me believe"
func_warning "that it is just a static archive that I should not use here."
fi
;;
esac
continue
;;
prog)
if test link != "$pass"; then
deplibs="$deplib $deplibs"
else
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
fi
continue
;;
esac # linkmode
;; # *.$libext
*.lo | *.$objext)
if test conv = "$pass"; then
deplibs="$deplib $deplibs"
elif test prog = "$linkmode"; then
if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then
# If there is no dlopen support or we're linking statically,
# we need to preload.
func_append newdlprefiles " $deplib"
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
func_append newdlfiles " $deplib"
fi
fi
continue
;;
%DEPLIBS%)
alldeplibs=:
continue
;;
esac # case $deplib
$found || test -f "$lib" \
|| func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'"
# Check to see that this really is a libtool archive.
func_lalib_unsafe_p "$lib" \
|| func_fatal_error "'$lib' is not a valid libtool archive"
func_dirname "$lib" "" "."
ladir=$func_dirname_result
dlname=
dlopen=
dlpreopen=
libdir=
library_names=
old_library=
inherited_linker_flags=
# If the library was installed with an old release of libtool,
# it will not redefine variables installed, or shouldnotlink
installed=yes
shouldnotlink=no
avoidtemprpath=
# Read the .la file
func_source "$lib"
# Convert "-framework foo" to "foo.ltframework"
if test -n "$inherited_linker_flags"; then
tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
case " $new_inherited_linker_flags " in
*" $tmp_inherited_linker_flag "*) ;;
*) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";;
esac
done
fi
dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
if test lib,link = "$linkmode,$pass" ||
test prog,scan = "$linkmode,$pass" ||
{ test prog != "$linkmode" && test lib != "$linkmode"; }; then
test -n "$dlopen" && func_append dlfiles " $dlopen"
test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
fi
if test conv = "$pass"; then
# Only check for convenience libraries
deplibs="$lib $deplibs"
if test -z "$libdir"; then
if test -z "$old_library"; then
func_fatal_error "cannot find name of link library for '$lib'"
fi
# It is a libtool convenience library, so add in its objects.
func_append convenience " $ladir/$objdir/$old_library"
func_append old_convenience " $ladir/$objdir/$old_library"
elif test prog != "$linkmode" && test lib != "$linkmode"; then
func_fatal_error "'$lib' is not a convenience library"
fi
tmp_libs=
for deplib in $dependency_libs; do
deplibs="$deplib $deplibs"
if $opt_preserve_dup_deps; then
case "$tmp_libs " in
*" $deplib "*) func_append specialdeplibs " $deplib" ;;
esac
fi
func_append tmp_libs " $deplib"
done
continue
fi # $pass = conv
# Get the name of the library we link against.
linklib=
if test -n "$old_library" &&
{ test yes = "$prefer_static_libs" ||
test built,no = "$prefer_static_libs,$installed"; }; then
linklib=$old_library
else
for l in $old_library $library_names; do
linklib=$l
done
fi
if test -z "$linklib"; then
func_fatal_error "cannot find name of link library for '$lib'"
fi
# This library was specified with -dlopen.
if test dlopen = "$pass"; then
test -z "$libdir" \
&& func_fatal_error "cannot -dlopen a convenience library: '$lib'"
if test -z "$dlname" ||
test yes != "$dlopen_support" ||
test no = "$build_libtool_libs"
then
# If there is no dlname, no dlopen support or we're linking
# statically, we need to preload. We also need to preload any
# dependent libraries so libltdl's deplib preloader doesn't
# bomb out in the load deplibs phase.
func_append dlprefiles " $lib $dependency_libs"
else
func_append newdlfiles " $lib"
fi
continue
fi # $pass = dlopen
# We need an absolute path.
case $ladir in
[\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;;
*)
abs_ladir=`cd "$ladir" && pwd`
if test -z "$abs_ladir"; then
func_warning "cannot determine absolute directory name of '$ladir'"
func_warning "passing it literally to the linker, although it might fail"
abs_ladir=$ladir
fi
;;
esac
func_basename "$lib"
laname=$func_basename_result
# Find the relevant object directory and library name.
if test yes = "$installed"; then
if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
func_warning "library '$lib' was moved."
dir=$ladir
absdir=$abs_ladir
libdir=$abs_ladir
else
dir=$lt_sysroot$libdir
absdir=$lt_sysroot$libdir
fi
test yes = "$hardcode_automatic" && avoidtemprpath=yes
else
if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
dir=$ladir
absdir=$abs_ladir
# Remove this search path later
func_append notinst_path " $abs_ladir"
else
dir=$ladir/$objdir
absdir=$abs_ladir/$objdir
# Remove this search path later
func_append notinst_path " $abs_ladir"
fi
fi # $installed = yes
func_stripname 'lib' '.la' "$laname"
name=$func_stripname_result
# This library was specified with -dlpreopen.
if test dlpreopen = "$pass"; then
if test -z "$libdir" && test prog = "$linkmode"; then
func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'"
fi
case $host in
# special handling for platforms with PE-DLLs.
*cygwin* | *mingw* | *windows* | *cegcc* )
# Linker will automatically link against shared library if both
# static and shared are present. Therefore, ensure we extract
# symbols from the import library if a shared library is present
# (otherwise, the dlopen module name will be incorrect). We do
# this by putting the import library name into $newdlprefiles.
# We recover the dlopen module name by 'saving' the la file
# name in a special purpose variable, and (later) extracting the
# dlname from the la file.
if test -n "$dlname"; then
func_tr_sh "$dir/$linklib"
eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
func_append newdlprefiles " $dir/$linklib"
else
func_append newdlprefiles " $dir/$old_library"
# Keep a list of preopened convenience libraries to check
# that they are being used correctly in the link pass.
test -z "$libdir" && \
func_append dlpreconveniencelibs " $dir/$old_library"
fi
;;
* )
# Prefer using a static library (so that no silly _DYNAMIC symbols
# are required to link).
if test -n "$old_library"; then
func_append newdlprefiles " $dir/$old_library"
# Keep a list of preopened convenience libraries to check
# that they are being used correctly in the link pass.
test -z "$libdir" && \
func_append dlpreconveniencelibs " $dir/$old_library"
# Otherwise, use the dlname, so that lt_dlopen finds it.
elif test -n "$dlname"; then
func_append newdlprefiles " $dir/$dlname"
else
func_append newdlprefiles " $dir/$linklib"
fi
;;
esac
fi # $pass = dlpreopen
if test -z "$libdir"; then
# Link the convenience library
if test lib = "$linkmode"; then
deplibs="$dir/$old_library $deplibs"
elif test prog,link = "$linkmode,$pass"; then
compile_deplibs="$dir/$old_library $compile_deplibs"
finalize_deplibs="$dir/$old_library $finalize_deplibs"
else
deplibs="$lib $deplibs" # used for prog,scan pass
fi
continue
fi
if test prog = "$linkmode" && test link != "$pass"; then
func_append newlib_search_path " $ladir"
deplibs="$lib $deplibs"
linkalldeplibs=false
if test no != "$link_all_deplibs" || test -z "$library_names" ||
test no = "$build_libtool_libs"; then
linkalldeplibs=:
fi
tmp_libs=
for deplib in $dependency_libs; do
case $deplib in
-L*) func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
func_append newlib_search_path " $func_resolve_sysroot_result"
;;
esac
# Need to link against all dependency_libs?
if $linkalldeplibs; then
deplibs="$deplib $deplibs"
else
# Need to hardcode shared library paths
# or/and link against static libraries
newdependency_libs="$deplib $newdependency_libs"
fi
if $opt_preserve_dup_deps; then
case "$tmp_libs " in
*" $deplib "*) func_append specialdeplibs " $deplib" ;;
esac
fi
func_append tmp_libs " $deplib"
done # for deplib
continue
fi # $linkmode = prog...
if test prog,link = "$linkmode,$pass"; then
if test -n "$library_names" &&
{ { test no = "$prefer_static_libs" ||
test built,yes = "$prefer_static_libs,$installed"; } ||
test -z "$old_library"; }; then
# We need to hardcode the library path
if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then
# Make sure the rpath contains only unique directories.
case $temp_rpath: in
*"$absdir:"*) ;;
*) case $absdir in
"$progdir/"*) func_append temp_rpath "$absdir:" ;;
*) func_append temp_rpath_tail "$absdir:" ;;
esac
esac
fi
# Hardcode the library path.
# Skip directories that are in the system default run-time
# search path.
case " $sys_lib_dlsearch_path " in
*" $absdir "*) ;;
*)
case "$compile_rpath$compile_rpath_tail " in
*" $absdir "*) ;;
*) case $absdir in
"$progdir/"*) func_append compile_rpath " $absdir" ;;
*) func_append compile_rpath_tail " $absdir" ;;
esac
esac
;;
esac
case " $sys_lib_dlsearch_path " in
*" $libdir "*) ;;
*)
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
;;
esac
fi # $linkmode,$pass = prog,link...
if $alldeplibs &&
{ test pass_all = "$deplibs_check_method" ||
{ test yes = "$build_libtool_libs" &&
test -n "$library_names"; }; }; then
# We only need to search for static libraries
continue
fi
fi
link_static=no # Whether the deplib will be linked statically
use_static_libs=$prefer_static_libs
if test built = "$use_static_libs" && test yes = "$installed"; then
use_static_libs=no
fi
if test -n "$library_names" &&
{ test no = "$use_static_libs" || test -z "$old_library"; }; then
case $host_os in
cygwin* | mingw* | windows* | cegcc* | os2*)
# No point in relinking DLLs because paths are not encoded
func_append notinst_deplibs " $lib"
need_relink=no
;;
*)
if test no = "$installed"; then
func_append notinst_deplibs " $lib"
need_relink=yes
fi
;;
esac
# This is a shared library
# Warn about portability, can't link against -module's on some
# systems (darwin). Don't bleat about dlopened modules though!
dlopenmodule=
for dlpremoduletest in $dlprefiles; do
if test "X$dlpremoduletest" = "X$lib"; then
dlopenmodule=$dlpremoduletest
break
fi
done
if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then
echo
if test prog = "$linkmode"; then
func_warning "Linking the executable $output against the loadable module"
else
func_warning "Linking the shared library $output against the loadable module"
fi
func_warning "$linklib is not portable!"
fi
if test lib = "$linkmode" &&
test yes = "$hardcode_into_libs"; then
# Hardcode the library path.
# Skip directories that are in the system default run-time
# search path.
case " $sys_lib_dlsearch_path " in
*" $absdir "*) ;;
*)
case "$compile_rpath$compile_rpath_tail " in
*" $absdir "*) ;;
*) case $absdir in
"$progdir/"*) func_append compile_rpath " $absdir" ;;
*) func_append compile_rpath_tail " $absdir" ;;
esac
esac
;;
esac
case " $sys_lib_dlsearch_path " in
*" $libdir "*) ;;
*)
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
;;
esac
fi
if test -n "$old_archive_from_expsyms_cmds"; then
# figure out the soname
set dummy $library_names
shift
realname=$1
shift
libname=`eval "\\$ECHO \"$libname_spec\""`
# use dlname if we got it. it's perfectly good, no?
if test -n "$dlname"; then
soname=$dlname
elif test -n "$soname_spec"; then
# bleh windows
case $host_os in
cygwin* | mingw* | windows* | cegcc* | os2*)
func_arith $current - $age
major=$func_arith_result
versuffix=-$major
;;
esac
eval soname=\"$soname_spec\"
else
soname=$realname
fi
# Make a new name for the extract_expsyms_cmds to use
soroot=$soname
func_basename "$soroot"
soname=$func_basename_result
func_stripname 'lib' '.dll' "$soname"
newlib=libimp-$func_stripname_result.a
# If the library has no export list, then create one now
if test -f "$output_objdir/$soname-def"; then :
else
func_verbose "extracting exported symbol list from '$soname'"
func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
fi
# Create $newlib
if test -f "$output_objdir/$newlib"; then :; else
func_verbose "generating import library for '$soname'"
func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
fi
# make sure the library variables are pointing to the new library
dir=$output_objdir
linklib=$newlib
fi # test -n "$old_archive_from_expsyms_cmds"
if test prog = "$linkmode" || test relink != "$opt_mode"; then
add_shlibpath=
add_dir=
add=
lib_linked=yes
case $hardcode_action in
immediate | unsupported)
if test no = "$hardcode_direct"; then
add=$dir/$linklib
case $host in
*-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;;
*-*-sysv4*uw2*) add_dir=-L$dir ;;
*-*-emscripten*) add_dir=-L$dir ;;
*-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
*-*-unixware7*) add_dir=-L$dir ;;
*-*-darwin* )
# if the lib is a (non-dlopened) module then we cannot
# link against it, someone is ignoring the earlier warnings
if /usr/bin/file -L $add 2> /dev/null |
$GREP ": [^:]* bundle" >/dev/null; then
if test "X$dlopenmodule" != "X$lib"; then
func_warning "lib $linklib is a module, not a shared library"
if test -z "$old_library"; then
func_warning "And there doesn't seem to be a static archive available"
func_warning "The link will probably fail, sorry"
else
add=$dir/$old_library
fi
elif test -n "$old_library"; then
add=$dir/$old_library
fi
fi
esac
elif test no = "$hardcode_minus_L"; then
case $host in
*-*-sunos*) add_shlibpath=$dir ;;
esac
add_dir=-L$dir
add=-l$name
elif test no = "$hardcode_shlibpath_var"; then
add_shlibpath=$dir
add=-l$name
else
lib_linked=no
fi
;;
relink)
if test yes = "$hardcode_direct" &&
test no = "$hardcode_direct_absolute"; then
add=$dir/$linklib
elif test yes = "$hardcode_minus_L"; then
add_dir=-L$absdir
# Try looking first in the location we're being installed to.
if test -n "$inst_prefix_dir"; then
case $libdir in
[\\/]*)
func_append add_dir " -L$inst_prefix_dir$libdir"
;;
esac
fi
add=-l$name
elif test yes = "$hardcode_shlibpath_var"; then
add_shlibpath=$dir
add=-l$name
else
lib_linked=no
fi
;;
*) lib_linked=no ;;
esac
if test yes != "$lib_linked"; then
func_fatal_configuration "unsupported hardcode properties"
fi
if test -n "$add_shlibpath"; then
case :$compile_shlibpath: in
*":$add_shlibpath:"*) ;;
*) func_append compile_shlibpath "$add_shlibpath:" ;;
esac
fi
if test prog = "$linkmode"; then
test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
test -n "$add" && compile_deplibs="$add $compile_deplibs"
else
test -n "$add_dir" && deplibs="$add_dir $deplibs"
test -n "$add" && deplibs="$add $deplibs"
if test yes != "$hardcode_direct" &&
test yes != "$hardcode_minus_L" &&
test yes = "$hardcode_shlibpath_var"; then
case :$finalize_shlibpath: in
*":$libdir:"*) ;;
*) func_append finalize_shlibpath "$libdir:" ;;
esac
fi
fi
fi
if test prog = "$linkmode" || test relink = "$opt_mode"; then
add_shlibpath=
add_dir=
add=
# Finalize command for both is simple: just hardcode it.
if test yes = "$hardcode_direct" &&
test no = "$hardcode_direct_absolute"; then
add=$libdir/$linklib
elif test yes = "$hardcode_minus_L"; then
add_dir=-L$lt_sysroot$libdir
add=-l$name
elif test yes = "$hardcode_shlibpath_var"; then
case :$finalize_shlibpath: in
*":$libdir:"*) ;;
*) func_append finalize_shlibpath "$libdir:" ;;
esac
add=-l$name
elif test yes = "$hardcode_automatic"; then
if test -n "$inst_prefix_dir" &&
test -f "$inst_prefix_dir$libdir/$linklib"; then
add=$inst_prefix_dir$libdir/$linklib
else
add=$libdir/$linklib
fi
else
# We cannot seem to hardcode it, guess we'll fake it.
add_dir=-L$lt_sysroot$libdir
# Try looking first in the location we're being installed to.
if test -n "$inst_prefix_dir"; then
case $libdir in
[\\/]*)
func_append add_dir " -L$inst_prefix_dir$libdir"
;;
esac
fi
add=-l$name
fi
if test prog = "$linkmode"; then
test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
else
test -n "$add_dir" && deplibs="$add_dir $deplibs"
test -n "$add" && deplibs="$add $deplibs"
fi
fi
elif test prog = "$linkmode"; then
# Here we assume that one of hardcode_direct or hardcode_minus_L
# is not unsupported. This is valid on all known static and
# shared platforms.
if test unsupported != "$hardcode_direct"; then
test -n "$old_library" && linklib=$old_library
compile_deplibs="$dir/$linklib $compile_deplibs"
finalize_deplibs="$dir/$linklib $finalize_deplibs"
else
compile_deplibs="-l$name -L$dir $compile_deplibs"
finalize_deplibs="-l$name -L$dir $finalize_deplibs"
fi
elif test yes = "$build_libtool_libs"; then
# Not a shared library
if test pass_all != "$deplibs_check_method"; then
# We're trying link a shared library against a static one
# but the system doesn't support it.
# Just print a warning and add the library to dependency_libs so
# that the program can be linked against the static library.
func_warning "This system cannot link to static lib archive $lib."
func_warning "I have the capability to make that library automatically link in when"
func_warning "you link to this library. But I can only do this if you have a"
func_warning "shared version of the library, which you do not appear to have."
if test yes = "$module"; then
func_warning "But as you try to build a module library, libtool will still create "
func_warning "a static module, that should work as long as the dlopening application"
func_warning "is linked with the -dlopen flag to resolve symbols at runtime."
if test -z "$global_symbol_pipe"; then
func_warning "However, this would only work if libtool was able to extract symbol"
func_warning "lists from a program, using 'nm' or equivalent, but libtool could"
func_warning "not find such a program. So, this module is probably useless."
func_warning "'nm' from GNU binutils and a full rebuild may help."
fi
if test no = "$build_old_libs"; then
build_libtool_libs=module
build_old_libs=yes
else
build_libtool_libs=no
fi
fi
else
deplibs="$dir/$old_library $deplibs"
link_static=yes
fi
fi # link shared/static library?
if test lib = "$linkmode"; then
if test -n "$dependency_libs" &&
{ test yes != "$hardcode_into_libs" ||
test yes = "$build_old_libs" ||
test yes = "$link_static"; }; then
# Extract -R from dependency_libs
temp_deplibs=
for libdir in $dependency_libs; do
case $libdir in
-R*) func_stripname '-R' '' "$libdir"
temp_xrpath=$func_stripname_result
case " $xrpath " in
*" $temp_xrpath "*) ;;
*) func_append xrpath " $temp_xrpath";;
esac;;
*) func_append temp_deplibs " $libdir";;
esac
done
dependency_libs=$temp_deplibs
fi
func_append newlib_search_path " $absdir"
# Link against this library
test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
# ... and its dependency_libs
tmp_libs=
for deplib in $dependency_libs; do
newdependency_libs="$deplib $newdependency_libs"
case $deplib in
-L*) func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result";;
*) func_resolve_sysroot "$deplib" ;;
esac
if $opt_preserve_dup_deps; then
case "$tmp_libs " in
*" $func_resolve_sysroot_result "*)
func_append specialdeplibs " $func_resolve_sysroot_result" ;;
esac
fi
func_append tmp_libs " $func_resolve_sysroot_result"
done
if test no != "$link_all_deplibs"; then
# Add the search paths of all dependency libraries
for deplib in $dependency_libs; do
path=
case $deplib in
-L*) path=$deplib ;;
*.la)
func_resolve_sysroot "$deplib"
deplib=$func_resolve_sysroot_result
func_dirname "$deplib" "" "."
dir=$func_dirname_result
# We need an absolute path.
case $dir in
[\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;;
*)
absdir=`cd "$dir" && pwd`
if test -z "$absdir"; then
func_warning "cannot determine absolute directory name of '$dir'"
absdir=$dir
fi
;;
esac
if $GREP "^installed=no" $deplib > /dev/null; then
case $host in
*-*-darwin*)
depdepl=
eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
if test -n "$deplibrary_names"; then
for tmp in $deplibrary_names; do
depdepl=$tmp
done
if test -f "$absdir/$objdir/$depdepl"; then
depdepl=$absdir/$objdir/$depdepl
darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
if test -z "$darwin_install_name"; then
darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
fi
func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl"
func_append linker_flags " -dylib_file $darwin_install_name:$depdepl"
path=
fi
fi
;;
*)
path=-L$absdir/$objdir
;;
esac
else
eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
test -z "$libdir" && \
func_fatal_error "'$deplib' is not a valid libtool archive"
test "$absdir" != "$libdir" && \
func_warning "'$deplib' seems to be moved"
path=-L$absdir
fi
;;
esac
case " $deplibs " in
*" $path "*) ;;
*) deplibs="$path $deplibs" ;;
esac
done
fi # link_all_deplibs != no
fi # linkmode = lib
done # for deplib in $libs
func_append temp_rpath "$temp_rpath_tail"
func_append compile_rpath "$compile_rpath_tail"
if test link = "$pass"; then
if test prog = "$linkmode"; then
compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
else
compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
fi
fi
dependency_libs=$newdependency_libs
if test dlpreopen = "$pass"; then
# Link the dlpreopened libraries before other libraries
for deplib in $save_deplibs; do
deplibs="$deplib $deplibs"
done
fi
if test dlopen != "$pass"; then
test conv = "$pass" || {
# Make sure lib_search_path contains only unique directories.
lib_search_path=
for dir in $newlib_search_path; do
case "$lib_search_path " in
*" $dir "*) ;;
*) func_append lib_search_path " $dir" ;;
esac
done
newlib_search_path=
}
if test prog,link = "$linkmode,$pass"; then
vars="compile_deplibs finalize_deplibs"
else
vars=deplibs
fi
for var in $vars dependency_libs; do
# Add libraries to $var in reverse order
eval tmp_libs=\"\$$var\"
new_libs=
# FIXME: Pedantically, this is the right thing to do, so
# that some nasty dependency loop isn't accidentally
# broken: new_libs="$deplib $new_libs"
for deplib in $tmp_libs; do
if $opt_preserve_dup_deps; then
new_libs="$deplib $new_libs"
else
# Pragmatically, this seems to cause very few problems in
# practice:
case $deplib in
-L*) new_libs="$deplib $new_libs" ;;
-R*) ;;
*)
# And here is the reason: when a library appears more
# than once as an explicit dependence of a library, or
# is implicitly linked in more than once by the
# compiler, it is considered special, and multiple
# occurrences thereof are not removed. Compare this
# with having the same library being listed as a
# dependency of multiple other libraries: in this case,
# we know (pedantically, we assume) the library does not
# need to be listed more than once, so we keep only the
# last copy. This is not always right, but it is rare
# enough that we require users that really mean to play
# such unportable linking tricks to link the library
# using -Wl,-lname, so that libtool does not consider it
# for duplicate removal. And if not possible for portability
# reasons, then --preserve-dup-deps should be used.
case " $specialdeplibs " in
*" $deplib "*) new_libs="$deplib $new_libs" ;;
*)
case " $new_libs " in
*" $deplib "*) ;;
*) new_libs="$deplib $new_libs" ;;
esac
;;
esac
;;
esac
fi
done
tmp_libs=
for deplib in $new_libs; do
case $deplib in
-L*)
case " $tmp_libs " in
*" $deplib "*) ;;
*) func_append tmp_libs " $deplib" ;;
esac
;;
*) func_append tmp_libs " $deplib" ;;
esac
done
eval $var=\"$tmp_libs\"
done # for var
fi
# Add Sun CC postdeps if required:
test CXX = "$tagname" && {
case $host_os in
linux*)
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ C*) # Sun C++ 5.9
func_suncc_cstd_abi
if test no != "$suncc_use_cstd_abi"; then
func_append postdeps ' -library=Cstd -library=Crun'
fi
;;
esac
;;
solaris*)
func_cc_basename "$CC"
case $func_cc_basename_result in
CC* | sunCC*)
func_suncc_cstd_abi
if test no != "$suncc_use_cstd_abi"; then
func_append postdeps ' -library=Cstd -library=Crun'
fi
;;
esac
;;
esac
}
# Last step: remove runtime libs from dependency_libs
# (they stay in deplibs)
tmp_libs=
for i in $dependency_libs; do
case " $predeps $postdeps $compiler_lib_search_path " in
*" $i "*)
i=
;;
esac
if test -n "$i"; then
func_append tmp_libs " $i"
fi
done
dependency_libs=$tmp_libs
done # for pass
if test prog = "$linkmode"; then
dlfiles=$newdlfiles
fi
if test prog = "$linkmode" || test lib = "$linkmode"; then
dlprefiles=$newdlprefiles
fi
case $linkmode in
oldlib)
if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
func_warning "'-dlopen' is ignored for archives"
fi
case " $deplibs" in
*\ -l* | *\ -L*)
func_warning "'-l' and '-L' are ignored for archives" ;;
esac
test -n "$rpath" && \
func_warning "'-rpath' is ignored for archives"
test -n "$xrpath" && \
func_warning "'-R' is ignored for archives"
test -n "$vinfo" && \
func_warning "'-version-info/-version-number' is ignored for archives"
test -n "$release" && \
func_warning "'-release' is ignored for archives"
test -n "$export_symbols$export_symbols_regex" && \
func_warning "'-export-symbols' is ignored for archives"
# Now set the variables for building old libraries.
build_libtool_libs=no
oldlibs=$output
func_append objs "$old_deplibs"
;;
lib)
# Make sure we only generate libraries of the form 'libNAME.la'.
case $outputname in
lib*)
func_stripname 'lib' '.la' "$outputname"
name=$func_stripname_result
eval shared_ext=\"$shrext_cmds\"
eval libname=\"$libname_spec\"
;;
*)
test no = "$module" \
&& func_fatal_help "libtool library '$output' must begin with 'lib'"
if test no != "$need_lib_prefix"; then
# Add the "lib" prefix for modules if required
func_stripname '' '.la' "$outputname"
name=$func_stripname_result
eval shared_ext=\"$shrext_cmds\"
eval libname=\"$libname_spec\"
else
func_stripname '' '.la' "$outputname"
libname=$func_stripname_result
fi
;;
esac
if test -n "$objs"; then
if test pass_all != "$deplibs_check_method"; then
func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs"
else
func_warning "Linking the shared library $output against the non-libtool objects $objs is not portable!"
func_append libobjs " $objs"
fi
fi
test no = "$dlself" \
|| func_warning "'-dlopen self' is ignored for libtool libraries"
set dummy $rpath
shift
test 1 -lt "$#" \
&& func_warning "ignoring multiple '-rpath's for a libtool library"
install_libdir=$1
oldlibs=
if test -z "$rpath"; then
if test yes = "$build_libtool_libs"; then
# Building a libtool convenience library.
# Some compilers have problems with a '.al' extension so
# convenience libraries should have the same extension an
# archive normally would.
oldlibs="$output_objdir/$libname.$libext $oldlibs"
build_libtool_libs=convenience
build_old_libs=yes
fi
test -n "$vinfo" && \
func_warning "'-version-info/-version-number' is ignored for convenience libraries"
test -n "$release" && \
func_warning "'-release' is ignored for convenience libraries"
else
# Parse the version information argument.
save_ifs=$IFS; IFS=:
set dummy $vinfo 0 0 0
shift
IFS=$save_ifs
test -n "$7" && \
func_fatal_help "too many parameters to '-version-info'"
# convert absolute version numbers to libtool ages
# this retains compatibility with .la files and attempts
# to make the code below a bit more comprehensible
case $vinfo_number in
yes)
number_major=$1
number_minor=$2
number_revision=$3
#
# There are really only two kinds -- those that
# use the current revision as the major version
# and those that subtract age and use age as
# a minor version. But, then there is irix
# that has an extra 1 added just for fun
#
case $version_type in
# correct linux to gnu/linux during the next big refactor
darwin|freebsd-elf|linux|midnightbsd-elf|osf|qnx|windows|none)
func_arith $number_major + $number_minor
current=$func_arith_result
age=$number_minor
revision=$number_revision
;;
freebsd-aout|sco|sunos)
current=$number_major
revision=$number_minor
age=0
;;
irix|nonstopux)
func_arith $number_major + $number_minor
current=$func_arith_result
age=$number_minor
revision=$number_minor
lt_irix_increment=no
;;
*)
func_fatal_configuration "$modename: unknown library version type '$version_type'"
;;
esac
;;
no)
current=$1
revision=$2
age=$3
;;
esac
# Check that each of the things are valid numbers.
if echo "$current" | $EGREP -v '(^0$)|(^[1-9]$)|(^[1-9][0-9]{1,4}$)' > /dev/null; then
func_error "CURRENT '$current' must be a nonnegative integer and <= 5 digits"
func_fatal_error "'$vinfo' is not valid version information"
fi
# Currently limiting revision length by Unix epoch time in nanoseconds.
if echo "$revision" | $EGREP -v '(^0$)|(^[1-9]$)|(^[1-9][0-9]{1,18}$)' > /dev/null; then
func_error "REVISION '$revision' must be a nonnegative integer and <= 19 digits"
func_fatal_error "'$vinfo' is not valid version information"
fi
if echo "$age" | $EGREP -v '(^0$)|(^[1-9]$)|(^[1-9][0-9]{1,4}$)' > /dev/null; then
func_error "AGE '$age' must be a nonnegative integer and <= 5 digits"
func_fatal_error "'$vinfo' is not valid version information"
fi
if test "$age" -gt "$current"; then
func_error "AGE '$age' is greater than the current interface number '$current'"
func_fatal_error "'$vinfo' is not valid version information"
fi
# Calculate the version variables.
major=
versuffix=
verstring=
case $version_type in
none) ;;
darwin)
# Like Linux, but with the current version available in
# verstring for coding it into the library header
func_arith $current - $age
major=.$func_arith_result
versuffix=$major.$age.$revision
# Darwin ld doesn't like 0 for these options...
func_arith $current + 1
minor_current=$func_arith_result
xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
# On Darwin other compilers
case $CC in
nagfor*)
verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
;;
*)
verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
;;
esac
;;
freebsd-aout)
major=.$current
versuffix=.$current.$revision
;;
freebsd-elf | midnightbsd-elf)
func_arith $current - $age
major=.$func_arith_result
versuffix=$major.$age.$revision
;;
irix | nonstopux)
if test no = "$lt_irix_increment"; then
func_arith $current - $age
else
func_arith $current - $age + 1
fi
major=$func_arith_result
case $version_type in
nonstopux) verstring_prefix=nonstopux ;;
*) verstring_prefix=sgi ;;
esac
verstring=$verstring_prefix$major.$revision
# Add in all the interfaces that we are compatible with.
loop=$revision
while test 0 -ne "$loop"; do
func_arith $revision - $loop
iface=$func_arith_result
func_arith $loop - 1
loop=$func_arith_result
verstring=$verstring_prefix$major.$iface:$verstring
done
# Before this point, $major must not contain '.'.
major=.$major
versuffix=$major.$revision
;;
linux) # correct to gnu/linux during the next big refactor
func_arith $current - $age
major=.$func_arith_result
versuffix=$major.$age.$revision
;;
osf)
func_arith $current - $age
major=.$func_arith_result
versuffix=.$current.$age.$revision
verstring=$current.$age.$revision
# Add in all the interfaces that we are compatible with.
loop=$age
while test 0 -ne "$loop"; do
func_arith $current - $loop
iface=$func_arith_result
func_arith $loop - 1
loop=$func_arith_result
verstring=$verstring:$iface.0
done
# Make executables depend on our current version.
func_append verstring ":$current.0"
;;
qnx)
func_arith $current - $age
major=.$func_arith_result
versuffix=$major.$age.$revision
;;
sco)
major=.$current
versuffix=.$current
;;
sunos)
major=.$current
versuffix=.$current.$revision
;;
windows)
# Use '-' rather than '.', since we only want one
# extension on DOS 8.3 file systems.
func_arith $current - $age
major=$func_arith_result
versuffix=-$major
;;
*)
func_fatal_configuration "unknown library version type '$version_type'"
;;
esac
# Clear the version info if we defaulted, and they specified a release.
if test -z "$vinfo" && test -n "$release"; then
major=
case $version_type in
darwin)
# we can't check for "0.0" in archive_cmds due to quoting
# problems, so we reset it completely
verstring=
;;
*)
verstring=0.0
;;
esac
if test no = "$need_version"; then
versuffix=
else
versuffix=.0.0
fi
fi
# Remove version info from name if versioning should be avoided
if test yes,no = "$avoid_version,$need_version"; then
major=
versuffix=
verstring=
fi
# Check to see if the archive will have undefined symbols.
if test yes = "$allow_undefined"; then
if test unsupported = "$allow_undefined_flag"; then
if test yes = "$build_old_libs"; then
func_warning "undefined symbols not allowed in $host shared libraries; building static only"
build_libtool_libs=no
else
func_fatal_error "can't build $host shared library unless -no-undefined is specified"
fi
fi
else
# Don't allow undefined symbols.
allow_undefined_flag=$no_undefined_flag
fi
fi
func_generate_dlsyms "$libname" "$libname" :
func_append libobjs " $symfileobj"
test " " = "$libobjs" && libobjs=
if test relink != "$opt_mode"; then
# Remove our outputs, but don't remove object files since they
# may have been created when compiling PIC objects.
removelist=
tempremovelist=`$ECHO "$output_objdir/*"`
for p in $tempremovelist; do
case $p in
*.$objext | *.gcno)
;;
$output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*)
if test -n "$precious_files_regex"; then
if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
then
continue
fi
fi
func_append removelist " $p"
;;
*) ;;
esac
done
test -n "$removelist" && \
func_show_eval "${RM}r \$removelist"
fi
# Now set the variables for building old libraries.
if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then
func_append oldlibs " $output_objdir/$libname.$libext"
# Transform .lo files to .o files.
oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP`
fi
# Eliminate all temporary directories.
#for path in $notinst_path; do
# lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
# deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
# dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
#done
if test -n "$xrpath"; then
# If the user specified any rpath flags, then add them.
temp_xrpath=
for libdir in $xrpath; do
func_replace_sysroot "$libdir"
func_append temp_xrpath " -R$func_replace_sysroot_result"
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
done
if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then
dependency_libs="$temp_xrpath $dependency_libs"
fi
fi
# Make sure dlfiles contains only unique files that won't be dlpreopened
old_dlfiles=$dlfiles
dlfiles=
for lib in $old_dlfiles; do
case " $dlprefiles $dlfiles " in
*" $lib "*) ;;
*) func_append dlfiles " $lib" ;;
esac
done
# Make sure dlprefiles contains only unique files
old_dlprefiles=$dlprefiles
dlprefiles=
for lib in $old_dlprefiles; do
case "$dlprefiles " in
*" $lib "*) ;;
*) func_append dlprefiles " $lib" ;;
esac
done
if test yes = "$build_libtool_libs"; then
if test -n "$rpath"; then
case $host in
*-*-cygwin* | *-*-mingw* | *-*-windows* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
# these systems don't actually have a c library (as such)!
;;
*-*-rhapsody* | *-*-darwin1.[012])
# Rhapsody C library is in the System framework
func_append deplibs " System.ltframework"
;;
*-*-netbsd*)
# Don't link with libc until the a.out ld.so is fixed.
;;
*-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-midnightbsd*)
# Do not include libc due to us having libc/libc_r.
;;
*-*-sco3.2v5* | *-*-sco5v6*)
# Causes problems with __ctype
;;
*-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
# Compiler inserts libc in the correct place for threads to work
;;
*)
# Add libc to deplibs on all other systems if necessary.
if test yes = "$build_libtool_need_lc"; then
func_append deplibs " -lc"
fi
;;
esac
fi
# Transform deplibs into only deplibs that can be linked in shared.
name_save=$name
libname_save=$libname
release_save=$release
versuffix_save=$versuffix
major_save=$major
# I'm not sure if I'm treating the release correctly. I think
# release should show up in the -l (ie -lgmp5) so we don't want to
# add it in twice. Is that correct?
release=
versuffix=
major=
newdeplibs=
droppeddeps=no
case $deplibs_check_method in
pass_all)
# Don't check for shared/static. Everything works.
# This might be a little naive. We might want to check
# whether the library exists or not. But this is on
# osf3 & osf4 and I'm not really sure... Just
# implementing what was already the behavior.
newdeplibs=$deplibs
;;
file_magic*)
set dummy $deplibs_check_method; shift
file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
for a_deplib in $deplibs; do
case $a_deplib in
-l*)
func_stripname -l '' "$a_deplib"
name=$func_stripname_result
if test yes = "$allow_libtool_libs_with_static_runtimes"; then
case " $predeps $postdeps " in
*" $a_deplib "*)
func_append newdeplibs " $a_deplib"
a_deplib=
;;
esac
fi
if test -n "$a_deplib"; then
libname=`eval "\\$ECHO \"$libname_spec\""`
if test -n "$file_magic_glob"; then
libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob`
else
libnameglob=$libname
fi
test yes = "$want_nocaseglob" && nocaseglob=`shopt -p nocaseglob`
for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
if test yes = "$want_nocaseglob"; then
shopt -s nocaseglob
potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
$nocaseglob
else
potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
fi
for potent_lib in $potential_libs; do
# Follow soft links.
if ls -lLd "$potent_lib" 2>/dev/null |
$GREP " -> " >/dev/null; then
continue
fi
# The statement above tries to avoid entering an
# endless loop below, in case of cyclic links.
# We might still enter an endless loop, since a link
# loop can be closed while we follow links,
# but so what?
potlib=$potent_lib
while test -h "$potlib" 2>/dev/null; do
potliblink=`ls -ld $potlib | $SED 's/.* -> //'`
case $potliblink in
[\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;;
*) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";;
esac
done
if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
$SED -e 10q |
$EGREP "$file_magic_regex" > /dev/null; then
func_append newdeplibs " $a_deplib"
a_deplib=
break 2
fi
done
done
fi
if test -n "$a_deplib"; then
droppeddeps=yes
func_warning "Linker path does not have real file for library $a_deplib."
func_warning "I have the capability to make that library automatically link in when"
func_warning "you link to this library. But I can only do this if you have a"
func_warning "shared version of the library, which you do not appear to have"
func_warning "because I did check the linker path looking for a file starting"
if test -z "$potlib"; then
func_warning "with $libname but no candidates were found. (...for file magic test)"
else
func_warning "with $libname and none of the candidates passed a file format test"
func_warning "using a file magic. Last file checked: $potlib"
fi
fi
;;
*)
# Add a -L argument.
func_append newdeplibs " $a_deplib"
;;
esac
done # Gone through all deplibs.
;;
match_pattern*)
set dummy $deplibs_check_method; shift
match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
for a_deplib in $deplibs; do
case $a_deplib in
-l*)
func_stripname -l '' "$a_deplib"
name=$func_stripname_result
if test yes = "$allow_libtool_libs_with_static_runtimes"; then
case " $predeps $postdeps " in
*" $a_deplib "*)
func_append newdeplibs " $a_deplib"
a_deplib=
;;
esac
fi
if test -n "$a_deplib"; then
libname=`eval "\\$ECHO \"$libname_spec\""`
for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
for potent_lib in $potential_libs; do
potlib=$potent_lib # see symlink-check above in file_magic test
if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
$EGREP "$match_pattern_regex" > /dev/null; then
func_append newdeplibs " $a_deplib"
a_deplib=
break 2
fi
done
done
fi
if test -n "$a_deplib"; then
droppeddeps=yes
func_warning "Linker path does not have real file for library $a_deplib."
func_warning "I have the capability to make that library automatically link in when"
func_warning "you link to this library. But I can only do this if you have a"
func_warning "shared version of the library, which you do not appear to have"
func_warning "because I did check the linker path looking for a file starting"
if test -z "$potlib"; then
func_warning "with $libname but no candidates were found. (...for regex pattern test)"
else
func_warning "with $libname and none of the candidates passed a file format test"
func_warning "using a regex pattern. Last file checked: $potlib"
fi
fi
;;
*)
# Add a -L argument.
func_append newdeplibs " $a_deplib"
;;
esac
done # Gone through all deplibs.
;;
none | unknown | *)
newdeplibs=
tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
if test yes = "$allow_libtool_libs_with_static_runtimes"; then
for i in $predeps $postdeps; do
# can't use Xsed below, because $i might contain '/'
tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"`
done
fi
case $tmp_deplibs in
*[!\ \ ]*)
echo
if test none = "$deplibs_check_method"; then
func_warning "Inter-library dependencies are not supported in this platform."
else
func_warning "Inter-library dependencies are not known to be supported."
fi
func_warning "All declared inter-library dependencies are being dropped."
droppeddeps=yes
;;
esac
;;
esac
versuffix=$versuffix_save
major=$major_save
release=$release_save
libname=$libname_save
name=$name_save
case $host in
*-*-rhapsody* | *-*-darwin1.[012])
# On Rhapsody replace the C library with the System framework
newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
;;
esac
if test yes = "$droppeddeps"; then
if test yes = "$module"; then
func_warning "libtool could not satisfy all declared inter-library"
func_warning "dependencies of module $libname. Therefore, libtool will create"
func_warning "a static module, that should work as long as the dlopening"
func_warning "application is linked with the -dlopen flag."
if test -z "$global_symbol_pipe"; then
func_warning "However, this would only work if libtool was able to extract symbol"
func_warning "lists from a program, using 'nm' or equivalent, but libtool could"
func_warning "not find such a program. So, this module is probably useless."
func_warning "'nm' from GNU binutils and a full rebuild may help."
fi
if test no = "$build_old_libs"; then
oldlibs=$output_objdir/$libname.$libext
build_libtool_libs=module
build_old_libs=yes
else
build_libtool_libs=no
fi
else
echo "*** The inter-library dependencies that have been dropped here will be"
echo "*** automatically added whenever a program is linked with this library"
echo "*** or is declared to -dlopen it."
if test no = "$allow_undefined"; then
echo
echo "*** Since this library must not contain undefined symbols,"
echo "*** because either the platform does not support them or"
echo "*** it was explicitly requested with -no-undefined,"
echo "*** libtool will only create a static version of it."
if test no = "$build_old_libs"; then
oldlibs=$output_objdir/$libname.$libext
build_libtool_libs=module
build_old_libs=yes
else
build_libtool_libs=no
fi
fi
fi
fi
# Done checking deplibs!
deplibs=$newdeplibs
fi
# Time to change all our "foo.ltframework" stuff back to "-framework foo"
case $host in
*-*-darwin*)
newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
;;
esac
# move library search paths that coincide with paths to not yet
# installed libraries to the beginning of the library search list
new_libs=
for path in $notinst_path; do
case " $new_libs " in
*" -L$path/$objdir "*) ;;
*)
case " $deplibs " in
*" -L$path/$objdir "*)
func_append new_libs " -L$path/$objdir" ;;
esac
;;
esac
done
for deplib in $deplibs; do
case $deplib in
-L*)
case " $new_libs " in
*" $deplib "*) ;;
*) func_append new_libs " $deplib" ;;
esac
;;
*) func_append new_libs " $deplib" ;;
esac
done
deplibs=$new_libs
# All the library-specific variables (install_libdir is set above).
library_names=
old_library=
dlname=
# Test again, we may have decided not to build it any more
if test yes = "$build_libtool_libs"; then
# Remove $wl instances when linking with ld.
# FIXME: should test the right _cmds variable.
case $archive_cmds in
*\$LD\ *) wl= ;;
esac
if test yes = "$hardcode_into_libs"; then
# Hardcode the library paths
hardcode_libdirs=
dep_rpath=
rpath=$finalize_rpath
test relink = "$opt_mode" || rpath=$compile_rpath$rpath
for libdir in $rpath; do
if test -n "$hardcode_libdir_flag_spec"; then
if test -n "$hardcode_libdir_separator"; then
func_replace_sysroot "$libdir"
libdir=$func_replace_sysroot_result
if test -z "$hardcode_libdirs"; then
hardcode_libdirs=$libdir
else
# Just accumulate the unique libdirs.
case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
*"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
;;
*)
func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
;;
esac
fi
else
eval flag=\"$hardcode_libdir_flag_spec\"
func_append dep_rpath " $flag"
fi
elif test -n "$runpath_var"; then
case "$perm_rpath " in
*" $libdir "*) ;;
*) func_append perm_rpath " $libdir" ;;
esac
fi
done
# Substitute the hardcoded libdirs into the rpath.
if test -n "$hardcode_libdir_separator" &&
test -n "$hardcode_libdirs"; then
libdir=$hardcode_libdirs
eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
fi
if test -n "$runpath_var" && test -n "$perm_rpath"; then
# We should set the runpath_var.
rpath=
for dir in $perm_rpath; do
func_append rpath "$dir:"
done
eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
fi
test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
fi
shlibpath=$finalize_shlibpath
test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath
if test -n "$shlibpath"; then
eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
fi
# Get the real and link names of the library.
eval shared_ext=\"$shrext_cmds\"
eval library_names=\"$library_names_spec\"
set dummy $library_names
shift
realname=$1
shift
if test -n "$soname_spec"; then
eval soname=\"$soname_spec\"
else
soname=$realname
fi
if test -z "$dlname"; then
dlname=$soname
fi
lib=$output_objdir/$realname
linknames=
for link
do
func_append linknames " $link"
done
# Use standard objects if they are pic
test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
test "X$libobjs" = "X " && libobjs=
delfiles=
if test -n "$export_symbols" && test -n "$include_expsyms"; then
$opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
export_symbols=$output_objdir/$libname.uexp
func_append delfiles " $export_symbols"
fi
orig_export_symbols=
case $host_os in
cygwin* | mingw* | windows* | cegcc*)
if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
# exporting using user supplied symfile
func_dll_def_p "$export_symbols" || {
# and it's NOT already a .def file. Must figure out
# which of the given symbols are data symbols and tag
# them as such. So, trigger use of export_symbols_cmds.
# export_symbols gets reassigned inside the "prepare
# the list of exported symbols" if statement, so the
# include_expsyms logic still works.
orig_export_symbols=$export_symbols
export_symbols=
always_export_symbols=yes
}
fi
;;
esac
# Prepare the list of exported symbols
if test -z "$export_symbols"; then
if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then
func_verbose "generating symbol list for '$libname.la'"
export_symbols=$output_objdir/$libname.expsym
$opt_dry_run || $RM $export_symbols
cmds=$export_symbols_cmds
save_ifs=$IFS; IFS='~'
for cmd1 in $cmds; do
IFS=$save_ifs
# Take the normal branch if the nm_file_list_spec branch
# doesn't work or if tool conversion is not needed.
case $nm_file_list_spec~$to_tool_file_cmd in
*~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
try_normal_branch=yes
eval cmd=\"$cmd1\"
func_len " $cmd"
len=$func_len_result
;;
*)
try_normal_branch=no
;;
esac
if test yes = "$try_normal_branch" \
&& { test "$len" -lt "$max_cmd_len" \
|| test "$max_cmd_len" -le -1; }
then
func_show_eval "$cmd" 'exit $?'
skipped_export=false
elif test -n "$nm_file_list_spec"; then
func_basename "$output"
output_la=$func_basename_result
save_libobjs=$libobjs
save_output=$output
output=$output_objdir/$output_la.nm
func_to_tool_file "$output"
libobjs=$nm_file_list_spec$func_to_tool_file_result
func_append delfiles " $output"
func_verbose "creating $NM input file list: $output"
for obj in $save_libobjs; do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result"
done > "$output"
eval cmd=\"$cmd1\"
func_show_eval "$cmd" 'exit $?'
output=$save_output
libobjs=$save_libobjs
skipped_export=false
else
# The command line is too long to execute in one step.
func_verbose "using reloadable object file for export list..."
skipped_export=:
# Break out early, otherwise skipped_export may be
# set to false by a later but shorter cmd.
break
fi
done
IFS=$save_ifs
if test -n "$export_symbols_regex" && test : != "$skipped_export"; then
func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
fi
fi
fi
if test -n "$export_symbols" && test -n "$include_expsyms"; then
tmp_export_symbols=$export_symbols
test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
$opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
fi
if test : != "$skipped_export" && test -n "$orig_export_symbols"; then
# The given exports_symbols file has to be filtered, so filter it.
func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
# FIXME: $output_objdir/$libname.filter potentially contains lots of
# 's' commands, which not all seds can handle. GNU sed should be fine
# though. Also, the filter scales superlinearly with the number of
# global variables. join(1) would be nice here, but unfortunately
# isn't a blessed tool.
$opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
func_append delfiles " $export_symbols $output_objdir/$libname.filter"
export_symbols=$output_objdir/$libname.def
$opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
fi
tmp_deplibs=
for test_deplib in $deplibs; do
case " $convenience " in
*" $test_deplib "*) ;;
*)
func_append tmp_deplibs " $test_deplib"
;;
esac
done
deplibs=$tmp_deplibs
if test -n "$convenience"; then
if test -n "$whole_archive_flag_spec" &&
test yes = "$compiler_needs_object" &&
test -z "$libobjs"; then
# extract the archives, so we have objects to list.
# TODO: could optimize this to just extract one archive.
whole_archive_flag_spec=
fi
if test -n "$whole_archive_flag_spec"; then
save_libobjs=$libobjs
eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
test "X$libobjs" = "X " && libobjs=
else
gentop=$output_objdir/${outputname}x
func_append generated " $gentop"
func_extract_archives $gentop $convenience
func_append libobjs " $func_extract_archives_result"
test "X$libobjs" = "X " && libobjs=
fi
fi
if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then
eval flag=\"$thread_safe_flag_spec\"
func_append linker_flags " $flag"
fi
# Make a backup of the uninstalled library when relinking
if test relink = "$opt_mode"; then
$opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
fi
# Do each of the archive commands.
if test yes = "$module" && test -n "$module_cmds"; then
if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
eval test_cmds=\"$module_expsym_cmds\"
cmds=$module_expsym_cmds
else
eval test_cmds=\"$module_cmds\"
cmds=$module_cmds
fi
else
if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
eval test_cmds=\"$archive_expsym_cmds\"
cmds=$archive_expsym_cmds
else
eval test_cmds=\"$archive_cmds\"
cmds=$archive_cmds
fi
fi
if test : != "$skipped_export" &&
func_len " $test_cmds" &&
len=$func_len_result &&
test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
:
else
# The command line is too long to link in one step, link piecewise
# or, if using GNU ld and skipped_export is not :, use a linker
# script.
# Save the value of $output and $libobjs because we want to
# use them later. If we have whole_archive_flag_spec, we
# want to use save_libobjs as it was before
# whole_archive_flag_spec was expanded, because we can't
# assume the linker understands whole_archive_flag_spec.
# This may have to be revisited, in case too many
# convenience libraries get linked in and end up exceeding
# the spec.
if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
save_libobjs=$libobjs
fi
save_output=$output
func_basename "$output"
output_la=$func_basename_result
# Clear the reloadable object creation command queue and
# initialize k to one.
test_cmds=
concat_cmds=
objlist=
last_robj=
k=1
if test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then
output=$output_objdir/$output_la.lnk
func_verbose "creating linker input file list: $output"
: > $output
set x $save_libobjs
shift
firstobj=
if test yes = "$compiler_needs_object"; then
firstobj="$1 "
shift
fi
for obj
do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result" >> $output
done
func_append delfiles " $output"
func_to_tool_file "$output"
output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
elif test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then
output=$output_objdir/$output_la.lnkscript
func_verbose "creating GNU ld script: $output"
echo 'INPUT (' > $output
for obj in $save_libobjs
do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result" >> $output
done
echo ')' >> $output
func_append delfiles " $output"
func_to_tool_file "$output"
output=$func_to_tool_file_result
else
if test -n "$save_libobjs"; then
func_verbose "creating reloadable object files..."
output=$output_objdir/$output_la-$k.$objext
eval test_cmds=\"$reload_cmds\"
func_len " $test_cmds"
len0=$func_len_result
len=$len0
# Loop over the list of objects to be linked.
for obj in $save_libobjs
do
func_len " $obj"
func_arith $len + $func_len_result
len=$func_arith_result
if test -z "$objlist" ||
test "$len" -lt "$max_cmd_len"; then
func_append objlist " $obj"
else
# The command $test_cmds is almost too long, add a
# command to the queue.
if test 1 -eq "$k"; then
# The first file doesn't have a previous command to add.
reload_objs=$objlist
eval concat_cmds=\"$reload_cmds\"
else
# All subsequent reloadable object files will link in
# the last one created.
reload_objs="$objlist $last_robj"
eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
fi
last_robj=$output_objdir/$output_la-$k.$objext
func_arith $k + 1
k=$func_arith_result
output=$output_objdir/$output_la-$k.$objext
objlist=" $obj"
func_len " $last_robj"
func_arith $len0 + $func_len_result
len=$func_arith_result
fi
done
# Handle the remaining objects by creating one last
# reloadable object file. All subsequent reloadable object
# files will link in the last one created.
test -z "$concat_cmds" || concat_cmds=$concat_cmds~
reload_objs="$objlist $last_robj"
eval concat_cmds=\"\$concat_cmds$reload_cmds\"
if test -n "$last_robj"; then
eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
fi
func_append delfiles " $output"
else
output=
fi
${skipped_export-false} && {
func_verbose "generating symbol list for '$libname.la'"
export_symbols=$output_objdir/$libname.expsym
$opt_dry_run || $RM $export_symbols
libobjs=$output
# Append the command to create the export file.
test -z "$concat_cmds" || concat_cmds=$concat_cmds~
eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
if test -n "$last_robj"; then
eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
fi
}
test -n "$save_libobjs" &&
func_verbose "creating a temporary reloadable object file: $output"
# Loop through the commands generated above and execute them.
save_ifs=$IFS; IFS='~'
for cmd in $concat_cmds; do
IFS=$save_ifs
$opt_quiet || {
func_quote_arg expand,pretty "$cmd"
eval "func_echo $func_quote_arg_result"
}
$opt_dry_run || eval "$cmd" || {
lt_exit=$?
# Restore the uninstalled library and exit
if test relink = "$opt_mode"; then
( cd "$output_objdir" && \
$RM "${realname}T" && \
$MV "${realname}U" "$realname" )
fi
exit $lt_exit
}
done
IFS=$save_ifs
if test -n "$export_symbols_regex" && ${skipped_export-false}; then
func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
fi
fi
${skipped_export-false} && {
if test -n "$export_symbols" && test -n "$include_expsyms"; then
tmp_export_symbols=$export_symbols
test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
$opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
fi
if test -n "$orig_export_symbols"; then
# The given exports_symbols file has to be filtered, so filter it.
func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
# FIXME: $output_objdir/$libname.filter potentially contains lots of
# 's' commands, which not all seds can handle. GNU sed should be fine
# though. Also, the filter scales superlinearly with the number of
# global variables. join(1) would be nice here, but unfortunately
# isn't a blessed tool.
$opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
func_append delfiles " $export_symbols $output_objdir/$libname.filter"
export_symbols=$output_objdir/$libname.def
$opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
fi
}
libobjs=$output
# Restore the value of output.
output=$save_output
if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
test "X$libobjs" = "X " && libobjs=
fi
# Expand the library linking commands again to reset the
# value of $libobjs for piecewise linking.
# Do each of the archive commands.
if test yes = "$module" && test -n "$module_cmds"; then
if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
cmds=$module_expsym_cmds
else
cmds=$module_cmds
fi
else
if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
cmds=$archive_expsym_cmds
else
cmds=$archive_cmds
fi
fi
fi
if test -n "$delfiles"; then
# Append the command to remove temporary files to $cmds.
eval cmds=\"\$cmds~\$RM $delfiles\"
fi
# Add any objects from preloaded convenience libraries
if test -n "$dlprefiles"; then
gentop=$output_objdir/${outputname}x
func_append generated " $gentop"
func_extract_archives $gentop $dlprefiles
func_append libobjs " $func_extract_archives_result"
test "X$libobjs" = "X " && libobjs=
fi
save_ifs=$IFS; IFS='~'
for cmd in $cmds; do
IFS=$sp$nl
eval cmd=\"$cmd\"
IFS=$save_ifs
$opt_quiet || {
func_quote_arg expand,pretty "$cmd"
eval "func_echo $func_quote_arg_result"
}
$opt_dry_run || eval "$cmd" || {
lt_exit=$?
# Restore the uninstalled library and exit
if test relink = "$opt_mode"; then
( cd "$output_objdir" && \
$RM "${realname}T" && \
$MV "${realname}U" "$realname" )
fi
exit $lt_exit
}
done
IFS=$save_ifs
# Restore the uninstalled library and exit
if test relink = "$opt_mode"; then
$opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
if test -n "$convenience"; then
if test -z "$whole_archive_flag_spec"; then
func_show_eval '${RM}r "$gentop"'
fi
fi
exit $EXIT_SUCCESS
fi
# Create links to the real library.
for linkname in $linknames; do
if test "$realname" != "$linkname"; then
func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
fi
done
# If -module or -export-dynamic was specified, set the dlname.
if test yes = "$module" || test yes = "$export_dynamic"; then
# On all known operating systems, these are identical.
dlname=$soname
fi
fi
;;
obj)
if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
func_warning "'-dlopen' is ignored for objects"
fi
case " $deplibs" in
*\ -l* | *\ -L*)
func_warning "'-l' and '-L' are ignored for objects" ;;
esac
test -n "$rpath" && \
func_warning "'-rpath' is ignored for objects"
test -n "$xrpath" && \
func_warning "'-R' is ignored for objects"
test -n "$vinfo" && \
func_warning "'-version-info' is ignored for objects"
test -n "$release" && \
func_warning "'-release' is ignored for objects"
case $output in
*.lo)
test -n "$objs$old_deplibs" && \
func_fatal_error "cannot build library object '$output' from non-libtool objects"
libobj=$output
func_lo2o "$libobj"
obj=$func_lo2o_result
;;
*)
libobj=
obj=$output
;;
esac
# Delete the old objects.
$opt_dry_run || $RM $obj $libobj
# Objects from convenience libraries. This assumes
# single-version convenience libraries. Whenever we create
# different ones for PIC/non-PIC, this we'll have to duplicate
# the extraction.
reload_conv_objs=
gentop=
# if reload_cmds runs $LD directly, get rid of -Wl from
# whole_archive_flag_spec and hope we can get by with turning comma
# into space.
case $reload_cmds in
*\$LD[\ \$]*) wl= ;;
esac
if test -n "$convenience"; then
if test -n "$whole_archive_flag_spec"; then
eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags
else
gentop=$output_objdir/${obj}x
func_append generated " $gentop"
func_extract_archives $gentop $convenience
reload_conv_objs="$reload_objs $func_extract_archives_result"
fi
fi
# If we're not building shared, we need to use non_pic_objs
test yes = "$build_libtool_libs" || libobjs=$non_pic_objects
# Create the old-style object.
reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs
output=$obj
func_execute_cmds "$reload_cmds" 'exit $?'
# Exit if we aren't doing a library object file.
if test -z "$libobj"; then
if test -n "$gentop"; then
func_show_eval '${RM}r "$gentop"'
fi
exit $EXIT_SUCCESS
fi
test yes = "$build_libtool_libs" || {
if test -n "$gentop"; then
func_show_eval '${RM}r "$gentop"'
fi
# Create an invalid libtool object if no PIC, so that we don't
# accidentally link it into a program.
# $show "echo timestamp > $libobj"
# $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
exit $EXIT_SUCCESS
}
if test -n "$pic_flag" || test default != "$pic_mode"; then
# Only do commands if we really have different PIC objects.
reload_objs="$libobjs $reload_conv_objs"
output=$libobj
func_execute_cmds "$reload_cmds" 'exit $?'
fi
if test -n "$gentop"; then
func_show_eval '${RM}r "$gentop"'
fi
exit $EXIT_SUCCESS
;;
prog)
case $host in
*cygwin*) func_stripname '' '.exe' "$output"
output=$func_stripname_result.exe;;
esac
test -n "$vinfo" && \
func_warning "'-version-info' is ignored for programs"
test -n "$release" && \
func_warning "'-release' is ignored for programs"
$preload \
&& test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \
&& func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support."
case $host in
*-*-rhapsody* | *-*-darwin1.[012])
# On Rhapsody replace the C library is the System framework
compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
;;
esac
case $host in
*-*-darwin*)
# Don't allow lazy linking, it breaks C++ global constructors
# But is supposedly fixed on 10.4 or later (yay!).
if test CXX = "$tagname"; then
case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
10.[0123])
func_append compile_command " $wl-bind_at_load"
func_append finalize_command " $wl-bind_at_load"
;;
esac
fi
# Time to change all our "foo.ltframework" stuff back to "-framework foo"
compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
;;
esac
# move library search paths that coincide with paths to not yet
# installed libraries to the beginning of the library search list
new_libs=
for path in $notinst_path; do
case " $new_libs " in
*" -L$path/$objdir "*) ;;
*)
case " $compile_deplibs " in
*" -L$path/$objdir "*)
func_append new_libs " -L$path/$objdir" ;;
esac
;;
esac
done
for deplib in $compile_deplibs; do
case $deplib in
-L*)
case " $new_libs " in
*" $deplib "*) ;;
*) func_append new_libs " $deplib" ;;
esac
;;
*) func_append new_libs " $deplib" ;;
esac
done
compile_deplibs=$new_libs
func_append compile_command " $compile_deplibs"
func_append finalize_command " $finalize_deplibs"
if test -n "$rpath$xrpath"; then
# If the user specified any rpath flags, then add them.
for libdir in $rpath $xrpath; do
# This is the magic to use -rpath.
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
done
fi
# Now hardcode the library paths
rpath=
hardcode_libdirs=
for libdir in $compile_rpath $finalize_rpath; do
if test -n "$hardcode_libdir_flag_spec"; then
if test -n "$hardcode_libdir_separator"; then
if test -z "$hardcode_libdirs"; then
hardcode_libdirs=$libdir
else
# Just accumulate the unique libdirs.
case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
*"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
;;
*)
func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
;;
esac
fi
else
eval flag=\"$hardcode_libdir_flag_spec\"
func_append rpath " $flag"
fi
elif test -n "$runpath_var"; then
case "$perm_rpath " in
*" $libdir "*) ;;
*) func_append perm_rpath " $libdir" ;;
esac
fi
case $host in
*-*-cygwin* | *-*-mingw* | *-*-windows* | *-*-pw32* | *-*-os2* | *-cegcc*)
testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'`
case :$dllsearchpath: in
*":$libdir:"*) ;;
::) dllsearchpath=$libdir;;
*) func_append dllsearchpath ":$libdir";;
esac
case :$dllsearchpath: in
*":$testbindir:"*) ;;
::) dllsearchpath=$testbindir;;
*) func_append dllsearchpath ":$testbindir";;
esac
;;
esac
done
# Substitute the hardcoded libdirs into the rpath.
if test -n "$hardcode_libdir_separator" &&
test -n "$hardcode_libdirs"; then
libdir=$hardcode_libdirs
eval rpath=\" $hardcode_libdir_flag_spec\"
fi
compile_rpath=$rpath
rpath=
hardcode_libdirs=
for libdir in $finalize_rpath; do
if test -n "$hardcode_libdir_flag_spec"; then
if test -n "$hardcode_libdir_separator"; then
if test -z "$hardcode_libdirs"; then
hardcode_libdirs=$libdir
else
# Just accumulate the unique libdirs.
case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
*"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
;;
*)
func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
;;
esac
fi
else
eval flag=\"$hardcode_libdir_flag_spec\"
func_append rpath " $flag"
fi
elif test -n "$runpath_var"; then
case "$finalize_perm_rpath " in
*" $libdir "*) ;;
*) func_append finalize_perm_rpath " $libdir" ;;
esac
fi
done
# Substitute the hardcoded libdirs into the rpath.
if test -n "$hardcode_libdir_separator" &&
test -n "$hardcode_libdirs"; then
libdir=$hardcode_libdirs
eval rpath=\" $hardcode_libdir_flag_spec\"
fi
finalize_rpath=$rpath
if test -n "$libobjs" && test yes = "$build_old_libs"; then
# Transform all the library objects into standard objects.
compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
fi
func_generate_dlsyms "$outputname" "@PROGRAM@" false
# template prelinking step
if test -n "$prelink_cmds"; then
func_execute_cmds "$prelink_cmds" 'exit $?'
fi
wrappers_required=:
case $host in
*cegcc* | *mingw32ce*)
# Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
wrappers_required=false
;;
*cygwin* | *mingw* | *windows* )
test yes = "$build_libtool_libs" || wrappers_required=false
;;
*)
if test no = "$need_relink" || test yes != "$build_libtool_libs"; then
wrappers_required=false
fi
;;
esac
$wrappers_required || {
# Replace the output file specification.
compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
link_command=$compile_command$compile_rpath
# We have no uninstalled library dependencies, so finalize right now.
exit_status=0
func_show_eval "$link_command" 'exit_status=$?'
if test -n "$postlink_cmds"; then
func_to_tool_file "$output"
postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
func_execute_cmds "$postlink_cmds" 'exit $?'
fi
# Delete the generated files.
if test -f "$output_objdir/${outputname}S.$objext"; then
func_show_eval '$RM "$output_objdir/${outputname}S.$objext"'
fi
exit $exit_status
}
if test -n "$compile_shlibpath$finalize_shlibpath"; then
compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
fi
if test -n "$finalize_shlibpath"; then
finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
fi
compile_var=
finalize_var=
if test -n "$runpath_var"; then
if test -n "$perm_rpath"; then
# We should set the runpath_var.
rpath=
for dir in $perm_rpath; do
func_append rpath "$dir:"
done
compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
fi
if test -n "$finalize_perm_rpath"; then
# We should set the runpath_var.
rpath=
for dir in $finalize_perm_rpath; do
func_append rpath "$dir:"
done
finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
fi
fi
if test yes = "$no_install"; then
# We don't need to create a wrapper script.
link_command=$compile_var$compile_command$compile_rpath
# Replace the output file specification.
link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
# Delete the old output file.
$opt_dry_run || $RM $output
# Link the executable and exit
func_show_eval "$link_command" 'exit $?'
if test -n "$postlink_cmds"; then
func_to_tool_file "$output"
postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
func_execute_cmds "$postlink_cmds" 'exit $?'
fi
exit $EXIT_SUCCESS
fi
case $hardcode_action,$fast_install in
relink,*)
# Fast installation is not supported
link_command=$compile_var$compile_command$compile_rpath
relink_command=$finalize_var$finalize_command$finalize_rpath
func_warning "this platform does not like uninstalled shared libraries"
func_warning "'$output' will be relinked during installation"
;;
*,yes)
link_command=$finalize_var$compile_command$finalize_rpath
relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
;;
*,no)
link_command=$compile_var$compile_command$compile_rpath
relink_command=$finalize_var$finalize_command$finalize_rpath
;;
*,needless)
link_command=$finalize_var$compile_command$finalize_rpath
relink_command=
;;
esac
# Replace the output file specification.
link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
# Delete the old output files.
$opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
func_show_eval "$link_command" 'exit $?'
if test -n "$postlink_cmds"; then
func_to_tool_file "$output_objdir/$outputname"
postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
func_execute_cmds "$postlink_cmds" 'exit $?'
fi
# Now create the wrapper script.
func_verbose "creating $output"
# Quote the relink command for shipping.
if test -n "$relink_command"; then
# Preserve any variables that may affect compiler behavior
for var in $variables_saved_for_relink; do
if eval test -z \"\${$var+set}\"; then
relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
elif eval var_value=\$$var; test -z "$var_value"; then
relink_command="$var=; export $var; $relink_command"
else
func_quote_arg pretty "$var_value"
relink_command="$var=$func_quote_arg_result; export $var; $relink_command"
fi
done
func_quote eval cd "`pwd`"
func_quote_arg pretty,unquoted "($func_quote_result; $relink_command)"
relink_command=$func_quote_arg_unquoted_result
fi
# Only actually do things if not in dry run mode.
$opt_dry_run || {
# win32 will think the script is a binary if it has
# a .exe suffix, so we strip it off here.
case $output in
*.exe) func_stripname '' '.exe' "$output"
output=$func_stripname_result ;;
esac
# test for cygwin because mv fails w/o .exe extensions
case $host in
*cygwin*)
exeext=.exe
func_stripname '' '.exe' "$outputname"
outputname=$func_stripname_result ;;
*) exeext= ;;
esac
case $host in
*cygwin* | *mingw* | windows* )
func_dirname_and_basename "$output" "" "."
output_name=$func_basename_result
output_path=$func_dirname_result
cwrappersource=$output_path/$objdir/lt-$output_name.c
cwrapper=$output_path/$output_name.exe
$RM $cwrappersource $cwrapper
trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
func_emit_cwrapperexe_src > $cwrappersource
# The wrapper executable is built using the $host compiler,
# because it contains $host paths and files. If cross-
# compiling, it, like the target executable, must be
# executed on the $host or under an emulation environment.
$opt_dry_run || {
$LTCC $LTCFLAGS -o $cwrapper $cwrappersource
$STRIP $cwrapper
}
# Now, create the wrapper script for func_source use:
func_ltwrapper_scriptname $cwrapper
$RM $func_ltwrapper_scriptname_result
trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
$opt_dry_run || {
# note: this script will not be executed, so do not chmod.
if test "x$build" = "x$host"; then
$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
else
func_emit_wrapper no > $func_ltwrapper_scriptname_result
fi
}
;;
* )
$RM $output
trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
func_emit_wrapper no > $output
chmod +x $output
;;
esac
}
exit $EXIT_SUCCESS
;;
esac
# See if we need to build an old-fashioned archive.
for oldlib in $oldlibs; do
case $build_libtool_libs in
convenience)
oldobjs="$libobjs_save $symfileobj"
addlibs=$convenience
build_libtool_libs=no
;;
module)
oldobjs=$libobjs_save
addlibs=$old_convenience
build_libtool_libs=no
;;
*)
oldobjs="$old_deplibs $non_pic_objects"
$preload && test -f "$symfileobj" \
&& func_append oldobjs " $symfileobj"
addlibs=$old_convenience
;;
esac
if test -n "$addlibs"; then
gentop=$output_objdir/${outputname}x
func_append generated " $gentop"
func_extract_archives $gentop $addlibs
func_append oldobjs " $func_extract_archives_result"
fi
# Do each command in the archive commands.
if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then
cmds=$old_archive_from_new_cmds
else
# Add any objects from preloaded convenience libraries
if test -n "$dlprefiles"; then
gentop=$output_objdir/${outputname}x
func_append generated " $gentop"
func_extract_archives $gentop $dlprefiles
func_append oldobjs " $func_extract_archives_result"
fi
# POSIX demands no paths to be encoded in archives. We have
# to avoid creating archives with duplicate basenames if we
# might have to extract them afterwards, e.g., when creating a
# static archive out of a convenience library, or when linking
# the entirety of a libtool archive into another (currently
# not supported by libtool).
if (for obj in $oldobjs
do
func_basename "$obj"
$ECHO "$func_basename_result"
done | sort | sort -uc >/dev/null 2>&1); then
:
else
echo "copying selected object files to avoid basename conflicts..."
gentop=$output_objdir/${outputname}x
func_append generated " $gentop"
func_mkdir_p "$gentop"
save_oldobjs=$oldobjs
oldobjs=
counter=1
for obj in $save_oldobjs
do
func_basename "$obj"
objbase=$func_basename_result
case " $oldobjs " in
" ") oldobjs=$obj ;;
*[\ /]"$objbase "*)
while :; do
# Make sure we don't pick an alternate name that also
# overlaps.
newobj=lt$counter-$objbase
func_arith $counter + 1
counter=$func_arith_result
case " $oldobjs " in
*[\ /]"$newobj "*) ;;
*) if test ! -f "$gentop/$newobj"; then break; fi ;;
esac
done
func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
func_append oldobjs " $gentop/$newobj"
;;
*) func_append oldobjs " $obj" ;;
esac
done
fi
func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
tool_oldlib=$func_to_tool_file_result
eval cmds=\"$old_archive_cmds\"
func_len " $cmds"
len=$func_len_result
if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
cmds=$old_archive_cmds
elif test -n "$archiver_list_spec"; then
func_verbose "using command file archive linking..."
for obj in $oldobjs
do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result"
done > $output_objdir/$libname.libcmd
func_to_tool_file "$output_objdir/$libname.libcmd"
oldobjs=" $archiver_list_spec$func_to_tool_file_result"
cmds=$old_archive_cmds
else
# the command line is too long to link in one step, link in parts
func_verbose "using piecewise archive linking..."
save_RANLIB=$RANLIB
RANLIB=:
objlist=
concat_cmds=
save_oldobjs=$oldobjs
oldobjs=
# Is there a better way of finding the last object in the list?
for obj in $save_oldobjs
do
last_oldobj=$obj
done
eval test_cmds=\"$old_archive_cmds\"
func_len " $test_cmds"
len0=$func_len_result
len=$len0
for obj in $save_oldobjs
do
func_len " $obj"
func_arith $len + $func_len_result
len=$func_arith_result
func_append objlist " $obj"
if test "$len" -lt "$max_cmd_len"; then
:
else
# the above command should be used before it gets too long
oldobjs=$objlist
if test "$obj" = "$last_oldobj"; then
RANLIB=$save_RANLIB
fi
test -z "$concat_cmds" || concat_cmds=$concat_cmds~
eval concat_cmds=\"\$concat_cmds$old_archive_cmds\"
objlist=
len=$len0
fi
done
RANLIB=$save_RANLIB
oldobjs=$objlist
if test -z "$oldobjs"; then
eval cmds=\"\$concat_cmds\"
else
eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
fi
fi
fi
func_execute_cmds "$cmds" 'exit $?'
done
test -n "$generated" && \
func_show_eval "${RM}r$generated"
# Now create the libtool archive.
case $output in
*.la)
old_library=
test yes = "$build_old_libs" && old_library=$libname.$libext
func_verbose "creating $output"
# Preserve any variables that may affect compiler behavior
for var in $variables_saved_for_relink; do
if eval test -z \"\${$var+set}\"; then
relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
elif eval var_value=\$$var; test -z "$var_value"; then
relink_command="$var=; export $var; $relink_command"
else
func_quote_arg pretty,unquoted "$var_value"
relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command"
fi
done
# Quote the link command for shipping.
func_quote eval cd "`pwd`"
relink_command="($func_quote_result; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
func_quote_arg pretty,unquoted "$relink_command"
relink_command=$func_quote_arg_unquoted_result
if test yes = "$hardcode_automatic"; then
relink_command=
fi
# Only create the output if not a dry run.
$opt_dry_run || {
for installed in no yes; do
if test yes = "$installed"; then
if test -z "$install_libdir"; then
break
fi
output=$output_objdir/${outputname}i
# Replace all uninstalled libtool libraries with the installed ones
newdependency_libs=
for deplib in $dependency_libs; do
case $deplib in
*.la)
func_basename "$deplib"
name=$func_basename_result
func_resolve_sysroot "$deplib"
eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result`
test -z "$libdir" && \
func_fatal_error "'$deplib' is not a valid libtool archive"
func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name"
;;
-L*)
func_stripname -L '' "$deplib"
func_replace_sysroot "$func_stripname_result"
func_append newdependency_libs " -L$func_replace_sysroot_result"
;;
-R*)
func_stripname -R '' "$deplib"
func_replace_sysroot "$func_stripname_result"
func_append newdependency_libs " -R$func_replace_sysroot_result"
;;
*) func_append newdependency_libs " $deplib" ;;
esac
done
dependency_libs=$newdependency_libs
newdlfiles=
for lib in $dlfiles; do
case $lib in
*.la)
func_basename "$lib"
name=$func_basename_result
eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
test -z "$libdir" && \
func_fatal_error "'$lib' is not a valid libtool archive"
func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name"
;;
*) func_append newdlfiles " $lib" ;;
esac
done
dlfiles=$newdlfiles
newdlprefiles=
for lib in $dlprefiles; do
case $lib in
*.la)
# Only pass preopened files to the pseudo-archive (for
# eventual linking with the app. that links it) if we
# didn't already link the preopened objects directly into
# the library:
func_basename "$lib"
name=$func_basename_result
eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
test -z "$libdir" && \
func_fatal_error "'$lib' is not a valid libtool archive"
func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name"
;;
esac
done
dlprefiles=$newdlprefiles
else
newdlfiles=
for lib in $dlfiles; do
case $lib in
[\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
*) abs=`pwd`"/$lib" ;;
esac
func_append newdlfiles " $abs"
done
dlfiles=$newdlfiles
newdlprefiles=
for lib in $dlprefiles; do
case $lib in
[\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
*) abs=`pwd`"/$lib" ;;
esac
func_append newdlprefiles " $abs"
done
dlprefiles=$newdlprefiles
fi
$RM $output
# place dlname in correct position for cygwin
# In fact, it would be nice if we could use this code for all target
# systems that can't hard-code library paths into their executables
# and that have no shared library path variable independent of PATH,
# but it turns out we can't easily determine that from inspecting
# libtool variables, so we have to hard-code the OSs to which it
# applies here; at the moment, that means platforms that use the PE
# object format with DLL files. See the long comment at the top of
# tests/bindir.at for full details.
tdlname=$dlname
case $host,$output,$installed,$module,$dlname in
*cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *windows*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
# If a -bindir argument was supplied, place the dll there.
if test -n "$bindir"; then
func_relative_path "$install_libdir" "$bindir"
tdlname=$func_relative_path_result/$dlname
else
# Otherwise fall back on heuristic.
tdlname=../bin/$dlname
fi
;;
esac
$ECHO > $output "\
# $outputname - a libtool library file
# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='$tdlname'
# Names of this library.
library_names='$library_names'
# The name of the static archive.
old_library='$old_library'
# Linker flags that cannot go in dependency_libs.
inherited_linker_flags='$new_inherited_linker_flags'
# Libraries that this one depends upon.
dependency_libs='$dependency_libs'
# Names of additional weak libraries provided by this library
weak_library_names='$weak_libs'
# Version information for $libname.
current=$current
age=$age
revision=$revision
# Is this an already installed library?
installed=$installed
# Should we warn about portability when linking against -modules?
shouldnotlink=$module
# Files to dlopen/dlpreopen
dlopen='$dlfiles'
dlpreopen='$dlprefiles'
# Directory that this library needs to be installed in:
libdir='$install_libdir'"
if test no,yes = "$installed,$need_relink"; then
$ECHO >> $output "\
relink_command=\"$relink_command\""
fi
done
}
# Do a symbolic link so that the libtool archive can be found in
# LD_LIBRARY_PATH before the program is installed.
func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
;;
esac
exit $EXIT_SUCCESS
}
if test link = "$opt_mode" || test relink = "$opt_mode"; then
func_mode_link ${1+"$@"}
fi
# func_mode_uninstall arg...
func_mode_uninstall ()
{
$debug_cmd
RM=$nonopt
files=
rmforce=false
exit_status=0
# This variable tells wrapper scripts just to set variables rather
# than running their programs.
libtool_install_magic=$magic
for arg
do
case $arg in
-f) func_append RM " $arg"; rmforce=: ;;
-*) func_append RM " $arg" ;;
*) func_append files " $arg" ;;
esac
done
test -z "$RM" && \
func_fatal_help "you must specify an RM program"
rmdirs=
for file in $files; do
func_dirname "$file" "" "."
dir=$func_dirname_result
if test . = "$dir"; then
odir=$objdir
else
odir=$dir/$objdir
fi
func_basename "$file"
name=$func_basename_result
test uninstall = "$opt_mode" && odir=$dir
# Remember odir for removal later, being careful to avoid duplicates
if test clean = "$opt_mode"; then
case " $rmdirs " in
*" $odir "*) ;;
*) func_append rmdirs " $odir" ;;
esac
fi
# Don't error if the file doesn't exist and rm -f was used.
if { test -L "$file"; } >/dev/null 2>&1 ||
{ test -h "$file"; } >/dev/null 2>&1 ||
test -f "$file"; then
:
elif test -d "$file"; then
exit_status=1
continue
elif $rmforce; then
continue
fi
rmfiles=$file
case $name in
*.la)
# Possibly a libtool archive, so verify it.
if func_lalib_p "$file"; then
func_source $dir/$name
# Delete the libtool libraries and symlinks.
for n in $library_names; do
func_append rmfiles " $odir/$n"
done
test -n "$old_library" && func_append rmfiles " $odir/$old_library"
case $opt_mode in
clean)
case " $library_names " in
*" $dlname "*) ;;
*) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;;
esac
test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i"
;;
uninstall)
if test -n "$library_names"; then
# Do each command in the postuninstall commands.
func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1'
fi
if test -n "$old_library"; then
# Do each command in the old_postuninstall commands.
func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1'
fi
# FIXME: should reinstall the best remaining shared library.
;;
esac
fi
;;
*.lo)
# Possibly a libtool object, so verify it.
if func_lalib_p "$file"; then
# Read the .lo file
func_source $dir/$name
# Add PIC object to the list of files to remove.
if test -n "$pic_object" && test none != "$pic_object"; then
func_append rmfiles " $dir/$pic_object"
fi
# Add non-PIC object to the list of files to remove.
if test -n "$non_pic_object" && test none != "$non_pic_object"; then
func_append rmfiles " $dir/$non_pic_object"
fi
fi
;;
*)
if test clean = "$opt_mode"; then
noexename=$name
case $file in
*.exe)
func_stripname '' '.exe' "$file"
file=$func_stripname_result
func_stripname '' '.exe' "$name"
noexename=$func_stripname_result
# $file with .exe has already been added to rmfiles,
# add $file without .exe
func_append rmfiles " $file"
;;
esac
# Do a test to see if this is a libtool program.
if func_ltwrapper_p "$file"; then
if func_ltwrapper_executable_p "$file"; then
func_ltwrapper_scriptname "$file"
relink_command=
func_source $func_ltwrapper_scriptname_result
func_append rmfiles " $func_ltwrapper_scriptname_result"
else
relink_command=
func_source $dir/$noexename
fi
# note $name still contains .exe if it was in $file originally
# as does the version of $file that was added into $rmfiles
func_append rmfiles " $odir/$name $odir/${name}S.$objext"
if test yes = "$fast_install" && test -n "$relink_command"; then
func_append rmfiles " $odir/lt-$name"
fi
if test "X$noexename" != "X$name"; then
func_append rmfiles " $odir/lt-$noexename.c"
fi
fi
fi
;;
esac
func_show_eval "$RM $rmfiles" 'exit_status=1'
done
# Try to remove the $objdir's in the directories where we deleted files
for dir in $rmdirs; do
if test -d "$dir"; then
func_show_eval "rmdir $dir >/dev/null 2>&1"
fi
done
exit $exit_status
}
if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then
func_mode_uninstall ${1+"$@"}
fi
test -z "$opt_mode" && {
help=$generic_help
func_fatal_help "you must specify a MODE"
}
test -z "$exec_cmd" && \
func_fatal_help "invalid operation mode '$opt_mode'"
if test -n "$exec_cmd"; then
eval exec "$exec_cmd"
exit $EXIT_FAILURE
fi
exit $exit_status
# The TAGs below are defined such that we never get into a situation
# where we disable both kinds of libraries. Given conflicting
# choices, we go for a static library, that is the most portable,
# since we can't tell whether shared libraries were disabled because
# the user asked for that or because the platform doesn't support
# them. This is particularly important on AIX, because we don't
# support having both static and shared libraries enabled at the same
# time on that platform, so we default to a shared-only configuration.
# If a disable-shared tag is given, we'll fallback to a static-only
# configuration. But we'll never go from static-only to shared-only.
# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
build_libtool_libs=no
build_old_libs=yes
# ### END LIBTOOL TAG CONFIG: disable-shared
# ### BEGIN LIBTOOL TAG CONFIG: disable-static
build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
# ### END LIBTOOL TAG CONFIG: disable-static
# Local Variables:
# mode:shell-script
# sh-indentation:2
# End:
wimlib-1.14.5/build-aux/missing 0000744 0001750 0001750 00000017065 15137024752 013665 0 ustar 00e e #! /bin/sh
# Common wrapper for a few potentially missing GNU and other programs.
scriptversion=2025-06-18.21; # UTC
# shellcheck disable=SC2006,SC2268 # we must support pre-POSIX shells
# Copyright (C) 1996-2025 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard , 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program 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 General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autogen autoheader autom4te automake autoreconf
bison flex help2man lex makeinfo perl yacc
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Report bugs to .
GNU Automake home page: .
General help using GNU software: ."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing (GNU Automake) $scriptversion"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=https://www.perl.org/
flex_URL=https://github.com/westes/flex
gnu_software_URL=https://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake|autoreconf)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
*)
:
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
autoheader_deps="'acconfig.h'"
automake_deps="'Makefile.am'"
aclocal_deps="'acinclude.m4'"
case $normalized_program in
aclocal*)
echo "You should only need it if you modified $aclocal_deps or"
echo "$configure_deps."
;;
autoconf*)
echo "You should only need it if you modified $configure_deps."
;;
autogen*)
echo "You should only need it if you modified a '.def' or '.tpl' file."
echo "You may want to install the GNU AutoGen package:"
echo "<$gnu_software_URL/autogen/>"
;;
autoheader*)
echo "You should only need it if you modified $autoheader_deps or"
echo "$configure_deps."
;;
automake*)
echo "You should only need it if you modified $automake_deps or"
echo "$configure_deps."
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
;;
autoreconf*)
echo "You should only need it if you modified $aclocal_deps or"
echo "$automake_deps or $autoheader_deps or $automake_deps or"
echo "$configure_deps."
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
perl*)
echo "You should only need it to run GNU Autoconf, GNU Automake, "
echo " assorted other tools, or if you modified a Perl source file."
echo "You may want to install the Perl 5 language interpreter:"
echo "<$perl_URL>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
program_details "$normalized_program"
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%Y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
wimlib-1.14.5/build-aux/depcomp 0000744 0001750 0001750 00000056224 15137024752 013643 0 ustar 00e e #! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2025-06-18.21; # UTC
# Copyright (C) 1999-2025 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program 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 General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva .
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to .
GNU Automake home page: .
General help using GNU software: .
EOF
exit $?
;;
-v | --v*)
echo "depcomp (GNU Automake) $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interference from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsolete pre-3.x GCC compilers.
## but also to in-use compilers like IBM xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%Y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
wimlib-1.14.5/build-aux/test-driver 0000744 0001750 0001750 00000012144 15137024752 014455 0 ustar 00e e #! /bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2025-06-18.21; # UTC
# Copyright (C) 2011-2025 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to or send patches to
# .
# Make unconditional expansion of undefined variables an error. This
# helps a lot in preventing typo-related bugs.
set -u
usage_error ()
{
echo "$0: $*" >&2
print_usage >&2
exit 2
}
print_usage ()
{
cat <.
GNU Automake home page: .
General help using GNU software: .
END
}
test_name= # Used for reporting.
log_file= # Where to save the output of the test script.
trs_file= # Where to save the metadata of the test run.
expect_failure=no
color_tests=no
collect_skipped_logs=yes
enable_hard_errors=yes
while test $# -gt 0; do
case $1 in
--help) print_usage; exit $?;;
--version) echo "test-driver (GNU Automake) $scriptversion"; exit $?;;
--test-name) test_name=$2; shift;;
--log-file) log_file=$2; shift;;
--trs-file) trs_file=$2; shift;;
--color-tests) color_tests=$2; shift;;
--collect-skipped-logs) collect_skipped_logs=$2; shift;;
--expect-failure) expect_failure=$2; shift;;
--enable-hard-errors) enable_hard_errors=$2; shift;;
--) shift; break;;
-*) usage_error "invalid option: '$1'";;
*) break;;
esac
shift
done
missing_opts=
test x"$test_name" = x && missing_opts="$missing_opts --test-name"
test x"$log_file" = x && missing_opts="$missing_opts --log-file"
test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
if test x"$missing_opts" != x; then
usage_error "the following mandatory options are missing:$missing_opts"
fi
if test $# -eq 0; then
usage_error "missing argument"
fi
if test $color_tests = yes; then
# Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
red='[0;31m' # Red.
grn='[0;32m' # Green.
lgn='[1;32m' # Light green.
blu='[1;34m' # Blue.
mgn='[0;35m' # Magenta.
std='[m' # No color.
else
red= grn= lgn= blu= mgn= std=
fi
do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
trap "st=129; $do_exit" 1
trap "st=130; $do_exit" 2
trap "st=141; $do_exit" 13
trap "st=143; $do_exit" 15
# Test script is run here. We create the file first, then append to it,
# to ameliorate tests themselves also writing to the log file. Our tests
# don't, but others can (automake bug#35762).
: >"$log_file"
"$@" >>"$log_file" 2>&1
estatus=$?
if test $enable_hard_errors = no && test $estatus -eq 99; then
tweaked_estatus=1
else
tweaked_estatus=$estatus
fi
case $tweaked_estatus:$expect_failure in
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
0:*) col=$grn res=PASS recheck=no gcopy=no;;
77:*) col=$blu res=SKIP recheck=no gcopy=$collect_skipped_logs;;
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
esac
# Report the test outcome and exit status in the logs, so that one can
# know whether the test passed or failed simply by looking at the '.log'
# file, without the need of also peaking into the corresponding '.trs'
# file (automake bug#11814).
echo "$res $test_name (exit status: $estatus)" >>"$log_file"
# Report outcome to console.
echo "${col}${res}${std}: $test_name"
# Register the test result, and other relevant metadata.
echo ":test-result: $res" > $trs_file
echo ":global-test-result: $res" >> $trs_file
echo ":recheck: $recheck" >> $trs_file
echo ":copy-in-global-log: $gcopy" >> $trs_file
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%Y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
wimlib-1.14.5/COPYING.LGPL 0000644 0001750 0001750 00000063463 15137020663 012166 0 ustar 00e e GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
Copyright (C)
This 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.
This 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 this library; if not, see .
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
, 1 April 1990
Moe Ghoul, President of Vice
That's all there is to it!
wimlib-1.14.5/Makefile.in 0000644 0001750 0001750 00000550024 15137024752 012440 0 ustar 00e e # Makefile.in generated by automake 1.18.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2025 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
##############################################################################
# General #
##############################################################################
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
am__rm_f = rm -f $(am__rm_f_notfound)
am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@WITH_NTFS_3G_TRUE@am__append_1 = src/ntfs-3g_apply.c \
@WITH_NTFS_3G_TRUE@ src/ntfs-3g_capture.c \
@WITH_NTFS_3G_TRUE@ include/wimlib/ntfs_3g.h
@WINDOWS_NATIVE_BUILD_TRUE@am__append_2 = src/wimboot.c \
@WINDOWS_NATIVE_BUILD_TRUE@ src/win32_common.c \
@WINDOWS_NATIVE_BUILD_TRUE@ src/win32_apply.c \
@WINDOWS_NATIVE_BUILD_TRUE@ src/win32_capture.c \
@WINDOWS_NATIVE_BUILD_TRUE@ src/win32_replacements.c \
@WINDOWS_NATIVE_BUILD_TRUE@ src/win32_vss.c \
@WINDOWS_NATIVE_BUILD_TRUE@ include/wimlib/wimboot.h \
@WINDOWS_NATIVE_BUILD_TRUE@ include/wimlib/win32.h \
@WINDOWS_NATIVE_BUILD_TRUE@ include/wimlib/win32_common.h \
@WINDOWS_NATIVE_BUILD_TRUE@ include/wimlib/win32_vss.h \
@WINDOWS_NATIVE_BUILD_TRUE@ include/wimlib/wof.h
@WINDOWS_NATIVE_BUILD_FALSE@am__append_3 = src/unix_apply.c \
@WINDOWS_NATIVE_BUILD_FALSE@ src/unix_capture.c
@ENABLE_TEST_SUPPORT_TRUE@am__append_4 = src/test_support.c \
@ENABLE_TEST_SUPPORT_TRUE@ include/wimlib/test_support.h
@ENABLE_TEST_SUPPORT_TRUE@@WINDOWS_NATIVE_BUILD_FALSE@am__append_5 = -lm
bin_PROGRAMS = wimlib-imagex$(EXEEXT)
@WINDOWS_NATIVE_BUILD_TRUE@am__append_6 = \
@WINDOWS_NATIVE_BUILD_TRUE@ programs/imagex-win32.c \
@WINDOWS_NATIVE_BUILD_TRUE@ programs/imagex-win32.h \
@WINDOWS_NATIVE_BUILD_TRUE@ programs/wgetopt.c \
@WINDOWS_NATIVE_BUILD_TRUE@ programs/wgetopt.h
check_PROGRAMS = tests/tree-cmp$(EXEEXT)
@WITH_FUSE_TRUE@am__append_7 = tests/test-imagex-mount
@WITH_NTFS_3G_TRUE@am__append_8 = tests/test-imagex-ntfs
@WINDOWS_NATIVE_BUILD_FALSE@TESTS = $(dist_check_SCRIPTS)
EXTRA_PROGRAMS = tests/wlfuzz$(EXEEXT)
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
$(am__configure_deps) $(dist_bin_SCRIPTS) \
$(am__dist_check_SCRIPTS_DIST) $(include_HEADERS) \
$(am__DIST_COMMON)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES = doc/Doxyfile wimlib.pc programs/mkwinpeimg
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" \
"$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \
"$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"
PROGRAMS = $(bin_PROGRAMS)
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
{ test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \
}
LTLIBRARIES = $(lib_LTLIBRARIES)
am__DEPENDENCIES_1 =
@WINDOWS_NATIVE_BUILD_FALSE@am__DEPENDENCIES_2 = \
@WINDOWS_NATIVE_BUILD_FALSE@ $(am__DEPENDENCIES_1)
@WINDOWS_NATIVE_BUILD_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
libwim_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_2)
am__libwim_la_SOURCES_DIST = src/add_image.c src/avl_tree.c \
src/blob_table.c src/compress.c src/compress_common.c \
src/compress_parallel.c src/compress_serial.c \
src/cpu_features.c src/decompress.c src/decompress_common.c \
src/delete_image.c src/dentry.c src/divsufsort.c \
src/encoding.c src/error.c src/export_image.c src/extract.c \
src/file_io.c src/header.c src/inode.c src/inode_fixup.c \
src/inode_table.c src/integrity.c src/iterate_dir.c src/join.c \
src/lcpit_matchfinder.c src/lzms_common.c src/lzms_compress.c \
src/lzms_decompress.c src/lzx_common.c src/lzx_compress.c \
src/lzx_decompress.c src/metadata_resource.c src/mount_image.c \
src/pathlist.c src/paths.c src/pattern.c src/progress.c \
src/reference.c src/registry.c src/reparse.c src/resource.c \
src/scan.c src/security.c src/sha1.c src/solid.c src/split.c \
src/tagged_items.c src/template.c src/textfile.c src/threads.c \
src/timestamp.c src/update_image.c src/util.c src/verify.c \
src/wim.c src/write.c src/xml.c src/xml_windows.c \
src/xmlproc.c src/xpress_compress.c src/xpress_decompress.c \
include/wimlib/alloca.h include/wimlib/apply.h \
include/wimlib/assert.h include/wimlib/avl_tree.h \
include/wimlib/bitops.h include/wimlib/blob_table.h \
include/wimlib/bt_matchfinder.h include/wimlib/case.h \
include/wimlib/compiler.h include/wimlib/compressor_ops.h \
include/wimlib/compress_common.h \
include/wimlib/chunk_compressor.h \
include/wimlib/cpu_features.h \
include/wimlib/decompressor_ops.h \
include/wimlib/decompress_common.h include/wimlib/dentry.h \
include/wimlib/divsufsort.h include/wimlib/encoding.h \
include/wimlib/endianness.h include/wimlib/error.h \
include/wimlib/file_io.h include/wimlib/glob.h \
include/wimlib/guid.h include/wimlib/hc_matchfinder.h \
include/wimlib/header.h include/wimlib/inode.h \
include/wimlib/inode_table.h include/wimlib/integrity.h \
include/wimlib/lcpit_matchfinder.h include/wimlib/list.h \
include/wimlib/lzms_common.h include/wimlib/lzms_constants.h \
include/wimlib/lzx_common.h include/wimlib/lzx_constants.h \
include/wimlib/matchfinder_common.h include/wimlib/metadata.h \
include/wimlib/object_id.h include/wimlib/pathlist.h \
include/wimlib/paths.h include/wimlib/pattern.h \
include/wimlib/progress.h include/wimlib/registry.h \
include/wimlib/reparse.h include/wimlib/resource.h \
include/wimlib/scan.h include/wimlib/security.h \
include/wimlib/security_descriptor.h include/wimlib/sha1.h \
include/wimlib/solid.h include/wimlib/tagged_items.h \
include/wimlib/textfile.h include/wimlib/threads.h \
include/wimlib/timestamp.h include/wimlib/types.h \
include/wimlib/unaligned.h include/wimlib/unix_data.h \
include/wimlib/util.h include/wimlib/wim.h \
include/wimlib/write.h include/wimlib/xattr.h \
include/wimlib/xml.h include/wimlib/xml_windows.h \
include/wimlib/xmlproc.h include/wimlib/xpress_constants.h \
src/ntfs-3g_apply.c src/ntfs-3g_capture.c \
include/wimlib/ntfs_3g.h src/wimboot.c src/win32_common.c \
src/win32_apply.c src/win32_capture.c src/win32_replacements.c \
src/win32_vss.c include/wimlib/wimboot.h \
include/wimlib/win32.h include/wimlib/win32_common.h \
include/wimlib/win32_vss.h include/wimlib/wof.h \
src/unix_apply.c src/unix_capture.c src/test_support.c \
include/wimlib/test_support.h
am__dirstamp = $(am__leading_dot)dirstamp
@WITH_NTFS_3G_TRUE@am__objects_1 = src/libwim_la-ntfs-3g_apply.lo \
@WITH_NTFS_3G_TRUE@ src/libwim_la-ntfs-3g_capture.lo
@WINDOWS_NATIVE_BUILD_TRUE@am__objects_2 = src/libwim_la-wimboot.lo \
@WINDOWS_NATIVE_BUILD_TRUE@ src/libwim_la-win32_common.lo \
@WINDOWS_NATIVE_BUILD_TRUE@ src/libwim_la-win32_apply.lo \
@WINDOWS_NATIVE_BUILD_TRUE@ src/libwim_la-win32_capture.lo \
@WINDOWS_NATIVE_BUILD_TRUE@ src/libwim_la-win32_replacements.lo \
@WINDOWS_NATIVE_BUILD_TRUE@ src/libwim_la-win32_vss.lo
@WINDOWS_NATIVE_BUILD_FALSE@am__objects_3 = \
@WINDOWS_NATIVE_BUILD_FALSE@ src/libwim_la-unix_apply.lo \
@WINDOWS_NATIVE_BUILD_FALSE@ src/libwim_la-unix_capture.lo
@ENABLE_TEST_SUPPORT_TRUE@am__objects_4 = \
@ENABLE_TEST_SUPPORT_TRUE@ src/libwim_la-test_support.lo
am_libwim_la_OBJECTS = src/libwim_la-add_image.lo \
src/libwim_la-avl_tree.lo src/libwim_la-blob_table.lo \
src/libwim_la-compress.lo src/libwim_la-compress_common.lo \
src/libwim_la-compress_parallel.lo \
src/libwim_la-compress_serial.lo src/libwim_la-cpu_features.lo \
src/libwim_la-decompress.lo src/libwim_la-decompress_common.lo \
src/libwim_la-delete_image.lo src/libwim_la-dentry.lo \
src/libwim_la-divsufsort.lo src/libwim_la-encoding.lo \
src/libwim_la-error.lo src/libwim_la-export_image.lo \
src/libwim_la-extract.lo src/libwim_la-file_io.lo \
src/libwim_la-header.lo src/libwim_la-inode.lo \
src/libwim_la-inode_fixup.lo src/libwim_la-inode_table.lo \
src/libwim_la-integrity.lo src/libwim_la-iterate_dir.lo \
src/libwim_la-join.lo src/libwim_la-lcpit_matchfinder.lo \
src/libwim_la-lzms_common.lo src/libwim_la-lzms_compress.lo \
src/libwim_la-lzms_decompress.lo src/libwim_la-lzx_common.lo \
src/libwim_la-lzx_compress.lo src/libwim_la-lzx_decompress.lo \
src/libwim_la-metadata_resource.lo \
src/libwim_la-mount_image.lo src/libwim_la-pathlist.lo \
src/libwim_la-paths.lo src/libwim_la-pattern.lo \
src/libwim_la-progress.lo src/libwim_la-reference.lo \
src/libwim_la-registry.lo src/libwim_la-reparse.lo \
src/libwim_la-resource.lo src/libwim_la-scan.lo \
src/libwim_la-security.lo src/libwim_la-sha1.lo \
src/libwim_la-solid.lo src/libwim_la-split.lo \
src/libwim_la-tagged_items.lo src/libwim_la-template.lo \
src/libwim_la-textfile.lo src/libwim_la-threads.lo \
src/libwim_la-timestamp.lo src/libwim_la-update_image.lo \
src/libwim_la-util.lo src/libwim_la-verify.lo \
src/libwim_la-wim.lo src/libwim_la-write.lo \
src/libwim_la-xml.lo src/libwim_la-xml_windows.lo \
src/libwim_la-xmlproc.lo src/libwim_la-xpress_compress.lo \
src/libwim_la-xpress_decompress.lo $(am__objects_1) \
$(am__objects_2) $(am__objects_3) $(am__objects_4)
libwim_la_OBJECTS = $(am_libwim_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
libwim_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libwim_la_CFLAGS) \
$(CFLAGS) $(libwim_la_LDFLAGS) $(LDFLAGS) -o $@
am_tests_tree_cmp_OBJECTS = tests/tree-cmp.$(OBJEXT)
tests_tree_cmp_OBJECTS = $(am_tests_tree_cmp_OBJECTS)
tests_tree_cmp_LDADD = $(LDADD)
am_tests_wlfuzz_OBJECTS = tests/wlfuzz.$(OBJEXT)
tests_wlfuzz_OBJECTS = $(am_tests_wlfuzz_OBJECTS)
tests_wlfuzz_DEPENDENCIES = $(top_builddir)/libwim.la
am__wimlib_imagex_SOURCES_DIST = programs/imagex.c include/wimlib.h \
include/wimlib_tchar.h programs/imagex-win32.c \
programs/imagex-win32.h programs/wgetopt.c programs/wgetopt.h
@WINDOWS_NATIVE_BUILD_TRUE@am__objects_5 = programs/wimlib_imagex-imagex-win32.$(OBJEXT) \
@WINDOWS_NATIVE_BUILD_TRUE@ programs/wimlib_imagex-wgetopt.$(OBJEXT)
am_wimlib_imagex_OBJECTS = programs/wimlib_imagex-imagex.$(OBJEXT) \
$(am__objects_5)
wimlib_imagex_OBJECTS = $(am_wimlib_imagex_OBJECTS)
wimlib_imagex_DEPENDENCIES = $(top_builddir)/libwim.la
wimlib_imagex_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(wimlib_imagex_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
am__dist_check_SCRIPTS_DIST = tests/test-imagex \
tests/test-imagex-capture_and_apply \
tests/test-imagex-update_and_extract tests/test-imagex-mount \
tests/test-imagex-ntfs
SCRIPTS = $(dist_bin_SCRIPTS)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = \
programs/$(DEPDIR)/wimlib_imagex-imagex-win32.Po \
programs/$(DEPDIR)/wimlib_imagex-imagex.Po \
programs/$(DEPDIR)/wimlib_imagex-wgetopt.Po \
src/$(DEPDIR)/libwim_la-add_image.Plo \
src/$(DEPDIR)/libwim_la-avl_tree.Plo \
src/$(DEPDIR)/libwim_la-blob_table.Plo \
src/$(DEPDIR)/libwim_la-compress.Plo \
src/$(DEPDIR)/libwim_la-compress_common.Plo \
src/$(DEPDIR)/libwim_la-compress_parallel.Plo \
src/$(DEPDIR)/libwim_la-compress_serial.Plo \
src/$(DEPDIR)/libwim_la-cpu_features.Plo \
src/$(DEPDIR)/libwim_la-decompress.Plo \
src/$(DEPDIR)/libwim_la-decompress_common.Plo \
src/$(DEPDIR)/libwim_la-delete_image.Plo \
src/$(DEPDIR)/libwim_la-dentry.Plo \
src/$(DEPDIR)/libwim_la-divsufsort.Plo \
src/$(DEPDIR)/libwim_la-encoding.Plo \
src/$(DEPDIR)/libwim_la-error.Plo \
src/$(DEPDIR)/libwim_la-export_image.Plo \
src/$(DEPDIR)/libwim_la-extract.Plo \
src/$(DEPDIR)/libwim_la-file_io.Plo \
src/$(DEPDIR)/libwim_la-header.Plo \
src/$(DEPDIR)/libwim_la-inode.Plo \
src/$(DEPDIR)/libwim_la-inode_fixup.Plo \
src/$(DEPDIR)/libwim_la-inode_table.Plo \
src/$(DEPDIR)/libwim_la-integrity.Plo \
src/$(DEPDIR)/libwim_la-iterate_dir.Plo \
src/$(DEPDIR)/libwim_la-join.Plo \
src/$(DEPDIR)/libwim_la-lcpit_matchfinder.Plo \
src/$(DEPDIR)/libwim_la-lzms_common.Plo \
src/$(DEPDIR)/libwim_la-lzms_compress.Plo \
src/$(DEPDIR)/libwim_la-lzms_decompress.Plo \
src/$(DEPDIR)/libwim_la-lzx_common.Plo \
src/$(DEPDIR)/libwim_la-lzx_compress.Plo \
src/$(DEPDIR)/libwim_la-lzx_decompress.Plo \
src/$(DEPDIR)/libwim_la-metadata_resource.Plo \
src/$(DEPDIR)/libwim_la-mount_image.Plo \
src/$(DEPDIR)/libwim_la-ntfs-3g_apply.Plo \
src/$(DEPDIR)/libwim_la-ntfs-3g_capture.Plo \
src/$(DEPDIR)/libwim_la-pathlist.Plo \
src/$(DEPDIR)/libwim_la-paths.Plo \
src/$(DEPDIR)/libwim_la-pattern.Plo \
src/$(DEPDIR)/libwim_la-progress.Plo \
src/$(DEPDIR)/libwim_la-reference.Plo \
src/$(DEPDIR)/libwim_la-registry.Plo \
src/$(DEPDIR)/libwim_la-reparse.Plo \
src/$(DEPDIR)/libwim_la-resource.Plo \
src/$(DEPDIR)/libwim_la-scan.Plo \
src/$(DEPDIR)/libwim_la-security.Plo \
src/$(DEPDIR)/libwim_la-sha1.Plo \
src/$(DEPDIR)/libwim_la-solid.Plo \
src/$(DEPDIR)/libwim_la-split.Plo \
src/$(DEPDIR)/libwim_la-tagged_items.Plo \
src/$(DEPDIR)/libwim_la-template.Plo \
src/$(DEPDIR)/libwim_la-test_support.Plo \
src/$(DEPDIR)/libwim_la-textfile.Plo \
src/$(DEPDIR)/libwim_la-threads.Plo \
src/$(DEPDIR)/libwim_la-timestamp.Plo \
src/$(DEPDIR)/libwim_la-unix_apply.Plo \
src/$(DEPDIR)/libwim_la-unix_capture.Plo \
src/$(DEPDIR)/libwim_la-update_image.Plo \
src/$(DEPDIR)/libwim_la-util.Plo \
src/$(DEPDIR)/libwim_la-verify.Plo \
src/$(DEPDIR)/libwim_la-wim.Plo \
src/$(DEPDIR)/libwim_la-wimboot.Plo \
src/$(DEPDIR)/libwim_la-win32_apply.Plo \
src/$(DEPDIR)/libwim_la-win32_capture.Plo \
src/$(DEPDIR)/libwim_la-win32_common.Plo \
src/$(DEPDIR)/libwim_la-win32_replacements.Plo \
src/$(DEPDIR)/libwim_la-win32_vss.Plo \
src/$(DEPDIR)/libwim_la-write.Plo \
src/$(DEPDIR)/libwim_la-xml.Plo \
src/$(DEPDIR)/libwim_la-xml_windows.Plo \
src/$(DEPDIR)/libwim_la-xmlproc.Plo \
src/$(DEPDIR)/libwim_la-xpress_compress.Plo \
src/$(DEPDIR)/libwim_la-xpress_decompress.Plo \
tests/$(DEPDIR)/tree-cmp.Po tests/$(DEPDIR)/wlfuzz.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libwim_la_SOURCES) $(tests_tree_cmp_SOURCES) \
$(tests_wlfuzz_SOURCES) $(wimlib_imagex_SOURCES)
DIST_SOURCES = $(am__libwim_la_SOURCES_DIST) $(tests_tree_cmp_SOURCES) \
$(tests_wlfuzz_SOURCES) $(am__wimlib_imagex_SOURCES_DIST)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
man1dir = $(mandir)/man1
NROFF = nroff
MANS = $(man1_MANS)
DATA = $(pkgconfig_DATA)
HEADERS = $(include_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
config.h.in
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
AM_RECURSIVE_TARGETS = cscope check recheck
am__tty_colors_dummy = \
mgn= red= grn= lgn= blu= brg= std=; \
am__color_tests=no
am__tty_colors = { \
$(am__tty_colors_dummy); \
if test "X$(AM_COLOR_TESTS)" = Xno; then \
am__color_tests=no; \
elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
am__color_tests=yes; \
elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
am__color_tests=yes; \
fi; \
if test $$am__color_tests = yes; then \
red='[0;31m'; \
grn='[0;32m'; \
lgn='[1;32m'; \
blu='[1;34m'; \
mgn='[0;35m'; \
brg='[1m'; \
std='[m'; \
fi; \
}
am__recheck_rx = ^[ ]*:recheck:[ ]*
am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
# A command that, given a newline-separated list of test names on the
# standard input, print the name of the tests that are to be re-run
# upon "make recheck".
am__list_recheck_tests = $(AWK) '{ \
recheck = 1; \
while ((rc = (getline line < ($$0 ".trs"))) != 0) \
{ \
if (rc < 0) \
{ \
if ((getline line2 < ($$0 ".log")) < 0) \
recheck = 0; \
break; \
} \
else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
{ \
recheck = 0; \
break; \
} \
else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
{ \
break; \
} \
}; \
if (recheck) \
print $$0; \
close ($$0 ".trs"); \
close ($$0 ".log"); \
}'
# A command that, given a newline-separated list of test names on the
# standard input, create the global log from their .trs and .log files.
am__create_global_log = $(AWK) ' \
function fatal(msg) \
{ \
print "fatal: making $@: " msg | "cat >&2"; \
exit 1; \
} \
function rst_section(header) \
{ \
print header; \
len = length(header); \
for (i = 1; i <= len; i = i + 1) \
printf "="; \
printf "\n\n"; \
} \
{ \
copy_in_global_log = 1; \
global_test_result = "RUN"; \
while ((rc = (getline line < ($$0 ".trs"))) != 0) \
{ \
if (rc < 0) \
fatal("failed to read from " $$0 ".trs"); \
if (line ~ /$(am__global_test_result_rx)/) \
{ \
sub("$(am__global_test_result_rx)", "", line); \
sub("[ ]*$$", "", line); \
global_test_result = line; \
} \
else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
copy_in_global_log = 0; \
}; \
if (copy_in_global_log) \
{ \
rst_section(global_test_result ": " $$0); \
while ((rc = (getline line < ($$0 ".log"))) != 0) \
{ \
if (rc < 0) \
fatal("failed to read from " $$0 ".log"); \
print line; \
}; \
printf "\n"; \
}; \
close ($$0 ".trs"); \
close ($$0 ".log"); \
}'
# Restructured Text title.
am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
# Solaris 10 'make', and several other traditional 'make' implementations,
# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
# by disabling -e (using the XSI extension "set +e") if it's set.
am__sh_e_setup = case $$- in *e*) set +e;; esac
# Default flags passed to test drivers.
am__common_driver_flags = \
--color-tests "$$am__color_tests" \
$$am__collect_skipped_logs \
--enable-hard-errors "$$am__enable_hard_errors" \
--expect-failure "$$am__expect_failure"
# To be inserted before the command running the test. Creates the
# directory for the log if needed. Stores in $dir the directory
# containing $f, in $tst the test, in $log the log. Executes the
# developer-defined test setup AM_TESTS_ENVIRONMENT (if any), and
# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
# will run the test scripts (or their associated LOG_COMPILER, if
# thy have one).
am__check_pre = \
$(am__sh_e_setup); \
$(am__vpath_adj_setup) $(am__vpath_adj) \
$(am__tty_colors); \
srcdir=$(srcdir); export srcdir; \
case "$@" in \
*/*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
*) am__odir=.;; \
esac; \
test "x$$am__odir" = x"." || test -d "$$am__odir" \
|| $(MKDIR_P) "$$am__odir" || exit $$?; \
if test -f "./$$f"; then dir=./; \
elif test -f "$$f"; then dir=; \
else dir="$(srcdir)/"; fi; \
tst=$$dir$$f; log='$@'; \
if test -n '$(IGNORE_SKIPPED_LOGS)'; then \
am__collect_skipped_logs='--collect-skipped-logs no'; \
else \
am__collect_skipped_logs=''; \
fi; \
if test -n '$(DISABLE_HARD_ERRORS)'; then \
am__enable_hard_errors=no; \
else \
am__enable_hard_errors=yes; \
fi; \
case " $(XFAIL_TESTS) " in \
*[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
am__expect_failure=yes;; \
*) \
am__expect_failure=no;; \
esac; \
$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
# A shell command to get the names of the tests scripts with any registered
# extension removed (i.e., equivalently, the names of the test logs, with
# the '.log' extension removed). The result is saved in the shell variable
# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
# since that might cause problem with VPATH rewrites for suffix-less tests.
# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
am__set_TESTS_bases = \
bases='$(TEST_LOGS)'; \
bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
bases=`echo $$bases`
AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)'
RECHECK_LOGS = $(TEST_LOGS)
TEST_SUITE_LOG = test-suite.log
TEST_EXTENSIONS = @EXEEXT@ .test
LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver
LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
am__set_b = \
case '$@' in \
*/*) \
case '$*' in \
*/*) b='$*';; \
*) b=`echo '$@' | sed 's/\.log$$//'`; \
esac;; \
*) \
b='$*';; \
esac
am__test_logs1 = $(TESTS:=.log)
am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
TEST_LOGS = $(am__test_logs2:.test.log=.log)
TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver
TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
$(TEST_LOG_FLAGS)
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
$(srcdir)/wimlib.pc.in $(top_srcdir)/build-aux/ar-lib \
$(top_srcdir)/build-aux/compile \
$(top_srcdir)/build-aux/config.guess \
$(top_srcdir)/build-aux/config.sub \
$(top_srcdir)/build-aux/depcomp \
$(top_srcdir)/build-aux/install-sh \
$(top_srcdir)/build-aux/ltmain.sh \
$(top_srcdir)/build-aux/missing \
$(top_srcdir)/build-aux/test-driver \
$(top_srcdir)/doc/Doxyfile.in \
$(top_srcdir)/programs/mkwinpeimg.in COPYING NEWS.md README.md \
build-aux/ar-lib build-aux/compile build-aux/config.guess \
build-aux/config.rpath build-aux/config.sub build-aux/depcomp \
build-aux/install-sh build-aux/ltmain.sh build-aux/missing
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
if test -d "$(distdir)"; then \
find "$(distdir)" -type d ! -perm -700 -exec chmod u+rwx {} ';' \
; rm -rf "$(distdir)" \
|| { sleep 5 && rm -rf "$(distdir)"; }; \
else :; fi
am__post_remove_distdir = $(am__remove_distdir)
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = -9
DIST_TARGETS = dist-gzip
# Exists only to be overridden by the user if desired.
AM_DISTCHECK_DVI_TARGET = dvi
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
distcleancheck_listfiles = \
find . \( -type f -a \! \
\( -name .nfs* -o -name .smb* -o -name .__afs* \) \) -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
FILECMD = @FILECMD@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBFUSE_CFLAGS = @LIBFUSE_CFLAGS@
LIBFUSE_LIBS = @LIBFUSE_LIBS@
LIBNTFS_3G_CFLAGS = @LIBNTFS_3G_CFLAGS@
LIBNTFS_3G_LIBS = @LIBNTFS_3G_LIBS@
LIBOBJS = @LIBOBJS@
LIBRT_LIBS = @LIBRT_LIBS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKGCONFIG_PRIVATE_LIBS = @PKGCONFIG_PRIVATE_LIBS@
PKGCONFIG_PRIVATE_REQUIRES = @PKGCONFIG_PRIVATE_REQUIRES@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLATFORM_CFLAGS = @PLATFORM_CFLAGS@
PLATFORM_CPPFLAGS = @PLATFORM_CPPFLAGS@
PLATFORM_LDFLAGS = @PLATFORM_LDFLAGS@
PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_CXX = @PTHREAD_CXX@
PTHREAD_LIBS = @PTHREAD_LIBS@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
ax_pthread_config = @ax_pthread_config@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -I$(top_srcdir)/include $(PLATFORM_CPPFLAGS) \
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
# Note: -std=gnu99 instead of -std=c99 is needed for unnamed structs and unions,
# which are in C11 but not C99. But we can't yet actually use -std=c11 because
# we want to support older versions of gcc.
AM_CFLAGS = -std=gnu99 $(PLATFORM_CFLAGS) -fno-common \
-Wmissing-prototypes -Wstrict-prototypes \
-Wundef -Wno-pointer-sign
AM_LDFLAGS = $(PLATFORM_LDFLAGS)
EXTRA_DIST = README.md README.WINDOWS.md NEWS.md COPYING COPYING.GPLv3 \
COPYING.LGPL examples tools/get-version-number.sh \
tools/windows-build.sh $(man1_MANS) tests/common_tests.sh \
tests/exclusionlists tests/test_utils.sh \
tests/security_descriptor_1.base64 \
tests/security_descriptor_1.bin \
tests/security_descriptor_2.base64 \
tests/security_descriptor_2.bin tests/wims
##############################################################################
# Library #
##############################################################################
lib_LTLIBRARIES = libwim.la
include_HEADERS = include/wimlib.h
pkgconfig_DATA = wimlib.pc
libwim_la_SOURCES = src/add_image.c src/avl_tree.c src/blob_table.c \
src/compress.c src/compress_common.c src/compress_parallel.c \
src/compress_serial.c src/cpu_features.c src/decompress.c \
src/decompress_common.c src/delete_image.c src/dentry.c \
src/divsufsort.c src/encoding.c src/error.c src/export_image.c \
src/extract.c src/file_io.c src/header.c src/inode.c \
src/inode_fixup.c src/inode_table.c src/integrity.c \
src/iterate_dir.c src/join.c src/lcpit_matchfinder.c \
src/lzms_common.c src/lzms_compress.c src/lzms_decompress.c \
src/lzx_common.c src/lzx_compress.c src/lzx_decompress.c \
src/metadata_resource.c src/mount_image.c src/pathlist.c \
src/paths.c src/pattern.c src/progress.c src/reference.c \
src/registry.c src/reparse.c src/resource.c src/scan.c \
src/security.c src/sha1.c src/solid.c src/split.c \
src/tagged_items.c src/template.c src/textfile.c src/threads.c \
src/timestamp.c src/update_image.c src/util.c src/verify.c \
src/wim.c src/write.c src/xml.c src/xml_windows.c \
src/xmlproc.c src/xpress_compress.c src/xpress_decompress.c \
include/wimlib/alloca.h include/wimlib/apply.h \
include/wimlib/assert.h include/wimlib/avl_tree.h \
include/wimlib/bitops.h include/wimlib/blob_table.h \
include/wimlib/bt_matchfinder.h include/wimlib/case.h \
include/wimlib/compiler.h include/wimlib/compressor_ops.h \
include/wimlib/compress_common.h \
include/wimlib/chunk_compressor.h \
include/wimlib/cpu_features.h \
include/wimlib/decompressor_ops.h \
include/wimlib/decompress_common.h include/wimlib/dentry.h \
include/wimlib/divsufsort.h include/wimlib/encoding.h \
include/wimlib/endianness.h include/wimlib/error.h \
include/wimlib/file_io.h include/wimlib/glob.h \
include/wimlib/guid.h include/wimlib/hc_matchfinder.h \
include/wimlib/header.h include/wimlib/inode.h \
include/wimlib/inode_table.h include/wimlib/integrity.h \
include/wimlib/lcpit_matchfinder.h include/wimlib/list.h \
include/wimlib/lzms_common.h include/wimlib/lzms_constants.h \
include/wimlib/lzx_common.h include/wimlib/lzx_constants.h \
include/wimlib/matchfinder_common.h include/wimlib/metadata.h \
include/wimlib/object_id.h include/wimlib/pathlist.h \
include/wimlib/paths.h include/wimlib/pattern.h \
include/wimlib/progress.h include/wimlib/registry.h \
include/wimlib/reparse.h include/wimlib/resource.h \
include/wimlib/scan.h include/wimlib/security.h \
include/wimlib/security_descriptor.h include/wimlib/sha1.h \
include/wimlib/solid.h include/wimlib/tagged_items.h \
include/wimlib/textfile.h include/wimlib/threads.h \
include/wimlib/timestamp.h include/wimlib/types.h \
include/wimlib/unaligned.h include/wimlib/unix_data.h \
include/wimlib/util.h include/wimlib/wim.h \
include/wimlib/write.h include/wimlib/xattr.h \
include/wimlib/xml.h include/wimlib/xml_windows.h \
include/wimlib/xmlproc.h include/wimlib/xpress_constants.h \
$(am__append_1) $(am__append_2) $(am__append_3) \
$(am__append_4)
@WINDOWS_NATIVE_BUILD_FALSE@PLATFORM_LIBS = $(am__append_5)
@WINDOWS_NATIVE_BUILD_TRUE@PLATFORM_LIBS = -lntdll $(am__append_5)
libwim_la_CFLAGS = \
-DBUILDING_WIMLIB \
$(AM_CFLAGS) \
$(PTHREAD_CFLAGS) \
$(LIBNTFS_3G_CFLAGS) \
$(LIBFUSE_CFLAGS)
libwim_la_LDFLAGS = $(AM_LDFLAGS) -version-info 42:0:27
libwim_la_LIBADD = \
$(PTHREAD_LIBS) \
$(LIBNTFS_3G_LIBS) \
$(LIBFUSE_LIBS) \
$(LIBRT_LIBS) \
$(PLATFORM_LIBS)
dist_bin_SCRIPTS = programs/mkwinpeimg
wimlib_imagex_SOURCES = programs/imagex.c include/wimlib.h \
include/wimlib_tchar.h $(am__append_6)
wimlib_imagex_CFLAGS = $(AM_CFLAGS) -Wno-deprecated-declarations
wimlib_imagex_LDADD = $(top_builddir)/libwim.la
wimlib_imagex_cmds = \
append \
apply \
capture \
delete \
dir \
export \
extract \
info \
join \
mount \
mountrw \
optimize \
split \
unmount \
update \
verify
##############################################################################
# Documentation #
##############################################################################
man1_MANS = \
doc/man1/wimlib-imagex.1 \
doc/man1/wimappend.1 \
doc/man1/wimapply.1 \
doc/man1/wimcapture.1 \
doc/man1/wimdelete.1 \
doc/man1/wimdir.1 \
doc/man1/wimexport.1 \
doc/man1/wimextract.1 \
doc/man1/wiminfo.1 \
doc/man1/wimjoin.1 \
doc/man1/wimmount.1 \
doc/man1/wimmountrw.1 \
doc/man1/wimoptimize.1 \
doc/man1/wimsplit.1 \
doc/man1/wimunmount.1 \
doc/man1/wimupdate.1 \
doc/man1/wimverify.1 \
doc/man1/mkwinpeimg.1
tests_tree_cmp_SOURCES = tests/tree-cmp.c
dist_check_SCRIPTS = tests/test-imagex \
tests/test-imagex-capture_and_apply \
tests/test-imagex-update_and_extract $(am__append_7) \
$(am__append_8)
tests_wlfuzz_SOURCES = tests/wlfuzz.c
tests_wlfuzz_LDADD = $(top_builddir)/libwim.la
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
am--refresh: Makefile
@:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
config.h: stamp-h1
@test -f $@ || rm -f stamp-h1
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
$(AM_V_at)rm -f stamp-h1
$(AM_V_GEN)cd $(top_builddir) && $(SHELL) ./config.status config.h
$(srcdir)/config.h.in: $(am__configure_deps)
$(AM_V_GEN)($(am__cd) $(top_srcdir) && $(AUTOHEADER))
$(AM_V_at)rm -f stamp-h1
$(AM_V_at)touch $@
distclean-hdr:
-rm -f config.h stamp-h1
doc/Doxyfile: $(top_builddir)/config.status $(top_srcdir)/doc/Doxyfile.in
cd $(top_builddir) && $(SHELL) ./config.status $@
wimlib.pc: $(top_builddir)/config.status $(srcdir)/wimlib.pc.in
cd $(top_builddir) && $(SHELL) ./config.status $@
programs/mkwinpeimg: $(top_builddir)/config.status $(top_srcdir)/programs/mkwinpeimg.in
cd $(top_builddir) && $(SHELL) ./config.status $@
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p \
|| test -f $$p1 \
; then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' \
-e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' \
`; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && $(am__rm_f) $$files
clean-binPROGRAMS:
$(am__rm_f) $(bin_PROGRAMS)
test -z "$(EXEEXT)" || $(am__rm_f) $(bin_PROGRAMS:$(EXEEXT)=)
clean-checkPROGRAMS:
$(am__rm_f) $(check_PROGRAMS)
test -z "$(EXEEXT)" || $(am__rm_f) $(check_PROGRAMS:$(EXEEXT)=)
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
list2="$$list2 $$p"; \
else :; fi; \
done; \
test -z "$$list2" || { \
echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
}
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
for p in $$list; do \
$(am__strip_dir) \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
done
clean-libLTLIBRARIES:
-$(am__rm_f) $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
echo rm -f $${locs}; \
$(am__rm_f) $${locs}
src/$(am__dirstamp):
@$(MKDIR_P) src
@: >>src/$(am__dirstamp)
src/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) src/$(DEPDIR)
@: >>src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-add_image.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-avl_tree.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-blob_table.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-compress.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-compress_common.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-compress_parallel.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-compress_serial.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-cpu_features.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-decompress.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-decompress_common.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-delete_image.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-dentry.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-divsufsort.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-encoding.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-error.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-export_image.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-extract.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-file_io.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-header.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-inode.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-inode_fixup.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-inode_table.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-integrity.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-iterate_dir.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-join.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-lcpit_matchfinder.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-lzms_common.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-lzms_compress.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-lzms_decompress.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-lzx_common.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-lzx_compress.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-lzx_decompress.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-metadata_resource.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-mount_image.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-pathlist.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-paths.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-pattern.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-progress.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-reference.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-registry.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-reparse.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-resource.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-scan.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-security.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-sha1.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-solid.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-split.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-tagged_items.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-template.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-textfile.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-threads.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-timestamp.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-update_image.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-util.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-verify.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-wim.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-write.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-xml.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-xml_windows.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-xmlproc.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-xpress_compress.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-xpress_decompress.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-ntfs-3g_apply.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-ntfs-3g_capture.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-wimboot.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-win32_common.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-win32_apply.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-win32_capture.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-win32_replacements.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-win32_vss.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-unix_apply.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-unix_capture.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/libwim_la-test_support.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
libwim.la: $(libwim_la_OBJECTS) $(libwim_la_DEPENDENCIES) $(EXTRA_libwim_la_DEPENDENCIES)
$(AM_V_CCLD)$(libwim_la_LINK) -rpath $(libdir) $(libwim_la_OBJECTS) $(libwim_la_LIBADD) $(LIBS)
tests/$(am__dirstamp):
@$(MKDIR_P) tests
@: >>tests/$(am__dirstamp)
tests/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) tests/$(DEPDIR)
@: >>tests/$(DEPDIR)/$(am__dirstamp)
tests/tree-cmp.$(OBJEXT): tests/$(am__dirstamp) \
tests/$(DEPDIR)/$(am__dirstamp)
tests/tree-cmp$(EXEEXT): $(tests_tree_cmp_OBJECTS) $(tests_tree_cmp_DEPENDENCIES) $(EXTRA_tests_tree_cmp_DEPENDENCIES) tests/$(am__dirstamp)
@rm -f tests/tree-cmp$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(tests_tree_cmp_OBJECTS) $(tests_tree_cmp_LDADD) $(LIBS)
tests/wlfuzz.$(OBJEXT): tests/$(am__dirstamp) \
tests/$(DEPDIR)/$(am__dirstamp)
tests/wlfuzz$(EXEEXT): $(tests_wlfuzz_OBJECTS) $(tests_wlfuzz_DEPENDENCIES) $(EXTRA_tests_wlfuzz_DEPENDENCIES) tests/$(am__dirstamp)
@rm -f tests/wlfuzz$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(tests_wlfuzz_OBJECTS) $(tests_wlfuzz_LDADD) $(LIBS)
programs/$(am__dirstamp):
@$(MKDIR_P) programs
@: >>programs/$(am__dirstamp)
programs/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) programs/$(DEPDIR)
@: >>programs/$(DEPDIR)/$(am__dirstamp)
programs/wimlib_imagex-imagex.$(OBJEXT): programs/$(am__dirstamp) \
programs/$(DEPDIR)/$(am__dirstamp)
programs/wimlib_imagex-imagex-win32.$(OBJEXT): \
programs/$(am__dirstamp) programs/$(DEPDIR)/$(am__dirstamp)
programs/wimlib_imagex-wgetopt.$(OBJEXT): programs/$(am__dirstamp) \
programs/$(DEPDIR)/$(am__dirstamp)
wimlib-imagex$(EXEEXT): $(wimlib_imagex_OBJECTS) $(wimlib_imagex_DEPENDENCIES) $(EXTRA_wimlib_imagex_DEPENDENCIES)
@rm -f wimlib-imagex$(EXEEXT)
$(AM_V_CCLD)$(wimlib_imagex_LINK) $(wimlib_imagex_OBJECTS) $(wimlib_imagex_LDADD) $(LIBS)
install-dist_binSCRIPTS: $(dist_bin_SCRIPTS)
@$(NORMAL_INSTALL)
@list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n' \
-e 'h;s|.*|.|' \
-e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) { files[d] = files[d] " " $$1; \
if (++n[d] == $(am__install_max)) { \
print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
else { print "f", d "/" $$4, $$1 } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \
$(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
uninstall-dist_binSCRIPTS:
@$(NORMAL_UNINSTALL)
@list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 's,.*/,,;$(transform)'`; \
dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
-rm -f programs/*.$(OBJEXT)
-rm -f src/*.$(OBJEXT)
-rm -f src/*.lo
-rm -f tests/*.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@programs/$(DEPDIR)/wimlib_imagex-imagex-win32.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@programs/$(DEPDIR)/wimlib_imagex-imagex.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@programs/$(DEPDIR)/wimlib_imagex-wgetopt.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-add_image.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-avl_tree.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-blob_table.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-compress.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-compress_common.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-compress_parallel.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-compress_serial.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-cpu_features.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-decompress.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-decompress_common.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-delete_image.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-dentry.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-divsufsort.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-encoding.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-error.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-export_image.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-extract.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-file_io.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-header.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-inode.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-inode_fixup.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-inode_table.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-integrity.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-iterate_dir.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-join.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-lcpit_matchfinder.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-lzms_common.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-lzms_compress.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-lzms_decompress.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-lzx_common.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-lzx_compress.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-lzx_decompress.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-metadata_resource.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-mount_image.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-ntfs-3g_apply.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-ntfs-3g_capture.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-pathlist.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-paths.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-pattern.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-progress.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-reference.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-registry.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-reparse.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-resource.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-scan.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-security.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-sha1.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-solid.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-split.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-tagged_items.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-template.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-test_support.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-textfile.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-threads.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-timestamp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-unix_apply.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-unix_capture.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-update_image.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-util.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-verify.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-wim.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-wimboot.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-win32_apply.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-win32_capture.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-win32_common.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-win32_replacements.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-win32_vss.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-write.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-xml.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-xml_windows.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-xmlproc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-xpress_compress.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libwim_la-xpress_decompress.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tree-cmp.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/wlfuzz.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@: >>$@
am--depfiles: $(am__depfiles_remade)
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
src/libwim_la-add_image.lo: src/add_image.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-add_image.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-add_image.Tpo -c -o src/libwim_la-add_image.lo `test -f 'src/add_image.c' || echo '$(srcdir)/'`src/add_image.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-add_image.Tpo src/$(DEPDIR)/libwim_la-add_image.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/add_image.c' object='src/libwim_la-add_image.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-add_image.lo `test -f 'src/add_image.c' || echo '$(srcdir)/'`src/add_image.c
src/libwim_la-avl_tree.lo: src/avl_tree.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-avl_tree.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-avl_tree.Tpo -c -o src/libwim_la-avl_tree.lo `test -f 'src/avl_tree.c' || echo '$(srcdir)/'`src/avl_tree.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-avl_tree.Tpo src/$(DEPDIR)/libwim_la-avl_tree.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/avl_tree.c' object='src/libwim_la-avl_tree.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-avl_tree.lo `test -f 'src/avl_tree.c' || echo '$(srcdir)/'`src/avl_tree.c
src/libwim_la-blob_table.lo: src/blob_table.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-blob_table.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-blob_table.Tpo -c -o src/libwim_la-blob_table.lo `test -f 'src/blob_table.c' || echo '$(srcdir)/'`src/blob_table.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-blob_table.Tpo src/$(DEPDIR)/libwim_la-blob_table.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/blob_table.c' object='src/libwim_la-blob_table.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-blob_table.lo `test -f 'src/blob_table.c' || echo '$(srcdir)/'`src/blob_table.c
src/libwim_la-compress.lo: src/compress.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-compress.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-compress.Tpo -c -o src/libwim_la-compress.lo `test -f 'src/compress.c' || echo '$(srcdir)/'`src/compress.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-compress.Tpo src/$(DEPDIR)/libwim_la-compress.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/compress.c' object='src/libwim_la-compress.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-compress.lo `test -f 'src/compress.c' || echo '$(srcdir)/'`src/compress.c
src/libwim_la-compress_common.lo: src/compress_common.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-compress_common.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-compress_common.Tpo -c -o src/libwim_la-compress_common.lo `test -f 'src/compress_common.c' || echo '$(srcdir)/'`src/compress_common.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-compress_common.Tpo src/$(DEPDIR)/libwim_la-compress_common.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/compress_common.c' object='src/libwim_la-compress_common.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-compress_common.lo `test -f 'src/compress_common.c' || echo '$(srcdir)/'`src/compress_common.c
src/libwim_la-compress_parallel.lo: src/compress_parallel.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-compress_parallel.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-compress_parallel.Tpo -c -o src/libwim_la-compress_parallel.lo `test -f 'src/compress_parallel.c' || echo '$(srcdir)/'`src/compress_parallel.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-compress_parallel.Tpo src/$(DEPDIR)/libwim_la-compress_parallel.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/compress_parallel.c' object='src/libwim_la-compress_parallel.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-compress_parallel.lo `test -f 'src/compress_parallel.c' || echo '$(srcdir)/'`src/compress_parallel.c
src/libwim_la-compress_serial.lo: src/compress_serial.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-compress_serial.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-compress_serial.Tpo -c -o src/libwim_la-compress_serial.lo `test -f 'src/compress_serial.c' || echo '$(srcdir)/'`src/compress_serial.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-compress_serial.Tpo src/$(DEPDIR)/libwim_la-compress_serial.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/compress_serial.c' object='src/libwim_la-compress_serial.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-compress_serial.lo `test -f 'src/compress_serial.c' || echo '$(srcdir)/'`src/compress_serial.c
src/libwim_la-cpu_features.lo: src/cpu_features.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-cpu_features.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-cpu_features.Tpo -c -o src/libwim_la-cpu_features.lo `test -f 'src/cpu_features.c' || echo '$(srcdir)/'`src/cpu_features.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-cpu_features.Tpo src/$(DEPDIR)/libwim_la-cpu_features.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/cpu_features.c' object='src/libwim_la-cpu_features.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-cpu_features.lo `test -f 'src/cpu_features.c' || echo '$(srcdir)/'`src/cpu_features.c
src/libwim_la-decompress.lo: src/decompress.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-decompress.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-decompress.Tpo -c -o src/libwim_la-decompress.lo `test -f 'src/decompress.c' || echo '$(srcdir)/'`src/decompress.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-decompress.Tpo src/$(DEPDIR)/libwim_la-decompress.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/decompress.c' object='src/libwim_la-decompress.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-decompress.lo `test -f 'src/decompress.c' || echo '$(srcdir)/'`src/decompress.c
src/libwim_la-decompress_common.lo: src/decompress_common.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-decompress_common.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-decompress_common.Tpo -c -o src/libwim_la-decompress_common.lo `test -f 'src/decompress_common.c' || echo '$(srcdir)/'`src/decompress_common.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-decompress_common.Tpo src/$(DEPDIR)/libwim_la-decompress_common.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/decompress_common.c' object='src/libwim_la-decompress_common.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-decompress_common.lo `test -f 'src/decompress_common.c' || echo '$(srcdir)/'`src/decompress_common.c
src/libwim_la-delete_image.lo: src/delete_image.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-delete_image.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-delete_image.Tpo -c -o src/libwim_la-delete_image.lo `test -f 'src/delete_image.c' || echo '$(srcdir)/'`src/delete_image.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-delete_image.Tpo src/$(DEPDIR)/libwim_la-delete_image.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/delete_image.c' object='src/libwim_la-delete_image.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-delete_image.lo `test -f 'src/delete_image.c' || echo '$(srcdir)/'`src/delete_image.c
src/libwim_la-dentry.lo: src/dentry.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-dentry.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-dentry.Tpo -c -o src/libwim_la-dentry.lo `test -f 'src/dentry.c' || echo '$(srcdir)/'`src/dentry.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-dentry.Tpo src/$(DEPDIR)/libwim_la-dentry.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/dentry.c' object='src/libwim_la-dentry.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-dentry.lo `test -f 'src/dentry.c' || echo '$(srcdir)/'`src/dentry.c
src/libwim_la-divsufsort.lo: src/divsufsort.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-divsufsort.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-divsufsort.Tpo -c -o src/libwim_la-divsufsort.lo `test -f 'src/divsufsort.c' || echo '$(srcdir)/'`src/divsufsort.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-divsufsort.Tpo src/$(DEPDIR)/libwim_la-divsufsort.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/divsufsort.c' object='src/libwim_la-divsufsort.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-divsufsort.lo `test -f 'src/divsufsort.c' || echo '$(srcdir)/'`src/divsufsort.c
src/libwim_la-encoding.lo: src/encoding.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-encoding.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-encoding.Tpo -c -o src/libwim_la-encoding.lo `test -f 'src/encoding.c' || echo '$(srcdir)/'`src/encoding.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-encoding.Tpo src/$(DEPDIR)/libwim_la-encoding.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/encoding.c' object='src/libwim_la-encoding.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-encoding.lo `test -f 'src/encoding.c' || echo '$(srcdir)/'`src/encoding.c
src/libwim_la-error.lo: src/error.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-error.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-error.Tpo -c -o src/libwim_la-error.lo `test -f 'src/error.c' || echo '$(srcdir)/'`src/error.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-error.Tpo src/$(DEPDIR)/libwim_la-error.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/error.c' object='src/libwim_la-error.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-error.lo `test -f 'src/error.c' || echo '$(srcdir)/'`src/error.c
src/libwim_la-export_image.lo: src/export_image.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-export_image.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-export_image.Tpo -c -o src/libwim_la-export_image.lo `test -f 'src/export_image.c' || echo '$(srcdir)/'`src/export_image.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-export_image.Tpo src/$(DEPDIR)/libwim_la-export_image.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/export_image.c' object='src/libwim_la-export_image.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-export_image.lo `test -f 'src/export_image.c' || echo '$(srcdir)/'`src/export_image.c
src/libwim_la-extract.lo: src/extract.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-extract.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-extract.Tpo -c -o src/libwim_la-extract.lo `test -f 'src/extract.c' || echo '$(srcdir)/'`src/extract.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-extract.Tpo src/$(DEPDIR)/libwim_la-extract.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/extract.c' object='src/libwim_la-extract.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-extract.lo `test -f 'src/extract.c' || echo '$(srcdir)/'`src/extract.c
src/libwim_la-file_io.lo: src/file_io.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-file_io.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-file_io.Tpo -c -o src/libwim_la-file_io.lo `test -f 'src/file_io.c' || echo '$(srcdir)/'`src/file_io.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-file_io.Tpo src/$(DEPDIR)/libwim_la-file_io.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/file_io.c' object='src/libwim_la-file_io.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-file_io.lo `test -f 'src/file_io.c' || echo '$(srcdir)/'`src/file_io.c
src/libwim_la-header.lo: src/header.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-header.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-header.Tpo -c -o src/libwim_la-header.lo `test -f 'src/header.c' || echo '$(srcdir)/'`src/header.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-header.Tpo src/$(DEPDIR)/libwim_la-header.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/header.c' object='src/libwim_la-header.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-header.lo `test -f 'src/header.c' || echo '$(srcdir)/'`src/header.c
src/libwim_la-inode.lo: src/inode.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-inode.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-inode.Tpo -c -o src/libwim_la-inode.lo `test -f 'src/inode.c' || echo '$(srcdir)/'`src/inode.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-inode.Tpo src/$(DEPDIR)/libwim_la-inode.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/inode.c' object='src/libwim_la-inode.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-inode.lo `test -f 'src/inode.c' || echo '$(srcdir)/'`src/inode.c
src/libwim_la-inode_fixup.lo: src/inode_fixup.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-inode_fixup.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-inode_fixup.Tpo -c -o src/libwim_la-inode_fixup.lo `test -f 'src/inode_fixup.c' || echo '$(srcdir)/'`src/inode_fixup.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-inode_fixup.Tpo src/$(DEPDIR)/libwim_la-inode_fixup.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/inode_fixup.c' object='src/libwim_la-inode_fixup.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-inode_fixup.lo `test -f 'src/inode_fixup.c' || echo '$(srcdir)/'`src/inode_fixup.c
src/libwim_la-inode_table.lo: src/inode_table.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-inode_table.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-inode_table.Tpo -c -o src/libwim_la-inode_table.lo `test -f 'src/inode_table.c' || echo '$(srcdir)/'`src/inode_table.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-inode_table.Tpo src/$(DEPDIR)/libwim_la-inode_table.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/inode_table.c' object='src/libwim_la-inode_table.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-inode_table.lo `test -f 'src/inode_table.c' || echo '$(srcdir)/'`src/inode_table.c
src/libwim_la-integrity.lo: src/integrity.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-integrity.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-integrity.Tpo -c -o src/libwim_la-integrity.lo `test -f 'src/integrity.c' || echo '$(srcdir)/'`src/integrity.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-integrity.Tpo src/$(DEPDIR)/libwim_la-integrity.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/integrity.c' object='src/libwim_la-integrity.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-integrity.lo `test -f 'src/integrity.c' || echo '$(srcdir)/'`src/integrity.c
src/libwim_la-iterate_dir.lo: src/iterate_dir.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-iterate_dir.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-iterate_dir.Tpo -c -o src/libwim_la-iterate_dir.lo `test -f 'src/iterate_dir.c' || echo '$(srcdir)/'`src/iterate_dir.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-iterate_dir.Tpo src/$(DEPDIR)/libwim_la-iterate_dir.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/iterate_dir.c' object='src/libwim_la-iterate_dir.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-iterate_dir.lo `test -f 'src/iterate_dir.c' || echo '$(srcdir)/'`src/iterate_dir.c
src/libwim_la-join.lo: src/join.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-join.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-join.Tpo -c -o src/libwim_la-join.lo `test -f 'src/join.c' || echo '$(srcdir)/'`src/join.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-join.Tpo src/$(DEPDIR)/libwim_la-join.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/join.c' object='src/libwim_la-join.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-join.lo `test -f 'src/join.c' || echo '$(srcdir)/'`src/join.c
src/libwim_la-lcpit_matchfinder.lo: src/lcpit_matchfinder.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-lcpit_matchfinder.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-lcpit_matchfinder.Tpo -c -o src/libwim_la-lcpit_matchfinder.lo `test -f 'src/lcpit_matchfinder.c' || echo '$(srcdir)/'`src/lcpit_matchfinder.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-lcpit_matchfinder.Tpo src/$(DEPDIR)/libwim_la-lcpit_matchfinder.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lcpit_matchfinder.c' object='src/libwim_la-lcpit_matchfinder.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-lcpit_matchfinder.lo `test -f 'src/lcpit_matchfinder.c' || echo '$(srcdir)/'`src/lcpit_matchfinder.c
src/libwim_la-lzms_common.lo: src/lzms_common.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-lzms_common.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-lzms_common.Tpo -c -o src/libwim_la-lzms_common.lo `test -f 'src/lzms_common.c' || echo '$(srcdir)/'`src/lzms_common.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-lzms_common.Tpo src/$(DEPDIR)/libwim_la-lzms_common.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lzms_common.c' object='src/libwim_la-lzms_common.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-lzms_common.lo `test -f 'src/lzms_common.c' || echo '$(srcdir)/'`src/lzms_common.c
src/libwim_la-lzms_compress.lo: src/lzms_compress.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-lzms_compress.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-lzms_compress.Tpo -c -o src/libwim_la-lzms_compress.lo `test -f 'src/lzms_compress.c' || echo '$(srcdir)/'`src/lzms_compress.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-lzms_compress.Tpo src/$(DEPDIR)/libwim_la-lzms_compress.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lzms_compress.c' object='src/libwim_la-lzms_compress.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-lzms_compress.lo `test -f 'src/lzms_compress.c' || echo '$(srcdir)/'`src/lzms_compress.c
src/libwim_la-lzms_decompress.lo: src/lzms_decompress.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-lzms_decompress.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-lzms_decompress.Tpo -c -o src/libwim_la-lzms_decompress.lo `test -f 'src/lzms_decompress.c' || echo '$(srcdir)/'`src/lzms_decompress.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-lzms_decompress.Tpo src/$(DEPDIR)/libwim_la-lzms_decompress.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lzms_decompress.c' object='src/libwim_la-lzms_decompress.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-lzms_decompress.lo `test -f 'src/lzms_decompress.c' || echo '$(srcdir)/'`src/lzms_decompress.c
src/libwim_la-lzx_common.lo: src/lzx_common.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-lzx_common.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-lzx_common.Tpo -c -o src/libwim_la-lzx_common.lo `test -f 'src/lzx_common.c' || echo '$(srcdir)/'`src/lzx_common.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-lzx_common.Tpo src/$(DEPDIR)/libwim_la-lzx_common.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lzx_common.c' object='src/libwim_la-lzx_common.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-lzx_common.lo `test -f 'src/lzx_common.c' || echo '$(srcdir)/'`src/lzx_common.c
src/libwim_la-lzx_compress.lo: src/lzx_compress.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-lzx_compress.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-lzx_compress.Tpo -c -o src/libwim_la-lzx_compress.lo `test -f 'src/lzx_compress.c' || echo '$(srcdir)/'`src/lzx_compress.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-lzx_compress.Tpo src/$(DEPDIR)/libwim_la-lzx_compress.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lzx_compress.c' object='src/libwim_la-lzx_compress.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-lzx_compress.lo `test -f 'src/lzx_compress.c' || echo '$(srcdir)/'`src/lzx_compress.c
src/libwim_la-lzx_decompress.lo: src/lzx_decompress.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-lzx_decompress.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-lzx_decompress.Tpo -c -o src/libwim_la-lzx_decompress.lo `test -f 'src/lzx_decompress.c' || echo '$(srcdir)/'`src/lzx_decompress.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-lzx_decompress.Tpo src/$(DEPDIR)/libwim_la-lzx_decompress.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/lzx_decompress.c' object='src/libwim_la-lzx_decompress.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-lzx_decompress.lo `test -f 'src/lzx_decompress.c' || echo '$(srcdir)/'`src/lzx_decompress.c
src/libwim_la-metadata_resource.lo: src/metadata_resource.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-metadata_resource.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-metadata_resource.Tpo -c -o src/libwim_la-metadata_resource.lo `test -f 'src/metadata_resource.c' || echo '$(srcdir)/'`src/metadata_resource.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-metadata_resource.Tpo src/$(DEPDIR)/libwim_la-metadata_resource.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/metadata_resource.c' object='src/libwim_la-metadata_resource.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-metadata_resource.lo `test -f 'src/metadata_resource.c' || echo '$(srcdir)/'`src/metadata_resource.c
src/libwim_la-mount_image.lo: src/mount_image.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-mount_image.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-mount_image.Tpo -c -o src/libwim_la-mount_image.lo `test -f 'src/mount_image.c' || echo '$(srcdir)/'`src/mount_image.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-mount_image.Tpo src/$(DEPDIR)/libwim_la-mount_image.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/mount_image.c' object='src/libwim_la-mount_image.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-mount_image.lo `test -f 'src/mount_image.c' || echo '$(srcdir)/'`src/mount_image.c
src/libwim_la-pathlist.lo: src/pathlist.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-pathlist.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-pathlist.Tpo -c -o src/libwim_la-pathlist.lo `test -f 'src/pathlist.c' || echo '$(srcdir)/'`src/pathlist.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-pathlist.Tpo src/$(DEPDIR)/libwim_la-pathlist.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pathlist.c' object='src/libwim_la-pathlist.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-pathlist.lo `test -f 'src/pathlist.c' || echo '$(srcdir)/'`src/pathlist.c
src/libwim_la-paths.lo: src/paths.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-paths.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-paths.Tpo -c -o src/libwim_la-paths.lo `test -f 'src/paths.c' || echo '$(srcdir)/'`src/paths.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-paths.Tpo src/$(DEPDIR)/libwim_la-paths.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/paths.c' object='src/libwim_la-paths.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-paths.lo `test -f 'src/paths.c' || echo '$(srcdir)/'`src/paths.c
src/libwim_la-pattern.lo: src/pattern.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-pattern.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-pattern.Tpo -c -o src/libwim_la-pattern.lo `test -f 'src/pattern.c' || echo '$(srcdir)/'`src/pattern.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-pattern.Tpo src/$(DEPDIR)/libwim_la-pattern.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pattern.c' object='src/libwim_la-pattern.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-pattern.lo `test -f 'src/pattern.c' || echo '$(srcdir)/'`src/pattern.c
src/libwim_la-progress.lo: src/progress.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-progress.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-progress.Tpo -c -o src/libwim_la-progress.lo `test -f 'src/progress.c' || echo '$(srcdir)/'`src/progress.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-progress.Tpo src/$(DEPDIR)/libwim_la-progress.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/progress.c' object='src/libwim_la-progress.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-progress.lo `test -f 'src/progress.c' || echo '$(srcdir)/'`src/progress.c
src/libwim_la-reference.lo: src/reference.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-reference.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-reference.Tpo -c -o src/libwim_la-reference.lo `test -f 'src/reference.c' || echo '$(srcdir)/'`src/reference.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-reference.Tpo src/$(DEPDIR)/libwim_la-reference.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/reference.c' object='src/libwim_la-reference.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-reference.lo `test -f 'src/reference.c' || echo '$(srcdir)/'`src/reference.c
src/libwim_la-registry.lo: src/registry.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-registry.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-registry.Tpo -c -o src/libwim_la-registry.lo `test -f 'src/registry.c' || echo '$(srcdir)/'`src/registry.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-registry.Tpo src/$(DEPDIR)/libwim_la-registry.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/registry.c' object='src/libwim_la-registry.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-registry.lo `test -f 'src/registry.c' || echo '$(srcdir)/'`src/registry.c
src/libwim_la-reparse.lo: src/reparse.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-reparse.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-reparse.Tpo -c -o src/libwim_la-reparse.lo `test -f 'src/reparse.c' || echo '$(srcdir)/'`src/reparse.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-reparse.Tpo src/$(DEPDIR)/libwim_la-reparse.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/reparse.c' object='src/libwim_la-reparse.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-reparse.lo `test -f 'src/reparse.c' || echo '$(srcdir)/'`src/reparse.c
src/libwim_la-resource.lo: src/resource.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-resource.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-resource.Tpo -c -o src/libwim_la-resource.lo `test -f 'src/resource.c' || echo '$(srcdir)/'`src/resource.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-resource.Tpo src/$(DEPDIR)/libwim_la-resource.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/resource.c' object='src/libwim_la-resource.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-resource.lo `test -f 'src/resource.c' || echo '$(srcdir)/'`src/resource.c
src/libwim_la-scan.lo: src/scan.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-scan.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-scan.Tpo -c -o src/libwim_la-scan.lo `test -f 'src/scan.c' || echo '$(srcdir)/'`src/scan.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-scan.Tpo src/$(DEPDIR)/libwim_la-scan.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/scan.c' object='src/libwim_la-scan.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-scan.lo `test -f 'src/scan.c' || echo '$(srcdir)/'`src/scan.c
src/libwim_la-security.lo: src/security.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-security.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-security.Tpo -c -o src/libwim_la-security.lo `test -f 'src/security.c' || echo '$(srcdir)/'`src/security.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-security.Tpo src/$(DEPDIR)/libwim_la-security.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/security.c' object='src/libwim_la-security.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-security.lo `test -f 'src/security.c' || echo '$(srcdir)/'`src/security.c
src/libwim_la-sha1.lo: src/sha1.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-sha1.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-sha1.Tpo -c -o src/libwim_la-sha1.lo `test -f 'src/sha1.c' || echo '$(srcdir)/'`src/sha1.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-sha1.Tpo src/$(DEPDIR)/libwim_la-sha1.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/sha1.c' object='src/libwim_la-sha1.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-sha1.lo `test -f 'src/sha1.c' || echo '$(srcdir)/'`src/sha1.c
src/libwim_la-solid.lo: src/solid.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-solid.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-solid.Tpo -c -o src/libwim_la-solid.lo `test -f 'src/solid.c' || echo '$(srcdir)/'`src/solid.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-solid.Tpo src/$(DEPDIR)/libwim_la-solid.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/solid.c' object='src/libwim_la-solid.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-solid.lo `test -f 'src/solid.c' || echo '$(srcdir)/'`src/solid.c
src/libwim_la-split.lo: src/split.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-split.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-split.Tpo -c -o src/libwim_la-split.lo `test -f 'src/split.c' || echo '$(srcdir)/'`src/split.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-split.Tpo src/$(DEPDIR)/libwim_la-split.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/split.c' object='src/libwim_la-split.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-split.lo `test -f 'src/split.c' || echo '$(srcdir)/'`src/split.c
src/libwim_la-tagged_items.lo: src/tagged_items.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-tagged_items.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-tagged_items.Tpo -c -o src/libwim_la-tagged_items.lo `test -f 'src/tagged_items.c' || echo '$(srcdir)/'`src/tagged_items.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-tagged_items.Tpo src/$(DEPDIR)/libwim_la-tagged_items.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/tagged_items.c' object='src/libwim_la-tagged_items.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-tagged_items.lo `test -f 'src/tagged_items.c' || echo '$(srcdir)/'`src/tagged_items.c
src/libwim_la-template.lo: src/template.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-template.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-template.Tpo -c -o src/libwim_la-template.lo `test -f 'src/template.c' || echo '$(srcdir)/'`src/template.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-template.Tpo src/$(DEPDIR)/libwim_la-template.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/template.c' object='src/libwim_la-template.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-template.lo `test -f 'src/template.c' || echo '$(srcdir)/'`src/template.c
src/libwim_la-textfile.lo: src/textfile.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-textfile.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-textfile.Tpo -c -o src/libwim_la-textfile.lo `test -f 'src/textfile.c' || echo '$(srcdir)/'`src/textfile.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-textfile.Tpo src/$(DEPDIR)/libwim_la-textfile.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/textfile.c' object='src/libwim_la-textfile.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-textfile.lo `test -f 'src/textfile.c' || echo '$(srcdir)/'`src/textfile.c
src/libwim_la-threads.lo: src/threads.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-threads.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-threads.Tpo -c -o src/libwim_la-threads.lo `test -f 'src/threads.c' || echo '$(srcdir)/'`src/threads.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-threads.Tpo src/$(DEPDIR)/libwim_la-threads.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/threads.c' object='src/libwim_la-threads.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-threads.lo `test -f 'src/threads.c' || echo '$(srcdir)/'`src/threads.c
src/libwim_la-timestamp.lo: src/timestamp.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-timestamp.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-timestamp.Tpo -c -o src/libwim_la-timestamp.lo `test -f 'src/timestamp.c' || echo '$(srcdir)/'`src/timestamp.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-timestamp.Tpo src/$(DEPDIR)/libwim_la-timestamp.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/timestamp.c' object='src/libwim_la-timestamp.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-timestamp.lo `test -f 'src/timestamp.c' || echo '$(srcdir)/'`src/timestamp.c
src/libwim_la-update_image.lo: src/update_image.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-update_image.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-update_image.Tpo -c -o src/libwim_la-update_image.lo `test -f 'src/update_image.c' || echo '$(srcdir)/'`src/update_image.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-update_image.Tpo src/$(DEPDIR)/libwim_la-update_image.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/update_image.c' object='src/libwim_la-update_image.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-update_image.lo `test -f 'src/update_image.c' || echo '$(srcdir)/'`src/update_image.c
src/libwim_la-util.lo: src/util.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-util.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-util.Tpo -c -o src/libwim_la-util.lo `test -f 'src/util.c' || echo '$(srcdir)/'`src/util.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-util.Tpo src/$(DEPDIR)/libwim_la-util.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/util.c' object='src/libwim_la-util.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-util.lo `test -f 'src/util.c' || echo '$(srcdir)/'`src/util.c
src/libwim_la-verify.lo: src/verify.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-verify.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-verify.Tpo -c -o src/libwim_la-verify.lo `test -f 'src/verify.c' || echo '$(srcdir)/'`src/verify.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-verify.Tpo src/$(DEPDIR)/libwim_la-verify.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/verify.c' object='src/libwim_la-verify.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-verify.lo `test -f 'src/verify.c' || echo '$(srcdir)/'`src/verify.c
src/libwim_la-wim.lo: src/wim.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-wim.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-wim.Tpo -c -o src/libwim_la-wim.lo `test -f 'src/wim.c' || echo '$(srcdir)/'`src/wim.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-wim.Tpo src/$(DEPDIR)/libwim_la-wim.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/wim.c' object='src/libwim_la-wim.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-wim.lo `test -f 'src/wim.c' || echo '$(srcdir)/'`src/wim.c
src/libwim_la-write.lo: src/write.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-write.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-write.Tpo -c -o src/libwim_la-write.lo `test -f 'src/write.c' || echo '$(srcdir)/'`src/write.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-write.Tpo src/$(DEPDIR)/libwim_la-write.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/write.c' object='src/libwim_la-write.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-write.lo `test -f 'src/write.c' || echo '$(srcdir)/'`src/write.c
src/libwim_la-xml.lo: src/xml.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-xml.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-xml.Tpo -c -o src/libwim_la-xml.lo `test -f 'src/xml.c' || echo '$(srcdir)/'`src/xml.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-xml.Tpo src/$(DEPDIR)/libwim_la-xml.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/xml.c' object='src/libwim_la-xml.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-xml.lo `test -f 'src/xml.c' || echo '$(srcdir)/'`src/xml.c
src/libwim_la-xml_windows.lo: src/xml_windows.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-xml_windows.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-xml_windows.Tpo -c -o src/libwim_la-xml_windows.lo `test -f 'src/xml_windows.c' || echo '$(srcdir)/'`src/xml_windows.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-xml_windows.Tpo src/$(DEPDIR)/libwim_la-xml_windows.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/xml_windows.c' object='src/libwim_la-xml_windows.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-xml_windows.lo `test -f 'src/xml_windows.c' || echo '$(srcdir)/'`src/xml_windows.c
src/libwim_la-xmlproc.lo: src/xmlproc.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-xmlproc.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-xmlproc.Tpo -c -o src/libwim_la-xmlproc.lo `test -f 'src/xmlproc.c' || echo '$(srcdir)/'`src/xmlproc.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-xmlproc.Tpo src/$(DEPDIR)/libwim_la-xmlproc.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/xmlproc.c' object='src/libwim_la-xmlproc.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-xmlproc.lo `test -f 'src/xmlproc.c' || echo '$(srcdir)/'`src/xmlproc.c
src/libwim_la-xpress_compress.lo: src/xpress_compress.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-xpress_compress.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-xpress_compress.Tpo -c -o src/libwim_la-xpress_compress.lo `test -f 'src/xpress_compress.c' || echo '$(srcdir)/'`src/xpress_compress.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-xpress_compress.Tpo src/$(DEPDIR)/libwim_la-xpress_compress.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/xpress_compress.c' object='src/libwim_la-xpress_compress.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-xpress_compress.lo `test -f 'src/xpress_compress.c' || echo '$(srcdir)/'`src/xpress_compress.c
src/libwim_la-xpress_decompress.lo: src/xpress_decompress.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-xpress_decompress.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-xpress_decompress.Tpo -c -o src/libwim_la-xpress_decompress.lo `test -f 'src/xpress_decompress.c' || echo '$(srcdir)/'`src/xpress_decompress.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-xpress_decompress.Tpo src/$(DEPDIR)/libwim_la-xpress_decompress.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/xpress_decompress.c' object='src/libwim_la-xpress_decompress.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-xpress_decompress.lo `test -f 'src/xpress_decompress.c' || echo '$(srcdir)/'`src/xpress_decompress.c
src/libwim_la-ntfs-3g_apply.lo: src/ntfs-3g_apply.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-ntfs-3g_apply.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-ntfs-3g_apply.Tpo -c -o src/libwim_la-ntfs-3g_apply.lo `test -f 'src/ntfs-3g_apply.c' || echo '$(srcdir)/'`src/ntfs-3g_apply.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-ntfs-3g_apply.Tpo src/$(DEPDIR)/libwim_la-ntfs-3g_apply.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ntfs-3g_apply.c' object='src/libwim_la-ntfs-3g_apply.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-ntfs-3g_apply.lo `test -f 'src/ntfs-3g_apply.c' || echo '$(srcdir)/'`src/ntfs-3g_apply.c
src/libwim_la-ntfs-3g_capture.lo: src/ntfs-3g_capture.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-ntfs-3g_capture.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-ntfs-3g_capture.Tpo -c -o src/libwim_la-ntfs-3g_capture.lo `test -f 'src/ntfs-3g_capture.c' || echo '$(srcdir)/'`src/ntfs-3g_capture.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-ntfs-3g_capture.Tpo src/$(DEPDIR)/libwim_la-ntfs-3g_capture.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ntfs-3g_capture.c' object='src/libwim_la-ntfs-3g_capture.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-ntfs-3g_capture.lo `test -f 'src/ntfs-3g_capture.c' || echo '$(srcdir)/'`src/ntfs-3g_capture.c
src/libwim_la-wimboot.lo: src/wimboot.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-wimboot.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-wimboot.Tpo -c -o src/libwim_la-wimboot.lo `test -f 'src/wimboot.c' || echo '$(srcdir)/'`src/wimboot.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-wimboot.Tpo src/$(DEPDIR)/libwim_la-wimboot.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/wimboot.c' object='src/libwim_la-wimboot.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-wimboot.lo `test -f 'src/wimboot.c' || echo '$(srcdir)/'`src/wimboot.c
src/libwim_la-win32_common.lo: src/win32_common.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-win32_common.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-win32_common.Tpo -c -o src/libwim_la-win32_common.lo `test -f 'src/win32_common.c' || echo '$(srcdir)/'`src/win32_common.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-win32_common.Tpo src/$(DEPDIR)/libwim_la-win32_common.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/win32_common.c' object='src/libwim_la-win32_common.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-win32_common.lo `test -f 'src/win32_common.c' || echo '$(srcdir)/'`src/win32_common.c
src/libwim_la-win32_apply.lo: src/win32_apply.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-win32_apply.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-win32_apply.Tpo -c -o src/libwim_la-win32_apply.lo `test -f 'src/win32_apply.c' || echo '$(srcdir)/'`src/win32_apply.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-win32_apply.Tpo src/$(DEPDIR)/libwim_la-win32_apply.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/win32_apply.c' object='src/libwim_la-win32_apply.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-win32_apply.lo `test -f 'src/win32_apply.c' || echo '$(srcdir)/'`src/win32_apply.c
src/libwim_la-win32_capture.lo: src/win32_capture.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-win32_capture.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-win32_capture.Tpo -c -o src/libwim_la-win32_capture.lo `test -f 'src/win32_capture.c' || echo '$(srcdir)/'`src/win32_capture.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-win32_capture.Tpo src/$(DEPDIR)/libwim_la-win32_capture.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/win32_capture.c' object='src/libwim_la-win32_capture.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-win32_capture.lo `test -f 'src/win32_capture.c' || echo '$(srcdir)/'`src/win32_capture.c
src/libwim_la-win32_replacements.lo: src/win32_replacements.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-win32_replacements.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-win32_replacements.Tpo -c -o src/libwim_la-win32_replacements.lo `test -f 'src/win32_replacements.c' || echo '$(srcdir)/'`src/win32_replacements.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-win32_replacements.Tpo src/$(DEPDIR)/libwim_la-win32_replacements.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/win32_replacements.c' object='src/libwim_la-win32_replacements.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-win32_replacements.lo `test -f 'src/win32_replacements.c' || echo '$(srcdir)/'`src/win32_replacements.c
src/libwim_la-win32_vss.lo: src/win32_vss.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-win32_vss.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-win32_vss.Tpo -c -o src/libwim_la-win32_vss.lo `test -f 'src/win32_vss.c' || echo '$(srcdir)/'`src/win32_vss.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-win32_vss.Tpo src/$(DEPDIR)/libwim_la-win32_vss.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/win32_vss.c' object='src/libwim_la-win32_vss.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-win32_vss.lo `test -f 'src/win32_vss.c' || echo '$(srcdir)/'`src/win32_vss.c
src/libwim_la-unix_apply.lo: src/unix_apply.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-unix_apply.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-unix_apply.Tpo -c -o src/libwim_la-unix_apply.lo `test -f 'src/unix_apply.c' || echo '$(srcdir)/'`src/unix_apply.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-unix_apply.Tpo src/$(DEPDIR)/libwim_la-unix_apply.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/unix_apply.c' object='src/libwim_la-unix_apply.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-unix_apply.lo `test -f 'src/unix_apply.c' || echo '$(srcdir)/'`src/unix_apply.c
src/libwim_la-unix_capture.lo: src/unix_capture.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-unix_capture.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-unix_capture.Tpo -c -o src/libwim_la-unix_capture.lo `test -f 'src/unix_capture.c' || echo '$(srcdir)/'`src/unix_capture.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-unix_capture.Tpo src/$(DEPDIR)/libwim_la-unix_capture.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/unix_capture.c' object='src/libwim_la-unix_capture.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-unix_capture.lo `test -f 'src/unix_capture.c' || echo '$(srcdir)/'`src/unix_capture.c
src/libwim_la-test_support.lo: src/test_support.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -MT src/libwim_la-test_support.lo -MD -MP -MF src/$(DEPDIR)/libwim_la-test_support.Tpo -c -o src/libwim_la-test_support.lo `test -f 'src/test_support.c' || echo '$(srcdir)/'`src/test_support.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libwim_la-test_support.Tpo src/$(DEPDIR)/libwim_la-test_support.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/test_support.c' object='src/libwim_la-test_support.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwim_la_CFLAGS) $(CFLAGS) -c -o src/libwim_la-test_support.lo `test -f 'src/test_support.c' || echo '$(srcdir)/'`src/test_support.c
programs/wimlib_imagex-imagex.o: programs/imagex.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -MT programs/wimlib_imagex-imagex.o -MD -MP -MF programs/$(DEPDIR)/wimlib_imagex-imagex.Tpo -c -o programs/wimlib_imagex-imagex.o `test -f 'programs/imagex.c' || echo '$(srcdir)/'`programs/imagex.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) programs/$(DEPDIR)/wimlib_imagex-imagex.Tpo programs/$(DEPDIR)/wimlib_imagex-imagex.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='programs/imagex.c' object='programs/wimlib_imagex-imagex.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -c -o programs/wimlib_imagex-imagex.o `test -f 'programs/imagex.c' || echo '$(srcdir)/'`programs/imagex.c
programs/wimlib_imagex-imagex.obj: programs/imagex.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -MT programs/wimlib_imagex-imagex.obj -MD -MP -MF programs/$(DEPDIR)/wimlib_imagex-imagex.Tpo -c -o programs/wimlib_imagex-imagex.obj `if test -f 'programs/imagex.c'; then $(CYGPATH_W) 'programs/imagex.c'; else $(CYGPATH_W) '$(srcdir)/programs/imagex.c'; fi`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) programs/$(DEPDIR)/wimlib_imagex-imagex.Tpo programs/$(DEPDIR)/wimlib_imagex-imagex.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='programs/imagex.c' object='programs/wimlib_imagex-imagex.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -c -o programs/wimlib_imagex-imagex.obj `if test -f 'programs/imagex.c'; then $(CYGPATH_W) 'programs/imagex.c'; else $(CYGPATH_W) '$(srcdir)/programs/imagex.c'; fi`
programs/wimlib_imagex-imagex-win32.o: programs/imagex-win32.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -MT programs/wimlib_imagex-imagex-win32.o -MD -MP -MF programs/$(DEPDIR)/wimlib_imagex-imagex-win32.Tpo -c -o programs/wimlib_imagex-imagex-win32.o `test -f 'programs/imagex-win32.c' || echo '$(srcdir)/'`programs/imagex-win32.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) programs/$(DEPDIR)/wimlib_imagex-imagex-win32.Tpo programs/$(DEPDIR)/wimlib_imagex-imagex-win32.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='programs/imagex-win32.c' object='programs/wimlib_imagex-imagex-win32.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -c -o programs/wimlib_imagex-imagex-win32.o `test -f 'programs/imagex-win32.c' || echo '$(srcdir)/'`programs/imagex-win32.c
programs/wimlib_imagex-imagex-win32.obj: programs/imagex-win32.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -MT programs/wimlib_imagex-imagex-win32.obj -MD -MP -MF programs/$(DEPDIR)/wimlib_imagex-imagex-win32.Tpo -c -o programs/wimlib_imagex-imagex-win32.obj `if test -f 'programs/imagex-win32.c'; then $(CYGPATH_W) 'programs/imagex-win32.c'; else $(CYGPATH_W) '$(srcdir)/programs/imagex-win32.c'; fi`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) programs/$(DEPDIR)/wimlib_imagex-imagex-win32.Tpo programs/$(DEPDIR)/wimlib_imagex-imagex-win32.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='programs/imagex-win32.c' object='programs/wimlib_imagex-imagex-win32.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -c -o programs/wimlib_imagex-imagex-win32.obj `if test -f 'programs/imagex-win32.c'; then $(CYGPATH_W) 'programs/imagex-win32.c'; else $(CYGPATH_W) '$(srcdir)/programs/imagex-win32.c'; fi`
programs/wimlib_imagex-wgetopt.o: programs/wgetopt.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -MT programs/wimlib_imagex-wgetopt.o -MD -MP -MF programs/$(DEPDIR)/wimlib_imagex-wgetopt.Tpo -c -o programs/wimlib_imagex-wgetopt.o `test -f 'programs/wgetopt.c' || echo '$(srcdir)/'`programs/wgetopt.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) programs/$(DEPDIR)/wimlib_imagex-wgetopt.Tpo programs/$(DEPDIR)/wimlib_imagex-wgetopt.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='programs/wgetopt.c' object='programs/wimlib_imagex-wgetopt.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -c -o programs/wimlib_imagex-wgetopt.o `test -f 'programs/wgetopt.c' || echo '$(srcdir)/'`programs/wgetopt.c
programs/wimlib_imagex-wgetopt.obj: programs/wgetopt.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -MT programs/wimlib_imagex-wgetopt.obj -MD -MP -MF programs/$(DEPDIR)/wimlib_imagex-wgetopt.Tpo -c -o programs/wimlib_imagex-wgetopt.obj `if test -f 'programs/wgetopt.c'; then $(CYGPATH_W) 'programs/wgetopt.c'; else $(CYGPATH_W) '$(srcdir)/programs/wgetopt.c'; fi`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) programs/$(DEPDIR)/wimlib_imagex-wgetopt.Tpo programs/$(DEPDIR)/wimlib_imagex-wgetopt.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='programs/wgetopt.c' object='programs/wimlib_imagex-wgetopt.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wimlib_imagex_CFLAGS) $(CFLAGS) -c -o programs/wimlib_imagex-wgetopt.obj `if test -f 'programs/wgetopt.c'; then $(CYGPATH_W) 'programs/wgetopt.c'; else $(CYGPATH_W) '$(srcdir)/programs/wgetopt.c'; fi`
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
-rm -rf src/.libs src/_libs
-rm -rf tests/.libs tests/_libs
distclean-libtool:
-rm -f libtool config.lt
install-man1: $(man1_MANS)
@$(NORMAL_INSTALL)
@list1='$(man1_MANS)'; \
list2=''; \
test -n "$(man1dir)" \
&& test -n "`echo $$list1$$list2`" \
|| exit 0; \
echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
{ for i in $$list1; do echo "$$i"; done; \
if test -n "$$list2"; then \
for i in $$list2; do echo "$$i"; done \
| sed -n '/\.1[a-z]*$$/p'; \
fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
done; }
uninstall-man1:
@$(NORMAL_UNINSTALL)
@list='$(man1_MANS)'; test -n "$(man1dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
install-pkgconfigDATA: $(pkgconfig_DATA)
@$(NORMAL_INSTALL)
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
done
uninstall-pkgconfigDATA:
@$(NORMAL_UNINSTALL)
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
$(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
$(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
done
uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscope: cscope.files
test ! -s cscope.files \
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
clean-cscope:
-rm -f cscope.files
cscope.files: clean-cscope cscopelist
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
# Recover from deleted '.trs' file; this should ensure that
# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
# to avoid problems with "make -n".
.log.trs:
rm -f $< $@
$(MAKE) $(AM_MAKEFLAGS) $<
# Leading 'am--fnord' is there to ensure the list of targets does not
# expand to empty, as could happen e.g. with make check TESTS=''.
am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
am--force-recheck:
@:
$(TEST_SUITE_LOG): $(TEST_LOGS)
@$(am__set_TESTS_bases); \
am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
redo_bases=`for i in $$bases; do \
am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
done`; \
if test -n "$$redo_bases"; then \
redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
if $(am__make_dryrun); then :; else \
rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
fi; \
fi; \
if test -n "$$am__remaking_logs"; then \
echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
"recursion detected" >&2; \
elif test -n "$$redo_logs"; then \
am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
fi; \
if $(am__make_dryrun); then :; else \
st=0; \
errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
for i in $$redo_bases; do \
test -f $$i.trs && test -r $$i.trs \
|| { echo "$$errmsg $$i.trs" >&2; st=1; }; \
test -f $$i.log && test -r $$i.log \
|| { echo "$$errmsg $$i.log" >&2; st=1; }; \
done; \
test $$st -eq 0 || exit 1; \
fi
@$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
ws='[ ]'; \
results=`for b in $$bases; do echo $$b.trs; done`; \
test -n "$$results" || results=/dev/null; \
all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
if test `expr $$fail + $$xpass + $$error` -eq 0; then \
success=true; \
else \
success=false; \
fi; \
br='==================='; br=$$br$$br$$br$$br; \
result_count () \
{ \
if test x"$$1" = x"--maybe-color"; then \
maybe_colorize=yes; \
elif test x"$$1" = x"--no-color"; then \
maybe_colorize=no; \
else \
echo "$@: invalid 'result_count' usage" >&2; exit 4; \
fi; \
shift; \
desc=$$1 count=$$2; \
if test $$maybe_colorize = yes && test $$count -gt 0; then \
color_start=$$3 color_end=$$std; \
else \
color_start= color_end=; \
fi; \
echo "$${color_start}# $$desc $$count$${color_end}"; \
}; \
create_testsuite_report () \
{ \
result_count $$1 "TOTAL:" $$all "$$brg"; \
result_count $$1 "PASS: " $$pass "$$grn"; \
result_count $$1 "SKIP: " $$skip "$$blu"; \
result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
result_count $$1 "FAIL: " $$fail "$$red"; \
result_count $$1 "XPASS:" $$xpass "$$red"; \
result_count $$1 "ERROR:" $$error "$$mgn"; \
}; \
output_system_information () \
{ \
echo; \
{ uname -a | $(AWK) '{ \
printf "System information (uname -a):"; \
for (i = 1; i < NF; ++i) \
{ \
if (i != 2) \
printf " %s", $$i; \
} \
printf "\n"; \
}'; } 2>&1; \
if test -r /etc/os-release; then \
echo "Distribution information (/etc/os-release):"; \
sed 8q /etc/os-release; \
elif test -r /etc/issue; then \
echo "Distribution information (/etc/issue):"; \
cat /etc/issue; \
fi; \
}; \
please_report () \
{ \
echo "Some test(s) failed. Please report this to $(PACKAGE_BUGREPORT),"; \
echo "together with the test-suite.log file (gzipped) and your system"; \
echo "information. Thanks."; \
}; \
{ \
echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
$(am__rst_title); \
create_testsuite_report --no-color; \
output_system_information; \
echo; \
echo ".. contents:: :depth: 2"; \
echo; \
for b in $$bases; do echo $$b; done \
| $(am__create_global_log); \
} >$(TEST_SUITE_LOG).tmp || exit 1; \
mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
if $$success; then \
col="$$grn"; \
else \
col="$$red"; \
test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
fi; \
echo "$${col}$$br$${std}"; \
echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \
echo "$${col}$$br$${std}"; \
create_testsuite_report --maybe-color; \
echo "$$col$$br$$std"; \
if $$success; then :; else \
echo "$${col}See $(subdir)/$(TEST_SUITE_LOG) for debugging.$${std}";\
if test -n "$(PACKAGE_BUGREPORT)"; then \
please_report | sed -e "s/^/$${col}/" -e s/'$$'/"$${std}"/; \
fi; \
echo "$$col$$br$$std"; \
fi; \
$$success || exit 1
check-TESTS: $(check_PROGRAMS) $(dist_check_SCRIPTS)
@$(am__rm_f) $(RECHECK_LOGS)
@$(am__rm_f) $(RECHECK_LOGS:.log=.trs)
@$(am__rm_f) $(TEST_SUITE_LOG)
@set +e; $(am__set_TESTS_bases); \
log_list=`for i in $$bases; do echo $$i.log; done`; \
log_list=`echo $$log_list`; \
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
exit $$?;
recheck: all $(check_PROGRAMS) $(dist_check_SCRIPTS)
@$(am__rm_f) $(TEST_SUITE_LOG)
@set +e; $(am__set_TESTS_bases); \
bases=`for i in $$bases; do echo $$i; done \
| $(am__list_recheck_tests)` || exit 1; \
log_list=`for i in $$bases; do echo $$i.log; done`; \
log_list=`echo $$log_list`; \
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
am__force_recheck=am--force-recheck \
TEST_LOGS="$$log_list"; \
exit $$?
tests/test-imagex.log: tests/test-imagex
@p='tests/test-imagex'; \
b='tests/test-imagex'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
tests/test-imagex-capture_and_apply.log: tests/test-imagex-capture_and_apply
@p='tests/test-imagex-capture_and_apply'; \
b='tests/test-imagex-capture_and_apply'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
tests/test-imagex-update_and_extract.log: tests/test-imagex-update_and_extract
@p='tests/test-imagex-update_and_extract'; \
b='tests/test-imagex-update_and_extract'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
tests/test-imagex-mount.log: tests/test-imagex-mount
@p='tests/test-imagex-mount'; \
b='tests/test-imagex-mount'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
tests/test-imagex-ntfs.log: tests/test-imagex-ntfs
@p='tests/test-imagex-ntfs'; \
b='tests/test-imagex-ntfs'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
.test.log:
@p='$<'; \
$(am__set_b); \
$(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
@am__EXEEXT_TRUE@.test$(EXEEXT).log:
@am__EXEEXT_TRUE@ @p='$<'; \
@am__EXEEXT_TRUE@ $(am__set_b); \
@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
$(am__remove_distdir)
$(AM_V_at)$(MKDIR_P) "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
-test -n "$(am__skip_mode_fix)" \
|| find "$(distdir)" -type d ! -perm -755 \
-exec chmod u+rwx,go+rx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r "$(distdir)"
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
$(am__post_remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
$(am__post_remove_distdir)
dist-bzip3: distdir
tardir=$(distdir) && $(am__tar) | bzip3 -c >$(distdir).tar.bz3
$(am__post_remove_distdir)
dist-lzip: distdir
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
$(am__post_remove_distdir)
dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__post_remove_distdir)
dist-zstd: distdir
tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
$(am__post_remove_distdir)
dist-tarZ: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__post_remove_distdir)
dist-shar: distdir
@echo WARNING: "Support for shar distribution archives is" \
"deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
$(am__post_remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__post_remove_distdir)
dist dist-all:
$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
$(am__post_remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
eval GZIP= gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.bz3*) \
bzip3 -dc $(distdir).tar.bz3 | $(am__untar) ;;\
*.tar.lz*) \
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
*.tar.xz*) \
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
eval GZIP= gzip -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
*.tar.zst*) \
zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
esac
chmod -R a-w $(distdir)
chmod u+w $(distdir)
mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
chmod a-w $(distdir)
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build/sub \
&& ../../configure \
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
&& rm -rf $(DIST_ARCHIVES) \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
&& cd "$$am__cwd" \
|| exit 1
$(am__post_remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
distuninstallcheck:
@test -n '$(distuninstallcheck_dir)' || { \
echo 'ERROR: trying to run $@ with an empty' \
'$$(distuninstallcheck_dir)' >&2; \
exit 1; \
}; \
$(am__cd) '$(distuninstallcheck_dir)' || { \
echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
exit 1; \
}; \
test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) \
$(dist_check_SCRIPTS)
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
check: check-am
all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(SCRIPTS) $(MANS) $(DATA) \
$(HEADERS) config.h
install-EXTRAPROGRAMS: install-libLTLIBRARIES
install-binPROGRAMS: install-libLTLIBRARIES
install-checkPROGRAMS: install-libLTLIBRARIES
installdirs:
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
-$(am__rm_f) $(TEST_LOGS)
-$(am__rm_f) $(TEST_LOGS:.log=.trs)
-$(am__rm_f) $(TEST_SUITE_LOG)
clean-generic:
distclean-generic:
-$(am__rm_f) $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
-$(am__rm_f) programs/$(DEPDIR)/$(am__dirstamp)
-$(am__rm_f) programs/$(am__dirstamp)
-$(am__rm_f) src/$(DEPDIR)/$(am__dirstamp)
-$(am__rm_f) src/$(am__dirstamp)
-$(am__rm_f) tests/$(DEPDIR)/$(am__dirstamp)
-$(am__rm_f) tests/$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
clean-libLTLIBRARIES clean-libtool mostlyclean-am
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -f programs/$(DEPDIR)/wimlib_imagex-imagex-win32.Po
-rm -f programs/$(DEPDIR)/wimlib_imagex-imagex.Po
-rm -f programs/$(DEPDIR)/wimlib_imagex-wgetopt.Po
-rm -f src/$(DEPDIR)/libwim_la-add_image.Plo
-rm -f src/$(DEPDIR)/libwim_la-avl_tree.Plo
-rm -f src/$(DEPDIR)/libwim_la-blob_table.Plo
-rm -f src/$(DEPDIR)/libwim_la-compress.Plo
-rm -f src/$(DEPDIR)/libwim_la-compress_common.Plo
-rm -f src/$(DEPDIR)/libwim_la-compress_parallel.Plo
-rm -f src/$(DEPDIR)/libwim_la-compress_serial.Plo
-rm -f src/$(DEPDIR)/libwim_la-cpu_features.Plo
-rm -f src/$(DEPDIR)/libwim_la-decompress.Plo
-rm -f src/$(DEPDIR)/libwim_la-decompress_common.Plo
-rm -f src/$(DEPDIR)/libwim_la-delete_image.Plo
-rm -f src/$(DEPDIR)/libwim_la-dentry.Plo
-rm -f src/$(DEPDIR)/libwim_la-divsufsort.Plo
-rm -f src/$(DEPDIR)/libwim_la-encoding.Plo
-rm -f src/$(DEPDIR)/libwim_la-error.Plo
-rm -f src/$(DEPDIR)/libwim_la-export_image.Plo
-rm -f src/$(DEPDIR)/libwim_la-extract.Plo
-rm -f src/$(DEPDIR)/libwim_la-file_io.Plo
-rm -f src/$(DEPDIR)/libwim_la-header.Plo
-rm -f src/$(DEPDIR)/libwim_la-inode.Plo
-rm -f src/$(DEPDIR)/libwim_la-inode_fixup.Plo
-rm -f src/$(DEPDIR)/libwim_la-inode_table.Plo
-rm -f src/$(DEPDIR)/libwim_la-integrity.Plo
-rm -f src/$(DEPDIR)/libwim_la-iterate_dir.Plo
-rm -f src/$(DEPDIR)/libwim_la-join.Plo
-rm -f src/$(DEPDIR)/libwim_la-lcpit_matchfinder.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzms_common.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzms_compress.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzms_decompress.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzx_common.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzx_compress.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzx_decompress.Plo
-rm -f src/$(DEPDIR)/libwim_la-metadata_resource.Plo
-rm -f src/$(DEPDIR)/libwim_la-mount_image.Plo
-rm -f src/$(DEPDIR)/libwim_la-ntfs-3g_apply.Plo
-rm -f src/$(DEPDIR)/libwim_la-ntfs-3g_capture.Plo
-rm -f src/$(DEPDIR)/libwim_la-pathlist.Plo
-rm -f src/$(DEPDIR)/libwim_la-paths.Plo
-rm -f src/$(DEPDIR)/libwim_la-pattern.Plo
-rm -f src/$(DEPDIR)/libwim_la-progress.Plo
-rm -f src/$(DEPDIR)/libwim_la-reference.Plo
-rm -f src/$(DEPDIR)/libwim_la-registry.Plo
-rm -f src/$(DEPDIR)/libwim_la-reparse.Plo
-rm -f src/$(DEPDIR)/libwim_la-resource.Plo
-rm -f src/$(DEPDIR)/libwim_la-scan.Plo
-rm -f src/$(DEPDIR)/libwim_la-security.Plo
-rm -f src/$(DEPDIR)/libwim_la-sha1.Plo
-rm -f src/$(DEPDIR)/libwim_la-solid.Plo
-rm -f src/$(DEPDIR)/libwim_la-split.Plo
-rm -f src/$(DEPDIR)/libwim_la-tagged_items.Plo
-rm -f src/$(DEPDIR)/libwim_la-template.Plo
-rm -f src/$(DEPDIR)/libwim_la-test_support.Plo
-rm -f src/$(DEPDIR)/libwim_la-textfile.Plo
-rm -f src/$(DEPDIR)/libwim_la-threads.Plo
-rm -f src/$(DEPDIR)/libwim_la-timestamp.Plo
-rm -f src/$(DEPDIR)/libwim_la-unix_apply.Plo
-rm -f src/$(DEPDIR)/libwim_la-unix_capture.Plo
-rm -f src/$(DEPDIR)/libwim_la-update_image.Plo
-rm -f src/$(DEPDIR)/libwim_la-util.Plo
-rm -f src/$(DEPDIR)/libwim_la-verify.Plo
-rm -f src/$(DEPDIR)/libwim_la-wim.Plo
-rm -f src/$(DEPDIR)/libwim_la-wimboot.Plo
-rm -f src/$(DEPDIR)/libwim_la-win32_apply.Plo
-rm -f src/$(DEPDIR)/libwim_la-win32_capture.Plo
-rm -f src/$(DEPDIR)/libwim_la-win32_common.Plo
-rm -f src/$(DEPDIR)/libwim_la-win32_replacements.Plo
-rm -f src/$(DEPDIR)/libwim_la-win32_vss.Plo
-rm -f src/$(DEPDIR)/libwim_la-write.Plo
-rm -f src/$(DEPDIR)/libwim_la-xml.Plo
-rm -f src/$(DEPDIR)/libwim_la-xml_windows.Plo
-rm -f src/$(DEPDIR)/libwim_la-xmlproc.Plo
-rm -f src/$(DEPDIR)/libwim_la-xpress_compress.Plo
-rm -f src/$(DEPDIR)/libwim_la-xpress_decompress.Plo
-rm -f tests/$(DEPDIR)/tree-cmp.Po
-rm -f tests/$(DEPDIR)/wlfuzz.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-includeHEADERS install-man \
install-pkgconfigDATA
@$(NORMAL_INSTALL)
$(MAKE) $(AM_MAKEFLAGS) install-data-hook
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-binPROGRAMS install-dist_binSCRIPTS \
install-libLTLIBRARIES
@$(NORMAL_INSTALL)
$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man: install-man1
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -f programs/$(DEPDIR)/wimlib_imagex-imagex-win32.Po
-rm -f programs/$(DEPDIR)/wimlib_imagex-imagex.Po
-rm -f programs/$(DEPDIR)/wimlib_imagex-wgetopt.Po
-rm -f src/$(DEPDIR)/libwim_la-add_image.Plo
-rm -f src/$(DEPDIR)/libwim_la-avl_tree.Plo
-rm -f src/$(DEPDIR)/libwim_la-blob_table.Plo
-rm -f src/$(DEPDIR)/libwim_la-compress.Plo
-rm -f src/$(DEPDIR)/libwim_la-compress_common.Plo
-rm -f src/$(DEPDIR)/libwim_la-compress_parallel.Plo
-rm -f src/$(DEPDIR)/libwim_la-compress_serial.Plo
-rm -f src/$(DEPDIR)/libwim_la-cpu_features.Plo
-rm -f src/$(DEPDIR)/libwim_la-decompress.Plo
-rm -f src/$(DEPDIR)/libwim_la-decompress_common.Plo
-rm -f src/$(DEPDIR)/libwim_la-delete_image.Plo
-rm -f src/$(DEPDIR)/libwim_la-dentry.Plo
-rm -f src/$(DEPDIR)/libwim_la-divsufsort.Plo
-rm -f src/$(DEPDIR)/libwim_la-encoding.Plo
-rm -f src/$(DEPDIR)/libwim_la-error.Plo
-rm -f src/$(DEPDIR)/libwim_la-export_image.Plo
-rm -f src/$(DEPDIR)/libwim_la-extract.Plo
-rm -f src/$(DEPDIR)/libwim_la-file_io.Plo
-rm -f src/$(DEPDIR)/libwim_la-header.Plo
-rm -f src/$(DEPDIR)/libwim_la-inode.Plo
-rm -f src/$(DEPDIR)/libwim_la-inode_fixup.Plo
-rm -f src/$(DEPDIR)/libwim_la-inode_table.Plo
-rm -f src/$(DEPDIR)/libwim_la-integrity.Plo
-rm -f src/$(DEPDIR)/libwim_la-iterate_dir.Plo
-rm -f src/$(DEPDIR)/libwim_la-join.Plo
-rm -f src/$(DEPDIR)/libwim_la-lcpit_matchfinder.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzms_common.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzms_compress.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzms_decompress.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzx_common.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzx_compress.Plo
-rm -f src/$(DEPDIR)/libwim_la-lzx_decompress.Plo
-rm -f src/$(DEPDIR)/libwim_la-metadata_resource.Plo
-rm -f src/$(DEPDIR)/libwim_la-mount_image.Plo
-rm -f src/$(DEPDIR)/libwim_la-ntfs-3g_apply.Plo
-rm -f src/$(DEPDIR)/libwim_la-ntfs-3g_capture.Plo
-rm -f src/$(DEPDIR)/libwim_la-pathlist.Plo
-rm -f src/$(DEPDIR)/libwim_la-paths.Plo
-rm -f src/$(DEPDIR)/libwim_la-pattern.Plo
-rm -f src/$(DEPDIR)/libwim_la-progress.Plo
-rm -f src/$(DEPDIR)/libwim_la-reference.Plo
-rm -f src/$(DEPDIR)/libwim_la-registry.Plo
-rm -f src/$(DEPDIR)/libwim_la-reparse.Plo
-rm -f src/$(DEPDIR)/libwim_la-resource.Plo
-rm -f src/$(DEPDIR)/libwim_la-scan.Plo
-rm -f src/$(DEPDIR)/libwim_la-security.Plo
-rm -f src/$(DEPDIR)/libwim_la-sha1.Plo
-rm -f src/$(DEPDIR)/libwim_la-solid.Plo
-rm -f src/$(DEPDIR)/libwim_la-split.Plo
-rm -f src/$(DEPDIR)/libwim_la-tagged_items.Plo
-rm -f src/$(DEPDIR)/libwim_la-template.Plo
-rm -f src/$(DEPDIR)/libwim_la-test_support.Plo
-rm -f src/$(DEPDIR)/libwim_la-textfile.Plo
-rm -f src/$(DEPDIR)/libwim_la-threads.Plo
-rm -f src/$(DEPDIR)/libwim_la-timestamp.Plo
-rm -f src/$(DEPDIR)/libwim_la-unix_apply.Plo
-rm -f src/$(DEPDIR)/libwim_la-unix_capture.Plo
-rm -f src/$(DEPDIR)/libwim_la-update_image.Plo
-rm -f src/$(DEPDIR)/libwim_la-util.Plo
-rm -f src/$(DEPDIR)/libwim_la-verify.Plo
-rm -f src/$(DEPDIR)/libwim_la-wim.Plo
-rm -f src/$(DEPDIR)/libwim_la-wimboot.Plo
-rm -f src/$(DEPDIR)/libwim_la-win32_apply.Plo
-rm -f src/$(DEPDIR)/libwim_la-win32_capture.Plo
-rm -f src/$(DEPDIR)/libwim_la-win32_common.Plo
-rm -f src/$(DEPDIR)/libwim_la-win32_replacements.Plo
-rm -f src/$(DEPDIR)/libwim_la-win32_vss.Plo
-rm -f src/$(DEPDIR)/libwim_la-write.Plo
-rm -f src/$(DEPDIR)/libwim_la-xml.Plo
-rm -f src/$(DEPDIR)/libwim_la-xml_windows.Plo
-rm -f src/$(DEPDIR)/libwim_la-xmlproc.Plo
-rm -f src/$(DEPDIR)/libwim_la-xpress_compress.Plo
-rm -f src/$(DEPDIR)/libwim_la-xpress_decompress.Plo
-rm -f tests/$(DEPDIR)/tree-cmp.Po
-rm -f tests/$(DEPDIR)/wlfuzz.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-dist_binSCRIPTS \
uninstall-includeHEADERS uninstall-libLTLIBRARIES \
uninstall-man uninstall-pkgconfigDATA
@$(NORMAL_INSTALL)
$(MAKE) $(AM_MAKEFLAGS) uninstall-hook
uninstall-man: uninstall-man1
.MAKE: all check-am install-am install-data-am install-exec-am \
install-strip uninstall-am
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles am--refresh check \
check-TESTS check-am clean clean-binPROGRAMS \
clean-checkPROGRAMS clean-cscope clean-generic \
clean-libLTLIBRARIES clean-libtool cscope cscopelist-am ctags \
ctags-am dist dist-all dist-bzip2 dist-bzip3 dist-gzip \
dist-lzip dist-shar dist-tarZ dist-xz dist-zip dist-zstd \
distcheck distclean distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags distcleancheck \
distdir distuninstallcheck dvi dvi-am html html-am info \
info-am install install-am install-binPROGRAMS install-data \
install-data-am install-data-hook install-dist_binSCRIPTS \
install-dvi install-dvi-am install-exec install-exec-am \
install-exec-hook install-html install-html-am \
install-includeHEADERS install-info install-info-am \
install-libLTLIBRARIES install-man install-man1 install-pdf \
install-pdf-am install-pkgconfigDATA install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am recheck tags tags-am uninstall \
uninstall-am uninstall-binPROGRAMS uninstall-dist_binSCRIPTS \
uninstall-hook uninstall-includeHEADERS \
uninstall-libLTLIBRARIES uninstall-man uninstall-man1 \
uninstall-pkgconfigDATA
.PRECIOUS: Makefile
wimlib.pc: config.status
##############################################################################
# Hooks #
##############################################################################
install-exec-hook:
for cmd in $(wimlib_imagex_cmds); do \
cd $(DESTDIR)$(bindir) && \
ln -f wimlib-imagex wim$${cmd}; \
done
install-data-hook:
for cmd in $(wimlib_imagex_cmds); do \
cd $(DESTDIR)$(mandir)/man1 && \
ln -sf wim$${cmd}.1 wimlib-imagex-$${cmd}.1; \
done
uninstall-hook:
for cmd in $(wimlib_imagex_cmds); do \
rm -f $(DESTDIR)$(bindir)/wim$${cmd}; \
rm -f $(DESTDIR)$(mandir)/man1/wim$${cmd}.1; \
done
##############################################################################
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
# Tell GNU make to disable its built-in pattern rules.
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%
wimlib-1.14.5/README.WINDOWS.md 0000644 0001750 0001750 00000013315 15137024476 013003 0 ustar 00e e # Introduction
wimlib is free and open source software that is available on both UNIX-like
systems and Windows. This file provides additional information specifically
about the Windows version of wimlib and the command line tool `wimlib-imagex`
that is distributed with it. It does not obsolete the generic
[README](README.md), which you should read too.
# Windows distribution
The Windows distribution of wimlib is a ZIP file containing the following items:
- `wimlib-imagex.exe`, a command-line tool to deal with WIM (.wim), split WIM
(.swm), and ESD (.esd) files that is inspired by Microsoft's ImageX and DISM.
This is a ready-to-run executable and not an installer.
- Very short batch scripts (e.g. `wimapply.cmd`) which are shortcuts to the
corresponding `wimlib-imagex` commands (e.g. `wimlib-imagex apply`).
- The library itself in DLL format (`libwim-15.dll`). `wimlib-imagex.exe`
requires this to run.
- The documentation, including this file, the generic README, and PDF
documentation for `wimlib-imagex` in the `doc` folder.
- License files for all software included. These are all free software
licenses. `COPYING.txt` is the main license, and it refers to
`COPYING.GPLv3.txt` and `COPYING.LGPL.txt`. The other licenses are for
third-party software included in the library.
- Development files in the `devel` folder. These are only needed if you are
developing C or C++ applications that use wimlib.
Note that there are separate ZIP files for 32-bit `i686` and 64-bit `x86_64`
binaries. They are both fully supported, but you should prefer the 64-bit
binaries when possible as they can be noticeably faster.
# wimlib-imagex
`wimlib-imagex` supports most features of Microsoft's ImageX as well as some
features that are supported by DISM but not by ImageX. wimlib-imagex also
supports some features that neither ImageX nor DISM support. Some of the
advantages of `wimlib-imagex` compared to ImageX and DISM are:
- `wimlib-imagex` provides "extract" and "update" commands which allow you to
quickly work with WIM images without mounting them.
- `wimlib-imagex` provides an easy-to-use "optimize" command which removes
wasted space from a WIM file and optionally recompresses it with stronger
compression.
- wimlib includes advanced implementations of all compression algorithms used in
WIM files. They usually outperform and outcompress their Microsoft
equivalents.
- `wimlib-imagex` supports solid WIM files and LZMS compression, for example as
used in ESD (.esd) files. (These are partially supported by recent DISM
versions but not by ImageX.)
- `wimlib-imagex` supports imaging a live Windows system. Just use the
`--snapshot` option.
- In many cases, `wimlib-imagex` has simpler command-line syntax than either
ImageX or DISM.
- Whenever possible, `wimlib-imagex` includes improved documentation and
informational output compared to Microsoft's software.
- wimlib and `wimlib-imagex` are free software, so you can modify and/or audit
the source code.
However, some limitations of `wimlib-imagex` compared to ImageX and DISM are:
- On Windows, `wimlib-imagex` does not support mounting WIM images.
- `wimlib-imagex` has no awareness of Windows "packages".
# Additional notes
It's recommended to use `wimlib-imagex` in scripts to avoid having to
interactively enter commands. However, note that `wimlib-imagex` is largely
just a command-line front-end for wimlib, and it's possible to use wimlib's API
in other front-ends or applications. Currently there is no official graphical
user interface available for wimlib or `wimlib-imagex`. However,
[Wimlib-clc](https://reboot.pro/files/file/588-wimlib-clc/) is an unofficial,
Windows-only graphical user interface for `wimlib-imagex`.
# Building from source
As with other open source software, advanced users may choose to build wimlib
from source, potentially with customizations. Currently, wimlib depends on
MinGW-w64 for its Windows support; Visual Studio is not supported. The Windows
binaries can be cross-compiled on Linux, or built on Windows using MSYS2 or
Cygwin. The following instructions show the MSYS2 method.
First, install MSYS2 by running the installer from
[msys2.org](https://www.msys2.org).
Then, open any MSYS2 shell and run the following command:
pacman -Syu --noconfirm
After that, open any MSYS2 shell again and run the following commands:
pacman -Syu --noconfirm git
git clone https://wimlib.net/git/wimlib
Note: By default the git repository will be on the `master` branch, which is the
latest development snapshot. Optionally, you can check out a specific version,
e.g. `cd wimlib && git checkout v1.14.5`. For old versions, please refer to the
documentation for that version, as things may have changed. It is also possible
to use a release tarball (e.g. `wimlib-1.14.5.tar.gz`) instead of the git repo.
Finally, to actually do a build, close the MSYS2 shell you have open, then open
one of the following from the Start menu:
- "MSYS2 MINGW64" - for `x86_64` binaries, built with gcc
- "MSYS2 CLANG64" - for `x86_64` binaries, built with clang
- "MSYS2 MINGW32" - for `i686` binaries, built with gcc
- "MSYS2 CLANGARM64" - for ARM64 binaries (EXPERIMENTAL)
(If unsure, use "MSYS2 MINGW64".) Then run the following commands:
cd wimlib
tools/windows-build.sh --install-prerequisites
The script will automatically download and install the packages needed to build
wimlib in the chosen MSYS2 environment, then build wimlib. The output will be
in a folder named similarly to `wimlib-1.14.5-windows-x86_64-bin`. Note that
your "home" folder within MSYS2 is `C:\msys64\home\%USERNAME%` by default.
Therefore, the full path to the output folder will be similar to
`C:\msys64\home\%USERNAME%\wimlib\wimlib-1.14.5-windows-x86_64-bin`.
wimlib-1.14.5/configure 0000744 0001750 0001750 00002161407 15137024752 012305 0 ustar 00e e #! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.72 for wimlib 1.14.5.
#
# Report bugs to .
#
#
# Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation,
# Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else case e in #(
e) case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac ;;
esac
fi
# Reset variables that may have inherited troublesome values from
# the environment.
# IFS needs to be set, to space, tab, and newline, in precisely that order.
# (If _AS_PATH_WALK were called with IFS unset, it would have the
# side effect of setting IFS to empty, thus disabling word splitting.)
# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
IFS=" "" $as_nl"
PS1='$ '
PS2='> '
PS4='+ '
# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE
# We cannot yet rely on "unset" to work, but we need these variables
# to be unset--not just set to an empty or harmless value--now, to
# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
# also avoids known problems related to "unset" and subshell syntax
# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
do eval test \${$as_var+y} \
&& ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
# Ensure that fds 0, 1, and 2 are open.
if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
PATH_SEPARATOR=';'
}
fi
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
;;
esac
# We did not find ourselves, most probably we were run as 'sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
_as_can_reexec=no; export _as_can_reexec;
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
*v*x* | *x*v* ) as_opts=-vx ;;
*v* ) as_opts=-v ;;
*x* ) as_opts=-x ;;
* ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed 'exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
else case e in #(
e) case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac ;;
esac
fi
"
as_required="as_fn_return () { (exit \$1); }
as_fn_success () { as_fn_return 0; }
as_fn_failure () { as_fn_return 1; }
as_fn_ret_success () { return 0; }
as_fn_ret_failure () { return 1; }
exitcode=0
as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
if ( set x; as_fn_ret_success y && test x = \"\$1\" )
then :
else case e in #(
e) exitcode=1; echo positional parameters were not saved. ;;
esac
fi
test x\$exitcode = x0 || exit 1
blah=\$(echo \$(echo blah))
test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
PATH=/empty FPATH=/empty; export PATH FPATH
test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
|| test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
if (eval "$as_required") 2>/dev/null
then :
as_have_required=yes
else case e in #(
e) as_have_required=no ;;
esac
fi
if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
then :
else case e in #(
e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
then :
CONFIG_SHELL=$as_shell as_have_required=yes
if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
then :
break 2
fi
fi
done;;
esac
as_found=false
done
IFS=$as_save_IFS
if $as_found
then :
else case e in #(
e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
then :
CONFIG_SHELL=$SHELL as_have_required=yes
fi ;;
esac
fi
if test "x$CONFIG_SHELL" != x
then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
*v*x* | *x*v* ) as_opts=-vx ;;
*v* ) as_opts=-v ;;
*x* ) as_opts=-x ;;
* ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed 'exec'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
if test x$as_have_required = xno
then :
printf "%s\n" "$0: This script requires a shell more modern than all"
printf "%s\n" "$0: the shells that I found on your system."
if test ${ZSH_VERSION+y} ; then
printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and
$0: https://wimlib.net/forums/ about your system, including
$0: any error possibly output before this message. Then
$0: install a modern shell, or manually run the script
$0: under such a shell if you do have one."
fi
exit 1
fi ;;
esac
fi
fi
SHELL=${CONFIG_SHELL-/bin/sh}
export SHELL
# Unset more variables known to interfere with behavior of common tools.
CLICOLOR_FORCE= GREP_OPTIONS=
unset CLICOLOR_FORCE GREP_OPTIONS
## --------------------- ##
## M4sh Shell Functions. ##
## --------------------- ##
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
return $1
} # as_fn_set_status
# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
set +e
as_fn_set_status $1
exit $1
} # as_fn_exit
# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{
case $as_dir in #(
-*) as_dir=./$as_dir;;
esac
test -d "$as_dir" || eval $as_mkdir_p || {
as_dirs=
while :; do
case $as_dir in #(
*\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
test -d "$as_dir" && break
done
test -z "$as_dirs" || eval "mkdir $as_dirs"
} || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
} # as_fn_mkdir_p
# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
test -f "$1" && test -x "$1"
} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
else case e in #(
e) as_fn_append ()
{
eval $1=\$$1\$2
} ;;
esac
fi # as_fn_append
# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
else case e in #(
e) as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
} ;;
esac
fi # as_fn_arith
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
if expr a : '\(a\)' >/dev/null 2>&1 &&
test "X`expr 00001 : '.*\(...\)'`" = X001; then
as_expr=expr
else
as_expr=false
fi
if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
as_dirname=dirname
else
as_dirname=false
fi
as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
}
/^X\/\(\/\/\)$/{
s//\1/
q
}
/^X\/\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
as_lineno_1=$LINENO as_lineno_1a=$LINENO
as_lineno_2=$LINENO as_lineno_2a=$LINENO
eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
# Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
sed -n '
p
/[$]LINENO/=
' <$as_myself |
sed '
t clear
:clear
s/[$]LINENO.*/&-/
t lineno
b
:lineno
N
:loop
s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
t loop
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
{ printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
# in an infinite loop. This has already happened in practice.
_as_can_reexec=no; export _as_can_reexec
# Don't try to exec as it changes $[0], causing all sort of problems
# (the dirname of $[0] is not the place where we might find the
# original and so on. Autoconf is especially sensitive to this).
. "./$as_me.lineno"
# Exit status is that of the last command.
exit
}
# Determine whether it's possible to make 'echo' print without a newline.
# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
case `echo 'xy\c'` in
*c*) ECHO_T=' ';; # ECHO_T is single tab character.
xy) ECHO_C='\c';;
*) echo `echo ksh88 bug on AIX 6.1` > /dev/null
ECHO_T=' ';;
esac;;
*)
ECHO_N='-n';;
esac
# For backward compatibility with old third-party macros, we provide
# the shell variables $as_echo and $as_echo_n. New code should use
# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
as_echo='printf %s\n'
as_echo_n='printf %s'
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
else
rm -f conf$$.dir
mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
if ln -s conf$$.file conf$$ 2>/dev/null; then
as_ln_s='ln -s'
# ... but there are two gotchas:
# 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
# In both cases, we have to default to 'cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -pR'
fi
else
as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
if mkdir -p . 2>/dev/null; then
as_mkdir_p='mkdir -p "$as_dir"'
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
as_test_x='test -x'
as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated
# Sed expression to map a string onto a valid variable name.
as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
as_tr_sh="eval sed '$as_sed_sh'" # deprecated
SHELL=${CONFIG_SHELL-/bin/sh}
test -n "$DJDIR" || exec 7<&0 &1
# Name of the host.
# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
# so uname gets run too.
ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
#
# Initializations.
#
ac_default_prefix=/usr/local
ac_clean_files=
ac_config_libobj_dir=.
LIBOBJS=
cross_compiling=no
subdirs=
MFLAGS=
MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='wimlib'
PACKAGE_TARNAME='wimlib'
PACKAGE_VERSION='1.14.5'
PACKAGE_STRING='wimlib 1.14.5'
PACKAGE_BUGREPORT='https://wimlib.net/forums/'
PACKAGE_URL=''
ac_unique_file="src/wim.c"
# Factoring default headers for most tests.
ac_includes_default="\
#include
#ifdef HAVE_STDIO_H
# include
#endif
#ifdef HAVE_STDLIB_H
# include
#endif
#ifdef HAVE_STRING_H
# include
#endif
#ifdef HAVE_INTTYPES_H
# include
#endif
#ifdef HAVE_STDINT_H
# include
#endif
#ifdef HAVE_STRINGS_H
# include
#endif
#ifdef HAVE_SYS_TYPES_H
# include
#endif
#ifdef HAVE_SYS_STAT_H
# include
#endif
#ifdef HAVE_UNISTD_H
# include
#endif"
ac_header_c_list=
ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
PKGCONFIG_PRIVATE_LIBS
PKGCONFIG_PRIVATE_REQUIRES
ENABLE_TEST_SUPPORT_FALSE
ENABLE_TEST_SUPPORT_TRUE
pkgconfigdir
WITH_FUSE_FALSE
WITH_FUSE_TRUE
LIBRT_LIBS
LIBFUSE_LIBS
LIBFUSE_CFLAGS
WITH_NTFS_3G_FALSE
WITH_NTFS_3G_TRUE
LIBNTFS_3G_LIBS
LIBNTFS_3G_CFLAGS
PTHREAD_CFLAGS
PTHREAD_LIBS
PTHREAD_CXX
PTHREAD_CC
ax_pthread_config
CPP
WINDOWS_NATIVE_BUILD_FALSE
WINDOWS_NATIVE_BUILD_TRUE
PLATFORM_LDFLAGS
PLATFORM_CFLAGS
PLATFORM_CPPFLAGS
PKG_CONFIG_LIBDIR
PKG_CONFIG_PATH
PKG_CONFIG
LT_SYS_LIBRARY_PATH
OTOOL64
OTOOL
LIPO
NMEDIT
DSYMUTIL
MANIFEST_TOOL
RANLIB
DLLTOOL
OBJDUMP
FILECMD
LN_S
NM
ac_ct_DUMPBIN
DUMPBIN
LD
FGREP
EGREP
GREP
SED
host_os
host_vendor
host_cpu
host
build_os
build_vendor
build_cpu
build
LIBTOOL
ac_ct_AR
AR
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
am__nodep
AMDEPBACKSLASH
AMDEP_FALSE
AMDEP_TRUE
am__include
DEPDIR
OBJEXT
EXEEXT
ac_ct_CC
CPPFLAGS
LDFLAGS
CFLAGS
CC
am__xargs_n
am__rm_f_notfound
AM_BACKSLASH
AM_DEFAULT_VERBOSITY
AM_DEFAULT_V
AM_V
CSCOPE
ETAGS
CTAGS
am__untar
am__tar
AMTAR
am__leading_dot
SET_MAKE
AWK
mkdir_p
MKDIR_P
INSTALL_STRIP_PROGRAM
STRIP
install_sh
MAKEINFO
AUTOHEADER
AUTOMAKE
AUTOCONF
ACLOCAL
VERSION
PACKAGE
CYGPATH_W
am__isrc
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
target_alias
host_alias
build_alias
LIBS
ECHO_T
ECHO_N
ECHO_C
DEFS
mandir
localedir
libdir
psdir
pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir
bindir
program_transform_name
prefix
exec_prefix
PACKAGE_URL
PACKAGE_BUGREPORT
PACKAGE_STRING
PACKAGE_VERSION
PACKAGE_TARNAME
PACKAGE_NAME
PATH_SEPARATOR
SHELL
am__quote'
ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_silent_rules
enable_dependency_tracking
enable_shared
enable_static
enable_pic
with_pic
enable_cxx_stdlib
enable_fast_install
enable_aix_soname
with_aix_soname
with_gnu_ld
with_sysroot
enable_libtool_lock
with_ntfs_3g
with_fuse
with_pkgconfigdir
enable_test_support
'
ac_precious_vars='build_alias
host_alias
target_alias
CC
CFLAGS
LDFLAGS
LIBS
CPPFLAGS
LT_SYS_LIBRARY_PATH
PKG_CONFIG
PKG_CONFIG_PATH
PKG_CONFIG_LIBDIR
CPP
LIBNTFS_3G_CFLAGS
LIBNTFS_3G_LIBS
LIBFUSE_CFLAGS
LIBFUSE_LIBS'
# Initialize some variables set by options.
ac_init_help=
ac_init_version=false
ac_unrecognized_opts=
ac_unrecognized_sep=
# The variables have the same names as the options, with
# dashes changed to underlines.
cache_file=/dev/null
exec_prefix=NONE
no_create=
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
verbose=
x_includes=NONE
x_libraries=NONE
# Installation directory options.
# These are left unexpanded so users can "make install exec_prefix=/foo"
# and all the variables that are supposed to be based on exec_prefix
# by default will actually change.
# Use braces instead of parens because sh, perl, etc. also accept them.
# (The list follows the same order as the GNU Coding Standards.)
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'
psdir='${docdir}'
libdir='${exec_prefix}/lib'
localedir='${datarootdir}/locale'
mandir='${datarootdir}/man'
ac_prev=
ac_dashdash=
for ac_option
do
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval $ac_prev=\$ac_option
ac_prev=
continue
fi
case $ac_option in
*=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
*=) ac_optarg= ;;
*) ac_optarg=yes ;;
esac
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
bindir=$ac_optarg ;;
-build | --build | --buil | --bui | --bu)
ac_prev=build_alias ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
build_alias=$ac_optarg ;;
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
cache_file=$ac_optarg ;;
--config-cache | -C)
cache_file=config.cache ;;
-datadir | --datadir | --datadi | --datad)
ac_prev=datadir ;;
-datadir=* | --datadir=* | --datadi=* | --datad=*)
datadir=$ac_optarg ;;
-datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
| --dataroo | --dataro | --datar)
ac_prev=datarootdir ;;
-datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
| --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
datarootdir=$ac_optarg ;;
-disable-* | --disable-*)
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid feature name: '$ac_useropt'"
ac_useropt_orig=$ac_useropt
ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval enable_$ac_useropt=no ;;
-docdir | --docdir | --docdi | --doc | --do)
ac_prev=docdir ;;
-docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
docdir=$ac_optarg ;;
-dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
ac_prev=dvidir ;;
-dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
dvidir=$ac_optarg ;;
-enable-* | --enable-*)
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid feature name: '$ac_useropt'"
ac_useropt_orig=$ac_useropt
ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval enable_$ac_useropt=\$ac_optarg ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
| --exec | --exe | --ex)
ac_prev=exec_prefix ;;
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
exec_prefix=$ac_optarg ;;
-gas | --gas | --ga | --g)
# Obsolete; use --with-gas.
with_gas=yes ;;
-help | --help | --hel | --he | -h)
ac_init_help=long ;;
-help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
ac_init_help=recursive ;;
-help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
ac_init_help=short ;;
-host | --host | --hos | --ho)
ac_prev=host_alias ;;
-host=* | --host=* | --hos=* | --ho=*)
host_alias=$ac_optarg ;;
-htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
ac_prev=htmldir ;;
-htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
| --ht=*)
htmldir=$ac_optarg ;;
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
| --includ=* | --inclu=* | --incl=* | --inc=*)
includedir=$ac_optarg ;;
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
infodir=$ac_optarg ;;
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
libdir=$ac_optarg ;;
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
| --libexe | --libex | --libe)
ac_prev=libexecdir ;;
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
| --libexe=* | --libex=* | --libe=*)
libexecdir=$ac_optarg ;;
-localedir | --localedir | --localedi | --localed | --locale)
ac_prev=localedir ;;
-localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
localedir=$ac_optarg ;;
-localstatedir | --localstatedir | --localstatedi | --localstated \
| --localstate | --localstat | --localsta | --localst | --locals)
ac_prev=localstatedir ;;
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
| --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
localstatedir=$ac_optarg ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
mandir=$ac_optarg ;;
-nfp | --nfp | --nf)
# Obsolete; use --without-fp.
with_fp=no ;;
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
| --no-cr | --no-c | -n)
no_create=yes ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
| --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
no_recursion=yes ;;
-oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
| --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
| --oldin | --oldi | --old | --ol | --o)
ac_prev=oldincludedir ;;
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
oldincludedir=$ac_optarg ;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
prefix=$ac_optarg ;;
-program-prefix | --program-prefix | --program-prefi | --program-pref \
| --program-pre | --program-pr | --program-p)
ac_prev=program_prefix ;;
-program-prefix=* | --program-prefix=* | --program-prefi=* \
| --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
program_prefix=$ac_optarg ;;
-program-suffix | --program-suffix | --program-suffi | --program-suff \
| --program-suf | --program-su | --program-s)
ac_prev=program_suffix ;;
-program-suffix=* | --program-suffix=* | --program-suffi=* \
| --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
program_suffix=$ac_optarg ;;
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
| --program-transform-n | --program-transform- \
| --program-transform | --program-transfor \
| --program-transfo | --program-transf \
| --program-trans | --program-tran \
| --progr-tra | --program-tr | --program-t)
ac_prev=program_transform_name ;;
-program-transform-name=* | --program-transform-name=* \
| --program-transform-nam=* | --program-transform-na=* \
| --program-transform-n=* | --program-transform-=* \
| --program-transform=* | --program-transfor=* \
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
program_transform_name=$ac_optarg ;;
-pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
ac_prev=pdfdir ;;
-pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
pdfdir=$ac_optarg ;;
-psdir | --psdir | --psdi | --psd | --ps)
ac_prev=psdir ;;
-psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
psdir=$ac_optarg ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
sbindir=$ac_optarg ;;
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
| --sharedst | --shareds | --shared | --share | --shar \
| --sha | --sh)
ac_prev=sharedstatedir ;;
-sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
sharedstatedir=$ac_optarg ;;
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
site=$ac_optarg ;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
srcdir=$ac_optarg ;;
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
| --syscon | --sysco | --sysc | --sys | --sy)
ac_prev=sysconfdir ;;
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
sysconfdir=$ac_optarg ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
ac_prev=target_alias ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
target_alias=$ac_optarg ;;
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
-version | --version | --versio | --versi | --vers | -V)
ac_init_version=: ;;
-with-* | --with-*)
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid package name: '$ac_useropt'"
ac_useropt_orig=$ac_useropt
ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval with_$ac_useropt=\$ac_optarg ;;
-without-* | --without-*)
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid package name: '$ac_useropt'"
ac_useropt_orig=$ac_useropt
ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval with_$ac_useropt=no ;;
--x)
# Obsolete; use --with-x.
with_x=yes ;;
-x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
| --x-incl | --x-inc | --x-in | --x-i)
ac_prev=x_includes ;;
-x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
| --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
x_includes=$ac_optarg ;;
-x-libraries | --x-libraries | --x-librarie | --x-librari \
| --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
ac_prev=x_libraries ;;
-x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
x_libraries=$ac_optarg ;;
-*) as_fn_error $? "unrecognized option: '$ac_option'
Try '$0 --help' for more information"
;;
*=*)
ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
# Reject names that are not valid shell variable names.
case $ac_envvar in #(
'' | [0-9]* | *[!_$as_cr_alnum]* )
as_fn_error $? "invalid variable name: '$ac_envvar'" ;;
esac
eval $ac_envvar=\$ac_optarg
export $ac_envvar ;;
*)
# FIXME: should be removed in autoconf 3.0.
printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
esac
done
if test -n "$ac_prev"; then
ac_option=--`echo $ac_prev | sed 's/_/-/g'`
as_fn_error $? "missing argument to $ac_option"
fi
if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
*) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
# Check all directory arguments for consistency.
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
case $ac_val in
*/ )
ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
eval $ac_var=\$ac_val;;
esac
# Be sure to have absolute directory names.
case $ac_val in
[\\/$]* | ?:[\\/]* ) continue;;
NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
esac
as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done
# There might be people who depend on the old broken behavior: '$host'
# used to hold the argument of --host etc.
# FIXME: To remove some day.
build=$build_alias
host=$host_alias
target=$target_alias
# FIXME: To remove some day.
if test "x$host_alias" != x; then
if test "x$build_alias" = x; then
cross_compiling=maybe
elif test "x$build_alias" != "x$host_alias"; then
cross_compiling=yes
fi
fi
ac_tool_prefix=
test -n "$host_alias" && ac_tool_prefix=$host_alias-
test "$silent" = yes && exec 6>/dev/null
ac_pwd=`pwd` && test -n "$ac_pwd" &&
ac_ls_di=`ls -di .` &&
ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
as_fn_error $? "working directory cannot be determined"
test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
as_fn_error $? "pwd does not report name of working directory"
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
ac_srcdir_defaulted=yes
# Try the directory containing this script, then the parent directory.
ac_confdir=`$as_dirname -- "$as_myself" ||
$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
srcdir=$ac_confdir
if test ! -r "$srcdir/$ac_unique_file"; then
srcdir=..
fi
else
ac_srcdir_defaulted=no
fi
if test ! -r "$srcdir/$ac_unique_file"; then
test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work"
ac_abs_confdir=`(
cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
srcdir=.
fi
# Remove unnecessary trailing slashes from srcdir.
# Double slashes in file names in object file debugging info
# mess up M-x gdb in Emacs.
case $srcdir in
*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
esac
for ac_var in $ac_precious_vars; do
eval ac_env_${ac_var}_set=\${${ac_var}+set}
eval ac_env_${ac_var}_value=\$${ac_var}
eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
eval ac_cv_env_${ac_var}_value=\$${ac_var}
done
#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
'configure' configures wimlib 1.14.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE. See below for descriptions of some of the useful variables.
Defaults for the options are specified in brackets.
Configuration:
-h, --help display this help and exit
--help=short display options specific to this package
--help=recursive display the short help of all the included packages
-V, --version display version information and exit
-q, --quiet, --silent do not print 'checking ...' messages
--cache-file=FILE cache test results in FILE [disabled]
-C, --config-cache alias for '--cache-file=config.cache'
-n, --no-create do not create output files
--srcdir=DIR find the sources in DIR [configure dir or '..']
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
[$ac_default_prefix]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
By default, 'make install' will install all the files in
'$ac_default_prefix/bin', '$ac_default_prefix/lib' etc. You can specify
an installation prefix other than '$ac_default_prefix' using '--prefix',
for instance '--prefix=\$HOME'.
For better control, use the options below.
Fine tuning of the installation directories:
--bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--libexecdir=DIR program executables [EPREFIX/libexec]
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
--datadir=DIR read-only architecture-independent data [DATAROOTDIR]
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
--docdir=DIR documentation root [DATAROOTDIR/doc/wimlib]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
--psdir=DIR ps documentation [DOCDIR]
_ACEOF
cat <<\_ACEOF
Program names:
--program-prefix=PREFIX prepend PREFIX to installed program names
--program-suffix=SUFFIX append SUFFIX to installed program names
--program-transform-name=PROGRAM run sed PROGRAM on installed program names
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
_ACEOF
fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of wimlib 1.14.5:";;
esac
cat <<\_ACEOF
Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-silent-rules less verbose build output (undo: "make V=1")
--disable-silent-rules verbose build output (undo: "make V=0")
--enable-dependency-tracking
do not reject slow dependency extractors
--disable-dependency-tracking
speeds up one-time build
--enable-shared[=PKGS] build shared libraries [default=yes]
--enable-static[=PKGS] build static libraries [default=yes]
--enable-pic[=PKGS] try to use only PIC/non-PIC objects [default=use
both]
--enable-cxx-stdlib[=PKGS]
let the compiler frontend decide what standard
libraries to link when building C++ shared libraries
and modules [default=no]
--enable-fast-install[=PKGS]
optimize for fast installation [default=yes]
--enable-aix-soname=aix|svr4|both
shared library versioning (aka "SONAME") variant to
provide on AIX, [default=aix].
--disable-libtool-lock avoid locking (might break parallel builds)
--enable-test-support Enable supporting code for tests (developers only)
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
--with-sysroot[=DIR] Search for dependent libraries within DIR (or the
compiler's sysroot if not specified).
--without-ntfs-3g build without libntfs-3g. This will disable the
ability to capture or apply a WIM image directly
from/to an unmounted NTFS volume.
--without-fuse build without libfuse3. This will disable the
ability to mount WIM images.
--with-pkgconfigdir=DIR pkgconfig file in DIR [LIBDIR/pkgconfig]
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L if you have libraries in a
nonstandard directory
LIBS libraries to pass to the linker, e.g. -l
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if
you have headers in a nonstandard directory
LT_SYS_LIBRARY_PATH
User-defined run-time library search path.
PKG_CONFIG path to pkg-config utility
PKG_CONFIG_PATH
directories to add to pkg-config's search path
PKG_CONFIG_LIBDIR
path overriding pkg-config's built-in search path
CPP C preprocessor
LIBNTFS_3G_CFLAGS
C compiler flags for LIBNTFS_3G, overriding pkg-config
LIBNTFS_3G_LIBS
linker flags for LIBNTFS_3G, overriding pkg-config
LIBFUSE_CFLAGS
C compiler flags for LIBFUSE, overriding pkg-config
LIBFUSE_LIBS
linker flags for LIBFUSE, overriding pkg-config
Use these variables to override the choices made by 'configure' or to help
it to find libraries and programs with nonstandard names/locations.
Report bugs to .
_ACEOF
ac_status=$?
fi
if test "$ac_init_help" = "recursive"; then
# If there are subdirs, report their specific --help.
for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
test -d "$ac_dir" ||
{ cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
continue
ac_builddir=.
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix
case $srcdir in
.) # We are building in place.
ac_srcdir=.
ac_top_srcdir=$ac_top_builddir_sub
ac_abs_top_srcdir=$ac_pwd ;;
[\\/]* | ?:[\\/]* ) # Absolute name.
ac_srcdir=$srcdir$ac_dir_suffix;
ac_top_srcdir=$srcdir
ac_abs_top_srcdir=$srcdir ;;
*) # Relative name.
ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
ac_top_srcdir=$ac_top_build_prefix$srcdir
ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
# Check for configure.gnu first; this name is used for a wrapper for
# Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
elif test -f "$ac_srcdir/configure"; then
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
wimlib configure 1.14.5
generated by GNU Autoconf 2.72
Copyright (C) 2023 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
exit
fi
## ------------------------ ##
## Autoconf initialization. ##
## ------------------------ ##
# ac_fn_c_try_compile LINENO
# --------------------------
# Try to compile conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest.$ac_objext
then :
ac_retval=0
else case e in #(
e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1 ;;
esac
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_compile
# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
}
then :
ac_retval=0
else case e in #(
e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1 ;;
esac
fi
# Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
# created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
# interfere with the next link command; also delete a directory that is
# left behind by Apple's compiler. We do this before executing the actions.
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_link
# ac_fn_c_try_run LINENO
# ----------------------
# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
# executables *can* be run.
ac_fn_c_try_run ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then :
ac_retval=0
else case e in #(
e) printf "%s\n" "$as_me: program exited with status $ac_status" >&5
printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status ;;
esac
fi
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_run
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
# INCLUDES, setting the cache variable VAR accordingly.
ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
eval "$3=yes"
else case e in #(
e) eval "$3=no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
eval ac_res=\$$3
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_header_compile
# ac_fn_c_check_func LINENO FUNC VAR
# ----------------------------------
# Tests whether FUNC exists, setting the cache variable VAR accordingly
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
printf %s "checking for $2... " >&6; }
if eval test \${$3+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case declares $2.
For example, HP-UX 11i declares gettimeofday. */
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $2 (void); below. */
#include
#undef $2
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char $2 (void);
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined __stub_$2 || defined __stub___$2
choke me
#endif
int
main (void)
{
return $2 ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
eval "$3=yes"
else case e in #(
e) eval "$3=no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext ;;
esac
fi
eval ac_res=\$$3
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
# ----------------------------------------------------
# Tries to find if the field MEMBER exists in type AGGR, after including
# INCLUDES, setting cache variable VAR accordingly.
ac_fn_c_check_member ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
printf %s "checking for $2.$3... " >&6; }
if eval test \${$4+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
main (void)
{
static $2 ac_aggr;
if (ac_aggr.$3)
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
eval "$4=yes"
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
main (void)
{
static $2 ac_aggr;
if (sizeof ac_aggr.$3)
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
eval "$4=yes"
else case e in #(
e) eval "$4=no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
eval ac_res=\$$4
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_member
# ac_fn_c_try_cpp LINENO
# ----------------------
# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_cpp ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if { { ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } > conftest.i && {
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
test ! -s conftest.err
}
then :
ac_retval=0
else case e in #(
e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1 ;;
esac
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_cpp
ac_configure_args_raw=
for ac_arg
do
case $ac_arg in
*\'*)
ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
as_fn_append ac_configure_args_raw " '$ac_arg'"
done
case $ac_configure_args_raw in
*$as_nl*)
ac_safe_unquote= ;;
*)
ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
ac_unsafe_a="$ac_unsafe_z#~"
ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
esac
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by wimlib $as_me 1.14.5, which was
generated by GNU Autoconf 2.72. Invocation command line was
$ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
## Platform. ##
## --------- ##
hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
_ASUNAME
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
} >&5
cat >&5 <<_ACEOF
## ----------- ##
## Core tests. ##
## ----------- ##
_ACEOF
# Keep a trace of the command line.
# Strip out --no-create and --no-recursion so they do not pile up.
# Strip out --silent because we don't want to record it for future runs.
# Also quote any args containing shell meta-characters.
# Make two passes to allow for proper duplicate-argument suppression.
ac_configure_args=
ac_configure_args0=
ac_configure_args1=
ac_must_keep_next=false
for ac_pass in 1 2
do
for ac_arg
do
case $ac_arg in
-no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
2)
as_fn_append ac_configure_args1 " '$ac_arg'"
if test $ac_must_keep_next = true; then
ac_must_keep_next=false # Got value, back to normal.
else
case $ac_arg in
*=* | --config-cache | -C | -disable-* | --disable-* \
| -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
| -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
| -with-* | --with-* | -without-* | --without-* | --x)
case "$ac_configure_args0 " in
"$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
esac
;;
-* ) ac_must_keep_next=true ;;
esac
fi
as_fn_append ac_configure_args " '$ac_arg'"
;;
esac
done
done
{ ac_configure_args0=; unset ac_configure_args0;}
{ ac_configure_args1=; unset ac_configure_args1;}
# When interrupted or exit'd, cleanup temporary files, and complete
# config.log. We remove comments because anyway the quotes in there
# would cause problems or look ugly.
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
# Sanitize IFS.
IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
# The following way of writing the cache mishandles newlines in values,
(
for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
eval ac_val=\$$ac_var
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
*_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
*) { eval $ac_var=; unset $ac_var;} ;;
esac ;;
esac
done
(set) 2>&1 |
case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
*${as_nl}ac_space=\ *)
sed -n \
"s/'\''/'\''\\\\'\'''\''/g;
s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
;; #(
*)
sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
;;
esac |
sort
)
echo
printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
for ac_var in $ac_subst_vars
do
eval ac_val=\$$ac_var
case $ac_val in
*\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
for ac_var in $ac_subst_files
do
eval ac_val=\$$ac_var
case $ac_val in
*\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
cat confdefs.h
echo
fi
test "$ac_signal" != 0 &&
printf "%s\n" "$as_me: caught signal $ac_signal"
printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
exit $exit_status
' 0
for ac_signal in 1 2 13 15; do
trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
done
ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
if test -n "$CONFIG_SITE"; then
ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
for ac_site_file in $ac_site_files
do
case $ac_site_file in #(
*/*) :
;; #(
*) :
ac_site_file=./$ac_site_file ;;
esac
if test -f "$ac_site_file" && test -r "$ac_site_file"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
|| { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See 'config.log' for more details" "$LINENO" 5; }
fi
done
if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
# Test code for whether the C compiler supports C89 (global declarations)
ac_c_conftest_c89_globals='
/* Does the compiler advertise C89 conformance?
Do not test the value of __STDC__, because some compilers set it to 0
while being otherwise adequately conformant. */
#if !defined __STDC__
# error "Compiler does not advertise C89 conformance"
#endif
#include
#include
struct stat;
/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
struct buf { int x; };
struct buf * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (char **p, int i)
{
return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
char *s;
va_list v;
va_start (v,p);
s = g (p, va_arg (v,int));
va_end (v);
return s;
}
/* C89 style stringification. */
#define noexpand_stringify(a) #a
const char *stringified = noexpand_stringify(arbitrary+token=sequence);
/* C89 style token pasting. Exercises some of the corner cases that
e.g. old MSVC gets wrong, but not very hard. */
#define noexpand_concat(a,b) a##b
#define expand_concat(a,b) noexpand_concat(a,b)
extern int vA;
extern int vbee;
#define aye A
#define bee B
int *pvA = &expand_concat(v,aye);
int *pvbee = &noexpand_concat(v,bee);
/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
function prototypes and stuff, but not \xHH hex character constants.
These do not provoke an error unfortunately, instead are silently treated
as an "x". The following induces an error, until -std is added to get
proper ANSI mode. Curiously \x00 != x always comes out true, for an
array size at least. It is necessary to write \x00 == 0 to get something
that is true only with -std. */
int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
inside strings and character constants. */
#define FOO(x) '\''x'\''
int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
int, int);'
# Test code for whether the C compiler supports C89 (body of main).
ac_c_conftest_c89_main='
ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
'
# Test code for whether the C compiler supports C99 (global declarations)
ac_c_conftest_c99_globals='
/* Does the compiler advertise C99 conformance? */
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
# error "Compiler does not advertise C99 conformance"
#endif
// See if C++-style comments work.
#include
extern int puts (const char *);
extern int printf (const char *, ...);
extern int dprintf (int, const char *, ...);
extern void *malloc (size_t);
extern void free (void *);
// Check varargs macros. These examples are taken from C99 6.10.3.5.
// dprintf is used instead of fprintf to avoid needing to declare
// FILE and stderr.
#define debug(...) dprintf (2, __VA_ARGS__)
#define showlist(...) puts (#__VA_ARGS__)
#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
static void
test_varargs_macros (void)
{
int x = 1234;
int y = 5678;
debug ("Flag");
debug ("X = %d\n", x);
showlist (The first, second, and third items.);
report (x>y, "x is %d but y is %d", x, y);
}
// Check long long types.
#define BIG64 18446744073709551615ull
#define BIG32 4294967295ul
#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
#if !BIG_OK
#error "your preprocessor is broken"
#endif
#if BIG_OK
#else
#error "your preprocessor is broken"
#endif
static long long int bignum = -9223372036854775807LL;
static unsigned long long int ubignum = BIG64;
struct incomplete_array
{
int datasize;
double data[];
};
struct named_init {
int number;
const wchar_t *name;
double average;
};
typedef const char *ccp;
static inline int
test_restrict (ccp restrict text)
{
// Iterate through items via the restricted pointer.
// Also check for declarations in for loops.
for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
continue;
return 0;
}
// Check varargs and va_copy.
static bool
test_varargs (const char *format, ...)
{
va_list args;
va_start (args, format);
va_list args_copy;
va_copy (args_copy, args);
const char *str = "";
int number = 0;
float fnumber = 0;
while (*format)
{
switch (*format++)
{
case '\''s'\'': // string
str = va_arg (args_copy, const char *);
break;
case '\''d'\'': // int
number = va_arg (args_copy, int);
break;
case '\''f'\'': // float
fnumber = va_arg (args_copy, double);
break;
default:
break;
}
}
va_end (args_copy);
va_end (args);
return *str && number && fnumber;
}
'
# Test code for whether the C compiler supports C99 (body of main).
ac_c_conftest_c99_main='
// Check bool.
_Bool success = false;
success |= (argc != 0);
// Check restrict.
if (test_restrict ("String literal") == 0)
success = true;
char *restrict newvar = "Another string";
// Check varargs.
success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
test_varargs_macros ();
// Check flexible array members.
struct incomplete_array *ia =
malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
ia->datasize = 10;
for (int i = 0; i < ia->datasize; ++i)
ia->data[i] = i * 1.234;
// Work around memory leak warnings.
free (ia);
// Check named initializers.
struct named_init ni = {
.number = 34,
.name = L"Test wide string",
.average = 543.34343,
};
ni.number = 58;
int dynamic_array[ni.number];
dynamic_array[0] = argv[0][0];
dynamic_array[ni.number - 1] = 543;
// work around unused variable warnings
ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
|| dynamic_array[ni.number - 1] != 543);
'
# Test code for whether the C compiler supports C11 (global declarations)
ac_c_conftest_c11_globals='
/* Does the compiler advertise C11 conformance? */
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
# error "Compiler does not advertise C11 conformance"
#endif
// Check _Alignas.
char _Alignas (double) aligned_as_double;
char _Alignas (0) no_special_alignment;
extern char aligned_as_int;
char _Alignas (0) _Alignas (int) aligned_as_int;
// Check _Alignof.
enum
{
int_alignment = _Alignof (int),
int_array_alignment = _Alignof (int[100]),
char_alignment = _Alignof (char)
};
_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
// Check _Noreturn.
int _Noreturn does_not_return (void) { for (;;) continue; }
// Check _Static_assert.
struct test_static_assert
{
int x;
_Static_assert (sizeof (int) <= sizeof (long int),
"_Static_assert does not work in struct");
long int y;
};
// Check UTF-8 literals.
#define u8 syntax error!
char const utf8_literal[] = u8"happens to be ASCII" "another string";
// Check duplicate typedefs.
typedef long *long_ptr;
typedef long int *long_ptr;
typedef long_ptr long_ptr;
// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
struct anonymous
{
union {
struct { int i; int j; };
struct { int k; long int l; } w;
};
int m;
} v1;
'
# Test code for whether the C compiler supports C11 (body of main).
ac_c_conftest_c11_main='
_Static_assert ((offsetof (struct anonymous, i)
== offsetof (struct anonymous, w.k)),
"Anonymous union alignment botch");
v1.i = 2;
v1.w.k = 5;
ok |= v1.i != 5;
'
# Test code for whether the C compiler supports C11 (complete).
ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
${ac_c_conftest_c99_globals}
${ac_c_conftest_c11_globals}
int
main (int argc, char **argv)
{
int ok = 0;
${ac_c_conftest_c89_main}
${ac_c_conftest_c99_main}
${ac_c_conftest_c11_main}
return ok;
}
"
# Test code for whether the C compiler supports C99 (complete).
ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
${ac_c_conftest_c99_globals}
int
main (int argc, char **argv)
{
int ok = 0;
${ac_c_conftest_c89_main}
${ac_c_conftest_c99_main}
return ok;
}
"
# Test code for whether the C compiler supports C89 (complete).
ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
int
main (int argc, char **argv)
{
int ok = 0;
${ac_c_conftest_c89_main}
return ok;
}
"
as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
# Auxiliary files required by this configure script.
ac_aux_files="config.guess config.sub ltmain.sh ar-lib compile missing install-sh"
# Locations in which to look for auxiliary files.
ac_aux_dir_candidates="${srcdir}/build-aux"
# Search for a directory containing all of the required auxiliary files,
# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
# If we don't find one directory that contains all the files we need,
# we report the set of missing files from the *first* directory in
# $ac_aux_dir_candidates and give up.
ac_missing_aux_files=""
ac_first_candidate=:
printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in $ac_aux_dir_candidates
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
as_found=:
printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
ac_aux_dir_found=yes
ac_install_sh=
for ac_aux in $ac_aux_files
do
# As a special case, if "install-sh" is required, that requirement
# can be satisfied by any of "install-sh", "install.sh", or "shtool",
# and $ac_install_sh is set appropriately for whichever one is found.
if test x"$ac_aux" = x"install-sh"
then
if test -f "${as_dir}install-sh"; then
printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
ac_install_sh="${as_dir}install-sh -c"
elif test -f "${as_dir}install.sh"; then
printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
ac_install_sh="${as_dir}install.sh -c"
elif test -f "${as_dir}shtool"; then
printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
ac_install_sh="${as_dir}shtool install -c"
else
ac_aux_dir_found=no
if $ac_first_candidate; then
ac_missing_aux_files="${ac_missing_aux_files} install-sh"
else
break
fi
fi
else
if test -f "${as_dir}${ac_aux}"; then
printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
else
ac_aux_dir_found=no
if $ac_first_candidate; then
ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
else
break
fi
fi
fi
done
if test "$ac_aux_dir_found" = yes; then
ac_aux_dir="$as_dir"
break
fi
ac_first_candidate=false
as_found=false
done
IFS=$as_save_IFS
if $as_found
then :
else case e in #(
e) as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 ;;
esac
fi
# These three variables are undocumented and unsupported,
# and are intended to be withdrawn in a future Autoconf release.
# They can cause serious problems if a builder's source tree is in a directory
# whose full name contains unusual characters.
if test -f "${ac_aux_dir}config.guess"; then
ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
fi
if test -f "${ac_aux_dir}config.sub"; then
ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
fi
if test -f "$ac_aux_dir/configure"; then
ac_configure="$SHELL ${ac_aux_dir}configure"
fi
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
for ac_var in $ac_precious_vars; do
eval ac_old_set=\$ac_cv_env_${ac_var}_set
eval ac_new_set=\$ac_env_${ac_var}_set
eval ac_old_val=\$ac_cv_env_${ac_var}_value
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5
printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5
printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
if test "x$ac_old_val" != "x$ac_new_val"; then
# differences in whitespace do not lead to failure.
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5
printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5
printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: '$ac_old_val'" >&5
printf "%s\n" "$as_me: former value: '$ac_old_val'" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: '$ac_new_val'" >&5
printf "%s\n" "$as_me: current value: '$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
*\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
*" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
*) as_fn_append ac_configure_args " '$ac_arg'" ;;
esac
fi
done
if $ac_cache_corrupted; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file'
and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
## -------------------- ##
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
am__api_version='1.18'
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AmigaOS /C/install, which installs bootblocks on floppy discs
# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# OS/2's system install, which has a completely different semantic
# ./install, which can be erroneously created by make from ./install.sh.
# Reject install programs that cannot install multiple files.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
printf %s "checking for a BSD-compatible install... " >&6; }
if test -z "$INSTALL"; then
if test ${ac_cv_path_install+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
# Account for fact that we put trailing slashes in our PATH walk.
case $as_dir in #((
./ | /[cC]/* | \
/etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
/usr/ucb/* ) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
# Don't use installbsd from OSF since it installs stuff as root
# by default.
for ac_prog in ginstall scoinst install; do
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then
if test $ac_prog = install &&
grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
:
elif test $ac_prog = install &&
grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# program-specific install script used by HP pwplus--don't use.
:
else
rm -rf conftest.one conftest.two conftest.dir
echo one > conftest.one
echo two > conftest.two
mkdir conftest.dir
if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" &&
test -s conftest.one && test -s conftest.two &&
test -s conftest.dir/conftest.one &&
test -s conftest.dir/conftest.two
then
ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c"
break 3
fi
fi
fi
done
done
;;
esac
done
IFS=$as_save_IFS
rm -rf conftest.one conftest.two conftest.dir
;;
esac
fi
if test ${ac_cv_path_install+y}; then
INSTALL=$ac_cv_path_install
else
# As a last resort, use the slow shell script. Don't cache a
# value for INSTALL within a source directory, because that will
# break other packages using the cache if that directory is
# removed, or if the value is a relative name.
INSTALL=$ac_install_sh
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
printf "%s\n" "$INSTALL" >&6; }
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether sleep supports fractional seconds" >&5
printf %s "checking whether sleep supports fractional seconds... " >&6; }
if test ${am_cv_sleep_fractional_seconds+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if sleep 0.001 2>/dev/null
then :
am_cv_sleep_fractional_seconds=yes
else case e in #(
e) am_cv_sleep_fractional_seconds=no ;;
esac
fi
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_sleep_fractional_seconds" >&5
printf "%s\n" "$am_cv_sleep_fractional_seconds" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking filesystem timestamp resolution" >&5
printf %s "checking filesystem timestamp resolution... " >&6; }
if test ${am_cv_filesystem_timestamp_resolution+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) # Default to the worst case.
am_cv_filesystem_timestamp_resolution=2
# Only try to go finer than 1 sec if sleep can do it.
# Don't try 1 sec, because if 0.01 sec and 0.1 sec don't work,
# - 1 sec is not much of a win compared to 2 sec, and
# - it takes 2 seconds to perform the test whether 1 sec works.
#
# Instead, just use the default 2s on platforms that have 1s resolution,
# accept the extra 1s delay when using $sleep in the Automake tests, in
# exchange for not incurring the 2s delay for running the test for all
# packages.
#
am_try_resolutions=
if test "$am_cv_sleep_fractional_seconds" = yes; then
# Even a millisecond often causes a bunch of false positives,
# so just try a hundredth of a second. The time saved between .001 and
# .01 is not terribly consequential.
am_try_resolutions="0.01 0.1 $am_try_resolutions"
fi
# In order to catch current-generation FAT out, we must *modify* files
# that already exist; the *creation* timestamp is finer. Use names
# that make ls -t sort them differently when they have equal
# timestamps than when they have distinct timestamps, keeping
# in mind that ls -t prints the *newest* file first.
rm -f conftest.ts?
: > conftest.ts1
: > conftest.ts2
: > conftest.ts3
# Make sure ls -t actually works. Do 'set' in a subshell so we don't
# clobber the current shell's arguments. (Outer-level square brackets
# are removed by m4; they're present so that m4 does not expand
# ; be careful, easy to get confused.)
if (
set X `ls -t conftest.ts[12]` &&
{
test "$*" != "X conftest.ts1 conftest.ts2" ||
test "$*" != "X conftest.ts2 conftest.ts1";
}
); then :; else
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
printf "%s\n" ""Bad output from ls -t: \"`ls -t conftest.ts[12]`\""" >&5
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "ls -t produces unexpected output.
Make sure there is not a broken ls alias in your environment.
See 'config.log' for more details" "$LINENO" 5; }
fi
for am_try_res in $am_try_resolutions; do
# Any one fine-grained sleep might happen to cross the boundary
# between two values of a coarser actual resolution, but if we do
# two fine-grained sleeps in a row, at least one of them will fall
# entirely within a coarse interval.
echo alpha > conftest.ts1
sleep $am_try_res
echo beta > conftest.ts2
sleep $am_try_res
echo gamma > conftest.ts3
# We assume that 'ls -t' will make use of high-resolution
# timestamps if the operating system supports them at all.
if (set X `ls -t conftest.ts?` &&
test "$2" = conftest.ts3 &&
test "$3" = conftest.ts2 &&
test "$4" = conftest.ts1); then
#
# Ok, ls -t worked. If we're at a resolution of 1 second, we're done,
# because we don't need to test make.
make_ok=true
if test $am_try_res != 1; then
# But if we've succeeded so far with a subsecond resolution, we
# have one more thing to check: make. It can happen that
# everything else supports the subsecond mtimes, but make doesn't;
# notably on macOS, which ships make 3.81 from 2006 (the last one
# released under GPLv2). https://bugs.gnu.org/68808
#
# We test $MAKE if it is defined in the environment, else "make".
# It might get overridden later, but our hope is that in practice
# it does not matter: it is the system "make" which is (by far)
# the most likely to be broken, whereas if the user overrides it,
# probably they did so with a better, or at least not worse, make.
# https://lists.gnu.org/archive/html/automake/2024-06/msg00051.html
#
# Create a Makefile (real tab character here):
rm -f conftest.mk
echo 'conftest.ts1: conftest.ts2' >conftest.mk
echo ' touch conftest.ts2' >>conftest.mk
#
# Now, running
# touch conftest.ts1; touch conftest.ts2; make
# should touch ts1 because ts2 is newer. This could happen by luck,
# but most often, it will fail if make's support is insufficient. So
# test for several consecutive successes.
#
# (We reuse conftest.ts[12] because we still want to modify existing
# files, not create new ones, per above.)
n=0
make=${MAKE-make}
until test $n -eq 3; do
echo one > conftest.ts1
sleep $am_try_res
echo two > conftest.ts2 # ts2 should now be newer than ts1
if $make -f conftest.mk | grep 'up to date' >/dev/null; then
make_ok=false
break # out of $n loop
fi
n=`expr $n + 1`
done
fi
#
if $make_ok; then
# Everything we know to check worked out, so call this resolution good.
am_cv_filesystem_timestamp_resolution=$am_try_res
break # out of $am_try_res loop
fi
# Otherwise, we'll go on to check the next resolution.
fi
done
rm -f conftest.ts?
# (end _am_filesystem_timestamp_resolution)
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_filesystem_timestamp_resolution" >&5
printf "%s\n" "$am_cv_filesystem_timestamp_resolution" >&6; }
# This check should not be cached, as it may vary across builds of
# different projects.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
printf %s "checking whether build environment is sane... " >&6; }
# Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter.
am_lf='
'
case `pwd` in
*[\\\"\#\$\&\'\`$am_lf]*)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
esac
case $srcdir in
*[\\\"\#\$\&\'\`$am_lf\ \ ]*)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
esac
# Do 'set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
am_build_env_is_sane=no
am_has_slept=no
rm -f conftest.file
for am_try in 1 2; do
echo "timestamp, slept: $am_has_slept" > conftest.file
if (
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
if test "$*" = "X"; then
# -L didn't work.
set X `ls -t "$srcdir/configure" conftest.file`
fi
test "$2" = conftest.file
); then
am_build_env_is_sane=yes
break
fi
# Just in case.
sleep "$am_cv_filesystem_timestamp_resolution"
am_has_slept=yes
done
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_build_env_is_sane" >&5
printf "%s\n" "$am_build_env_is_sane" >&6; }
if test "$am_build_env_is_sane" = no; then
as_fn_error $? "newly created file is older than distributed files!
Check your system clock" "$LINENO" 5
fi
# If we didn't sleep, we still need to ensure time stamps of config.status and
# generated files are strictly newer.
am_sleep_pid=
if test -e conftest.file || grep 'slept: no' conftest.file >/dev/null 2>&1
then :
else case e in #(
e) ( sleep "$am_cv_filesystem_timestamp_resolution" ) &
am_sleep_pid=$!
;;
esac
fi
rm -f conftest.file
test "$program_prefix" != NONE &&
program_transform_name="s&^&$program_prefix&;$program_transform_name"
# Use a double $ so make ignores it.
test "$program_suffix" != NONE &&
program_transform_name="s&\$&$program_suffix&;$program_transform_name"
# Double any \ or $.
# By default was 's,x,x', remove it if useless.
ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"`
# Expand $ac_aux_dir to an absolute path.
am_aux_dir=`cd "$ac_aux_dir" && pwd`
if test x"${MISSING+set}" != xset; then
MISSING="\${SHELL} '$am_aux_dir/missing'"
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then
am_missing_run="$MISSING "
else
am_missing_run=
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
fi
if test x"${install_sh+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
*)
install_sh="\${SHELL} $am_aux_dir/install-sh"
esac
fi
# Installed binaries are usually stripped using 'strip' when the user
# run "make install-strip". However 'strip' might not be the right
# tool to use in cross-compilation environments, therefore Automake
# will honor the 'STRIP' environment variable to overrule this program.
if test "$cross_compiling" != no; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
set dummy ${ac_tool_prefix}strip; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_STRIP+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$STRIP"; then
ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_STRIP="${ac_tool_prefix}strip"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
STRIP=$ac_cv_prog_STRIP
if test -n "$STRIP"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
printf "%s\n" "$STRIP" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_STRIP"; then
ac_ct_STRIP=$STRIP
# Extract the first word of "strip", so it can be a program name with args.
set dummy strip; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_STRIP+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_STRIP"; then
ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_STRIP="strip"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
if test -n "$ac_ct_STRIP"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
printf "%s\n" "$ac_ct_STRIP" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_STRIP" = x; then
STRIP=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
STRIP=$ac_ct_STRIP
fi
else
STRIP="$ac_cv_prog_STRIP"
fi
fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5
printf %s "checking for a race-free mkdir -p... " >&6; }
if test -z "$MKDIR_P"; then
if test ${ac_cv_path_mkdir+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_prog in mkdir gmkdir; do
for ac_exec_ext in '' $ac_executable_extensions; do
as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue
case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #(
'mkdir ('*'coreutils) '* | \
*'BusyBox '* | \
'mkdir (fileutils) '4.1*)
ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext
break 3;;
esac
done
done
done
IFS=$as_save_IFS
;;
esac
fi
test -d ./--version && rmdir ./--version
if test ${ac_cv_path_mkdir+y}; then
MKDIR_P="$ac_cv_path_mkdir -p"
else
# As a last resort, use plain mkdir -p,
# in the hope it doesn't have the bugs of ancient mkdir.
MKDIR_P='mkdir -p'
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
printf "%s\n" "$MKDIR_P" >&6; }
for ac_prog in gawk mawk nawk awk
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_AWK+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$AWK"; then
ac_cv_prog_AWK="$AWK" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_AWK="$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
AWK=$ac_cv_prog_AWK
if test -n "$AWK"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
printf "%s\n" "$AWK" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$AWK" && break
done
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
set x ${MAKE-make}
ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
if eval test \${ac_cv_prog_make_${ac_make}_set+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat >conftest.make <<\_ACEOF
SHELL = /bin/sh
all:
@echo '@@@%%%=$(MAKE)=@@@%%%'
_ACEOF
# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
case `${MAKE-make} -f conftest.make 2>/dev/null` in
*@@@%%%=?*=@@@%%%*)
eval ac_cv_prog_make_${ac_make}_set=yes;;
*)
eval ac_cv_prog_make_${ac_make}_set=no;;
esac
rm -f conftest.make ;;
esac
fi
if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
SET_MAKE=
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
SET_MAKE="MAKE=${MAKE-make}"
fi
rm -rf .tst 2>/dev/null
mkdir .tst 2>/dev/null
if test -d .tst; then
am__leading_dot=.
else
am__leading_dot=_
fi
rmdir .tst 2>/dev/null
AM_DEFAULT_VERBOSITY=1
# Check whether --enable-silent-rules was given.
if test ${enable_silent_rules+y}
then :
enableval=$enable_silent_rules;
fi
am_make=${MAKE-make}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
printf %s "checking whether $am_make supports nested variables... " >&6; }
if test ${am_cv_make_support_nested_variables+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if printf "%s\n" 'TRUE=$(BAR$(V))
BAR0=false
BAR1=true
V=1
am__doit:
@$(TRUE)
.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
am_cv_make_support_nested_variables=yes
else
am_cv_make_support_nested_variables=no
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
printf "%s\n" "$am_cv_make_support_nested_variables" >&6; }
AM_BACKSLASH='\'
am__rm_f_notfound=
if (rm -f && rm -fr && rm -rf) 2>/dev/null
then :
else case e in #(
e) am__rm_f_notfound='""' ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking xargs -n works" >&5
printf %s "checking xargs -n works... " >&6; }
if test ${am_cv_xargs_n_works+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test "`echo 1 2 3 | xargs -n2 echo`" = "1 2
3"
then :
am_cv_xargs_n_works=yes
else case e in #(
e) am_cv_xargs_n_works=no ;;
esac
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_xargs_n_works" >&5
printf "%s\n" "$am_cv_xargs_n_works" >&6; }
if test "$am_cv_xargs_n_works" = yes
then :
am__xargs_n='xargs -n'
else case e in #(
e) am__xargs_n='am__xargs_n () { shift; sed "s/ /\\n/g" | while read am__xargs_n_arg; do "" "$am__xargs_n_arg"; done; }'
;;
esac
fi
if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I."
am__isrc=' -I$(srcdir)'
# test to see if srcdir already configured
if test -f $srcdir/config.status; then
as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
fi
fi
# test whether we have cygpath
if test -z "$CYGPATH_W"; then
if (cygpath --version) >/dev/null 2>/dev/null; then
CYGPATH_W='cygpath -w'
else
CYGPATH_W=echo
fi
fi
# Define the identity of the package.
PACKAGE='wimlib'
VERSION='1.14.5'
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h
# Some tools Automake needs.
ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see:
#
#
mkdir_p='$(MKDIR_P)'
# We need awk for the "check" target (and possibly the TAP driver). The
# system "awk" is bad on some platforms.
# Always define AMTAR for backward compatibility. Yes, it's still used
# in the wild :-( We should find a proper way to deprecate it ...
AMTAR='$${TAR-tar}'
# We'll loop over all known methods to create a tar archive until one works.
_am_tools='gnutar plaintar pax cpio none'
# The POSIX 1988 'ustar' format is defined with fixed-size fields.
# There is notably a 21 bits limit for the UID and the GID. In fact,
# the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
# and bug#13588).
am_max_uid=2097151 # 2^21 - 1
am_max_gid=$am_max_uid
# The $UID and $GID variables are not portable, so we need to resort
# to the POSIX-mandated id(1) utility. Errors in the 'id' calls
# below are definitely unexpected, so allow the users to see them
# (that is, avoid stderr redirection).
am_uid=`id -u || echo unknown`
am_gid=`id -g || echo unknown`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5
printf %s "checking whether UID '$am_uid' is supported by ustar format... " >&6; }
if test x$am_uid = xunknown; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ancient id detected; assuming current UID is ok, but dist-ustar might not work" >&5
printf "%s\n" "$as_me: WARNING: ancient id detected; assuming current UID is ok, but dist-ustar might not work" >&2;}
elif test $am_uid -le $am_max_uid; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
_am_tools=none
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5
printf %s "checking whether GID '$am_gid' is supported by ustar format... " >&6; }
if test x$gm_gid = xunknown; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ancient id detected; assuming current GID is ok, but dist-ustar might not work" >&5
printf "%s\n" "$as_me: WARNING: ancient id detected; assuming current GID is ok, but dist-ustar might not work" >&2;}
elif test $am_gid -le $am_max_gid; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
_am_tools=none
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5
printf %s "checking how to create a ustar tar archive... " >&6; }
# Go ahead even if we have the value already cached. We do so because we
# need to set the values for the 'am__tar' and 'am__untar' variables.
_am_tools=${am_cv_prog_tar_ustar-$_am_tools}
for _am_tool in $_am_tools; do
case $_am_tool in
gnutar)
for _am_tar in tar gnutar gtar; do
{ echo "$as_me:$LINENO: $_am_tar --version" >&5
($_am_tar --version) >&5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && break
done
am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"'
am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"'
am__untar="$_am_tar -xf -"
;;
plaintar)
# Must skip GNU tar: if it does not support --format= it doesn't create
# ustar tarball either.
(tar --version) >/dev/null 2>&1 && continue
am__tar='tar chf - "$$tardir"'
am__tar_='tar chf - "$tardir"'
am__untar='tar xf -'
;;
pax)
am__tar='pax -L -x ustar -w "$$tardir"'
am__tar_='pax -L -x ustar -w "$tardir"'
am__untar='pax -r'
;;
cpio)
am__tar='find "$$tardir" -print | cpio -o -H ustar -L'
am__tar_='find "$tardir" -print | cpio -o -H ustar -L'
am__untar='cpio -i -H ustar -d'
;;
none)
am__tar=false
am__tar_=false
am__untar=false
;;
esac
# If the value was cached, stop now. We just wanted to have am__tar
# and am__untar set.
test -n "${am_cv_prog_tar_ustar}" && break
# tar/untar a dummy directory, and stop if the command works.
rm -rf conftest.dir
mkdir conftest.dir
echo GrepMe > conftest.dir/file
{ echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5
(tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }
rm -rf conftest.dir
if test -s conftest.tar; then
{ echo "$as_me:$LINENO: $am__untar &5
($am__untar &5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }
{ echo "$as_me:$LINENO: cat conftest.dir/file" >&5
(cat conftest.dir/file) >&5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
fi
done
rm -rf conftest.dir
if test ${am_cv_prog_tar_ustar+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) am_cv_prog_tar_ustar=$_am_tool ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5
printf "%s\n" "$am_cv_prog_tar_ustar" >&6; }
# Variables for tags utilities; see am/tags.am
if test -z "$CTAGS"; then
CTAGS=ctags
fi
if test -z "$ETAGS"; then
ETAGS=etags
fi
if test -z "$CSCOPE"; then
CSCOPE=cscope
fi
AM_DEFAULT_VERBOSITY=0
DEPDIR="${am__leading_dot}deps"
ac_config_commands="$ac_config_commands depfiles"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; }
cat > confinc.mk << 'END'
am__doit:
@echo this is the am__doit target >confinc.out
.PHONY: am__doit
END
am__include="#"
am__quote=
# BSD make does it like this.
echo '.include "confinc.mk" # ignored' > confmf.BSD
# Other make implementations (GNU, Solaris 10, AIX) do it like this.
echo 'include confinc.mk # ignored' > confmf.GNU
_am_result=no
for s in GNU BSD; do
{ echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
(${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }
case $?:`cat confinc.out 2>/dev/null` in #(
'0:this is the am__doit target') :
case $s in #(
BSD) :
am__include='.include' am__quote='"' ;; #(
*) :
am__include='include' am__quote='' ;;
esac ;; #(
*) :
;;
esac
if test "$am__include" != "#"; then
_am_result="yes ($s style)"
break
fi
done
rm -f confinc.* confmf.*
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
printf "%s\n" "${_am_result}" >&6; }
# Check whether --enable-dependency-tracking was given.
if test ${enable_dependency_tracking+y}
then :
enableval=$enable_dependency_tracking;
fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
AMDEP_FALSE='#'
else
AMDEP_TRUE='#'
AMDEP_FALSE=
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
else
CC="$ac_cv_prog_CC"
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
ac_prog_rejected=no
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
set dummy $ac_cv_prog_CC
shift
if test $# != 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
for ac_prog in cl.exe
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$CC" && break
done
fi
if test -z "$CC"; then
ac_ct_CC=$CC
for ac_prog in cl.exe
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$ac_ct_CC" && break
done
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
fi
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
set dummy ${ac_tool_prefix}clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}clang"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "clang", so it can be a program name with args.
set dummy clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="clang"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
else
CC="$ac_cv_prog_CC"
fi
fi
test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See 'config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
sed '10a\
... rest of stderr output deleted ...
10q' conftest.err >conftest.er1
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
printf %s "checking whether the C compiler works... " >&6; }
ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
ac_rmfiles=
for ac_file in $ac_files
do
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
* ) ac_rmfiles="$ac_rmfiles $ac_file";;
esac
done
rm -f $ac_rmfiles
if { { ac_try="$ac_link_default"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
then :
# Autoconf-2.13 could set the ac_cv_exeext variable to 'no'.
# So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
# so that the user can short-circuit this test for compilers unknown to
# Autoconf.
for ac_file in $ac_files ''
do
test -f "$ac_file" || continue
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
;;
[ab].out )
# We found the default executable, but exeext='' is most
# certainly right.
break;;
*.* )
if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
# We set ac_cv_exeext here because the later test for it is not
# safe: cross compilers may not add the suffix if given an '-o'
# argument, so we may need to know it at that point already.
# Even if this section looks crufty: it has the advantage of
# actually working.
break;;
* )
break;;
esac
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
else case e in #(
e) ac_file='' ;;
esac
fi
if test -z "$ac_file"
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See 'config.log' for more details" "$LINENO" 5; }
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; } ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
printf %s "checking for C compiler default output file name... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
then :
# If both 'conftest.exe' and 'conftest' are 'present' (well, observable)
# catch 'conftest.exe'. For instance with Cygwin, 'ls conftest' will
# work properly (i.e., refer to 'conftest.exe'), while it won't with
# 'rm'.
for ac_file in conftest.exe conftest conftest.*; do
test -f "$ac_file" || continue
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
*.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
break;;
* ) break;;
esac
done
else case e in #(
e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See 'config.log' for more details" "$LINENO" 5; } ;;
esac
fi
rm -f conftest conftest$ac_cv_exeext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
printf "%s\n" "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
int
main (void)
{
FILE *f = fopen ("conftest.out", "w");
if (!f)
return 1;
return ferror (f) || fclose (f) != 0;
;
return 0;
}
_ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use '--host'.
See 'config.log' for more details" "$LINENO" 5; }
fi
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
printf "%s\n" "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext \
conftest.o conftest.obj conftest.out
ac_clean_files=$ac_clean_files_save
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
printf %s "checking for suffix of object files... " >&6; }
if test ${ac_cv_objext+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
rm -f conftest.o conftest.obj
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
*) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
break;;
esac
done
else case e in #(
e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See 'config.log' for more details" "$LINENO" 5; } ;;
esac
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
printf %s "checking whether the compiler supports GNU C... " >&6; }
if test ${ac_cv_c_compiler_gnu+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
#ifndef __GNUC__
choke me
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_compiler_gnu=yes
else case e in #(
e) ac_compiler_gnu=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
printf %s "checking whether $CC accepts -g... " >&6; }
if test ${ac_cv_prog_cc_g+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_g=yes
else case e in #(
e) CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
else case e in #(
e) ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_g=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-g"
fi
else
if test "$GCC" = yes; then
CFLAGS="-O2"
else
CFLAGS=
fi
fi
ac_prog_cc_stdc=no
if test x$ac_prog_cc_stdc = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
printf %s "checking for $CC option to enable C11 features... " >&6; }
if test ${ac_cv_prog_cc_c11+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_c_conftest_c11_program
_ACEOF
for ac_arg in '' -std=gnu11
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_c11=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c11" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC ;;
esac
fi
if test "x$ac_cv_prog_cc_c11" = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else case e in #(
e) if test "x$ac_cv_prog_cc_c11" = x
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
CC="$CC $ac_cv_prog_cc_c11" ;;
esac
fi
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
ac_prog_cc_stdc=c11 ;;
esac
fi
fi
if test x$ac_prog_cc_stdc = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
printf %s "checking for $CC option to enable C99 features... " >&6; }
if test ${ac_cv_prog_cc_c99+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_cv_prog_cc_c99=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_c_conftest_c99_program
_ACEOF
for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_c99=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c99" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC ;;
esac
fi
if test "x$ac_cv_prog_cc_c99" = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else case e in #(
e) if test "x$ac_cv_prog_cc_c99" = x
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
CC="$CC $ac_cv_prog_cc_c99" ;;
esac
fi
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
ac_prog_cc_stdc=c99 ;;
esac
fi
fi
if test x$ac_prog_cc_stdc = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
printf %s "checking for $CC option to enable C89 features... " >&6; }
if test ${ac_cv_prog_cc_c89+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_cv_prog_cc_c89=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_c_conftest_c89_program
_ACEOF
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_c89=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC ;;
esac
fi
if test "x$ac_cv_prog_cc_c89" = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else case e in #(
e) if test "x$ac_cv_prog_cc_c89" = x
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
CC="$CC $ac_cv_prog_cc_c89" ;;
esac
fi
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
ac_prog_cc_stdc=c89 ;;
esac
fi
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
printf %s "checking whether $CC understands -c and -o together... " >&6; }
if test ${am_cv_prog_cc_c_o+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
# Make sure it works both with $CC and with simple cc.
# Following AC_PROG_CC_C_O, we do the test twice because some
# compilers refuse to overwrite an existing .o file with -o,
# though they will create one.
am_cv_prog_cc_c_o=yes
for am_i in 1 2; do
if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } \
&& test -f conftest2.$ac_objext; then
: OK
else
am_cv_prog_cc_c_o=no
break
fi
done
# aligned with autoconf, so not including core; see bug#72225.
rm -f -r a.out a.exe b.out conftest.$ac_ext conftest.$ac_objext \
conftest.dSYM conftest1.$ac_ext conftest1.$ac_objext conftest1.dSYM \
conftest2.$ac_ext conftest2.$ac_objext conftest2.dSYM
unset am_i ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
printf "%s\n" "$am_cv_prog_cc_c_o" >&6; }
if test "$am_cv_prog_cc_c_o" != yes; then
# Losing compiler, so override with the script.
# FIXME: It is wrong to rewrite CC.
# But if we don't then we get into trouble of one sort or another.
# A longer-term fix would be to have automake use am__CC in this case,
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
CC="$am_aux_dir/compile $CC"
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
depcc="$CC" am_compiler_list=
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
printf %s "checking dependency style of $depcc... " >&6; }
if test ${am_cv_CC_dependencies_compiler_type+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
# We make a subdir and do the tests there. Otherwise we can end up
# making bogus files that we don't know about and never remove. For
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named 'D' -- because '-MD' means "put the output
# in D".
rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
cp "$am_depcomp" conftest.dir
cd conftest.dir
# We will build objects and dependencies in a subdirectory because
# it helps to detect inapplicable dependency modes. For instance
# both Tru64's cc and ICC support -MD to output dependencies as a
# side effect of compilation, but ICC will put the dependencies in
# the current directory while Tru64 will put them in the object
# directory.
mkdir sub
am_cv_CC_dependencies_compiler_type=none
if test "$am_compiler_list" = ""; then
am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
fi
am__universal=false
case " $depcc " in #(
*\ -arch\ *\ -arch\ *) am__universal=true ;;
esac
for depmode in $am_compiler_list; do
# Setup a source with many dependencies, because some compilers
# like to wrap large dependency lists on column 80 (with \), and
# we should not choose a depcomp mode which is confused by this.
#
# We need to recreate these files for each test, as the compiler may
# overwrite some of them when testing with obscure command lines.
# This happens at least with the AIX C compiler.
: > sub/conftest.c
for i in 1 2 3 4 5 6; do
echo '#include "conftst'$i'.h"' >> sub/conftest.c
# Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
# Solaris 10 /bin/sh.
echo '/* dummy */' > sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
# We check with '-c' and '-o' for the sake of the "dashmstdout"
# mode. It turns out that the SunPro C++ compiler does not properly
# handle '-M -o', and we need to detect this. Also, some Intel
# versions had trouble with output in subdirs.
am__obj=sub/conftest.${OBJEXT-o}
am__minus_obj="-o $am__obj"
case $depmode in
gcc)
# This depmode causes a compiler race in universal mode.
test "$am__universal" = false || continue
;;
nosideeffect)
# After this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested.
if test "x$enable_dependency_tracking" = xyes; then
continue
else
break
fi
;;
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok '-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
am__obj=conftest.${OBJEXT-o}
am__minus_obj=
;;
none) break ;;
esac
if depmode=$depmode \
source=sub/conftest.c object=$am__obj \
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
$SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
>/dev/null 2>conftest.err &&
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
# icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message
# that says an option was ignored or not supported.
# When given -MP, icc 7.0 and 7.1 complain thus:
# icc: Command line warning: ignoring option '-M'; no argument required
# The diagnosis changed in icc 8.0:
# icc: Command line remark: option '-MP' not supported
if (grep 'ignoring option' conftest.err ||
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
am_cv_CC_dependencies_compiler_type=$depmode
break
fi
fi
done
cd ..
rm -rf conftest.dir
else
am_cv_CC_dependencies_compiler_type=none
fi
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; }
CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
if
test "x$enable_dependency_tracking" != xno \
&& test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
am__fastdepCC_TRUE=
am__fastdepCC_FALSE='#'
else
am__fastdepCC_TRUE='#'
am__fastdepCC_FALSE=
fi
ac_header= ac_cache=
for ac_item in $ac_header_c_list
do
if test $ac_cache; then
ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
printf "%s\n" "#define $ac_item 1" >> confdefs.h
fi
ac_header= ac_cache=
elif test $ac_header; then
ac_cache=$ac_item
else
ac_header=$ac_item
fi
done
if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
then :
printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
printf %s "checking whether byte ordering is bigendian... " >&6; }
if test ${ac_cv_c_bigendian+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_cv_c_bigendian=unknown
# See if we're dealing with a universal compiler.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifndef __APPLE_CC__
not a universal capable compiler
#endif
typedef int dummy;
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
# Check for potential -arch flags. It is not universal unless
# there are at least two -arch flags with different values.
ac_arch=
ac_prev=
for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
if test -n "$ac_prev"; then
case $ac_word in
i?86 | x86_64 | ppc | ppc64)
if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
ac_arch=$ac_word
else
ac_cv_c_bigendian=universal
break
fi
;;
esac
ac_prev=
elif test "x$ac_word" = "x-arch"; then
ac_prev=arch
fi
done
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test $ac_cv_c_bigendian = unknown; then
# See if sys/param.h defines the BYTE_ORDER macro.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#include
int
main (void)
{
#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \\
&& defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \\
&& LITTLE_ENDIAN)
bogus endian macros
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
# It does; now see whether it defined to BIG_ENDIAN or not.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
#include
int
main (void)
{
#if BYTE_ORDER != BIG_ENDIAN
not big endian
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_c_bigendian=yes
else case e in #(
e) ac_cv_c_bigendian=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
if test $ac_cv_c_bigendian = unknown; then
# See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
int
main (void)
{
#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
bogus endian macros
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
# It does; now see whether it defined to _BIG_ENDIAN or not.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
int
main (void)
{
#ifndef _BIG_ENDIAN
not big endian
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_c_bigendian=yes
else case e in #(
e) ac_cv_c_bigendian=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
if test $ac_cv_c_bigendian = unknown; then
# Compile a test program.
if test "$cross_compiling" = yes
then :
# Try to guess by grepping values from an object file.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
unsigned short int ascii_mm[] =
{ 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
unsigned short int ascii_ii[] =
{ 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
int use_ascii (int i) {
return ascii_mm[i] + ascii_ii[i];
}
unsigned short int ebcdic_ii[] =
{ 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
unsigned short int ebcdic_mm[] =
{ 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
int use_ebcdic (int i) {
return ebcdic_mm[i] + ebcdic_ii[i];
}
int
main (int argc, char **argv)
{
/* Intimidate the compiler so that it does not
optimize the arrays away. */
char *p = argv[0];
ascii_mm[1] = *p++; ebcdic_mm[1] = *p++;
ascii_ii[1] = *p++; ebcdic_ii[1] = *p++;
return use_ascii (argc) == use_ebcdic (*p);
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
if grep BIGenDianSyS conftest$ac_exeext >/dev/null; then
ac_cv_c_bigendian=yes
fi
if grep LiTTleEnDian conftest$ac_exeext >/dev/null ; then
if test "$ac_cv_c_bigendian" = unknown; then
ac_cv_c_bigendian=no
else
# finding both strings is unlikely to happen, but who knows?
ac_cv_c_bigendian=unknown
fi
fi
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
int
main (void)
{
/* Are we little or big endian? From Harbison&Steele. */
union
{
long int l;
char c[sizeof (long int)];
} u;
u.l = 1;
return u.c[sizeof (long int) - 1] == 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"
then :
ac_cv_c_bigendian=no
else case e in #(
e) ac_cv_c_bigendian=yes ;;
esac
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
printf "%s\n" "$ac_cv_c_bigendian" >&6; }
case $ac_cv_c_bigendian in #(
yes)
printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h
;; #(
no)
;; #(
universal)
printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
;; #(
*)
as_fn_error $? "unknown endianness
presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
esac
if test -n "$ac_tool_prefix"; then
for ac_prog in ar lib "link -lib"
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_AR+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$AR"; then
ac_cv_prog_AR="$AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
printf "%s\n" "$AR" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$AR" && break
done
fi
if test -z "$AR"; then
ac_ct_AR=$AR
for ac_prog in ar lib "link -lib"
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_AR+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_AR"; then
ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_AR="$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
printf "%s\n" "$ac_ct_AR" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$ac_ct_AR" && break
done
if test "x$ac_ct_AR" = x; then
AR="false"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
AR=$ac_ct_AR
fi
fi
: ${AR=ar}
: ${ARFLAGS=cr}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5
printf %s "checking the archiver ($AR) interface... " >&6; }
if test ${am_cv_ar_interface+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
am_cv_ar_interface=ar
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int some_variable = 0;
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
am_ar_try='$AR $ARFLAGS libconftest.a conftest.$ac_objext >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
(eval $am_ar_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if test "$ac_status" -eq 0; then
am_cv_ar_interface=ar
else
am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
(eval $am_ar_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if test "$ac_status" -eq 0; then
am_cv_ar_interface=lib
else
am_cv_ar_interface=unknown
fi
fi
rm -f conftest.lib libconftest.a
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5
printf "%s\n" "$am_cv_ar_interface" >&6; }
case $am_cv_ar_interface in
ar)
;;
lib)
# Microsoft lib, so override with the ar-lib wrapper script.
# FIXME: It is wrong to rewrite AR.
# But if we don't then we get into trouble of one sort or another.
# A longer-term fix would be to have automake use am__AR in this case,
# and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
# similar.
AR="$am_aux_dir/ar-lib $AR"
;;
unknown)
as_fn_error $? "could not determine $AR interface" "$LINENO" 5
;;
esac
case `pwd` in
*\ * | *\ *)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
printf "%s\n" "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
esac
macro_version='2.6.0'
macro_revision='2.6.0'
ltmain=$ac_aux_dir/ltmain.sh
# Make sure we can run config.sub.
$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
printf %s "checking build system type... " >&6; }
if test ${ac_cv_build+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
esac
build=$ac_cv_build
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_build
shift
build_cpu=$1
build_vendor=$2
shift; shift
# Remember, the first character of IFS is used to create $*,
# except with old shells:
build_os=$*
IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
printf %s "checking host system type... " >&6; }
if test ${ac_cv_host+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
esac
host=$ac_cv_host
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_host
shift
host_cpu=$1
host_vendor=$2
shift; shift
# Remember, the first character of IFS is used to create $*,
# except with old shells:
host_os=$*
IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
# Backslashify metacharacters that are still active within
# double-quoted strings.
sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
# Same as above, but do not quote variable references.
double_quote_subst='s/\(["`\\]\)/\\\1/g'
# Sed substitution to delay expansion of an escaped shell variable in a
# double_quote_subst'ed string.
delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
# Sed substitution to delay expansion of an escaped single quote.
delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
# Sed substitution to avoid accidental globbing in evaled expressions
no_glob_subst='s/\*/\\\*/g'
ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
printf %s "checking how to print strings... " >&6; }
# Test print first, because it will be a builtin if present.
if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
ECHO='print -r --'
elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
ECHO='printf %s\n'
else
# Use this function as a fallback that always works.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
$1
_LTECHO_EOF'
}
ECHO='func_fallback_echo'
fi
# func_echo_all arg...
# Invoke $ECHO with all args, space-separated.
func_echo_all ()
{
$ECHO ""
}
case $ECHO in
printf*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: printf" >&5
printf "%s\n" "printf" >&6; } ;;
print*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
printf "%s\n" "print -r" >&6; } ;;
*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cat" >&5
printf "%s\n" "cat" >&6; } ;;
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
printf %s "checking for a sed that does not truncate output... " >&6; }
if test ${ac_cv_path_SED+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
for ac_i in 1 2 3 4 5 6 7; do
ac_script="$ac_script$as_nl$ac_script"
done
echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
{ ac_script=; unset ac_script;}
if test -z "$SED"; then
ac_path_SED_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_prog in sed gsed
do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_SED="$as_dir$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_SED" || continue
# Check for GNU ac_path_SED and select it if it is found.
# Check for GNU $ac_path_SED
case `"$ac_path_SED" --version 2>&1` in #(
*GNU*)
ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
#(
*)
ac_count=0
printf %s 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
printf "%s\n" '' >> "conftest.nl"
"$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_SED_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_SED="$ac_path_SED"
ac_path_SED_max=$ac_count
fi
# 10*(2^10) chars as input seems more than enough
test $ac_count -gt 10 && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
$ac_path_SED_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_SED"; then
as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
fi
else
ac_cv_path_SED=$SED
fi
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
printf "%s\n" "$ac_cv_path_SED" >&6; }
SED="$ac_cv_path_SED"
rm -f conftest.sed
test -z "$SED" && SED=sed
Xsed="$SED -e 1s/^X//"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
printf %s "checking for grep that handles long lines and -e... " >&6; }
if test ${ac_cv_path_GREP+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -z "$GREP"; then
ac_path_GREP_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_prog in grep ggrep
do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_GREP" || continue
# Check for GNU ac_path_GREP and select it if it is found.
# Check for GNU $ac_path_GREP
case `"$ac_path_GREP" --version 2>&1` in #(
*GNU*)
ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
#(
*)
ac_count=0
printf %s 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
printf "%s\n" 'GREP' >> "conftest.nl"
"$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_GREP_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_GREP="$ac_path_GREP"
ac_path_GREP_max=$ac_count
fi
# 10*(2^10) chars as input seems more than enough
test $ac_count -gt 10 && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
$ac_path_GREP_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_GREP"; then
as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_GREP=$GREP
fi
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
printf "%s\n" "$ac_cv_path_GREP" >&6; }
GREP="$ac_cv_path_GREP"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
printf %s "checking for egrep... " >&6; }
if test ${ac_cv_path_EGREP+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
then ac_cv_path_EGREP="$GREP -E"
else
if test -z "$EGREP"; then
ac_path_EGREP_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_prog in egrep
do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_EGREP" || continue
# Check for GNU ac_path_EGREP and select it if it is found.
# Check for GNU $ac_path_EGREP
case `"$ac_path_EGREP" --version 2>&1` in #(
*GNU*)
ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
#(
*)
ac_count=0
printf %s 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
printf "%s\n" 'EGREP' >> "conftest.nl"
"$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_EGREP_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_EGREP="$ac_path_EGREP"
ac_path_EGREP_max=$ac_count
fi
# 10*(2^10) chars as input seems more than enough
test $ac_count -gt 10 && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
$ac_path_EGREP_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_EGREP"; then
as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_EGREP=$EGREP
fi
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
printf "%s\n" "$ac_cv_path_EGREP" >&6; }
EGREP="$ac_cv_path_EGREP"
EGREP_TRADITIONAL=$EGREP
ac_cv_path_EGREP_TRADITIONAL=$EGREP
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
printf %s "checking for fgrep... " >&6; }
if test ${ac_cv_path_FGREP+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
then ac_cv_path_FGREP="$GREP -F"
else
if test -z "$FGREP"; then
ac_path_FGREP_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_prog in fgrep
do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_FGREP="$as_dir$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_FGREP" || continue
# Check for GNU ac_path_FGREP and select it if it is found.
# Check for GNU $ac_path_FGREP
case `"$ac_path_FGREP" --version 2>&1` in #(
*GNU*)
ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
#(
*)
ac_count=0
printf %s 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
printf "%s\n" 'FGREP' >> "conftest.nl"
"$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_FGREP_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_FGREP="$ac_path_FGREP"
ac_path_FGREP_max=$ac_count
fi
# 10*(2^10) chars as input seems more than enough
test $ac_count -gt 10 && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
$ac_path_FGREP_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_FGREP"; then
as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_FGREP=$FGREP
fi
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
printf "%s\n" "$ac_cv_path_FGREP" >&6; }
FGREP="$ac_cv_path_FGREP"
test -z "$GREP" && GREP=grep
# Check whether --with-gnu-ld was given.
if test ${with_gnu_ld+y}
then :
withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
else case e in #(
e) with_gnu_ld=no ;;
esac
fi
ac_prog=ld
if test yes = "$GCC"; then
# Check if gcc -print-prog-name=ld gives a path.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
printf %s "checking for ld used by $CC... " >&6; }
case $host in
*-*-mingw* | *-*-windows*)
# gcc leaves a trailing carriage return, which upsets mingw
ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
*)
ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
esac
case $ac_prog in
# Accept absolute paths.
[\\/]* | ?:[\\/]*)
re_direlt='/[^/][^/]*/\.\./'
# Canonicalize the pathname of ld
ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
done
test -z "$LD" && LD=$ac_prog
;;
"")
# If it fails, then pretend we aren't using GCC.
ac_prog=ld
;;
*)
# If it is relative, then search for the first ld in PATH.
with_gnu_ld=unknown
;;
esac
elif test yes = "$with_gnu_ld"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
printf %s "checking for GNU ld... " >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
printf %s "checking for non-GNU ld... " >&6; }
fi
if test ${lt_cv_path_LD+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -z "$LD"; then
lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
for ac_dir in $PATH; do
IFS=$lt_save_ifs
test -z "$ac_dir" && ac_dir=.
if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
lt_cv_path_LD=$ac_dir/$ac_prog
# Check to see if the program is GNU ld. I'd rather use --version,
# but apparently some variants of GNU ld only accept -v.
# Break only if it was the GNU/non-GNU ld that we prefer.
case `"$lt_cv_path_LD" -v 2>&1 &5
printf "%s\n" "$LD" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
printf %s "checking if the linker ($LD) is GNU ld... " >&6; }
if test ${lt_cv_prog_gnu_ld+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) # I'd rather use --version here, but apparently some GNU lds only accept -v.
case `$LD -v 2>&1 &5
printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; }
with_gnu_ld=$lt_cv_prog_gnu_ld
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
printf %s "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
if test ${lt_cv_path_NM+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$NM"; then
# Let the user override the test.
lt_cv_path_NM=$NM
else
lt_nm_to_check=${ac_tool_prefix}nm
if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
lt_nm_to_check="$lt_nm_to_check nm"
fi
for lt_tmp_nm in $lt_nm_to_check; do
lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
IFS=$lt_save_ifs
test -z "$ac_dir" && ac_dir=.
tmp_nm=$ac_dir/$lt_tmp_nm
if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
# Check to see if the nm accepts a BSD-compat flag.
# Adding the 'sed 1q' prevents false positives on HP-UX, which says:
# nm: unknown option "B" ignored
# Tru64's nm complains that /dev/null is an invalid object file
# MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
case $build_os in
mingw* | windows*) lt_bad_file=conftest.nm/nofile ;;
*) lt_bad_file=/dev/null ;;
esac
case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
*$lt_bad_file* | *'Invalid file or object type'*)
lt_cv_path_NM="$tmp_nm -B"
break 2
;;
*)
case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
*/dev/null*)
lt_cv_path_NM="$tmp_nm -p"
break 2
;;
*)
lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
continue # so that we can try to find one that supports BSD flags
;;
esac
;;
esac
fi
done
IFS=$lt_save_ifs
done
: ${lt_cv_path_NM=no}
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
printf "%s\n" "$lt_cv_path_NM" >&6; }
if test no != "$lt_cv_path_NM"; then
NM=$lt_cv_path_NM
else
# Didn't find any BSD compatible name lister, look for dumpbin.
if test -n "$DUMPBIN"; then :
# Let the user override the test.
else
if test -n "$ac_tool_prefix"; then
for ac_prog in dumpbin "link -dump"
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_DUMPBIN+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$DUMPBIN"; then
ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
DUMPBIN=$ac_cv_prog_DUMPBIN
if test -n "$DUMPBIN"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
printf "%s\n" "$DUMPBIN" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$DUMPBIN" && break
done
fi
if test -z "$DUMPBIN"; then
ac_ct_DUMPBIN=$DUMPBIN
for ac_prog in dumpbin "link -dump"
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_DUMPBIN+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_DUMPBIN"; then
ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
if test -n "$ac_ct_DUMPBIN"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
printf "%s\n" "$ac_ct_DUMPBIN" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$ac_ct_DUMPBIN" && break
done
if test "x$ac_ct_DUMPBIN" = x; then
DUMPBIN=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
DUMPBIN=$ac_ct_DUMPBIN
fi
fi
case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
*COFF*)
DUMPBIN="$DUMPBIN -symbols -headers"
;;
*)
DUMPBIN=:
;;
esac
fi
if test : != "$DUMPBIN"; then
NM=$DUMPBIN
fi
fi
test -z "$NM" && NM=nm
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
printf %s "checking the name lister ($NM) interface... " >&6; }
if test ${lt_cv_nm_interface+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
(eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
(eval echo "\"\$as_me:$LINENO: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
fi
rm -f conftest* ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
printf "%s\n" "$lt_cv_nm_interface" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
printf %s "checking whether ln -s works... " >&6; }
LN_S=$as_ln_s
if test "$LN_S" = "ln -s"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
printf "%s\n" "no, using $LN_S" >&6; }
fi
# find the maximum length of command line arguments
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
printf %s "checking the maximum length of command line arguments... " >&6; }
if test ${lt_cv_sys_max_cmd_len+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) i=0
teststring=ABCD
case $build_os in
msdosdjgpp*)
# On DJGPP, this test can blow up pretty badly due to problems in libc
# (any single argument exceeding 2000 bytes causes a buffer overrun
# during glob expansion). Even if it were fixed, the result of this
# check would be larger than it should be.
lt_cv_sys_max_cmd_len=12288; # 12K is about right
;;
gnu* | ironclad*)
# Under GNU Hurd and Ironclad, this test is not required because there
# is no limit to the length of command line arguments.
# Libtool will interpret -1 as no limit whatsoever
lt_cv_sys_max_cmd_len=-1;
;;
cygwin* | mingw* | windows* | cegcc*)
# On Win9x/ME, this test blows up -- it succeeds, but takes
# about 5 minutes as the teststring grows exponentially.
# Worse, since 9x/ME are not pre-emptively multitasking,
# you end up with a "frozen" computer, even though with patience
# the test eventually succeeds (with a max line length of 256k).
# Instead, let's just punt: use the minimum linelength reported by
# all of the supported platforms: 8192 (on NT/2K/XP).
lt_cv_sys_max_cmd_len=8192;
;;
mint*)
# On MiNT this can take a long time and run out of memory.
lt_cv_sys_max_cmd_len=8192;
;;
amigaos*)
# On AmigaOS with pdksh, this test takes hours, literally.
# So we just punt and use a minimum line length of 8192.
lt_cv_sys_max_cmd_len=8192;
;;
darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
# This has been around since 386BSD, at least. Likely further.
if test -x /sbin/sysctl; then
lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
elif test -x /usr/sbin/sysctl; then
lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
else
lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
fi
# And add a safety zone
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
;;
interix*)
# We know the value 262144 and hardcode it with a safety zone (like BSD)
lt_cv_sys_max_cmd_len=196608
;;
os2*)
# The test takes a long time on OS/2.
lt_cv_sys_max_cmd_len=8192
;;
osf*)
# Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
# due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
# nice to cause kernel panics so lets avoid the loop below.
# First set a reasonable default.
lt_cv_sys_max_cmd_len=16384
#
if test -x /sbin/sysconfig; then
case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
*1*) lt_cv_sys_max_cmd_len=-1 ;;
esac
fi
;;
sco3.2v5*)
lt_cv_sys_max_cmd_len=102400
;;
sysv5* | sco5v6* | sysv4.2uw2*)
kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
if test -n "$kargmax"; then
lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[ ]//'`
else
lt_cv_sys_max_cmd_len=32768
fi
;;
*)
lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
if test -n "$lt_cv_sys_max_cmd_len" && \
test undefined != "$lt_cv_sys_max_cmd_len"; then
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
else
# Make teststring a little bigger before we do anything with it.
# a 1K string should be a reasonable start.
for i in 1 2 3 4 5 6 7 8; do
teststring=$teststring$teststring
done
SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
# If test is not a shell built-in, we'll probably end up computing a
# maximum length that is only half of the actual maximum length, but
# we can't tell.
while { test X`env echo "$teststring$teststring" 2>/dev/null` \
= "X$teststring$teststring"; } >/dev/null 2>&1 &&
test 17 != "$i" # 1/2 MB should be enough
do
i=`expr $i + 1`
teststring=$teststring$teststring
done
# Only check the string length outside the loop.
lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
teststring=
# Add a significant safety factor because C++ compilers can tack on
# massive amounts of additional arguments before passing them to the
# linker. It appears as though 1/2 is a usable value.
lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
fi
;;
esac
;;
esac
fi
if test -n "$lt_cv_sys_max_cmd_len"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
printf "%s\n" "$lt_cv_sys_max_cmd_len" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
printf "%s\n" "none" >&6; }
fi
max_cmd_len=$lt_cv_sys_max_cmd_len
: ${CP="cp -f"}
: ${MV="mv -f"}
: ${RM="rm -f"}
if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
lt_unset=unset
else
lt_unset=false
fi
# test EBCDIC or ASCII
case `echo X|tr X '\101'` in
A) # ASCII based system
# \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
lt_SP2NL='tr \040 \012'
lt_NL2SP='tr \015\012 \040\040'
;;
*) # EBCDIC based system
lt_SP2NL='tr \100 \n'
lt_NL2SP='tr \r\n \100\100'
;;
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
printf %s "checking how to convert $build file names to $host format... " >&6; }
if test ${lt_cv_to_host_file_cmd+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) case $host in
*-*-mingw* )
case $build in
*-*-mingw* | *-*-windows* ) # actually msys
lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
;;
*-*-cygwin* )
lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
;;
* ) # otherwise, assume *nix
lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
;;
esac
;;
*-*-cygwin* )
case $build in
*-*-mingw* | *-*-windows* ) # actually msys
lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
;;
*-*-cygwin* )
lt_cv_to_host_file_cmd=func_convert_file_noop
;;
* ) # otherwise, assume *nix
lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
;;
esac
;;
* ) # unhandled hosts (and "normal" native builds)
lt_cv_to_host_file_cmd=func_convert_file_noop
;;
esac
;;
esac
fi
to_host_file_cmd=$lt_cv_to_host_file_cmd
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
printf "%s\n" "$lt_cv_to_host_file_cmd" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
printf %s "checking how to convert $build file names to toolchain format... " >&6; }
if test ${lt_cv_to_tool_file_cmd+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) #assume ordinary cross tools, or native build.
lt_cv_to_tool_file_cmd=func_convert_file_noop
case $host in
*-*-mingw* | *-*-windows* )
case $build in
*-*-mingw* | *-*-windows* ) # actually msys
lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
;;
esac
;;
esac
;;
esac
fi
to_tool_file_cmd=$lt_cv_to_tool_file_cmd
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
printf "%s\n" "$lt_cv_to_tool_file_cmd" >&6; }
case $host in #(
*-*-mingw* | *-*-windows* | *-*-cygwin*) :
case $build in #(
*-*-mingw* | *-*-windows* | *-*-cygwin*) :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether cygpath is installed" >&5
printf %s "checking whether cygpath is installed... " >&6; }
if test ${lt_cv_cygpath_installed+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_cygpath_installed=ignoring
cygpath --help &> /dev/null
_lt_result=$?
if test 0 = "$_lt_result"
then :
lt_cv_cygpath_installed=yes
else case e in #(
e) lt_cv_cygpath_installed=no ;;
esac
fi
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cygpath_installed" >&5
printf "%s\n" "$lt_cv_cygpath_installed" >&6; }
if test "xyes" != "x$lt_cv_cygpath_installed"
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use cmd with one slash or two slashes" >&5
printf %s "checking whether to use cmd with one slash or two slashes... " >&6; }
if test ${lt_cv_cmd_slashes+y}
then :
printf %s "(cached) " >&6
else case e in #(
e)
_lt_result=`cmd /c echo one-slash works. Not checked //c echo two-slashes 2>/dev/null`
if test 0 != $?
then :
as_fn_error $? "Do not know how to convert paths" "$LINENO" 5
fi
case $_lt_result in #(
one-slash*) :
lt_cv_cmd_slashes="one" ;; #(
two-slashes*) :
lt_cv_cmd_slashes="two" ;; #(
*) :
as_fn_error $? "Do not know how to convert paths" "$LINENO" 5
;;
esac
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cmd_slashes" >&5
printf "%s\n" "$lt_cv_cmd_slashes" >&6; }
fi
;; #(
*) :
;;
esac
;; #(
*) :
;;
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
printf %s "checking for $LD option to reload object files... " >&6; }
if test ${lt_cv_ld_reload_flag+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_ld_reload_flag='-r' ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
printf "%s\n" "$lt_cv_ld_reload_flag" >&6; }
reload_flag=$lt_cv_ld_reload_flag
case $reload_flag in
"" | " "*) ;;
*) reload_flag=" $reload_flag" ;;
esac
reload_cmds='$LD$reload_flag -o $output$reload_objs'
case $host_os in
cygwin* | mingw* | windows* | pw32* | cegcc*)
if test yes != "$GCC"; then
reload_cmds=false
fi
;;
darwin*)
if test yes = "$GCC"; then
reload_cmds='$LTCC $LTCFLAGS $stdlibflag $wl-r -o $output$reload_objs'
else
reload_cmds='$LD$reload_flag -o $output$reload_objs'
fi
;;
esac
# Extract the first word of "file", so it can be a program name with args.
set dummy file; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_FILECMD+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$FILECMD"; then
ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_FILECMD="file"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_prog_FILECMD" && ac_cv_prog_FILECMD=":"
fi ;;
esac
fi
FILECMD=$ac_cv_prog_FILECMD
if test -n "$FILECMD"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5
printf "%s\n" "$FILECMD" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
set dummy ${ac_tool_prefix}objdump; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_OBJDUMP+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$OBJDUMP"; then
ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
OBJDUMP=$ac_cv_prog_OBJDUMP
if test -n "$OBJDUMP"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
printf "%s\n" "$OBJDUMP" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_OBJDUMP"; then
ac_ct_OBJDUMP=$OBJDUMP
# Extract the first word of "objdump", so it can be a program name with args.
set dummy objdump; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_OBJDUMP+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_OBJDUMP"; then
ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_OBJDUMP="objdump"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
if test -n "$ac_ct_OBJDUMP"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
printf "%s\n" "$ac_ct_OBJDUMP" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_OBJDUMP" = x; then
OBJDUMP="false"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
OBJDUMP=$ac_ct_OBJDUMP
fi
else
OBJDUMP="$ac_cv_prog_OBJDUMP"
fi
test -z "$OBJDUMP" && OBJDUMP=objdump
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
printf %s "checking how to recognize dependent libraries... " >&6; }
if test ${lt_cv_deplibs_check_method+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_file_magic_cmd='$MAGIC_CMD'
lt_cv_file_magic_test_file=
lt_cv_deplibs_check_method='unknown'
# Need to set the preceding variable on all platforms that support
# interlibrary dependencies.
# 'none' -- dependencies not supported.
# 'unknown' -- same as none, but documents that we really don't know.
# 'pass_all' -- all dependencies passed with no checks.
# 'file_magic [[regex]]' -- check by looking for files in library path
# that responds to the $file_magic_cmd with a given extended regex.
# If you have 'file' or equivalent on your system and you're not sure
# whether 'pass_all' will *always* work, you probably want this one.
case $host_os in
aix[4-9]*)
lt_cv_deplibs_check_method=pass_all
;;
beos*)
lt_cv_deplibs_check_method=pass_all
;;
bsdi[45]*)
lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
lt_cv_file_magic_cmd='$FILECMD -L'
lt_cv_file_magic_test_file=/shlib/libc.so
;;
cygwin*)
# func_win32_libid is a shell function defined in ltmain.sh
lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
lt_cv_file_magic_cmd='func_win32_libid'
;;
mingw* | windows* | pw32*)
# Base MSYS/MinGW do not provide the 'file' command needed by
# func_win32_libid shell function, so use a weaker test based on 'objdump',
# unless we find 'file', for example because we are cross-compiling.
if ( file / ) >/dev/null 2>&1; then
lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
lt_cv_file_magic_cmd='func_win32_libid'
else
# Keep this pattern in sync with the one in func_win32_libid.
lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64|pe-aarch64)'
lt_cv_file_magic_cmd='$OBJDUMP -f'
fi
;;
cegcc*)
# use the weaker test based on 'objdump'. See mingw*.
lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
lt_cv_file_magic_cmd='$OBJDUMP -f'
;;
darwin* | rhapsody*)
lt_cv_deplibs_check_method=pass_all
;;
freebsd* | dragonfly* | midnightbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
case $host_cpu in
i*86 )
# Not sure whether the presence of OpenBSD here was a mistake.
# Let's accept both of them until this is cleared up.
lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
lt_cv_file_magic_cmd=$FILECMD
lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
;;
esac
else
lt_cv_deplibs_check_method=pass_all
fi
;;
haiku*)
lt_cv_deplibs_check_method=pass_all
;;
hpux10.20* | hpux11*)
lt_cv_file_magic_cmd=$FILECMD
case $host_cpu in
ia64*)
lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
;;
hppa*64*)
lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
;;
*)
lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
lt_cv_file_magic_test_file=/usr/lib/libc.sl
;;
esac
;;
interix[3-9]*)
# PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
;;
irix5* | irix6* | nonstopux*)
case $LD in
*-32|*"-32 ") libmagic=32-bit;;
*-n32|*"-n32 ") libmagic=N32;;
*-64|*"-64 ") libmagic=64-bit;;
*) libmagic=never-match;;
esac
lt_cv_deplibs_check_method=pass_all
;;
*-mlibc)
lt_cv_deplibs_check_method=pass_all
;;
# This must be glibc/ELF.
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
lt_cv_deplibs_check_method=pass_all
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
else
lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
fi
;;
newos6*)
lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
lt_cv_file_magic_cmd=$FILECMD
lt_cv_file_magic_test_file=/usr/lib/libnls.so
;;
*nto* | *qnx*)
lt_cv_deplibs_check_method=pass_all
;;
openbsd*)
if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
else
lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
fi
;;
osf3* | osf4* | osf5*)
lt_cv_deplibs_check_method=pass_all
;;
rdos*)
lt_cv_deplibs_check_method=pass_all
;;
serenity*)
lt_cv_deplibs_check_method=pass_all
;;
solaris*)
lt_cv_deplibs_check_method=pass_all
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
lt_cv_deplibs_check_method=pass_all
;;
sysv4 | sysv4.3*)
case $host_vendor in
motorola)
lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
;;
ncr)
lt_cv_deplibs_check_method=pass_all
;;
sequent)
lt_cv_file_magic_cmd='/bin/file'
lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
;;
sni)
lt_cv_file_magic_cmd='/bin/file'
lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
lt_cv_file_magic_test_file=/lib/libc.so
;;
siemens)
lt_cv_deplibs_check_method=pass_all
;;
pc)
lt_cv_deplibs_check_method=pass_all
;;
esac
;;
tpf*)
lt_cv_deplibs_check_method=pass_all
;;
os2*)
lt_cv_deplibs_check_method=pass_all
;;
esac
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
printf "%s\n" "$lt_cv_deplibs_check_method" >&6; }
file_magic_glob=
want_nocaseglob=no
if test "$build" = "$host"; then
case $host_os in
mingw* | windows* | pw32*)
if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
want_nocaseglob=yes
else
file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
fi
;;
esac
fi
file_magic_cmd=$lt_cv_file_magic_cmd
deplibs_check_method=$lt_cv_deplibs_check_method
test -z "$deplibs_check_method" && deplibs_check_method=unknown
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
set dummy ${ac_tool_prefix}dlltool; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_DLLTOOL+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$DLLTOOL"; then
ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
DLLTOOL=$ac_cv_prog_DLLTOOL
if test -n "$DLLTOOL"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
printf "%s\n" "$DLLTOOL" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_DLLTOOL"; then
ac_ct_DLLTOOL=$DLLTOOL
# Extract the first word of "dlltool", so it can be a program name with args.
set dummy dlltool; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_DLLTOOL+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_DLLTOOL"; then
ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_DLLTOOL="dlltool"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
if test -n "$ac_ct_DLLTOOL"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
printf "%s\n" "$ac_ct_DLLTOOL" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_DLLTOOL" = x; then
DLLTOOL="false"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
DLLTOOL=$ac_ct_DLLTOOL
fi
else
DLLTOOL="$ac_cv_prog_DLLTOOL"
fi
test -z "$DLLTOOL" && DLLTOOL=dlltool
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
printf %s "checking how to associate runtime and link libraries... " >&6; }
if test ${lt_cv_sharedlib_from_linklib_cmd+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_sharedlib_from_linklib_cmd='unknown'
case $host_os in
cygwin* | mingw* | windows* | pw32* | cegcc*)
# two different shell functions defined in ltmain.sh;
# decide which one to use based on capabilities of $DLLTOOL
case `$DLLTOOL --help 2>&1` in
*--identify-strict*)
lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
;;
*)
lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
;;
esac
;;
*)
# fallback: assume linklib IS sharedlib
lt_cv_sharedlib_from_linklib_cmd=$ECHO
;;
esac
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
printf "%s\n" "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_RANLIB+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
printf "%s\n" "$RANLIB" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_RANLIB"; then
ac_ct_RANLIB=$RANLIB
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_RANLIB+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_RANLIB"; then
ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_RANLIB="ranlib"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
printf "%s\n" "$ac_ct_RANLIB" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_RANLIB" = x; then
RANLIB=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
RANLIB=$ac_ct_RANLIB
fi
else
RANLIB="$ac_cv_prog_RANLIB"
fi
if test -n "$ac_tool_prefix"; then
for ac_prog in ar
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_AR+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$AR"; then
ac_cv_prog_AR="$AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
printf "%s\n" "$AR" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$AR" && break
done
fi
if test -z "$AR"; then
ac_ct_AR=$AR
for ac_prog in ar
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_AR+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_AR"; then
ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_AR="$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
printf "%s\n" "$ac_ct_AR" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$ac_ct_AR" && break
done
if test "x$ac_ct_AR" = x; then
AR="false"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
AR=$ac_ct_AR
fi
fi
: ${AR=ar}
# Use ARFLAGS variable as AR's operation code to sync the variable naming with
# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
# higher priority because that's what people were doing historically (setting
# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS
# variable obsoleted/removed.
test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
lt_ar_flags=$AR_FLAGS
# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override
# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
printf %s "checking for archiver @FILE support... " >&6; }
if test ${lt_cv_ar_at_file+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_ar_at_file=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
echo conftest.$ac_objext > conftest.lst
lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
(eval $lt_ar_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if test 0 -eq "$ac_status"; then
# Ensure the archiver fails upon bogus file names.
rm -f conftest.$ac_objext libconftest.a
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
(eval $lt_ar_try) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if test 0 -ne "$ac_status"; then
lt_cv_ar_at_file=@
fi
fi
rm -f conftest.* libconftest.a
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
printf "%s\n" "$lt_cv_ar_at_file" >&6; }
if test no = "$lt_cv_ar_at_file"; then
archiver_list_spec=
else
archiver_list_spec=$lt_cv_ar_at_file
fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
set dummy ${ac_tool_prefix}strip; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_STRIP+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$STRIP"; then
ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_STRIP="${ac_tool_prefix}strip"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
STRIP=$ac_cv_prog_STRIP
if test -n "$STRIP"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
printf "%s\n" "$STRIP" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_STRIP"; then
ac_ct_STRIP=$STRIP
# Extract the first word of "strip", so it can be a program name with args.
set dummy strip; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_STRIP+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_STRIP"; then
ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_STRIP="strip"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
if test -n "$ac_ct_STRIP"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
printf "%s\n" "$ac_ct_STRIP" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_STRIP" = x; then
STRIP=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
STRIP=$ac_ct_STRIP
fi
else
STRIP="$ac_cv_prog_STRIP"
fi
test -z "$STRIP" && STRIP=:
test -z "$RANLIB" && RANLIB=:
# Determine commands to create old-style static archives.
old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
old_postinstall_cmds='chmod 644 $oldlib'
old_postuninstall_cmds=
if test -n "$RANLIB"; then
old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
fi
case $host_os in
darwin*)
lock_old_archive_extraction=yes ;;
*)
lock_old_archive_extraction=no ;;
esac
# If no C compiler was specified, use CC.
LTCC=${LTCC-"$CC"}
# If no C compiler flags were specified, use CFLAGS.
LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
# Allow CC to be a program name with arguments.
compiler=$CC
# Check for command to grab the raw symbol name followed by C symbol from nm.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
printf %s "checking command to parse $NM output from $compiler object... " >&6; }
if test ${lt_cv_sys_global_symbol_pipe+y}
then :
printf %s "(cached) " >&6
else case e in #(
e)
# These are sane defaults that work on at least a few old systems.
# [They come from Ultrix. What could be older than Ultrix?!! ;)]
# Character class describing NM global symbol codes.
symcode='[BCDEGRST]'
# Regexp to match symbols that can be accessed directly from C.
sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
# Define system-specific variables.
case $host_os in
aix*)
symcode='[BCDT]'
;;
cygwin* | mingw* | windows* | pw32* | cegcc*)
symcode='[ABCDGISTW]'
;;
hpux*)
if test ia64 = "$host_cpu"; then
symcode='[ABCDEGRST]'
fi
;;
irix* | nonstopux*)
symcode='[BCDEGRST]'
;;
osf*)
symcode='[BCDEGQRST]'
;;
solaris*)
symcode='[BCDRT]'
;;
sco3.2v5*)
symcode='[DT]'
;;
sysv4.2uw2*)
symcode='[DT]'
;;
sysv5* | sco5v6* | unixware* | OpenUNIX*)
symcode='[ABDT]'
;;
sysv4)
symcode='[DFNSTU]'
;;
esac
# If we're using GNU nm, then use its standard symbol codes.
case `$NM -V 2>&1` in
*GNU* | *'with BFD'*)
symcode='[ABCDGIRSTW]' ;;
esac
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
# Gets list of data symbols to import.
lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \([a-zA-Z_][a-zA-Z0-9_]*\)$/\1/p'"
# Adjust the below global symbol transforms to fixup imported variables.
lt_cdecl_hook=" -e 's/^I .* \([a-zA-Z_][a-zA-Z0-9_]*\)$/extern __declspec(dllimport) char \1;/p'"
lt_c_name_hook=" -e 's/^I .* \([a-zA-Z_][a-zA-Z0-9_]*\)$/ {\"\1\", (void *) 0},/p'"
lt_c_name_lib_hook="\
-e 's/^I .* \(lib[a-zA-Z_][a-zA-Z0-9_]*\)$/ {\"\1\", (void *) 0},/p'\
-e 's/^I .* \([a-zA-Z_][a-zA-Z0-9_]*\)$/ {\"lib\1\", (void *) 0},/p'"
else
# Disable hooks by default.
lt_cv_sys_global_symbol_to_import=
lt_cdecl_hook=
lt_c_name_hook=
lt_c_name_lib_hook=
fi
# Transform an extracted symbol line into a proper C declaration.
# Some systems (esp. on ia64) link data and code symbols differently,
# so use this general approach.
lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
$lt_cdecl_hook\
" -e 's/^T .* \([a-zA-Z_][a-zA-Z0-9_]*\)$/extern int \1();/p'"\
" -e 's/^$symcode$symcode* .* \([a-zA-Z_][a-zA-Z0-9_]*\)$/extern char \1;/p'"
# Transform an extracted symbol line into symbol name and symbol address
lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
$lt_c_name_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \([a-zA-Z_][a-zA-Z0-9_]*\)$/ {\"\1\", (void *) \&\1},/p'"
# Transform an extracted symbol line into symbol name with lib prefix and
# symbol address.
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
$lt_c_name_lib_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(lib[a-zA-Z_][a-zA-Z0-9_]*\)$/ {\"\1\", (void *) \&\1},/p'"\
" -e 's/^$symcode$symcode* .* \([a-zA-Z_][a-zA-Z0-9_]*\)$/ {\"lib\1\", (void *) \&\1},/p'"
# Handle CRLF in mingw tool chain
opt_cr=
case $build_os in
mingw* | windows*)
opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
;;
esac
# Try without a prefix underscore, then with it.
for ac_symprfx in "" "_"; do
# Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
symxfrm="\\1 $ac_symprfx\\2 \\2"
# Write the raw and C identifiers.
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
# Fake it for dumpbin and say T for any non-static function,
# D for any global variable and I for any imported variable.
# Also find C++ and __fastcall symbols from MSVC++ or ICC,
# which start with @ or ?. And Cygwin gawk-4.1.4-3 and newer
# treats input as binary, have to drop carriage return first.
lt_cv_sys_global_symbol_pipe="$AWK '"\
" {sub(/\\r\$/,\"\")};"\
" {last_section=section; section=\$ 3};"\
" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
" \$ 0!~/External *\|/{next};"\
" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
" {if(hide[section]) next};"\
" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
" ' prfx=^$ac_symprfx"
else
lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
fi
lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
# Check to see that the pipe works correctly.
pipe_works=no
rm -f conftest*
cat > conftest.$ac_ext <<_LT_EOF
#ifdef __cplusplus
extern "C" {
#endif
char nm_test_var;
void nm_test_func(void);
void nm_test_func(void){}
#ifdef __cplusplus
}
#endif
int main(void){nm_test_var='a';nm_test_func();return(0);}
_LT_EOF
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
# Now try to grab the symbols.
nlist=conftest.nm
$ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5
if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then
# Try sorting and uniquifying the output.
if sort "$nlist" | uniq > "$nlist"T; then
mv -f "$nlist"T "$nlist"
else
rm -f "$nlist"T
fi
# Make sure that we snagged all the symbols we need.
if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
cat <<_LT_EOF > conftest.$ac_ext
/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
/* DATA imports from DLLs on WIN32 can't be const, because runtime
relocations are performed -- see ld's documentation on pseudo-relocs. */
# define LT_DLSYM_CONST
#elif defined __osf__
/* This system does not cope well with relocations in const data. */
# define LT_DLSYM_CONST
#else
# define LT_DLSYM_CONST const
#endif
#ifdef __cplusplus
extern "C" {
#endif
_LT_EOF
# Now generate the symbol file.
eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
cat <<_LT_EOF >> conftest.$ac_ext
/* The mapping between symbol names and symbols. */
LT_DLSYM_CONST struct {
const char *name;
void *address;
}
lt__PROGRAM__LTX_preloaded_symbols[] =
{
{ "@PROGRAM@", (void *) 0 },
_LT_EOF
$SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
cat <<\_LT_EOF >> conftest.$ac_ext
{0, (void *) 0}
};
/* This works around a problem in FreeBSD linker */
#ifdef FREEBSD_WORKAROUND
static const void *lt_preloaded_setup() {
return lt__PROGRAM__LTX_preloaded_symbols;
}
#endif
#ifdef __cplusplus
}
#endif
_LT_EOF
# Now try linking the two files.
mv conftest.$ac_objext conftstm.$ac_objext
lt_globsym_save_LIBS=$LIBS
lt_globsym_save_CFLAGS=$CFLAGS
LIBS=conftstm.$ac_objext
CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
(eval $ac_link) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && test -s conftest$ac_exeext; then
pipe_works=yes
fi
LIBS=$lt_globsym_save_LIBS
CFLAGS=$lt_globsym_save_CFLAGS
else
echo "cannot find nm_test_func in $nlist" >&5
fi
else
echo "cannot find nm_test_var in $nlist" >&5
fi
else
echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
fi
else
echo "$progname: failed program was:" >&5
cat conftest.$ac_ext >&5
fi
rm -rf conftest* conftst*
# Do not use the global_symbol_pipe unless it works.
if test yes = "$pipe_works"; then
break
else
lt_cv_sys_global_symbol_pipe=
fi
done
;;
esac
fi
if test -z "$lt_cv_sys_global_symbol_pipe"; then
lt_cv_sys_global_symbol_to_cdecl=
fi
if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5
printf "%s\n" "failed" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5
printf "%s\n" "ok" >&6; }
fi
# Response file support.
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
nm_file_list_spec='@'
elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
nm_file_list_spec='@'
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
printf %s "checking for sysroot... " >&6; }
# Check whether --with-sysroot was given.
if test ${with_sysroot+y}
then :
withval=$with_sysroot;
else case e in #(
e) with_sysroot=no ;;
esac
fi
lt_sysroot=
case $with_sysroot in #(
yes)
if test yes = "$GCC"; then
# Trim trailing / since we'll always append absolute paths and we want
# to avoid //, if only for less confusing output for the user.
lt_sysroot=`$CC --print-sysroot 2>/dev/null | $SED 's:/\+$::'`
fi
;; #(
/*)
lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
;; #(
no|'')
;; #(
*)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5
printf "%s\n" "$with_sysroot" >&6; }
as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
;;
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
printf "%s\n" "${lt_sysroot:-no}" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5
printf %s "checking for a working dd... " >&6; }
if test ${ac_cv_path_lt_DD+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) printf 0123456789abcdef0123456789abcdef >conftest.i
cat conftest.i conftest.i >conftest2.i
: ${lt_DD:=$DD}
if test -z "$lt_DD"; then
ac_path_lt_DD_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_prog in dd
do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_lt_DD="$as_dir$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_lt_DD" || continue
if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
cmp -s conftest.i conftest.out \
&& ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
fi
$ac_path_lt_DD_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_lt_DD"; then
:
fi
else
ac_cv_path_lt_DD=$lt_DD
fi
rm -f conftest.i conftest2.i conftest.out ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5
printf "%s\n" "$ac_cv_path_lt_DD" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5
printf %s "checking how to truncate binary pipes... " >&6; }
if test ${lt_cv_truncate_bin+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) printf 0123456789abcdef0123456789abcdef >conftest.i
cat conftest.i conftest.i >conftest2.i
lt_cv_truncate_bin=
if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
cmp -s conftest.i conftest.out \
&& lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
fi
rm -f conftest.i conftest2.i conftest.out
test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5
printf "%s\n" "$lt_cv_truncate_bin" >&6; }
# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
func_cc_basename ()
{
for cc_temp in $*""; do
case $cc_temp in
compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
\-*) ;;
*) break;;
esac
done
func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
}
# Check whether --enable-libtool-lock was given.
if test ${enable_libtool_lock+y}
then :
enableval=$enable_libtool_lock;
fi
test no = "$enable_libtool_lock" || enable_libtool_lock=yes
# Some flags need to be propagated to the compiler or linker for good
# libtool support.
case $host in
ia64-*-hpux*)
# Find out what ABI is being produced by ac_compile, and set mode
# options accordingly.
echo 'int i;' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
case `$FILECMD conftest.$ac_objext` in
*ELF-32*)
HPUX_IA64_MODE=32
;;
*ELF-64*)
HPUX_IA64_MODE=64
;;
esac
fi
rm -rf conftest*
;;
*-*-irix6*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly.
echo '#line '$LINENO' "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
if test yes = "$lt_cv_prog_gnu_ld"; then
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
LD="${LD-ld} -melf32bsmip"
;;
*N32*)
LD="${LD-ld} -melf32bmipn32"
;;
*64-bit*)
LD="${LD-ld} -melf64bmip"
;;
esac
else
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
LD="${LD-ld} -32"
;;
*N32*)
LD="${LD-ld} -n32"
;;
*64-bit*)
LD="${LD-ld} -64"
;;
esac
fi
fi
rm -rf conftest*
;;
mips64*-*linux*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly.
echo '#line '$LINENO' "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
emul=elf
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
emul="${emul}32"
;;
*64-bit*)
emul="${emul}64"
;;
esac
case `$FILECMD conftest.$ac_objext` in
*MSB*)
emul="${emul}btsmip"
;;
*LSB*)
emul="${emul}ltsmip"
;;
esac
case `$FILECMD conftest.$ac_objext` in
*N32*)
emul="${emul}n32"
;;
esac
LD="${LD-ld} -m $emul"
fi
rm -rf conftest*
;;
x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
s390*-*linux*|s390*-*tpf*|sparc*-*linux*|x86_64-gnu*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly. Note that the listed cases only cover the
# situations where additional linker options are needed (such as when
# doing 32-bit compilation for a host where ld defaults to 64-bit, or
# vice versa); the common cases where no linker options are needed do
# not appear in the list.
echo 'int i;' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
case `$FILECMD conftest.o` in
*32-bit*)
case $host in
x86_64-*kfreebsd*-gnu)
LD="${LD-ld} -m elf_i386_fbsd"
;;
x86_64-*linux*|x86_64-gnu*)
case `$FILECMD conftest.o` in
*x86-64*)
LD="${LD-ld} -m elf32_x86_64"
;;
*)
LD="${LD-ld} -m elf_i386"
;;
esac
;;
powerpc64le-*linux*)
LD="${LD-ld} -m elf32lppclinux"
;;
powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
LD="${LD-ld} -m elf_s390"
;;
sparc64-*linux*)
LD="${LD-ld} -m elf32_sparc"
;;
esac
;;
*64-bit*)
case $host in
x86_64-*kfreebsd*-gnu)
LD="${LD-ld} -m elf_x86_64_fbsd"
;;
x86_64-*linux*|x86_64-gnu*)
LD="${LD-ld} -m elf_x86_64"
;;
powerpcle-*linux*)
LD="${LD-ld} -m elf64lppc"
;;
powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
LD="${LD-ld} -m elf64_s390"
;;
sparc*-*linux*)
LD="${LD-ld} -m elf64_sparc"
;;
esac
;;
esac
fi
rm -rf conftest*
;;
*-*-sco3.2v5*)
# On SCO OpenServer 5, we need -belf to get full-featured binaries.
SAVE_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -belf"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
printf %s "checking whether the C compiler needs -belf... " >&6; }
if test ${lt_cv_cc_needs_belf+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
lt_cv_cc_needs_belf=yes
else case e in #(
e) lt_cv_cc_needs_belf=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
printf "%s\n" "$lt_cv_cc_needs_belf" >&6; }
if test yes != "$lt_cv_cc_needs_belf"; then
# this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
CFLAGS=$SAVE_CFLAGS
fi
;;
*-*solaris*)
# Find out what ABI is being produced by ac_compile, and set linker
# options accordingly.
echo 'int i;' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
case `$FILECMD conftest.o` in
*64-bit*)
case $lt_cv_prog_gnu_ld in
yes*)
case $host in
i?86-*-solaris*|x86_64-*-solaris*)
LD="${LD-ld} -m elf_x86_64"
;;
sparc*-*-solaris*)
LD="${LD-ld} -m elf64_sparc"
;;
esac
# GNU ld 2.21 introduced _sol2 emulations. Use them if available.
if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
LD=${LD-ld}_sol2
fi
;;
*)
if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
LD="${LD-ld} -64"
fi
;;
esac
;;
esac
fi
rm -rf conftest*
;;
esac
need_locks=$enable_libtool_lock
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
set dummy ${ac_tool_prefix}mt; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_MANIFEST_TOOL+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$MANIFEST_TOOL"; then
ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
if test -n "$MANIFEST_TOOL"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
printf "%s\n" "$MANIFEST_TOOL" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
# Extract the first word of "mt", so it can be a program name with args.
set dummy mt; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_MANIFEST_TOOL+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_MANIFEST_TOOL"; then
ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
if test -n "$ac_ct_MANIFEST_TOOL"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
printf "%s\n" "$ac_ct_MANIFEST_TOOL" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_MANIFEST_TOOL" = x; then
MANIFEST_TOOL=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
fi
else
MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
fi
test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
printf %s "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
if test ${lt_cv_path_manifest_tool+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_path_manifest_tool=no
echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
$MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
cat conftest.err >&5
if $GREP 'Manifest Tool' conftest.out > /dev/null; then
lt_cv_path_manifest_tool=yes
fi
rm -f conftest* ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_manifest_tool" >&5
printf "%s\n" "$lt_cv_path_manifest_tool" >&6; }
if test yes != "$lt_cv_path_manifest_tool"; then
MANIFEST_TOOL=:
fi
case $host_os in
rhapsody* | darwin*)
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_DSYMUTIL+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$DSYMUTIL"; then
ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
DSYMUTIL=$ac_cv_prog_DSYMUTIL
if test -n "$DSYMUTIL"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
printf "%s\n" "$DSYMUTIL" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_DSYMUTIL"; then
ac_ct_DSYMUTIL=$DSYMUTIL
# Extract the first word of "dsymutil", so it can be a program name with args.
set dummy dsymutil; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_DSYMUTIL+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_DSYMUTIL"; then
ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
if test -n "$ac_ct_DSYMUTIL"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
printf "%s\n" "$ac_ct_DSYMUTIL" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_DSYMUTIL" = x; then
DSYMUTIL=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
DSYMUTIL=$ac_ct_DSYMUTIL
fi
else
DSYMUTIL="$ac_cv_prog_DSYMUTIL"
fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
set dummy ${ac_tool_prefix}nmedit; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_NMEDIT+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$NMEDIT"; then
ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
NMEDIT=$ac_cv_prog_NMEDIT
if test -n "$NMEDIT"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
printf "%s\n" "$NMEDIT" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_NMEDIT"; then
ac_ct_NMEDIT=$NMEDIT
# Extract the first word of "nmedit", so it can be a program name with args.
set dummy nmedit; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_NMEDIT+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_NMEDIT"; then
ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_NMEDIT="nmedit"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
if test -n "$ac_ct_NMEDIT"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
printf "%s\n" "$ac_ct_NMEDIT" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_NMEDIT" = x; then
NMEDIT=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
NMEDIT=$ac_ct_NMEDIT
fi
else
NMEDIT="$ac_cv_prog_NMEDIT"
fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
set dummy ${ac_tool_prefix}lipo; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_LIPO+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$LIPO"; then
ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
LIPO=$ac_cv_prog_LIPO
if test -n "$LIPO"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
printf "%s\n" "$LIPO" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_LIPO"; then
ac_ct_LIPO=$LIPO
# Extract the first word of "lipo", so it can be a program name with args.
set dummy lipo; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_LIPO+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_LIPO"; then
ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_LIPO="lipo"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
if test -n "$ac_ct_LIPO"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
printf "%s\n" "$ac_ct_LIPO" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_LIPO" = x; then
LIPO=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
LIPO=$ac_ct_LIPO
fi
else
LIPO="$ac_cv_prog_LIPO"
fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
set dummy ${ac_tool_prefix}otool; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_OTOOL+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$OTOOL"; then
ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
OTOOL=$ac_cv_prog_OTOOL
if test -n "$OTOOL"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
printf "%s\n" "$OTOOL" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_OTOOL"; then
ac_ct_OTOOL=$OTOOL
# Extract the first word of "otool", so it can be a program name with args.
set dummy otool; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_OTOOL+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_OTOOL"; then
ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_OTOOL="otool"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
if test -n "$ac_ct_OTOOL"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
printf "%s\n" "$ac_ct_OTOOL" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_OTOOL" = x; then
OTOOL=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
OTOOL=$ac_ct_OTOOL
fi
else
OTOOL="$ac_cv_prog_OTOOL"
fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
set dummy ${ac_tool_prefix}otool64; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_OTOOL64+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$OTOOL64"; then
ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
OTOOL64=$ac_cv_prog_OTOOL64
if test -n "$OTOOL64"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
printf "%s\n" "$OTOOL64" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_OTOOL64"; then
ac_ct_OTOOL64=$OTOOL64
# Extract the first word of "otool64", so it can be a program name with args.
set dummy otool64; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_OTOOL64+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_OTOOL64"; then
ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_OTOOL64="otool64"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
if test -n "$ac_ct_OTOOL64"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
printf "%s\n" "$ac_ct_OTOOL64" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_OTOOL64" = x; then
OTOOL64=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
OTOOL64=$ac_ct_OTOOL64
fi
else
OTOOL64="$ac_cv_prog_OTOOL64"
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
printf %s "checking for -single_module linker flag... " >&6; }
if test ${lt_cv_apple_cc_single_mod+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_apple_cc_single_mod=no
if test -z "$LT_MULTI_MODULE"; then
# By default we will add the -single_module flag. You can override
# by either setting the environment variable LT_MULTI_MODULE
# non-empty at configure time, or by adding -multi_module to the
# link flags.
rm -rf libconftest.dylib*
echo "int foo(void){return 1;}" > conftest.c
echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
-dynamiclib -Wl,-single_module conftest.c" >&5
$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
-dynamiclib -Wl,-single_module conftest.c 2>conftest.err
_lt_result=$?
# If there is a non-empty error log, and "single_module"
# appears in it, assume the flag caused a linker warning
if test -s conftest.err && $GREP single_module conftest.err; then
cat conftest.err >&5
# Otherwise, if the output was created with a 0 exit code from
# the compiler, it worked.
elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
lt_cv_apple_cc_single_mod=yes
else
cat conftest.err >&5
fi
rm -rf libconftest.dylib*
rm -f conftest.*
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
printf "%s\n" "$lt_cv_apple_cc_single_mod" >&6; }
# Feature test to disable chained fixups since it is not
# compatible with '-undefined dynamic_lookup'
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -no_fixup_chains linker flag" >&5
printf %s "checking for -no_fixup_chains linker flag... " >&6; }
if test ${lt_cv_support_no_fixup_chains+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -Wl,-no_fixup_chains"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
lt_cv_support_no_fixup_chains=yes
else case e in #(
e) lt_cv_support_no_fixup_chains=no
;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LDFLAGS=$save_LDFLAGS
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_support_no_fixup_chains" >&5
printf "%s\n" "$lt_cv_support_no_fixup_chains" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
printf %s "checking for -exported_symbols_list linker flag... " >&6; }
if test ${lt_cv_ld_exported_symbols_list+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_ld_exported_symbols_list=no
save_LDFLAGS=$LDFLAGS
echo "_main" > conftest.sym
LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
lt_cv_ld_exported_symbols_list=yes
else case e in #(
e) lt_cv_ld_exported_symbols_list=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LDFLAGS=$save_LDFLAGS
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
printf "%s\n" "$lt_cv_ld_exported_symbols_list" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
printf %s "checking for -force_load linker flag... " >&6; }
if test ${lt_cv_ld_force_load+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_ld_force_load=no
cat > conftest.c << _LT_EOF
int forced_loaded() { return 2;}
_LT_EOF
echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
$LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5
$AR $AR_FLAGS libconftest.a conftest.o 2>&5
echo "$RANLIB libconftest.a" >&5
$RANLIB libconftest.a 2>&5
cat > conftest.c << _LT_EOF
int main(void) { return 0;}
_LT_EOF
echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
_lt_result=$?
if test -s conftest.err && $GREP force_load conftest.err; then
cat conftest.err >&5
elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
lt_cv_ld_force_load=yes
else
cat conftest.err >&5
fi
rm -f conftest.err libconftest.a conftest conftest.c
rm -rf conftest.dSYM
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
printf "%s\n" "$lt_cv_ld_force_load" >&6; }
case $host_os in
rhapsody* | darwin1.[012])
_lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
darwin1.*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
darwin*)
case $MACOSX_DEPLOYMENT_TARGET,$host in
10.[012],*|,*powerpc*-darwin[5-8]*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup'
if test yes = "$lt_cv_support_no_fixup_chains"; then
as_fn_append _lt_dar_allow_undefined ' $wl-no_fixup_chains'
fi
;;
esac
;;
esac
if test yes = "$lt_cv_apple_cc_single_mod"; then
_lt_dar_single_mod='$single_module'
fi
_lt_dar_needs_single_mod=no
case $host_os in
rhapsody* | darwin1.*)
_lt_dar_needs_single_mod=yes ;;
darwin*)
# When targeting Mac OS X 10.4 (darwin 8) or later,
# -single_module is the default and -multi_module is unsupported.
# The toolchain on macOS 10.14 (darwin 18) and later cannot
# target any OS version that needs -single_module.
case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
10.0,*-darwin[567].*|10.[0-3],*-darwin[5-9].*|10.[0-3],*-darwin1[0-7].*)
_lt_dar_needs_single_mod=yes ;;
esac
;;
esac
if test yes = "$lt_cv_ld_exported_symbols_list"; then
_lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
else
_lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
fi
if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
_lt_dsymutil='~$DSYMUTIL $lib || :'
else
_lt_dsymutil=
fi
;;
esac
# func_munge_path_list VARIABLE PATH
# -----------------------------------
# VARIABLE is name of variable containing _space_ separated list of
# directories to be munged by the contents of PATH, which is string
# having a format:
# "DIR[:DIR]:"
# string "DIR[ DIR]" will be prepended to VARIABLE
# ":DIR[:DIR]"
# string "DIR[ DIR]" will be appended to VARIABLE
# "DIRP[:DIRP]::[DIRA:]DIRA"
# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
# "DIRA[ DIRA]" will be appended to VARIABLE
# "DIR[:DIR]"
# VARIABLE will be replaced by "DIR[ DIR]"
func_munge_path_list ()
{
case x$2 in
x)
;;
*:)
eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
;;
x:*)
eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
;;
*::*)
eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
;;
*)
eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
;;
esac
}
ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
"
if test "x$ac_cv_header_dlfcn_h" = xyes
then :
printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h
fi
# Set options
enable_dlopen=no
enable_win32_dll=no
# Check whether --enable-shared was given.
if test ${enable_shared+y}
then :
enableval=$enable_shared; p=${PACKAGE-default}
case $enableval in
yes) enable_shared=yes ;;
no) enable_shared=no ;;
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS=$lt_save_ifs
;;
esac
else case e in #(
e) enable_shared=yes ;;
esac
fi
# Check whether --enable-static was given.
if test ${enable_static+y}
then :
enableval=$enable_static; p=${PACKAGE-default}
case $enableval in
yes) enable_static=yes ;;
no) enable_static=no ;;
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS=$lt_save_ifs
;;
esac
else case e in #(
e) enable_static=yes ;;
esac
fi
# Check whether --enable-pic was given.
if test ${enable_pic+y}
then :
enableval=$enable_pic; lt_p=${PACKAGE-default}
case $enableval in
yes|no) pic_mode=$enableval ;;
*)
pic_mode=default
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for lt_pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$lt_pkg" = "X$lt_p"; then
pic_mode=yes
fi
done
IFS=$lt_save_ifs
;;
esac
else case e in #(
e) # Check whether --with-pic was given.
if test ${with_pic+y}
then :
withval=$with_pic; lt_p=${PACKAGE-default}
case $withval in
yes|no) pic_mode=$withval ;;
*)
pic_mode=default
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for lt_pkg in $withval; do
IFS=$lt_save_ifs
if test "X$lt_pkg" = "X$lt_p"; then
pic_mode=yes
fi
done
IFS=$lt_save_ifs
;;
esac
else case e in #(
e) pic_mode=default ;;
esac
fi
;;
esac
fi
stdlibflag=-nostdlib
# Check whether --enable-cxx-stdlib was given.
if test ${enable_cxx_stdlib+y}
then :
enableval=$enable_cxx_stdlib; p=${PACKAGE-default}
case $enableval in
yes) enable_cxx_stdlib=yes ;;
no) enable_cxx_stdlib=no ;;
*)
enable_cxx_stdlib=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_cxx_stdlib=yes
fi
done
IFS=$lt_save_ifs
;;
esac
else case e in #(
e) enable_cxx_stdlib=no ;;
esac
fi
if test yes = "$enable_cxx_stdlib"; then
stdlibflag=
fi
# Check whether --enable-fast-install was given.
if test ${enable_fast_install+y}
then :
enableval=$enable_fast_install; p=${PACKAGE-default}
case $enableval in
yes) enable_fast_install=yes ;;
no) enable_fast_install=no ;;
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS=$lt_save_ifs
;;
esac
else case e in #(
e) enable_fast_install=yes ;;
esac
fi
shared_archive_member_spec=
case $host,$enable_shared in
power*-*-aix[5-9]*,yes)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
printf %s "checking which variant of shared library versioning to provide... " >&6; }
# Check whether --enable-aix-soname was given.
if test ${enable_aix_soname+y}
then :
enableval=$enable_aix_soname; case $enableval in
aix|svr4|both)
;;
*)
as_fn_error $? "Unknown argument to --enable-aix-soname" "$LINENO" 5
;;
esac
lt_cv_with_aix_soname=$enable_aix_soname
else case e in #(
e) # Check whether --with-aix-soname was given.
if test ${with_aix_soname+y}
then :
withval=$with_aix_soname; case $withval in
aix|svr4|both)
;;
*)
as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5
;;
esac
lt_cv_with_aix_soname=$with_aix_soname
else case e in #(
e) if test ${lt_cv_with_aix_soname+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_with_aix_soname=aix ;;
esac
fi
;;
esac
fi
enable_aix_soname=$lt_cv_with_aix_soname ;;
esac
fi
with_aix_soname=$enable_aix_soname
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5
printf "%s\n" "$with_aix_soname" >&6; }
if test aix != "$with_aix_soname"; then
# For the AIX way of multilib, we name the shared archive member
# based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
# and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
# Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
# the AIX toolchain works better with OBJECT_MODE set (default 32).
if test 64 = "${OBJECT_MODE-32}"; then
shared_archive_member_spec=shr_64
else
shared_archive_member_spec=shr
fi
fi
;;
power*-*-aix[5-9]*,'')
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: for $host, specify if building shared libraries for versioning (svr4|both)" >&5
printf "%s\n" "$as_me: WARNING: for $host, specify if building shared libraries for versioning (svr4|both)" >&2;}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
printf %s "checking which variant of shared library versioning to provide... " >&6; }
with_aix_soname=aix
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: (default) $with_aix_soname" >&5
printf "%s\n" "(default) $with_aix_soname" >&6; }
;;
*)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
printf %s "checking which variant of shared library versioning to provide... " >&6; }
with_aix_soname=aix
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: (default) $with_aix_soname" >&5
printf "%s\n" "(default) $with_aix_soname" >&6; }
;;
esac
# This can be used to rebuild libtool when needed
LIBTOOL_DEPS=$ltmain
# Always use our own libtool.
LIBTOOL='$(SHELL) $(top_builddir)/libtool'
test -z "$LN_S" && LN_S="ln -s"
if test -n "${ZSH_VERSION+set}"; then
setopt NO_GLOB_SUBST
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
printf %s "checking for objdir... " >&6; }
if test ${lt_cv_objdir+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) rm -f .libs 2>/dev/null
mkdir .libs 2>/dev/null
if test -d .libs; then
lt_cv_objdir=.libs
else
# MS-DOS does not allow filenames that begin with a dot.
lt_cv_objdir=_libs
fi
rmdir .libs 2>/dev/null ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
printf "%s\n" "$lt_cv_objdir" >&6; }
objdir=$lt_cv_objdir
printf "%s\n" "#define LT_OBJDIR \"$lt_cv_objdir/\"" >>confdefs.h
case $host_os in
aix3*)
# AIX sometimes has problems with the GCC collect2 program. For some
# reason, if we set the COLLECT_NAMES environment variable, the problems
# vanish in a puff of smoke.
if test set != "${COLLECT_NAMES+set}"; then
COLLECT_NAMES=
export COLLECT_NAMES
fi
;;
esac
# Global variables:
ofile=libtool
can_build_shared=yes
# All known linkers require a '.a' archive for static linking (except MSVC and
# ICC, which need '.lib').
libext=a
with_gnu_ld=$lt_cv_prog_gnu_ld
old_CC=$CC
old_CFLAGS=$CFLAGS
# Set sane defaults for various variables
test -z "$CC" && CC=cc
test -z "$LTCC" && LTCC=$CC
test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
test -z "$LD" && LD=ld
test -z "$ac_objext" && ac_objext=o
func_cc_basename $compiler
cc_basename=$func_cc_basename_result
# Only perform the check for file, if the check method requires it
test -z "$MAGIC_CMD" && MAGIC_CMD=file
case $deplibs_check_method in
file_magic*)
if test "$file_magic_cmd" = '$MAGIC_CMD'; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
printf %s "checking for ${ac_tool_prefix}file... " >&6; }
if test ${lt_cv_path_MAGIC_CMD+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) case $MAGIC_CMD in
[\\/*] | ?:[\\/]*)
lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
;;
*)
lt_save_MAGIC_CMD=$MAGIC_CMD
lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
for ac_dir in $ac_dummy; do
IFS=$lt_save_ifs
test -z "$ac_dir" && ac_dir=.
if test -f "$ac_dir/${ac_tool_prefix}file"; then
lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file"
if test -n "$file_magic_test_file"; then
case $deplibs_check_method in
"file_magic "*)
file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
MAGIC_CMD=$lt_cv_path_MAGIC_CMD
if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
$EGREP "$file_magic_regex" > /dev/null; then
:
else
cat <<_LT_EOF 1>&2
*** Warning: the command libtool uses to detect shared libraries,
*** $file_magic_cmd, produces output that libtool cannot recognize.
*** The result is that libtool may fail to recognize shared libraries
*** as such. This will affect the creation of libtool libraries that
*** depend on shared libraries, but programs linked with such libtool
*** libraries will work regardless of this problem. Nevertheless, you
*** may want to report the problem to your system manager and/or to
*** bug-libtool@gnu.org
_LT_EOF
fi ;;
esac
fi
break
fi
done
IFS=$lt_save_ifs
MAGIC_CMD=$lt_save_MAGIC_CMD
;;
esac ;;
esac
fi
MAGIC_CMD=$lt_cv_path_MAGIC_CMD
if test -n "$MAGIC_CMD"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
printf "%s\n" "$MAGIC_CMD" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test -z "$lt_cv_path_MAGIC_CMD"; then
if test -n "$ac_tool_prefix"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for file" >&5
printf %s "checking for file... " >&6; }
if test ${lt_cv_path_MAGIC_CMD+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) case $MAGIC_CMD in
[\\/*] | ?:[\\/]*)
lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
;;
*)
lt_save_MAGIC_CMD=$MAGIC_CMD
lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
for ac_dir in $ac_dummy; do
IFS=$lt_save_ifs
test -z "$ac_dir" && ac_dir=.
if test -f "$ac_dir/file"; then
lt_cv_path_MAGIC_CMD=$ac_dir/"file"
if test -n "$file_magic_test_file"; then
case $deplibs_check_method in
"file_magic "*)
file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
MAGIC_CMD=$lt_cv_path_MAGIC_CMD
if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
$EGREP "$file_magic_regex" > /dev/null; then
:
else
cat <<_LT_EOF 1>&2
*** Warning: the command libtool uses to detect shared libraries,
*** $file_magic_cmd, produces output that libtool cannot recognize.
*** The result is that libtool may fail to recognize shared libraries
*** as such. This will affect the creation of libtool libraries that
*** depend on shared libraries, but programs linked with such libtool
*** libraries will work regardless of this problem. Nevertheless, you
*** may want to report the problem to your system manager and/or to
*** bug-libtool@gnu.org
_LT_EOF
fi ;;
esac
fi
break
fi
done
IFS=$lt_save_ifs
MAGIC_CMD=$lt_save_MAGIC_CMD
;;
esac ;;
esac
fi
MAGIC_CMD=$lt_cv_path_MAGIC_CMD
if test -n "$MAGIC_CMD"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
printf "%s\n" "$MAGIC_CMD" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
else
MAGIC_CMD=:
fi
fi
fi
;;
esac
# Use C for the default configuration in the libtool script
lt_save_CC=$CC
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
# Source file extension for C test sources.
ac_ext=c
# Object file extension for compiled C test sources.
objext=o
objext=$objext
# Code to be used in simple compile tests
lt_simple_compile_test_code="int some_variable = 0;"
# Code to be used in simple link tests
lt_simple_link_test_code='int main(void){return(0);}'
# If no C compiler was specified, use CC.
LTCC=${LTCC-"$CC"}
# If no C compiler flags were specified, use CFLAGS.
LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
# Allow CC to be a program name with arguments.
compiler=$CC
# Save the default compiler, since it gets overwritten when the other
# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
compiler_DEFAULT=$CC
# save warnings/boilerplate of simple test code
ac_outfile=conftest.$ac_objext
echo "$lt_simple_compile_test_code" >conftest.$ac_ext
eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
_lt_compiler_boilerplate=`cat conftest.err`
$RM conftest*
ac_outfile=conftest.$ac_objext
echo "$lt_simple_link_test_code" >conftest.$ac_ext
eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
_lt_linker_boilerplate=`cat conftest.err`
$RM -r conftest*
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then
lt_prog_compiler_no_builtin_flag=
if test yes = "$GCC"; then
case $cc_basename in
nvcc*)
lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
*)
lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
printf %s "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
if test ${lt_cv_prog_compiler_rtti_exceptions+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_prog_compiler_rtti_exceptions=no
ac_outfile=conftest.$ac_objext
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment
# Insert the option either (1) after the last *FLAGS variable, or
# (2) before a word containing "conftest.", or (3) at the end.
# Note that $ac_compile itself does not contain backslashes and begins
# with a dollar sign (not a hyphen), so the echo should work correctly.
# The option is referenced via a variable to avoid confusing sed.
lt_compile=`echo "$ac_compile" | $SED \
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
$ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.expsym
$SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
if test ! -s conftest.er2 || diff conftest.expsym conftest.er2 >/dev/null; then
lt_cv_prog_compiler_rtti_exceptions=yes
fi
fi
$RM conftest*
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
printf "%s\n" "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then
lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
else
:
fi
fi
lt_prog_compiler_wl=
lt_prog_compiler_pic=
lt_prog_compiler_static=
if test yes = "$GCC"; then
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_static='-static'
case $host_os in
aix*)
# All AIX code is PIC.
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
lt_prog_compiler_static='-Bstatic'
fi
lt_prog_compiler_pic='-fPIC'
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
lt_prog_compiler_pic='-fPIC'
;;
m68k)
# FIXME: we need at least 68020 code to build shared libraries, but
# adding the '-m68020' flag to GCC prevents building anything better,
# like '-m68040'.
lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
;;
esac
;;
beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
# PIC is the default for these OSes.
;;
mingw* | windows* | cygwin* | pw32* | os2* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
# Although the cygwin gcc ignores -fPIC, still need this for old-style
# (--disable-auto-import) libraries
lt_prog_compiler_pic='-DDLL_EXPORT'
case $host_os in
os2*)
lt_prog_compiler_static='$wl-static'
;;
esac
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
lt_prog_compiler_pic='-fno-common'
;;
haiku*)
# PIC is the default for Haiku.
# The "-static" flag exists, but is broken.
lt_prog_compiler_static=
;;
hpux*)
# PIC is the default for 64-bit PA HP-UX, but not for 32-bit
# PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
# sets the default TLS model and affects inlining.
case $host_cpu in
hppa*64*)
# +Z the default
;;
*)
lt_prog_compiler_pic='-fPIC'
;;
esac
;;
interix[3-9]*)
# Interix 3.x gcc -fpic/-fPIC options generate broken code.
# Instead, we relocate shared libraries at runtime.
;;
msdosdjgpp*)
# Just because we use GCC doesn't mean we suddenly get shared libraries
# on systems that don't support them.
lt_prog_compiler_can_build_shared=no
enable_shared=no
;;
*nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
lt_prog_compiler_pic='-fPIC -shared'
;;
sysv4*MP*)
if test -d /usr/nec; then
lt_prog_compiler_pic=-Kconform_pic
fi
;;
*)
lt_prog_compiler_pic='-fPIC'
;;
esac
case $cc_basename in
nvcc*) # Cuda Compiler Driver 2.2
lt_prog_compiler_wl='-Xlinker '
if test -n "$lt_prog_compiler_pic"; then
lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
fi
;;
esac
else
# PORTME Check for flag to pass linker flags through the system compiler.
case $host_os in
aix*)
lt_prog_compiler_wl='-Wl,'
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
lt_prog_compiler_static='-Bstatic'
else
lt_prog_compiler_static='-bnso -bI:/lib/syscalls.expsym'
fi
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
lt_prog_compiler_pic='-fno-common'
case $cc_basename in
nagfor*)
# NAG Fortran compiler
lt_prog_compiler_wl='-Wl,-Wl,,'
lt_prog_compiler_pic='-PIC'
lt_prog_compiler_static='-Bstatic'
;;
esac
;;
mingw* | windows* | cygwin* | pw32* | os2* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
lt_prog_compiler_pic='-DDLL_EXPORT'
case $host_os in
os2*)
lt_prog_compiler_static='$wl-static'
;;
esac
;;
hpux9* | hpux10* | hpux11*)
lt_prog_compiler_wl='-Wl,'
# PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
# not for PA HP-UX.
case $host_cpu in
hppa*64*|ia64*)
# +Z the default
;;
*)
lt_prog_compiler_pic='+Z'
;;
esac
# Is there a better lt_prog_compiler_static that works with the bundled CC?
lt_prog_compiler_static='$wl-a ${wl}archive'
;;
irix5* | irix6* | nonstopux*)
lt_prog_compiler_wl='-Wl,'
# PIC (with -KPIC) is the default.
lt_prog_compiler_static='-non_shared'
;;
*-mlibc)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fPIC'
lt_prog_compiler_static='-static'
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu* | freebsd*)
case $cc_basename in
# old Intel for x86_64, which still supported -KPIC.
ecc*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-static'
;;
*flang* | ftn | f18* | f95*)
# Flang compiler.
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fPIC'
lt_prog_compiler_static='-static'
;;
# icc used to be incompatible with GCC.
# ICC 10 doesn't accept -KPIC any more.
icc* | ifort* | icx* | ifx*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fPIC'
lt_prog_compiler_static='-static'
;;
# Lahey Fortran 8.1.
lf95*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='--shared'
lt_prog_compiler_static='--static'
;;
nagfor*)
# NAG Fortran compiler
lt_prog_compiler_wl='-Wl,-Wl,,'
lt_prog_compiler_pic='-PIC'
lt_prog_compiler_static='-Bstatic'
;;
tcc*)
# Fabrice Bellard et al's Tiny C Compiler
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fPIC'
lt_prog_compiler_static='-static'
;;
pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
# Portland Group compilers (*not* the Pentium gcc compiler,
# which looks to be a dead project)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fpic'
lt_prog_compiler_static='-Bstatic'
;;
ccc*)
lt_prog_compiler_wl='-Wl,'
# All Alpha code is PIC.
lt_prog_compiler_static='-non_shared'
;;
xl* | bgxl* | bgf* | mpixl*)
# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-qpic'
lt_prog_compiler_static='-qstaticlink'
;;
*)
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
# Sun Fortran 8.3 passes all unrecognized flags to the linker
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
lt_prog_compiler_wl=''
;;
*Sun\ F* | *Sun*Fortran*)
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
lt_prog_compiler_wl='-Qoption ld '
;;
*Sun\ C*)
# Sun C 5.9
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
lt_prog_compiler_wl='-Wl,'
;;
*Intel*\ [CF]*Compiler*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fPIC'
lt_prog_compiler_static='-static'
;;
*Portland\ Group*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fpic'
lt_prog_compiler_static='-Bstatic'
;;
esac
;;
esac
;;
newsos6)
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
;;
*nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
lt_prog_compiler_pic='-fPIC -shared'
;;
osf3* | osf4* | osf5*)
lt_prog_compiler_wl='-Wl,'
# All OSF/1 code is PIC.
lt_prog_compiler_static='-non_shared'
;;
rdos*)
lt_prog_compiler_static='-non_shared'
;;
serenity*)
;;
solaris*)
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
case $cc_basename in
f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
lt_prog_compiler_wl='-Qoption ld ';;
*)
lt_prog_compiler_wl='-Wl,';;
esac
;;
sunos4*)
lt_prog_compiler_wl='-Qoption ld '
lt_prog_compiler_pic='-PIC'
lt_prog_compiler_static='-Bstatic'
;;
sysv4 | sysv4.2uw2* | sysv4.3*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
;;
sysv4*MP*)
if test -d /usr/nec; then
lt_prog_compiler_pic='-Kconform_pic'
lt_prog_compiler_static='-Bstatic'
fi
;;
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
;;
unicos*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_can_build_shared=no
;;
uts4*)
lt_prog_compiler_pic='-pic'
lt_prog_compiler_static='-Bstatic'
;;
*)
lt_prog_compiler_can_build_shared=no
;;
esac
fi
case $host_os in
# For platforms that do not support PIC, -DPIC is meaningless:
*djgpp*)
lt_prog_compiler_pic=
;;
*)
lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
;;
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
printf %s "checking for $compiler option to produce PIC... " >&6; }
if test ${lt_cv_prog_compiler_pic+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_prog_compiler_pic=$lt_prog_compiler_pic ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
printf "%s\n" "$lt_cv_prog_compiler_pic" >&6; }
lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
#
# Check to make sure the PIC flag actually works.
#
if test -n "$lt_prog_compiler_pic"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
if test ${lt_cv_prog_compiler_pic_works+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_prog_compiler_pic_works=no
ac_outfile=conftest.$ac_objext
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment
# Insert the option either (1) after the last *FLAGS variable, or
# (2) before a word containing "conftest.", or (3) at the end.
# Note that $ac_compile itself does not contain backslashes and begins
# with a dollar sign (not a hyphen), so the echo should work correctly.
# The option is referenced via a variable to avoid confusing sed.
lt_compile=`echo "$ac_compile" | $SED \
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
$ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.expsym
$SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
if test ! -s conftest.er2 || diff conftest.expsym conftest.er2 >/dev/null; then
lt_cv_prog_compiler_pic_works=yes
fi
fi
$RM conftest*
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
printf "%s\n" "$lt_cv_prog_compiler_pic_works" >&6; }
if test yes = "$lt_cv_prog_compiler_pic_works"; then
case $lt_prog_compiler_pic in
"" | " "*) ;;
*) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
esac
else
lt_prog_compiler_pic=
lt_prog_compiler_can_build_shared=no
fi
fi
#
# Check to make sure the static flag actually works.
#
wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
if test ${lt_cv_prog_compiler_static_works+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_prog_compiler_static_works=no
save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
echo "$lt_simple_link_test_code" > conftest.$ac_ext
if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
# The linker can only warn and ignore the option if not recognized
# So say no if there are warnings
if test -s conftest.err; then
# Append any errors to the config.log.
cat conftest.err 1>&5
$ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.expsym
$SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
if diff conftest.expsym conftest.er2 >/dev/null; then
lt_cv_prog_compiler_static_works=yes
fi
else
lt_cv_prog_compiler_static_works=yes
fi
fi
$RM -r conftest*
LDFLAGS=$save_LDFLAGS
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
printf "%s\n" "$lt_cv_prog_compiler_static_works" >&6; }
if test yes = "$lt_cv_prog_compiler_static_works"; then
:
else
lt_prog_compiler_static=
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
if test ${lt_cv_prog_compiler_c_o+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_prog_compiler_c_o=no
$RM -r conftest 2>/dev/null
mkdir conftest
cd conftest
mkdir out
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
lt_compiler_flag="-o out/conftest2.$ac_objext"
# Insert the option either (1) after the last *FLAGS variable, or
# (2) before a word containing "conftest.", or (3) at the end.
# Note that $ac_compile itself does not contain backslashes and begins
# with a dollar sign (not a hyphen), so the echo should work correctly.
lt_compile=`echo "$ac_compile" | $SED \
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
$ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.expsym
$SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
if test ! -s out/conftest.er2 || diff out/conftest.expsym out/conftest.er2 >/dev/null; then
lt_cv_prog_compiler_c_o=yes
fi
fi
chmod u+w . 2>&5
$RM conftest*
# SGI C++ compiler will create directory out/ii_files/ for
# template instantiation
test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
$RM out/* && rmdir out
cd ..
$RM -r conftest
$RM conftest*
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
if test ${lt_cv_prog_compiler_c_o+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_prog_compiler_c_o=no
$RM -r conftest 2>/dev/null
mkdir conftest
cd conftest
mkdir out
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
lt_compiler_flag="-o out/conftest2.$ac_objext"
# Insert the option either (1) after the last *FLAGS variable, or
# (2) before a word containing "conftest.", or (3) at the end.
# Note that $ac_compile itself does not contain backslashes and begins
# with a dollar sign (not a hyphen), so the echo should work correctly.
lt_compile=`echo "$ac_compile" | $SED \
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
$ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.expsym
$SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
if test ! -s out/conftest.er2 || diff out/conftest.expsym out/conftest.er2 >/dev/null; then
lt_cv_prog_compiler_c_o=yes
fi
fi
chmod u+w . 2>&5
$RM conftest*
# SGI C++ compiler will create directory out/ii_files/ for
# template instantiation
test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
$RM out/* && rmdir out
cd ..
$RM -r conftest
$RM conftest*
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
hard_links=nottested
if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then
# do not overwrite the value of need_locks provided by the user
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
printf %s "checking if we can lock with hard links... " >&6; }
hard_links=yes
$RM conftest*
ln conftest.a conftest.b 2>/dev/null && hard_links=no
touch conftest.a
ln conftest.a conftest.b 2>&5 || hard_links=no
ln conftest.a conftest.b 2>/dev/null && hard_links=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
printf "%s\n" "$hard_links" >&6; }
if test no = "$hard_links"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
need_locks=warn
fi
else
need_locks=no
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
runpath_var=
allow_undefined_flag=
always_export_symbols=no
archive_cmds=
archive_expsym_cmds=
compiler_needs_object=no
enable_shared_with_static_runtimes=no
export_dynamic_flag_spec=
export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
hardcode_automatic=no
hardcode_direct=no
hardcode_direct_absolute=no
hardcode_libdir_flag_spec=
hardcode_libdir_separator=
hardcode_minus_L=no
hardcode_shlibpath_var=unsupported
inherit_rpath=no
link_all_deplibs=unknown
module_cmds=
module_expsym_cmds=
old_archive_from_new_cmds=
old_archive_from_expsyms_cmds=
thread_safe_flag_spec=
whole_archive_flag_spec=
# include_expsyms should be a list of space-separated symbols to be *always*
# included in the symbol list
include_expsyms=
# exclude_expsyms can be an extended regexp of symbols to exclude
# it will be wrapped by ' (' and ')$', so one must not match beginning or
# end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
# as well as any symbol that contains 'd'.
exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
# platforms (ab)use it in PIC code, but their linkers get confused if
# the symbol is explicitly referenced. Since portable code cannot
# rely on this symbol name, it's probably fine to never include it in
# preloaded symbol tables.
# Exclude shared library initialization/finalization symbols.
extract_expsyms_cmds=
case $host_os in
cygwin* | mingw* | windows* | pw32* | cegcc*)
# FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++ or Intel C++ Compiler.
if test yes != "$GCC"; then
with_gnu_ld=no
fi
;;
interix*)
# we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
with_gnu_ld=yes
;;
esac
ld_shlibs=yes
# On some targets, GNU ld is compatible enough with the native linker
# that we're better off using the native interface for both.
lt_use_gnu_ld_interface=no
if test yes = "$with_gnu_ld"; then
case $host_os in
aix*)
# The AIX port of GNU ld has always aspired to compatibility
# with the native linker. However, as the warning in the GNU ld
# block says, versions before 2.19.5* couldn't really create working
# shared libraries, regardless of the interface used.
case `$LD -v 2>&1` in
*\ \(GNU\ Binutils\)\ 2.19.5*) ;;
*\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
*\ \(GNU\ Binutils\)\ [3-9]*) ;;
*)
lt_use_gnu_ld_interface=yes
;;
esac
;;
*)
lt_use_gnu_ld_interface=yes
;;
esac
fi
if test yes = "$lt_use_gnu_ld_interface"; then
# If archive_cmds runs LD, not CC, wlarc should be empty
wlarc='$wl'
# Set some defaults for GNU ld with shared library support. These
# are reset later if shared libraries are not supported. Putting them
# here allows them to be overridden if necessary.
runpath_var=LD_RUN_PATH
hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
export_dynamic_flag_spec='$wl--export-dynamic'
# ancient GNU ld didn't support --whole-archive et. al.
if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
else
whole_archive_flag_spec=
fi
supports_anon_versioning=no
case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
*GNU\ gold*) supports_anon_versioning=yes ;;
*\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
*\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
*\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
*\ 2.11.*) ;; # other 2.11 versions
*) supports_anon_versioning=yes ;;
esac
# See if GNU ld supports shared libraries.
case $host_os in
aix[3-9]*)
# On AIX/PPC, the GNU linker is very broken
if test ia64 != "$host_cpu"; then
ld_shlibs=no
cat <<_LT_EOF 1>&2
*** Warning: the GNU linker, at least up to release 2.19, is reported
*** to be unable to reliably create shared libraries on AIX.
*** Therefore, libtool is disabling shared libraries support. If you
*** really care for shared libraries, you may want to install binutils
*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
*** You will then need to restart the configuration process.
_LT_EOF
fi
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
archive_expsym_cmds=''
;;
m68k)
archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
;;
esac
;;
beos*)
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
allow_undefined_flag=unsupported
# Joseph Beckenbach says some releases of gcc
# support --undefined. This deserves some investigation. FIXME
archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
else
ld_shlibs=no
fi
;;
cygwin* | mingw* | windows* | pw32* | cegcc*)
# _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
# as there is no search path for DLLs.
hardcode_libdir_flag_spec='-L$libdir'
export_dynamic_flag_spec='$wl--export-all-symbols'
allow_undefined_flag=unsupported
always_export_symbols=no
enable_shared_with_static_runtimes=yes
export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
file_list_spec='@'
if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
# If the export-symbols file already is a .def file, use it as
# is; otherwise, prepend EXPORTS...
archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then
cp $export_symbols $output_objdir/$soname.def;
else
echo EXPORTS > $output_objdir/$soname.def;
cat $export_symbols >> $output_objdir/$soname.def;
fi~
$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
else
ld_shlibs=no
fi
;;
haiku*)
archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
link_all_deplibs=no
;;
os2*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
allow_undefined_flag=unsupported
shrext_cmds=.dll
archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
prefix_cmds="$SED"~
if test EXPORTS = "`$SED 1q $export_symbols`"; then
prefix_cmds="$prefix_cmds -e 1d";
fi~
prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
old_archive_from_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
enable_shared_with_static_runtimes=yes
file_list_spec='@'
;;
interix[3-9]*)
hardcode_direct=no
hardcode_shlibpath_var=no
hardcode_libdir_flag_spec='$wl-rpath,$libdir'
export_dynamic_flag_spec='$wl-E'
# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
# Instead, shared libraries are loaded at an image base (0x10000000 by
# default) and relocated if they conflict, which is a slow very memory
# consuming and fragmenting process. To avoid this, we pick a random,
# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
# time. Moving up from 0x10000000 also allows more sbrk(2) space.
archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
;;
*-mlibc)
archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
;;
gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
tmp_diet=no
if test linux-dietlibc = "$host_os"; then
case $cc_basename in
diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
esac
fi
if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
&& test no = "$tmp_diet"
then
tmp_addflag=' $pic_flag'
tmp_sharedflag='-shared'
case $cc_basename,$host_cpu in
pgcc*) # Portland Group C compiler
whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
tmp_addflag=' $pic_flag'
;;
pgf77* | pgf90* | pgf95* | pgfortran*)
# Portland Group f77 and f90 compilers
whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
tmp_addflag=' $pic_flag -Mnomain' ;;
ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
tmp_addflag=' -i_dynamic' ;;
efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
tmp_addflag=' -i_dynamic -nofor_main' ;;
ifc* | ifort* | ifx*) # Intel Fortran compiler
tmp_addflag=' -nofor_main' ;;
lf95*) # Lahey Fortran 8.1
whole_archive_flag_spec=
tmp_sharedflag='--shared' ;;
nagfor*) # NAGFOR 5.3
tmp_sharedflag='-Wl,-shared' ;;
xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
tmp_sharedflag='-qmkshrobj'
tmp_addflag= ;;
nvcc*) # Cuda Compiler Driver 2.2
whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
compiler_needs_object=yes
;;
esac
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ C*) # Sun C 5.9
whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
compiler_needs_object=yes
tmp_sharedflag='-G' ;;
*Sun\ F*) # Sun Fortran 8.3
tmp_sharedflag='-G' ;;
esac
archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
if test yes = "$supports_anon_versioning"; then
archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
fi
case $cc_basename in
tcc*)
hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
export_dynamic_flag_spec='-rdynamic'
;;
xlf* | bgf* | bgxlf* | mpixlf*)
# IBM XL Fortran 10.1 on PPC cannot create shared libs itself
whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
if test yes = "$supports_anon_versioning"; then
archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
fi
;;
esac
else
ld_shlibs=no
fi
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
wlarc=
else
archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
fi
;;
solaris*)
if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
ld_shlibs=no
cat <<_LT_EOF 1>&2
*** Warning: The releases 2.8.* of the GNU linker cannot reliably
*** create shared libraries on Solaris systems. Therefore, libtool
*** is disabling shared libraries support. We urge you to upgrade GNU
*** binutils to release 2.9.1 or newer. Another option is to modify
*** your PATH or compiler configuration so that the native linker is
*** used, and then restart.
_LT_EOF
elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
else
ld_shlibs=no
fi
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
case `$LD -v 2>&1` in
*\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
ld_shlibs=no
cat <<_LT_EOF 1>&2
*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
*** reliably create shared libraries on SCO systems. Therefore, libtool
*** is disabling shared libraries support. We urge you to upgrade GNU
*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
*** your PATH or compiler configuration so that the native linker is
*** used, and then restart.
_LT_EOF
;;
*)
# For security reasons, it is highly recommended that you always
# use absolute paths for naming shared libraries, and exclude the
# DT_RUNPATH tag from executables and libraries. But doing so
# requires that you compile everything twice, which is a pain.
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
else
ld_shlibs=no
fi
;;
esac
;;
sunos4*)
archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
wlarc=
hardcode_direct=yes
hardcode_shlibpath_var=no
;;
*)
if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
else
ld_shlibs=no
fi
;;
esac
if test no = "$ld_shlibs"; then
runpath_var=
hardcode_libdir_flag_spec=
export_dynamic_flag_spec=
whole_archive_flag_spec=
fi
else
# PORTME fill in a description of your system's linker (not GNU ld)
case $host_os in
aix3*)
allow_undefined_flag=unsupported
always_export_symbols=yes
archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
# Note: this linker hardcodes the directories in LIBPATH if there
# are no directories specified by -L.
hardcode_minus_L=yes
if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
# Neither direct hardcoding nor static linking is supported with a
# broken collect2.
hardcode_direct=unsupported
fi
;;
aix[4-9]*)
if test ia64 = "$host_cpu"; then
# On IA64, the linker does run time linking by default, so we don't
# have to do anything special.
aix_use_runtimelinking=no
exp_sym_flag='-Bexport'
no_entry_flag=
else
# If we're using GNU nm, then we don't want the "-C" option.
# -C means demangle to GNU nm, but means don't demangle to AIX nm.
# Without the "-l" option, or with the "-B" option, AIX nm treats
# weak defined symbols like other global defined symbols, whereas
# GNU nm marks them as "W".
# While the 'weak' keyword is ignored in the Export File, we need
# it in the Import File for the 'aix-soname' feature, so we have
# to replace the "-B" option with "-P" for AIX nm.
if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
else
export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
fi
aix_use_runtimelinking=no
# Test if we are trying to use run time linking or normal
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
# have runtime linking enabled, and use it for executables.
# For shared libraries, we enable/disable runtime linking
# depending on the kind of the shared library created -
# when "with_aix_soname,aix_use_runtimelinking" is:
# "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
# "aix,yes" lib.so shared, rtl:yes, for executables
# lib.a static archive
# "both,no" lib.so.V(shr.o) shared, rtl:yes
# lib.a(lib.so.V) shared, rtl:no, for executables
# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
# lib.a(lib.so.V) shared, rtl:no
# "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
# lib.a static archive
case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
for ld_flag in $LDFLAGS; do
if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
aix_use_runtimelinking=yes
break
fi
done
if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
# With aix-soname=svr4, we create the lib.so.V shared archives only,
# so we don't have lib.a shared libs to link our executables.
# We have to force runtime linking in this case.
aix_use_runtimelinking=yes
LDFLAGS="$LDFLAGS -Wl,-brtl"
fi
;;
esac
exp_sym_flag='-bexport'
no_entry_flag='-bnoentry'
fi
# When large executables or shared objects are built, AIX ld can
# have problems creating the table of contents. If linking a library
# or program results in "error TOC overflow" add -mminimal-toc to
# CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
# enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
archive_cmds=''
hardcode_direct=yes
hardcode_direct_absolute=yes
hardcode_libdir_separator=':'
link_all_deplibs=yes
file_list_spec='$wl-f,'
case $with_aix_soname,$aix_use_runtimelinking in
aix,*) ;; # traditional, no import file
svr4,* | *,yes) # use import file
# The Import File defines what to hardcode.
hardcode_direct=no
hardcode_direct_absolute=no
;;
esac
if test yes = "$GCC"; then
case $host_os in aix4.[012]|aix4.[012].*)
# We only want to do this on AIX 4.2 and lower, the check
# below for broken collect2 doesn't work under 4.3+
collect2name=`$CC -print-prog-name=collect2`
if test -f "$collect2name" &&
strings "$collect2name" | $GREP resolve_lib_name >/dev/null
then
# We have reworked collect2
:
else
# We have old collect2
hardcode_direct=unsupported
# It fails to find uninstalled libraries when the uninstalled
# path is not listed in the libpath. Setting hardcode_minus_L
# to unsupported forces relinking
hardcode_minus_L=yes
hardcode_libdir_flag_spec='-L$libdir'
hardcode_libdir_separator=
fi
;;
esac
shared_flag='-shared'
if test yes = "$aix_use_runtimelinking"; then
shared_flag="$shared_flag "'$wl-G'
fi
# Need to ensure runtime linking is disabled for the traditional
# shared library, or the linker may eventually find shared libraries
# /with/ Import File - we do not want to mix them.
shared_flag_aix='-shared'
shared_flag_svr4='-shared $wl-G'
else
# not using gcc
if test ia64 = "$host_cpu"; then
# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
# chokes on -Wl,-G. The following line is correct:
shared_flag='-G'
else
if test yes = "$aix_use_runtimelinking"; then
shared_flag='$wl-G'
else
shared_flag='$wl-bM:SRE'
fi
shared_flag_aix='$wl-bM:SRE'
shared_flag_svr4='$wl-G'
fi
fi
export_dynamic_flag_spec='$wl-bexpall'
# It seems that -bexpall does not export symbols beginning with
# underscore (_), so it is better to generate a list of symbols to export.
always_export_symbols=yes
if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
# Warning - without using the other runtime loading flags (-brtl),
# -berok will link without error, but may produce a broken library.
allow_undefined_flag='-berok'
# Determine the default libpath from the value encoded in an
# empty executable.
if test set = "${lt_cv_aix_libpath+set}"; then
aix_libpath=$lt_cv_aix_libpath
else
if test ${lt_cv_aix_libpath_+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
lt_aix_libpath_sed='
/Import File Strings/,/^$/ {
/^0/ {
s/^0 *\([^ ]*\) *$/\1/
p
}
}'
lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
# Check for a 64-bit object if we didn't find anything.
if test -z "$lt_cv_aix_libpath_"; then
lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
fi
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test -z "$lt_cv_aix_libpath_"; then
lt_cv_aix_libpath_=/usr/lib:/lib
fi
;;
esac
fi
aix_libpath=$lt_cv_aix_libpath_
fi
hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
else
if test ia64 = "$host_cpu"; then
hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib'
allow_undefined_flag="-z nodefs"
archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
else
# Determine the default libpath from the value encoded in an
# empty executable.
if test set = "${lt_cv_aix_libpath+set}"; then
aix_libpath=$lt_cv_aix_libpath
else
if test ${lt_cv_aix_libpath_+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
lt_aix_libpath_sed='
/Import File Strings/,/^$/ {
/^0/ {
s/^0 *\([^ ]*\) *$/\1/
p
}
}'
lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
# Check for a 64-bit object if we didn't find anything.
if test -z "$lt_cv_aix_libpath_"; then
lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
fi
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test -z "$lt_cv_aix_libpath_"; then
lt_cv_aix_libpath_=/usr/lib:/lib
fi
;;
esac
fi
aix_libpath=$lt_cv_aix_libpath_
fi
hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
# Warning - without using the other run time loading flags,
# -berok will link without error, but may produce a broken library.
no_undefined_flag=' $wl-bernotok'
allow_undefined_flag=' $wl-berok'
if test yes = "$with_gnu_ld"; then
# We only use this code for GNU lds that support --whole-archive.
whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive'
else
# Exported symbols can be pulled into shared objects from archives
whole_archive_flag_spec='$convenience'
fi
archive_cmds_need_lc=yes
archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
# -brtl affects multiple linker settings, -berok does not and is overridden later
compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
if test svr4 != "$with_aix_soname"; then
# This is similar to how AIX traditionally builds its shared libraries.
archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
fi
if test aix != "$with_aix_soname"; then
archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
else
# used by -dlpreopen to get the symbols
archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
fi
archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d'
fi
fi
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
archive_expsym_cmds=''
;;
m68k)
archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
;;
esac
;;
bsdi[45]*)
export_dynamic_flag_spec=-rdynamic
;;
cygwin* | mingw* | windows* | pw32* | cegcc*)
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++ or Intel C++ Compiler.
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
case $cc_basename in
cl* | icl* | icx* | icpx*)
# Native MSVC and Intel compilers
hardcode_libdir_flag_spec=' '
allow_undefined_flag=unsupported
always_export_symbols=yes
file_list_spec='@'
# Tell ltmain to make .lib files, not .a files.
libext=lib
# Tell ltmain to make .dll files, not .so files.
shrext_cmds=.dll
# FIXME: Setting linknames here is a bad hack.
# A check exists to verify if there are linker flags, which will use
# different commands when linking.
archive_cmds='$CC -Fe$output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then
cp "$export_symbols" "$output_objdir/$soname.def";
echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.expsym";
else
$SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.expsym;
fi~
if test -z "$linker_flags"; then
$CC -Fe$tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.expsym" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib";
else
$CC -Fe$tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.expsym" -Wl,$linker_flags-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib";
fi~
linknames='
# The linker will not automatically build a static lib if we build a DLL.
# _LT_TAGVAR(old_archive_from_new_cmds, )='true'
enable_shared_with_static_runtimes=yes
exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
# Don't use ranlib
old_postinstall_cmds='chmod 644 $oldlib'
postlink_cmds='lt_outputfile="@OUTPUT@"~
lt_tool_outputfile="@TOOL_OUTPUT@"~
case $lt_outputfile in
*.exe|*.EXE) ;;
*)
lt_outputfile=$lt_outputfile.exe
lt_tool_outputfile=$lt_tool_outputfile.exe
;;
esac~
if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
$MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
$RM "$lt_outputfile.manifest";
fi'
;;
*)
# Assume MSVC and ICC wrapper
hardcode_libdir_flag_spec=' '
allow_undefined_flag=unsupported
# Tell ltmain to make .lib files, not .a files.
libext=lib
# Tell ltmain to make .dll files, not .so files.
shrext_cmds=.dll
# FIXME: Setting linknames here is a bad hack.
archive_cmds='$CC -Fe$lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
# The linker will automatically build a .lib file if we build a DLL.
old_archive_from_new_cmds='true'
# FIXME: Should let the user specify the lib program.
old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
enable_shared_with_static_runtimes=yes
;;
esac
;;
darwin* | rhapsody*)
archive_cmds_need_lc=no
hardcode_direct=no
hardcode_automatic=yes
hardcode_shlibpath_var=unsupported
if test yes = "$lt_cv_ld_force_load"; then
whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
else
whole_archive_flag_spec=''
fi
link_all_deplibs=yes
allow_undefined_flag=$_lt_dar_allow_undefined
case $cc_basename in
ifort*|nagfor*) _lt_dar_can_shared=yes ;;
*) _lt_dar_can_shared=$GCC ;;
esac
if test yes = "$_lt_dar_can_shared"; then
output_verbose_link_cmd=func_echo_all
archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
else
ld_shlibs=no
fi
;;
dgux*)
archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
hardcode_libdir_flag_spec='-L$libdir'
hardcode_shlibpath_var=no
;;
# FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
# support. Future versions do this automatically, but an explicit c++rt0.o
# does not break anything, and helps significantly (at the cost of a little
# extra space).
freebsd2.2*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
hardcode_shlibpath_var=no
;;
# Unfortunately, older versions of FreeBSD 2 do not have this feature.
freebsd2.*)
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_minus_L=yes
hardcode_shlibpath_var=no
;;
# FreeBSD 3 and greater uses gcc -shared to do shared libraries.
freebsd* | dragonfly* | midnightbsd*)
archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
hardcode_shlibpath_var=no
;;
hpux9*)
if test yes = "$GCC"; then
archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
else
archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
fi
hardcode_libdir_flag_spec='$wl+b $wl$libdir'
hardcode_libdir_separator=:
hardcode_direct=yes
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
export_dynamic_flag_spec='$wl-E'
;;
hpux10*)
if test yes,no = "$GCC,$with_gnu_ld"; then
archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
else
archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
fi
if test no = "$with_gnu_ld"; then
hardcode_libdir_flag_spec='$wl+b $wl$libdir'
hardcode_libdir_separator=:
hardcode_direct=yes
hardcode_direct_absolute=yes
export_dynamic_flag_spec='$wl-E'
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
fi
;;
hpux11*)
if test yes,no = "$GCC,$with_gnu_ld"; then
case $host_cpu in
hppa*64*)
archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
ia64*)
archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
;;
*)
archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
;;
esac
else
case $host_cpu in
hppa*64*)
archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
;;
ia64*)
archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
;;
*)
# Older versions of the 11.00 compiler do not understand -b yet
# (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
printf %s "checking if $CC understands -b... " >&6; }
if test ${lt_cv_prog_compiler__b+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_prog_compiler__b=no
save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -b"
echo "$lt_simple_link_test_code" > conftest.$ac_ext
if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
# The linker can only warn and ignore the option if not recognized
# So say no if there are warnings
if test -s conftest.err; then
# Append any errors to the config.log.
cat conftest.err 1>&5
$ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.expsym
$SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
if diff conftest.expsym conftest.er2 >/dev/null; then
lt_cv_prog_compiler__b=yes
fi
else
lt_cv_prog_compiler__b=yes
fi
fi
$RM -r conftest*
LDFLAGS=$save_LDFLAGS
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
printf "%s\n" "$lt_cv_prog_compiler__b" >&6; }
if test yes = "$lt_cv_prog_compiler__b"; then
archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
else
archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
fi
;;
esac
fi
if test no = "$with_gnu_ld"; then
hardcode_libdir_flag_spec='$wl+b $wl$libdir'
hardcode_libdir_separator=:
case $host_cpu in
hppa*64*|ia64*)
hardcode_direct=no
hardcode_shlibpath_var=no
;;
*)
hardcode_direct=yes
hardcode_direct_absolute=yes
export_dynamic_flag_spec='$wl-E'
# hardcode_minus_L: Not really in the search PATH,
# but as the default location of the library.
hardcode_minus_L=yes
;;
esac
fi
;;
irix5* | irix6* | nonstopux*)
if test yes = "$GCC"; then
archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
# Try to use the -exported_symbol ld option, if it does not
# work, assume that -exports_file does not work either and
# implicitly export all symbols.
# This should be the same for all languages, so no per-tag cache variable.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
printf %s "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
if test ${lt_cv_irix_exported_symbol+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int foo (void) { return 0; }
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
lt_cv_irix_exported_symbol=yes
else case e in #(
e) lt_cv_irix_exported_symbol=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LDFLAGS=$save_LDFLAGS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
if test yes = "$lt_cv_irix_exported_symbol"; then
archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
fi
else
archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
fi
archive_cmds_need_lc='no'
hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
hardcode_libdir_separator=:
inherit_rpath=yes
link_all_deplibs=yes
;;
*-mlibc)
;;
linux*)
case $cc_basename in
tcc*)
# Fabrice Bellard et al's Tiny C Compiler
ld_shlibs=yes
archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
;;
esac
;;
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
else
archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
fi
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
hardcode_shlibpath_var=no
;;
newsos6)
archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes
hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
hardcode_libdir_separator=:
hardcode_shlibpath_var=no
;;
*nto* | *qnx*)
;;
openbsd*)
if test -f /usr/libexec/ld.so; then
hardcode_direct=yes
hardcode_shlibpath_var=no
hardcode_direct_absolute=yes
if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
hardcode_libdir_flag_spec='$wl-rpath,$libdir'
export_dynamic_flag_spec='$wl-E'
else
archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
hardcode_libdir_flag_spec='$wl-rpath,$libdir'
fi
else
ld_shlibs=no
fi
;;
os2*)
hardcode_libdir_flag_spec='-L$libdir'
hardcode_minus_L=yes
allow_undefined_flag=unsupported
shrext_cmds=.dll
archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
$ECHO EXPORTS >> $output_objdir/$libname.def~
prefix_cmds="$SED"~
if test EXPORTS = "`$SED 1q $export_symbols`"; then
prefix_cmds="$prefix_cmds -e 1d";
fi~
prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
emximp -o $lib $output_objdir/$libname.def'
old_archive_from_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
enable_shared_with_static_runtimes=yes
file_list_spec='@'
;;
osf3*)
if test yes = "$GCC"; then
allow_undefined_flag=' $wl-expect_unresolved $wl\*'
archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
else
allow_undefined_flag=' -expect_unresolved \*'
archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
fi
archive_cmds_need_lc='no'
hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
hardcode_libdir_separator=:
;;
osf4* | osf5*) # as osf3* with the addition of -msym flag
if test yes = "$GCC"; then
allow_undefined_flag=' $wl-expect_unresolved $wl\*'
archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
else
allow_undefined_flag=' -expect_unresolved \*'
archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.expsym; done; printf "%s\\n" "-hidden">> $lib.expsym~
$CC -shared$allow_undefined_flag $wl-input $wl$lib.expsym $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.expsym'
# Both c and cxx compiler support -rpath directly
hardcode_libdir_flag_spec='-rpath $libdir'
fi
archive_cmds_need_lc='no'
hardcode_libdir_separator=:
;;
serenity*)
;;
solaris*)
no_undefined_flag=' -z defs'
if test yes = "$GCC"; then
wlarc='$wl'
archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
archive_expsym_cmds='echo "{ global:" > $lib.expsym~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.expsym~echo "local: *; };" >> $lib.expsym~
$CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.expsym $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.expsym'
else
case `$CC -V 2>&1` in
*"Compilers 5.0"*)
wlarc=''
archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
archive_expsym_cmds='echo "{ global:" > $lib.expsym~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.expsym~echo "local: *; };" >> $lib.expsym~
$LD -G$allow_undefined_flag -M $lib.expsym -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.expsym'
;;
*)
wlarc='$wl'
archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
archive_expsym_cmds='echo "{ global:" > $lib.expsym~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.expsym~echo "local: *; };" >> $lib.expsym~
$CC -G$allow_undefined_flag -M $lib.expsym -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.expsym'
;;
esac
fi
hardcode_libdir_flag_spec='-R$libdir'
hardcode_shlibpath_var=no
case $host_os in
solaris2.[0-5] | solaris2.[0-5].*) ;;
*)
# The compiler driver will combine and reorder linker options,
# but understands '-z linker_flag'. GCC discards it without '$wl',
# but is careful enough not to reorder.
# Supported since Solaris 2.6 (maybe 2.5.1?)
if test yes = "$GCC"; then
whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
else
whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
fi
;;
esac
link_all_deplibs=yes
;;
sunos4*)
if test sequent = "$host_vendor"; then
# Use $CC to link under sequent, because it throws in some extra .o
# files that make .init and .fini sections work.
archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
else
archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
fi
hardcode_libdir_flag_spec='-L$libdir'
hardcode_direct=yes
hardcode_minus_L=yes
hardcode_shlibpath_var=no
;;
sysv4)
case $host_vendor in
sni)
archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=yes # is this really true???
;;
siemens)
## LD is ld it makes a PLAMLIB
## CC just makes a GrossModule.
archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
reload_cmds='$CC -r -o $output$reload_objs'
hardcode_direct=no
;;
motorola)
archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
hardcode_direct=no #Motorola manual says yes, but my tests say they lie
;;
esac
runpath_var='LD_RUN_PATH'
hardcode_shlibpath_var=no
;;
sysv4.3*)
archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
hardcode_shlibpath_var=no
export_dynamic_flag_spec='-Bexport'
;;
sysv4*MP*)
if test -d /usr/nec; then
archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
hardcode_shlibpath_var=no
runpath_var=LD_RUN_PATH
hardcode_runpath_var=yes
ld_shlibs=yes
fi
;;
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
no_undefined_flag='$wl-z,text'
archive_cmds_need_lc=no
hardcode_shlibpath_var=no
runpath_var='LD_RUN_PATH'
if test yes = "$GCC"; then
archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
else
archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
fi
;;
sysv5* | sco3.2v5* | sco5v6*)
# Note: We CANNOT use -z defs as we might desire, because we do not
# link with -lc, and that would cause any symbols used from libc to
# always be unresolved, which means just about no library would
# ever link correctly. If we're not using GNU ld we use -z text
# though, which does catch some bad symbols but isn't as heavy-handed
# as -z defs.
no_undefined_flag='$wl-z,text'
allow_undefined_flag='$wl-z,nodefs'
archive_cmds_need_lc=no
hardcode_shlibpath_var=no
hardcode_libdir_flag_spec='$wl-R,$libdir'
hardcode_libdir_separator=':'
link_all_deplibs=yes
export_dynamic_flag_spec='$wl-Bexport'
runpath_var='LD_RUN_PATH'
if test yes = "$GCC"; then
archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
else
archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
fi
;;
uts4*)
archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
hardcode_libdir_flag_spec='-L$libdir'
hardcode_shlibpath_var=no
;;
*)
ld_shlibs=no
;;
esac
if test sni = "$host_vendor"; then
case $host in
sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
export_dynamic_flag_spec='$wl-Blargedynsym'
;;
esac
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
printf "%s\n" "$ld_shlibs" >&6; }
test no = "$ld_shlibs" && can_build_shared=no
with_gnu_ld=$with_gnu_ld
#
# Do we need to explicitly link libc?
#
case "x$archive_cmds_need_lc" in
x|xyes)
# Assume -lc should be added
archive_cmds_need_lc=yes
if test yes,yes = "$GCC,$enable_shared"; then
case $archive_cmds in
*'~'*)
# FIXME: we may have to deal with multi-command sequences.
;;
'$CC '*)
# Test whether the compiler implicitly links with -lc since on some
# systems, -lgcc has to come before -lc. If gcc already passes -lc
# to ld, don't add -lc before -lgcc.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
printf %s "checking whether -lc should be explicitly linked in... " >&6; }
if test ${lt_cv_archive_cmds_need_lc+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) $RM conftest*
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } 2>conftest.err; then
soname=conftest
lib=conftest
libobjs=conftest.$ac_objext
deplibs=
wl=$lt_prog_compiler_wl
pic_flag=$lt_prog_compiler_pic
compiler_flags=-v
linker_flags=-v
verstring=
output_objdir=.
libname=conftest
lt_save_allow_undefined_flag=$allow_undefined_flag
allow_undefined_flag=
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
(eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
then
lt_cv_archive_cmds_need_lc=no
else
lt_cv_archive_cmds_need_lc=yes
fi
allow_undefined_flag=$lt_save_allow_undefined_flag
else
cat conftest.err 1>&5
fi
$RM conftest*
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
printf "%s\n" "$lt_cv_archive_cmds_need_lc" >&6; }
archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
;;
esac
fi
;;
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
printf %s "checking dynamic linker characteristics... " >&6; }
if test yes = "$GCC"; then
case $host_os in
darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
*) lt_awk_arg='/^libraries:/' ;;
esac
case $host_os in
mingw* | windows* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;;
*) lt_sed_strip_eq='s|=/|/|g' ;;
esac
lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
case $lt_search_path_spec in
*\;*)
# if the path contains ";" then we assume it to be the separator
# otherwise default to the standard path separator (i.e. ":") - it is
# assumed that no part of a normal pathname contains ";" but that should
# okay in the real world where ";" in dirpaths is itself problematic.
lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
;;
*)
lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
;;
esac
# Ok, now we have the path, separated by spaces, we can step through it
# and add multilib dir if necessary...
lt_tmp_lt_search_path_spec=
lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
# ...but if some path component already ends with the multilib dir we assume
# that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
case "$lt_multi_os_dir; $lt_search_path_spec " in
"/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
lt_multi_os_dir=
;;
esac
for lt_sys_path in $lt_search_path_spec; do
if test -d "$lt_sys_path$lt_multi_os_dir"; then
lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
elif test -n "$lt_multi_os_dir"; then
test -d "$lt_sys_path" && \
lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
fi
done
lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
BEGIN {RS = " "; FS = "/|\n";} {
lt_foo = "";
lt_count = 0;
for (lt_i = NF; lt_i > 0; lt_i--) {
if ($lt_i != "" && $lt_i != ".") {
if ($lt_i == "..") {
lt_count++;
} else {
if (lt_count == 0) {
lt_foo = "/" $lt_i lt_foo;
} else {
lt_count--;
}
}
}
}
if (lt_foo != "") { lt_freq[lt_foo]++; }
if (lt_freq[lt_foo] == 1) { print lt_foo; }
}'`
# AWK program above erroneously prepends '/' to C:/dos/paths
# for these hosts.
case $host_os in
mingw* | windows* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
$SED 's|/\([A-Za-z]:\)|\1|g'` ;;
esac
sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
else
sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
fi
library_names_spec=
libname_spec='lib$name'
soname_spec=
shrext_cmds=.so
postinstall_cmds=
postuninstall_cmds=
finish_cmds=
finish_eval=
shlibpath_var=
shlibpath_overrides_runpath=unknown
version_type=none
dynamic_linker="$host_os ld.so"
sys_lib_dlsearch_path_spec="/lib /usr/lib"
need_lib_prefix=unknown
hardcode_into_libs=no
# when you set need_version to no, make sure it does not cause -set_version
# flags to be left without arguments
need_version=unknown
case $host_os in
aix3*)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
shlibpath_var=LIBPATH
# AIX 3 has no versioning support, so we append a major version to the name.
soname_spec='$libname$release$shared_ext$major'
;;
aix[4-9]*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
hardcode_into_libs=yes
if test ia64 = "$host_cpu"; then
# AIX 5 supports IA64
library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
else
# With GCC up to 2.95.x, collect2 would create an import file
# for dependence libraries. The import file would start with
# the line '#! .'. This would cause the generated library to
# depend on '.', always an invalid library. This was fixed in
# development snapshots of GCC prior to 3.0.
case $host_os in
aix4 | aix4.[01] | aix4.[01].*)
if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
echo ' yes '
echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
:
else
can_build_shared=no
fi
;;
esac
# Using Import Files as archive members, it is possible to support
# filename-based versioning of shared library archives on AIX. While
# this would work for both with and without runtime linking, it will
# prevent static linking of such archives. So we do filename-based
# shared library versioning with .so extension only, which is used
# when both runtime linking and shared linking is enabled.
# Unfortunately, runtime linking may impact performance, so we do
# not want this to be the default eventually. Also, we use the
# versioned .so libs for executables only if there is the -brtl
# linker flag in LDFLAGS as well, or --enable-aix-soname=svr4 only.
# To allow for filename-based versioning support, we need to create
# libNAME.so.V as an archive file, containing:
# *) an Import File, referring to the versioned filename of the
# archive as well as the shared archive member, telling the
# bitwidth (32 or 64) of that shared object, and providing the
# list of exported symbols of that shared object, eventually
# decorated with the 'weak' keyword
# *) the shared object with the F_LOADONLY flag set, to really avoid
# it being seen by the linker.
# At run time we better use the real file rather than another symlink,
# but for link time we create the symlink libNAME.so -> libNAME.so.V
case $with_aix_soname,$aix_use_runtimelinking in
# AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
# soname into executable. Probably we can add versioning support to
# collect2, so additional links can be useful in future.
aix,yes) # traditional libtool
dynamic_linker='AIX unversionable lib.so'
# If using run time linking (on AIX 4.2 or later) use lib.so
# instead of lib.a to let people know that these are not
# typical AIX shared libraries.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
;;
aix,no) # traditional AIX only
dynamic_linker='AIX lib.a(lib.so.V)'
# We preserve .a as extension for shared libraries through AIX4.2
# and later when we are not doing run time linking.
library_names_spec='$libname$release.a $libname.a'
soname_spec='$libname$release$shared_ext$major'
;;
svr4,*) # full svr4 only
dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
# We do not specify a path in Import Files, so LIBPATH fires.
shlibpath_overrides_runpath=yes
;;
*,yes) # both, prefer svr4
dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
# unpreferred sharedlib libNAME.a needs extra handling
postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
# We do not specify a path in Import Files, so LIBPATH fires.
shlibpath_overrides_runpath=yes
;;
*,no) # both, prefer aix
dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
library_names_spec='$libname$release.a $libname.a'
soname_spec='$libname$release$shared_ext$major'
# unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
;;
esac
shlibpath_var=LIBPATH
fi
;;
amigaos*)
case $host_cpu in
powerpc)
# Since July 2007 AmigaOS4 officially supports .so libraries.
# When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
;;
m68k)
library_names_spec='$libname.ixlibrary $libname.a'
# Create ${libname}_ixlibrary.a entries in /sys/libs.
finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
;;
esac
;;
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"
shlibpath_var=LIBRARY_PATH
;;
bsdi[45]*)
version_type=linux # correct to gnu/linux during the next big refactor
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
shlibpath_var=LD_LIBRARY_PATH
sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
# the default ld.so.conf also contains /usr/contrib/lib and
# /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
# libtool to hard-code these into programs
;;
cygwin* | mingw* | windows* | pw32* | cegcc*)
version_type=windows
shrext_cmds=.dll
need_version=no
need_lib_prefix=no
case $GCC,$cc_basename in
yes,*)
# gcc
library_names_spec='$libname.dll.a'
# DLL is installed to $(libdir)/../bin by postinstall_cmds
# If user builds GCC with multilib enabled,
# it should just install on $(libdir)
# not on $(libdir)/../bin or 32 bits dlls would override 64 bit ones.
if test xyes = x"$multilib"; then
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
$install_prog $dir/$dlname $destdir/$dlname~
chmod a+x $destdir/$dlname~
if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
eval '\''$striplib $destdir/$dlname'\'' || exit \$?;
fi'
else
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname~
chmod a+x \$dldir/$dlname~
if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
fi'
fi
postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
dlpath=$dir/\$dldll~
$RM \$dlpath'
shlibpath_overrides_runpath=yes
case $host_os in
cygwin*)
# Cygwin DLLs use 'cyg' prefix rather than 'lib'
soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
;;
mingw* | windows* | cegcc*)
# MinGW DLLs use traditional 'lib' prefix
soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
;;
pw32*)
# pw32 DLLs use 'pw' prefix rather than 'lib'
library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
;;
esac
dynamic_linker='Win32 ld.exe'
;;
*,cl* | *,icl* | *,icx*)
# Native MSVC and Intel compilers
libname_spec='$name'
soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
library_names_spec='$libname.dll.lib'
case $build_os in
mingw* | windows*)
sys_lib_search_path_spec=
lt_save_ifs=$IFS
IFS=';'
for lt_path in $LIB
do
IFS=$lt_save_ifs
# Let DOS variable expansion print the short 8.3 style file name.
lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
done
IFS=$lt_save_ifs
# Convert to MSYS style.
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
;;
cygwin*)
# Convert to unix form, then to dos form, then back to unix form
# but this time dos style (no spaces!) so that the unix form looks
# like /cygdrive/c/PROGRA~1:/cygdr...
sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
;;
*)
sys_lib_search_path_spec=$LIB
if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
# It is most probably a Windows format PATH.
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
else
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
fi
# FIXME: find the short name or the path components, as spaces are
# common. (e.g. "Program Files" -> "PROGRA~1")
;;
esac
# DLL is installed to $(libdir)/../bin by postinstall_cmds
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname'
postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
dlpath=$dir/\$dldll~
$RM \$dlpath'
shlibpath_overrides_runpath=yes
dynamic_linker='Win32 link.exe'
;;
*)
# Assume MSVC and ICC wrapper
library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
dynamic_linker='Win32 ld.exe'
;;
esac
# FIXME: first we should search . and the directory the executable is in
shlibpath_var=PATH
;;
darwin* | rhapsody*)
dynamic_linker="$host_os dyld"
version_type=darwin
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
soname_spec='$libname$release$major$shared_ext'
shlibpath_overrides_runpath=yes
shlibpath_var=DYLD_LIBRARY_PATH
shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
;;
dgux*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
;;
freebsd* | dragonfly* | midnightbsd*)
# DragonFly does not have aout. When/if they implement a new
# versioning mechanism, adjust this.
if test -x /usr/bin/objformat; then
objformat=`/usr/bin/objformat`
else
case $host_os in
freebsd[23].*) objformat=aout ;;
*) objformat=elf ;;
esac
fi
version_type=freebsd-$objformat
case $version_type in
freebsd-elf*)
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
need_version=no
need_lib_prefix=no
;;
freebsd-*)
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
need_version=yes
;;
esac
case $host_cpu in
powerpc64)
# On FreeBSD bi-arch platforms, a different variable is used for 32-bit
# binaries. See .
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int test_pointer_size[sizeof (void *) - 5];
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
shlibpath_var=LD_LIBRARY_PATH
else case e in #(
e) shlibpath_var=LD_32_LIBRARY_PATH ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
;;
*)
shlibpath_var=LD_LIBRARY_PATH
;;
esac
case $host_os in
freebsd2.*)
shlibpath_overrides_runpath=yes
;;
freebsd3.[01]* | freebsdelf3.[01]*)
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
;;
freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
*) # from 4.6 on, and DragonFly
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
;;
esac
;;
haiku*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
dynamic_linker="$host_os runtime_loader"
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LIBRARY_PATH
shlibpath_overrides_runpath=no
sys_lib_search_path_spec='/boot/system/non-packaged/develop/lib /boot/system/develop/lib'
sys_lib_dlsearch_path_spec='/boot/home/config/non-packaged/lib /boot/home/config/lib /boot/system/non-packaged/lib /boot/system/lib'
hardcode_into_libs=no
;;
hpux9* | hpux10* | hpux11*)
# Give a soname corresponding to the major version so that dld.sl refuses to
# link against other versions.
version_type=sunos
need_lib_prefix=no
need_version=no
case $host_cpu in
ia64*)
shrext_cmds='.so'
hardcode_into_libs=yes
dynamic_linker="$host_os dld.so"
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
if test 32 = "$HPUX_IA64_MODE"; then
sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
sys_lib_dlsearch_path_spec=/usr/lib/hpux32
else
sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
sys_lib_dlsearch_path_spec=/usr/lib/hpux64
fi
;;
hppa*64*)
shrext_cmds='.sl'
hardcode_into_libs=yes
dynamic_linker="$host_os dld.sl"
shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
;;
*)
shrext_cmds='.sl'
dynamic_linker="$host_os dld.sl"
shlibpath_var=SHLIB_PATH
shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
;;
esac
# HP-UX runs *really* slowly unless shared libraries are mode 555, ...
postinstall_cmds='chmod 555 $lib'
# or fails outright, so override atomically:
install_override_mode=555
;;
interix[3-9]*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
irix5* | irix6* | nonstopux*)
case $host_os in
nonstopux*) version_type=nonstopux ;;
*)
if test yes = "$lt_cv_prog_gnu_ld"; then
version_type=linux # correct to gnu/linux during the next big refactor
else
version_type=irix
fi ;;
esac
need_lib_prefix=no
need_version=no
soname_spec='$libname$release$shared_ext$major'
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
case $host_os in
irix5* | nonstopux*)
libsuff= shlibsuff=
;;
*)
case $LD in # libtool.m4 will add one of these switches to LD
*-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
libsuff= shlibsuff= libmagic=32-bit;;
*-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
libsuff=32 shlibsuff=N32 libmagic=N32;;
*-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
libsuff=64 shlibsuff=64 libmagic=64-bit;;
*) libsuff= shlibsuff= libmagic=never-match;;
esac
;;
esac
shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
shlibpath_overrides_runpath=no
sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
hardcode_into_libs=yes
;;
*-mlibc)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
dynamic_linker='mlibc ld.so'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
# No shared lib support for Linux oldld, aout, or coff.
linux*oldld* | linux*aout* | linux*coff*)
dynamic_linker=no
;;
linux*android*)
version_type=none # Android doesn't support versioned libraries.
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext $libname$shared_ext'
soname_spec='$libname$release$shared_ext'
finish_cmds=
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
# This implies no fast_install, which is unacceptable.
# Some rework will be needed to allow for fast_install
# before this can be enabled.
hardcode_into_libs=yes
dynamic_linker='Android linker'
# -rpath works at least for libraries that are not overridden by
# libraries installed in system locations.
hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
;;
# This must be glibc/ELF.
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
# Some binutils ld are patched to set DT_RUNPATH
if test ${lt_cv_shlibpath_overrides_runpath+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_shlibpath_overrides_runpath=no
save_LDFLAGS=$LDFLAGS
save_libdir=$libdir
eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null
then :
lt_cv_shlibpath_overrides_runpath=yes
fi
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LDFLAGS=$save_LDFLAGS
libdir=$save_libdir
;;
esac
fi
shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
# This implies no fast_install, which is unacceptable.
# Some rework will be needed to allow for fast_install
# before this can be enabled.
hardcode_into_libs=yes
# Ideally, we could use ldconfig to report *all* directories which are
# searched for libraries, however this is still not possible. Aside from not
# being certain /sbin/ldconfig is available, command
# 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
# even though it is searched at run-time. Try to do the best guess by
# appending ld.so.conf contents (and includes) to the search path.
if test -f /etc/ld.so.conf; then
lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
fi
# We used to test for /lib/ld.so.1 and disable shared libraries on
# powerpc, because MkLinux only supported shared libraries with the
# GNU dynamic linker. Since this was broken with cross compilers,
# most powerpc-linux boxes support dynamic linking these days and
# people can always --disable-shared, the test was removed, and we
# assume the GNU/Linux dynamic linker is in use.
dynamic_linker='GNU/Linux ld.so'
;;
netbsdelf*-gnu)
version_type=linux
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
dynamic_linker='NetBSD ld.elf_so'
enable_cxx_stdlib=yes
stdlibflag=
;;
netbsd*)
version_type=sunos
need_lib_prefix=no
need_version=no
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
dynamic_linker='NetBSD (a.out) ld.so'
else
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
dynamic_linker='NetBSD ld.elf_so'
fi
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
enable_cxx_stdlib=yes
stdlibflag=
;;
newsos6)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
;;
*nto* | *qnx*)
version_type=qnx
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
dynamic_linker='ldqnx.so'
;;
openbsd*)
version_type=sunos
sys_lib_dlsearch_path_spec=/usr/lib
need_lib_prefix=no
if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
need_version=no
else
need_version=yes
fi
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
;;
os2*)
libname_spec='$name'
version_type=windows
shrext_cmds=.dll
need_version=no
need_lib_prefix=no
# OS/2 can only load a DLL with a base name of 8 characters or less.
soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
v=$($ECHO $release$versuffix | tr -d .-);
n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
$ECHO $n$v`$shared_ext'
library_names_spec='${libname}_dll.$libext'
dynamic_linker='OS/2 ld.exe'
shlibpath_var=BEGINLIBPATH
sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
postinstall_cmds='base_file=`basename \$file`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname~
chmod a+x \$dldir/$dlname~
if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
fi'
postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
dlpath=$dir/\$dldll~
$RM \$dlpath'
;;
osf3* | osf4* | osf5*)
version_type=osf
need_lib_prefix=no
need_version=no
soname_spec='$libname$release$shared_ext$major'
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
;;
rdos*)
dynamic_linker=no
;;
serenity*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
dynamic_linker='SerenityOS LibELF'
;;
solaris*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
# ldd complains unless libraries are executable
postinstall_cmds='chmod +x $lib'
;;
sunos4*)
version_type=sunos
library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
if test yes = "$with_gnu_ld"; then
need_lib_prefix=no
fi
need_version=yes
;;
sysv4 | sysv4.3*)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
case $host_vendor in
sni)
shlibpath_overrides_runpath=no
need_lib_prefix=no
runpath_var=LD_RUN_PATH
;;
siemens)
need_lib_prefix=no
;;
motorola)
need_lib_prefix=no
need_version=no
shlibpath_overrides_runpath=no
sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
;;
esac
;;
sysv4*MP*)
if test -d /usr/nec; then
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
soname_spec='$libname$shared_ext.$major'
shlibpath_var=LD_LIBRARY_PATH
fi
;;
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
version_type=sco
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=yes
hardcode_into_libs=yes
if test yes = "$with_gnu_ld"; then
sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
else
sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
case $host_os in
sco3.2v5*)
sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
;;
esac
fi
sys_lib_dlsearch_path_spec='/usr/lib'
;;
tpf*)
# TPF is a cross-target only. Preferred cross-host = GNU/Linux.
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
;;
uts4*)
version_type=linux # correct to gnu/linux during the next big refactor
library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
soname_spec='$libname$release$shared_ext$major'
shlibpath_var=LD_LIBRARY_PATH
;;
emscripten*)
version_type=none
need_lib_prefix=no
need_version=no
library_names_spec='$libname$release$shared_ext'
soname_spec='$libname$release$shared_ext'
finish_cmds=
dynamic_linker="Emscripten linker"
lt_prog_compiler_wl=
lt_prog_compiler_pic=
lt_prog_compiler_static=
if test yes = "$GCC"; then
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_static='-static'
case $host_os in
aix*)
# All AIX code is PIC.
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
lt_prog_compiler_static='-Bstatic'
fi
lt_prog_compiler_pic='-fPIC'
;;
amigaos*)
case $host_cpu in
powerpc)
# see comment about AmigaOS4 .so support
lt_prog_compiler_pic='-fPIC'
;;
m68k)
# FIXME: we need at least 68020 code to build shared libraries, but
# adding the '-m68020' flag to GCC prevents building anything better,
# like '-m68040'.
lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
;;
esac
;;
beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
# PIC is the default for these OSes.
;;
mingw* | windows* | cygwin* | pw32* | os2* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
# Although the cygwin gcc ignores -fPIC, still need this for old-style
# (--disable-auto-import) libraries
lt_prog_compiler_pic='-DDLL_EXPORT'
case $host_os in
os2*)
lt_prog_compiler_static='$wl-static'
;;
esac
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
lt_prog_compiler_pic='-fno-common'
;;
haiku*)
# PIC is the default for Haiku.
# The "-static" flag exists, but is broken.
lt_prog_compiler_static=
;;
hpux*)
# PIC is the default for 64-bit PA HP-UX, but not for 32-bit
# PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
# sets the default TLS model and affects inlining.
case $host_cpu in
hppa*64*)
# +Z the default
;;
*)
lt_prog_compiler_pic='-fPIC'
;;
esac
;;
interix[3-9]*)
# Interix 3.x gcc -fpic/-fPIC options generate broken code.
# Instead, we relocate shared libraries at runtime.
;;
msdosdjgpp*)
# Just because we use GCC doesn't mean we suddenly get shared libraries
# on systems that don't support them.
lt_prog_compiler_can_build_shared=no
enable_shared=no
;;
*nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
lt_prog_compiler_pic='-fPIC -shared'
;;
sysv4*MP*)
if test -d /usr/nec; then
lt_prog_compiler_pic=-Kconform_pic
fi
;;
*)
lt_prog_compiler_pic='-fPIC'
;;
esac
case $cc_basename in
nvcc*) # Cuda Compiler Driver 2.2
lt_prog_compiler_wl='-Xlinker '
if test -n "$lt_prog_compiler_pic"; then
lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
fi
;;
esac
else
# PORTME Check for flag to pass linker flags through the system compiler.
case $host_os in
aix*)
lt_prog_compiler_wl='-Wl,'
if test ia64 = "$host_cpu"; then
# AIX 5 now supports IA64 processor
lt_prog_compiler_static='-Bstatic'
else
lt_prog_compiler_static='-bnso -bI:/lib/syscalls.expsym'
fi
;;
darwin* | rhapsody*)
# PIC is the default on this platform
# Common symbols not allowed in MH_DYLIB files
lt_prog_compiler_pic='-fno-common'
case $cc_basename in
nagfor*)
# NAG Fortran compiler
lt_prog_compiler_wl='-Wl,-Wl,,'
lt_prog_compiler_pic='-PIC'
lt_prog_compiler_static='-Bstatic'
;;
esac
;;
mingw* | windows* | cygwin* | pw32* | os2* | cegcc*)
# This hack is so that the source file can tell whether it is being
# built for inclusion in a dll (and should export symbols for example).
lt_prog_compiler_pic='-DDLL_EXPORT'
case $host_os in
os2*)
lt_prog_compiler_static='$wl-static'
;;
esac
;;
hpux9* | hpux10* | hpux11*)
lt_prog_compiler_wl='-Wl,'
# PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
# not for PA HP-UX.
case $host_cpu in
hppa*64*|ia64*)
# +Z the default
;;
*)
lt_prog_compiler_pic='+Z'
;;
esac
# Is there a better lt_prog_compiler_static that works with the bundled CC?
lt_prog_compiler_static='$wl-a ${wl}archive'
;;
irix5* | irix6* | nonstopux*)
lt_prog_compiler_wl='-Wl,'
# PIC (with -KPIC) is the default.
lt_prog_compiler_static='-non_shared'
;;
*-mlibc)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fPIC'
lt_prog_compiler_static='-static'
;;
linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu* | freebsd*)
case $cc_basename in
# old Intel for x86_64, which still supported -KPIC.
ecc*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-static'
;;
*flang* | ftn | f18* | f95*)
# Flang compiler.
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fPIC'
lt_prog_compiler_static='-static'
;;
# icc used to be incompatible with GCC.
# ICC 10 doesn't accept -KPIC any more.
icc* | ifort* | icx* | ifx*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fPIC'
lt_prog_compiler_static='-static'
;;
# Lahey Fortran 8.1.
lf95*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='--shared'
lt_prog_compiler_static='--static'
;;
nagfor*)
# NAG Fortran compiler
lt_prog_compiler_wl='-Wl,-Wl,,'
lt_prog_compiler_pic='-PIC'
lt_prog_compiler_static='-Bstatic'
;;
tcc*)
# Fabrice Bellard et al's Tiny C Compiler
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fPIC'
lt_prog_compiler_static='-static'
;;
pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
# Portland Group compilers (*not* the Pentium gcc compiler,
# which looks to be a dead project)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fpic'
lt_prog_compiler_static='-Bstatic'
;;
ccc*)
lt_prog_compiler_wl='-Wl,'
# All Alpha code is PIC.
lt_prog_compiler_static='-non_shared'
;;
xl* | bgxl* | bgf* | mpixl*)
# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-qpic'
lt_prog_compiler_static='-qstaticlink'
;;
*)
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
# Sun Fortran 8.3 passes all unrecognized flags to the linker
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
lt_prog_compiler_wl=''
;;
*Sun\ F* | *Sun*Fortran*)
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
lt_prog_compiler_wl='-Qoption ld '
;;
*Sun\ C*)
# Sun C 5.9
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
lt_prog_compiler_wl='-Wl,'
;;
*Intel*\ [CF]*Compiler*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fPIC'
lt_prog_compiler_static='-static'
;;
*Portland\ Group*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-fpic'
lt_prog_compiler_static='-Bstatic'
;;
esac
;;
esac
;;
newsos6)
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
;;
*nto* | *qnx*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
# it will coredump.
lt_prog_compiler_pic='-fPIC -shared'
;;
osf3* | osf4* | osf5*)
lt_prog_compiler_wl='-Wl,'
# All OSF/1 code is PIC.
lt_prog_compiler_static='-non_shared'
;;
rdos*)
lt_prog_compiler_static='-non_shared'
;;
serenity*)
;;
solaris*)
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
case $cc_basename in
f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
lt_prog_compiler_wl='-Qoption ld ';;
*)
lt_prog_compiler_wl='-Wl,';;
esac
;;
sunos4*)
lt_prog_compiler_wl='-Qoption ld '
lt_prog_compiler_pic='-PIC'
lt_prog_compiler_static='-Bstatic'
;;
sysv4 | sysv4.2uw2* | sysv4.3*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
;;
sysv4*MP*)
if test -d /usr/nec; then
lt_prog_compiler_pic='-Kconform_pic'
lt_prog_compiler_static='-Bstatic'
fi
;;
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_pic='-KPIC'
lt_prog_compiler_static='-Bstatic'
;;
unicos*)
lt_prog_compiler_wl='-Wl,'
lt_prog_compiler_can_build_shared=no
;;
uts4*)
lt_prog_compiler_pic='-pic'
lt_prog_compiler_static='-Bstatic'
;;
*)
lt_prog_compiler_can_build_shared=no
;;
esac
fi
case $host_os in
# For platforms that do not support PIC, -DPIC is meaningless:
*djgpp*)
lt_prog_compiler_pic=
;;
*)
lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
;;
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
printf %s "checking for $compiler option to produce PIC... " >&6; }
if test ${lt_cv_prog_compiler_pic+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_prog_compiler_pic=$lt_prog_compiler_pic ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
printf "%s\n" "$lt_cv_prog_compiler_pic" >&6; }
lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
#
# Check to make sure the PIC flag actually works.
#
if test -n "$lt_prog_compiler_pic"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
if test ${lt_cv_prog_compiler_pic_works+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_prog_compiler_pic_works=no
ac_outfile=conftest.$ac_objext
echo "$lt_simple_compile_test_code" > conftest.$ac_ext
lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment
# Insert the option either (1) after the last *FLAGS variable, or
# (2) before a word containing "conftest.", or (3) at the end.
# Note that $ac_compile itself does not contain backslashes and begins
# with a dollar sign (not a hyphen), so the echo should work correctly.
# The option is referenced via a variable to avoid confusing sed.
lt_compile=`echo "$ac_compile" | $SED \
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
$ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.expsym
$SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
if test ! -s conftest.er2 || diff conftest.expsym conftest.er2 >/dev/null; then
lt_cv_prog_compiler_pic_works=yes
fi
fi
$RM conftest*
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
printf "%s\n" "$lt_cv_prog_compiler_pic_works" >&6; }
if test yes = "$lt_cv_prog_compiler_pic_works"; then
case $lt_prog_compiler_pic in
"" | " "*) ;;
*) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
esac
else
lt_prog_compiler_pic=
lt_prog_compiler_can_build_shared=no
fi
fi
#
# Check to make sure the static flag actually works.
#
wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
if test ${lt_cv_prog_compiler_static_works+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) lt_cv_prog_compiler_static_works=no
save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
echo "$lt_simple_link_test_code" > conftest.$ac_ext
if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
# The linker can only warn and ignore the option if not recognized
# So say no if there are warnings
if test -s conftest.err; then
# Append any errors to the config.log.
cat conftest.err 1>&5
$ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.expsym
$SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
if diff conftest.expsym conftest.er2 >/dev/null; then
lt_cv_prog_compiler_static_works=yes
fi
else
lt_cv_prog_compiler_static_works=yes
fi
fi
$RM -r conftest*
LDFLAGS=$save_LDFLAGS
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
printf "%s\n" "$lt_cv_prog_compiler_static_works" >&6; }
if test yes = "$lt_cv_prog_compiler_static_works"; then
:
else
lt_prog_compiler_static=
fi
='-fPIC'
archive_cmds='$CC -sSIDE_MODULE=2 -shared $libobjs $deplibs $compiler_flags -o $lib'
archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -sSIDE_MODULE=2 -shared $libobjs $deplibs $compiler_flags -o $lib -s EXPORTED_FUNCTIONS=@$output_objdir/$soname.expsym'
archive_cmds_need_lc=no
no_undefined_flag=
;;
*)
dynamic_linker=no
;;
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
printf "%s\n" "$dynamic_linker" >&6; }
test no = "$dynamic_linker" && can_build_shared=no
variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
if test yes = "$GCC"; then
variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
fi
if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
fi
if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
fi
# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
printf %s "checking how to hardcode library paths into programs... " >&6; }
hardcode_action=
if test -n "$hardcode_libdir_flag_spec" ||
test -n "$runpath_var" ||
test yes = "$hardcode_automatic"; then
# We can hardcode non-existent directories.
if test no != "$hardcode_direct" &&
# If the only mechanism to avoid hardcoding is shlibpath_var, we
# have to relink, otherwise we might link with an installed library
# when we should be linking with a yet-to-be-installed one
## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" &&
test no != "$hardcode_minus_L"; then
# Linking always hardcodes the temporary library directory.
hardcode_action=relink
else
# We can link without hardcoding, and we can hardcode nonexisting dirs.
hardcode_action=immediate
fi
else
# We cannot hardcode anything, or else we can only hardcode existing
# directories.
hardcode_action=unsupported
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
printf "%s\n" "$hardcode_action" >&6; }
if test relink = "$hardcode_action" ||
test yes = "$inherit_rpath"; then
# Fast installation is not supported
enable_fast_install=no
elif test yes = "$shlibpath_overrides_runpath" ||
test no = "$enable_shared"; then
# Fast installation is not necessary
enable_fast_install=needless
fi
if test yes != "$enable_dlopen"; then
enable_dlopen=unknown
enable_dlopen_self=unknown
enable_dlopen_self_static=unknown
else
lt_cv_dlopen=no
lt_cv_dlopen_libs=
case $host_os in
beos*)
lt_cv_dlopen=load_add_on
lt_cv_dlopen_libs=
lt_cv_dlopen_self=yes
;;
mingw* | windows* | pw32* | cegcc*)
lt_cv_dlopen=LoadLibrary
lt_cv_dlopen_libs=
;;
cygwin*)
lt_cv_dlopen=dlopen
lt_cv_dlopen_libs=
;;
darwin*)
# if libdl is installed we need to link against it
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
printf %s "checking for dlopen in -ldl... " >&6; }
if test ${ac_cv_lib_dl_dlopen+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-ldl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char dlopen (void);
int
main (void)
{
return dlopen ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_dl_dlopen=yes
else case e in #(
e) ac_cv_lib_dl_dlopen=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
if test "x$ac_cv_lib_dl_dlopen" = xyes
then :
lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
else case e in #(
e)
lt_cv_dlopen=dyld
lt_cv_dlopen_libs=
lt_cv_dlopen_self=yes
;;
esac
fi
;;
tpf*)
# Don't try to run any link tests for TPF. We know it's impossible
# because TPF is a cross-compiler, and we know how we open DSOs.
lt_cv_dlopen=dlopen
lt_cv_dlopen_libs=
lt_cv_dlopen_self=no
;;
*)
ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
if test "x$ac_cv_func_shl_load" = xyes
then :
lt_cv_dlopen=shl_load
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
printf %s "checking for shl_load in -ldld... " >&6; }
if test ${ac_cv_lib_dld_shl_load+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-ldld $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char shl_load (void);
int
main (void)
{
return shl_load ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_dld_shl_load=yes
else case e in #(
e) ac_cv_lib_dld_shl_load=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; }
if test "x$ac_cv_lib_dld_shl_load" = xyes
then :
lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld
else case e in #(
e) ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
if test "x$ac_cv_func_dlopen" = xyes
then :
lt_cv_dlopen=dlopen
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
printf %s "checking for dlopen in -ldl... " >&6; }
if test ${ac_cv_lib_dl_dlopen+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-ldl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char dlopen (void);
int
main (void)
{
return dlopen ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_dl_dlopen=yes
else case e in #(
e) ac_cv_lib_dl_dlopen=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
if test "x$ac_cv_lib_dl_dlopen" = xyes
then :
lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
printf %s "checking for dlopen in -lsvld... " >&6; }
if test ${ac_cv_lib_svld_dlopen+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lsvld $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char dlopen (void);
int
main (void)
{
return dlopen ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_svld_dlopen=yes
else case e in #(
e) ac_cv_lib_svld_dlopen=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
printf "%s\n" "$ac_cv_lib_svld_dlopen" >&6; }
if test "x$ac_cv_lib_svld_dlopen" = xyes
then :
lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
printf %s "checking for dld_link in -ldld... " >&6; }
if test ${ac_cv_lib_dld_dld_link+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-ldld $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char dld_link (void);
int
main (void)
{
return dld_link ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_dld_dld_link=yes
else case e in #(
e) ac_cv_lib_dld_dld_link=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
printf "%s\n" "$ac_cv_lib_dld_dld_link" >&6; }
if test "x$ac_cv_lib_dld_dld_link" = xyes
then :
lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld
fi
;;
esac
fi
;;
esac
fi
;;
esac
fi
;;
esac
fi
;;
esac
fi
;;
esac
if test no = "$lt_cv_dlopen"; then
enable_dlopen=no
else
enable_dlopen=yes
fi
case $lt_cv_dlopen in
dlopen)
save_CPPFLAGS=$CPPFLAGS
test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
save_LDFLAGS=$LDFLAGS
wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
save_LIBS=$LIBS
LIBS="$lt_cv_dlopen_libs $LIBS"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
printf %s "checking whether a program can dlopen itself... " >&6; }
if test ${lt_cv_dlopen_self+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test yes = "$cross_compiling"; then :
lt_cv_dlopen_self=cross
else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line $LINENO "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
#include
#endif
#include
#ifdef RTLD_GLOBAL
# define LT_DLGLOBAL RTLD_GLOBAL
#else
# ifdef DL_GLOBAL
# define LT_DLGLOBAL DL_GLOBAL
# else
# define LT_DLGLOBAL 0
# endif
#endif
/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
find out it does not work in some platform. */
#ifndef LT_DLLAZY_OR_NOW
# ifdef RTLD_LAZY
# define LT_DLLAZY_OR_NOW RTLD_LAZY
# else
# ifdef DL_LAZY
# define LT_DLLAZY_OR_NOW DL_LAZY
# else
# ifdef RTLD_NOW
# define LT_DLLAZY_OR_NOW RTLD_NOW
# else
# ifdef DL_NOW
# define LT_DLLAZY_OR_NOW DL_NOW
# else
# define LT_DLLAZY_OR_NOW 0
# endif
# endif
# endif
# endif
#endif
/* When -fvisibility=hidden is used, assume the code has been annotated
correspondingly for the symbols needed. */
#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
int fnord (void) __attribute__((visibility("default")));
#endif
int fnord (void) { return 42; }
int main (void)
{
void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
int status = $lt_dlunknown;
if (self)
{
if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
else
{
if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
else puts (dlerror ());
}
/* dlclose (self); */
}
else
puts (dlerror ());
return status;
}
_LT_EOF
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
(eval $ac_link) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
(./conftest; exit; ) >&5 2>/dev/null
lt_status=$?
case x$lt_status in
x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
esac
else :
# compilation failed
lt_cv_dlopen_self=no
fi
fi
rm -fr conftest*
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
printf "%s\n" "$lt_cv_dlopen_self" >&6; }
if test yes = "$lt_cv_dlopen_self"; then
wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
printf %s "checking whether a statically linked program can dlopen itself... " >&6; }
if test ${lt_cv_dlopen_self_static+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test yes = "$cross_compiling"; then :
lt_cv_dlopen_self_static=cross
else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line $LINENO "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
#include
#endif
#include
#ifdef RTLD_GLOBAL
# define LT_DLGLOBAL RTLD_GLOBAL
#else
# ifdef DL_GLOBAL
# define LT_DLGLOBAL DL_GLOBAL
# else
# define LT_DLGLOBAL 0
# endif
#endif
/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
find out it does not work in some platform. */
#ifndef LT_DLLAZY_OR_NOW
# ifdef RTLD_LAZY
# define LT_DLLAZY_OR_NOW RTLD_LAZY
# else
# ifdef DL_LAZY
# define LT_DLLAZY_OR_NOW DL_LAZY
# else
# ifdef RTLD_NOW
# define LT_DLLAZY_OR_NOW RTLD_NOW
# else
# ifdef DL_NOW
# define LT_DLLAZY_OR_NOW DL_NOW
# else
# define LT_DLLAZY_OR_NOW 0
# endif
# endif
# endif
# endif
#endif
/* When -fvisibility=hidden is used, assume the code has been annotated
correspondingly for the symbols needed. */
#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
int fnord (void) __attribute__((visibility("default")));
#endif
int fnord (void) { return 42; }
int main (void)
{
void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
int status = $lt_dlunknown;
if (self)
{
if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
else
{
if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
else puts (dlerror ());
}
/* dlclose (self); */
}
else
puts (dlerror ());
return status;
}
_LT_EOF
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
(eval $ac_link) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
(./conftest; exit; ) >&5 2>/dev/null
lt_status=$?
case x$lt_status in
x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
esac
else :
# compilation failed
lt_cv_dlopen_self_static=no
fi
fi
rm -fr conftest*
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
printf "%s\n" "$lt_cv_dlopen_self_static" >&6; }
fi
CPPFLAGS=$save_CPPFLAGS
LDFLAGS=$save_LDFLAGS
LIBS=$save_LIBS
;;
esac
case $lt_cv_dlopen_self in
yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
*) enable_dlopen_self=unknown ;;
esac
case $lt_cv_dlopen_self_static in
yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
*) enable_dlopen_self_static=unknown ;;
esac
fi
striplib=
old_striplib=
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
printf %s "checking whether stripping libraries is possible... " >&6; }
if test -z "$STRIP"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
else
if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
old_striplib="$STRIP --strip-debug"
striplib="$STRIP --strip-unneeded"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
else
case $host_os in
darwin*)
# FIXME - insert some real tests, host_os isn't really good enough
striplib="$STRIP -x"
old_striplib="$STRIP -S"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
;;
freebsd*)
if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
old_striplib="$STRIP --strip-debug"
striplib="$STRIP --strip-unneeded"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
;;
*)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
;;
esac
fi
fi
# Report what library types will actually be built
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
printf %s "checking if libtool supports shared libraries... " >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
printf "%s\n" "$can_build_shared" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
printf %s "checking whether to build shared libraries... " >&6; }
test no = "$can_build_shared" && enable_shared=no
# On AIX, shared libraries and static libraries use the same namespace, and
# are all built from PIC.
case $host_os in
aix3*)
test yes = "$enable_shared" && enable_static=no
if test -n "$RANLIB"; then
archive_cmds="$archive_cmds~\$RANLIB \$lib"
postinstall_cmds='$RANLIB $lib'
fi
;;
aix[4-9]*)
if test ia64 != "$host_cpu"; then
case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
yes,aix,yes) ;; # shared object as lib.so file only
yes,svr4,*) ;; # shared object as lib.so archive member only
yes,*) enable_static=no ;; # shared object in lib.a archive as well
esac
fi
;;
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
printf "%s\n" "$enable_shared" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
printf %s "checking whether to build static libraries... " >&6; }
# Make sure either enable_shared or enable_static is yes.
test yes = "$enable_shared" || enable_static=yes
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
printf "%s\n" "$enable_static" >&6; }
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
CC=$lt_save_CC
ac_config_commands="$ac_config_commands libtool"
# Only expand once:
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_path_PKG_CONFIG+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) case $PKG_CONFIG in
[\\/]* | ?:[\\/]*)
ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac ;;
esac
fi
PKG_CONFIG=$ac_cv_path_PKG_CONFIG
if test -n "$PKG_CONFIG"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
printf "%s\n" "$PKG_CONFIG" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_path_PKG_CONFIG"; then
ac_pt_PKG_CONFIG=$PKG_CONFIG
# Extract the first word of "pkg-config", so it can be a program name with args.
set dummy pkg-config; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_path_ac_pt_PKG_CONFIG+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) case $ac_pt_PKG_CONFIG in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac ;;
esac
fi
ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
if test -n "$ac_pt_PKG_CONFIG"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_pt_PKG_CONFIG" = x; then
PKG_CONFIG=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
PKG_CONFIG=$ac_pt_PKG_CONFIG
fi
else
PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
fi
fi
if test -n "$PKG_CONFIG"; then
_pkg_min_version=0.9.0
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
PKG_CONFIG=""
fi
fi
if test -z "$PKG_CONFIG"; then
as_fn_error $? "pkg-config not found" "$LINENO" 5
fi
ac_config_headers="$ac_config_headers config.h"
ac_config_files="$ac_config_files Makefile doc/Doxyfile wimlib.pc"
ac_config_files="$ac_config_files programs/mkwinpeimg"
PKGCONFIG_PRIVATE_REQUIRES=""
PKGCONFIG_PRIVATE_LIBS=""
###############################################################################
# General platform features #
###############################################################################
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
else
CC="$ac_cv_prog_CC"
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
ac_prog_rejected=no
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
set dummy $ac_cv_prog_CC
shift
if test $# != 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
for ac_prog in cl.exe
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$CC" && break
done
fi
if test -z "$CC"; then
ac_ct_CC=$CC
for ac_prog in cl.exe
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$ac_ct_CC" && break
done
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
fi
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
set dummy ${ac_tool_prefix}clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}clang"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
printf "%s\n" "$CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "clang", so it can be a program name with args.
set dummy clang; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ac_ct_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="clang"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
printf "%s\n" "$ac_ct_CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
else
CC="$ac_cv_prog_CC"
fi
fi
test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See 'config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
sed '10a\
... rest of stderr output deleted ...
10q' conftest.err >conftest.er1
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
printf %s "checking whether the compiler supports GNU C... " >&6; }
if test ${ac_cv_c_compiler_gnu+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
#ifndef __GNUC__
choke me
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_compiler_gnu=yes
else case e in #(
e) ac_compiler_gnu=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
printf %s "checking whether $CC accepts -g... " >&6; }
if test ${ac_cv_prog_cc_g+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_g=yes
else case e in #(
e) CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
else case e in #(
e) ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_g=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-g"
fi
else
if test "$GCC" = yes; then
CFLAGS="-O2"
else
CFLAGS=
fi
fi
ac_prog_cc_stdc=no
if test x$ac_prog_cc_stdc = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
printf %s "checking for $CC option to enable C11 features... " >&6; }
if test ${ac_cv_prog_cc_c11+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_c_conftest_c11_program
_ACEOF
for ac_arg in '' -std=gnu11
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_c11=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c11" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC ;;
esac
fi
if test "x$ac_cv_prog_cc_c11" = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else case e in #(
e) if test "x$ac_cv_prog_cc_c11" = x
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
CC="$CC $ac_cv_prog_cc_c11" ;;
esac
fi
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
ac_prog_cc_stdc=c11 ;;
esac
fi
fi
if test x$ac_prog_cc_stdc = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
printf %s "checking for $CC option to enable C99 features... " >&6; }
if test ${ac_cv_prog_cc_c99+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_cv_prog_cc_c99=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_c_conftest_c99_program
_ACEOF
for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_c99=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c99" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC ;;
esac
fi
if test "x$ac_cv_prog_cc_c99" = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else case e in #(
e) if test "x$ac_cv_prog_cc_c99" = x
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
CC="$CC $ac_cv_prog_cc_c99" ;;
esac
fi
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
ac_prog_cc_stdc=c99 ;;
esac
fi
fi
if test x$ac_prog_cc_stdc = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
printf %s "checking for $CC option to enable C89 features... " >&6; }
if test ${ac_cv_prog_cc_c89+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_cv_prog_cc_c89=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_c_conftest_c89_program
_ACEOF
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"
then :
ac_cv_prog_cc_c89=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC ;;
esac
fi
if test "x$ac_cv_prog_cc_c89" = xno
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
printf "%s\n" "unsupported" >&6; }
else case e in #(
e) if test "x$ac_cv_prog_cc_c89" = x
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
printf "%s\n" "none needed" >&6; }
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
CC="$CC $ac_cv_prog_cc_c89" ;;
esac
fi
ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
ac_prog_cc_stdc=c89 ;;
esac
fi
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
printf %s "checking whether $CC understands -c and -o together... " >&6; }
if test ${am_cv_prog_cc_c_o+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
# Make sure it works both with $CC and with simple cc.
# Following AC_PROG_CC_C_O, we do the test twice because some
# compilers refuse to overwrite an existing .o file with -o,
# though they will create one.
am_cv_prog_cc_c_o=yes
for am_i in 1 2; do
if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } \
&& test -f conftest2.$ac_objext; then
: OK
else
am_cv_prog_cc_c_o=no
break
fi
done
# aligned with autoconf, so not including core; see bug#72225.
rm -f -r a.out a.exe b.out conftest.$ac_ext conftest.$ac_objext \
conftest.dSYM conftest1.$ac_ext conftest1.$ac_objext conftest1.dSYM \
conftest2.$ac_ext conftest2.$ac_objext conftest2.dSYM
unset am_i ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
printf "%s\n" "$am_cv_prog_cc_c_o" >&6; }
if test "$am_cv_prog_cc_c_o" != yes; then
# Losing compiler, so override with the script.
# FIXME: It is wrong to rewrite CC.
# But if we don't then we get into trouble of one sort or another.
# A longer-term fix would be to have automake use am__CC in this case,
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
CC="$am_aux_dir/compile $CC"
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
depcc="$CC" am_compiler_list=
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
printf %s "checking dependency style of $depcc... " >&6; }
if test ${am_cv_CC_dependencies_compiler_type+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
# We make a subdir and do the tests there. Otherwise we can end up
# making bogus files that we don't know about and never remove. For
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named 'D' -- because '-MD' means "put the output
# in D".
rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
cp "$am_depcomp" conftest.dir
cd conftest.dir
# We will build objects and dependencies in a subdirectory because
# it helps to detect inapplicable dependency modes. For instance
# both Tru64's cc and ICC support -MD to output dependencies as a
# side effect of compilation, but ICC will put the dependencies in
# the current directory while Tru64 will put them in the object
# directory.
mkdir sub
am_cv_CC_dependencies_compiler_type=none
if test "$am_compiler_list" = ""; then
am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
fi
am__universal=false
case " $depcc " in #(
*\ -arch\ *\ -arch\ *) am__universal=true ;;
esac
for depmode in $am_compiler_list; do
# Setup a source with many dependencies, because some compilers
# like to wrap large dependency lists on column 80 (with \), and
# we should not choose a depcomp mode which is confused by this.
#
# We need to recreate these files for each test, as the compiler may
# overwrite some of them when testing with obscure command lines.
# This happens at least with the AIX C compiler.
: > sub/conftest.c
for i in 1 2 3 4 5 6; do
echo '#include "conftst'$i'.h"' >> sub/conftest.c
# Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
# Solaris 10 /bin/sh.
echo '/* dummy */' > sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
# We check with '-c' and '-o' for the sake of the "dashmstdout"
# mode. It turns out that the SunPro C++ compiler does not properly
# handle '-M -o', and we need to detect this. Also, some Intel
# versions had trouble with output in subdirs.
am__obj=sub/conftest.${OBJEXT-o}
am__minus_obj="-o $am__obj"
case $depmode in
gcc)
# This depmode causes a compiler race in universal mode.
test "$am__universal" = false || continue
;;
nosideeffect)
# After this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested.
if test "x$enable_dependency_tracking" = xyes; then
continue
else
break
fi
;;
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok '-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
am__obj=conftest.${OBJEXT-o}
am__minus_obj=
;;
none) break ;;
esac
if depmode=$depmode \
source=sub/conftest.c object=$am__obj \
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
$SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
>/dev/null 2>conftest.err &&
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
# icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message
# that says an option was ignored or not supported.
# When given -MP, icc 7.0 and 7.1 complain thus:
# icc: Command line warning: ignoring option '-M'; no argument required
# The diagnosis changed in icc 8.0:
# icc: Command line remark: option '-MP' not supported
if (grep 'ignoring option' conftest.err ||
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
am_cv_CC_dependencies_compiler_type=$depmode
break
fi
fi
done
cd ..
rm -rf conftest.dir
else
am_cv_CC_dependencies_compiler_type=none
fi
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; }
CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
if
test "x$enable_dependency_tracking" != xno \
&& test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
am__fastdepCC_TRUE=
am__fastdepCC_FALSE='#'
else
am__fastdepCC_TRUE='#'
am__fastdepCC_FALSE=
fi
WINDOWS_NATIVE_BUILD="no"
PLATFORM_CPPFLAGS=""
PLATFORM_CFLAGS="-fvisibility=hidden"
PLATFORM_LDFLAGS=""
case "$host_os" in
mingw*)
# Native Windows
WINDOWS_NATIVE_BUILD="yes"
# -D__MINGW_USE_VC2005_COMPAT: make time_t 64-bit on 32-bit Windows.
PLATFORM_CPPFLAGS="-D_POSIX -D_POSIX_THREAD_SAFE_FUNCTIONS -DUNICODE -D_UNICODE -D_CRT_NON_CONFORMING_SWPRINTFS -D__MINGW_USE_VC2005_COMPAT -D_WIN32_WINNT=0x0600"
PLATFORM_CFLAGS="-municode -mno-ms-bitfields"
PLATFORM_LDFLAGS="-no-undefined"
WITH_NTFS_3G_DEFAULT="no"
WITH_FUSE_DEFAULT="no"
;;
linux*)
# Linux
WITH_NTFS_3G_DEFAULT="yes"
WITH_FUSE_DEFAULT="yes"
;;
*)
# Other UNIX
WITH_NTFS_3G_DEFAULT="yes"
WITH_FUSE_DEFAULT="no"
;;
esac
PLATFORM_CPPFLAGS=$PLATFORM_CPPFLAGS
PLATFORM_CFLAGS=$PLATFORM_CFLAGS
PLATFORM_LDFLAGS=$PLATFORM_LDFLAGS
if test "$WINDOWS_NATIVE_BUILD" = "yes"; then
WINDOWS_NATIVE_BUILD_TRUE=
WINDOWS_NATIVE_BUILD_FALSE='#'
else
WINDOWS_NATIVE_BUILD_TRUE='#'
WINDOWS_NATIVE_BUILD_FALSE=
fi
# Useful functions which we can do without.
ac_fn_c_check_func "$LINENO" "futimens" "ac_cv_func_futimens"
if test "x$ac_cv_func_futimens" = xyes
then :
printf "%s\n" "#define HAVE_FUTIMENS 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "utimensat" "ac_cv_func_utimensat"
if test "x$ac_cv_func_utimensat" = xyes
then :
printf "%s\n" "#define HAVE_UTIMENSAT 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "flock" "ac_cv_func_flock"
if test "x$ac_cv_func_flock" = xyes
then :
printf "%s\n" "#define HAVE_FLOCK 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "mempcpy" "ac_cv_func_mempcpy"
if test "x$ac_cv_func_mempcpy" = xyes
then :
printf "%s\n" "#define HAVE_MEMPCPY 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "openat" "ac_cv_func_openat"
if test "x$ac_cv_func_openat" = xyes
then :
printf "%s\n" "#define HAVE_OPENAT 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "fstatat" "ac_cv_func_fstatat"
if test "x$ac_cv_func_fstatat" = xyes
then :
printf "%s\n" "#define HAVE_FSTATAT 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "readlinkat" "ac_cv_func_readlinkat"
if test "x$ac_cv_func_readlinkat" = xyes
then :
printf "%s\n" "#define HAVE_READLINKAT 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "fdopendir" "ac_cv_func_fdopendir"
if test "x$ac_cv_func_fdopendir" = xyes
then :
printf "%s\n" "#define HAVE_FDOPENDIR 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "posix_fallocate" "ac_cv_func_posix_fallocate"
if test "x$ac_cv_func_posix_fallocate" = xyes
then :
printf "%s\n" "#define HAVE_POSIX_FALLOCATE 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "llistxattr" "ac_cv_func_llistxattr"
if test "x$ac_cv_func_llistxattr" = xyes
then :
printf "%s\n" "#define HAVE_LLISTXATTR 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "lgetxattr" "ac_cv_func_lgetxattr"
if test "x$ac_cv_func_lgetxattr" = xyes
then :
printf "%s\n" "#define HAVE_LGETXATTR 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "fsetxattr" "ac_cv_func_fsetxattr"
if test "x$ac_cv_func_fsetxattr" = xyes
then :
printf "%s\n" "#define HAVE_FSETXATTR 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "lsetxattr" "ac_cv_func_lsetxattr"
if test "x$ac_cv_func_lsetxattr" = xyes
then :
printf "%s\n" "#define HAVE_LSETXATTR 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "getopt_long_only" "ac_cv_func_getopt_long_only"
if test "x$ac_cv_func_getopt_long_only" = xyes
then :
printf "%s\n" "#define HAVE_GETOPT_LONG_ONLY 1" >>confdefs.h
fi
# Header checks, most of which are only here to satisfy conditional includes
# made by the libntfs-3g headers.
ac_fn_c_check_header_compile "$LINENO" "alloca.h" "ac_cv_header_alloca_h" "$ac_includes_default"
if test "x$ac_cv_header_alloca_h" = xyes
then :
printf "%s\n" "#define HAVE_ALLOCA_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "byteswap.h" "ac_cv_header_byteswap_h" "$ac_includes_default"
if test "x$ac_cv_header_byteswap_h" = xyes
then :
printf "%s\n" "#define HAVE_BYTESWAP_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "endian.h" "ac_cv_header_endian_h" "$ac_includes_default"
if test "x$ac_cv_header_endian_h" = xyes
then :
printf "%s\n" "#define HAVE_ENDIAN_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "errno.h" "ac_cv_header_errno_h" "$ac_includes_default"
if test "x$ac_cv_header_errno_h" = xyes
then :
printf "%s\n" "#define HAVE_ERRNO_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "glob.h" "ac_cv_header_glob_h" "$ac_includes_default"
if test "x$ac_cv_header_glob_h" = xyes
then :
printf "%s\n" "#define HAVE_GLOB_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "machine/endian.h" "ac_cv_header_machine_endian_h" "$ac_includes_default"
if test "x$ac_cv_header_machine_endian_h" = xyes
then :
printf "%s\n" "#define HAVE_MACHINE_ENDIAN_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "stdarg.h" "ac_cv_header_stdarg_h" "$ac_includes_default"
if test "x$ac_cv_header_stdarg_h" = xyes
then :
printf "%s\n" "#define HAVE_STDARG_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "stddef.h" "ac_cv_header_stddef_h" "$ac_includes_default"
if test "x$ac_cv_header_stddef_h" = xyes
then :
printf "%s\n" "#define HAVE_STDDEF_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
if test "x$ac_cv_header_stdlib_h" = xyes
then :
printf "%s\n" "#define HAVE_STDLIB_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "sys/byteorder.h" "ac_cv_header_sys_byteorder_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_byteorder_h" = xyes
then :
printf "%s\n" "#define HAVE_SYS_BYTEORDER_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "sys/endian.h" "ac_cv_header_sys_endian_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_endian_h" = xyes
then :
printf "%s\n" "#define HAVE_SYS_ENDIAN_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "sys/file.h" "ac_cv_header_sys_file_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_file_h" = xyes
then :
printf "%s\n" "#define HAVE_SYS_FILE_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "sys/syscall.h" "ac_cv_header_sys_syscall_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_syscall_h" = xyes
then :
printf "%s\n" "#define HAVE_SYS_SYSCALL_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" "ac_cv_header_sys_sysctl_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_sysctl_h" = xyes
then :
printf "%s\n" "#define HAVE_SYS_SYSCTL_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "sys/times.h" "ac_cv_header_sys_times_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_times_h" = xyes
then :
printf "%s\n" "#define HAVE_SYS_TIMES_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "sys/xattr.h" "ac_cv_header_sys_xattr_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_xattr_h" = xyes
then :
printf "%s\n" "#define HAVE_SYS_XATTR_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "time.h" "ac_cv_header_time_h" "$ac_includes_default"
if test "x$ac_cv_header_time_h" = xyes
then :
printf "%s\n" "#define HAVE_TIME_H 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "utime.h" "ac_cv_header_utime_h" "$ac_includes_default"
if test "x$ac_cv_header_utime_h" = xyes
then :
printf "%s\n" "#define HAVE_UTIME_H 1" >>confdefs.h
fi
# Does stat() support nanosecond-precision timestamps? (This is relevant on
# UNIX but not on Windows.)
ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "#include
"
if test "x$ac_cv_member_struct_stat_st_mtim" = xyes
then :
printf "%s\n" "#define HAVE_STAT_NANOSECOND_PRECISION 1" >>confdefs.h
fi
###############################################################################
# Required libraries #
###############################################################################
# ------------------------------ pthreads -------------------------------------
if test "$WINDOWS_NATIVE_BUILD" != "yes"; then
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
printf %s "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
if test ${ac_cv_prog_CPP+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) # Double quotes because $CC needs to be expanded
for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
do
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :
else case e in #(
e) # Broken: fails on valid input.
continue ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :
# Broken: success on invalid input.
continue
else case e in #(
e) # Passes both tests.
ac_preproc_ok=:
break ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok
then :
break
fi
done
ac_cv_prog_CPP=$CPP
;;
esac
fi
CPP=$ac_cv_prog_CPP
else
ac_cv_prog_CPP=$CPP
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
printf "%s\n" "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :
else case e in #(
e) # Broken: fails on valid input.
continue ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
_ACEOF
if ac_fn_c_try_cpp "$LINENO"
then :
# Broken: success on invalid input.
continue
else case e in #(
e) # Passes both tests.
ac_preproc_ok=:
break ;;
esac
fi
rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok
then :
else case e in #(
e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
See 'config.log' for more details" "$LINENO" 5; } ;;
esac
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep -e" >&5
printf %s "checking for egrep -e... " >&6; }
if test ${ac_cv_path_EGREP_TRADITIONAL+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -z "$EGREP_TRADITIONAL"; then
ac_path_EGREP_TRADITIONAL_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_prog in grep ggrep
do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_EGREP_TRADITIONAL="$as_dir$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_EGREP_TRADITIONAL" || continue
# Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found.
# Check for GNU $ac_path_EGREP_TRADITIONAL
case `"$ac_path_EGREP_TRADITIONAL" --version 2>&1` in #(
*GNU*)
ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_found=:;;
#(
*)
ac_count=0
printf %s 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
printf "%s\n" 'EGREP_TRADITIONAL' >> "conftest.nl"
"$ac_path_EGREP_TRADITIONAL" -E 'EGR(EP|AC)_TRADITIONAL$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL"
ac_path_EGREP_TRADITIONAL_max=$ac_count
fi
# 10*(2^10) chars as input seems more than enough
test $ac_count -gt 10 && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
$ac_path_EGREP_TRADITIONAL_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_EGREP_TRADITIONAL"; then
:
fi
else
ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL
fi
if test "$ac_cv_path_EGREP_TRADITIONAL"
then :
ac_cv_path_EGREP_TRADITIONAL="$ac_cv_path_EGREP_TRADITIONAL -E"
else case e in #(
e) if test -z "$EGREP_TRADITIONAL"; then
ac_path_EGREP_TRADITIONAL_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_prog in egrep
do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_EGREP_TRADITIONAL="$as_dir$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_EGREP_TRADITIONAL" || continue
# Check for GNU ac_path_EGREP_TRADITIONAL and select it if it is found.
# Check for GNU $ac_path_EGREP_TRADITIONAL
case `"$ac_path_EGREP_TRADITIONAL" --version 2>&1` in #(
*GNU*)
ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL" ac_path_EGREP_TRADITIONAL_found=:;;
#(
*)
ac_count=0
printf %s 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
printf "%s\n" 'EGREP_TRADITIONAL' >> "conftest.nl"
"$ac_path_EGREP_TRADITIONAL" 'EGR(EP|AC)_TRADITIONAL$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_EGREP_TRADITIONAL_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_EGREP_TRADITIONAL="$ac_path_EGREP_TRADITIONAL"
ac_path_EGREP_TRADITIONAL_max=$ac_count
fi
# 10*(2^10) chars as input seems more than enough
test $ac_count -gt 10 && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
$ac_path_EGREP_TRADITIONAL_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_EGREP_TRADITIONAL"; then
as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_EGREP_TRADITIONAL=$EGREP_TRADITIONAL
fi
;;
esac
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP_TRADITIONAL" >&5
printf "%s\n" "$ac_cv_path_EGREP_TRADITIONAL" >&6; }
EGREP_TRADITIONAL=$ac_cv_path_EGREP_TRADITIONAL
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on Tru64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
ax_pthread_save_CC="$CC"
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
if test "x$PTHREAD_CC" != "x"
then :
CC="$PTHREAD_CC"
fi
if test "x$PTHREAD_CXX" != "x"
then :
CXX="$PTHREAD_CXX"
fi
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5
printf %s "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char pthread_join (void);
int
main (void)
{
return pthread_join ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ax_pthread_ok=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5
printf "%s\n" "$ax_pthread_ok" >&6; }
if test "x$ax_pthread_ok" = "xno"; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
CC="$ax_pthread_save_CC"
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items with a "," contain both
# C compiler flags (before ",") and linker flags (after ","). Other items
# starting with a "-" are C compiler flags, and remaining items are
# library names, except for "none" which indicates that we try without
# any flags at all, and "pthread-config" which is a program returning
# the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
# (Note: HP C rejects this with "bad form for `-t' option")
# -pthreads: Solaris/gcc (Note: HP C also rejects)
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads and
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
# is present but should not be used directly; and before -mthreads,
# because the compiler interprets this as "-mt" + "-hreads")
# -mthreads: Mingw32/gcc, Lynx/gcc
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case $host_os in
freebsd*)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
;;
hpux*)
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
# multi-threading and also sets -lpthread."
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
;;
openedition*)
# IBM z/OS requires a feature-test macro to be defined in order to
# enable POSIX threads at all, so give the user a hint if this is
# not set. (We don't define these ourselves, as they can affect
# other portions of the system API in unpredictable ways.)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
AX_PTHREAD_ZOS_MISSING
# endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP_TRADITIONAL "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5
printf "%s\n" "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;}
fi
rm -rf conftest*
;;
solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (N.B.: The stubs are missing
# pthread_cleanup_push, or rather a function called by this macro,
# so we could check for that, but who knows whether they'll stub
# that too in a future libc.) So we'll check first for the
# standard Solaris way of linking pthreads (-mt -lpthread).
ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
;;
esac
# Are we compiling with Clang?
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5
printf %s "checking whether $CC is Clang... " >&6; }
if test ${ax_cv_PTHREAD_CLANG+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ax_cv_PTHREAD_CLANG=no
# Note that Autoconf sets GCC=yes for Clang as well as GCC
if test "x$GCC" = "xyes"; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
# if defined(__clang__) && defined(__llvm__)
AX_PTHREAD_CC_IS_CLANG
# endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP_TRADITIONAL "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1
then :
ax_cv_PTHREAD_CLANG=yes
fi
rm -rf conftest*
fi
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5
printf "%s\n" "$ax_cv_PTHREAD_CLANG" >&6; }
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
# Note that for GCC and Clang -pthread generally implies -lpthread,
# except when -nostdlib is passed.
# This is problematic using libtool to build C++ shared libraries with pthread:
# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
# To solve this, first try -pthread together with -lpthread for GCC
if test "x$GCC" = "xyes"
then :
ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"
fi
# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
if test "x$ax_pthread_clang" = "xyes"
then :
ax_pthread_flags="-pthread,-lpthread -pthread"
fi
# The presence of a feature test macro requesting re-entrant function
# definitions is, on some systems, a strong hint that pthreads support is
# correctly enabled
case $host_os in
darwin* | hpux* | linux* | osf* | solaris*)
ax_pthread_check_macro="_REENTRANT"
;;
aix*)
ax_pthread_check_macro="_THREAD_SAFE"
;;
*)
ax_pthread_check_macro="--"
;;
esac
if test "x$ax_pthread_check_macro" = "x--"
then :
ax_pthread_check_cond=0
else case e in #(
e) ax_pthread_check_cond="!defined($ax_pthread_check_macro)" ;;
esac
fi
if test "x$ax_pthread_ok" = "xno"; then
for ax_pthread_try_flag in $ax_pthread_flags; do
case $ax_pthread_try_flag in
none)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5
printf %s "checking whether pthreads work without any flags... " >&6; }
;;
*,*)
PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with \"$PTHREAD_CFLAGS\" and \"$PTHREAD_LIBS\"" >&5
printf %s "checking whether pthreads work with \"$PTHREAD_CFLAGS\" and \"$PTHREAD_LIBS\"... " >&6; }
;;
-*)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5
printf %s "checking whether pthreads work with $ax_pthread_try_flag... " >&6; }
PTHREAD_CFLAGS="$ax_pthread_try_flag"
;;
pthread-config)
# Extract the first word of "pthread-config", so it can be a program name with args.
set dummy pthread-config; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_ax_pthread_config+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$ax_pthread_config"; then
ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ax_pthread_config="yes"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no"
fi ;;
esac
fi
ax_pthread_config=$ac_cv_prog_ax_pthread_config
if test -n "$ax_pthread_config"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5
printf "%s\n" "$ax_pthread_config" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
if test "x$ax_pthread_config" = "xno"
then :
continue
fi
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5
printf %s "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; }
PTHREAD_LIBS="-l$ax_pthread_try_flag"
;;
esac
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
# if $ax_pthread_check_cond
# error "$ax_pthread_check_macro must be defined"
# endif
static void *some_global = NULL;
static void routine(void *a)
{
/* To avoid any unused-parameter or
unused-but-set-parameter warning. */
some_global = a;
}
static void *start_routine(void *a) { return a; }
int
main (void)
{
pthread_t th; pthread_attr_t attr;
pthread_create(&th, 0, start_routine, 0);
pthread_join(th, 0);
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_cleanup_pop(0) /* ; */
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ax_pthread_ok=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5
printf "%s\n" "$ax_pthread_ok" >&6; }
if test "x$ax_pthread_ok" = "xyes"
then :
break
fi
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Clang needs special handling, because older versions handle the -pthread
# option in a rather... idiosyncratic way
if test "x$ax_pthread_clang" = "xyes"; then
# Clang takes -pthread; it has never supported any other flag
# (Note 1: This will need to be revisited if a system that Clang
# supports has POSIX threads in a separate library. This tends not
# to be the way of modern systems, but it's conceivable.)
# (Note 2: On some systems, notably Darwin, -pthread is not needed
# to get POSIX threads support; the API is always present and
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
# -pthread does define _REENTRANT, and while the Darwin headers
# ignore this macro, third-party headers might not.)
# However, older versions of Clang make a point of warning the user
# that, in an invocation where only linking and no compilation is
# taking place, the -pthread option has no effect ("argument unused
# during compilation"). They expect -pthread to be passed in only
# when source code is being compiled.
#
# Problem is, this is at odds with the way Automake and most other
# C build frameworks function, which is that the same flags used in
# compilation (CFLAGS) are also used in linking. Many systems
# supported by AX_PTHREAD require exactly this for POSIX threads
# support, and in fact it is often not straightforward to specify a
# flag that is used only in the compilation phase and not in
# linking. Such a scenario is extremely rare in practice.
#
# Even though use of the -pthread flag in linking would only print
# a warning, this can be a nuisance for well-run software projects
# that build with -Werror. So if the active version of Clang has
# this misfeature, we search for an option to squash it.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5
printf %s "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; }
if test ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
# Create an alternate version of $ac_link that compiles and
# links in two steps (.c -> .o, .o -> exe) instead of one
# (.c -> exe), because the warning occurs only in the second
# step
ax_pthread_save_ac_link="$ac_link"
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
ax_pthread_link_step=`printf "%s\n" "$ac_link" | sed "$ax_pthread_sed"`
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
ax_pthread_save_CFLAGS="$CFLAGS"
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
if test "x$ax_pthread_try" = "xunknown"
then :
break
fi
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
ac_link="$ax_pthread_save_ac_link"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void){return 0;}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_link="$ax_pthread_2step_ac_link"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void){return 0;}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
done
ac_link="$ax_pthread_save_ac_link"
CFLAGS="$ax_pthread_save_CFLAGS"
if test "x$ax_pthread_try" = "x"
then :
ax_pthread_try=no
fi
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5
printf "%s\n" "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; }
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
no | unknown) ;;
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
esac
fi # $ax_pthread_clang = yes
# Various other checks:
if test "x$ax_pthread_ok" = "xyes"; then
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5
printf %s "checking for joinable pthread attribute... " >&6; }
if test ${ax_cv_PTHREAD_JOINABLE_ATTR+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ax_cv_PTHREAD_JOINABLE_ATTR=unknown
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
int
main (void)
{
int attr = $ax_pthread_attr; return attr /* ; */
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
done
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5
printf "%s\n" "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; }
if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
test "x$ax_pthread_joinable_attr_defined" != "xyes"
then :
printf "%s\n" "#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR" >>confdefs.h
ax_pthread_joinable_attr_defined=yes
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5
printf %s "checking whether more special flags are required for pthreads... " >&6; }
if test ${ax_cv_PTHREAD_SPECIAL_FLAGS+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ax_cv_PTHREAD_SPECIAL_FLAGS=no
case $host_os in
solaris*)
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
;;
esac
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5
printf "%s\n" "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; }
if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
test "x$ax_pthread_special_flags_added" != "xyes"
then :
PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
ax_pthread_special_flags_added=yes
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5
printf %s "checking for PTHREAD_PRIO_INHERIT... " >&6; }
if test ${ax_cv_PTHREAD_PRIO_INHERIT+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include
int
main (void)
{
int i = PTHREAD_PRIO_INHERIT;
return i;
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ax_cv_PTHREAD_PRIO_INHERIT=yes
else case e in #(
e) ax_cv_PTHREAD_PRIO_INHERIT=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5
printf "%s\n" "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; }
if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
test "x$ax_pthread_prio_inherit_defined" != "xyes"
then :
printf "%s\n" "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h
ax_pthread_prio_inherit_defined=yes
fi
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
# More AIX lossage: compile with *_r variant
if test "x$GCC" != "xyes"; then
case $host_os in
aix*)
case "x/$CC" in #(
x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) :
#handle absolute path differently from PATH based program lookup
case "x$CC" in #(
x/*) :
if as_fn_executable_p ${CC}_r
then :
PTHREAD_CC="${CC}_r"
fi
if test "x${CXX}" != "x"
then :
if as_fn_executable_p ${CXX}_r
then :
PTHREAD_CXX="${CXX}_r"
fi
fi
;; #(
*) :
for ac_prog in ${CC}_r
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_PTHREAD_CC+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$PTHREAD_CC"; then
ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_PTHREAD_CC="$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
PTHREAD_CC=$ac_cv_prog_PTHREAD_CC
if test -n "$PTHREAD_CC"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5
printf "%s\n" "$PTHREAD_CC" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$PTHREAD_CC" && break
done
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
if test "x${CXX}" != "x"
then :
for ac_prog in ${CXX}_r
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
printf %s "checking for $ac_word... " >&6; }
if test ${ac_cv_prog_PTHREAD_CXX+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test -n "$PTHREAD_CXX"; then
ac_cv_prog_PTHREAD_CXX="$PTHREAD_CXX" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_PTHREAD_CXX="$ac_prog"
printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi ;;
esac
fi
PTHREAD_CXX=$ac_cv_prog_PTHREAD_CXX
if test -n "$PTHREAD_CXX"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CXX" >&5
printf "%s\n" "$PTHREAD_CXX" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
test -n "$PTHREAD_CXX" && break
done
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
fi
;;
esac
;; #(
*) :
;;
esac
;;
esac
fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test "x$ax_pthread_ok" = "xyes"; then
printf "%s\n" "#define HAVE_PTHREAD 1" >>confdefs.h
:
else
ax_pthread_ok=no
as_fn_error $? "\"cannot find pthreads library\"" "$LINENO" 5
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
fi
###############################################################################
# Configuration options #
###############################################################################
# ------------------------- ntfs-3g support -----------------------------------
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to include support for ntfs-3g" >&5
printf %s "checking whether to include support for ntfs-3g... " >&6; }
# Check whether --with-ntfs-3g was given.
if test ${with_ntfs_3g+y}
then :
withval=$with_ntfs_3g; WITH_NTFS_3G=$withval
else case e in #(
e) WITH_NTFS_3G=$WITH_NTFS_3G_DEFAULT ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WITH_NTFS_3G" >&5
printf "%s\n" "$WITH_NTFS_3G" >&6; }
if test "$WITH_NTFS_3G" = "yes"; then
pkg_failed=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libntfs-3g >= 2011.4.12" >&5
printf %s "checking for libntfs-3g >= 2011.4.12... " >&6; }
if test -n "$LIBNTFS_3G_CFLAGS"; then
pkg_cv_LIBNTFS_3G_CFLAGS="$LIBNTFS_3G_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libntfs-3g >= 2011.4.12\""; } >&5
($PKG_CONFIG --exists --print-errors "libntfs-3g >= 2011.4.12") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LIBNTFS_3G_CFLAGS=`$PKG_CONFIG --cflags "libntfs-3g >= 2011.4.12" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$LIBNTFS_3G_LIBS"; then
pkg_cv_LIBNTFS_3G_LIBS="$LIBNTFS_3G_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libntfs-3g >= 2011.4.12\""; } >&5
($PKG_CONFIG --exists --print-errors "libntfs-3g >= 2011.4.12") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LIBNTFS_3G_LIBS=`$PKG_CONFIG --libs "libntfs-3g >= 2011.4.12" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test $pkg_failed = yes; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
LIBNTFS_3G_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libntfs-3g >= 2011.4.12" 2>&1`
else
LIBNTFS_3G_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libntfs-3g >= 2011.4.12" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$LIBNTFS_3G_PKG_ERRORS" >&5
as_fn_error $? "Cannot find libntfs-3g version 2011-4-12 or
later! Without libntfs-3g, wimlib cannot include support for
capturing or applying a WIM image directly from/to an unmounted
NTFS volume while preserving NTFS-specific data such as
security descriptors and named data streams. Either install
libntfs-3g, or configure --without-ntfs-3g to disable this
feature. If your operating system packages development files
separately, the package you need to install may be called
ntfs-3g-dev, ntfs-3g-devel, or similar." "$LINENO" 5
elif test $pkg_failed = untried; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
as_fn_error $? "Cannot find libntfs-3g version 2011-4-12 or
later! Without libntfs-3g, wimlib cannot include support for
capturing or applying a WIM image directly from/to an unmounted
NTFS volume while preserving NTFS-specific data such as
security descriptors and named data streams. Either install
libntfs-3g, or configure --without-ntfs-3g to disable this
feature. If your operating system packages development files
separately, the package you need to install may be called
ntfs-3g-dev, ntfs-3g-devel, or similar." "$LINENO" 5
else
LIBNTFS_3G_CFLAGS=$pkg_cv_LIBNTFS_3G_CFLAGS
LIBNTFS_3G_LIBS=$pkg_cv_LIBNTFS_3G_LIBS
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
fi
PKGCONFIG_PRIVATE_REQUIRES="$PKGCONFIG_PRIVATE_REQUIRES libntfs-3g"
printf "%s\n" "#define WITH_NTFS_3G 1" >>confdefs.h
fi
if test "$WITH_NTFS_3G" = "yes"; then
WITH_NTFS_3G_TRUE=
WITH_NTFS_3G_FALSE='#'
else
WITH_NTFS_3G_TRUE='#'
WITH_NTFS_3G_FALSE=
fi
# ------------------------ FUSE mount support ---------------------------------
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to include support for mounting WIMs" >&5
printf %s "checking whether to include support for mounting WIMs... " >&6; }
# Check whether --with-fuse was given.
if test ${with_fuse+y}
then :
withval=$with_fuse; WITH_FUSE=$withval
else case e in #(
e) WITH_FUSE=$WITH_FUSE_DEFAULT ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WITH_FUSE" >&5
printf "%s\n" "$WITH_FUSE" >&6; }
if test "$WITH_FUSE" = "yes"; then
pkg_failed=no
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fuse3" >&5
printf %s "checking for fuse3... " >&6; }
if test -n "$LIBFUSE_CFLAGS"; then
pkg_cv_LIBFUSE_CFLAGS="$LIBFUSE_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"fuse3\""; } >&5
($PKG_CONFIG --exists --print-errors "fuse3") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LIBFUSE_CFLAGS=`$PKG_CONFIG --cflags "fuse3" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$LIBFUSE_LIBS"; then
pkg_cv_LIBFUSE_LIBS="$LIBFUSE_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"fuse3\""; } >&5
($PKG_CONFIG --exists --print-errors "fuse3") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LIBFUSE_LIBS=`$PKG_CONFIG --libs "fuse3" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test $pkg_failed = yes; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
LIBFUSE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "fuse3" 2>&1`
else
LIBFUSE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "fuse3" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$LIBFUSE_PKG_ERRORS" >&5
as_fn_error $? "Cannot find libfuse3!
Without libfuse3, wimlib cannot include support for mounting WIM
images. Either install libfuse3, or configure --without-fuse to
disable this feature. If your operating system packages
development files separately, the package you need to install
may be called libfuse3-dev, fuse-devel, or similar." "$LINENO" 5
elif test $pkg_failed = untried; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
as_fn_error $? "Cannot find libfuse3!
Without libfuse3, wimlib cannot include support for mounting WIM
images. Either install libfuse3, or configure --without-fuse to
disable this feature. If your operating system packages
development files separately, the package you need to install
may be called libfuse3-dev, fuse-devel, or similar." "$LINENO" 5
else
LIBFUSE_CFLAGS=$pkg_cv_LIBFUSE_CFLAGS
LIBFUSE_LIBS=$pkg_cv_LIBFUSE_LIBS
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
fi
PKGCONFIG_PRIVATE_REQUIRES="$PKGCONFIG_PRIVATE_REQUIRES fuse"
printf "%s\n" "#define WITH_FUSE 1" >>confdefs.h
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mq_open in -lrt" >&5
printf %s "checking for mq_open in -lrt... " >&6; }
if test ${ac_cv_lib_rt_mq_open+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char mq_open (void);
int
main (void)
{
return mq_open ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_rt_mq_open=yes
else case e in #(
e) ac_cv_lib_rt_mq_open=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_mq_open" >&5
printf "%s\n" "$ac_cv_lib_rt_mq_open" >&6; }
if test "x$ac_cv_lib_rt_mq_open" = xyes
then :
printf "%s\n" "#define HAVE_LIBRT 1" >>confdefs.h
LIBS="-lrt $LIBS"
else case e in #(
e) as_fn_error $? "Cannot find librt (the POSIX.1b Realtime
Extensions Library)! wimlib needs this for the POSIX message queue
functions, which are used in the code for mounting WIM images. Recent
versions of glibc include this library. Either install this library, or
configure --without-fuse to disable support for mounting WIM images." "$LINENO" 5 ;;
esac
fi
PKGCONFIG_PRIVATE_LIBS="$PKGCONFIG_PRIVATE_LIBS -lrt"
LIBRT_LIBS=-lrt
fi
if test "$WITH_FUSE" = "yes"; then
WITH_FUSE_TRUE=
WITH_FUSE_FALSE='#'
else
WITH_FUSE_TRUE='#'
WITH_FUSE_FALSE=
fi
# ----------------------------- Other options ---------------------------------
# Check whether --with-pkgconfigdir was given.
if test ${with_pkgconfigdir+y}
then :
withval=$with_pkgconfigdir; pkgconfigdir=$withval
else case e in #(
e) pkgconfigdir='${libdir}/pkgconfig' ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable supporting code for tests" >&5
printf %s "checking whether to enable supporting code for tests... " >&6; }
# Check whether --enable-test-support was given.
if test ${enable_test_support+y}
then :
enableval=$enable_test_support; ENABLE_TEST_SUPPORT=$enableval
else case e in #(
e) ENABLE_TEST_SUPPORT=no ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ENABLE_TEST_SUPPORT" >&5
printf "%s\n" "$ENABLE_TEST_SUPPORT" >&6; }
if test "$ENABLE_TEST_SUPPORT" = "yes" ; then
printf "%s\n" "#define ENABLE_TEST_SUPPORT 1" >>confdefs.h
fi
if test "$ENABLE_TEST_SUPPORT" = "yes"; then
ENABLE_TEST_SUPPORT_TRUE=
ENABLE_TEST_SUPPORT_FALSE='#'
else
ENABLE_TEST_SUPPORT_TRUE='#'
ENABLE_TEST_SUPPORT_FALSE=
fi
###############################################################################
PKGCONFIG_PRIVATE_REQUIRES=$PKGCONFIG_PRIVATE_REQUIRES
PKGCONFIG_PRIVATE_LIBS=$PKGCONFIG_PRIVATE_LIBS
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems. If it contains results you don't
# want to keep, you may remove or edit it.
#
# config.status only pays attention to the cache file if you give it
# the --recheck option to rerun configure.
#
# 'ac_cv_env_foo' variables (set or unset) will be overridden when
# loading this file, other *unset* 'ac_cv_foo' will be assigned the
# following values.
_ACEOF
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, we kill variables containing newlines.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(
for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
eval ac_val=\$$ac_var
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
*_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
*) { eval $ac_var=; unset $ac_var;} ;;
esac ;;
esac
done
(set) 2>&1 |
case $as_nl`(ac_space=' '; set) 2>&1` in #(
*${as_nl}ac_space=\ *)
# 'set' does not quote correctly, so add quotes: double-quote
# substitution turns \\\\ into \\, and sed turns \\ into \.
sed -n \
"s/'/'\\\\''/g;
s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
;; #(
*)
# 'set' quotes correctly as required by POSIX, so do not add quotes.
sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
;;
esac |
sort
) |
sed '
/^ac_cv_env_/b end
t clear
:clear
s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
case $cache_file in #(
*/* | ?:*)
mv -f confcache "$cache_file"$$ &&
mv -f "$cache_file"$$ "$cache_file" ;; #(
*)
mv -f confcache "$cache_file" ;;
esac
fi
fi
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
DEFS=-DHAVE_CONFIG_H
ac_libobjs=
ac_ltlibobjs=
U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
done
LIBOBJS=$ac_libobjs
LTLIBOBJS=$ac_ltlibobjs
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
printf %s "checking that generated files are newer than configure... " >&6; }
if test -n "$am_sleep_pid"; then
# Hide warnings about reused PIDs.
wait $am_sleep_pid 2>/dev/null
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5
printf "%s\n" "done" >&6; }
case $enable_silent_rules in # (((
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
esac
if test $am_cv_make_support_nested_variables = yes; then
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
if test -n "$EXEEXT"; then
am__EXEEXT_TRUE=
am__EXEEXT_FALSE='#'
else
am__EXEEXT_TRUE='#'
am__EXEEXT_FALSE=
fi
if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
as_fn_error $? "conditional \"AMDEP\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${WINDOWS_NATIVE_BUILD_TRUE}" && test -z "${WINDOWS_NATIVE_BUILD_FALSE}"; then
as_fn_error $? "conditional \"WINDOWS_NATIVE_BUILD\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${WITH_NTFS_3G_TRUE}" && test -z "${WITH_NTFS_3G_FALSE}"; then
as_fn_error $? "conditional \"WITH_NTFS_3G\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${WITH_FUSE_TRUE}" && test -z "${WITH_FUSE_FALSE}"; then
as_fn_error $? "conditional \"WITH_FUSE\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${ENABLE_TEST_SUPPORT_TRUE}" && test -z "${ENABLE_TEST_SUPPORT_FALSE}"; then
as_fn_error $? "conditional \"ENABLE_TEST_SUPPORT\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.
debug=false
ac_cs_recheck=false
ac_cs_silent=false
SHELL=\${CONFIG_SHELL-$SHELL}
export SHELL
_ASEOF
cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else case e in #(
e) case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac ;;
esac
fi
# Reset variables that may have inherited troublesome values from
# the environment.
# IFS needs to be set, to space, tab, and newline, in precisely that order.
# (If _AS_PATH_WALK were called with IFS unset, it would have the
# side effect of setting IFS to empty, thus disabling word splitting.)
# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
IFS=" "" $as_nl"
PS1='$ '
PS2='> '
PS4='+ '
# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE
# We cannot yet rely on "unset" to work, but we need these variables
# to be unset--not just set to an empty or harmless value--now, to
# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
# also avoids known problems related to "unset" and subshell syntax
# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
do eval test \${$as_var+y} \
&& ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
# Ensure that fds 0, 1, and 2 are open.
if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
PATH_SEPARATOR=';'
}
fi
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
case $as_dir in #(((
'') as_dir=./ ;;
*/) ;;
*) as_dir=$as_dir/ ;;
esac
test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
;;
esac
# We did not find ourselves, most probably we were run as 'sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
return $1
} # as_fn_set_status
# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
set +e
as_fn_set_status $1
exit $1
} # as_fn_exit
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
else case e in #(
e) as_fn_append ()
{
eval $1=\$$1\$2
} ;;
esac
fi # as_fn_append
# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
else case e in #(
e) as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
} ;;
esac
fi # as_fn_arith
if expr a : '\(a\)' >/dev/null 2>&1 &&
test "X`expr 00001 : '.*\(...\)'`" = X001; then
as_expr=expr
else
as_expr=false
fi
if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
as_dirname=dirname
else
as_dirname=false
fi
as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
}
/^X\/\(\/\/\)$/{
s//\1/
q
}
/^X\/\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
# Determine whether it's possible to make 'echo' print without a newline.
# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
case `echo 'xy\c'` in
*c*) ECHO_T=' ';; # ECHO_T is single tab character.
xy) ECHO_C='\c';;
*) echo `echo ksh88 bug on AIX 6.1` > /dev/null
ECHO_T=' ';;
esac;;
*)
ECHO_N='-n';;
esac
# For backward compatibility with old third-party macros, we provide
# the shell variables $as_echo and $as_echo_n. New code should use
# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
as_echo='printf %s\n'
as_echo_n='printf %s'
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
else
rm -f conf$$.dir
mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
if ln -s conf$$.file conf$$ 2>/dev/null; then
as_ln_s='ln -s'
# ... but there are two gotchas:
# 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
# In both cases, we have to default to 'cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -pR'
fi
else
as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{
case $as_dir in #(
-*) as_dir=./$as_dir;;
esac
test -d "$as_dir" || eval $as_mkdir_p || {
as_dirs=
while :; do
case $as_dir in #(
*\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
test -d "$as_dir" && break
done
test -z "$as_dirs" || eval "mkdir $as_dirs"
} || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
} # as_fn_mkdir_p
if mkdir -p . 2>/dev/null; then
as_mkdir_p='mkdir -p "$as_dir"'
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
test -f "$1" && test -x "$1"
} # as_fn_executable_p
as_test_x='test -x'
as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated
# Sed expression to map a string onto a valid variable name.
as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
as_tr_sh="eval sed '$as_sed_sh'" # deprecated
exec 6>&1
## ----------------------------------- ##
## Main body of $CONFIG_STATUS script. ##
## ----------------------------------- ##
_ASEOF
test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by wimlib $as_me 1.14.5, which was
generated by GNU Autoconf 2.72. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
CONFIG_LINKS = $CONFIG_LINKS
CONFIG_COMMANDS = $CONFIG_COMMANDS
$ $0 $@
on `(hostname || uname -n) 2>/dev/null | sed 1q`
"
_ACEOF
case $ac_config_files in *"
"*) set x $ac_config_files; shift; ac_config_files=$*;;
esac
case $ac_config_headers in *"
"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
esac
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# Files that config.status was made for.
config_files="$ac_config_files"
config_headers="$ac_config_headers"
config_commands="$ac_config_commands"
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
'$as_me' instantiates files and other configuration actions
from templates according to the current configuration. Unless the files
and actions are specified as TAGs, all are instantiated by default.
Usage: $0 [OPTION]... [TAG]...
-h, --help print this help, then exit
-V, --version print version number and configuration settings, then exit
--config print configuration, then exit
-q, --quiet, --silent
do not print progress messages
-d, --debug don't remove temporary files
--recheck update $as_me by reconfiguring in the same conditions
--file=FILE[:TEMPLATE]
instantiate the configuration file FILE
--header=FILE[:TEMPLATE]
instantiate the configuration header FILE
Configuration files:
$config_files
Configuration headers:
$config_headers
Configuration commands:
$config_commands
Report bugs to ."
_ACEOF
ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
wimlib config.status 1.14.5
configured by $0, generated by GNU Autoconf 2.72,
with options \\"\$ac_cs_config\\"
Copyright (C) 2023 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
ac_pwd='$ac_pwd'
srcdir='$srcdir'
INSTALL='$INSTALL'
MKDIR_P='$MKDIR_P'
AWK='$AWK'
test -n "\$AWK" || AWK=awk
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# The default lists apply if the user does not specify any file.
ac_need_defaults=:
while test $# != 0
do
case $1 in
--*=?*)
ac_option=`expr "X$1" : 'X\([^=]*\)='`
ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
ac_shift=:
;;
--*=)
ac_option=`expr "X$1" : 'X\([^=]*\)='`
ac_optarg=
ac_shift=:
;;
*)
ac_option=$1
ac_optarg=$2
ac_shift=shift
;;
esac
case $ac_option in
# Handling of the options.
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
*\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--header | --heade | --head | --hea )
$ac_shift
case $ac_optarg in
*\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
as_fn_append CONFIG_HEADERS " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h)
# Conflict between --help and --header
as_fn_error $? "ambiguous option: '$1'
Try '$0 --help' for more information.";;
--help | --hel | -h )
printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
# This is an error.
-*) as_fn_error $? "unrecognized option: '$1'
Try '$0 --help' for more information." ;;
*) as_fn_append ac_config_targets " $1"
ac_need_defaults=false ;;
esac
shift
done
ac_configure_extra_args=
if $ac_cs_silent; then
exec 6>/dev/null
ac_configure_extra_args="$ac_configure_extra_args --silent"
fi
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
\printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
fi
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
exec 5>>config.log
{
echo
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
printf "%s\n" "$ac_log"
} >&5
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
#
# INIT-COMMANDS
#
AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
# The HP-UX ksh and POSIX shell print the target directory to stdout
# if CDPATH is set.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
sed_quote_subst='$sed_quote_subst'
double_quote_subst='$double_quote_subst'
delay_variable_subst='$delay_variable_subst'
macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
enable_cxx_stdlib='`$ECHO "$enable_cxx_stdlib" | $SED "$delay_single_quote_subst"`'
stdlibflag='`$ECHO "$stdlibflag" | $SED "$delay_single_quote_subst"`'
enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`'
SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
lt_cv_cygpath_installed='`$ECHO "$lt_cv_cygpath_installed" | $SED "$delay_single_quote_subst"`'
reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`'
OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`'
AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`'
lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`'
nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`'
objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`'
hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
LTCC='$LTCC'
LTCFLAGS='$LTCFLAGS'
compiler='$compiler_DEFAULT'
# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
\$1
_LTECHO_EOF'
}
# Quote evaled strings.
for var in SHELL \
ECHO \
PATH_SEPARATOR \
SED \
GREP \
EGREP \
FGREP \
LD \
NM \
LN_S \
lt_SP2NL \
lt_NL2SP \
reload_flag \
FILECMD \
OBJDUMP \
deplibs_check_method \
file_magic_cmd \
file_magic_glob \
want_nocaseglob \
DLLTOOL \
sharedlib_from_linklib_cmd \
AR \
lt_ar_flags \
archiver_list_spec \
STRIP \
RANLIB \
CC \
CFLAGS \
compiler \
lt_cv_sys_global_symbol_pipe \
lt_cv_sys_global_symbol_to_cdecl \
lt_cv_sys_global_symbol_to_import \
lt_cv_sys_global_symbol_to_c_name_address \
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
lt_cv_nm_interface \
nm_file_list_spec \
lt_cv_truncate_bin \
lt_prog_compiler_no_builtin_flag \
lt_prog_compiler_pic \
lt_prog_compiler_wl \
lt_prog_compiler_static \
lt_cv_prog_compiler_c_o \
need_locks \
MANIFEST_TOOL \
DSYMUTIL \
NMEDIT \
LIPO \
OTOOL \
OTOOL64 \
shrext_cmds \
export_dynamic_flag_spec \
whole_archive_flag_spec \
compiler_needs_object \
with_gnu_ld \
allow_undefined_flag \
no_undefined_flag \
hardcode_libdir_flag_spec \
hardcode_libdir_separator \
exclude_expsyms \
include_expsyms \
file_list_spec \
variables_saved_for_relink \
libname_spec \
library_names_spec \
soname_spec \
install_override_mode \
finish_eval \
old_striplib \
striplib; do
case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
*[\\\\\\\`\\"\\\$]*)
eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
;;
*)
eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
;;
esac
done
# Double-quote double-evaled strings.
for var in reload_cmds \
old_postinstall_cmds \
old_postuninstall_cmds \
old_archive_cmds \
extract_expsyms_cmds \
old_archive_from_new_cmds \
old_archive_from_expsyms_cmds \
archive_cmds \
archive_expsym_cmds \
module_cmds \
module_expsym_cmds \
export_symbols_cmds \
prelink_cmds \
postlink_cmds \
postinstall_cmds \
postuninstall_cmds \
finish_cmds \
sys_lib_search_path_spec \
configure_time_dlsearch_path \
configure_time_lt_sys_library_path; do
case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
*[\\\\\\\`\\"\\\$]*)
eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
;;
*)
eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
;;
esac
done
ac_aux_dir='$ac_aux_dir'
# See if we are running on zsh, and set the options that allow our
# commands through without removal of \ escapes INIT.
if test -n "\${ZSH_VERSION+set}"; then
setopt NO_GLOB_SUBST
fi
PACKAGE='$PACKAGE'
VERSION='$VERSION'
RM='$RM'
ofile='$ofile'
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Handling of arguments.
for ac_config_target in $ac_config_targets
do
case $ac_config_target in
"depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
"libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"doc/Doxyfile") CONFIG_FILES="$CONFIG_FILES doc/Doxyfile" ;;
"wimlib.pc") CONFIG_FILES="$CONFIG_FILES wimlib.pc" ;;
"programs/mkwinpeimg") CONFIG_FILES="$CONFIG_FILES programs/mkwinpeimg" ;;
*) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;;
esac
done
# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used. Set only those that are not.
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers
test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands
fi
# Have a temporary directory for convenience. Make it in the build tree
# simply because there is no reason against having it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
# Hook for its removal unless debugging.
# Note that there is a small window in which the directory will not be cleaned:
# after its creation but before its name has been assigned to '$tmp'.
$debug ||
{
tmp= ac_tmp=
trap 'exit_status=$?
: "${ac_tmp:=$tmp}"
{ test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
' 0
trap 'as_fn_exit 1' 1 2 13 15
}
# Create a (secure) tmp directory for tmp files.
{
tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
test -d "$tmp"
} ||
{
tmp=./conf$$-$RANDOM
(umask 077 && mkdir "$tmp")
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
ac_tmp=$tmp
# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
# This happens for instance with './config.status config.h'.
if test -n "$CONFIG_FILES"; then
ac_cr=`echo X | tr X '\015'`
# On cygwin, bash can eat \r inside `` if the user requested igncr.
# But we know of no other shell where ac_cr would be empty at this
# point, so we can use a bashism as a fallback.
if test "x$ac_cr" = x; then
eval ac_cr=\$\'\\r\'
fi
ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null`
if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
ac_cs_awk_cr='\\r'
else
ac_cs_awk_cr=$ac_cr
fi
echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
_ACEOF
{
echo "cat >conf$$subs.awk <<_ACEOF" &&
echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
echo "_ACEOF"
} >conf$$subs.sh ||
as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
. ./conf$$subs.sh ||
as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
if test $ac_delim_n = $ac_delim_num; then
break
elif $ac_last_try; then
as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
done
rm -f conf$$subs.sh
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
_ACEOF
sed -n '
h
s/^/S["/; s/!.*/"]=/
p
g
s/^[^!]*!//
:repl
t repl
s/'"$ac_delim"'$//
t delim
:nl
h
s/\(.\{148\}\)..*/\1/
t more1
s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
p
n
b repl
:more1
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t nl
:delim
h
s/\(.\{148\}\)..*/\1/
t more2
s/["\\]/\\&/g; s/^/"/; s/$/"/
p
b
:more2
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t delim
' >$CONFIG_STATUS || ac_write_fail=1
rm -f conf$$subs.awk
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACAWK
cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
for (key in S) S_is_set[key] = 1
FS = ""
}
{
line = $ 0
nfields = split(line, field, "@")
substed = 0
len = length(field[1])
for (i = 2; i < nfields; i++) {
key = field[i]
keylen = length(key)
if (S_is_set[key]) {
value = S[key]
line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
len += length(value) + length(field[++i])
substed = 1
} else
len += 1 + keylen
}
print line
}
_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
else
cat
fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
|| as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF
# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
h
s///
s/^/:/
s/[ ]*$/:/
s/:\$(srcdir):/:/g
s/:\${srcdir}:/:/g
s/:@srcdir@:/:/g
s/^:*//
s/:*$//
x
s/\(=[ ]*\).*/\1/
G
s/\n//
s/^[^=]*=[ ]*$//
}'
fi
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
fi # test -n "$CONFIG_FILES"
# Set up the scripts for CONFIG_HEADERS section.
# No need to generate them if there are no CONFIG_HEADERS.
# This happens for instance with './config.status Makefile'.
if test -n "$CONFIG_HEADERS"; then
cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
BEGIN {
_ACEOF
# Transform confdefs.h into an awk script 'defines.awk', embedded as
# here-document in config.status, that substitutes the proper values into
# config.h.in to produce config.h.
# Create a delimiter string that does not exist in confdefs.h, to ease
# handling of long lines.
ac_delim='%!_!# '
for ac_last_try in false false :; do
ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
if test -z "$ac_tt"; then
break
elif $ac_last_try; then
as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
done
# For the awk script, D is an array of macro values keyed by name,
# likewise P contains macro parameters if any. Preserve backslash
# newline sequences.
ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
sed -n '
s/.\{148\}/&'"$ac_delim"'/g
t rset
:rset
s/^[ ]*#[ ]*define[ ][ ]*/ /
t def
d
:def
s/\\$//
t bsnl
s/["\\]/\\&/g
s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
D["\1"]=" \3"/p
s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
d
:bsnl
s/["\\]/\\&/g
s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
D["\1"]=" \3\\\\\\n"\\/p
t cont
s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
t cont
d
:cont
n
s/.\{148\}/&'"$ac_delim"'/g
t clear
:clear
s/\\$//
t bsnlc
s/["\\]/\\&/g; s/^/"/; s/$/"/p
d
:bsnlc
s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
b cont
' >$CONFIG_STATUS || ac_write_fail=1
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
for (key in D) D_is_set[key] = 1
FS = ""
}
/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
line = \$ 0
split(line, arg, " ")
if (arg[1] == "#") {
defundef = arg[2]
mac1 = arg[3]
} else {
defundef = substr(arg[1], 2)
mac1 = arg[2]
}
split(mac1, mac2, "(") #)
macro = mac2[1]
prefix = substr(line, 1, index(line, defundef) - 1)
if (D_is_set[macro]) {
# Preserve the white space surrounding the "#".
print prefix "define", macro P[macro] D[macro]
next
} else {
# Replace #undef with comments. This is necessary, for example,
# in the case of _POSIX_SOURCE, which is predefined and required
# on some systems where configure will not decide to define it.
if (defundef == "undef") {
print "/*", prefix defundef, macro, "*/"
next
}
}
}
{ print }
_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
fi # test -n "$CONFIG_HEADERS"
eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
shift
for ac_tag
do
case $ac_tag in
:[FHLC]) ac_mode=$ac_tag; continue;;
esac
case $ac_mode$ac_tag in
:[FHL]*:*);;
:L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;;
:[FH]-) ac_tag=-:-;;
:[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
esac
ac_save_IFS=$IFS
IFS=:
set x $ac_tag
IFS=$ac_save_IFS
shift
ac_file=$1
shift
case $ac_mode in
:L) ac_source=$1;;
:[FH])
ac_file_inputs=
for ac_f
do
case $ac_f in
-) ac_f="$ac_tmp/stdin";;
*) # Look for the file first in the build tree, then in the source tree
# (if the path is not absolute). The absolute path cannot be DOS-style,
# because $ac_f cannot contain ':'.
test -f "$ac_f" ||
case $ac_f in
[\\/$]*) false;;
*) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
esac ||
as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;;
esac
case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
# Let's still pretend it is 'configure' which instantiates (i.e., don't
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
case $ac_tag in
*:-:* | *:-) cat >"$ac_tmp/stdin" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
esac
;;
esac
ac_dir=`$as_dirname -- "$ac_file" ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
as_dir="$ac_dir"; as_fn_mkdir_p
ac_builddir=.
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix
case $srcdir in
.) # We are building in place.
ac_srcdir=.
ac_top_srcdir=$ac_top_builddir_sub
ac_abs_top_srcdir=$ac_pwd ;;
[\\/]* | ?:[\\/]* ) # Absolute name.
ac_srcdir=$srcdir$ac_dir_suffix;
ac_top_srcdir=$srcdir
ac_abs_top_srcdir=$srcdir ;;
*) # Relative name.
ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
ac_top_srcdir=$ac_top_build_prefix$srcdir
ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
case $ac_mode in
:F)
#
# CONFIG_FILE
#
case $INSTALL in
[\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
*) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
esac
ac_MKDIR_P=$MKDIR_P
case $MKDIR_P in
[\\/$]* | ?:[\\/]* ) ;;
*/*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
esac
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# If the template does not know about datarootdir, expand it.
# FIXME: This hack should be removed a few years after 2.60.
ac_datarootdir_hack=; ac_datarootdir_seen=
ac_sed_dataroot='
/datarootdir/ {
p
q
}
/@datadir@/p
/@docdir@/p
/@infodir@/p
/@localedir@/p
/@mandir@/p'
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
s&@datadir@&$datadir&g
s&@docdir@&$docdir&g
s&@infodir@&$infodir&g
s&@localedir@&$localedir&g
s&@mandir@&$mandir&g
s&\\\${datarootdir}&$datarootdir&g' ;;
esac
_ACEOF
# Neutralize VPATH when '$srcdir' = '.'.
# Shell code in configure.ac might set extrasub.
# FIXME: do we really want to maintain this feature?
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_sed_extra="$ac_vpsub
$extrasub
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
:t
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
s|@configure_input@|$ac_sed_conf_input|;t t
s&@top_builddir@&$ac_top_builddir_sub&;t t
s&@top_build_prefix@&$ac_top_build_prefix&;t t
s&@srcdir@&$ac_srcdir&;t t
s&@abs_srcdir@&$ac_abs_srcdir&;t t
s&@top_srcdir@&$ac_top_srcdir&;t t
s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
s&@builddir@&$ac_builddir&;t t
s&@abs_builddir@&$ac_abs_builddir&;t t
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
s&@INSTALL@&$ac_INSTALL&;t t
s&@MKDIR_P@&$ac_MKDIR_P&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
>$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
case $ac_file in
-) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
*) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
esac \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
;;
:H)
#
# CONFIG_HEADER
#
if test x"$ac_file" != x-; then
{
printf "%s\n" "/* $configure_input */" >&1 \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
} >"$ac_tmp/config.h" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
printf "%s\n" "$as_me: $ac_file is unchanged" >&6;}
else
rm -f "$ac_file"
mv "$ac_tmp/config.h" "$ac_file" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
fi
else
printf "%s\n" "/* $configure_input */" >&1 \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
|| as_fn_error $? "could not create -" "$LINENO" 5
fi
# Compute "$ac_file"'s index in $config_headers.
_am_arg="$ac_file"
_am_stamp_count=1
for _am_header in $config_headers :; do
case $_am_header in
$_am_arg | $_am_arg:* )
break ;;
* )
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
esac
done
echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$_am_arg" : 'X\(//\)[^/]' \| \
X"$_am_arg" : 'X\(//\)$' \| \
X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$_am_arg" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`/stamp-h$_am_stamp_count
;;
:C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
printf "%s\n" "$as_me: executing $ac_file commands" >&6;}
;;
esac
case $ac_file$ac_mode in
"depfiles":C) test x"$AMDEP_TRUE" != x"" || {
# Older Autoconf quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
# TODO: see whether this extra hack can be removed once we start
# requiring Autoconf 2.70 or later.
case $CONFIG_FILES in #(
*\'*) :
eval set x "$CONFIG_FILES" ;; #(
*) :
set x $CONFIG_FILES ;; #(
*) :
;;
esac
shift
# Used to flag and report bootstrapping failures.
am_rc=0
for am_mf
do
# Strip MF so we end up with the name of the file.
am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile which includes
# dependency-tracking related rules and includes.
# Grep'ing the whole file directly is not great: AIX grep has a line
# limit of 2048, but all sed's we know have understand at least 4000.
sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
|| continue
am_dirpart=`$as_dirname -- "$am_mf" ||
$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$am_mf" : 'X\(//\)[^/]' \| \
X"$am_mf" : 'X\(//\)$' \| \
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X"$am_mf" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
am_filepart=`$as_basename -- "$am_mf" ||
$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
X"$am_mf" : 'X\(//\)$' \| \
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
printf "%s\n" X/"$am_mf" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
}
/^X\/\(\/\/\)$/{
s//\1/
q
}
/^X\/\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
{ echo "$as_me:$LINENO: cd "$am_dirpart" \
&& sed -e '/# am--include-marker/d' "$am_filepart" \
| $MAKE -f - am--depfiles" >&5
(cd "$am_dirpart" \
&& sed -e '/# am--include-marker/d' "$am_filepart" \
| $MAKE -f - am--depfiles) >&5 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } || am_rc=$?
done
if test $am_rc -ne 0; then
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "Something went wrong bootstrapping makefile fragments
for automatic dependency tracking. If GNU make was not used, consider
re-running the configure script with MAKE=\"gmake\" (or whatever is
necessary). You can also try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).
See 'config.log' for more details" "$LINENO" 5; }
fi
{ am_dirpart=; unset am_dirpart;}
{ am_filepart=; unset am_filepart;}
{ am_mf=; unset am_mf;}
{ am_rc=; unset am_rc;}
rm -f conftest-deps.mk
}
;;
"libtool":C)
# See if we are running on zsh, and set the options that allow our
# commands through without removal of \ escapes.
if test -n "${ZSH_VERSION+set}"; then
setopt NO_GLOB_SUBST
fi
cfgfile=${ofile}T
trap "$RM \"$cfgfile\"; exit 1" 1 2 15
$RM "$cfgfile"
cat <<_LT_EOF >> "$cfgfile"
#! $SHELL
# Generated automatically by $as_me ($PACKAGE) $VERSION
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
# Provide generalized library-building support services.
# Written by Gordon Matzigkeit, 1996
# Copyright (C) 2025 Free Software Foundation, Inc.
# This is free software; see the source for copying conditions. There is NO
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# GNU Libtool is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program or library that is built
# using GNU Libtool, you may include this file under the same
# distribution terms that you use for the rest of that program.
#
# GNU Libtool 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# The names of the tagged configurations supported by this script.
available_tags=''
# Configured defaults for sys_lib_dlsearch_path munging.
: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
# ### BEGIN LIBTOOL CONFIG
# Which release of libtool.m4 was used?
macro_version=$macro_version
macro_revision=$macro_revision
# Whether or not to build shared libraries.
build_libtool_libs=$enable_shared
# Whether or not to build static libraries.
build_old_libs=$enable_static
# What type of objects to build.
pic_mode=$pic_mode
# Whether to let the compiler frontend decide what standard libraries to link when building C++ shared libraries and modules.
enable_cxx_stdlib=$enable_cxx_stdlib
# Flag used for specifying not to link standard libraries.
stdlibflag=$stdlibflag
# Whether or not to optimize for fast installation.
fast_install=$enable_fast_install
# Shared archive member basename,for filename based shared library versioning on AIX.
shared_archive_member_spec=$shared_archive_member_spec
# Shell to use when invoking shell scripts.
SHELL=$lt_SHELL
# An echo program that protects backslashes.
ECHO=$lt_ECHO
# The PATH separator for the build system.
PATH_SEPARATOR=$lt_PATH_SEPARATOR
# The host system.
host_alias=$host_alias
host=$host
host_os=$host_os
# The build system.
build_alias=$build_alias
build=$build
build_os=$build_os
# A sed program that does not truncate output.
SED=$lt_SED
# Sed that helps us avoid accidentally triggering echo(1) options like -n.
Xsed="\$SED -e 1s/^X//"
# A grep program that handles long lines.
GREP=$lt_GREP
# An ERE matcher.
EGREP=$lt_EGREP
# A literal string matcher.
FGREP=$lt_FGREP
# A BSD- or MS-compatible name lister.
NM=$lt_NM
# Whether we need soft or hard links.
LN_S=$lt_LN_S
# What is the maximum length of a command?
max_cmd_len=$max_cmd_len
# Object file suffix (normally "o").
objext=$ac_objext
# Executable file suffix (normally "").
exeext=$exeext
# whether the shell understands "unset".
lt_unset=$lt_unset
# turn spaces into newlines.
SP2NL=$lt_lt_SP2NL
# turn newlines into spaces.
NL2SP=$lt_lt_NL2SP
# convert \$build file names to \$host format.
to_host_file_cmd=$lt_cv_to_host_file_cmd
# convert \$build files to toolchain format.
to_tool_file_cmd=$lt_cv_to_tool_file_cmd
# whether cygpath is installed.
cygpath_installed=$lt_cv_cygpath_installed
# A file(cmd) program that detects file types.
FILECMD=$lt_FILECMD
# An object symbol dumper.
OBJDUMP=$lt_OBJDUMP
# Method to check whether dependent libraries are shared objects.
deplibs_check_method=$lt_deplibs_check_method
# Command to use when deplibs_check_method = "file_magic".
file_magic_cmd=$lt_file_magic_cmd
# How to find potential files when deplibs_check_method = "file_magic".
file_magic_glob=$lt_file_magic_glob
# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
want_nocaseglob=$lt_want_nocaseglob
# DLL creation program.
DLLTOOL=$lt_DLLTOOL
# Command to associate shared and link libraries.
sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
# The archiver.
AR=$lt_AR
# Flags to create an archive (by configure).
lt_ar_flags=$lt_lt_ar_flags
# Flags to create an archive.
AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"}
# How to feed a file listing to the archiver.
archiver_list_spec=$lt_archiver_list_spec
# A symbol stripping program.
STRIP=$lt_STRIP
# Commands used to install an old-style archive.
RANLIB=$lt_RANLIB
old_postinstall_cmds=$lt_old_postinstall_cmds
old_postuninstall_cmds=$lt_old_postuninstall_cmds
# Whether to use a lock for old archive extraction.
lock_old_archive_extraction=$lock_old_archive_extraction
# A C compiler.
LTCC=$lt_CC
# LTCC compiler flags.
LTCFLAGS=$lt_CFLAGS
# Take the output of nm and produce a listing of raw symbols and C names.
global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
# Transform the output of nm in a proper C declaration.
global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
# Transform the output of nm into a list of symbols to manually relocate.
global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
# Transform the output of nm in a C name address pair.
global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
# Transform the output of nm in a C name address pair when lib prefix is needed.
global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
# The name lister interface.
nm_interface=$lt_lt_cv_nm_interface
# Specify filename containing input files for \$NM.
nm_file_list_spec=$lt_nm_file_list_spec
# The root where to search for dependent libraries,and where our libraries should be installed.
lt_sysroot=$lt_sysroot
# Command to truncate a binary pipe.
lt_truncate_bin=$lt_lt_cv_truncate_bin
# The name of the directory that contains temporary libtool files.
objdir=$objdir
# Used to examine libraries when file_magic_cmd begins with "file".
MAGIC_CMD=$MAGIC_CMD
# Must we lock files when doing compilation?
need_locks=$lt_need_locks
# Manifest tool.
MANIFEST_TOOL=$lt_MANIFEST_TOOL
# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
DSYMUTIL=$lt_DSYMUTIL
# Tool to change global to local symbols on Mac OS X.
NMEDIT=$lt_NMEDIT
# Tool to manipulate fat objects and archives on Mac OS X.
LIPO=$lt_LIPO
# ldd/readelf like tool for Mach-O binaries on Mac OS X.
OTOOL=$lt_OTOOL
# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
OTOOL64=$lt_OTOOL64
# Old archive suffix (normally "a").
libext=$libext
# Shared library suffix (normally ".so").
shrext_cmds=$lt_shrext_cmds
# The commands to extract the exported symbol list from a shared archive.
extract_expsyms_cmds=$lt_extract_expsyms_cmds
# Variables whose values should be saved in libtool wrapper scripts and
# restored at link time.
variables_saved_for_relink=$lt_variables_saved_for_relink
# Do we need the "lib" prefix for modules?
need_lib_prefix=$need_lib_prefix
# Do we need a version for libraries?
need_version=$need_version
# Library versioning type.
version_type=$version_type
# Shared library runtime path variable.
runpath_var=$runpath_var
# Shared library path variable.
shlibpath_var=$shlibpath_var
# Is shlibpath searched before the hard-coded library search path?
shlibpath_overrides_runpath=$shlibpath_overrides_runpath
# Format of library name prefix.
libname_spec=$lt_libname_spec
# List of archive names. First name is the real one, the rest are links.
# The last name is the one that the linker finds with -lNAME
library_names_spec=$lt_library_names_spec
# The coded name of the library, if different from the real name.
soname_spec=$lt_soname_spec
# Permission mode override for installation of shared libraries.
install_override_mode=$lt_install_override_mode
# Command to use after installation of a shared archive.
postinstall_cmds=$lt_postinstall_cmds
# Command to use after uninstallation of a shared archive.
postuninstall_cmds=$lt_postuninstall_cmds
# Commands used to finish a libtool library installation in a directory.
finish_cmds=$lt_finish_cmds
# As "finish_cmds", except a single script fragment to be evaled but
# not shown.
finish_eval=$lt_finish_eval
# Whether we should hardcode library paths into libraries.
hardcode_into_libs=$hardcode_into_libs
# Compile-time system search path for libraries.
sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
# Detected run-time system search path for libraries.
sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
# Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
# Whether dlopen is supported.
dlopen_support=$enable_dlopen
# Whether dlopen of programs is supported.
dlopen_self=$enable_dlopen_self
# Whether dlopen of statically linked programs is supported.
dlopen_self_static=$enable_dlopen_self_static
# Commands to strip libraries.
old_striplib=$lt_old_striplib
striplib=$lt_striplib
# The linker used to build libraries.
LD=$lt_LD
# How to create reloadable object files.
reload_flag=$lt_reload_flag
reload_cmds=$lt_reload_cmds
# Commands used to build an old-style archive.
old_archive_cmds=$lt_old_archive_cmds
# A language specific compiler.
CC=$lt_compiler
# Is the compiler the GNU compiler?
with_gcc=$GCC
# Compiler flag to turn off builtin functions.
no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
# Additional compiler flags for building library objects.
pic_flag=$lt_lt_prog_compiler_pic
# How to pass a linker flag through the compiler.
wl=$lt_lt_prog_compiler_wl
# Compiler flag to prevent dynamic linking.
link_static_flag=$lt_lt_prog_compiler_static
# Does compiler simultaneously support -c and -o options?
compiler_c_o=$lt_lt_cv_prog_compiler_c_o
# Whether or not to add -lc for building shared libraries.
build_libtool_need_lc=$archive_cmds_need_lc
# Whether or not to disallow shared libs when runtime libs are static.
allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
# Compiler flag to allow reflexive dlopens.
export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
# Compiler flag to generate shared objects directly from archives.
whole_archive_flag_spec=$lt_whole_archive_flag_spec
# Whether the compiler copes with passing no objects directly.
compiler_needs_object=$lt_compiler_needs_object
# Create an old-style archive from a shared archive.
old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
# Create a temporary old-style archive to link instead of a shared archive.
old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
# Commands used to build a shared archive.
archive_cmds=$lt_archive_cmds
archive_expsym_cmds=$lt_archive_expsym_cmds
# Commands used to build a loadable module if different from building
# a shared archive.
module_cmds=$lt_module_cmds
module_expsym_cmds=$lt_module_expsym_cmds
# Whether we are building with GNU ld or not.
with_gnu_ld=$lt_with_gnu_ld
# Flag that allows shared libraries with undefined symbols to be built.
allow_undefined_flag=$lt_allow_undefined_flag
# Flag that enforces no undefined symbols.
no_undefined_flag=$lt_no_undefined_flag
# Flag to hardcode \$libdir into a binary during linking.
# This must work even if \$libdir does not exist
hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
# Whether we need a single "-rpath" flag with a separated argument.
hardcode_libdir_separator=$lt_hardcode_libdir_separator
# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
# DIR into the resulting binary.
hardcode_direct=$hardcode_direct
# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
# DIR into the resulting binary and the resulting library dependency is
# "absolute",i.e. impossible to change by setting \$shlibpath_var if the
# library is relocated.
hardcode_direct_absolute=$hardcode_direct_absolute
# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
# into the resulting binary.
hardcode_minus_L=$hardcode_minus_L
# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
# into the resulting binary.
hardcode_shlibpath_var=$hardcode_shlibpath_var
# Set to "yes" if building a shared library automatically hardcodes DIR
# into the library and all subsequent libraries and executables linked
# against it.
hardcode_automatic=$hardcode_automatic
# Set to yes if linker adds runtime paths of dependent libraries
# to runtime path list.
inherit_rpath=$inherit_rpath
# Whether libtool must link a program against all its dependency libraries.
link_all_deplibs=$link_all_deplibs
# Set to "yes" if exported symbols are required.
always_export_symbols=$always_export_symbols
# The commands to list exported symbols.
export_symbols_cmds=$lt_export_symbols_cmds
# Symbols that should not be listed in the preloaded symbols.
exclude_expsyms=$lt_exclude_expsyms
# Symbols that must always be exported.
include_expsyms=$lt_include_expsyms
# Commands necessary for linking programs (against libraries) with templates.
prelink_cmds=$lt_prelink_cmds
# Commands necessary for finishing linking programs.
postlink_cmds=$lt_postlink_cmds
# Specify filename containing input files.
file_list_spec=$lt_file_list_spec
# How to hardcode a shared library path into an executable.
hardcode_action=$hardcode_action
# ### END LIBTOOL CONFIG
_LT_EOF
cat <<'_LT_EOF' >> "$cfgfile"
# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
# func_munge_path_list VARIABLE PATH
# -----------------------------------
# VARIABLE is name of variable containing _space_ separated list of
# directories to be munged by the contents of PATH, which is string
# having a format:
# "DIR[:DIR]:"
# string "DIR[ DIR]" will be prepended to VARIABLE
# ":DIR[:DIR]"
# string "DIR[ DIR]" will be appended to VARIABLE
# "DIRP[:DIRP]::[DIRA:]DIRA"
# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
# "DIRA[ DIRA]" will be appended to VARIABLE
# "DIR[:DIR]"
# VARIABLE will be replaced by "DIR[ DIR]"
func_munge_path_list ()
{
case x$2 in
x)
;;
*:)
eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
;;
x:*)
eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
;;
*::*)
eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
;;
*)
eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
;;
esac
}
# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
func_cc_basename ()
{
for cc_temp in $*""; do
case $cc_temp in
compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
\-*) ;;
*) break;;
esac
done
func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
}
# ### END FUNCTIONS SHARED WITH CONFIGURE
_LT_EOF
case $host_os in
aix3*)
cat <<\_LT_EOF >> "$cfgfile"
# AIX sometimes has problems with the GCC collect2 program. For some
# reason, if we set the COLLECT_NAMES environment variable, the problems
# vanish in a puff of smoke.
if test set != "${COLLECT_NAMES+set}"; then
COLLECT_NAMES=
export COLLECT_NAMES
fi
_LT_EOF
;;
esac
ltmain=$ac_aux_dir/ltmain.sh
# We use sed instead of cat because bash on DJGPP gets confused if
# if finds mixed CR/LF and LF-only lines. Since sed operates in
# text mode, it properly converts lines to CR/LF. This bash problem
# is reportedly fixed, but why not run on old versions too?
$SED '$q' "$ltmain" >> "$cfgfile" \
|| (rm -f "$cfgfile"; exit 1)
mv -f "$cfgfile" "$ofile" ||
(rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
chmod +x "$ofile"
;;
"programs/mkwinpeimg":F) chmod +x programs/mkwinpeimg ;;
esac
done # for ac_tag
as_fn_exit 0
_ACEOF
ac_clean_files=$ac_clean_files_save
test $ac_write_fail = 0 ||
as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
# configure is writing to config.log, and then calls config.status.
# config.status does its own redirection, appending to config.log.
# Unfortunately, on DOS this fails, as config.log is still kept open
# by configure, so config.status won't be able to write to it; its
# output is simply discarded. So we exec the FD to /dev/null,
# effectively closing config.log, so it can be properly (re)opened and
# appended to by config.status. When coming back to configure, we
# need to make the FD available again.
if test "$no_create" != yes; then
ac_cs_success=:
ac_config_status_args=
test "$silent" = yes &&
ac_config_status_args="$ac_config_status_args --quiet"
exec 5>/dev/null
$SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
exec 5>>config.log
# Use ||, not &&, to avoid exiting from the if with $? = 1, which
# would make configure fail if this is the last instruction.
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
wimlib-1.14.5/src/ 0000755 0001750 0001750 00000000000 15137024753 011155 5 ustar 00e e wimlib-1.14.5/src/lzx_decompress.c 0000644 0001750 0001750 00000041731 15137020663 014364 0 ustar 00e e /*
* lzx_decompress.c
*
* A decompressor for the LZX compression format, as used in WIM files.
*/
/*
* Copyright (C) 2012-2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
/*
* LZX is an LZ77 and Huffman-code based compression format that has many
* similarities to DEFLATE (the format used by zlib/gzip). The compression
* ratio is as good or better than DEFLATE. See lzx_compress.c for a format
* overview, and see https://en.wikipedia.org/wiki/LZX_(algorithm) for a
* historical overview. Here I make some pragmatic notes.
*
* The old specification for LZX is the document "Microsoft LZX Data Compression
* Format" (1997). It defines the LZX format as used in cabinet files. Allowed
* window sizes are 2^n where 15 <= n <= 21. However, this document contains
* several errors, so don't read too much into it...
*
* The new specification for LZX is the document "[MS-PATCH]: LZX DELTA
* Compression and Decompression" (2014). It defines the LZX format as used by
* Microsoft's binary patcher. It corrects several errors in the 1997 document
* and extends the format in several ways --- namely, optional reference data,
* up to 2^25 byte windows, and longer match lengths.
*
* WIM files use a more restricted form of LZX. No LZX DELTA extensions are
* present, the window is not "sliding", E8 preprocessing is done
* unconditionally with a fixed file size, and the maximum window size is always
* 2^15 bytes (equal to the size of each "chunk" in a compressed WIM resource).
* This code is primarily intended to implement this form of LZX. But although
* not compatible with WIMGAPI, this code also supports maximum window sizes up
* to 2^21 bytes.
*
* TODO: Add support for window sizes up to 2^25 bytes.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include "wimlib/decompressor_ops.h"
#include "wimlib/decompress_common.h"
#include "wimlib/error.h"
#include "wimlib/lzx_common.h"
#include "wimlib/util.h"
/* These values are chosen for fast decompression. */
#define LZX_MAINCODE_TABLEBITS 11
#define LZX_LENCODE_TABLEBITS 9
#define LZX_PRECODE_TABLEBITS 6
#define LZX_ALIGNEDCODE_TABLEBITS 7
#define LZX_READ_LENS_MAX_OVERRUN 50
struct lzx_decompressor {
DECODE_TABLE(maincode_decode_table, LZX_MAINCODE_MAX_NUM_SYMBOLS,
LZX_MAINCODE_TABLEBITS, LZX_MAX_MAIN_CODEWORD_LEN);
u8 maincode_lens[LZX_MAINCODE_MAX_NUM_SYMBOLS + LZX_READ_LENS_MAX_OVERRUN];
DECODE_TABLE(lencode_decode_table, LZX_LENCODE_NUM_SYMBOLS,
LZX_LENCODE_TABLEBITS, LZX_MAX_LEN_CODEWORD_LEN);
u8 lencode_lens[LZX_LENCODE_NUM_SYMBOLS + LZX_READ_LENS_MAX_OVERRUN];
union {
DECODE_TABLE(alignedcode_decode_table, LZX_ALIGNEDCODE_NUM_SYMBOLS,
LZX_ALIGNEDCODE_TABLEBITS, LZX_MAX_ALIGNED_CODEWORD_LEN);
u8 alignedcode_lens[LZX_ALIGNEDCODE_NUM_SYMBOLS];
};
union {
DECODE_TABLE(precode_decode_table, LZX_PRECODE_NUM_SYMBOLS,
LZX_PRECODE_TABLEBITS, LZX_MAX_PRE_CODEWORD_LEN);
u8 precode_lens[LZX_PRECODE_NUM_SYMBOLS];
u8 extra_offset_bits[LZX_MAX_OFFSET_SLOTS];
};
union {
DECODE_TABLE_WORKING_SPACE(maincode_working_space,
LZX_MAINCODE_MAX_NUM_SYMBOLS,
LZX_MAX_MAIN_CODEWORD_LEN);
DECODE_TABLE_WORKING_SPACE(lencode_working_space,
LZX_LENCODE_NUM_SYMBOLS,
LZX_MAX_LEN_CODEWORD_LEN);
DECODE_TABLE_WORKING_SPACE(alignedcode_working_space,
LZX_ALIGNEDCODE_NUM_SYMBOLS,
LZX_MAX_ALIGNED_CODEWORD_LEN);
DECODE_TABLE_WORKING_SPACE(precode_working_space,
LZX_PRECODE_NUM_SYMBOLS,
LZX_MAX_PRE_CODEWORD_LEN);
};
unsigned window_order;
unsigned num_main_syms;
/* Like lzx_extra_offset_bits[], but does not include the entropy-coded
* bits of aligned offset blocks */
u8 extra_offset_bits_minus_aligned[LZX_MAX_OFFSET_SLOTS];
} __attribute__((aligned(DECODE_TABLE_ALIGNMENT)));
/* Read a Huffman-encoded symbol using the precode. */
static forceinline unsigned
read_presym(const struct lzx_decompressor *d, struct input_bitstream *is)
{
return read_huffsym(is, d->precode_decode_table,
LZX_PRECODE_TABLEBITS, LZX_MAX_PRE_CODEWORD_LEN);
}
/* Read a Huffman-encoded symbol using the main code. */
static forceinline unsigned
read_mainsym(const struct lzx_decompressor *d, struct input_bitstream *is)
{
return read_huffsym(is, d->maincode_decode_table,
LZX_MAINCODE_TABLEBITS, LZX_MAX_MAIN_CODEWORD_LEN);
}
/* Read a Huffman-encoded symbol using the length code. */
static forceinline unsigned
read_lensym(const struct lzx_decompressor *d, struct input_bitstream *is)
{
return read_huffsym(is, d->lencode_decode_table,
LZX_LENCODE_TABLEBITS, LZX_MAX_LEN_CODEWORD_LEN);
}
/* Read a Huffman-encoded symbol using the aligned offset code. */
static forceinline unsigned
read_alignedsym(const struct lzx_decompressor *d, struct input_bitstream *is)
{
return read_huffsym(is, d->alignedcode_decode_table,
LZX_ALIGNEDCODE_TABLEBITS, LZX_MAX_ALIGNED_CODEWORD_LEN);
}
/*
* Read a precode from the compressed input bitstream, then use it to decode
* @num_lens codeword length values and write them to @lens.
*/
static int
lzx_read_codeword_lens(struct lzx_decompressor *d, struct input_bitstream *is,
u8 *lens, unsigned num_lens)
{
u8 *len_ptr = lens;
u8 *lens_end = lens + num_lens;
/* Read the lengths of the precode codewords. These are stored
* explicitly. */
for (int i = 0; i < LZX_PRECODE_NUM_SYMBOLS; i++) {
d->precode_lens[i] =
bitstream_read_bits(is, LZX_PRECODE_ELEMENT_SIZE);
}
/* Build the decoding table for the precode. */
if (make_huffman_decode_table(d->precode_decode_table,
LZX_PRECODE_NUM_SYMBOLS,
LZX_PRECODE_TABLEBITS,
d->precode_lens,
LZX_MAX_PRE_CODEWORD_LEN,
d->precode_working_space))
return -1;
/* Decode the codeword lengths. */
do {
unsigned presym;
u8 len;
/* Read the next precode symbol. */
presym = read_presym(d, is);
if (presym < 17) {
/* Difference from old length */
len = *len_ptr - presym;
if ((s8)len < 0)
len += 17;
*len_ptr++ = len;
} else {
/* Special RLE values */
unsigned run_len;
if (presym == 17) {
/* Run of 0's */
run_len = 4 + bitstream_read_bits(is, 4);
len = 0;
} else if (presym == 18) {
/* Longer run of 0's */
run_len = 20 + bitstream_read_bits(is, 5);
len = 0;
} else {
/* Run of identical lengths */
run_len = 4 + bitstream_read_bits(is, 1);
presym = read_presym(d, is);
if (unlikely(presym > 17))
return -1;
len = *len_ptr - presym;
if ((s8)len < 0)
len += 17;
}
do {
*len_ptr++ = len;
} while (--run_len);
/*
* The worst case overrun is when presym == 18,
* run_len == 20 + 31, and only 1 length was remaining.
* So LZX_READ_LENS_MAX_OVERRUN == 50.
*
* Overrun while reading the first half of maincode_lens
* can corrupt the previous values in the second half.
* This doesn't really matter because the resulting
* lengths will still be in range, and data that
* generates overruns is invalid anyway.
*/
}
} while (len_ptr < lens_end);
return 0;
}
/*
* Read the header of an LZX block. For all block types, the block type and
* size is saved in *block_type_ret and *block_size_ret, respectively. For
* compressed blocks, the codeword lengths are also saved. For uncompressed
* blocks, the recent offsets queue is also updated.
*/
static int
lzx_read_block_header(struct lzx_decompressor *d, struct input_bitstream *is,
u32 recent_offsets[], int *block_type_ret,
u32 *block_size_ret)
{
int block_type;
u32 block_size;
bitstream_ensure_bits(is, 4);
/* Read the block type. */
block_type = bitstream_pop_bits(is, 3);
/* Read the block size. */
if (bitstream_pop_bits(is, 1)) {
block_size = LZX_DEFAULT_BLOCK_SIZE;
} else {
block_size = bitstream_read_bits(is, 16);
if (d->window_order >= 16) {
block_size <<= 8;
block_size |= bitstream_read_bits(is, 8);
}
}
switch (block_type) {
case LZX_BLOCKTYPE_ALIGNED:
/* Read the aligned offset codeword lengths. */
for (int i = 0; i < LZX_ALIGNEDCODE_NUM_SYMBOLS; i++) {
d->alignedcode_lens[i] =
bitstream_read_bits(is,
LZX_ALIGNEDCODE_ELEMENT_SIZE);
}
/* Fall though, since the rest of the header for aligned offset
* blocks is the same as that for verbatim blocks. */
case LZX_BLOCKTYPE_VERBATIM:
/* Read the main codeword lengths, which are divided into two
* parts: literal symbols and match headers. */
if (lzx_read_codeword_lens(d, is, d->maincode_lens,
LZX_NUM_CHARS))
return -1;
if (lzx_read_codeword_lens(d, is, d->maincode_lens + LZX_NUM_CHARS,
d->num_main_syms - LZX_NUM_CHARS))
return -1;
/* Read the length codeword lengths. */
if (lzx_read_codeword_lens(d, is, d->lencode_lens,
LZX_LENCODE_NUM_SYMBOLS))
return -1;
break;
case LZX_BLOCKTYPE_UNCOMPRESSED:
/*
* The header of an uncompressed block contains new values for
* the recent offsets queue, starting on the next 16-bit
* boundary in the bitstream. Careful: if the stream is
* *already* aligned, the correct thing to do is to throw away
* the next 16 bits (this is probably a mistake in the format).
*/
bitstream_ensure_bits(is, 1);
bitstream_align(is);
recent_offsets[0] = bitstream_read_u32(is);
recent_offsets[1] = bitstream_read_u32(is);
recent_offsets[2] = bitstream_read_u32(is);
/* Offsets of 0 are invalid. */
if (recent_offsets[0] == 0 || recent_offsets[1] == 0 ||
recent_offsets[2] == 0)
return -1;
break;
default:
/* Unrecognized block type. */
return -1;
}
*block_type_ret = block_type;
*block_size_ret = block_size;
return 0;
}
/* Decompress a block of LZX-compressed data. */
static int
lzx_decompress_block(struct lzx_decompressor *d, struct input_bitstream *_is,
int block_type, u32 block_size,
u8 * const out_begin, u8 *out_next, u32 recent_offsets[])
{
/*
* Redeclare the input bitstream on the stack. This shouldn't be
* needed, but it can improve the main loop's performance significantly
* with both gcc and clang, apparently because the compiler otherwise
* gets confused and doesn't properly allocate registers for
* 'is->bitbuf' et al. and/or thinks 'is->next' may point into 'is'.
*/
struct input_bitstream is_onstack = *_is;
struct input_bitstream *is = &is_onstack;
u8 * const block_end = out_next + block_size;
unsigned min_aligned_offset_slot;
/*
* Build the Huffman decode tables. We always need to build the main
* and length decode tables. For aligned blocks we additionally need to
* build the aligned offset decode table.
*/
if (make_huffman_decode_table(d->maincode_decode_table,
d->num_main_syms,
LZX_MAINCODE_TABLEBITS,
d->maincode_lens,
LZX_MAX_MAIN_CODEWORD_LEN,
d->maincode_working_space))
return -1;
if (make_huffman_decode_table(d->lencode_decode_table,
LZX_LENCODE_NUM_SYMBOLS,
LZX_LENCODE_TABLEBITS,
d->lencode_lens,
LZX_MAX_LEN_CODEWORD_LEN,
d->lencode_working_space))
return -1;
if (block_type == LZX_BLOCKTYPE_ALIGNED) {
if (make_huffman_decode_table(d->alignedcode_decode_table,
LZX_ALIGNEDCODE_NUM_SYMBOLS,
LZX_ALIGNEDCODE_TABLEBITS,
d->alignedcode_lens,
LZX_MAX_ALIGNED_CODEWORD_LEN,
d->alignedcode_working_space))
return -1;
min_aligned_offset_slot = LZX_MIN_ALIGNED_OFFSET_SLOT;
memcpy(d->extra_offset_bits, d->extra_offset_bits_minus_aligned,
sizeof(lzx_extra_offset_bits));
} else {
min_aligned_offset_slot = LZX_MAX_OFFSET_SLOTS;
memcpy(d->extra_offset_bits, lzx_extra_offset_bits,
sizeof(lzx_extra_offset_bits));
}
/* Decode the literals and matches. */
do {
unsigned mainsym;
unsigned length;
u32 offset;
unsigned offset_slot;
mainsym = read_mainsym(d, is);
if (mainsym < LZX_NUM_CHARS) {
/* Literal */
*out_next++ = mainsym;
continue;
}
/* Match */
/* Decode the length header and offset slot. */
STATIC_ASSERT(LZX_NUM_CHARS % LZX_NUM_LEN_HEADERS == 0);
length = mainsym % LZX_NUM_LEN_HEADERS;
offset_slot = (mainsym - LZX_NUM_CHARS) / LZX_NUM_LEN_HEADERS;
/* If needed, read a length symbol to decode the full length. */
if (length == LZX_NUM_PRIMARY_LENS)
length += read_lensym(d, is);
length += LZX_MIN_MATCH_LEN;
if (offset_slot < LZX_NUM_RECENT_OFFSETS) {
/* Repeat offset */
/* Note: This isn't a real LRU queue, since using the R2
* offset doesn't bump the R1 offset down to R2. */
offset = recent_offsets[offset_slot];
recent_offsets[offset_slot] = recent_offsets[0];
} else {
/* Explicit offset */
offset = bitstream_read_bits(is, d->extra_offset_bits[offset_slot]);
if (offset_slot >= min_aligned_offset_slot) {
offset = (offset << LZX_NUM_ALIGNED_OFFSET_BITS) |
read_alignedsym(d, is);
}
offset += lzx_offset_slot_base[offset_slot];
/* Update the match offset LRU queue. */
STATIC_ASSERT(LZX_NUM_RECENT_OFFSETS == 3);
recent_offsets[2] = recent_offsets[1];
recent_offsets[1] = recent_offsets[0];
}
recent_offsets[0] = offset;
/* Validate the match and copy it to the current position. */
if (unlikely(lz_copy(length, offset, out_begin,
out_next, block_end, LZX_MIN_MATCH_LEN)))
return -1;
out_next += length;
} while (out_next != block_end);
*_is = is_onstack;
return 0;
}
static int
lzx_decompress(const void *restrict compressed_data, size_t compressed_size,
void *restrict uncompressed_data, size_t uncompressed_size,
void *restrict _d)
{
struct lzx_decompressor *d = _d;
u8 * const out_begin = uncompressed_data;
u8 *out_next = out_begin;
u8 * const out_end = out_begin + uncompressed_size;
struct input_bitstream is;
STATIC_ASSERT(LZX_NUM_RECENT_OFFSETS == 3);
u32 recent_offsets[LZX_NUM_RECENT_OFFSETS] = {1, 1, 1};
unsigned may_have_e8_byte = 0;
init_input_bitstream(&is, compressed_data, compressed_size);
/* Codeword lengths begin as all 0's for delta encoding purposes. */
memset(d->maincode_lens, 0, d->num_main_syms);
memset(d->lencode_lens, 0, LZX_LENCODE_NUM_SYMBOLS);
/* Decompress blocks until we have all the uncompressed data. */
while (out_next != out_end) {
int block_type;
u32 block_size;
if (lzx_read_block_header(d, &is, recent_offsets,
&block_type, &block_size))
return -1;
if (block_size < 1 || block_size > out_end - out_next)
return -1;
if (likely(block_type != LZX_BLOCKTYPE_UNCOMPRESSED)) {
/* Compressed block */
if (lzx_decompress_block(d, &is, block_type, block_size,
out_begin, out_next,
recent_offsets))
return -1;
/* If the first E8 byte was in this block, then it must
* have been encoded as a literal using mainsym E8. */
may_have_e8_byte |= d->maincode_lens[0xE8];
} else {
/* Uncompressed block */
if (bitstream_read_bytes(&is, out_next, block_size))
return -1;
/* Re-align the bitstream if needed. */
if (block_size & 1)
bitstream_read_byte(&is);
/* There may have been an E8 byte in the block. */
may_have_e8_byte = 1;
}
out_next += block_size;
}
/* Postprocess the data unless it cannot possibly contain E8 bytes. */
if (may_have_e8_byte)
lzx_postprocess(uncompressed_data, uncompressed_size);
return 0;
}
static int
lzx_create_decompressor(size_t max_block_size, void **d_ret)
{
unsigned window_order;
struct lzx_decompressor *d;
window_order = lzx_get_window_order(max_block_size);
if (window_order == 0)
return WIMLIB_ERR_INVALID_PARAM;
d = ALIGNED_MALLOC(sizeof(*d), DECODE_TABLE_ALIGNMENT);
if (!d)
return WIMLIB_ERR_NOMEM;
d->window_order = window_order;
d->num_main_syms = lzx_get_num_main_syms(window_order);
/* Initialize 'd->extra_offset_bits_minus_aligned'. */
STATIC_ASSERT(sizeof(d->extra_offset_bits_minus_aligned) ==
sizeof(lzx_extra_offset_bits));
STATIC_ASSERT(sizeof(d->extra_offset_bits) ==
sizeof(lzx_extra_offset_bits));
memcpy(d->extra_offset_bits_minus_aligned, lzx_extra_offset_bits,
sizeof(lzx_extra_offset_bits));
for (unsigned offset_slot = LZX_MIN_ALIGNED_OFFSET_SLOT;
offset_slot < LZX_MAX_OFFSET_SLOTS; offset_slot++)
{
d->extra_offset_bits_minus_aligned[offset_slot] -=
LZX_NUM_ALIGNED_OFFSET_BITS;
}
*d_ret = d;
return 0;
}
static void
lzx_free_decompressor(void *_d)
{
ALIGNED_FREE(_d);
}
const struct decompressor_ops lzx_decompressor_ops = {
.create_decompressor = lzx_create_decompressor,
.decompress = lzx_decompress,
.free_decompressor = lzx_free_decompressor,
};
wimlib-1.14.5/src/divsufsort.c 0000644 0001750 0001750 00000132330 15137011205 013517 0 ustar 00e e /*
* divsufsort.c for libdivsufsort-lite
* Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/divsufsort.h"
#include "wimlib/util.h"
#define DIVSUFSORT_ASSERT(expr)
/*- Constants -*/
#define ALPHABET_SIZE 256
#define BUCKET_A_SIZE (ALPHABET_SIZE)
#define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE)
#define SS_INSERTIONSORT_THRESHOLD 8
#define SS_BLOCKSIZE 1024
/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */
#if SS_BLOCKSIZE == 0
# define SS_MISORT_STACKSIZE (96)
#elif SS_BLOCKSIZE <= 4096
# define SS_MISORT_STACKSIZE (16)
#else
# define SS_MISORT_STACKSIZE (24)
#endif
#define SS_SMERGE_STACKSIZE (32)
#define TR_INSERTIONSORT_THRESHOLD (8)
#define TR_STACKSIZE (64)
/*- Macros -*/
#define STACK_PUSH(_a, _b, _c, _d)\
do {\
DIVSUFSORT_ASSERT(ssize < STACK_SIZE);\
stack[ssize].a = (_a), stack[ssize].b = (_b),\
stack[ssize].c = (_c), stack[ssize++].d = (_d);\
} while(0)
#define STACK_PUSH5(_a, _b, _c, _d, _e)\
do {\
DIVSUFSORT_ASSERT(ssize < STACK_SIZE);\
stack[ssize].a = (_a), stack[ssize].b = (_b),\
stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\
} while(0)
#define STACK_POP(_a, _b, _c, _d)\
do {\
DIVSUFSORT_ASSERT(0 <= ssize);\
if(ssize == 0) { return; }\
(_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
(_c) = stack[ssize].c, (_d) = stack[ssize].d;\
} while(0)
#define STACK_POP5(_a, _b, _c, _d, _e)\
do {\
DIVSUFSORT_ASSERT(0 <= ssize);\
if(ssize == 0) { return; }\
(_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
(_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\
} while(0)
#define BUCKET_A(_c0) bucket_A[(_c0)]
#if ALPHABET_SIZE == 256
#define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)])
#define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)])
#else
#define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)])
#define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)])
#endif
/*- Private Functions -*/
static const int lg_table[256]= {
-1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)
static forceinline
int
ss_ilg(int n) {
#if SS_BLOCKSIZE == 0
return (n & 0xffff0000) ?
((n & 0xff000000) ?
24 + lg_table[(n >> 24) & 0xff] :
16 + lg_table[(n >> 16) & 0xff]) :
((n & 0x0000ff00) ?
8 + lg_table[(n >> 8) & 0xff] :
0 + lg_table[(n >> 0) & 0xff]);
#elif SS_BLOCKSIZE < 256
return lg_table[n];
#else
return (n & 0xff00) ?
8 + lg_table[(n >> 8) & 0xff] :
0 + lg_table[(n >> 0) & 0xff];
#endif
}
#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */
#if SS_BLOCKSIZE != 0
static const int sqq_table[256] = {
0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61,
64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89,
90, 91, 93, 94, 96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109,
110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155,
156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168,
169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180,
181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191,
192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201,
202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211,
212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221,
221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230,
230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247,
247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255
};
static forceinline
int
ss_isqrt(int x) {
int y, e;
if(x >= (SS_BLOCKSIZE * SS_BLOCKSIZE)) { return SS_BLOCKSIZE; }
e = (x & 0xffff0000) ?
((x & 0xff000000) ?
24 + lg_table[(x >> 24) & 0xff] :
16 + lg_table[(x >> 16) & 0xff]) :
((x & 0x0000ff00) ?
8 + lg_table[(x >> 8) & 0xff] :
0 + lg_table[(x >> 0) & 0xff]);
if(e >= 16) {
y = sqq_table[x >> ((e - 6) - (e & 1))] << ((e >> 1) - 7);
if(e >= 24) { y = (y + 1 + x / y) >> 1; }
y = (y + 1 + x / y) >> 1;
} else if(e >= 8) {
y = (sqq_table[x >> ((e - 6) - (e & 1))] >> (7 - (e >> 1))) + 1;
} else {
return sqq_table[x] >> 4;
}
return (x < (y * y)) ? y - 1 : y;
}
#endif /* SS_BLOCKSIZE != 0 */
/*---------------------------------------------------------------------------*/
/* Compares two suffixes. */
static forceinline
int
ss_compare(const unsigned char *T,
const int *p1, const int *p2,
int depth) {
const unsigned char *U1, *U2, *U1n, *U2n;
for(U1 = T + depth + *p1,
U2 = T + depth + *p2,
U1n = T + *(p1 + 1) + 2,
U2n = T + *(p2 + 1) + 2;
(U1 < U1n) && (U2 < U2n) && (*U1 == *U2);
++U1, ++U2) {
}
return U1 < U1n ?
(U2 < U2n ? *U1 - *U2 : 1) :
(U2 < U2n ? -1 : 0);
}
/*---------------------------------------------------------------------------*/
#if (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1)
/* Insertionsort for small size groups */
static
void
ss_insertionsort(const unsigned char *T, const int *PA,
int *first, int *last, int depth) {
int *i, *j;
int t;
int r;
for(i = last - 2; first <= i; --i) {
for(t = *i, j = i + 1; 0 < (r = ss_compare(T, PA + t, PA + *j, depth));) {
do { *(j - 1) = *j; } while((++j < last) && (*j < 0));
if(last <= j) { break; }
}
if(r == 0) { *j = ~*j; }
*(j - 1) = t;
}
}
#endif /* (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) */
/*---------------------------------------------------------------------------*/
#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)
static forceinline
void
ss_fixdown(const unsigned char *Td, const int *PA,
int *SA, int i, int size) {
int j, k;
int v;
int c, d, e;
for(v = SA[i], c = Td[PA[v]]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {
d = Td[PA[SA[k = j++]]];
if(d < (e = Td[PA[SA[j]]])) { k = j; d = e; }
if(d <= c) { break; }
}
SA[i] = v;
}
/* Simple top-down heapsort. */
static
void
ss_heapsort(const unsigned char *Td, const int *PA, int *SA, int size) {
int i, m;
int t;
m = size;
if((size % 2) == 0) {
m--;
if(Td[PA[SA[m / 2]]] < Td[PA[SA[m]]]) { SWAP(SA[m], SA[m / 2]); }
}
for(i = m / 2 - 1; 0 <= i; --i) { ss_fixdown(Td, PA, SA, i, m); }
if((size % 2) == 0) { SWAP(SA[0], SA[m]); ss_fixdown(Td, PA, SA, 0, m); }
for(i = m - 1; 0 < i; --i) {
t = SA[0], SA[0] = SA[i];
ss_fixdown(Td, PA, SA, 0, i);
SA[i] = t;
}
}
/*---------------------------------------------------------------------------*/
/* Returns the median of three elements. */
static forceinline
int *
ss_median3(const unsigned char *Td, const int *PA,
int *v1, int *v2, int *v3) {
if(Td[PA[*v1]] > Td[PA[*v2]]) { SWAP(v1, v2); }
if(Td[PA[*v2]] > Td[PA[*v3]]) {
if(Td[PA[*v1]] > Td[PA[*v3]]) { return v1; }
else { return v3; }
}
return v2;
}
/* Returns the median of five elements. */
static forceinline
int *
ss_median5(const unsigned char *Td, const int *PA,
int *v1, int *v2, int *v3, int *v4, int *v5) {
if(Td[PA[*v2]] > Td[PA[*v3]]) { SWAP(v2, v3); }
if(Td[PA[*v4]] > Td[PA[*v5]]) { SWAP(v4, v5); }
if(Td[PA[*v2]] > Td[PA[*v4]]) { SWAP(v2, v4); SWAP(v3, v5); }
if(Td[PA[*v1]] > Td[PA[*v3]]) { SWAP(v1, v3); }
if(Td[PA[*v1]] > Td[PA[*v4]]) { SWAP(v1, v4); SWAP(v3, v5); }
if(Td[PA[*v3]] > Td[PA[*v4]]) { return v4; }
return v3;
}
/* Returns the pivot element. */
static forceinline
int *
ss_pivot(const unsigned char *Td, const int *PA, int *first, int *last) {
int *middle;
int t;
t = last - first;
middle = first + t / 2;
if(t <= 512) {
if(t <= 32) {
return ss_median3(Td, PA, first, middle, last - 1);
} else {
t >>= 2;
return ss_median5(Td, PA, first, first + t, middle, last - 1 - t, last - 1);
}
}
t >>= 3;
first = ss_median3(Td, PA, first, first + t, first + (t << 1));
middle = ss_median3(Td, PA, middle - t, middle, middle + t);
last = ss_median3(Td, PA, last - 1 - (t << 1), last - 1 - t, last - 1);
return ss_median3(Td, PA, first, middle, last);
}
/*---------------------------------------------------------------------------*/
/* Binary partition for substrings. */
static forceinline
int *
ss_partition(const int *PA,
int *first, int *last, int depth) {
int *a, *b;
int t;
for(a = first - 1, b = last;;) {
for(; (++a < b) && ((PA[*a] + depth) >= (PA[*a + 1] + 1));) { *a = ~*a; }
for(; (a < --b) && ((PA[*b] + depth) < (PA[*b + 1] + 1));) { }
if(b <= a) { break; }
t = ~*b;
*b = *a;
*a = t;
}
if(first < a) { *first = ~*first; }
return a;
}
/* Multikey introsort for medium size groups. */
static
void
ss_mintrosort(const unsigned char *T, const int *PA,
int *first, int *last,
int depth) {
#define STACK_SIZE SS_MISORT_STACKSIZE
struct { int *a, *b, c; int d; } stack[STACK_SIZE];
const unsigned char *Td;
int *a, *b, *c, *d, *e, *f;
int s, t;
int ssize;
int limit;
int v, x = 0;
for(ssize = 0, limit = ss_ilg(last - first);;) {
if((last - first) <= SS_INSERTIONSORT_THRESHOLD) {
#if 1 < SS_INSERTIONSORT_THRESHOLD
if(1 < (last - first)) { ss_insertionsort(T, PA, first, last, depth); }
#endif
STACK_POP(first, last, depth, limit);
continue;
}
Td = T + depth;
if(limit-- == 0) { ss_heapsort(Td, PA, first, last - first); }
if(limit < 0) {
for(a = first + 1, v = Td[PA[*first]]; a < last; ++a) {
if((x = Td[PA[*a]]) != v) {
if(1 < (a - first)) { break; }
v = x;
first = a;
}
}
if(Td[PA[*first] - 1] < v) {
first = ss_partition(PA, first, a, depth);
}
if((a - first) <= (last - a)) {
if(1 < (a - first)) {
STACK_PUSH(a, last, depth, -1);
last = a, depth += 1, limit = ss_ilg(a - first);
} else {
first = a, limit = -1;
}
} else {
if(1 < (last - a)) {
STACK_PUSH(first, a, depth + 1, ss_ilg(a - first));
first = a, limit = -1;
} else {
last = a, depth += 1, limit = ss_ilg(a - first);
}
}
continue;
}
/* choose pivot */
a = ss_pivot(Td, PA, first, last);
v = Td[PA[*a]];
SWAP(*first, *a);
/* partition */
for(b = first; (++b < last) && ((x = Td[PA[*b]]) == v);) { }
if(((a = b) < last) && (x < v)) {
for(; (++b < last) && ((x = Td[PA[*b]]) <= v);) {
if(x == v) { SWAP(*b, *a); ++a; }
}
}
for(c = last; (b < --c) && ((x = Td[PA[*c]]) == v);) { }
if((b < (d = c)) && (x > v)) {
for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {
if(x == v) { SWAP(*c, *d); --d; }
}
}
for(; b < c;) {
SWAP(*b, *c);
for(; (++b < c) && ((x = Td[PA[*b]]) <= v);) {
if(x == v) { SWAP(*b, *a); ++a; }
}
for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {
if(x == v) { SWAP(*c, *d); --d; }
}
}
if(a <= d) {
c = b - 1;
if((s = a - first) > (t = b - a)) { s = t; }
for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
if((s = d - c) > (t = last - d - 1)) { s = t; }
for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
a = first + (b - a), c = last - (d - c);
b = (v <= Td[PA[*a] - 1]) ? a : ss_partition(PA, a, c, depth);
if((a - first) <= (last - c)) {
if((last - c) <= (c - b)) {
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
STACK_PUSH(c, last, depth, limit);
last = a;
} else if((a - first) <= (c - b)) {
STACK_PUSH(c, last, depth, limit);
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
last = a;
} else {
STACK_PUSH(c, last, depth, limit);
STACK_PUSH(first, a, depth, limit);
first = b, last = c, depth += 1, limit = ss_ilg(c - b);
}
} else {
if((a - first) <= (c - b)) {
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
STACK_PUSH(first, a, depth, limit);
first = c;
} else if((last - c) <= (c - b)) {
STACK_PUSH(first, a, depth, limit);
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
first = c;
} else {
STACK_PUSH(first, a, depth, limit);
STACK_PUSH(c, last, depth, limit);
first = b, last = c, depth += 1, limit = ss_ilg(c - b);
}
}
} else {
limit += 1;
if(Td[PA[*first] - 1] < v) {
first = ss_partition(PA, first, last, depth);
limit = ss_ilg(last - first);
}
depth += 1;
}
}
#undef STACK_SIZE
}
#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */
/*---------------------------------------------------------------------------*/
#if SS_BLOCKSIZE != 0
static forceinline
void
ss_blockswap(int *a, int *b, int n) {
int t;
for(; 0 < n; --n, ++a, ++b) {
t = *a, *a = *b, *b = t;
}
}
static forceinline
void
ss_rotate(int *first, int *middle, int *last) {
int *a, *b, t;
int l, r;
l = middle - first, r = last - middle;
for(; (0 < l) && (0 < r);) {
if(l == r) { ss_blockswap(first, middle, l); break; }
if(l < r) {
a = last - 1, b = middle - 1;
t = *a;
do {
*a-- = *b, *b-- = *a;
if(b < first) {
*a = t;
last = a;
if((r -= l + 1) <= l) { break; }
a -= 1, b = middle - 1;
t = *a;
}
} while(1);
} else {
a = first, b = middle;
t = *a;
do {
*a++ = *b, *b++ = *a;
if(last <= b) {
*a = t;
first = a + 1;
if((l -= r + 1) <= r) { break; }
a += 1, b = middle;
t = *a;
}
} while(1);
}
}
}
/*---------------------------------------------------------------------------*/
static
void
ss_inplacemerge(const unsigned char *T, const int *PA,
int *first, int *middle, int *last,
int depth) {
const int *p;
int *a, *b;
int len, half;
int q, r;
int x;
for(;;) {
if(*(last - 1) < 0) { x = 1; p = PA + ~*(last - 1); }
else { x = 0; p = PA + *(last - 1); }
for(a = first, len = middle - first, half = len >> 1, r = -1;
0 < len;
len = half, half >>= 1) {
b = a + half;
q = ss_compare(T, PA + ((0 <= *b) ? *b : ~*b), p, depth);
if(q < 0) {
a = b + 1;
half -= (len & 1) ^ 1;
} else {
r = q;
}
}
if(a < middle) {
if(r == 0) { *a = ~*a; }
ss_rotate(a, middle, last);
last -= middle - a;
middle = a;
if(first == middle) { break; }
}
--last;
if(x != 0) { while(*--last < 0) { } }
if(middle == last) { break; }
}
}
/*---------------------------------------------------------------------------*/
/* Merge-forward with internal buffer. */
static
void
ss_mergeforward(const unsigned char *T, const int *PA,
int *first, int *middle, int *last,
int *buf, int depth) {
int *a, *b, *c, *bufend;
int t;
int r;
bufend = buf + (middle - first) - 1;
ss_blockswap(buf, first, middle - first);
for(t = *(a = first), b = buf, c = middle;;) {
r = ss_compare(T, PA + *b, PA + *c, depth);
if(r < 0) {
do {
*a++ = *b;
if(bufend <= b) { *bufend = t; return; }
*b++ = *a;
} while(*b < 0);
} else if(r > 0) {
do {
*a++ = *c, *c++ = *a;
if(last <= c) {
while(b < bufend) { *a++ = *b, *b++ = *a; }
*a = *b, *b = t;
return;
}
} while(*c < 0);
} else {
*c = ~*c;
do {
*a++ = *b;
if(bufend <= b) { *bufend = t; return; }
*b++ = *a;
} while(*b < 0);
do {
*a++ = *c, *c++ = *a;
if(last <= c) {
while(b < bufend) { *a++ = *b, *b++ = *a; }
*a = *b, *b = t;
return;
}
} while(*c < 0);
}
}
}
/* Merge-backward with internal buffer. */
static
void
ss_mergebackward(const unsigned char *T, const int *PA,
int *first, int *middle, int *last,
int *buf, int depth) {
const int *p1, *p2;
int *a, *b, *c, *bufend;
int t;
int r;
int x;
bufend = buf + (last - middle) - 1;
ss_blockswap(buf, middle, last - middle);
x = 0;
if(*bufend < 0) { p1 = PA + ~*bufend; x |= 1; }
else { p1 = PA + *bufend; }
if(*(middle - 1) < 0) { p2 = PA + ~*(middle - 1); x |= 2; }
else { p2 = PA + *(middle - 1); }
for(t = *(a = last - 1), b = bufend, c = middle - 1;;) {
r = ss_compare(T, p1, p2, depth);
if(0 < r) {
if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }
*a-- = *b;
if(b <= buf) { *buf = t; break; }
*b-- = *a;
if(*b < 0) { p1 = PA + ~*b; x |= 1; }
else { p1 = PA + *b; }
} else if(r < 0) {
if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }
*a-- = *c, *c-- = *a;
if(c < first) {
while(buf < b) { *a-- = *b, *b-- = *a; }
*a = *b, *b = t;
break;
}
if(*c < 0) { p2 = PA + ~*c; x |= 2; }
else { p2 = PA + *c; }
} else {
if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }
*a-- = ~*b;
if(b <= buf) { *buf = t; break; }
*b-- = *a;
if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }
*a-- = *c, *c-- = *a;
if(c < first) {
while(buf < b) { *a-- = *b, *b-- = *a; }
*a = *b, *b = t;
break;
}
if(*b < 0) { p1 = PA + ~*b; x |= 1; }
else { p1 = PA + *b; }
if(*c < 0) { p2 = PA + ~*c; x |= 2; }
else { p2 = PA + *c; }
}
}
}
/* D&C based merge. */
static
void
ss_swapmerge(const unsigned char *T, const int *PA,
int *first, int *middle, int *last,
int *buf, int bufsize, int depth) {
#define STACK_SIZE SS_SMERGE_STACKSIZE
#define GETIDX(a) ((0 <= (a)) ? (a) : (~(a)))
#define MERGE_CHECK(a, b, c)\
do {\
if(((c) & 1) ||\
(((c) & 2) && (ss_compare(T, PA + GETIDX(*((a) - 1)), PA + *(a), depth) == 0))) {\
*(a) = ~*(a);\
}\
if(((c) & 4) && ((ss_compare(T, PA + GETIDX(*((b) - 1)), PA + *(b), depth) == 0))) {\
*(b) = ~*(b);\
}\
} while(0)
struct { int *a, *b, *c; int d; } stack[STACK_SIZE];
int *l, *r, *lm, *rm;
int m, len, half;
int ssize;
int check, next;
for(check = 0, ssize = 0;;) {
if((last - middle) <= bufsize) {
if((first < middle) && (middle < last)) {
ss_mergebackward(T, PA, first, middle, last, buf, depth);
}
MERGE_CHECK(first, last, check);
STACK_POP(first, middle, last, check);
continue;
}
if((middle - first) <= bufsize) {
if(first < middle) {
ss_mergeforward(T, PA, first, middle, last, buf, depth);
}
MERGE_CHECK(first, last, check);
STACK_POP(first, middle, last, check);
continue;
}
for(m = 0, len = MIN(middle - first, last - middle), half = len >> 1;
0 < len;
len = half, half >>= 1) {
if(ss_compare(T, PA + GETIDX(*(middle + m + half)),
PA + GETIDX(*(middle - m - half - 1)), depth) < 0) {
m += half + 1;
half -= (len & 1) ^ 1;
}
}
if(0 < m) {
lm = middle - m, rm = middle + m;
ss_blockswap(lm, middle, m);
l = r = middle, next = 0;
if(rm < last) {
if(*rm < 0) {
*rm = ~*rm;
if(first < lm) { for(; *--l < 0;) { } next |= 4; }
next |= 1;
} else if(first < lm) {
for(; *r < 0; ++r) { }
next |= 2;
}
}
if((l - first) <= (last - r)) {
STACK_PUSH(r, rm, last, (next & 3) | (check & 4));
middle = lm, last = l, check = (check & 3) | (next & 4);
} else {
if((next & 2) && (r == middle)) { next ^= 6; }
STACK_PUSH(first, lm, l, (check & 3) | (next & 4));
first = r, middle = rm, check = (next & 3) | (check & 4);
}
} else {
if(ss_compare(T, PA + GETIDX(*(middle - 1)), PA + *middle, depth) == 0) {
*middle = ~*middle;
}
MERGE_CHECK(first, last, check);
STACK_POP(first, middle, last, check);
}
}
#undef STACK_SIZE
}
#endif /* SS_BLOCKSIZE != 0 */
/*---------------------------------------------------------------------------*/
/* Substring sort */
static
void
sssort(const unsigned char *T, const int *PA,
int *first, int *last,
int *buf, int bufsize,
int depth, int n, int lastsuffix) {
int *a;
#if SS_BLOCKSIZE != 0
int *b, *middle, *curbuf;
int j, k, curbufsize, limit;
#endif
int i;
if(lastsuffix != 0) { ++first; }
#if SS_BLOCKSIZE == 0
ss_mintrosort(T, PA, first, last, depth);
#else
if((bufsize < SS_BLOCKSIZE) &&
(bufsize < (last - first)) &&
(bufsize < (limit = ss_isqrt(last - first)))) {
if(SS_BLOCKSIZE < limit) { limit = SS_BLOCKSIZE; }
buf = middle = last - limit, bufsize = limit;
} else {
middle = last, limit = 0;
}
for(a = first, i = 0; SS_BLOCKSIZE < (middle - a); a += SS_BLOCKSIZE, ++i) {
#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
ss_mintrosort(T, PA, a, a + SS_BLOCKSIZE, depth);
#elif 1 < SS_BLOCKSIZE
ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth);
#endif
curbufsize = last - (a + SS_BLOCKSIZE);
curbuf = a + SS_BLOCKSIZE;
if(curbufsize <= bufsize) { curbufsize = bufsize, curbuf = buf; }
for(b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) {
ss_swapmerge(T, PA, b - k, b, b + k, curbuf, curbufsize, depth);
}
}
#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
ss_mintrosort(T, PA, a, middle, depth);
#elif 1 < SS_BLOCKSIZE
ss_insertionsort(T, PA, a, middle, depth);
#endif
for(k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) {
if(i & 1) {
ss_swapmerge(T, PA, a - k, a, middle, buf, bufsize, depth);
a -= k;
}
}
if(limit != 0) {
#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
ss_mintrosort(T, PA, middle, last, depth);
#elif 1 < SS_BLOCKSIZE
ss_insertionsort(T, PA, middle, last, depth);
#endif
ss_inplacemerge(T, PA, first, middle, last, depth);
}
#endif
if(lastsuffix != 0) {
/* Insert last type B* suffix. */
int PAi[2]; PAi[0] = PA[*(first - 1)], PAi[1] = n - 2;
for(a = first, i = *(first - 1);
(a < last) && ((*a < 0) || (0 < ss_compare(T, &(PAi[0]), PA + *a, depth)));
++a) {
*(a - 1) = *a;
}
*(a - 1) = i;
}
}
/*---------------------------------------------------------------------------*/
static forceinline
int
tr_ilg(int n) {
return (n & 0xffff0000) ?
((n & 0xff000000) ?
24 + lg_table[(n >> 24) & 0xff] :
16 + lg_table[(n >> 16) & 0xff]) :
((n & 0x0000ff00) ?
8 + lg_table[(n >> 8) & 0xff] :
0 + lg_table[(n >> 0) & 0xff]);
}
/*---------------------------------------------------------------------------*/
/* Simple insertionsort for small size groups. */
static
void
tr_insertionsort(const int *ISAd, int *first, int *last) {
int *a, *b;
int t, r;
for(a = first + 1; a < last; ++a) {
for(t = *a, b = a - 1; 0 > (r = ISAd[t] - ISAd[*b]);) {
do { *(b + 1) = *b; } while((first <= --b) && (*b < 0));
if(b < first) { break; }
}
if(r == 0) { *b = ~*b; }
*(b + 1) = t;
}
}
/*---------------------------------------------------------------------------*/
static forceinline
void
tr_fixdown(const int *ISAd, int *SA, int i, int size) {
int j, k;
int v;
int c, d, e;
for(v = SA[i], c = ISAd[v]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {
d = ISAd[SA[k = j++]];
if(d < (e = ISAd[SA[j]])) { k = j; d = e; }
if(d <= c) { break; }
}
SA[i] = v;
}
/* Simple top-down heapsort. */
static
void
tr_heapsort(const int *ISAd, int *SA, int size) {
int i, m;
int t;
m = size;
if((size % 2) == 0) {
m--;
if(ISAd[SA[m / 2]] < ISAd[SA[m]]) { SWAP(SA[m], SA[m / 2]); }
}
for(i = m / 2 - 1; 0 <= i; --i) { tr_fixdown(ISAd, SA, i, m); }
if((size % 2) == 0) { SWAP(SA[0], SA[m]); tr_fixdown(ISAd, SA, 0, m); }
for(i = m - 1; 0 < i; --i) {
t = SA[0], SA[0] = SA[i];
tr_fixdown(ISAd, SA, 0, i);
SA[i] = t;
}
}
/*---------------------------------------------------------------------------*/
/* Returns the median of three elements. */
static forceinline
int *
tr_median3(const int *ISAd, int *v1, int *v2, int *v3) {
if(ISAd[*v1] > ISAd[*v2]) { SWAP(v1, v2); }
if(ISAd[*v2] > ISAd[*v3]) {
if(ISAd[*v1] > ISAd[*v3]) { return v1; }
else { return v3; }
}
return v2;
}
/* Returns the median of five elements. */
static forceinline
int *
tr_median5(const int *ISAd,
int *v1, int *v2, int *v3, int *v4, int *v5) {
if(ISAd[*v2] > ISAd[*v3]) { SWAP(v2, v3); }
if(ISAd[*v4] > ISAd[*v5]) { SWAP(v4, v5); }
if(ISAd[*v2] > ISAd[*v4]) { SWAP(v2, v4); SWAP(v3, v5); }
if(ISAd[*v1] > ISAd[*v3]) { SWAP(v1, v3); }
if(ISAd[*v1] > ISAd[*v4]) { SWAP(v1, v4); SWAP(v3, v5); }
if(ISAd[*v3] > ISAd[*v4]) { return v4; }
return v3;
}
/* Returns the pivot element. */
static forceinline
int *
tr_pivot(const int *ISAd, int *first, int *last) {
int *middle;
int t;
t = last - first;
middle = first + t / 2;
if(t <= 512) {
if(t <= 32) {
return tr_median3(ISAd, first, middle, last - 1);
} else {
t >>= 2;
return tr_median5(ISAd, first, first + t, middle, last - 1 - t, last - 1);
}
}
t >>= 3;
first = tr_median3(ISAd, first, first + t, first + (t << 1));
middle = tr_median3(ISAd, middle - t, middle, middle + t);
last = tr_median3(ISAd, last - 1 - (t << 1), last - 1 - t, last - 1);
return tr_median3(ISAd, first, middle, last);
}
/*---------------------------------------------------------------------------*/
typedef struct _trbudget_t trbudget_t;
struct _trbudget_t {
int chance;
int remain;
int incval;
int count;
};
static forceinline
void
trbudget_init(trbudget_t *budget, int chance, int incval) {
budget->chance = chance;
budget->remain = budget->incval = incval;
}
static forceinline
int
trbudget_check(trbudget_t *budget, int size) {
if(size <= budget->remain) { budget->remain -= size; return 1; }
if(budget->chance == 0) { budget->count += size; return 0; }
budget->remain += budget->incval - size;
budget->chance -= 1;
return 1;
}
/*---------------------------------------------------------------------------*/
static forceinline
void
tr_partition(const int *ISAd,
int *first, int *middle, int *last,
int **pa, int **pb, int v) {
int *a, *b, *c, *d, *e, *f;
int t, s;
int x = 0;
for(b = middle - 1; (++b < last) && ((x = ISAd[*b]) == v);) { }
if(((a = b) < last) && (x < v)) {
for(; (++b < last) && ((x = ISAd[*b]) <= v);) {
if(x == v) { SWAP(*b, *a); ++a; }
}
}
for(c = last; (b < --c) && ((x = ISAd[*c]) == v);) { }
if((b < (d = c)) && (x > v)) {
for(; (b < --c) && ((x = ISAd[*c]) >= v);) {
if(x == v) { SWAP(*c, *d); --d; }
}
}
for(; b < c;) {
SWAP(*b, *c);
for(; (++b < c) && ((x = ISAd[*b]) <= v);) {
if(x == v) { SWAP(*b, *a); ++a; }
}
for(; (b < --c) && ((x = ISAd[*c]) >= v);) {
if(x == v) { SWAP(*c, *d); --d; }
}
}
if(a <= d) {
c = b - 1;
if((s = a - first) > (t = b - a)) { s = t; }
for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
if((s = d - c) > (t = last - d - 1)) { s = t; }
for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
first += (b - a), last -= (d - c);
}
*pa = first, *pb = last;
}
static
void
tr_copy(int *ISA, const int *SA,
int *first, int *a, int *b, int *last,
int depth) {
/* sort suffixes of middle partition
by using sorted order of suffixes of left and right partition. */
int *c, *d, *e;
int s, v;
v = b - SA - 1;
for(c = first, d = a - 1; c <= d; ++c) {
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
*++d = s;
ISA[s] = d - SA;
}
}
for(c = last - 1, e = d + 1, d = b; e < d; --c) {
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
*--d = s;
ISA[s] = d - SA;
}
}
}
static
void
tr_partialcopy(int *ISA, const int *SA,
int *first, int *a, int *b, int *last,
int depth) {
int *c, *d, *e;
int s, v;
int rank, lastrank, newrank = -1;
v = b - SA - 1;
lastrank = -1;
for(c = first, d = a - 1; c <= d; ++c) {
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
*++d = s;
rank = ISA[s + depth];
if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
ISA[s] = newrank;
}
}
lastrank = -1;
for(e = d; first <= e; --e) {
rank = ISA[*e];
if(lastrank != rank) { lastrank = rank; newrank = e - SA; }
if(newrank != rank) { ISA[*e] = newrank; }
}
lastrank = -1;
for(c = last - 1, e = d + 1, d = b; e < d; --c) {
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
*--d = s;
rank = ISA[s + depth];
if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
ISA[s] = newrank;
}
}
}
static
void
tr_introsort(int *ISA, const int *ISAd,
int *SA, int *first, int *last,
trbudget_t *budget) {
#define STACK_SIZE TR_STACKSIZE
struct { const int *a; int *b, *c; int d, e; }stack[STACK_SIZE];
int *a, *b, *c;
int v, x = 0;
int incr = ISAd - ISA;
int limit, next;
int ssize, trlink = -1;
for(ssize = 0, limit = tr_ilg(last - first);;) {
if(limit < 0) {
if(limit == -1) {
/* tandem repeat partition */
tr_partition(ISAd - incr, first, first, last, &a, &b, last - SA - 1);
/* update ranks */
if(a < last) {
for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
}
if(b < last) {
for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; }
}
/* push */
if(1 < (b - a)) {
STACK_PUSH5(NULL, a, b, 0, 0);
STACK_PUSH5(ISAd - incr, first, last, -2, trlink);
trlink = ssize - 2;
}
if((a - first) <= (last - b)) {
if(1 < (a - first)) {
STACK_PUSH5(ISAd, b, last, tr_ilg(last - b), trlink);
last = a, limit = tr_ilg(a - first);
} else if(1 < (last - b)) {
first = b, limit = tr_ilg(last - b);
} else {
STACK_POP5(ISAd, first, last, limit, trlink);
}
} else {
if(1 < (last - b)) {
STACK_PUSH5(ISAd, first, a, tr_ilg(a - first), trlink);
first = b, limit = tr_ilg(last - b);
} else if(1 < (a - first)) {
last = a, limit = tr_ilg(a - first);
} else {
STACK_POP5(ISAd, first, last, limit, trlink);
}
}
} else if(limit == -2) {
/* tandem repeat copy */
a = stack[--ssize].b, b = stack[ssize].c;
if(stack[ssize].d == 0) {
tr_copy(ISA, SA, first, a, b, last, ISAd - ISA);
} else {
if(0 <= trlink) { stack[trlink].d = -1; }
tr_partialcopy(ISA, SA, first, a, b, last, ISAd - ISA);
}
STACK_POP5(ISAd, first, last, limit, trlink);
} else {
/* sorted partition */
if(0 <= *first) {
a = first;
do { ISA[*a] = a - SA; } while((++a < last) && (0 <= *a));
first = a;
}
if(first < last) {
a = first; do { *a = ~*a; } while(*++a < 0);
next = (ISA[*a] != ISAd[*a]) ? tr_ilg(a - first + 1) : -1;
if(++a < last) { for(b = first, v = a - SA - 1; b < a; ++b) { ISA[*b] = v; } }
/* push */
if(trbudget_check(budget, a - first)) {
if((a - first) <= (last - a)) {
STACK_PUSH5(ISAd, a, last, -3, trlink);
ISAd += incr, last = a, limit = next;
} else {
if(1 < (last - a)) {
STACK_PUSH5(ISAd + incr, first, a, next, trlink);
first = a, limit = -3;
} else {
ISAd += incr, last = a, limit = next;
}
}
} else {
if(0 <= trlink) { stack[trlink].d = -1; }
if(1 < (last - a)) {
first = a, limit = -3;
} else {
STACK_POP5(ISAd, first, last, limit, trlink);
}
}
} else {
STACK_POP5(ISAd, first, last, limit, trlink);
}
}
continue;
}
if((last - first) <= TR_INSERTIONSORT_THRESHOLD) {
tr_insertionsort(ISAd, first, last);
limit = -3;
continue;
}
if(limit-- == 0) {
tr_heapsort(ISAd, first, last - first);
for(a = last - 1; first < a; a = b) {
for(x = ISAd[*a], b = a - 1; (first <= b) && (ISAd[*b] == x); --b) { *b = ~*b; }
}
limit = -3;
continue;
}
/* choose pivot */
a = tr_pivot(ISAd, first, last);
SWAP(*first, *a);
v = ISAd[*first];
/* partition */
tr_partition(ISAd, first, first + 1, last, &a, &b, v);
if((last - first) != (b - a)) {
next = (ISA[*a] != v) ? tr_ilg(b - a) : -1;
/* update ranks */
for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
if(b < last) { for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } }
/* push */
if((1 < (b - a)) && (trbudget_check(budget, b - a))) {
if((a - first) <= (last - b)) {
if((last - b) <= (b - a)) {
if(1 < (a - first)) {
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
STACK_PUSH5(ISAd, b, last, limit, trlink);
last = a;
} else if(1 < (last - b)) {
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
first = b;
} else {
ISAd += incr, first = a, last = b, limit = next;
}
} else if((a - first) <= (b - a)) {
if(1 < (a - first)) {
STACK_PUSH5(ISAd, b, last, limit, trlink);
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
last = a;
} else {
STACK_PUSH5(ISAd, b, last, limit, trlink);
ISAd += incr, first = a, last = b, limit = next;
}
} else {
STACK_PUSH5(ISAd, b, last, limit, trlink);
STACK_PUSH5(ISAd, first, a, limit, trlink);
ISAd += incr, first = a, last = b, limit = next;
}
} else {
if((a - first) <= (b - a)) {
if(1 < (last - b)) {
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
STACK_PUSH5(ISAd, first, a, limit, trlink);
first = b;
} else if(1 < (a - first)) {
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
last = a;
} else {
ISAd += incr, first = a, last = b, limit = next;
}
} else if((last - b) <= (b - a)) {
if(1 < (last - b)) {
STACK_PUSH5(ISAd, first, a, limit, trlink);
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
first = b;
} else {
STACK_PUSH5(ISAd, first, a, limit, trlink);
ISAd += incr, first = a, last = b, limit = next;
}
} else {
STACK_PUSH5(ISAd, first, a, limit, trlink);
STACK_PUSH5(ISAd, b, last, limit, trlink);
ISAd += incr, first = a, last = b, limit = next;
}
}
} else {
if((1 < (b - a)) && (0 <= trlink)) { stack[trlink].d = -1; }
if((a - first) <= (last - b)) {
if(1 < (a - first)) {
STACK_PUSH5(ISAd, b, last, limit, trlink);
last = a;
} else if(1 < (last - b)) {
first = b;
} else {
STACK_POP5(ISAd, first, last, limit, trlink);
}
} else {
if(1 < (last - b)) {
STACK_PUSH5(ISAd, first, a, limit, trlink);
first = b;
} else if(1 < (a - first)) {
last = a;
} else {
STACK_POP5(ISAd, first, last, limit, trlink);
}
}
}
} else {
if(trbudget_check(budget, last - first)) {
limit = tr_ilg(last - first), ISAd += incr;
} else {
if(0 <= trlink) { stack[trlink].d = -1; }
STACK_POP5(ISAd, first, last, limit, trlink);
}
}
}
#undef STACK_SIZE
}
/*---------------------------------------------------------------------------*/
/* Tandem repeat sort */
static
void
trsort(int *ISA, int *SA, int n, int depth) {
int *ISAd;
int *first, *last;
trbudget_t budget;
int t, skip, unsorted;
trbudget_init(&budget, tr_ilg(n) * 2 / 3, n);
/* trbudget_init(&budget, tr_ilg(n) * 3 / 4, n); */
for(ISAd = ISA + depth; -n < *SA; ISAd += ISAd - ISA) {
first = SA;
skip = 0;
unsorted = 0;
do {
if((t = *first) < 0) { first -= t; skip += t; }
else {
if(skip != 0) { *(first + skip) = skip; skip = 0; }
last = SA + ISA[t] + 1;
if(1 < (last - first)) {
budget.count = 0;
tr_introsort(ISA, ISAd, SA, first, last, &budget);
if(budget.count != 0) { unsorted += budget.count; }
else { skip = first - last; }
} else if((last - first) == 1) {
skip = -1;
}
first = last;
}
} while(first < (SA + n));
if(skip != 0) { *(first + skip) = skip; }
if(unsorted == 0) { break; }
}
}
/*---------------------------------------------------------------------------*/
/* Sorts suffixes of type B*. */
static
int
sort_typeBstar(const unsigned char *T, int *SA,
int *bucket_A, int *bucket_B,
int n) {
int *PAb, *ISAb, *buf;
int i, j, k, t, m, bufsize;
int c0, c1;
/* Initialize bucket arrays. */
for(i = 0; i < BUCKET_A_SIZE; ++i) { bucket_A[i] = 0; }
for(i = 0; i < BUCKET_B_SIZE; ++i) { bucket_B[i] = 0; }
/* Count the number of occurrences of the first one or two characters of each
type A, B and B* suffix. Moreover, store the beginning position of all
type B* suffixes into the array SA. */
for(i = n - 1, m = n, c0 = T[n - 1]; 0 <= i;) {
/* type A suffix. */
do { ++BUCKET_A(c1 = c0); } while((0 <= --i) && ((c0 = T[i]) >= c1));
if(0 <= i) {
/* type B* suffix. */
++BUCKET_BSTAR(c0, c1);
SA[--m] = i;
/* type B suffix. */
for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) {
++BUCKET_B(c0, c1);
}
}
}
m = n - m;
/*
note:
A type B* suffix is lexicographically smaller than a type B suffix that
begins with the same first two characters.
*/
/* Calculate the index of start/end point of each bucket. */
for(c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) {
t = i + BUCKET_A(c0);
BUCKET_A(c0) = i + j; /* start point */
i = t + BUCKET_B(c0, c0);
for(c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) {
j += BUCKET_BSTAR(c0, c1);
BUCKET_BSTAR(c0, c1) = j; /* end point */
i += BUCKET_B(c0, c1);
}
}
if(0 < m) {
/* Sort the type B* suffixes by their first two characters. */
PAb = SA + n - m; ISAb = SA + m;
for(i = m - 2; 0 <= i; --i) {
t = PAb[i], c0 = T[t], c1 = T[t + 1];
SA[--BUCKET_BSTAR(c0, c1)] = i;
}
t = PAb[m - 1], c0 = T[t], c1 = T[t + 1];
SA[--BUCKET_BSTAR(c0, c1)] = m - 1;
/* Sort the type B* substrings using sssort. */
buf = SA + m, bufsize = n - (2 * m);
for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) {
for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) {
i = BUCKET_BSTAR(c0, c1);
if(1 < (j - i)) {
sssort(T, PAb, SA + i, SA + j,
buf, bufsize, 2, n, *(SA + i) == (m - 1));
}
}
}
/* Compute ranks of type B* substrings. */
for(i = m - 1; 0 <= i; --i) {
if(0 <= SA[i]) {
j = i;
do { ISAb[SA[i]] = i; } while((0 <= --i) && (0 <= SA[i]));
SA[i + 1] = i - j;
if(i <= 0) { break; }
}
j = i;
do { ISAb[SA[i] = ~SA[i]] = j; } while(SA[--i] < 0);
ISAb[SA[i]] = j;
}
/* Construct the inverse suffix array of type B* suffixes using trsort. */
trsort(ISAb, SA, m, 1);
/* Set the sorted order of tyoe B* suffixes. */
for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) {
for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { }
if(0 <= i) {
t = i;
for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { }
SA[ISAb[--j]] = ((t == 0) || (1 < (t - i))) ? t : ~t;
}
}
/* Calculate the index of start/end point of each bucket. */
BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */
for(c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) {
i = BUCKET_A(c0 + 1) - 1;
for(c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) {
t = i - BUCKET_B(c0, c1);
BUCKET_B(c0, c1) = i; /* end point */
/* Move all type B* suffixes to the correct position. */
for(i = t, j = BUCKET_BSTAR(c0, c1);
j <= k;
--i, --k) { SA[i] = SA[k]; }
}
BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */
BUCKET_B(c0, c0) = i; /* end point */
}
}
return m;
}
/* Constructs the suffix array by using the sorted order of type B* suffixes. */
static
void
construct_SA(const unsigned char *T, int *SA,
int *bucket_A, int *bucket_B,
int n, int m) {
int *i, *j, *k;
int s;
int c0, c1, c2;
if(0 < m) {
/* Construct the sorted order of type B suffixes by using
the sorted order of type B* suffixes. */
for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
/* Scan the suffix array from right to left. */
for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
i <= j;
--j) {
if(0 < (s = *j)) {
DIVSUFSORT_ASSERT(T[s] == c1);
DIVSUFSORT_ASSERT(((s + 1) < n) && (T[s] <= T[s + 1]));
DIVSUFSORT_ASSERT(T[s - 1] <= T[s]);
*j = ~s;
c0 = T[--s];
if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
if(c0 != c2) {
if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
k = SA + BUCKET_B(c2 = c0, c1);
}
DIVSUFSORT_ASSERT(k < j);
*k-- = s;
} else {
DIVSUFSORT_ASSERT(((s == 0) && (T[s] == c1)) || (s < 0));
*j = ~s;
}
}
}
}
/* Construct the suffix array by using
the sorted order of type B suffixes. */
k = SA + BUCKET_A(c2 = T[n - 1]);
*k++ = (T[n - 2] < c2) ? ~(n - 1) : (n - 1);
/* Scan the suffix array from left to right. */
for(i = SA, j = SA + n; i < j; ++i) {
if(0 < (s = *i)) {
DIVSUFSORT_ASSERT(T[s - 1] >= T[s]);
c0 = T[--s];
if((s == 0) || (T[s - 1] < c0)) { s = ~s; }
if(c0 != c2) {
BUCKET_A(c2) = k - SA;
k = SA + BUCKET_A(c2 = c0);
}
DIVSUFSORT_ASSERT(i < k);
*k++ = s;
} else {
DIVSUFSORT_ASSERT(s < 0);
*i = ~s;
}
}
}
/*---------------------------------------------------------------------------*/
/*- Function -*/
/* XXX Modified from original: use provided temporary space instead of
* allocating it. */
void
divsufsort(const u8 *T, u32 *SA, u32 n, u32 *tmp)
{
u32 *bucket_A = tmp;
u32 *bucket_B = tmp + BUCKET_A_SIZE;
u32 m;
switch (n) {
case 0:
break;
case 1:
SA[0] = 0;
break;
case 2:
m = (T[0] < T[1]);
SA[m ^ 1] = 0;
SA[m] = 1;
break;
default:
m = sort_typeBstar(T, SA, bucket_A, bucket_B, n);
construct_SA(T, SA, bucket_A, bucket_B, n, m);
break;
}
}
wimlib-1.14.5/src/update_image.c 0000644 0001750 0001750 00000117527 15137020663 013756 0 ustar 00e e /*
* update_image.c - see description below
*/
/*
* Copyright (C) 2013, 2014 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
/*
* This file contains the implementation of wimlib_update_image(), which is one
* of the two ways by which library users can make changes to a WIM image. (The
* other way is by mounting an image read-write.) wimlib_update_image() is also
* used in the implementation of wimlib_add_image(), since "create a WIM image
* from this directory tree" is equivalent to "create an empty WIM image, then
* update it to add this directory tree as the root".
*
* wimlib_update_image() processes a list of commands passed to it. Currently,
* the following types of commands are supported:
*
* - Add a directory tree from an external source (filesystem or NTFS volume).
* This can be used to add new files or to replace existing files.
* - Delete a file or directory tree.
* - Rename a file or directory tree.
*
* Not supported are creating links to existing files or changing metadata of
* existing files.
*
* wimlib_update_image() is atomic. If it cannot complete successfully, then
* all changes are rolled back and the WIMStruct is left unchanged. Rollback is
* implemented by breaking the commands into primitive operations such as "link
* this dentry tree here" which can be undone by doing the opposite operations
* in reverse order.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#include "wimlib/alloca.h"
#include "wimlib/assert.h"
#include "wimlib/blob_table.h"
#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/metadata.h"
#include "wimlib/paths.h"
#include "wimlib/progress.h"
#include "wimlib/scan.h"
#include "wimlib/test_support.h"
#include "wimlib/xml_windows.h"
/* Saved specification of a "primitive" update operation that was performed. */
struct update_primitive {
enum {
/* Unlinked a dentry from its parent directory. */
UNLINK_DENTRY,
/* Linked a dentry into its parent directory. */
LINK_DENTRY,
/* Changed the file name of a dentry. */
CHANGE_FILE_NAME,
/* Changed the short name of a dentry. */
CHANGE_SHORT_NAME,
} type;
union {
/* For UNLINK_DENTRY and LINK_DENTRY operations */
struct {
/* Dentry that was linked or unlinked. */
struct wim_dentry *subject;
/* For link operations, the directory into which
* @subject was linked, or NULL if @subject was set as
* the root of the image.
*
* For unlink operations, the directory from which
* @subject was unlinked, or NULL if @subject was unset
* as the root of the image. */
struct wim_dentry *parent;
} link;
/* For CHANGE_FILE_NAME and CHANGE_SHORT_NAME operations */
struct {
/* Dentry that had its name changed. */
struct wim_dentry *subject;
/* The old name. */
utf16lechar *old_name;
} name;
};
};
/* Chronological list of primitive operations that were executed for a single
* logical update command, such as 'add', 'delete', or 'rename'. */
struct update_primitive_list {
struct update_primitive *entries;
struct update_primitive inline_entries[4];
size_t num_entries;
size_t num_alloc_entries;
};
/* Journal for managing the executing of zero or more logical update commands,
* such as 'add', 'delete', or 'rename'. This allows either committing or
* rolling back the commands. */
struct update_command_journal {
/* Number of update commands this journal contains. */
size_t num_cmds;
/* Index of currently executing update command. */
size_t cur_cmd;
/* Location of the WIM image's root pointer. */
struct wim_dentry **root_p;
/* Pointer to the blob table of the WIM (may needed for rollback) */
struct blob_table *blob_table;
/* List of dentries that are currently unlinked from the WIM image.
* These must be freed when no longer needed for commit or rollback. */
struct list_head orphans;
/* Per-command logs. */
struct update_primitive_list cmd_prims[];
};
static void
init_update_primitive_list(struct update_primitive_list *l)
{
l->entries = l->inline_entries;
l->num_entries = 0;
l->num_alloc_entries = ARRAY_LEN(l->inline_entries);
}
/* Allocates a new journal for managing the execution of up to @num_cmds update
* commands. */
static struct update_command_journal *
new_update_command_journal(size_t num_cmds, struct wim_dentry **root_p,
struct blob_table *blob_table)
{
struct update_command_journal *j;
j = MALLOC(sizeof(*j) + num_cmds * sizeof(j->cmd_prims[0]));
if (j) {
j->num_cmds = num_cmds;
j->cur_cmd = 0;
j->root_p = root_p;
j->blob_table = blob_table;
INIT_LIST_HEAD(&j->orphans);
for (size_t i = 0; i < num_cmds; i++)
init_update_primitive_list(&j->cmd_prims[i]);
}
return j;
}
/* Don't call this directly; use commit_update() or rollback_update() instead.
*/
static void
free_update_command_journal(struct update_command_journal *j)
{
struct wim_dentry *orphan;
/* Free orphaned dentry trees */
while (!list_empty(&j->orphans)) {
orphan = list_first_entry(&j->orphans,
struct wim_dentry, d_tmp_list);
list_del(&orphan->d_tmp_list);
free_dentry_tree(orphan, j->blob_table);
}
for (size_t i = 0; i < j->num_cmds; i++)
if (j->cmd_prims[i].entries != j->cmd_prims[i].inline_entries)
FREE(j->cmd_prims[i].entries);
FREE(j);
}
/* Add the entry @prim to the update command journal @j. */
static int
record_update_primitive(struct update_command_journal *j,
struct update_primitive prim)
{
struct update_primitive_list *l;
l = &j->cmd_prims[j->cur_cmd];
if (l->num_entries == l->num_alloc_entries) {
struct update_primitive *new_entries;
size_t new_num_alloc_entries;
size_t new_size;
new_num_alloc_entries = l->num_alloc_entries * 2;
new_size = new_num_alloc_entries * sizeof(new_entries[0]);
if (l->entries == l->inline_entries) {
new_entries = MALLOC(new_size);
if (!new_entries)
return WIMLIB_ERR_NOMEM;
memcpy(new_entries, l->inline_entries,
sizeof(l->inline_entries));
} else {
new_entries = REALLOC(l->entries, new_size);
if (!new_entries)
return WIMLIB_ERR_NOMEM;
}
l->entries = new_entries;
l->num_alloc_entries = new_num_alloc_entries;
}
l->entries[l->num_entries++] = prim;
return 0;
}
static void
do_unlink(struct wim_dentry *subject, struct wim_dentry *parent,
struct wim_dentry **root_p)
{
if (parent) {
/* Unlink @subject from its @parent. */
wimlib_assert(subject->d_parent == parent);
unlink_dentry(subject);
} else {
/* Unset @subject as the root of the image. */
*root_p = NULL;
}
subject->d_parent = subject;
}
static void
do_link(struct wim_dentry *subject, struct wim_dentry *parent,
struct wim_dentry **root_p)
{
if (parent) {
/* Link @subject to its @parent */
struct wim_dentry *existing;
existing = dentry_add_child(parent, subject);
wimlib_assert(!existing);
} else {
/* Set @subject as root of the image */
*root_p = subject;
}
}
/* Undo a link operation. */
static void
rollback_link(struct wim_dentry *subject, struct wim_dentry *parent,
struct wim_dentry **root_p, struct list_head *orphans)
{
/* Unlink is the opposite of link */
do_unlink(subject, parent, root_p);
/* @subject is now unlinked. Add it to orphans. */
list_add(&subject->d_tmp_list, orphans);
subject->d_is_orphan = 1;
}
/* Undo an unlink operation. */
static void
rollback_unlink(struct wim_dentry *subject, struct wim_dentry *parent,
struct wim_dentry **root_p)
{
/* Link is the opposite of unlink */
do_link(subject, parent, root_p);
/* @subject is no longer unlinked. Delete it from orphans. */
list_del(&subject->d_tmp_list);
subject->d_is_orphan = 0;
}
/* Rollback a name change operation. */
static void
rollback_name_change(utf16lechar *old_name,
utf16lechar **name_ptr, u16 *name_nbytes_ptr)
{
/* Free the new name, then replace it with the old name. */
FREE(*name_ptr);
if (old_name) {
*name_ptr = old_name;
*name_nbytes_ptr = utf16le_len_bytes(old_name);
} else {
*name_ptr = NULL;
*name_nbytes_ptr = 0;
}
}
/* Rollback a primitive update operation. */
static void
rollback_update_primitive(const struct update_primitive *prim,
struct wim_dentry **root_p,
struct list_head *orphans)
{
switch (prim->type) {
case LINK_DENTRY:
rollback_link(prim->link.subject, prim->link.parent, root_p,
orphans);
break;
case UNLINK_DENTRY:
rollback_unlink(prim->link.subject, prim->link.parent, root_p);
break;
case CHANGE_FILE_NAME:
rollback_name_change(prim->name.old_name,
&prim->name.subject->d_name,
&prim->name.subject->d_name_nbytes);
break;
case CHANGE_SHORT_NAME:
rollback_name_change(prim->name.old_name,
&prim->name.subject->d_short_name,
&prim->name.subject->d_short_name_nbytes);
break;
}
}
/* Rollback a logical update command */
static void
rollback_update_command(const struct update_primitive_list *l,
struct wim_dentry **root_p,
struct list_head *orphans)
{
size_t i = l->num_entries;
/* Rollback each primitive operation, in reverse order. */
while (i--)
rollback_update_primitive(&l->entries[i], root_p, orphans);
}
/****************************************************************************/
/* Link @subject into the directory @parent; or, if @parent is NULL, set
* @subject as the root of the WIM image.
*
* This is the journaled version, so it can be rolled back. */
static int
journaled_link(struct update_command_journal *j,
struct wim_dentry *subject, struct wim_dentry *parent)
{
struct update_primitive prim;
int ret;
prim.type = LINK_DENTRY;
prim.link.subject = subject;
prim.link.parent = parent;
ret = record_update_primitive(j, prim);
if (ret)
return ret;
do_link(subject, parent, j->root_p);
if (subject->d_is_orphan) {
list_del(&subject->d_tmp_list);
subject->d_is_orphan = 0;
}
return 0;
}
/* Unlink @subject from the WIM image.
*
* This is the journaled version, so it can be rolled back. */
static int
journaled_unlink(struct update_command_journal *j, struct wim_dentry *subject)
{
struct wim_dentry *parent;
struct update_primitive prim;
int ret;
if (dentry_is_root(subject))
parent = NULL;
else
parent = subject->d_parent;
prim.type = UNLINK_DENTRY;
prim.link.subject = subject;
prim.link.parent = parent;
ret = record_update_primitive(j, prim);
if (ret)
return ret;
do_unlink(subject, parent, j->root_p);
list_add(&subject->d_tmp_list, &j->orphans);
subject->d_is_orphan = 1;
return 0;
}
/* Change the name of @dentry to @new_name_tstr.
*
* This is the journaled version, so it can be rolled back. */
static int
journaled_change_name(struct update_command_journal *j,
struct wim_dentry *dentry, const tchar *new_name_tstr)
{
int ret;
utf16lechar *new_name;
size_t new_name_nbytes;
struct update_primitive prim;
/* Set the long name. */
ret = tstr_to_utf16le(new_name_tstr,
tstrlen(new_name_tstr) * sizeof(tchar),
&new_name, &new_name_nbytes);
if (ret)
return ret;
prim.type = CHANGE_FILE_NAME;
prim.name.subject = dentry;
prim.name.old_name = dentry->d_name;
ret = record_update_primitive(j, prim);
if (ret) {
FREE(new_name);
return ret;
}
dentry->d_name = new_name;
dentry->d_name_nbytes = new_name_nbytes;
/* Clear the short name. */
prim.type = CHANGE_SHORT_NAME;
prim.name.subject = dentry;
prim.name.old_name = dentry->d_short_name;
ret = record_update_primitive(j, prim);
if (ret)
return ret;
dentry->d_short_name = NULL;
dentry->d_short_name_nbytes = 0;
return 0;
}
static void
next_command(struct update_command_journal *j)
{
j->cur_cmd++;
}
static void
commit_update(struct update_command_journal *j)
{
for (size_t i = 0; i < j->num_cmds; i++)
{
for (size_t k = 0; k < j->cmd_prims[i].num_entries; k++)
{
if (j->cmd_prims[i].entries[k].type == CHANGE_FILE_NAME ||
j->cmd_prims[i].entries[k].type == CHANGE_SHORT_NAME)
{
FREE(j->cmd_prims[i].entries[k].name.old_name);
}
}
}
free_update_command_journal(j);
}
static void
rollback_update(struct update_command_journal *j)
{
/* Rollback each logical update command, in reverse order. */
size_t i = j->cur_cmd;
if (i < j->num_cmds)
i++;
while (i--)
rollback_update_command(&j->cmd_prims[i], j->root_p, &j->orphans);
free_update_command_journal(j);
}
static int
handle_conflict(struct wim_dentry *branch, struct wim_dentry *existing,
struct update_command_journal *j,
int add_flags,
wimlib_progress_func_t progfunc, void *progctx)
{
bool branch_is_dir = dentry_is_directory(branch);
bool existing_is_dir = dentry_is_directory(existing);
if (branch_is_dir != existing_is_dir) {
if (existing_is_dir) {
ERROR("\"%"TS"\" is a directory!\n"
" Specify the path at which "
"to place the file inside this directory.",
dentry_full_path(existing));
return WIMLIB_ERR_IS_DIRECTORY;
} else {
ERROR("Can't place directory at \"%"TS"\" because "
"a nondirectory file already exists there!",
dentry_full_path(existing));
return WIMLIB_ERR_NOTDIR;
}
}
if (branch_is_dir) {
/* Directory overlay */
while (dentry_has_children(branch)) {
struct wim_dentry *new_child;
struct wim_dentry *existing_child;
int ret;
new_child = dentry_any_child(branch);
existing_child =
get_dentry_child_with_utf16le_name(existing,
new_child->d_name,
new_child->d_name_nbytes,
WIMLIB_CASE_PLATFORM_DEFAULT);
unlink_dentry(new_child);
if (existing_child) {
ret = handle_conflict(new_child, existing_child,
j, add_flags,
progfunc, progctx);
} else {
ret = journaled_link(j, new_child, existing);
}
if (ret) {
dentry_add_child(branch, new_child);
return ret;
}
}
free_dentry_tree(branch, j->blob_table);
return 0;
} else if (add_flags & WIMLIB_ADD_FLAG_NO_REPLACE) {
/* Can't replace nondirectory file */
ERROR("Refusing to overwrite nondirectory file \"%"TS"\"",
dentry_full_path(existing));
return WIMLIB_ERR_INVALID_OVERLAY;
} else {
/* Replace nondirectory file */
struct wim_dentry *parent;
int ret;
parent = existing->d_parent;
ret = calculate_dentry_full_path(existing);
if (ret)
return ret;
if (add_flags & WIMLIB_ADD_FLAG_VERBOSE) {
union wimlib_progress_info info;
info.replace.path_in_wim = existing->d_full_path;
ret = call_progress(progfunc,
WIMLIB_PROGRESS_MSG_REPLACE_FILE_IN_WIM,
&info, progctx);
if (ret)
return ret;
}
ret = journaled_unlink(j, existing);
if (ret)
return ret;
return journaled_link(j, branch, parent);
}
}
static int
do_attach_branch(struct wim_dentry *branch, const utf16lechar *target,
struct update_command_journal *j,
int add_flags, wimlib_progress_func_t progfunc, void *progctx)
{
struct wim_dentry *parent;
struct wim_dentry *existing;
const utf16lechar empty_name[1] = {0};
const utf16lechar *cur_component_name;
size_t cur_component_nbytes;
const utf16lechar *next_component_name;
int ret;
/* Attempt to create root directory before proceeding to the "real"
* first component */
parent = NULL;
existing = *j->root_p;
cur_component_name = empty_name;
cur_component_nbytes = 0;
/* Skip leading slashes */
next_component_name = target;
while (*next_component_name == cpu_to_le16(WIM_PATH_SEPARATOR))
next_component_name++;
while (*next_component_name) { /* While not the last component ... */
const utf16lechar *end;
if (existing) {
/* Descend into existing directory */
if (!dentry_is_directory(existing)) {
ERROR("\"%"TS"\" in the WIM image "
"is not a directory!",
dentry_full_path(existing));
return WIMLIB_ERR_NOTDIR;
}
} else {
/* A parent directory of the target didn't exist. Make
* the way by creating a filler directory. */
struct wim_dentry *filler;
ret = new_filler_directory(&filler);
if (ret)
return ret;
ret = dentry_set_name_utf16le(filler,
cur_component_name,
cur_component_nbytes);
if (ret) {
free_dentry(filler);
return ret;
}
ret = journaled_link(j, filler, parent);
if (ret) {
free_dentry(filler);
return ret;
}
existing = filler;
}
/* Advance to next component */
cur_component_name = next_component_name;
end = cur_component_name + 1;
while (*end && *end != cpu_to_le16(WIM_PATH_SEPARATOR))
end++;
next_component_name = end;
if (*end) {
/* There will still be more components after this. */
do {
} while (*++next_component_name == cpu_to_le16(WIM_PATH_SEPARATOR));
wimlib_assert(*next_component_name); /* No trailing slashes */
} else {
/* This will be the last component */
next_component_name = end;
}
parent = existing;
cur_component_nbytes = (end - cur_component_name) * sizeof(utf16lechar);
existing = get_dentry_child_with_utf16le_name(
parent,
cur_component_name,
cur_component_nbytes,
WIMLIB_CASE_PLATFORM_DEFAULT);
}
/* Last component */
if (existing) {
return handle_conflict(branch, existing, j, add_flags,
progfunc, progctx);
} else {
return journaled_link(j, branch, parent);
}
}
/*
* Place the directory entry tree @branch at the path @target_tstr in the WIM
* image.
*
* @target_tstr cannot contain trailing slashes, and all path separators must be
* WIM_PATH_SEPARATOR.
*
* On success, @branch is committed to the journal @j.
* Otherwise @branch is freed.
*
* The relevant @add_flags are WIMLIB_ADD_FLAG_NO_REPLACE and
* WIMLIB_ADD_FLAG_VERBOSE.
*/
static int
attach_branch(struct wim_dentry *branch, const tchar *target_tstr,
struct update_command_journal *j, int add_flags,
wimlib_progress_func_t progfunc, void *progctx)
{
int ret;
const utf16lechar *target;
ret = 0;
if (unlikely(!branch))
goto out;
ret = tstr_get_utf16le(target_tstr, &target);
if (ret)
goto out_free_branch;
STATIC_ASSERT(WIM_PATH_SEPARATOR == OS_PREFERRED_PATH_SEPARATOR);
ret = dentry_set_name(branch, path_basename(target_tstr));
if (ret)
goto out_free_target;
ret = do_attach_branch(branch, target, j, add_flags, progfunc, progctx);
if (ret)
goto out_free_target;
/* branch was successfully committed to the journal */
branch = NULL;
out_free_target:
tstr_put_utf16le(target);
out_free_branch:
free_dentry_tree(branch, j->blob_table);
out:
return ret;
}
static const char wincfg[] =
"[ExclusionList]\n"
"/$ntfs.log\n"
"/hiberfil.sys\n"
"/pagefile.sys\n"
"/swapfile.sys\n"
"/System Volume Information\n"
"/RECYCLER\n"
"/$RECYCLE.BIN\n"
"/$Recycle.Bin\n"
"/Windows/CSC\n";
static const tchar *wimboot_cfgfile =
WIMLIB_WIM_PATH_SEPARATOR_STRING T("Windows")
WIMLIB_WIM_PATH_SEPARATOR_STRING T("System32")
WIMLIB_WIM_PATH_SEPARATOR_STRING T("WimBootCompress.ini");
static int
get_capture_config(const tchar *config_file, struct capture_config *config,
int add_flags, const tchar *fs_source_path)
{
int ret;
tchar *tmp_config_file = NULL;
memset(config, 0, sizeof(*config));
/* For WIMBoot capture, check for default capture configuration file
* unless one was explicitly specified. */
if (!config_file && (add_flags & WIMLIB_ADD_FLAG_WIMBOOT)) {
/* XXX: Handle loading file correctly when in NTFS volume. */
size_t len = tstrlen(fs_source_path) +
tstrlen(wimboot_cfgfile);
struct stat st;
tmp_config_file = MALLOC((len + 1) * sizeof(tchar));
if (!tmp_config_file)
return WIMLIB_ERR_NOMEM;
tsprintf(tmp_config_file, T("%"TS"%"TS),
fs_source_path, wimboot_cfgfile);
if (!tstat(tmp_config_file, &st)) {
config_file = tmp_config_file;
add_flags &= ~WIMLIB_ADD_FLAG_WINCONFIG;
} else {
WARNING("\"%"TS"\" does not exist.\n"
" Using default capture configuration!",
tmp_config_file);
}
}
if (add_flags & WIMLIB_ADD_FLAG_WINCONFIG) {
/* Use Windows default. */
if (config_file)
return WIMLIB_ERR_INVALID_PARAM;
ret = read_capture_config(T("wincfg"), wincfg,
sizeof(wincfg) - 1, config);
} else if (config_file) {
/* Use the specified configuration file. */
ret = read_capture_config(config_file, NULL, 0, config);
} else {
/* ... Or don't use any configuration file at all. No files
* will be excluded from capture, all files will be compressed,
* etc. */
ret = 0;
}
FREE(tmp_config_file);
return ret;
}
static int
execute_add_command(struct update_command_journal *j,
WIMStruct *wim,
const struct wimlib_update_command *add_cmd,
struct wim_inode_table *inode_table,
struct wim_sd_set *sd_set,
struct list_head *unhashed_blobs)
{
int ret;
int add_flags;
tchar *fs_source_path;
tchar *wim_target_path;
const tchar *config_file;
struct scan_params params;
struct capture_config config;
scan_tree_t scan_tree = platform_default_scan_tree;
struct wim_dentry *branch;
add_flags = add_cmd->add.add_flags;
fs_source_path = add_cmd->add.fs_source_path;
wim_target_path = add_cmd->add.wim_target_path;
config_file = add_cmd->add.config_file;
memset(¶ms, 0, sizeof(params));
#ifdef WITH_NTFS_3G
if (add_flags & WIMLIB_ADD_FLAG_NTFS)
scan_tree = ntfs_3g_build_dentry_tree;
#endif
#ifdef ENABLE_TEST_SUPPORT
if (add_flags & WIMLIB_ADD_FLAG_GENERATE_TEST_DATA)
scan_tree = generate_dentry_tree;
#endif
ret = get_capture_config(config_file, &config,
add_flags, fs_source_path);
if (ret)
goto out;
params.blob_table = wim->blob_table;
params.unhashed_blobs = unhashed_blobs;
params.inode_table = inode_table;
params.sd_set = sd_set;
params.config = &config;
params.add_flags = add_flags;
params.progfunc = wim->progfunc;
params.progctx = wim->progctx;
params.progress.scan.source = fs_source_path;
params.progress.scan.wim_target_path = wim_target_path;
ret = call_progress(params.progfunc, WIMLIB_PROGRESS_MSG_SCAN_BEGIN,
¶ms.progress, params.progctx);
if (ret)
goto out_destroy_config;
if (WIMLIB_IS_WIM_ROOT_PATH(wim_target_path))
params.add_flags |= WIMLIB_ADD_FLAG_ROOT;
ret = (*scan_tree)(&branch, fs_source_path, ¶ms);
if (ret)
goto out_destroy_config;
ret = call_progress(params.progfunc, WIMLIB_PROGRESS_MSG_SCAN_END,
¶ms.progress, params.progctx);
if (ret) {
free_dentry_tree(branch, wim->blob_table);
goto out_destroy_config;
}
if (WIMLIB_IS_WIM_ROOT_PATH(wim_target_path) &&
branch && !dentry_is_directory(branch))
{
ERROR("\"%"TS"\" is not a directory!", fs_source_path);
ret = WIMLIB_ERR_NOTDIR;
free_dentry_tree(branch, wim->blob_table);
goto out_destroy_config;
}
ret = attach_branch(branch, wim_target_path, j,
add_flags, params.progfunc, params.progctx);
if (ret)
goto out_destroy_config;
if (config_file && (add_flags & WIMLIB_ADD_FLAG_WIMBOOT) &&
WIMLIB_IS_WIM_ROOT_PATH(wim_target_path))
{
params.add_flags = 0;
params.progfunc = NULL;
params.config = NULL;
/* If a capture configuration file was explicitly specified when
* capturing an image in WIMBoot mode, save it as
* /Windows/System32/WimBootCompress.ini in the WIM image. */
ret = platform_default_scan_tree(&branch, config_file, ¶ms);
if (ret)
goto out_destroy_config;
ret = attach_branch(branch, wimboot_cfgfile, j, 0, NULL, NULL);
if (ret)
goto out_destroy_config;
}
if (WIMLIB_IS_WIM_ROOT_PATH(wim_target_path)) {
ret = set_windows_specific_info(wim);
if (ret)
goto out_destroy_config;
}
ret = 0;
out_destroy_config:
destroy_capture_config(&config);
out:
FREE(params.cur_path);
return ret;
}
static int
execute_delete_command(struct update_command_journal *j,
WIMStruct *wim,
const struct wimlib_update_command *delete_cmd)
{
int flags;
const tchar *wim_path;
struct wim_dentry *tree;
flags = delete_cmd->delete_.delete_flags;
wim_path = delete_cmd->delete_.wim_path;
tree = get_dentry(wim, wim_path, WIMLIB_CASE_PLATFORM_DEFAULT);
if (!tree) {
/* Path to delete does not exist in the WIM. */
if (flags & WIMLIB_DELETE_FLAG_FORCE) {
return 0;
} else {
ERROR("Path \"%"TS"\" does not exist in WIM image %d",
wim_path, wim->current_image);
return WIMLIB_ERR_PATH_DOES_NOT_EXIST;
}
}
if (dentry_is_directory(tree) && !(flags & WIMLIB_DELETE_FLAG_RECURSIVE)) {
ERROR("Path \"%"TS"\" in WIM image %d is a directory "
"but a recursive delete was not requested",
wim_path, wim->current_image);
return WIMLIB_ERR_IS_DIRECTORY;
}
return journaled_unlink(j, tree);
}
static int
free_dentry_full_path(struct wim_dentry *dentry, void *_ignore)
{
FREE(dentry->d_full_path);
dentry->d_full_path = NULL;
return 0;
}
/* Is @d1 a (possibly nonproper) ancestor of @d2? */
static bool
is_ancestor(const struct wim_dentry *d1, const struct wim_dentry *d2)
{
for (;;) {
if (d2 == d1)
return true;
if (dentry_is_root(d2))
return false;
d2 = d2->d_parent;
}
}
/* Rename a file or directory in the WIM.
*
* This returns a -errno value.
*
* The journal @j is optional.
*/
int
rename_wim_path(WIMStruct *wim, const tchar *from, const tchar *to,
CASE_SENSITIVITY_TYPE case_type, bool noreplace,
struct update_command_journal *j)
{
struct wim_dentry *src;
struct wim_dentry *dst;
struct wim_dentry *parent_of_dst;
int ret;
/* This rename() implementation currently only supports actual files
* (not alternate data streams) */
src = get_dentry(wim, from, case_type);
if (!src)
return -errno;
dst = get_dentry(wim, to, case_type);
if (dst) {
/* Destination file exists */
if (noreplace)
return -EEXIST;
if (src == dst) /* Same file */
return 0;
if (!dentry_is_directory(src)) {
/* Cannot rename non-directory to directory. */
if (dentry_is_directory(dst))
return -EISDIR;
} else {
/* Cannot rename directory to a non-directory or a non-empty
* directory */
if (!dentry_is_directory(dst))
return -ENOTDIR;
if (dentry_has_children(dst))
return -ENOTEMPTY;
}
parent_of_dst = dst->d_parent;
} else {
/* Destination does not exist */
parent_of_dst = get_parent_dentry(wim, to, case_type);
if (!parent_of_dst)
return -errno;
if (!dentry_is_directory(parent_of_dst))
return -ENOTDIR;
}
/* @src can't be an ancestor of @dst. Otherwise we're unlinking @src
* from the tree and creating a loop... */
if (is_ancestor(src, parent_of_dst))
return -EBUSY;
if (j) {
if (dst)
if (journaled_unlink(j, dst))
return -ENOMEM;
if (journaled_unlink(j, src))
return -ENOMEM;
if (journaled_change_name(j, src, path_basename(to)))
return -ENOMEM;
if (journaled_link(j, src, parent_of_dst))
return -ENOMEM;
} else {
ret = dentry_set_name(src, path_basename(to));
if (ret)
return -ENOMEM;
if (dst) {
unlink_dentry(dst);
free_dentry_tree(dst, wim->blob_table);
}
unlink_dentry(src);
dentry_add_child(parent_of_dst, src);
}
if (src->d_full_path)
for_dentry_in_tree(src, free_dentry_full_path, NULL);
return 0;
}
static int
execute_rename_command(struct update_command_journal *j,
WIMStruct *wim,
const struct wimlib_update_command *rename_cmd)
{
int ret;
ret = rename_wim_path(wim, rename_cmd->rename.wim_source_path,
rename_cmd->rename.wim_target_path,
WIMLIB_CASE_PLATFORM_DEFAULT, false, j);
if (ret) {
ret = -ret;
errno = ret;
ERROR_WITH_ERRNO("Can't rename \"%"TS"\" to \"%"TS"\"",
rename_cmd->rename.wim_source_path,
rename_cmd->rename.wim_target_path);
switch (ret) {
case ENOMEM:
ret = WIMLIB_ERR_NOMEM;
break;
case ENOTDIR:
ret = WIMLIB_ERR_NOTDIR;
break;
case ENOTEMPTY:
case EBUSY:
/* XXX: EBUSY is returned when the rename would create a
* loop. It maybe should have its own error code. */
ret = WIMLIB_ERR_NOTEMPTY;
break;
case EISDIR:
ret = WIMLIB_ERR_IS_DIRECTORY;
break;
case ENOENT:
default:
ret = WIMLIB_ERR_PATH_DOES_NOT_EXIST;
break;
}
}
return ret;
}
static bool
have_command_type(const struct wimlib_update_command *cmds, size_t num_cmds,
enum wimlib_update_op op)
{
for (size_t i = 0; i < num_cmds; i++)
if (cmds[i].op == op)
return true;
return false;
}
static int
execute_update_commands(WIMStruct *wim,
const struct wimlib_update_command *cmds,
size_t num_cmds,
int update_flags)
{
struct wim_inode_table *inode_table;
struct wim_sd_set *sd_set;
struct list_head unhashed_blobs;
struct update_command_journal *j;
union wimlib_progress_info info;
int ret;
if (have_command_type(cmds, num_cmds, WIMLIB_UPDATE_OP_ADD)) {
/* If we have at least one "add" command, create the inode and
* security descriptor tables to index new inodes and new
* security descriptors, respectively. */
inode_table = alloca(sizeof(struct wim_inode_table));
sd_set = alloca(sizeof(struct wim_sd_set));
ret = init_inode_table(inode_table, 64);
if (ret)
goto out;
ret = init_sd_set(sd_set, wim_get_current_security_data(wim));
if (ret)
goto out_destroy_inode_table;
INIT_LIST_HEAD(&unhashed_blobs);
} else {
inode_table = NULL;
sd_set = NULL;
}
/* Start an in-memory journal to allow rollback if something goes wrong
*/
j = new_update_command_journal(num_cmds,
&wim_get_current_image_metadata(wim)->root_dentry,
wim->blob_table);
if (!j) {
ret = WIMLIB_ERR_NOMEM;
goto out_destroy_sd_set;
}
info.update.completed_commands = 0;
info.update.total_commands = num_cmds;
ret = 0;
for (size_t i = 0; i < num_cmds; i++) {
info.update.command = &cmds[i];
if (update_flags & WIMLIB_UPDATE_FLAG_SEND_PROGRESS) {
ret = call_progress(wim->progfunc,
WIMLIB_PROGRESS_MSG_UPDATE_BEGIN_COMMAND,
&info, wim->progctx);
if (ret)
goto rollback;
}
switch (cmds[i].op) {
case WIMLIB_UPDATE_OP_ADD:
ret = execute_add_command(j, wim, &cmds[i], inode_table,
sd_set, &unhashed_blobs);
break;
case WIMLIB_UPDATE_OP_DELETE:
ret = execute_delete_command(j, wim, &cmds[i]);
break;
case WIMLIB_UPDATE_OP_RENAME:
ret = execute_rename_command(j, wim, &cmds[i]);
break;
}
if (unlikely(ret))
goto rollback;
info.update.completed_commands++;
if (update_flags & WIMLIB_UPDATE_FLAG_SEND_PROGRESS) {
ret = call_progress(wim->progfunc,
WIMLIB_PROGRESS_MSG_UPDATE_END_COMMAND,
&info, wim->progctx);
if (ret)
goto rollback;
}
next_command(j);
}
commit_update(j);
if (inode_table) {
struct wim_image_metadata *imd;
imd = wim_get_current_image_metadata(wim);
list_splice_tail(&unhashed_blobs, &imd->unhashed_blobs);
inode_table_prepare_inode_list(inode_table, &imd->inode_list);
}
goto out_destroy_sd_set;
rollback:
if (sd_set)
rollback_new_security_descriptors(sd_set);
rollback_update(j);
out_destroy_sd_set:
if (sd_set)
destroy_sd_set(sd_set);
out_destroy_inode_table:
if (inode_table)
destroy_inode_table(inode_table);
out:
return ret;
}
static int
check_add_command(struct wimlib_update_command *cmd,
const struct wim_header *hdr)
{
int add_flags = cmd->add.add_flags;
if (add_flags & ~(WIMLIB_ADD_FLAG_NTFS |
WIMLIB_ADD_FLAG_DEREFERENCE |
WIMLIB_ADD_FLAG_VERBOSE |
/* BOOT doesn't make sense for wimlib_update_image(). */
/*WIMLIB_ADD_FLAG_BOOT |*/
WIMLIB_ADD_FLAG_UNIX_DATA |
WIMLIB_ADD_FLAG_NO_ACLS |
WIMLIB_ADD_FLAG_STRICT_ACLS |
WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE |
WIMLIB_ADD_FLAG_RPFIX |
WIMLIB_ADD_FLAG_NORPFIX |
WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE |
WIMLIB_ADD_FLAG_WINCONFIG |
WIMLIB_ADD_FLAG_WIMBOOT |
WIMLIB_ADD_FLAG_NO_REPLACE |
WIMLIB_ADD_FLAG_TEST_FILE_EXCLUSION |
WIMLIB_ADD_FLAG_SNAPSHOT |
#ifdef ENABLE_TEST_SUPPORT
WIMLIB_ADD_FLAG_GENERATE_TEST_DATA |
#endif
WIMLIB_ADD_FLAG_FILE_PATHS_UNNEEDED))
return WIMLIB_ERR_INVALID_PARAM;
bool is_entire_image = WIMLIB_IS_WIM_ROOT_PATH(cmd->add.wim_target_path);
#ifndef WITH_NTFS_3G
if (add_flags & WIMLIB_ADD_FLAG_NTFS) {
ERROR("NTFS-3G capture mode is unsupported because wimlib "
"was compiled --without-ntfs-3g");
return WIMLIB_ERR_UNSUPPORTED;
}
#endif
#ifdef _WIN32
/* Check for flags not supported on Windows. */
if (add_flags & WIMLIB_ADD_FLAG_UNIX_DATA) {
ERROR("Capturing UNIX-specific data is not supported on Windows");
return WIMLIB_ERR_UNSUPPORTED;
}
if (add_flags & WIMLIB_ADD_FLAG_DEREFERENCE) {
ERROR("Dereferencing symbolic links is not supported on Windows");
return WIMLIB_ERR_UNSUPPORTED;
}
#else
/* Check for flags only supported on Windows. */
/* Currently, SNAPSHOT means Windows VSS. In the future, it perhaps
* could be implemented for other types of snapshots, such as btrfs. */
if (add_flags & WIMLIB_ADD_FLAG_SNAPSHOT) {
ERROR("Snapshot mode is only supported on Windows, where it uses VSS.");
return WIMLIB_ERR_UNSUPPORTED;
}
#endif
/* VERBOSE implies EXCLUDE_VERBOSE */
if (add_flags & WIMLIB_ADD_FLAG_VERBOSE)
add_flags |= WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE;
/* Check for contradictory reparse point fixup flags */
if ((add_flags & (WIMLIB_ADD_FLAG_RPFIX |
WIMLIB_ADD_FLAG_NORPFIX)) ==
(WIMLIB_ADD_FLAG_RPFIX |
WIMLIB_ADD_FLAG_NORPFIX))
{
ERROR("Cannot specify RPFIX and NORPFIX flags "
"at the same time!");
return WIMLIB_ERR_INVALID_PARAM;
}
/* Set default behavior on reparse point fixups if requested */
if ((add_flags & (WIMLIB_ADD_FLAG_RPFIX |
WIMLIB_ADD_FLAG_NORPFIX)) == 0)
{
/* Do reparse-point fixups by default if we are capturing an
* entire image and either the header flag is set from previous
* images, or if this is the first image being added. */
if (is_entire_image &&
((hdr->flags & WIM_HDR_FLAG_RP_FIX) || hdr->image_count == 1))
add_flags |= WIMLIB_ADD_FLAG_RPFIX;
}
if (!is_entire_image) {
if (add_flags & WIMLIB_ADD_FLAG_RPFIX) {
ERROR("Cannot do reparse point fixups when "
"not capturing a full image!");
return WIMLIB_ERR_INVALID_PARAM;
}
}
/* We may have modified the add flags. */
cmd->add.add_flags = add_flags;
return 0;
}
static int
check_delete_command(const struct wimlib_update_command *cmd)
{
if (cmd->delete_.delete_flags & ~(WIMLIB_DELETE_FLAG_FORCE |
WIMLIB_DELETE_FLAG_RECURSIVE))
return WIMLIB_ERR_INVALID_PARAM;
return 0;
}
static int
check_rename_command(const struct wimlib_update_command *cmd)
{
if (cmd->rename.rename_flags != 0)
return WIMLIB_ERR_INVALID_PARAM;
return 0;
}
static int
check_update_command(struct wimlib_update_command *cmd,
const struct wim_header *hdr)
{
switch (cmd->op) {
case WIMLIB_UPDATE_OP_ADD:
return check_add_command(cmd, hdr);
case WIMLIB_UPDATE_OP_DELETE:
return check_delete_command(cmd);
case WIMLIB_UPDATE_OP_RENAME:
return check_rename_command(cmd);
}
return 0;
}
static int
check_update_commands(struct wimlib_update_command *cmds, size_t num_cmds,
const struct wim_header *hdr)
{
int ret = 0;
for (size_t i = 0; i < num_cmds; i++) {
ret = check_update_command(&cmds[i], hdr);
if (ret)
break;
}
return ret;
}
static void
free_update_commands(struct wimlib_update_command *cmds, size_t num_cmds)
{
if (cmds) {
for (size_t i = 0; i < num_cmds; i++) {
switch (cmds[i].op) {
case WIMLIB_UPDATE_OP_ADD:
FREE(cmds[i].add.wim_target_path);
break;
case WIMLIB_UPDATE_OP_DELETE:
FREE(cmds[i].delete_.wim_path);
break;
case WIMLIB_UPDATE_OP_RENAME:
FREE(cmds[i].rename.wim_source_path);
FREE(cmds[i].rename.wim_target_path);
break;
}
}
FREE(cmds);
}
}
static int
copy_update_commands(const struct wimlib_update_command *cmds,
size_t num_cmds,
struct wimlib_update_command **cmds_copy_ret)
{
int ret;
struct wimlib_update_command *cmds_copy;
cmds_copy = CALLOC(num_cmds, sizeof(cmds[0]));
if (!cmds_copy)
goto oom;
for (size_t i = 0; i < num_cmds; i++) {
cmds_copy[i].op = cmds[i].op;
switch (cmds[i].op) {
case WIMLIB_UPDATE_OP_ADD:
cmds_copy[i].add.fs_source_path = cmds[i].add.fs_source_path;
cmds_copy[i].add.wim_target_path =
canonicalize_wim_path(cmds[i].add.wim_target_path);
if (!cmds_copy[i].add.wim_target_path)
goto oom;
cmds_copy[i].add.config_file = cmds[i].add.config_file;
cmds_copy[i].add.add_flags = cmds[i].add.add_flags;
break;
case WIMLIB_UPDATE_OP_DELETE:
cmds_copy[i].delete_.wim_path =
canonicalize_wim_path(cmds[i].delete_.wim_path);
if (!cmds_copy[i].delete_.wim_path)
goto oom;
cmds_copy[i].delete_.delete_flags = cmds[i].delete_.delete_flags;
break;
case WIMLIB_UPDATE_OP_RENAME:
cmds_copy[i].rename.wim_source_path =
canonicalize_wim_path(cmds[i].rename.wim_source_path);
cmds_copy[i].rename.wim_target_path =
canonicalize_wim_path(cmds[i].rename.wim_target_path);
if (!cmds_copy[i].rename.wim_source_path ||
!cmds_copy[i].rename.wim_target_path)
goto oom;
break;
default:
ERROR("Unknown update operation %u", cmds[i].op);
ret = WIMLIB_ERR_INVALID_PARAM;
goto err;
}
}
*cmds_copy_ret = cmds_copy;
ret = 0;
out:
return ret;
oom:
ret = WIMLIB_ERR_NOMEM;
err:
free_update_commands(cmds_copy, num_cmds);
goto out;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_update_image(WIMStruct *wim,
int image,
const struct wimlib_update_command *cmds,
size_t num_cmds,
int update_flags)
{
int ret;
struct wim_image_metadata *imd;
struct wimlib_update_command *cmds_copy;
if (update_flags & ~WIMLIB_UPDATE_FLAG_SEND_PROGRESS)
return WIMLIB_ERR_INVALID_PARAM;
/* Load the metadata for the image to modify (if not loaded already) */
ret = select_wim_image(wim, image);
if (ret)
return ret;
imd = wim->image_metadata[image - 1];
/* Don't allow updating an image currently being shared by multiple
* WIMStructs (as a result of an export) */
if (imd->refcnt > 1)
return WIMLIB_ERR_IMAGE_HAS_MULTIPLE_REFERENCES;
/* Make a copy of the update commands, in the process doing certain
* canonicalizations on paths (e.g. translating backslashes to forward
* slashes). This is done to avoid modifying the caller's copy of the
* commands. */
ret = copy_update_commands(cmds, num_cmds, &cmds_copy);
if (ret)
return ret;
/* Perform additional checks on the update commands before we execute
* them. */
ret = check_update_commands(cmds_copy, num_cmds, &wim->hdr);
if (ret)
goto out_free_cmds_copy;
/* Actually execute the update commands. */
ret = execute_update_commands(wim, cmds_copy, num_cmds, update_flags);
if (ret)
goto out_free_cmds_copy;
mark_image_dirty(imd);
for (size_t i = 0; i < num_cmds; i++)
if (cmds_copy[i].op == WIMLIB_UPDATE_OP_ADD &&
cmds_copy[i].add.add_flags & WIMLIB_ADD_FLAG_RPFIX)
wim->hdr.flags |= WIM_HDR_FLAG_RP_FIX;
out_free_cmds_copy:
free_update_commands(cmds_copy, num_cmds);
return ret;
}
WIMLIBAPI int
wimlib_delete_path(WIMStruct *wim, int image,
const tchar *path, int delete_flags)
{
struct wimlib_update_command cmd;
cmd.op = WIMLIB_UPDATE_OP_DELETE;
cmd.delete_.wim_path = (tchar *)path;
cmd.delete_.delete_flags = delete_flags;
return wimlib_update_image(wim, image, &cmd, 1, 0);
}
WIMLIBAPI int
wimlib_rename_path(WIMStruct *wim, int image,
const tchar *source_path, const tchar *dest_path)
{
struct wimlib_update_command cmd;
cmd.op = WIMLIB_UPDATE_OP_RENAME;
cmd.rename.wim_source_path = (tchar *)source_path;
cmd.rename.wim_target_path = (tchar *)dest_path;
cmd.rename.rename_flags = 0;
return wimlib_update_image(wim, image, &cmd, 1, 0);
}
WIMLIBAPI int
wimlib_add_tree(WIMStruct *wim, int image,
const tchar *fs_source_path, const tchar *wim_target_path,
int add_flags)
{
struct wimlib_update_command cmd;
cmd.op = WIMLIB_UPDATE_OP_ADD;
cmd.add.fs_source_path = (tchar *)fs_source_path;
cmd.add.wim_target_path = (tchar *)wim_target_path;
cmd.add.add_flags = add_flags;
cmd.add.config_file = NULL;
return wimlib_update_image(wim, image, &cmd, 1, 0);
}
wimlib-1.14.5/src/security.c 0000644 0001750 0001750 00000024437 15137020663 013176 0 ustar 00e e /*
* security.c
*
* Read and write the per-WIM-image table of security descriptors.
*/
/*
* Copyright 2012-2023 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/assert.h"
#include "wimlib/avl_tree.h"
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/security.h"
#include "wimlib/sha1.h"
#include "wimlib/util.h"
struct wim_security_data_disk {
le32 total_length;
le32 num_entries;
le64 sizes[];
} __attribute__((packed));
struct wim_security_data *
new_wim_security_data(void)
{
return CALLOC(1, sizeof(struct wim_security_data));
}
/*
* Reads the security data from the metadata resource of a WIM image.
*
* @buf
* Buffer containing an uncompressed WIM metadata resource.
* @buf_len
* Length of the uncompressed metadata resource, in bytes.
* @sd_ret
* On success, a pointer to the resulting security data structure will be
* returned here.
*
* Note: There is no `offset' argument because the security data is located at
* the beginning of the metadata resource.
*
* Return values:
* WIMLIB_ERR_SUCCESS (0)
* WIMLIB_ERR_INVALID_METADATA_RESOURCE
* WIMLIB_ERR_NOMEM
*/
int
read_wim_security_data(const u8 *buf, size_t buf_len,
struct wim_security_data **sd_ret)
{
struct wim_security_data *sd;
int ret;
u64 total_len;
u64 sizes_size;
u64 size_no_descriptors;
const struct wim_security_data_disk *sd_disk;
const u8 *p;
if (buf_len < 8)
return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
sd = new_wim_security_data();
if (!sd)
goto out_of_memory;
sd_disk = (const struct wim_security_data_disk *)buf;
sd->total_length = ALIGN(le32_to_cpu(sd_disk->total_length), 8);
sd->num_entries = le32_to_cpu(sd_disk->num_entries);
/* Length field of 0 is a special case that really means length
* of 8. */
if (sd->total_length == 0)
sd->total_length = 8;
/* The security_id field of each dentry is a signed 32-bit integer, so
* the possible indices into the security descriptors table are 0
* through 0x7fffffff. Which means 0x80000000 security descriptors
* maximum. Not like you should ever have anywhere close to that many
* security descriptors! */
if (sd->num_entries > 0x80000000)
goto out_invalid_sd;
/* Verify the listed total length of the security data is big enough to
* include the sizes array, verify that the file data is big enough to
* include it as well, then allocate the array of sizes.
*
* Note: The total length of the security data must fit in a 32-bit
* integer, even though each security descriptor size is a 64-bit
* integer. This is stupid, and we need to be careful not to actually
* let the security descriptor sizes be over 0xffffffff. */
if (sd->total_length > buf_len)
goto out_invalid_sd;
sizes_size = (u64)sd->num_entries * sizeof(u64);
size_no_descriptors = 8 + sizes_size;
if (size_no_descriptors > sd->total_length)
goto out_invalid_sd;
total_len = size_no_descriptors;
/* Return immediately if no security descriptors. */
if (sd->num_entries == 0)
goto out_descriptors_ready;
/* Allocate a new buffer for the sizes array */
sd->sizes = MALLOC(sizes_size);
if (!sd->sizes)
goto out_of_memory;
/* Copy the sizes array into the new buffer */
for (u32 i = 0; i < sd->num_entries; i++) {
sd->sizes[i] = le64_to_cpu(sd_disk->sizes[i]);
if (sd->sizes[i] > 0xffffffff)
goto out_invalid_sd;
}
p = (const u8*)sd_disk + size_no_descriptors;
/* Allocate the array of pointers to the security descriptors, then read
* them into separate buffers. */
sd->descriptors = CALLOC(sd->num_entries, sizeof(sd->descriptors[0]));
if (!sd->descriptors)
goto out_of_memory;
for (u32 i = 0; i < sd->num_entries; i++) {
if (sd->sizes[i] == 0)
continue;
total_len += sd->sizes[i];
if (total_len > (u64)sd->total_length)
goto out_invalid_sd;
sd->descriptors[i] = memdup(p, sd->sizes[i]);
if (!sd->descriptors[i])
goto out_of_memory;
p += sd->sizes[i];
}
out_descriptors_ready:
if (ALIGN(total_len, 8) != sd->total_length) {
WARNING("Stored WIM security data total length was "
"%"PRIu32" bytes, but calculated %"PRIu32" bytes",
sd->total_length, (u32)total_len);
}
*sd_ret = sd;
ret = 0;
goto out;
out_invalid_sd:
ERROR("WIM security data is invalid!");
ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE;
goto out_free_sd;
out_of_memory:
ERROR("Out of memory while reading WIM security data!");
ret = WIMLIB_ERR_NOMEM;
out_free_sd:
free_wim_security_data(sd);
out:
return ret;
}
/*
* Writes the security data for a WIM image to an in-memory buffer.
*/
u8 *
write_wim_security_data(const struct wim_security_data * restrict sd,
u8 * restrict p)
{
u8 *orig_p = p;
struct wim_security_data_disk *sd_disk = (struct wim_security_data_disk*)p;
u32 num_entries = sd->num_entries;
sd_disk->total_length = cpu_to_le32(sd->total_length);
sd_disk->num_entries = cpu_to_le32(num_entries);
for (u32 i = 0; i < num_entries; i++)
sd_disk->sizes[i] = cpu_to_le64(sd->sizes[i]);
p = (u8*)&sd_disk->sizes[num_entries];
for (u32 i = 0; i < num_entries; i++)
p = mempcpy(p, sd->descriptors[i], sd->sizes[i]);
while ((uintptr_t)p & 7)
*p++ = 0;
wimlib_assert(p - orig_p == sd->total_length);
return p;
}
void
free_wim_security_data(struct wim_security_data *sd)
{
if (sd) {
u8 **descriptors = sd->descriptors;
u32 num_entries = sd->num_entries;
if (descriptors)
while (num_entries--)
FREE(*descriptors++);
FREE(sd->sizes);
FREE(sd->descriptors);
FREE(sd);
}
}
struct sd_node {
s32 security_id;
u8 hash[SHA1_HASH_SIZE];
struct avl_tree_node index_node;
};
#define SD_NODE(avl_node) \
avl_tree_entry(avl_node, struct sd_node, index_node)
static void
free_sd_tree(struct avl_tree_node *node)
{
if (node) {
free_sd_tree(node->left);
free_sd_tree(node->right);
FREE(SD_NODE(node));
}
}
void
rollback_new_security_descriptors(struct wim_sd_set *sd_set)
{
struct wim_security_data *sd = sd_set->sd;
u32 i;
for (i = sd_set->orig_num_entries; i < sd->num_entries; i++)
FREE(sd->descriptors[i]);
sd->num_entries = sd_set->orig_num_entries;
}
/* Frees a security descriptor index set. */
void
destroy_sd_set(struct wim_sd_set *sd_set)
{
free_sd_tree(sd_set->root);
}
static int
_avl_cmp_nodes_by_hash(const struct avl_tree_node *n1,
const struct avl_tree_node *n2)
{
return hashes_cmp(SD_NODE(n1)->hash, SD_NODE(n2)->hash);
}
/* Inserts a new node into the security descriptor index tree. Returns true
* if successful (not a duplicate). */
static bool
insert_sd_node(struct wim_sd_set *set, struct sd_node *new)
{
return NULL == avl_tree_insert(&set->root, &new->index_node,
_avl_cmp_nodes_by_hash);
}
/* Returns the index of the security descriptor having a SHA1 message digest of
* @hash. If not found, return -1. */
static s32
lookup_sd(struct wim_sd_set *set, const u8 hash[SHA1_HASH_SIZE])
{
struct avl_tree_node *res;
struct sd_node dummy;
copy_hash(dummy.hash, hash);
res = avl_tree_lookup_node(set->root, &dummy.index_node,
_avl_cmp_nodes_by_hash);
if (!res)
return -1;
return SD_NODE(res)->security_id;
}
/*
* Adds a security descriptor to the indexed security descriptor set as well as
* the corresponding `struct wim_security_data', and returns the new security
* ID; or, if there is an existing security descriptor that is the same, return
* the security ID for it. If a new security descriptor cannot be allocated,
* return -1.
*/
s32
sd_set_add_sd(struct wim_sd_set *sd_set, const char *descriptor, size_t size)
{
u8 hash[SHA1_HASH_SIZE];
s32 security_id;
struct sd_node *new;
u8 **descriptors;
u64 *sizes;
u8 *descr_copy;
struct wim_security_data *sd;
bool bret;
sha1(descriptor, size, hash);
security_id = lookup_sd(sd_set, hash);
if (security_id >= 0) /* Identical descriptor already exists */
goto out;
/* Need to add a new security descriptor */
security_id = -1;
new = MALLOC(sizeof(*new));
if (!new)
goto out;
descr_copy = memdup(descriptor, size);
if (!descr_copy)
goto out_free_node;
sd = sd_set->sd;
new->security_id = sd->num_entries;
copy_hash(new->hash, hash);
/* There typically are only a few dozen security descriptors in a
* directory tree, so expanding the array of security descriptors by
* only 1 extra space each time should not be a problem. */
descriptors = REALLOC(sd->descriptors,
(sd->num_entries + 1) * sizeof(sd->descriptors[0]));
if (!descriptors)
goto out_free_descr;
sd->descriptors = descriptors;
sizes = REALLOC(sd->sizes,
(sd->num_entries + 1) * sizeof(sd->sizes[0]));
if (!sizes)
goto out_free_descr;
sd->sizes = sizes;
sd->descriptors[sd->num_entries] = descr_copy;
sd->sizes[sd->num_entries] = size;
sd->num_entries++;
bret = insert_sd_node(sd_set, new);
wimlib_assert(bret);
security_id = new->security_id;
goto out;
out_free_descr:
FREE(descr_copy);
out_free_node:
FREE(new);
out:
return security_id;
}
/* Initialize a `struct sd_set' mapping from SHA1 message digests of security
* descriptors to indices into the security descriptors table of the WIM image
* (security IDs). */
int
init_sd_set(struct wim_sd_set *sd_set, struct wim_security_data *sd)
{
int ret;
sd_set->sd = sd;
sd_set->root = NULL;
/* Remember the original number of security descriptors so that newly
* added ones can be rolled back if needed. */
sd_set->orig_num_entries = sd->num_entries;
for (u32 i = 0; i < sd->num_entries; i++) {
struct sd_node *new;
new = MALLOC(sizeof(struct sd_node));
if (!new) {
ret = WIMLIB_ERR_NOMEM;
goto out_destroy_sd_set;
}
sha1(sd->descriptors[i], sd->sizes[i], new->hash);
new->security_id = i;
if (!insert_sd_node(sd_set, new))
FREE(new); /* Ignore duplicate security descriptor */
}
ret = 0;
goto out;
out_destroy_sd_set:
destroy_sd_set(sd_set);
out:
return ret;
}
wimlib-1.14.5/src/verify.c 0000644 0001750 0001750 00000010505 15137020663 012622 0 ustar 00e e /*
* verify.c
*
* Verify WIM files.
*/
/*
* Copyright (C) 2012, 2013, 2014 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/blob_table.h"
#include "wimlib/dentry.h"
#include "wimlib/error.h"
#include "wimlib/metadata.h"
#include "wimlib/progress.h"
#include "wimlib/security.h"
static int
append_blob_to_list(struct blob_descriptor *blob, void *_list)
{
list_add(&blob->extraction_list, (struct list_head *)_list);
return 0;
}
struct verify_blob_list_ctx {
wimlib_progress_func_t progfunc;
void *progctx;
union wimlib_progress_info *progress;
u64 next_progress;
};
static int
verify_continue_blob(const struct blob_descriptor *blob, u64 offset,
const void *chunk, size_t size, void *_ctx)
{
struct verify_blob_list_ctx *ctx = _ctx;
union wimlib_progress_info *progress = ctx->progress;
if (offset + size == blob->size)
progress->verify_streams.completed_streams++;
progress->verify_streams.completed_bytes += size;
if (progress->verify_streams.completed_bytes >= ctx->next_progress) {
int ret = call_progress(ctx->progfunc,
WIMLIB_PROGRESS_MSG_VERIFY_STREAMS,
progress, ctx->progctx);
if (ret)
return ret;
set_next_progress(progress->verify_streams.completed_bytes,
progress->verify_streams.total_bytes,
&ctx->next_progress);
}
return 0;
}
static int
verify_file_data_present(struct wim_image_metadata *imd,
struct blob_table *blob_table)
{
struct wim_inode *inode;
int ret;
image_for_each_inode(inode, imd) {
ret = inode_resolve_streams(inode, blob_table, false);
if (ret)
return ret;
}
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_verify_wim(WIMStruct *wim, int verify_flags)
{
int ret;
LIST_HEAD(blob_list);
union wimlib_progress_info progress;
struct verify_blob_list_ctx ctx;
struct blob_descriptor *blob;
struct read_blob_callbacks cbs = {
.continue_blob = verify_continue_blob,
.ctx = &ctx,
};
/* Check parameters */
if (!wim)
return WIMLIB_ERR_INVALID_PARAM;
if (verify_flags)
return WIMLIB_ERR_INVALID_PARAM;
/* Verify the images */
if (wim_has_metadata(wim)) {
memset(&progress, 0, sizeof(progress));
progress.verify_image.wimfile = wim->filename;
progress.verify_image.total_images = wim->hdr.image_count;
for (int i = 1; i <= wim->hdr.image_count; i++) {
progress.verify_image.current_image = i;
ret = call_progress(wim->progfunc, WIMLIB_PROGRESS_MSG_BEGIN_VERIFY_IMAGE,
&progress, wim->progctx);
if (ret)
return ret;
ret = select_wim_image(wim, i);
if (ret)
return ret;
ret = verify_file_data_present(wim_get_current_image_metadata(wim),
wim->blob_table);
if (ret)
return ret;
ret = call_progress(wim->progfunc, WIMLIB_PROGRESS_MSG_END_VERIFY_IMAGE,
&progress, wim->progctx);
if (ret)
return ret;
}
} else {
WARNING("\"%"TS"\" does not contain image metadata. Skipping image verification.",
wim->filename);
}
/* Verify the blobs: SHA-1 message digests must match */
for_blob_in_table(wim->blob_table, append_blob_to_list, &blob_list);
memset(&progress, 0, sizeof(progress));
progress.verify_streams.wimfile = wim->filename;
list_for_each_entry(blob, &blob_list, extraction_list) {
progress.verify_streams.total_streams++;
progress.verify_streams.total_bytes += blob->size;
}
ctx.progfunc = wim->progfunc;
ctx.progctx = wim->progctx;
ctx.progress = &progress;
ctx.next_progress = 0;
ret = call_progress(ctx.progfunc, WIMLIB_PROGRESS_MSG_VERIFY_STREAMS,
ctx.progress, ctx.progctx);
if (ret)
return ret;
return read_blob_list(&blob_list,
offsetof(struct blob_descriptor, extraction_list),
&cbs, VERIFY_BLOB_HASHES);
}
wimlib-1.14.5/src/wim.c 0000644 0001750 0001750 00000066300 15137020663 012116 0 ustar 00e e /*
* wim.c - High-level code dealing with WIMStructs and images.
*/
/*
* Copyright 2012-2023 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#include
#include
#include "wimlib.h"
#include "wimlib/assert.h"
#include "wimlib/blob_table.h"
#include "wimlib/cpu_features.h"
#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/file_io.h"
#include "wimlib/integrity.h"
#include "wimlib/metadata.h"
#include "wimlib/security.h"
#include "wimlib/threads.h"
#include "wimlib/wim.h"
#include "wimlib/xml.h"
#include "wimlib/win32.h"
/* Information about the available compression types for the WIM format. */
static const struct {
const tchar *name;
u32 min_chunk_size;
u32 max_chunk_size;
u32 default_nonsolid_chunk_size;
u32 default_solid_chunk_size;
} wim_ctype_info[] = {
[WIMLIB_COMPRESSION_TYPE_NONE] = {
.name = T("None"),
.min_chunk_size = 0,
.max_chunk_size = 0,
.default_nonsolid_chunk_size = 0,
.default_solid_chunk_size = 0,
},
[WIMLIB_COMPRESSION_TYPE_XPRESS] = {
.name = T("XPRESS"),
.min_chunk_size = 4096,
.max_chunk_size = 65536,
.default_nonsolid_chunk_size = 32768,
.default_solid_chunk_size = 32768,
},
[WIMLIB_COMPRESSION_TYPE_LZX] = {
.name = T("LZX"),
.min_chunk_size = 32768,
.max_chunk_size = 2097152,
.default_nonsolid_chunk_size = 32768,
.default_solid_chunk_size = 32768,
},
[WIMLIB_COMPRESSION_TYPE_LZMS] = {
.name = T("LZMS"),
.min_chunk_size = 32768,
.max_chunk_size = 1073741824,
.default_nonsolid_chunk_size = 131072,
.default_solid_chunk_size = 67108864,
},
};
/* Is the specified compression type valid? */
static bool
wim_compression_type_valid(enum wimlib_compression_type ctype)
{
return (unsigned)ctype < ARRAY_LEN(wim_ctype_info) &&
wim_ctype_info[(unsigned)ctype].name != NULL;
}
/* Is the specified chunk size valid for the compression type? */
static bool
wim_chunk_size_valid(u32 chunk_size, enum wimlib_compression_type ctype)
{
if (!(chunk_size == 0 || is_power_of_2(chunk_size)))
return false;
return chunk_size >= wim_ctype_info[(unsigned)ctype].min_chunk_size &&
chunk_size <= wim_ctype_info[(unsigned)ctype].max_chunk_size;
}
/* Return the default chunk size to use for the specified compression type in
* non-solid resources. */
static u32
wim_default_nonsolid_chunk_size(enum wimlib_compression_type ctype)
{
return wim_ctype_info[(unsigned)ctype].default_nonsolid_chunk_size;
}
/* Return the default chunk size to use for the specified compression type in
* solid resources. */
static u32
wim_default_solid_chunk_size(enum wimlib_compression_type ctype)
{
return wim_ctype_info[(unsigned)ctype].default_solid_chunk_size;
}
/* Return the default compression type to use in solid resources. */
static enum wimlib_compression_type
wim_default_solid_compression_type(void)
{
return WIMLIB_COMPRESSION_TYPE_LZMS;
}
static int
is_blob_in_solid_resource(struct blob_descriptor *blob, void *_ignore)
{
return blob->blob_location == BLOB_IN_WIM &&
(blob->rdesc->flags & WIM_RESHDR_FLAG_SOLID);
}
bool
wim_has_solid_resources(const WIMStruct *wim)
{
return for_blob_in_table(wim->blob_table, is_blob_in_solid_resource, NULL);
}
static WIMStruct *
new_wim_struct(void)
{
WIMStruct *wim = CALLOC(1, sizeof(WIMStruct));
if (!wim)
return NULL;
wim->refcnt = 1;
filedes_invalidate(&wim->in_fd);
filedes_invalidate(&wim->out_fd);
wim->out_solid_compression_type = wim_default_solid_compression_type();
wim->out_solid_chunk_size = wim_default_solid_chunk_size(
wim->out_solid_compression_type);
return wim;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_create_new_wim(enum wimlib_compression_type ctype, WIMStruct **wim_ret)
{
int ret;
WIMStruct *wim;
ret = wimlib_global_init(0);
if (ret)
return ret;
if (!wim_ret)
return WIMLIB_ERR_INVALID_PARAM;
if (!wim_compression_type_valid(ctype))
return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
wim = new_wim_struct();
if (!wim)
return WIMLIB_ERR_NOMEM;
/* Fill in wim->hdr with default values */
wim->hdr.magic = WIM_MAGIC;
wim->hdr.wim_version = WIM_VERSION_DEFAULT;
wim->hdr.part_number = 1;
wim->hdr.total_parts = 1;
wim->compression_type = WIMLIB_COMPRESSION_TYPE_NONE;
/* Set the output compression type */
wim->out_compression_type = ctype;
wim->out_chunk_size = wim_default_nonsolid_chunk_size(ctype);
/* Allocate an empty XML info and blob table */
wim->xml_info = xml_new_info_struct();
wim->blob_table = new_blob_table(64);
if (!wim->xml_info || !wim->blob_table) {
wimlib_free(wim);
return WIMLIB_ERR_NOMEM;
}
*wim_ret = wim;
return 0;
}
static void
unload_image_metadata(struct wim_image_metadata *imd)
{
free_dentry_tree(imd->root_dentry, NULL);
imd->root_dentry = NULL;
free_wim_security_data(imd->security_data);
imd->security_data = NULL;
INIT_HLIST_HEAD(&imd->inode_list);
}
/* Release a reference to the specified image metadata. This assumes that no
* WIMStruct has the image selected. */
void
put_image_metadata(struct wim_image_metadata *imd)
{
struct blob_descriptor *blob, *tmp;
if (!imd)
return;
wimlib_assert(imd->refcnt > 0);
if (--imd->refcnt != 0)
return;
wimlib_assert(imd->selected_refcnt == 0);
unload_image_metadata(imd);
list_for_each_entry_safe(blob, tmp, &imd->unhashed_blobs, unhashed_list)
free_blob_descriptor(blob);
free_blob_descriptor(imd->metadata_blob);
FREE(imd);
}
/* Appends the specified image metadata structure to the array of image metadata
* for a WIM, and increments the image count. */
int
append_image_metadata(WIMStruct *wim, struct wim_image_metadata *imd)
{
struct wim_image_metadata **imd_array;
if (!wim_has_metadata(wim))
return WIMLIB_ERR_METADATA_NOT_FOUND;
if (wim->hdr.image_count >= MAX_IMAGES)
return WIMLIB_ERR_IMAGE_COUNT;
imd_array = REALLOC(wim->image_metadata,
sizeof(wim->image_metadata[0]) * (wim->hdr.image_count + 1));
if (!imd_array)
return WIMLIB_ERR_NOMEM;
wim->image_metadata = imd_array;
imd_array[wim->hdr.image_count++] = imd;
return 0;
}
static struct wim_image_metadata *
new_image_metadata(struct blob_descriptor *metadata_blob,
struct wim_security_data *security_data)
{
struct wim_image_metadata *imd;
imd = CALLOC(1, sizeof(*imd));
if (!imd)
return NULL;
metadata_blob->is_metadata = 1;
imd->refcnt = 1;
imd->selected_refcnt = 0;
imd->root_dentry = NULL;
imd->security_data = security_data;
imd->metadata_blob = metadata_blob;
INIT_HLIST_HEAD(&imd->inode_list);
INIT_LIST_HEAD(&imd->unhashed_blobs);
imd->stats_outdated = false;
return imd;
}
/* Create an image metadata structure for a new empty image. */
struct wim_image_metadata *
new_empty_image_metadata(void)
{
struct blob_descriptor *metadata_blob;
struct wim_security_data *security_data;
struct wim_image_metadata *imd;
metadata_blob = new_blob_descriptor();
security_data = new_wim_security_data();
if (metadata_blob && security_data) {
metadata_blob->refcnt = 1;
imd = new_image_metadata(metadata_blob, security_data);
if (imd)
return imd;
}
free_blob_descriptor(metadata_blob);
FREE(security_data);
return NULL;
}
/* Create an image metadata structure that refers to the specified metadata
* resource and is initially not loaded. */
struct wim_image_metadata *
new_unloaded_image_metadata(struct blob_descriptor *metadata_blob)
{
wimlib_assert(metadata_blob->blob_location == BLOB_IN_WIM);
return new_image_metadata(metadata_blob, NULL);
}
/*
* Load the metadata for the specified WIM image into memory and set it
* as the WIMStruct's currently selected image.
*
* @wim
* The WIMStruct for the WIM.
* @image
* The 1-based index of the image in the WIM to select.
*
* On success, 0 will be returned, wim->current_image will be set to
* @image, and wim_get_current_image_metadata() can be used to retrieve
* metadata information for the image.
*
* On failure, WIMLIB_ERR_INVALID_IMAGE, WIMLIB_ERR_METADATA_NOT_FOUND,
* or another error code will be returned.
*/
int
select_wim_image(WIMStruct *wim, int image)
{
struct wim_image_metadata *imd;
int ret;
if (image == WIMLIB_NO_IMAGE)
return WIMLIB_ERR_INVALID_IMAGE;
if (image == wim->current_image)
return 0;
if (image < 1 || image > wim->hdr.image_count)
return WIMLIB_ERR_INVALID_IMAGE;
if (!wim_has_metadata(wim))
return WIMLIB_ERR_METADATA_NOT_FOUND;
deselect_current_wim_image(wim);
imd = wim->image_metadata[image - 1];
if (!is_image_loaded(imd)) {
ret = read_metadata_resource(imd);
if (ret)
return ret;
}
wim->current_image = image;
imd->selected_refcnt++;
return 0;
}
/*
* Deselect the WIMStruct's currently selected image, if any. To reduce memory
* usage, possibly unload the newly deselected image's metadata from memory.
*/
void
deselect_current_wim_image(WIMStruct *wim)
{
struct wim_image_metadata *imd;
if (wim->current_image == WIMLIB_NO_IMAGE)
return;
imd = wim_get_current_image_metadata(wim);
wimlib_assert(imd->selected_refcnt > 0);
imd->selected_refcnt--;
wim->current_image = WIMLIB_NO_IMAGE;
if (can_unload_image(imd)) {
wimlib_assert(list_empty(&imd->unhashed_blobs));
unload_image_metadata(imd);
}
}
/*
* Calls a function on images in the WIM. If @image is WIMLIB_ALL_IMAGES,
* @visitor is called on the WIM once for each image, with each image selected
* as the current image in turn. If @image is a certain image, @visitor is
* called on the WIM only once, with that image selected.
*/
int
for_image(WIMStruct *wim, int image, int (*visitor)(WIMStruct *))
{
int ret;
int start;
int end;
int i;
if (image == WIMLIB_ALL_IMAGES) {
start = 1;
end = wim->hdr.image_count;
} else if (image >= 1 && image <= wim->hdr.image_count) {
start = image;
end = image;
} else {
return WIMLIB_ERR_INVALID_IMAGE;
}
for (i = start; i <= end; i++) {
ret = select_wim_image(wim, i);
if (ret != 0)
return ret;
ret = visitor(wim);
if (ret != 0)
return ret;
}
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_resolve_image(WIMStruct *wim, const tchar *image_name_or_num)
{
tchar *p;
long image;
int i;
if (!image_name_or_num || !*image_name_or_num)
return WIMLIB_NO_IMAGE;
if (!tstrcasecmp(image_name_or_num, T("all"))
|| !tstrcasecmp(image_name_or_num, T("*")))
return WIMLIB_ALL_IMAGES;
image = tstrtol(image_name_or_num, &p, 10);
if (p != image_name_or_num && *p == T('\0') && image > 0) {
if (image > wim->hdr.image_count)
return WIMLIB_NO_IMAGE;
return image;
} else {
for (i = 1; i <= wim->hdr.image_count; i++) {
if (!tstrcmp(image_name_or_num,
wimlib_get_image_name(wim, i)))
return i;
}
return WIMLIB_NO_IMAGE;
}
}
/* API function documented in wimlib.h */
WIMLIBAPI void
wimlib_print_available_images(const WIMStruct *wim, int image)
{
int first;
int last;
int i;
int n;
if (image == WIMLIB_ALL_IMAGES) {
n = tprintf(T("Available Images:\n"));
first = 1;
last = wim->hdr.image_count;
} else if (image >= 1 && image <= wim->hdr.image_count) {
n = tprintf(T("Information for Image %d\n"), image);
first = image;
last = image;
} else {
tprintf(T("wimlib_print_available_images(): Invalid image %d"),
image);
return;
}
for (i = 0; i < n - 1; i++)
tputchar(T('-'));
tputchar(T('\n'));
for (i = first; i <= last; i++)
xml_print_image_info(wim->xml_info, i);
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_get_wim_info(WIMStruct *wim, struct wimlib_wim_info *info)
{
memset(info, 0, sizeof(struct wimlib_wim_info));
copy_guid(info->guid, wim->hdr.guid);
info->image_count = wim->hdr.image_count;
info->boot_index = wim->hdr.boot_idx;
info->wim_version = wim->hdr.wim_version;
info->chunk_size = wim->chunk_size;
info->part_number = wim->hdr.part_number;
info->total_parts = wim->hdr.total_parts;
info->compression_type = wim->compression_type;
info->total_bytes = xml_get_total_bytes(wim->xml_info);
info->has_integrity_table = wim_has_integrity_table(wim);
info->opened_from_file = (wim->filename != NULL);
info->is_readonly = (wim->hdr.flags & WIM_HDR_FLAG_READONLY) ||
(wim->hdr.total_parts != 1) ||
(wim->filename && taccess(wim->filename, W_OK));
info->has_rpfix = (wim->hdr.flags & WIM_HDR_FLAG_RP_FIX) != 0;
info->is_marked_readonly = (wim->hdr.flags & WIM_HDR_FLAG_READONLY) != 0;
info->write_in_progress = (wim->hdr.flags & WIM_HDR_FLAG_WRITE_IN_PROGRESS) != 0;
info->metadata_only = (wim->hdr.flags & WIM_HDR_FLAG_METADATA_ONLY) != 0;
info->resource_only = (wim->hdr.flags & WIM_HDR_FLAG_RESOURCE_ONLY) != 0;
info->spanned = (wim->hdr.flags & WIM_HDR_FLAG_SPANNED) != 0;
info->pipable = wim_is_pipable(wim);
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_set_wim_info(WIMStruct *wim, const struct wimlib_wim_info *info, int which)
{
if (which & ~(WIMLIB_CHANGE_READONLY_FLAG |
WIMLIB_CHANGE_GUID |
WIMLIB_CHANGE_BOOT_INDEX |
WIMLIB_CHANGE_RPFIX_FLAG))
return WIMLIB_ERR_INVALID_PARAM;
if ((which & WIMLIB_CHANGE_BOOT_INDEX) &&
info->boot_index > wim->hdr.image_count)
return WIMLIB_ERR_INVALID_IMAGE;
if (which & WIMLIB_CHANGE_READONLY_FLAG) {
if (info->is_marked_readonly)
wim->hdr.flags |= WIM_HDR_FLAG_READONLY;
else
wim->hdr.flags &= ~WIM_HDR_FLAG_READONLY;
}
if (which & WIMLIB_CHANGE_GUID)
copy_guid(wim->hdr.guid, info->guid);
if (which & WIMLIB_CHANGE_BOOT_INDEX)
wim->hdr.boot_idx = info->boot_index;
if (which & WIMLIB_CHANGE_RPFIX_FLAG) {
if (info->has_rpfix)
wim->hdr.flags |= WIM_HDR_FLAG_RP_FIX;
else
wim->hdr.flags &= ~WIM_HDR_FLAG_RP_FIX;
}
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_set_output_compression_type(WIMStruct *wim,
enum wimlib_compression_type ctype)
{
if (!wim_compression_type_valid(ctype))
return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
wim->out_compression_type = ctype;
/* Reset the chunk size if it's no longer valid. */
if (!wim_chunk_size_valid(wim->out_chunk_size, ctype))
wim->out_chunk_size = wim_default_nonsolid_chunk_size(ctype);
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_set_output_pack_compression_type(WIMStruct *wim,
enum wimlib_compression_type ctype)
{
if (!wim_compression_type_valid(ctype))
return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
/* Solid resources can't be uncompressed. */
if (ctype == WIMLIB_COMPRESSION_TYPE_NONE)
return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
wim->out_solid_compression_type = ctype;
/* Reset the chunk size if it's no longer valid. */
if (!wim_chunk_size_valid(wim->out_solid_chunk_size, ctype))
wim->out_solid_chunk_size = wim_default_solid_chunk_size(ctype);
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_set_output_chunk_size(WIMStruct *wim, u32 chunk_size)
{
if (chunk_size == 0) {
wim->out_chunk_size =
wim_default_nonsolid_chunk_size(wim->out_compression_type);
return 0;
}
if (!wim_chunk_size_valid(chunk_size, wim->out_compression_type))
return WIMLIB_ERR_INVALID_CHUNK_SIZE;
wim->out_chunk_size = chunk_size;
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_set_output_pack_chunk_size(WIMStruct *wim, u32 chunk_size)
{
if (chunk_size == 0) {
wim->out_solid_chunk_size =
wim_default_solid_chunk_size(wim->out_solid_compression_type);
return 0;
}
if (!wim_chunk_size_valid(chunk_size, wim->out_solid_compression_type))
return WIMLIB_ERR_INVALID_CHUNK_SIZE;
wim->out_solid_chunk_size = chunk_size;
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI const tchar *
wimlib_get_compression_type_string(enum wimlib_compression_type ctype)
{
if (!wim_compression_type_valid(ctype))
return T("Invalid");
return wim_ctype_info[(unsigned)ctype].name;
}
WIMLIBAPI void
wimlib_register_progress_function(WIMStruct *wim,
wimlib_progress_func_t progfunc,
void *progctx)
{
wim->progfunc = progfunc;
wim->progctx = progctx;
}
static int
open_wim_file(const tchar *filename, struct filedes *fd_ret)
{
int raw_fd;
raw_fd = topen(filename, O_RDONLY | O_BINARY);
if (raw_fd < 0) {
ERROR_WITH_ERRNO("Can't open \"%"TS"\" read-only", filename);
return WIMLIB_ERR_OPEN;
}
filedes_init(fd_ret, raw_fd);
return 0;
}
/*
* Begins the reading of a WIM file; opens the file and reads its header and
* blob table, and optionally checks the integrity.
*/
static int
begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags)
{
int ret;
const tchar *wimfile;
if (open_flags & WIMLIB_OPEN_FLAG_FROM_PIPE) {
wimfile = NULL;
filedes_init(&wim->in_fd, *(const int*)wim_filename_or_fd);
wim->in_fd.is_pipe = 1;
} else {
struct stat stbuf;
wimfile = wim_filename_or_fd;
ret = open_wim_file(wimfile, &wim->in_fd);
if (ret)
return ret;
/* The file size is needed for enforcing some limits later. */
if (fstat(wim->in_fd.fd, &stbuf) == 0)
wim->file_size = stbuf.st_size;
/* The absolute path to the WIM is requested so that
* wimlib_overwrite() still works even if the process changes
* its working directory. This actually happens if a WIM is
* mounted read-write, since the FUSE thread changes directory
* to "/", and it needs to be able to find the WIM file again.
*
* This will break if the full path to the WIM changes in the
* intervening time...
*
* Warning: in Windows native builds, realpath() calls the
* replacement function in win32_replacements.c.
*/
wim->filename = realpath(wimfile, NULL);
if (!wim->filename) {
ERROR_WITH_ERRNO("Failed to get full path to file "
"\"%"TS"\"", wimfile);
if (errno == ENOMEM)
return WIMLIB_ERR_NOMEM;
else
return WIMLIB_ERR_NO_FILENAME;
}
}
ret = read_wim_header(wim, &wim->hdr);
if (ret)
return ret;
if (wim->hdr.flags & WIM_HDR_FLAG_WRITE_IN_PROGRESS) {
WARNING("The WIM_HDR_FLAG_WRITE_IN_PROGRESS flag is set in the header of\n"
" \"%"TS"\". It may be being changed by another process,\n"
" or a process may have crashed while writing the WIM.",
wimfile);
}
if (open_flags & WIMLIB_OPEN_FLAG_WRITE_ACCESS) {
ret = can_modify_wim(wim);
if (ret)
return ret;
}
if ((open_flags & WIMLIB_OPEN_FLAG_ERROR_IF_SPLIT) &&
(wim->hdr.total_parts != 1))
return WIMLIB_ERR_IS_SPLIT_WIM;
/* If the boot index is invalid, print a warning and set it to 0 */
if (wim->hdr.boot_idx > wim->hdr.image_count) {
WARNING("Ignoring invalid boot index.");
wim->hdr.boot_idx = 0;
}
/* Check and cache the compression type */
if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESSION) {
if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_LZX) {
wim->compression_type = WIMLIB_COMPRESSION_TYPE_LZX;
} else if (wim->hdr.flags & (WIM_HDR_FLAG_COMPRESS_XPRESS |
WIM_HDR_FLAG_COMPRESS_XPRESS_2)) {
wim->compression_type = WIMLIB_COMPRESSION_TYPE_XPRESS;
} else if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_LZMS) {
wim->compression_type = WIMLIB_COMPRESSION_TYPE_LZMS;
} else {
return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
}
} else {
wim->compression_type = WIMLIB_COMPRESSION_TYPE_NONE;
}
wim->out_compression_type = wim->compression_type;
/* Check and cache the chunk size. */
wim->chunk_size = wim->hdr.chunk_size;
wim->out_chunk_size = wim->chunk_size;
if (!wim_chunk_size_valid(wim->chunk_size, wim->compression_type)) {
ERROR("Invalid chunk size (%"PRIu32" bytes) "
"for compression type %"TS"!", wim->chunk_size,
wimlib_get_compression_type_string(wim->compression_type));
return WIMLIB_ERR_INVALID_CHUNK_SIZE;
}
if (open_flags & WIMLIB_OPEN_FLAG_CHECK_INTEGRITY) {
ret = check_wim_integrity(wim);
if (ret == WIM_INTEGRITY_NONEXISTENT) {
WARNING("\"%"TS"\" does not contain integrity "
"information. Skipping integrity check.",
wimfile);
} else if (ret == WIM_INTEGRITY_NOT_OK) {
return WIMLIB_ERR_INTEGRITY;
} else if (ret != WIM_INTEGRITY_OK) {
return ret;
}
}
if (wim->hdr.image_count != 0 && wim->hdr.part_number == 1) {
wim->image_metadata = CALLOC(wim->hdr.image_count,
sizeof(wim->image_metadata[0]));
if (!wim->image_metadata)
return WIMLIB_ERR_NOMEM;
}
if (open_flags & WIMLIB_OPEN_FLAG_FROM_PIPE) {
wim->blob_table = new_blob_table(64);
if (!wim->blob_table)
return WIMLIB_ERR_NOMEM;
} else {
if (wim->hdr.blob_table_reshdr.uncompressed_size == 0 &&
wim->hdr.xml_data_reshdr.uncompressed_size == 0)
return WIMLIB_ERR_WIM_IS_INCOMPLETE;
ret = read_wim_xml_data(wim);
if (ret)
return ret;
if (xml_get_image_count(wim->xml_info) != wim->hdr.image_count) {
ERROR("The WIM's header is inconsistent with its XML data.\n"
" Please submit a bug report if you believe this "
"WIM file should be considered valid.");
return WIMLIB_ERR_IMAGE_COUNT;
}
ret = read_blob_table(wim);
if (ret)
return ret;
}
return 0;
}
int
open_wim_as_WIMStruct(const void *wim_filename_or_fd, int open_flags,
WIMStruct **wim_ret,
wimlib_progress_func_t progfunc, void *progctx)
{
WIMStruct *wim;
int ret;
ret = wimlib_global_init(0);
if (ret)
return ret;
wim = new_wim_struct();
if (!wim)
return WIMLIB_ERR_NOMEM;
wim->progfunc = progfunc;
wim->progctx = progctx;
ret = begin_read(wim, wim_filename_or_fd, open_flags);
if (ret) {
wimlib_free(wim);
return ret;
}
*wim_ret = wim;
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_open_wim_with_progress(const tchar *wimfile, int open_flags,
WIMStruct **wim_ret,
wimlib_progress_func_t progfunc, void *progctx)
{
if (open_flags & ~(WIMLIB_OPEN_FLAG_CHECK_INTEGRITY |
WIMLIB_OPEN_FLAG_ERROR_IF_SPLIT |
WIMLIB_OPEN_FLAG_WRITE_ACCESS))
return WIMLIB_ERR_INVALID_PARAM;
if (!wimfile || !*wimfile || !wim_ret)
return WIMLIB_ERR_INVALID_PARAM;
return open_wim_as_WIMStruct(wimfile, open_flags, wim_ret,
progfunc, progctx);
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_open_wim(const tchar *wimfile, int open_flags, WIMStruct **wim_ret)
{
return wimlib_open_wim_with_progress(wimfile, open_flags, wim_ret,
NULL, NULL);
}
/* Checksum all blobs that are unhashed (other than the metadata blobs), merging
* them into the blob table as needed. This is a no-op unless files have been
* added to an image in the same WIMStruct. */
int
wim_checksum_unhashed_blobs(WIMStruct *wim)
{
int ret;
if (!wim_has_metadata(wim))
return 0;
for (int i = 0; i < wim->hdr.image_count; i++) {
struct blob_descriptor *blob, *tmp;
struct wim_image_metadata *imd = wim->image_metadata[i];
image_for_each_unhashed_blob_safe(blob, tmp, imd) {
struct blob_descriptor *new_blob;
ret = hash_unhashed_blob(blob, wim->blob_table, &new_blob);
if (ret)
return ret;
if (new_blob != blob)
free_blob_descriptor(blob);
}
}
return 0;
}
/*
* can_modify_wim - Check if a given WIM is writeable. This is only the case if
* it meets the following three conditions:
*
* 1. Write access is allowed to the underlying file (if any) at the filesystem level.
* 2. The WIM is not part of a spanned set.
* 3. The WIM_HDR_FLAG_READONLY flag is not set in the WIM header.
*
* Return value is 0 if writable; WIMLIB_ERR_WIM_IS_READONLY otherwise.
*/
int
can_modify_wim(WIMStruct *wim)
{
if (wim->filename) {
if (taccess(wim->filename, W_OK)) {
ERROR_WITH_ERRNO("Can't modify \"%"TS"\"", wim->filename);
return WIMLIB_ERR_WIM_IS_READONLY;
}
}
if (wim->hdr.total_parts != 1) {
ERROR("Cannot modify \"%"TS"\": is part of a split WIM",
wim->filename);
return WIMLIB_ERR_WIM_IS_READONLY;
}
if (wim->hdr.flags & WIM_HDR_FLAG_READONLY) {
ERROR("Cannot modify \"%"TS"\": is marked read-only",
wim->filename);
return WIMLIB_ERR_WIM_IS_READONLY;
}
return 0;
}
/* Release a reference to a WIMStruct. If the reference count reaches 0, the
* WIMStruct is freed. */
void
wim_decrement_refcnt(WIMStruct *wim)
{
wimlib_assert(wim->refcnt > 0);
if (--wim->refcnt != 0)
return;
if (filedes_valid(&wim->in_fd))
filedes_close(&wim->in_fd);
if (filedes_valid(&wim->out_fd))
filedes_close(&wim->out_fd);
wimlib_free_decompressor(wim->decompressor);
xml_free_info_struct(wim->xml_info);
FREE(wim->filename);
FREE(wim);
}
/* API function documented in wimlib.h */
WIMLIBAPI void
wimlib_free(WIMStruct *wim)
{
if (!wim)
return;
/* The blob table and image metadata are freed immediately, but other
* members of the WIMStruct such as the input file descriptor are
* retained until no more exported resources reference the WIMStruct. */
free_blob_table(wim->blob_table);
wim->blob_table = NULL;
if (wim->image_metadata != NULL) {
deselect_current_wim_image(wim);
for (int i = 0; i < wim->hdr.image_count; i++)
put_image_metadata(wim->image_metadata[i]);
FREE(wim->image_metadata);
wim->image_metadata = NULL;
}
wim_decrement_refcnt(wim);
}
/* API function documented in wimlib.h */
WIMLIBAPI u32
wimlib_get_version(void)
{
return (WIMLIB_MAJOR_VERSION << 20) |
(WIMLIB_MINOR_VERSION << 10) |
WIMLIB_PATCH_VERSION;
}
WIMLIBAPI const tchar *
wimlib_get_version_string(void)
{
return T(PACKAGE_VERSION);
}
static bool lib_initialized = false;
static struct mutex lib_initialization_mutex = MUTEX_INITIALIZER;
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_global_init(int init_flags)
{
int ret = 0;
if (lib_initialized)
goto out;
mutex_lock(&lib_initialization_mutex);
if (lib_initialized)
goto out_unlock;
if (!wimlib_error_file)
wimlib_error_file = stderr;
ret = WIMLIB_ERR_INVALID_PARAM;
if (init_flags & ~(WIMLIB_INIT_FLAG_ASSUME_UTF8 |
WIMLIB_INIT_FLAG_DONT_ACQUIRE_PRIVILEGES |
WIMLIB_INIT_FLAG_STRICT_CAPTURE_PRIVILEGES |
WIMLIB_INIT_FLAG_STRICT_APPLY_PRIVILEGES |
WIMLIB_INIT_FLAG_DEFAULT_CASE_SENSITIVE |
WIMLIB_INIT_FLAG_DEFAULT_CASE_INSENSITIVE))
goto out_unlock;
ret = WIMLIB_ERR_INVALID_PARAM;
if ((init_flags & (WIMLIB_INIT_FLAG_DEFAULT_CASE_SENSITIVE |
WIMLIB_INIT_FLAG_DEFAULT_CASE_INSENSITIVE))
== (WIMLIB_INIT_FLAG_DEFAULT_CASE_SENSITIVE |
WIMLIB_INIT_FLAG_DEFAULT_CASE_INSENSITIVE))
goto out_unlock;
init_cpu_features();
#ifdef _WIN32
ret = win32_global_init(init_flags);
if (ret)
goto out_unlock;
#endif
init_upcase();
if (init_flags & WIMLIB_INIT_FLAG_DEFAULT_CASE_SENSITIVE)
default_ignore_case = false;
else if (init_flags & WIMLIB_INIT_FLAG_DEFAULT_CASE_INSENSITIVE)
default_ignore_case = true;
lib_initialized = true;
ret = 0;
out_unlock:
mutex_unlock(&lib_initialization_mutex);
out:
return ret;
}
/* API function documented in wimlib.h */
WIMLIBAPI void
wimlib_global_cleanup(void)
{
if (!lib_initialized)
return;
mutex_lock(&lib_initialization_mutex);
if (!lib_initialized)
goto out_unlock;
#ifdef _WIN32
win32_global_cleanup();
#endif
wimlib_set_error_file(NULL);
lib_initialized = false;
out_unlock:
mutex_unlock(&lib_initialization_mutex);
}
wimlib-1.14.5/src/xpress_compress.c 0000644 0001750 0001750 00000103100 15137020663 014547 0 ustar 00e e /*
* xpress_compress.c
*
* A compressor for the XPRESS compression format (Huffman variant).
*/
/*
* Copyright (C) 2012, 2013, 2014 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
/*
* The maximum buffer size, in bytes, that can be compressed. An XPRESS
* compressor instance must be created with a 'max_bufsize' less than or equal
* to this value.
*/
#define XPRESS_MAX_BUFSIZE 65536
/*
* Define to 1 to enable the near-optimal parsing algorithm at high compression
* levels. The near-optimal parsing algorithm produces a compression ratio
* significantly better than the greedy and lazy algorithms. However, it is
* much slower.
*/
#define SUPPORT_NEAR_OPTIMAL_PARSING 1
/*
* The lowest compression level at which near-optimal parsing is enabled.
*/
#define MIN_LEVEL_FOR_NEAR_OPTIMAL 60
/*
* Matchfinder definitions. For XPRESS, only a 16-bit matchfinder is needed.
*/
#define mf_pos_t u16
#define MF_SUFFIX
/*
* Note: although XPRESS can potentially use a sliding window, it isn't well
* suited for large buffers of data because there is no way to reset the Huffman
* code. Therefore, we only allow buffers in which there is no restriction on
* match offsets (no sliding window). This simplifies the code and allows some
* optimizations.
*/
#include "wimlib/bitops.h"
#include "wimlib/compress_common.h"
#include "wimlib/compressor_ops.h"
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/hc_matchfinder.h"
#include "wimlib/unaligned.h"
#include "wimlib/util.h"
#include "wimlib/xpress_constants.h"
#if SUPPORT_NEAR_OPTIMAL_PARSING
/*
* CACHE_RESERVE_PER_POS is the number of lz_match structures to reserve in the
* match cache for each byte position. This value should be high enough so that
* virtually the time, all matches found in the input buffer can fit in the
* match cache. However, fallback behavior on cache overflow is still required.
*/
#define CACHE_RESERVE_PER_POS 8
/*
* We use a binary-tree based matchfinder for optimal parsing because it can
* find more matches in the same number of steps compared to hash-chain based
* matchfinders. In addition, since we need to find matches at almost every
* position, there isn't much penalty for keeping the sequences sorted in the
* binary trees.
*/
#include "wimlib/bt_matchfinder.h"
struct xpress_optimum_node;
#endif /* SUPPORT_NEAR_OPTIMAL_PARSING */
struct xpress_item;
/* The main XPRESS compressor structure */
struct xpress_compressor {
/* Pointer to the compress() implementation chosen at allocation time */
size_t (*impl)(struct xpress_compressor *,
const void *, size_t, void *, size_t);
/* Symbol frequency counters for the Huffman code */
u32 freqs[XPRESS_NUM_SYMBOLS];
/* The Huffman codewords and their lengths */
u32 codewords[XPRESS_NUM_SYMBOLS];
u8 lens[XPRESS_NUM_SYMBOLS];
/* The "nice" match length: if a match of this length is found, then
* choose it immediately without further consideration. */
unsigned nice_match_length;
/* The maximum search depth: consider at most this many potential
* matches at each position. */
unsigned max_search_depth;
union {
/* Data for greedy or lazy parsing */
struct {
struct xpress_item *chosen_items;
struct hc_matchfinder hc_mf;
/* hc_mf must be last! */
};
#if SUPPORT_NEAR_OPTIMAL_PARSING
/* Data for near-optimal parsing */
struct {
struct xpress_optimum_node *optimum_nodes;
struct lz_match *match_cache;
struct lz_match *cache_overflow_mark;
unsigned num_optim_passes;
u32 costs[XPRESS_NUM_SYMBOLS];
struct bt_matchfinder bt_mf;
/* bt_mf must be last! */
};
#endif
};
};
#if SUPPORT_NEAR_OPTIMAL_PARSING
/*
* This structure represents a byte position in the input buffer and a node in
* the graph of possible match/literal choices.
*
* Logically, each incoming edge to this node is labeled with a literal or a
* match that can be taken to reach this position from an earlier position; and
* each outgoing edge from this node is labeled with a literal or a match that
* can be taken to advance from this position to a later position.
*
* But these "edges" are actually stored elsewhere (in 'match_cache'). Here we
* associate with each node just two pieces of information:
*
* 'cost_to_end' is the minimum cost to reach the end of the buffer from
* this position.
*
* 'item' represents the literal or match that must be chosen from here to
* reach the end of the buffer with the minimum cost. Equivalently, this
* can be interpreted as the label of the outgoing edge on the minimum cost
* path to the "end of buffer" node from this node.
*/
struct xpress_optimum_node {
u32 cost_to_end;
/*
* Notes on the match/literal representation used here:
*
* The low bits of 'item' are the length: 1 if the item is a
* literal, or the match length if the item is a match.
*
* The high bits of 'item' are the actual literal byte if the item
* is a literal, or the match offset if the item is a match.
*/
#define OPTIMUM_OFFSET_SHIFT 16
#define OPTIMUM_LEN_MASK (((u32)1 << OPTIMUM_OFFSET_SHIFT) - 1)
u32 item;
};
#endif /* SUPPORT_NEAR_OPTIMAL_PARSING */
/* An intermediate representation of an XPRESS match or literal */
struct xpress_item {
/*
* Bits 0 - 8: Symbol
* Bits 9 - 24: Length - XPRESS_MIN_MATCH_LEN
* Bits 25 - 28: Number of extra offset bits
* Bits 29+ : Extra offset bits
*
* Unfortunately, gcc generates worse code if we use real bitfields here.
*/
u64 data;
};
/*
* Structure to keep track of the current state of sending compressed data to
* the output buffer.
*
* The XPRESS bitstream is encoded as a sequence of little endian 16-bit coding
* units interwoven with literal bytes.
*/
struct xpress_output_bitstream {
/* Bits that haven't yet been written to the output buffer. */
u32 bitbuf;
/* Number of bits currently held in @bitbuf. */
u32 bitcount;
/* Pointer to the start of the output buffer. */
u8 *start;
/* Pointer to the location in the output buffer at which to write the
* next 16 bits. */
u8 *next_bits;
/* Pointer to the location in the output buffer at which to write the
* next 16 bits, after @next_bits. */
u8 *next_bits2;
/* Pointer to the location in the output buffer at which to write the
* next literal byte. */
u8 *next_byte;
/* Pointer to the end of the output buffer. */
u8 *end;
};
/* Reset the symbol frequencies for the XPRESS Huffman code. */
static void
xpress_reset_symbol_frequencies(struct xpress_compressor *c)
{
memset(c->freqs, 0, sizeof(c->freqs));
}
/*
* Make the Huffman code for XPRESS.
*
* Input: c->freqs
* Output: c->lens and c->codewords
*/
static void
xpress_make_huffman_code(struct xpress_compressor *c)
{
make_canonical_huffman_code(XPRESS_NUM_SYMBOLS, XPRESS_MAX_CODEWORD_LEN,
c->freqs, c->lens, c->codewords);
}
/*
* Initialize the output bitstream.
*
* @os
* The output bitstream structure to initialize.
* @buffer
* The output buffer.
* @size
* Size of @buffer, in bytes. Must be at least 4.
*/
static void
xpress_init_output(struct xpress_output_bitstream *os, void *buffer, size_t size)
{
os->bitbuf = 0;
os->bitcount = 0;
os->start = buffer;
os->next_bits = os->start;
os->next_bits2 = os->start + 2;
os->next_byte = os->start + 4;
os->end = os->start + size;
}
/*
* Write some bits to the output bitstream.
*
* The bits are given by the low-order @num_bits bits of @bits. Higher-order
* bits in @bits cannot be set. At most 16 bits can be written at once.
*
* If the output buffer space is exhausted, then the bits will be ignored, and
* xpress_flush_output() will return 0 when it gets called.
*/
static forceinline void
xpress_write_bits(struct xpress_output_bitstream *os,
const u32 bits, const unsigned num_bits)
{
/* This code is optimized for XPRESS, which never needs to write more
* than 16 bits at once. */
os->bitcount += num_bits;
os->bitbuf = (os->bitbuf << num_bits) | bits;
if (os->bitcount > 16) {
os->bitcount -= 16;
if (os->end - os->next_byte >= 2) {
put_unaligned_le16(os->bitbuf >> os->bitcount, os->next_bits);
os->next_bits = os->next_bits2;
os->next_bits2 = os->next_byte;
os->next_byte += 2;
}
}
}
/*
* Interweave a literal byte into the output bitstream.
*/
static forceinline void
xpress_write_byte(struct xpress_output_bitstream *os, u8 byte)
{
if (os->next_byte < os->end)
*os->next_byte++ = byte;
}
/*
* Interweave two literal bytes into the output bitstream.
*/
static forceinline void
xpress_write_u16(struct xpress_output_bitstream *os, u16 v)
{
if (os->end - os->next_byte >= 2) {
put_unaligned_le16(v, os->next_byte);
os->next_byte += 2;
}
}
/*
* Flush the last coding unit to the output buffer if needed. Return the total
* number of bytes written to the output buffer, or 0 if an overflow occurred.
*/
static size_t
xpress_flush_output(struct xpress_output_bitstream *os)
{
if (os->end - os->next_byte < 2)
return 0;
put_unaligned_le16(os->bitbuf << (16 - os->bitcount), os->next_bits);
put_unaligned_le16(0, os->next_bits2);
return os->next_byte - os->start;
}
static forceinline void
xpress_write_extra_length_bytes(struct xpress_output_bitstream *os,
unsigned adjusted_len)
{
/* If length >= 18, output one extra length byte.
* If length >= 273, output three (total) extra length bytes. */
if (adjusted_len >= 0xF) {
u8 byte1 = min(adjusted_len - 0xF, 0xFF);
xpress_write_byte(os, byte1);
if (byte1 == 0xFF)
xpress_write_u16(os, adjusted_len);
}
}
/* Output a match or literal. */
static forceinline void
xpress_write_item(struct xpress_item item, struct xpress_output_bitstream *os,
const u32 codewords[], const u8 lens[])
{
u64 data = item.data;
unsigned symbol = data & 0x1FF;
xpress_write_bits(os, codewords[symbol], lens[symbol]);
if (symbol >= XPRESS_NUM_CHARS) {
/* Match, not a literal */
xpress_write_extra_length_bytes(os, (data >> 9) & 0xFFFF);
xpress_write_bits(os, data >> 29, (data >> 25) & 0xF);
}
}
/* Output a sequence of XPRESS matches and literals. */
static void
xpress_write_items(struct xpress_output_bitstream *os,
const struct xpress_item items[], size_t num_items,
const u32 codewords[], const u8 lens[])
{
for (size_t i = 0; i < num_items; i++)
xpress_write_item(items[i], os, codewords, lens);
}
#if SUPPORT_NEAR_OPTIMAL_PARSING
/*
* Follow the minimum cost path in the graph of possible match/literal choices
* and write out the matches/literals using the specified Huffman code.
*
* Note: this is slightly duplicated with xpress_write_items(). However, we
* don't want to waste time translating between intermediate match/literal
* representations.
*/
static void
xpress_write_item_list(struct xpress_output_bitstream *os,
struct xpress_optimum_node *optimum_nodes,
size_t count, const u32 codewords[], const u8 lens[])
{
struct xpress_optimum_node *cur_node = optimum_nodes;
struct xpress_optimum_node *end_node = optimum_nodes + count;
do {
unsigned length = cur_node->item & OPTIMUM_LEN_MASK;
unsigned offset = cur_node->item >> OPTIMUM_OFFSET_SHIFT;
if (length == 1) {
/* Literal */
unsigned literal = offset;
xpress_write_bits(os, codewords[literal], lens[literal]);
} else {
/* Match */
unsigned adjusted_len;
unsigned log2_offset;
unsigned len_hdr;
unsigned sym;
adjusted_len = length - XPRESS_MIN_MATCH_LEN;
log2_offset = bsr32(offset);
len_hdr = min(0xF, adjusted_len);
sym = XPRESS_NUM_CHARS + ((log2_offset << 4) | len_hdr);
xpress_write_bits(os, codewords[sym], lens[sym]);
xpress_write_extra_length_bytes(os, adjusted_len);
xpress_write_bits(os, offset - (1U << log2_offset),
log2_offset);
}
cur_node += length;
} while (cur_node != end_node);
}
#endif /* SUPPORT_NEAR_OPTIMAL_PARSING */
/*
* Output the XPRESS-compressed data, given the sequence of match/literal
* "items" that was chosen to represent the input data.
*
* If @near_optimal is %false, then the items are taken from the array
* c->chosen_items[0...count].
*
* If @near_optimal is %true, then the items are taken from the minimum cost
* path stored in c->optimum_nodes[0...count].
*/
static size_t
xpress_write(struct xpress_compressor *c, void *out, size_t out_nbytes_avail,
size_t count, bool near_optimal)
{
u8 *cptr;
struct xpress_output_bitstream os;
size_t out_size;
/* Account for the end-of-data symbol and make the Huffman code. */
c->freqs[XPRESS_END_OF_DATA]++;
xpress_make_huffman_code(c);
/* Output the Huffman code as a series of 512 4-bit lengths. */
cptr = out;
for (unsigned i = 0; i < XPRESS_NUM_SYMBOLS; i += 2)
*cptr++ = (c->lens[i + 1] << 4) | c->lens[i];
xpress_init_output(&os, cptr, out_nbytes_avail - XPRESS_NUM_SYMBOLS / 2);
/* Output the Huffman-encoded items. */
#if SUPPORT_NEAR_OPTIMAL_PARSING
if (near_optimal) {
xpress_write_item_list(&os, c->optimum_nodes, count,
c->codewords, c->lens);
} else
#endif
{
xpress_write_items(&os, c->chosen_items, count,
c->codewords, c->lens);
}
/* Write the end-of-data symbol (needed for MS compatibility) */
xpress_write_bits(&os, c->codewords[XPRESS_END_OF_DATA],
c->lens[XPRESS_END_OF_DATA]);
/* Flush any pending data. Then return the compressed size if the
* compressed data fit in the output buffer, or 0 if it did not. */
out_size = xpress_flush_output(&os);
if (out_size == 0)
return 0;
return out_size + XPRESS_NUM_SYMBOLS / 2;
}
/* Tally the Huffman symbol for a literal and return the intermediate
* representation of that literal. */
static forceinline struct xpress_item
xpress_record_literal(struct xpress_compressor *c, unsigned literal)
{
c->freqs[literal]++;
return (struct xpress_item) {
.data = literal,
};
}
/* Tally the Huffman symbol for a match and return the intermediate
* representation of that match. */
static forceinline struct xpress_item
xpress_record_match(struct xpress_compressor *c, unsigned length, unsigned offset)
{
unsigned adjusted_len = length - XPRESS_MIN_MATCH_LEN;
unsigned len_hdr = min(adjusted_len, 0xF);
unsigned log2_offset = bsr32(offset);
unsigned sym = XPRESS_NUM_CHARS + ((log2_offset << 4) | len_hdr);
c->freqs[sym]++;
return (struct xpress_item) {
.data = (u64)sym |
((u64)adjusted_len << 9) |
((u64)log2_offset << 25) |
((u64)(offset ^ (1U << log2_offset)) << 29),
};
}
/*
* This is the "greedy" XPRESS compressor. It always chooses the longest match.
* (Exception: as a heuristic, we pass up length 3 matches that have large
* offsets.)
*/
static size_t
xpress_compress_greedy(struct xpress_compressor * restrict c,
const void * restrict in, size_t in_nbytes,
void * restrict out, size_t out_nbytes_avail)
{
const u8 * const in_begin = in;
const u8 * in_next = in_begin;
const u8 * const in_end = in_begin + in_nbytes;
struct xpress_item *next_chosen_item = c->chosen_items;
unsigned len_3_too_far;
u32 next_hashes[2] = {};
if (in_nbytes <= 8192)
len_3_too_far = 2048;
else
len_3_too_far = 4096;
hc_matchfinder_init(&c->hc_mf);
do {
unsigned length;
unsigned offset;
length = hc_matchfinder_longest_match(&c->hc_mf,
in_begin,
in_next,
XPRESS_MIN_MATCH_LEN - 1,
in_end - in_next,
min(in_end - in_next, c->nice_match_length),
c->max_search_depth,
next_hashes,
&offset);
if (length >= XPRESS_MIN_MATCH_LEN &&
!(length == XPRESS_MIN_MATCH_LEN && offset >= len_3_too_far))
{
/* Match found */
*next_chosen_item++ =
xpress_record_match(c, length, offset);
in_next += 1;
hc_matchfinder_skip_bytes(&c->hc_mf,
in_begin,
in_next,
in_end,
length - 1,
next_hashes);
in_next += length - 1;
} else {
/* No match found */
*next_chosen_item++ =
xpress_record_literal(c, *in_next);
in_next += 1;
}
} while (in_next != in_end);
return xpress_write(c, out, out_nbytes_avail,
next_chosen_item - c->chosen_items, false);
}
/*
* This is the "lazy" XPRESS compressor. Before choosing a match, it checks to
* see if there's a longer match at the next position. If yes, it outputs a
* literal and continues to the next position. If no, it outputs the match.
*/
static size_t
xpress_compress_lazy(struct xpress_compressor * restrict c,
const void * restrict in, size_t in_nbytes,
void * restrict out, size_t out_nbytes_avail)
{
const u8 * const in_begin = in;
const u8 * in_next = in_begin;
const u8 * const in_end = in_begin + in_nbytes;
struct xpress_item *next_chosen_item = c->chosen_items;
unsigned len_3_too_far;
u32 next_hashes[2] = {};
if (in_nbytes <= 8192)
len_3_too_far = 2048;
else
len_3_too_far = 4096;
hc_matchfinder_init(&c->hc_mf);
do {
unsigned cur_len;
unsigned cur_offset;
unsigned next_len;
unsigned next_offset;
/* Find the longest match at the current position. */
cur_len = hc_matchfinder_longest_match(&c->hc_mf,
in_begin,
in_next,
XPRESS_MIN_MATCH_LEN - 1,
in_end - in_next,
min(in_end - in_next, c->nice_match_length),
c->max_search_depth,
next_hashes,
&cur_offset);
in_next += 1;
if (cur_len < XPRESS_MIN_MATCH_LEN ||
(cur_len == XPRESS_MIN_MATCH_LEN &&
cur_offset >= len_3_too_far))
{
/* No match found. Choose a literal. */
*next_chosen_item++ =
xpress_record_literal(c, *(in_next - 1));
continue;
}
have_cur_match:
/* We have a match at the current position. */
/* If the current match is very long, choose it immediately. */
if (cur_len >= c->nice_match_length) {
*next_chosen_item++ =
xpress_record_match(c, cur_len, cur_offset);
hc_matchfinder_skip_bytes(&c->hc_mf,
in_begin,
in_next,
in_end,
cur_len - 1,
next_hashes);
in_next += cur_len - 1;
continue;
}
/*
* Try to find a match at the next position.
*
* Note: since we already have a match at the *current*
* position, we use only half the 'max_search_depth' when
* checking the *next* position. This is a useful trade-off
* because it's more worthwhile to use a greater search depth on
* the initial match than on the next match (since a lot of the
* time, that next match won't even be used).
*
* Note: it's possible to structure the code such that there's
* only one call to longest_match(), which handles both the
* "find the initial match" and "try to find a longer match"
* cases. However, it is faster to have two call sites, with
* longest_match() inlined at each.
*/
next_len = hc_matchfinder_longest_match(&c->hc_mf,
in_begin,
in_next,
cur_len,
in_end - in_next,
min(in_end - in_next, c->nice_match_length),
c->max_search_depth / 2,
next_hashes,
&next_offset);
in_next += 1;
if (next_len > cur_len) {
/* Found a longer match at the next position, so output
* a literal. */
*next_chosen_item++ =
xpress_record_literal(c, *(in_next - 2));
cur_len = next_len;
cur_offset = next_offset;
goto have_cur_match;
} else {
/* Didn't find a longer match at the next position, so
* output the current match. */
*next_chosen_item++ =
xpress_record_match(c, cur_len, cur_offset);
hc_matchfinder_skip_bytes(&c->hc_mf,
in_begin,
in_next,
in_end,
cur_len - 2,
next_hashes);
in_next += cur_len - 2;
continue;
}
} while (in_next != in_end);
return xpress_write(c, out, out_nbytes_avail,
next_chosen_item - c->chosen_items, false);
}
#if SUPPORT_NEAR_OPTIMAL_PARSING
/*
* Set Huffman symbol costs for the first optimization pass.
*
* It works well to assume that each Huffman symbol is equally probable. This
* results in each symbol being assigned a cost of -log2(1.0/num_syms) where
* 'num_syms' is the number of symbols in the alphabet.
*/
static void
xpress_set_default_costs(struct xpress_compressor *c)
{
for (unsigned i = 0; i < XPRESS_NUM_SYMBOLS; i++)
c->costs[i] = 9;
}
/* Update the cost model based on the codeword lengths @c->lens. */
static void
xpress_update_costs(struct xpress_compressor *c)
{
for (unsigned i = 0; i < XPRESS_NUM_SYMBOLS; i++)
c->costs[i] = c->lens[i] ? c->lens[i] : XPRESS_MAX_CODEWORD_LEN;
}
/*
* Follow the minimum cost path in the graph of possible match/literal choices
* and compute the frequencies of the Huffman symbols that are needed to output
* those matches and literals.
*/
static void
xpress_tally_item_list(struct xpress_compressor *c,
struct xpress_optimum_node *end_node)
{
struct xpress_optimum_node *cur_node = c->optimum_nodes;
do {
unsigned length = cur_node->item & OPTIMUM_LEN_MASK;
unsigned offset = cur_node->item >> OPTIMUM_OFFSET_SHIFT;
if (length == 1) {
/* Literal */
unsigned literal = offset;
c->freqs[literal]++;
} else {
/* Match */
unsigned adjusted_len;
unsigned log2_offset;
unsigned len_hdr;
unsigned sym;
adjusted_len = length - XPRESS_MIN_MATCH_LEN;
log2_offset = bsr32(offset);
len_hdr = min(0xF, adjusted_len);
sym = XPRESS_NUM_CHARS + ((log2_offset << 4) | len_hdr);
c->freqs[sym]++;
}
cur_node += length;
} while (cur_node != end_node);
}
/*
* Find a new minimum cost path through the graph of possible match/literal
* choices. We find the minimum cost path from 'c->optimum_nodes[0]', which
* represents the node at the beginning of the input buffer, to
* 'c->optimum_nodes[in_nbytes]', which represents the node at the end of the
* input buffer. Edge costs are evaluated using the cost model 'c->costs'.
*
* The algorithm works backward, starting at 'c->optimum_nodes[in_nbytes]' and
* proceeding backwards one position at a time. At each position, the minimum
* cost to reach 'c->optimum_nodes[in_nbytes]' from that position is computed
* and the match/literal choice is saved.
*/
static void
xpress_find_min_cost_path(struct xpress_compressor *c, size_t in_nbytes,
struct lz_match *end_cache_ptr)
{
struct xpress_optimum_node *cur_node = c->optimum_nodes + in_nbytes;
struct lz_match *cache_ptr = end_cache_ptr;
cur_node->cost_to_end = 0;
do {
unsigned literal;
u32 best_item;
u32 best_cost_to_end;
unsigned num_matches;
struct lz_match *match;
unsigned len;
cur_node--;
cache_ptr--;
literal = cache_ptr->offset;
/* Consider coding a literal. */
best_item = ((u32)literal << OPTIMUM_OFFSET_SHIFT) | 1;
best_cost_to_end = c->costs[literal] +
(cur_node + 1)->cost_to_end;
num_matches = cache_ptr->length;
if (num_matches == 0) {
/* No matches; the only choice is the literal. */
cur_node->cost_to_end = best_cost_to_end;
cur_node->item = best_item;
continue;
}
/*
* Consider each match length from the minimum
* (XPRESS_MIN_MATCH_LEN) to the length of the longest match
* found at this position. For each length, consider only the
* smallest offset for which that length is available. Although
* this is not guaranteed to be optimal due to the possibility
* of a larger offset costing less than a smaller offset to
* code, this is a very useful heuristic.
*/
match = cache_ptr - num_matches;
len = XPRESS_MIN_MATCH_LEN;
if (cache_ptr[-1].length < 0xF + XPRESS_MIN_MATCH_LEN) {
/* All lengths are small. Optimize accordingly. */
do {
unsigned offset;
unsigned log2_offset;
u32 offset_cost;
offset = match->offset;
log2_offset = bsr32(offset);
offset_cost = log2_offset;
do {
unsigned len_hdr;
unsigned sym;
u32 cost_to_end;
len_hdr = len - XPRESS_MIN_MATCH_LEN;
sym = XPRESS_NUM_CHARS +
((log2_offset << 4) | len_hdr);
cost_to_end =
offset_cost + c->costs[sym] +
(cur_node + len)->cost_to_end;
if (cost_to_end < best_cost_to_end) {
best_cost_to_end = cost_to_end;
best_item =
((u32)offset <<
OPTIMUM_OFFSET_SHIFT) | len;
}
} while (++len <= match->length);
} while (++match != cache_ptr);
} else {
/* Some lengths are big. */
do {
unsigned offset;
unsigned log2_offset;
u32 offset_cost;
offset = match->offset;
log2_offset = bsr32(offset);
offset_cost = log2_offset;
do {
unsigned adjusted_len;
unsigned len_hdr;
unsigned sym;
u32 cost_to_end;
adjusted_len = len - XPRESS_MIN_MATCH_LEN;
len_hdr = min(adjusted_len, 0xF);
sym = XPRESS_NUM_CHARS +
((log2_offset << 4) | len_hdr);
cost_to_end =
offset_cost + c->costs[sym] +
(cur_node + len)->cost_to_end;
if (adjusted_len >= 0xF) {
cost_to_end += 8;
if (adjusted_len - 0xF >= 0xFF)
cost_to_end += 16;
}
if (cost_to_end < best_cost_to_end) {
best_cost_to_end = cost_to_end;
best_item =
((u32)offset <<
OPTIMUM_OFFSET_SHIFT) | len;
}
} while (++len <= match->length);
} while (++match != cache_ptr);
}
cache_ptr -= num_matches;
cur_node->cost_to_end = best_cost_to_end;
cur_node->item = best_item;
} while (cur_node != c->optimum_nodes);
}
/*
* This routine finds matches at each position in the buffer in[0...in_nbytes].
* The matches are cached in the array c->match_cache, and the return value is a
* pointer past the last slot in this array that was filled.
*/
static struct lz_match *
xpress_find_matches(struct xpress_compressor * restrict c,
const void * restrict in, size_t in_nbytes)
{
const u8 * const in_begin = in;
const u8 *in_next = in_begin;
struct lz_match *cache_ptr = c->match_cache;
u32 next_hashes[2] = {};
u32 max_len = in_nbytes;
u32 nice_len = min(max_len, c->nice_match_length);
bt_matchfinder_init(&c->bt_mf);
for (;;) {
struct lz_match *matches;
u32 best_len;
/* If we've found so many matches that the cache might overflow
* if we keep finding more, then stop finding matches. This
* case is very unlikely. */
if (unlikely(cache_ptr >= c->cache_overflow_mark ||
max_len < BT_MATCHFINDER_REQUIRED_NBYTES))
break;
matches = cache_ptr;
/* Find matches with the current position using the binary tree
* matchfinder and save them in the next available slots in
* the match cache. */
cache_ptr =
bt_matchfinder_get_matches(&c->bt_mf,
in_begin,
in_next - in_begin,
max_len,
nice_len,
c->max_search_depth,
next_hashes,
&best_len,
cache_ptr);
cache_ptr->length = cache_ptr - matches;
cache_ptr->offset = *in_next++;
cache_ptr++;
max_len--;
nice_len = min(nice_len, max_len);
/*
* If there was a very long match found, then don't cache any
* matches for the bytes covered by that match. This avoids
* degenerate behavior when compressing highly redundant data,
* where the number of matches can be very large.
*
* This heuristic doesn't actually hurt the compression ratio
* very much. If there's a long match, then the data must be
* highly compressible, so it doesn't matter as much what we do.
*/
if (best_len >= nice_len) {
if (unlikely(best_len +
BT_MATCHFINDER_REQUIRED_NBYTES >= max_len))
break;
--best_len;
do {
bt_matchfinder_skip_byte(&c->bt_mf,
in_begin,
in_next - in_begin,
nice_len,
c->max_search_depth,
next_hashes);
cache_ptr->length = 0;
cache_ptr->offset = *in_next++;
cache_ptr++;
max_len--;
nice_len = min(nice_len, max_len);
} while (--best_len);
}
}
while (max_len--) {
cache_ptr->length = 0;
cache_ptr->offset = *in_next++;
cache_ptr++;
}
return cache_ptr;
}
/*
* This is the "near-optimal" XPRESS compressor. It computes a compressed
* representation of the input buffer by executing a minimum cost path search
* over the graph of possible match/literal choices, assuming a certain cost for
* each Huffman symbol. The result is usually close to optimal, but it is *not*
* guaranteed to be optimal because of (a) heuristic restrictions in which
* matches are considered, and (b) symbol costs are unknown until those symbols
* have already been chosen --- so iterative optimization must be used, and the
* algorithm might converge on a local optimum rather than a global optimum.
*/
static size_t
xpress_compress_near_optimal(struct xpress_compressor * restrict c,
const void * restrict in, size_t in_nbytes,
void * restrict out, size_t out_nbytes_avail)
{
struct lz_match *end_cache_ptr;
unsigned num_passes_remaining = c->num_optim_passes;
/* Run the input buffer through the matchfinder and save the results. */
end_cache_ptr = xpress_find_matches(c, in, in_nbytes);
/* The first optimization pass uses a default cost model. Each
* additional optimization pass uses a cost model derived from the
* Huffman code computed in the previous pass. */
xpress_set_default_costs(c);
do {
xpress_find_min_cost_path(c, in_nbytes, end_cache_ptr);
xpress_tally_item_list(c, c->optimum_nodes + in_nbytes);
if (num_passes_remaining > 1) {
c->freqs[XPRESS_END_OF_DATA]++;
xpress_make_huffman_code(c);
xpress_update_costs(c);
xpress_reset_symbol_frequencies(c);
}
} while (--num_passes_remaining);
return xpress_write(c, out, out_nbytes_avail, in_nbytes, true);
}
#endif /* SUPPORT_NEAR_OPTIMAL_PARSING */
static size_t
xpress_get_compressor_size(size_t max_bufsize, unsigned compression_level)
{
#if SUPPORT_NEAR_OPTIMAL_PARSING
if (compression_level >= MIN_LEVEL_FOR_NEAR_OPTIMAL)
return offsetof(struct xpress_compressor, bt_mf) +
bt_matchfinder_size(max_bufsize);
#endif
return offsetof(struct xpress_compressor, hc_mf) +
hc_matchfinder_size(max_bufsize);
}
static u64
xpress_get_needed_memory(size_t max_bufsize, unsigned compression_level,
bool destructive)
{
u64 size = 0;
if (max_bufsize > XPRESS_MAX_BUFSIZE)
return 0;
size += xpress_get_compressor_size(max_bufsize, compression_level);
if (compression_level < MIN_LEVEL_FOR_NEAR_OPTIMAL ||
!SUPPORT_NEAR_OPTIMAL_PARSING) {
/* chosen_items */
size += max_bufsize * sizeof(struct xpress_item);
}
#if SUPPORT_NEAR_OPTIMAL_PARSING
else {
/* optimum_nodes */
size += (max_bufsize + 1) * sizeof(struct xpress_optimum_node);
/* match_cache */
size += ((max_bufsize * CACHE_RESERVE_PER_POS) +
XPRESS_MAX_MATCH_LEN + max_bufsize) *
sizeof(struct lz_match);
}
#endif
return size;
}
static int
xpress_create_compressor(size_t max_bufsize, unsigned compression_level,
bool destructive, void **c_ret)
{
struct xpress_compressor *c;
if (max_bufsize > XPRESS_MAX_BUFSIZE)
return WIMLIB_ERR_INVALID_PARAM;
c = MALLOC(xpress_get_compressor_size(max_bufsize, compression_level));
if (!c)
goto oom0;
if (compression_level < MIN_LEVEL_FOR_NEAR_OPTIMAL ||
!SUPPORT_NEAR_OPTIMAL_PARSING)
{
c->chosen_items = MALLOC(max_bufsize * sizeof(struct xpress_item));
if (!c->chosen_items)
goto oom1;
if (compression_level < 30) {
c->impl = xpress_compress_greedy;
c->max_search_depth = (compression_level * 30) / 16;
c->nice_match_length = (compression_level * 60) / 16;
} else {
c->impl = xpress_compress_lazy;
c->max_search_depth = (compression_level * 30) / 32;
c->nice_match_length = (compression_level * 60) / 32;
/* xpress_compress_lazy() needs max_search_depth >= 2
* because it halves the max_search_depth when
* attempting a lazy match, and max_search_depth cannot
* be 0. */
if (c->max_search_depth < 2)
c->max_search_depth = 2;
}
}
#if SUPPORT_NEAR_OPTIMAL_PARSING
else {
c->optimum_nodes = MALLOC((max_bufsize + 1) *
sizeof(struct xpress_optimum_node));
c->match_cache = MALLOC(((max_bufsize * CACHE_RESERVE_PER_POS) +
XPRESS_MAX_MATCH_LEN + max_bufsize) *
sizeof(struct lz_match));
if (!c->optimum_nodes || !c->match_cache) {
FREE(c->optimum_nodes);
FREE(c->match_cache);
goto oom1;
}
c->cache_overflow_mark =
&c->match_cache[max_bufsize * CACHE_RESERVE_PER_POS];
c->impl = xpress_compress_near_optimal;
c->max_search_depth = (compression_level * 28) / 100;
c->nice_match_length = (compression_level * 56) / 100;
c->num_optim_passes = compression_level / 40;
}
#endif /* SUPPORT_NEAR_OPTIMAL_PARSING */
/* max_search_depth == 0 is invalid. */
if (c->max_search_depth < 1)
c->max_search_depth = 1;
*c_ret = c;
return 0;
oom1:
FREE(c);
oom0:
return WIMLIB_ERR_NOMEM;
}
static size_t
xpress_compress(const void *restrict in, size_t in_nbytes,
void *restrict out, size_t out_nbytes_avail, void *restrict _c)
{
struct xpress_compressor *c = _c;
/* Don't bother trying to compress very small inputs. */
if (in_nbytes < 25)
return 0;
if (out_nbytes_avail <= XPRESS_NUM_SYMBOLS / 2 + 4)
return 0;
xpress_reset_symbol_frequencies(c);
return (*c->impl)(c, in, in_nbytes, out, out_nbytes_avail);
}
static void
xpress_free_compressor(void *_c)
{
struct xpress_compressor *c = _c;
#if SUPPORT_NEAR_OPTIMAL_PARSING
if (c->impl == xpress_compress_near_optimal) {
FREE(c->optimum_nodes);
FREE(c->match_cache);
} else
#endif
FREE(c->chosen_items);
FREE(c);
}
const struct compressor_ops xpress_compressor_ops = {
.get_needed_memory = xpress_get_needed_memory,
.create_compressor = xpress_create_compressor,
.compress = xpress_compress,
.free_compressor = xpress_free_compressor,
};
wimlib-1.14.5/src/integrity.c 0000644 0001750 0001750 00000032204 15137020663 013334 0 ustar 00e e /*
* integrity.c
*
* WIM files can optionally contain a table of SHA1 message digests at the end,
* one digest for each chunk of the file of some specified size (often 10 MB).
* This file implements the checking and writing of this table.
*/
/*
* Copyright (C) 2012-2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/assert.h"
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/file_io.h"
#include "wimlib/integrity.h"
#include "wimlib/progress.h"
#include "wimlib/resource.h"
#include "wimlib/sha1.h"
#include "wimlib/wim.h"
#include "wimlib/write.h"
/* Size, in bytes, of each SHA1-summed chunk, when wimlib writes integrity
* information. */
#define INTEGRITY_CHUNK_SIZE 10485760
/* Only use a different chunk size for compatibility with an existing integrity
* table if the chunk size is between these two numbers. */
#define INTEGRITY_MIN_CHUNK_SIZE 4096
#define INTEGRITY_MAX_CHUNK_SIZE 134217728
struct integrity_table {
u32 size;
u32 num_entries;
u32 chunk_size;
u8 sha1sums[][20];
} __attribute__((packed));
static int
calculate_chunk_sha1(struct filedes *in_fd, size_t this_chunk_size,
off_t offset, u8 sha1_md[])
{
u8 buf[BUFFER_SIZE];
struct sha1_ctx ctx;
size_t bytes_remaining;
size_t bytes_to_read;
int ret;
bytes_remaining = this_chunk_size;
sha1_init(&ctx);
do {
bytes_to_read = min(bytes_remaining, sizeof(buf));
ret = full_pread(in_fd, buf, bytes_to_read, offset);
if (ret) {
ERROR_WITH_ERRNO("Read error while calculating "
"integrity checksums");
return ret;
}
sha1_update(&ctx, buf, bytes_to_read);
bytes_remaining -= bytes_to_read;
offset += bytes_to_read;
} while (bytes_remaining);
sha1_final(&ctx, sha1_md);
return 0;
}
/*
* read_integrity_table: - Reads the integrity table from a WIM file.
*
* @wim:
* WIMStruct for the WIM file; @wim->hdr.integrity_table_reshdr specifies
* the location of the integrity table. @wim->in_fd is expected to be a
* seekable file descriptor to the WIM file opened for reading.
*
* @num_checked_bytes:
* Number of bytes of data that should be checked by the integrity table.
*
* @table_ret:
* On success, a pointer to an in-memory structure containing the integrity
* information is written to this location.
*
* Return values:
* WIMLIB_ERR_SUCCESS (0)
* WIMLIB_ERR_INVALID_INTEGRITY_TABLE
* WIMLIB_ERR_NOMEM
* WIMLIB_ERR_READ
* WIMLIB_ERR_UNEXPECTED_END_OF_FILE
*/
int
read_integrity_table(WIMStruct *wim, u64 num_checked_bytes,
struct integrity_table **table_ret)
{
void *buf;
struct integrity_table *table;
int ret;
STATIC_ASSERT(sizeof(struct integrity_table) == 12);
if (wim->hdr.integrity_table_reshdr.uncompressed_size < 12)
return WIMLIB_ERR_INVALID_INTEGRITY_TABLE;
ret = wim_reshdr_to_data(&wim->hdr.integrity_table_reshdr, wim, &buf);
if (ret)
return ret;
table = buf;
table->size = le32_to_cpu((_force_attr le32)table->size);
table->num_entries = le32_to_cpu((_force_attr le32)table->num_entries);
table->chunk_size = le32_to_cpu((_force_attr le32)table->chunk_size);
if (table->size != wim->hdr.integrity_table_reshdr.uncompressed_size ||
table->size != (u64)table->num_entries * SHA1_HASH_SIZE + 12 ||
table->chunk_size == 0 ||
table->num_entries != DIV_ROUND_UP(num_checked_bytes, table->chunk_size))
{
FREE(table);
return WIMLIB_ERR_INVALID_INTEGRITY_TABLE;
}
*table_ret = table;
return 0;
}
/*
* calculate_integrity_table():
*
* Calculates an integrity table for the data in a file beginning at offset 208
* (WIM_HEADER_DISK_SIZE).
*
* @in_fd:
* File descriptor for the file to be checked, opened for reading. Does
* not need to be at any specific location in the file.
*
* @new_check_end:
* Offset of byte after the last byte to be checked.
*
* @old_table:
* If non-NULL, a pointer to the table containing the previously calculated
* integrity data for a prefix of this file.
*
* @old_check_end:
* If @old_table is non-NULL, the byte after the last byte that was checked
* in the old table. Must be less than or equal to new_check_end.
*
* @integrity_table_ret:
* On success, a pointer to the calculated integrity table is written into
* this location.
*
* Return values:
* WIMLIB_ERR_SUCCESS (0)
* WIMLIB_ERR_NOMEM
* WIMLIB_ERR_READ
* WIMLIB_ERR_UNEXPECTED_END_OF_FILE
*/
static int
calculate_integrity_table(struct filedes *in_fd,
off_t new_check_end,
const struct integrity_table *old_table,
off_t old_check_end,
struct integrity_table **integrity_table_ret,
wimlib_progress_func_t progfunc,
void *progctx)
{
int ret;
size_t chunk_size = INTEGRITY_CHUNK_SIZE;
/* If an old table is provided, set the chunk size to be compatible with
* the old chunk size, unless the old chunk size was weird. */
if (old_table != NULL) {
if (old_table->num_entries == 0 ||
old_table->chunk_size < INTEGRITY_MIN_CHUNK_SIZE ||
old_table->chunk_size > INTEGRITY_MAX_CHUNK_SIZE)
old_table = NULL;
else
chunk_size = old_table->chunk_size;
}
u64 old_check_bytes = old_check_end - WIM_HEADER_DISK_SIZE;
u64 new_check_bytes = new_check_end - WIM_HEADER_DISK_SIZE;
u32 old_num_chunks = DIV_ROUND_UP(old_check_bytes, chunk_size);
u32 new_num_chunks = DIV_ROUND_UP(new_check_bytes, chunk_size);
size_t old_last_chunk_size = MODULO_NONZERO(old_check_bytes, chunk_size);
size_t new_last_chunk_size = MODULO_NONZERO(new_check_bytes, chunk_size);
size_t new_table_size = 12 + new_num_chunks * SHA1_HASH_SIZE;
struct integrity_table *new_table = MALLOC(new_table_size);
if (!new_table)
return WIMLIB_ERR_NOMEM;
new_table->num_entries = new_num_chunks;
new_table->size = new_table_size;
new_table->chunk_size = chunk_size;
u64 offset = WIM_HEADER_DISK_SIZE;
union wimlib_progress_info progress;
progress.integrity.total_bytes = new_check_bytes;
progress.integrity.total_chunks = new_num_chunks;
progress.integrity.completed_chunks = 0;
progress.integrity.completed_bytes = 0;
progress.integrity.chunk_size = chunk_size;
progress.integrity.filename = NULL;
ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_CALC_INTEGRITY,
&progress, progctx);
if (ret)
goto out_free_new_table;
for (u32 i = 0; i < new_num_chunks; i++) {
size_t this_chunk_size;
if (i == new_num_chunks - 1)
this_chunk_size = new_last_chunk_size;
else
this_chunk_size = chunk_size;
if (old_table &&
((this_chunk_size == chunk_size && i < old_num_chunks - 1) ||
(i == old_num_chunks - 1 && this_chunk_size == old_last_chunk_size)))
{
/* Can use SHA1 message digest from old integrity table
* */
copy_hash(new_table->sha1sums[i], old_table->sha1sums[i]);
} else {
/* Calculate the SHA1 message digest of this chunk */
ret = calculate_chunk_sha1(in_fd, this_chunk_size,
offset, new_table->sha1sums[i]);
if (ret)
goto out_free_new_table;
}
offset += this_chunk_size;
progress.integrity.completed_chunks++;
progress.integrity.completed_bytes += this_chunk_size;
ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_CALC_INTEGRITY,
&progress, progctx);
if (ret)
goto out_free_new_table;
}
*integrity_table_ret = new_table;
return 0;
out_free_new_table:
FREE(new_table);
return ret;
}
/*
* write_integrity_table():
*
* Writes a WIM integrity table (a list of SHA1 message digests of raw 10 MiB
* chunks of the file).
*
* This function can optionally re-use entries from an older integrity table.
* To do this, specify old_blob_table_end and old_table.
*
* On success, @wim->out_hdr.integrity_table_reshdr will be filled in with
* information about the integrity table that was written.
*
* @wim:
* WIMStruct for the WIM file. @wim->out_fd must be a seekable descriptor
* to the new WIM file, opened read-write, positioned at the location at
* which the integrity table is to be written.
*
* @new_blob_table_end:
* The offset of the byte directly following the blob table in the WIM
* being written.
*
* @old_blob_table_end:
* If nonzero, the offset of the byte directly following the old blob table
* in the WIM.
*
* @old_table
* Pointer to the old integrity table read into memory, or NULL if not
* specified.
*/
int
write_integrity_table(WIMStruct *wim,
off_t new_blob_table_end,
off_t old_blob_table_end,
struct integrity_table *old_table)
{
struct integrity_table *new_table;
int ret;
u32 new_table_size;
wimlib_assert(old_blob_table_end <= new_blob_table_end);
ret = calculate_integrity_table(&wim->out_fd, new_blob_table_end,
old_table, old_blob_table_end,
&new_table, wim->progfunc, wim->progctx);
if (ret)
return ret;
new_table_size = new_table->size;
new_table->size = (_force_attr u32)cpu_to_le32(new_table->size);
new_table->num_entries = (_force_attr u32)cpu_to_le32(new_table->num_entries);
new_table->chunk_size = (_force_attr u32)cpu_to_le32(new_table->chunk_size);
ret = write_wim_resource_from_buffer(new_table,
new_table_size,
false,
&wim->out_fd,
WIMLIB_COMPRESSION_TYPE_NONE,
0,
&wim->out_hdr.integrity_table_reshdr,
NULL,
0);
FREE(new_table);
return ret;
}
/*
* verify_integrity():
*
* Checks a WIM for consistency with the integrity table.
*
* @in_fd:
* File descriptor to the WIM file, opened for reading.
*
* @table:
* The integrity table for the WIM, read into memory.
*
* @bytes_to_check:
* Number of bytes in the WIM that need to be checked (offset of end of the
* blob table minus offset of end of the header).
*
* Returns:
* > 0 (WIMLIB_ERR_READ, WIMLIB_ERR_UNEXPECTED_END_OF_FILE) on error
* 0 (WIM_INTEGRITY_OK) if the integrity was checked successfully and there
* were no inconsistencies.
* -1 (WIM_INTEGRITY_NOT_OK) if the WIM failed the integrity check.
*/
static int
verify_integrity(struct filedes *in_fd, const tchar *filename,
const struct integrity_table *table,
u64 bytes_to_check,
wimlib_progress_func_t progfunc, void *progctx)
{
int ret;
u64 offset = WIM_HEADER_DISK_SIZE;
u8 sha1_md[SHA1_HASH_SIZE];
union wimlib_progress_info progress;
progress.integrity.total_bytes = bytes_to_check;
progress.integrity.total_chunks = table->num_entries;
progress.integrity.completed_chunks = 0;
progress.integrity.completed_bytes = 0;
progress.integrity.chunk_size = table->chunk_size;
progress.integrity.filename = filename;
ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY,
&progress, progctx);
if (ret)
return ret;
for (u32 i = 0; i < table->num_entries; i++) {
size_t this_chunk_size;
if (i == table->num_entries - 1)
this_chunk_size = MODULO_NONZERO(bytes_to_check,
table->chunk_size);
else
this_chunk_size = table->chunk_size;
ret = calculate_chunk_sha1(in_fd, this_chunk_size, offset, sha1_md);
if (ret)
return ret;
if (!hashes_equal(sha1_md, table->sha1sums[i]))
return WIM_INTEGRITY_NOT_OK;
offset += this_chunk_size;
progress.integrity.completed_chunks++;
progress.integrity.completed_bytes += this_chunk_size;
ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY,
&progress, progctx);
if (ret)
return ret;
}
return WIM_INTEGRITY_OK;
}
/*
* check_wim_integrity():
*
* Verifies the integrity of the WIM by making sure the SHA1 message digests of
* ~10 MiB chunks of the WIM match up with the values given in the integrity
* table.
*
* @wim:
* The WIM, opened for reading.
*
* Returns:
* > 0 (WIMLIB_ERR_INVALID_INTEGRITY_TABLE, WIMLIB_ERR_READ,
* WIMLIB_ERR_UNEXPECTED_END_OF_FILE) on error
* 0 (WIM_INTEGRITY_OK) if the integrity was checked successfully and there
* were no inconsistencies.
* -1 (WIM_INTEGRITY_NOT_OK) if the WIM failed the integrity check.
* -2 (WIM_INTEGRITY_NONEXISTENT) if the WIM contains no integrity
* information.
*/
int
check_wim_integrity(WIMStruct *wim)
{
int ret;
u64 bytes_to_check;
struct integrity_table *table;
u64 end_blob_table_offset;
if (!wim_has_integrity_table(wim))
return WIM_INTEGRITY_NONEXISTENT;
end_blob_table_offset = wim->hdr.blob_table_reshdr.offset_in_wim +
wim->hdr.blob_table_reshdr.size_in_wim;
if (end_blob_table_offset < WIM_HEADER_DISK_SIZE) {
ERROR("WIM blob table ends before WIM header ends!");
return WIMLIB_ERR_INVALID_INTEGRITY_TABLE;
}
bytes_to_check = end_blob_table_offset - WIM_HEADER_DISK_SIZE;
ret = read_integrity_table(wim, bytes_to_check, &table);
if (ret)
return ret;
ret = verify_integrity(&wim->in_fd, wim->filename, table,
bytes_to_check, wim->progfunc, wim->progctx);
FREE(table);
return ret;
}
wimlib-1.14.5/src/inode.c 0000644 0001750 0001750 00000040766 15137020663 012430 0 ustar 00e e /*
* inode.c
*
* Functions that operate on WIM inodes.
*
* See dentry.c for a description of the relationship between WIM dentries and
* WIM inodes.
*/
/*
* Copyright (C) 2012-2018 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include "wimlib/assert.h"
#include "wimlib/blob_table.h"
#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/error.h"
#include "wimlib/inode.h"
#include "wimlib/timestamp.h"
/*
* The 'stream_name' field of unnamed streams always points to this array, which
* is an empty UTF-16 string.
*/
const utf16lechar NO_STREAM_NAME[1];
/* Allocate a new inode and associate the specified dentry with it. */
struct wim_inode *
new_inode(struct wim_dentry *dentry, bool set_timestamps)
{
struct wim_inode *inode;
inode = CALLOC(1, sizeof(struct wim_inode));
if (!inode)
return NULL;
inode->i_security_id = -1;
/*inode->i_nlink = 0;*/
inode->i_rp_flags = WIM_RP_FLAG_NOT_FIXED;
INIT_HLIST_HEAD(&inode->i_alias_list);
inode->i_streams = inode->i_embedded_streams;
if (set_timestamps) {
u64 now = now_as_wim_timestamp();
inode->i_creation_time = now;
inode->i_last_access_time = now;
inode->i_last_write_time = now;
}
d_associate(dentry, inode);
return inode;
}
static inline void
destroy_stream(struct wim_inode_stream *strm)
{
if (strm->stream_name != NO_STREAM_NAME)
FREE(strm->stream_name);
}
static void
free_inode(struct wim_inode *inode)
{
for (unsigned i = 0; i < inode->i_num_streams; i++)
destroy_stream(&inode->i_streams[i]);
if (inode->i_streams != inode->i_embedded_streams)
FREE(inode->i_streams);
if (inode->i_extra)
FREE(inode->i_extra);
if (!hlist_unhashed(&inode->i_hlist_node))
hlist_del(&inode->i_hlist_node);
FREE(inode);
}
static inline void
free_inode_if_unneeded(struct wim_inode *inode)
{
if (inode->i_nlink)
return;
#ifdef WITH_FUSE
if (inode->i_num_opened_fds)
return;
#endif
free_inode(inode);
}
/* Associate a dentry with the specified inode. */
void
d_associate(struct wim_dentry *dentry, struct wim_inode *inode)
{
wimlib_assert(!dentry->d_inode);
hlist_add_head(&dentry->d_alias_node, &inode->i_alias_list);
dentry->d_inode = inode;
inode->i_nlink++;
}
/* Disassociate a dentry from its inode, if any. Following this, free the inode
* if it is no longer in use. */
void
d_disassociate(struct wim_dentry *dentry)
{
struct wim_inode *inode = dentry->d_inode;
if (unlikely(!inode))
return;
wimlib_assert(inode->i_nlink > 0);
hlist_del(&dentry->d_alias_node);
dentry->d_inode = NULL;
inode->i_nlink--;
free_inode_if_unneeded(inode);
}
#ifdef WITH_FUSE
void
inode_dec_num_opened_fds(struct wim_inode *inode)
{
wimlib_assert(inode->i_num_opened_fds > 0);
if (--inode->i_num_opened_fds == 0) {
/* The last file descriptor to this inode was closed. */
FREE(inode->i_fds);
inode->i_fds = NULL;
inode->i_num_allocated_fds = 0;
free_inode_if_unneeded(inode);
}
}
#endif
/*
* Retrieve a stream of an inode.
*
* @inode
* The inode from which the stream is desired
* @stream_type
* The type of the stream desired
* @stream_name
* The name of the stream desired as a null-terminated UTF-16LE string, or
* NO_STREAM_NAME if an unnamed stream is desired
*
* Returns a pointer to the stream if found, otherwise NULL.
*/
struct wim_inode_stream *
inode_get_stream(const struct wim_inode *inode, int stream_type,
const utf16lechar *stream_name)
{
if (stream_name == NO_STREAM_NAME) /* Optimization */
return inode_get_unnamed_stream(inode, stream_type);
for (unsigned i = 0; i < inode->i_num_streams; i++) {
struct wim_inode_stream *strm = &inode->i_streams[i];
if (strm->stream_type == stream_type &&
!cmp_utf16le_strings_z(strm->stream_name, stream_name,
default_ignore_case))
{
return strm;
}
}
return NULL;
}
/*
* This is equivalent to inode_get_stream(inode, stream_type, NO_STREAM_NAME),
* but this optimizes for the unnamed case by not doing full string comparisons.
*/
struct wim_inode_stream *
inode_get_unnamed_stream(const struct wim_inode *inode, int stream_type)
{
for (unsigned i = 0; i < inode->i_num_streams; i++) {
struct wim_inode_stream *strm = &inode->i_streams[i];
if (strm->stream_type == stream_type &&
strm->stream_name == NO_STREAM_NAME)
{
return strm;
}
}
return NULL;
}
static void
inode_set_stream_blob(struct wim_inode *inode, struct wim_inode_stream *strm,
struct blob_descriptor *new_blob)
{
strm->_stream_blob = new_blob;
strm->stream_resolved = 1;
if (new_blob)
new_blob->refcnt += inode->i_nlink;
}
static void
inode_unset_stream_blob(struct wim_inode *inode, struct wim_inode_stream *strm,
struct blob_table *blob_table)
{
struct blob_descriptor *old_blob;
old_blob = stream_blob(strm, blob_table);
if (old_blob)
blob_subtract_refcnt(old_blob, blob_table, inode->i_nlink);
strm->_stream_blob = NULL;
strm->stream_resolved = 1;
}
/*
* Replace the blob associated with the specified stream.
*
* @inode
* The inode containing @strm
* @strm
* The stream whose data needs to be replaced
* @new_blob
* The new blob descriptor to assign
* @blob_table
* Pointer to the blob table in which data blobs are being indexed
*/
void
inode_replace_stream_blob(struct wim_inode *inode,
struct wim_inode_stream *strm,
struct blob_descriptor *new_blob,
struct blob_table *blob_table)
{
inode_unset_stream_blob(inode, strm, blob_table);
inode_set_stream_blob(inode, strm, new_blob);
}
/*
* Add a new stream to the specified inode.
*
* @inode
* The inode to which to add the stream
* @stream_type
* The type of the stream being added
* @stream_name
* The name of the stream being added as a null-terminated UTF-16LE string,
* or NO_STREAM_NAME if the stream is unnamed
* @blob
* The blob that the new stream will initially reference, or NULL
*
* Returns a pointer to the new stream, or NULL with errno set if it could not
* be added.
*/
struct wim_inode_stream *
inode_add_stream(struct wim_inode *inode, int stream_type,
const utf16lechar *stream_name, struct blob_descriptor *blob)
{
if (inode->i_num_streams >= 0xFFFF) {
ERROR("Inode has too many streams! Path=\"%"TS"\"",
inode_any_full_path(inode));
errno = EFBIG;
return NULL;
}
struct wim_inode_stream *streams;
struct wim_inode_stream *new_strm;
if (inode->i_streams == inode->i_embedded_streams) {
if (inode->i_num_streams < ARRAY_LEN(inode->i_embedded_streams)) {
streams = inode->i_embedded_streams;
} else {
streams = MALLOC((inode->i_num_streams + 1) *
sizeof(inode->i_streams[0]));
if (!streams)
return NULL;
memcpy(streams, inode->i_streams,
(inode->i_num_streams *
sizeof(inode->i_streams[0])));
inode->i_streams = streams;
}
} else {
streams = REALLOC(inode->i_streams,
(inode->i_num_streams + 1) *
sizeof(inode->i_streams[0]));
if (!streams)
return NULL;
inode->i_streams = streams;
}
new_strm = &streams[inode->i_num_streams];
memset(new_strm, 0, sizeof(*new_strm));
new_strm->stream_type = stream_type;
if (!*stream_name) {
/* Unnamed stream */
new_strm->stream_name = (utf16lechar *)NO_STREAM_NAME;
} else {
/* Named stream */
new_strm->stream_name = utf16le_dup(stream_name);
if (!new_strm->stream_name)
return NULL;
}
new_strm->stream_id = inode->i_next_stream_id++;
inode_set_stream_blob(inode, new_strm, blob);
inode->i_num_streams++;
return new_strm;
}
/*
* Replace the data of the specified stream.
*
* @inode
* The inode containing @strm
* @strm
* The stream whose data needs to be replaced
* @data
* The buffer of data to assign to the stream
* @size
* Size of the @data buffer, in bytes
* @blob_table
* Pointer to the blob table in which data blobs are being indexed
*
* Returns true if successful; false with errno set if unsuccessful.
*/
bool
inode_replace_stream_data(struct wim_inode *inode,
struct wim_inode_stream *strm,
const void *data, size_t size,
struct blob_table *blob_table)
{
struct blob_descriptor *new_blob = NULL;
if (size) {
new_blob = new_blob_from_data_buffer(data, size, blob_table);
if (!new_blob)
return false;
}
inode_replace_stream_blob(inode, strm, new_blob, blob_table);
return true;
}
/*
* Add a new stream to the specified inode and assign it the specified data.
*
* @inode
* The inode to which to add the stream
* @stream_type
* The type of the stream being added
* @stream_name
* The name of the stream being added as a null-terminated UTF-16LE string,
* or NO_STREAM_NAME if the stream is unnamed
* @data
* The buffer of data to assign to the new stream
* @size
* Size of the @data buffer, in bytes
* @blob_table
* Pointer to the blob table in which data blobs are being indexed
*
* Returns true if successful; false with errno set if unsuccessful.
*/
bool
inode_add_stream_with_data(struct wim_inode *inode,
int stream_type, const utf16lechar *stream_name,
const void *data, size_t size,
struct blob_table *blob_table)
{
struct wim_inode_stream *strm;
struct blob_descriptor *blob = NULL;
strm = inode_add_stream(inode, stream_type, stream_name, NULL);
if (!strm)
return false;
if (size) {
blob = new_blob_from_data_buffer(data, size, blob_table);
if (unlikely(!blob)) {
inode_remove_stream(inode, strm, blob_table);
return false;
}
}
inode_set_stream_blob(inode, strm, blob);
return true;
}
/*
* Remove a stream from the specified inode.
*
* This handles releasing the references to the blob descriptor, if any.
*/
void
inode_remove_stream(struct wim_inode *inode, struct wim_inode_stream *strm,
struct blob_table *blob_table)
{
unsigned idx = strm - inode->i_streams;
wimlib_assert(idx < inode->i_num_streams);
inode_unset_stream_blob(inode, strm, blob_table);
destroy_stream(strm);
memmove(strm, strm + 1,
(inode->i_num_streams - idx - 1) * sizeof(inode->i_streams[0]));
inode->i_num_streams--;
}
/* Returns true iff the specified inode has at least one named data stream. */
bool
inode_has_named_data_stream(const struct wim_inode *inode)
{
for (unsigned i = 0; i < inode->i_num_streams; i++)
if (stream_is_named_data_stream(&inode->i_streams[i]))
return true;
return false;
}
/*
* Resolve an inode's streams.
*
* For each stream, this replaces the SHA-1 message digest of the blob data with
* a pointer to the 'struct blob_descriptor' for the blob. Blob descriptors are
* looked up in @table.
*
* If @force is %false:
* If any of the needed blobs do not exist in @table, return
* WIMLIB_ERR_RESOURCE_NOT_FOUND.
* If @force is %true:
* If any of the needed blobs do not exist in @table, allocate new blob
* descriptors for them and insert them into @table. This does not, of
* course, cause the data of these blobs to magically exist, but this is
* needed by the code for extraction from a pipe.
*
* Returns 0 on success; WIMLIB_ERR_NOMEM if out of memory; or
* WIMLIB_ERR_RESOURCE_NOT_FOUND if @force is %false and at least one blob
* referenced by the inode was missing.
*/
int
inode_resolve_streams(struct wim_inode *inode, struct blob_table *table,
bool force)
{
for (unsigned i = 0; i < inode->i_num_streams; i++) {
struct wim_inode_stream *strm = &inode->i_streams[i];
if (strm->stream_resolved)
continue;
const u8 *hash = stream_hash(strm);
struct blob_descriptor *blob = NULL;
if (!is_zero_hash(hash)) {
blob = lookup_blob(table, hash);
if (!blob) {
if (!force)
return blob_not_found_error(inode, hash);
blob = new_blob_descriptor();
if (!blob)
return WIMLIB_ERR_NOMEM;
copy_hash(blob->hash, hash);
blob_table_insert(table, blob);
}
}
strm->_stream_blob = blob;
strm->stream_resolved = 1;
}
return 0;
}
int
blob_not_found_error(const struct wim_inode *inode, const u8 *hash)
{
if (wimlib_print_errors) {
tchar hashstr[SHA1_HASH_STRING_LEN];
sprint_hash(hash, hashstr);
ERROR("\"%"TS"\": blob not found\n"
" SHA-1 message digest of missing blob:\n"
" %"TS"",
inode_any_full_path(inode), hashstr);
}
return WIMLIB_ERR_RESOURCE_NOT_FOUND;
}
/*
* Return the blob descriptor for the specified stream, or NULL if the stream is
* empty or its blob is not available in @table.
*/
struct blob_descriptor *
stream_blob(const struct wim_inode_stream *strm, const struct blob_table *table)
{
if (strm->stream_resolved)
return strm->_stream_blob;
else
return lookup_blob(table, strm->_stream_hash);
}
/*
* Return the SHA-1 message digest of the data of the specified stream, or a
* void SHA-1 of all zeroes if the specified stream is empty, or NULL if the
* specified stream is unhashed. (Most callers ensure the stream cannot be
* unhashed.)
*/
const u8 *
stream_hash(const struct wim_inode_stream *strm)
{
if (!strm->stream_resolved)
return strm->_stream_hash;
if (!strm->_stream_blob)
return zero_hash;
if (strm->_stream_blob->unhashed)
return NULL;
return strm->_stream_blob->hash;
}
/*
* Return the blob descriptor for the unnamed data stream of the inode, or NULL
* if the inode does not have an unnamed data stream, the inode's unnamed data
* stream is empty, or the blob for the inode's unnamed data stream is not
* available in @blob_table.
*/
struct blob_descriptor *
inode_get_blob_for_unnamed_data_stream(const struct wim_inode *inode,
const struct blob_table *blob_table)
{
const struct wim_inode_stream *strm;
strm = inode_get_unnamed_data_stream(inode);
if (!strm)
return NULL;
return stream_blob(strm, blob_table);
}
/* Like inode_get_blob_for_unnamed_data_stream(), but assumes the unnamed data
* stream is resolved. */
struct blob_descriptor *
inode_get_blob_for_unnamed_data_stream_resolved(const struct wim_inode *inode)
{
const struct wim_inode_stream *strm;
strm = inode_get_unnamed_data_stream(inode);
if (!strm)
return NULL;
return stream_blob_resolved(strm);
}
/*
* Return the SHA-1 message digest of the unnamed data stream of the inode, or a
* void SHA-1 of all zeroes if the inode does not have an unnamed data stream or
* if the inode's unnamed data stream is empty, or NULL if the inode's unnamed
* data stream is unhashed. (Most callers ensure the stream cannot be
* unhashed.)
*/
const u8 *
inode_get_hash_of_unnamed_data_stream(const struct wim_inode *inode)
{
const struct wim_inode_stream *strm;
strm = inode_get_unnamed_data_stream(inode);
if (!strm)
return zero_hash;
return stream_hash(strm);
}
/* Acquire another reference to each blob referenced by this inode. This is
* necessary when creating a hard link to this inode.
*
* All streams of the inode must be resolved. */
void
inode_ref_blobs(struct wim_inode *inode)
{
for (unsigned i = 0; i < inode->i_num_streams; i++) {
struct blob_descriptor *blob;
blob = stream_blob_resolved(&inode->i_streams[i]);
if (blob)
blob->refcnt++;
}
}
/* Release a reference to each blob referenced by this inode. This is necessary
* when deleting a hard link to this inode. */
void
inode_unref_blobs(struct wim_inode *inode, struct blob_table *blob_table)
{
for (unsigned i = 0; i < inode->i_num_streams; i++) {
struct blob_descriptor *blob;
blob = stream_blob(&inode->i_streams[i], blob_table);
if (blob)
blob_decrement_refcnt(blob, blob_table);
}
}
/*
* Given a blob descriptor, return a pointer to the pointer contained in the
* stream that references it.
*
* This is only possible for "unhashed" blobs, which are guaranteed to have only
* one referencing stream, and that reference is guaranteed to be in a resolved
* stream. (It can't be in an unresolved stream, since that would imply the
* hash is known!)
*/
struct blob_descriptor **
retrieve_pointer_to_unhashed_blob(struct blob_descriptor *blob)
{
wimlib_assert(blob->unhashed);
struct wim_inode *inode = blob->back_inode;
for (unsigned i = 0; i < inode->i_num_streams; i++) {
if (inode->i_streams[i].stream_id == blob->back_stream_id) {
wimlib_assert(inode->i_streams[i]._stream_blob == blob);
return &inode->i_streams[i]._stream_blob;
}
}
wimlib_assert(0);
return NULL;
}
wimlib-1.14.5/src/unix_apply.c 0000644 0001750 0001750 00000065101 15137020663 013510 0 ustar 00e e /*
* unix_apply.c - Code to apply files from a WIM image on UNIX.
*/
/*
* Copyright (C) 2012-2018 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#include
#include
#include
#ifdef HAVE_SYS_XATTR_H
# include
#endif
#include
#include "wimlib/apply.h"
#include "wimlib/assert.h"
#include "wimlib/blob_table.h"
#include "wimlib/dentry.h"
#include "wimlib/error.h"
#include "wimlib/file_io.h"
#include "wimlib/reparse.h"
#include "wimlib/timestamp.h"
#include "wimlib/unix_data.h"
#include "wimlib/xattr.h"
/* We don't require O_NOFOLLOW, but the advantage of having it is that if we
* need to extract a file to a location at which there exists a symbolic link,
* open(..., O_NOFOLLOW | ...) recognizes the symbolic link rather than
* following it and creating the file somewhere else. (Equivalent to
* FILE_OPEN_REPARSE_POINT on Windows.) */
#ifndef O_NOFOLLOW
# define O_NOFOLLOW 0
#endif
static int
unix_get_supported_features(const char *target,
struct wim_features *supported_features)
{
supported_features->sparse_files = 1;
supported_features->hard_links = 1;
supported_features->symlink_reparse_points = 1;
supported_features->unix_data = 1;
supported_features->timestamps = 1;
supported_features->case_sensitive_filenames = 1;
#ifdef HAVE_LINUX_XATTR_SUPPORT
supported_features->xattrs = 1;
#endif
return 0;
}
#define NUM_PATHBUFS 2 /* We need 2 when creating hard links */
struct unix_apply_ctx {
/* Extract flags, the pointer to the WIMStruct, etc. */
struct apply_ctx common;
/* Buffers for building extraction paths (allocated). */
char *pathbufs[NUM_PATHBUFS];
/* Index of next pathbuf to use */
unsigned which_pathbuf;
/* Currently open file descriptors for extraction */
struct filedes open_fds[MAX_OPEN_FILES];
/* Number of currently open file descriptors in open_fds, starting from
* the beginning of the array. */
unsigned num_open_fds;
/* For each currently open file, whether we're writing to it in "sparse"
* mode or not. */
bool is_sparse_file[MAX_OPEN_FILES];
/* Whether is_sparse_file[] is true for any currently open file */
bool any_sparse_files;
/* Buffer for reading reparse point data into memory */
u8 reparse_data[REPARSE_DATA_MAX_SIZE];
/* Pointer to the next byte in @reparse_data to fill */
u8 *reparse_ptr;
/* Absolute path to the target directory (allocated buffer). Only set
* if needed for absolute symbolic link fixups. */
char *target_abspath;
/* Number of characters in target_abspath. */
size_t target_abspath_nchars;
/* Number of special files we couldn't create due to EPERM */
unsigned long num_special_files_ignored;
};
/* Returns the number of characters needed to represent the path to the
* specified @dentry when extracted, not including the null terminator or the
* path to the target directory itself. */
static size_t
unix_dentry_path_length(const struct wim_dentry *dentry)
{
size_t len = 0;
const struct wim_dentry *d;
d = dentry;
do {
len += d->d_extraction_name_nchars + 1;
d = d->d_parent;
} while (!dentry_is_root(d) && will_extract_dentry(d));
return len;
}
/* Returns the maximum number of characters needed to represent the path to any
* dentry in @dentry_list when extracted, including the null terminator and the
* path to the target directory itself. */
static size_t
unix_compute_path_max(const struct list_head *dentry_list,
const struct unix_apply_ctx *ctx)
{
size_t max = 0;
size_t len;
const struct wim_dentry *dentry;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
len = unix_dentry_path_length(dentry);
if (len > max)
max = len;
}
/* Account for target and null terminator. */
return ctx->common.target_nchars + max + 1;
}
/* Builds and returns the filesystem path to which to extract @dentry.
* This cycles through NUM_PATHBUFS different buffers. */
static const char *
unix_build_extraction_path(const struct wim_dentry *dentry,
struct unix_apply_ctx *ctx)
{
char *pathbuf;
char *p;
const struct wim_dentry *d;
pathbuf = ctx->pathbufs[ctx->which_pathbuf];
ctx->which_pathbuf = (ctx->which_pathbuf + 1) % NUM_PATHBUFS;
p = &pathbuf[ctx->common.target_nchars +
unix_dentry_path_length(dentry)];
*p = '\0';
d = dentry;
do {
p -= d->d_extraction_name_nchars;
if (d->d_extraction_name_nchars)
memcpy(p, d->d_extraction_name,
d->d_extraction_name_nchars);
*--p = '/';
d = d->d_parent;
} while (!dentry_is_root(d) && will_extract_dentry(d));
return pathbuf;
}
/* This causes the next call to unix_build_extraction_path() to use the same
* path buffer as the previous call. */
static void
unix_reuse_pathbuf(struct unix_apply_ctx *ctx)
{
ctx->which_pathbuf = (ctx->which_pathbuf - 1) % NUM_PATHBUFS;
}
/* Builds and returns the filesystem path to which to extract an unspecified
* alias of the @inode. This cycles through NUM_PATHBUFS different buffers. */
static const char *
unix_build_inode_extraction_path(const struct wim_inode *inode,
struct unix_apply_ctx *ctx)
{
return unix_build_extraction_path(inode_first_extraction_dentry(inode), ctx);
}
/* Should the specified file be extracted as a directory on UNIX? We extract
* the file as a directory if FILE_ATTRIBUTE_DIRECTORY is set and the file does
* not have a symlink or junction reparse point. It *may* have a different type
* of reparse point. */
static inline bool
should_extract_as_directory(const struct wim_inode *inode)
{
return (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) &&
!inode_is_symlink(inode);
}
/* Sets the timestamps on a file being extracted.
*
* Either @fd or @path must be specified (not -1 and not NULL, respectively).
*/
static int
unix_set_timestamps(int fd, const char *path, u64 atime, u64 mtime)
{
{
struct timespec times[2];
times[0] = wim_timestamp_to_timespec(atime);
times[1] = wim_timestamp_to_timespec(mtime);
errno = ENOSYS;
#ifdef HAVE_FUTIMENS
if (fd >= 0 && !futimens(fd, times))
return 0;
#endif
#ifdef HAVE_UTIMENSAT
if (fd < 0 && !utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW))
return 0;
#endif
if (errno != ENOSYS)
return WIMLIB_ERR_SET_TIMESTAMPS;
}
{
struct timeval times[2];
times[0] = wim_timestamp_to_timeval(atime);
times[1] = wim_timestamp_to_timeval(mtime);
if (fd >= 0 && !futimes(fd, times))
return 0;
if (fd < 0 && !lutimes(path, times))
return 0;
return WIMLIB_ERR_SET_TIMESTAMPS;
}
}
static int
unix_set_owner_and_group(int fd, const char *path, uid_t uid, gid_t gid)
{
if (fd >= 0 && !fchown(fd, uid, gid))
return 0;
if (fd < 0 && !lchown(path, uid, gid))
return 0;
return WIMLIB_ERR_SET_SECURITY;
}
static int
unix_set_mode(int fd, const char *path, mode_t mode)
{
if (fd >= 0 && !fchmod(fd, mode))
return 0;
if (fd < 0 && !chmod(path, mode))
return 0;
return WIMLIB_ERR_SET_SECURITY;
}
#ifdef HAVE_LINUX_XATTR_SUPPORT
/* Apply extended attributes to a file */
static int
apply_linux_xattrs(int fd, const struct wim_inode *inode,
const char *path, struct unix_apply_ctx *ctx,
const void *entries, size_t entries_size, bool is_old_format)
{
const void * const entries_end = entries + entries_size;
char name[WIM_XATTR_NAME_MAX + 1];
for (const void *entry = entries;
entry < entries_end;
entry = is_old_format ? (const void *)old_xattr_entry_next(entry) :
(const void *)xattr_entry_next(entry))
{
bool valid;
u16 name_len;
const void *value;
u32 value_len;
int res;
if (is_old_format) {
valid = old_valid_xattr_entry(entry,
entries_end - entry);
} else {
valid = valid_xattr_entry(entry, entries_end - entry);
}
if (!valid) {
if (!path) {
path = unix_build_inode_extraction_path(inode,
ctx);
}
ERROR("\"%s\": extended attribute is corrupt or unsupported",
path);
return WIMLIB_ERR_INVALID_XATTR;
}
if (is_old_format) {
const struct wimlib_xattr_entry_old *e = entry;
name_len = le16_to_cpu(e->name_len);
memcpy(name, e->name, name_len);
value = e->name + name_len;
value_len = le32_to_cpu(e->value_len);
} else {
const struct wim_xattr_entry *e = entry;
name_len = e->name_len;
memcpy(name, e->name, name_len);
value = e->name + name_len + 1;
value_len = le16_to_cpu(e->value_len);
}
name[name_len] = '\0';
if (fd >= 0)
res = fsetxattr(fd, name, value, value_len, 0);
else
res = lsetxattr(path, name, value, value_len, 0);
if (unlikely(res != 0)) {
if (!path) {
path = unix_build_inode_extraction_path(inode,
ctx);
}
if (is_linux_security_xattr(name) &&
(ctx->common.extract_flags &
WIMLIB_EXTRACT_FLAG_STRICT_ACLS))
{
ERROR_WITH_ERRNO("\"%s\": unable to set extended attribute \"%s\"",
path, name);
return WIMLIB_ERR_SET_XATTR;
}
WARNING_WITH_ERRNO("\"%s\": unable to set extended attribute \"%s\"",
path, name);
}
}
return 0;
}
#endif /* HAVE_LINUX_XATTR_SUPPORT */
/*
* Apply UNIX-specific metadata to a file if available. This includes standard
* UNIX permissions (uid, gid, and mode) and possibly extended attributes too.
*
* Note that some xattrs which grant privileges, e.g. security.capability, are
* cleared by Linux on chown(), even when running as root. Also, when running
* as non-root, if we need to chmod() the file to readonly, we can't do that
* before setting xattrs because setxattr() requires write permission. These
* restrictions result in the following ordering which we follow: chown(),
* setxattr(), then chmod().
*
* N.B. the file may be specified by either 'fd' (for regular files) or 'path',
* and it may be a symlink. For symlinks we need lchown() and lsetxattr() but
* need to skip the chmod(), since mode bits are not meaningful for symlinks.
*/
static int
apply_unix_metadata(int fd, const struct wim_inode *inode,
const char *path, struct unix_apply_ctx *ctx)
{
bool have_dat;
struct wimlib_unix_data dat;
#ifdef HAVE_LINUX_XATTR_SUPPORT
const void *entries;
u32 entries_size;
bool is_old_format;
#endif
int ret;
have_dat = inode_get_unix_data(inode, &dat);
if (have_dat) {
ret = unix_set_owner_and_group(fd, path, dat.uid, dat.gid);
if (ret) {
if (!path)
path = unix_build_inode_extraction_path(inode, ctx);
if (ctx->common.extract_flags &
WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
{
ERROR_WITH_ERRNO("\"%s\": unable to set uid=%"PRIu32" and gid=%"PRIu32,
path, dat.uid, dat.gid);
return ret;
}
WARNING_WITH_ERRNO("\"%s\": unable to set uid=%"PRIu32" and gid=%"PRIu32,
path, dat.uid, dat.gid);
}
}
#ifdef HAVE_LINUX_XATTR_SUPPORT
entries = inode_get_linux_xattrs(inode, &entries_size, &is_old_format);
if (entries) {
ret = apply_linux_xattrs(fd, inode, path, ctx,
entries, entries_size, is_old_format);
if (ret)
return ret;
}
#endif
if (have_dat && !inode_is_symlink(inode)) {
ret = unix_set_mode(fd, path, dat.mode);
if (ret) {
if (!path)
path = unix_build_inode_extraction_path(inode, ctx);
if (ctx->common.extract_flags &
WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
{
ERROR_WITH_ERRNO("\"%s\": unable to set mode=0%"PRIo32,
path, dat.mode);
return ret;
}
WARNING_WITH_ERRNO("\"%s\": unable to set mode=0%"PRIo32,
path, dat.mode);
}
}
return 0;
}
/*
* Set metadata on an extracted file.
*
* @fd is an open file descriptor to the extracted file, or -1. @path is the
* path to the extracted file, or NULL. If valid, this function uses @fd.
* Otherwise, if valid, it uses @path. Otherwise, it calculates the path to one
* alias of the extracted file and uses it.
*/
static int
unix_set_metadata(int fd, const struct wim_inode *inode,
const char *path, struct unix_apply_ctx *ctx)
{
int ret;
if (fd < 0 && !path)
path = unix_build_inode_extraction_path(inode, ctx);
if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) {
ret = apply_unix_metadata(fd, inode, path, ctx);
if (ret)
return ret;
}
ret = unix_set_timestamps(fd, path, inode->i_last_access_time,
inode->i_last_write_time);
if (ret) {
if (!path)
path = unix_build_inode_extraction_path(inode, ctx);
if (ctx->common.extract_flags &
WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS)
{
ERROR_WITH_ERRNO("\"%s\": unable to set timestamps", path);
return ret;
}
WARNING_WITH_ERRNO("\"%s\": unable to set timestamps", path);
}
return 0;
}
/* Extract all needed aliases of the @inode, where one alias, corresponding to
* @first_dentry, has already been extracted to @first_path. */
static int
unix_create_hardlinks(const struct wim_inode *inode,
const struct wim_dentry *first_dentry,
const char *first_path, struct unix_apply_ctx *ctx)
{
const struct wim_dentry *dentry;
const char *newpath;
inode_for_each_extraction_alias(dentry, inode) {
if (dentry == first_dentry)
continue;
newpath = unix_build_extraction_path(dentry, ctx);
retry_link:
if (link(first_path, newpath)) {
if (errno == EEXIST && !unlink(newpath))
goto retry_link;
ERROR_WITH_ERRNO("Can't create hard link "
"\"%s\" => \"%s\"", newpath, first_path);
return WIMLIB_ERR_LINK;
}
unix_reuse_pathbuf(ctx);
}
return 0;
}
/* If @dentry represents a directory, create it. */
static int
unix_create_if_directory(const struct wim_dentry *dentry,
struct unix_apply_ctx *ctx)
{
const char *path;
struct stat stbuf;
if (!should_extract_as_directory(dentry->d_inode))
return 0;
path = unix_build_extraction_path(dentry, ctx);
if (mkdir(path, 0755) &&
/* It's okay if the path already exists, as long as it's a
* directory. */
!(errno == EEXIST && !lstat(path, &stbuf) && S_ISDIR(stbuf.st_mode)))
{
ERROR_WITH_ERRNO("Can't create directory \"%s\"", path);
return WIMLIB_ERR_MKDIR;
}
return report_file_created(&ctx->common);
}
/* If @dentry represents an empty regular file or a special file, create it, set
* its metadata, and create any needed hard links. */
static int
unix_extract_if_empty_file(const struct wim_dentry *dentry,
struct unix_apply_ctx *ctx)
{
const struct wim_inode *inode;
struct wimlib_unix_data unix_data;
const char *path;
int ret;
inode = dentry->d_inode;
/* Extract all aliases only when the "first" comes up. */
if (dentry != inode_first_extraction_dentry(inode))
return 0;
/* Is this a directory, a symbolic link, or any type of nonempty file?
*/
if (should_extract_as_directory(inode) || inode_is_symlink(inode) ||
inode_get_blob_for_unnamed_data_stream_resolved(inode))
return 0;
/* Recognize special files in UNIX_DATA mode */
if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) &&
inode_get_unix_data(inode, &unix_data) &&
!S_ISREG(unix_data.mode))
{
path = unix_build_extraction_path(dentry, ctx);
retry_mknod:
if (mknod(path, unix_data.mode, unix_data.rdev)) {
if (errno == EPERM) {
WARNING_WITH_ERRNO("Can't create special "
"file \"%s\"", path);
ctx->num_special_files_ignored++;
return 0;
}
if (errno == EEXIST && !unlink(path))
goto retry_mknod;
ERROR_WITH_ERRNO("Can't create special file \"%s\"",
path);
return WIMLIB_ERR_MKNOD;
}
/* On special files, we can set timestamps immediately because
* we don't need to write any data to them. */
ret = unix_set_metadata(-1, inode, path, ctx);
} else {
int fd;
path = unix_build_extraction_path(dentry, ctx);
retry_create:
fd = open(path, O_EXCL | O_CREAT | O_WRONLY | O_NOFOLLOW, 0644);
if (fd < 0) {
if (errno == EEXIST && !unlink(path))
goto retry_create;
ERROR_WITH_ERRNO("Can't create regular file \"%s\"", path);
return WIMLIB_ERR_OPEN;
}
/* On empty files, we can set timestamps immediately because we
* don't need to write any data to them. */
ret = unix_set_metadata(fd, inode, path, ctx);
if (close(fd) && !ret) {
ERROR_WITH_ERRNO("Error closing \"%s\"", path);
ret = WIMLIB_ERR_WRITE;
}
}
if (ret)
return ret;
ret = unix_create_hardlinks(inode, dentry, path, ctx);
if (ret)
return ret;
return report_file_created(&ctx->common);
}
static int
unix_create_dirs_and_empty_files(const struct list_head *dentry_list,
struct unix_apply_ctx *ctx)
{
const struct wim_dentry *dentry;
int ret;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
ret = unix_create_if_directory(dentry, ctx);
if (ret)
return ret;
}
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
ret = unix_extract_if_empty_file(dentry, ctx);
if (ret)
return ret;
}
return 0;
}
static void
unix_count_dentries(const struct list_head *dentry_list,
u64 *dir_count_ret, u64 *empty_file_count_ret)
{
const struct wim_dentry *dentry;
u64 dir_count = 0;
u64 empty_file_count = 0;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
const struct wim_inode *inode = dentry->d_inode;
if (should_extract_as_directory(inode))
dir_count++;
else if ((dentry == inode_first_extraction_dentry(inode)) &&
!inode_is_symlink(inode) &&
!inode_get_blob_for_unnamed_data_stream_resolved(inode))
empty_file_count++;
}
*dir_count_ret = dir_count;
*empty_file_count_ret = empty_file_count;
}
static int
unix_create_symlink(const struct wim_inode *inode, const char *path,
size_t rpdatalen, struct unix_apply_ctx *ctx)
{
char target[REPARSE_POINT_MAX_SIZE];
struct blob_descriptor blob_override;
int ret;
blob_set_is_located_in_attached_buffer(&blob_override,
ctx->reparse_data, rpdatalen);
ret = wim_inode_readlink(inode, target, sizeof(target) - 1,
&blob_override,
ctx->target_abspath,
ctx->target_abspath_nchars);
if (unlikely(ret < 0)) {
errno = -ret;
return WIMLIB_ERR_READLINK;
}
target[ret] = '\0';
retry_symlink:
if (symlink(target, path)) {
if (errno == EEXIST && !unlink(path))
goto retry_symlink;
return WIMLIB_ERR_LINK;
}
return 0;
}
static void
unix_cleanup_open_fds(struct unix_apply_ctx *ctx, unsigned offset)
{
for (unsigned i = offset; i < ctx->num_open_fds; i++)
filedes_close(&ctx->open_fds[i]);
ctx->num_open_fds = 0;
ctx->any_sparse_files = false;
}
static int
unix_begin_extract_blob_instance(const struct blob_descriptor *blob,
const struct wim_inode *inode,
const struct wim_inode_stream *strm,
struct unix_apply_ctx *ctx)
{
const struct wim_dentry *first_dentry;
const char *first_path;
int fd;
if (unlikely(strm->stream_type == STREAM_TYPE_REPARSE_POINT)) {
/* On UNIX, symbolic links must be created with symlink(), which
* requires that the full link target be available. */
if (blob->size > REPARSE_DATA_MAX_SIZE) {
ERROR_WITH_ERRNO("Reparse data of \"%s\" has size "
"%"PRIu64" bytes (exceeds %u bytes)",
inode_any_full_path(inode),
blob->size, REPARSE_DATA_MAX_SIZE);
return WIMLIB_ERR_INVALID_REPARSE_DATA;
}
ctx->reparse_ptr = ctx->reparse_data;
return 0;
}
wimlib_assert(stream_is_unnamed_data_stream(strm));
/* Unnamed data stream of "regular" file */
/* This should be ensured by extract_blob_list() */
wimlib_assert(ctx->num_open_fds < MAX_OPEN_FILES);
first_dentry = inode_first_extraction_dentry(inode);
first_path = unix_build_extraction_path(first_dentry, ctx);
retry_create:
fd = open(first_path, O_EXCL | O_CREAT | O_WRONLY | O_NOFOLLOW, 0644);
if (fd < 0) {
if (errno == EEXIST && !unlink(first_path))
goto retry_create;
ERROR_WITH_ERRNO("Can't create regular file \"%s\"", first_path);
return WIMLIB_ERR_OPEN;
}
if (inode->i_attributes & FILE_ATTRIBUTE_SPARSE_FILE) {
ctx->is_sparse_file[ctx->num_open_fds] = true;
ctx->any_sparse_files = true;
} else {
ctx->is_sparse_file[ctx->num_open_fds] = false;
#ifdef HAVE_POSIX_FALLOCATE
posix_fallocate(fd, 0, blob->size);
#endif
}
filedes_init(&ctx->open_fds[ctx->num_open_fds++], fd);
return unix_create_hardlinks(inode, first_dentry, first_path, ctx);
}
/* Called when starting to read a blob for extraction */
static int
unix_begin_extract_blob(struct blob_descriptor *blob, void *_ctx)
{
struct unix_apply_ctx *ctx = _ctx;
const struct blob_extraction_target *targets = blob_extraction_targets(blob);
for (u32 i = 0; i < blob->out_refcnt; i++) {
int ret = unix_begin_extract_blob_instance(blob,
targets[i].inode,
targets[i].stream,
ctx);
if (ret) {
ctx->reparse_ptr = NULL;
unix_cleanup_open_fds(ctx, 0);
return ret;
}
}
return 0;
}
/* Called when the next chunk of a blob has been read for extraction */
static int
unix_extract_chunk(const struct blob_descriptor *blob, u64 offset,
const void *chunk, size_t size, void *_ctx)
{
struct unix_apply_ctx *ctx = _ctx;
const void * const end = chunk + size;
const void *p;
bool zeroes;
size_t len;
unsigned i;
int ret;
/*
* For sparse files, only write nonzero regions. This lets the
* filesystem use holes to represent zero regions.
*/
for (p = chunk; p != end; p += len, offset += len) {
zeroes = maybe_detect_sparse_region(p, end - p, &len,
ctx->any_sparse_files);
for (i = 0; i < ctx->num_open_fds; i++) {
if (!zeroes || !ctx->is_sparse_file[i]) {
ret = full_pwrite(&ctx->open_fds[i],
p, len, offset);
if (ret)
goto err;
}
}
}
if (ctx->reparse_ptr)
ctx->reparse_ptr = mempcpy(ctx->reparse_ptr, chunk, size);
return 0;
err:
ERROR_WITH_ERRNO("Error writing data to filesystem");
return ret;
}
/* Called when a blob has been fully read for extraction */
static int
unix_end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx)
{
struct unix_apply_ctx *ctx = _ctx;
int ret;
unsigned j;
const struct blob_extraction_target *targets = blob_extraction_targets(blob);
ctx->reparse_ptr = NULL;
if (status) {
unix_cleanup_open_fds(ctx, 0);
return status;
}
j = 0;
ret = 0;
for (u32 i = 0; i < blob->out_refcnt; i++) {
struct wim_inode *inode = targets[i].inode;
if (inode_is_symlink(inode)) {
/* We finally have the symlink data, so we can create
* the symlink. */
const char *path;
path = unix_build_inode_extraction_path(inode, ctx);
ret = unix_create_symlink(inode, path, blob->size, ctx);
if (ret) {
ERROR_WITH_ERRNO("Can't create symbolic link "
"\"%s\"", path);
break;
}
ret = unix_set_metadata(-1, inode, path, ctx);
if (ret)
break;
} else {
struct filedes *fd = &ctx->open_fds[j];
/* If the file is sparse, extend it to its final size. */
if (ctx->is_sparse_file[j] && ftruncate(fd->fd, blob->size)) {
ERROR_WITH_ERRNO("Error extending \"%s\" to final size",
unix_build_inode_extraction_path(inode, ctx));
ret = WIMLIB_ERR_WRITE;
break;
}
/* Set metadata on regular file just before closing. */
ret = unix_set_metadata(fd->fd, inode, NULL, ctx);
if (ret)
break;
if (filedes_close(fd)) {
ERROR_WITH_ERRNO("Error closing \"%s\"",
unix_build_inode_extraction_path(inode, ctx));
ret = WIMLIB_ERR_WRITE;
break;
}
j++;
}
}
unix_cleanup_open_fds(ctx, j);
return ret;
}
static int
unix_set_dir_metadata(struct list_head *dentry_list, struct unix_apply_ctx *ctx)
{
const struct wim_dentry *dentry;
int ret;
list_for_each_entry_reverse(dentry, dentry_list, d_extraction_list_node) {
if (should_extract_as_directory(dentry->d_inode)) {
ret = unix_set_metadata(-1, dentry->d_inode, NULL, ctx);
if (ret)
return ret;
ret = report_file_metadata_applied(&ctx->common);
if (ret)
return ret;
}
}
return 0;
}
static int
unix_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
{
int ret;
struct unix_apply_ctx *ctx = (struct unix_apply_ctx *)_ctx;
size_t path_max;
u64 dir_count;
u64 empty_file_count;
/* Compute the maximum path length that will be needed, then allocate
* some path buffers. */
path_max = unix_compute_path_max(dentry_list, ctx);
for (unsigned i = 0; i < NUM_PATHBUFS; i++) {
ctx->pathbufs[i] = MALLOC(path_max);
if (!ctx->pathbufs[i]) {
ret = WIMLIB_ERR_NOMEM;
goto out;
}
/* Pre-fill the target in each path buffer. We'll just append
* the rest of the paths after this. */
memcpy(ctx->pathbufs[i],
ctx->common.target, ctx->common.target_nchars);
}
/* Extract directories and empty regular files. Directories are needed
* because we can't extract any other files until their directories
* exist. Empty files are needed because they don't have
* representatives in the blob list. */
unix_count_dentries(dentry_list, &dir_count, &empty_file_count);
ret = start_file_structure_phase(&ctx->common, dir_count + empty_file_count);
if (ret)
goto out;
ret = unix_create_dirs_and_empty_files(dentry_list, ctx);
if (ret)
goto out;
ret = end_file_structure_phase(&ctx->common);
if (ret)
goto out;
/* Get full path to target if needed for absolute symlink fixups. */
if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_RPFIX) &&
ctx->common.required_features.symlink_reparse_points)
{
ctx->target_abspath = realpath(ctx->common.target, NULL);
if (!ctx->target_abspath) {
ret = WIMLIB_ERR_NOMEM;
goto out;
}
ctx->target_abspath_nchars = strlen(ctx->target_abspath);
}
/* Extract nonempty regular files and symbolic links. */
struct read_blob_callbacks cbs = {
.begin_blob = unix_begin_extract_blob,
.continue_blob = unix_extract_chunk,
.end_blob = unix_end_extract_blob,
.ctx = ctx,
};
ret = extract_blob_list(&ctx->common, &cbs);
if (ret)
goto out;
/* Set directory metadata. We do this last so that we get the right
* directory timestamps. */
ret = start_file_metadata_phase(&ctx->common, dir_count);
if (ret)
goto out;
ret = unix_set_dir_metadata(dentry_list, ctx);
if (ret)
goto out;
ret = end_file_metadata_phase(&ctx->common);
if (ret)
goto out;
if (ctx->num_special_files_ignored) {
WARNING("%lu special files were not extracted due to EPERM!",
ctx->num_special_files_ignored);
}
out:
for (unsigned i = 0; i < NUM_PATHBUFS; i++)
FREE(ctx->pathbufs[i]);
FREE(ctx->target_abspath);
return ret;
}
const struct apply_operations unix_apply_ops = {
.name = "UNIX",
.get_supported_features = unix_get_supported_features,
.extract = unix_extract,
.context_size = sizeof(struct unix_apply_ctx),
};
wimlib-1.14.5/src/reparse.c 0000644 0001750 0001750 00000036312 15137020663 012763 0 ustar 00e e /*
* reparse.c - Reparse point handling
*/
/*
* Copyright (C) 2012, 2013, 2015 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include "wimlib/alloca.h"
#include "wimlib/blob_table.h"
#include "wimlib/endianness.h"
#include "wimlib/encoding.h"
#include "wimlib/error.h"
#include "wimlib/guid.h"
#include "wimlib/inode.h"
#include "wimlib/reparse.h"
#include "wimlib/resource.h"
/*
* Reconstruct the header of a reparse point buffer. This is necessary because
* only reparse data is stored in WIM files. The reparse tag is instead stored
* in the on-disk WIM dentry, and the reparse data length is equal to the size
* of the blob in which the reparse data was stored, minus the size of a GUID
* (16 bytes) if the reparse tag does not have the "Microsoft" bit set.
*/
void
complete_reparse_point(struct reparse_buffer_disk *rpbuf,
const struct wim_inode *inode, u16 blob_size)
{
rpbuf->rptag = cpu_to_le32(inode->i_reparse_tag);
if (blob_size >= GUID_SIZE && !(inode->i_reparse_tag & 0x80000000))
blob_size -= GUID_SIZE;
rpbuf->rpdatalen = cpu_to_le16(blob_size);
rpbuf->rpreserved = cpu_to_le16(inode->i_rp_reserved);
}
/* Parse the buffer for a symbolic link or junction reparse point and fill in a
* 'struct link_reparse_point'. */
int
parse_link_reparse_point(const struct reparse_buffer_disk *rpbuf, u16 rpbuflen,
struct link_reparse_point *link)
{
u16 substitute_name_offset;
u16 print_name_offset;
const u8 *data;
link->rptag = le32_to_cpu(rpbuf->rptag);
/* Not a symbolic link or junction? */
if (link->rptag != WIM_IO_REPARSE_TAG_SYMLINK &&
link->rptag != WIM_IO_REPARSE_TAG_MOUNT_POINT)
return WIMLIB_ERR_INVALID_REPARSE_DATA;
/* Is the buffer too small to be a symlink or a junction? */
if (rpbuflen < offsetof(struct reparse_buffer_disk, link.junction.data))
return WIMLIB_ERR_INVALID_REPARSE_DATA;
link->rpreserved = le16_to_cpu(rpbuf->rpreserved);
link->substitute_name_nbytes = le16_to_cpu(rpbuf->link.substitute_name_nbytes);
substitute_name_offset = le16_to_cpu(rpbuf->link.substitute_name_offset);
link->print_name_nbytes = le16_to_cpu(rpbuf->link.print_name_nbytes);
print_name_offset = le16_to_cpu(rpbuf->link.print_name_offset);
/* The names must be properly sized and aligned. */
if ((substitute_name_offset | print_name_offset |
link->substitute_name_nbytes | link->print_name_nbytes) & 1)
return WIMLIB_ERR_INVALID_REPARSE_DATA;
if (link->rptag == WIM_IO_REPARSE_TAG_SYMLINK) {
if (rpbuflen < offsetof(struct reparse_buffer_disk, link.symlink.data))
return WIMLIB_ERR_INVALID_REPARSE_DATA;
link->symlink_flags = le32_to_cpu(rpbuf->link.symlink.flags);
data = rpbuf->link.symlink.data;
} else {
data = rpbuf->link.junction.data;
}
/* Verify that the names don't overflow the buffer. */
if ((data - (const u8 *)rpbuf) + substitute_name_offset +
link->substitute_name_nbytes > rpbuflen)
return WIMLIB_ERR_INVALID_REPARSE_DATA;
if ((data - (const u8 *)rpbuf) + print_name_offset +
link->print_name_nbytes > rpbuflen)
return WIMLIB_ERR_INVALID_REPARSE_DATA;
/* Save the name pointers. */
link->substitute_name = (utf16lechar *)&data[substitute_name_offset];
link->print_name = (utf16lechar *)&data[print_name_offset];
return 0;
}
/* Translate a 'struct link_reparse_point' into a reparse point buffer. */
int
make_link_reparse_point(const struct link_reparse_point *link,
struct reparse_buffer_disk *rpbuf, u16 *rpbuflen_ret)
{
u8 *data;
if (link->rptag == WIM_IO_REPARSE_TAG_SYMLINK)
data = rpbuf->link.symlink.data;
else if (link->rptag == WIM_IO_REPARSE_TAG_MOUNT_POINT)
data = rpbuf->link.junction.data;
else /* Callers should forbid this case, but check anyway. */
return WIMLIB_ERR_INVALID_REPARSE_DATA;
/* Check if the names are too long to fit in a reparse point. */
if ((data - (u8 *)rpbuf) + link->substitute_name_nbytes +
link->print_name_nbytes +
2 * sizeof(utf16lechar) > REPARSE_POINT_MAX_SIZE)
return WIMLIB_ERR_INVALID_REPARSE_DATA;
rpbuf->rptag = cpu_to_le32(link->rptag);
rpbuf->rpreserved = cpu_to_le16(link->rpreserved);
rpbuf->link.substitute_name_offset = cpu_to_le16(0);
rpbuf->link.substitute_name_nbytes = cpu_to_le16(link->substitute_name_nbytes);
rpbuf->link.print_name_offset = cpu_to_le16(link->substitute_name_nbytes +
sizeof(utf16lechar));
rpbuf->link.print_name_nbytes = cpu_to_le16(link->print_name_nbytes);
if (link->rptag == WIM_IO_REPARSE_TAG_SYMLINK)
rpbuf->link.symlink.flags = cpu_to_le32(link->symlink_flags);
/* We null-terminate the substitute and print names, although this isn't
* strictly necessary. Note that the nbytes fields do not include the
* null terminators. */
data = mempcpy(data, link->substitute_name, link->substitute_name_nbytes);
*(utf16lechar *)data = cpu_to_le16(0);
data += sizeof(utf16lechar);
data = mempcpy(data, link->print_name, link->print_name_nbytes);
*(utf16lechar *)data = cpu_to_le16(0);
data += sizeof(utf16lechar);
rpbuf->rpdatalen = cpu_to_le16(data - rpbuf->rpdata);
*rpbuflen_ret = data - (u8 *)rpbuf;
return 0;
}
/* UNIX symlink <=> Windows reparse point translation */
#ifndef _WIN32
/* Retrieve the inode's reparse point buffer into @rpbuf and @rpbuflen_ret.
* This gets the reparse data from @blob if specified, otherwise from the
* inode's reparse point stream. The inode's streams must be resolved. */
static int
wim_inode_get_reparse_point(const struct wim_inode *inode,
struct reparse_buffer_disk *rpbuf,
u16 *rpbuflen_ret,
const struct blob_descriptor *blob)
{
int ret;
u16 blob_size = 0;
if (!blob) {
const struct wim_inode_stream *strm;
strm = inode_get_unnamed_stream(inode, STREAM_TYPE_REPARSE_POINT);
if (strm)
blob = stream_blob_resolved(strm);
}
if (blob) {
if (blob->size > REPARSE_DATA_MAX_SIZE)
return WIMLIB_ERR_INVALID_REPARSE_DATA;
blob_size = blob->size;
ret = read_blob_into_buf(blob, rpbuf->rpdata);
if (ret)
return ret;
}
complete_reparse_point(rpbuf, inode, blob_size);
*rpbuflen_ret = REPARSE_DATA_OFFSET + blob_size;
return 0;
}
static void
copy(char **buf_p, size_t *bufsize_p, const char *src, size_t src_size)
{
size_t n = min(*bufsize_p, src_size);
memcpy(*buf_p, src, n);
*buf_p += n;
*bufsize_p -= n;
}
/*
* Get a UNIX-style symlink target from the WIM inode for a reparse point.
*
* @inode
* The inode from which to read the symlink. If not a symbolic link or
* junction reparse point, then -EINVAL will be returned.
* @buf
* Buffer into which to place the link target.
* @bufsize
* Available space in @buf, in bytes.
* @blob
* If not NULL, the blob from which to read the reparse data. Otherwise,
* the reparse data will be read from the reparse point stream of @inode.
* @altroot
* If @altroot_len != 0 and the link is an absolute link that was stored as
* "fixed", then prepend this path to the link target.
* @altroot_len
* Length of the @altroot string or 0.
*
* Similar to POSIX readlink(), this function writes as much of the symlink
* target as possible (up to @bufsize bytes) to @buf with no null terminator and
* returns the number of bytes written or a negative errno value on error. Note
* that the target is truncated and @bufsize is returned in the overflow case.
*/
int
wim_inode_readlink(const struct wim_inode *inode, char *buf, size_t bufsize,
const struct blob_descriptor *blob,
const char *altroot, size_t altroot_len)
{
struct reparse_buffer_disk rpbuf;
u16 rpbuflen;
struct link_reparse_point link;
char *target_buffer;
char *target;
size_t target_len;
char *buf_ptr;
bool rpfix_ok = false;
/* Not a symbolic link or junction? */
if (!inode_is_symlink(inode))
return -EINVAL;
/* Retrieve the native Windows "substitute name". */
if (wim_inode_get_reparse_point(inode, &rpbuf, &rpbuflen, blob))
return -EIO;
if (parse_link_reparse_point(&rpbuf, rpbuflen, &link))
return -EINVAL;
/* Translate the substitute name to a multibyte string. */
if (utf16le_to_tstr(link.substitute_name, link.substitute_name_nbytes,
&target_buffer, &target_len))
return -errno;
target = target_buffer;
/*
* The substitute name is a native Windows NT path. There are two cases:
*
* 1. The reparse point is a symlink (rptag=WIM_IO_REPARSE_TAG_SYMLINK)
* and SYMBOLIC_LINK_RELATIVE is set. Windows resolves the path
* relative to the directory containing the reparse point file. In
* this case, we just translate the path separators.
* 2. Otherwise, Windows resolves the path from the root of the Windows
* NT kernel object namespace. In this case, we attempt to strip the
* device name, in addition to translating the path separators; e.g.
* "\??\C:\Users\Public" is translated to "/Users/Public".
*
* Also in case (2) the link target may have been stored as "fixed",
* meaning that with the device portion stripped off it is effectively
* "relative to the root of the WIM image". If this is the case, and if
* the caller provided an alternate root directory, then rewrite the
* link to be relative to that directory.
*/
if (!link_is_relative_symlink(&link)) {
static const char *const nt_root_dirs[] = {
"\\??\\", "\\DosDevices\\", "\\Device\\",
};
for (size_t i = 0; i < ARRAY_LEN(nt_root_dirs); i++) {
size_t len = strlen(nt_root_dirs[i]);
if (!strncmp(target, nt_root_dirs[i], len)) {
char *p = target + len;
while (*p == '\\')
p++;
while (*p && *p != '\\')
p++;
target_len -= (p - target);
target = p;
break;
}
}
if (!(inode->i_rp_flags & WIM_RP_FLAG_NOT_FIXED))
rpfix_ok = true;
}
/* Translate backslashes (Windows NT path separator) to forward slashes
* (UNIX path separator). In addition, translate forwards slashes to
* backslashes; this enables lossless handling of UNIX symbolic link
* targets that contain the backslash character. */
for (char *p = target; *p; p++) {
if (*p == '\\')
*p = '/';
else if (*p == '/')
*p = '\\';
}
/* Copy as much of the link target as possible to the output buffer and
* return the number of bytes copied. */
buf_ptr = buf;
if (rpfix_ok && altroot_len != 0) {
copy(&buf_ptr, &bufsize, altroot, altroot_len);
} else if (target_len == 0) {
/* An absolute link target that was made relative to the same
* directory pointed to will end up empty if the original target
* did not have a trailing slash. Here, we are reading this
* adjusted link target without prefixing it. This usually
* doesn't happen, but if it does then we need to change it to
* "/" so that it is a valid target. */
target = "/";
target_len = 1;
}
copy(&buf_ptr, &bufsize, target, target_len);
FREE(target_buffer);
return buf_ptr - buf;
}
/* Given a UNIX-style symbolic link target, create a Windows-style reparse point
* buffer and assign it to the specified inode. */
int
wim_inode_set_symlink(struct wim_inode *inode, const char *_target,
struct blob_table *blob_table)
{
int ret;
utf16lechar *target;
size_t target_nbytes;
struct link_reparse_point link;
struct reparse_buffer_disk rpbuf;
u16 rpbuflen;
/* Translate the link target to UTF-16LE. */
ret = tstr_to_utf16le(_target, strlen(_target), &target, &target_nbytes);
if (ret)
return ret;
/* Translate forward slashes (UNIX path separator) to backslashes
* (Windows NT path separator). In addition, translate backslashes to
* forward slashes; this enables lossless handling of UNIX symbolic link
* targets that contain the backslash character. */
for (utf16lechar *p = target; *p; p++) {
if (*p == cpu_to_le16('/'))
*p = cpu_to_le16('\\');
else if (*p == cpu_to_le16('\\'))
*p = cpu_to_le16('/');
}
link.rptag = WIM_IO_REPARSE_TAG_SYMLINK;
link.rpreserved = 0;
/* Note: an absolute link that was rewritten to be relative to another
* directory is assumed to either be empty or to have a leading slash.
* See unix_relativize_link_target(). */
if (*target == cpu_to_le16('\\') || !*target) {
/*
* UNIX link target was absolute. In this case we represent the
* link as a symlink reparse point with SYMBOLIC_LINK_RELATIVE
* cleared. For this to work we need to assign it a path that
* can be resolved from the root of the Windows NT kernel object
* namespace. We do this by using "\??\C:" as a dummy prefix.
*
* Note that we could instead represent UNIX absolute links by
* setting SYMBOLIC_LINK_RELATIVE and then leaving the path
* backslash-prefixed like "\Users\Public". On Windows this is
* valid and denotes a path relative to the root of the
* filesystem on which the reparse point resides. The problem
* with this is that neither WIMGAPI nor wimlib (on Windows)
* will do "reparse point fixups" when extracting such links
* (modifying the link target to point into the actual
* extraction directory). So for the greatest cross-platform
* consistency, we have to use the fake C: drive approach.
*/
static const utf16lechar prefix[6] = {
cpu_to_le16('\\'),
cpu_to_le16('?'),
cpu_to_le16('?'),
cpu_to_le16('\\'),
cpu_to_le16('C'),
cpu_to_le16(':'),
};
/* Do not show \??\ in print name */
const size_t num_unprintable_chars = 4;
link.symlink_flags = 0;
link.substitute_name_nbytes = sizeof(prefix) + target_nbytes;
link.substitute_name = alloca(link.substitute_name_nbytes);
memcpy(link.substitute_name, prefix, sizeof(prefix));
memcpy(link.substitute_name + ARRAY_LEN(prefix), target, target_nbytes);
link.print_name_nbytes = link.substitute_name_nbytes -
(num_unprintable_chars * sizeof(utf16lechar));
link.print_name = link.substitute_name + num_unprintable_chars;
} else {
/* UNIX link target was relative. In this case we represent the
* link as a symlink reparse point with SYMBOLIC_LINK_RELATIVE
* set. This causes Windows to interpret the link relative to
* the directory containing the reparse point file. */
link.symlink_flags = SYMBOLIC_LINK_RELATIVE;
link.substitute_name_nbytes = target_nbytes;
link.substitute_name = target;
link.print_name_nbytes = target_nbytes;
link.print_name = target;
}
/* Generate the reparse buffer. */
ret = make_link_reparse_point(&link, &rpbuf, &rpbuflen);
if (ret)
goto out_free_target;
/* Save the reparse data with the inode. */
ret = WIMLIB_ERR_NOMEM;
if (!inode_add_stream_with_data(inode,
STREAM_TYPE_REPARSE_POINT,
NO_STREAM_NAME,
rpbuf.rpdata,
rpbuflen - REPARSE_DATA_OFFSET,
blob_table))
goto out_free_target;
/* The inode is now a reparse point. */
inode->i_reparse_tag = link.rptag;
inode->i_attributes &= ~FILE_ATTRIBUTE_NORMAL;
inode->i_attributes |= FILE_ATTRIBUTE_REPARSE_POINT;
ret = 0;
out_free_target:
FREE(target);
return ret;
}
#endif /* !_WIN32 */
wimlib-1.14.5/src/inode_table.c 0000644 0001750 0001750 00000014076 15137020663 013572 0 ustar 00e e /*
* inode_table.c - hard link detection
*/
/*
* Copyright (C) 2012-2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/bitops.h"
#include "wimlib/dentry.h"
#include "wimlib/error.h"
#include "wimlib/inode.h"
#include "wimlib/inode_table.h"
#include "wimlib/list.h"
#include "wimlib/util.h"
/* Initialize a hash table for hard link detection. */
int
init_inode_table(struct wim_inode_table *table, size_t capacity)
{
capacity = roundup_pow_of_2(capacity);
table->array = CALLOC(capacity, sizeof(table->array[0]));
if (!table->array)
return WIMLIB_ERR_NOMEM;
table->filled = 0;
table->capacity = capacity;
INIT_HLIST_HEAD(&table->extra_inodes);
return 0;
}
/* Free the memory allocated by init_inode_table(). */
void
destroy_inode_table(struct wim_inode_table *table)
{
FREE(table->array);
}
/* Double the capacity of the inode hash table. */
void
enlarge_inode_table(struct wim_inode_table *table)
{
const size_t old_capacity = table->capacity;
const size_t new_capacity = old_capacity * 2;
struct hlist_head *old_array = table->array;
struct hlist_head *new_array;
struct wim_inode *inode;
struct hlist_node *tmp;
new_array = CALLOC(new_capacity, sizeof(struct hlist_head));
if (!new_array)
return;
table->array = new_array;
table->capacity = new_capacity;
for (size_t i = 0; i < old_capacity; i++) {
hlist_for_each_entry_safe(inode, tmp, &old_array[i], i_hlist_node) {
hlist_add_head(&inode->i_hlist_node,
&new_array[hash_inode(table, inode->i_ino,
inode->i_devno)]);
}
}
FREE(old_array);
}
/*
* Allocate a new dentry, with hard link detection.
*
* @table
* The inode table being used for the current directory scan operation. It
* will contain the mapping from (ino, devno) pairs to inodes.
*
* @name
* The name to give the new dentry.
*
* @ino
* The inode number of the file, read from the filesystem.
*
* @devno
* The device number of the file, read from the filesystem. Proper setting
* of this parameter prevents cross-device hardlinks from being created.
* If this is not a problem (perhaps because the current directory scan
* operation is guaranteed to never traverse a filesystem boundary), then
* this parameter can just be a fixed value such as 0.
*
* @noshare
* If %true, the new dentry will not be hard linked to any existing inode,
* regardless of the values of @ino and @devno. If %false, normal hard
* link detection will be done.
*
* @dentry_ret
* On success, a pointer to the new dentry will be returned in this
* location. If i_nlink of the dentry's inode is greater than 1, then this
* function created a hard link to an existing inode rather than creating a
* new inode.
*
* On success, returns 0. On failure, returns WIMLIB_ERR_NOMEM or an error code
* resulting from a failed string conversion.
*/
int
inode_table_new_dentry(struct wim_inode_table *table, const tchar *name,
u64 ino, u64 devno, bool noshare,
struct wim_dentry **dentry_ret)
{
struct wim_dentry *dentry;
struct wim_inode *inode;
struct hlist_head *list;
int ret;
if (noshare) {
/* No hard link detection */
list = &table->extra_inodes;
} else {
/* Hard link detection */
list = &table->array[hash_inode(table, ino, devno)];
hlist_for_each_entry(inode, list, i_hlist_node) {
if (inode->i_ino != ino || inode->i_devno != devno)
continue;
/*
* Since the WIM file format does not support directory
* hard links, automatically un-hard-link any that are
* found. We no longer print a warning when doing this,
* considering that this condition trips when capturing
* hard-linked symlinks to directories on Linux. (Those
* get translated into "directory reparse points",
* despite not being directories originally. And
* un-hard-linking them doesn't really matter.)
*/
if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
/* Inode found; use it. */
return new_dentry_with_existing_inode(name, inode,
dentry_ret);
}
/* Inode not found; create it. */
}
ret = new_dentry_with_new_inode(name, false, &dentry);
if (ret)
return ret;
inode = dentry->d_inode;
inode->i_ino = ino;
inode->i_devno = devno;
hlist_add_head(&inode->i_hlist_node, list);
if (list != &table->extra_inodes)
if (++table->filled > table->capacity)
enlarge_inode_table(table);
*dentry_ret = dentry;
return 0;
}
/*
* Following the allocation of dentries with hard link detection using
* inode_table_new_dentry(), this function will assign consecutive inode numbers
* to the new set of inodes. It will also append the list of new inodes to the
* list @head, which must contain any inodes already existing in the WIM image.
*/
void
inode_table_prepare_inode_list(struct wim_inode_table *table,
struct hlist_head *head)
{
struct wim_inode *inode;
struct hlist_node *tmp;
u64 cur_ino = 1;
/* Re-assign inode numbers in the existing list to avoid duplicates. */
hlist_for_each_entry(inode, head, i_hlist_node)
inode->i_ino = cur_ino++;
/* Assign inode numbers to the new inodes and move them to the image's
* inode list. */
for (size_t i = 0; i < table->capacity; i++) {
hlist_for_each_entry_safe(inode, tmp, &table->array[i], i_hlist_node) {
inode->i_ino = cur_ino++;
hlist_add_head(&inode->i_hlist_node, head);
}
}
hlist_for_each_entry_safe(inode, tmp, &table->extra_inodes, i_hlist_node) {
inode->i_ino = cur_ino++;
hlist_add_head(&inode->i_hlist_node, head);
}
}
wimlib-1.14.5/src/xpress_decompress.c 0000644 0001750 0001750 00000013554 15137020663 015075 0 ustar 00e e /*
* xpress_decompress.c
*
* A decompressor for the XPRESS compression format (Huffman variant).
*/
/*
*
* Copyright (C) 2012-2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
/*
* The XPRESS compression format is an LZ77 and Huffman-code based algorithm.
* That means it is fairly similar to LZX compression, but XPRESS is simpler, so
* it is a little faster to compress and decompress.
*
* The XPRESS compression format is mostly documented in a file called "[MS-XCA]
* Xpress Compression Algorithm". In the MSDN library, it can currently be
* found under Open Specifications => Protocols => Windows Protocols => Windows
* Server Protocols => [MS-XCA] Xpress Compression Algorithm". The format in
* WIMs is specifically the algorithm labeled as the "LZ77+Huffman Algorithm"
* (there apparently are some other versions of XPRESS as well).
*
* If you are already familiar with the LZ77 algorithm and Huffman coding, the
* XPRESS format is fairly simple. The compressed data begins with 256 bytes
* that contain 512 4-bit integers that are the lengths of the symbols in the
* Huffman code used for match/literal headers. In contrast with more
* complicated formats such as DEFLATE and LZX, this is the only Huffman code
* that is used for the entirety of the XPRESS compressed data, and the codeword
* lengths are not encoded with a pretree.
*
* The rest of the compressed data is Huffman-encoded symbols. Values 0 through
* 255 represent the corresponding literal bytes. Values 256 through 511
* represent matches and may require extra bits or bytes to be read to get the
* match offset and match length.
*
* The trickiest part is probably the way in which literal bytes for match
* lengths are interleaved in the bitstream.
*
* Also, a caveat--- according to Microsoft's documentation for XPRESS,
*
* "Some implementation of the decompression algorithm expect an extra
* symbol to mark the end of the data. Specifically, some implementations
* fail during decompression if the Huffman symbol 256 is not found after
* the actual data."
*
* This is the case with Microsoft's implementation in WIMGAPI, for example. So
* although our implementation doesn't currently check for this extra symbol,
* compressors would be wise to add it.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/decompressor_ops.h"
#include "wimlib/decompress_common.h"
#include "wimlib/error.h"
#include "wimlib/util.h"
#include "wimlib/xpress_constants.h"
/* This value is chosen for fast decompression. */
#define XPRESS_TABLEBITS 11
struct xpress_decompressor {
union {
DECODE_TABLE(decode_table, XPRESS_NUM_SYMBOLS,
XPRESS_TABLEBITS, XPRESS_MAX_CODEWORD_LEN);
u8 lens[XPRESS_NUM_SYMBOLS];
};
DECODE_TABLE_WORKING_SPACE(working_space, XPRESS_NUM_SYMBOLS,
XPRESS_MAX_CODEWORD_LEN);
} __attribute__((aligned(DECODE_TABLE_ALIGNMENT)));
static int
xpress_decompress(const void *restrict compressed_data, size_t compressed_size,
void *restrict uncompressed_data, size_t uncompressed_size,
void *restrict _d)
{
struct xpress_decompressor *d = _d;
const u8 * const in_begin = compressed_data;
u8 * const out_begin = uncompressed_data;
u8 *out_next = out_begin;
u8 * const out_end = out_begin + uncompressed_size;
struct input_bitstream is;
/* Read the Huffman codeword lengths. */
if (compressed_size < XPRESS_NUM_SYMBOLS / 2)
return -1;
for (int i = 0; i < XPRESS_NUM_SYMBOLS / 2; i++) {
d->lens[2 * i + 0] = in_begin[i] & 0xf;
d->lens[2 * i + 1] = in_begin[i] >> 4;
}
/* Build a decoding table for the Huffman code. */
if (make_huffman_decode_table(d->decode_table, XPRESS_NUM_SYMBOLS,
XPRESS_TABLEBITS, d->lens,
XPRESS_MAX_CODEWORD_LEN,
d->working_space))
return -1;
/* Decode the matches and literals. */
init_input_bitstream(&is, in_begin + XPRESS_NUM_SYMBOLS / 2,
compressed_size - XPRESS_NUM_SYMBOLS / 2);
while (out_next != out_end) {
unsigned sym;
unsigned log2_offset;
u32 length;
u32 offset;
sym = read_huffsym(&is, d->decode_table,
XPRESS_TABLEBITS, XPRESS_MAX_CODEWORD_LEN);
if (sym < XPRESS_NUM_CHARS) {
/* Literal */
*out_next++ = sym;
} else {
/* Match */
length = sym & 0xf;
log2_offset = (sym >> 4) & 0xf;
bitstream_ensure_bits(&is, 16);
offset = ((u32)1 << log2_offset) |
bitstream_pop_bits(&is, log2_offset);
if (length == 0xf) {
length += bitstream_read_byte(&is);
if (length == 0xf + 0xff)
length = bitstream_read_u16(&is);
}
length += XPRESS_MIN_MATCH_LEN;
if (unlikely(lz_copy(length, offset,
out_begin, out_next, out_end,
XPRESS_MIN_MATCH_LEN)))
return -1;
out_next += length;
}
}
return 0;
}
static int
xpress_create_decompressor(size_t max_block_size, void **d_ret)
{
struct xpress_decompressor *d;
if (max_block_size > XPRESS_MAX_OFFSET + 1)
return WIMLIB_ERR_INVALID_PARAM;
d = ALIGNED_MALLOC(sizeof(*d), DECODE_TABLE_ALIGNMENT);
if (!d)
return WIMLIB_ERR_NOMEM;
*d_ret = d;
return 0;
}
static void
xpress_free_decompressor(void *_d)
{
ALIGNED_FREE(_d);
}
const struct decompressor_ops xpress_decompressor_ops = {
.create_decompressor = xpress_create_decompressor,
.decompress = xpress_decompress,
.free_decompressor = xpress_free_decompressor,
};
wimlib-1.14.5/src/tagged_items.c 0000644 0001750 0001750 00000014325 15137020663 013756 0 ustar 00e e /*
* tagged_items.c
*
* Support for tagged metadata items that can be appended to WIM directory
* entries.
*/
/*
* Copyright (C) 2014-2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/assert.h"
#include "wimlib/endianness.h"
#include "wimlib/inode.h"
#include "wimlib/tagged_items.h"
#include "wimlib/unix_data.h"
/*
* Header that begins each tagged metadata item associated with a file in a WIM
* metadata resource
*/
struct tagged_item_header {
/* identifies the type of metadata item (see TAG_* constants) */
le32 tag;
/* size of this item's data in bytes, excluding this header */
le32 length;
/* followed by the item's data */
u8 data[0];
/* then zero-padded to an 8-byte boundary */
} __attribute__((aligned(8)));
/*
* Retrieve from @inode the first metadata item that is tagged with @tag and
* contains at least @min_len bytes of data. If found, return a pointer to the
* item's data and write its actual length to @actual_len_ret if not NULL. If
* not found, return NULL.
*/
void *
inode_get_tagged_item(const struct wim_inode *inode, u32 tag, u32 min_len,
u32 *actual_len_ret)
{
struct tagged_item_header *hdr;
size_t len_remaining;
STATIC_ASSERT(sizeof(*hdr) == 8);
if (!inode->i_extra)
return NULL;
hdr = (struct tagged_item_header *)inode->i_extra->data;
len_remaining = inode->i_extra->size;
/* Iterate through the tagged items. */
while (len_remaining >= sizeof(*hdr) + min_len) {
u32 len = le32_to_cpu(hdr->length);
u32 full_len = sizeof(*hdr) + ALIGN(len, 8);
/* Length overflow (corrupted item list)? */
if (unlikely(full_len < len || full_len > len_remaining))
return NULL;
/* Matches the item we wanted? */
if (le32_to_cpu(hdr->tag) == tag && len >= min_len) {
if (actual_len_ret)
*actual_len_ret = len;
return hdr->data;
}
len_remaining -= full_len;
hdr = (struct tagged_item_header *)((u8 *)hdr + full_len);
}
return NULL;
}
/*
* Add a tagged item to the specified inode and return a pointer to its
* uninitialized data, which the caller must initialize. No check is made for
* whether the inode already has item(s) with the specified tag.
*/
static void *
inode_add_tagged_item(struct wim_inode *inode, u32 tag, u32 len)
{
struct wim_inode_extra *extra;
struct tagged_item_header *hdr;
size_t oldsize = (inode->i_extra ? inode->i_extra->size : 0);
size_t newsize = oldsize + sizeof(*hdr) + ALIGN(len, 8);
wimlib_assert(oldsize % 8 == 0);
extra = REALLOC(inode->i_extra, sizeof(*extra) + newsize);
if (!extra)
return NULL;
inode->i_extra = extra;
extra->size = newsize;
hdr = (struct tagged_item_header *)&extra->data[oldsize];
hdr->tag = cpu_to_le32(tag);
hdr->length = cpu_to_le32(len);
memset(hdr->data + len, 0, -len & 7); /* pad to next 8-byte boundary */
return hdr->data;
}
/*
* Add a tagged item containing the specified data to the specified inode, first
* removing any existing items with the same tag. Returns %true if successful,
* %false if failed (out of memory).
*/
bool
inode_set_tagged_item(struct wim_inode *inode, u32 tag,
const void *data, u32 len)
{
u8 *p;
u32 old_len;
/* Remove any existing items with the same tag */
while ((p = inode_get_tagged_item(inode, tag, 0, &old_len)) != NULL) {
p -= sizeof(struct tagged_item_header);
old_len += sizeof(struct tagged_item_header);
old_len = ALIGN(old_len, 8);
memmove(p, p + old_len, (inode->i_extra->data +
inode->i_extra->size) - (p + old_len));
inode->i_extra->size -= old_len;
}
/* Add the new item */
p = inode_add_tagged_item(inode, tag, len);
if (!p)
return false;
memcpy(p, data, len);
return true;
}
struct wimlib_unix_data_disk {
le32 uid;
le32 gid;
le32 mode;
le32 rdev;
};
static inline struct wimlib_unix_data_disk *
inode_get_unix_data_disk(const struct wim_inode *inode)
{
return inode_get_tagged_item(inode, TAG_WIMLIB_UNIX_DATA,
sizeof(struct wimlib_unix_data_disk),
NULL);
}
/* Return %true iff the specified inode has standard UNIX metadata. */
bool
inode_has_unix_data(const struct wim_inode *inode)
{
return inode_get_unix_data_disk(inode) != NULL;
}
/*
* Get an inode's standard UNIX metadata.
*
* If the inode has standard UNIX metadata, returns %true and fills @unix_data.
* Otherwise returns %false.
*/
bool
inode_get_unix_data(const struct wim_inode *inode,
struct wimlib_unix_data *unix_data)
{
const struct wimlib_unix_data_disk *p;
p = inode_get_unix_data_disk(inode);
if (!p)
return false;
unix_data->uid = le32_to_cpu(p->uid);
unix_data->gid = le32_to_cpu(p->gid);
unix_data->mode = le32_to_cpu(p->mode);
unix_data->rdev = le32_to_cpu(p->rdev);
return true;
}
/*
* Set an inode's standard UNIX metadata.
*
* Callers must specify all members in @unix_data. If the inode does not yet
* have standard UNIX metadata, it is given these values. Otherwise, only the
* values that also have the corresponding flags in @which set are changed.
*
* Returns %true if successful, %false if failed (out of memory).
*/
bool
inode_set_unix_data(struct wim_inode *inode, struct wimlib_unix_data *unix_data,
int which)
{
struct wimlib_unix_data_disk *p;
p = inode_get_unix_data_disk(inode);
if (!p) {
p = inode_add_tagged_item(inode, TAG_WIMLIB_UNIX_DATA,
sizeof(*p));
if (!p)
return false;
which = UNIX_DATA_ALL;
}
if (which & UNIX_DATA_UID)
p->uid = cpu_to_le32(unix_data->uid);
if (which & UNIX_DATA_GID)
p->gid = cpu_to_le32(unix_data->gid);
if (which & UNIX_DATA_MODE)
p->mode = cpu_to_le32(unix_data->mode);
if (which & UNIX_DATA_RDEV)
p->rdev = cpu_to_le32(unix_data->rdev);
return true;
}
wimlib-1.14.5/src/progress.c 0000644 0001750 0001750 00000003017 15137020663 013162 0 ustar 00e e /*
* progress.c
*/
/*
* Copyright (C) 2014 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/progress.h"
int
report_error(wimlib_progress_func_t progfunc,
void *progctx, int error_code, const tchar *path)
{
int ret;
union wimlib_progress_info progress;
tchar *cookie;
if (error_code == WIMLIB_ERR_SUCCESS ||
error_code == WIMLIB_ERR_ABORTED_BY_PROGRESS ||
error_code == WIMLIB_ERR_UNKNOWN_PROGRESS_STATUS)
return error_code;
progress.handle_error.path = path;
progress.handle_error.error_code = error_code;
progress.handle_error.will_ignore = false;
cookie = progress_get_win32_path(path);
ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_HANDLE_ERROR,
&progress, progctx);
progress_put_win32_path(cookie);
if (ret)
return ret;
if (!progress.handle_error.will_ignore)
return error_code;
return 0;
}
wimlib-1.14.5/src/compress_common.c 0000644 0001750 0001750 00000060253 15137011205 014516 0 ustar 00e e /*
* compress_common.c
*
* Code for compression shared among multiple compression formats.
*
* Copyright 2022 Eric Biggers
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include "wimlib/assert.h"
#include "wimlib/compress_common.h"
#include "wimlib/util.h"
/*
* Given the binary tree node A[subtree_idx] whose children already satisfy the
* maxheap property, swap the node with its greater child until it is greater
* than or equal to both of its children, so that the maxheap property is
* satisfied in the subtree rooted at A[subtree_idx]. 'A' uses 1-based indices.
*/
static void
heapify_subtree(u32 A[], unsigned length, unsigned subtree_idx)
{
unsigned parent_idx;
unsigned child_idx;
u32 v;
v = A[subtree_idx];
parent_idx = subtree_idx;
while ((child_idx = parent_idx * 2) <= length) {
if (child_idx < length && A[child_idx + 1] > A[child_idx])
child_idx++;
if (v >= A[child_idx])
break;
A[parent_idx] = A[child_idx];
parent_idx = child_idx;
}
A[parent_idx] = v;
}
/*
* Rearrange the array 'A' so that it satisfies the maxheap property.
* 'A' uses 1-based indices, so the children of A[i] are A[i*2] and A[i*2 + 1].
*/
static void
heapify_array(u32 A[], unsigned length)
{
unsigned subtree_idx;
for (subtree_idx = length / 2; subtree_idx >= 1; subtree_idx--)
heapify_subtree(A, length, subtree_idx);
}
/*
* Sort the array 'A', which contains 'length' unsigned 32-bit integers.
*
* Note: name this function heap_sort() instead of heapsort() to avoid colliding
* with heapsort() from stdlib.h on BSD-derived systems --- though this isn't
* necessary when compiling with -D_ANSI_SOURCE, which is the better solution.
*/
static void
heap_sort(u32 A[], unsigned length)
{
A--; /* Use 1-based indices */
heapify_array(A, length);
while (length >= 2) {
u32 tmp = A[length];
A[length] = A[1];
A[1] = tmp;
length--;
heapify_subtree(A, length, 1);
}
}
#define NUM_SYMBOL_BITS 10
#define NUM_FREQ_BITS (32 - NUM_SYMBOL_BITS)
#define SYMBOL_MASK ((1 << NUM_SYMBOL_BITS) - 1)
#define FREQ_MASK (~SYMBOL_MASK)
#define GET_NUM_COUNTERS(num_syms) (num_syms)
/*
* Sort the symbols primarily by frequency and secondarily by symbol value.
* Discard symbols with zero frequency and fill in an array with the remaining
* symbols, along with their frequencies. The low NUM_SYMBOL_BITS bits of each
* array entry will contain the symbol value, and the remaining bits will
* contain the frequency.
*
* @num_syms
* Number of symbols in the alphabet, at most 1 << NUM_SYMBOL_BITS.
*
* @freqs[num_syms]
* Frequency of each symbol, summing to at most (1 << NUM_FREQ_BITS) - 1.
*
* @lens[num_syms]
* An array that eventually will hold the length of each codeword. This
* function only fills in the codeword lengths for symbols that have zero
* frequency, which are not well defined per se but will be set to 0.
*
* @symout[num_syms]
* The output array, described above.
*
* Returns the number of entries in 'symout' that were filled. This is the
* number of symbols that have nonzero frequency.
*/
static unsigned
sort_symbols(unsigned num_syms, const u32 freqs[], u8 lens[], u32 symout[])
{
unsigned sym;
unsigned i;
unsigned num_used_syms;
unsigned num_counters;
unsigned counters[GET_NUM_COUNTERS(MAX_NUM_SYMS)];
/*
* We use heapsort, but with an added optimization. Since often most
* symbol frequencies are low, we first do a count sort using a limited
* number of counters. High frequencies are counted in the last
* counter, and only they will be sorted with heapsort.
*
* Note: with more symbols, it is generally beneficial to have more
* counters. About 1 counter per symbol seems fastest.
*/
num_counters = GET_NUM_COUNTERS(num_syms);
memset(counters, 0, num_counters * sizeof(counters[0]));
/* Count the frequencies. */
for (sym = 0; sym < num_syms; sym++)
counters[MIN(freqs[sym], num_counters - 1)]++;
/*
* Make the counters cumulative, ignoring the zero-th, which counted
* symbols with zero frequency. As a side effect, this calculates the
* number of symbols with nonzero frequency.
*/
num_used_syms = 0;
for (i = 1; i < num_counters; i++) {
unsigned count = counters[i];
counters[i] = num_used_syms;
num_used_syms += count;
}
/*
* Sort nonzero-frequency symbols using the counters. At the same time,
* set the codeword lengths of zero-frequency symbols to 0.
*/
for (sym = 0; sym < num_syms; sym++) {
u32 freq = freqs[sym];
if (freq != 0) {
symout[counters[MIN(freq, num_counters - 1)]++] =
sym | (freq << NUM_SYMBOL_BITS);
} else {
lens[sym] = 0;
}
}
/* Sort the symbols counted in the last counter. */
heap_sort(symout + counters[num_counters - 2],
counters[num_counters - 1] - counters[num_counters - 2]);
return num_used_syms;
}
/*
* Build a Huffman tree.
*
* This is an optimized implementation that
* (a) takes advantage of the frequencies being already sorted;
* (b) only generates non-leaf nodes, since the non-leaf nodes of a Huffman
* tree are sufficient to generate a canonical code;
* (c) Only stores parent pointers, not child pointers;
* (d) Produces the nodes in the same memory used for input frequency
* information.
*
* Array 'A', which contains 'sym_count' entries, is used for both input and
* output. For this function, 'sym_count' must be at least 2.
*
* For input, the array must contain the frequencies of the symbols, sorted in
* increasing order. Specifically, each entry must contain a frequency left
* shifted by NUM_SYMBOL_BITS bits. Any data in the low NUM_SYMBOL_BITS bits of
* the entries will be ignored by this function. Although these bits will, in
* fact, contain the symbols that correspond to the frequencies, this function
* is concerned with frequencies only and keeps the symbols as-is.
*
* For output, this function will produce the non-leaf nodes of the Huffman
* tree. These nodes will be stored in the first (sym_count - 1) entries of the
* array. Entry A[sym_count - 2] will represent the root node. Each other node
* will contain the zero-based index of its parent node in 'A', left shifted by
* NUM_SYMBOL_BITS bits. The low NUM_SYMBOL_BITS bits of each entry in A will
* be kept as-is. Again, note that although these low bits will, in fact,
* contain a symbol value, this symbol will have *no relationship* with the
* Huffman tree node that happens to occupy the same slot. This is because this
* implementation only generates the non-leaf nodes of the tree.
*/
static void
build_tree(u32 A[], unsigned sym_count)
{
const unsigned last_idx = sym_count - 1;
/* Index of the next lowest frequency leaf that still needs a parent */
unsigned i = 0;
/*
* Index of the next lowest frequency non-leaf that still needs a
* parent, or 'e' if there is currently no such node
*/
unsigned b = 0;
/* Index of the next spot for a non-leaf (will overwrite a leaf) */
unsigned e = 0;
do {
u32 new_freq;
/*
* Select the next two lowest frequency nodes among the leaves
* A[i] and non-leaves A[b], and create a new node A[e] to be
* their parent. Set the new node's frequency to the sum of the
* frequencies of its two children.
*
* Usually the next two lowest frequency nodes are of the same
* type (leaf or non-leaf), so check those cases first.
*/
if (i + 1 <= last_idx &&
(b == e || (A[i + 1] & FREQ_MASK) <= (A[b] & FREQ_MASK))) {
/* Two leaves */
new_freq = (A[i] & FREQ_MASK) + (A[i + 1] & FREQ_MASK);
i += 2;
} else if (b + 2 <= e &&
(i > last_idx ||
(A[b + 1] & FREQ_MASK) < (A[i] & FREQ_MASK))) {
/* Two non-leaves */
new_freq = (A[b] & FREQ_MASK) + (A[b + 1] & FREQ_MASK);
A[b] = (e << NUM_SYMBOL_BITS) | (A[b] & SYMBOL_MASK);
A[b + 1] = (e << NUM_SYMBOL_BITS) |
(A[b + 1] & SYMBOL_MASK);
b += 2;
} else {
/* One leaf and one non-leaf */
new_freq = (A[i] & FREQ_MASK) + (A[b] & FREQ_MASK);
A[b] = (e << NUM_SYMBOL_BITS) | (A[b] & SYMBOL_MASK);
i++;
b++;
}
A[e] = new_freq | (A[e] & SYMBOL_MASK);
/*
* A binary tree with 'n' leaves has 'n - 1' non-leaves, so the
* tree is complete once we've created 'n - 1' non-leaves.
*/
} while (++e < last_idx);
}
/*
* Given the stripped-down Huffman tree constructed by build_tree(), determine
* the number of codewords that should be assigned each possible length, taking
* into account the length-limited constraint.
*
* @A
* The array produced by build_tree(), containing parent index information
* for the non-leaf nodes of the Huffman tree. Each entry in this array is
* a node; a node's parent always has a greater index than that node
* itself. This function will overwrite the parent index information in
* this array, so essentially it will destroy the tree. However, the data
* in the low NUM_SYMBOL_BITS of each entry will be preserved.
*
* @root_idx
* The 0-based index of the root node in 'A', and consequently one less
* than the number of tree node entries in 'A'. (Or, really 2 less than
* the actual length of 'A'.)
*
* @len_counts
* An array of length ('max_codeword_len' + 1) in which the number of
* codewords having each length <= max_codeword_len will be returned.
*
* @max_codeword_len
* The maximum permissible codeword length.
*/
static void
compute_length_counts(u32 A[], unsigned root_idx, unsigned len_counts[],
unsigned max_codeword_len)
{
unsigned len;
int node;
/*
* The key observations are:
*
* (1) We can traverse the non-leaf nodes of the tree, always visiting a
* parent before its children, by simply iterating through the array
* in reverse order. Consequently, we can compute the depth of each
* node in one pass, overwriting the parent indices with depths.
*
* (2) We can initially assume that in the real Huffman tree, both
* children of the root are leaves. This corresponds to two
* codewords of length 1. Then, whenever we visit a (non-leaf) node
* during the traversal, we modify this assumption to account for
* the current node *not* being a leaf, but rather its two children
* being leaves. This causes the loss of one codeword for the
* current depth and the addition of two codewords for the current
* depth plus one.
*
* (3) We can handle the length-limited constraint fairly easily by
* simply using the largest length available when a depth exceeds
* max_codeword_len.
*/
for (len = 0; len <= max_codeword_len; len++)
len_counts[len] = 0;
len_counts[1] = 2;
/* Set the root node's depth to 0. */
A[root_idx] &= SYMBOL_MASK;
for (node = root_idx - 1; node >= 0; node--) {
/* Calculate the depth of this node. */
unsigned parent = A[node] >> NUM_SYMBOL_BITS;
unsigned parent_depth = A[parent] >> NUM_SYMBOL_BITS;
unsigned depth = parent_depth + 1;
unsigned len = depth;
/*
* Set the depth of this node so that it is available when its
* children (if any) are processed.
*/
A[node] = (A[node] & SYMBOL_MASK) | (depth << NUM_SYMBOL_BITS);
/*
* If needed, decrease the length to meet the length-limited
* constraint. This is not the optimal method for generating
* length-limited Huffman codes! But it should be good enough.
*/
if (len >= max_codeword_len) {
len = max_codeword_len;
do {
len--;
} while (len_counts[len] == 0);
}
/*
* Account for the fact that we have a non-leaf node at the
* current depth.
*/
len_counts[len]--;
len_counts[len + 1] += 2;
}
}
/*
* Generate the codewords for a canonical Huffman code.
*
* @A
* The output array for codewords. In addition, initially this
* array must contain the symbols, sorted primarily by frequency and
* secondarily by symbol value, in the low NUM_SYMBOL_BITS bits of
* each entry.
*
* @len
* Output array for codeword lengths.
*
* @len_counts
* An array that provides the number of codewords that will have
* each possible length <= max_codeword_len.
*
* @max_codeword_len
* Maximum length, in bits, of each codeword.
*
* @num_syms
* Number of symbols in the alphabet, including symbols with zero
* frequency. This is the length of the 'A' and 'len' arrays.
*/
static void
gen_codewords(u32 A[], u8 lens[], const unsigned len_counts[],
unsigned max_codeword_len, unsigned num_syms)
{
u32 next_codewords[MAX_CODEWORD_LEN + 1];
unsigned i;
unsigned len;
unsigned sym;
/*
* Given the number of codewords that will have each length, assign
* codeword lengths to symbols. We do this by assigning the lengths in
* decreasing order to the symbols sorted primarily by increasing
* frequency and secondarily by increasing symbol value.
*/
for (i = 0, len = max_codeword_len; len >= 1; len--) {
unsigned count = len_counts[len];
while (count--)
lens[A[i++] & SYMBOL_MASK] = len;
}
/*
* Generate the codewords themselves. We initialize the
* 'next_codewords' array to provide the lexicographically first
* codeword of each length, then assign codewords in symbol order. This
* produces a canonical code.
*/
next_codewords[0] = 0;
next_codewords[1] = 0;
for (len = 2; len <= max_codeword_len; len++)
next_codewords[len] =
(next_codewords[len - 1] + len_counts[len - 1]) << 1;
for (sym = 0; sym < num_syms; sym++)
A[sym] = next_codewords[lens[sym]]++;
}
/*
* ---------------------------------------------------------------------
* make_canonical_huffman_code()
* ---------------------------------------------------------------------
*
* Given an alphabet and the frequency of each symbol in it, construct a
* length-limited canonical Huffman code.
*
* @num_syms
* The number of symbols in the alphabet. The symbols are the integers in
* the range [0, num_syms - 1]. This parameter must be at least 2 and
* must not exceed (1 << NUM_SYMBOL_BITS).
*
* @max_codeword_len
* The maximum permissible codeword length.
*
* @freqs
* An array of length @num_syms that gives the frequency of each symbol.
* It is valid for some, none, or all of the frequencies to be 0. The sum
* of frequencies must not exceed (1 << NUM_FREQ_BITS) - 1.
*
* @lens
* An array of @num_syms entries in which this function will return the
* length, in bits, of the codeword assigned to each symbol. Symbols with
* 0 frequency will not have codewords per se, but their entries in this
* array will be set to 0. No lengths greater than @max_codeword_len will
* be assigned.
*
* @codewords
* An array of @num_syms entries in which this function will return the
* codeword for each symbol, right-justified and padded on the left with
* zeroes. Codewords for symbols with 0 frequency will be undefined.
*
* ---------------------------------------------------------------------
*
* This function builds a length-limited canonical Huffman code.
*
* A length-limited Huffman code contains no codewords longer than some
* specified length, and has exactly (with some algorithms) or approximately
* (with the algorithm used here) the minimum weighted path length from the
* root, given this constraint.
*
* A canonical Huffman code satisfies the properties that a longer codeword
* never lexicographically precedes a shorter codeword, and the lexicographic
* ordering of codewords of the same length is the same as the lexicographic
* ordering of the corresponding symbols. A canonical Huffman code, or more
* generally a canonical prefix code, can be reconstructed from only a list
* containing the codeword length of each symbol.
*
* The classic algorithm to generate a Huffman code creates a node for each
* symbol, then inserts these nodes into a min-heap keyed by symbol frequency.
* Then, repeatedly, the two lowest-frequency nodes are removed from the
* min-heap and added as the children of a new node having frequency equal to
* the sum of its two children, which is then inserted into the min-heap. When
* only a single node remains in the min-heap, it is the root of the Huffman
* tree. The codeword for each symbol is determined by the path needed to reach
* the corresponding node from the root. Descending to the left child appends a
* 0 bit, whereas descending to the right child appends a 1 bit.
*
* The classic algorithm is relatively easy to understand, but it is subject to
* a number of inefficiencies. In practice, it is fastest to first sort the
* symbols by frequency. (This itself can be subject to an optimization based
* on the fact that most frequencies tend to be low.) At the same time, we sort
* secondarily by symbol value, which aids the process of generating a canonical
* code. Then, during tree construction, no heap is necessary because both the
* leaf nodes and the unparented non-leaf nodes can be easily maintained in
* sorted order. Consequently, there can never be more than two possibilities
* for the next-lowest-frequency node.
*
* In addition, because we're generating a canonical code, we actually don't
* need the leaf nodes of the tree at all, only the non-leaf nodes. This is
* because for canonical code generation we don't need to know where the symbols
* are in the tree. Rather, we only need to know how many leaf nodes have each
* depth (codeword length). And this information can, in fact, be quickly
* generated from the tree of non-leaves only.
*
* Furthermore, we can build this stripped-down Huffman tree directly in the
* array in which the codewords are to be generated, provided that these array
* slots are large enough to hold a symbol and frequency value.
*
* Still furthermore, we don't even need to maintain explicit child pointers.
* We only need the parent pointers, and even those can be overwritten in-place
* with depth information as part of the process of extracting codeword lengths
* from the tree. So in summary, we do NOT need a big structure like:
*
* struct huffman_tree_node {
* unsigned int symbol;
* unsigned int frequency;
* unsigned int depth;
* struct huffman_tree_node *left_child;
* struct huffman_tree_node *right_child;
* };
*
*
* ... which often gets used in "naive" implementations of Huffman code
* generation.
*
* Many of these optimizations are based on the implementation in 7-Zip (source
* file: C/HuffEnc.c), which was placed in the public domain by Igor Pavlov.
*
* NOTE: in general, the same frequencies can be used to generate different
* length-limited canonical Huffman codes. One choice we have is during tree
* construction, when we must decide whether to prefer a leaf or non-leaf when
* there is a tie in frequency. Another choice we have is how to deal with
* codewords that would exceed @max_codeword_len bits in length. Both of these
* choices affect the resulting codeword lengths, which otherwise can be mapped
* uniquely onto the resulting canonical Huffman code.
*
* Normally, there is no problem with choosing one valid code over another,
* provided that they produce similar compression ratios. However, the LZMS
* compression format uses adaptive Huffman coding. It requires that both the
* decompressor and compressor build a canonical code equivalent to that which
* can be generated by using the classic Huffman tree construction algorithm and
* always processing leaves before non-leaves when there is a frequency tie.
* Therefore, we make sure to do this. This method also has the advantage of
* sometimes shortening the longest codeword that is generated.
*
* There also is the issue of how codewords longer than @max_codeword_len are
* dealt with. Fortunately, for LZMS this is irrelevant because for the LZMS
* alphabets no codeword can ever exceed LZMS_MAX_CODEWORD_LEN (= 15). Since
* the LZMS algorithm regularly halves all frequencies, the frequencies cannot
* become high enough for a length 16 codeword to be generated. Specifically, I
* think that if ties are broken in favor of non-leaves (as we do), the lowest
* total frequency that would give a length-16 codeword would be the sum of the
* frequencies 1 1 1 3 4 7 11 18 29 47 76 123 199 322 521 843 1364, which is
* 3570. And in LZMS we can't get a frequency that high based on the alphabet
* sizes, rebuild frequencies, and scaling factors. This worst-case scenario is
* based on the following degenerate case (only the bottom of the tree shown):
*
* ...
* 17
* / \
* 10 7
* / \
* 6 4
* / \
* 3 3
* / \
* 2 1
* / \
* 1 1
*
* Excluding the first leaves (those with value 1), each leaf value must be
* greater than the non-leaf up 1 and down 2 from it; otherwise that leaf would
* have taken precedence over that non-leaf and been combined with the leaf
* below, thereby decreasing the height compared to that shown.
*
* Interesting fact: if we were to instead prioritize non-leaves over leaves,
* then the worst case frequencies would be the Fibonacci sequence, plus an
* extra frequency of 1. In this hypothetical scenario, it would be slightly
* easier for longer codewords to be generated.
*/
void
make_canonical_huffman_code(unsigned num_syms, unsigned max_codeword_len,
const u32 freqs[], u8 lens[], u32 codewords[])
{
u32 *A = codewords;
unsigned num_used_syms;
wimlib_assert(num_syms <= MAX_NUM_SYMS);
STATIC_ASSERT(MAX_NUM_SYMS <= 1 << NUM_SYMBOL_BITS);
wimlib_assert(max_codeword_len <= MAX_CODEWORD_LEN);
/*
* We begin by sorting the symbols primarily by frequency and
* secondarily by symbol value. As an optimization, the array used for
* this purpose ('A') shares storage with the space in which we will
* eventually return the codewords.
*/
num_used_syms = sort_symbols(num_syms, freqs, lens, A);
/*
* 'num_used_syms' is the number of symbols with nonzero frequency.
* This may be less than @num_syms. 'num_used_syms' is also the number
* of entries in 'A' that are valid. Each entry consists of a distinct
* symbol and a nonzero frequency packed into a 32-bit integer.
*/
/*
* Handle special cases where only 0 or 1 symbols were used (had nonzero
* frequency).
*/
if (unlikely(num_used_syms == 0)) {
/*
* Code is empty. sort_symbols() already set all lengths to 0,
* so there is nothing more to do.
*/
return;
}
if (unlikely(num_used_syms == 1)) {
/*
* Only one symbol was used, so we only need one codeword. But
* two codewords are needed to form the smallest complete
* Huffman code, which uses codewords 0 and 1. Therefore, we
* choose another symbol to which to assign a codeword. We use
* 0 (if the used symbol is not 0) or 1 (if the used symbol is
* 0). In either case, the lesser-valued symbol must be
* assigned codeword 0 so that the resulting code is canonical.
*/
unsigned sym = A[0] & SYMBOL_MASK;
unsigned nonzero_idx = sym ? sym : 1;
codewords[0] = 0;
lens[0] = 1;
codewords[nonzero_idx] = 1;
lens[nonzero_idx] = 1;
return;
}
/*
* Build a stripped-down version of the Huffman tree, sharing the array
* 'A' with the symbol values. Then extract length counts from the tree
* and use them to generate the final codewords.
*/
build_tree(A, num_used_syms);
{
unsigned len_counts[MAX_CODEWORD_LEN + 1];
compute_length_counts(A, num_used_syms - 2,
len_counts, max_codeword_len);
gen_codewords(A, lens, len_counts, max_codeword_len, num_syms);
}
}
wimlib-1.14.5/src/pattern.c 0000644 0001750 0001750 00000013207 15137020663 012775 0 ustar 00e e /*
* pattern.c
*
* Wildcard pattern matching functions.
*/
/*
* Copyright (C) 2013, 2015 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/paths.h"
#include "wimlib/pattern.h"
static bool
string_matches_pattern(const tchar *string, const tchar * const string_end,
const tchar *pattern, const tchar * const pattern_end)
{
for (; string != string_end; string++, pattern++) {
if (pattern == pattern_end)
return false;
if (*pattern == T('*')) {
return string_matches_pattern(string, string_end,
pattern + 1, pattern_end) ||
string_matches_pattern(string + 1, string_end,
pattern, pattern_end);
}
if (*string != *pattern && *pattern != T('?') &&
!(default_ignore_case &&
totlower(*string) == totlower(*pattern)))
return false;
}
while (pattern != pattern_end && *pattern == T('*'))
pattern++;
return pattern == pattern_end;
}
/* Advance past zero or more path separators. */
static const tchar *
advance_to_next_component(const tchar *p)
{
while (*p == WIM_PATH_SEPARATOR)
p++;
return p;
}
/* Advance past a nonempty path component. */
static const tchar *
advance_through_component(const tchar *p)
{
do {
p++;
} while (*p && *p != WIM_PATH_SEPARATOR);
return p;
}
/*
* Determine whether a path matches a wildcard pattern.
*
* @path
* The null-terminated path string to match.
* @pattern
* The null-terminated wildcard pattern to match. It can contain the
* wildcard characters '*' (which matches zero or more characters) and '?'
* (which matches any single character). If there is no leading path
* separator, then the match is attempted with the filename component of
* @path only; otherwise, the match is attempted with the entire @path.
* @match_flags
* MATCH_* flags, see the flag definitions.
*
* @path and @pattern can both contain path separators (character
* WIM_PATH_SEPARATOR). Leading and trailing path separators are not
* significant, except when determining whether to match only the filename
* component as noted above. The lengths of interior path separator sequences
* are not significant. The '*' and '?' characters act within a single path
* component only (they do not match path separators).
*
* Matching is done with the default case sensitivity behavior.
*
* Returns %true iff the path matched the pattern.
*/
bool
match_path(const tchar *path, const tchar *pattern, int match_flags)
{
/* Filename only? */
if (*pattern != WIM_PATH_SEPARATOR)
path = path_basename(path);
for (;;) {
const tchar *path_component_end;
const tchar *pattern_component_end;
path = advance_to_next_component(path);
pattern = advance_to_next_component(pattern);
/* Is the pattern exhausted? */
if (!*pattern)
return !*path || (match_flags & MATCH_RECURSIVELY);
/* Is the path exhausted (but not the pattern)? */
if (!*path)
return (match_flags & MATCH_ANCESTORS);
path_component_end = advance_through_component(path);
pattern_component_end = advance_through_component(pattern);
/* Do the components match? */
if (!string_matches_pattern(path, path_component_end,
pattern, pattern_component_end))
return false;
path = path_component_end;
pattern = pattern_component_end;
}
}
/*
* Expand a path pattern in an in-memory tree of dentries.
*
* @root
* The root of the directory tree in which to expand the pattern.
* @pattern
* The path pattern to expand, which may contain the '*' and '?' wildcard
* characters. Path separators must be WIM_PATH_SEPARATOR. Leading and
* trailing path separators are ignored. The default case sensitivity
* behavior is used.
* @consume_dentry
* A callback function which will receive each matched directory entry.
* @ctx
* Opaque context argument for @consume_dentry.
*
* @return 0 on success; a positive error code on failure; or the first nonzero
* value returned by @consume_dentry.
*/
int
expand_path_pattern(struct wim_dentry *root, const tchar *pattern,
int (*consume_dentry)(struct wim_dentry *, void *),
void *ctx)
{
const tchar *pattern_component_end;
struct wim_dentry *child;
if (!root)
return 0;
pattern = advance_to_next_component(pattern);
/* If there are no more components, then 'root' is matched. */
if (!*pattern)
return (*consume_dentry)(root, ctx);
pattern_component_end = advance_through_component(pattern);
/* For each child dentry that matches the current pattern component,
* recurse with the remainder of the pattern. */
for_dentry_child(child, root) {
const tchar *name;
size_t name_nbytes;
int ret;
ret = utf16le_get_tstr(child->d_name, child->d_name_nbytes,
&name, &name_nbytes);
if (ret)
return ret;
if (string_matches_pattern(name, &name[name_nbytes / sizeof(tchar)],
pattern, pattern_component_end))
ret = expand_path_pattern(child, pattern_component_end,
consume_dentry, ctx);
utf16le_put_tstr(name);
if (ret)
return ret;
}
return 0;
}
wimlib-1.14.5/src/win32_apply.c 0000644 0001750 0001750 00000305363 15137020663 013476 0 ustar 00e e /*
* win32_apply.c - Windows-specific code for applying files from a WIM image.
*/
/*
* Copyright 2013-2023 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef _WIN32
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/win32_common.h"
#include "wimlib/apply.h"
#include "wimlib/assert.h"
#include "wimlib/blob_table.h"
#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/error.h"
#include "wimlib/metadata.h"
#include "wimlib/object_id.h"
#include "wimlib/paths.h"
#include "wimlib/pattern.h"
#include "wimlib/reparse.h"
#include "wimlib/scan.h" /* for mangle_pat() and match_pattern_list() */
#include "wimlib/textfile.h"
#include "wimlib/wimboot.h"
#include "wimlib/wof.h"
#include "wimlib/xattr.h"
#include "wimlib/xml.h"
struct win32_apply_ctx {
/* Extract flags, the pointer to the WIMStruct, etc. */
struct apply_ctx common;
/* WIMBoot information, only filled in if WIMLIB_EXTRACT_FLAG_WIMBOOT
* was provided */
struct {
/* This array contains the WIM files registered with WOF on the
* target volume for this extraction operation. All WIMStructs
* in this array are distinct and have ->filename != NULL. */
struct wimboot_wim {
WIMStruct *wim;
u64 data_source_id;
u8 blob_table_hash[SHA1_HASH_SIZE];
} *wims;
size_t num_wims;
bool wof_running;
bool have_wrong_version_wims;
bool have_uncompressed_wims;
bool have_unsupported_compressed_resources;
bool have_huge_resources;
} wimboot;
/* External backing information */
struct string_list *prepopulate_pats;
void *mem_prepopulate_pats;
bool tried_to_load_prepopulate_list;
/* Open handle to the target directory */
HANDLE h_target;
/* NT namespace path to the target directory (buffer allocated) */
UNICODE_STRING target_ntpath;
/* Temporary buffer for building paths (buffer allocated) */
UNICODE_STRING pathbuf;
/* Object attributes to reuse for opening files in the target directory.
* (attr.ObjectName == &pathbuf) and (attr.RootDirectory == h_target).
*/
OBJECT_ATTRIBUTES attr;
/* Temporary I/O status block for system calls */
IO_STATUS_BLOCK iosb;
/* Allocated buffer for creating "printable" paths from our
* target-relative NT paths */
wchar_t *print_buffer;
/* Allocated buffer for reading blob data when it cannot be extracted
* directly */
u8 *data_buffer;
/* Pointer to the next byte in @data_buffer to fill */
u8 *data_buffer_ptr;
/* Size allocated in @data_buffer */
size_t data_buffer_size;
/* Current offset in the raw encrypted file being written */
size_t encrypted_offset;
/* Current size of the raw encrypted file being written */
size_t encrypted_size;
/* Temporary buffer for reparse data */
struct reparse_buffer_disk rpbuf;
/* Temporary buffer for reparse data of "fixed" absolute symbolic links
* and junctions */
struct reparse_buffer_disk rpfixbuf;
/* Array of open handles to filesystem streams currently being written
*/
HANDLE open_handles[MAX_OPEN_FILES];
/* Number of handles in @open_handles currently open (filled in from the
* beginning of the array) */
unsigned num_open_handles;
/* For each currently open stream, whether we're writing to it in
* "sparse" mode or not. */
bool is_sparse_stream[MAX_OPEN_FILES];
/* Whether is_sparse_stream[] is true for any currently open stream */
bool any_sparse_streams;
/* List of dentries, joined by @d_tmp_list, that need to have reparse
* data extracted as soon as the whole blob has been read into
* @data_buffer. */
struct list_head reparse_dentries;
/* List of dentries, joined by @d_tmp_list, that need to have raw
* encrypted data extracted as soon as the whole blob has been read into
* @data_buffer. */
struct list_head encrypted_dentries;
/* Number of files for which we didn't have permission to set the full
* security descriptor. */
unsigned long partial_security_descriptors;
/* Number of files for which we didn't have permission to set any part
* of the security descriptor. */
unsigned long no_security_descriptors;
/* Number of files for which we couldn't set the short name. */
unsigned long num_set_short_name_failures;
/* Number of files for which we couldn't remove the short name. */
unsigned long num_remove_short_name_failures;
/* Number of files on which we couldn't set System Compression. */
unsigned long num_system_compression_failures;
/* The number of files which, for compatibility with the Windows
* bootloader, were not compressed using the requested system
* compression format. This includes matches with the hardcoded pattern
* list only; it does not include matches with patterns in
* [PrepopulateList]. */
unsigned long num_system_compression_exclusions;
/* Number of files for which we couldn't set the object ID. */
unsigned long num_object_id_failures;
/* Number of files for which we couldn't set extended attributes. */
unsigned long num_xattr_failures;
/* The Windows build number of the image being applied, or 0 if unknown.
*/
u64 windows_build_number;
/* Have we tried to enable short name support on the target volume yet?
*/
bool tried_to_enable_short_names;
};
/* Get the drive letter from a Windows path, or return the null character if the
* path is relative. */
static wchar_t
get_drive_letter(const wchar_t *path)
{
/* Skip \\?\ prefix */
if (!wcsncmp(path, L"\\\\?\\", 4))
path += 4;
/* Return drive letter if valid */
if (((path[0] >= L'a' && path[0] <= L'z') ||
(path[0] >= L'A' && path[0] <= L'Z')) && path[1] == L':')
return path[0];
return L'\0';
}
static void
get_vol_flags(const wchar_t *target, DWORD *vol_flags_ret,
bool *short_names_supported_ret)
{
wchar_t filesystem_name[MAX_PATH + 1];
wchar_t drive[4];
wchar_t *volume = NULL;
*vol_flags_ret = 0;
*short_names_supported_ret = false;
drive[0] = get_drive_letter(target);
if (drive[0]) {
drive[1] = L':';
drive[2] = L'\\';
drive[3] = L'\0';
volume = drive;
}
if (!GetVolumeInformation(volume, NULL, 0, NULL, NULL,
vol_flags_ret, filesystem_name,
ARRAY_LEN(filesystem_name)))
{
win32_warning(GetLastError(),
L"Failed to get volume information for \"%ls\"",
target);
return;
}
if (wcsstr(filesystem_name, L"NTFS")) {
/*
* FILE_SUPPORTS_HARD_LINKS and
* FILE_SUPPORTS_EXTENDED_ATTRIBUTES are only supported on
* Windows 7 and later. Force them on anyway if the filesystem
* is NTFS.
*/
*vol_flags_ret |= FILE_SUPPORTS_HARD_LINKS;
*vol_flags_ret |= FILE_SUPPORTS_EXTENDED_ATTRIBUTES;
/* There's no volume flag for short names, but according to the
* MS documentation they are only user-settable on NTFS. */
*short_names_supported_ret = true;
}
}
static const wchar_t *
current_path(struct win32_apply_ctx *ctx);
static void
build_extraction_path(const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx);
static int
report_dentry_apply_error(const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx, int ret)
{
build_extraction_path(dentry, ctx);
return report_apply_error(&ctx->common, ret, current_path(ctx));
}
static inline int
check_apply_error(const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx, int ret)
{
if (unlikely(ret))
ret = report_dentry_apply_error(dentry, ctx, ret);
return ret;
}
static int
win32_get_supported_features(const wchar_t *target,
struct wim_features *supported_features)
{
DWORD vol_flags;
bool short_names_supported;
/* Query the features of the target volume. */
get_vol_flags(target, &vol_flags, &short_names_supported);
supported_features->readonly_files = 1;
supported_features->hidden_files = 1;
supported_features->system_files = 1;
supported_features->archive_files = 1;
if (vol_flags & FILE_FILE_COMPRESSION)
supported_features->compressed_files = 1;
if (vol_flags & FILE_SUPPORTS_ENCRYPTION) {
supported_features->encrypted_files = 1;
supported_features->encrypted_directories = 1;
}
supported_features->not_context_indexed_files = 1;
if (vol_flags & FILE_SUPPORTS_SPARSE_FILES)
supported_features->sparse_files = 1;
if (vol_flags & FILE_NAMED_STREAMS)
supported_features->named_data_streams = 1;
if (vol_flags & FILE_SUPPORTS_HARD_LINKS)
supported_features->hard_links = 1;
if (vol_flags & FILE_SUPPORTS_REPARSE_POINTS)
supported_features->reparse_points = 1;
if (vol_flags & FILE_PERSISTENT_ACLS)
supported_features->security_descriptors = 1;
if (short_names_supported)
supported_features->short_names = 1;
if (vol_flags & FILE_SUPPORTS_OBJECT_IDS)
supported_features->object_ids = 1;
supported_features->timestamps = 1;
if (vol_flags & FILE_CASE_SENSITIVE_SEARCH) {
/*
* The filesystem supports case-sensitive filenames. But does
* the operating system as well? This normally requires the
* registry setting ObCaseInsensitive=0. We can test it
* indirectly by attempting to open the "\SystemRoot" symbolic
* link using a name with the wrong case. If we get
* STATUS_OBJECT_NAME_NOT_FOUND instead of STATUS_ACCESS_DENIED,
* then case-sensitive names must be enabled.
*/
UNICODE_STRING path;
OBJECT_ATTRIBUTES attr;
HANDLE h;
NTSTATUS status;
RtlInitUnicodeString(&path, L"\\systemroot");
InitializeObjectAttributes(&attr, &path, 0, NULL, NULL);
status = NtOpenSymbolicLinkObject(&h, 0, &attr);
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
supported_features->case_sensitive_filenames = 1;
}
if (vol_flags & FILE_SUPPORTS_EXTENDED_ATTRIBUTES)
supported_features->xattrs = 1;
return 0;
}
#define COMPACT_FLAGS (WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS4K | \
WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS8K | \
WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS16K | \
WIMLIB_EXTRACT_FLAG_COMPACT_LZX)
/*
* If not done already, load the patterns from the [PrepopulateList] section of
* WimBootCompress.ini in the WIM image being extracted.
*
* Note: WimBootCompress.ini applies to both types of "external backing":
*
* - WIM backing ("WIMBoot" - Windows 8.1 and later)
* - File backing ("System Compression" - Windows 10 and later)
*/
static int
load_prepopulate_pats(struct win32_apply_ctx *ctx)
{
const wchar_t *path = L"\\Windows\\System32\\WimBootCompress.ini";
struct wim_dentry *dentry;
const struct blob_descriptor *blob;
int ret;
void *buf;
struct string_list *strings;
void *mem;
struct text_file_section sec;
if (ctx->tried_to_load_prepopulate_list)
return 0;
ctx->tried_to_load_prepopulate_list = true;
dentry = get_dentry(ctx->common.wim, path, WIMLIB_CASE_INSENSITIVE);
if (!dentry ||
(dentry->d_inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
FILE_ATTRIBUTE_REPARSE_POINT |
FILE_ATTRIBUTE_ENCRYPTED)) ||
!(blob = inode_get_blob_for_unnamed_data_stream(dentry->d_inode,
ctx->common.wim->blob_table)))
{
WARNING("%ls does not exist in the WIM image.\n"
" The default configuration will be used instead; it assumes that all\n"
" files are valid for external backing regardless of path, equivalent\n"
" to an empty [PrepopulateList] section.", path);
return WIMLIB_ERR_PATH_DOES_NOT_EXIST;
}
ret = read_blob_into_alloc_buf(blob, &buf);
if (ret)
return ret;
strings = CALLOC(1, sizeof(struct string_list));
if (!strings) {
FREE(buf);
return WIMLIB_ERR_NOMEM;
}
sec.name = T("PrepopulateList");
sec.strings = strings;
ret = load_text_file(path, buf, blob->size, &mem, &sec, 1,
LOAD_TEXT_FILE_REMOVE_QUOTES |
LOAD_TEXT_FILE_NO_WARNINGS,
mangle_pat);
STATIC_ASSERT(OS_PREFERRED_PATH_SEPARATOR == WIM_PATH_SEPARATOR);
FREE(buf);
if (ret) {
FREE(strings);
return ret;
}
ctx->prepopulate_pats = strings;
ctx->mem_prepopulate_pats = mem;
return 0;
}
/* Returns %true if the specified absolute path to a file in the WIM image can
* be subject to external backing when extracted. Otherwise returns %false. */
static bool
can_externally_back_path(const wchar_t *path, const struct win32_apply_ctx *ctx)
{
/* Does the path match a pattern given in the [PrepopulateList] section
* of WimBootCompress.ini? */
if (ctx->prepopulate_pats && match_pattern_list(path, ctx->prepopulate_pats,
MATCH_RECURSIVELY))
return false;
/* Since we attempt to modify the SYSTEM registry after it's extracted
* (see end_wimboot_extraction()), it can't be extracted as externally
* backed. This extends to associated files such as SYSTEM.LOG that
* also must be writable in order to write to the registry. Normally,
* SYSTEM is in [PrepopulateList], and the SYSTEM.* files match patterns
* in [ExclusionList] and therefore are not captured in the WIM at all.
* However, a WIM that wasn't specifically captured in "WIMBoot mode"
* may contain SYSTEM.* files. So to make things "just work", hard-code
* the pattern. */
if (match_path(path, L"\\Windows\\System32\\config\\SYSTEM*", 0))
return false;
return true;
}
/* Can the specified WIM resource be used as the source of an external backing
* for the wof.sys WIM provider? */
static bool
is_resource_valid_for_external_backing(const struct wim_resource_descriptor *rdesc,
struct win32_apply_ctx *ctx)
{
/* Must be the original WIM file format. This check excludes pipable
* resources and solid resources. It also excludes other resources
* contained in such files even if they would be otherwise compatible.
*/
if (rdesc->wim->hdr.magic != WIM_MAGIC ||
rdesc->wim->hdr.wim_version != WIM_VERSION_DEFAULT)
{
ctx->wimboot.have_wrong_version_wims = true;
return false;
}
/*
* Whitelist of compression types and chunk sizes supported by
* Microsoft's WOF driver.
*
* Notes:
* - Uncompressed WIMs result in BSOD. However, this only applies to
* the WIM file itself, not to uncompressed resources in a WIM file
* that is otherwise compressed.
* - XPRESS 64K sometimes appears to work, but sometimes it causes
* reads to fail with STATUS_UNSUCCESSFUL.
*/
switch (rdesc->compression_type) {
case WIMLIB_COMPRESSION_TYPE_NONE:
if (rdesc->wim->compression_type == WIMLIB_COMPRESSION_TYPE_NONE) {
ctx->wimboot.have_uncompressed_wims = true;
return false;
}
break;
case WIMLIB_COMPRESSION_TYPE_XPRESS:
switch (rdesc->chunk_size) {
case 4096:
case 8192:
case 16384:
case 32768:
break;
default:
ctx->wimboot.have_unsupported_compressed_resources = true;
return false;
}
break;
case WIMLIB_COMPRESSION_TYPE_LZX:
switch (rdesc->chunk_size) {
case 32768:
break;
default:
ctx->wimboot.have_unsupported_compressed_resources = true;
return false;
}
break;
default:
ctx->wimboot.have_unsupported_compressed_resources = true;
return false;
}
/* Microsoft's WoF driver errors out if it tries to satisfy a read with
* ending offset >= 4 GiB from an externally backed file. */
if (rdesc->uncompressed_size > 4200000000) {
ctx->wimboot.have_huge_resources = true;
return false;
}
return true;
}
#define EXTERNAL_BACKING_NOT_ENABLED -1
#define EXTERNAL_BACKING_NOT_POSSIBLE -2
#define EXTERNAL_BACKING_EXCLUDED -3
/*
* Determines whether the specified file will be externally backed. Returns a
* negative status code if no, 0 if yes, or a positive wimlib error code on
* error. If the file is excluded from external backing based on its path, then
* *excluded_dentry_ret is set to the dentry for the path that matched the
* exclusion rule.
*
* Note that this logic applies to both types of "external backing":
*
* - WIM backing ("WIMBoot" - Windows 8.1 and later)
* - File backing ("System Compression" - Windows 10 and later)
*
* However, in the case of WIM backing we also need to validate that the WIM
* resource that would be the source of the backing is supported by the wof.sys
* WIM provider.
*/
static int
will_externally_back_inode(struct wim_inode *inode, struct win32_apply_ctx *ctx,
const struct wim_dentry **excluded_dentry_ret,
bool wimboot_mode)
{
struct wim_dentry *dentry;
struct blob_descriptor *blob;
int ret;
if (load_prepopulate_pats(ctx) == WIMLIB_ERR_NOMEM)
return WIMLIB_ERR_NOMEM;
if (inode->i_can_externally_back)
return 0;
/* This may do redundant checks because the cached value
* i_can_externally_back is 2-state (as opposed to 3-state:
* unknown/no/yes). But most files can be externally backed, so this
* way is fine. */
if (inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
FILE_ATTRIBUTE_REPARSE_POINT |
FILE_ATTRIBUTE_ENCRYPTED))
return EXTERNAL_BACKING_NOT_POSSIBLE;
blob = inode_get_blob_for_unnamed_data_stream_resolved(inode);
if (!blob)
return EXTERNAL_BACKING_NOT_POSSIBLE;
if (wimboot_mode &&
(blob->blob_location != BLOB_IN_WIM ||
!is_resource_valid_for_external_backing(blob->rdesc, ctx)))
return EXTERNAL_BACKING_NOT_POSSIBLE;
/*
* We need to check the patterns in [PrepopulateList] against every name
* of the inode, in case any of them match.
*/
inode_for_each_extraction_alias(dentry, inode) {
ret = calculate_dentry_full_path(dentry);
if (ret)
return ret;
if (!can_externally_back_path(dentry->d_full_path, ctx)) {
if (excluded_dentry_ret)
*excluded_dentry_ret = dentry;
return EXTERNAL_BACKING_EXCLUDED;
}
}
inode->i_can_externally_back = 1;
return 0;
}
/*
* Determines if the unnamed data stream of a file will be created as a WIM
* external backing (a "WIMBoot pointer file"), as opposed to a standard
* extraction.
*/
static int
win32_will_back_from_wim(struct wim_dentry *dentry, struct apply_ctx *_ctx)
{
struct win32_apply_ctx *ctx = (struct win32_apply_ctx *)_ctx;
if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT))
return EXTERNAL_BACKING_NOT_ENABLED;
return will_externally_back_inode(dentry->d_inode, ctx, NULL, true);
}
/* Find the WOF registration information for the specified WIM file. */
static struct wimboot_wim *
find_wimboot_wim(WIMStruct *wim_to_find, struct win32_apply_ctx *ctx)
{
for (size_t i = 0; i < ctx->wimboot.num_wims; i++)
if (wim_to_find == ctx->wimboot.wims[i].wim)
return &ctx->wimboot.wims[i];
wimlib_assert(0);
return NULL;
}
static int
set_backed_from_wim(HANDLE h, struct wim_inode *inode, struct win32_apply_ctx *ctx)
{
int ret;
const struct wim_dentry *excluded_dentry;
const struct blob_descriptor *blob;
const struct wimboot_wim *wimboot_wim;
ret = will_externally_back_inode(inode, ctx, &excluded_dentry, true);
if (ret > 0) /* Error. */
return ret;
if (ret < 0 && ret != EXTERNAL_BACKING_EXCLUDED)
return 0; /* Not externally backing, other than due to exclusion. */
if (unlikely(ret == EXTERNAL_BACKING_EXCLUDED)) {
/* Not externally backing due to exclusion. */
union wimlib_progress_info info;
build_extraction_path(excluded_dentry, ctx);
info.wimboot_exclude.path_in_wim = excluded_dentry->d_full_path;
info.wimboot_exclude.extraction_path = current_path(ctx);
return call_progress(ctx->common.progfunc,
WIMLIB_PROGRESS_MSG_WIMBOOT_EXCLUDE,
&info, ctx->common.progctx);
}
/* Externally backing. */
blob = inode_get_blob_for_unnamed_data_stream_resolved(inode);
wimboot_wim = find_wimboot_wim(blob->rdesc->wim, ctx);
if (unlikely(!wimboot_set_pointer(h,
blob,
wimboot_wim->data_source_id,
wimboot_wim->blob_table_hash,
ctx->wimboot.wof_running)))
{
const DWORD err = GetLastError();
build_extraction_path(inode_first_extraction_dentry(inode), ctx);
win32_error(err, L"\"%ls\": Couldn't set WIMBoot pointer data",
current_path(ctx));
return WIMLIB_ERR_WIMBOOT;
}
return 0;
}
/* Calculates the SHA-1 message digest of the WIM's blob table. */
static int
hash_blob_table(WIMStruct *wim, u8 hash[SHA1_HASH_SIZE])
{
return wim_reshdr_to_hash(&wim->hdr.blob_table_reshdr, wim, hash);
}
static int
register_wim_with_wof(WIMStruct *wim, struct win32_apply_ctx *ctx)
{
struct wimboot_wim *p;
int ret;
/* Check if already registered */
for (size_t i = 0; i < ctx->wimboot.num_wims; i++)
if (wim == ctx->wimboot.wims[i].wim)
return 0;
/* Not yet registered */
p = REALLOC(ctx->wimboot.wims,
(ctx->wimboot.num_wims + 1) * sizeof(ctx->wimboot.wims[0]));
if (!p)
return WIMLIB_ERR_NOMEM;
ctx->wimboot.wims = p;
ctx->wimboot.wims[ctx->wimboot.num_wims].wim = wim;
ret = hash_blob_table(wim, ctx->wimboot.wims[ctx->wimboot.num_wims].blob_table_hash);
if (ret)
return ret;
ret = wimboot_alloc_data_source_id(wim->filename,
wim->hdr.guid,
ctx->common.wim->current_image,
ctx->common.target,
&ctx->wimboot.wims[ctx->wimboot.num_wims].data_source_id,
&ctx->wimboot.wof_running);
if (ret)
return ret;
ctx->wimboot.num_wims++;
return 0;
}
/* Prepare for doing a "WIMBoot" extraction by registering each source WIM file
* with WOF on the target volume. */
static int
start_wimboot_extraction(struct list_head *dentry_list, struct win32_apply_ctx *ctx)
{
int ret;
struct wim_dentry *dentry;
if (!xml_get_wimboot(ctx->common.wim->xml_info,
ctx->common.wim->current_image))
WARNING("The WIM image is not marked as WIMBoot compatible. This usually\n"
" means it is not intended to be used to back a Windows operating\n"
" system. Proceeding anyway.");
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
struct blob_descriptor *blob;
ret = win32_will_back_from_wim(dentry, &ctx->common);
if (ret > 0) /* Error */
return ret;
if (ret < 0) /* Won't externally back */
continue;
blob = inode_get_blob_for_unnamed_data_stream_resolved(dentry->d_inode);
ret = register_wim_with_wof(blob->rdesc->wim, ctx);
if (ret)
return ret;
}
if (ctx->wimboot.have_wrong_version_wims) {
WARNING("At least one of the source WIM files uses a version of the WIM\n"
" file format that not supported by Microsoft's wof.sys driver.\n"
" Files whose data is contained in one of these WIM files will be\n"
" extracted as full files rather than externally backed.");
}
if (ctx->wimboot.have_uncompressed_wims) {
WARNING("At least one of the source WIM files is uncompressed. Files whose\n"
" data is contained in an uncompressed WIM file will be extracted as\n"
" full files rather than externally backed, since uncompressed WIM\n"
" files are not supported by Microsoft's wof.sys driver.");
}
if (ctx->wimboot.have_unsupported_compressed_resources) {
WARNING("At least one of the source WIM files uses a compression format that\n"
" is not supported by Microsoft's wof.sys driver. Files whose data is\n"
" contained in a compressed resource in one of these WIM files will be\n"
" extracted as full files rather than externally backed. (The\n"
" compression formats supported by wof.sys are: XPRESS 4K, XPRESS 8K,\n"
" XPRESS 16K, XPRESS 32K, and LZX 32K.)");
}
if (ctx->wimboot.have_huge_resources) {
WARNING("Some files exceeded 4.2 GB in size. Such files will be extracted\n"
" as full files rather than externally backed, since very large files\n"
" are not supported by Microsoft's wof.sys driver.");
}
return 0;
}
static void
build_win32_extraction_path(const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx);
/* Sets WimBoot=1 in the extracted SYSTEM registry hive.
*
* WIMGAPI does this, and it's possible that it's important.
* But I don't know exactly what this value means to Windows. */
static int
end_wimboot_extraction(struct win32_apply_ctx *ctx)
{
struct wim_dentry *dentry;
wchar_t subkeyname[32];
LONG res;
LONG res2;
HKEY key;
DWORD value;
dentry = get_dentry(ctx->common.wim, L"\\Windows\\System32\\config\\SYSTEM",
WIMLIB_CASE_INSENSITIVE);
if (!dentry || !will_extract_dentry(dentry))
goto out;
if (!will_extract_dentry(wim_get_current_root_dentry(ctx->common.wim)))
goto out;
/* Not bothering to use the native routines (e.g. NtLoadKey()) for this.
* If this doesn't work, you probably also have many other problems. */
build_win32_extraction_path(dentry, ctx);
get_random_alnum_chars(subkeyname, 20);
subkeyname[20] = L'\0';
res = RegLoadKey(HKEY_LOCAL_MACHINE, subkeyname, ctx->pathbuf.Buffer);
if (res)
goto out_check_res;
wcscpy(&subkeyname[20], L"\\Setup");
res = RegCreateKeyEx(HKEY_LOCAL_MACHINE, subkeyname, 0, NULL,
REG_OPTION_BACKUP_RESTORE, 0, NULL, &key, NULL);
if (res)
goto out_unload_key;
value = 1;
res = RegSetValueEx(key, L"WimBoot", 0, REG_DWORD,
(const BYTE *)&value, sizeof(DWORD));
if (res)
goto out_close_key;
res = RegFlushKey(key);
out_close_key:
res2 = RegCloseKey(key);
if (!res)
res = res2;
out_unload_key:
subkeyname[20] = L'\0';
RegUnLoadKey(HKEY_LOCAL_MACHINE, subkeyname);
out_check_res:
if (res) {
/* Warning only. */
win32_warning(res, L"Failed to set \\Setup: dword \"WimBoot\"=1 "
"value in registry hive \"%ls\"",
ctx->pathbuf.Buffer);
}
out:
return 0;
}
/* Returns the number of wide characters needed to represent the path to the
* specified @dentry, relative to the target directory, when extracted.
*
* Does not include null terminator (not needed for NtCreateFile). */
static size_t
dentry_extraction_path_length(const struct wim_dentry *dentry)
{
size_t len = 0;
const struct wim_dentry *d;
d = dentry;
do {
len += d->d_extraction_name_nchars + 1;
d = d->d_parent;
} while (!dentry_is_root(d) && will_extract_dentry(d));
return --len; /* No leading slash */
}
/* Returns the length of the longest string that might need to be appended to
* the path to an alias of an inode to open or create a named data stream.
*
* If the inode has no named data streams, this will be 0. Otherwise, this will
* be 1 plus the length of the longest-named data stream, since the data stream
* name must be separated from the path by the ':' character. */
static size_t
inode_longest_named_data_stream_spec(const struct wim_inode *inode)
{
size_t max = 0;
for (unsigned i = 0; i < inode->i_num_streams; i++) {
const struct wim_inode_stream *strm = &inode->i_streams[i];
if (!stream_is_named_data_stream(strm))
continue;
size_t len = utf16le_len_chars(strm->stream_name);
if (len > max)
max = len;
}
if (max)
max += 1;
return max;
}
/* Find the length, in wide characters, of the longest path needed for
* extraction of any file in @dentry_list relative to the target directory.
*
* Accounts for named data streams, but does not include null terminator (not
* needed for NtCreateFile). */
static size_t
compute_path_max(struct list_head *dentry_list)
{
size_t max = 0;
const struct wim_dentry *dentry;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
size_t len;
len = dentry_extraction_path_length(dentry);
/* Account for named data streams */
len += inode_longest_named_data_stream_spec(dentry->d_inode);
if (len > max)
max = len;
}
return max;
}
/* Build the path at which to extract the @dentry, relative to the target
* directory.
*
* The path is saved in ctx->pathbuf. */
static void
build_extraction_path(const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx)
{
size_t len;
wchar_t *p;
const struct wim_dentry *d;
len = dentry_extraction_path_length(dentry);
ctx->pathbuf.Length = len * sizeof(wchar_t);
p = ctx->pathbuf.Buffer + len;
for (d = dentry;
!dentry_is_root(d->d_parent) && will_extract_dentry(d->d_parent);
d = d->d_parent)
{
p -= d->d_extraction_name_nchars;
if (d->d_extraction_name_nchars)
wmemcpy(p, d->d_extraction_name,
d->d_extraction_name_nchars);
*--p = '\\';
}
/* No leading slash */
p -= d->d_extraction_name_nchars;
wmemcpy(p, d->d_extraction_name, d->d_extraction_name_nchars);
}
/* Build the path at which to extract the @dentry, relative to the target
* directory, adding the suffix for a named data stream.
*
* The path is saved in ctx->pathbuf. */
static void
build_extraction_path_with_ads(const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx,
const wchar_t *stream_name,
size_t stream_name_nchars)
{
wchar_t *p;
build_extraction_path(dentry, ctx);
/* Add :NAME for named data stream */
p = ctx->pathbuf.Buffer + (ctx->pathbuf.Length / sizeof(wchar_t));
*p++ = L':';
wmemcpy(p, stream_name, stream_name_nchars);
ctx->pathbuf.Length += (1 + stream_name_nchars) * sizeof(wchar_t);
}
/* Build the Win32 namespace path to the specified @dentry when extracted.
*
* The path is saved in ctx->pathbuf and will be null terminated.
*
* XXX: We could get rid of this if it wasn't needed for the file encryption
* APIs, and the registry manipulation in WIMBoot mode. */
static void
build_win32_extraction_path(const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx)
{
build_extraction_path(dentry, ctx);
/* Prepend target_ntpath to our relative path, then change \??\ into \\?\ */
memmove(ctx->pathbuf.Buffer +
(ctx->target_ntpath.Length / sizeof(wchar_t)) + 1,
ctx->pathbuf.Buffer, ctx->pathbuf.Length);
memcpy(ctx->pathbuf.Buffer, ctx->target_ntpath.Buffer,
ctx->target_ntpath.Length);
ctx->pathbuf.Buffer[ctx->target_ntpath.Length / sizeof(wchar_t)] = L'\\';
ctx->pathbuf.Length += ctx->target_ntpath.Length + sizeof(wchar_t);
ctx->pathbuf.Buffer[ctx->pathbuf.Length / sizeof(wchar_t)] = L'\0';
wimlib_assert(ctx->pathbuf.Length >= 4 * sizeof(wchar_t) &&
!wmemcmp(ctx->pathbuf.Buffer, L"\\??\\", 4));
ctx->pathbuf.Buffer[1] = L'\\';
}
/* Returns a "printable" representation of the last relative NT path that was
* constructed with build_extraction_path() or build_extraction_path_with_ads().
*
* This will be overwritten by the next call to this function. */
static const wchar_t *
current_path(struct win32_apply_ctx *ctx)
{
wchar_t *p = ctx->print_buffer;
p = wmempcpy(p, ctx->common.target, ctx->common.target_nchars);
*p++ = L'\\';
p = wmempcpy(p, ctx->pathbuf.Buffer, ctx->pathbuf.Length / sizeof(wchar_t));
*p = L'\0';
return ctx->print_buffer;
}
/* Open handle to the target directory if it is not already open. If the target
* directory does not exist, this creates it. */
static int
open_target_directory(struct win32_apply_ctx *ctx)
{
NTSTATUS status;
if (ctx->h_target)
return 0;
ctx->attr.Length = sizeof(ctx->attr);
ctx->attr.RootDirectory = NULL;
ctx->attr.ObjectName = &ctx->target_ntpath;
/* Don't use FILE_OPEN_REPARSE_POINT here; we want the extraction to
* happen at the directory "pointed to" by the reparse point. */
status = NtCreateFile(&ctx->h_target,
FILE_TRAVERSE,
&ctx->attr,
&ctx->iosb,
NULL,
0,
FILE_SHARE_VALID_FLAGS,
FILE_OPEN_IF,
FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT,
NULL,
0);
if (!NT_SUCCESS(status)) {
winnt_error(status, L"Can't open or create directory \"%ls\"",
ctx->common.target);
return WIMLIB_ERR_OPENDIR;
}
ctx->attr.RootDirectory = ctx->h_target;
ctx->attr.ObjectName = &ctx->pathbuf;
return 0;
}
static void
close_target_directory(struct win32_apply_ctx *ctx)
{
if (ctx->h_target) {
NtClose(ctx->h_target);
ctx->h_target = NULL;
ctx->attr.RootDirectory = NULL;
}
}
/*
* Ensures the target directory exists and opens a handle to it, in preparation
* of using paths relative to it.
*/
static int
prepare_target(struct list_head *dentry_list, struct win32_apply_ctx *ctx)
{
int ret;
size_t path_max;
ret = win32_path_to_nt_path(ctx->common.target, &ctx->target_ntpath);
if (ret)
return ret;
ret = open_target_directory(ctx);
if (ret)
return ret;
path_max = compute_path_max(dentry_list);
/* Add some extra for building Win32 paths for the file encryption APIs,
* and ensure we have at least enough to potentially use an 8.3 name for
* the last component. */
path_max += max(2 + (ctx->target_ntpath.Length / sizeof(wchar_t)),
8 + 1 + 3);
ctx->pathbuf.MaximumLength = path_max * sizeof(wchar_t);
if (ctx->pathbuf.MaximumLength != path_max * sizeof(wchar_t)) {
/* Paths are too long for a UNICODE_STRING! */
ERROR("Some paths are too long to extract (> 32768 characters)!");
return WIMLIB_ERR_UNSUPPORTED;
}
ctx->pathbuf.Buffer = MALLOC(ctx->pathbuf.MaximumLength);
if (!ctx->pathbuf.Buffer)
return WIMLIB_ERR_NOMEM;
ctx->print_buffer = MALLOC((ctx->common.target_nchars + 1 + path_max + 1) *
sizeof(wchar_t));
if (!ctx->print_buffer)
return WIMLIB_ERR_NOMEM;
return 0;
}
/* When creating an inode that will have a short (DOS) name, we create it using
* the long name associated with the short name. This ensures that the short
* name gets associated with the correct long name. */
static struct wim_dentry *
first_extraction_alias(const struct wim_inode *inode)
{
struct wim_dentry *dentry;
inode_for_each_extraction_alias(dentry, inode)
if (dentry_has_short_name(dentry))
return dentry;
return inode_first_extraction_dentry(inode);
}
/*
* Set or clear FILE_ATTRIBUTE_COMPRESSED if the inherited value is different
* from the desired value.
*
* Note that you can NOT override the inherited value of
* FILE_ATTRIBUTE_COMPRESSED directly with NtCreateFile().
*/
static int
adjust_compression_attribute(HANDLE h, const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx)
{
const bool compressed = (dentry->d_inode->i_attributes &
FILE_ATTRIBUTE_COMPRESSED);
FILE_BASIC_INFORMATION info;
USHORT compression_state;
NTSTATUS status;
if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)
return 0;
if (!ctx->common.supported_features.compressed_files)
return 0;
/* Get current attributes */
status = NtQueryInformationFile(h, &ctx->iosb, &info, sizeof(info),
FileBasicInformation);
if (NT_SUCCESS(status) &&
compressed == !!(info.FileAttributes & FILE_ATTRIBUTE_COMPRESSED))
{
/* Nothing needs to be done. */
return 0;
}
/* Set the new compression state */
if (compressed)
compression_state = COMPRESSION_FORMAT_DEFAULT;
else
compression_state = COMPRESSION_FORMAT_NONE;
status = winnt_fsctl(h, FSCTL_SET_COMPRESSION,
&compression_state, sizeof(USHORT), NULL, 0, NULL);
if (NT_SUCCESS(status))
return 0;
winnt_error(status, L"Can't %s compression attribute on \"%ls\"",
(compressed ? "set" : "clear"), current_path(ctx));
return WIMLIB_ERR_SET_ATTRIBUTES;
}
static bool
need_sparse_flag(const struct wim_inode *inode,
const struct win32_apply_ctx *ctx)
{
return (inode->i_attributes & FILE_ATTRIBUTE_SPARSE_FILE) &&
ctx->common.supported_features.sparse_files;
}
static int
set_sparse_flag(HANDLE h, struct win32_apply_ctx *ctx)
{
NTSTATUS status;
status = winnt_fsctl(h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, NULL);
if (NT_SUCCESS(status))
return 0;
winnt_error(status, L"Can't set sparse flag on \"%ls\"",
current_path(ctx));
return WIMLIB_ERR_SET_ATTRIBUTES;
}
/* Try to enable short name support on the target volume. If successful, return
* true. If unsuccessful, issue a warning and return false. */
static bool
try_to_enable_short_names(const wchar_t *volume)
{
HANDLE h;
FILE_FS_PERSISTENT_VOLUME_INFORMATION info;
BOOL bret;
DWORD bytesReturned;
h = CreateFile(volume, GENERIC_WRITE,
FILE_SHARE_VALID_FLAGS, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE)
goto fail;
info.VolumeFlags = 0;
info.FlagMask = PERSISTENT_VOLUME_STATE_SHORT_NAME_CREATION_DISABLED;
info.Version = 1;
info.Reserved = 0;
bret = DeviceIoControl(h, FSCTL_SET_PERSISTENT_VOLUME_STATE,
&info, sizeof(info), NULL, 0,
&bytesReturned, NULL);
CloseHandle(h);
if (!bret)
goto fail;
return true;
fail:
win32_warning(GetLastError(),
L"Failed to enable short name support on %ls",
volume + 4);
return false;
}
static NTSTATUS
remove_conflicting_short_name(const struct wim_dentry *dentry, struct win32_apply_ctx *ctx)
{
wchar_t *name;
wchar_t *end;
NTSTATUS status;
HANDLE h;
size_t bufsize = offsetof(FILE_NAME_INFORMATION, FileName) +
(13 * sizeof(wchar_t));
u8 buf[bufsize] __attribute__((aligned(8)));
bool retried = false;
FILE_NAME_INFORMATION *info = (FILE_NAME_INFORMATION *)buf;
memset(buf, 0, bufsize);
/* Build the path with the short name. */
name = &ctx->pathbuf.Buffer[ctx->pathbuf.Length / sizeof(wchar_t)];
while (name != ctx->pathbuf.Buffer && *(name - 1) != L'\\')
name--;
end = mempcpy(name, dentry->d_short_name, dentry->d_short_name_nbytes);
ctx->pathbuf.Length = ((u8 *)end - (u8 *)ctx->pathbuf.Buffer);
/* Open the conflicting file (by short name). */
status = NtOpenFile(&h, GENERIC_WRITE | DELETE,
&ctx->attr, &ctx->iosb,
FILE_SHARE_VALID_FLAGS,
FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS(status)) {
winnt_warning(status, L"Can't open \"%ls\"", current_path(ctx));
goto out;
}
#if 0
WARNING("Overriding conflicting short name; path=\"%ls\"",
current_path(ctx));
#endif
/* Try to remove the short name on the conflicting file. */
retry:
status = NtSetInformationFile(h, &ctx->iosb, info, bufsize,
FileShortNameInformation);
if (status == STATUS_INVALID_PARAMETER && !retried) {
/* Microsoft forgot to make it possible to remove short names
* until Windows 7. Oops. Use a random short name instead. */
get_random_alnum_chars(info->FileName, 8);
wcscpy(&info->FileName[8], L".WLB");
info->FileNameLength = 12 * sizeof(wchar_t);
retried = true;
goto retry;
}
NtClose(h);
out:
build_extraction_path(dentry, ctx);
return status;
}
/* Set the short name on the open file @h which has been created at the location
* indicated by @dentry.
*
* Note that this may add, change, or remove the short name.
*
* @h must be opened with DELETE access.
*
* Returns 0 or WIMLIB_ERR_SET_SHORT_NAME. The latter only happens in
* STRICT_SHORT_NAMES mode.
*/
static int
set_short_name(HANDLE h, const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx)
{
if (!ctx->common.supported_features.short_names)
return 0;
/*
* Note: The size of the FILE_NAME_INFORMATION buffer must be such that
* FileName contains at least 2 wide characters (4 bytes). Otherwise,
* NtSetInformationFile() will return STATUS_INFO_LENGTH_MISMATCH. This
* is despite the fact that FileNameLength can validly be 0 or 2 bytes,
* with the former case being removing the existing short name if
* present, rather than setting one.
*
* The null terminator is seemingly optional, but to be safe we include
* space for it and zero all unused space.
*/
size_t bufsize = offsetof(FILE_NAME_INFORMATION, FileName) +
max(dentry->d_short_name_nbytes, sizeof(wchar_t)) +
sizeof(wchar_t);
u8 buf[bufsize] __attribute__((aligned(8)));
FILE_NAME_INFORMATION *info = (FILE_NAME_INFORMATION *)buf;
NTSTATUS status;
bool tried_to_remove_existing = false;
memset(buf, 0, bufsize);
info->FileNameLength = dentry->d_short_name_nbytes;
memcpy(info->FileName, dentry->d_short_name, dentry->d_short_name_nbytes);
retry:
status = NtSetInformationFile(h, &ctx->iosb, info, bufsize,
FileShortNameInformation);
if (NT_SUCCESS(status))
return 0;
if (status == STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME) {
if (dentry->d_short_name_nbytes == 0)
return 0;
if (!ctx->tried_to_enable_short_names) {
wchar_t volume[7];
int ret;
ctx->tried_to_enable_short_names = true;
ret = win32_get_drive_path(ctx->common.target,
volume);
if (ret)
return ret;
if (try_to_enable_short_names(volume))
goto retry;
}
}
/*
* Short names can conflict in several cases:
*
* - a file being extracted has a short name conflicting with an
* existing file
*
* - a file being extracted has a short name conflicting with another
* file being extracted (possible, but shouldn't happen)
*
* - a file being extracted has a short name that conflicts with the
* automatically generated short name of a file we previously
* extracted, but failed to set the short name for. Sounds unlikely,
* but this actually does happen fairly often on versions of Windows
* prior to Windows 7 because they do not support removing short names
* from files.
*/
if (unlikely(status == STATUS_OBJECT_NAME_COLLISION) &&
dentry->d_short_name_nbytes && !tried_to_remove_existing)
{
tried_to_remove_existing = true;
status = remove_conflicting_short_name(dentry, ctx);
if (NT_SUCCESS(status))
goto retry;
}
/* By default, failure to set short names is not an error (since short
* names aren't too important anymore...). */
if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES)) {
if (dentry->d_short_name_nbytes)
ctx->num_set_short_name_failures++;
else
ctx->num_remove_short_name_failures++;
return 0;
}
winnt_error(status, L"Can't set short name on \"%ls\"", current_path(ctx));
return WIMLIB_ERR_SET_SHORT_NAME;
}
/*
* A wrapper around NtCreateFile() to make it slightly more usable...
* This uses the path currently constructed in ctx->pathbuf.
*
* Also, we always specify SYNCHRONIZE access, FILE_OPEN_FOR_BACKUP_INTENT, and
* FILE_OPEN_REPARSE_POINT.
*/
static NTSTATUS
do_create_file(PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
PLARGE_INTEGER AllocationSize,
ULONG FileAttributes,
ULONG CreateDisposition,
ULONG CreateOptions,
struct win32_apply_ctx *ctx)
{
return NtCreateFile(FileHandle,
DesiredAccess | SYNCHRONIZE,
&ctx->attr,
&ctx->iosb,
AllocationSize,
FileAttributes,
FILE_SHARE_VALID_FLAGS,
CreateDisposition,
CreateOptions |
FILE_OPEN_FOR_BACKUP_INTENT |
FILE_OPEN_REPARSE_POINT,
NULL,
0);
}
/* Like do_create_file(), but builds the extraction path of the @dentry first.
*/
static NTSTATUS
create_file(PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
PLARGE_INTEGER AllocationSize,
ULONG FileAttributes,
ULONG CreateDisposition,
ULONG CreateOptions,
const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx)
{
build_extraction_path(dentry, ctx);
return do_create_file(FileHandle,
DesiredAccess,
AllocationSize,
FileAttributes,
CreateDisposition,
CreateOptions,
ctx);
}
static int
delete_file_or_stream(struct win32_apply_ctx *ctx)
{
NTSTATUS status;
HANDLE h;
ULONG perms = DELETE;
ULONG flags = FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE;
/* First try opening the file with FILE_DELETE_ON_CLOSE. In most cases,
* all we have to do is that plus close the file handle. */
retry:
status = do_create_file(&h, perms, NULL, 0, FILE_OPEN, flags, ctx);
if (unlikely(status == STATUS_CANNOT_DELETE)) {
/* This error occurs for files with FILE_ATTRIBUTE_READONLY set.
* Try an alternate approach: first open the file without
* FILE_DELETE_ON_CLOSE, then reset the file attributes, then
* set the "delete" disposition on the handle. */
if (flags & FILE_DELETE_ON_CLOSE) {
flags &= ~FILE_DELETE_ON_CLOSE;
perms |= FILE_WRITE_ATTRIBUTES;
goto retry;
}
}
if (unlikely(!NT_SUCCESS(status))) {
winnt_error(status, L"Can't open \"%ls\" for deletion "
"(perms=%x, flags=%x)",
current_path(ctx), (u32)perms, (u32)flags);
return WIMLIB_ERR_OPEN;
}
if (unlikely(!(flags & FILE_DELETE_ON_CLOSE))) {
FILE_BASIC_INFORMATION basic_info =
{ .FileAttributes = FILE_ATTRIBUTE_NORMAL };
status = NtSetInformationFile(h, &ctx->iosb, &basic_info,
sizeof(basic_info),
FileBasicInformation);
if (!NT_SUCCESS(status)) {
winnt_error(status, L"Can't reset attributes of \"%ls\" "
"to prepare for deletion", current_path(ctx));
NtClose(h);
return WIMLIB_ERR_SET_ATTRIBUTES;
}
FILE_DISPOSITION_INFORMATION disp_info =
{ .DoDeleteFile = TRUE };
status = NtSetInformationFile(h, &ctx->iosb, &disp_info,
sizeof(disp_info),
FileDispositionInformation);
if (!NT_SUCCESS(status)) {
winnt_error(status, L"Can't set delete-on-close "
"disposition on \"%ls\"", current_path(ctx));
NtClose(h);
return WIMLIB_ERR_SET_ATTRIBUTES;
}
}
status = NtClose(h);
if (unlikely(!NT_SUCCESS(status))) {
winnt_error(status, L"Error closing \"%ls\" after setting "
"delete-on-close disposition", current_path(ctx));
return WIMLIB_ERR_OPEN;
}
return 0;
}
/*
* Create a nondirectory file or named data stream at the current path,
* superseding any that already exists at that path. If successful, return an
* open handle to the file or named data stream with the requested permissions.
*/
static int
supersede_file_or_stream(struct win32_apply_ctx *ctx, DWORD perms,
HANDLE *h_ret)
{
NTSTATUS status;
bool retried = false;
/* FILE_ATTRIBUTE_SYSTEM is needed to ensure that
* FILE_ATTRIBUTE_ENCRYPTED doesn't get set before we want it to be. */
retry:
status = do_create_file(h_ret,
perms,
NULL,
FILE_ATTRIBUTE_SYSTEM,
FILE_CREATE,
FILE_NON_DIRECTORY_FILE,
ctx);
if (likely(NT_SUCCESS(status)))
return 0;
/* STATUS_OBJECT_NAME_COLLISION means that the file or stream already
* exists. Delete the existing file or stream, then try again.
*
* Note: we don't use FILE_OVERWRITE_IF or FILE_SUPERSEDE because of
* problems with certain file attributes, especially
* FILE_ATTRIBUTE_ENCRYPTED. FILE_SUPERSEDE is also broken in the
* Windows PE ramdisk. */
if (status == STATUS_OBJECT_NAME_COLLISION && !retried) {
int ret = delete_file_or_stream(ctx);
if (ret)
return ret;
retried = true;
goto retry;
}
winnt_error(status, L"Can't create \"%ls\"", current_path(ctx));
return WIMLIB_ERR_OPEN;
}
/* Set the reparse point @rpbuf of length @rpbuflen on the extracted file
* corresponding to the WIM dentry @dentry. */
static int
do_set_reparse_point(const struct wim_dentry *dentry,
const struct reparse_buffer_disk *rpbuf, u16 rpbuflen,
struct win32_apply_ctx *ctx)
{
NTSTATUS status;
HANDLE h;
status = create_file(&h, GENERIC_WRITE, NULL,
0, FILE_OPEN, 0, dentry, ctx);
if (!NT_SUCCESS(status))
goto fail;
status = winnt_fsctl(h, FSCTL_SET_REPARSE_POINT,
rpbuf, rpbuflen, NULL, 0, NULL);
NtClose(h);
if (NT_SUCCESS(status))
return 0;
/* On Windows, by default only the Administrator can create symbolic
* links for some reason. By default we just issue a warning if this
* appears to be the problem. Use WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS
* to get a hard error. */
if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS)
&& (status == STATUS_PRIVILEGE_NOT_HELD ||
status == STATUS_ACCESS_DENIED)
&& (dentry->d_inode->i_reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK ||
dentry->d_inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT))
{
WARNING("Can't create symbolic link \"%ls\"! \n"
" (Need Administrator rights, or at least "
"the\n"
" SeCreateSymbolicLink privilege.)",
current_path(ctx));
return 0;
}
fail:
winnt_error(status, L"Can't set reparse data on \"%ls\"",
current_path(ctx));
return WIMLIB_ERR_SET_REPARSE_DATA;
}
/*
* Create empty named data streams and potentially a reparse point for the
* specified file, if any.
*
* Since these won't have blob descriptors, they won't show up in the call to
* extract_blob_list(). Hence the need for the special case.
*/
static int
create_empty_streams(const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx)
{
const struct wim_inode *inode = dentry->d_inode;
int ret;
for (unsigned i = 0; i < inode->i_num_streams; i++) {
const struct wim_inode_stream *strm = &inode->i_streams[i];
if (stream_blob_resolved(strm) != NULL)
continue;
if (strm->stream_type == STREAM_TYPE_REPARSE_POINT &&
ctx->common.supported_features.reparse_points)
{
u8 buf[REPARSE_DATA_OFFSET] __attribute__((aligned(8)));
struct reparse_buffer_disk *rpbuf =
(struct reparse_buffer_disk *)buf;
complete_reparse_point(rpbuf, inode, 0);
ret = do_set_reparse_point(dentry, rpbuf,
REPARSE_DATA_OFFSET, ctx);
if (ret)
return ret;
} else if (stream_is_named_data_stream(strm) &&
ctx->common.supported_features.named_data_streams)
{
HANDLE h;
build_extraction_path_with_ads(dentry, ctx,
strm->stream_name,
utf16le_len_chars(strm->stream_name));
/*
* Note: do not request any permissions on the handle.
* Otherwise, we may encounter a Windows bug where the
* parent directory DACL denies read access to the new
* named data stream, even when using backup semantics!
*/
ret = supersede_file_or_stream(ctx, 0, &h);
build_extraction_path(dentry, ctx);
if (ret)
return ret;
NtClose(h);
}
}
return 0;
}
/*
* Creates the directory named by @dentry, or uses an existing directory at that
* location. If necessary, sets the short name and/or fixes compression and
* encryption attributes.
*
* Returns 0, WIMLIB_ERR_MKDIR, or WIMLIB_ERR_SET_SHORT_NAME.
*/
static int
create_directory(const struct wim_dentry *dentry, struct win32_apply_ctx *ctx)
{
DWORD perms;
NTSTATUS status;
HANDLE h;
int ret;
/* DELETE is needed for set_short_name(); GENERIC_READ and GENERIC_WRITE
* are needed for adjust_compression_attribute(). */
perms = GENERIC_READ | GENERIC_WRITE;
if (!dentry_is_root(dentry))
perms |= DELETE;
/* FILE_ATTRIBUTE_SYSTEM is needed to ensure that
* FILE_ATTRIBUTE_ENCRYPTED doesn't get set before we want it to be. */
status = create_file(&h, perms, NULL, FILE_ATTRIBUTE_SYSTEM,
FILE_OPEN_IF, FILE_DIRECTORY_FILE, dentry, ctx);
if (unlikely(!NT_SUCCESS(status))) {
const wchar_t *path = current_path(ctx);
winnt_error(status, L"Can't create directory \"%ls\"", path);
/* Check for known issue with WindowsApps directory. */
if (status == STATUS_ACCESS_DENIED &&
(wcsstr(path, L"\\WindowsApps\\") ||
wcsstr(path, L"\\InfusedApps\\"))) {
ERROR(
"You seem to be trying to extract files to the WindowsApps directory.\n"
" Windows 8.1 and later use new file permissions in this directory that\n"
" cannot be overridden, even by backup/restore programs. To extract your\n"
" files anyway, you need to choose a different target directory, delete\n"
" the WindowsApps directory entirely, reformat the volume, do the\n"
" extraction from a non-broken operating system such as Windows 7 or\n"
" Linux, or wait for Microsoft to fix the design flaw in their operating\n"
" system. This is *not* a bug in wimlib. See this thread for more\n"
" information: https://wimlib.net/forums/viewtopic.php?f=1&t=261");
}
return WIMLIB_ERR_MKDIR;
}
if (ctx->iosb.Information == FILE_OPENED) {
/* If we opened an existing directory, try to clear its file
* attributes. As far as I know, this only actually makes a
* difference in the case where a FILE_ATTRIBUTE_READONLY
* directory has a named data stream which needs to be
* extracted. You cannot create a named data stream of such a
* directory, even though this contradicts Microsoft's
* documentation for FILE_ATTRIBUTE_READONLY which states it is
* not honored for directories! */
if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)) {
FILE_BASIC_INFORMATION basic_info =
{ .FileAttributes = FILE_ATTRIBUTE_NORMAL };
NtSetInformationFile(h, &ctx->iosb, &basic_info,
sizeof(basic_info),
FileBasicInformation);
}
}
if (!dentry_is_root(dentry)) {
ret = set_short_name(h, dentry, ctx);
if (ret)
goto out;
}
ret = adjust_compression_attribute(h, dentry, ctx);
out:
NtClose(h);
return ret;
}
/*
* Create all the directories being extracted, other than the target directory
* itself.
*
* Note: we don't honor directory hard links. However, we don't allow them to
* exist in WIM images anyway (see inode_fixup.c).
*/
static int
create_directories(struct list_head *dentry_list,
struct win32_apply_ctx *ctx)
{
const struct wim_dentry *dentry;
int ret;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
if (!(dentry->d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY))
continue;
/* Note: Here we include files with
* FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_REPARSE_POINT, but we
* wait until later to actually set the reparse data. */
ret = create_directory(dentry, ctx);
if (!ret)
ret = create_empty_streams(dentry, ctx);
ret = check_apply_error(dentry, ctx, ret);
if (ret)
return ret;
ret = report_file_created(&ctx->common);
if (ret)
return ret;
}
return 0;
}
/*
* Creates the nondirectory file named by @dentry.
*
* On success, returns an open handle to the file in @h_ret, with GENERIC_READ,
* GENERIC_WRITE, and DELETE access. Also, the path to the file will be saved
* in ctx->pathbuf. On failure, returns an error code.
*/
static int
create_nondirectory_inode(HANDLE *h_ret, const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx)
{
int ret;
HANDLE h;
build_extraction_path(dentry, ctx);
ret = supersede_file_or_stream(ctx,
GENERIC_READ | GENERIC_WRITE | DELETE,
&h);
if (ret)
goto out;
ret = adjust_compression_attribute(h, dentry, ctx);
if (ret)
goto out_close;
if (need_sparse_flag(dentry->d_inode, ctx)) {
ret = set_sparse_flag(h, ctx);
if (ret)
goto out_close;
}
ret = create_empty_streams(dentry, ctx);
if (ret)
goto out_close;
*h_ret = h;
return 0;
out_close:
NtClose(h);
out:
return ret;
}
/* Creates a hard link at the location named by @dentry to the file represented
* by the open handle @h. Or, if the target volume does not support hard links,
* create a separate file instead. */
static int
create_link(HANDLE h, const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx)
{
if (ctx->common.supported_features.hard_links) {
build_extraction_path(dentry, ctx);
size_t bufsize = offsetof(FILE_LINK_INFORMATION, FileName) +
ctx->pathbuf.Length + sizeof(wchar_t);
u8 buf[bufsize] __attribute__((aligned(8)));
FILE_LINK_INFORMATION *info = (FILE_LINK_INFORMATION *)buf;
NTSTATUS status;
info->ReplaceIfExists = TRUE;
info->RootDirectory = ctx->attr.RootDirectory;
info->FileNameLength = ctx->pathbuf.Length;
memcpy(info->FileName, ctx->pathbuf.Buffer, ctx->pathbuf.Length);
info->FileName[info->FileNameLength / 2] = L'\0';
/*
* Note: the null terminator isn't actually necessary, but if
* you don't add the extra character, you get
* STATUS_INFO_LENGTH_MISMATCH when FileNameLength is 2.
*/
/*
* When fuzzing with wlfuzz.exe, creating a hard link sometimes
* fails with STATUS_ACCESS_DENIED. However, it eventually
* succeeds when re-attempted...
*/
int i = 0;
do {
status = NtSetInformationFile(h, &ctx->iosb, info,
bufsize,
FileLinkInformation);
if (NT_SUCCESS(status))
return 0;
} while (++i < 32);
winnt_error(status, L"Failed to create link \"%ls\"",
current_path(ctx));
return WIMLIB_ERR_LINK;
} else {
HANDLE h2;
int ret;
ret = create_nondirectory_inode(&h2, dentry, ctx);
if (ret)
return ret;
NtClose(h2);
return 0;
}
}
/* Given an inode (represented by the open handle @h) for which one link has
* been created (named by @first_dentry), create the other links.
*
* Or, if the target volume does not support hard links, create separate files.
*
* Note: This uses ctx->pathbuf and does not reset it.
*/
static int
create_links(HANDLE h, const struct wim_dentry *first_dentry,
struct win32_apply_ctx *ctx)
{
const struct wim_inode *inode = first_dentry->d_inode;
const struct wim_dentry *dentry;
int ret;
inode_for_each_extraction_alias(dentry, inode) {
if (dentry != first_dentry) {
ret = create_link(h, dentry, ctx);
if (ret)
return ret;
}
}
return 0;
}
/* Create a nondirectory file, including all links. */
static int
create_nondirectory(struct wim_inode *inode, struct win32_apply_ctx *ctx)
{
struct wim_dentry *first_dentry;
HANDLE h;
int ret;
first_dentry = first_extraction_alias(inode);
/* Create first link. */
ret = create_nondirectory_inode(&h, first_dentry, ctx);
if (ret)
return ret;
/* Set short name. */
ret = set_short_name(h, first_dentry, ctx);
/* Create additional links, OR if hard links are not supported just
* create more files. */
if (!ret)
ret = create_links(h, first_dentry, ctx);
/* "WIMBoot" extraction: set external backing by the WIM file if needed. */
if (!ret && unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT))
ret = set_backed_from_wim(h, inode, ctx);
NtClose(h);
return ret;
}
/* Create all the nondirectory files being extracted, including all aliases
* (hard links). */
static int
create_nondirectories(struct list_head *dentry_list, struct win32_apply_ctx *ctx)
{
struct wim_dentry *dentry;
struct wim_inode *inode;
int ret;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
inode = dentry->d_inode;
if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
/* Call create_nondirectory() only once per inode */
if (dentry == inode_first_extraction_dentry(inode)) {
ret = create_nondirectory(inode, ctx);
ret = check_apply_error(dentry, ctx, ret);
if (ret)
return ret;
}
ret = report_file_created(&ctx->common);
if (ret)
return ret;
}
return 0;
}
static void
close_handles(struct win32_apply_ctx *ctx)
{
for (unsigned i = 0; i < ctx->num_open_handles; i++)
NtClose(ctx->open_handles[i]);
}
/* Prepare to read the next blob, which has size @blob_size, into an in-memory
* buffer. */
static bool
prepare_data_buffer(struct win32_apply_ctx *ctx, u64 blob_size)
{
if (blob_size > ctx->data_buffer_size) {
/* Larger buffer needed. */
void *new_buffer;
if ((size_t)blob_size != blob_size)
return false;
new_buffer = REALLOC(ctx->data_buffer, blob_size);
if (!new_buffer)
return false;
ctx->data_buffer = new_buffer;
ctx->data_buffer_size = blob_size;
}
/* On the first call this changes data_buffer_ptr from NULL, which tells
* extract_chunk() that the data buffer needs to be filled while reading
* the stream data. */
ctx->data_buffer_ptr = ctx->data_buffer;
return true;
}
static int
begin_extract_blob_instance(const struct blob_descriptor *blob,
struct wim_dentry *dentry,
const struct wim_inode_stream *strm,
struct win32_apply_ctx *ctx)
{
HANDLE h;
NTSTATUS status;
if (unlikely(strm->stream_type == STREAM_TYPE_REPARSE_POINT)) {
/* We can't write the reparse point stream directly; we must set
* it with FSCTL_SET_REPARSE_POINT, which requires that all the
* data be available. So, stage the data in a buffer. */
if (!prepare_data_buffer(ctx, blob->size))
return WIMLIB_ERR_NOMEM;
list_add_tail(&dentry->d_tmp_list, &ctx->reparse_dentries);
return 0;
}
if (unlikely(strm->stream_type == STREAM_TYPE_EFSRPC_RAW_DATA)) {
/* We can't write encrypted files directly; we must use
* WriteEncryptedFileRaw(), which requires providing the data
* through a callback function. This can't easily be combined
* with our own callback-based approach.
*
* The current workaround is to simply read the blob into memory
* and write the encrypted file from that.
*
* TODO: This isn't sufficient for extremely large encrypted
* files. Perhaps we should create an extra thread to write
* such files... */
if (!prepare_data_buffer(ctx, blob->size))
return WIMLIB_ERR_NOMEM;
list_add_tail(&dentry->d_tmp_list, &ctx->encrypted_dentries);
return 0;
}
/* It's a data stream (may be unnamed or named). */
wimlib_assert(strm->stream_type == STREAM_TYPE_DATA);
if (ctx->num_open_handles == MAX_OPEN_FILES) {
/* XXX: Fix this. But because of the checks in
* extract_blob_list(), this can now only happen on a filesystem
* that does not support hard links. */
ERROR("Can't extract data: too many open files!");
return WIMLIB_ERR_UNSUPPORTED;
}
if (unlikely(stream_is_named(strm))) {
build_extraction_path_with_ads(dentry, ctx,
strm->stream_name,
utf16le_len_chars(strm->stream_name));
} else {
build_extraction_path(dentry, ctx);
}
/* Open a new handle */
status = do_create_file(&h,
FILE_WRITE_DATA | SYNCHRONIZE,
NULL, 0, FILE_OPEN_IF,
FILE_SEQUENTIAL_ONLY |
FILE_SYNCHRONOUS_IO_NONALERT,
ctx);
if (!NT_SUCCESS(status)) {
winnt_error(status, L"Can't open \"%ls\" for writing",
current_path(ctx));
return WIMLIB_ERR_OPEN;
}
ctx->is_sparse_stream[ctx->num_open_handles] = false;
if (need_sparse_flag(dentry->d_inode, ctx)) {
/* If the stream is unnamed, then the sparse flag was already
* set when the file was created. But if the stream is named,
* then we need to set the sparse flag here. */
if (unlikely(stream_is_named(strm))) {
int ret = set_sparse_flag(h, ctx);
if (ret) {
NtClose(h);
return ret;
}
}
ctx->is_sparse_stream[ctx->num_open_handles] = true;
ctx->any_sparse_streams = true;
} else {
/* Allocate space for the data. */
FILE_ALLOCATION_INFORMATION info =
{ .AllocationSize = { .QuadPart = blob->size }};
NtSetInformationFile(h, &ctx->iosb, &info, sizeof(info),
FileAllocationInformation);
}
ctx->open_handles[ctx->num_open_handles++] = h;
return 0;
}
/* Given a Windows NT namespace path, such as \??\e:\Windows\System32, return a
* pointer to the suffix of the path that begins with the device directly, such
* as e:\Windows\System32. */
static const wchar_t *
skip_nt_toplevel_component(const wchar_t *path, size_t path_nchars)
{
static const wchar_t * const dirs[] = {
L"\\??\\",
L"\\DosDevices\\",
L"\\Device\\",
};
const wchar_t * const end = path + path_nchars;
for (size_t i = 0; i < ARRAY_LEN(dirs); i++) {
size_t len = wcslen(dirs[i]);
if (len <= (end - path) && !wmemcmp(path, dirs[i], len)) {
path += len;
while (path != end && *path == L'\\')
path++;
return path;
}
}
return path;
}
/*
* Given a Windows NT namespace path, such as \??\e:\Windows\System32, return a
* pointer to the suffix of the path that is device-relative but possibly with
* leading slashes, such as \Windows\System32.
*
* The path has an explicit length and is not necessarily null terminated.
*/
static const wchar_t *
get_device_relative_path(const wchar_t *path, size_t path_nchars)
{
const wchar_t * const orig_path = path;
const wchar_t * const end = path + path_nchars;
path = skip_nt_toplevel_component(path, path_nchars);
if (path == orig_path)
return orig_path;
while (path != end && *path != L'\\')
path++;
return path;
}
/*
* Given a reparse point buffer for an inode for which the absolute link target
* was relativized when it was archived, de-relative the link target to be
* consistent with the actual extraction location.
*/
static void
try_rpfix(struct reparse_buffer_disk *rpbuf, u16 *rpbuflen_p,
struct win32_apply_ctx *ctx)
{
struct link_reparse_point link;
size_t orig_subst_name_nchars;
const wchar_t *relpath;
size_t relpath_nchars;
size_t target_ntpath_nchars;
size_t fixed_subst_name_nchars;
const wchar_t *fixed_print_name;
size_t fixed_print_name_nchars;
/* Do nothing if the reparse data is invalid. */
if (parse_link_reparse_point(rpbuf, *rpbuflen_p, &link))
return;
/* Do nothing if the reparse point is a relative symbolic link. */
if (link_is_relative_symlink(&link))
return;
/* Build the new substitute name from the NT namespace path to the
* target directory, then a path separator, then the "device relative"
* part of the old substitute name. */
orig_subst_name_nchars = link.substitute_name_nbytes / sizeof(wchar_t);
relpath = get_device_relative_path(link.substitute_name,
orig_subst_name_nchars);
relpath_nchars = orig_subst_name_nchars -
(relpath - link.substitute_name);
target_ntpath_nchars = ctx->target_ntpath.Length / sizeof(wchar_t);
/* If the target directory is a filesystem root, such as \??\C:\, then
* it already will have a trailing slash. Don't include this slash if
* we are already adding slashes via 'relpath'. This prevents an extra
* slash from being generated each time the link is extracted. And
* unlike on UNIX, the number of slashes in paths on Windows can be
* significant; Windows won't understand the link target if it contains
* too many slashes. */
if (target_ntpath_nchars > 0 && relpath_nchars > 0 &&
ctx->target_ntpath.Buffer[target_ntpath_nchars - 1] == L'\\')
target_ntpath_nchars--;
/* Also remove extra slashes from the beginning of 'relpath'. Normally
* this isn't needed, but this is here to make the extra slash(es) added
* by wimlib pre-v1.9.1 get removed automatically. */
while (relpath_nchars >= 2 &&
relpath[0] == L'\\' && relpath[1] == L'\\') {
relpath++;
relpath_nchars--;
}
fixed_subst_name_nchars = target_ntpath_nchars + relpath_nchars;
wchar_t fixed_subst_name[fixed_subst_name_nchars];
wmemcpy(fixed_subst_name, ctx->target_ntpath.Buffer, target_ntpath_nchars);
wmemcpy(&fixed_subst_name[target_ntpath_nchars], relpath, relpath_nchars);
/* Doesn't need to be null-terminated. */
/* Print name should be Win32, but not all NT names can even be
* translated to Win32 names. But we can at least delete the top-level
* directory, such as \??\, and this will have the expected result in
* the usual case. */
fixed_print_name = skip_nt_toplevel_component(fixed_subst_name,
fixed_subst_name_nchars);
fixed_print_name_nchars = fixed_subst_name_nchars - (fixed_print_name -
fixed_subst_name);
link.substitute_name = fixed_subst_name;
link.substitute_name_nbytes = fixed_subst_name_nchars * sizeof(wchar_t);
link.print_name = (wchar_t *)fixed_print_name;
link.print_name_nbytes = fixed_print_name_nchars * sizeof(wchar_t);
make_link_reparse_point(&link, rpbuf, rpbuflen_p);
}
/* Sets the reparse point on the specified file. This handles "fixing" the
* targets of absolute symbolic links and junctions if WIMLIB_EXTRACT_FLAG_RPFIX
* was specified. */
static int
set_reparse_point(const struct wim_dentry *dentry,
const struct reparse_buffer_disk *rpbuf, u16 rpbuflen,
struct win32_apply_ctx *ctx)
{
if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_RPFIX)
&& !(dentry->d_inode->i_rp_flags & WIM_RP_FLAG_NOT_FIXED))
{
memcpy(&ctx->rpfixbuf, rpbuf, rpbuflen);
try_rpfix(&ctx->rpfixbuf, &rpbuflen, ctx);
rpbuf = &ctx->rpfixbuf;
}
return do_set_reparse_point(dentry, rpbuf, rpbuflen, ctx);
}
/* Import the next block of raw encrypted data */
static DWORD WINAPI
import_encrypted_data(PBYTE pbData, PVOID pvCallbackContext, PULONG Length)
{
struct win32_apply_ctx *ctx = pvCallbackContext;
ULONG copy_len;
copy_len = min(ctx->encrypted_size - ctx->encrypted_offset, *Length);
memcpy(pbData, &ctx->data_buffer[ctx->encrypted_offset], copy_len);
ctx->encrypted_offset += copy_len;
*Length = copy_len;
return ERROR_SUCCESS;
}
/*
* Write the raw encrypted data to the already-created file (or directory)
* corresponding to @dentry.
*
* The raw encrypted data is provided in ctx->data_buffer, and its size is
* ctx->encrypted_size.
*
* This function may close the target directory, in which case the caller needs
* to re-open it if needed.
*/
static int
extract_encrypted_file(const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx)
{
void *rawctx;
DWORD err;
ULONG flags;
bool retried;
/* Temporarily build a Win32 path for OpenEncryptedFileRaw() */
build_win32_extraction_path(dentry, ctx);
flags = CREATE_FOR_IMPORT | OVERWRITE_HIDDEN;
if (dentry->d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
flags |= CREATE_FOR_DIR;
retried = false;
retry:
err = OpenEncryptedFileRaw(ctx->pathbuf.Buffer, flags, &rawctx);
if (err == ERROR_SHARING_VIOLATION && !retried) {
/* This can be caused by the handle we have open to the target
* directory. Try closing it temporarily. */
close_target_directory(ctx);
retried = true;
goto retry;
}
/* Restore the NT namespace path */
build_extraction_path(dentry, ctx);
if (err != ERROR_SUCCESS) {
win32_error(err, L"Can't open \"%ls\" for encrypted import",
current_path(ctx));
return WIMLIB_ERR_OPEN;
}
ctx->encrypted_offset = 0;
err = WriteEncryptedFileRaw(import_encrypted_data, ctx, rawctx);
CloseEncryptedFileRaw(rawctx);
if (err != ERROR_SUCCESS) {
win32_error(err, L"Can't import encrypted file \"%ls\"",
current_path(ctx));
return WIMLIB_ERR_WRITE;
}
return 0;
}
/* Called when starting to read a blob for extraction */
static int
win32_begin_extract_blob(struct blob_descriptor *blob, void *_ctx)
{
struct win32_apply_ctx *ctx = _ctx;
const struct blob_extraction_target *targets = blob_extraction_targets(blob);
int ret;
ctx->num_open_handles = 0;
ctx->data_buffer_ptr = NULL;
ctx->any_sparse_streams = false;
INIT_LIST_HEAD(&ctx->reparse_dentries);
INIT_LIST_HEAD(&ctx->encrypted_dentries);
for (u32 i = 0; i < blob->out_refcnt; i++) {
const struct wim_inode *inode = targets[i].inode;
const struct wim_inode_stream *strm = targets[i].stream;
struct wim_dentry *dentry;
/* A copy of the blob needs to be extracted to @inode. */
if (ctx->common.supported_features.hard_links) {
dentry = inode_first_extraction_dentry(inode);
ret = begin_extract_blob_instance(blob, dentry, strm, ctx);
ret = check_apply_error(dentry, ctx, ret);
if (ret)
goto fail;
} else {
/* Hard links not supported. Extract the blob
* separately to each alias of the inode. */
inode_for_each_extraction_alias(dentry, inode) {
ret = begin_extract_blob_instance(blob, dentry, strm, ctx);
ret = check_apply_error(dentry, ctx, ret);
if (ret)
goto fail;
}
}
}
return 0;
fail:
close_handles(ctx);
return ret;
}
static int
pwrite_to_handle(HANDLE h, const void *data, size_t size, u64 offset)
{
const void * const end = data + size;
const void *p;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
for (p = data; p != end; p += iosb.Information,
offset += iosb.Information)
{
LARGE_INTEGER offs = { .QuadPart = offset };
status = NtWriteFile(h, NULL, NULL, NULL, &iosb,
(void *)p, min(INT32_MAX, end - p),
&offs, NULL);
if (!NT_SUCCESS(status)) {
winnt_error(status,
L"Error writing data to target volume");
return WIMLIB_ERR_WRITE;
}
}
return 0;
}
/* Called when the next chunk of a blob has been read for extraction */
static int
win32_extract_chunk(const struct blob_descriptor *blob, u64 offset,
const void *chunk, size_t size, void *_ctx)
{
struct win32_apply_ctx *ctx = _ctx;
const void * const end = chunk + size;
const void *p;
bool zeroes;
size_t len;
unsigned i;
int ret;
/*
* For sparse streams, only write nonzero regions. This lets the
* filesystem use holes to represent zero regions.
*/
for (p = chunk; p != end; p += len, offset += len) {
zeroes = maybe_detect_sparse_region(p, end - p, &len,
ctx->any_sparse_streams);
for (i = 0; i < ctx->num_open_handles; i++) {
if (!zeroes || !ctx->is_sparse_stream[i]) {
ret = pwrite_to_handle(ctx->open_handles[i],
p, len, offset);
if (ret)
return ret;
}
}
}
/* Copy the data chunk into the buffer (if needed) */
if (ctx->data_buffer_ptr)
ctx->data_buffer_ptr = mempcpy(ctx->data_buffer_ptr,
chunk, size);
return 0;
}
static int
get_system_compression_format(int extract_flags)
{
if (extract_flags & WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS4K)
return FILE_PROVIDER_COMPRESSION_XPRESS4K;
if (extract_flags & WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS8K)
return FILE_PROVIDER_COMPRESSION_XPRESS8K;
if (extract_flags & WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS16K)
return FILE_PROVIDER_COMPRESSION_XPRESS16K;
return FILE_PROVIDER_COMPRESSION_LZX;
}
static const wchar_t *
get_system_compression_format_string(int format)
{
switch (format) {
case FILE_PROVIDER_COMPRESSION_XPRESS4K:
return L"XPRESS4K";
case FILE_PROVIDER_COMPRESSION_XPRESS8K:
return L"XPRESS8K";
case FILE_PROVIDER_COMPRESSION_XPRESS16K:
return L"XPRESS16K";
default:
return L"LZX";
}
}
static NTSTATUS
set_system_compression(HANDLE h, int format)
{
NTSTATUS status;
struct {
WOF_EXTERNAL_INFO wof_info;
FILE_PROVIDER_EXTERNAL_INFO_V1 file_info;
} in = {
.wof_info = {
.Version = WOF_CURRENT_VERSION,
.Provider = WOF_PROVIDER_FILE,
},
.file_info = {
.Version = FILE_PROVIDER_CURRENT_VERSION,
.Algorithm = format,
},
};
/* We intentionally use NtFsControlFile() rather than DeviceIoControl()
* here because the "compressing this object would not save space"
* status code does not map to a valid Win32 error code on older
* versions of Windows (before Windows 10?). This can be a problem if
* the WOFADK driver is being used rather than the regular WOF, since
* WOFADK can be used on older versions of Windows. */
status = winnt_fsctl(h, FSCTL_SET_EXTERNAL_BACKING,
&in, sizeof(in), NULL, 0, NULL);
if (status == 0xC000046F) /* "Compressing this object would not save space." */
return STATUS_SUCCESS;
return status;
}
/* Hard-coded list of files which the Windows bootloader may need to access
* before the WOF driver has been loaded. */
static const wchar_t * const bootloader_pattern_strings[] = {
L"*winload.*",
L"*winresume.*",
L"\\Windows\\AppPatch\\drvmain.sdb",
L"\\Windows\\Boot\\DVD\\*",
L"\\Windows\\Boot\\EFI\\*",
L"\\Windows\\bootstat.dat",
L"\\Windows\\Fonts\\vgaoem.fon",
L"\\Windows\\Fonts\\vgasys.fon",
L"\\Windows\\INF\\errata.inf",
L"\\Windows\\System32\\config\\*",
L"\\Windows\\System32\\ntkrnlpa.exe",
L"\\Windows\\System32\\ntoskrnl.exe",
L"\\Windows\\System32\\bootvid.dll",
L"\\Windows\\System32\\ci.dll",
L"\\Windows\\System32\\hal*.dll",
L"\\Windows\\System32\\mcupdate_AuthenticAMD.dll",
L"\\Windows\\System32\\mcupdate_GenuineIntel.dll",
L"\\Windows\\System32\\pshed.dll",
L"\\Windows\\System32\\apisetschema.dll",
L"\\Windows\\System32\\api-ms-win*.dll",
L"\\Windows\\System32\\ext-ms-win*.dll",
L"\\Windows\\System32\\KernelBase.dll",
L"\\Windows\\System32\\drivers\\*.sys",
L"\\Windows\\System32\\*.nls",
L"\\Windows\\System32\\kbd*.dll",
L"\\Windows\\System32\\kd*.dll",
L"\\Windows\\System32\\clfs.sys",
L"\\Windows\\System32\\CodeIntegrity\\driver.stl",
};
static const struct string_list bootloader_patterns = {
.strings = (wchar_t **)bootloader_pattern_strings,
.num_strings = ARRAY_LEN(bootloader_pattern_strings),
};
/* Returns true if the specified system compression format is supported by the
* bootloader of the image being applied. */
static bool
bootloader_supports_compression_format(struct win32_apply_ctx *ctx, int format)
{
/* Windows 10 and later support XPRESS4K */
if (format == FILE_PROVIDER_COMPRESSION_XPRESS4K)
return ctx->windows_build_number >= 10240;
/*
* Windows 10 version 1903 and later support the other formats;
* see https://wimlib.net/forums/viewtopic.php?f=1&t=444
*/
return ctx->windows_build_number >= 18362;
}
static NTSTATUS
set_system_compression_on_inode(struct wim_inode *inode, int format,
struct win32_apply_ctx *ctx)
{
bool retried = false;
NTSTATUS status;
HANDLE h;
/* If it may be needed for compatibility with the Windows bootloader,
* force this file to XPRESS4K or uncompressed format. */
if (!bootloader_supports_compression_format(ctx, format)) {
/* We need to check the patterns against every name of the
* inode, in case any of them match. */
struct wim_dentry *dentry;
inode_for_each_extraction_alias(dentry, inode) {
bool incompatible;
bool warned;
if (calculate_dentry_full_path(dentry)) {
ERROR("Unable to compute file path!");
return STATUS_NO_MEMORY;
}
incompatible = match_pattern_list(dentry->d_full_path,
&bootloader_patterns,
MATCH_RECURSIVELY);
FREE(dentry->d_full_path);
dentry->d_full_path = NULL;
if (!incompatible)
continue;
warned = (ctx->num_system_compression_exclusions++ > 0);
if (bootloader_supports_compression_format(ctx,
FILE_PROVIDER_COMPRESSION_XPRESS4K))
{
/* Force to XPRESS4K */
if (!warned) {
WARNING("For compatibility with the "
"Windows bootloader, some "
"files are being\n"
" compacted "
"using the XPRESS4K format "
"instead of the %"TS" format\n"
" you requested.",
get_system_compression_format_string(format));
}
format = FILE_PROVIDER_COMPRESSION_XPRESS4K;
break;
} else {
/* Force to uncompressed */
if (!warned) {
WARNING("For compatibility with the "
"Windows bootloader, some "
"files will not\n"
" be compressed with"
" system compression "
"(\"compacted\").");
}
return STATUS_SUCCESS;
}
}
}
/* Open the extracted file. */
status = create_file(&h, GENERIC_READ | GENERIC_WRITE, NULL,
0, FILE_OPEN, 0,
inode_first_extraction_dentry(inode), ctx);
if (!NT_SUCCESS(status))
return status;
retry:
/* Compress the file. If the attempt fails with "invalid device
* request", then attach wof.sys (or wofadk.sys) and retry. */
status = set_system_compression(h, format);
if (unlikely(status == STATUS_INVALID_DEVICE_REQUEST && !retried)) {
wchar_t drive_path[7];
if (!win32_get_drive_path(ctx->common.target, drive_path) &&
win32_try_to_attach_wof(drive_path + 4)) {
retried = true;
goto retry;
}
}
NtClose(h);
return status;
}
/*
* This function is called when doing a "compact-mode" extraction and we just
* finished extracting a blob to one or more locations. For each location that
* was the unnamed data stream of a file, this function compresses the
* corresponding file using System Compression, if allowed.
*
* Note: we're doing the compression immediately after extracting the data
* rather than during a separate compression pass. This way should be faster
* since the operating system should still have the file's data cached.
*
* Note: we're having the operating system do the compression, which is not
* ideal because wimlib could create the compressed data faster and more
* efficiently (the compressed data format is identical to a WIM resource). But
* we seemingly don't have a choice because WOF prevents applications from
* creating its reparse points.
*/
static void
handle_system_compression(struct blob_descriptor *blob, struct win32_apply_ctx *ctx)
{
const struct blob_extraction_target *targets = blob_extraction_targets(blob);
const int format = get_system_compression_format(ctx->common.extract_flags);
for (u32 i = 0; i < blob->out_refcnt; i++) {
struct wim_inode *inode = targets[i].inode;
struct wim_inode_stream *strm = targets[i].stream;
NTSTATUS status;
if (!stream_is_unnamed_data_stream(strm))
continue;
if (will_externally_back_inode(inode, ctx, NULL, false) != 0)
continue;
status = set_system_compression_on_inode(inode, format, ctx);
if (likely(NT_SUCCESS(status)))
continue;
if (status == STATUS_INVALID_DEVICE_REQUEST) {
WARNING(
"The request to compress the extracted files using System Compression\n"
" will not be honored because the operating system or target volume\n"
" does not support it. System Compression is only supported on\n"
" Windows 10 and later, and only on NTFS volumes.");
ctx->common.extract_flags &= ~COMPACT_FLAGS;
return;
}
ctx->num_system_compression_failures++;
if (ctx->num_system_compression_failures < 10) {
winnt_warning(status, L"\"%ls\": Failed to compress "
"extracted file using System Compression",
current_path(ctx));
} else if (ctx->num_system_compression_failures == 10) {
WARNING("Suppressing further warnings about "
"System Compression failures.");
}
}
}
/* Called when a blob has been fully read for extraction */
static int
win32_end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx)
{
struct win32_apply_ctx *ctx = _ctx;
int ret;
const struct wim_dentry *dentry;
/* Extend sparse streams to their final size. */
if (ctx->any_sparse_streams && !status) {
for (unsigned i = 0; i < ctx->num_open_handles; i++) {
FILE_END_OF_FILE_INFORMATION info =
{ .EndOfFile = { .QuadPart = blob->size } };
NTSTATUS ntstatus;
if (!ctx->is_sparse_stream[i])
continue;
ntstatus = NtSetInformationFile(ctx->open_handles[i],
&ctx->iosb,
&info, sizeof(info),
FileEndOfFileInformation);
if (!NT_SUCCESS(ntstatus)) {
winnt_error(ntstatus, L"Error writing data to "
"target volume (while extending)");
status = WIMLIB_ERR_WRITE;
break;
}
}
}
close_handles(ctx);
if (status)
return status;
if (unlikely(ctx->common.extract_flags & COMPACT_FLAGS))
handle_system_compression(blob, ctx);
if (likely(!ctx->data_buffer_ptr))
return 0;
if (!list_empty(&ctx->reparse_dentries)) {
if (blob->size > REPARSE_DATA_MAX_SIZE) {
dentry = list_first_entry(&ctx->reparse_dentries,
struct wim_dentry, d_tmp_list);
build_extraction_path(dentry, ctx);
ERROR("Reparse data of \"%ls\" has size "
"%"PRIu64" bytes (exceeds %u bytes)",
current_path(ctx), blob->size,
REPARSE_DATA_MAX_SIZE);
ret = WIMLIB_ERR_INVALID_REPARSE_DATA;
return check_apply_error(dentry, ctx, ret);
}
/* Reparse data */
memcpy(ctx->rpbuf.rpdata, ctx->data_buffer, blob->size);
list_for_each_entry(dentry, &ctx->reparse_dentries, d_tmp_list) {
/* Reparse point header */
complete_reparse_point(&ctx->rpbuf, dentry->d_inode,
blob->size);
ret = set_reparse_point(dentry, &ctx->rpbuf,
REPARSE_DATA_OFFSET + blob->size,
ctx);
ret = check_apply_error(dentry, ctx, ret);
if (ret)
return ret;
}
}
if (!list_empty(&ctx->encrypted_dentries)) {
ctx->encrypted_size = blob->size;
list_for_each_entry(dentry, &ctx->encrypted_dentries, d_tmp_list) {
ret = extract_encrypted_file(dentry, ctx);
ret = check_apply_error(dentry, ctx, ret);
if (ret)
return ret;
/* Re-open the target directory if needed. */
ret = open_target_directory(ctx);
if (ret)
return ret;
}
}
return 0;
}
/* Attributes that can't be set directly */
#define SPECIAL_ATTRIBUTES \
(FILE_ATTRIBUTE_REPARSE_POINT | \
FILE_ATTRIBUTE_DIRECTORY | \
FILE_ATTRIBUTE_ENCRYPTED | \
FILE_ATTRIBUTE_SPARSE_FILE | \
FILE_ATTRIBUTE_COMPRESSED)
static void
set_object_id(HANDLE h, const struct wim_inode *inode,
struct win32_apply_ctx *ctx)
{
const void *object_id;
u32 len;
NTSTATUS status;
if (!ctx->common.supported_features.object_ids)
return;
object_id = inode_get_object_id(inode, &len);
if (likely(object_id == NULL)) /* No object ID? */
return;
status = winnt_fsctl(h, FSCTL_SET_OBJECT_ID,
object_id, len, NULL, 0, NULL);
if (NT_SUCCESS(status))
return;
/* Object IDs must be unique within the filesystem. A duplicate might
* occur if an image containing object IDs is applied twice to the same
* filesystem. Arguably, the user should be warned in this case; but
* the reality seems to be that nothing important cares about object IDs
* except the Distributed Link Tracking Service... so for now these
* failures are just ignored. */
if (status == STATUS_DUPLICATE_NAME ||
status == STATUS_OBJECT_NAME_COLLISION)
return;
ctx->num_object_id_failures++;
if (ctx->num_object_id_failures < 10) {
winnt_warning(status, L"Can't set object ID on \"%ls\"",
current_path(ctx));
} else if (ctx->num_object_id_failures == 10) {
WARNING("Suppressing further warnings about failure to set "
"object IDs.");
}
}
static int
set_xattrs(HANDLE h, const struct wim_inode *inode, struct win32_apply_ctx *ctx)
{
const void *entries, *entries_end;
u32 len;
const struct wim_xattr_entry *entry;
size_t bufsize = 0;
u8 _buf[1024] __attribute__((aligned(4)));
u8 *buf = _buf;
FILE_FULL_EA_INFORMATION *ea, *ea_prev;
NTSTATUS status;
int ret;
if (!ctx->common.supported_features.xattrs)
return 0;
entries = inode_get_xattrs(inode, &len);
if (likely(entries == NULL || len == 0)) /* No extended attributes? */
return 0;
entries_end = entries + len;
entry = entries;
for (entry = entries; (void *)entry < entries_end;
entry = xattr_entry_next(entry)) {
if (!valid_xattr_entry(entry, entries_end - (void *)entry)) {
ERROR("\"%"TS"\": extended attribute is corrupt or unsupported",
inode_any_full_path(inode));
return WIMLIB_ERR_INVALID_XATTR;
}
bufsize += ALIGN(offsetof(FILE_FULL_EA_INFORMATION, EaName) +
entry->name_len + 1 +
le16_to_cpu(entry->value_len), 4);
}
if (unlikely(bufsize != (u32)bufsize)) {
ERROR("\"%"TS"\": too many extended attributes to extract!",
inode_any_full_path(inode));
return WIMLIB_ERR_INVALID_XATTR;
}
if (unlikely(bufsize > sizeof(_buf))) {
buf = MALLOC(bufsize);
if (!buf)
return WIMLIB_ERR_NOMEM;
}
ea_prev = NULL;
ea = (FILE_FULL_EA_INFORMATION *)buf;
for (entry = entries; (void *)entry < entries_end;
entry = xattr_entry_next(entry)) {
u8 *p;
if (ea_prev)
ea_prev->NextEntryOffset = (u8 *)ea - (u8 *)ea_prev;
ea->Flags = entry->flags;
ea->EaNameLength = entry->name_len;
ea->EaValueLength = le16_to_cpu(entry->value_len);
p = mempcpy(ea->EaName, entry->name,
ea->EaNameLength + 1 + ea->EaValueLength);
while ((uintptr_t)p & 3)
*p++ = 0;
ea_prev = ea;
ea = (FILE_FULL_EA_INFORMATION *)p;
}
ea_prev->NextEntryOffset = 0;
wimlib_assert((u8 *)ea - buf == bufsize);
status = NtSetEaFile(h, &ctx->iosb, buf, bufsize);
if (unlikely(!NT_SUCCESS(status))) {
if (status == STATUS_EAS_NOT_SUPPORTED) {
/* This happens with Samba. */
WARNING("Filesystem advertised extended attribute (EA) support, but it doesn't\n"
" work. EAs will not be extracted.");
ctx->common.supported_features.xattrs = 0;
} else if (status == STATUS_INVALID_EA_NAME) {
ctx->num_xattr_failures++;
if (ctx->num_xattr_failures < 5) {
winnt_warning(status,
L"Can't set extended attributes on \"%ls\"",
current_path(ctx));
} else if (ctx->num_xattr_failures == 5) {
WARNING("Suppressing further warnings about "
"failure to set extended attributes.");
}
} else {
winnt_error(status, L"Can't set extended attributes on \"%ls\"",
current_path(ctx));
ret = WIMLIB_ERR_SET_XATTR;
goto out;
}
}
ret = 0;
out:
if (buf != _buf)
FREE(buf);
return ret;
}
/* Set the security descriptor @desc, of @desc_size bytes, on the file with open
* handle @h. */
static NTSTATUS
set_security_descriptor(HANDLE h, const void *_desc,
size_t desc_size, struct win32_apply_ctx *ctx)
{
SECURITY_INFORMATION info;
NTSTATUS status;
SECURITY_DESCRIPTOR_RELATIVE *desc;
/*
* Ideally, we would just pass in the security descriptor buffer as-is.
* But it turns out that Windows can mess up the security descriptor
* even when using the low-level NtSetSecurityObject() function:
*
* - Windows will clear SE_DACL_AUTO_INHERITED if it is set in the
* passed buffer. To actually get Windows to set
* SE_DACL_AUTO_INHERITED, the application must set the non-persistent
* flag SE_DACL_AUTO_INHERIT_REQ. As usual, Microsoft didn't bother
* to properly document either of these flags. It's unclear how
* important SE_DACL_AUTO_INHERITED actually is, but to be safe we use
* the SE_DACL_AUTO_INHERIT_REQ workaround to set it if needed.
*
* - The above also applies to the equivalent SACL flags,
* SE_SACL_AUTO_INHERITED and SE_SACL_AUTO_INHERIT_REQ.
*
* - If the application says that it's setting
* DACL_SECURITY_INFORMATION, then Windows sets SE_DACL_PRESENT in the
* resulting security descriptor, even if the security descriptor the
* application provided did not have a DACL. This seems to be
* unavoidable, since omitting DACL_SECURITY_INFORMATION would cause a
* default DACL to remain. Fortunately, this behavior seems harmless,
* since the resulting DACL will still be "null" --- but it will be
* "the other representation of null".
*
* - The above also applies to SACL_SECURITY_INFORMATION and
* SE_SACL_PRESENT. Again, it's seemingly unavoidable but "harmless"
* that Windows changes the representation of a "null SACL".
*/
if (likely(desc_size <= STACK_MAX)) {
desc = alloca(desc_size);
} else {
desc = MALLOC(desc_size);
if (!desc)
return STATUS_NO_MEMORY;
}
memcpy(desc, _desc, desc_size);
if (likely(desc_size >= 4)) {
if (desc->Control & SE_DACL_AUTO_INHERITED)
desc->Control |= SE_DACL_AUTO_INHERIT_REQ;
if (desc->Control & SE_SACL_AUTO_INHERITED)
desc->Control |= SE_SACL_AUTO_INHERIT_REQ;
}
/*
* More API insanity. We want to set the entire security descriptor
* as-is. But all available APIs require specifying the specific parts
* of the security descriptor being set. Especially annoying is that
* mandatory integrity labels are part of the SACL, but they aren't set
* with SACL_SECURITY_INFORMATION. Instead, applications must also
* specify LABEL_SECURITY_INFORMATION (Windows Vista, Windows 7) or
* BACKUP_SECURITY_INFORMATION (Windows 8). But at least older versions
* of Windows don't error out if you provide these newer flags...
*
* Also, if the process isn't running as Administrator, then it probably
* doesn't have SE_RESTORE_PRIVILEGE. In this case, it will always get
* the STATUS_PRIVILEGE_NOT_HELD error by trying to set the SACL, even
* if the security descriptor it provided did not have a SACL. By
* default, in this case we try to recover and set as much of the
* security descriptor as possible --- potentially excluding the DACL, and
* even the owner, as well as the SACL.
*/
info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION |
LABEL_SECURITY_INFORMATION | BACKUP_SECURITY_INFORMATION;
/*
* It's also worth noting that SetFileSecurity() is unusable because it
* doesn't request "backup semantics" when it opens the file internally.
* NtSetSecurityObject() seems to be the best function to use in backup
* applications. (SetSecurityInfo() should also work, but it's harder
* to use and must call NtSetSecurityObject() internally anyway.
* BackupWrite() is theoretically usable as well, but it's inflexible
* and poorly documented.)
*/
retry:
status = NtSetSecurityObject(h, info, desc);
if (NT_SUCCESS(status))
goto out_maybe_free_desc;
/* Failed to set the requested parts of the security descriptor. If the
* error was permissions-related, try to set fewer parts of the security
* descriptor, unless WIMLIB_EXTRACT_FLAG_STRICT_ACLS is enabled. */
if ((status == STATUS_PRIVILEGE_NOT_HELD ||
status == STATUS_ACCESS_DENIED) &&
!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS))
{
if (info & SACL_SECURITY_INFORMATION) {
info &= ~(SACL_SECURITY_INFORMATION |
LABEL_SECURITY_INFORMATION |
BACKUP_SECURITY_INFORMATION);
ctx->partial_security_descriptors++;
goto retry;
}
if (info & DACL_SECURITY_INFORMATION) {
info &= ~DACL_SECURITY_INFORMATION;
goto retry;
}
if (info & OWNER_SECURITY_INFORMATION) {
info &= ~OWNER_SECURITY_INFORMATION;
goto retry;
}
/* Nothing left except GROUP, and if we removed it we
* wouldn't have anything at all. */
}
/* No part of the security descriptor could be set, or
* WIMLIB_EXTRACT_FLAG_STRICT_ACLS is enabled and the full security
* descriptor could not be set. */
if (!(info & SACL_SECURITY_INFORMATION))
ctx->partial_security_descriptors--;
ctx->no_security_descriptors++;
out_maybe_free_desc:
if (unlikely(desc_size > STACK_MAX))
FREE(desc);
return status;
}
/* Set metadata on the open file @h from the WIM inode @inode. */
static int
do_apply_metadata_to_file(HANDLE h, const struct wim_inode *inode,
struct win32_apply_ctx *ctx)
{
FILE_BASIC_INFORMATION info;
NTSTATUS status;
int ret;
/* Set the file's object ID if present and object IDs are supported by
* the filesystem. */
set_object_id(h, inode, ctx);
/* Set the file's extended attributes (EAs) if present and EAs are
* supported by the filesystem. */
ret = set_xattrs(h, inode, ctx);
if (ret)
return ret;
/* Set the file's security descriptor if present and we're not in
* NO_ACLS mode */
if (inode_has_security_descriptor(inode) &&
!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS))
{
const struct wim_security_data *sd;
const void *desc;
size_t desc_size;
sd = wim_get_current_security_data(ctx->common.wim);
desc = sd->descriptors[inode->i_security_id];
desc_size = sd->sizes[inode->i_security_id];
status = set_security_descriptor(h, desc, desc_size, ctx);
if (!NT_SUCCESS(status) &&
(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS))
{
winnt_error(status,
L"Can't set security descriptor on \"%ls\"",
current_path(ctx));
return WIMLIB_ERR_SET_SECURITY;
}
}
/* Set attributes and timestamps */
info.CreationTime.QuadPart = inode->i_creation_time;
info.LastAccessTime.QuadPart = inode->i_last_access_time;
info.LastWriteTime.QuadPart = inode->i_last_write_time;
info.ChangeTime.QuadPart = 0;
if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES) {
info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
} else {
info.FileAttributes = inode->i_attributes & ~SPECIAL_ATTRIBUTES;
if (info.FileAttributes == 0)
info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
}
status = NtSetInformationFile(h, &ctx->iosb, &info, sizeof(info),
FileBasicInformation);
/* On FAT volumes we get STATUS_INVALID_PARAMETER if we try to set
* attributes on the root directory. (Apparently because FAT doesn't
* actually have a place to store those attributes!) */
if (!NT_SUCCESS(status)
&& !(status == STATUS_INVALID_PARAMETER &&
dentry_is_root(inode_first_extraction_dentry(inode))))
{
winnt_error(status, L"Can't set basic metadata on \"%ls\"",
current_path(ctx));
return WIMLIB_ERR_SET_ATTRIBUTES;
}
return 0;
}
static int
apply_metadata_to_file(const struct wim_dentry *dentry,
struct win32_apply_ctx *ctx)
{
const struct wim_inode *inode = dentry->d_inode;
DWORD perms;
HANDLE h;
NTSTATUS status;
int ret;
perms = FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | WRITE_DAC |
WRITE_OWNER | ACCESS_SYSTEM_SECURITY;
build_extraction_path(dentry, ctx);
/* Open a handle with as many relevant permissions as possible. */
while (!NT_SUCCESS(status = do_create_file(&h, perms, NULL,
0, FILE_OPEN, 0, ctx)))
{
if (status == STATUS_PRIVILEGE_NOT_HELD ||
status == STATUS_ACCESS_DENIED)
{
if (perms & ACCESS_SYSTEM_SECURITY) {
perms &= ~ACCESS_SYSTEM_SECURITY;
continue;
}
if (perms & WRITE_DAC) {
perms &= ~WRITE_DAC;
continue;
}
if (perms & WRITE_OWNER) {
perms &= ~WRITE_OWNER;
continue;
}
}
winnt_error(status, L"Can't open \"%ls\" to set metadata",
current_path(ctx));
return WIMLIB_ERR_OPEN;
}
ret = do_apply_metadata_to_file(h, inode, ctx);
NtClose(h);
return ret;
}
static int
apply_metadata(struct list_head *dentry_list, struct win32_apply_ctx *ctx)
{
const struct wim_dentry *dentry;
int ret;
/* We go in reverse so that metadata is set on all a directory's
* children before the directory itself. This avoids any potential
* problems with attributes, timestamps, or security descriptors. */
list_for_each_entry_reverse(dentry, dentry_list, d_extraction_list_node)
{
ret = apply_metadata_to_file(dentry, ctx);
ret = check_apply_error(dentry, ctx, ret);
if (ret)
return ret;
ret = report_file_metadata_applied(&ctx->common);
if (ret)
return ret;
}
return 0;
}
/* Issue warnings about problems during the extraction for which warnings were
* not already issued (due to the high number of potential warnings if we issued
* them per-file). */
static void
do_warnings(const struct win32_apply_ctx *ctx)
{
if (ctx->partial_security_descriptors == 0
&& ctx->no_security_descriptors == 0
&& ctx->num_set_short_name_failures == 0
#if 0
&& ctx->num_remove_short_name_failures == 0
#endif
)
return;
WARNING("Extraction to \"%ls\" complete, but with one or more warnings:",
ctx->common.target);
if (ctx->num_set_short_name_failures) {
WARNING("- Could not set short names on %lu files or directories",
ctx->num_set_short_name_failures);
}
#if 0
if (ctx->num_remove_short_name_failures) {
WARNING("- Could not remove short names on %lu files or directories"
" (This is expected on Vista and earlier)",
ctx->num_remove_short_name_failures);
}
#endif
if (ctx->partial_security_descriptors) {
WARNING("- Could only partially set the security descriptor\n"
" on %lu files or directories.",
ctx->partial_security_descriptors);
}
if (ctx->no_security_descriptors) {
WARNING("- Could not set security descriptor at all\n"
" on %lu files or directories.",
ctx->no_security_descriptors);
}
if (ctx->partial_security_descriptors || ctx->no_security_descriptors) {
WARNING("To fully restore all security descriptors, run the program\n"
" with Administrator rights.");
}
}
static u64
count_dentries(const struct list_head *dentry_list)
{
const struct list_head *cur;
u64 count = 0;
list_for_each(cur, dentry_list)
count++;
return count;
}
/* Extract files from a WIM image to a directory on Windows */
static int
win32_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
{
int ret;
struct win32_apply_ctx *ctx = (struct win32_apply_ctx *)_ctx;
u64 dentry_count;
ret = prepare_target(dentry_list, ctx);
if (ret)
goto out;
if (unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT)) {
ret = start_wimboot_extraction(dentry_list, ctx);
if (ret)
goto out;
}
ctx->windows_build_number = xml_get_windows_build_number(ctx->common.wim->xml_info,
ctx->common.wim->current_image);
dentry_count = count_dentries(dentry_list);
ret = start_file_structure_phase(&ctx->common, dentry_count);
if (ret)
goto out;
ret = create_directories(dentry_list, ctx);
if (ret)
goto out;
ret = create_nondirectories(dentry_list, ctx);
if (ret)
goto out;
ret = end_file_structure_phase(&ctx->common);
if (ret)
goto out;
struct read_blob_callbacks cbs = {
.begin_blob = win32_begin_extract_blob,
.continue_blob = win32_extract_chunk,
.end_blob = win32_end_extract_blob,
.ctx = ctx,
};
ret = extract_blob_list(&ctx->common, &cbs);
if (ret)
goto out;
ret = start_file_metadata_phase(&ctx->common, dentry_count);
if (ret)
goto out;
ret = apply_metadata(dentry_list, ctx);
if (ret)
goto out;
ret = end_file_metadata_phase(&ctx->common);
if (ret)
goto out;
if (unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT)) {
ret = end_wimboot_extraction(ctx);
if (ret)
goto out;
}
do_warnings(ctx);
out:
close_target_directory(ctx);
if (ctx->target_ntpath.Buffer)
HeapFree(GetProcessHeap(), 0, ctx->target_ntpath.Buffer);
FREE(ctx->pathbuf.Buffer);
FREE(ctx->print_buffer);
FREE(ctx->wimboot.wims);
if (ctx->prepopulate_pats) {
FREE(ctx->prepopulate_pats->strings);
FREE(ctx->prepopulate_pats);
}
FREE(ctx->mem_prepopulate_pats);
FREE(ctx->data_buffer);
return ret;
}
const struct apply_operations win32_apply_ops = {
.name = "Windows",
.get_supported_features = win32_get_supported_features,
.extract = win32_extract,
.will_back_from_wim = win32_will_back_from_wim,
.context_size = sizeof(struct win32_apply_ctx),
};
#endif /* _WIN32 */
wimlib-1.14.5/src/encoding.c 0000644 0001750 0001750 00000036414 15137020663 013113 0 ustar 00e e /*
* encoding.c - UTF-8 and UTF-16LE codecs and utility functions
*
* Copyright 2012-2023 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include "wimlib/encoding.h"
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/unaligned.h"
#include "wimlib/util.h"
/*
* Allow unpaired surrogates, such as might exist in Windows-style filenames ---
* which are normally valid UTF-16LE, but are actually treated as opaque
* sequences of 16-bit WCHARs by Windows. When decoding "UTF-16LE", unpaired
* surrogates will be decoded as their surrogate codepoints; and when encoding
* to and from "UTF-8", the encoding will actually be WTF-8 ("Wobbly
* Transformation Format - 8-bit"), a superset of UTF-8 which permits the
* surrogate codepoints.
*
* In combination with also allowing the "non-character" codepoints U+FFFE and
* U+FFFF, the result is that every Windows-style filename can be translated to
* a UNIX-style filename.
*
* Unfortunately, the converse is not true: not every UNIX filename can be
* translated to a Windows filename. Only UNIX filenames that are valid "WTF-8"
* can be translated. I considered ways to define a bijective mapping, but
* there did not seem to be a straightforward way. The "UTF-8b" scheme, for
* example, would map each invalid byte 'b' to a surrogate "escape code" 'U+DC00
* + b'. The problem with this was that surrogate escape codes can be combined
* to create a valid UTF-8 sequence, thus breaking the bijection by mapping
* multiple Windows filenames to a single UNIX filename.
*/
#define ALLOW_UNPAIRED_SURROGATES 1
#define INVALID_CODEPOINT 0xFFFFFFFF
#define VALIDATE(expr) if (validate && unlikely(!(expr))) goto invalid
#define IS_SURROGATE(c) ((c) >= 0xD800 && (c) < 0xE000)
#define IS_HIGH_SURROGATE(c) ((c) >= 0xD800 && (c) < 0xDC00)
#define IS_LOW_SURROGATE(c) ((c) >= 0xDC00 && (c) < 0xE000)
#define IS_UTF8_TAIL(c) (((c) & 0xC0) == 0x80)
/*
* Decode the next Unicode codepoint from the string at @in, which has
* @remaining >= 1 bytes remaining. Return the number of bytes consumed and
* write the decoded codepoint to *c_ret.
*
* If the input might not be a valid string in the source encoding, then
* @validate must be specified as %true, and then on invalid input the function
* consumes at least one byte and sets *c_ret to INVALID_CODEPOINT. If the
* input is guaranteed to be valid, then @validate may be specified as %false.
*/
typedef unsigned (*decode_codepoint_fn)(const u8 *in, size_t remaining,
bool validate, u32 *c_ret);
/* Encode the Unicode codepoint @c and return the number of bytes used. */
typedef unsigned (*encode_codepoint_fn)(u32 c, u8 *out);
static forceinline unsigned
utf8_decode_codepoint(const u8 *in, size_t remaining, bool validate, u32 *c_ret)
{
if (likely(in[0] < 0x80)) { /* U+0...U+7F */
*c_ret = in[0];
return 1;
}
if (in[0] < 0xE0) { /* U+80...U+7FF */
VALIDATE(in[0] >= 0xC2 && remaining >= 2 &&
IS_UTF8_TAIL(in[1]));
*c_ret = ((u32)(in[0] & 0x1F) << 6) |
((u32)(in[1] & 0x3F) << 0);
return 2;
}
if (in[0] < 0xF0) { /* U+800...U+FFFF, possibly excluding surrogates */
VALIDATE(remaining >= 3 &&
IS_UTF8_TAIL(in[1]) &&
IS_UTF8_TAIL(in[2]));
*c_ret = ((u32)(in[0] & 0x0F) << 12) |
((u32)(in[1] & 0x3F) << 6) |
((u32)(in[2] & 0x3F) << 0);
VALIDATE(*c_ret >= 0x800);
#if !ALLOW_UNPAIRED_SURROGATES
VALIDATE(!IS_SURROGATE(*c_ret));
#endif
return 3;
}
/* U+10000...U+10FFFF */
VALIDATE(in[0] < 0xF8 && remaining >= 4 &&
IS_UTF8_TAIL(in[1]) &&
IS_UTF8_TAIL(in[2]) &&
IS_UTF8_TAIL(in[3]));
*c_ret = ((u32)(in[0] & 0x07) << 18) |
((u32)(in[1] & 0x3F) << 12) |
((u32)(in[2] & 0x3F) << 6) |
((u32)(in[3] & 0x3F) << 0);
VALIDATE(*c_ret >= 0x10000 && *c_ret <= 0x10FFFF);
return 4;
invalid:
*c_ret = INVALID_CODEPOINT;
return 1;
}
static forceinline unsigned
utf8_encode_codepoint(u32 c, u8 *out)
{
if (likely(c < 0x80)) {
out[0] = c;
return 1;
}
if (c < 0x800) {
out[0] = 0xC0 | (c >> 6);
out[1] = 0x80 | (c & 0x3F);
return 2;
}
if (c < 0x10000) {
out[0] = 0xE0 | (c >> 12);
out[1] = 0x80 | ((c >> 6) & 0x3F);
out[2] = 0x80 | (c & 0x3F);
return 3;
}
out[0] = 0xF0 | (c >> 18);
out[1] = 0x80 | ((c >> 12) & 0x3F);
out[2] = 0x80 | ((c >> 6) & 0x3F);
out[3] = 0x80 | (c & 0x3F);
return 4;
}
static forceinline unsigned
utf16le_decode_codepoint(const u8 *in, size_t remaining, bool validate,
u32 *c_ret)
{
u32 h, l;
VALIDATE(remaining >= 2);
h = get_unaligned_le16(in);
if (unlikely(IS_SURROGATE(h))) {
/* Surrogate pairs are U+10000...U+10FFFF.
* Unpaired surrogates are U+D800...U+DFFF. */
#if ALLOW_UNPAIRED_SURROGATES
if (unlikely(!IS_HIGH_SURROGATE(h) || remaining < 4))
goto unpaired;
l = get_unaligned_le16(in + 2);
if (unlikely(!IS_LOW_SURROGATE(l)))
goto unpaired;
#else
VALIDATE(IS_HIGH_SURROGATE(h) && remaining >= 4);
l = get_unaligned_le16(in + 2);
VALIDATE(IS_LOW_SURROGATE(l));
#endif
*c_ret = 0x10000 + ((h - 0xD800) << 10) + (l - 0xDC00);
return 4;
}
#if ALLOW_UNPAIRED_SURROGATES
unpaired:
#endif
*c_ret = h;
return 2;
invalid:
*c_ret = INVALID_CODEPOINT;
return min(remaining, 2);
}
static forceinline unsigned
utf16le_encode_codepoint(u32 c, u8 *out)
{
if (likely(c < 0x10000)) {
put_unaligned_le16(c, out);
return 2;
}
c -= 0x10000;
put_unaligned_le16(0xD800 + (c >> 10), out);
put_unaligned_le16(0xDC00 + (c & 0x3FF), out + 2);
return 4;
}
/*
* Convert the string @in of size @in_nbytes from the encoding given by the
* @decode_codepoint function to the encoding given by the @encode_codepoint
* function. @in does not need to be null-terminated, but a null terminator
* will be added to the output string.
*
* On success, write the allocated output string to @out_ret (must not be NULL)
* and its size excluding the null terminator to @out_nbytes_ret (may be NULL).
*
* If the input string is malformed, return @ilseq_err with errno set to EILSEQ.
* If out of memory, return WIMLIB_ERR_NOMEM with errno set to ENOMEM.
*/
static forceinline int
convert_string(const u8 * const in, const size_t in_nbytes,
u8 **out_ret, size_t *out_nbytes_ret,
int ilseq_err,
decode_codepoint_fn decode_codepoint,
encode_codepoint_fn encode_codepoint)
{
size_t i;
u8 *p_out;
size_t out_nbytes = 0;
u8 *out;
u8 tmp[8]; /* assuming no codepoint requires > 8 bytes to encode */
u32 c;
/* Validate the input string and compute the output size. */
for (i = 0; i < in_nbytes; ) {
i += (*decode_codepoint)(&in[i], in_nbytes - i, true, &c);
if (unlikely(c == INVALID_CODEPOINT)) {
errno = EILSEQ;
return ilseq_err;
}
out_nbytes += (*encode_codepoint)(c, tmp);
}
/* Allocate the output string, including space for a null terminator. */
out = MALLOC(out_nbytes + (*encode_codepoint)(0, tmp));
if (unlikely(!out))
return WIMLIB_ERR_NOMEM;
/* Do the conversion. */
p_out = out;
for (i = 0; i < in_nbytes; ) {
i += (*decode_codepoint)(&in[i], in_nbytes - i, false, &c);
p_out += (*encode_codepoint)(c, p_out);
}
/* Add a null terminator. */
(*encode_codepoint)(0, p_out);
/* Return the output string and its size (by reference). */
*out_ret = out;
if (out_nbytes_ret)
*out_nbytes_ret = out_nbytes;
return 0;
}
int
utf8_to_utf16le(const char *in, size_t in_nbytes,
utf16lechar **out_ret, size_t *out_nbytes_ret)
{
return convert_string((const u8 *)in, in_nbytes,
(u8 **)out_ret, out_nbytes_ret,
WIMLIB_ERR_INVALID_UTF8_STRING,
utf8_decode_codepoint, utf16le_encode_codepoint);
}
int
utf16le_to_utf8(const utf16lechar *in, size_t in_nbytes,
char **out_ret, size_t *out_nbytes_ret)
{
return convert_string((const u8 *)in, in_nbytes,
(u8 **)out_ret, out_nbytes_ret,
WIMLIB_ERR_INVALID_UTF16_STRING,
utf16le_decode_codepoint, utf8_encode_codepoint);
}
/*
* A table that maps from UCS-2 characters to their upper case equivalents.
* Index and array values are both CPU endian.
* Note: this is only an *approximation* of real UTF-16 case folding.
*/
u16 upcase[65536];
void
init_upcase(void)
{
/* This is the table used in NTFS volumes formatted by Windows 10.
* It was compressed by tools/compress_upcase_table.c. */
static const u16 upcase_compressed[] = {
0x0000, 0x0000, 0x0060, 0x0000, 0x0000, 0xffe0, 0x0019, 0x0061,
0x0061, 0x0000, 0x001b, 0x005d, 0x0008, 0x0060, 0x0000, 0x0079,
0x0000, 0x0000, 0x0000, 0xffff, 0x002f, 0x0100, 0x0002, 0x0000,
0x0007, 0x012b, 0x0011, 0x0121, 0x002f, 0x0103, 0x0006, 0x0101,
0x0000, 0x00c3, 0x0006, 0x0131, 0x0007, 0x012e, 0x0004, 0x0000,
0x0003, 0x012f, 0x0000, 0x0061, 0x0004, 0x0130, 0x0000, 0x00a3,
0x0003, 0x0000, 0x0000, 0x0082, 0x000b, 0x0131, 0x0006, 0x0189,
0x0008, 0x012f, 0x0007, 0x012e, 0x0000, 0x0038, 0x0006, 0x0000,
0x0000, 0xfffe, 0x0007, 0x01c4, 0x000f, 0x0101, 0x0000, 0xffb1,
0x0015, 0x011e, 0x0004, 0x01cc, 0x002a, 0x0149, 0x0014, 0x0149,
0x0007, 0x0000, 0x0009, 0x018c, 0x000b, 0x0138, 0x0000, 0x2a1f,
0x0000, 0x2a1c, 0x0000, 0x0000, 0x0000, 0xff2e, 0x0000, 0xff32,
0x0000, 0x0000, 0x0000, 0xff33, 0x0000, 0xff33, 0x0000, 0x0000,
0x0000, 0xff36, 0x0000, 0x0000, 0x0000, 0xff35, 0x0004, 0x0000,
0x0002, 0x0257, 0x0000, 0x0000, 0x0000, 0xff31, 0x0004, 0x0000,
0x0000, 0xff2f, 0x0000, 0xff2d, 0x0000, 0x0000, 0x0000, 0x29f7,
0x0003, 0x0000, 0x0002, 0x0269, 0x0000, 0x29fd, 0x0000, 0xff2b,
0x0002, 0x0000, 0x0000, 0xff2a, 0x0007, 0x0000, 0x0000, 0x29e7,
0x0002, 0x0000, 0x0000, 0xff26, 0x0005, 0x027e, 0x0003, 0x027e,
0x0000, 0xffbb, 0x0000, 0xff27, 0x0000, 0xff27, 0x0000, 0xffb9,
0x0005, 0x0000, 0x0000, 0xff25, 0x0065, 0x007b, 0x0079, 0x0293,
0x0008, 0x012d, 0x0003, 0x019c, 0x0002, 0x037b, 0x002e, 0x0000,
0x0000, 0xffda, 0x0000, 0xffdb, 0x0002, 0x03ad, 0x0012, 0x0060,
0x000a, 0x0060, 0x0000, 0xffc0, 0x0000, 0xffc1, 0x0000, 0xffc1,
0x0008, 0x0000, 0x0000, 0xfff8, 0x001a, 0x0118, 0x0000, 0x0007,
0x0008, 0x018d, 0x0009, 0x0233, 0x0046, 0x0035, 0x0006, 0x0061,
0x0000, 0xffb0, 0x000f, 0x0450, 0x0025, 0x010e, 0x000a, 0x036b,
0x0032, 0x048b, 0x000e, 0x0100, 0x0000, 0xfff1, 0x0037, 0x048a,
0x0026, 0x0465, 0x0034, 0x0000, 0x0000, 0xffd0, 0x0025, 0x0561,
0x00de, 0x0293, 0x1714, 0x0587, 0x0000, 0x8a04, 0x0003, 0x0000,
0x0000, 0x0ee6, 0x0087, 0x02ee, 0x0092, 0x1e01, 0x0069, 0x1df7,
0x0000, 0x0008, 0x0007, 0x1f00, 0x0008, 0x0000, 0x000e, 0x1f02,
0x0008, 0x1f0e, 0x0010, 0x1f06, 0x001a, 0x1f06, 0x0002, 0x1f0f,
0x0007, 0x1f50, 0x0017, 0x1f19, 0x0000, 0x004a, 0x0000, 0x004a,
0x0000, 0x0056, 0x0003, 0x1f72, 0x0000, 0x0064, 0x0000, 0x0064,
0x0000, 0x0080, 0x0000, 0x0080, 0x0000, 0x0070, 0x0000, 0x0070,
0x0000, 0x007e, 0x0000, 0x007e, 0x0028, 0x1f1e, 0x000c, 0x1f06,
0x0000, 0x0000, 0x0000, 0x0009, 0x000f, 0x0000, 0x000d, 0x1fb3,
0x000d, 0x1f44, 0x0008, 0x1fcd, 0x0006, 0x03f2, 0x0015, 0x1fbb,
0x014e, 0x0587, 0x0000, 0xffe4, 0x0021, 0x0000, 0x0000, 0xfff0,
0x000f, 0x2170, 0x000a, 0x0238, 0x0346, 0x0587, 0x0000, 0xffe6,
0x0019, 0x24d0, 0x0746, 0x0587, 0x0026, 0x0561, 0x000b, 0x057e,
0x0004, 0x012f, 0x0000, 0xd5d5, 0x0000, 0xd5d8, 0x000c, 0x022e,
0x000e, 0x03f8, 0x006e, 0x1e33, 0x0011, 0x0000, 0x0000, 0xe3a0,
0x0025, 0x2d00, 0x17f2, 0x0587, 0x6129, 0x2d26, 0x002e, 0x0201,
0x002a, 0x1def, 0x0098, 0xa5b7, 0x0040, 0x1dff, 0x000e, 0x0368,
0x000d, 0x022b, 0x034c, 0x2184, 0x5469, 0x2d26, 0x007f, 0x0061,
0x0040, 0x0000,
};
/* Simple LZ decoder */
const u16 *in_next = upcase_compressed;
for (u32 i = 0; i < ARRAY_LEN(upcase); ) {
u16 length = *in_next++;
u16 src_pos = *in_next++;
if (length == 0) {
/* Literal */
upcase[i++] = src_pos;
} else {
/* Match */
do {
upcase[i++] = upcase[src_pos++];
} while (--length);
}
}
/* Delta filter */
for (u32 i = 0; i < ARRAY_LEN(upcase); i++)
upcase[i] += i;
}
/*
* Compare UTF-16LE strings case-sensitively (%ignore_case == false) or
* case-insensitively (%ignore_case == true).
*
* This is implemented using the default upper-case table used by NTFS. It does
* not handle all possible cases allowed by UTF-16LE. For example, different
* normalizations of the same sequence of "characters" are not considered equal.
* It hopefully does the right thing most of the time though.
*/
int
cmp_utf16le_strings(const utf16lechar *s1, size_t n1,
const utf16lechar *s2, size_t n2,
bool ignore_case)
{
size_t n = min(n1, n2);
if (ignore_case) {
for (size_t i = 0; i < n; i++) {
u16 c1 = upcase[le16_to_cpu(s1[i])];
u16 c2 = upcase[le16_to_cpu(s2[i])];
if (c1 != c2)
return (c1 < c2) ? -1 : 1;
}
} else {
for (size_t i = 0; i < n; i++) {
u16 c1 = le16_to_cpu(s1[i]);
u16 c2 = le16_to_cpu(s2[i]);
if (c1 != c2)
return (c1 < c2) ? -1 : 1;
}
}
if (n1 == n2)
return 0;
return (n1 < n2) ? -1 : 1;
}
/* Like cmp_utf16le_strings(), but assumes the strings are null terminated. */
int
cmp_utf16le_strings_z(const utf16lechar *s1, const utf16lechar *s2,
bool ignore_case)
{
if (ignore_case) {
for (;;) {
u16 c1 = upcase[le16_to_cpu(*s1)];
u16 c2 = upcase[le16_to_cpu(*s2)];
if (c1 != c2)
return (c1 < c2) ? -1 : 1;
if (c1 == 0)
return 0;
s1++, s2++;
}
} else {
while (*s1 && *s1 == *s2)
s1++, s2++;
if (*s1 == *s2)
return 0;
return (le16_to_cpu(*s1) < le16_to_cpu(*s2)) ? -1 : 1;
}
}
/* Duplicate a UTF-16 string. The input string might not be null terminated and
* might be misaligned, but the returned string is guaranteed to be null
* terminated and properly aligned. */
utf16lechar *
utf16le_dupz(const void *s, size_t size)
{
utf16lechar *dup = MALLOC(size + sizeof(utf16lechar));
if (dup) {
memcpy(dup, s, size);
dup[size / sizeof(utf16lechar)] = 0;
}
return dup;
}
/* Duplicate a null-terminated UTF-16 string. */
utf16lechar *
utf16le_dup(const utf16lechar *s)
{
return memdup(s, utf16le_len_bytes(s) + sizeof(utf16lechar));
}
/* Return the length, in bytes, of a null terminated UTF-16 string, excluding
* the null terminator. */
size_t
utf16le_len_bytes(const utf16lechar *s)
{
const utf16lechar *p = s;
while (*p)
p++;
return (p - s) * sizeof(utf16lechar);
}
/* Return the length, in UTF-16 coding units, of a null terminated UTF-16
* string, excluding the null terminator. */
size_t
utf16le_len_chars(const utf16lechar *s)
{
return utf16le_len_bytes(s) / sizeof(utf16lechar);
}
#ifdef ENABLE_TEST_SUPPORT
#include "wimlib/test_support.h"
WIMLIBAPI int
wimlib_utf8_to_utf16le(const char *in, size_t in_nbytes,
utf16lechar **out_ret, size_t *out_nbytes_ret)
{
return utf8_to_utf16le(in, in_nbytes, out_ret, out_nbytes_ret);
}
WIMLIBAPI int
wimlib_utf16le_to_utf8(const utf16lechar *in, size_t in_nbytes,
char **out_ret, size_t *out_nbytes_ret)
{
return utf16le_to_utf8(in, in_nbytes, out_ret, out_nbytes_ret);
}
#endif /* ENABLE_TEST_SUPPORT */
wimlib-1.14.5/src/split.c 0000644 0001750 0001750 00000015316 15137020663 012456 0 ustar 00e e /*
* split.c
*
* Split a WIM file into parts.
*/
/*
* Copyright (C) 2012, 2013 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib.h"
#include "wimlib/alloca.h"
#include "wimlib/blob_table.h"
#include "wimlib/error.h"
#include "wimlib/list.h"
#include "wimlib/metadata.h"
#include "wimlib/paths.h"
#include "wimlib/progress.h"
#include "wimlib/resource.h"
#include "wimlib/wim.h"
#include "wimlib/write.h"
struct swm_part_info {
struct list_head blob_list;
u64 size;
};
static void
copy_part_info(struct swm_part_info *dst, struct swm_part_info *src)
{
list_replace(&src->blob_list, &dst->blob_list);
dst->size = src->size;
}
struct swm_info {
struct swm_part_info *parts;
unsigned num_parts;
unsigned num_alloc_parts;
u64 total_bytes;
u64 max_part_size;
};
static int
write_split_wim(WIMStruct *orig_wim, const tchar *swm_name,
struct swm_info *swm_info, int write_flags)
{
size_t swm_name_len;
tchar *swm_name_buf;
const tchar *dot;
tchar *swm_suffix;
size_t swm_base_name_len;
union wimlib_progress_info progress;
unsigned part_number;
int ret;
u8 guid[GUID_SIZE];
swm_name_len = tstrlen(swm_name);
swm_name_buf = alloca((swm_name_len + 20) * sizeof(tchar));
tstrcpy(swm_name_buf, swm_name);
dot = tstrrchr(path_basename(swm_name_buf), T('.'));
if (dot) {
swm_base_name_len = dot - swm_name_buf;
swm_suffix = alloca((tstrlen(dot) + 1) * sizeof(tchar));
tstrcpy(swm_suffix, dot);
} else {
swm_base_name_len = swm_name_len;
swm_suffix = alloca(1 * sizeof(tchar));
swm_suffix[0] = T('\0');
}
progress.split.completed_bytes = 0;
progress.split.total_bytes = 0;
for (part_number = 1; part_number <= swm_info->num_parts; part_number++)
progress.split.total_bytes += swm_info->parts[part_number - 1].size;
progress.split.total_parts = swm_info->num_parts;
generate_guid(guid);
for (part_number = 1; part_number <= swm_info->num_parts; part_number++) {
int part_write_flags;
if (part_number != 1) {
tsprintf(swm_name_buf + swm_base_name_len,
T("%u%"TS), part_number, swm_suffix);
}
progress.split.cur_part_number = part_number;
progress.split.part_name = swm_name_buf;
ret = call_progress(orig_wim->progfunc,
WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART,
&progress,
orig_wim->progctx);
if (ret)
return ret;
part_write_flags = write_flags;
part_write_flags |= WIMLIB_WRITE_FLAG_USE_EXISTING_TOTALBYTES;
if (part_number != 1)
part_write_flags |= WIMLIB_WRITE_FLAG_NO_METADATA;
ret = write_wim_part(orig_wim,
progress.split.part_name,
WIMLIB_ALL_IMAGES,
part_write_flags,
1,
part_number,
swm_info->num_parts,
&swm_info->parts[part_number - 1].blob_list,
guid);
if (ret)
return ret;
progress.split.completed_bytes += swm_info->parts[part_number - 1].size;
ret = call_progress(orig_wim->progfunc,
WIMLIB_PROGRESS_MSG_SPLIT_END_PART,
&progress,
orig_wim->progctx);
if (ret)
return ret;
}
return 0;
}
static int
start_new_swm_part(struct swm_info *swm_info)
{
if (swm_info->num_parts == swm_info->num_alloc_parts) {
struct swm_part_info *parts;
size_t num_alloc_parts = swm_info->num_alloc_parts;
num_alloc_parts += 8;
parts = MALLOC(num_alloc_parts * sizeof(parts[0]));
if (!parts)
return WIMLIB_ERR_NOMEM;
for (unsigned i = 0; i < swm_info->num_parts; i++)
copy_part_info(&parts[i], &swm_info->parts[i]);
FREE(swm_info->parts);
swm_info->parts = parts;
swm_info->num_alloc_parts = num_alloc_parts;
}
swm_info->num_parts++;
INIT_LIST_HEAD(&swm_info->parts[swm_info->num_parts - 1].blob_list);
swm_info->parts[swm_info->num_parts - 1].size = 0;
return 0;
}
static int
add_blob_to_swm(struct blob_descriptor *blob, void *_swm_info)
{
struct swm_info *swm_info = _swm_info;
u64 blob_stored_size;
int ret;
if (blob->blob_location == BLOB_IN_WIM)
blob_stored_size = blob->rdesc->size_in_wim;
else
blob_stored_size = blob->size;
/* Start the next part if adding this blob exceeds the maximum part
* size, UNLESS the blob is metadata or if no blobs at all have been
* added to the current part. */
if ((swm_info->parts[swm_info->num_parts - 1].size +
blob_stored_size >= swm_info->max_part_size)
&& !(blob->is_metadata ||
swm_info->parts[swm_info->num_parts - 1].size == 0))
{
ret = start_new_swm_part(swm_info);
if (ret)
return ret;
}
swm_info->parts[swm_info->num_parts - 1].size += blob_stored_size;
if (!blob->is_metadata) {
list_add_tail(&blob->write_blobs_list,
&swm_info->parts[swm_info->num_parts - 1].blob_list);
}
swm_info->total_bytes += blob_stored_size;
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_split(WIMStruct *wim, const tchar *swm_name,
u64 part_size, int write_flags)
{
struct swm_info swm_info;
unsigned i;
int ret;
if (swm_name == NULL || swm_name[0] == T('\0') || part_size == 0)
return WIMLIB_ERR_INVALID_PARAM;
if (write_flags & ~WIMLIB_WRITE_MASK_PUBLIC)
return WIMLIB_ERR_INVALID_PARAM;
if (!wim_has_metadata(wim))
return WIMLIB_ERR_METADATA_NOT_FOUND;
if (wim_has_solid_resources(wim)) {
ERROR("Splitting of WIM containing solid resources is not supported.\n"
" Export it in non-solid format first.");
return WIMLIB_ERR_UNSUPPORTED;
}
for (i = 0; i < wim->hdr.image_count; i++) {
if (!is_image_unchanged_from_wim(wim->image_metadata[i], wim)) {
ERROR("Only an unmodified, on-disk WIM file can be split.");
return WIMLIB_ERR_UNSUPPORTED;
}
}
memset(&swm_info, 0, sizeof(swm_info));
swm_info.max_part_size = part_size;
ret = start_new_swm_part(&swm_info);
if (ret)
goto out_free_swm_info;
for (i = 0; i < wim->hdr.image_count; i++) {
ret = add_blob_to_swm(wim->image_metadata[i]->metadata_blob,
&swm_info);
if (ret)
goto out_free_swm_info;
}
ret = for_blob_in_table_sorted_by_sequential_order(wim->blob_table,
add_blob_to_swm,
&swm_info);
if (ret)
goto out_free_swm_info;
ret = write_split_wim(wim, swm_name, &swm_info, write_flags);
out_free_swm_info:
FREE(swm_info.parts);
return ret;
}
wimlib-1.14.5/src/reference.c 0000644 0001750 0001750 00000013637 15137020663 013265 0 ustar 00e e /*
* reference.c
*
* Reference blobs from external WIM file(s).
*/
/*
* Copyright (C) 2013, 2014, 2015 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib.h"
#include "wimlib/blob_table.h"
#include "wimlib/error.h"
#include "wimlib/glob.h"
#include "wimlib/wim.h"
#define WIMLIB_REF_MASK_PUBLIC (WIMLIB_REF_FLAG_GLOB_ENABLE | \
WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH)
struct reference_info {
WIMStruct *dest_wim;
struct list_head new_blobs;
int ref_flags;
struct blob_table *src_table;
};
static void
init_reference_info(struct reference_info *info, WIMStruct *dest_wim,
int ref_flags)
{
info->dest_wim = dest_wim;
INIT_LIST_HEAD(&info->new_blobs);
info->ref_flags = ref_flags;
}
static void
rollback_reference_info(struct reference_info *info)
{
struct blob_descriptor *blob;
while (!list_empty(&info->new_blobs)) {
blob = list_first_entry(&info->new_blobs,
struct blob_descriptor, blob_table_list);
list_del(&blob->blob_table_list);
blob_table_unlink(info->dest_wim->blob_table, blob);
free_blob_descriptor(blob);
}
}
static bool
need_blob(const struct reference_info *info, const struct blob_descriptor *blob)
{
return !lookup_blob(info->dest_wim->blob_table, blob->hash);
}
static void
reference_blob(struct reference_info *info, struct blob_descriptor *blob)
{
blob_table_insert(info->dest_wim->blob_table, blob);
list_add(&blob->blob_table_list, &info->new_blobs);
}
static int
blob_clone_if_new(struct blob_descriptor *blob, void *_info)
{
struct reference_info *info = _info;
if (need_blob(info, blob)) {
blob = clone_blob_descriptor(blob);
if (unlikely(!blob))
return WIMLIB_ERR_NOMEM;
reference_blob(info, blob);
}
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_reference_resources(WIMStruct *wim, WIMStruct **resource_wims,
unsigned num_resource_wims, int ref_flags)
{
unsigned i;
struct reference_info info;
int ret = 0;
if (wim == NULL)
return WIMLIB_ERR_INVALID_PARAM;
if (num_resource_wims != 0 && resource_wims == NULL)
return WIMLIB_ERR_INVALID_PARAM;
if (ref_flags & ~WIMLIB_REF_MASK_PUBLIC)
return WIMLIB_ERR_INVALID_PARAM;
for (i = 0; i < num_resource_wims; i++)
if (resource_wims[i] == NULL)
return WIMLIB_ERR_INVALID_PARAM;
init_reference_info(&info, wim, ref_flags);
for (i = 0; i < num_resource_wims; i++) {
ret = for_blob_in_table(resource_wims[i]->blob_table,
blob_clone_if_new, &info);
if (ret)
break;
}
if (unlikely(ret))
rollback_reference_info(&info);
return ret;
}
static int
blob_gift(struct blob_descriptor *blob, void *_info)
{
struct reference_info *info = _info;
blob_table_unlink(info->src_table, blob);
if (need_blob(info, blob))
reference_blob(info, blob);
else
free_blob_descriptor(blob);
return 0;
}
static int
reference_resource_path(struct reference_info *info, const tchar *path,
int open_flags)
{
int ret;
WIMStruct *src_wim;
ret = wimlib_open_wim_with_progress(path, open_flags, &src_wim,
info->dest_wim->progfunc,
info->dest_wim->progctx);
if (ret)
return ret;
info->src_table = src_wim->blob_table;
for_blob_in_table(src_wim->blob_table, blob_gift, info);
wimlib_free(src_wim);
return 0;
}
static int
reference_resource_paths(struct reference_info *info,
const tchar * const *paths, unsigned num_paths,
int open_flags)
{
for (unsigned i = 0; i < num_paths; i++) {
int ret = reference_resource_path(info, paths[i], open_flags);
if (ret)
return ret;
}
return 0;
}
static int
reference_resource_glob(struct reference_info *info,
const tchar *refglob, int open_flags)
{
int ret;
glob_t globbuf;
/* Note: glob() is replaced in Windows native builds. */
ret = tglob(refglob, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
if (unlikely(ret)) {
if (ret == GLOB_NOMATCH) {
if (info->ref_flags &
WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH)
{
ERROR("Found no files for glob \"%"TS"\"", refglob);
return WIMLIB_ERR_GLOB_HAD_NO_MATCHES;
}
return reference_resource_path(info,
refglob,
open_flags);
}
ERROR_WITH_ERRNO("Failed to process glob \"%"TS"\"", refglob);
if (ret == GLOB_NOSPACE)
return WIMLIB_ERR_NOMEM;
return WIMLIB_ERR_READ;
}
ret = reference_resource_paths(info,
(const tchar * const *)globbuf.gl_pathv,
globbuf.gl_pathc,
open_flags);
globfree(&globbuf);
return ret;
}
static int
reference_resource_globs(struct reference_info *info,
const tchar * const *globs, unsigned num_globs,
int open_flags)
{
for (unsigned i = 0; i < num_globs; i++) {
int ret = reference_resource_glob(info, globs[i], open_flags);
if (ret)
return ret;
}
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_reference_resource_files(WIMStruct *wim,
const tchar * const *paths_or_globs,
unsigned count, int ref_flags, int open_flags)
{
struct reference_info info;
int ret;
if (ref_flags & ~WIMLIB_REF_MASK_PUBLIC)
return WIMLIB_ERR_INVALID_PARAM;
init_reference_info(&info, wim, ref_flags);
if (ref_flags & WIMLIB_REF_FLAG_GLOB_ENABLE)
ret = reference_resource_globs(&info, paths_or_globs, count, open_flags);
else
ret = reference_resource_paths(&info, paths_or_globs, count, open_flags);
if (unlikely(ret))
rollback_reference_info(&info);
return ret;
}
wimlib-1.14.5/src/timestamp.c 0000644 0001750 0001750 00000007337 15137020663 013332 0 ustar 00e e /*
* timestamp.c
*
* Conversion between Windows NT timestamps and UNIX timestamps.
*/
/*
* Copyright (C) 2012-2017 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib.h" /* for struct wimlib_timespec */
#include "wimlib/timestamp.h"
/*
* Timestamps in WIM files are Windows NT timestamps, or FILETIMEs: 64-bit
* values storing the number of 100-nanosecond ticks since January 1, 1601.
*
* Note: UNIX timestamps are signed; Windows timestamps are not. Negative UNIX
* timestamps represent times before 1970-01-01. When such a timestamp is
* converted to a Windows timestamp, we can preserve the correct date provided
* that it is not also before 1601-01-01.
*/
#define NANOSECONDS_PER_TICK 100
#define TICKS_PER_SECOND (1000000000 / NANOSECONDS_PER_TICK)
#define TICKS_PER_MICROSECOND (TICKS_PER_SECOND / 1000000)
/*
* EPOCH_DISTANCE is the number of seconds separating the Windows NT and UNIX
* epochs. This is equal to ((1970-1601)*365+89)*24*60*60. 89 is the number
* of leap years between 1970 and 1601.
*/
#define EPOCH_DISTANCE 11644473600
/* Windows NT timestamps to UNIX timestamps */
time_t
wim_timestamp_to_time_t(u64 timestamp)
{
return (timestamp / TICKS_PER_SECOND) - EPOCH_DISTANCE;
}
void
wim_timestamp_to_wimlib_timespec(u64 timestamp, struct wimlib_timespec *wts,
s32 *high_part_ret)
{
s64 sec = (timestamp / TICKS_PER_SECOND) - EPOCH_DISTANCE;
wts->tv_sec = sec;
wts->tv_nsec = (timestamp % TICKS_PER_SECOND) * NANOSECONDS_PER_TICK;
if (sizeof(wts->tv_sec) == 4)
*high_part_ret = sec >> 32;
}
#ifdef _WIN32
static void __attribute__((unused))
check_sizeof_time_t(void)
{
/* Windows builds should always be using 64-bit time_t now. */
STATIC_ASSERT(sizeof(time_t) == 8);
}
#else
struct timeval
wim_timestamp_to_timeval(u64 timestamp)
{
return (struct timeval) {
.tv_sec = wim_timestamp_to_time_t(timestamp),
.tv_usec = (timestamp % TICKS_PER_SECOND) / TICKS_PER_MICROSECOND,
};
}
struct timespec
wim_timestamp_to_timespec(u64 timestamp)
{
return (struct timespec) {
.tv_sec = wim_timestamp_to_time_t(timestamp),
.tv_nsec = (timestamp % TICKS_PER_SECOND) * NANOSECONDS_PER_TICK,
};
}
#endif /* !_WIN32 */
/* UNIX timestamps to Windows NT timestamps */
u64
time_t_to_wim_timestamp(time_t t)
{
return ((u64)t + EPOCH_DISTANCE) * TICKS_PER_SECOND;
}
#ifndef _WIN32
u64
timeval_to_wim_timestamp(const struct timeval *tv)
{
return time_t_to_wim_timestamp(tv->tv_sec) +
(u32)tv->tv_usec * TICKS_PER_MICROSECOND;
}
u64
timespec_to_wim_timestamp(const struct timespec *ts)
{
return time_t_to_wim_timestamp(ts->tv_sec) +
(u32)ts->tv_nsec / NANOSECONDS_PER_TICK;
}
/* Retrieve the current time as a WIM timestamp. */
u64
now_as_wim_timestamp(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return timeval_to_wim_timestamp(&tv);
}
#endif /* !_WIN32 */
/* Translate a WIM timestamp into a human-readable string. */
void
wim_timestamp_to_str(u64 timestamp, tchar *buf, size_t len)
{
struct tm tm;
time_t t = wim_timestamp_to_time_t(timestamp);
gmtime_r(&t, &tm);
tstrftime(buf, len, T("%a %b %d %H:%M:%S %Y UTC"), &tm);
}
wimlib-1.14.5/src/lzms_compress.c 0000644 0001750 0001750 00000213761 15137020663 014227 0 ustar 00e e /*
* lzms_compress.c
*
* A compressor for the LZMS compression format.
*/
/*
* Copyright (C) 2013, 2014, 2015 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include "wimlib/compress_common.h"
#include "wimlib/compressor_ops.h"
#include "wimlib/error.h"
#include "wimlib/lcpit_matchfinder.h"
#include "wimlib/lzms_common.h"
#include "wimlib/matchfinder_common.h"
#include "wimlib/unaligned.h"
#include "wimlib/util.h"
/*
* MAX_FAST_LENGTH is the maximum match length for which the length slot can be
* looked up directly in 'fast_length_slot_tab' and the length cost can be
* looked up directly in 'fast_length_cost_tab'.
*
* We also limit the 'nice_match_len' parameter to this value. Consequently, if
* the longest match found is shorter than 'nice_match_len', then it must also
* be shorter than MAX_FAST_LENGTH. This makes it possible to do fast lookups
* of length costs using 'fast_length_cost_tab' without having to keep checking
* whether the length exceeds MAX_FAST_LENGTH or not.
*/
#define MAX_FAST_LENGTH 255
/* NUM_OPTIM_NODES is the maximum number of bytes the parsing algorithm will
* step forward before forcing the pending items to be encoded. If this value
* is increased, then there will be fewer forced flushes, but the probability
* entries and Huffman codes will be more likely to become outdated. */
#define NUM_OPTIM_NODES 2048
/* COST_SHIFT is a scaling factor that makes it possible to consider fractional
* bit costs. A single bit has a cost of (1 << COST_SHIFT). */
#define COST_SHIFT 6
/* Length of the hash table for finding delta matches */
#define DELTA_HASH_ORDER 17
#define DELTA_HASH_LENGTH ((u32)1 << DELTA_HASH_ORDER)
/* The number of bytes to hash when finding delta matches; also taken to be the
* minimum length of an explicit offset delta match */
#define NBYTES_HASHED_FOR_DELTA 3
/* The number of delta match powers to consider (must be <=
* LZMS_NUM_DELTA_POWER_SYMS) */
#define NUM_POWERS_TO_CONSIDER 6
/* This structure tracks the state of writing bits as a series of 16-bit coding
* units, starting at the end of the output buffer and proceeding backwards. */
struct lzms_output_bitstream {
/* Bits that haven't yet been written to the output buffer */
u64 bitbuf;
/* Number of bits currently held in @bitbuf */
unsigned bitcount;
/* Pointer to the beginning of the output buffer (this is the "end" when
* writing backwards!) */
u8 *begin;
/* Pointer to just past the next position in the output buffer at which
* to output a 16-bit coding unit */
u8 *next;
};
/* This structure tracks the state of range encoding and its output, which
* starts at the beginning of the output buffer and proceeds forwards. */
struct lzms_range_encoder {
/* The lower boundary of the current range. Logically, this is a 33-bit
* integer whose high bit is needed to detect carries. */
u64 lower_bound;
/* The size of the current range */
u32 range_size;
/* The next 16-bit coding unit to output */
u16 cache;
/* The number of 16-bit coding units whose output has been delayed due
* to possible carrying. The first such coding unit is @cache; all
* subsequent such coding units are 0xffff. */
u32 cache_size;
/* Pointer to the beginning of the output buffer */
u8 *begin;
/* Pointer to the position in the output buffer at which the next coding
* unit must be written */
u8 *next;
/* Pointer to just past the end of the output buffer */
u8 *end;
};
/* Bookkeeping information for an adaptive Huffman code */
struct lzms_huffman_rebuild_info {
/* The remaining number of symbols to encode until this code must be
* rebuilt */
unsigned num_syms_until_rebuild;
/* The number of symbols in this code */
unsigned num_syms;
/* The rebuild frequency of this code, in symbols */
unsigned rebuild_freq;
/* The Huffman codeword of each symbol in this code */
u32 *codewords;
/* The length of each Huffman codeword, in bits */
u8 *lens;
/* The frequency of each symbol in this code */
u32 *freqs;
};
/*
* The compressor-internal representation of a match or literal.
*
* Literals have length=1; matches have length > 1. (We disallow matches of
* length 1, even though this is a valid length in LZMS.)
*
* The source is encoded as follows:
*
* - Literals: the literal byte itself
* - Explicit offset LZ matches: the match offset plus (LZMS_NUM_LZ_REPS - 1)
* - Repeat offset LZ matches: the index of the offset in recent_lz_offsets
* - Explicit offset delta matches: DELTA_SOURCE_TAG is set, the next 3 bits are
* the power, and the remainder is the raw offset plus (LZMS_NUM_DELTA_REPS-1)
* - Repeat offset delta matches: DELTA_SOURCE_TAG is set, and the remainder is
* the index of the (power, raw_offset) pair in recent_delta_pairs
*/
struct lzms_item {
u32 length;
u32 source;
};
#define DELTA_SOURCE_TAG ((u32)1 << 31)
#define DELTA_SOURCE_POWER_SHIFT 28
#define DELTA_SOURCE_RAW_OFFSET_MASK (((u32)1 << DELTA_SOURCE_POWER_SHIFT) - 1)
static void __attribute__((unused))
check_that_powers_fit_in_bitfield(void)
{
STATIC_ASSERT(LZMS_NUM_DELTA_POWER_SYMS <= (1 << (31 - DELTA_SOURCE_POWER_SHIFT)));
}
/* A stripped-down version of the adaptive state in LZMS which excludes the
* probability entries and Huffman codes */
struct lzms_adaptive_state {
/* Recent offsets for LZ matches */
u32 recent_lz_offsets[LZMS_NUM_LZ_REPS + 1];
u32 prev_lz_offset; /* 0 means none */
u32 upcoming_lz_offset; /* 0 means none */
/* Recent (power, raw offset) pairs for delta matches.
* The low DELTA_SOURCE_POWER_SHIFT bits of each entry are the raw
* offset, and the high bits are the power. */
u32 recent_delta_pairs[LZMS_NUM_DELTA_REPS + 1];
u32 prev_delta_pair; /* 0 means none */
u32 upcoming_delta_pair; /* 0 means none */
/* States for predicting the probabilities of item types */
u8 main_state;
u8 match_state;
u8 lz_state;
u8 lz_rep_states[LZMS_NUM_LZ_REP_DECISIONS];
u8 delta_state;
u8 delta_rep_states[LZMS_NUM_DELTA_REP_DECISIONS];
} __attribute__((aligned(64)));
/*
* This structure represents a byte position in the preprocessed input data and
* a node in the graph of possible match/literal choices.
*
* Logically, each incoming edge to this node is labeled with a literal or a
* match that can be taken to reach this position from an earlier position; and
* each outgoing edge from this node is labeled with a literal or a match that
* can be taken to advance from this position to a later position.
*/
struct lzms_optimum_node {
/*
* The cost of the lowest-cost path that has been found to reach this
* position. This can change as progressively lower cost paths are
* found to reach this position.
*/
u32 cost;
#define INFINITE_COST UINT32_MAX
/*
* @item is the last item that was taken to reach this position to reach
* it with the stored @cost. This can change as progressively lower
* cost paths are found to reach this position.
*
* In some cases we look ahead more than one item. If we looked ahead n
* items to reach this position, then @item is the last item taken,
* @extra_items contains the other items ordered from second-to-last to
* first, and @num_extra_items is n - 1.
*/
unsigned num_extra_items;
struct lzms_item item;
struct lzms_item extra_items[2];
/*
* The adaptive state that exists at this position. This is filled in
* lazily, only after the minimum-cost path to this position is found.
*
* Note: the way the algorithm handles this adaptive state in the
* "minimum-cost" parse is actually only an approximation. It's
* possible for the globally optimal, minimum cost path to contain a
* prefix, ending at a position, where that path prefix is *not* the
* minimum cost path to that position. This can happen if such a path
* prefix results in a different adaptive state which results in lower
* costs later. Although the algorithm does do some heuristic
* multi-item lookaheads, it does not solve this problem in general.
*
* Note: this adaptive state structure also does not include the
* probability entries or current Huffman codewords. Those aren't
* maintained per-position and are only updated occasionally.
*/
struct lzms_adaptive_state state;
} __attribute__((aligned(64)));
/* The main compressor structure */
struct lzms_compressor {
/* The matchfinder for LZ matches */
struct lcpit_matchfinder mf;
/* The preprocessed buffer of data being compressed */
u8 *in_buffer;
/* The number of bytes of data to be compressed, which is the number of
* bytes of data in @in_buffer that are actually valid */
size_t in_nbytes;
/*
* Boolean flags to enable consideration of various types of multi-step
* operations during parsing.
*
* Among other cases, multi-step operations can help with gaps where two
* matches are separated by a non-matching byte.
*
* This idea is borrowed from Igor Pavlov's LZMA encoder.
*/
bool try_lit_lzrep0;
bool try_lzrep_lit_lzrep0;
bool try_lzmatch_lit_lzrep0;
/*
* If true, the compressor can use delta matches. This slows down
* compression. It improves the compression ratio greatly, slightly, or
* not at all, depending on the input data.
*/
bool use_delta_matches;
/* If true, the compressor need not preserve the input buffer if it
* compresses the data successfully. */
bool destructive;
/* 'last_target_usages' is a large array that is only needed for
* preprocessing, so it is in union with fields that don't need to be
* initialized until after preprocessing. */
union {
struct {
/* Temporary space to store matches found by the LZ matchfinder */
struct lz_match matches[MAX_FAST_LENGTH - LZMS_MIN_MATCH_LENGTH + 1];
/* Hash table for finding delta matches */
u32 delta_hash_table[DELTA_HASH_LENGTH];
/* For each delta power, the hash code for the next sequence */
u32 next_delta_hashes[NUM_POWERS_TO_CONSIDER];
/* The per-byte graph nodes for near-optimal parsing */
struct lzms_optimum_node optimum_nodes[NUM_OPTIM_NODES + MAX_FAST_LENGTH +
1 + MAX_FAST_LENGTH];
/* Table: length => current cost for small match lengths */
u32 fast_length_cost_tab[MAX_FAST_LENGTH + 1];
/* Range encoder which outputs to the beginning of the compressed data
* buffer, proceeding forwards */
struct lzms_range_encoder rc;
/* Bitstream which outputs to the end of the compressed data buffer,
* proceeding backwards */
struct lzms_output_bitstream os;
/* States and probability entries for item type disambiguation */
unsigned main_state;
unsigned match_state;
unsigned lz_state;
unsigned lz_rep_states[LZMS_NUM_LZ_REP_DECISIONS];
unsigned delta_state;
unsigned delta_rep_states[LZMS_NUM_DELTA_REP_DECISIONS];
struct lzms_probabilites probs;
/* Huffman codes */
struct lzms_huffman_rebuild_info literal_rebuild_info;
u32 literal_codewords[LZMS_NUM_LITERAL_SYMS];
u8 literal_lens[LZMS_NUM_LITERAL_SYMS];
u32 literal_freqs[LZMS_NUM_LITERAL_SYMS];
struct lzms_huffman_rebuild_info lz_offset_rebuild_info;
u32 lz_offset_codewords[LZMS_MAX_NUM_OFFSET_SYMS];
u8 lz_offset_lens[LZMS_MAX_NUM_OFFSET_SYMS];
u32 lz_offset_freqs[LZMS_MAX_NUM_OFFSET_SYMS];
struct lzms_huffman_rebuild_info length_rebuild_info;
u32 length_codewords[LZMS_NUM_LENGTH_SYMS];
u8 length_lens[LZMS_NUM_LENGTH_SYMS];
u32 length_freqs[LZMS_NUM_LENGTH_SYMS];
struct lzms_huffman_rebuild_info delta_offset_rebuild_info;
u32 delta_offset_codewords[LZMS_MAX_NUM_OFFSET_SYMS];
u8 delta_offset_lens[LZMS_MAX_NUM_OFFSET_SYMS];
u32 delta_offset_freqs[LZMS_MAX_NUM_OFFSET_SYMS];
struct lzms_huffman_rebuild_info delta_power_rebuild_info;
u32 delta_power_codewords[LZMS_NUM_DELTA_POWER_SYMS];
u8 delta_power_lens[LZMS_NUM_DELTA_POWER_SYMS];
u32 delta_power_freqs[LZMS_NUM_DELTA_POWER_SYMS];
}; /* struct */
s32 last_target_usages[65536];
}; /* union */
/* Table: length => length slot for small match lengths */
u8 fast_length_slot_tab[MAX_FAST_LENGTH + 1];
/* Tables for mapping offsets to offset slots */
/* slots [0, 167); 0 <= num_extra_bits <= 10 */
u8 offset_slot_tab_1[0xe4a5];
/* slots [167, 427); 11 <= num_extra_bits <= 15 */
u16 offset_slot_tab_2[0x3d0000 >> 11];
/* slots [427, 799); 16 <= num_extra_bits */
u16 offset_slot_tab_3[((LZMS_MAX_MATCH_OFFSET + 1) - 0xe4a5) >> 16];
};
/******************************************************************************
* Offset and length slot acceleration *
******************************************************************************/
/* Generate the acceleration table for length slots. */
static void
lzms_init_fast_length_slot_tab(struct lzms_compressor *c)
{
unsigned slot = 0;
for (u32 len = LZMS_MIN_MATCH_LENGTH; len <= MAX_FAST_LENGTH; len++) {
if (len >= lzms_length_slot_base[slot + 1])
slot++;
c->fast_length_slot_tab[len] = slot;
}
}
/* Generate the acceleration tables for offset slots. */
static void
lzms_init_offset_slot_tabs(struct lzms_compressor *c)
{
u32 offset;
unsigned slot = 0;
/* slots [0, 167); 0 <= num_extra_bits <= 10 */
for (offset = 1; offset < 0xe4a5; offset++) {
if (offset >= lzms_offset_slot_base[slot + 1])
slot++;
c->offset_slot_tab_1[offset] = slot;
}
/* slots [167, 427); 11 <= num_extra_bits <= 15 */
for (; offset < 0x3de4a5; offset += (u32)1 << 11) {
if (offset >= lzms_offset_slot_base[slot + 1])
slot++;
c->offset_slot_tab_2[(offset - 0xe4a5) >> 11] = slot;
}
/* slots [427, 799); 16 <= num_extra_bits */
for (; offset < LZMS_MAX_MATCH_OFFSET + 1; offset += (u32)1 << 16) {
if (offset >= lzms_offset_slot_base[slot + 1])
slot++;
c->offset_slot_tab_3[(offset - 0xe4a5) >> 16] = slot;
}
}
/*
* Return the length slot for the specified match length, using the compressor's
* acceleration table if the length is small enough.
*/
static forceinline unsigned
lzms_comp_get_length_slot(const struct lzms_compressor *c, u32 length)
{
if (likely(length <= MAX_FAST_LENGTH))
return c->fast_length_slot_tab[length];
return lzms_get_length_slot(length);
}
/*
* Return the offset slot for the specified match offset, using the compressor's
* acceleration tables to speed up the mapping.
*/
static forceinline unsigned
lzms_comp_get_offset_slot(const struct lzms_compressor *c, u32 offset)
{
if (offset < 0xe4a5)
return c->offset_slot_tab_1[offset];
offset -= 0xe4a5;
if (offset < 0x3d0000)
return c->offset_slot_tab_2[offset >> 11];
return c->offset_slot_tab_3[offset >> 16];
}
/******************************************************************************
* Range encoding *
******************************************************************************/
/*
* Initialize the range encoder @rc to write forwards to the specified buffer
* @out that is @size bytes long.
*/
static void
lzms_range_encoder_init(struct lzms_range_encoder *rc, u8 *out, size_t size)
{
rc->lower_bound = 0;
rc->range_size = 0xffffffff;
rc->cache = 0;
rc->cache_size = 1;
rc->begin = out;
rc->next = out - sizeof(le16);
rc->end = out + (size & ~1);
}
/*
* Attempt to flush bits from the range encoder.
*
* The basic idea is that we're writing bits from @rc->lower_bound to the
* output. However, due to carrying, the writing of coding units with the
* maximum value, as well as one prior coding unit, must be delayed until it is
* determined whether a carry is needed.
*
* This is based on the public domain code for LZMA written by Igor Pavlov, but
* with the following differences:
*
* - In LZMS, 16-bit coding units are required rather than 8-bit.
*
* - In LZMS, the first coding unit is not ignored by the decompressor, so
* the encoder cannot output a dummy value to that position.
*/
static void
lzms_range_encoder_shift_low(struct lzms_range_encoder *rc)
{
if ((u32)(rc->lower_bound) < 0xffff0000 ||
(u32)(rc->lower_bound >> 32) != 0)
{
/* Carry not needed (rc->lower_bound < 0xffff0000), or carry
* occurred ((rc->lower_bound >> 32) != 0, a.k.a. the carry bit
* is 1). */
do {
if (likely(rc->next >= rc->begin)) {
if (rc->next != rc->end) {
put_unaligned_le16(rc->cache +
(u16)(rc->lower_bound >> 32),
rc->next);
rc->next += sizeof(le16);
}
} else {
rc->next += sizeof(le16);
}
rc->cache = 0xffff;
} while (--rc->cache_size != 0);
rc->cache = (rc->lower_bound >> 16) & 0xffff;
}
++rc->cache_size;
rc->lower_bound = (rc->lower_bound & 0xffff) << 16;
}
static bool
lzms_range_encoder_flush(struct lzms_range_encoder *rc)
{
for (int i = 0; i < 4; i++)
lzms_range_encoder_shift_low(rc);
return rc->next != rc->end;
}
/*
* Encode the next bit using the range encoder.
*
* @prob is the probability out of LZMS_PROBABILITY_DENOMINATOR that the next
* bit is 0 rather than 1.
*/
static forceinline void
lzms_range_encode_bit(struct lzms_range_encoder *rc, int bit, u32 prob)
{
/* Normalize if needed. */
if (rc->range_size <= 0xffff) {
rc->range_size <<= 16;
lzms_range_encoder_shift_low(rc);
}
u32 bound = (rc->range_size >> LZMS_PROBABILITY_BITS) * prob;
if (bit == 0) {
rc->range_size = bound;
} else {
rc->lower_bound += bound;
rc->range_size -= bound;
}
}
/*
* Encode a bit. This wraps around lzms_range_encode_bit() to handle using and
* updating the state and its corresponding probability entry.
*/
static forceinline void
lzms_encode_bit(int bit, unsigned *state_p, unsigned num_states,
struct lzms_probability_entry *probs,
struct lzms_range_encoder *rc)
{
struct lzms_probability_entry *prob_entry;
u32 prob;
/* Load the probability entry for the current state. */
prob_entry = &probs[*state_p];
/* Update the state based on the next bit. */
*state_p = ((*state_p << 1) | bit) & (num_states - 1);
/* Get the probability that the bit is 0. */
prob = lzms_get_probability(prob_entry);
/* Update the probability entry. */
lzms_update_probability_entry(prob_entry, bit);
/* Encode the bit using the range encoder. */
lzms_range_encode_bit(rc, bit, prob);
}
/* Helper functions for encoding bits in the various decision classes */
static void
lzms_encode_main_bit(struct lzms_compressor *c, int bit)
{
lzms_encode_bit(bit, &c->main_state, LZMS_NUM_MAIN_PROBS,
c->probs.main, &c->rc);
}
static void
lzms_encode_match_bit(struct lzms_compressor *c, int bit)
{
lzms_encode_bit(bit, &c->match_state, LZMS_NUM_MATCH_PROBS,
c->probs.match, &c->rc);
}
static void
lzms_encode_lz_bit(struct lzms_compressor *c, int bit)
{
lzms_encode_bit(bit, &c->lz_state, LZMS_NUM_LZ_PROBS,
c->probs.lz, &c->rc);
}
static void
lzms_encode_lz_rep_bit(struct lzms_compressor *c, int bit, int idx)
{
lzms_encode_bit(bit, &c->lz_rep_states[idx], LZMS_NUM_LZ_REP_PROBS,
c->probs.lz_rep[idx], &c->rc);
}
static void
lzms_encode_delta_bit(struct lzms_compressor *c, int bit)
{
lzms_encode_bit(bit, &c->delta_state, LZMS_NUM_DELTA_PROBS,
c->probs.delta, &c->rc);
}
static void
lzms_encode_delta_rep_bit(struct lzms_compressor *c, int bit, int idx)
{
lzms_encode_bit(bit, &c->delta_rep_states[idx], LZMS_NUM_DELTA_REP_PROBS,
c->probs.delta_rep[idx], &c->rc);
}
/******************************************************************************
* Huffman encoding and verbatim bits *
******************************************************************************/
/*
* Initialize the output bitstream @os to write backwards to the specified
* buffer @out that is @size bytes long.
*/
static void
lzms_output_bitstream_init(struct lzms_output_bitstream *os,
u8 *out, size_t size)
{
os->bitbuf = 0;
os->bitcount = 0;
os->begin = out;
os->next = out + (size & ~1);
}
/*
* Write some bits, contained in the low-order @num_bits bits of @bits, to the
* output bitstream @os.
*
* @max_num_bits is a compile-time constant that specifies the maximum number of
* bits that can ever be written at this call site.
*/
static forceinline void
lzms_write_bits(struct lzms_output_bitstream *os, const u32 bits,
const unsigned num_bits, const unsigned max_num_bits)
{
/* Add the bits to the bit buffer variable. */
os->bitcount += num_bits;
os->bitbuf = (os->bitbuf << num_bits) | bits;
/* Check whether any coding units need to be written. */
while (os->bitcount >= 16) {
os->bitcount -= 16;
/* Write a coding unit, unless it would underflow the buffer. */
if (os->next != os->begin) {
os->next -= sizeof(le16);
put_unaligned_le16(os->bitbuf >> os->bitcount, os->next);
}
/* Optimization for call sites that never write more than 16
* bits at once. */
if (max_num_bits <= 16)
break;
}
}
/*
* Flush the output bitstream, ensuring that all bits written to it have been
* written to memory. Return %true if all bits have been output successfully,
* or %false if an overrun occurred.
*/
static bool
lzms_output_bitstream_flush(struct lzms_output_bitstream *os)
{
if (os->next == os->begin)
return false;
if (os->bitcount != 0) {
os->next -= sizeof(le16);
put_unaligned_le16(os->bitbuf << (16 - os->bitcount), os->next);
}
return true;
}
static void
lzms_build_huffman_code(struct lzms_huffman_rebuild_info *rebuild_info)
{
make_canonical_huffman_code(rebuild_info->num_syms,
LZMS_MAX_CODEWORD_LENGTH,
rebuild_info->freqs,
rebuild_info->lens,
rebuild_info->codewords);
rebuild_info->num_syms_until_rebuild = rebuild_info->rebuild_freq;
}
static void
lzms_init_huffman_code(struct lzms_huffman_rebuild_info *rebuild_info,
unsigned num_syms, unsigned rebuild_freq,
u32 *codewords, u8 *lens, u32 *freqs)
{
rebuild_info->num_syms = num_syms;
rebuild_info->rebuild_freq = rebuild_freq;
rebuild_info->codewords = codewords;
rebuild_info->lens = lens;
rebuild_info->freqs = freqs;
lzms_init_symbol_frequencies(freqs, num_syms);
lzms_build_huffman_code(rebuild_info);
}
static void
lzms_rebuild_huffman_code(struct lzms_huffman_rebuild_info *rebuild_info)
{
lzms_build_huffman_code(rebuild_info);
lzms_dilute_symbol_frequencies(rebuild_info->freqs, rebuild_info->num_syms);
}
/*
* Encode a symbol using the specified Huffman code. Then, if the Huffman code
* needs to be rebuilt, rebuild it and return true; otherwise return false.
*/
static forceinline bool
lzms_huffman_encode_symbol(unsigned sym,
const u32 *codewords, const u8 *lens, u32 *freqs,
struct lzms_output_bitstream *os,
struct lzms_huffman_rebuild_info *rebuild_info)
{
lzms_write_bits(os, codewords[sym], lens[sym], LZMS_MAX_CODEWORD_LENGTH);
++freqs[sym];
if (--rebuild_info->num_syms_until_rebuild == 0) {
lzms_rebuild_huffman_code(rebuild_info);
return true;
}
return false;
}
/* Helper routines to encode symbols using the various Huffman codes */
static bool
lzms_encode_literal_symbol(struct lzms_compressor *c, unsigned sym)
{
return lzms_huffman_encode_symbol(sym, c->literal_codewords,
c->literal_lens, c->literal_freqs,
&c->os, &c->literal_rebuild_info);
}
static bool
lzms_encode_lz_offset_symbol(struct lzms_compressor *c, unsigned sym)
{
return lzms_huffman_encode_symbol(sym, c->lz_offset_codewords,
c->lz_offset_lens, c->lz_offset_freqs,
&c->os, &c->lz_offset_rebuild_info);
}
static bool
lzms_encode_length_symbol(struct lzms_compressor *c, unsigned sym)
{
return lzms_huffman_encode_symbol(sym, c->length_codewords,
c->length_lens, c->length_freqs,
&c->os, &c->length_rebuild_info);
}
static bool
lzms_encode_delta_offset_symbol(struct lzms_compressor *c, unsigned sym)
{
return lzms_huffman_encode_symbol(sym, c->delta_offset_codewords,
c->delta_offset_lens, c->delta_offset_freqs,
&c->os, &c->delta_offset_rebuild_info);
}
static bool
lzms_encode_delta_power_symbol(struct lzms_compressor *c, unsigned sym)
{
return lzms_huffman_encode_symbol(sym, c->delta_power_codewords,
c->delta_power_lens, c->delta_power_freqs,
&c->os, &c->delta_power_rebuild_info);
}
static void
lzms_update_fast_length_costs(struct lzms_compressor *c);
/*
* Encode a match length. If this causes the Huffman code for length symbols to
* be rebuilt, also update the length costs array used by the parser.
*/
static void
lzms_encode_length(struct lzms_compressor *c, u32 length)
{
unsigned slot = lzms_comp_get_length_slot(c, length);
if (lzms_encode_length_symbol(c, slot))
lzms_update_fast_length_costs(c);
lzms_write_bits(&c->os, length - lzms_length_slot_base[slot],
lzms_extra_length_bits[slot],
LZMS_MAX_EXTRA_LENGTH_BITS);
}
/* Encode the offset of an LZ match. */
static void
lzms_encode_lz_offset(struct lzms_compressor *c, u32 offset)
{
unsigned slot = lzms_comp_get_offset_slot(c, offset);
lzms_encode_lz_offset_symbol(c, slot);
lzms_write_bits(&c->os, offset - lzms_offset_slot_base[slot],
lzms_extra_offset_bits[slot],
LZMS_MAX_EXTRA_OFFSET_BITS);
}
/* Encode the raw offset of a delta match. */
static void
lzms_encode_delta_raw_offset(struct lzms_compressor *c, u32 raw_offset)
{
unsigned slot = lzms_comp_get_offset_slot(c, raw_offset);
lzms_encode_delta_offset_symbol(c, slot);
lzms_write_bits(&c->os, raw_offset - lzms_offset_slot_base[slot],
lzms_extra_offset_bits[slot],
LZMS_MAX_EXTRA_OFFSET_BITS);
}
/******************************************************************************
* Item encoding *
******************************************************************************/
/* Encode the specified item, which may be a literal or any type of match. */
static void
lzms_encode_item(struct lzms_compressor *c, u32 length, u32 source)
{
/* Main bit: 0 = literal, 1 = match */
int main_bit = (length > 1);
lzms_encode_main_bit(c, main_bit);
if (!main_bit) {
/* Literal */
unsigned literal = source;
lzms_encode_literal_symbol(c, literal);
} else {
/* Match */
/* Match bit: 0 = LZ match, 1 = delta match */
int match_bit = (source & DELTA_SOURCE_TAG) != 0;
lzms_encode_match_bit(c, match_bit);
if (!match_bit) {
/* LZ match */
/* LZ bit: 0 = explicit offset, 1 = repeat offset */
int lz_bit = (source < LZMS_NUM_LZ_REPS);
lzms_encode_lz_bit(c, lz_bit);
if (!lz_bit) {
/* Explicit offset LZ match */
u32 offset = source - (LZMS_NUM_LZ_REPS - 1);
lzms_encode_lz_offset(c, offset);
} else {
/* Repeat offset LZ match */
int rep_idx = source;
for (int i = 0; i < rep_idx; i++)
lzms_encode_lz_rep_bit(c, 1, i);
if (rep_idx < LZMS_NUM_LZ_REP_DECISIONS)
lzms_encode_lz_rep_bit(c, 0, rep_idx);
}
} else {
/* Delta match */
source &= ~DELTA_SOURCE_TAG;
/* Delta bit: 0 = explicit offset, 1 = repeat offset */
int delta_bit = (source < LZMS_NUM_DELTA_REPS);
lzms_encode_delta_bit(c, delta_bit);
if (!delta_bit) {
/* Explicit offset delta match */
u32 power = source >> DELTA_SOURCE_POWER_SHIFT;
u32 raw_offset = (source & DELTA_SOURCE_RAW_OFFSET_MASK) -
(LZMS_NUM_DELTA_REPS - 1);
lzms_encode_delta_power_symbol(c, power);
lzms_encode_delta_raw_offset(c, raw_offset);
} else {
/* Repeat offset delta match */
int rep_idx = source;
for (int i = 0; i < rep_idx; i++)
lzms_encode_delta_rep_bit(c, 1, i);
if (rep_idx < LZMS_NUM_DELTA_REP_DECISIONS)
lzms_encode_delta_rep_bit(c, 0, rep_idx);
}
}
/* Match length (encoded the same way for any match type) */
lzms_encode_length(c, length);
}
}
/* Encode a list of matches and literals chosen by the parsing algorithm. */
static void
lzms_encode_nonempty_item_list(struct lzms_compressor *c,
struct lzms_optimum_node *end_node)
{
/* Since we've stored at each node the item we took to arrive at that
* node, we can trace our chosen path in backwards order. However, for
* encoding we need to trace our chosen path in forwards order. To make
* this possible, the following loop moves the items from their
* destination nodes to their source nodes, which effectively reverses
* the path. (Think of it like reversing a singly-linked list.) */
struct lzms_optimum_node *cur_node = end_node;
struct lzms_item saved_item = cur_node->item;
do {
struct lzms_item item = saved_item;
if (cur_node->num_extra_items > 0) {
/* Handle an arrival via multi-item lookahead. */
unsigned i = 0;
struct lzms_optimum_node *orig_node = cur_node;
do {
cur_node -= item.length;
cur_node->item = item;
item = orig_node->extra_items[i];
} while (++i != orig_node->num_extra_items);
}
cur_node -= item.length;
saved_item = cur_node->item;
cur_node->item = item;
} while (cur_node != c->optimum_nodes);
/* Now trace the chosen path in forwards order, encoding each item. */
do {
lzms_encode_item(c, cur_node->item.length, cur_node->item.source);
cur_node += cur_node->item.length;
} while (cur_node != end_node);
}
static forceinline void
lzms_encode_item_list(struct lzms_compressor *c,
struct lzms_optimum_node *end_node)
{
if (end_node != c->optimum_nodes)
lzms_encode_nonempty_item_list(c, end_node);
}
/******************************************************************************
* Cost evaluation *
******************************************************************************/
/*
* If p is the predicted probability of the next bit being a 0, then the number
* of bits required to encode a 0 bit using a binary range encoder is the real
* number -log2(p), and the number of bits required to encode a 1 bit is the
* real number -log2(1 - p). To avoid computing either of these expressions at
* runtime, 'lzms_bit_costs' is a precomputed table that stores a mapping from
* probability to cost for each possible probability. Specifically, the array
* indices are the numerators of the possible probabilities in LZMS, where the
* denominators are LZMS_PROBABILITY_DENOMINATOR; and the stored costs are the
* bit costs multiplied by 1<
static void
lzms_compute_bit_costs(void)
{
for (u32 i = 0; i <= LZMS_PROBABILITY_DENOMINATOR; i++) {
u32 prob = i;
if (prob == 0)
prob++;
else if (prob == LZMS_PROBABILITY_DENOMINATOR)
prob--;
lzms_bit_costs[i] = round(-log2((double)prob / LZMS_PROBABILITY_DENOMINATOR) *
(1 << COST_SHIFT));
}
}
#endif
/* Return the cost to encode a 0 bit in the specified context. */
static forceinline u32
lzms_bit_0_cost(unsigned state, const struct lzms_probability_entry *probs)
{
return lzms_bit_costs[probs[state].num_recent_zero_bits];
}
/* Return the cost to encode a 1 bit in the specified context. */
static forceinline u32
lzms_bit_1_cost(unsigned state, const struct lzms_probability_entry *probs)
{
return lzms_bit_costs[LZMS_PROBABILITY_DENOMINATOR -
probs[state].num_recent_zero_bits];
}
/* Return the cost to encode a literal, including the main bit. */
static forceinline u32
lzms_literal_cost(struct lzms_compressor *c, unsigned main_state, unsigned literal)
{
return lzms_bit_0_cost(main_state, c->probs.main) +
((u32)c->literal_lens[literal] << COST_SHIFT);
}
/* Update 'fast_length_cost_tab' to use the latest Huffman code. */
static void
lzms_update_fast_length_costs(struct lzms_compressor *c)
{
int slot = -1;
u32 cost = 0;
for (u32 len = LZMS_MIN_MATCH_LENGTH; len <= MAX_FAST_LENGTH; len++) {
if (len >= lzms_length_slot_base[slot + 1]) {
slot++;
cost = (u32)(c->length_lens[slot] +
lzms_extra_length_bits[slot]) << COST_SHIFT;
}
c->fast_length_cost_tab[len] = cost;
}
}
/* Return the cost to encode the specified match length, which must not exceed
* MAX_FAST_LENGTH. */
static forceinline u32
lzms_fast_length_cost(const struct lzms_compressor *c, u32 length)
{
return c->fast_length_cost_tab[length];
}
/* Return the cost to encode the specified LZ match offset. */
static forceinline u32
lzms_lz_offset_cost(const struct lzms_compressor *c, u32 offset)
{
unsigned slot = lzms_comp_get_offset_slot(c, offset);
u32 num_bits = c->lz_offset_lens[slot] + lzms_extra_offset_bits[slot];
return num_bits << COST_SHIFT;
}
/* Return the cost to encode the specified delta power and raw offset. */
static forceinline u32
lzms_delta_source_cost(const struct lzms_compressor *c, u32 power, u32 raw_offset)
{
unsigned slot = lzms_comp_get_offset_slot(c, raw_offset);
u32 num_bits = c->delta_power_lens[power] + c->delta_offset_lens[slot] +
lzms_extra_offset_bits[slot];
return num_bits << COST_SHIFT;
}
/******************************************************************************
* Adaptive state *
******************************************************************************/
static void
lzms_init_adaptive_state(struct lzms_adaptive_state *state)
{
for (int i = 0; i < LZMS_NUM_LZ_REPS + 1; i++)
state->recent_lz_offsets[i] = i + 1;
state->prev_lz_offset = 0;
state->upcoming_lz_offset = 0;
for (int i = 0; i < LZMS_NUM_DELTA_REPS + 1; i++)
state->recent_delta_pairs[i] = i + 1;
state->prev_delta_pair = 0;
state->upcoming_delta_pair = 0;
state->main_state = 0;
state->match_state = 0;
state->lz_state = 0;
for (int i = 0; i < LZMS_NUM_LZ_REP_DECISIONS; i++)
state->lz_rep_states[i] = 0;
state->delta_state = 0;
for (int i = 0; i < LZMS_NUM_DELTA_REP_DECISIONS; i++)
state->delta_rep_states[i] = 0;
}
/*
* Update the LRU queues for match sources when advancing by one item.
*
* Note: using LZMA as a point of comparison, the LRU queues in LZMS are more
* complex because:
* - there are separate queues for LZ and delta matches
* - updates to the queues are delayed by one encoded item (this prevents
* sources from being bumped up to index 0 too early)
*/
static void
lzms_update_lru_queues(struct lzms_adaptive_state *state)
{
if (state->prev_lz_offset != 0) {
for (int i = LZMS_NUM_LZ_REPS - 1; i >= 0; i--)
state->recent_lz_offsets[i + 1] = state->recent_lz_offsets[i];
state->recent_lz_offsets[0] = state->prev_lz_offset;
}
state->prev_lz_offset = state->upcoming_lz_offset;
if (state->prev_delta_pair != 0) {
for (int i = LZMS_NUM_DELTA_REPS - 1; i >= 0; i--)
state->recent_delta_pairs[i + 1] = state->recent_delta_pairs[i];
state->recent_delta_pairs[0] = state->prev_delta_pair;
}
state->prev_delta_pair = state->upcoming_delta_pair;
}
static forceinline void
lzms_update_state(u8 *state_p, int bit, unsigned num_states)
{
*state_p = ((*state_p << 1) | bit) & (num_states - 1);
}
static forceinline void
lzms_update_main_state(struct lzms_adaptive_state *state, int is_match)
{
lzms_update_state(&state->main_state, is_match, LZMS_NUM_MAIN_PROBS);
}
static forceinline void
lzms_update_match_state(struct lzms_adaptive_state *state, int is_delta)
{
lzms_update_state(&state->match_state, is_delta, LZMS_NUM_MATCH_PROBS);
}
static forceinline void
lzms_update_lz_state(struct lzms_adaptive_state *state, int is_rep)
{
lzms_update_state(&state->lz_state, is_rep, LZMS_NUM_LZ_PROBS);
}
static forceinline void
lzms_update_lz_rep_states(struct lzms_adaptive_state *state, int rep_idx)
{
for (int i = 0; i < rep_idx; i++)
lzms_update_state(&state->lz_rep_states[i], 1, LZMS_NUM_LZ_REP_PROBS);
if (rep_idx < LZMS_NUM_LZ_REP_DECISIONS)
lzms_update_state(&state->lz_rep_states[rep_idx], 0, LZMS_NUM_LZ_REP_PROBS);
}
static forceinline void
lzms_update_delta_state(struct lzms_adaptive_state *state, int is_rep)
{
lzms_update_state(&state->delta_state, is_rep, LZMS_NUM_DELTA_PROBS);
}
static forceinline void
lzms_update_delta_rep_states(struct lzms_adaptive_state *state, int rep_idx)
{
for (int i = 0; i < rep_idx; i++)
lzms_update_state(&state->delta_rep_states[i], 1, LZMS_NUM_DELTA_REP_PROBS);
if (rep_idx < LZMS_NUM_DELTA_REP_DECISIONS)
lzms_update_state(&state->delta_rep_states[rep_idx], 0, LZMS_NUM_DELTA_REP_PROBS);
}
/******************************************************************************
* Matchfinding *
******************************************************************************/
/* Note: this code just handles finding delta matches. The code for finding LZ
* matches is elsewhere. */
/* Initialize the delta matchfinder for a new input buffer. */
static void
lzms_init_delta_matchfinder(struct lzms_compressor *c)
{
/* Set all entries to use an invalid power, which will never match. */
STATIC_ASSERT(NUM_POWERS_TO_CONSIDER < (1 << (32 - DELTA_SOURCE_POWER_SHIFT)));
memset(c->delta_hash_table, 0xFF, sizeof(c->delta_hash_table));
/* Initialize the next hash code for each power. We can just use zeroes
* initially; it doesn't really matter. */
for (u32 i = 0; i < NUM_POWERS_TO_CONSIDER; i++)
c->next_delta_hashes[i] = 0;
}
/*
* Compute a DELTA_HASH_ORDER-bit hash code for the first
* NBYTES_HASHED_FOR_DELTA bytes of the sequence beginning at @p when taken in a
* delta context with the specified @span.
*/
static forceinline u32
lzms_delta_hash(const u8 *p, const u32 pos, u32 span)
{
/* A delta match has a certain span and an offset that is a multiple of
* that span. To reduce wasted space we use a single combined hash
* table for all spans and positions, but to minimize collisions we
* include in the hash code computation the span and the low-order bits
* of the current position. */
STATIC_ASSERT(NBYTES_HASHED_FOR_DELTA == 3);
u8 d0 = *(p + 0) - *(p + 0 - span);
u8 d1 = *(p + 1) - *(p + 1 - span);
u8 d2 = *(p + 2) - *(p + 2 - span);
u32 v = ((span + (pos & (span - 1))) << 24) |
((u32)d2 << 16) | ((u32)d1 << 8) | d0;
return lz_hash(v, DELTA_HASH_ORDER);
}
/*
* Given a match between @in_next and @matchptr in a delta context with the
* specified @span and having the initial @len, extend the match as far as
* possible, up to a limit of @max_len.
*/
static forceinline u32
lzms_extend_delta_match(const u8 *in_next, const u8 *matchptr,
u32 len, u32 max_len, u32 span)
{
while (len < max_len &&
(u8)(*(in_next + len) - *(in_next + len - span)) ==
(u8)(*(matchptr + len) - *(matchptr + len - span)))
{
len++;
}
return len;
}
static void
lzms_delta_matchfinder_skip_bytes(struct lzms_compressor *c,
const u8 *in_next, u32 count)
{
u32 pos = in_next - c->in_buffer;
if (unlikely(c->in_nbytes - (pos + count) <= NBYTES_HASHED_FOR_DELTA + 1))
return;
do {
/* Update the hash table for each power. */
for (u32 power = 0; power < NUM_POWERS_TO_CONSIDER; power++) {
const u32 span = (u32)1 << power;
if (unlikely(pos < span))
continue;
const u32 next_hash = lzms_delta_hash(in_next + 1, pos + 1, span);
const u32 hash = c->next_delta_hashes[power];
c->delta_hash_table[hash] =
(power << DELTA_SOURCE_POWER_SHIFT) | pos;
c->next_delta_hashes[power] = next_hash;
prefetchw(&c->delta_hash_table[next_hash]);
}
} while (in_next++, pos++, --count);
}
/*
* Skip the next @count bytes (don't search for matches at them). @in_next
* points to the first byte to skip. The return value is @in_next + count.
*/
static const u8 *
lzms_skip_bytes(struct lzms_compressor *c, u32 count, const u8 *in_next)
{
lcpit_matchfinder_skip_bytes(&c->mf, count);
if (c->use_delta_matches)
lzms_delta_matchfinder_skip_bytes(c, in_next, count);
return in_next + count;
}
/******************************************************************************
* "Near-optimal" parsing *
******************************************************************************/
/*
* The main near-optimal parsing routine.
*
* Briefly, the algorithm does an approximate minimum-cost path search to find a
* "near-optimal" sequence of matches and literals to output, based on the
* current cost model. The algorithm steps forward, position by position (byte
* by byte), and updates the minimum cost path to reach each later position that
* can be reached using a match or literal from the current position. This is
* essentially Dijkstra's algorithm in disguise: the graph nodes are positions,
* the graph edges are possible matches/literals to code, and the cost of each
* edge is the estimated number of bits (scaled up by COST_SHIFT) that will be
* required to output the corresponding match or literal. But one difference is
* that we actually compute the lowest-cost path in pieces, where each piece is
* terminated when there are no choices to be made.
*
* The costs of literals and matches are estimated using the range encoder
* states and the semi-adaptive Huffman codes. Except for range encoding
* states, costs are assumed to be constant throughout a single run of the
* parsing algorithm, which can parse up to NUM_OPTIM_NODES bytes of data. This
* introduces a source of non-optimality because the probabilities and Huffman
* codes can change over this part of the data. And of course, there are
* various other reasons why the result isn't optimal in terms of compression
* ratio.
*/
static void
lzms_near_optimal_parse(struct lzms_compressor *c)
{
const u8 *in_next = c->in_buffer;
const u8 * const in_end = &c->in_buffer[c->in_nbytes];
struct lzms_optimum_node *cur_node;
struct lzms_optimum_node *end_node;
/* Set initial length costs for lengths <= MAX_FAST_LENGTH. */
lzms_update_fast_length_costs(c);
/* Set up the initial adaptive state. */
lzms_init_adaptive_state(&c->optimum_nodes[0].state);
begin:
/* Start building a new list of items, which will correspond to the next
* piece of the overall minimum-cost path. */
cur_node = c->optimum_nodes;
cur_node->cost = 0;
end_node = cur_node;
if (in_next == in_end)
return;
/* The following loop runs once for each per byte in the input buffer,
* except in a few shortcut cases. */
for (;;) {
u32 num_matches;
/* Repeat offset LZ matches */
if (likely(in_next - c->in_buffer >= LZMS_NUM_LZ_REPS &&
in_end - in_next >= 2))
{
for (int rep_idx = 0; rep_idx < LZMS_NUM_LZ_REPS; rep_idx++) {
/* Looking for a repeat offset LZ match at queue
* index @rep_idx */
const u32 offset = cur_node->state.recent_lz_offsets[rep_idx];
const u8 * const matchptr = in_next - offset;
/* Check the first 2 bytes before entering the extension loop. */
if (load_u16_unaligned(in_next) != load_u16_unaligned(matchptr))
continue;
/* Extend the match to its full length. */
const u32 rep_len = lz_extend(in_next, matchptr, 2, in_end - in_next);
/* Early out for long repeat offset LZ match */
if (rep_len >= c->mf.nice_match_len) {
in_next = lzms_skip_bytes(c, rep_len, in_next);
lzms_encode_item_list(c, cur_node);
lzms_encode_item(c, rep_len, rep_idx);
c->optimum_nodes[0].state = cur_node->state;
cur_node = &c->optimum_nodes[0];
cur_node->state.upcoming_lz_offset =
cur_node->state.recent_lz_offsets[rep_idx];
cur_node->state.upcoming_delta_pair = 0;
for (int i = rep_idx; i < LZMS_NUM_LZ_REPS; i++)
cur_node->state.recent_lz_offsets[i] =
cur_node->state.recent_lz_offsets[i + 1];
lzms_update_lru_queues(&cur_node->state);
lzms_update_main_state(&cur_node->state, 1);
lzms_update_match_state(&cur_node->state, 0);
lzms_update_lz_state(&cur_node->state, 1);
lzms_update_lz_rep_states(&cur_node->state, rep_idx);
goto begin;
}
while (end_node < cur_node + rep_len)
(++end_node)->cost = INFINITE_COST;
u32 base_cost = cur_node->cost +
lzms_bit_1_cost(cur_node->state.main_state,
c->probs.main) +
lzms_bit_0_cost(cur_node->state.match_state,
c->probs.match) +
lzms_bit_1_cost(cur_node->state.lz_state,
c->probs.lz);
for (int i = 0; i < rep_idx; i++)
base_cost += lzms_bit_1_cost(cur_node->state.lz_rep_states[i],
c->probs.lz_rep[i]);
if (rep_idx < LZMS_NUM_LZ_REP_DECISIONS)
base_cost += lzms_bit_0_cost(cur_node->state.lz_rep_states[rep_idx],
c->probs.lz_rep[rep_idx]);
u32 len = 2;
do {
u32 cost = base_cost + lzms_fast_length_cost(c, len);
if (cost < (cur_node + len)->cost) {
(cur_node + len)->cost = cost;
(cur_node + len)->item = (struct lzms_item) {
.length = len,
.source = rep_idx,
};
(cur_node + len)->num_extra_items = 0;
}
} while (++len <= rep_len);
/* try LZ-rep + lit + LZ-rep0 */
if (c->try_lzrep_lit_lzrep0 &&
in_end - (in_next + rep_len) >= 3 &&
load_u16_unaligned(in_next + rep_len + 1) ==
load_u16_unaligned(matchptr + rep_len + 1))
{
const u32 rep0_len = lz_extend(in_next + rep_len + 1,
matchptr + rep_len + 1,
2,
min(c->mf.nice_match_len,
in_end - (in_next + rep_len + 1)));
unsigned main_state = cur_node->state.main_state;
unsigned match_state = cur_node->state.match_state;
unsigned lz_state = cur_node->state.lz_state;
unsigned lz_rep0_state = cur_node->state.lz_rep_states[0];
/* update states for LZ-rep */
main_state = ((main_state << 1) | 1) % LZMS_NUM_MAIN_PROBS;
match_state = ((match_state << 1) | 0) % LZMS_NUM_MATCH_PROBS;
lz_state = ((lz_state << 1) | 1) % LZMS_NUM_LZ_PROBS;
lz_rep0_state = ((lz_rep0_state << 1) | (rep_idx > 0)) %
LZMS_NUM_LZ_REP_PROBS;
/* LZ-rep cost */
u32 cost = base_cost + lzms_fast_length_cost(c, rep_len);
/* add literal cost */
cost += lzms_literal_cost(c, main_state, *(in_next + rep_len));
/* update state for literal */
main_state = ((main_state << 1) | 0) % LZMS_NUM_MAIN_PROBS;
/* add LZ-rep0 cost */
cost += lzms_bit_1_cost(main_state, c->probs.main) +
lzms_bit_0_cost(match_state, c->probs.match) +
lzms_bit_1_cost(lz_state, c->probs.lz) +
lzms_bit_0_cost(lz_rep0_state, c->probs.lz_rep[0]) +
lzms_fast_length_cost(c, rep0_len);
const u32 total_len = rep_len + 1 + rep0_len;
while (end_node < cur_node + total_len)
(++end_node)->cost = INFINITE_COST;
if (cost < (cur_node + total_len)->cost) {
(cur_node + total_len)->cost = cost;
(cur_node + total_len)->item = (struct lzms_item) {
.length = rep0_len,
.source = 0,
};
(cur_node + total_len)->extra_items[0] = (struct lzms_item) {
.length = 1,
.source = *(in_next + rep_len),
};
(cur_node + total_len)->extra_items[1] = (struct lzms_item) {
.length = rep_len,
.source = rep_idx,
};
(cur_node + total_len)->num_extra_items = 2;
}
}
}
}
/* Repeat offset delta matches */
if (c->use_delta_matches &&
likely(in_next - c->in_buffer >= LZMS_NUM_DELTA_REPS + 1 &&
(in_end - in_next >= 2)))
{
for (int rep_idx = 0; rep_idx < LZMS_NUM_DELTA_REPS; rep_idx++) {
/* Looking for a repeat offset delta match at
* queue index @rep_idx */
const u32 pair = cur_node->state.recent_delta_pairs[rep_idx];
const u32 power = pair >> DELTA_SOURCE_POWER_SHIFT;
const u32 raw_offset = pair & DELTA_SOURCE_RAW_OFFSET_MASK;
const u32 span = (u32)1 << power;
const u32 offset = raw_offset << power;
const u8 * const matchptr = in_next - offset;
/* Check the first 2 bytes before entering the
* extension loop. */
if (((u8)(*(in_next + 0) - *(in_next + 0 - span)) !=
(u8)(*(matchptr + 0) - *(matchptr + 0 - span))) ||
((u8)(*(in_next + 1) - *(in_next + 1 - span)) !=
(u8)(*(matchptr + 1) - *(matchptr + 1 - span))))
continue;
/* Extend the match to its full length. */
const u32 rep_len = lzms_extend_delta_match(in_next, matchptr,
2, in_end - in_next,
span);
/* Early out for long repeat offset delta match */
if (rep_len >= c->mf.nice_match_len) {
in_next = lzms_skip_bytes(c, rep_len, in_next);
lzms_encode_item_list(c, cur_node);
lzms_encode_item(c, rep_len, DELTA_SOURCE_TAG | rep_idx);
c->optimum_nodes[0].state = cur_node->state;
cur_node = &c->optimum_nodes[0];
cur_node->state.upcoming_delta_pair = pair;
cur_node->state.upcoming_lz_offset = 0;
for (int i = rep_idx; i < LZMS_NUM_DELTA_REPS; i++)
cur_node->state.recent_delta_pairs[i] =
cur_node->state.recent_delta_pairs[i + 1];
lzms_update_lru_queues(&cur_node->state);
lzms_update_main_state(&cur_node->state, 1);
lzms_update_match_state(&cur_node->state, 1);
lzms_update_delta_state(&cur_node->state, 1);
lzms_update_delta_rep_states(&cur_node->state, rep_idx);
goto begin;
}
while (end_node < cur_node + rep_len)
(++end_node)->cost = INFINITE_COST;
u32 base_cost = cur_node->cost +
lzms_bit_1_cost(cur_node->state.main_state,
c->probs.main) +
lzms_bit_1_cost(cur_node->state.match_state,
c->probs.match) +
lzms_bit_1_cost(cur_node->state.delta_state,
c->probs.delta);
for (int i = 0; i < rep_idx; i++)
base_cost += lzms_bit_1_cost(cur_node->state.delta_rep_states[i],
c->probs.delta_rep[i]);
if (rep_idx < LZMS_NUM_DELTA_REP_DECISIONS)
base_cost += lzms_bit_0_cost(cur_node->state.delta_rep_states[rep_idx],
c->probs.delta_rep[rep_idx]);
u32 len = 2;
do {
u32 cost = base_cost + lzms_fast_length_cost(c, len);
if (cost < (cur_node + len)->cost) {
(cur_node + len)->cost = cost;
(cur_node + len)->item = (struct lzms_item) {
.length = len,
.source = DELTA_SOURCE_TAG | rep_idx,
};
(cur_node + len)->num_extra_items = 0;
}
} while (++len <= rep_len);
}
}
/* Explicit offset LZ matches */
num_matches = lcpit_matchfinder_get_matches(&c->mf, c->matches);
if (num_matches) {
u32 best_len = c->matches[0].length;
/* Early out for long explicit offset LZ match */
if (best_len >= c->mf.nice_match_len) {
const u32 offset = c->matches[0].offset;
/* Extend the match as far as possible.
* This is necessary because the LCP-interval
* tree matchfinder only reports up to
* nice_match_len bytes. */
best_len = lz_extend(in_next, in_next - offset,
best_len, in_end - in_next);
in_next = lzms_skip_bytes(c, best_len - 1, in_next + 1);
lzms_encode_item_list(c, cur_node);
lzms_encode_item(c, best_len, offset + LZMS_NUM_LZ_REPS - 1);
c->optimum_nodes[0].state = cur_node->state;
cur_node = &c->optimum_nodes[0];
cur_node->state.upcoming_lz_offset = offset;
cur_node->state.upcoming_delta_pair = 0;
lzms_update_lru_queues(&cur_node->state);
lzms_update_main_state(&cur_node->state, 1);
lzms_update_match_state(&cur_node->state, 0);
lzms_update_lz_state(&cur_node->state, 0);
goto begin;
}
while (end_node < cur_node + best_len)
(++end_node)->cost = INFINITE_COST;
u32 base_cost = cur_node->cost +
lzms_bit_1_cost(cur_node->state.main_state,
c->probs.main) +
lzms_bit_0_cost(cur_node->state.match_state,
c->probs.match) +
lzms_bit_0_cost(cur_node->state.lz_state,
c->probs.lz);
if (c->try_lzmatch_lit_lzrep0 &&
likely(in_end - (in_next + c->matches[0].length) >= 3))
{
/* try LZ-match + lit + LZ-rep0 */
u32 l = 2;
u32 i = num_matches - 1;
do {
const u32 len = c->matches[i].length;
const u32 offset = c->matches[i].offset;
const u32 position_cost = base_cost +
lzms_lz_offset_cost(c, offset);
do {
u32 cost = position_cost + lzms_fast_length_cost(c, l);
if (cost < (cur_node + l)->cost) {
(cur_node + l)->cost = cost;
(cur_node + l)->item = (struct lzms_item) {
.length = l,
.source = offset + (LZMS_NUM_LZ_REPS - 1),
};
(cur_node + l)->num_extra_items = 0;
}
} while (++l <= len);
const u8 * const matchptr = in_next - offset;
if (load_u16_unaligned(matchptr + len + 1) !=
load_u16_unaligned(in_next + len + 1))
continue;
const u32 rep0_len = lz_extend(in_next + len + 1,
matchptr + len + 1,
2,
min(c->mf.nice_match_len,
in_end - (in_next + len + 1)));
unsigned main_state = cur_node->state.main_state;
unsigned match_state = cur_node->state.match_state;
unsigned lz_state = cur_node->state.lz_state;
/* update states for LZ-match */
main_state = ((main_state << 1) | 1) % LZMS_NUM_MAIN_PROBS;
match_state = ((match_state << 1) | 0) % LZMS_NUM_MATCH_PROBS;
lz_state = ((lz_state << 1) | 0) % LZMS_NUM_LZ_PROBS;
/* LZ-match cost */
u32 cost = position_cost + lzms_fast_length_cost(c, len);
/* add literal cost */
cost += lzms_literal_cost(c, main_state, *(in_next + len));
/* update state for literal */
main_state = ((main_state << 1) | 0) % LZMS_NUM_MAIN_PROBS;
/* add LZ-rep0 cost */
cost += lzms_bit_1_cost(main_state, c->probs.main) +
lzms_bit_0_cost(match_state, c->probs.match) +
lzms_bit_1_cost(lz_state, c->probs.lz) +
lzms_bit_0_cost(cur_node->state.lz_rep_states[0],
c->probs.lz_rep[0]) +
lzms_fast_length_cost(c, rep0_len);
const u32 total_len = len + 1 + rep0_len;
while (end_node < cur_node + total_len)
(++end_node)->cost = INFINITE_COST;
if (cost < (cur_node + total_len)->cost) {
(cur_node + total_len)->cost = cost;
(cur_node + total_len)->item = (struct lzms_item) {
.length = rep0_len,
.source = 0,
};
(cur_node + total_len)->extra_items[0] = (struct lzms_item) {
.length = 1,
.source = *(in_next + len),
};
(cur_node + total_len)->extra_items[1] = (struct lzms_item) {
.length = len,
.source = offset + LZMS_NUM_LZ_REPS - 1,
};
(cur_node + total_len)->num_extra_items = 2;
}
} while (i--);
} else {
u32 l = 2;
u32 i = num_matches - 1;
do {
u32 position_cost = base_cost +
lzms_lz_offset_cost(c, c->matches[i].offset);
do {
u32 cost = position_cost + lzms_fast_length_cost(c, l);
if (cost < (cur_node + l)->cost) {
(cur_node + l)->cost = cost;
(cur_node + l)->item = (struct lzms_item) {
.length = l,
.source = c->matches[i].offset +
(LZMS_NUM_LZ_REPS - 1),
};
(cur_node + l)->num_extra_items = 0;
}
} while (++l <= c->matches[i].length);
} while (i--);
}
}
/* Explicit offset delta matches */
if (c->use_delta_matches &&
likely(in_end - in_next >= NBYTES_HASHED_FOR_DELTA + 1))
{
const u32 pos = in_next - c->in_buffer;
/* Consider each possible power (log2 of span) */
STATIC_ASSERT(NUM_POWERS_TO_CONSIDER <= LZMS_NUM_DELTA_POWER_SYMS);
for (u32 power = 0; power < NUM_POWERS_TO_CONSIDER; power++) {
const u32 span = (u32)1 << power;
if (unlikely(pos < span))
continue;
const u32 next_hash = lzms_delta_hash(in_next + 1, pos + 1, span);
const u32 hash = c->next_delta_hashes[power];
const u32 cur_match = c->delta_hash_table[hash];
c->delta_hash_table[hash] = (power << DELTA_SOURCE_POWER_SHIFT) | pos;
c->next_delta_hashes[power] = next_hash;
prefetchw(&c->delta_hash_table[next_hash]);
if (power != cur_match >> DELTA_SOURCE_POWER_SHIFT)
continue;
const u32 offset = pos - (cur_match & DELTA_SOURCE_RAW_OFFSET_MASK);
/* The offset must be a multiple of span. */
if (offset & (span - 1))
continue;
const u8 * const matchptr = in_next - offset;
/* Check the first 3 bytes before entering the
* extension loop. */
STATIC_ASSERT(NBYTES_HASHED_FOR_DELTA == 3);
if (((u8)(*(in_next + 0) - *(in_next + 0 - span)) !=
(u8)(*(matchptr + 0) - *(matchptr + 0 - span))) ||
((u8)(*(in_next + 1) - *(in_next + 1 - span)) !=
(u8)(*(matchptr + 1) - *(matchptr + 1 - span))) ||
((u8)(*(in_next + 2) - *(in_next + 2 - span)) !=
(u8)(*(matchptr + 2) - *(matchptr + 2 - span))))
continue;
/* Extend the delta match to its full length. */
const u32 len = lzms_extend_delta_match(in_next,
matchptr,
NBYTES_HASHED_FOR_DELTA,
in_end - in_next,
span);
const u32 raw_offset = offset >> power;
if (unlikely(raw_offset > DELTA_SOURCE_RAW_OFFSET_MASK -
(LZMS_NUM_DELTA_REPS - 1)))
continue;
const u32 pair = (power << DELTA_SOURCE_POWER_SHIFT) |
raw_offset;
const u32 source = DELTA_SOURCE_TAG |
(pair + LZMS_NUM_DELTA_REPS - 1);
/* Early out for long explicit offset delta match */
if (len >= c->mf.nice_match_len) {
in_next = lzms_skip_bytes(c, len - 1, in_next + 1);
lzms_encode_item_list(c, cur_node);
lzms_encode_item(c, len, source);
c->optimum_nodes[0].state = cur_node->state;
cur_node = &c->optimum_nodes[0];
cur_node->state.upcoming_lz_offset = 0;
cur_node->state.upcoming_delta_pair = pair;
lzms_update_lru_queues(&cur_node->state);
lzms_update_main_state(&cur_node->state, 1);
lzms_update_match_state(&cur_node->state, 1);
lzms_update_delta_state(&cur_node->state, 0);
goto begin;
}
while (end_node < cur_node + len)
(++end_node)->cost = INFINITE_COST;
u32 base_cost = cur_node->cost +
lzms_bit_1_cost(cur_node->state.main_state,
c->probs.main) +
lzms_bit_1_cost(cur_node->state.match_state,
c->probs.match) +
lzms_bit_0_cost(cur_node->state.delta_state,
c->probs.delta) +
lzms_delta_source_cost(c, power, raw_offset);
u32 l = NBYTES_HASHED_FOR_DELTA;
do {
u32 cost = base_cost + lzms_fast_length_cost(c, l);
if (cost < (cur_node + l)->cost) {
(cur_node + l)->cost = cost;
(cur_node + l)->item = (struct lzms_item) {
.length = l,
.source = source,
};
(cur_node + l)->num_extra_items = 0;
}
} while (++l <= len);
}
}
/* Literal */
if (end_node < cur_node + 1)
(++end_node)->cost = INFINITE_COST;
const u32 cur_and_lit_cost = cur_node->cost +
lzms_literal_cost(c, cur_node->state.main_state,
*in_next);
if (cur_and_lit_cost < (cur_node + 1)->cost) {
(cur_node + 1)->cost = cur_and_lit_cost;
(cur_node + 1)->item = (struct lzms_item) {
.length = 1,
.source = *in_next,
};
(cur_node + 1)->num_extra_items = 0;
} else if (c->try_lit_lzrep0 && in_end - (in_next + 1) >= 2) {
/* try lit + LZ-rep0 */
const u32 offset =
(cur_node->state.prev_lz_offset) ?
cur_node->state.prev_lz_offset :
cur_node->state.recent_lz_offsets[0];
if (load_u16_unaligned(in_next + 1) ==
load_u16_unaligned(in_next + 1 - offset))
{
const u32 rep0_len = lz_extend(in_next + 1,
in_next + 1 - offset,
2,
min(in_end - (in_next + 1),
c->mf.nice_match_len));
unsigned main_state = cur_node->state.main_state;
/* Update main_state after literal */
main_state = (main_state << 1 | 0) % LZMS_NUM_MAIN_PROBS;
/* Add cost of LZ-rep0 */
const u32 cost = cur_and_lit_cost +
lzms_bit_1_cost(main_state, c->probs.main) +
lzms_bit_0_cost(cur_node->state.match_state,
c->probs.match) +
lzms_bit_1_cost(cur_node->state.lz_state,
c->probs.lz) +
lzms_bit_0_cost(cur_node->state.lz_rep_states[0],
c->probs.lz_rep[0]) +
lzms_fast_length_cost(c, rep0_len);
const u32 total_len = 1 + rep0_len;
while (end_node < cur_node + total_len)
(++end_node)->cost = INFINITE_COST;
if (cost < (cur_node + total_len)->cost) {
(cur_node + total_len)->cost = cost;
(cur_node + total_len)->item = (struct lzms_item) {
.length = rep0_len,
.source = 0,
};
(cur_node + total_len)->extra_items[0] = (struct lzms_item) {
.length = 1,
.source = *in_next,
};
(cur_node + total_len)->num_extra_items = 1;
}
}
}
/* Advance to the next position. */
in_next++;
cur_node++;
/* The lowest-cost path to the current position is now known.
* Finalize the adaptive state that results from taking this
* lowest-cost path. */
struct lzms_item item_to_take = cur_node->item;
struct lzms_optimum_node *source_node = cur_node - item_to_take.length;
int next_item_idx = -1;
for (unsigned i = 0; i < cur_node->num_extra_items; i++) {
item_to_take = cur_node->extra_items[i];
source_node -= item_to_take.length;
next_item_idx++;
}
cur_node->state = source_node->state;
for (;;) {
const u32 length = item_to_take.length;
u32 source = item_to_take.source;
cur_node->state.upcoming_lz_offset = 0;
cur_node->state.upcoming_delta_pair = 0;
if (length > 1) {
/* Match */
lzms_update_main_state(&cur_node->state, 1);
if (source & DELTA_SOURCE_TAG) {
/* Delta match */
lzms_update_match_state(&cur_node->state, 1);
source &= ~DELTA_SOURCE_TAG;
if (source >= LZMS_NUM_DELTA_REPS) {
/* Explicit offset delta match */
lzms_update_delta_state(&cur_node->state, 0);
cur_node->state.upcoming_delta_pair =
source - (LZMS_NUM_DELTA_REPS - 1);
} else {
/* Repeat offset delta match */
int rep_idx = source;
lzms_update_delta_state(&cur_node->state, 1);
lzms_update_delta_rep_states(&cur_node->state, rep_idx);
cur_node->state.upcoming_delta_pair =
cur_node->state.recent_delta_pairs[rep_idx];
for (int i = rep_idx; i < LZMS_NUM_DELTA_REPS; i++)
cur_node->state.recent_delta_pairs[i] =
cur_node->state.recent_delta_pairs[i + 1];
}
} else {
lzms_update_match_state(&cur_node->state, 0);
if (source >= LZMS_NUM_LZ_REPS) {
/* Explicit offset LZ match */
lzms_update_lz_state(&cur_node->state, 0);
cur_node->state.upcoming_lz_offset =
source - (LZMS_NUM_LZ_REPS - 1);
} else {
/* Repeat offset LZ match */
int rep_idx = source;
lzms_update_lz_state(&cur_node->state, 1);
lzms_update_lz_rep_states(&cur_node->state, rep_idx);
cur_node->state.upcoming_lz_offset =
cur_node->state.recent_lz_offsets[rep_idx];
for (int i = rep_idx; i < LZMS_NUM_LZ_REPS; i++)
cur_node->state.recent_lz_offsets[i] =
cur_node->state.recent_lz_offsets[i + 1];
}
}
} else {
/* Literal */
lzms_update_main_state(&cur_node->state, 0);
}
lzms_update_lru_queues(&cur_node->state);
if (next_item_idx < 0)
break;
if (next_item_idx == 0)
item_to_take = cur_node->item;
else
item_to_take = cur_node->extra_items[next_item_idx - 1];
--next_item_idx;
}
/*
* This loop will terminate when either of the following
* conditions is true:
*
* (1) cur_node == end_node
*
* There are no paths that extend beyond the current
* position. In this case, any path to a later position
* must pass through the current position, so we can go
* ahead and choose the list of items that led to this
* position.
*
* (2) cur_node == &c->optimum_nodes[NUM_OPTIM_NODES]
*
* This bounds the number of times the algorithm can step
* forward before it is guaranteed to start choosing items.
* This limits the memory usage. It also guarantees that
* the parser will not go too long without updating the
* probability tables.
*
* Note: no check for end-of-buffer is needed because
* end-of-buffer will trigger condition (1).
*/
if (cur_node == end_node ||
cur_node == &c->optimum_nodes[NUM_OPTIM_NODES])
{
lzms_encode_nonempty_item_list(c, cur_node);
c->optimum_nodes[0].state = cur_node->state;
goto begin;
}
}
}
static void
lzms_init_states_and_probabilities(struct lzms_compressor *c)
{
c->main_state = 0;
c->match_state = 0;
c->lz_state = 0;
for (int i = 0; i < LZMS_NUM_LZ_REP_DECISIONS; i++)
c->lz_rep_states[i] = 0;
c->delta_state = 0;
for (int i = 0; i < LZMS_NUM_DELTA_REP_DECISIONS; i++)
c->delta_rep_states[i] = 0;
lzms_init_probabilities(&c->probs);
}
static void
lzms_init_huffman_codes(struct lzms_compressor *c, unsigned num_offset_slots)
{
lzms_init_huffman_code(&c->literal_rebuild_info,
LZMS_NUM_LITERAL_SYMS,
LZMS_LITERAL_CODE_REBUILD_FREQ,
c->literal_codewords,
c->literal_lens,
c->literal_freqs);
lzms_init_huffman_code(&c->lz_offset_rebuild_info,
num_offset_slots,
LZMS_LZ_OFFSET_CODE_REBUILD_FREQ,
c->lz_offset_codewords,
c->lz_offset_lens,
c->lz_offset_freqs);
lzms_init_huffman_code(&c->length_rebuild_info,
LZMS_NUM_LENGTH_SYMS,
LZMS_LENGTH_CODE_REBUILD_FREQ,
c->length_codewords,
c->length_lens,
c->length_freqs);
lzms_init_huffman_code(&c->delta_offset_rebuild_info,
num_offset_slots,
LZMS_DELTA_OFFSET_CODE_REBUILD_FREQ,
c->delta_offset_codewords,
c->delta_offset_lens,
c->delta_offset_freqs);
lzms_init_huffman_code(&c->delta_power_rebuild_info,
LZMS_NUM_DELTA_POWER_SYMS,
LZMS_DELTA_POWER_CODE_REBUILD_FREQ,
c->delta_power_codewords,
c->delta_power_lens,
c->delta_power_freqs);
}
/*
* Flush the output streams, prepare the final compressed data, and return its
* size in bytes.
*
* A return value of 0 indicates that the data could not be compressed to fit in
* the available space.
*/
static size_t
lzms_finalize(struct lzms_compressor *c)
{
size_t num_forwards_bytes;
size_t num_backwards_bytes;
/* Flush both the forwards and backwards streams, and make sure they
* didn't cross each other and start overwriting each other's data. */
if (!lzms_output_bitstream_flush(&c->os))
return 0;
if (!lzms_range_encoder_flush(&c->rc))
return 0;
if (c->rc.next > c->os.next)
return 0;
/* Now the compressed buffer contains the data output by the forwards
* bitstream, then empty space, then data output by the backwards
* bitstream. Move the data output by the backwards bitstream to be
* adjacent to the data output by the forward bitstream, and calculate
* the compressed size that this results in. */
num_forwards_bytes = c->rc.next - c->rc.begin;
num_backwards_bytes = c->rc.end - c->os.next;
memmove(c->rc.next, c->os.next, num_backwards_bytes);
return num_forwards_bytes + num_backwards_bytes;
}
static u64
lzms_get_needed_memory(size_t max_bufsize, unsigned compression_level,
bool destructive)
{
u64 size = 0;
if (max_bufsize > LZMS_MAX_BUFFER_SIZE)
return 0;
size += sizeof(struct lzms_compressor);
if (!destructive)
size += max_bufsize; /* in_buffer */
/* mf */
size += lcpit_matchfinder_get_needed_memory(max_bufsize);
return size;
}
static int
lzms_create_compressor(size_t max_bufsize, unsigned compression_level,
bool destructive, void **c_ret)
{
struct lzms_compressor *c;
u32 nice_match_len;
if (max_bufsize > LZMS_MAX_BUFFER_SIZE)
return WIMLIB_ERR_INVALID_PARAM;
c = ALIGNED_MALLOC(sizeof(struct lzms_compressor), 64);
if (!c)
goto oom0;
c->destructive = destructive;
/* Scale nice_match_len with the compression level. But to allow an
* optimization for length cost calculations, don't allow nice_match_len
* to exceed MAX_FAST_LENGTH. */
nice_match_len = min(((u64)compression_level * 63) / 50, MAX_FAST_LENGTH);
c->use_delta_matches = (compression_level >= 35);
c->try_lzmatch_lit_lzrep0 = (compression_level >= 45);
c->try_lit_lzrep0 = (compression_level >= 60);
c->try_lzrep_lit_lzrep0 = (compression_level >= 60);
if (!c->destructive) {
c->in_buffer = MALLOC(max_bufsize);
if (!c->in_buffer)
goto oom1;
}
if (!lcpit_matchfinder_init(&c->mf, max_bufsize, 2, nice_match_len))
goto oom2;
lzms_init_fast_length_slot_tab(c);
lzms_init_offset_slot_tabs(c);
*c_ret = c;
return 0;
oom2:
if (!c->destructive)
FREE(c->in_buffer);
oom1:
ALIGNED_FREE(c);
oom0:
return WIMLIB_ERR_NOMEM;
}
static size_t
lzms_compress(const void *restrict in, size_t in_nbytes,
void *restrict out, size_t out_nbytes_avail, void *restrict _c)
{
struct lzms_compressor *c = _c;
size_t result;
/* Don't bother trying to compress extremely small inputs. */
if (in_nbytes < 4)
return 0;
/* Copy the input data into the internal buffer and preprocess it. */
if (c->destructive)
c->in_buffer = (void *)in;
else
memcpy(c->in_buffer, in, in_nbytes);
c->in_nbytes = in_nbytes;
lzms_x86_filter(c->in_buffer, in_nbytes, c->last_target_usages, false);
/* Prepare the matchfinders. */
lcpit_matchfinder_load_buffer(&c->mf, c->in_buffer, c->in_nbytes);
if (c->use_delta_matches)
lzms_init_delta_matchfinder(c);
/* Initialize the encoder structures. */
lzms_range_encoder_init(&c->rc, out, out_nbytes_avail);
lzms_output_bitstream_init(&c->os, out, out_nbytes_avail);
lzms_init_states_and_probabilities(c);
lzms_init_huffman_codes(c, lzms_get_num_offset_slots(c->in_nbytes));
/* The main loop: parse and encode. */
lzms_near_optimal_parse(c);
/* Return the compressed data size or 0. */
result = lzms_finalize(c);
if (!result && c->destructive)
lzms_x86_filter(c->in_buffer, c->in_nbytes, c->last_target_usages, true);
return result;
}
static void
lzms_free_compressor(void *_c)
{
struct lzms_compressor *c = _c;
if (!c->destructive)
FREE(c->in_buffer);
lcpit_matchfinder_destroy(&c->mf);
ALIGNED_FREE(c);
}
const struct compressor_ops lzms_compressor_ops = {
.get_needed_memory = lzms_get_needed_memory,
.create_compressor = lzms_create_compressor,
.compress = lzms_compress,
.free_compressor = lzms_free_compressor,
};
wimlib-1.14.5/src/extract.c 0000644 0001750 0001750 00000166500 15137020663 012777 0 ustar 00e e /*
* extract.c
*
* Support for extracting WIM images, or files or directories contained in a WIM
* image.
*/
/*
* Copyright (C) 2012-2018 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
/*
* This file provides the API functions wimlib_extract_image(),
* wimlib_extract_image_from_pipe(), wimlib_extract_paths(), and
* wimlib_extract_pathlist(). Internally, all end up calling
* do_wimlib_extract_paths() and extract_trees().
*
* Although wimlib supports multiple extraction modes/backends (NTFS-3G, UNIX,
* Win32), this file does not itself have code to extract files or directories
* to any specific target; instead, it handles generic functionality and relies
* on lower-level callback functions declared in `struct apply_operations' to do
* the actual extraction.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#include
#include
#include "wimlib/apply.h"
#include "wimlib/assert.h"
#include "wimlib/blob_table.h"
#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/metadata.h"
#include "wimlib/object_id.h"
#include "wimlib/pathlist.h"
#include "wimlib/paths.h"
#include "wimlib/pattern.h"
#include "wimlib/reparse.h"
#include "wimlib/resource.h"
#include "wimlib/security.h"
#include "wimlib/unix_data.h"
#include "wimlib/wim.h"
#include "wimlib/win32.h" /* for realpath() equivalent */
#include "wimlib/xattr.h"
#include "wimlib/xml.h"
#define WIMLIB_EXTRACT_FLAG_FROM_PIPE 0x80000000
#define WIMLIB_EXTRACT_FLAG_IMAGEMODE 0x40000000
/* Keep in sync with wimlib.h */
#define WIMLIB_EXTRACT_MASK_PUBLIC \
(WIMLIB_EXTRACT_FLAG_NTFS | \
WIMLIB_EXTRACT_FLAG_RECOVER_DATA | \
WIMLIB_EXTRACT_FLAG_UNIX_DATA | \
WIMLIB_EXTRACT_FLAG_NO_ACLS | \
WIMLIB_EXTRACT_FLAG_STRICT_ACLS | \
WIMLIB_EXTRACT_FLAG_RPFIX | \
WIMLIB_EXTRACT_FLAG_NORPFIX | \
WIMLIB_EXTRACT_FLAG_TO_STDOUT | \
WIMLIB_EXTRACT_FLAG_REPLACE_INVALID_FILENAMES | \
WIMLIB_EXTRACT_FLAG_ALL_CASE_CONFLICTS | \
WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS | \
WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES | \
WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS | \
WIMLIB_EXTRACT_FLAG_GLOB_PATHS | \
WIMLIB_EXTRACT_FLAG_STRICT_GLOB | \
WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES | \
WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE | \
WIMLIB_EXTRACT_FLAG_WIMBOOT | \
WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS4K | \
WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS8K | \
WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS16K | \
WIMLIB_EXTRACT_FLAG_COMPACT_LZX \
)
/* Send WIMLIB_PROGRESS_MSG_EXTRACT_FILE_STRUCTURE or
* WIMLIB_PROGRESS_MSG_EXTRACT_METADATA. */
int
do_file_extract_progress(struct apply_ctx *ctx, enum wimlib_progress_msg msg)
{
ctx->count_until_file_progress = 500; /* Arbitrary value to limit calls */
return extract_progress(ctx, msg);
}
static int
start_file_phase(struct apply_ctx *ctx, u64 end_file_count, enum wimlib_progress_msg msg)
{
ctx->progress.extract.current_file_count = 0;
ctx->progress.extract.end_file_count = end_file_count;
return do_file_extract_progress(ctx, msg);
}
int
start_file_structure_phase(struct apply_ctx *ctx, u64 end_file_count)
{
return start_file_phase(ctx, end_file_count, WIMLIB_PROGRESS_MSG_EXTRACT_FILE_STRUCTURE);
}
int
start_file_metadata_phase(struct apply_ctx *ctx, u64 end_file_count)
{
return start_file_phase(ctx, end_file_count, WIMLIB_PROGRESS_MSG_EXTRACT_METADATA);
}
static int
end_file_phase(struct apply_ctx *ctx, enum wimlib_progress_msg msg)
{
ctx->progress.extract.current_file_count = ctx->progress.extract.end_file_count;
return do_file_extract_progress(ctx, msg);
}
int
end_file_structure_phase(struct apply_ctx *ctx)
{
return end_file_phase(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_FILE_STRUCTURE);
}
int
end_file_metadata_phase(struct apply_ctx *ctx)
{
return end_file_phase(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_METADATA);
}
/* Are all bytes in the specified buffer zero? */
static bool
is_all_zeroes(const u8 *p, const size_t size)
{
const u8 * const end = p + size;
for (; (uintptr_t)p % WORDBYTES && p != end; p++)
if (*p)
return false;
for (; end - p >= WORDBYTES; p += WORDBYTES)
if (*(const machine_word_t *)p)
return false;
for (; p != end; p++)
if (*p)
return false;
return true;
}
/*
* Sparse regions should be detected at the granularity of the filesystem block
* size. For now just assume 4096 bytes, which is the default block size on
* NTFS and most Linux filesystems.
*/
#define SPARSE_UNIT 4096
/*
* Detect whether the specified buffer begins with a region of all zero bytes.
* Return %true if a zero region was found or %false if a nonzero region was
* found, and sets *len_ret to the length of the region. This operates at a
* granularity of SPARSE_UNIT bytes, meaning that to extend a zero region, there
* must be SPARSE_UNIT zero bytes with no interruption, but to extend a nonzero
* region, just one nonzero byte in the next SPARSE_UNIT bytes is sufficient.
*
* Note: besides compression, the WIM format doesn't yet have a way to
* efficiently represent zero regions, so that's why we need to detect them
* ourselves. Things will still fall apart badly on extremely large sparse
* files, but this is a start...
*/
bool
detect_sparse_region(const void *data, size_t size, size_t *len_ret)
{
const void *p = data;
const void * const end = data + size;
size_t len = 0;
bool zeroes = false;
while (p != end) {
size_t n = min(end - p, SPARSE_UNIT);
bool z = is_all_zeroes(p, n);
if (len != 0 && z != zeroes)
break;
zeroes = z;
len += n;
p += n;
}
*len_ret = len;
return zeroes;
}
#define PWM_FOUND_WIM_HDR (-1)
/* Read the header for a blob in a pipable WIM. If @pwm_hdr_ret is not NULL,
* also look for a pipable WIM header and return PWM_FOUND_WIM_HDR if found. */
static int
read_pwm_blob_header(WIMStruct *pwm, u8 hash_ret[SHA1_HASH_SIZE],
struct wim_reshdr *reshdr_ret,
struct wim_header_disk *pwm_hdr_ret)
{
int ret;
struct pwm_blob_hdr blob_hdr;
u64 magic;
ret = full_read(&pwm->in_fd, &blob_hdr, sizeof(blob_hdr));
if (unlikely(ret))
goto read_error;
magic = le64_to_cpu(blob_hdr.magic);
if (magic == PWM_MAGIC && pwm_hdr_ret != NULL) {
memcpy(pwm_hdr_ret, &blob_hdr, sizeof(blob_hdr));
ret = full_read(&pwm->in_fd,
(u8 *)pwm_hdr_ret + sizeof(blob_hdr),
sizeof(*pwm_hdr_ret) - sizeof(blob_hdr));
if (unlikely(ret))
goto read_error;
return PWM_FOUND_WIM_HDR;
}
if (unlikely(magic != PWM_BLOB_MAGIC)) {
ERROR("Data read on pipe is invalid (expected blob header)");
return WIMLIB_ERR_INVALID_PIPABLE_WIM;
}
copy_hash(hash_ret, blob_hdr.hash);
reshdr_ret->size_in_wim = 0; /* Not available */
reshdr_ret->flags = le32_to_cpu(blob_hdr.flags);
reshdr_ret->offset_in_wim = pwm->in_fd.offset;
reshdr_ret->uncompressed_size = le64_to_cpu(blob_hdr.uncompressed_size);
if (unlikely(reshdr_ret->uncompressed_size == 0)) {
ERROR("Data read on pipe is invalid (resource is of 0 size)");
return WIMLIB_ERR_INVALID_PIPABLE_WIM;
}
return 0;
read_error:
if (ret == WIMLIB_ERR_UNEXPECTED_END_OF_FILE)
ERROR("The pipe ended before all needed data was sent!");
else
ERROR_WITH_ERRNO("Error reading pipable WIM from pipe");
return ret;
}
static int
read_blobs_from_pipe(struct apply_ctx *ctx, const struct read_blob_callbacks *cbs)
{
int ret;
u8 hash[SHA1_HASH_SIZE];
struct wim_reshdr reshdr;
struct wim_header_disk pwm_hdr;
struct wim_resource_descriptor rdesc;
struct blob_descriptor *blob;
copy_guid(ctx->progress.extract.guid, ctx->wim->hdr.guid);
ctx->progress.extract.part_number = ctx->wim->hdr.part_number;
ctx->progress.extract.total_parts = ctx->wim->hdr.total_parts;
ret = extract_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN);
if (ret)
return ret;
while (ctx->num_blobs_remaining) {
ret = read_pwm_blob_header(ctx->wim, hash, &reshdr, &pwm_hdr);
if (ret == PWM_FOUND_WIM_HDR) {
u16 part_number = le16_to_cpu(pwm_hdr.part_number);
u16 total_parts = le16_to_cpu(pwm_hdr.total_parts);
if (part_number == ctx->progress.extract.part_number &&
total_parts == ctx->progress.extract.total_parts &&
guids_equal(pwm_hdr.guid, ctx->progress.extract.guid))
continue;
copy_guid(ctx->progress.extract.guid, pwm_hdr.guid);
ctx->progress.extract.part_number = part_number;
ctx->progress.extract.total_parts = total_parts;
ret = extract_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN);
if (ret)
return ret;
continue;
}
if (ret)
return ret;
if (!(reshdr.flags & WIM_RESHDR_FLAG_METADATA)
&& (blob = lookup_blob(ctx->wim->blob_table, hash))
&& (blob->out_refcnt))
{
wim_reshdr_to_desc_and_blob(&reshdr, ctx->wim, &rdesc, blob);
ret = read_blob_with_sha1(blob, cbs,
ctx->extract_flags &
WIMLIB_EXTRACT_FLAG_RECOVER_DATA);
blob_unset_is_located_in_wim_resource(blob);
if (ret)
return ret;
ctx->num_blobs_remaining--;
} else {
wim_reshdr_to_desc(&reshdr, ctx->wim, &rdesc);
ret = skip_wim_resource(&rdesc);
if (ret)
return ret;
}
}
return 0;
}
static int
handle_pwm_metadata_resource(WIMStruct *pwm, int image, bool is_needed)
{
struct blob_descriptor *blob;
struct wim_reshdr reshdr;
struct wim_resource_descriptor *rdesc;
int ret;
ret = WIMLIB_ERR_NOMEM;
blob = new_blob_descriptor();
if (!blob)
goto out;
ret = read_pwm_blob_header(pwm, blob->hash, &reshdr, NULL);
if (ret)
goto out;
ret = WIMLIB_ERR_INVALID_PIPABLE_WIM;
if (!(reshdr.flags & WIM_RESHDR_FLAG_METADATA)) {
ERROR("Expected metadata resource, but found non-metadata "
"resource");
goto out;
}
ret = WIMLIB_ERR_NOMEM;
rdesc = MALLOC(sizeof(*rdesc));
if (!rdesc)
goto out;
wim_reshdr_to_desc_and_blob(&reshdr, pwm, rdesc, blob);
pwm->refcnt++;
ret = WIMLIB_ERR_NOMEM;
pwm->image_metadata[image - 1] = new_unloaded_image_metadata(blob);
if (!pwm->image_metadata[image - 1])
goto out;
blob = NULL;
/* If the metadata resource is for the image being extracted, then parse
* it and save the metadata in memory. Otherwise, skip over it. */
if (is_needed)
ret = select_wim_image(pwm, image);
else
ret = skip_wim_resource(rdesc);
out:
free_blob_descriptor(blob);
return ret;
}
/* Creates a temporary file opened for writing. The open file descriptor is
* returned in @fd_ret and its name is returned in @name_ret (dynamically
* allocated). */
static int
create_temporary_file(struct filedes *fd_ret, tchar **name_ret)
{
tchar *name;
int raw_fd;
#ifdef _WIN32
retry:
name = _wtempnam(NULL, L"wimlib");
if (!name) {
ERROR_WITH_ERRNO("Failed to create temporary filename");
return WIMLIB_ERR_NOMEM;
}
raw_fd = _wopen(name, O_WRONLY | O_CREAT | O_EXCL | O_BINARY |
_O_SHORT_LIVED, 0600);
if (raw_fd < 0 && errno == EEXIST) {
FREE(name);
goto retry;
}
#else /* _WIN32 */
const char *tmpdir = getenv("TMPDIR");
if (!tmpdir)
tmpdir = P_tmpdir;
name = MALLOC(strlen(tmpdir) + 1 + 6 + 6 + 1);
if (!name)
return WIMLIB_ERR_NOMEM;
sprintf(name, "%s/wimlibXXXXXX", tmpdir);
raw_fd = mkstemp(name);
#endif /* !_WIN32 */
if (raw_fd < 0) {
ERROR_WITH_ERRNO("Failed to create temporary file "
"\"%"TS"\"", name);
FREE(name);
return WIMLIB_ERR_OPEN;
}
filedes_init(fd_ret, raw_fd);
*name_ret = name;
return 0;
}
static int
begin_extract_blob(struct blob_descriptor *blob, void *_ctx)
{
struct apply_ctx *ctx = _ctx;
if (unlikely(blob->out_refcnt > MAX_OPEN_FILES))
return create_temporary_file(&ctx->tmpfile_fd, &ctx->tmpfile_name);
return call_begin_blob(blob, ctx->saved_cbs);
}
static int
extract_chunk(const struct blob_descriptor *blob, u64 offset,
const void *chunk, size_t size, void *_ctx)
{
struct apply_ctx *ctx = _ctx;
union wimlib_progress_info *progress = &ctx->progress;
bool last = (offset + size == blob->size);
int ret;
if (likely(ctx->supported_features.hard_links)) {
progress->extract.completed_bytes +=
(u64)size * blob->out_refcnt;
if (last)
progress->extract.completed_streams += blob->out_refcnt;
} else {
const struct blob_extraction_target *targets =
blob_extraction_targets(blob);
for (u32 i = 0; i < blob->out_refcnt; i++) {
const struct wim_inode *inode = targets[i].inode;
const struct wim_dentry *dentry;
inode_for_each_extraction_alias(dentry, inode) {
progress->extract.completed_bytes += size;
if (last)
progress->extract.completed_streams++;
}
}
}
if (progress->extract.completed_bytes >= ctx->next_progress) {
ret = extract_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS);
if (ret)
return ret;
set_next_progress(progress->extract.completed_bytes,
progress->extract.total_bytes,
&ctx->next_progress);
}
if (unlikely(filedes_valid(&ctx->tmpfile_fd))) {
/* Just extracting to temporary file for now. */
ret = full_write(&ctx->tmpfile_fd, chunk, size);
if (ret) {
ERROR_WITH_ERRNO("Error writing data to "
"temporary file \"%"TS"\"",
ctx->tmpfile_name);
}
return ret;
}
return call_continue_blob(blob, offset, chunk, size, ctx->saved_cbs);
}
/* Copy the blob's data from the temporary file to each of its targets.
*
* This is executed only in the very uncommon case that a blob is being
* extracted to more than MAX_OPEN_FILES targets! */
static int
extract_from_tmpfile(const tchar *tmpfile_name,
const struct blob_descriptor *orig_blob,
const struct read_blob_callbacks *cbs)
{
struct blob_descriptor tmpfile_blob;
const struct blob_extraction_target *targets = blob_extraction_targets(orig_blob);
int ret;
memcpy(&tmpfile_blob, orig_blob, sizeof(struct blob_descriptor));
tmpfile_blob.blob_location = BLOB_IN_FILE_ON_DISK;
tmpfile_blob.file_on_disk = (tchar *)tmpfile_name;
tmpfile_blob.out_refcnt = 1;
for (u32 i = 0; i < orig_blob->out_refcnt; i++) {
tmpfile_blob.inline_blob_extraction_targets[0] = targets[i];
ret = read_blob_with_cbs(&tmpfile_blob, cbs, false);
if (ret)
return ret;
}
return 0;
}
static void
warn_about_corrupted_file(struct wim_dentry *dentry,
const struct wim_inode_stream *stream)
{
WARNING("Corruption in %s\"%"TS"\"! Extracting anyway since data recovery mode is enabled.",
stream_is_unnamed_data_stream(stream) ? "" : "alternate stream of ",
dentry_full_path(dentry));
}
static int
end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx)
{
struct apply_ctx *ctx = _ctx;
if ((ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RECOVER_DATA) &&
!status && blob->corrupted) {
const struct blob_extraction_target *targets =
blob_extraction_targets(blob);
for (u32 i = 0; i < blob->out_refcnt; i++) {
struct wim_dentry *dentry =
inode_first_extraction_dentry(targets[i].inode);
warn_about_corrupted_file(dentry, targets[i].stream);
}
}
if (unlikely(filedes_valid(&ctx->tmpfile_fd))) {
filedes_close(&ctx->tmpfile_fd);
if (!status)
status = extract_from_tmpfile(ctx->tmpfile_name, blob,
ctx->saved_cbs);
filedes_invalidate(&ctx->tmpfile_fd);
tunlink(ctx->tmpfile_name);
FREE(ctx->tmpfile_name);
return status;
}
return call_end_blob(blob, status, ctx->saved_cbs);
}
/*
* Read the list of blobs to extract and feed their data into the specified
* callback functions.
*
* This handles checksumming each blob.
*
* This also handles sending WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS.
*
* This also works if the WIM is being read from a pipe.
*
* This also will split up blobs that will need to be extracted to more than
* MAX_OPEN_FILES locations, as measured by the 'out_refcnt' of each blob.
* Therefore, the apply_operations implementation need not worry about running
* out of file descriptors, unless it might open more than one file descriptor
* per 'blob_extraction_target' (e.g. Win32 currently might because the
* destination file system might not support hard links).
*/
int
extract_blob_list(struct apply_ctx *ctx, const struct read_blob_callbacks *cbs)
{
struct read_blob_callbacks wrapper_cbs = {
.begin_blob = begin_extract_blob,
.continue_blob = extract_chunk,
.end_blob = end_extract_blob,
.ctx = ctx,
};
ctx->saved_cbs = cbs;
if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_FROM_PIPE) {
return read_blobs_from_pipe(ctx, &wrapper_cbs);
} else {
int flags = VERIFY_BLOB_HASHES;
if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RECOVER_DATA)
flags |= RECOVER_DATA;
return read_blob_list(&ctx->blob_list,
offsetof(struct blob_descriptor,
extraction_list),
&wrapper_cbs, flags);
}
}
/* Extract a WIM dentry to standard output.
*
* This obviously doesn't make sense in all cases. We return an error if the
* dentry does not correspond to a regular file. Otherwise we extract the
* unnamed data stream only. */
static int
extract_dentry_to_stdout(struct wim_dentry *dentry,
const struct blob_table *blob_table, int extract_flags)
{
struct wim_inode *inode = dentry->d_inode;
struct blob_descriptor *blob;
struct filedes _stdout;
bool recover = (extract_flags & WIMLIB_EXTRACT_FLAG_RECOVER_DATA);
int ret;
if (inode->i_attributes & (FILE_ATTRIBUTE_REPARSE_POINT |
FILE_ATTRIBUTE_DIRECTORY |
FILE_ATTRIBUTE_ENCRYPTED))
{
ERROR("\"%"TS"\" is not a regular file and therefore cannot be "
"extracted to standard output", dentry_full_path(dentry));
return WIMLIB_ERR_NOT_A_REGULAR_FILE;
}
blob = inode_get_blob_for_unnamed_data_stream(inode, blob_table);
if (!blob) {
const u8 *hash = inode_get_hash_of_unnamed_data_stream(inode);
if (!is_zero_hash(hash))
return blob_not_found_error(inode, hash);
return 0;
}
filedes_init(&_stdout, STDOUT_FILENO);
ret = extract_blob_to_fd(blob, &_stdout, recover);
if (ret)
return ret;
if (recover && blob->corrupted)
warn_about_corrupted_file(dentry,
inode_get_unnamed_data_stream(inode));
return 0;
}
static int
extract_dentries_to_stdout(struct wim_dentry **dentries, size_t num_dentries,
const struct blob_table *blob_table,
int extract_flags)
{
for (size_t i = 0; i < num_dentries; i++) {
int ret = extract_dentry_to_stdout(dentries[i], blob_table,
extract_flags);
if (ret)
return ret;
}
return 0;
}
/**********************************************************************/
/*
* Removes duplicate dentries from the array.
*
* Returns the new number of dentries, packed at the front of the array.
*/
static size_t
remove_duplicate_trees(struct wim_dentry **trees, size_t num_trees)
{
size_t i, j = 0;
for (i = 0; i < num_trees; i++) {
if (!trees[i]->d_tmp_flag) {
/* Found distinct dentry. */
trees[i]->d_tmp_flag = 1;
trees[j++] = trees[i];
}
}
for (i = 0; i < j; i++)
trees[i]->d_tmp_flag = 0;
return j;
}
/*
* Remove dentries that are descendants of other dentries in the array.
*
* Returns the new number of dentries, packed at the front of the array.
*/
static size_t
remove_contained_trees(struct wim_dentry **trees, size_t num_trees)
{
size_t i, j = 0;
for (i = 0; i < num_trees; i++)
trees[i]->d_tmp_flag = 1;
for (i = 0; i < num_trees; i++) {
struct wim_dentry *d = trees[i];
while (!dentry_is_root(d)) {
d = d->d_parent;
if (d->d_tmp_flag)
goto tree_contained;
}
trees[j++] = trees[i];
continue;
tree_contained:
trees[i]->d_tmp_flag = 0;
}
for (i = 0; i < j; i++)
trees[i]->d_tmp_flag = 0;
return j;
}
static int
dentry_append_to_list(struct wim_dentry *dentry, void *_dentry_list)
{
struct list_head *dentry_list = _dentry_list;
list_add_tail(&dentry->d_extraction_list_node, dentry_list);
return 0;
}
static void
dentry_reset_extraction_list_node(struct wim_dentry *dentry)
{
dentry->d_extraction_list_node = (struct list_head){NULL, NULL};
}
static int
dentry_delete_from_list(struct wim_dentry *dentry, void *_ignore)
{
if (will_extract_dentry(dentry)) {
list_del(&dentry->d_extraction_list_node);
dentry_reset_extraction_list_node(dentry);
}
return 0;
}
/*
* Build the preliminary list of dentries to be extracted.
*
* The list maintains the invariant that if d1 and d2 are in the list and d1 is
* an ancestor of d2, then d1 appears before d2 in the list.
*/
static void
build_dentry_list(struct list_head *dentry_list, struct wim_dentry **trees,
size_t num_trees, bool add_ancestors)
{
INIT_LIST_HEAD(dentry_list);
/* Add the trees recursively. */
for (size_t i = 0; i < num_trees; i++)
for_dentry_in_tree(trees[i], dentry_append_to_list, dentry_list);
/* If requested, add ancestors of the trees. */
if (add_ancestors) {
for (size_t i = 0; i < num_trees; i++) {
struct wim_dentry *dentry = trees[i];
struct wim_dentry *ancestor;
struct list_head *place_after;
if (dentry_is_root(dentry))
continue;
place_after = dentry_list;
ancestor = dentry;
do {
ancestor = ancestor->d_parent;
if (will_extract_dentry(ancestor)) {
place_after = &ancestor->d_extraction_list_node;
break;
}
} while (!dentry_is_root(ancestor));
ancestor = dentry;
do {
ancestor = ancestor->d_parent;
if (will_extract_dentry(ancestor))
break;
list_add(&ancestor->d_extraction_list_node, place_after);
} while (!dentry_is_root(ancestor));
}
}
}
static void
destroy_dentry_list(struct list_head *dentry_list)
{
struct wim_dentry *dentry, *tmp;
struct wim_inode *inode;
list_for_each_entry_safe(dentry, tmp, dentry_list, d_extraction_list_node) {
inode = dentry->d_inode;
dentry_reset_extraction_list_node(dentry);
inode->i_visited = 0;
inode->i_can_externally_back = 0;
if ((void *)dentry->d_extraction_name != (void *)dentry->d_name)
FREE(dentry->d_extraction_name);
dentry->d_extraction_name = NULL;
dentry->d_extraction_name_nchars = 0;
}
}
static void
destroy_blob_list(struct list_head *blob_list)
{
struct blob_descriptor *blob;
list_for_each_entry(blob, blob_list, extraction_list)
if (blob->out_refcnt > ARRAY_LEN(blob->inline_blob_extraction_targets))
FREE(blob->blob_extraction_targets);
}
#ifdef _WIN32
static const utf16lechar replacement_char = cpu_to_le16(0xfffd);
#else
static const utf16lechar replacement_char = cpu_to_le16('?');
#endif
static bool
file_name_valid(utf16lechar *name, size_t num_chars, bool fix)
{
size_t i;
if (num_chars == 0)
return true;
for (i = 0; i < num_chars; i++) {
switch (le16_to_cpu(name[i])) {
#ifdef _WIN32
case '\x01'...'\x1F':
case '\\':
case ':':
case '*':
case '?':
case '"':
case '<':
case '>':
case '|':
#endif
case '/':
case '\0':
if (fix)
name[i] = replacement_char;
else
return false;
}
}
return true;
}
static int
dentry_calculate_extraction_name(struct wim_dentry *dentry,
struct apply_ctx *ctx)
{
int ret;
if (dentry_is_root(dentry))
return 0;
#ifdef WITH_NTFS_3G
if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
dentry->d_extraction_name = dentry->d_name;
dentry->d_extraction_name_nchars = dentry->d_name_nbytes /
sizeof(utf16lechar);
return 0;
}
#endif
if (!ctx->supported_features.case_sensitive_filenames) {
struct wim_dentry *other;
dentry_for_each_ci_match(other, dentry) {
if (will_extract_dentry(other)) {
if (ctx->extract_flags &
WIMLIB_EXTRACT_FLAG_ALL_CASE_CONFLICTS) {
WARNING("\"%"TS"\" has the same "
"case-insensitive name as "
"\"%"TS"\"; extracting "
"dummy name instead",
dentry_full_path(dentry),
dentry_full_path(other));
goto out_replace;
} else {
WARNING("Not extracting \"%"TS"\": "
"has same case-insensitive "
"name as \"%"TS"\"",
dentry_full_path(dentry),
dentry_full_path(other));
goto skip_dentry;
}
}
}
}
if (file_name_valid(dentry->d_name, dentry->d_name_nbytes / 2, false)) {
size_t nbytes = 0;
ret = utf16le_get_tstr(dentry->d_name,
dentry->d_name_nbytes,
(const tchar **)&dentry->d_extraction_name,
&nbytes);
dentry->d_extraction_name_nchars = nbytes / sizeof(tchar);
return ret;
} else {
if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_REPLACE_INVALID_FILENAMES)
{
WARNING("\"%"TS"\" has an invalid filename "
"that is not supported on this platform; "
"extracting dummy name instead",
dentry_full_path(dentry));
goto out_replace;
} else {
WARNING("Not extracting \"%"TS"\": has an invalid filename "
"that is not supported on this platform",
dentry_full_path(dentry));
goto skip_dentry;
}
}
out_replace:
{
utf16lechar utf16_name_copy[dentry->d_name_nbytes / 2];
memcpy(utf16_name_copy, dentry->d_name, dentry->d_name_nbytes);
file_name_valid(utf16_name_copy, dentry->d_name_nbytes / 2, true);
const tchar *tchar_name;
size_t tchar_nchars;
ret = utf16le_get_tstr(utf16_name_copy,
dentry->d_name_nbytes,
&tchar_name, &tchar_nchars);
if (ret)
return ret;
tchar_nchars /= sizeof(tchar);
size_t fixed_name_num_chars = tchar_nchars;
tchar fixed_name[tchar_nchars + 50];
tmemcpy(fixed_name, tchar_name, tchar_nchars);
fixed_name_num_chars += tsprintf(fixed_name + tchar_nchars,
T(" (invalid filename #%lu)"),
++ctx->invalid_sequence);
utf16le_put_tstr(tchar_name);
dentry->d_extraction_name = TSTRDUP(fixed_name);
if (!dentry->d_extraction_name)
return WIMLIB_ERR_NOMEM;
dentry->d_extraction_name_nchars = fixed_name_num_chars;
}
return 0;
skip_dentry:
for_dentry_in_tree(dentry, dentry_delete_from_list, NULL);
return 0;
}
/*
* Calculate the actual filename component at which each WIM dentry will be
* extracted, with special handling for dentries that are unsupported by the
* extraction backend or have invalid names.
*
* ctx->supported_features must be filled in.
*
* Possible error codes: WIMLIB_ERR_NOMEM, WIMLIB_ERR_INVALID_UTF16_STRING
*/
static int
dentry_list_calculate_extraction_names(struct list_head *dentry_list,
struct apply_ctx *ctx)
{
struct list_head *prev, *cur;
/* Can't use list_for_each_entry() because a call to
* dentry_calculate_extraction_name() may delete the current dentry and
* its children from the list. */
prev = dentry_list;
for (;;) {
struct wim_dentry *dentry;
int ret;
cur = prev->next;
if (cur == dentry_list)
break;
dentry = list_entry(cur, struct wim_dentry, d_extraction_list_node);
ret = dentry_calculate_extraction_name(dentry, ctx);
if (ret)
return ret;
if (prev->next == cur)
prev = cur;
else
; /* Current dentry and its children (which follow in
the list) were deleted. prev stays the same. */
}
return 0;
}
static int
dentry_resolve_streams(struct wim_dentry *dentry, int extract_flags,
struct blob_table *blob_table)
{
struct wim_inode *inode = dentry->d_inode;
struct blob_descriptor *blob;
int ret;
bool force = false;
/* Special case: when extracting from a pipe, the WIM blob table is
* initially empty, so "resolving" an inode's streams is initially not
* possible. However, we still need to keep track of which blobs,
* identified by SHA-1 message digests, need to be extracted, so we
* "resolve" the inode's streams anyway by allocating a 'struct
* blob_descriptor' for each one. */
if (extract_flags & WIMLIB_EXTRACT_FLAG_FROM_PIPE)
force = true;
ret = inode_resolve_streams(inode, blob_table, force);
if (ret)
return ret;
for (unsigned i = 0; i < inode->i_num_streams; i++) {
blob = stream_blob_resolved(&inode->i_streams[i]);
if (blob)
blob->out_refcnt = 0;
}
return 0;
}
/*
* For each dentry to be extracted, resolve all streams in the corresponding
* inode and set 'out_refcnt' in all referenced blob_descriptors to 0.
*
* Possible error codes: WIMLIB_ERR_RESOURCE_NOT_FOUND, WIMLIB_ERR_NOMEM.
*/
static int
dentry_list_resolve_streams(struct list_head *dentry_list,
struct apply_ctx *ctx)
{
struct wim_dentry *dentry;
int ret;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
ret = dentry_resolve_streams(dentry,
ctx->extract_flags,
ctx->wim->blob_table);
if (ret)
return ret;
}
return 0;
}
static int
ref_stream(struct wim_inode_stream *strm, struct wim_dentry *dentry,
struct apply_ctx *ctx)
{
struct wim_inode *inode = dentry->d_inode;
struct blob_descriptor *blob = stream_blob_resolved(strm);
struct blob_extraction_target *targets;
if (!blob)
return 0;
/* Tally the size only for each actual extraction of the stream (not
* additional hard links to the inode). */
if (inode->i_visited && ctx->supported_features.hard_links)
return 0;
ctx->progress.extract.total_bytes += blob->size;
ctx->progress.extract.total_streams++;
if (inode->i_visited)
return 0;
/* Add each blob to 'ctx->blob_list' only one time, regardless of how
* many extraction targets it will have. */
if (blob->out_refcnt == 0) {
list_add_tail(&blob->extraction_list, &ctx->blob_list);
ctx->num_blobs_remaining++;
}
/* Set this stream as an extraction target of 'blob'. */
if (blob->out_refcnt < ARRAY_LEN(blob->inline_blob_extraction_targets)) {
targets = blob->inline_blob_extraction_targets;
} else {
struct blob_extraction_target *prev_targets;
size_t alloc_blob_extraction_targets;
if (blob->out_refcnt == ARRAY_LEN(blob->inline_blob_extraction_targets)) {
prev_targets = NULL;
alloc_blob_extraction_targets = ARRAY_LEN(blob->inline_blob_extraction_targets);
} else {
prev_targets = blob->blob_extraction_targets;
alloc_blob_extraction_targets = blob->alloc_blob_extraction_targets;
}
if (blob->out_refcnt == alloc_blob_extraction_targets) {
alloc_blob_extraction_targets *= 2;
targets = REALLOC(prev_targets,
alloc_blob_extraction_targets *
sizeof(targets[0]));
if (!targets)
return WIMLIB_ERR_NOMEM;
if (!prev_targets) {
memcpy(targets,
blob->inline_blob_extraction_targets,
sizeof(blob->inline_blob_extraction_targets));
}
blob->blob_extraction_targets = targets;
blob->alloc_blob_extraction_targets = alloc_blob_extraction_targets;
}
targets = blob->blob_extraction_targets;
}
targets[blob->out_refcnt].inode = inode;
targets[blob->out_refcnt].stream = strm;
blob->out_refcnt++;
return 0;
}
static int
ref_stream_if_needed(struct wim_dentry *dentry, struct wim_inode *inode,
struct wim_inode_stream *strm, struct apply_ctx *ctx)
{
bool need_stream = false;
switch (strm->stream_type) {
case STREAM_TYPE_DATA:
if (stream_is_named(strm)) {
/* Named data stream */
if (ctx->supported_features.named_data_streams)
need_stream = true;
} else if (!(inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
FILE_ATTRIBUTE_ENCRYPTED))
&& !(inode_is_symlink(inode)
&& !ctx->supported_features.reparse_points
&& ctx->supported_features.symlink_reparse_points))
{
/*
* Unnamed data stream. Skip if any of the following is true:
*
* - file is a directory
* - file is encrypted
* - backend needs to create the file as UNIX symlink
* - backend will extract the stream as externally
* backed from the WIM archive itself
*/
if (ctx->apply_ops->will_back_from_wim) {
int ret = (*ctx->apply_ops->will_back_from_wim)(dentry, ctx);
if (ret > 0) /* Error? */
return ret;
if (ret < 0) /* Won't externally back? */
need_stream = true;
} else {
need_stream = true;
}
}
break;
case STREAM_TYPE_REPARSE_POINT:
wimlib_assert(inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT);
if (ctx->supported_features.reparse_points ||
(inode_is_symlink(inode) &&
ctx->supported_features.symlink_reparse_points))
need_stream = true;
break;
case STREAM_TYPE_EFSRPC_RAW_DATA:
wimlib_assert(inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED);
if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) {
if (ctx->supported_features.encrypted_directories)
need_stream = true;
} else {
if (ctx->supported_features.encrypted_files)
need_stream = true;
}
break;
}
if (need_stream)
return ref_stream(strm, dentry, ctx);
return 0;
}
static int
dentry_ref_streams(struct wim_dentry *dentry, struct apply_ctx *ctx)
{
struct wim_inode *inode = dentry->d_inode;
for (unsigned i = 0; i < inode->i_num_streams; i++) {
int ret = ref_stream_if_needed(dentry, inode,
&inode->i_streams[i], ctx);
if (ret)
return ret;
}
inode->i_visited = 1;
return 0;
}
/*
* Given a list of dentries to be extracted, build the list of blobs that need
* to be extracted, and for each blob determine the streams to which that blob
* will be extracted.
*
* This also initializes the extract progress info with byte and blob
* information.
*
* ctx->supported_features must be filled in.
*/
static int
dentry_list_ref_streams(struct list_head *dentry_list, struct apply_ctx *ctx)
{
struct wim_dentry *dentry;
int ret;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
ret = dentry_ref_streams(dentry, ctx);
if (ret)
return ret;
}
list_for_each_entry(dentry, dentry_list, d_extraction_list_node)
dentry->d_inode->i_visited = 0;
return 0;
}
static void
dentry_list_build_inode_alias_lists(struct list_head *dentry_list)
{
struct wim_dentry *dentry;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node)
dentry->d_inode->i_first_extraction_alias = NULL;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
dentry->d_next_extraction_alias = dentry->d_inode->i_first_extraction_alias;
dentry->d_inode->i_first_extraction_alias = dentry;
}
}
static void
inode_tally_features(const struct wim_inode *inode,
struct wim_features *features)
{
if (inode->i_attributes & FILE_ATTRIBUTE_READONLY)
features->readonly_files++;
if (inode->i_attributes & FILE_ATTRIBUTE_HIDDEN)
features->hidden_files++;
if (inode->i_attributes & FILE_ATTRIBUTE_SYSTEM)
features->system_files++;
if (inode->i_attributes & FILE_ATTRIBUTE_ARCHIVE)
features->archive_files++;
if (inode->i_attributes & FILE_ATTRIBUTE_COMPRESSED)
features->compressed_files++;
if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
features->encrypted_directories++;
else
features->encrypted_files++;
}
if (inode->i_attributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
features->not_context_indexed_files++;
if (inode->i_attributes & FILE_ATTRIBUTE_SPARSE_FILE)
features->sparse_files++;
if (inode_has_named_data_stream(inode))
features->named_data_streams++;
if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
features->reparse_points++;
if (inode_is_symlink(inode))
features->symlink_reparse_points++;
else
features->other_reparse_points++;
}
if (inode_has_security_descriptor(inode))
features->security_descriptors++;
if (inode_has_unix_data(inode))
features->unix_data++;
if (inode_has_object_id(inode))
features->object_ids++;
if (inode_has_xattrs(inode))
features->xattrs++;
}
/* Tally features necessary to extract a dentry and the corresponding inode. */
static void
dentry_tally_features(struct wim_dentry *dentry, struct wim_features *features)
{
struct wim_inode *inode = dentry->d_inode;
if (dentry_has_short_name(dentry))
features->short_names++;
if (inode->i_visited) {
features->hard_links++;
} else {
inode_tally_features(inode, features);
inode->i_visited = 1;
}
}
/* Tally the features necessary to extract the specified dentries. */
static void
dentry_list_get_features(struct list_head *dentry_list,
struct wim_features *features)
{
struct wim_dentry *dentry;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node)
dentry_tally_features(dentry, features);
list_for_each_entry(dentry, dentry_list, d_extraction_list_node)
dentry->d_inode->i_visited = 0;
}
static int
do_feature_check(const struct wim_features *required_features,
const struct wim_features *supported_features,
int extract_flags)
{
/* Encrypted files. */
if (required_features->encrypted_files &&
!supported_features->encrypted_files)
WARNING("Ignoring EFS-encrypted data of %lu files",
required_features->encrypted_files);
/* Named data streams. */
if (required_features->named_data_streams &&
!supported_features->named_data_streams)
WARNING("Ignoring named data streams of %lu files",
required_features->named_data_streams);
/* File attributes. */
if (!(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)) {
if (required_features->readonly_files &&
!supported_features->readonly_files)
WARNING("Ignoring FILE_ATTRIBUTE_READONLY of %lu files",
required_features->readonly_files);
if (required_features->hidden_files &&
!supported_features->hidden_files)
WARNING("Ignoring FILE_ATTRIBUTE_HIDDEN of %lu files",
required_features->hidden_files);
if (required_features->system_files &&
!supported_features->system_files)
WARNING("Ignoring FILE_ATTRIBUTE_SYSTEM of %lu files",
required_features->system_files);
/* Note: Don't bother the user about FILE_ATTRIBUTE_ARCHIVE.
* We're an archive program, so theoretically we can do what we
* want with it. */
if (required_features->compressed_files &&
!supported_features->compressed_files)
WARNING("Ignoring FILE_ATTRIBUTE_COMPRESSED of %lu files",
required_features->compressed_files);
if (required_features->not_context_indexed_files &&
!supported_features->not_context_indexed_files)
WARNING("Ignoring FILE_ATTRIBUTE_NOT_CONTENT_INDEXED of %lu files",
required_features->not_context_indexed_files);
if (required_features->sparse_files &&
!supported_features->sparse_files)
WARNING("Ignoring FILE_ATTRIBUTE_SPARSE_FILE of %lu files",
required_features->sparse_files);
if (required_features->encrypted_directories &&
!supported_features->encrypted_directories)
WARNING("Ignoring FILE_ATTRIBUTE_ENCRYPTED of %lu directories",
required_features->encrypted_directories);
}
/* Hard links. */
if (required_features->hard_links && !supported_features->hard_links)
WARNING("Extracting %lu hard links as independent files",
required_features->hard_links);
/* Symbolic links and reparse points. */
if ((extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS) &&
required_features->symlink_reparse_points &&
!supported_features->symlink_reparse_points &&
!supported_features->reparse_points)
{
ERROR("Extraction backend does not support symbolic links!");
return WIMLIB_ERR_UNSUPPORTED;
}
if (required_features->reparse_points &&
!supported_features->reparse_points)
{
if (supported_features->symlink_reparse_points) {
if (required_features->other_reparse_points) {
WARNING("Ignoring reparse data of %lu non-symlink/junction files",
required_features->other_reparse_points);
}
} else {
WARNING("Ignoring reparse data of %lu files",
required_features->reparse_points);
}
}
/* Security descriptors. */
if (((extract_flags & (WIMLIB_EXTRACT_FLAG_STRICT_ACLS |
WIMLIB_EXTRACT_FLAG_UNIX_DATA))
== WIMLIB_EXTRACT_FLAG_STRICT_ACLS) &&
required_features->security_descriptors &&
!supported_features->security_descriptors)
{
ERROR("Extraction backend does not support security descriptors!");
return WIMLIB_ERR_UNSUPPORTED;
}
if (!(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS) &&
required_features->security_descriptors &&
!supported_features->security_descriptors)
WARNING("Ignoring Windows NT security descriptors of %lu files",
required_features->security_descriptors);
/* Standard UNIX metadata */
if (required_features->unix_data &&
(!supported_features->unix_data ||
!(extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA)))
{
if (extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) {
ERROR("Requested UNIX metadata extraction, but "
"extraction backend does not support it!");
return WIMLIB_ERR_UNSUPPORTED;
}
WARNING("Ignoring UNIX metadata (uid/gid/mode/rdev) of %lu files%"TS,
required_features->unix_data,
(supported_features->unix_data ?
T("\n (use --unix-data mode to extract these)") : T("")));
}
/* Extended attributes */
if (required_features->xattrs &&
(!supported_features->xattrs ||
(supported_features->unix_data &&
!(extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA))))
{
WARNING("Ignoring extended attributes of %lu files%"TS,
required_features->xattrs,
(supported_features->xattrs ?
T("\n (use --unix-data mode to extract these)") : T("")));
}
/* Object IDs. */
if (required_features->object_ids && !supported_features->object_ids) {
WARNING("Ignoring object IDs of %lu files",
required_features->object_ids);
}
/* DOS Names. */
if (required_features->short_names &&
!supported_features->short_names)
{
if (extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES) {
ERROR("Extraction backend does not support DOS names!");
return WIMLIB_ERR_UNSUPPORTED;
}
WARNING("Ignoring DOS names of %lu files",
required_features->short_names);
}
/* Timestamps. */
if ((extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS) &&
!supported_features->timestamps)
{
ERROR("Extraction backend does not support timestamps!");
return WIMLIB_ERR_UNSUPPORTED;
}
return 0;
}
static const struct apply_operations *
select_apply_operations(int extract_flags)
{
#ifdef WITH_NTFS_3G
if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS)
return &ntfs_3g_apply_ops;
#endif
#ifdef _WIN32
return &win32_apply_ops;
#else
return &unix_apply_ops;
#endif
}
static int
extract_trees(WIMStruct *wim, struct wim_dentry **trees, size_t num_trees,
const tchar *target, int extract_flags)
{
const struct apply_operations *ops;
struct apply_ctx *ctx;
int ret;
LIST_HEAD(dentry_list);
if (extract_flags & WIMLIB_EXTRACT_FLAG_TO_STDOUT) {
ret = extract_dentries_to_stdout(trees, num_trees,
wim->blob_table,
extract_flags);
goto out;
}
num_trees = remove_duplicate_trees(trees, num_trees);
num_trees = remove_contained_trees(trees, num_trees);
ops = select_apply_operations(extract_flags);
if (num_trees > 1 && ops->single_tree_only) {
ERROR("Extracting multiple directory trees "
"at once is not supported in %s extraction mode!",
ops->name);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out;
}
ctx = CALLOC(1, ops->context_size);
if (!ctx) {
ret = WIMLIB_ERR_NOMEM;
goto out;
}
ctx->wim = wim;
ctx->target = target;
ctx->target_nchars = tstrlen(target);
ctx->extract_flags = extract_flags;
if (ctx->wim->progfunc) {
ctx->progfunc = ctx->wim->progfunc;
ctx->progctx = ctx->wim->progctx;
ctx->progress.extract.image = wim->current_image;
ctx->progress.extract.extract_flags = (extract_flags &
WIMLIB_EXTRACT_MASK_PUBLIC);
ctx->progress.extract.wimfile_name = wim->filename;
ctx->progress.extract.image_name = wimlib_get_image_name(wim,
wim->current_image);
ctx->progress.extract.target = target;
}
INIT_LIST_HEAD(&ctx->blob_list);
filedes_invalidate(&ctx->tmpfile_fd);
ctx->apply_ops = ops;
ret = (*ops->get_supported_features)(target, &ctx->supported_features);
if (ret)
goto out_cleanup;
build_dentry_list(&dentry_list, trees, num_trees,
!(extract_flags &
WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE));
dentry_list_get_features(&dentry_list, &ctx->required_features);
ret = do_feature_check(&ctx->required_features, &ctx->supported_features,
ctx->extract_flags);
if (ret)
goto out_cleanup;
ret = dentry_list_calculate_extraction_names(&dentry_list, ctx);
if (ret)
goto out_cleanup;
if (unlikely(list_empty(&dentry_list))) {
WARNING("There is nothing to extract!");
goto out_cleanup;
}
ret = dentry_list_resolve_streams(&dentry_list, ctx);
if (ret)
goto out_cleanup;
dentry_list_build_inode_alias_lists(&dentry_list);
ret = dentry_list_ref_streams(&dentry_list, ctx);
if (ret)
goto out_cleanup;
if (extract_flags & WIMLIB_EXTRACT_FLAG_FROM_PIPE) {
/* When extracting from a pipe, the number of bytes of data to
* extract can't be determined in the normal way (examining the
* blob table), since at this point all we have is a set of
* SHA-1 message digests of blobs that need to be extracted.
* However, we can get a reasonably accurate estimate by taking
* from the corresponding in the WIM XML
* data. This does assume that a full image is being extracted,
* but currently there is no API for doing otherwise. (Also,
* subtract from this if hard links are
* supported by the extraction mode.) */
ctx->progress.extract.total_bytes =
xml_get_image_total_bytes(wim->xml_info,
wim->current_image);
if (ctx->supported_features.hard_links) {
ctx->progress.extract.total_bytes -=
xml_get_image_hard_link_bytes(wim->xml_info,
wim->current_image);
}
}
ret = extract_progress(ctx,
((extract_flags & WIMLIB_EXTRACT_FLAG_IMAGEMODE) ?
WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN :
WIMLIB_PROGRESS_MSG_EXTRACT_TREE_BEGIN));
if (ret)
goto out_cleanup;
ret = (*ops->extract)(&dentry_list, ctx);
if (ret)
goto out_cleanup;
if (ctx->progress.extract.completed_bytes <
ctx->progress.extract.total_bytes)
{
ctx->progress.extract.completed_bytes =
ctx->progress.extract.total_bytes;
ret = extract_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS);
if (ret)
goto out_cleanup;
}
ret = extract_progress(ctx,
((extract_flags & WIMLIB_EXTRACT_FLAG_IMAGEMODE) ?
WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_END :
WIMLIB_PROGRESS_MSG_EXTRACT_TREE_END));
out_cleanup:
destroy_blob_list(&ctx->blob_list);
destroy_dentry_list(&dentry_list);
FREE(ctx);
out:
return ret;
}
static int
mkdir_if_needed(const tchar *target)
{
if (!tmkdir(target, 0755))
return 0;
if (errno == EEXIST)
return 0;
#ifdef _WIN32
/* _wmkdir() fails with EACCES if called on a drive root directory. */
if (errno == EACCES)
return 0;
#endif
ERROR_WITH_ERRNO("Failed to create directory \"%"TS"\"", target);
return WIMLIB_ERR_MKDIR;
}
/* Make sure the extraction flags make sense, and update them if needed. */
static int
check_extract_flags(const WIMStruct *wim, int *extract_flags_p)
{
int extract_flags = *extract_flags_p;
/* Check for invalid flag combinations */
if ((extract_flags &
(WIMLIB_EXTRACT_FLAG_NO_ACLS |
WIMLIB_EXTRACT_FLAG_STRICT_ACLS)) == (WIMLIB_EXTRACT_FLAG_NO_ACLS |
WIMLIB_EXTRACT_FLAG_STRICT_ACLS))
return WIMLIB_ERR_INVALID_PARAM;
if ((extract_flags &
(WIMLIB_EXTRACT_FLAG_RPFIX |
WIMLIB_EXTRACT_FLAG_NORPFIX)) == (WIMLIB_EXTRACT_FLAG_RPFIX |
WIMLIB_EXTRACT_FLAG_NORPFIX))
return WIMLIB_ERR_INVALID_PARAM;
#ifndef WITH_NTFS_3G
if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
ERROR("wimlib was compiled without support for NTFS-3G, so\n"
" it cannot apply a WIM image directly to an NTFS volume.");
return WIMLIB_ERR_UNSUPPORTED;
}
#endif
if (extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT) {
#ifdef _WIN32
if (!wim->filename)
return WIMLIB_ERR_NO_FILENAME;
#else
ERROR("WIMBoot extraction is only supported on Windows!");
return WIMLIB_ERR_UNSUPPORTED;
#endif
}
if (extract_flags & (WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS4K |
WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS8K |
WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS16K |
WIMLIB_EXTRACT_FLAG_COMPACT_LZX))
{
#ifdef _WIN32
int count = 0;
count += ((extract_flags & WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS4K) != 0);
count += ((extract_flags & WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS8K) != 0);
count += ((extract_flags & WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS16K) != 0);
count += ((extract_flags & WIMLIB_EXTRACT_FLAG_COMPACT_LZX) != 0);
if (count != 1) {
ERROR("Only one compression format can be specified "
"for compact-mode extraction!");
return WIMLIB_ERR_INVALID_PARAM;
}
if (extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT) {
ERROR("Compact-mode extraction and WIMBoot-mode "
"extraction are mutually exclusive!");
return WIMLIB_ERR_INVALID_PARAM;
}
#else
ERROR("Compact-mode extraction (System Compression) "
"is only supported on Windows!");
return WIMLIB_ERR_UNSUPPORTED;
#endif
}
if ((extract_flags & (WIMLIB_EXTRACT_FLAG_RPFIX |
WIMLIB_EXTRACT_FLAG_NORPFIX |
WIMLIB_EXTRACT_FLAG_IMAGEMODE)) ==
WIMLIB_EXTRACT_FLAG_IMAGEMODE)
{
/* For full-image extraction, do reparse point fixups by default
* if the WIM header says they are enabled. */
if (wim->hdr.flags & WIM_HDR_FLAG_RP_FIX)
extract_flags |= WIMLIB_EXTRACT_FLAG_RPFIX;
}
*extract_flags_p = extract_flags;
return 0;
}
struct append_dentry_ctx {
struct wim_dentry **dentries;
size_t num_dentries;
size_t num_alloc_dentries;
};
static int
append_dentry_cb(struct wim_dentry *dentry, void *_ctx)
{
struct append_dentry_ctx *ctx = _ctx;
if (ctx->num_dentries == ctx->num_alloc_dentries) {
struct wim_dentry **new_dentries;
size_t new_length;
new_length = max(ctx->num_alloc_dentries + 8,
ctx->num_alloc_dentries * 3 / 2);
new_dentries = REALLOC(ctx->dentries,
new_length * sizeof(ctx->dentries[0]));
if (new_dentries == NULL)
return WIMLIB_ERR_NOMEM;
ctx->dentries = new_dentries;
ctx->num_alloc_dentries = new_length;
}
ctx->dentries[ctx->num_dentries++] = dentry;
return 0;
}
/* Append dentries matched by a path which can contain wildcard characters. */
static int
append_matched_dentries(WIMStruct *wim, const tchar *orig_pattern,
int extract_flags, struct append_dentry_ctx *ctx)
{
const size_t count_before = ctx->num_dentries;
tchar *pattern;
int ret;
pattern = canonicalize_wim_path(orig_pattern);
if (!pattern)
return WIMLIB_ERR_NOMEM;
ret = expand_path_pattern(wim_get_current_root_dentry(wim), pattern,
append_dentry_cb, ctx);
FREE(pattern);
if (ret || ctx->num_dentries > count_before)
return ret;
if (extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_GLOB) {
ERROR("No matches for path pattern \"%"TS"\"", orig_pattern);
return WIMLIB_ERR_PATH_DOES_NOT_EXIST;
}
WARNING("No matches for path pattern \"%"TS"\"", orig_pattern);
return 0;
}
static int
do_wimlib_extract_paths(WIMStruct *wim, int image, const tchar *target,
const tchar * const *paths, size_t num_paths,
int extract_flags)
{
int ret;
struct wim_dentry **trees;
size_t num_trees;
if (wim == NULL || target == NULL || target[0] == T('\0') ||
(num_paths != 0 && paths == NULL))
return WIMLIB_ERR_INVALID_PARAM;
ret = check_extract_flags(wim, &extract_flags);
if (ret)
return ret;
ret = select_wim_image(wim, image);
if (ret)
return ret;
ret = wim_checksum_unhashed_blobs(wim);
if (ret)
return ret;
if ((extract_flags & (WIMLIB_EXTRACT_FLAG_NTFS |
WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE)) ==
(WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE))
{
ret = mkdir_if_needed(target);
if (ret)
return ret;
}
if (extract_flags & WIMLIB_EXTRACT_FLAG_GLOB_PATHS) {
struct append_dentry_ctx append_dentry_ctx = {
.dentries = NULL,
.num_dentries = 0,
.num_alloc_dentries = 0,
};
for (size_t i = 0; i < num_paths; i++) {
ret = append_matched_dentries(wim, paths[i],
extract_flags,
&append_dentry_ctx);
if (ret) {
trees = append_dentry_ctx.dentries;
goto out_free_trees;
}
}
trees = append_dentry_ctx.dentries;
num_trees = append_dentry_ctx.num_dentries;
} else {
trees = MALLOC(num_paths * sizeof(trees[0]));
if (trees == NULL)
return WIMLIB_ERR_NOMEM;
for (size_t i = 0; i < num_paths; i++) {
tchar *path = canonicalize_wim_path(paths[i]);
if (path == NULL) {
ret = WIMLIB_ERR_NOMEM;
goto out_free_trees;
}
trees[i] = get_dentry(wim, path,
WIMLIB_CASE_PLATFORM_DEFAULT);
FREE(path);
if (trees[i] == NULL) {
ERROR("Path \"%"TS"\" does not exist "
"in WIM image %d",
paths[i], wim->current_image);
ret = WIMLIB_ERR_PATH_DOES_NOT_EXIST;
goto out_free_trees;
}
}
num_trees = num_paths;
}
if (num_trees == 0) {
ret = 0;
goto out_free_trees;
}
ret = extract_trees(wim, trees, num_trees, target, extract_flags);
out_free_trees:
FREE(trees);
return ret;
}
static int
extract_single_image(WIMStruct *wim, int image,
const tchar *target, int extract_flags)
{
const tchar *path = WIMLIB_WIM_ROOT_PATH;
extract_flags |= WIMLIB_EXTRACT_FLAG_IMAGEMODE;
return do_wimlib_extract_paths(wim, image, target, &path, 1, extract_flags);
}
static const tchar * const filename_forbidden_chars =
#ifdef _WIN32
T("<>:\"/\\|?*");
#else
T("/");
#endif
/* This function checks if it is okay to use a WIM image's name as a directory
* name. */
static bool
image_name_ok_as_dir(const tchar *image_name)
{
return image_name && *image_name &&
!tstrpbrk(image_name, filename_forbidden_chars) &&
tstrcmp(image_name, T(".")) &&
tstrcmp(image_name, T("..")) &&
tstrlen(image_name) <= 128;
}
/* Extracts all images from the WIM to the directory @target, with the images
* placed in subdirectories named by their image names. */
static int
extract_all_images(WIMStruct *wim, const tchar *target, int extract_flags)
{
size_t output_path_len = tstrlen(target);
tchar buf[output_path_len + 1 + 128 + 1];
int ret;
int image;
const tchar *image_name;
if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
ERROR("Cannot extract multiple images in NTFS extraction mode.");
return WIMLIB_ERR_INVALID_PARAM;
}
ret = mkdir_if_needed(target);
if (ret)
return ret;
tmemcpy(buf, target, output_path_len);
buf[output_path_len] = OS_PREFERRED_PATH_SEPARATOR;
for (image = 1; image <= wim->hdr.image_count; image++) {
image_name = wimlib_get_image_name(wim, image);
if (image_name_ok_as_dir(image_name)) {
tstrcpy(buf + output_path_len + 1, image_name);
} else {
/* Image name is empty or contains forbidden characters.
* Use image number instead. */
tsprintf(buf + output_path_len + 1, T("%d"), image);
}
ret = extract_single_image(wim, image, buf, extract_flags);
if (ret)
return ret;
}
return 0;
}
static int
do_wimlib_extract_image(WIMStruct *wim, int image, const tchar *target,
int extract_flags)
{
if (extract_flags & (WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE |
WIMLIB_EXTRACT_FLAG_TO_STDOUT |
WIMLIB_EXTRACT_FLAG_GLOB_PATHS))
return WIMLIB_ERR_INVALID_PARAM;
if (image == WIMLIB_ALL_IMAGES)
return extract_all_images(wim, target, extract_flags);
else
return extract_single_image(wim, image, target, extract_flags);
}
/****************************************************************************
* Extraction API *
****************************************************************************/
WIMLIBAPI int
wimlib_extract_paths(WIMStruct *wim, int image, const tchar *target,
const tchar * const *paths, size_t num_paths,
int extract_flags)
{
if (extract_flags & ~WIMLIB_EXTRACT_MASK_PUBLIC)
return WIMLIB_ERR_INVALID_PARAM;
return do_wimlib_extract_paths(wim, image, target, paths, num_paths,
extract_flags);
}
WIMLIBAPI int
wimlib_extract_pathlist(WIMStruct *wim, int image, const tchar *target,
const tchar *path_list_file, int extract_flags)
{
int ret;
tchar **paths;
size_t num_paths;
void *mem;
ret = read_path_list_file(path_list_file, &paths, &num_paths, &mem);
if (ret) {
ERROR("Failed to read path list file \"%"TS"\"",
path_list_file ? path_list_file : T(""));
return ret;
}
ret = wimlib_extract_paths(wim, image, target,
(const tchar * const *)paths, num_paths,
extract_flags);
FREE(paths);
FREE(mem);
return ret;
}
WIMLIBAPI int
wimlib_extract_image_from_pipe_with_progress(int pipe_fd,
const tchar *image_num_or_name,
const tchar *target,
int extract_flags,
wimlib_progress_func_t progfunc,
void *progctx)
{
int ret;
WIMStruct *pwm;
struct filedes *in_fd;
int image;
unsigned i;
if (extract_flags & ~WIMLIB_EXTRACT_MASK_PUBLIC)
return WIMLIB_ERR_INVALID_PARAM;
/* Read the WIM header from the pipe and get a WIMStruct to represent
* the pipable WIM. Caveats: Unlike getting a WIMStruct with
* wimlib_open_wim(), getting a WIMStruct in this way will result in an
* empty blob table, no XML data read, and no filename set. */
ret = open_wim_as_WIMStruct(&pipe_fd, WIMLIB_OPEN_FLAG_FROM_PIPE, &pwm,
progfunc, progctx);
if (ret)
return ret;
/* Sanity check to make sure this is a pipable WIM. */
if (pwm->hdr.magic != PWM_MAGIC) {
ERROR("The WIM being read from file descriptor %d "
"is not pipable!", pipe_fd);
ret = WIMLIB_ERR_NOT_PIPABLE;
goto out_wimlib_free;
}
/* Sanity check to make sure the first part of a pipable split WIM is
* sent over the pipe first. */
if (pwm->hdr.part_number != 1) {
ERROR("The first part of the split WIM must be "
"sent over the pipe first.");
ret = WIMLIB_ERR_INVALID_PIPABLE_WIM;
goto out_wimlib_free;
}
in_fd = &pwm->in_fd;
wimlib_assert(in_fd->offset == WIM_HEADER_DISK_SIZE);
/* As mentioned, the WIMStruct we created from the pipe does not have
* XML data yet. Fix this by reading the extra copy of the XML data
* that directly follows the header in pipable WIMs. (Note: see
* write_pipable_wim() for more details about the format of pipable
* WIMs.) */
{
u8 hash[SHA1_HASH_SIZE];
ret = read_pwm_blob_header(pwm, hash,
&pwm->hdr.xml_data_reshdr, NULL);
if (ret)
goto out_wimlib_free;
if (!(pwm->hdr.xml_data_reshdr.flags & WIM_RESHDR_FLAG_METADATA)) {
ERROR("Expected XML data, but found non-metadata resource.");
ret = WIMLIB_ERR_INVALID_PIPABLE_WIM;
goto out_wimlib_free;
}
ret = read_wim_xml_data(pwm);
if (ret)
goto out_wimlib_free;
if (xml_get_image_count(pwm->xml_info) != pwm->hdr.image_count) {
ERROR("Image count in XML data is not the same as in WIM header.");
ret = WIMLIB_ERR_IMAGE_COUNT;
goto out_wimlib_free;
}
}
/* Get image index (this may use the XML data that was just read to
* resolve an image name). */
if (image_num_or_name) {
image = wimlib_resolve_image(pwm, image_num_or_name);
if (image == WIMLIB_NO_IMAGE) {
ERROR("\"%"TS"\" is not a valid image in the pipable WIM!",
image_num_or_name);
ret = WIMLIB_ERR_INVALID_IMAGE;
goto out_wimlib_free;
} else if (image == WIMLIB_ALL_IMAGES) {
ERROR("Applying all images from a pipe is not supported!");
ret = WIMLIB_ERR_INVALID_IMAGE;
goto out_wimlib_free;
}
} else {
if (pwm->hdr.image_count != 1) {
ERROR("No image was specified, but the pipable WIM "
"did not contain exactly 1 image");
ret = WIMLIB_ERR_INVALID_IMAGE;
goto out_wimlib_free;
}
image = 1;
}
/* Load the needed metadata resource. */
for (i = 1; i <= pwm->hdr.image_count; i++) {
ret = handle_pwm_metadata_resource(pwm, i, i == image);
if (ret)
goto out_wimlib_free;
}
/* Extract the image. */
extract_flags |= WIMLIB_EXTRACT_FLAG_FROM_PIPE;
ret = do_wimlib_extract_image(pwm, image, target, extract_flags);
/* Clean up and return. */
out_wimlib_free:
wimlib_free(pwm);
return ret;
}
WIMLIBAPI int
wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name,
const tchar *target, int extract_flags)
{
return wimlib_extract_image_from_pipe_with_progress(pipe_fd,
image_num_or_name,
target,
extract_flags,
NULL,
NULL);
}
WIMLIBAPI int
wimlib_extract_image(WIMStruct *wim, int image, const tchar *target,
int extract_flags)
{
if (extract_flags & ~WIMLIB_EXTRACT_MASK_PUBLIC)
return WIMLIB_ERR_INVALID_PARAM;
return do_wimlib_extract_image(wim, image, target, extract_flags);
}
wimlib-1.14.5/src/ntfs-3g_apply.c 0000644 0001750 0001750 00000071764 15137020663 014022 0 ustar 00e e /*
* ntfs-3g_apply.c
*
* Apply a WIM image directly to an NTFS volume using libntfs-3g. Restore as
* much information as possible, including security data, file attributes, DOS
* names, alternate data streams, and object IDs.
*
* Note: because NTFS-3G offers inode-based interfaces, we actually don't need
* to deal with paths at all! (Other than for error messages.)
*/
/*
* Copyright (C) 2012-2017 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#include
#include
#include
#include
#include "wimlib/assert.h"
#include "wimlib/apply.h"
#include "wimlib/blob_table.h"
#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/error.h"
#include "wimlib/metadata.h"
#include "wimlib/ntfs_3g.h"
#include "wimlib/object_id.h"
#include "wimlib/reparse.h"
#include "wimlib/security.h"
static int
ntfs_3g_get_supported_features(const char *target,
struct wim_features *supported_features)
{
supported_features->readonly_files = 1;
supported_features->hidden_files = 1;
supported_features->system_files = 1;
supported_features->archive_files = 1;
supported_features->compressed_files = 1;
supported_features->not_context_indexed_files = 1;
supported_features->sparse_files = 1;
supported_features->named_data_streams = 1;
supported_features->hard_links = 1;
supported_features->reparse_points = 1;
supported_features->security_descriptors = 1;
supported_features->short_names = 1;
supported_features->object_ids = 1;
supported_features->timestamps = 1;
supported_features->case_sensitive_filenames = 1;
return 0;
}
struct ntfs_3g_apply_ctx {
/* Extract flags, the pointer to the WIMStruct, etc. */
struct apply_ctx common;
/* Pointer to the open NTFS volume */
ntfs_volume *vol;
ntfs_attr *open_attrs[MAX_OPEN_FILES];
unsigned num_open_attrs;
ntfs_inode *open_inodes[MAX_OPEN_FILES];
unsigned num_open_inodes;
/* For each currently open attribute, whether we're writing to it in
* "sparse" mode or not. */
bool is_sparse_attr[MAX_OPEN_FILES];
/* Whether is_sparse_attr[] is true for any currently open attribute */
bool any_sparse_attrs;
struct reparse_buffer_disk rpbuf;
u8 *reparse_ptr;
unsigned num_reparse_inodes;
ntfs_inode *ntfs_reparse_inodes[MAX_OPEN_FILES];
struct wim_inode *wim_reparse_inodes[MAX_OPEN_FILES];
};
static int
ntfs_3g_set_timestamps(ntfs_inode *ni, const struct wim_inode *inode)
{
u64 times[3] = {
inode->i_creation_time,
inode->i_last_write_time,
inode->i_last_access_time,
};
if (ntfs_inode_set_times(ni, (const char *)times, sizeof(times), 0))
return WIMLIB_ERR_SET_TIMESTAMPS;
return 0;
}
/* Restore the timestamps on the NTFS inode corresponding to @inode. */
static int
ntfs_3g_restore_timestamps(ntfs_volume *vol, const struct wim_inode *inode)
{
ntfs_inode *ni;
int res;
ni = ntfs_inode_open(vol, inode->i_mft_no);
if (!ni)
goto fail;
res = ntfs_3g_set_timestamps(ni, inode);
if (ntfs_inode_close(ni) || res)
goto fail;
return 0;
fail:
ERROR_WITH_ERRNO("Failed to update timestamps of \"%s\" in NTFS volume",
dentry_full_path(inode_first_extraction_dentry(inode)));
return WIMLIB_ERR_SET_TIMESTAMPS;
}
/* Restore the DOS name of the @dentry.
* This closes both @ni and @dir_ni.
* If either is NULL, then they are opened temporarily. */
static int
ntfs_3g_restore_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
struct wim_dentry *dentry, ntfs_volume *vol)
{
int ret;
const char *dos_name;
size_t dos_name_nbytes;
/* Note: ntfs_set_ntfs_dos_name() closes both inodes (even if it fails).
* And it takes in a multibyte string, even though it translates it to
* UTF-16LE internally... which is annoying because we currently have
* the UTF-16LE string but not the multibyte string. */
ret = utf16le_get_tstr(dentry->d_short_name, dentry->d_short_name_nbytes,
&dos_name, &dos_name_nbytes);
if (ret)
goto out_close;
if (!dir_ni)
dir_ni = ntfs_inode_open(vol, dentry->d_parent->d_inode->i_mft_no);
if (!ni)
ni = ntfs_inode_open(vol, dentry->d_inode->i_mft_no);
if (dir_ni && ni) {
ret = ntfs_set_ntfs_dos_name(ni, dir_ni,
dos_name, dos_name_nbytes, 0);
dir_ni = NULL;
ni = NULL;
} else {
ret = -1;
}
utf16le_put_tstr(dos_name);
if (unlikely(ret)) {
int err = errno;
ERROR_WITH_ERRNO("Failed to set DOS name of \"%s\" in NTFS "
"volume", dentry_full_path(dentry));
if (err == EILSEQ) {
ERROR("This error may have been caused by a known "
"bug in libntfs-3g where it is unable to set "
"DOS names on files whose long names contain "
"unpaired surrogate characters. This bug "
"was fixed in NTFS-3G version 2017.3.23.");
}
if (err == EINVAL) {
utf16lechar c =
dentry->d_name[dentry->d_name_nbytes / 2 - 1];
if (c == cpu_to_le16('.') || c == cpu_to_le16(' ')) {
ERROR("This error was probably caused by a "
"known bug in libntfs-3g where it is "
"unable to set DOS names on files whose "
"long names end with a dot or space "
"character. This bug was fixed in "
"NTFS-3G version 2017.3.23.");
}
}
ret = WIMLIB_ERR_SET_SHORT_NAME;
goto out_close;
}
/* Unlike most other NTFS-3G functions, ntfs_set_ntfs_dos_name()
* changes the directory's last modification timestamp...
* Change it back. */
return ntfs_3g_restore_timestamps(vol, dentry->d_parent->d_inode);
out_close:
/* ntfs_inode_close() can take a NULL argument, but it's probably best
* not to rely on this behavior. */
if (ni)
ntfs_inode_close(ni);
if (dir_ni)
ntfs_inode_close(dir_ni);
return ret;
}
static int
ntfs_3g_restore_reparse_point(ntfs_inode *ni, const struct wim_inode *inode,
unsigned blob_size, struct ntfs_3g_apply_ctx *ctx)
{
complete_reparse_point(&ctx->rpbuf, inode, blob_size);
if (ntfs_set_ntfs_reparse_data(ni, (const char *)&ctx->rpbuf,
REPARSE_DATA_OFFSET + blob_size, 0))
{
int err = errno;
ERROR_WITH_ERRNO("Failed to set reparse data on \"%s\"",
dentry_full_path(
inode_first_extraction_dentry(inode)));
if (err == EINVAL && !(inode->i_reparse_tag & 0x80000000)) {
WARNING("This reparse point had a non-Microsoft reparse "
"tag. The preceding error may have been caused "
"by a known bug in libntfs-3g where it does not "
"correctly validate non-Microsoft reparse "
"points. This bug was fixed in NTFS-3G version "
"2016.2.22.");
}
return WIMLIB_ERR_SET_REPARSE_DATA;
}
return 0;
}
static bool
ntfs_3g_has_empty_attributes(const struct wim_inode *inode)
{
for (unsigned i = 0; i < inode->i_num_streams; i++) {
const struct wim_inode_stream *strm = &inode->i_streams[i];
if (stream_blob_resolved(strm) == NULL &&
(strm->stream_type == STREAM_TYPE_REPARSE_POINT ||
stream_is_named_data_stream(strm)))
return true;
}
return false;
}
/*
* Create empty attributes (named data streams and potentially a reparse point)
* for the specified file, if there are any.
*
* Since these won't have blob descriptors, they won't show up in the call to
* extract_blob_list(). Hence the need for the special case.
*
* Keep this in sync with ntfs_3g_has_empty_attributes()!
*/
static int
ntfs_3g_create_empty_attributes(ntfs_inode *ni,
const struct wim_inode *inode,
struct ntfs_3g_apply_ctx *ctx)
{
for (unsigned i = 0; i < inode->i_num_streams; i++) {
const struct wim_inode_stream *strm = &inode->i_streams[i];
int ret;
if (stream_blob_resolved(strm) != NULL)
continue;
if (strm->stream_type == STREAM_TYPE_REPARSE_POINT) {
ret = ntfs_3g_restore_reparse_point(ni, inode, 0, ctx);
if (ret)
return ret;
} else if (stream_is_named_data_stream(strm)) {
if (ntfs_attr_add(ni, AT_DATA, strm->stream_name,
utf16le_len_chars(strm->stream_name),
NULL, 0))
{
ERROR_WITH_ERRNO("Failed to create named data "
"stream of \"%s\"",
dentry_full_path(
inode_first_extraction_dentry(inode)));
return WIMLIB_ERR_NTFS_3G;
}
}
}
return 0;
}
/* Set attributes, security descriptor, and timestamps on the NTFS inode @ni.
*/
static int
ntfs_3g_set_metadata(ntfs_inode *ni, const struct wim_inode *inode,
const struct ntfs_3g_apply_ctx *ctx)
{
int extract_flags;
const struct wim_security_data *sd;
struct wim_dentry *one_dentry;
int ret;
extract_flags = ctx->common.extract_flags;
sd = wim_get_current_security_data(ctx->common.wim);
one_dentry = inode_first_extraction_dentry(inode);
/* Object ID */
{
u32 len;
const void *object_id = inode_get_object_id(inode, &len);
if (unlikely(object_id != NULL) &&
ntfs_set_ntfs_object_id(ni, object_id, len, 0))
{
if (errno == EEXIST) {
WARNING("Duplicate object ID on file \"%s\"",
dentry_full_path(one_dentry));
} else {
ERROR_WITH_ERRNO("Failed to set object ID on "
"\"%s\" in NTFS volume",
dentry_full_path(one_dentry));
return WIMLIB_ERR_NTFS_3G;
}
}
}
/* Attributes */
if (!(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)) {
u32 attrib = inode->i_attributes;
if (ntfs_set_ntfs_attrib(ni, (const char *)&attrib,
sizeof(attrib), 0))
{
ERROR_WITH_ERRNO("Failed to set attributes on \"%s\" "
"in NTFS volume",
dentry_full_path(one_dentry));
return WIMLIB_ERR_SET_ATTRIBUTES;
}
}
/* Security descriptor */
if (inode_has_security_descriptor(inode)
&& !(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS))
{
struct SECURITY_CONTEXT sec_ctx = { ctx->vol };
const void *desc;
size_t desc_size;
desc = sd->descriptors[inode->i_security_id];
desc_size = sd->sizes[inode->i_security_id];
ret = ntfs_set_ntfs_acl(&sec_ctx, ni, desc, desc_size, 0);
if (unlikely(ret)) {
int err = errno;
ERROR_WITH_ERRNO("Failed to set security descriptor on "
"\"%s\" in NTFS volume",
dentry_full_path(one_dentry));
if (err == EINVAL && wimlib_print_errors) {
fprintf(wimlib_error_file,
"The security descriptor is: ");
print_byte_field(desc, desc_size, wimlib_error_file);
fprintf(wimlib_error_file,
"\n\nThis error occurred because libntfs-3g thinks "
"the security descriptor is invalid. There "
"are several known bugs with libntfs-3g's "
"security descriptor validation logic in older "
"versions. Please upgrade to NTFS-3G version "
"2016.2.22 or later if you haven't already.\n");
}
return WIMLIB_ERR_SET_SECURITY;
}
}
/* Timestamps */
ret = ntfs_3g_set_timestamps(ni, inode);
if (ret) {
ERROR_WITH_ERRNO("Failed to set timestamps on \"%s\" "
"in NTFS volume",
dentry_full_path(one_dentry));
return ret;
}
return 0;
}
/* Recursively creates all the subdirectories of @dir, which has been created as
* the NTFS inode @dir_ni. */
static int
ntfs_3g_create_dirs_recursive(ntfs_inode *dir_ni, struct wim_dentry *dir,
struct ntfs_3g_apply_ctx *ctx)
{
struct wim_dentry *child;
for_dentry_child(child, dir) {
ntfs_inode *ni;
int ret;
if (!(child->d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY))
continue;
if (!will_extract_dentry(child))
continue;
ni = ntfs_create(dir_ni, 0, child->d_extraction_name,
child->d_extraction_name_nchars, S_IFDIR);
if (!ni) {
ERROR_WITH_ERRNO("Error creating \"%s\" in NTFS volume",
dentry_full_path(child));
return WIMLIB_ERR_NTFS_3G;
}
child->d_inode->i_mft_no = ni->mft_no;
ret = report_file_created(&ctx->common);
if (!ret)
ret = ntfs_3g_set_metadata(ni, child->d_inode, ctx);
if (!ret)
ret = ntfs_3g_create_dirs_recursive(ni, child, ctx);
if (ntfs_inode_close_in_dir(ni, dir_ni) && !ret) {
ERROR_WITH_ERRNO("Error closing \"%s\" in NTFS volume",
dentry_full_path(child));
ret = WIMLIB_ERR_NTFS_3G;
}
if (ret)
return ret;
}
return 0;
}
/* For each WIM dentry in the @root tree that represents a directory, create the
* corresponding directory in the NTFS volume @ctx->vol. */
static int
ntfs_3g_create_directories(struct wim_dentry *root,
struct list_head *dentry_list,
struct ntfs_3g_apply_ctx *ctx)
{
ntfs_inode *root_ni;
int ret;
struct wim_dentry *dentry;
/* Create the directories using POSIX names. */
root_ni = ntfs_inode_open(ctx->vol, FILE_root);
if (!root_ni) {
ERROR_WITH_ERRNO("Can't open root of NTFS volume");
return WIMLIB_ERR_NTFS_3G;
}
root->d_inode->i_mft_no = FILE_root;
ret = ntfs_3g_set_metadata(root_ni, root->d_inode, ctx);
if (!ret)
ret = ntfs_3g_create_dirs_recursive(root_ni, root, ctx);
if (ntfs_inode_close(root_ni) && !ret) {
ERROR_WITH_ERRNO("Error closing root of NTFS volume");
ret = WIMLIB_ERR_NTFS_3G;
}
if (ret)
return ret;
/* Set the DOS name of any directory that has one. In addition, create
* empty attributes for directories that have them. Note that creating
* an empty reparse point attribute must happen *after* setting the DOS
* name in order to work around a case where ntfs_set_ntfs_dos_name()
* fails with EOPNOTSUPP. This bug was fixed in NTFS-3G version
* 2016.2.22. */
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
const struct wim_inode *inode = dentry->d_inode;
if (!(inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY))
continue;
if (dentry_has_short_name(dentry)) {
ret = ntfs_3g_restore_dos_name(NULL, NULL, dentry,
ctx->vol);
if (ret)
return ret;
ret = report_file_created(&ctx->common);
if (ret)
return ret;
}
if (ntfs_3g_has_empty_attributes(inode)) {
ntfs_inode *ni;
ret = WIMLIB_ERR_NTFS_3G;
ni = ntfs_inode_open(ctx->vol, inode->i_mft_no);
if (ni) {
ret = ntfs_3g_create_empty_attributes(ni, inode,
ctx);
if (ntfs_inode_close(ni) && !ret)
ret = WIMLIB_ERR_NTFS_3G;
}
if (ret) {
ERROR_WITH_ERRNO("Failed to create empty "
"attributes of directory "
"\"%s\" in NTFS volume",
dentry_full_path(dentry));
return ret;
}
}
}
return 0;
}
/* When creating an inode that will have a short (DOS) name, we create it using
* the long name associated with the short name. This ensures that the short
* name gets associated with the correct long name. */
static struct wim_dentry *
ntfs_3g_first_extraction_alias(struct wim_inode *inode)
{
struct wim_dentry *dentry;
inode_for_each_extraction_alias(dentry, inode)
if (dentry_has_short_name(dentry))
return dentry;
return inode_first_extraction_dentry(inode);
}
/*
* Add a hard link for the NTFS inode @ni at the location corresponding to the
* WIM dentry @dentry.
*
* The parent directory must have already been created on the NTFS volume.
*
* Returns 0 on success; returns WIMLIB_ERR_NTFS_3G and sets errno on failure.
*/
static int
ntfs_3g_add_link(ntfs_inode *ni, struct wim_dentry *dentry)
{
ntfs_inode *dir_ni;
int res;
/* Open the inode of the parent directory. */
dir_ni = ntfs_inode_open(ni->vol, dentry->d_parent->d_inode->i_mft_no);
if (!dir_ni)
goto fail;
/* Create the link. */
res = ntfs_link(ni, dir_ni, dentry->d_extraction_name,
dentry->d_extraction_name_nchars);
/* Close the parent directory. */
if (ntfs_inode_close(dir_ni) || res)
goto fail;
return 0;
fail:
ERROR_WITH_ERRNO("Can't create link \"%s\" in NTFS volume",
dentry_full_path(dentry));
return WIMLIB_ERR_NTFS_3G;
}
static int
ntfs_3g_create_nondirectory(struct wim_inode *inode,
struct ntfs_3g_apply_ctx *ctx)
{
struct wim_dentry *first_dentry;
ntfs_inode *dir_ni;
ntfs_inode *ni;
struct wim_dentry *dentry;
int ret;
first_dentry = ntfs_3g_first_extraction_alias(inode);
/* Create first link. */
dir_ni = ntfs_inode_open(ctx->vol, first_dentry->d_parent->d_inode->i_mft_no);
if (!dir_ni) {
ERROR_WITH_ERRNO("Can't open \"%s\" in NTFS volume",
dentry_full_path(first_dentry->d_parent));
return WIMLIB_ERR_NTFS_3G;
}
ni = ntfs_create(dir_ni, 0, first_dentry->d_extraction_name,
first_dentry->d_extraction_name_nchars, S_IFREG);
if (!ni) {
ERROR_WITH_ERRNO("Can't create \"%s\" in NTFS volume",
dentry_full_path(first_dentry));
ntfs_inode_close(dir_ni);
return WIMLIB_ERR_NTFS_3G;
}
inode->i_mft_no = ni->mft_no;
/* Set short name if present. */
if (dentry_has_short_name(first_dentry)) {
ret = ntfs_3g_restore_dos_name(ni, dir_ni, first_dentry, ctx->vol);
/* ntfs_3g_restore_dos_name() closed both 'ni' and 'dir_ni'. */
if (ret)
return ret;
/* Reopen the inode. */
ni = ntfs_inode_open(ctx->vol, inode->i_mft_no);
if (!ni) {
ERROR_WITH_ERRNO("Failed to reopen \"%s\" "
"in NTFS volume",
dentry_full_path(first_dentry));
return WIMLIB_ERR_NTFS_3G;
}
} else {
/* Close the directory in which the first link was created. */
if (ntfs_inode_close(dir_ni)) {
ERROR_WITH_ERRNO("Failed to close \"%s\" in NTFS volume",
dentry_full_path(first_dentry->d_parent));
ret = WIMLIB_ERR_NTFS_3G;
goto out_close_ni;
}
}
/* Create additional links if present. */
inode_for_each_extraction_alias(dentry, inode) {
if (dentry != first_dentry) {
ret = ntfs_3g_add_link(ni, dentry);
if (ret)
goto out_close_ni;
}
}
/* Set metadata. */
ret = ntfs_3g_set_metadata(ni, inode, ctx);
if (ret)
goto out_close_ni;
ret = ntfs_3g_create_empty_attributes(ni, inode, ctx);
out_close_ni:
/* Close the inode. */
if (ntfs_inode_close(ni) && !ret) {
ERROR_WITH_ERRNO("Error closing \"%s\" in NTFS volume",
dentry_full_path(first_dentry));
ret = WIMLIB_ERR_NTFS_3G;
}
return ret;
}
/* For each WIM dentry in the @dentry_list that represents a nondirectory file,
* create the corresponding nondirectory file in the NTFS volume.
*
* Directories must have already been created. */
static int
ntfs_3g_create_nondirectories(struct list_head *dentry_list,
struct ntfs_3g_apply_ctx *ctx)
{
struct wim_dentry *dentry;
struct wim_inode *inode;
int ret;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
inode = dentry->d_inode;
if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
if (dentry == inode_first_extraction_dentry(inode)) {
ret = ntfs_3g_create_nondirectory(inode, ctx);
if (ret)
return ret;
}
ret = report_file_created(&ctx->common);
if (ret)
return ret;
}
return 0;
}
static int
ntfs_3g_begin_extract_blob_instance(struct blob_descriptor *blob,
ntfs_inode *ni,
struct wim_inode *inode,
const struct wim_inode_stream *strm,
struct ntfs_3g_apply_ctx *ctx)
{
struct wim_dentry *one_dentry = inode_first_extraction_dentry(inode);
ntfschar *stream_name;
size_t stream_name_nchars;
ntfs_attr *na;
if (unlikely(strm->stream_type == STREAM_TYPE_REPARSE_POINT)) {
if (blob->size > REPARSE_DATA_MAX_SIZE) {
ERROR("Reparse data of \"%s\" has size "
"%"PRIu64" bytes (exceeds %u bytes)",
dentry_full_path(one_dentry),
blob->size, REPARSE_DATA_MAX_SIZE);
return WIMLIB_ERR_INVALID_REPARSE_DATA;
}
ctx->reparse_ptr = ctx->rpbuf.rpdata;
ctx->ntfs_reparse_inodes[ctx->num_reparse_inodes] = ni;
ctx->wim_reparse_inodes[ctx->num_reparse_inodes] = inode;
ctx->num_reparse_inodes++;
return 0;
}
/* It's a data stream (may be unnamed or named). */
wimlib_assert(strm->stream_type == STREAM_TYPE_DATA);
if (unlikely(stream_is_named(strm))) {
stream_name = strm->stream_name;
stream_name_nchars = utf16le_len_chars(stream_name);
if (ntfs_attr_add(ni, AT_DATA, stream_name,
stream_name_nchars, NULL, 0))
{
ERROR_WITH_ERRNO("Failed to create named data stream of \"%s\"",
dentry_full_path(one_dentry));
return WIMLIB_ERR_NTFS_3G;
}
} else {
/* Don't pass an empty string other than AT_UNNAMED to
* ntfs_attr_open() --- it violates assumptions made by
* libntfs-3g. */
stream_name = AT_UNNAMED;
stream_name_nchars = 0;
}
/* This should be ensured by extract_blob_list() */
wimlib_assert(ctx->num_open_attrs < MAX_OPEN_FILES);
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_nchars);
if (!na) {
ERROR_WITH_ERRNO("Failed to open data stream of \"%s\"",
dentry_full_path(one_dentry));
return WIMLIB_ERR_NTFS_3G;
}
/*
* Note: there are problems with trying to combine compression with
* sparseness when extracting. For example, doing ntfs_attr_truncate()
* at the end to extend the attribute to its final size actually extends
* to a compression block size boundary rather than to the requested
* size. Until these problems are solved, we always write the full data
* to compressed attributes. We also don't attempt to preallocate space
* for compressed attributes, since we don't know how much space they
* are going to actually need.
*/
ctx->is_sparse_attr[ctx->num_open_attrs] = false;
if (!(na->data_flags & ATTR_COMPRESSION_MASK)) {
if (inode->i_attributes & FILE_ATTRIBUTE_SPARSE_FILE) {
ctx->is_sparse_attr[ctx->num_open_attrs] = true;
ctx->any_sparse_attrs = true;
} else {
ntfs_attr_truncate_solid(na, blob->size);
}
}
ctx->open_attrs[ctx->num_open_attrs++] = na;
return 0;
}
static int
ntfs_3g_cleanup_blob_extract(struct ntfs_3g_apply_ctx *ctx)
{
int ret = 0;
for (unsigned i = 0; i < ctx->num_open_attrs; i++) {
if (ntfs_attr_pclose(ctx->open_attrs[i]))
ret = -1;
ntfs_attr_close(ctx->open_attrs[i]);
}
ctx->num_open_attrs = 0;
for (unsigned i = 0; i < ctx->num_open_inodes; i++) {
if (ntfs_inode_close(ctx->open_inodes[i]))
ret = -1;
}
ctx->num_open_inodes = 0;
ctx->any_sparse_attrs = false;
ctx->reparse_ptr = NULL;
ctx->num_reparse_inodes = 0;
return ret;
}
static ntfs_inode *
ntfs_3g_open_inode(struct wim_inode *inode, struct ntfs_3g_apply_ctx *ctx)
{
ntfs_inode *ni;
/* If the same blob is being extracted to multiple streams of the same
* inode, then we must only open the inode once. */
if (unlikely(inode->i_num_streams > 1)) {
for (unsigned i = 0; i < ctx->num_open_inodes; i++) {
if (ctx->open_inodes[i]->mft_no == inode->i_mft_no) {
return ctx->open_inodes[i];
}
}
}
ni = ntfs_inode_open(ctx->vol, inode->i_mft_no);
if (unlikely(!ni)) {
ERROR_WITH_ERRNO("Can't open \"%s\" in NTFS volume",
dentry_full_path(
inode_first_extraction_dentry(inode)));
return NULL;
}
ctx->open_inodes[ctx->num_open_inodes++] = ni;
return ni;
}
static int
ntfs_3g_begin_extract_blob(struct blob_descriptor *blob, void *_ctx)
{
struct ntfs_3g_apply_ctx *ctx = _ctx;
const struct blob_extraction_target *targets = blob_extraction_targets(blob);
int ret;
ntfs_inode *ni;
for (u32 i = 0; i < blob->out_refcnt; i++) {
ret = WIMLIB_ERR_NTFS_3G;
ni = ntfs_3g_open_inode(targets[i].inode, ctx);
if (!ni)
goto out_cleanup;
ret = ntfs_3g_begin_extract_blob_instance(blob, ni,
targets[i].inode,
targets[i].stream, ctx);
if (ret)
goto out_cleanup;
}
ret = 0;
goto out;
out_cleanup:
ntfs_3g_cleanup_blob_extract(ctx);
out:
return ret;
}
/*
* Note: prior to NTFS-3G version 2016.2.22, ntfs_attr_pwrite() could return a
* short count in non-error cases, contrary to its documentation. Specifically,
* a short count could be returned when writing to a compressed attribute and
* the requested count exceeded the size of an NTFS "compression block".
* Therefore, we must continue calling ntfs_attr_pwrite() until all bytes have
* been written or a real error has occurred.
*/
static bool
ntfs_3g_full_pwrite(ntfs_attr *na, u64 offset, size_t size, const u8 *data)
{
while (size) {
s64 res = ntfs_attr_pwrite(na, offset, size, data);
if (unlikely(res <= 0))
return false;
wimlib_assert(res <= size);
offset += res;
size -= res;
data += res;
}
return true;
}
static int
ntfs_3g_extract_chunk(const struct blob_descriptor *blob, u64 offset,
const void *chunk, size_t size, void *_ctx)
{
struct ntfs_3g_apply_ctx *ctx = _ctx;
const void * const end = chunk + size;
const void *p;
bool zeroes;
size_t len;
unsigned i;
/*
* For sparse attributes, only write nonzero regions. This lets the
* filesystem use holes to represent zero regions.
*/
for (p = chunk; p != end; p += len, offset += len) {
zeroes = maybe_detect_sparse_region(p, end - p, &len,
ctx->any_sparse_attrs);
for (i = 0; i < ctx->num_open_attrs; i++) {
if (!zeroes || !ctx->is_sparse_attr[i]) {
if (!ntfs_3g_full_pwrite(ctx->open_attrs[i],
offset, len, p))
goto err;
}
}
}
if (ctx->reparse_ptr)
ctx->reparse_ptr = mempcpy(ctx->reparse_ptr, chunk, size);
return 0;
err:
ERROR_WITH_ERRNO("Error writing data to NTFS volume");
return WIMLIB_ERR_NTFS_3G;
}
static int
ntfs_3g_end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx)
{
struct ntfs_3g_apply_ctx *ctx = _ctx;
int ret;
if (status) {
ret = status;
goto out;
}
/* Extend sparse attributes to their final size. */
if (ctx->any_sparse_attrs) {
for (unsigned i = 0; i < ctx->num_open_attrs; i++) {
if (!ctx->is_sparse_attr[i])
continue;
if (ntfs_attr_truncate(ctx->open_attrs[i], blob->size))
{
ERROR_WITH_ERRNO("Error extending attribute to "
"final size");
ret = WIMLIB_ERR_WRITE;
goto out;
}
}
}
for (u32 i = 0; i < ctx->num_reparse_inodes; i++) {
ret = ntfs_3g_restore_reparse_point(ctx->ntfs_reparse_inodes[i],
ctx->wim_reparse_inodes[i],
blob->size, ctx);
if (ret)
goto out;
}
ret = 0;
out:
if (ntfs_3g_cleanup_blob_extract(ctx) && !ret) {
ERROR_WITH_ERRNO("Error writing data to NTFS volume");
ret = WIMLIB_ERR_NTFS_3G;
}
return ret;
}
static u64
ntfs_3g_count_dentries(const struct list_head *dentry_list)
{
const struct wim_dentry *dentry;
u64 count = 0;
list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
count++;
if ((dentry->d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) &&
dentry_has_short_name(dentry))
{
count++;
}
}
return count;
}
static int
ntfs_3g_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
{
struct ntfs_3g_apply_ctx *ctx = (struct ntfs_3g_apply_ctx *)_ctx;
ntfs_volume *vol;
struct wim_dentry *root;
int ret;
/* For NTFS-3G extraction mode we require that the dentries to extract
* form a single tree. */
root = list_first_entry(dentry_list, struct wim_dentry,
d_extraction_list_node);
/* Mount the NTFS volume. */
vol = ntfs_mount(ctx->common.target, 0);
if (!vol) {
ERROR_WITH_ERRNO("Failed to mount \"%s\" with NTFS-3G",
ctx->common.target);
return WIMLIB_ERR_NTFS_3G;
}
ctx->vol = vol;
/* Opening $Secure is required to set security descriptors in NTFS v3.0
* format, where security descriptors are stored in a per-volume index
* rather than being fully specified for each file. */
if (ntfs_open_secure(vol) && vol->major_ver >= 3) {
ERROR_WITH_ERRNO("Unable to open security descriptor index of "
"NTFS volume \"%s\"", ctx->common.target);
ret = WIMLIB_ERR_NTFS_3G;
goto out_unmount;
}
/* Create all inodes and aliases, including short names, and set
* metadata (attributes, security descriptors, and timestamps). */
ret = start_file_structure_phase(&ctx->common,
ntfs_3g_count_dentries(dentry_list));
if (ret)
goto out_unmount;
ret = ntfs_3g_create_directories(root, dentry_list, ctx);
if (ret)
goto out_unmount;
ret = ntfs_3g_create_nondirectories(dentry_list, ctx);
if (ret)
goto out_unmount;
ret = end_file_structure_phase(&ctx->common);
if (ret)
goto out_unmount;
/* Extract blobs. */
struct read_blob_callbacks cbs = {
.begin_blob = ntfs_3g_begin_extract_blob,
.continue_blob = ntfs_3g_extract_chunk,
.end_blob = ntfs_3g_end_extract_blob,
.ctx = ctx,
};
ret = extract_blob_list(&ctx->common, &cbs);
/* We do not need a final pass to set timestamps because libntfs-3g does
* not update timestamps automatically (exception:
* ntfs_set_ntfs_dos_name() does, but we handle this elsewhere). */
out_unmount:
if (vol->secure_ni) {
ntfs_index_ctx_put(vol->secure_xsii);
ntfs_index_ctx_put(vol->secure_xsdh);
if (ntfs_inode_close(vol->secure_ni) && !ret) {
ERROR_WITH_ERRNO("Failed to close security descriptor "
"index of NTFS volume \"%s\"",
ctx->common.target);
ret = WIMLIB_ERR_NTFS_3G;
}
vol->secure_ni = NULL;
}
if (ntfs_umount(ctx->vol, FALSE) && !ret) {
ERROR_WITH_ERRNO("Failed to unmount \"%s\" with NTFS-3G",
ctx->common.target);
ret = WIMLIB_ERR_NTFS_3G;
}
return ret;
}
const struct apply_operations ntfs_3g_apply_ops = {
.name = "NTFS-3G",
.get_supported_features = ntfs_3g_get_supported_features,
.extract = ntfs_3g_extract,
.context_size = sizeof(struct ntfs_3g_apply_ctx),
.single_tree_only = true,
};
wimlib-1.14.5/src/ntfs-3g_capture.c 0000644 0001750 0001750 00000060336 15137020663 014331 0 ustar 00e e /*
* ntfs-3g_capture.c
*
* Capture a WIM image directly from an NTFS volume using libntfs-3g. We capture
* everything we can, including security data and alternate data streams.
*/
/*
* Copyright (C) 2012-2017 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef WITH_NTFS_3G
#include
#include
#include /* for ENODATA, if needed */
#include
#include
#include
#include
#include "wimlib/alloca.h"
#include "wimlib/assert.h"
#include "wimlib/blob_table.h"
#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/ntfs_3g.h"
#include "wimlib/object_id.h"
#include "wimlib/paths.h"
#include "wimlib/reparse.h"
#include "wimlib/scan.h"
#include "wimlib/security.h"
/* NTFS-3G 2013 renamed MS_RDONLY to NTFS_MNT_RDONLY. We can't check for the
* existence of NTFS_MNT_RDONLY at compilation time because it's an enum. We
* also can't check for MS_RDONLY being missing because it's also a system
* constant. So check if the NTFS-3G specific MS_IGNORE_HIBERFILE is defined;
* if yes, then we need to use the old MS_RDONLY. */
#ifdef MS_IGNORE_HIBERFILE
# define NTFS_MNT_RDONLY MS_RDONLY
#endif
/* A reference-counted NTFS volume than is automatically unmounted when the
* reference count reaches 0 */
struct ntfs_volume_wrapper {
ntfs_volume *vol;
size_t refcnt;
bool dedup_warned;
};
/* Description of where data is located in an NTFS volume */
struct ntfs_location {
struct ntfs_volume_wrapper *volume;
u64 mft_no;
ATTR_TYPES attr_type;
u32 attr_name_nchars;
ntfschar *attr_name;
u64 sort_key;
};
static struct ntfs_volume_wrapper *
get_ntfs_volume(struct ntfs_volume_wrapper *volume)
{
volume->refcnt++;
return volume;
}
static void
put_ntfs_volume(struct ntfs_volume_wrapper *volume)
{
if (--volume->refcnt == 0) {
ntfs_umount(volume->vol, FALSE);
FREE(volume);
}
}
static inline const ntfschar *
attr_record_name(const ATTR_RECORD *record)
{
return (const ntfschar *)
((const u8 *)record + le16_to_cpu(record->name_offset));
}
static ntfs_attr *
open_ntfs_attr(ntfs_inode *ni, const struct ntfs_location *loc)
{
ntfs_attr *na;
na = ntfs_attr_open(ni, loc->attr_type, loc->attr_name,
loc->attr_name_nchars);
if (!na) {
ERROR_WITH_ERRNO("Failed to open attribute of NTFS inode %"PRIu64,
loc->mft_no);
}
return na;
}
int
read_ntfs_attribute_prefix(const struct blob_descriptor *blob, u64 size,
const struct consume_chunk_callback *cb,
bool recover_data)
{
const struct ntfs_location *loc = blob->ntfs_loc;
ntfs_volume *vol = loc->volume->vol;
ntfs_inode *ni;
ntfs_attr *na;
s64 pos;
s64 bytes_remaining;
int ret;
u8 buf[BUFFER_SIZE];
ni = ntfs_inode_open(vol, loc->mft_no);
if (!ni) {
ERROR_WITH_ERRNO("Failed to open NTFS inode %"PRIu64,
loc->mft_no);
ret = WIMLIB_ERR_NTFS_3G;
goto out;
}
na = open_ntfs_attr(ni, loc);
if (!na) {
ret = WIMLIB_ERR_NTFS_3G;
goto out_close_ntfs_inode;
}
pos = (loc->attr_type == AT_REPARSE_POINT) ? REPARSE_DATA_OFFSET : 0;
bytes_remaining = size;
while (bytes_remaining) {
s64 to_read = min(bytes_remaining, sizeof(buf));
if (ntfs_attr_pread(na, pos, to_read, buf) != to_read) {
ERROR_WITH_ERRNO("Error reading data from NTFS inode "
"%"PRIu64, loc->mft_no);
ret = WIMLIB_ERR_NTFS_3G;
goto out_close_ntfs_attr;
}
pos += to_read;
bytes_remaining -= to_read;
ret = consume_chunk(cb, buf, to_read);
if (ret)
goto out_close_ntfs_attr;
}
ret = 0;
out_close_ntfs_attr:
ntfs_attr_close(na);
out_close_ntfs_inode:
ntfs_inode_close(ni);
out:
return ret;
}
void
free_ntfs_location(struct ntfs_location *loc)
{
put_ntfs_volume(loc->volume);
if (loc->attr_name != AT_UNNAMED)
FREE(loc->attr_name);
FREE(loc);
}
struct ntfs_location *
clone_ntfs_location(const struct ntfs_location *loc)
{
struct ntfs_location *new = memdup(loc, sizeof(*loc));
if (!new)
goto err0;
if (loc->attr_name != AT_UNNAMED) {
new->attr_name = utf16le_dup(loc->attr_name);
if (!new->attr_name)
goto err1;
}
new->volume = get_ntfs_volume(loc->volume);
return new;
err1:
FREE(new);
err0:
return NULL;
}
int
cmp_ntfs_locations(const struct ntfs_location *loc1,
const struct ntfs_location *loc2)
{
return cmp_u64(loc1->sort_key, loc2->sort_key);
}
/* Read rptag and rpreserved from the NTFS inode and save them in the WIM inode.
*/
static int
read_reparse_header(ntfs_inode *ni, struct wim_inode *inode)
{
struct {
le32 rptag;
le16 rpdatalen;
le16 rpreserved;
} hdr;
s64 res;
ntfs_attr *na;
na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0);
if (!na)
return WIMLIB_ERR_NTFS_3G;
res = ntfs_attr_pread(na, 0, sizeof(hdr), &hdr);
ntfs_attr_close(na);
if (res != sizeof(hdr))
return WIMLIB_ERR_NTFS_3G;
inode->i_reparse_tag = le32_to_cpu(hdr.rptag);
inode->i_rp_reserved = le16_to_cpu(hdr.rpreserved);
return 0;
}
static void
warn_special_reparse_points(const struct wim_inode *inode,
const struct scan_params *params,
struct ntfs_volume_wrapper *volume)
{
if (inode->i_reparse_tag == WIM_IO_REPARSE_TAG_DEDUP &&
(params->add_flags & WIMLIB_ADD_FLAG_WINCONFIG) &&
!volume->dedup_warned)
{
WARNING(
"Filesystem includes files deduplicated with Windows'\n"
" Data Deduplication feature, which to properly restore\n"
" would require that the chunk store in \"System Volume Information\"\n"
" be included in the WIM image. By default \"System Volume Information\"\n"
" is excluded, so you may want to use a custom capture configuration\n"
" file which includes it.");
volume->dedup_warned = true;
}
}
static int
attr_type_to_wimlib_stream_type(ATTR_TYPES type)
{
switch (type) {
case AT_DATA:
return STREAM_TYPE_DATA;
case AT_REPARSE_POINT:
return STREAM_TYPE_REPARSE_POINT;
default:
wimlib_assert(0);
return STREAM_TYPE_UNKNOWN;
}
}
/* When sorting blobs located in NTFS volumes for sequential reading, we sort
* first by starting LCN of the attribute if available, otherwise no sort order
* is defined. This usually results in better sequential access to the volume.
*/
static int
set_attr_sort_key(ntfs_inode *ni, struct ntfs_location *loc)
{
ntfs_attr *na;
runlist_element *rl;
na = open_ntfs_attr(ni, loc);
if (!na)
return WIMLIB_ERR_NTFS_3G;
rl = ntfs_attr_find_vcn(na, 0);
if (rl && rl->lcn != LCN_HOLE)
loc->sort_key = rl->lcn;
else
loc->sort_key = 0;
ntfs_attr_close(na);
return 0;
}
/*
* Add a new stream to the specified inode, with duplicate checking.
*
* This works around a problem where NTFS-3G can list multiple unnamed data
* streams for a single file. In this case we can only keep one. We'll prefer
* one that is nonempty.
*/
static int
add_stream(struct wim_inode *inode, const char *path, int stream_type,
const utf16lechar *stream_name, struct blob_descriptor **blob_p,
struct list_head *unhashed_blobs)
{
struct blob_descriptor *blob = *blob_p;
struct wim_inode_stream *strm;
strm = inode_get_stream(inode, stream_type, stream_name);
if (unlikely(strm)) {
/* Stream already existed. */
if (!blob)
return 0;
if (stream_blob_resolved(strm)) {
WARNING("\"%s\" has multiple nonempty streams "
"with the same type and name! Only the first "
"will be saved.", path);
return 0;
}
inode_replace_stream_blob(inode, strm, blob, NULL);
} else {
strm = inode_add_stream(inode, stream_type, stream_name, blob);
if (unlikely(!strm))
return WIMLIB_ERR_NOMEM;
}
prepare_unhashed_blob(blob, inode, strm->stream_id, unhashed_blobs);
*blob_p = NULL;
return 0;
}
/* Save information about an NTFS attribute (stream) to a WIM inode. */
static int
scan_ntfs_attr(struct wim_inode *inode,
ntfs_inode *ni,
const char *path,
struct list_head *unhashed_blobs,
struct ntfs_volume_wrapper *volume,
ATTR_TYPES type,
const ATTR_RECORD *record)
{
u64 data_size = ntfs_get_attribute_value_length(record);
const u32 name_nchars = record->name_length;
struct blob_descriptor *blob = NULL;
utf16lechar *stream_name = (utf16lechar *)NO_STREAM_NAME;
int ret;
if (unlikely(name_nchars)) {
/* Named stream */
stream_name = utf16le_dupz(attr_record_name(record),
name_nchars * sizeof(ntfschar));
if (!stream_name) {
ret = WIMLIB_ERR_NOMEM;
goto out_cleanup;
}
}
if (unlikely(type == AT_REPARSE_POINT)) {
if (data_size < REPARSE_DATA_OFFSET) {
ERROR("Reparse point attribute of \"%s\" "
"is too short!", path);
ret = WIMLIB_ERR_INVALID_REPARSE_DATA;
goto out_cleanup;
}
data_size -= REPARSE_DATA_OFFSET;
ret = read_reparse_header(ni, inode);
if (ret) {
ERROR_WITH_ERRNO("Error reading reparse point header "
"of \"%s\"", path);
goto out_cleanup;
}
}
/* If the stream is non-empty, set up a blob descriptor for it. */
if (data_size != 0) {
blob = new_blob_descriptor();
if (unlikely(!blob)) {
ret = WIMLIB_ERR_NOMEM;
goto out_cleanup;
}
blob->ntfs_loc = MALLOC(sizeof(struct ntfs_location));
if (unlikely(!blob->ntfs_loc)) {
ret = WIMLIB_ERR_NOMEM;
goto out_cleanup;
}
blob->blob_location = BLOB_IN_NTFS_VOLUME;
blob->size = data_size;
blob->ntfs_loc->volume = get_ntfs_volume(volume);
blob->ntfs_loc->mft_no = ni->mft_no;
blob->ntfs_loc->attr_type = type;
if (unlikely(name_nchars)) {
blob->ntfs_loc->attr_name_nchars = name_nchars;
blob->ntfs_loc->attr_name = utf16le_dup(stream_name);
if (!blob->ntfs_loc->attr_name) {
ret = WIMLIB_ERR_NOMEM;
goto out_cleanup;
}
} else {
blob->ntfs_loc->attr_name_nchars = 0;
blob->ntfs_loc->attr_name = AT_UNNAMED;
}
ret = set_attr_sort_key(ni, blob->ntfs_loc);
if (ret)
goto out_cleanup;
}
ret = add_stream(inode, path, attr_type_to_wimlib_stream_type(type),
stream_name, &blob, unhashed_blobs);
out_cleanup:
free_blob_descriptor(blob);
if (stream_name != NO_STREAM_NAME)
FREE(stream_name);
return ret;
}
/* Scan attributes of the specified type from a file in the NTFS volume */
static int
scan_ntfs_attrs_with_type(struct wim_inode *inode,
ntfs_inode *ni,
const char *path,
struct list_head *unhashed_blobs,
struct ntfs_volume_wrapper *volume,
ATTR_TYPES type)
{
ntfs_attr_search_ctx *actx;
int ret;
actx = ntfs_attr_get_search_ctx(ni, NULL);
if (!actx) {
ERROR_WITH_ERRNO("Failed to get NTFS attribute search "
"context for \"%s\"", path);
return WIMLIB_ERR_NTFS_3G;
}
while (!ntfs_attr_lookup(type, NULL, 0,
CASE_SENSITIVE, 0, NULL, 0, actx))
{
ret = scan_ntfs_attr(inode,
ni,
path,
unhashed_blobs,
volume,
type,
actx->attr);
if (ret)
goto out_put_actx;
}
if (errno != ENOENT) {
ERROR_WITH_ERRNO("Error listing NTFS attributes of \"%s\"", path);
ret = WIMLIB_ERR_NTFS_3G;
goto out_put_actx;
}
ret = 0;
out_put_actx:
ntfs_attr_put_search_ctx(actx);
return ret;
}
static noinline_for_stack int
load_object_id(ntfs_inode *ni, struct wim_inode *inode)
{
OBJECT_ID_ATTR attr;
int len;
len = ntfs_get_ntfs_object_id(ni, (char *)&attr, sizeof(attr));
if (likely(len == -ENODATA || len == 0))
return 0;
if (len < 0)
return WIMLIB_ERR_NTFS_3G;
if (!inode_set_object_id(inode, &attr, len))
return WIMLIB_ERR_NOMEM;
return 0;
}
/* Load the security descriptor of an NTFS inode into the corresponding WIM
* inode and the WIM image's security descriptor set. */
static noinline_for_stack int
get_security_descriptor(ntfs_inode *ni, struct wim_inode *inode,
ntfs_volume *vol, struct wim_sd_set *sd_set)
{
struct SECURITY_CONTEXT scx = {.vol = vol};
char _buf[4096];
char *buf = _buf;
size_t avail_size = sizeof(_buf);
int ret;
retry:
ret = ntfs_get_ntfs_acl(&scx, ni, buf, avail_size);
if (unlikely(ret < 0)) {
ret = WIMLIB_ERR_NTFS_3G;
goto out;
}
if (unlikely(ret > avail_size)) {
if (unlikely(buf != _buf))
FREE(buf);
buf = MALLOC(ret);
if (!buf) {
ret = WIMLIB_ERR_NOMEM;
goto out;
}
avail_size = ret;
goto retry;
}
if (likely(ret > 0)) {
inode->i_security_id = sd_set_add_sd(sd_set, buf, ret);
if (unlikely(inode->i_security_id < 0)) {
ret = WIMLIB_ERR_NOMEM;
goto out;
}
}
ret = 0;
out:
if (unlikely(buf != _buf))
FREE(buf);
return ret;
}
/* Binary tree that maps NTFS inode numbers to DOS names */
struct dos_name_map {
struct avl_tree_node *root;
};
struct dos_name_node {
struct avl_tree_node index_node;
char dos_name[24];
int name_nbytes;
u64 ntfs_ino;
};
#define DOS_NAME_NODE(avl_node) \
avl_tree_entry(avl_node, struct dos_name_node, index_node)
static int
_avl_cmp_by_ntfs_ino(const struct avl_tree_node *n1,
const struct avl_tree_node *n2)
{
return cmp_u64(DOS_NAME_NODE(n1)->ntfs_ino,
DOS_NAME_NODE(n2)->ntfs_ino);
}
/* Inserts a new DOS name into the map */
static int
insert_dos_name(struct dos_name_map *map, const ntfschar *dos_name,
size_t name_nbytes, u64 ntfs_ino)
{
struct dos_name_node *new_node;
new_node = MALLOC(sizeof(struct dos_name_node));
if (!new_node)
return WIMLIB_ERR_NOMEM;
/* DOS names are supposed to be 12 characters max (that's 24 bytes,
* assuming 2-byte ntfs characters) */
wimlib_assert(name_nbytes <= sizeof(new_node->dos_name));
/* Initialize the DOS name, DOS name length, and NTFS inode number of
* the search tree node */
memcpy(new_node->dos_name, dos_name, name_nbytes);
new_node->name_nbytes = name_nbytes;
new_node->ntfs_ino = ntfs_ino;
/* Insert the search tree node */
if (avl_tree_insert(&map->root, &new_node->index_node,
_avl_cmp_by_ntfs_ino))
{
/* This should be impossible since an NTFS inode cannot have
* multiple DOS names, and we only should get each DOS name
* entry once from the ntfs_readdir() calls. */
WARNING("NTFS inode %"PRIu64" has multiple DOS names", ntfs_ino);
FREE(new_node);
}
return 0;
}
/* Returns a structure that contains the DOS name and its length for an NTFS
* inode, or NULL if the inode has no DOS name. */
static struct dos_name_node *
lookup_dos_name(const struct dos_name_map *map, u64 ntfs_ino)
{
struct dos_name_node dummy;
struct avl_tree_node *res;
dummy.ntfs_ino = ntfs_ino;
res = avl_tree_lookup_node(map->root, &dummy.index_node,
_avl_cmp_by_ntfs_ino);
if (!res)
return NULL;
return DOS_NAME_NODE(res);
}
static int
set_dentry_dos_name(struct wim_dentry *dentry, const struct dos_name_map *map)
{
const struct dos_name_node *node;
if (dentry->d_is_win32_name) {
node = lookup_dos_name(map, dentry->d_inode->i_ino);
if (node) {
dentry->d_short_name = utf16le_dupz(node->dos_name,
node->name_nbytes);
if (!dentry->d_short_name)
return WIMLIB_ERR_NOMEM;
dentry->d_short_name_nbytes = node->name_nbytes;
} else {
WARNING("NTFS inode %"PRIu64" has Win32 name with no "
"corresponding DOS name",
dentry->d_inode->i_ino);
}
}
return 0;
}
static void
destroy_dos_name_map(struct dos_name_map *map)
{
struct dos_name_node *node;
avl_tree_for_each_in_postorder(node, map->root,
struct dos_name_node, index_node)
FREE(node);
}
struct readdir_ctx {
struct wim_dentry *parent;
struct dos_name_map dos_name_map;
struct ntfs_volume_wrapper *volume;
struct scan_params *params;
int ret;
};
static int
ntfs_3g_build_dentry_tree_recursive(struct wim_dentry **root_p,
const MFT_REF mref,
const char *filename,
int name_type,
struct ntfs_volume_wrapper *volume,
struct scan_params *params);
static int
filldir(void *_ctx, const ntfschar *name, const int name_nchars,
const int name_type, const s64 pos, const MFT_REF mref,
const unsigned dt_type)
{
struct readdir_ctx *ctx = _ctx;
struct scan_params *params = ctx->params;
const size_t name_nbytes = name_nchars * sizeof(ntfschar);
char *mbs_name;
size_t mbs_name_nbytes;
size_t orig_path_nchars;
struct wim_dentry *child;
int ret;
if (name_type & FILE_NAME_DOS) {
/* If this is the entry for a DOS name, store it for later. */
ret = insert_dos_name(&ctx->dos_name_map, name,
name_nbytes, MREF(mref));
/* Return now if an error occurred or if this is just a DOS name
* and not a Win32+DOS name. */
if (ret != 0 || name_type == FILE_NAME_DOS)
goto out;
}
ret = utf16le_to_tstr(name, name_nbytes, &mbs_name, &mbs_name_nbytes);
if (ret)
goto out;
if (should_ignore_filename(mbs_name, mbs_name_nbytes))
goto out_free_mbs_name;
ret = WIMLIB_ERR_NOMEM;
if (!pathbuf_append_name(params, mbs_name, mbs_name_nbytes,
&orig_path_nchars))
goto out_free_mbs_name;
child = NULL;
ret = ntfs_3g_build_dentry_tree_recursive(&child, mref, mbs_name,
name_type, ctx->volume,
params);
pathbuf_truncate(params, orig_path_nchars);
attach_scanned_tree(ctx->parent, child, params->blob_table);
out_free_mbs_name:
FREE(mbs_name);
out:
ctx->ret = ret;
return ret;
}
static int
ntfs_3g_recurse_directory(ntfs_inode *ni, struct wim_dentry *parent,
struct ntfs_volume_wrapper *volume,
struct scan_params *params)
{
int ret;
s64 pos = 0;
struct readdir_ctx ctx = {
.parent = parent,
.dos_name_map = { .root = NULL },
.volume = volume,
.params = params,
.ret = 0,
};
ret = ntfs_readdir(ni, &pos, &ctx, filldir);
if (unlikely(ret)) {
if (ctx.ret) {
/* wimlib error */
ret = ctx.ret;
} else {
/* error from ntfs_readdir() itself */
ERROR_WITH_ERRNO("Error reading directory \"%s\"",
params->cur_path);
ret = WIMLIB_ERR_NTFS_3G;
}
} else {
struct wim_dentry *child;
ret = 0;
for_dentry_child(child, parent) {
ret = set_dentry_dos_name(child, &ctx.dos_name_map);
if (ret)
break;
}
}
destroy_dos_name_map(&ctx.dos_name_map);
return ret;
}
static int
ntfs_3g_build_dentry_tree_recursive(struct wim_dentry **root_ret,
const MFT_REF mref,
const char *filename,
int name_type,
struct ntfs_volume_wrapper *volume,
struct scan_params *params)
{
const char *path = params->cur_path;
u32 attributes;
int ret;
struct wim_dentry *root = NULL;
struct wim_inode *inode = NULL;
ntfs_inode *ni = NULL;
ret = try_exclude(params);
if (unlikely(ret < 0)) /* Excluded? */
goto out_progress;
if (unlikely(ret > 0)) /* Error? */
goto out;
ni = ntfs_inode_open(volume->vol, mref);
if (!ni) {
ERROR_WITH_ERRNO("Failed to open NTFS file \"%s\"", path);
ret = WIMLIB_ERR_NTFS_3G;
goto out;
}
/* Get file attributes */
ret = ntfs_get_ntfs_attrib(ni, (char*)&attributes, sizeof(attributes));
if (ret != sizeof(attributes)) {
ERROR_WITH_ERRNO("Failed to get NTFS attributes from \"%s\"", path);
ret = WIMLIB_ERR_NTFS_3G;
goto out;
}
if (unlikely(attributes & FILE_ATTRIBUTE_ENCRYPTED)) {
if (params->add_flags & WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE)
{
ERROR("Can't archive \"%s\" because NTFS-3G capture mode "
"does not support encrypted files and directories", path);
ret = WIMLIB_ERR_UNSUPPORTED_FILE;
goto out;
}
ret = do_scan_progress(params, WIMLIB_SCAN_DENTRY_UNSUPPORTED, NULL);
goto out;
}
/* Create a WIM dentry with an associated inode, which may be shared */
ret = inode_table_new_dentry(params->inode_table, filename,
ni->mft_no, 0, false, &root);
if (ret)
goto out;
if (name_type & FILE_NAME_WIN32) /* Win32 or Win32+DOS name (rather than POSIX) */
root->d_is_win32_name = 1;
inode = root->d_inode;
if (inode->i_nlink > 1) {
/* Shared inode; nothing more to do */
goto out_progress;
}
inode->i_creation_time = le64_to_cpu(ni->creation_time);
inode->i_last_write_time = le64_to_cpu(ni->last_data_change_time);
inode->i_last_access_time = le64_to_cpu(ni->last_access_time);
inode->i_attributes = attributes;
if (attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
/* Scan the reparse point stream. */
ret = scan_ntfs_attrs_with_type(inode, ni, path,
params->unhashed_blobs,
volume, AT_REPARSE_POINT);
if (ret)
goto out;
warn_special_reparse_points(inode, params, volume);
/*
* In NTFS-3G capture mode, the Windows drive letter of the
* volume is unknown, so there's no way to know whether absolute
* symlinks point into the same volume or not. Therefore, never
* do reparse point fixups in this mode. I.e., neither modify
* the reparse data nor clear WIM_RP_FLAG_NOT_FIXED.
*
* wimlib v1.14.4 and earlier did clear WIM_RP_FLAG_NOT_FIXED in
* this case, despite not modifying the reparse data. It mostly
* worked, since NTFS-3G capture mode only allows capturing an
* entire volume anyway. However, it caused issues where DISM
* would sometimes misunderstand the symlinks or consider them
* to be invalid when trying to apply the reverse fixup.
*/
}
/* Load the object ID. */
ret = load_object_id(ni, inode);
if (ret) {
ERROR_WITH_ERRNO("Error reading object ID of \"%s\"", path);
goto out;
}
/* Scan the data streams.
*
* Note: directories should not have an unnamed data stream, but they
* may have named data streams. Nondirectories (including reparse
* points) can have an unnamed data stream as well as named data
* streams. */
ret = scan_ntfs_attrs_with_type(inode, ni, path, params->unhashed_blobs,
volume, AT_DATA);
if (ret)
goto out;
if (!(params->add_flags & WIMLIB_ADD_FLAG_NO_ACLS)) {
ret = get_security_descriptor(ni, inode, volume->vol,
params->sd_set);
if (ret) {
ERROR_WITH_ERRNO("Error reading security descriptor "
"of \"%s\"", path);
goto out;
}
}
if (inode_is_directory(inode)) {
ret = ntfs_3g_recurse_directory(ni, root, volume, params);
if (ret)
goto out;
}
out_progress:
if (root == NULL)
ret = do_scan_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL);
else
ret = do_scan_progress(params, WIMLIB_SCAN_DENTRY_OK, inode);
out:
if (ni)
ntfs_inode_close(ni);
if (unlikely(ret)) {
free_dentry_tree(root, params->blob_table);
root = NULL;
ret = report_scan_error(params, ret);
}
*root_ret = root;
return ret;
}
int
ntfs_3g_build_dentry_tree(struct wim_dentry **root_ret,
const char *device, struct scan_params *params)
{
struct ntfs_volume_wrapper *volume;
ntfs_volume *vol;
int ret;
volume = CALLOC(1, sizeof(struct ntfs_volume_wrapper));
if (!volume)
return WIMLIB_ERR_NOMEM;
vol = ntfs_mount(device, NTFS_MNT_RDONLY);
if (!vol) {
ERROR_WITH_ERRNO("Failed to mount NTFS volume \"%s\" read-only",
device);
FREE(volume);
return WIMLIB_ERR_NTFS_3G;
}
volume->vol = vol;
volume->refcnt = 1;
/* Currently, libntfs-3g users that need to read security descriptors
* are required to call ntfs_open_secure() to open the volume's security
* descriptor index, "$Secure". This is only required to work on NTFS
* v3.0+, as older versions did not have a security descriptor index. */
if (ntfs_open_secure(vol) && vol->major_ver >= 3) {
ERROR_WITH_ERRNO("Unable to open security descriptor index of "
"NTFS volume \"%s\"", device);
ret = WIMLIB_ERR_NTFS_3G;
goto out_put_ntfs_volume;
}
/* We don't want to capture the special NTFS files such as $Bitmap. Not
* to be confused with "hidden" or "system" files which are real files
* that we do need to capture. */
NVolClearShowSysFiles(vol);
ret = pathbuf_init(params, "/");
if (ret)
goto out_close_secure;
ret = ntfs_3g_build_dentry_tree_recursive(root_ret, FILE_root, "",
FILE_NAME_POSIX, volume,
params);
out_close_secure:
/* Undo the effects of ntfs_open_secure(). This is not yet done
* automatically by ntfs_umount(). But NULL out the inode to
* potentially be robust against future versions doing so. */
if (vol->secure_ni) {
ntfs_index_ctx_put(vol->secure_xsii);
ntfs_index_ctx_put(vol->secure_xsdh);
ntfs_inode_close(vol->secure_ni);
vol->secure_ni = NULL;
}
out_put_ntfs_volume:
put_ntfs_volume(volume);
return ret;
}
#endif /* WITH_NTFS_3G */
wimlib-1.14.5/src/lzx_compress.c 0000644 0001750 0001750 00000305430 15137020663 014052 0 ustar 00e e /*
* lzx_compress.c
*
* A compressor for the LZX compression format, as used in WIM archives.
*/
/*
* Copyright (C) 2012-2017 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
/*
* This file contains a compressor for the LZX ("Lempel-Ziv eXtended")
* compression format, as used in the WIM (Windows IMaging) file format.
*
* Two different LZX-compatible algorithms are implemented: "near-optimal" and
* "lazy". "Near-optimal" is significantly slower than "lazy", but results in a
* better compression ratio. The "near-optimal" algorithm is used at the
* default compression level.
*
* This file may need some slight modifications to be used outside of the WIM
* format. In particular, in other situations the LZX block header might be
* slightly different, and sliding window support might be required.
*
* LZX is a compression format derived from DEFLATE, the format used by zlib and
* gzip. Both LZX and DEFLATE use LZ77 matching and Huffman coding. Certain
* details are quite similar, such as the method for storing Huffman codes.
* However, the main differences are:
*
* - LZX preprocesses the data to attempt to make x86 machine code slightly more
* compressible before attempting to compress it further.
*
* - LZX uses a "main" alphabet which combines literals and matches, with the
* match symbols containing a "length header" (giving all or part of the match
* length) and an "offset slot" (giving, roughly speaking, the order of
* magnitude of the match offset).
*
* - LZX does not have static Huffman blocks (that is, the kind with preset
* Huffman codes); however it does have two types of dynamic Huffman blocks
* ("verbatim" and "aligned").
*
* - LZX has a minimum match length of 2 rather than 3. Length 2 matches can be
* useful, but generally only if the compressor is smart about choosing them.
*
* - In LZX, offset slots 0 through 2 actually represent entries in an LRU queue
* of match offsets. This is very useful for certain types of files, such as
* binary files that have repeating records.
*/
/******************************************************************************/
/* General parameters */
/*----------------------------------------------------------------------------*/
/*
* The compressor uses the faster algorithm at levels <= MAX_FAST_LEVEL. It
* uses the slower algorithm at levels > MAX_FAST_LEVEL.
*/
#define MAX_FAST_LEVEL 34
/*
* The compressor-side limits on the codeword lengths (in bits) for each Huffman
* code. To make outputting bits slightly faster, some of these limits are
* lower than the limits defined by the LZX format. This does not significantly
* affect the compression ratio.
*/
#define MAIN_CODEWORD_LIMIT 16
#define LENGTH_CODEWORD_LIMIT 12
#define ALIGNED_CODEWORD_LIMIT 7
#define PRE_CODEWORD_LIMIT 7
/******************************************************************************/
/* Block splitting parameters */
/*----------------------------------------------------------------------------*/
/*
* The compressor always outputs blocks of at least this size in bytes, except
* for the last block which may need to be smaller.
*/
#define MIN_BLOCK_SIZE 6500
/*
* The compressor attempts to end a block when it reaches this size in bytes.
* The final size might be slightly larger due to matches extending beyond the
* end of the block. Specifically:
*
* - The near-optimal compressor may choose a match of up to LZX_MAX_MATCH_LEN
* bytes starting at position 'SOFT_MAX_BLOCK_SIZE - 1'.
*
* - The lazy compressor may choose a sequence of literals starting at position
* 'SOFT_MAX_BLOCK_SIZE - 1' when it sees a sequence of increasingly better
* matches. The final match may be up to LZX_MAX_MATCH_LEN bytes. The
* length of the literal sequence is approximately limited by the "nice match
* length" parameter.
*/
#define SOFT_MAX_BLOCK_SIZE 100000
/*
* The number of observed items (matches and literals) that represents
* sufficient data for the compressor to decide whether the current block should
* be ended or not.
*/
#define NUM_OBSERVATIONS_PER_BLOCK_CHECK 400
/******************************************************************************/
/* Parameters for slower algorithm */
/*----------------------------------------------------------------------------*/
/*
* The log base 2 of the number of entries in the hash table for finding length
* 2 matches. This could be as high as 16, but using a smaller hash table
* speeds up compression due to reduced cache pressure.
*/
#define BT_MATCHFINDER_HASH2_ORDER 12
/*
* The number of lz_match structures in the match cache, excluding the extra
* "overflow" entries. This value should be high enough so that nearly the
* time, all matches found in a given block can fit in the match cache.
* However, fallback behavior (immediately terminating the block) on cache
* overflow is still required.
*/
#define CACHE_LENGTH (SOFT_MAX_BLOCK_SIZE * 5)
/*
* An upper bound on the number of matches that can ever be saved in the match
* cache for a single position. Since each match we save for a single position
* has a distinct length, we can use the number of possible match lengths in LZX
* as this bound. This bound is guaranteed to be valid in all cases, although
* if 'nice_match_length < LZX_MAX_MATCH_LEN', then it will never actually be
* reached.
*/
#define MAX_MATCHES_PER_POS LZX_NUM_LENS
/*
* A scaling factor that makes it possible to consider fractional bit costs. A
* single bit has a cost of BIT_COST.
*
* Note: this is only useful as a statistical trick for when the true costs are
* unknown. Ultimately, each token in LZX requires a whole number of bits to
* output.
*/
#define BIT_COST 64
/*
* Should the compressor take into account the costs of aligned offset symbols
* instead of assuming that all are equally likely?
*/
#define CONSIDER_ALIGNED_COSTS 1
/*
* Should the "minimum" cost path search algorithm consider "gap" matches, where
* a normal match is followed by a literal, then by a match with the same
* offset? This is one specific, somewhat common situation in which the true
* minimum cost path is often different from the path found by looking only one
* edge ahead.
*/
#define CONSIDER_GAP_MATCHES 1
/******************************************************************************/
/* Includes */
/*----------------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/compress_common.h"
#include "wimlib/compressor_ops.h"
#include "wimlib/error.h"
#include "wimlib/lzx_common.h"
#include "wimlib/unaligned.h"
#include "wimlib/util.h"
/* Note: BT_MATCHFINDER_HASH2_ORDER must be defined before including
* bt_matchfinder.h. */
/* Matchfinders with 16-bit positions */
#define mf_pos_t u16
#define MF_SUFFIX _16
#include "wimlib/bt_matchfinder.h"
#include "wimlib/hc_matchfinder.h"
/* Matchfinders with 32-bit positions */
#undef mf_pos_t
#undef MF_SUFFIX
#define mf_pos_t u32
#define MF_SUFFIX _32
#include "wimlib/bt_matchfinder.h"
#include "wimlib/hc_matchfinder.h"
/******************************************************************************/
/* Compressor structure */
/*----------------------------------------------------------------------------*/
/* Codewords for the Huffman codes */
struct lzx_codewords {
u32 main[LZX_MAINCODE_MAX_NUM_SYMBOLS];
u32 len[LZX_LENCODE_NUM_SYMBOLS];
u32 aligned[LZX_ALIGNEDCODE_NUM_SYMBOLS];
};
/*
* Codeword lengths, in bits, for the Huffman codes.
*
* A codeword length of 0 means the corresponding codeword has zero frequency.
*
* The main and length codes each have one extra entry for use as a sentinel.
* See lzx_write_compressed_code().
*/
struct lzx_lens {
u8 main[LZX_MAINCODE_MAX_NUM_SYMBOLS + 1];
u8 len[LZX_LENCODE_NUM_SYMBOLS + 1];
u8 aligned[LZX_ALIGNEDCODE_NUM_SYMBOLS];
};
/* Codewords and lengths for the Huffman codes */
struct lzx_codes {
struct lzx_codewords codewords;
struct lzx_lens lens;
};
/* Symbol frequency counters for the Huffman-encoded alphabets */
struct lzx_freqs {
u32 main[LZX_MAINCODE_MAX_NUM_SYMBOLS];
u32 len[LZX_LENCODE_NUM_SYMBOLS];
u32 aligned[LZX_ALIGNEDCODE_NUM_SYMBOLS];
};
/* Block split statistics. See the "Block splitting algorithm" section later in
* this file for details. */
#define NUM_LITERAL_OBSERVATION_TYPES 8
#define NUM_MATCH_OBSERVATION_TYPES 2
#define NUM_OBSERVATION_TYPES (NUM_LITERAL_OBSERVATION_TYPES + \
NUM_MATCH_OBSERVATION_TYPES)
struct lzx_block_split_stats {
u32 new_observations[NUM_OBSERVATION_TYPES];
u32 observations[NUM_OBSERVATION_TYPES];
u32 num_new_observations;
u32 num_observations;
};
/*
* Represents a run of literals followed by a match or end-of-block. This
* structure is needed to temporarily store items chosen by the compressor,
* since items cannot be written until all items for the block have been chosen
* and the block's Huffman codes have been computed.
*/
struct lzx_sequence {
/*
* Bits 9..31: the number of literals in this run. This may be 0 and
* can be at most about SOFT_MAX_BLOCK_LENGTH. The literals are not
* stored explicitly in this structure; instead, they are read directly
* from the uncompressed data.
*
* Bits 0..8: the length of the match which follows the literals, or 0
* if this literal run was the last in the block, so there is no match
* which follows it. This can be at most LZX_MAX_MATCH_LEN.
*/
u32 litrunlen_and_matchlen;
#define SEQ_MATCHLEN_BITS 9
#define SEQ_MATCHLEN_MASK (((u32)1 << SEQ_MATCHLEN_BITS) - 1)
/*
* If 'matchlen' doesn't indicate end-of-block, then this contains:
*
* Bits 10..31: either the offset plus LZX_OFFSET_ADJUSTMENT or a recent
* offset code, depending on the offset slot encoded in the main symbol.
*
* Bits 0..9: the main symbol.
*/
u32 adjusted_offset_and_mainsym;
#define SEQ_MAINSYM_BITS 10
#define SEQ_MAINSYM_MASK (((u32)1 << SEQ_MAINSYM_BITS) - 1)
} __attribute__((aligned(8)));
/*
* This structure represents a byte position in the input buffer and a node in
* the graph of possible match/literal choices.
*
* Logically, each incoming edge to this node is labeled with a literal or a
* match that can be taken to reach this position from an earlier position; and
* each outgoing edge from this node is labeled with a literal or a match that
* can be taken to advance from this position to a later position.
*/
struct lzx_optimum_node {
/* The cost, in bits, of the lowest-cost path that has been found to
* reach this position. This can change as progressively lower cost
* paths are found to reach this position. */
u32 cost;
/*
* The best arrival to this node, i.e. the match or literal that was
* used to arrive to this position at the given 'cost'. This can change
* as progressively lower cost paths are found to reach this position.
*
* For non-gap matches, this variable is divided into two bitfields
* whose meanings depend on the item type:
*
* Literals:
* Low bits are 0, high bits are the literal.
*
* Explicit offset matches:
* Low bits are the match length, high bits are the offset plus
* LZX_OFFSET_ADJUSTMENT.
*
* Repeat offset matches:
* Low bits are the match length, high bits are the queue index.
*
* For gap matches, identified by OPTIMUM_GAP_MATCH set, special
* behavior applies --- see the code.
*/
u32 item;
#define OPTIMUM_OFFSET_SHIFT SEQ_MATCHLEN_BITS
#define OPTIMUM_LEN_MASK SEQ_MATCHLEN_MASK
#if CONSIDER_GAP_MATCHES
# define OPTIMUM_GAP_MATCH 0x80000000
#endif
} __attribute__((aligned(8)));
/* The cost model for near-optimal parsing */
struct lzx_costs {
/*
* 'match_cost[offset_slot][len - LZX_MIN_MATCH_LEN]' is the cost of a
* length 'len' match which has an offset belonging to 'offset_slot'.
* The cost includes the main symbol, the length symbol if required, and
* the extra offset bits if any, excluding any entropy-coded bits
* (aligned offset bits). It does *not* include the cost of the aligned
* offset symbol which may be required.
*/
u16 match_cost[LZX_MAX_OFFSET_SLOTS][LZX_NUM_LENS];
/* Cost of each symbol in the main code */
u32 main[LZX_MAINCODE_MAX_NUM_SYMBOLS];
/* Cost of each symbol in the length code */
u32 len[LZX_LENCODE_NUM_SYMBOLS];
#if CONSIDER_ALIGNED_COSTS
/* Cost of each symbol in the aligned offset code */
u32 aligned[LZX_ALIGNEDCODE_NUM_SYMBOLS];
#endif
};
struct lzx_output_bitstream;
/* The main LZX compressor structure */
struct lzx_compressor {
/* The buffer for preprocessed input data, if not using destructive
* compression */
void *in_buffer;
/* If true, then the compressor need not preserve the input buffer if it
* compresses the data successfully */
bool destructive;
/* Pointer to the compress() implementation chosen at allocation time */
void (*impl)(struct lzx_compressor *, const u8 *, size_t,
struct lzx_output_bitstream *);
/* The log base 2 of the window size for match offset encoding purposes.
* This will be >= LZX_MIN_WINDOW_ORDER and <= LZX_MAX_WINDOW_ORDER. */
unsigned window_order;
/* The number of symbols in the main alphabet. This depends on the
* window order, since the window order determines the maximum possible
* match offset. */
unsigned num_main_syms;
/* The "nice" match length: if a match of this length is found, then it
* is chosen immediately without further consideration. */
unsigned nice_match_length;
/* The maximum search depth: at most this many potential matches are
* considered at each position. */
unsigned max_search_depth;
/* The number of optimization passes per block */
unsigned num_optim_passes;
/* The symbol frequency counters for the current block */
struct lzx_freqs freqs;
/* Block split statistics for the current block */
struct lzx_block_split_stats split_stats;
/* The Huffman codes for the current and previous blocks. The one with
* index 'codes_index' is for the current block, and the other one is
* for the previous block. */
struct lzx_codes codes[2];
unsigned codes_index;
/* The matches and literals that the compressor has chosen for the
* current block. The required length of this array is limited by the
* maximum number of matches that can ever be chosen for a single block,
* plus one for the special entry at the end. */
struct lzx_sequence chosen_sequences[
DIV_ROUND_UP(SOFT_MAX_BLOCK_SIZE, LZX_MIN_MATCH_LEN) + 1];
/* Tables for mapping adjusted offsets to offset slots */
u8 offset_slot_tab_1[32768]; /* offset slots [0, 29] */
u8 offset_slot_tab_2[128]; /* offset slots [30, 49] */
union {
/* Data for lzx_compress_lazy() */
struct {
/* Hash chains matchfinder (MUST BE LAST!!!) */
union {
struct hc_matchfinder_16 hc_mf_16;
struct hc_matchfinder_32 hc_mf_32;
};
};
/* Data for lzx_compress_near_optimal() */
struct {
/*
* Array of nodes, one per position, for running the
* minimum-cost path algorithm.
*
* This array must be large enough to accommodate the
* worst-case number of nodes, which occurs if the
* compressor finds a match of length LZX_MAX_MATCH_LEN
* at position 'SOFT_MAX_BLOCK_SIZE - 1', producing a
* block of size 'SOFT_MAX_BLOCK_SIZE - 1 +
* LZX_MAX_MATCH_LEN'. Add one for the end-of-block
* node.
*/
struct lzx_optimum_node optimum_nodes[
SOFT_MAX_BLOCK_SIZE - 1 +
LZX_MAX_MATCH_LEN + 1];
/* The cost model for the current optimization pass */
struct lzx_costs costs;
/*
* Cached matches for the current block. This array
* contains the matches that were found at each position
* in the block. Specifically, for each position, there
* is a special 'struct lz_match' whose 'length' field
* contains the number of matches that were found at
* that position; this is followed by the matches
* themselves, if any, sorted by strictly increasing
* length.
*
* Note: in rare cases, there will be a very high number
* of matches in the block and this array will overflow.
* If this happens, we force the end of the current
* block. CACHE_LENGTH is the length at which we
* actually check for overflow. The extra slots beyond
* this are enough to absorb the worst case overflow,
* which occurs if starting at &match_cache[CACHE_LENGTH
* - 1], we write the match count header, then write
* MAX_MATCHES_PER_POS matches, then skip searching for
* matches at 'LZX_MAX_MATCH_LEN - 1' positions and
* write the match count header for each.
*/
struct lz_match match_cache[CACHE_LENGTH +
MAX_MATCHES_PER_POS +
LZX_MAX_MATCH_LEN - 1];
/* Binary trees matchfinder (MUST BE LAST!!!) */
union {
struct bt_matchfinder_16 bt_mf_16;
struct bt_matchfinder_32 bt_mf_32;
};
};
};
};
/******************************************************************************/
/* Matchfinder utilities */
/*----------------------------------------------------------------------------*/
/*
* Will a matchfinder using 16-bit positions be sufficient for compressing
* buffers of up to the specified size? The limit could be 65536 bytes, but we
* also want to optimize out the use of offset_slot_tab_2 in the 16-bit case.
* This requires that the limit be no more than the length of offset_slot_tab_1
* (currently 32768).
*/
static forceinline bool
lzx_is_16_bit(size_t max_bufsize)
{
STATIC_ASSERT(ARRAY_LEN(((struct lzx_compressor *)0)->offset_slot_tab_1) == 32768);
return max_bufsize <= 32768;
}
/*
* Return the offset slot for the specified adjusted match offset.
*/
static forceinline unsigned
lzx_get_offset_slot(struct lzx_compressor *c, u32 adjusted_offset,
bool is_16_bit)
{
if (__builtin_constant_p(adjusted_offset) &&
adjusted_offset < LZX_NUM_RECENT_OFFSETS)
return adjusted_offset;
if (is_16_bit || adjusted_offset < ARRAY_LEN(c->offset_slot_tab_1))
return c->offset_slot_tab_1[adjusted_offset];
return c->offset_slot_tab_2[adjusted_offset >> 14];
}
/*
* For a match that has the specified length and adjusted offset, tally its main
* symbol, and if needed its length symbol; then return its main symbol.
*/
static forceinline unsigned
lzx_tally_main_and_lensyms(struct lzx_compressor *c, unsigned length,
u32 adjusted_offset, bool is_16_bit)
{
unsigned mainsym;
if (length >= LZX_MIN_SECONDARY_LEN) {
/* Length symbol needed */
c->freqs.len[length - LZX_MIN_SECONDARY_LEN]++;
mainsym = LZX_NUM_CHARS + LZX_NUM_PRIMARY_LENS;
} else {
/* No length symbol needed */
mainsym = LZX_NUM_CHARS + length - LZX_MIN_MATCH_LEN;
}
mainsym += LZX_NUM_LEN_HEADERS *
lzx_get_offset_slot(c, adjusted_offset, is_16_bit);
c->freqs.main[mainsym]++;
return mainsym;
}
/*
* The following macros call either the 16-bit or the 32-bit version of a
* matchfinder function based on the value of 'is_16_bit', which will be known
* at compilation time.
*/
#define CALL_HC_MF(is_16_bit, c, funcname, ...) \
((is_16_bit) ? CONCAT(funcname, _16)(&(c)->hc_mf_16, ##__VA_ARGS__) : \
CONCAT(funcname, _32)(&(c)->hc_mf_32, ##__VA_ARGS__));
#define CALL_BT_MF(is_16_bit, c, funcname, ...) \
((is_16_bit) ? CONCAT(funcname, _16)(&(c)->bt_mf_16, ##__VA_ARGS__) : \
CONCAT(funcname, _32)(&(c)->bt_mf_32, ##__VA_ARGS__));
/******************************************************************************/
/* Output bitstream */
/*----------------------------------------------------------------------------*/
/*
* The LZX bitstream is encoded as a sequence of little endian 16-bit coding
* units. Bits are ordered from most significant to least significant within
* each coding unit.
*/
/*
* Structure to keep track of the current state of sending bits to the
* compressed output buffer.
*/
struct lzx_output_bitstream {
/* Bits that haven't yet been written to the output buffer */
machine_word_t bitbuf;
/* Number of bits currently held in @bitbuf */
machine_word_t bitcount;
/* Pointer to the start of the output buffer */
u8 *start;
/* Pointer to the position in the output buffer at which the next coding
* unit should be written */
u8 *next;
/* Pointer to just past the end of the output buffer, rounded down by
* one byte if needed to make 'end - start' a multiple of 2 */
u8 *end;
};
/* Can the specified number of bits always be added to 'bitbuf' after all
* pending 16-bit coding units have been flushed? */
#define CAN_BUFFER(n) ((n) <= WORDBITS - 15)
/* Initialize the output bitstream to write to the specified buffer. */
static void
lzx_init_output(struct lzx_output_bitstream *os, void *buffer, size_t size)
{
os->bitbuf = 0;
os->bitcount = 0;
os->start = buffer;
os->next = buffer;
os->end = (u8 *)buffer + (size & ~1);
}
/*
* Add some bits to the bitbuffer variable of the output bitstream. The caller
* must make sure there is enough room.
*/
static forceinline void
lzx_add_bits(struct lzx_output_bitstream *os, u32 bits, unsigned num_bits)
{
os->bitbuf = (os->bitbuf << num_bits) | bits;
os->bitcount += num_bits;
}
/*
* Flush bits from the bitbuffer variable to the output buffer. 'max_num_bits'
* specifies the maximum number of bits that may have been added since the last
* flush.
*/
static forceinline void
lzx_flush_bits(struct lzx_output_bitstream *os, unsigned max_num_bits)
{
/* Masking the number of bits to shift is only needed to avoid undefined
* behavior; we don't actually care about the results of bad shifts. On
* x86, the explicit masking generates no extra code. */
const u32 shift_mask = WORDBITS - 1;
if (os->end - os->next < 6)
return;
put_unaligned_le16(os->bitbuf >> ((os->bitcount - 16) &
shift_mask), os->next + 0);
if (max_num_bits > 16)
put_unaligned_le16(os->bitbuf >> ((os->bitcount - 32) &
shift_mask), os->next + 2);
if (max_num_bits > 32)
put_unaligned_le16(os->bitbuf >> ((os->bitcount - 48) &
shift_mask), os->next + 4);
os->next += (os->bitcount >> 4) << 1;
os->bitcount &= 15;
}
/* Add at most 16 bits to the bitbuffer and flush it. */
static forceinline void
lzx_write_bits(struct lzx_output_bitstream *os, u32 bits, unsigned num_bits)
{
lzx_add_bits(os, bits, num_bits);
lzx_flush_bits(os, 16);
}
/*
* Flush the last coding unit to the output buffer if needed. Return the total
* number of bytes written to the output buffer, or 0 if an overflow occurred.
*/
static size_t
lzx_flush_output(struct lzx_output_bitstream *os)
{
if (os->end - os->next < 6)
return 0;
if (os->bitcount != 0) {
put_unaligned_le16(os->bitbuf << (16 - os->bitcount), os->next);
os->next += 2;
}
return os->next - os->start;
}
/******************************************************************************/
/* Preparing Huffman codes */
/*----------------------------------------------------------------------------*/
/*
* Build the Huffman codes. This takes as input the frequency tables for each
* code and produces as output a set of tables that map symbols to codewords and
* codeword lengths.
*/
static void
lzx_build_huffman_codes(struct lzx_compressor *c)
{
const struct lzx_freqs *freqs = &c->freqs;
struct lzx_codes *codes = &c->codes[c->codes_index];
STATIC_ASSERT(MAIN_CODEWORD_LIMIT >= 9 &&
MAIN_CODEWORD_LIMIT <= LZX_MAX_MAIN_CODEWORD_LEN);
make_canonical_huffman_code(c->num_main_syms,
MAIN_CODEWORD_LIMIT,
freqs->main,
codes->lens.main,
codes->codewords.main);
STATIC_ASSERT(LENGTH_CODEWORD_LIMIT >= 8 &&
LENGTH_CODEWORD_LIMIT <= LZX_MAX_LEN_CODEWORD_LEN);
make_canonical_huffman_code(LZX_LENCODE_NUM_SYMBOLS,
LENGTH_CODEWORD_LIMIT,
freqs->len,
codes->lens.len,
codes->codewords.len);
STATIC_ASSERT(ALIGNED_CODEWORD_LIMIT >= LZX_NUM_ALIGNED_OFFSET_BITS &&
ALIGNED_CODEWORD_LIMIT <= LZX_MAX_ALIGNED_CODEWORD_LEN);
make_canonical_huffman_code(LZX_ALIGNEDCODE_NUM_SYMBOLS,
ALIGNED_CODEWORD_LIMIT,
freqs->aligned,
codes->lens.aligned,
codes->codewords.aligned);
}
/* Reset the symbol frequencies for the current block. */
static void
lzx_reset_symbol_frequencies(struct lzx_compressor *c)
{
memset(&c->freqs, 0, sizeof(c->freqs));
}
static unsigned
lzx_compute_precode_items(const u8 lens[restrict],
const u8 prev_lens[restrict],
u32 precode_freqs[restrict],
unsigned precode_items[restrict])
{
unsigned *itemptr;
unsigned run_start;
unsigned run_end;
unsigned extra_bits;
int delta;
u8 len;
itemptr = precode_items;
run_start = 0;
while (!((len = lens[run_start]) & 0x80)) {
/* len = the length being repeated */
/* Find the next run of codeword lengths. */
run_end = run_start + 1;
/* Fast case for a single length. */
if (likely(len != lens[run_end])) {
delta = prev_lens[run_start] - len;
if (delta < 0)
delta += 17;
precode_freqs[delta]++;
*itemptr++ = delta;
run_start++;
continue;
}
/* Extend the run. */
do {
run_end++;
} while (len == lens[run_end]);
if (len == 0) {
/* Run of zeroes. */
/* Symbol 18: RLE 20 to 51 zeroes at a time. */
while ((run_end - run_start) >= 20) {
extra_bits = min((run_end - run_start) - 20, 0x1F);
precode_freqs[18]++;
*itemptr++ = 18 | (extra_bits << 5);
run_start += 20 + extra_bits;
}
/* Symbol 17: RLE 4 to 19 zeroes at a time. */
if ((run_end - run_start) >= 4) {
extra_bits = min((run_end - run_start) - 4, 0xF);
precode_freqs[17]++;
*itemptr++ = 17 | (extra_bits << 5);
run_start += 4 + extra_bits;
}
} else {
/* A run of nonzero lengths. */
/* Symbol 19: RLE 4 to 5 of any length at a time. */
while ((run_end - run_start) >= 4) {
extra_bits = (run_end - run_start) > 4;
delta = prev_lens[run_start] - len;
if (delta < 0)
delta += 17;
precode_freqs[19]++;
precode_freqs[delta]++;
*itemptr++ = 19 | (extra_bits << 5) | (delta << 6);
run_start += 4 + extra_bits;
}
}
/* Output any remaining lengths without RLE. */
while (run_start != run_end) {
delta = prev_lens[run_start] - len;
if (delta < 0)
delta += 17;
precode_freqs[delta]++;
*itemptr++ = delta;
run_start++;
}
}
return itemptr - precode_items;
}
/******************************************************************************/
/* Outputting compressed data */
/*----------------------------------------------------------------------------*/
/*
* Output a Huffman code in the compressed form used in LZX.
*
* The Huffman code is represented in the output as a logical series of codeword
* lengths from which the Huffman code, which must be in canonical form, can be
* reconstructed.
*
* The codeword lengths are themselves compressed using a separate Huffman code,
* the "precode", which contains a symbol for each possible codeword length in
* the larger code as well as several special symbols to represent repeated
* codeword lengths (a form of run-length encoding). The precode is itself
* constructed in canonical form, and its codeword lengths are represented
* literally in 20 4-bit fields that immediately precede the compressed codeword
* lengths of the larger code.
*
* Furthermore, the codeword lengths of the larger code are actually represented
* as deltas from the codeword lengths of the corresponding code in the previous
* block.
*
* @os:
* Bitstream to which to write the compressed Huffman code.
* @lens:
* The codeword lengths, indexed by symbol, in the Huffman code.
* @prev_lens:
* The codeword lengths, indexed by symbol, in the corresponding Huffman
* code in the previous block, or all zeroes if this is the first block.
* @num_lens:
* The number of symbols in the Huffman code.
*/
static void
lzx_write_compressed_code(struct lzx_output_bitstream *os,
const u8 lens[restrict],
const u8 prev_lens[restrict],
unsigned num_lens)
{
u32 precode_freqs[LZX_PRECODE_NUM_SYMBOLS];
u8 precode_lens[LZX_PRECODE_NUM_SYMBOLS];
u32 precode_codewords[LZX_PRECODE_NUM_SYMBOLS];
unsigned precode_items[num_lens];
unsigned num_precode_items;
unsigned precode_item;
unsigned precode_sym;
unsigned i;
u8 saved = lens[num_lens];
*(u8 *)(lens + num_lens) = 0x80;
for (i = 0; i < LZX_PRECODE_NUM_SYMBOLS; i++)
precode_freqs[i] = 0;
/* Compute the "items" (RLE / literal tokens and extra bits) with which
* the codeword lengths in the larger code will be output. */
num_precode_items = lzx_compute_precode_items(lens,
prev_lens,
precode_freqs,
precode_items);
/* Build the precode. */
STATIC_ASSERT(PRE_CODEWORD_LIMIT >= 5 &&
PRE_CODEWORD_LIMIT <= LZX_MAX_PRE_CODEWORD_LEN);
make_canonical_huffman_code(LZX_PRECODE_NUM_SYMBOLS, PRE_CODEWORD_LIMIT,
precode_freqs, precode_lens,
precode_codewords);
/* Output the lengths of the codewords in the precode. */
for (i = 0; i < LZX_PRECODE_NUM_SYMBOLS; i++)
lzx_write_bits(os, precode_lens[i], LZX_PRECODE_ELEMENT_SIZE);
/* Output the encoded lengths of the codewords in the larger code. */
for (i = 0; i < num_precode_items; i++) {
precode_item = precode_items[i];
precode_sym = precode_item & 0x1F;
lzx_add_bits(os, precode_codewords[precode_sym],
precode_lens[precode_sym]);
if (precode_sym >= 17) {
if (precode_sym == 17) {
lzx_add_bits(os, precode_item >> 5, 4);
} else if (precode_sym == 18) {
lzx_add_bits(os, precode_item >> 5, 5);
} else {
lzx_add_bits(os, (precode_item >> 5) & 1, 1);
precode_sym = precode_item >> 6;
lzx_add_bits(os, precode_codewords[precode_sym],
precode_lens[precode_sym]);
}
}
STATIC_ASSERT(CAN_BUFFER(2 * PRE_CODEWORD_LIMIT + 1));
lzx_flush_bits(os, 2 * PRE_CODEWORD_LIMIT + 1);
}
*(u8 *)(lens + num_lens) = saved;
}
/*
* Write all matches and literal bytes (which were precomputed) in an LZX
* compressed block to the output bitstream in the final compressed
* representation.
*
* @os
* The output bitstream.
* @block_type
* The chosen type of the LZX compressed block (LZX_BLOCKTYPE_ALIGNED or
* LZX_BLOCKTYPE_VERBATIM).
* @block_data
* The uncompressed data of the block.
* @sequences
* The matches and literals to output, given as a series of sequences.
* @codes
* The main, length, and aligned offset Huffman codes for the block.
*/
static void
lzx_write_sequences(struct lzx_output_bitstream *os, int block_type,
const u8 *block_data, const struct lzx_sequence sequences[],
const struct lzx_codes *codes)
{
const struct lzx_sequence *seq = sequences;
unsigned min_aligned_offset_slot;
if (block_type == LZX_BLOCKTYPE_ALIGNED)
min_aligned_offset_slot = LZX_MIN_ALIGNED_OFFSET_SLOT;
else
min_aligned_offset_slot = LZX_MAX_OFFSET_SLOTS;
for (;;) {
/* Output the next sequence. */
u32 litrunlen = seq->litrunlen_and_matchlen >> SEQ_MATCHLEN_BITS;
unsigned matchlen = seq->litrunlen_and_matchlen & SEQ_MATCHLEN_MASK;
STATIC_ASSERT((u32)~SEQ_MATCHLEN_MASK >> SEQ_MATCHLEN_BITS >=
SOFT_MAX_BLOCK_SIZE);
u32 adjusted_offset;
unsigned main_symbol;
unsigned offset_slot;
unsigned num_extra_bits;
u32 extra_bits;
/* Output the literal run of the sequence. */
if (litrunlen) { /* Is the literal run nonempty? */
/* Verify optimization is enabled on 64-bit */
STATIC_ASSERT(WORDBITS < 64 ||
CAN_BUFFER(3 * MAIN_CODEWORD_LIMIT));
if (CAN_BUFFER(3 * MAIN_CODEWORD_LIMIT)) {
/* 64-bit: write 3 literals at a time. */
while (litrunlen >= 3) {
unsigned lit0 = block_data[0];
unsigned lit1 = block_data[1];
unsigned lit2 = block_data[2];
lzx_add_bits(os, codes->codewords.main[lit0],
codes->lens.main[lit0]);
lzx_add_bits(os, codes->codewords.main[lit1],
codes->lens.main[lit1]);
lzx_add_bits(os, codes->codewords.main[lit2],
codes->lens.main[lit2]);
lzx_flush_bits(os, 3 * MAIN_CODEWORD_LIMIT);
block_data += 3;
litrunlen -= 3;
}
if (litrunlen--) {
unsigned lit = *block_data++;
lzx_add_bits(os, codes->codewords.main[lit],
codes->lens.main[lit]);
if (litrunlen--) {
unsigned lit = *block_data++;
lzx_add_bits(os, codes->codewords.main[lit],
codes->lens.main[lit]);
lzx_flush_bits(os, 2 * MAIN_CODEWORD_LIMIT);
} else {
lzx_flush_bits(os, 1 * MAIN_CODEWORD_LIMIT);
}
}
} else {
/* 32-bit: write 1 literal at a time. */
do {
unsigned lit = *block_data++;
lzx_add_bits(os, codes->codewords.main[lit],
codes->lens.main[lit]);
lzx_flush_bits(os, MAIN_CODEWORD_LIMIT);
} while (--litrunlen);
}
}
/* Was this the last literal run? */
if (matchlen == 0)
return;
/* Nope; output the match. */
block_data += matchlen;
adjusted_offset = seq->adjusted_offset_and_mainsym >> SEQ_MAINSYM_BITS;
main_symbol = seq->adjusted_offset_and_mainsym & SEQ_MAINSYM_MASK;
offset_slot = (main_symbol - LZX_NUM_CHARS) / LZX_NUM_LEN_HEADERS;
num_extra_bits = lzx_extra_offset_bits[offset_slot];
extra_bits = adjusted_offset - (lzx_offset_slot_base[offset_slot] +
LZX_OFFSET_ADJUSTMENT);
#define MAX_MATCH_BITS (MAIN_CODEWORD_LIMIT + \
LENGTH_CODEWORD_LIMIT + \
LZX_MAX_NUM_EXTRA_BITS - \
LZX_NUM_ALIGNED_OFFSET_BITS + \
ALIGNED_CODEWORD_LIMIT)
/* Verify optimization is enabled on 64-bit */
STATIC_ASSERT(WORDBITS < 64 || CAN_BUFFER(MAX_MATCH_BITS));
/* Output the main symbol for the match. */
lzx_add_bits(os, codes->codewords.main[main_symbol],
codes->lens.main[main_symbol]);
if (!CAN_BUFFER(MAX_MATCH_BITS))
lzx_flush_bits(os, MAIN_CODEWORD_LIMIT);
/* If needed, output the length symbol for the match. */
if (matchlen >= LZX_MIN_SECONDARY_LEN) {
lzx_add_bits(os, codes->codewords.len[matchlen -
LZX_MIN_SECONDARY_LEN],
codes->lens.len[matchlen -
LZX_MIN_SECONDARY_LEN]);
if (!CAN_BUFFER(MAX_MATCH_BITS))
lzx_flush_bits(os, LENGTH_CODEWORD_LIMIT);
}
/* Output the extra offset bits for the match. In aligned
* offset blocks, the lowest 3 bits of the adjusted offset are
* Huffman-encoded using the aligned offset code, provided that
* there are at least extra 3 offset bits required. All other
* extra offset bits are output verbatim. */
if (offset_slot >= min_aligned_offset_slot) {
lzx_add_bits(os, extra_bits >> LZX_NUM_ALIGNED_OFFSET_BITS,
num_extra_bits - LZX_NUM_ALIGNED_OFFSET_BITS);
if (!CAN_BUFFER(MAX_MATCH_BITS))
lzx_flush_bits(os, LZX_MAX_NUM_EXTRA_BITS -
LZX_NUM_ALIGNED_OFFSET_BITS);
lzx_add_bits(os, codes->codewords.aligned[adjusted_offset &
LZX_ALIGNED_OFFSET_BITMASK],
codes->lens.aligned[adjusted_offset &
LZX_ALIGNED_OFFSET_BITMASK]);
if (!CAN_BUFFER(MAX_MATCH_BITS))
lzx_flush_bits(os, ALIGNED_CODEWORD_LIMIT);
} else {
STATIC_ASSERT(CAN_BUFFER(LZX_MAX_NUM_EXTRA_BITS));
lzx_add_bits(os, extra_bits, num_extra_bits);
if (!CAN_BUFFER(MAX_MATCH_BITS))
lzx_flush_bits(os, LZX_MAX_NUM_EXTRA_BITS);
}
if (CAN_BUFFER(MAX_MATCH_BITS))
lzx_flush_bits(os, MAX_MATCH_BITS);
/* Advance to the next sequence. */
seq++;
}
}
static void
lzx_write_compressed_block(const u8 *block_begin,
int block_type,
u32 block_size,
unsigned window_order,
unsigned num_main_syms,
const struct lzx_sequence sequences[],
const struct lzx_codes * codes,
const struct lzx_lens * prev_lens,
struct lzx_output_bitstream * os)
{
/* The first three bits indicate the type of block and are one of the
* LZX_BLOCKTYPE_* constants. */
lzx_write_bits(os, block_type, 3);
/*
* Output the block size.
*
* The original LZX format encoded the block size in 24 bits. However,
* the LZX format used in WIM archives uses 1 bit to specify whether the
* block has the default size of 32768 bytes, then optionally 16 bits to
* specify a non-default size. This works fine for Microsoft's WIM
* software (WIMGAPI), which never compresses more than 32768 bytes at a
* time with LZX. However, as an extension, our LZX compressor supports
* compressing up to 2097152 bytes, with a corresponding increase in
* window size. It is possible for blocks in these larger buffers to
* exceed 65535 bytes; such blocks cannot have their size represented in
* 16 bits.
*
* The chosen solution was to use 24 bits for the block size when
* possibly required --- specifically, when the compressor has been
* allocated to be capable of compressing more than 32768 bytes at once
* (which also causes the number of main symbols to be increased).
*/
if (block_size == LZX_DEFAULT_BLOCK_SIZE) {
lzx_write_bits(os, 1, 1);
} else {
lzx_write_bits(os, 0, 1);
if (window_order >= 16)
lzx_write_bits(os, block_size >> 16, 8);
lzx_write_bits(os, block_size & 0xFFFF, 16);
}
/* If it's an aligned offset block, output the aligned offset code. */
if (block_type == LZX_BLOCKTYPE_ALIGNED) {
for (int i = 0; i < LZX_ALIGNEDCODE_NUM_SYMBOLS; i++) {
lzx_write_bits(os, codes->lens.aligned[i],
LZX_ALIGNEDCODE_ELEMENT_SIZE);
}
}
/* Output the main code (two parts). */
lzx_write_compressed_code(os, codes->lens.main,
prev_lens->main,
LZX_NUM_CHARS);
lzx_write_compressed_code(os, codes->lens.main + LZX_NUM_CHARS,
prev_lens->main + LZX_NUM_CHARS,
num_main_syms - LZX_NUM_CHARS);
/* Output the length code. */
lzx_write_compressed_code(os, codes->lens.len,
prev_lens->len,
LZX_LENCODE_NUM_SYMBOLS);
/* Output the compressed matches and literals. */
lzx_write_sequences(os, block_type, block_begin, sequences, codes);
}
/*
* Given the frequencies of symbols in an LZX-compressed block and the
* corresponding Huffman codes, return LZX_BLOCKTYPE_ALIGNED or
* LZX_BLOCKTYPE_VERBATIM if an aligned offset or verbatim block, respectively,
* will take fewer bits to output.
*/
static int
lzx_choose_verbatim_or_aligned(const struct lzx_freqs * freqs,
const struct lzx_codes * codes)
{
u32 verbatim_cost = 0;
u32 aligned_cost = 0;
/* A verbatim block requires 3 bits in each place that an aligned offset
* symbol would be used in an aligned offset block. */
for (unsigned i = 0; i < LZX_ALIGNEDCODE_NUM_SYMBOLS; i++) {
verbatim_cost += LZX_NUM_ALIGNED_OFFSET_BITS * freqs->aligned[i];
aligned_cost += codes->lens.aligned[i] * freqs->aligned[i];
}
/* Account for the cost of sending the codeword lengths of the aligned
* offset code. */
aligned_cost += LZX_ALIGNEDCODE_ELEMENT_SIZE *
LZX_ALIGNEDCODE_NUM_SYMBOLS;
if (aligned_cost < verbatim_cost)
return LZX_BLOCKTYPE_ALIGNED;
else
return LZX_BLOCKTYPE_VERBATIM;
}
/*
* Flush an LZX block:
*
* 1. Build the Huffman codes.
* 2. Decide whether to output the block as VERBATIM or ALIGNED.
* 3. Write the block.
* 4. Swap the indices of the current and previous Huffman codes.
*
* Note: we never output UNCOMPRESSED blocks. This probably should be
* implemented sometime, but it doesn't make much difference.
*/
static void
lzx_flush_block(struct lzx_compressor *c, struct lzx_output_bitstream *os,
const u8 *block_begin, u32 block_size, u32 seq_idx)
{
int block_type;
lzx_build_huffman_codes(c);
block_type = lzx_choose_verbatim_or_aligned(&c->freqs,
&c->codes[c->codes_index]);
lzx_write_compressed_block(block_begin,
block_type,
block_size,
c->window_order,
c->num_main_syms,
&c->chosen_sequences[seq_idx],
&c->codes[c->codes_index],
&c->codes[c->codes_index ^ 1].lens,
os);
c->codes_index ^= 1;
}
/******************************************************************************/
/* Block splitting algorithm */
/*----------------------------------------------------------------------------*/
/*
* The problem of block splitting is to decide when it is worthwhile to start a
* new block with new entropy codes. There is a theoretically optimal solution:
* recursively consider every possible block split, considering the exact cost
* of each block, and choose the minimum cost approach. But this is far too
* slow. Instead, as an approximation, we can count symbols and after every N
* symbols, compare the expected distribution of symbols based on the previous
* data with the actual distribution. If they differ "by enough", then start a
* new block.
*
* As an optimization and heuristic, we don't distinguish between every symbol
* but rather we combine many symbols into a single "observation type". For
* literals we only look at the high bits and low bits, and for matches we only
* look at whether the match is long or not. The assumption is that for typical
* "real" data, places that are good block boundaries will tend to be noticeable
* based only on changes in these aggregate frequencies, without looking for
* subtle differences in individual symbols. For example, a change from ASCII
* bytes to non-ASCII bytes, or from few matches (generally less compressible)
* to many matches (generally more compressible), would be easily noticed based
* on the aggregates.
*
* For determining whether the frequency distributions are "different enough" to
* start a new block, the simply heuristic of splitting when the sum of absolute
* differences exceeds a constant seems to be good enough.
*
* Finally, for an approximation, it is not strictly necessary that the exact
* symbols being used are considered. With "near-optimal parsing", for example,
* the actual symbols that will be used are unknown until after the block
* boundary is chosen and the block has been optimized. Since the final choices
* cannot be used, we can use preliminary "greedy" choices instead.
*/
/* Initialize the block split statistics when starting a new block. */
static void
lzx_init_block_split_stats(struct lzx_block_split_stats *stats)
{
memset(stats, 0, sizeof(*stats));
}
/* Literal observation. Heuristic: use the top 2 bits and low 1 bits of the
* literal, for 8 possible literal observation types. */
static forceinline void
lzx_observe_literal(struct lzx_block_split_stats *stats, u8 lit)
{
stats->new_observations[((lit >> 5) & 0x6) | (lit & 1)]++;
stats->num_new_observations++;
}
/* Match observation. Heuristic: use one observation type for "short match" and
* one observation type for "long match". */
static forceinline void
lzx_observe_match(struct lzx_block_split_stats *stats, unsigned length)
{
stats->new_observations[NUM_LITERAL_OBSERVATION_TYPES + (length >= 5)]++;
stats->num_new_observations++;
}
static bool
lzx_should_end_block(struct lzx_block_split_stats *stats)
{
if (stats->num_observations > 0) {
/* Note: to avoid slow divisions, we do not divide by
* 'num_observations', but rather do all math with the numbers
* multiplied by 'num_observations'. */
u32 total_delta = 0;
for (int i = 0; i < NUM_OBSERVATION_TYPES; i++) {
u32 expected = stats->observations[i] *
stats->num_new_observations;
u32 actual = stats->new_observations[i] *
stats->num_observations;
u32 delta = (actual > expected) ? actual - expected :
expected - actual;
total_delta += delta;
}
/* Ready to end the block? */
if (total_delta >=
stats->num_new_observations * 7 / 8 * stats->num_observations)
return true;
}
for (int i = 0; i < NUM_OBSERVATION_TYPES; i++) {
stats->num_observations += stats->new_observations[i];
stats->observations[i] += stats->new_observations[i];
stats->new_observations[i] = 0;
}
stats->num_new_observations = 0;
return false;
}
/******************************************************************************/
/* Slower ("near-optimal") compression algorithm */
/*----------------------------------------------------------------------------*/
/*
* Least-recently-used queue for match offsets.
*
* This is represented as a 64-bit integer for efficiency. There are three
* offsets of 21 bits each. Bit 64 is garbage.
*/
struct lzx_lru_queue {
u64 R;
} __attribute__((aligned(8)));
#define LZX_QUEUE_OFFSET_SHIFT 21
#define LZX_QUEUE_OFFSET_MASK (((u64)1 << LZX_QUEUE_OFFSET_SHIFT) - 1)
#define LZX_QUEUE_R0_SHIFT (0 * LZX_QUEUE_OFFSET_SHIFT)
#define LZX_QUEUE_R1_SHIFT (1 * LZX_QUEUE_OFFSET_SHIFT)
#define LZX_QUEUE_R2_SHIFT (2 * LZX_QUEUE_OFFSET_SHIFT)
#define LZX_QUEUE_R0_MASK (LZX_QUEUE_OFFSET_MASK << LZX_QUEUE_R0_SHIFT)
#define LZX_QUEUE_R1_MASK (LZX_QUEUE_OFFSET_MASK << LZX_QUEUE_R1_SHIFT)
#define LZX_QUEUE_R2_MASK (LZX_QUEUE_OFFSET_MASK << LZX_QUEUE_R2_SHIFT)
#define LZX_QUEUE_INITIALIZER { \
((u64)1 << LZX_QUEUE_R0_SHIFT) | \
((u64)1 << LZX_QUEUE_R1_SHIFT) | \
((u64)1 << LZX_QUEUE_R2_SHIFT) }
static forceinline u64
lzx_lru_queue_R0(struct lzx_lru_queue queue)
{
return (queue.R >> LZX_QUEUE_R0_SHIFT) & LZX_QUEUE_OFFSET_MASK;
}
static forceinline u64
lzx_lru_queue_R1(struct lzx_lru_queue queue)
{
return (queue.R >> LZX_QUEUE_R1_SHIFT) & LZX_QUEUE_OFFSET_MASK;
}
static forceinline u64
lzx_lru_queue_R2(struct lzx_lru_queue queue)
{
return (queue.R >> LZX_QUEUE_R2_SHIFT) & LZX_QUEUE_OFFSET_MASK;
}
/* Push a match offset onto the front (most recently used) end of the queue. */
static forceinline struct lzx_lru_queue
lzx_lru_queue_push(struct lzx_lru_queue queue, u32 offset)
{
return (struct lzx_lru_queue) {
.R = (queue.R << LZX_QUEUE_OFFSET_SHIFT) | offset,
};
}
/* Swap a match offset to the front of the queue. */
static forceinline struct lzx_lru_queue
lzx_lru_queue_swap(struct lzx_lru_queue queue, unsigned idx)
{
unsigned shift = idx * 21;
const u64 mask = LZX_QUEUE_R0_MASK;
const u64 mask_high = mask << shift;
return (struct lzx_lru_queue) {
(queue.R & ~(mask | mask_high)) |
((queue.R & mask_high) >> shift) |
((queue.R & mask) << shift)
};
}
static forceinline u32
lzx_walk_item_list(struct lzx_compressor *c, u32 block_size, bool is_16_bit,
bool record)
{
struct lzx_sequence *seq =
&c->chosen_sequences[ARRAY_LEN(c->chosen_sequences) - 1];
u32 node_idx = block_size;
u32 litrun_end; /* if record=true: end of the current literal run */
if (record) {
/* The last sequence has matchlen 0 */
seq->litrunlen_and_matchlen = 0;
litrun_end = node_idx;
}
for (;;) {
u32 item;
unsigned matchlen;
u32 adjusted_offset;
unsigned mainsym;
/* Tally literals until either a match or the beginning of the
* block is reached. Note: the item in the node at the
* beginning of the block (c->optimum_nodes[0]) has all bits
* set, causing this loop to end when it is reached. */
for (;;) {
item = c->optimum_nodes[node_idx].item;
if (item & OPTIMUM_LEN_MASK)
break;
c->freqs.main[item >> OPTIMUM_OFFSET_SHIFT]++;
node_idx--;
}
#if CONSIDER_GAP_MATCHES
if (item & OPTIMUM_GAP_MATCH) {
if (node_idx == 0)
break;
/* Tally/record the rep0 match after the gap. */
matchlen = item & OPTIMUM_LEN_MASK;
mainsym = lzx_tally_main_and_lensyms(c, matchlen, 0,
is_16_bit);
if (record) {
seq->litrunlen_and_matchlen |=
(litrun_end - node_idx) <<
SEQ_MATCHLEN_BITS;
seq--;
seq->litrunlen_and_matchlen = matchlen;
seq->adjusted_offset_and_mainsym = mainsym;
litrun_end = node_idx - matchlen;
}
/* Tally the literal in the gap. */
c->freqs.main[(u8)(item >> OPTIMUM_OFFSET_SHIFT)]++;
/* Fall through and tally the match before the gap.
* (It was temporarily saved in the 'cost' field of the
* previous node, which was free to reuse.) */
item = c->optimum_nodes[--node_idx].cost;
node_idx -= matchlen;
}
#else /* CONSIDER_GAP_MATCHES */
if (node_idx == 0)
break;
#endif /* !CONSIDER_GAP_MATCHES */
/* Tally/record a match. */
matchlen = item & OPTIMUM_LEN_MASK;
adjusted_offset = item >> OPTIMUM_OFFSET_SHIFT;
mainsym = lzx_tally_main_and_lensyms(c, matchlen,
adjusted_offset,
is_16_bit);
if (adjusted_offset >= LZX_MIN_ALIGNED_OFFSET +
LZX_OFFSET_ADJUSTMENT)
c->freqs.aligned[adjusted_offset &
LZX_ALIGNED_OFFSET_BITMASK]++;
if (record) {
seq->litrunlen_and_matchlen |=
(litrun_end - node_idx) << SEQ_MATCHLEN_BITS;
seq--;
seq->litrunlen_and_matchlen = matchlen;
seq->adjusted_offset_and_mainsym =
(adjusted_offset << SEQ_MAINSYM_BITS) | mainsym;
litrun_end = node_idx - matchlen;
}
node_idx -= matchlen;
}
/* Record the literal run length for the first sequence. */
if (record) {
seq->litrunlen_and_matchlen |=
(litrun_end - node_idx) << SEQ_MATCHLEN_BITS;
}
/* Return the index in chosen_sequences at which the sequences begin. */
return seq - &c->chosen_sequences[0];
}
/*
* Given the minimum-cost path computed through the item graph for the current
* block, walk the path and count how many of each symbol in each Huffman-coded
* alphabet would be required to output the items (matches and literals) along
* the path.
*
* Note that the path will be walked backwards (from the end of the block to the
* beginning of the block), but this doesn't matter because this function only
* computes frequencies.
*/
static forceinline void
lzx_tally_item_list(struct lzx_compressor *c, u32 block_size, bool is_16_bit)
{
lzx_walk_item_list(c, block_size, is_16_bit, false);
}
/*
* Like lzx_tally_item_list(), but this function also generates the list of
* lzx_sequences for the minimum-cost path and writes it to c->chosen_sequences,
* ready to be output to the bitstream after the Huffman codes are computed.
* The lzx_sequences will be written to decreasing memory addresses as the path
* is walked backwards, which means they will end up in the expected
* first-to-last order. The return value is the index in c->chosen_sequences at
* which the lzx_sequences begin.
*/
static forceinline u32
lzx_record_item_list(struct lzx_compressor *c, u32 block_size, bool is_16_bit)
{
return lzx_walk_item_list(c, block_size, is_16_bit, true);
}
/*
* Find an inexpensive path through the graph of possible match/literal choices
* for the current block. The nodes of the graph are
* c->optimum_nodes[0...block_size]. They correspond directly to the bytes in
* the current block, plus one extra node for end-of-block. The edges of the
* graph are matches and literals. The goal is to find the minimum cost path
* from 'c->optimum_nodes[0]' to 'c->optimum_nodes[block_size]', given the cost
* model 'c->costs'.
*
* The algorithm works forwards, starting at 'c->optimum_nodes[0]' and
* proceeding forwards one node at a time. At each node, a selection of matches
* (len >= 2), as well as the literal byte (len = 1), is considered. An item of
* length 'len' provides a new path to reach the node 'len' bytes later. If
* such a path is the lowest cost found so far to reach that later node, then
* that later node is updated with the new cost and the "arrival" which provided
* that cost.
*
* Note that although this algorithm is based on minimum cost path search, due
* to various simplifying assumptions the result is not guaranteed to be the
* true minimum cost, or "optimal", path over the graph of all valid LZX
* representations of this block.
*
* Also, note that because of the presence of the recent offsets queue (which is
* a type of adaptive state), the algorithm cannot work backwards and compute
* "cost to end" instead of "cost to beginning". Furthermore, the way the
* algorithm handles this adaptive state in the "minimum cost" parse is actually
* only an approximation. It's possible for the globally optimal, minimum cost
* path to contain a prefix, ending at a position, where that path prefix is
* *not* the minimum cost path to that position. This can happen if such a path
* prefix results in a different adaptive state which results in lower costs
* later. The algorithm does not solve this problem in general; it only looks
* one step ahead, with the exception of special consideration for "gap
* matches".
*/
static forceinline struct lzx_lru_queue
lzx_find_min_cost_path(struct lzx_compressor * const restrict c,
const u8 * const restrict block_begin,
const u32 block_size,
const struct lzx_lru_queue initial_queue,
bool is_16_bit)
{
struct lzx_optimum_node *cur_node = c->optimum_nodes;
struct lzx_optimum_node * const end_node = cur_node + block_size;
struct lz_match *cache_ptr = c->match_cache;
const u8 *in_next = block_begin;
const u8 * const block_end = block_begin + block_size;
/*
* Instead of storing the match offset LRU queues in the
* 'lzx_optimum_node' structures, we save memory (and cache lines) by
* storing them in a smaller array. This works because the algorithm
* only requires a limited history of the adaptive state. Once a given
* state is more than LZX_MAX_MATCH_LEN bytes behind the current node
* (more if gap match consideration is enabled; we just round up to 512
* so it's a power of 2), it is no longer needed.
*
* The QUEUE() macro finds the queue for the given node. This macro has
* been optimized by taking advantage of 'struct lzx_lru_queue' and
* 'struct lzx_optimum_node' both being 8 bytes in size and alignment.
*/
struct lzx_lru_queue queues[512];
STATIC_ASSERT(ARRAY_LEN(queues) >= LZX_MAX_MATCH_LEN + 1);
STATIC_ASSERT(sizeof(c->optimum_nodes[0]) == sizeof(queues[0]));
#define QUEUE(node) \
(*(struct lzx_lru_queue *)((char *)queues + \
((uintptr_t)(node) % (ARRAY_LEN(queues) * sizeof(queues[0])))))
/*(queues[(uintptr_t)(node) / sizeof(*(node)) % ARRAY_LEN(queues)])*/
#if CONSIDER_GAP_MATCHES
u32 matches_before_gap[ARRAY_LEN(queues)];
#define MATCH_BEFORE_GAP(node) \
(matches_before_gap[(uintptr_t)(node) / sizeof(*(node)) % \
ARRAY_LEN(matches_before_gap)])
#endif
/*
* Initially, the cost to reach each node is "infinity".
*
* The first node actually should have cost 0, but "infinity"
* (0xFFFFFFFF) works just as well because it immediately overflows.
*
* The following statement also intentionally sets the 'item' of the
* first node, which would otherwise have no meaning, to 0xFFFFFFFF for
* use as a sentinel. See lzx_walk_item_list().
*/
memset(c->optimum_nodes, 0xFF,
(block_size + 1) * sizeof(c->optimum_nodes[0]));
/* Initialize the recent offsets queue for the first node. */
QUEUE(cur_node) = initial_queue;
do { /* For each node in the block in position order... */
unsigned num_matches;
unsigned literal;
u32 cost;
/*
* A selection of matches for the block was already saved in
* memory so that we don't have to run the uncompressed data
* through the matchfinder on every optimization pass. However,
* we still search for repeat offset matches during each
* optimization pass because we cannot predict the state of the
* recent offsets queue. But as a heuristic, we don't bother
* searching for repeat offset matches if the general-purpose
* matchfinder failed to find any matches.
*
* Note that a match of length n at some offset implies there is
* also a match of length l for LZX_MIN_MATCH_LEN <= l <= n at
* that same offset. In other words, we don't necessarily need
* to use the full length of a match. The key heuristic that
* saves a significicant amount of time is that for each
* distinct length, we only consider the smallest offset for
* which that length is available. This heuristic also applies
* to repeat offsets, which we order specially: R0 < R1 < R2 <
* any explicit offset. Of course, this heuristic may be
* produce suboptimal results because offset slots in LZX are
* subject to entropy encoding, but in practice this is a useful
* heuristic.
*/
num_matches = cache_ptr->length;
cache_ptr++;
if (num_matches) {
struct lz_match *end_matches = cache_ptr + num_matches;
unsigned next_len = LZX_MIN_MATCH_LEN;
unsigned max_len = min(block_end - in_next, LZX_MAX_MATCH_LEN);
const u8 *matchptr;
/* Consider rep0 matches. */
matchptr = in_next - lzx_lru_queue_R0(QUEUE(cur_node));
if (load_u16_unaligned(matchptr) != load_u16_unaligned(in_next))
goto rep0_done;
STATIC_ASSERT(LZX_MIN_MATCH_LEN == 2);
do {
u32 cost = cur_node->cost +
c->costs.match_cost[0][
next_len - LZX_MIN_MATCH_LEN];
if (cost <= (cur_node + next_len)->cost) {
(cur_node + next_len)->cost = cost;
(cur_node + next_len)->item =
(0 << OPTIMUM_OFFSET_SHIFT) | next_len;
}
if (unlikely(++next_len > max_len)) {
cache_ptr = end_matches;
goto done_matches;
}
} while (in_next[next_len - 1] == matchptr[next_len - 1]);
rep0_done:
/* Consider rep1 matches. */
matchptr = in_next - lzx_lru_queue_R1(QUEUE(cur_node));
if (load_u16_unaligned(matchptr) != load_u16_unaligned(in_next))
goto rep1_done;
if (matchptr[next_len - 1] != in_next[next_len - 1])
goto rep1_done;
for (unsigned len = 2; len < next_len - 1; len++)
if (matchptr[len] != in_next[len])
goto rep1_done;
do {
u32 cost = cur_node->cost +
c->costs.match_cost[1][
next_len - LZX_MIN_MATCH_LEN];
if (cost <= (cur_node + next_len)->cost) {
(cur_node + next_len)->cost = cost;
(cur_node + next_len)->item =
(1 << OPTIMUM_OFFSET_SHIFT) | next_len;
}
if (unlikely(++next_len > max_len)) {
cache_ptr = end_matches;
goto done_matches;
}
} while (in_next[next_len - 1] == matchptr[next_len - 1]);
rep1_done:
/* Consider rep2 matches. */
matchptr = in_next - lzx_lru_queue_R2(QUEUE(cur_node));
if (load_u16_unaligned(matchptr) != load_u16_unaligned(in_next))
goto rep2_done;
if (matchptr[next_len - 1] != in_next[next_len - 1])
goto rep2_done;
for (unsigned len = 2; len < next_len - 1; len++)
if (matchptr[len] != in_next[len])
goto rep2_done;
do {
u32 cost = cur_node->cost +
c->costs.match_cost[2][
next_len - LZX_MIN_MATCH_LEN];
if (cost <= (cur_node + next_len)->cost) {
(cur_node + next_len)->cost = cost;
(cur_node + next_len)->item =
(2 << OPTIMUM_OFFSET_SHIFT) | next_len;
}
if (unlikely(++next_len > max_len)) {
cache_ptr = end_matches;
goto done_matches;
}
} while (in_next[next_len - 1] == matchptr[next_len - 1]);
rep2_done:
while (next_len > cache_ptr->length)
if (++cache_ptr == end_matches)
goto done_matches;
/* Consider explicit offset matches. */
for (;;) {
u32 offset = cache_ptr->offset;
u32 adjusted_offset = offset + LZX_OFFSET_ADJUSTMENT;
unsigned offset_slot = lzx_get_offset_slot(c, adjusted_offset, is_16_bit);
u32 base_cost = cur_node->cost;
u32 cost;
#if CONSIDER_ALIGNED_COSTS
if (offset >= LZX_MIN_ALIGNED_OFFSET)
base_cost += c->costs.aligned[adjusted_offset &
LZX_ALIGNED_OFFSET_BITMASK];
#endif
do {
cost = base_cost +
c->costs.match_cost[offset_slot][
next_len - LZX_MIN_MATCH_LEN];
if (cost < (cur_node + next_len)->cost) {
(cur_node + next_len)->cost = cost;
(cur_node + next_len)->item =
(adjusted_offset << OPTIMUM_OFFSET_SHIFT) | next_len;
}
} while (++next_len <= cache_ptr->length);
if (++cache_ptr == end_matches) {
#if CONSIDER_GAP_MATCHES
/* Also consider the longest explicit
* offset match as a "gap match": match
* + lit + rep0. */
s32 remaining = (block_end - in_next) - (s32)next_len;
if (likely(remaining >= 2)) {
const u8 *strptr = in_next + next_len;
const u8 *matchptr = strptr - offset;
if (load_u16_unaligned(strptr) == load_u16_unaligned(matchptr)) {
STATIC_ASSERT(ARRAY_LEN(queues) - LZX_MAX_MATCH_LEN - 2 >= 250);
STATIC_ASSERT(ARRAY_LEN(queues) == ARRAY_LEN(matches_before_gap));
unsigned limit = min(remaining,
min(ARRAY_LEN(queues) - LZX_MAX_MATCH_LEN - 2,
LZX_MAX_MATCH_LEN));
unsigned rep0_len = lz_extend(strptr, matchptr, 2, limit);
u8 lit = strptr[-1];
cost += c->costs.main[lit] +
c->costs.match_cost[0][rep0_len - LZX_MIN_MATCH_LEN];
unsigned total_len = next_len + rep0_len;
if (cost < (cur_node + total_len)->cost) {
(cur_node + total_len)->cost = cost;
(cur_node + total_len)->item =
OPTIMUM_GAP_MATCH |
((u32)lit << OPTIMUM_OFFSET_SHIFT) |
rep0_len;
MATCH_BEFORE_GAP(cur_node + total_len) =
(adjusted_offset << OPTIMUM_OFFSET_SHIFT) |
(next_len - 1);
}
}
}
#endif /* CONSIDER_GAP_MATCHES */
break;
}
}
}
done_matches:
/* Consider coding a literal.
* To avoid an extra branch, actually checking the preferability
* of coding the literal is integrated into the queue update
* code below. */
literal = *in_next++;
cost = cur_node->cost + c->costs.main[literal];
/* Advance to the next position. */
cur_node++;
/* The lowest-cost path to the current position is now known.
* Finalize the recent offsets queue that results from taking
* this lowest-cost path. */
if (cost <= cur_node->cost) {
/* Literal: queue remains unchanged. */
cur_node->cost = cost;
cur_node->item = (u32)literal << OPTIMUM_OFFSET_SHIFT;
QUEUE(cur_node) = QUEUE(cur_node - 1);
} else {
/* Match: queue update is needed. */
unsigned len = cur_node->item & OPTIMUM_LEN_MASK;
#if CONSIDER_GAP_MATCHES
s32 adjusted_offset = (s32)cur_node->item >> OPTIMUM_OFFSET_SHIFT;
STATIC_ASSERT(OPTIMUM_GAP_MATCH == 0x80000000); /* assuming sign extension */
#else
u32 adjusted_offset = cur_node->item >> OPTIMUM_OFFSET_SHIFT;
#endif
if (adjusted_offset >= LZX_NUM_RECENT_OFFSETS) {
/* Explicit offset match: insert offset at front. */
QUEUE(cur_node) =
lzx_lru_queue_push(QUEUE(cur_node - len),
adjusted_offset - LZX_OFFSET_ADJUSTMENT);
}
#if CONSIDER_GAP_MATCHES
else if (adjusted_offset < 0) {
/* "Gap match": Explicit offset match, then a
* literal, then rep0 match. Save the explicit
* offset match information in the cost field of
* the previous node, which isn't needed
* anymore. Then insert the offset at the front
* of the queue. */
u32 match_before_gap = MATCH_BEFORE_GAP(cur_node);
(cur_node - 1)->cost = match_before_gap;
QUEUE(cur_node) =
lzx_lru_queue_push(QUEUE(cur_node - len - 1 -
(match_before_gap & OPTIMUM_LEN_MASK)),
(match_before_gap >> OPTIMUM_OFFSET_SHIFT) -
LZX_OFFSET_ADJUSTMENT);
}
#endif
else {
/* Repeat offset match: swap offset to front. */
QUEUE(cur_node) =
lzx_lru_queue_swap(QUEUE(cur_node - len),
adjusted_offset);
}
}
} while (cur_node != end_node);
/* Return the recent offsets queue at the end of the path. */
return QUEUE(cur_node);
}
/*
* Given the costs for the main and length codewords (c->costs.main and
* c->costs.len), initialize the match cost array (c->costs.match_cost) which
* directly provides the cost of every possible (length, offset slot) pair.
*/
static void
lzx_compute_match_costs(struct lzx_compressor *c)
{
unsigned num_offset_slots = (c->num_main_syms - LZX_NUM_CHARS) /
LZX_NUM_LEN_HEADERS;
struct lzx_costs *costs = &c->costs;
unsigned main_symbol = LZX_NUM_CHARS;
for (unsigned offset_slot = 0; offset_slot < num_offset_slots;
offset_slot++)
{
u32 extra_cost = lzx_extra_offset_bits[offset_slot] * BIT_COST;
unsigned i;
#if CONSIDER_ALIGNED_COSTS
if (offset_slot >= LZX_MIN_ALIGNED_OFFSET_SLOT)
extra_cost -= LZX_NUM_ALIGNED_OFFSET_BITS * BIT_COST;
#endif
for (i = 0; i < LZX_NUM_PRIMARY_LENS; i++) {
costs->match_cost[offset_slot][i] =
costs->main[main_symbol++] + extra_cost;
}
extra_cost += costs->main[main_symbol++];
for (; i < LZX_NUM_LENS; i++) {
costs->match_cost[offset_slot][i] =
costs->len[i - LZX_NUM_PRIMARY_LENS] +
extra_cost;
}
}
}
/*
* Fast approximation for log2f(x). This is not as accurate as the standard C
* version. It does not need to be perfectly accurate because it is only used
* for estimating symbol costs, which is very approximate anyway.
*/
static float
log2f_fast(float x)
{
union {
float f;
s32 i;
} u = { .f = x };
/* Extract the exponent and subtract 127 to remove the bias. This gives
* the integer part of the result. */
float res = ((u.i >> 23) & 0xFF) - 127;
/* Set the exponent to 0 (plus bias of 127). This transforms the number
* to the range [1, 2) while retaining the same mantissa. */
u.i = (u.i & ~(0xFF << 23)) | (127 << 23);
/*
* Approximate the log2 of the transformed number using a degree 2
* interpolating polynomial for log2(x) over the interval [1, 2). Then
* add this to the extracted exponent to produce the final approximation
* of log2(x).
*
* The coefficients of the interpolating polynomial used here were found
* using the script tools/log2_interpolation.r.
*/
return res - 1.653124006f + u.f * (1.9941812f - u.f * 0.3347490189f);
}
/*
* Return the estimated cost of a symbol which has been estimated to have the
* given probability.
*/
static u32
lzx_cost_for_probability(float prob)
{
/*
* The basic formula is:
*
* entropy = -log2(probability)
*
* Use this to get the cost in fractional bits. Then multiply by our
* scaling factor of BIT_COST and convert to an integer.
*
* In addition, the minimum cost is BIT_COST (one bit) because the
* entropy coding method will be Huffman codes.
*
* Careful: even though 'prob' should be <= 1.0, 'log2f_fast(prob)' may
* be positive due to inaccuracy in our log2 approximation. Therefore,
* we cannot, in general, assume the computed cost is non-negative, and
* we should make sure negative costs get rounded up correctly.
*/
s32 cost = -log2f_fast(prob) * BIT_COST;
return max(cost, BIT_COST);
}
/*
* Mapping: number of used literals => heuristic probability of a literal times
* 6870. Generated by running this R command:
*
* cat(paste(round(6870*2^-((304+(0:256))/64)), collapse=", "))
*/
static const u8 literal_scaled_probs[257] = {
255, 253, 250, 247, 244, 242, 239, 237, 234, 232, 229, 227, 224, 222,
219, 217, 215, 212, 210, 208, 206, 203, 201, 199, 197, 195, 193, 191,
189, 186, 184, 182, 181, 179, 177, 175, 173, 171, 169, 167, 166, 164,
162, 160, 159, 157, 155, 153, 152, 150, 149, 147, 145, 144, 142, 141,
139, 138, 136, 135, 133, 132, 130, 129, 128, 126, 125, 124, 122, 121,
120, 118, 117, 116, 115, 113, 112, 111, 110, 109, 107, 106, 105, 104,
103, 102, 101, 100, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86,
86, 85, 84, 83, 82, 81, 80, 79, 78, 78, 77, 76, 75, 74, 73, 73, 72, 71,
70, 70, 69, 68, 67, 67, 66, 65, 65, 64, 63, 62, 62, 61, 60, 60, 59, 59,
58, 57, 57, 56, 55, 55, 54, 54, 53, 53, 52, 51, 51, 50, 50, 49, 49, 48,
48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 40,
39, 39, 38, 38, 38, 37, 37, 36, 36, 36, 35, 35, 34, 34, 34, 33, 33, 33,
32, 32, 32, 31, 31, 31, 30, 30, 30, 29, 29, 29, 28, 28, 28, 27, 27, 27,
27, 26, 26, 26, 25, 25, 25, 25, 24, 24, 24, 24, 23, 23, 23, 23, 22, 22,
22, 22, 21, 21, 21, 21, 20, 20, 20, 20, 20, 19, 19, 19, 19, 19, 18, 18,
18, 18, 18, 17, 17, 17, 17, 17, 16, 16, 16, 16
};
/*
* Mapping: length symbol => default cost of that symbol. This is derived from
* sample data but has been slightly edited to add more bias towards the
* shortest lengths, which are the most common.
*/
static const u16 lzx_default_len_costs[LZX_LENCODE_NUM_SYMBOLS] = {
300, 310, 320, 330, 360, 396, 399, 416, 451, 448, 463, 466, 505, 492,
503, 514, 547, 531, 566, 561, 589, 563, 592, 586, 623, 602, 639, 627,
659, 643, 657, 650, 685, 662, 661, 672, 685, 686, 696, 680, 657, 682,
666, 699, 674, 699, 679, 709, 688, 712, 692, 714, 694, 716, 698, 712,
706, 727, 714, 727, 713, 723, 712, 718, 719, 719, 720, 735, 725, 735,
728, 740, 727, 739, 727, 742, 716, 733, 733, 740, 738, 746, 737, 747,
738, 745, 736, 748, 742, 749, 745, 749, 743, 748, 741, 752, 745, 752,
747, 750, 747, 752, 748, 753, 750, 752, 753, 753, 749, 744, 752, 755,
753, 756, 745, 748, 746, 745, 723, 757, 755, 758, 755, 758, 752, 757,
754, 757, 755, 759, 755, 758, 753, 755, 755, 758, 757, 761, 755, 750,
758, 759, 759, 760, 758, 751, 757, 757, 759, 759, 758, 759, 758, 761,
750, 761, 758, 760, 759, 761, 758, 761, 760, 752, 759, 760, 759, 759,
757, 762, 760, 761, 761, 748, 761, 760, 762, 763, 752, 762, 762, 763,
762, 762, 763, 763, 762, 763, 762, 763, 762, 763, 763, 764, 763, 762,
763, 762, 762, 762, 764, 764, 763, 764, 763, 763, 763, 762, 763, 763,
762, 764, 764, 763, 762, 763, 763, 763, 763, 762, 764, 763, 762, 764,
764, 763, 763, 765, 764, 764, 762, 763, 764, 765, 763, 764, 763, 764,
762, 764, 764, 754, 763, 764, 763, 763, 762, 763, 584,
};
/* Set default costs to bootstrap the iterative optimization algorithm. */
static void
lzx_set_default_costs(struct lzx_compressor *c)
{
unsigned i;
u32 num_literals = 0;
u32 num_used_literals = 0;
float inv_num_matches = 1.0f / c->freqs.main[LZX_NUM_CHARS];
float inv_num_items;
float prob_match = 1.0f;
u32 match_cost;
float base_literal_prob;
/* Some numbers here have been hardcoded to assume a bit cost of 64. */
STATIC_ASSERT(BIT_COST == 64);
/* Estimate the number of literals that will used. 'num_literals' is
* the total number, whereas 'num_used_literals' is the number of
* distinct symbols. */
for (i = 0; i < LZX_NUM_CHARS; i++) {
num_literals += c->freqs.main[i];
num_used_literals += (c->freqs.main[i] != 0);
}
/* Note: all match headers were tallied as symbol 'LZX_NUM_CHARS'. We
* don't attempt to estimate which ones will be used. */
inv_num_items = 1.0f / (num_literals + c->freqs.main[LZX_NUM_CHARS]);
base_literal_prob = literal_scaled_probs[num_used_literals] *
(1.0f / 6870.0f);
/* Literal costs. We use two different methods to compute the
* probability of each literal and mix together their results. */
for (i = 0; i < LZX_NUM_CHARS; i++) {
u32 freq = c->freqs.main[i];
if (freq != 0) {
float prob = 0.5f * ((freq * inv_num_items) +
base_literal_prob);
c->costs.main[i] = lzx_cost_for_probability(prob);
prob_match -= prob;
} else {
c->costs.main[i] = 11 * BIT_COST;
}
}
/* Match header costs. We just assume that all match headers are
* equally probable, but we do take into account the relative cost of a
* match header vs. a literal depending on how common matches are
* expected to be vs. literals. */
prob_match = max(prob_match, 0.15f);
match_cost = lzx_cost_for_probability(prob_match / (c->num_main_syms -
LZX_NUM_CHARS));
for (; i < c->num_main_syms; i++)
c->costs.main[i] = match_cost;
/* Length symbol costs. These are just set to fixed values which
* reflect the fact the smallest lengths are typically the most common,
* and therefore are typically the cheapest. */
for (i = 0; i < LZX_LENCODE_NUM_SYMBOLS; i++)
c->costs.len[i] = lzx_default_len_costs[i];
#if CONSIDER_ALIGNED_COSTS
/* Aligned offset symbol costs. These are derived from the estimated
* probability of each aligned offset symbol. */
for (i = 0; i < LZX_ALIGNEDCODE_NUM_SYMBOLS; i++) {
/* We intentionally tallied the frequencies in the wrong slots,
* not accounting for LZX_OFFSET_ADJUSTMENT, since doing the
* fixup here is faster: a constant 8 subtractions here vs. one
* addition for every match. */
unsigned j = (i - LZX_OFFSET_ADJUSTMENT) & LZX_ALIGNED_OFFSET_BITMASK;
if (c->freqs.aligned[j] != 0) {
float prob = c->freqs.aligned[j] * inv_num_matches;
c->costs.aligned[i] = lzx_cost_for_probability(prob);
} else {
c->costs.aligned[i] =
(2 * LZX_NUM_ALIGNED_OFFSET_BITS) * BIT_COST;
}
}
#endif
}
/* Update the current cost model to reflect the computed Huffman codes. */
static void
lzx_set_costs_from_codes(struct lzx_compressor *c)
{
unsigned i;
const struct lzx_lens *lens = &c->codes[c->codes_index].lens;
for (i = 0; i < c->num_main_syms; i++) {
c->costs.main[i] = (lens->main[i] ? lens->main[i] :
MAIN_CODEWORD_LIMIT) * BIT_COST;
}
for (i = 0; i < LZX_LENCODE_NUM_SYMBOLS; i++) {
c->costs.len[i] = (lens->len[i] ? lens->len[i] :
LENGTH_CODEWORD_LIMIT) * BIT_COST;
}
#if CONSIDER_ALIGNED_COSTS
for (i = 0; i < LZX_ALIGNEDCODE_NUM_SYMBOLS; i++) {
c->costs.aligned[i] = (lens->aligned[i] ? lens->aligned[i] :
ALIGNED_CODEWORD_LIMIT) * BIT_COST;
}
#endif
}
/*
* Choose a "near-optimal" literal/match sequence to use for the current block,
* then flush the block. Because the cost of each Huffman symbol is unknown
* until the Huffman codes have been built and the Huffman codes themselves
* depend on the symbol frequencies, this uses an iterative optimization
* algorithm to approximate an optimal solution. The first optimization pass
* for the block uses default costs; additional passes use costs derived from
* the Huffman codes computed in the previous pass.
*/
static forceinline struct lzx_lru_queue
lzx_optimize_and_flush_block(struct lzx_compressor * const restrict c,
struct lzx_output_bitstream * const restrict os,
const u8 * const restrict block_begin,
const u32 block_size,
const struct lzx_lru_queue initial_queue,
bool is_16_bit)
{
unsigned num_passes_remaining = c->num_optim_passes;
struct lzx_lru_queue new_queue;
u32 seq_idx;
lzx_set_default_costs(c);
for (;;) {
lzx_compute_match_costs(c);
new_queue = lzx_find_min_cost_path(c, block_begin, block_size,
initial_queue, is_16_bit);
if (--num_passes_remaining == 0)
break;
/* At least one optimization pass remains. Update the costs. */
lzx_reset_symbol_frequencies(c);
lzx_tally_item_list(c, block_size, is_16_bit);
lzx_build_huffman_codes(c);
lzx_set_costs_from_codes(c);
}
/* Done optimizing. Generate the sequence list and flush the block. */
lzx_reset_symbol_frequencies(c);
seq_idx = lzx_record_item_list(c, block_size, is_16_bit);
lzx_flush_block(c, os, block_begin, block_size, seq_idx);
return new_queue;
}
/*
* This is the "near-optimal" LZX compressor.
*
* For each block, it performs a relatively thorough graph search to find an
* inexpensive (in terms of compressed size) way to output the block.
*
* Note: there are actually many things this algorithm leaves on the table in
* terms of compression ratio. So although it may be "near-optimal", it is
* certainly not "optimal". The goal is not to produce the optimal compression
* ratio, which for LZX is probably impossible within any practical amount of
* time, but rather to produce a compression ratio significantly better than a
* simpler "greedy" or "lazy" parse while still being relatively fast.
*/
static forceinline void
lzx_compress_near_optimal(struct lzx_compressor * restrict c,
const u8 * const restrict in_begin, size_t in_nbytes,
struct lzx_output_bitstream * restrict os,
bool is_16_bit)
{
const u8 * in_next = in_begin;
const u8 * const in_end = in_begin + in_nbytes;
u32 max_len = LZX_MAX_MATCH_LEN;
u32 nice_len = min(c->nice_match_length, max_len);
u32 next_hashes[2] = {0, 0};
struct lzx_lru_queue queue = LZX_QUEUE_INITIALIZER;
/* Initialize the matchfinder. */
CALL_BT_MF(is_16_bit, c, bt_matchfinder_init);
do {
/* Starting a new block */
const u8 * const in_block_begin = in_next;
const u8 * const in_max_block_end =
in_next + min(SOFT_MAX_BLOCK_SIZE, in_end - in_next);
struct lz_match *cache_ptr = c->match_cache;
const u8 *next_search_pos = in_next;
const u8 *next_observation = in_next;
const u8 *next_pause_point =
min(in_next + min(MIN_BLOCK_SIZE,
in_max_block_end - in_next),
in_max_block_end - min(LZX_MAX_MATCH_LEN - 1,
in_max_block_end - in_next));
lzx_init_block_split_stats(&c->split_stats);
lzx_reset_symbol_frequencies(c);
if (in_next >= next_pause_point)
goto pause;
/*
* Run the input buffer through the matchfinder, caching the
* matches, until we decide to end the block.
*
* For a tighter matchfinding loop, we compute a "pause point",
* which is the next position at which we may need to check
* whether to end the block or to decrease max_len. We then
* only do these extra checks upon reaching the pause point.
*/
resume_matchfinding:
do {
if (in_next >= next_search_pos) {
/* Search for matches at this position. */
struct lz_match *lz_matchptr;
u32 best_len;
lz_matchptr = CALL_BT_MF(is_16_bit, c,
bt_matchfinder_get_matches,
in_begin,
in_next - in_begin,
max_len,
nice_len,
c->max_search_depth,
next_hashes,
&best_len,
cache_ptr + 1);
cache_ptr->length = lz_matchptr - (cache_ptr + 1);
cache_ptr = lz_matchptr;
/* Accumulate literal/match statistics for block
* splitting and for generating the initial cost
* model. */
if (in_next >= next_observation) {
best_len = cache_ptr[-1].length;
if (best_len >= 3) {
/* Match (len >= 3) */
/*
* Note: for performance reasons this has
* been simplified significantly:
*
* - We wait until later to account for
* LZX_OFFSET_ADJUSTMENT.
* - We don't account for repeat offsets.
* - We don't account for different match headers.
*/
c->freqs.aligned[cache_ptr[-1].offset &
LZX_ALIGNED_OFFSET_BITMASK]++;
c->freqs.main[LZX_NUM_CHARS]++;
lzx_observe_match(&c->split_stats, best_len);
next_observation = in_next + best_len;
} else {
/* Literal */
c->freqs.main[*in_next]++;
lzx_observe_literal(&c->split_stats, *in_next);
next_observation = in_next + 1;
}
}
/*
* If there was a very long match found, then
* don't cache any matches for the bytes covered
* by that match. This avoids degenerate
* behavior when compressing highly redundant
* data, where the number of matches can be very
* large.
*
* This heuristic doesn't actually hurt the
* compression ratio *too* much. If there's a
* long match, then the data must be highly
* compressible, so it doesn't matter as much
* what we do.
*/
if (best_len >= nice_len)
next_search_pos = in_next + best_len;
} else {
/* Don't search for matches at this position. */
CALL_BT_MF(is_16_bit, c,
bt_matchfinder_skip_byte,
in_begin,
in_next - in_begin,
nice_len,
c->max_search_depth,
next_hashes);
cache_ptr->length = 0;
cache_ptr++;
}
} while (++in_next < next_pause_point &&
likely(cache_ptr < &c->match_cache[CACHE_LENGTH]));
pause:
/* Adjust max_len and nice_len if we're nearing the end of the
* input buffer. In addition, if we are so close to the end of
* the input buffer that there cannot be any more matches, then
* just advance through the last few positions and record no
* matches. */
if (unlikely(max_len > in_end - in_next)) {
max_len = in_end - in_next;
nice_len = min(max_len, nice_len);
if (max_len < BT_MATCHFINDER_REQUIRED_NBYTES) {
while (in_next != in_end) {
cache_ptr->length = 0;
cache_ptr++;
in_next++;
}
}
}
/* End the block if the match cache may overflow. */
if (unlikely(cache_ptr >= &c->match_cache[CACHE_LENGTH]))
goto end_block;
/* End the block if the soft maximum size has been reached. */
if (in_next >= in_max_block_end)
goto end_block;
/* End the block if the block splitting algorithm thinks this is
* a good place to do so. */
if (c->split_stats.num_new_observations >=
NUM_OBSERVATIONS_PER_BLOCK_CHECK &&
in_max_block_end - in_next >= MIN_BLOCK_SIZE &&
lzx_should_end_block(&c->split_stats))
goto end_block;
/* It's not time to end the block yet. Compute the next pause
* point and resume matchfinding. */
next_pause_point =
min(in_next + min(NUM_OBSERVATIONS_PER_BLOCK_CHECK * 2 -
c->split_stats.num_new_observations,
in_max_block_end - in_next),
in_max_block_end - min(LZX_MAX_MATCH_LEN - 1,
in_max_block_end - in_next));
goto resume_matchfinding;
end_block:
/* We've decided on a block boundary and cached matches. Now
* choose a match/literal sequence and flush the block. */
queue = lzx_optimize_and_flush_block(c, os, in_block_begin,
in_next - in_block_begin,
queue, is_16_bit);
} while (in_next != in_end);
}
static void
lzx_compress_near_optimal_16(struct lzx_compressor *c, const u8 *in,
size_t in_nbytes, struct lzx_output_bitstream *os)
{
lzx_compress_near_optimal(c, in, in_nbytes, os, true);
}
static void
lzx_compress_near_optimal_32(struct lzx_compressor *c, const u8 *in,
size_t in_nbytes, struct lzx_output_bitstream *os)
{
lzx_compress_near_optimal(c, in, in_nbytes, os, false);
}
/******************************************************************************/
/* Faster ("lazy") compression algorithm */
/*----------------------------------------------------------------------------*/
/*
* Called when the compressor chooses to use a literal. This tallies the
* Huffman symbol for the literal, increments the current literal run length,
* and "observes" the literal for the block split statistics.
*/
static forceinline void
lzx_choose_literal(struct lzx_compressor *c, unsigned literal, u32 *litrunlen_p)
{
lzx_observe_literal(&c->split_stats, literal);
c->freqs.main[literal]++;
++*litrunlen_p;
}
/*
* Called when the compressor chooses to use a match. This tallies the Huffman
* symbol(s) for a match, saves the match data and the length of the preceding
* literal run, updates the recent offsets queue, and "observes" the match for
* the block split statistics.
*/
static forceinline void
lzx_choose_match(struct lzx_compressor *c, unsigned length, u32 adjusted_offset,
u32 recent_offsets[LZX_NUM_RECENT_OFFSETS], bool is_16_bit,
u32 *litrunlen_p, struct lzx_sequence **next_seq_p)
{
struct lzx_sequence *next_seq = *next_seq_p;
unsigned mainsym;
lzx_observe_match(&c->split_stats, length);
mainsym = lzx_tally_main_and_lensyms(c, length, adjusted_offset,
is_16_bit);
next_seq->litrunlen_and_matchlen =
(*litrunlen_p << SEQ_MATCHLEN_BITS) | length;
next_seq->adjusted_offset_and_mainsym =
(adjusted_offset << SEQ_MAINSYM_BITS) | mainsym;
/* Update the recent offsets queue. */
if (adjusted_offset < LZX_NUM_RECENT_OFFSETS) {
/* Repeat offset match. */
swap(recent_offsets[0], recent_offsets[adjusted_offset]);
} else {
/* Explicit offset match. */
/* Tally the aligned offset symbol if needed. */
if (adjusted_offset >= LZX_MIN_ALIGNED_OFFSET + LZX_OFFSET_ADJUSTMENT)
c->freqs.aligned[adjusted_offset & LZX_ALIGNED_OFFSET_BITMASK]++;
recent_offsets[2] = recent_offsets[1];
recent_offsets[1] = recent_offsets[0];
recent_offsets[0] = adjusted_offset - LZX_OFFSET_ADJUSTMENT;
}
/* Reset the literal run length and advance to the next sequence. */
*next_seq_p = next_seq + 1;
*litrunlen_p = 0;
}
/*
* Called when the compressor ends a block. This finshes the last lzx_sequence,
* which is just a literal run with no following match. This literal run might
* be empty.
*/
static forceinline void
lzx_finish_sequence(struct lzx_sequence *last_seq, u32 litrunlen)
{
last_seq->litrunlen_and_matchlen = litrunlen << SEQ_MATCHLEN_BITS;
}
/*
* Find the longest repeat offset match with the current position. If a match
* is found, return its length and set *best_rep_idx_ret to the index of its
* offset in @recent_offsets. Otherwise, return 0.
*
* Don't bother with length 2 matches; consider matches of length >= 3 only.
* Also assume that max_len >= 3.
*/
static unsigned
lzx_find_longest_repeat_offset_match(const u8 * const in_next,
const u32 recent_offsets[],
const unsigned max_len,
unsigned *best_rep_idx_ret)
{
STATIC_ASSERT(LZX_NUM_RECENT_OFFSETS == 3); /* loop is unrolled */
const u32 seq3 = load_u24_unaligned(in_next);
const u8 *matchptr;
unsigned best_rep_len = 0;
unsigned best_rep_idx = 0;
unsigned rep_len;
/* Check for rep0 match (most recent offset) */
matchptr = in_next - recent_offsets[0];
if (load_u24_unaligned(matchptr) == seq3)
best_rep_len = lz_extend(in_next, matchptr, 3, max_len);
/* Check for rep1 match (second most recent offset) */
matchptr = in_next - recent_offsets[1];
if (load_u24_unaligned(matchptr) == seq3) {
rep_len = lz_extend(in_next, matchptr, 3, max_len);
if (rep_len > best_rep_len) {
best_rep_len = rep_len;
best_rep_idx = 1;
}
}
/* Check for rep2 match (third most recent offset) */
matchptr = in_next - recent_offsets[2];
if (load_u24_unaligned(matchptr) == seq3) {
rep_len = lz_extend(in_next, matchptr, 3, max_len);
if (rep_len > best_rep_len) {
best_rep_len = rep_len;
best_rep_idx = 2;
}
}
*best_rep_idx_ret = best_rep_idx;
return best_rep_len;
}
/*
* Fast heuristic scoring for lazy parsing: how "good" is this match?
* This is mainly determined by the length: longer matches are better.
* However, we also give a bonus to close (small offset) matches and to repeat
* offset matches, since those require fewer bits to encode.
*/
static forceinline unsigned
lzx_explicit_offset_match_score(unsigned len, u32 adjusted_offset)
{
unsigned score = len;
if (adjusted_offset < 4096)
score++;
if (adjusted_offset < 256)
score++;
return score;
}
static forceinline unsigned
lzx_repeat_offset_match_score(unsigned rep_len, unsigned rep_idx)
{
return rep_len + 3;
}
/*
* This is the "lazy" LZX compressor. The basic idea is that before it chooses
* a match, it checks to see if there's a longer match at the next position. If
* yes, it chooses a literal and continues to the next position. If no, it
* chooses the match.
*
* Some additional heuristics are used as well. Repeat offset matches are
* considered favorably and sometimes are chosen immediately. In addition, long
* matches (at least "nice_len" bytes) are chosen immediately as well. Finally,
* when we decide whether a match is "better" than another, we take the offset
* into consideration as well as the length.
*/
static forceinline void
lzx_compress_lazy(struct lzx_compressor * restrict c,
const u8 * const restrict in_begin, size_t in_nbytes,
struct lzx_output_bitstream * restrict os, bool is_16_bit)
{
const u8 * in_next = in_begin;
const u8 * const in_end = in_begin + in_nbytes;
unsigned max_len = LZX_MAX_MATCH_LEN;
unsigned nice_len = min(c->nice_match_length, max_len);
STATIC_ASSERT(LZX_NUM_RECENT_OFFSETS == 3);
u32 recent_offsets[LZX_NUM_RECENT_OFFSETS] = {1, 1, 1};
u32 next_hashes[2] = {0, 0};
/* Initialize the matchfinder. */
CALL_HC_MF(is_16_bit, c, hc_matchfinder_init);
do {
/* Starting a new block */
const u8 * const in_block_begin = in_next;
const u8 * const in_max_block_end =
in_next + min(SOFT_MAX_BLOCK_SIZE, in_end - in_next);
struct lzx_sequence *next_seq = c->chosen_sequences;
u32 litrunlen = 0;
unsigned cur_len;
u32 cur_offset;
u32 cur_adjusted_offset;
unsigned cur_score;
unsigned next_len;
u32 next_offset;
u32 next_adjusted_offset;
unsigned next_score;
unsigned best_rep_len;
unsigned best_rep_idx;
unsigned rep_score;
unsigned skip_len;
lzx_reset_symbol_frequencies(c);
lzx_init_block_split_stats(&c->split_stats);
do {
/* Adjust max_len and nice_len if we're nearing the end
* of the input buffer. */
if (unlikely(max_len > in_end - in_next)) {
max_len = in_end - in_next;
nice_len = min(max_len, nice_len);
}
/* Find the longest match (subject to the
* max_search_depth cutoff parameter) with the current
* position. Don't bother with length 2 matches; only
* look for matches of length >= 3. */
cur_len = CALL_HC_MF(is_16_bit, c,
hc_matchfinder_longest_match,
in_begin,
in_next,
2,
max_len,
nice_len,
c->max_search_depth,
next_hashes,
&cur_offset);
/* If there was no match found, or the only match found
* was a distant short match, then choose a literal. */
if (cur_len < 3 ||
(cur_len == 3 &&
cur_offset >= 8192 - LZX_OFFSET_ADJUSTMENT &&
cur_offset != recent_offsets[0] &&
cur_offset != recent_offsets[1] &&
cur_offset != recent_offsets[2]))
{
lzx_choose_literal(c, *in_next, &litrunlen);
in_next++;
continue;
}
/* Heuristic: if this match has the most recent offset,
* then go ahead and choose it as a rep0 match. */
if (cur_offset == recent_offsets[0]) {
in_next++;
skip_len = cur_len - 1;
cur_adjusted_offset = 0;
goto choose_cur_match;
}
/* Compute the longest match's score as an explicit
* offset match. */
cur_adjusted_offset = cur_offset + LZX_OFFSET_ADJUSTMENT;
cur_score = lzx_explicit_offset_match_score(cur_len, cur_adjusted_offset);
/* Find the longest repeat offset match at this
* position. If we find one and it's "better" than the
* explicit offset match we found, then go ahead and
* choose the repeat offset match immediately. */
best_rep_len = lzx_find_longest_repeat_offset_match(in_next,
recent_offsets,
max_len,
&best_rep_idx);
in_next++;
if (best_rep_len != 0 &&
(rep_score = lzx_repeat_offset_match_score(best_rep_len,
best_rep_idx)) >= cur_score)
{
cur_len = best_rep_len;
cur_adjusted_offset = best_rep_idx;
skip_len = best_rep_len - 1;
goto choose_cur_match;
}
have_cur_match:
/*
* We have a match at the current position. If the
* match is very long, then choose it immediately.
* Otherwise, see if there's a better match at the next
* position.
*/
if (cur_len >= nice_len) {
skip_len = cur_len - 1;
goto choose_cur_match;
}
if (unlikely(max_len > in_end - in_next)) {
max_len = in_end - in_next;
nice_len = min(max_len, nice_len);
}
next_len = CALL_HC_MF(is_16_bit, c,
hc_matchfinder_longest_match,
in_begin,
in_next,
cur_len - 2,
max_len,
nice_len,
c->max_search_depth / 2,
next_hashes,
&next_offset);
if (next_len <= cur_len - 2) {
/* No potentially better match was found. */
in_next++;
skip_len = cur_len - 2;
goto choose_cur_match;
}
next_adjusted_offset = next_offset + LZX_OFFSET_ADJUSTMENT;
next_score = lzx_explicit_offset_match_score(next_len, next_adjusted_offset);
best_rep_len = lzx_find_longest_repeat_offset_match(in_next,
recent_offsets,
max_len,
&best_rep_idx);
in_next++;
if (best_rep_len != 0 &&
(rep_score = lzx_repeat_offset_match_score(best_rep_len,
best_rep_idx)) >= next_score)
{
if (rep_score > cur_score) {
/* The next match is better, and it's a
* repeat offset match. */
lzx_choose_literal(c, *(in_next - 2),
&litrunlen);
cur_len = best_rep_len;
cur_adjusted_offset = best_rep_idx;
skip_len = cur_len - 1;
goto choose_cur_match;
}
} else {
if (next_score > cur_score) {
/* The next match is better, and it's an
* explicit offset match. */
lzx_choose_literal(c, *(in_next - 2),
&litrunlen);
cur_len = next_len;
cur_adjusted_offset = next_adjusted_offset;
cur_score = next_score;
goto have_cur_match;
}
}
/* The original match was better; choose it. */
skip_len = cur_len - 2;
choose_cur_match:
/* Choose a match and have the matchfinder skip over its
* remaining bytes. */
lzx_choose_match(c, cur_len, cur_adjusted_offset,
recent_offsets, is_16_bit,
&litrunlen, &next_seq);
CALL_HC_MF(is_16_bit, c,
hc_matchfinder_skip_bytes,
in_begin,
in_next,
in_end,
skip_len,
next_hashes);
in_next += skip_len;
/* Keep going until it's time to end the block. */
} while (in_next < in_max_block_end &&
!(c->split_stats.num_new_observations >=
NUM_OBSERVATIONS_PER_BLOCK_CHECK &&
in_next - in_block_begin >= MIN_BLOCK_SIZE &&
in_end - in_next >= MIN_BLOCK_SIZE &&
lzx_should_end_block(&c->split_stats)));
/* Flush the block. */
lzx_finish_sequence(next_seq, litrunlen);
lzx_flush_block(c, os, in_block_begin, in_next - in_block_begin, 0);
/* Keep going until we've reached the end of the input buffer. */
} while (in_next != in_end);
}
static void
lzx_compress_lazy_16(struct lzx_compressor *c, const u8 *in, size_t in_nbytes,
struct lzx_output_bitstream *os)
{
lzx_compress_lazy(c, in, in_nbytes, os, true);
}
static void
lzx_compress_lazy_32(struct lzx_compressor *c, const u8 *in, size_t in_nbytes,
struct lzx_output_bitstream *os)
{
lzx_compress_lazy(c, in, in_nbytes, os, false);
}
/******************************************************************************/
/* Compressor operations */
/*----------------------------------------------------------------------------*/
/*
* Generate tables for mapping match offsets (actually, "adjusted" match
* offsets) to offset slots.
*/
static void
lzx_init_offset_slot_tabs(struct lzx_compressor *c)
{
u32 adjusted_offset = 0;
unsigned slot = 0;
/* slots [0, 29] */
for (; adjusted_offset < ARRAY_LEN(c->offset_slot_tab_1);
adjusted_offset++)
{
if (adjusted_offset >= lzx_offset_slot_base[slot + 1] +
LZX_OFFSET_ADJUSTMENT)
slot++;
c->offset_slot_tab_1[adjusted_offset] = slot;
}
/* slots [30, 49] */
for (; adjusted_offset < LZX_MAX_WINDOW_SIZE;
adjusted_offset += (u32)1 << 14)
{
if (adjusted_offset >= lzx_offset_slot_base[slot + 1] +
LZX_OFFSET_ADJUSTMENT)
slot++;
c->offset_slot_tab_2[adjusted_offset >> 14] = slot;
}
}
static size_t
lzx_get_compressor_size(size_t max_bufsize, unsigned compression_level)
{
if (compression_level <= MAX_FAST_LEVEL) {
if (lzx_is_16_bit(max_bufsize))
return offsetof(struct lzx_compressor, hc_mf_16) +
hc_matchfinder_size_16(max_bufsize);
else
return offsetof(struct lzx_compressor, hc_mf_32) +
hc_matchfinder_size_32(max_bufsize);
} else {
if (lzx_is_16_bit(max_bufsize))
return offsetof(struct lzx_compressor, bt_mf_16) +
bt_matchfinder_size_16(max_bufsize);
else
return offsetof(struct lzx_compressor, bt_mf_32) +
bt_matchfinder_size_32(max_bufsize);
}
}
/* Compute the amount of memory needed to allocate an LZX compressor. */
static u64
lzx_get_needed_memory(size_t max_bufsize, unsigned compression_level,
bool destructive)
{
u64 size = 0;
if (max_bufsize > LZX_MAX_WINDOW_SIZE)
return 0;
size += lzx_get_compressor_size(max_bufsize, compression_level);
if (!destructive)
size += max_bufsize; /* account for in_buffer */
return size;
}
/* Allocate an LZX compressor. */
static int
lzx_create_compressor(size_t max_bufsize, unsigned compression_level,
bool destructive, void **c_ret)
{
unsigned window_order;
struct lzx_compressor *c;
/* Validate the maximum buffer size and get the window order from it. */
window_order = lzx_get_window_order(max_bufsize);
if (window_order == 0)
return WIMLIB_ERR_INVALID_PARAM;
/* Allocate the compressor. */
c = MALLOC(lzx_get_compressor_size(max_bufsize, compression_level));
if (!c)
goto oom0;
c->window_order = window_order;
c->num_main_syms = lzx_get_num_main_syms(window_order);
c->destructive = destructive;
/* Allocate the buffer for preprocessed data if needed. */
if (!c->destructive) {
c->in_buffer = MALLOC(max_bufsize);
if (!c->in_buffer)
goto oom1;
}
if (compression_level <= MAX_FAST_LEVEL) {
/* Fast compression: Use lazy parsing. */
if (lzx_is_16_bit(max_bufsize))
c->impl = lzx_compress_lazy_16;
else
c->impl = lzx_compress_lazy_32;
/* Scale max_search_depth and nice_match_length with the
* compression level. */
c->max_search_depth = (60 * compression_level) / 20;
c->nice_match_length = (80 * compression_level) / 20;
/* lzx_compress_lazy() needs max_search_depth >= 2 because it
* halves the max_search_depth when attempting a lazy match, and
* max_search_depth must be at least 1. */
c->max_search_depth = max(c->max_search_depth, 2);
} else {
/* Normal / high compression: Use near-optimal parsing. */
if (lzx_is_16_bit(max_bufsize))
c->impl = lzx_compress_near_optimal_16;
else
c->impl = lzx_compress_near_optimal_32;
/* Scale max_search_depth and nice_match_length with the
* compression level. */
c->max_search_depth = (24 * compression_level) / 50;
c->nice_match_length = (48 * compression_level) / 50;
/* Also scale num_optim_passes with the compression level. But
* the more passes there are, the less they help --- so don't
* add them linearly. */
c->num_optim_passes = 1;
c->num_optim_passes += (compression_level >= 45);
c->num_optim_passes += (compression_level >= 70);
c->num_optim_passes += (compression_level >= 100);
c->num_optim_passes += (compression_level >= 150);
c->num_optim_passes += (compression_level >= 200);
c->num_optim_passes += (compression_level >= 300);
/* max_search_depth must be at least 1. */
c->max_search_depth = max(c->max_search_depth, 1);
}
/* Prepare the offset => offset slot mapping. */
lzx_init_offset_slot_tabs(c);
*c_ret = c;
return 0;
oom1:
FREE(c);
oom0:
return WIMLIB_ERR_NOMEM;
}
/* Compress a buffer of data. */
static size_t
lzx_compress(const void *restrict in, size_t in_nbytes,
void *restrict out, size_t out_nbytes_avail, void *restrict _c)
{
struct lzx_compressor *c = _c;
struct lzx_output_bitstream os;
size_t result;
/* Don't bother trying to compress very small inputs. */
if (in_nbytes < 64)
return 0;
/* If the compressor is in "destructive" mode, then we can directly
* preprocess the input data. Otherwise, we need to copy it into an
* internal buffer first. */
if (!c->destructive) {
memcpy(c->in_buffer, in, in_nbytes);
in = c->in_buffer;
}
/* Preprocess the input data. */
lzx_preprocess((void *)in, in_nbytes);
/* Initially, the previous Huffman codeword lengths are all zeroes. */
c->codes_index = 0;
memset(&c->codes[1].lens, 0, sizeof(struct lzx_lens));
/* Initialize the output bitstream. */
lzx_init_output(&os, out, out_nbytes_avail);
/* Call the compression level-specific compress() function. */
(*c->impl)(c, in, in_nbytes, &os);
/* Flush the output bitstream. */
result = lzx_flush_output(&os);
/* If the data did not compress to less than its original size and we
* preprocessed the original buffer, then postprocess it to restore it
* to its original state. */
if (result == 0 && c->destructive)
lzx_postprocess((void *)in, in_nbytes);
/* Return the number of compressed bytes, or 0 if the input did not
* compress to less than its original size. */
return result;
}
/* Free an LZX compressor. */
static void
lzx_free_compressor(void *_c)
{
struct lzx_compressor *c = _c;
if (!c->destructive)
FREE(c->in_buffer);
FREE(c);
}
const struct compressor_ops lzx_compressor_ops = {
.get_needed_memory = lzx_get_needed_memory,
.create_compressor = lzx_create_compressor,
.compress = lzx_compress,
.free_compressor = lzx_free_compressor,
};
wimlib-1.14.5/src/mount_image.c 0000644 0001750 0001750 00000202621 15137020663 013624 0 ustar 00e e /*
* mount_image.c
*
* This file implements mounting of WIM images using FUSE
* (Filesystem in Userspace). See https://github.com/libfuse/libfuse
*
* Currently it is only expected to work on Linux.
*/
/*
* Copyright 2012-2023 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib.h"
#include "wimlib/error.h"
#ifdef WITH_FUSE
#ifdef _WIN32
# error "FUSE mount not supported on Windows! Please configure --without-fuse"
#endif
#define FUSE_USE_VERSION 30
#include /* sometimes required before */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "wimlib/blob_table.h"
#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/metadata.h"
#include "wimlib/paths.h"
#include "wimlib/progress.h"
#include "wimlib/reparse.h"
#include "wimlib/threads.h"
#include "wimlib/timestamp.h"
#include "wimlib/unix_data.h"
#include "wimlib/write.h"
#include "wimlib/xml.h"
#ifndef O_NOFOLLOW
# define O_NOFOLLOW 0 /* Security only... */
#endif
#ifndef ENOATTR
# define ENOATTR ENODATA
#endif
#ifndef RENAME_NOREPLACE
# define RENAME_NOREPLACE (1 << 0)
#endif
#ifndef RENAME_EXCHANGE
# define RENAME_EXCHANGE (1 << 1)
#endif
#define WIMFS_MQUEUE_NAME_LEN 32
#define WIMLIB_UNMOUNT_FLAG_SEND_PROGRESS 0x80000000
struct wimfs_unmount_info {
unsigned unmount_flags;
char mq_name[WIMFS_MQUEUE_NAME_LEN + 1];
};
struct commit_progress_report {
enum wimlib_progress_msg msg;
union wimlib_progress_info info;
};
/* Description of an open file on a mounted WIM image. Actually, this
* represents the open state of a particular data stream of an inode, rather
* than the inode itself. (An inode might have multiple named data streams in
* addition to the default, unnamed data stream.) At a given time, an inode in
* the WIM image might have multiple file descriptors open to it, each to any
* one of its data streams. */
struct wimfs_fd {
/* Pointer to the inode of this open file.
* 'i_num_opened_fds' of the inode tracks the number of file descriptors
* that reference it. */
struct wim_inode *f_inode;
/* Pointer to the blob descriptor for the data stream that has been
* opened. 'num_opened_fds' of the blob descriptor tracks the number of
* file descriptors that reference it. Or, this value may be NULL,
* which indicates that the opened stream is empty and consequently does
* not have a blob descriptor. */
struct blob_descriptor *f_blob;
/* If valid (filedes_valid(&f_staging_fd)), this contains the
* corresponding native file descriptor for the staging file that has
* been created for reading from and/or writing to this open stream. A
* single staging file might have multiple file descriptors open to it
* simultaneously, each used by a different 'struct wimfs_fd'.
*
* Or, if invalid (!filedes_valid(&f_staging_fd)), this 'struct
* wimfs_fd' is not associated with a staging file. This is permissible
* only if this 'struct wimfs_fd' was opened read-only and the stream
* has not yet been extracted to a staging file. */
struct filedes f_staging_fd;
/* 0-based index of this file descriptor in the file descriptor table of
* its inode. */
u16 f_idx;
/* Unique ID of the opened stream in the inode. This will stay the same
* even if the indices of the inode's streams are changed by a deletion.
*/
u32 f_stream_id;
};
#define WIMFS_FD(fi) ((struct wimfs_fd *)(uintptr_t)((fi)->fh))
/* Context structure for a mounted WIM image. */
struct wimfs_context {
/* The WIMStruct containing the mounted image. The mounted image is the
* currently selected image (wim->current_image). */
WIMStruct *wim;
/* Flags passed to wimlib_mount_image() (WIMLIB_MOUNT_FLAG_*). */
int mount_flags;
/* Default flags for path lookup in the WIM image. */
int default_lookup_flags;
/* Information about the user who has mounted the WIM image */
uid_t owner_uid;
gid_t owner_gid;
/* Absolute path to the mountpoint directory (may be needed for absolute
* symbolic link fixups) */
char *mountpoint_abspath;
size_t mountpoint_abspath_nchars;
/* Information about the staging directory for a read-write mount. */
int parent_dir_fd;
int staging_dir_fd;
char *staging_dir_name;
/* For read-write mounts, the inode number to be assigned to the next
* created file. Note: since this isn't a persistent filesystem and we
* can re-assign the inode numbers just before mounting the image, it's
* good enough to just generate inode numbers sequentially. */
u64 next_ino;
/* Number of file descriptors open to the mounted WIM image. */
unsigned long num_open_fds;
/* For read-write mounts, the original metadata resource of the mounted
* image. */
struct blob_descriptor *metadata_resource;
/* Parameters for unmounting the image (can be set via extended
* attribute "wimfs.unmount_info"). */
struct wimfs_unmount_info unmount_info;
};
#define WIMFS_CTX(fuse_ctx) ((struct wimfs_context*)(fuse_ctx)->private_data)
/* Retrieve the context structure for the currently mounted WIM image.
*
* Note: this is a per-thread variable. It is possible for different threads to
* mount different images at the same time in the same process, although they
* must use different WIMStructs! */
static inline struct wimfs_context *
wimfs_get_context(void)
{
return WIMFS_CTX(fuse_get_context());
}
static void
wimfs_inc_num_open_fds(void)
{
wimfs_get_context()->num_open_fds++;
}
static void
wimfs_dec_num_open_fds(void)
{
wimfs_get_context()->num_open_fds--;
}
/* Retrieve the WIMStruct for the currently mounted WIM image. */
static inline WIMStruct *
wimfs_get_WIMStruct(void)
{
return wimfs_get_context()->wim;
}
/* Is write permission requested on the file? */
static inline bool
flags_writable(int open_flags)
{
int accmode = (open_flags & O_ACCMODE);
return (accmode == O_RDWR || accmode == O_WRONLY);
}
static mode_t
fuse_mask_mode(mode_t mode, const struct fuse_context *fuse_ctx)
{
return mode & ~fuse_ctx->umask;
}
/*
* Allocate a file descriptor to a data stream in the mounted WIM image.
*
* @inode
* The inode containing the stream being opened
* @strm
* The stream of the inode being opened
* @fd_ret
* On success, a pointer to the new file descriptor will be stored here.
*
* Returns 0 or a -errno code.
*/
static int
alloc_wimfs_fd(struct wim_inode *inode,
struct wim_inode_stream *strm,
struct wimfs_fd **fd_ret)
{
static const u16 min_fds_per_alloc = 8;
static const u16 max_fds = 0xffff;
u16 i;
struct wimfs_fd *fd;
if (inode->i_num_opened_fds == inode->i_num_allocated_fds) {
u16 num_new_fds;
struct wimfs_fd **fds;
/* Expand this inode's file descriptor table. */
num_new_fds = max(min_fds_per_alloc,
inode->i_num_allocated_fds / 4);
num_new_fds = min(num_new_fds,
max_fds - inode->i_num_allocated_fds);
if (num_new_fds == 0)
return -EMFILE;
fds = REALLOC(inode->i_fds,
(inode->i_num_allocated_fds + num_new_fds) *
sizeof(fds[0]));
if (!fds)
return -ENOMEM;
memset(&fds[inode->i_num_allocated_fds], 0,
num_new_fds * sizeof(fds[0]));
inode->i_fds = fds;
inode->i_num_allocated_fds += num_new_fds;
inode->i_next_fd = inode->i_num_opened_fds;
}
/* Allocate the file descriptor in the first available space in the
* inode's file descriptor table.
*
* i_next_fd is the lower bound on the next open slot. */
for (i = inode->i_next_fd; inode->i_fds[i]; i++)
;
fd = MALLOC(sizeof(*fd));
if (!fd)
return -ENOMEM;
fd->f_inode = inode;
fd->f_blob = stream_blob_resolved(strm);
filedes_invalidate(&fd->f_staging_fd);
fd->f_idx = i;
fd->f_stream_id = strm->stream_id;
*fd_ret = fd;
inode->i_fds[i] = fd;
inode->i_num_opened_fds++;
if (fd->f_blob)
fd->f_blob->num_opened_fds++;
wimfs_inc_num_open_fds();
inode->i_next_fd = i + 1;
return 0;
}
/*
* Close a file descriptor to a data stream in the mounted WIM image.
*
* Returns 0 or a -errno code. The file descriptor is always closed.
*/
static int
close_wimfs_fd(struct wimfs_fd *fd)
{
int ret = 0;
struct wim_inode *inode;
/* Close the staging file if open. */
if (filedes_valid(&fd->f_staging_fd))
if (filedes_close(&fd->f_staging_fd))
ret = -errno;
/* Release this file descriptor from its blob descriptor. */
if (fd->f_blob)
blob_decrement_num_opened_fds(fd->f_blob);
wimfs_dec_num_open_fds();
/* Release this file descriptor from its inode. */
inode = fd->f_inode;
inode->i_fds[fd->f_idx] = NULL;
if (fd->f_idx < inode->i_next_fd)
inode->i_next_fd = fd->f_idx;
FREE(fd);
inode_dec_num_opened_fds(inode);
return ret;
}
/*
* Translate a path into the corresponding inode in the mounted WIM image.
*
* See get_dentry() for more information.
*
* Returns a pointer to the resulting inode, or NULL with errno set.
*/
static struct wim_inode *
wim_pathname_to_inode(WIMStruct *wim, const char *path)
{
struct wim_dentry *dentry;
dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
if (!dentry)
return NULL;
return dentry->d_inode;
}
/* Can look up named data stream with colon syntax */
#define LOOKUP_FLAG_ADS_OK 0x01
/* Can look up directory (otherwise get -ENOTDIR) */
#define LOOKUP_FLAG_DIRECTORY_OK 0x02
/* Get the data stream of the specified name from the specified inode. Returns
* NULL with errno set if not found. */
static struct wim_inode_stream *
inode_get_data_stream_tstr(const struct wim_inode *inode,
const char *stream_name)
{
struct wim_inode_stream *strm;
if (!stream_name || !*stream_name) {
strm = inode_get_unnamed_data_stream(inode);
} else {
const utf16lechar *uname;
if (tstr_get_utf16le(stream_name, &uname))
return NULL;
strm = inode_get_stream(inode, STREAM_TYPE_DATA, uname);
tstr_put_utf16le(uname);
}
if (!strm)
errno = ENOENT;
return strm;
}
/*
* Translate a path into the corresponding dentry and stream in the mounted WIM
* image.
*
* Returns 0 or a -errno code. @dentry_ret and @strm_ret are both optional.
*/
static int
wim_pathname_to_stream(const struct wimfs_context *ctx,
const char *path,
int lookup_flags,
struct wim_dentry **dentry_ret,
struct wim_inode_stream **strm_ret)
{
WIMStruct *wim = ctx->wim;
struct wim_dentry *dentry;
struct wim_inode *inode;
struct wim_inode_stream *strm;
const char *stream_name = NULL;
char *p = NULL;
lookup_flags |= ctx->default_lookup_flags;
if (lookup_flags & LOOKUP_FLAG_ADS_OK) {
stream_name = path_stream_name(path);
if (stream_name) {
p = (char *)stream_name - 1;
*p = '\0';
}
}
dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
if (p)
*p = ':';
if (!dentry)
return -errno;
inode = dentry->d_inode;
if (inode_resolve_streams(inode, wim->blob_table, false))
return -EIO;
if (!(lookup_flags & LOOKUP_FLAG_DIRECTORY_OK)
&& inode_is_directory(inode))
return -EISDIR;
strm = inode_get_data_stream_tstr(inode, stream_name);
if (!strm) {
/* Force creation of an unnamed data stream */
if (!stream_name)
strm = inode_add_stream(inode, STREAM_TYPE_DATA,
NO_STREAM_NAME, NULL);
if (!strm)
return -errno;
}
if (dentry_ret)
*dentry_ret = dentry;
if (strm_ret)
*strm_ret = strm;
return 0;
}
/*
* Create a new file in the mounted WIM image.
*
* @fuse_ctx
* The FUSE context for the mounted image.
* @path
* The path at which to create the first link to the new file. If a file
* already exists at this path, -EEXIST is returned.
* @mode
* The UNIX mode for the new file. This is only fully honored if
* WIMLIB_MOUNT_FLAG_UNIX_DATA was passed to wimlib_mount_image().
* @rdev
* The device ID for the new file, encoding the major and minor device
* numbers. This is only honored if WIMLIB_MOUNT_FLAG_UNIX_DATA was passed
* to wimlib_mount_image().
* @dentry_ret
* On success, a pointer to the new dentry is returned here. Its d_inode
* member will point to the new inode that was created for it and added to
* the mounted WIM image.
*
* Returns 0 or a -errno code.
*/
static int
create_file(struct fuse_context *fuse_ctx, const char *path,
mode_t mode, dev_t rdev, struct wim_dentry **dentry_ret)
{
struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
struct wim_dentry *parent;
const char *basename;
struct wim_dentry *dentry;
struct wim_inode *inode;
parent = get_parent_dentry(wimfs_ctx->wim, path, WIMLIB_CASE_SENSITIVE);
if (!parent)
return -errno;
if (!dentry_is_directory(parent))
return -ENOTDIR;
basename = path_basename(path);
if (get_dentry_child_with_name(parent, basename, WIMLIB_CASE_SENSITIVE))
return -EEXIST;
if (new_dentry_with_new_inode(basename, true, &dentry))
return -ENOMEM;
inode = dentry->d_inode;
inode->i_ino = wimfs_ctx->next_ino++;
/* Note: we still use FILE_ATTRIBUTE_NORMAL for device nodes, named
* pipes, and sockets. The real mode is in the UNIX metadata. */
if (S_ISDIR(mode))
inode->i_attributes = FILE_ATTRIBUTE_DIRECTORY;
else
inode->i_attributes = FILE_ATTRIBUTE_NORMAL;
if (wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) {
struct wimlib_unix_data unix_data;
unix_data.uid = fuse_ctx->uid;
unix_data.gid = fuse_ctx->gid;
unix_data.mode = fuse_mask_mode(mode, fuse_ctx);
unix_data.rdev = rdev;
if (!inode_set_unix_data(inode, &unix_data, UNIX_DATA_ALL))
{
free_dentry(dentry);
return -ENOMEM;
}
}
hlist_add_head(&inode->i_hlist_node,
&wim_get_current_image_metadata(wimfs_ctx->wim)->inode_list);
dentry_add_child(parent, dentry);
*dentry_ret = dentry;
return 0;
}
/*
* Remove a dentry from the mounted WIM image; i.e. remove an alias for an
* inode.
*/
static void
remove_dentry(struct wim_dentry *dentry, struct blob_table *blob_table)
{
/* Drop blob references. */
inode_unref_blobs(dentry->d_inode, blob_table);
/* Unlink the dentry from the image's dentry tree. */
unlink_dentry(dentry);
/* Delete the dentry. This will also decrement the link count of the
* corresponding inode, and possibly cause it to be deleted as well. */
free_dentry(dentry);
}
/* Generate UNIX filetype mode bits for the specified WIM inode, based on its
* Windows file attributes. */
static mode_t
inode_unix_file_type(const struct wim_inode *inode)
{
if (inode_is_symlink(inode))
return S_IFLNK;
else if (inode_is_directory(inode))
return S_IFDIR;
else
return S_IFREG;
}
/* Generate a default UNIX mode for the specified WIM inode. */
static mode_t
inode_default_unix_mode(const struct wim_inode *inode)
{
return inode_unix_file_type(inode) | 0777;
}
static u64
blob_size(const struct blob_descriptor *blob)
{
if (!blob)
return 0;
return blob->size;
}
static u64
blob_stored_size(const struct blob_descriptor *blob)
{
if (!blob)
return 0;
if (blob->blob_location == BLOB_IN_WIM &&
blob->size == blob->rdesc->uncompressed_size)
return blob->rdesc->size_in_wim;
return blob->size;
}
/*
* Retrieve standard UNIX metadata ('struct stat') for a WIM inode.
*
* @blob is the blob descriptor for the stream of the inode that is being
* queried, or NULL. We mostly return the same information for all streams, but
* st_size and st_blocks may be different for different streams.
*
* This always returns 0.
*/
static int
inode_to_stbuf(const struct wim_inode *inode,
const struct blob_descriptor *blob, struct stat *stbuf)
{
const struct wimfs_context *ctx = wimfs_get_context();
struct wimlib_unix_data unix_data;
memset(stbuf, 0, sizeof(struct stat));
if ((ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA) &&
inode_get_unix_data(inode, &unix_data))
{
/* Use the user ID, group ID, mode, and device ID from the
* inode's extra UNIX metadata information. */
stbuf->st_uid = unix_data.uid;
stbuf->st_gid = unix_data.gid;
stbuf->st_mode = unix_data.mode;
stbuf->st_rdev = unix_data.rdev;
} else {
/* Generate default values for the user ID, group ID, and mode.
*
* Note: in the case of an allow_other mount, fuse_context.uid
* may not be the same as wimfs_context.owner_uid! */
stbuf->st_uid = ctx->owner_uid;
stbuf->st_gid = ctx->owner_gid;
stbuf->st_mode = inode_default_unix_mode(inode);
}
stbuf->st_ino = inode->i_ino;
stbuf->st_nlink = inode->i_nlink;
stbuf->st_size = blob_size(blob);
#ifdef HAVE_STAT_NANOSECOND_PRECISION
stbuf->st_atim = wim_timestamp_to_timespec(inode->i_last_access_time);
stbuf->st_mtim = wim_timestamp_to_timespec(inode->i_last_write_time);
stbuf->st_ctim = stbuf->st_mtim;
#else
stbuf->st_atime = wim_timestamp_to_time_t(inode->i_last_access_time);
stbuf->st_mtime = wim_timestamp_to_time_t(inode->i_last_write_time);
stbuf->st_ctime = stbuf->st_mtime;
#endif
stbuf->st_blocks = DIV_ROUND_UP(blob_stored_size(blob), 512);
return 0;
}
/* Update the last access and last write timestamps of a WIM inode. */
static void
touch_inode(struct wim_inode *inode)
{
u64 now = now_as_wim_timestamp();
inode->i_last_access_time = now;
inode->i_last_write_time = now;
}
static void
touch_parent(struct wim_dentry *dentry)
{
touch_inode(dentry->d_parent->d_inode);
}
/*
* Update inode metadata after a regular file's contents have changed:
*
* - Update the timestamps
* - Clear the setuid and setgid bits
*/
static void
file_contents_changed(struct wim_inode *inode)
{
struct wimlib_unix_data unix_data;
bool ok;
touch_inode(inode);
if (inode_get_unix_data(inode, &unix_data)) {
unix_data.mode &= ~(S_ISUID | S_ISGID);
ok = inode_set_unix_data(inode, &unix_data, UNIX_DATA_MODE);
/*
* This cannot fail because no memory allocation should have
* been required, as the UNIX data already exists.
*/
wimlib_assert(ok);
} /* Else, set[ug]id can't be set, so there's nothing to do. */
}
/*
* Create a new file in the staging directory for a read-write mounted image.
*
* On success, returns the file descriptor for the new staging file, opened for
* writing. In addition, stores the allocated name of the staging file in
* @name_ret.
*
* On failure, returns -1 and sets errno.
*/
static int
create_staging_file(const struct wimfs_context *ctx, char **name_ret)
{
static const size_t STAGING_FILE_NAME_LEN = 20;
char *name;
int fd;
name = MALLOC(STAGING_FILE_NAME_LEN + 1);
if (!name)
return -1;
name[STAGING_FILE_NAME_LEN] = '\0';
retry:
get_random_alnum_chars(name, STAGING_FILE_NAME_LEN);
fd = openat(ctx->staging_dir_fd, name,
O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
if (unlikely(fd < 0)) {
if (unlikely(errno == EEXIST))
/* Try again with another name. */
goto retry;
FREE(name);
} else {
*name_ret = name;
}
return fd;
}
/*
* Extract a blob to the staging directory. This is necessary when a stream
* using the blob is being opened for writing and the blob has not already been
* extracted to the staging directory.
*
* @inode
* The inode containing the stream being opened for writing.
* @strm
* The stream being opened for writing. The blob descriptor to which the
* stream refers will be changed by this function.
* @size
* Number of bytes of the blob to extract and include in the staging file.
* It may be less than the actual blob length, in which case only a prefix
* of the blob will be extracted. It may also be more than the actual blob
* length, in which case the extra space will be zero-filled.
*
* Returns 0 or a -errno code.
*/
static int
extract_blob_to_staging_dir(struct wim_inode *inode,
struct wim_inode_stream *strm,
off_t size, const struct wimfs_context *ctx)
{
struct blob_descriptor *old_blob;
struct blob_descriptor *new_blob;
char *staging_file_name;
int staging_fd;
off_t extract_size;
int result;
int ret;
old_blob = stream_blob_resolved(strm);
/* Create the staging file. */
staging_fd = create_staging_file(ctx, &staging_file_name);
if (unlikely(staging_fd < 0))
return -errno;
/* Extract the stream to the staging file (possibly truncated). */
if (old_blob) {
struct filedes fd;
filedes_init(&fd, staging_fd);
errno = 0;
extract_size = min(old_blob->size, size);
result = extract_blob_prefix_to_fd(old_blob, extract_size, &fd);
} else {
extract_size = 0;
result = 0;
}
/* In the case of truncate() to more than the file length, extend the
* staging file with zeroes by calling ftruncate(). */
if (!result && size > extract_size)
result = ftruncate(staging_fd, size);
/* Close the staging file. */
if (close(staging_fd))
result = -1;
/* If an error occurred, unlink the staging file. */
if (unlikely(result)) {
/* extract_blob_to_fd() should set errno, but if it didn't,
* set a default value. */
ret = errno ? -errno : -EIO;
goto out_delete_staging_file;
}
/* Create a blob descriptor for the staging file. */
new_blob = new_blob_descriptor();
if (unlikely(!new_blob)) {
ret = -ENOMEM;
goto out_delete_staging_file;
}
/* There may already be open file descriptors to this stream if it's
* previously been opened read-only, but just now we're opening it
* read-write. Identify those file descriptors, update them to use the
* new blob descriptor, and open staging file descriptors for them. */
for (u16 i = 0, j = 0; j < inode->i_num_opened_fds; i++) {
struct wimfs_fd *fd;
int raw_fd;
fd = inode->i_fds[i];
if (!fd)
continue;
j++;
if (fd->f_stream_id != strm->stream_id)
continue;
/* This is a readonly fd for the same stream. */
fd->f_blob = new_blob;
new_blob->num_opened_fds++;
raw_fd = openat(ctx->staging_dir_fd, staging_file_name,
O_RDONLY | O_NOFOLLOW);
if (unlikely(raw_fd < 0)) {
ret = -errno;
goto out_revert_fd_changes;
}
filedes_init(&fd->f_staging_fd, raw_fd);
}
if (old_blob)
old_blob->num_opened_fds -= new_blob->num_opened_fds;
new_blob->blob_location = BLOB_IN_STAGING_FILE;
new_blob->staging_file_name = staging_file_name;
new_blob->staging_dir_fd = ctx->staging_dir_fd;
new_blob->size = size;
prepare_unhashed_blob(new_blob, inode, strm->stream_id,
&wim_get_current_image_metadata(ctx->wim)->unhashed_blobs);
inode_replace_stream_blob(inode, strm, new_blob, ctx->wim->blob_table);
if (size != blob_size(old_blob))
file_contents_changed(inode);
return 0;
out_revert_fd_changes:
for (u16 i = 0; new_blob->num_opened_fds; i++) {
struct wimfs_fd *fd = inode->i_fds[i];
if (fd && fd->f_stream_id == strm->stream_id) {
fd->f_blob = old_blob;
if (filedes_valid(&fd->f_staging_fd)) {
filedes_close(&fd->f_staging_fd);
filedes_invalidate(&fd->f_staging_fd);
}
new_blob->num_opened_fds--;
}
}
free_blob_descriptor(new_blob);
out_delete_staging_file:
unlinkat(ctx->staging_dir_fd, staging_file_name, 0);
FREE(staging_file_name);
return ret;
}
/*
* Create the staging directory for the WIM file.
*
* The staging directory will be created in the directory specified by the open
* file descriptor @parent_dir_fd. It will be given a randomly generated name
* based on @wim_basename, the name of the WIM file.
*
* On success, returns a file descriptor to the open staging directory with
* O_RDONLY access. In addition, stores the allocated name of the staging
* directory (relative to @parent_dir_fd) in @staging_dir_name_ret.
* On failure, returns -1 and sets errno.
*/
static int
make_staging_dir_at(int parent_dir_fd, const char *wim_basename,
char **staging_dir_name_ret)
{
static const char common_suffix[8] = ".staging";
static const size_t random_suffix_len = 10;
size_t wim_basename_len;
size_t staging_dir_name_len;
char *staging_dir_name;
char *p;
int fd;
wim_basename_len = strlen(wim_basename);
staging_dir_name_len = wim_basename_len + sizeof(common_suffix) +
random_suffix_len;
staging_dir_name = MALLOC(staging_dir_name_len + 1);
if (!staging_dir_name)
return -1;
p = staging_dir_name;
p = mempcpy(p, wim_basename, wim_basename_len);
p = mempcpy(p, common_suffix, sizeof(common_suffix));
get_random_alnum_chars(p, random_suffix_len);
p += random_suffix_len;
*p = '\0';
if (mkdirat(parent_dir_fd, staging_dir_name, 0700))
goto err1;
fd = openat(parent_dir_fd, staging_dir_name,
O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
if (fd < 0)
goto err2;
*staging_dir_name_ret = staging_dir_name;
return fd;
err2:
unlinkat(parent_dir_fd, staging_dir_name, AT_REMOVEDIR);
err1:
FREE(staging_dir_name);
return -1;
}
/*
* Create the staging directory and set ctx->staging_dir_fd,
* ctx->staging_dir_name, and ctx->parent_dir_fd.
*/
static int
make_staging_dir(struct wimfs_context *ctx, const char *parent_dir_path)
{
const char *wim_basename;
char *end = NULL;
int ret;
wim_basename = path_basename(ctx->wim->filename);
if (!parent_dir_path) {
/* The user did not specify a directory. Default to creating
* the staging directory alongside the WIM file. */
if (wim_basename > ctx->wim->filename) {
parent_dir_path = ctx->wim->filename;
end = (char *)(wim_basename - 1);
/* *end must be a slash. Temporarily overwrite it so we
* can open the parent directory. */
*end = '\0';
} else {
parent_dir_path = ".";
}
}
/* Open the parent directory (in which we'll create our staging
* directory). */
ctx->parent_dir_fd = open(parent_dir_path, O_RDONLY | O_DIRECTORY);
if (ctx->parent_dir_fd < 0) {
ERROR_WITH_ERRNO("Can't open directory \"%s\"",
parent_dir_path);
ret = WIMLIB_ERR_OPENDIR;
goto out_restore_wim_filename;
}
ctx->staging_dir_fd = make_staging_dir_at(ctx->parent_dir_fd,
wim_basename,
&ctx->staging_dir_name);
if (ctx->staging_dir_fd < 0) {
ERROR_WITH_ERRNO("Can't create staging directory in \"%s\"",
parent_dir_path);
close(ctx->parent_dir_fd);
ret = WIMLIB_ERR_MKDIR;
goto out_restore_wim_filename;
}
ret = 0;
out_restore_wim_filename:
if (end)
*end = '/';
return ret;
}
/* Deletes the staging directory, undoing the effects of a successful call to
* make_staging_dir(). */
static void
delete_staging_dir(struct wimfs_context *ctx)
{
DIR *dir;
struct dirent *ent;
dir = fdopendir(ctx->staging_dir_fd);
if (dir) {
while ((ent = readdir(dir)))
unlinkat(ctx->staging_dir_fd, ent->d_name, 0);
closedir(dir);
} else {
close(ctx->staging_dir_fd);
}
if (unlinkat(ctx->parent_dir_fd, ctx->staging_dir_name, AT_REMOVEDIR))
WARNING_WITH_ERRNO("Could not delete staging directory");
FREE(ctx->staging_dir_name);
close(ctx->parent_dir_fd);
}
static void
prepare_inodes(struct wimfs_context *ctx)
{
struct wim_image_metadata *imd;
struct wim_inode *inode;
ctx->next_ino = 1;
imd = wim_get_current_image_metadata(ctx->wim);
image_for_each_inode(inode, imd) {
inode->i_ino = ctx->next_ino++;
inode->i_num_opened_fds = 0;
inode->i_num_allocated_fds = 0;
inode->i_fds = NULL;
}
}
/* Delete the 'struct blob_descriptor' for any stream that was modified
* or created in the read-write mounted image and had a final size of 0. */
static void
delete_empty_blobs(struct wimfs_context *ctx)
{
struct blob_descriptor *blob, *tmp;
struct wim_image_metadata *imd;
imd = wim_get_current_image_metadata(ctx->wim);
image_for_each_unhashed_blob_safe(blob, tmp, imd) {
if (!blob->size) {
*retrieve_pointer_to_unhashed_blob(blob) = NULL;
list_del(&blob->unhashed_list);
free_blob_descriptor(blob);
}
}
}
/* Close all file descriptors open to the specified inode.
*
* Note: closing the last file descriptor might free the inode. */
static void
inode_close_fds(struct wim_inode *inode)
{
u16 num_open_fds = inode->i_num_opened_fds;
for (u16 i = 0; num_open_fds; i++) {
if (inode->i_fds[i]) {
close_wimfs_fd(inode->i_fds[i]);
num_open_fds--;
}
}
}
/* Close all file descriptors open to the mounted image. */
static void
close_all_fds(struct wimfs_context *ctx)
{
struct wim_inode *inode;
struct hlist_node *tmp;
struct wim_image_metadata *imd;
imd = wim_get_current_image_metadata(ctx->wim);
image_for_each_inode_safe(inode, tmp, imd)
inode_close_fds(inode);
}
/* Moves the currently selected image, which may have been modified, to a new
* index, and sets the original index to refer to a reset (unmodified) copy of
* the image. */
static int
renew_current_image(struct wimfs_context *ctx)
{
WIMStruct *wim = ctx->wim;
int image = wim->current_image;
struct wim_image_metadata *imd;
struct wim_inode *inode;
int ret;
ret = WIMLIB_ERR_NOMEM;
imd = new_unloaded_image_metadata(ctx->metadata_resource);
if (!imd)
goto err;
ret = append_image_metadata(wim, wim->image_metadata[image - 1]);
if (ret)
goto err_put_imd;
ret = xml_export_image(wim->xml_info, image,
wim->xml_info, NULL, NULL, false);
if (ret)
goto err_undo_append;
wim->image_metadata[image - 1] = imd;
wim->current_image = wim->hdr.image_count;
ret = select_wim_image(wim, image);
if (ret)
goto err_undo_export;
image_for_each_inode(inode, imd) {
for (unsigned i = 0; i < inode->i_num_streams; i++) {
struct blob_descriptor *blob;
blob = stream_blob(&inode->i_streams[i],
wim->blob_table);
if (blob)
blob->refcnt += inode->i_nlink;
}
}
select_wim_image(wim, wim->hdr.image_count);
ctx->metadata_resource = NULL;
return 0;
err_undo_export:
xml_delete_image(wim->xml_info, wim->hdr.image_count);
wim->image_metadata[image - 1] = wim->image_metadata[wim->hdr.image_count - 1];
wim->current_image = image;
err_undo_append:
wim->hdr.image_count--;
err_put_imd:
imd->metadata_blob = NULL;
put_image_metadata(imd);
err:
return ret;
}
static enum wimlib_progress_status
commit_progress_func(enum wimlib_progress_msg msg,
union wimlib_progress_info *info, void *progctx)
{
mqd_t mq = *(mqd_t *)progctx;
struct commit_progress_report report;
memset(&report, 0, sizeof(report));
report.msg = msg;
if (info)
report.info = *info;
mq_send(mq, (const char *)&report, sizeof(report), 1);
return WIMLIB_PROGRESS_STATUS_CONTINUE;
}
/* Commit the mounted image to the underlying WIM file. */
static int
commit_image(struct wimfs_context *ctx, int unmount_flags, mqd_t mq)
{
int write_flags;
if (unmount_flags & WIMLIB_UNMOUNT_FLAG_SEND_PROGRESS)
wimlib_register_progress_function(ctx->wim,
commit_progress_func, &mq);
else
wimlib_register_progress_function(ctx->wim, NULL, NULL);
if (unmount_flags & WIMLIB_UNMOUNT_FLAG_NEW_IMAGE) {
int ret = renew_current_image(ctx);
if (ret)
return ret;
}
delete_empty_blobs(ctx);
write_flags = 0;
if (unmount_flags & WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY)
write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
if (unmount_flags & WIMLIB_UNMOUNT_FLAG_REBUILD)
write_flags |= WIMLIB_WRITE_FLAG_REBUILD;
if (unmount_flags & WIMLIB_UNMOUNT_FLAG_RECOMPRESS)
write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
return wimlib_overwrite(ctx->wim, write_flags, 0);
}
/* In the case of an allow_other mount, only the mount owner and root are
* allowed to unmount the filesystem. */
static bool
may_unmount_wimfs(void)
{
const struct fuse_context *fuse_ctx = fuse_get_context();
const struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
return (fuse_ctx->uid == wimfs_ctx->owner_uid ||
fuse_ctx->uid == 0);
}
/* Unmount the mounted image, called from the daemon process. */
static int
unmount_wimfs(void)
{
struct fuse_context *fuse_ctx = fuse_get_context();
struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
const struct wimfs_unmount_info *info = &wimfs_ctx->unmount_info;
int unmount_flags = info->unmount_flags;
mqd_t mq = (mqd_t)-1;
int ret;
/* Ignore COMMIT if the image is mounted read-only. */
if (!(wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_READWRITE))
unmount_flags &= ~WIMLIB_UNMOUNT_FLAG_COMMIT;
if (unmount_flags & WIMLIB_UNMOUNT_FLAG_SEND_PROGRESS) {
mq = mq_open(info->mq_name, O_WRONLY | O_NONBLOCK);
if (mq == (mqd_t)-1) {
ret = WIMLIB_ERR_MQUEUE;
goto out;
}
}
if (wimfs_ctx->num_open_fds) {
/* There are still open file descriptors to the image. */
/* With COMMIT, refuse to unmount unless FORCE is also
* specified. */
if ((unmount_flags & (WIMLIB_UNMOUNT_FLAG_COMMIT |
WIMLIB_UNMOUNT_FLAG_FORCE))
== WIMLIB_UNMOUNT_FLAG_COMMIT)
{
ret = WIMLIB_ERR_MOUNTED_IMAGE_IS_BUSY;
goto out;
}
/* Force-close all file descriptors. */
close_all_fds(wimfs_ctx);
}
if (unmount_flags & WIMLIB_UNMOUNT_FLAG_COMMIT)
ret = commit_image(wimfs_ctx, unmount_flags, mq);
else
ret = 0; /* Read-only mount, or discarding changes to
a read-write mount */
out:
/* Leave the image mounted if commit failed, unless this is a
* forced unmount. The user can retry without COMMIT if they
* want. */
if (!ret || (unmount_flags & WIMLIB_UNMOUNT_FLAG_FORCE)) {
unlock_wim_for_append(wimfs_ctx->wim);
fuse_exit(fuse_ctx->fuse);
}
if (mq != (mqd_t)-1)
mq_close(mq);
return ret;
}
static void *
wimfs_init(struct fuse_conn_info *conn, struct fuse_config *cfg)
{
/*
* Cache positive name lookups indefinitely, since names can only be
* added, removed, or modified through the mounted filesystem itself.
*/
cfg->entry_timeout = 1000000000;
/*
* Cache negative name lookups indefinitely, since names can only be
* added, removed, or modified through the mounted filesystem itself.
*/
cfg->negative_timeout = 1000000000;
/*
* Don't cache file/directory attributes. This is needed as a
* workaround for the fact that when caching attributes, the high level
* interface to libfuse considers a file which has several hard-linked
* names as several different files. (Otherwise, we could cache our
* file/directory attributes indefinitely, since they can only be
* changed through the mounted filesystem itself.)
*/
cfg->attr_timeout = 0;
/*
* If an open file is unlinked, unlink it for real rather than renaming
* it to a hidden file. Our code supports this; an unlinked inode is
* retained until all its file descriptors have been closed.
*/
cfg->hard_remove = 1;
/*
* Make FUSE use the inode numbers we provide. We want this, because we
* have inodes and will number them ourselves.
*/
cfg->use_ino = 1;
/*
* Cache the contents of files. This will speed up repeated access to
* files on a mounted WIM image, since they won't need to be
* decompressed repeatedly. This option is valid because data in the
* WIM image should never be changed externally. (Although, if someone
* really wanted to they could modify the WIM file or mess with the
* staging directory; but then they're asking for trouble.)
*/
cfg->kernel_cache = 1;
/*
* We keep track of file descriptor structures (struct wimfs_fd), so
* there is no need to have the file path provided on operations such as
* read().
*/
cfg->nullpath_ok = 1;
return wimfs_get_context();
}
static int
wimfs_chmod(const char *path, mode_t mask, struct fuse_file_info *fi)
{
const struct wimfs_context *ctx = wimfs_get_context();
struct wim_inode *inode;
struct wimlib_unix_data unix_data;
if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
return -EOPNOTSUPP;
if (fi) {
inode = WIMFS_FD(fi)->f_inode;
} else {
inode = wim_pathname_to_inode(ctx->wim, path);
if (!inode)
return -errno;
}
unix_data.uid = ctx->owner_uid;
unix_data.gid = ctx->owner_gid;
unix_data.mode = mask;
unix_data.rdev = 0;
if (!inode_set_unix_data(inode, &unix_data, UNIX_DATA_MODE))
return -ENOMEM;
return 0;
}
static int
wimfs_chown(const char *path, uid_t uid, gid_t gid, struct fuse_file_info *fi)
{
const struct wimfs_context *ctx = wimfs_get_context();
struct wim_inode *inode;
struct wimlib_unix_data unix_data;
int which;
if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
return -EOPNOTSUPP;
if (fi) {
inode = WIMFS_FD(fi)->f_inode;
} else {
inode = wim_pathname_to_inode(ctx->wim, path);
if (!inode)
return -errno;
}
which = 0;
if (uid != (uid_t)-1)
which |= UNIX_DATA_UID;
else
uid = ctx->owner_uid;
if (gid != (gid_t)-1)
which |= UNIX_DATA_GID;
else
gid = ctx->owner_gid;
unix_data.uid = uid;
unix_data.gid = gid;
unix_data.mode = inode_default_unix_mode(inode);
unix_data.rdev = 0;
if (!inode_set_unix_data(inode, &unix_data, which))
return -ENOMEM;
return 0;
}
static int
wimfs_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
{
const struct wimfs_context *ctx = wimfs_get_context();
const struct wim_inode *inode;
const struct blob_descriptor *blob;
int ret;
if (fi) {
const struct wimfs_fd *fd = WIMFS_FD(fi);
inode = fd->f_inode;
blob = fd->f_blob;
} else {
struct wim_dentry *dentry;
struct wim_inode_stream *strm;
ret = wim_pathname_to_stream(ctx, path,
LOOKUP_FLAG_DIRECTORY_OK,
&dentry, &strm);
if (ret)
return ret;
inode = dentry->d_inode;
blob = stream_blob_resolved(strm);
}
return inode_to_stbuf(inode, blob, stbuf);
}
static int
copy_xattr(char *dest, size_t destsize, const void *src, size_t srcsize)
{
if (destsize) {
if (destsize < srcsize)
return -ERANGE;
memcpy(dest, src, srcsize);
}
return srcsize;
}
static int
wimfs_getxattr(const char *path, const char *name, char *value,
size_t size)
{
const struct wimfs_context *ctx = wimfs_get_context();
const struct wim_inode *inode;
const struct wim_inode_stream *strm;
const struct blob_descriptor *blob;
if (!strncmp(name, "wimfs.", 6)) {
/* Handle some magical extended attributes. These really should
* be ioctls, but directory ioctls aren't supported until
* libfuse 2.9, and even then they are broken. */
name += 6;
if (!strcmp(name, "wim_filename")) {
return copy_xattr(value, size, ctx->wim->filename,
strlen(ctx->wim->filename));
}
if (!strcmp(name, "wim_info")) {
struct wimlib_wim_info info;
wimlib_get_wim_info(ctx->wim, &info);
return copy_xattr(value, size, &info, sizeof(info));
}
if (!strcmp(name, "mounted_image")) {
return copy_xattr(value, size,
&ctx->wim->current_image, sizeof(int));
}
if (!strcmp(name, "mount_flags")) {
return copy_xattr(value, size,
&ctx->mount_flags, sizeof(int));
}
if (!strcmp(name, "unmount")) {
if (!may_unmount_wimfs())
return -EPERM;
if (size) {
int status;
if (size < sizeof(int))
return -ERANGE;
status = unmount_wimfs();
memcpy(value, &status, sizeof(int));
}
return sizeof(int);
}
return -ENOATTR;
}
if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
return -ENOTSUP;
if (strncmp(name, "user.", 5))
return -ENOATTR;
name += 5;
if (!*name)
return -ENOATTR;
/* Querying a named data stream */
inode = wim_pathname_to_inode(ctx->wim, path);
if (!inode)
return -errno;
strm = inode_get_data_stream_tstr(inode, name);
if (!strm)
return (errno == ENOENT) ? -ENOATTR : -errno;
blob = stream_blob_resolved(strm);
if (!blob)
return 0;
if (unlikely(blob->size > INT_MAX))
return -EFBIG;
if (size) {
if (size < blob->size)
return -ERANGE;
if (read_blob_into_buf(blob, value))
return errno ? -errno : -EIO;
}
return blob->size;
}
static int
wimfs_link(const char *existing_path, const char *new_path)
{
WIMStruct *wim = wimfs_get_WIMStruct();
const char *new_name;
struct wim_inode *inode;
struct wim_dentry *dir;
struct wim_dentry *new_alias;
inode = wim_pathname_to_inode(wim, existing_path);
if (!inode)
return -errno;
if (inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
FILE_ATTRIBUTE_REPARSE_POINT))
return -EPERM;
new_name = path_basename(new_path);
dir = get_parent_dentry(wim, new_path, WIMLIB_CASE_SENSITIVE);
if (!dir)
return -errno;
if (!dentry_is_directory(dir))
return -ENOTDIR;
if (get_dentry_child_with_name(dir, new_name, WIMLIB_CASE_SENSITIVE))
return -EEXIST;
if (new_dentry_with_existing_inode(new_name, inode, &new_alias))
return -ENOMEM;
dentry_add_child(dir, new_alias);
touch_inode(dir->d_inode);
return 0;
}
static int
wimfs_listxattr(const char *path, char *list, size_t size)
{
const struct wimfs_context *ctx = wimfs_get_context();
const struct wim_inode *inode;
char *p = list;
int total_size = 0;
if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
return -ENOTSUP;
/* List named data streams, or get the list size. We report each named
* data stream "X" as an extended attribute "user.X". */
inode = wim_pathname_to_inode(ctx->wim, path);
if (!inode)
return -errno;
for (unsigned i = 0; i < inode->i_num_streams; i++) {
const struct wim_inode_stream *strm;
char *stream_name_mbs;
size_t stream_name_mbs_nbytes;
strm = &inode->i_streams[i];
if (!stream_is_named_data_stream(strm))
continue;
if (utf16le_to_tstr(strm->stream_name,
utf16le_len_bytes(strm->stream_name),
&stream_name_mbs,
&stream_name_mbs_nbytes))
return -errno;
if (unlikely(INT_MAX - total_size < stream_name_mbs_nbytes + 6)) {
FREE(stream_name_mbs);
return -EFBIG;
}
total_size += stream_name_mbs_nbytes + 6;
if (size) {
if (list + size - p < stream_name_mbs_nbytes + 6) {
FREE(stream_name_mbs);
return -ERANGE;
}
p = mempcpy(p, "user.", 5);
p = mempcpy(p, stream_name_mbs, stream_name_mbs_nbytes);
*p++ = '\0';
}
FREE(stream_name_mbs);
}
return total_size;
}
static int
wimfs_mkdir(const char *path, mode_t mode)
{
struct wim_dentry *dentry;
int ret;
/* Note: according to fuse.h, mode may not include S_IFDIR */
ret = create_file(fuse_get_context(), path, mode | S_IFDIR, 0, &dentry);
if (ret)
return ret;
touch_parent(dentry);
return 0;
}
static int
wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
{
struct fuse_context *fuse_ctx = fuse_get_context();
struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
const char *stream_name;
if ((wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
&& (stream_name = path_stream_name(path)))
{
struct wim_inode *inode;
struct wim_inode_stream *existing_strm;
struct wim_inode_stream *new_strm;
char *p;
const utf16lechar *uname;
/* Create a named data stream. */
if (!S_ISREG(mode))
return -EOPNOTSUPP;
p = (char *)stream_name - 1;
*p = '\0';
inode = wim_pathname_to_inode(wimfs_ctx->wim, path);
*p = ':';
if (!inode)
return -errno;
if (tstr_get_utf16le(stream_name, &uname))
return -errno;
existing_strm = inode_get_stream(inode, STREAM_TYPE_DATA, uname);
if (existing_strm) {
tstr_put_utf16le(uname);
return -EEXIST;
}
new_strm = inode_add_stream(inode, STREAM_TYPE_DATA, uname, NULL);
tstr_put_utf16le(uname);
if (!new_strm)
return -errno;
return 0;
} else {
/* Create a regular file, device node, named pipe, or socket.
*/
struct wim_dentry *dentry;
int ret;
if (!S_ISREG(mode) &&
!(wimfs_ctx->mount_flags & WIMLIB_MOUNT_FLAG_UNIX_DATA))
return -EPERM;
ret = create_file(fuse_ctx, path, mode, rdev, &dentry);
if (ret)
return ret;
touch_parent(dentry);
return 0;
}
}
static int
wimfs_open(const char *path, struct fuse_file_info *fi)
{
struct wimfs_context *ctx = wimfs_get_context();
struct wim_dentry *dentry;
struct wim_inode *inode;
struct wim_inode_stream *strm;
struct blob_descriptor *blob;
struct wimfs_fd *fd;
int ret;
ret = wim_pathname_to_stream(ctx, path, 0, &dentry, &strm);
if (ret)
return ret;
inode = dentry->d_inode;
blob = stream_blob_resolved(strm);
/* The data of the file being opened may be in the staging directory
* (read-write mounts only) or in the WIM. If it's in the staging
* directory, we need to open a native file descriptor for the
* corresponding file. Otherwise, we can read the file data directly
* from the WIM file if we are opening it read-only, but we need to
* extract the data to the staging directory if we are opening it
* writable. */
if (flags_writable(fi->flags) &&
(!blob || blob->blob_location != BLOB_IN_STAGING_FILE)) {
ret = extract_blob_to_staging_dir(inode,
strm,
blob_size(blob),
ctx);
if (ret)
return ret;
blob = stream_blob_resolved(strm);
}
ret = alloc_wimfs_fd(inode, strm, &fd);
if (ret)
return ret;
if (blob && blob->blob_location == BLOB_IN_STAGING_FILE) {
int raw_fd;
raw_fd = openat(blob->staging_dir_fd, blob->staging_file_name,
(fi->flags & (O_ACCMODE | O_TRUNC)) |
O_NOFOLLOW);
if (raw_fd < 0) {
close_wimfs_fd(fd);
return -errno;
}
filedes_init(&fd->f_staging_fd, raw_fd);
if (fi->flags & O_TRUNC) {
blob->size = 0;
file_contents_changed(inode);
}
}
fi->fh = (uintptr_t)fd;
return 0;
}
static int
wimfs_opendir(const char *path, struct fuse_file_info *fi)
{
WIMStruct *wim = wimfs_get_WIMStruct();
struct wim_inode *inode;
struct wim_inode_stream *strm;
struct wimfs_fd *fd;
int ret;
inode = wim_pathname_to_inode(wim, path);
if (!inode)
return -errno;
if (!inode_is_directory(inode))
return -ENOTDIR;
strm = inode_get_unnamed_data_stream(inode);
if (!strm)
return -ENOTDIR;
ret = alloc_wimfs_fd(inode, strm, &fd);
if (ret)
return ret;
fi->fh = (uintptr_t)fd;
return 0;
}
static int
wimfs_read(const char *path, char *buf, size_t size,
off_t offset, struct fuse_file_info *fi)
{
struct wimfs_fd *fd = WIMFS_FD(fi);
const struct blob_descriptor *blob;
ssize_t ret;
blob = fd->f_blob;
if (!blob)
return 0;
if (offset >= blob->size)
return 0;
if (size > blob->size - offset)
size = blob->size - offset;
if (!size)
return 0;
switch (blob->blob_location) {
case BLOB_IN_WIM:
if (read_partial_wim_blob_into_buf(blob, offset, size, buf))
ret = errno ? -errno : -EIO;
else
ret = size;
break;
case BLOB_IN_STAGING_FILE:
ret = pread(fd->f_staging_fd.fd, buf, size, offset);
if (ret < 0)
ret = -errno;
break;
case BLOB_IN_ATTACHED_BUFFER:
memcpy(buf, blob->attached_buffer + offset, size);
ret = size;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static int
wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi,
enum fuse_readdir_flags flags)
{
struct wimfs_fd *fd = WIMFS_FD(fi);
const struct wim_inode *inode;
const struct wim_dentry *child;
int ret;
inode = fd->f_inode;
ret = filler(buf, ".", NULL, 0, 0);
if (ret)
return ret;
ret = filler(buf, "..", NULL, 0, 0);
if (ret)
return ret;
for_inode_child(child, inode) {
char *name;
size_t name_nbytes;
if (utf16le_to_tstr(child->d_name, child->d_name_nbytes,
&name, &name_nbytes))
return -errno;
ret = filler(buf, name, NULL, 0, 0);
FREE(name);
if (ret)
return ret;
}
return 0;
}
static int
wimfs_readlink(const char *path, char *buf, size_t bufsize)
{
struct wimfs_context *ctx = wimfs_get_context();
const struct wim_inode *inode;
int ret;
inode = wim_pathname_to_inode(ctx->wim, path);
if (!inode)
return -errno;
if (bufsize <= 0)
return -EINVAL;
ret = wim_inode_readlink(inode, buf, bufsize - 1, NULL,
ctx->mountpoint_abspath,
ctx->mountpoint_abspath_nchars);
if (ret < 0)
return ret;
buf[ret] = '\0';
return 0;
}
/* We use this for both release() and releasedir(), since in both cases we
* simply need to close the file descriptor. */
static int
wimfs_release(const char *path, struct fuse_file_info *fi)
{
return close_wimfs_fd(WIMFS_FD(fi));
}
static int
wimfs_removexattr(const char *path, const char *name)
{
struct wimfs_context *ctx = wimfs_get_context();
struct wim_inode *inode;
struct wim_inode_stream *strm;
if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
return -ENOTSUP;
if (strncmp(name, "user.", 5))
return -ENOATTR;
name += 5;
if (!*name)
return -ENOATTR;
/* Removing a named data stream. */
inode = wim_pathname_to_inode(ctx->wim, path);
if (!inode)
return -errno;
strm = inode_get_data_stream_tstr(inode, name);
if (!strm)
return (errno == ENOENT) ? -ENOATTR : -errno;
inode_remove_stream(inode, strm, ctx->wim->blob_table);
return 0;
}
static int
wimfs_rename(const char *from, const char *to, unsigned int flags)
{
if (flags & RENAME_EXCHANGE)
return -EINVAL;
return rename_wim_path(wimfs_get_WIMStruct(), from, to,
WIMLIB_CASE_SENSITIVE,
(flags & RENAME_NOREPLACE), NULL);
}
static int
wimfs_rmdir(const char *path)
{
WIMStruct *wim = wimfs_get_WIMStruct();
struct wim_dentry *dentry;
dentry = get_dentry(wim, path, WIMLIB_CASE_SENSITIVE);
if (!dentry)
return -errno;
if (!dentry_is_directory(dentry))
return -ENOTDIR;
if (dentry_has_children(dentry))
return -ENOTEMPTY;
touch_parent(dentry);
remove_dentry(dentry, wim->blob_table);
return 0;
}
static int
wimfs_setxattr(const char *path, const char *name,
const char *value, size_t size, int flags)
{
struct wimfs_context *ctx = wimfs_get_context();
struct wim_inode *inode;
struct wim_inode_stream *strm;
const utf16lechar *uname;
int ret;
if (!strncmp(name, "wimfs.", 6)) {
/* Handle some magical extended attributes. These really should
* be ioctls, but directory ioctls aren't supported until
* libfuse 2.9, and even then they are broken. [Fixed by
* libfuse commit e3b7d4c278a26520be63d99d6ea84b26906fe73d] */
name += 6;
if (!strcmp(name, "unmount_info")) {
if (!may_unmount_wimfs())
return -EPERM;
if (size < sizeof(struct wimfs_unmount_info))
return -EINVAL;
memcpy(&ctx->unmount_info, value,
sizeof(struct wimfs_unmount_info));
return 0;
}
return -ENOATTR;
}
if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
return -ENOTSUP;
if (strncmp(name, "user.", 5))
return -ENOATTR;
name += 5;
if (!*name)
return -ENOATTR;
/* Setting the contents of a named data stream. */
inode = wim_pathname_to_inode(ctx->wim, path);
if (!inode)
return -errno;
ret = tstr_get_utf16le(name, &uname);
if (ret)
return -errno;
strm = inode_get_stream(inode, STREAM_TYPE_DATA, uname);
if (strm) {
ret = -EEXIST;
if (flags & XATTR_CREATE)
goto out_put_uname;
} else {
ret = -ENOATTR;
if (flags & XATTR_REPLACE)
goto out_put_uname;
}
if (strm) {
if (!inode_replace_stream_data(inode, strm, value, size,
ctx->wim->blob_table))
{
ret = -errno;
goto out_put_uname;
}
} else {
if (!inode_add_stream_with_data(inode, STREAM_TYPE_DATA, uname,
value, size, ctx->wim->blob_table))
{
ret = -errno;
goto out_put_uname;
}
}
ret = 0;
out_put_uname:
tstr_put_utf16le(uname);
return ret;
}
static int
wimfs_symlink(const char *to, const char *from)
{
struct fuse_context *fuse_ctx = fuse_get_context();
struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
struct wim_dentry *dentry;
int ret;
ret = create_file(fuse_ctx, from, S_IFLNK | 0777, 0, &dentry);
if (ret)
return ret;
ret = wim_inode_set_symlink(dentry->d_inode, to,
wimfs_ctx->wim->blob_table);
if (ret) {
remove_dentry(dentry, wimfs_ctx->wim->blob_table);
if (ret == WIMLIB_ERR_NOMEM)
ret = -ENOMEM;
else
ret = -EINVAL;
} else {
touch_parent(dentry);
}
return ret;
}
static int
do_truncate(int staging_fd, off_t size,
struct wim_inode *inode, struct blob_descriptor *blob)
{
if (ftruncate(staging_fd, size))
return -errno;
file_contents_changed(inode);
blob->size = size;
return 0;
}
static int
wimfs_truncate(const char *path, off_t size, struct fuse_file_info *fi)
{
const struct wimfs_context *ctx = wimfs_get_context();
struct wim_dentry *dentry;
struct wim_inode_stream *strm;
struct blob_descriptor *blob;
int ret;
int staging_fd;
if (fi) {
struct wimfs_fd *fd = WIMFS_FD(fi);
return do_truncate(fd->f_staging_fd.fd, size, fd->f_inode,
fd->f_blob);
}
ret = wim_pathname_to_stream(ctx, path, 0, &dentry, &strm);
if (ret)
return ret;
blob = stream_blob_resolved(strm);
if (!blob && !size)
return 0;
if (!blob || blob->blob_location != BLOB_IN_STAGING_FILE) {
return extract_blob_to_staging_dir(dentry->d_inode,
strm, size, ctx);
}
/* Truncate the staging file. */
staging_fd = openat(blob->staging_dir_fd, blob->staging_file_name,
O_WRONLY | O_NOFOLLOW);
if (staging_fd < 0)
return -errno;
ret = do_truncate(staging_fd, size, dentry->d_inode, blob);
if (close(staging_fd) && !ret)
ret = -errno;
return ret;
}
static int
wimfs_unlink(const char *path)
{
const struct wimfs_context *ctx = wimfs_get_context();
struct wim_dentry *dentry;
struct wim_inode_stream *strm;
int ret;
ret = wim_pathname_to_stream(ctx, path, 0, &dentry, &strm);
if (ret)
return ret;
if (stream_is_named(strm)) {
inode_remove_stream(dentry->d_inode, strm,
ctx->wim->blob_table);
} else {
touch_parent(dentry);
remove_dentry(dentry, ctx->wim->blob_table);
}
return 0;
}
/*
* Change the timestamp on a file dentry.
*
* Note that alternate data streams do not have their own timestamps.
*/
static int
wimfs_utimens(const char *path, const struct timespec tv[2],
struct fuse_file_info *fi)
{
struct wim_inode *inode;
if (fi) {
inode = WIMFS_FD(fi)->f_inode;
} else {
inode = wim_pathname_to_inode(wimfs_get_WIMStruct(), path);
if (!inode)
return -errno;
}
if (tv[0].tv_nsec != UTIME_OMIT) {
if (tv[0].tv_nsec == UTIME_NOW)
inode->i_last_access_time = now_as_wim_timestamp();
else
inode->i_last_access_time = timespec_to_wim_timestamp(&tv[0]);
}
if (tv[1].tv_nsec != UTIME_OMIT) {
if (tv[1].tv_nsec == UTIME_NOW)
inode->i_last_write_time = now_as_wim_timestamp();
else
inode->i_last_write_time = timespec_to_wim_timestamp(&tv[1]);
}
return 0;
}
static int
wimfs_write(const char *path, const char *buf, size_t size,
off_t offset, struct fuse_file_info *fi)
{
struct wimfs_fd *fd = WIMFS_FD(fi);
ssize_t ret;
ret = pwrite(fd->f_staging_fd.fd, buf, size, offset);
if (ret < 0)
return -errno;
if (offset + size > fd->f_blob->size)
fd->f_blob->size = offset + size;
file_contents_changed(fd->f_inode);
return ret;
}
static const struct fuse_operations wimfs_operations = {
.init = wimfs_init,
.chmod = wimfs_chmod,
.chown = wimfs_chown,
.getattr = wimfs_getattr,
.getxattr = wimfs_getxattr,
.link = wimfs_link,
.listxattr = wimfs_listxattr,
.mkdir = wimfs_mkdir,
.mknod = wimfs_mknod,
.open = wimfs_open,
.opendir = wimfs_opendir,
.read = wimfs_read,
.readdir = wimfs_readdir,
.readlink = wimfs_readlink,
.release = wimfs_release,
.releasedir = wimfs_release,
.removexattr = wimfs_removexattr,
.rename = wimfs_rename,
.rmdir = wimfs_rmdir,
.setxattr = wimfs_setxattr,
.symlink = wimfs_symlink,
.truncate = wimfs_truncate,
.unlink = wimfs_unlink,
.utimens = wimfs_utimens,
.write = wimfs_write,
};
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
int mount_flags, const char *staging_dir)
{
int ret;
struct wim_image_metadata *imd;
struct wimfs_context ctx;
char *fuse_argv[16];
int fuse_argc;
if (!wim || !dir || !*dir)
return WIMLIB_ERR_INVALID_PARAM;
if (mount_flags & ~(WIMLIB_MOUNT_FLAG_READWRITE |
WIMLIB_MOUNT_FLAG_DEBUG |
WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS |
WIMLIB_MOUNT_FLAG_UNIX_DATA |
WIMLIB_MOUNT_FLAG_ALLOW_OTHER))
return WIMLIB_ERR_INVALID_PARAM;
/* For read-write mount, check for write access to the WIM. */
if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
if (!wim->filename)
return WIMLIB_ERR_NO_FILENAME;
ret = can_modify_wim(wim);
if (ret)
return ret;
}
/* Select the image to mount. */
ret = select_wim_image(wim, image);
if (ret)
return ret;
/* Get the metadata for the image to mount. */
imd = wim_get_current_image_metadata(wim);
/* To avoid complicating things, we don't support mounting images to
* which in-memory modifications have already been made. */
if (is_image_dirty(imd)) {
ERROR("Cannot mount a modified WIM image!");
return WIMLIB_ERR_INVALID_PARAM;
}
if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
if (imd->refcnt > 1)
return WIMLIB_ERR_IMAGE_HAS_MULTIPLE_REFERENCES;
ret = lock_wim_for_append(wim);
if (ret)
return ret;
}
if (wim_has_solid_resources(wim)) {
WARNING("Mounting a WIM file containing solid-compressed data; "
"file access may be slow.");
}
/* If the user did not specify an interface for accessing named
* data streams, use the default (extended attributes). */
if (!(mount_flags & (WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE |
WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR |
WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)))
mount_flags |= WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR;
/* Start initializing the wimfs_context. */
memset(&ctx, 0, sizeof(struct wimfs_context));
ctx.wim = wim;
ctx.mount_flags = mount_flags;
if (mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS)
ctx.default_lookup_flags = LOOKUP_FLAG_ADS_OK;
/* For read-write mounts, create the staging directory, save a reference
* to the image's metadata resource, and mark the image dirty. */
if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
ret = make_staging_dir(&ctx, staging_dir);
if (ret)
goto out;
ret = WIMLIB_ERR_NOMEM;
ctx.metadata_resource = clone_blob_descriptor(
imd->metadata_blob);
if (!ctx.metadata_resource)
goto out;
mark_image_dirty(imd);
}
ctx.owner_uid = getuid();
ctx.owner_gid = getgid();
/* Number the inodes in the mounted image sequentially and initialize
* the file descriptor arrays */
prepare_inodes(&ctx);
/* Save the absolute path to the mountpoint directory. */
ctx.mountpoint_abspath = realpath(dir, NULL);
if (ctx.mountpoint_abspath)
ctx.mountpoint_abspath_nchars = strlen(ctx.mountpoint_abspath);
/* Build the FUSE command line. */
fuse_argc = 0;
fuse_argv[fuse_argc++] = "wimlib";
fuse_argv[fuse_argc++] = (char *)dir;
/* Disable multi-threaded operation. */
fuse_argv[fuse_argc++] = "-s";
/* Enable FUSE debug mode (don't fork) if requested by the user. */
if (mount_flags & WIMLIB_MOUNT_FLAG_DEBUG)
fuse_argv[fuse_argc++] = "-d";
/*
* Build the FUSE mount options:
*
* subtype=wimfs
* Name for our filesystem (main type is "fuse").
*
* default_permissions
* FUSE will perform permission checking. Useful when
* WIMLIB_MOUNT_FLAG_UNIX_DATA is provided and the WIM image
* contains the UNIX permissions for each file.
*/
char optstring[128] = "subtype=wimfs,default_permissions";
fuse_argv[fuse_argc++] = "-o";
fuse_argv[fuse_argc++] = optstring;
if (!(mount_flags & WIMLIB_MOUNT_FLAG_READWRITE))
strcat(optstring, ",ro");
if (mount_flags & WIMLIB_MOUNT_FLAG_ALLOW_OTHER)
strcat(optstring, ",allow_other");
fuse_argv[fuse_argc] = NULL;
/* Mount our filesystem. */
ret = fuse_main(fuse_argc, fuse_argv, &wimfs_operations, &ctx);
/* Cleanup and return. */
if (ret)
ret = WIMLIB_ERR_FUSE;
out:
FREE(ctx.mountpoint_abspath);
free_blob_descriptor(ctx.metadata_resource);
if (ctx.staging_dir_name)
delete_staging_dir(&ctx);
unlock_wim_for_append(wim);
return ret;
}
struct commit_progress_thread_args {
mqd_t mq;
wimlib_progress_func_t progfunc;
void *progctx;
};
static void *
commit_progress_thread_proc(void *_args)
{
struct commit_progress_thread_args *args = _args;
struct commit_progress_report report;
ssize_t ret;
for (;;) {
ret = mq_receive(args->mq,
(char *)&report, sizeof(report), NULL);
if (ret == sizeof(report)) {
call_progress(args->progfunc, report.msg,
&report.info, args->progctx);
} else {
if (ret == 0 || (ret < 0 && errno != EINTR))
break;
}
}
return NULL;
}
static void
generate_message_queue_name(char name[WIMFS_MQUEUE_NAME_LEN + 1])
{
name[0] = '/';
memcpy(name + 1, "wimfs-", 6);
get_random_alnum_chars(name + 7, WIMFS_MQUEUE_NAME_LEN - 7);
name[WIMFS_MQUEUE_NAME_LEN] = '\0';
}
static mqd_t
create_message_queue(const char *name)
{
bool am_root;
mode_t umask_save;
mode_t mode;
struct mq_attr attr;
mqd_t mq;
memset(&attr, 0, sizeof(attr));
attr.mq_maxmsg = 8;
attr.mq_msgsize = sizeof(struct commit_progress_report);
am_root = (geteuid() == 0);
if (am_root) {
/* Filesystem mounted as normal user with --allow-other should
* be able to send messages to root user, if they're doing the
* unmount. */
umask_save = umask(0);
mode = 0666;
} else {
mode = 0600;
}
mq = mq_open(name, O_RDWR | O_CREAT | O_EXCL, mode, &attr);
if (am_root)
umask(umask_save);
return mq;
}
/* Unmount a read-only or read-write mounted WIM image. */
static int
do_unmount(const char *dir)
{
int status;
ssize_t len;
len = getxattr(dir, "wimfs.unmount", &status, sizeof(int));
if (len == sizeof(int))
return status;
else if (len < 0 && (errno == EACCES || errno == EPERM))
return WIMLIB_ERR_NOT_PERMITTED_TO_UNMOUNT;
else
return WIMLIB_ERR_NOT_A_MOUNTPOINT;
}
static int
set_unmount_info(const char *dir, const struct wimfs_unmount_info *unmount_info)
{
if (!setxattr(dir, "wimfs.unmount_info",
unmount_info, sizeof(struct wimfs_unmount_info), 0))
return 0;
else if (errno == EROFS)
return 0;
else if (errno == EACCES || errno == EPERM)
return WIMLIB_ERR_NOT_PERMITTED_TO_UNMOUNT;
else
return WIMLIB_ERR_NOT_A_MOUNTPOINT;
}
static int
do_unmount_discard(const char *dir)
{
int ret;
struct wimfs_unmount_info unmount_info;
memset(&unmount_info, 0, sizeof(unmount_info));
ret = set_unmount_info(dir, &unmount_info);
if (ret)
return ret;
return do_unmount(dir);
}
/* Unmount a read-write mounted WIM image, committing the changes. */
static int
do_unmount_commit(const char *dir, int unmount_flags,
wimlib_progress_func_t progfunc, void *progctx)
{
struct wimfs_unmount_info unmount_info;
mqd_t mq = (mqd_t)-1;
struct commit_progress_thread_args args;
struct thread commit_progress_tid;
int ret;
memset(&unmount_info, 0, sizeof(unmount_info));
unmount_info.unmount_flags = unmount_flags;
/* The current thread will be stuck in getxattr() until the image is
* committed. Create a thread to handle the progress messages. */
if (progfunc) {
generate_message_queue_name(unmount_info.mq_name);
mq = create_message_queue(unmount_info.mq_name);
if (mq == (mqd_t)-1) {
ERROR_WITH_ERRNO("Can't create POSIX message queue");
return WIMLIB_ERR_MQUEUE;
}
args.mq = mq;
args.progfunc = progfunc;
args.progctx = progctx;
if (!thread_create(&commit_progress_tid,
commit_progress_thread_proc, &args)) {
ret = WIMLIB_ERR_NOMEM;
goto out_delete_mq;
}
unmount_info.unmount_flags |= WIMLIB_UNMOUNT_FLAG_SEND_PROGRESS;
}
ret = set_unmount_info(dir, &unmount_info);
if (!ret)
ret = do_unmount(dir);
if (progfunc) {
/* Terminate the progress thread. */
char empty[1];
mq_send(mq, empty, 0, 1);
thread_join(&commit_progress_tid);
}
out_delete_mq:
if (progfunc) {
mq_close(mq);
mq_unlink(unmount_info.mq_name);
}
return ret;
}
static int
begin_unmount(const char *dir, int unmount_flags, int *mount_flags_ret,
wimlib_progress_func_t progfunc, void *progctx)
{
int mount_flags;
int mounted_image;
int wim_filename_len;
union wimlib_progress_info progress;
if (getxattr(dir, "wimfs.mount_flags",
&mount_flags, sizeof(int)) != sizeof(int))
return WIMLIB_ERR_NOT_A_MOUNTPOINT;
*mount_flags_ret = mount_flags;
if (!progfunc)
return 0;
if (getxattr(dir, "wimfs.mounted_image",
&mounted_image, sizeof(int)) != sizeof(int))
return WIMLIB_ERR_NOT_A_MOUNTPOINT;
wim_filename_len = getxattr(dir, "wimfs.wim_filename", NULL, 0);
if (wim_filename_len < 0)
return WIMLIB_ERR_NOT_A_MOUNTPOINT;
char wim_filename[wim_filename_len + 1];
if (getxattr(dir, "wimfs.wim_filename",
wim_filename, wim_filename_len) != wim_filename_len)
return WIMLIB_ERR_NOT_A_MOUNTPOINT;
wim_filename[wim_filename_len] = '\0';
progress.unmount.mountpoint = dir;
progress.unmount.mounted_wim = wim_filename;
progress.unmount.mounted_image = mounted_image;
progress.unmount.mount_flags = mount_flags;
progress.unmount.unmount_flags = unmount_flags;
return call_progress(progfunc, WIMLIB_PROGRESS_MSG_UNMOUNT_BEGIN,
&progress, progctx);
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_unmount_image_with_progress(const char *dir, int unmount_flags,
wimlib_progress_func_t progfunc, void *progctx)
{
int mount_flags;
int ret;
ret = wimlib_global_init(0);
if (ret)
return ret;
if (unmount_flags & ~(WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY |
WIMLIB_UNMOUNT_FLAG_COMMIT |
WIMLIB_UNMOUNT_FLAG_REBUILD |
WIMLIB_UNMOUNT_FLAG_RECOMPRESS |
WIMLIB_UNMOUNT_FLAG_FORCE |
WIMLIB_UNMOUNT_FLAG_NEW_IMAGE))
return WIMLIB_ERR_INVALID_PARAM;
ret = begin_unmount(dir, unmount_flags, &mount_flags,
progfunc, progctx);
if (ret)
return ret;
if ((unmount_flags & WIMLIB_UNMOUNT_FLAG_COMMIT) &&
(mount_flags & WIMLIB_MOUNT_FLAG_READWRITE))
return do_unmount_commit(dir, unmount_flags,
progfunc, progctx);
else
return do_unmount_discard(dir);
}
#else /* WITH_FUSE */
static int
mount_unsupported_error(void)
{
#ifdef _WIN32
ERROR("Sorry-- Mounting WIM images is not supported on Windows!");
#else
ERROR("wimlib was compiled with --without-fuse, which disables support "
"for mounting WIMs.");
#endif
return WIMLIB_ERR_UNSUPPORTED;
}
WIMLIBAPI int
wimlib_unmount_image_with_progress(const tchar *dir, int unmount_flags,
wimlib_progress_func_t progfunc, void *progctx)
{
return mount_unsupported_error();
}
WIMLIBAPI int
wimlib_mount_image(WIMStruct *wim, int image, const tchar *dir,
int mount_flags, const tchar *staging_dir)
{
return mount_unsupported_error();
}
#endif /* !WITH_FUSE */
WIMLIBAPI int
wimlib_unmount_image(const tchar *dir, int unmount_flags)
{
return wimlib_unmount_image_with_progress(dir, unmount_flags, NULL, NULL);
}
wimlib-1.14.5/src/file_io.c 0000644 0001750 0001750 00000011553 15137020663 012730 0 ustar 00e e /*
* file_io.c - Helper functions for reading and writing to file descriptors.
*/
/*
* Copyright (C) 2013 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include "wimlib/error.h"
#include "wimlib/file_io.h"
#include "wimlib/util.h"
#ifdef _WIN32
# include "wimlib/win32.h"
# define read win32_read
# define write win32_write
# define pread win32_pread
# define pwrite win32_pwrite
#endif
/*
* Wrapper around read() that checks for errors and keeps retrying until all
* requested bytes have been read or until end-of file has occurred.
*
* Return values:
* WIMLIB_ERR_SUCCESS (0)
* WIMLIB_ERR_READ (errno set)
* WIMLIB_ERR_UNEXPECTED_END_OF_FILE (errno set to EINVAL)
*/
int
full_read(struct filedes *fd, void *buf, size_t count)
{
while (count) {
ssize_t ret = read(fd->fd, buf, count);
if (unlikely(ret <= 0)) {
if (ret == 0) {
errno = EINVAL;
return WIMLIB_ERR_UNEXPECTED_END_OF_FILE;
}
if (errno == EINTR)
continue;
return WIMLIB_ERR_READ;
}
buf += ret;
count -= ret;
fd->offset += ret;
}
return 0;
}
static int
pipe_read(struct filedes *fd, void *buf, size_t count, off_t offset)
{
int ret;
/* Verify the offset. */
if (offset < fd->offset) {
ERROR("Can't seek backwards in pipe "
"(offset %"PRIu64" => %"PRIu64").\n"
" Make sure the WIM was captured as "
"pipable.", fd->offset, offset);
errno = ESPIPE;
return WIMLIB_ERR_RESOURCE_ORDER;
}
/* Manually seek to the requested position. */
while (fd->offset != offset) {
size_t bytes_to_read = min(offset - fd->offset, BUFFER_SIZE);
u8 dummy[bytes_to_read];
ret = full_read(fd, dummy, bytes_to_read);
if (ret)
return ret;
}
/* Do the actual read. */
return full_read(fd, buf, count);
}
/*
* Wrapper around pread() that checks for errors and keeps retrying until all
* requested bytes have been read or until end-of file has occurred. This also
* transparently handle reading from pipe files, but the caller needs to be sure
* the requested offset is greater than or equal to the current offset, or else
* WIMLIB_ERR_RESOURCE_ORDER will be returned.
*
* Return values:
* WIMLIB_ERR_SUCCESS (0)
* WIMLIB_ERR_READ (errno set)
* WIMLIB_ERR_UNEXPECTED_END_OF_FILE (errno set to EINVAL)
* WIMLIB_ERR_RESOURCE_ORDER (errno set to ESPIPE)
*/
int
full_pread(struct filedes *fd, void *buf, size_t count, off_t offset)
{
if (fd->is_pipe)
goto is_pipe;
while (count) {
ssize_t ret = pread(fd->fd, buf, count, offset);
if (unlikely(ret <= 0)) {
if (ret == 0) {
errno = EINVAL;
return WIMLIB_ERR_UNEXPECTED_END_OF_FILE;
}
if (errno == EINTR)
continue;
if (errno == ESPIPE) {
fd->is_pipe = 1;
goto is_pipe;
}
return WIMLIB_ERR_READ;
}
buf += ret;
count -= ret;
offset += ret;
}
return 0;
is_pipe:
return pipe_read(fd, buf, count, offset);
}
/*
* Wrapper around write() that checks for errors and keeps retrying until all
* requested bytes have been written.
*
* Return values:
* WIMLIB_ERR_SUCCESS (0)
* WIMLIB_ERR_WRITE (errno set)
*/
int
full_write(struct filedes *fd, const void *buf, size_t count)
{
while (count) {
ssize_t ret = write(fd->fd, buf, count);
if (unlikely(ret < 0)) {
if (errno == EINTR)
continue;
return WIMLIB_ERR_WRITE;
}
buf += ret;
count -= ret;
fd->offset += ret;
}
return 0;
}
/*
* Wrapper around pwrite() that checks for errors and keeps retrying until all
* requested bytes have been written.
*
* Return values:
* WIMLIB_ERR_SUCCESS (0)
* WIMLIB_ERR_WRITE (errno set)
*/
int
full_pwrite(struct filedes *fd, const void *buf, size_t count, off_t offset)
{
while (count) {
ssize_t ret = pwrite(fd->fd, buf, count, offset);
if (unlikely(ret < 0)) {
if (errno == EINTR)
continue;
return WIMLIB_ERR_WRITE;
}
buf += ret;
count -= ret;
offset += ret;
}
return 0;
}
off_t filedes_seek(struct filedes *fd, off_t offset)
{
if (fd->is_pipe) {
errno = ESPIPE;
return -1;
}
if (fd->offset != offset) {
if (lseek(fd->fd, offset, SEEK_SET) == -1)
return -1;
fd->offset = offset;
}
return offset;
}
bool filedes_is_seekable(struct filedes *fd)
{
return !fd->is_pipe && lseek(fd->fd, 0, SEEK_CUR) != -1;
}
wimlib-1.14.5/src/xmlproc.c 0000644 0001750 0001750 00000044533 15137020663 013012 0 ustar 00e e /*
* xmlproc.c
*
* A simple XML 1.0 processor. This handles all XML features that are used in
* WIM files, plus a bit more for futureproofing. It omits problematic
* features, such as expansion of entities other than simple escape sequences.
*/
/*
* Copyright 2023 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include "wimlib/error.h"
#include "wimlib/test_support.h"
#include "wimlib/util.h"
#include "wimlib/xmlproc.h"
/*----------------------------------------------------------------------------*
* XML node utility functions *
*----------------------------------------------------------------------------*/
static tchar *
tstrdupz(const tchar *str, size_t len)
{
tchar *new_str = CALLOC(len + 1, sizeof(str[0]));
if (new_str)
tmemcpy(new_str, str, len);
return new_str;
}
static struct xml_node *
xml_new_node(struct xml_node *parent, enum xml_node_type type,
const tchar *name, size_t name_len,
const tchar *value, size_t value_len)
{
struct xml_node *node = CALLOC(1, sizeof(*node));
if (!node)
return NULL;
node->type = type;
INIT_LIST_HEAD(&node->children);
if (name) {
node->name = tstrdupz(name, name_len);
if (!node->name)
goto oom;
}
if (value) {
node->value = tstrdupz(value, value_len);
if (!node->value)
goto oom;
}
if (parent)
xml_add_child(parent, node);
return node;
oom:
xml_free_node(node);
return NULL;
}
/*
* Create a new ELEMENT node, and if @parent is non-NULL add the new node under
* @parent which should be another ELEMENT.
*/
struct xml_node *
xml_new_element(struct xml_node *parent, const tchar *name)
{
return xml_new_node(parent, XML_ELEMENT_NODE, name, tstrlen(name),
NULL, 0);
}
/*
* Create a new ELEMENT node with an attached TEXT node, and if @parent is
* non-NULL add the new ELEMENT under @parent which should be another ELEMENT.
*/
struct xml_node *
xml_new_element_with_text(struct xml_node *parent, const tchar *name,
const tchar *text)
{
struct xml_node *element = xml_new_element(parent, name);
if (element && xml_element_set_text(element, text) != 0) {
xml_free_node(element);
return NULL;
}
return element;
}
/* Append @child to the children list of @parent. */
void
xml_add_child(struct xml_node *parent, struct xml_node *child)
{
xml_unlink_node(child); /* Shouldn't be needed, but be safe. */
child->parent = parent;
list_add_tail(&child->sibling_link, &parent->children);
}
/* Unlink @node from its parent, if it has one. */
void
xml_unlink_node(struct xml_node *node)
{
if (node->parent) {
list_del(&node->sibling_link);
node->parent = NULL;
}
}
static void
xml_free_children(struct xml_node *parent)
{
struct xml_node *child, *tmp;
list_for_each_entry_safe(child, tmp, &parent->children, sibling_link)
xml_free_node(child);
}
/* Recursively free @node, first unlinking it if needed. @node may be NULL. */
void
xml_free_node(struct xml_node *node)
{
if (node) {
xml_unlink_node(node);
xml_free_children(node);
FREE(node->name);
FREE(node->value);
FREE(node);
}
}
/*
* Return the text from the first TEXT child node of @element, or NULL if no
* such node exists. @element may be NULL.
*/
const tchar *
xml_element_get_text(const struct xml_node *element)
{
const struct xml_node *child;
xml_node_for_each_child(element, child)
if (child->type == XML_TEXT_NODE)
return child->value;
return NULL;
}
/*
* Set the contents of the given @element to the given @text, replacing the
* entire existing contents if any.
*/
int
xml_element_set_text(struct xml_node *element, const tchar *text)
{
struct xml_node *text_node = xml_new_node(NULL, XML_TEXT_NODE, NULL, 0,
text, tstrlen(text));
if (!text_node)
return WIMLIB_ERR_NOMEM;
xml_free_children(element);
xml_add_child(element, text_node);
return 0;
}
static int
xml_element_append_text(struct xml_node *element,
const tchar *text, size_t text_len)
{
struct xml_node *last_child;
if (!list_empty(&element->children) &&
(last_child =
list_last_entry(&element->children, struct xml_node,
sibling_link))->type == XML_TEXT_NODE) {
/*
* The new TEXT would directly follow another TEXT, so simplify
* the tree by just appending to the existing TEXT. (This case
* can theoretically be reached via the use of CDATA...)
*/
size_t old_len = tstrlen(last_child->value);
tchar *new_value = CALLOC(old_len + text_len + 1,
sizeof(new_value[0]));
if (!new_value)
return WIMLIB_ERR_NOMEM;
tmemcpy(new_value, last_child->value, old_len);
tmemcpy(&new_value[old_len], text, text_len);
FREE(last_child->value);
last_child->value = new_value;
return 0;
}
if (!xml_new_node(element, XML_TEXT_NODE, NULL, 0, text, text_len))
return WIMLIB_ERR_NOMEM;
return 0;
}
/* Find the attribute with the given @name on @element. */
struct xml_node *
xml_get_attrib(const struct xml_node *element, const tchar *name)
{
struct xml_node *child;
xml_node_for_each_child(element, child) {
if (child->type == XML_ATTRIBUTE_NODE &&
!tstrcmp(child->name, name))
return child;
}
return NULL;
}
/* Set the attribute @name=@value on the given @element. */
int
xml_set_attrib(struct xml_node *element, const tchar *name, const tchar *value)
{
struct xml_node *attrib = xml_new_node(NULL, XML_ATTRIBUTE_NODE,
name, tstrlen(name),
value, tstrlen(value));
if (!attrib)
return WIMLIB_ERR_NOMEM;
xml_replace_child(element, attrib);
return 0;
}
/*
* Add the ELEMENT or ATTRIBUTE node @replacement under the ELEMENT @parent,
* replacing any node with the same type and name that already exists.
*/
void
xml_replace_child(struct xml_node *parent, struct xml_node *replacement)
{
struct xml_node *child;
xml_unlink_node(replacement); /* Shouldn't be needed, but be safe. */
xml_node_for_each_child(parent, child) {
if (child->type == replacement->type &&
!tstrcmp(child->name, replacement->name)) {
list_replace(&child->sibling_link,
&replacement->sibling_link);
replacement->parent = parent;
child->parent = NULL;
xml_free_node(child);
return;
}
}
xml_add_child(parent, replacement);
}
struct xml_node *
xml_clone_tree(struct xml_node *orig)
{
struct xml_node *clone, *orig_child, *clone_child;
clone = xml_new_node(NULL, orig->type,
orig->name, orig->name ? tstrlen(orig->name) : 0,
orig->value, orig->value ? tstrlen(orig->value) : 0);
if (!clone)
return NULL;
xml_node_for_each_child(orig, orig_child) {
clone_child = xml_clone_tree(orig_child);
if (!clone_child)
goto oom;
xml_add_child(clone, clone_child);
}
return clone;
oom:
xml_free_node(clone);
return NULL;
}
/*----------------------------------------------------------------------------*
* XML string validation *
*----------------------------------------------------------------------------*/
/*
* Functions that check for legal names and values in XML 1.0. These are
* currently slightly over-lenient, as they allow everything non-ASCII. These
* are also not currently used by the XML parser to reject non-well-formed
* documents, but rather just by the user of the XML processor (xml.c) in order
* to avoid introducing illegal names and values into the document.
*/
static inline bool
is_whitespace(tchar c)
{
return c == ' ' || c == '\n' || c == '\r' || c == '\t';
}
static inline bool
is_name_start_char(tchar c)
{
return (c & 0x7f) != c /* overly lenient for now */ ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
c == ':' || c == '_';
}
static inline bool
is_name_char(tchar c)
{
return is_name_start_char(c) ||
(c >= '0' && c <= '9') || c == '-' || c == '.';
}
/* Allow characters used in element "paths"; see do_xml_path_walk() */
static inline bool
is_path_char(tchar c)
{
return c == '/' || c == '[' || c == ']';
}
bool
xml_legal_path(const tchar *p)
{
if (!is_name_start_char(*p) && !is_path_char(*p))
return false;
for (p = p + 1; *p; p++) {
if (!is_name_char(*p) && !is_path_char(*p))
return false;
}
return true;
}
bool
xml_legal_value(const tchar *p)
{
for (; *p; p++) {
/* Careful: tchar can be signed. */
if (*p > 0 && *p < 0x20 && !is_whitespace(*p))
return false;
}
return true;
}
#if TCHAR_IS_UTF16LE
#define BYTE_ORDER_MARK (tchar[]){ 0xfeff, 0 }
#else
#define BYTE_ORDER_MARK "\xEF\xBB\xBF"
#endif
/*----------------------------------------------------------------------------*
* XML parsing *
*----------------------------------------------------------------------------*/
#define CHECK(cond) if (!(cond)) goto bad
static inline void
skip_whitespace(const tchar **pp)
{
const tchar *p = *pp;
while (is_whitespace(*p))
p++;
*pp = p;
}
static inline bool
skip_string(const tchar **pp, const tchar *str)
{
const tchar *p = *pp;
size_t len = tstrlen(str);
if (tstrncmp(p, str, len))
return false;
*pp = p + len;
return true;
}
static inline bool
find_and_skip(const tchar **pp, const tchar *str)
{
const tchar *p = *pp;
p = tstrstr(p, str);
if (!p)
return false;
*pp = p + tstrlen(str);
return true;
}
static bool
skip_misc(const tchar **pp)
{
const tchar *p = *pp, *prev_p;
do {
prev_p = p;
skip_whitespace(&p);
/* Discard XML declaration and top-level PIs for now. */
if (skip_string(&p, T("")) && !find_and_skip(&p, T("?>")))
return false;
/* Discard DOCTYPE declaration for now. */
if (skip_string(&p, T("")))
return false;
/* Discard top-level comments for now. */
if (skip_string(&p, T("")))
return false;
} while (p != prev_p);
*pp = p;
return true;
}
static inline const tchar *
get_escape_seq(tchar c)
{
switch (c) {
case '<':
return T("<");
case '>':
return T(">");
case '&':
return T("&");
case '\'':
return T("'");
case '"':
return T(""");
}
return NULL;
}
/* Note: 'str' must be NUL-terminated, but only 'len' chars are used. */
static int
unescape_string(const tchar *str, size_t len, tchar **unescaped_ret)
{
const tchar *in_p = str;
tchar *unescaped, *out_p;
unescaped = CALLOC(len + 1, sizeof(str[0]));
if (!unescaped)
return WIMLIB_ERR_NOMEM;
out_p = unescaped;
while (in_p < &str[len]) {
if (*in_p != '&')
*out_p++ = *in_p++;
else if (skip_string(&in_p, T("<")))
*out_p++ = '<';
else if (skip_string(&in_p, T(">")))
*out_p++ = '>';
else if (skip_string(&in_p, T("&")))
*out_p++ = '&';
else if (skip_string(&in_p, T("'")))
*out_p++ = '\'';
else if (skip_string(&in_p, T(""")))
*out_p++ = '"';
else
goto bad;
}
if (in_p > &str[len])
goto bad;
*unescaped_ret = unescaped;
return 0;
bad:
ERROR("Error unescaping string '%.*"TS"'", (int)len, str);
FREE(unescaped);
return WIMLIB_ERR_XML;
}
static int
parse_element(const tchar **pp, struct xml_node *parent, int depth,
struct xml_node **node_ret);
static int
parse_contents(const tchar **pp, struct xml_node *element, int depth)
{
const tchar *p = *pp;
int ret;
for (;;) {
const tchar *raw_text = p;
tchar *text;
for (; *p != '<'; p++) {
if (*p == '\0')
return WIMLIB_ERR_XML;
}
if (p > raw_text) {
ret = unescape_string(raw_text, p - raw_text, &text);
if (ret)
return ret;
ret = xml_element_append_text(element, text,
tstrlen(text));
FREE(text);
if (ret)
return ret;
}
if (p[1] == '/') {
break; /* Reached the end tag of @element */
} else if (p[1] == '?') {
/* Discard processing instructions for now. */
p += 2;
if (!find_and_skip(&p, T("?>")))
return WIMLIB_ERR_XML;
continue;
} else if (p[1] == '!') {
if (skip_string(&p, T("")))
return WIMLIB_ERR_XML;
ret = xml_element_append_text(element, raw_text,
p - 3 - raw_text);
if (ret)
return ret;
continue;
} else if (skip_string(&p, T("")))
return WIMLIB_ERR_XML;
continue;
}
return WIMLIB_ERR_XML;
}
ret = parse_element(&p, element, depth + 1, NULL);
if (ret)
return ret;
}
*pp = p;
return 0;
}
static int
parse_element(const tchar **pp, struct xml_node *parent, int depth,
struct xml_node **element_ret)
{
const tchar *p = *pp;
struct xml_node *element = NULL;
const tchar *name_start;
size_t name_len;
int ret;
/* Parse the start tag. */
CHECK(depth < 50);
CHECK(*p == '<');
p++;
name_start = p;
while (!is_whitespace(*p) && *p != '>' && *p != '/' && *p != '\0')
p++;
name_len = p - name_start;
CHECK(name_len > 0);
element = xml_new_node(parent, XML_ELEMENT_NODE, name_start, name_len,
NULL, 0);
if (!element) {
ret = WIMLIB_ERR_NOMEM;
goto error;
}
/* Parse the attributes list within the start tag. */
while (is_whitespace(*p)) {
const tchar *attr_name_start, *attr_value_start;
size_t attr_name_len, attr_value_len;
tchar *attr_value;
tchar quote;
skip_whitespace(&p);
if (*p == '/' || *p == '>')
break;
attr_name_start = p;
while (*p != '=' && !is_whitespace(*p) && *p != '\0')
p++;
attr_name_len = p - attr_name_start;
skip_whitespace(&p);
CHECK(attr_name_len > 0 && *p == '=');
p++;
skip_whitespace(&p);
quote = *p;
CHECK(quote == '\'' || quote == '"');
attr_value_start = ++p;
while (*p != quote && *p != '\0')
p++;
CHECK(*p == quote);
attr_value_len = p - attr_value_start;
p++;
ret = unescape_string(attr_value_start, attr_value_len,
&attr_value);
if (ret)
goto error;
ret = xml_new_node(element, XML_ATTRIBUTE_NODE,
attr_name_start, attr_name_len,
attr_value, tstrlen(attr_value))
? 0 : WIMLIB_ERR_NOMEM;
FREE(attr_value);
if (ret)
goto error;
}
if (*p == '/') {
/* Closing an empty element tag */
p++;
} else {
/* Closing the start tag */
CHECK(*p == '>');
p++;
/* Parse the contents, then the end tag. */
ret = parse_contents(&p, element, depth);
if (ret)
goto error;
CHECK(*p == '<');
p++;
CHECK(*p == '/');
p++;
CHECK(!tstrncmp(p, name_start, name_len));
p += name_len;
skip_whitespace(&p);
}
CHECK(*p == '>');
p++;
*pp = p;
if (element_ret)
*element_ret = element;
return 0;
error:
xml_free_node(element);
return ret;
bad:
ret = WIMLIB_ERR_XML;
goto error;
}
/*
* Deserialize an XML document and return its root node in @doc_ret. The
* document must be given as a NUL-terminated string of 'tchar', i.e. UTF-16LE
* in Windows builds and UTF-8 everywhere else.
*/
int
xml_parse_document(const tchar *p, struct xml_node **doc_ret)
{
int ret;
struct xml_node *doc;
skip_string(&p, BYTE_ORDER_MARK);
if (!skip_misc(&p))
return WIMLIB_ERR_XML;
ret = parse_element(&p, NULL, 0, &doc);
if (ret)
return ret;
if (!skip_misc(&p) || *p) {
xml_free_node(doc);
return WIMLIB_ERR_XML;
}
*doc_ret = doc;
return 0;
}
/*----------------------------------------------------------------------------*
* XML writing *
*----------------------------------------------------------------------------*/
static void
xml_write(struct xml_out_buf *buf, const tchar *str, size_t len)
{
if (buf->count + len + 1 > buf->capacity) {
size_t new_capacity = max3(buf->count + len + 1,
buf->capacity * 2, 4096);
tchar *new_buf = REALLOC(buf->buf,
new_capacity * sizeof(str[0]));
if (!new_buf) {
buf->oom = true;
return;
}
buf->buf = new_buf;
buf->capacity = new_capacity;
}
tmemcpy(&buf->buf[buf->count], str, len);
buf->count += len;
}
static void
xml_puts(struct xml_out_buf *buf, const tchar *str)
{
xml_write(buf, str, tstrlen(str));
}
static void
xml_escape_and_puts(struct xml_out_buf *buf, const tchar *str)
{
const tchar *p = str, *saved, *seq = NULL;
for (;; p++) {
for (saved = p; *p && (seq = get_escape_seq(*p)) == NULL; p++)
;
xml_write(buf, saved, p - saved);
if (!*p)
return;
xml_puts(buf, seq);
}
}
static void
xml_write_element(struct xml_node *element, struct xml_out_buf *buf)
{
struct xml_node *child;
/* Write the start tag. */
xml_puts(buf, T("<"));
xml_puts(buf, element->name);
xml_node_for_each_child(element, child) {
if (child->type == XML_ATTRIBUTE_NODE) {
xml_puts(buf, T(" "));
xml_puts(buf, child->name);
xml_puts(buf, T("=\""));
xml_escape_and_puts(buf, child->value);
xml_puts(buf, T("\""));
}
}
xml_puts(buf, T(">"));
/* Write the contents. */
xml_node_for_each_child(element, child) {
if (child->type == XML_TEXT_NODE)
xml_escape_and_puts(buf, child->value);
else if (child->type == XML_ELEMENT_NODE)
xml_write_element(child, buf);
}
/* Write the end tag. */
xml_puts(buf, T(""));
xml_puts(buf, element->name);
xml_puts(buf, T(">"));
}
/*
* Serialize the document @doc into @buf as a NUL-terminated string of 'tchar',
* i.e. UTF-16LE in Windows builds and UTF-8 everywhere else. A byte order mark
* (BOM) is included, as this is needed for compatibility with WIMGAPI.
*/
int
xml_write_document(struct xml_node *doc, struct xml_out_buf *buf)
{
xml_puts(buf, BYTE_ORDER_MARK);
xml_write_element(doc, buf);
if (buf->oom)
return WIMLIB_ERR_NOMEM;
buf->buf[buf->count] = '\0';
return 0;
}
/*----------------------------------------------------------------------------*
* Test support *
*----------------------------------------------------------------------------*/
#ifdef ENABLE_TEST_SUPPORT
WIMLIBAPI int
wimlib_parse_and_write_xml_doc(const tchar *in, tchar **out_ret)
{
struct xml_node *doc;
struct xml_out_buf buf = {};
int ret;
ret = xml_parse_document(in, &doc);
if (ret)
return ret;
ret = xml_write_document(doc, &buf);
xml_free_node(doc);
*out_ret = buf.buf;
return ret;
}
#endif /* ENABLE_TEST_SUPPORT */
wimlib-1.14.5/src/cpu_features.c 0000644 0001750 0001750 00000016167 15137011205 014005 0 ustar 00e e /*
* cpu_features.c - runtime CPU feature detection
*
* Copyright 2022-2023 Eric Biggers
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/cpu_features.h"
#if CPU_FEATURES_ENABLED
#include "wimlib/util.h"
#include
#include
#if defined(__i386__) || defined(__x86_64__)
/*
* With old GCC versions we have to manually save and restore the x86_32 PIC
* register (ebx). See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47602
*/
#if defined(__i386__) && defined(__PIC__)
# define EBX_CONSTRAINT "=&r"
#else
# define EBX_CONSTRAINT "=b"
#endif
/* Execute the CPUID instruction. */
static inline void
cpuid(u32 leaf, u32 subleaf, u32 *a, u32 *b, u32 *c, u32 *d)
{
asm volatile(".ifnc %%ebx, %1; mov %%ebx, %1; .endif\n"
"cpuid \n"
".ifnc %%ebx, %1; xchg %%ebx, %1; .endif\n"
: "=a" (*a), EBX_CONSTRAINT (*b), "=c" (*c), "=d" (*d)
: "a" (leaf), "c" (subleaf));
}
/* Read an extended control register. */
static inline u64
read_xcr(u32 index)
{
u32 d, a;
/*
* Execute the "xgetbv" instruction. Old versions of binutils do not
* recognize this instruction, so list the raw bytes instead.
*
* This must be 'volatile' to prevent this code from being moved out
* from under the check for OSXSAVE.
*/
asm volatile(".byte 0x0f, 0x01, 0xd0" :
"=d" (d), "=a" (a) : "c" (index));
return ((u64)d << 32) | a;
}
static u32
get_cpu_features(void)
{
u32 max_leaf, a, b, c, d;
u64 xcr0 = 0;
u32 features = 0;
/* EAX=0: Highest Function Parameter and Manufacturer ID */
cpuid(0, 0, &max_leaf, &b, &c, &d);
if (max_leaf < 1)
return features;
/* EAX=1: Processor Info and Feature Bits */
cpuid(1, 0, &a, &b, &c, &d);
if (c & (1 << 9))
features |= X86_CPU_FEATURE_SSSE3;
if (c & (1 << 19))
features |= X86_CPU_FEATURE_SSE4_1;
if (c & (1 << 20))
features |= X86_CPU_FEATURE_SSE4_2;
if (c & (1 << 27))
xcr0 = read_xcr(0);
if ((c & (1 << 28)) && ((xcr0 & 0x6) == 0x6))
features |= X86_CPU_FEATURE_AVX;
if (max_leaf < 7)
return features;
/* EAX=7, ECX=0: Extended Features */
cpuid(7, 0, &a, &b, &c, &d);
if (b & (1 << 8))
features |= X86_CPU_FEATURE_BMI2;
if (b & (1 << 29))
features |= X86_CPU_FEATURE_SHA;
return features;
}
#elif defined(__aarch64__) && defined(__linux__)
/*
* On Linux, arm32 and arm64 CPU features can be detected by reading the
* AT_HWCAP and AT_HWCAP2 values from /proc/self/auxv.
*
* Ideally we'd use the C library function getauxval(), but it's not guaranteed
* to be available: it was only added to glibc in 2.16, and in Android it was
* added to API level 18 for arm32 and level 21 for arm64.
*/
#include
#include
#include
#include
#define AT_HWCAP 16
#define AT_HWCAP2 26
static void scan_auxv(unsigned long *hwcap, unsigned long *hwcap2)
{
int fd;
unsigned long auxbuf[32];
int filled = 0;
int i;
fd = open("/proc/self/auxv", O_RDONLY);
if (fd < 0)
return;
for (;;) {
do {
int ret = read(fd, &((char *)auxbuf)[filled],
sizeof(auxbuf) - filled);
if (ret <= 0) {
if (ret < 0 && errno == EINTR)
continue;
goto out;
}
filled += ret;
} while (filled < 2 * sizeof(long));
i = 0;
do {
unsigned long type = auxbuf[i];
unsigned long value = auxbuf[i + 1];
if (type == AT_HWCAP)
*hwcap = value;
else if (type == AT_HWCAP2)
*hwcap2 = value;
i += 2;
filled -= 2 * sizeof(long);
} while (filled >= 2 * sizeof(long));
memmove(auxbuf, &auxbuf[i], filled);
}
out:
close(fd);
}
static u32
get_cpu_features(void)
{
unsigned long hwcap = 0;
unsigned long hwcap2 = 0;
u32 features = 0;
scan_auxv(&hwcap, &hwcap2);
if (hwcap & (1 << 5)) /* HWCAP_SHA1 */
features |= ARM_CPU_FEATURE_SHA1;
return features;
}
#elif defined(__aarch64__) && defined(__APPLE__)
/* On Apple platforms, arm64 CPU features can be detected via sysctlbyname(). */
#include
#include
static const struct {
const char *name;
u32 feature;
} feature_sysctls[] = {
{ "hw.optional.arm.FEAT_SHA1", ARM_CPU_FEATURE_SHA1 },
};
static u32
get_cpu_features(void)
{
u32 features = 0;
for (size_t i = 0; i < ARRAY_LEN(feature_sysctls); i++) {
const char *name = feature_sysctls[i].name;
u32 val = 0;
size_t valsize = sizeof(val);
if (sysctlbyname(name, &val, &valsize, NULL, 0) == 0 &&
valsize == sizeof(val) && val == 1)
features |= feature_sysctls[i].feature;
}
return features;
}
#elif defined(__aarch64__) && defined(_WIN32)
#include
static u32
get_cpu_features(void)
{
u32 features = 0;
if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE))
features |= ARM_CPU_FEATURE_SHA1;
return features;
}
#else
# error "CPU_FEATURES_ENABLED was set but no implementation is available!"
#endif
static const struct {
const char *name;
u32 feature;
} feature_table[] = {
#if defined(__i386__) || defined(__x86_64__)
{"ssse3", X86_CPU_FEATURE_SSSE3},
{"sse4.1", X86_CPU_FEATURE_SSE4_1},
{"sse4.2", X86_CPU_FEATURE_SSE4_2},
{"avx", X86_CPU_FEATURE_AVX},
{"bmi2", X86_CPU_FEATURE_BMI2},
{"sha", X86_CPU_FEATURE_SHA},
{"sha1", X86_CPU_FEATURE_SHA},
#elif defined(__aarch64__)
{"sha1", ARM_CPU_FEATURE_SHA1},
#else
# error "CPU_FEATURES_ENABLED was set but no features are defined!"
#endif
{"*", 0xFFFFFFFF},
};
static u32
find_cpu_feature(const char *name, size_t namelen)
{
for (size_t i = 0; i < ARRAY_LEN(feature_table); i++) {
if (namelen == strlen(feature_table[i].name) &&
memcmp(name, feature_table[i].name, namelen) == 0)
return feature_table[i].feature;
}
return 0;
}
u32 cpu_features;
void init_cpu_features(void)
{
char *p, *sep;
cpu_features = get_cpu_features();
/*
* Allow disabling CPU features via an environmental variable for
* testing purposes. Syntax is comma-separated list of feature names.
*/
p = getenv("WIMLIB_DISABLE_CPU_FEATURES");
if (likely(p == NULL))
return;
for (; (sep = strchr(p, ',')) != NULL; p = sep + 1)
cpu_features &= ~find_cpu_feature(p, sep - p);
cpu_features &= ~find_cpu_feature(p, strlen(p));
}
#endif /* CPU_FEATURES_ENABLED */
wimlib-1.14.5/src/sha1.c 0000644 0001750 0001750 00000053504 15137011205 012150 0 ustar 00e e /*
* sha1.c - implementation of the Secure Hash Algorithm version 1 (FIPS 180-1)
*
* Copyright 2022-2023 Eric Biggers
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/cpu_features.h"
#include "wimlib/endianness.h"
#include "wimlib/sha1.h"
#include "wimlib/unaligned.h"
/*----------------------------------------------------------------------------*
* Shared helpers *
*----------------------------------------------------------------------------*/
static inline u32
rol32(u32 v, int bits)
{
return (v << bits) | (v >> (32 - bits));
}
/* Expands to the round constant for the given round */
#define SHA1_K(i) \
(((i) < 20) ? 0x5A827999 : \
((i) < 40) ? 0x6ED9EBA1 : \
((i) < 60) ? 0x8F1BBCDC : \
0xCA62C1D6)
/* Expands to the computation on b, c, and d for the given round */
#define SHA1_F(i, b, c, d) \
(((i) < 20) ? /* Choice */ (b & (c ^ d)) ^ d : \
((i) < 40) ? /* Parity */ b ^ c ^ d : \
((i) < 60) ? /* Majority */ (c & d) ^ (b & (c ^ d)) : \
/* Parity */ b ^ c ^ d)
/*
* Expands to a memory barrier for the given array, preventing values of the
* array from being cached in registers past the barrier. Use this to prevent
* the compiler from making counter-productive optimizations when there aren't
* enough registers available to hold the full array.
*/
#define FORCE_NOT_CACHED(array) asm volatile("" : "+m" (array))
/*
* Expands to FORCE_NOT_CACHED() if the architecture has 16 or fewer general
* purpose registers, otherwise does nothing.
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
# define FORCE_NOT_CACHED_IF_FEW_REGS(array) FORCE_NOT_CACHED(array)
#else
# define FORCE_NOT_CACHED_IF_FEW_REGS(array) (void)(array)
#endif
/*----------------------------------------------------------------------------*
* Generic implementation *
*----------------------------------------------------------------------------*/
/*
* This is SHA-1 in portable C code. It computes the message schedule
* just-in-time, in a rolling window of length 16.
*/
#define SHA1_GENERIC_ROUND(i, a, b, c, d, e) \
FORCE_NOT_CACHED_IF_FEW_REGS(w); \
if ((i) < 16) \
w[i] = get_unaligned_be32(data + ((i) * 4)); \
else \
w[(i) % 16] = rol32(w[((i) - 16) % 16] ^ \
w[((i) - 14) % 16] ^ \
w[((i) - 8) % 16] ^ \
w[((i) - 3) % 16], 1); \
e += w[(i) % 16] + rol32(a, 5) + SHA1_F((i), b, c, d) + SHA1_K(i); \
b = rol32(b, 30);
/* implicit: the new (a, b, c, d, e) is the old (e, a, b, c, d) */
#define SHA1_GENERIC_5ROUNDS(i) \
SHA1_GENERIC_ROUND((i) + 0, a, b, c, d, e); \
SHA1_GENERIC_ROUND((i) + 1, e, a, b, c, d); \
SHA1_GENERIC_ROUND((i) + 2, d, e, a, b, c); \
SHA1_GENERIC_ROUND((i) + 3, c, d, e, a, b); \
SHA1_GENERIC_ROUND((i) + 4, b, c, d, e, a);
#define SHA1_GENERIC_20ROUNDS(i) \
SHA1_GENERIC_5ROUNDS((i) + 0); \
SHA1_GENERIC_5ROUNDS((i) + 5); \
SHA1_GENERIC_5ROUNDS((i) + 10); \
SHA1_GENERIC_5ROUNDS((i) + 15);
static void
sha1_blocks_generic(u32 h[5], const void *data, size_t num_blocks)
{
do {
u32 a = h[0];
u32 b = h[1];
u32 c = h[2];
u32 d = h[3];
u32 e = h[4];
u32 w[16];
SHA1_GENERIC_20ROUNDS(0);
SHA1_GENERIC_20ROUNDS(20);
SHA1_GENERIC_20ROUNDS(40);
SHA1_GENERIC_20ROUNDS(60);
h[0] += a;
h[1] += b;
h[2] += c;
h[3] += d;
h[4] += e;
data += SHA1_BLOCK_SIZE;
} while (--num_blocks);
}
/*----------------------------------------------------------------------------*
* x86 SSSE3 (and AVX+BMI2) implementation *
*----------------------------------------------------------------------------*/
/*
* This is SHA-1 using the x86 SSSE3 instructions. A copy of it is also
* compiled with AVX and BMI2 code generation enabled for improved performance.
*
* Unfortunately this isn't actually much faster than the generic
* implementation, since only the message schedule can be vectorized, not the
* SHA itself. The vectorized computation of the message schedule is
* interleaved with the scalar computation of the SHA itself.
*
* Specifically, 16 rounds ahead of time, the words of the message schedule are
* calculated, the round constants are added to them, and they are stored in a
* temporary array that the scalar code reads from later. This is done 4 words
* at a time, but split into 4 steps, so that one step is executed during each
* round. Rounds 16-31 use the usual formula 'w[i] = rol32(w[i-16] ^ w[i-14] ^
* w[i-8] ^ w[i-3], 1)', while rounds 32-79 use the equivalent formula 'w[i] =
* rol32(w[i-32] ^ w[i-28] ^ w[i-16] ^ w[i-6], 2)' for improved vectorization.
*
* During rounds 80-95, the first 16 message schedule words for the next block
* are prepared.
*/
#if defined(__i386__) || defined(__x86_64__)
#include
#define SHA1_SSSE3_PRECALC(i, w0, w1, w2, w3, w4, w5, w6, w7) \
if ((i) % 20 == 0) \
k = _mm_set1_epi32(SHA1_K((i) % 80)); \
if ((i) < 32) { \
/*
* Vectorized computation of w[i] = rol32(w[i-16] ^ w[i-14] ^
* w[i-8] ^ w[i-3], 1) for i...i+3, split into 4 steps.
* w[i-16..i+3] are in (w0, w1, w2, w3, w4).
*/ \
if ((i) % 4 == 0) { \
w4 = _mm_alignr_epi8(w1, w0, 8) ^ w2; \
t0 = _mm_srli_si128(w3, 4); \
} else if ((i) % 4 == 1) { \
t0 ^= w4 ^ w0; \
t1 = _mm_slli_si128(t0, 12); \
} else if ((i) % 4 == 2) { \
t2 = _mm_slli_epi32(t1, 2); \
w4 = _mm_slli_epi32(t0, 1); \
t0 = _mm_srli_epi32(t0, 31); \
t2 ^= _mm_srli_epi32(t1, 30); \
} else { \
w4 ^= t0 ^ t2; \
t0 = _mm_add_epi32(w4, k); \
_mm_store_si128((__m128i *)&tmp[((i) - 3) % 16], t0); \
} \
} else if ((i) < 80) { \
/*
* Vectorized computation of w[i] = rol32(w[i-32] ^ w[i-28] ^
* w[i-16] ^ w[i-6], 2) for i...i+3, split into 4 steps.
* w[i-32..i+3] are in (w4, w5, w6, w7, w0, w1, w2, w3, w4);
* note the reuse of w4.
*/ \
if ((i) % 4 == 0) \
w4 ^= _mm_alignr_epi8(w3, w2, 8); \
else if ((i) % 4 == 1) \
w4 ^= w5 ^ w0; \
else if ((i) % 4 == 2) \
w4 = _mm_slli_epi32(w4, 2) ^ \
_mm_srli_epi32(w4, 30); \
else \
_mm_store_si128((__m128i *)&tmp[((i) - 3) % 16],\
_mm_add_epi32(w4, k)); \
} else if ((i) < 96) { \
/* Precomputation of w[0..15] for next block */ \
if ((i) == 80 && --num_blocks != 0) \
data += SHA1_BLOCK_SIZE; \
if ((i) % 4 == 0) \
w0 = _mm_loadu_si128(data + (((i) - 80) * 4)); \
else if ((i) % 4 == 1) \
w0 = _mm_shuffle_epi8(w0, bswap32_mask); \
else if ((i) % 4 == 2) \
t0 = _mm_add_epi32(w0, k); \
else \
_mm_store_si128((__m128i *)&tmp[(i) - 83], t0); \
}
#define SHA1_SSSE3_2ROUNDS(i, a, b, c, d, e, w0, w1, w2, w3, w4, w5, w6, w7) \
FORCE_NOT_CACHED(tmp); \
e += tmp[(i) % 16] + rol32(a, 5) + SHA1_F((i), b, c, d); \
b = rol32(b, 30); \
SHA1_SSSE3_PRECALC((i) + 16, w0, w1, w2, w3, w4, w5, w6, w7); \
FORCE_NOT_CACHED(tmp); \
d += tmp[((i) + 1) % 16] + rol32(e, 5) + SHA1_F((i) + 1, a, b, c); \
SHA1_SSSE3_PRECALC((i) + 17, w0, w1, w2, w3, w4, w5, w6, w7); \
a = rol32(a, 30);
/* implicit: the new (a, b, c, d, e) is the old (d, e, a, b, c) */
#define SHA1_SSSE3_4ROUNDS(i, a, b, c, d, e, w0, w1, w2, w3, w4, w5, w6, w7) \
SHA1_SSSE3_2ROUNDS((i) + 0, a, b, c, d, e, w0, w1, w2, w3, w4, w5, w6, w7); \
SHA1_SSSE3_2ROUNDS((i) + 2, d, e, a, b, c, w0, w1, w2, w3, w4, w5, w6, w7); \
/*
* implicit: the new (w0-w7) is the old (w1-w7,w0),
* and the new (a, b, c, d, e) is the old (b, c, d, e, a)
*/
#define SHA1_SSSE3_20ROUNDS(i, w0, w1, w2, w3, w4, w5, w6, w7) \
SHA1_SSSE3_4ROUNDS((i) + 0, a, b, c, d, e, w0, w1, w2, w3, w4, w5, w6, w7); \
SHA1_SSSE3_4ROUNDS((i) + 4, b, c, d, e, a, w1, w2, w3, w4, w5, w6, w7, w0); \
SHA1_SSSE3_4ROUNDS((i) + 8, c, d, e, a, b, w2, w3, w4, w5, w6, w7, w0, w1); \
SHA1_SSSE3_4ROUNDS((i) + 12, d, e, a, b, c, w3, w4, w5, w6, w7, w0, w1, w2); \
SHA1_SSSE3_4ROUNDS((i) + 16, e, a, b, c, d, w4, w5, w6, w7, w0, w1, w2, w3);
/* implicit: the new (w0-w7) is the old (w5-w7,w0-w4) */
#define SHA1_SSSE3_BODY \
const __m128i bswap32_mask = \
_mm_setr_epi8( 3, 2, 1, 0, 7, 6, 5, 4, \
11, 10, 9, 8, 15, 14, 13, 12); \
__m128i w0, w1, w2, w3, w4, w5, w6, w7; \
__m128i k = _mm_set1_epi32(SHA1_K(0)); \
u32 tmp[16] __attribute__((aligned(16))); \
\
w0 = _mm_shuffle_epi8(_mm_loadu_si128(data + 0), bswap32_mask); \
w1 = _mm_shuffle_epi8(_mm_loadu_si128(data + 16), bswap32_mask); \
w2 = _mm_shuffle_epi8(_mm_loadu_si128(data + 32), bswap32_mask); \
w3 = _mm_shuffle_epi8(_mm_loadu_si128(data + 48), bswap32_mask); \
_mm_store_si128((__m128i *)&tmp[0], _mm_add_epi32(w0, k)); \
_mm_store_si128((__m128i *)&tmp[4], _mm_add_epi32(w1, k)); \
_mm_store_si128((__m128i *)&tmp[8], _mm_add_epi32(w2, k)); \
_mm_store_si128((__m128i *)&tmp[12], _mm_add_epi32(w3, k)); \
\
do { \
u32 a = h[0]; \
u32 b = h[1]; \
u32 c = h[2]; \
u32 d = h[3]; \
u32 e = h[4]; \
__m128i t0, t1, t2; \
\
SHA1_SSSE3_20ROUNDS(0, w0, w1, w2, w3, w4, w5, w6, w7); \
SHA1_SSSE3_20ROUNDS(20, w5, w6, w7, w0, w1, w2, w3, w4); \
SHA1_SSSE3_20ROUNDS(40, w2, w3, w4, w5, w6, w7, w0, w1); \
SHA1_SSSE3_20ROUNDS(60, w7, w0, w1, w2, w3, w4, w5, w6); \
\
h[0] += a; \
h[1] += b; \
h[2] += c; \
h[3] += d; \
h[4] += e; \
\
/* 'data' and 'num_blocks' were updated at start of round 64. */ \
} while (num_blocks);
#define HAVE_SHA1_BLOCKS_X86_SSSE3
static void __attribute__((target("ssse3")))
sha1_blocks_x86_ssse3(u32 h[5], const void *data, size_t num_blocks)
{
SHA1_SSSE3_BODY;
}
#define HAVE_SHA1_BLOCKS_X86_AVX_BMI2
static void __attribute__((target("avx,bmi2")))
sha1_blocks_x86_avx_bmi2(u32 h[5], const void *data, size_t num_blocks)
{
SHA1_SSSE3_BODY;
}
#endif /* x86 SSSE3 (and AVX+BMI2) implementation */
/*----------------------------------------------------------------------------*
* x86 SHA Extensions implementation *
*----------------------------------------------------------------------------*/
/*
* This is SHA-1 using the x86 SHA extensions.
*
* The SHA1RNDS4 instruction does most of the work. It takes in a 128-bit
* vector containing 'a', 'b', 'c', and 'd' (high-order to low-order), a 128-bit
* vector containing the next 4 words of the message schedule with 'e' added to
* the high-order word, and an immediate that identifies the current 20-round
* section. It does 4 rounds and updates 'a', 'b', 'c', and 'd' accordingly.
*
* Each SHA1RNDS4 is paired with SHA1NEXTE. It takes in the abcd vector,
* calculates the value of 'e' after 4 rounds, and adds it to the high-order
* word of a vector that contains the next 4 words of the message schedule.
*
* Each 4 words of the message schedule for rounds 16-79 is calculated as
* rol32(w[i-16] ^ w[i-14] ^ w[i-8] ^ w[i-3], 1) in three steps using the
* SHA1MSG1, PXOR, and SHA1MSG2 instructions. This happens in a rolling window,
* so during the j'th set of 4 rounds we do the SHA1MSG2 step for j+1'th set of
* message schedule words, PXOR for j+2'th set, and SHA1MSG1 for the j+3'th set.
*/
#if defined(__i386__) || defined(__x86_64__)
#include
#define SHA1_NI_4ROUNDS(i, w0, w1, w2, w3, we0, we1) \
if ((i) < 16) \
w0 = _mm_shuffle_epi8( \
_mm_loadu_si128(data + ((i) * 4)), bswap_mask); \
if ((i) == 0) \
we0 = _mm_add_epi32(h_e, w0); \
else \
we0 = _mm_sha1nexte_epu32(/* old abcd */ we0, w0); \
we1 = abcd; \
if ((i) >= 12 && (i) < 76) \
w1 = _mm_sha1msg2_epu32(w1, w0); \
abcd = _mm_sha1rnds4_epu32(abcd, we0, (i) / 20); \
if ((i) >= 8 && (i) < 72) \
w2 ^= w0; \
if ((i) >= 4 && (i) < 68) \
w3 = _mm_sha1msg1_epu32(w3, w0); \
/*
* implicit: the new (w0, w1, w2, w3) is the old (w1, w2, w3, w0),
* and the new (we0, we1) is the old (we1, we0)
*/
#define SHA1_NI_16ROUNDS(i) \
SHA1_NI_4ROUNDS((i) + 0, w0, w1, w2, w3, we0, we1); \
SHA1_NI_4ROUNDS((i) + 4, w1, w2, w3, w0, we1, we0); \
SHA1_NI_4ROUNDS((i) + 8, w2, w3, w0, w1, we0, we1); \
SHA1_NI_4ROUNDS((i) + 12, w3, w0, w1, w2, we1, we0);
#define HAVE_SHA1_BLOCKS_X86_SHA
static void __attribute__((target("sha,sse4.1")))
sha1_blocks_x86_sha(u32 h[5], const void *data, size_t num_blocks)
{
const __m128i bswap_mask =
_mm_setr_epi8(15, 14, 13, 12, 11, 10, 9, 8,
7, 6, 5, 4, 3, 2, 1, 0);
__m128i h_abcd = _mm_shuffle_epi32(
_mm_loadu_si128((__m128i *)h), 0x1B);
__m128i h_e = _mm_setr_epi32(0, 0, 0, h[4]);
do {
__m128i abcd = h_abcd;
__m128i w0, w1, w2, w3, we0, we1;
SHA1_NI_16ROUNDS(0);
SHA1_NI_16ROUNDS(16);
SHA1_NI_16ROUNDS(32);
SHA1_NI_16ROUNDS(48);
SHA1_NI_16ROUNDS(64);
h_abcd = _mm_add_epi32(h_abcd, abcd);
h_e = _mm_sha1nexte_epu32(we0, h_e);
data += SHA1_BLOCK_SIZE;
} while (--num_blocks);
_mm_storeu_si128((__m128i *)h, _mm_shuffle_epi32(h_abcd, 0x1B));
h[4] = _mm_extract_epi32(h_e, 3);
}
#endif /* x86 SHA Extensions implementation */
/*----------------------------------------------------------------------------*
* ARMv8 Crypto Extensions implementation *
*----------------------------------------------------------------------------*/
/*
* This is SHA-1 using the ARMv8 Crypto Extensions.
*
* This does 4 rounds at a time, and it works very similarily to the x86 SHA
* Extensions implementation. The differences are fairly minor:
*
* - x86 has SHA1RNDS4 that takes an immediate that identifies the set of 20
* rounds, and it handles adding the round constants. ARM has SHA1C for
* rounds 0-19, SHA1P for rounds 20-39 and 60-79, and SHA1M for rounds 40-59.
* These don't add the round constants, so that must be done separately.
*
* - ARM needs only two instructions, instead of x86's three, to prepare each
* set of 4 message schedule words: SHA1SU0 which does w[i-16] ^ w[i-14] ^
* w[i-8], and SHA1SU1 which XOR's in w[i-3] and rotates left by 1.
*/
#if defined(__aarch64__) && \
(defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 5))
/*
* clang's arm_neon.h used to have a bug where it only defined the SHA-1
* intrinsics when CRYPTO (clang 12 and earlier) or SHA2 (clang 13 and 14) is
* enabled in the main target. This prevents them from being used in target
* attribute functions. Work around this by defining the macros ourselves.
*/
#if defined(__clang__) && __clang_major__ <= 15
# ifndef __ARM_FEATURE_CRYPTO
# define __ARM_FEATURE_CRYPTO 1
# define DEFINED_ARM_FEATURE_CRYPTO
# endif
# ifndef __ARM_FEATURE_SHA2
# define __ARM_FEATURE_SHA2 1
# define DEFINED_ARM_FEATURE_SHA2
# endif
#endif
#include
#ifdef DEFINED_ARM_FEATURE_CRYPTO
# undef __ARM_FEATURE_CRYPTO
#endif
#ifdef DEFINED_ARM_FEATURE_SHA2
# undef __ARM_FEATURE_SHA2
#endif
/* Expands to a vector containing 4 copies of the given round's constant */
#define SHA1_CE_K(i) \
((i) < 20 ? k0 : \
(i) < 40 ? k1 : \
(i) < 60 ? k2 : \
k3)
/* Expands to the appropriate instruction for the given round */
#define SHA1_CE_OP(i, abcd, e, w) \
((i) < 20 ? vsha1cq_u32((abcd), (e), (w)) : \
(i) < 40 ? vsha1pq_u32((abcd), (e), (w)) : \
(i) < 60 ? vsha1mq_u32((abcd), (e), (w)) : \
vsha1pq_u32((abcd), (e), (w)))
#define SHA1_CE_4ROUNDS(i, w0, w1, w2, w3, e0, e1) \
tmp = w0 + SHA1_CE_K(i); \
e1 = vsha1h_u32(vgetq_lane_u32(abcd, 0)); \
abcd = SHA1_CE_OP((i), abcd, e0, tmp); \
if ((i) >= 12 && (i) < 76) \
w1 = vsha1su1q_u32(w1, w0); \
if ((i) >= 8 && (i) < 72) \
w2 = vsha1su0q_u32(w2, w3, w0);
/*
* implicit: the new (w0, w1, w2, w3) is the old (w1, w2, w3, w0),
* and the new (e0, e1) is the old (e1, e0)
*/
#define SHA1_CE_16ROUNDS(i) \
SHA1_CE_4ROUNDS((i) + 0, w0, w1, w2, w3, e0, e1); \
SHA1_CE_4ROUNDS((i) + 4, w1, w2, w3, w0, e1, e0); \
SHA1_CE_4ROUNDS((i) + 8, w2, w3, w0, w1, e0, e1); \
SHA1_CE_4ROUNDS((i) + 12, w3, w0, w1, w2, e1, e0);
#define HAVE_SHA1_BLOCKS_ARM_CE
static void
#ifdef __clang__
/*
* clang has the SHA-1 instructions under "sha2". "crypto" used to work
* too, but only in clang 15 and earlier. So, use "sha2" here.
*/
__attribute__((target("sha2")))
#else
/* gcc wants "+crypto". "+sha2" doesn't work. */
__attribute__((target("+crypto")))
#endif
sha1_blocks_arm_ce(u32 h[5], const void *data, size_t num_blocks)
{
uint32x4_t h_abcd = vld1q_u32(h);
uint32x4_t k0 = vdupq_n_u32(SHA1_K(0));
uint32x4_t k1 = vdupq_n_u32(SHA1_K(20));
uint32x4_t k2 = vdupq_n_u32(SHA1_K(40));
uint32x4_t k3 = vdupq_n_u32(SHA1_K(60));
do {
uint32x4_t abcd = h_abcd;
u32 e0 = h[4], e1;
uint32x4_t tmp, w0, w1, w2, w3;
w0 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(data + 0)));
w1 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(data + 16)));
w2 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(data + 32)));
w3 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(data + 48)));
SHA1_CE_16ROUNDS(0);
SHA1_CE_16ROUNDS(16);
SHA1_CE_16ROUNDS(32);
SHA1_CE_16ROUNDS(48);
SHA1_CE_16ROUNDS(64);
h_abcd += abcd;
h[4] += e0;
data += SHA1_BLOCK_SIZE;
} while (--num_blocks);
vst1q_u32(h, h_abcd);
}
#endif /* ARMv8 Crypto Extensions implementation */
/*----------------------------------------------------------------------------*
* Everything else *
*----------------------------------------------------------------------------*/
static void
sha1_blocks(u32 h[5], const void *data, size_t num_blocks)
{
#ifdef HAVE_SHA1_BLOCKS_X86_SHA
if ((cpu_features & (X86_CPU_FEATURE_SHA | X86_CPU_FEATURE_SSE4_1)) ==
(X86_CPU_FEATURE_SHA | X86_CPU_FEATURE_SSE4_1))
return sha1_blocks_x86_sha(h, data, num_blocks);
#endif
#ifdef HAVE_SHA1_BLOCKS_X86_AVX_BMI2
if ((cpu_features & (X86_CPU_FEATURE_AVX | X86_CPU_FEATURE_BMI2)) ==
(X86_CPU_FEATURE_AVX | X86_CPU_FEATURE_BMI2))
return sha1_blocks_x86_avx_bmi2(h, data, num_blocks);
#endif
#ifdef HAVE_SHA1_BLOCKS_X86_SSSE3
if (cpu_features & X86_CPU_FEATURE_SSSE3)
return sha1_blocks_x86_ssse3(h, data, num_blocks);
#endif
#ifdef HAVE_SHA1_BLOCKS_ARM_CE
if (cpu_features & ARM_CPU_FEATURE_SHA1)
return sha1_blocks_arm_ce(h, data, num_blocks);
#endif
return sha1_blocks_generic(h, data, num_blocks);
}
/*
* Initialize the given SHA-1 context.
*
* After sha1_init(), call sha1_update() zero or more times to provide the data
* to be hashed. Then call sha1_final() to get the resulting message digest.
*/
void
sha1_init(struct sha1_ctx *ctx)
{
ctx->bytecount = 0;
ctx->h[0] = 0x67452301;
ctx->h[1] = 0xEFCDAB89;
ctx->h[2] = 0x98BADCFE;
ctx->h[3] = 0x10325476;
ctx->h[4] = 0xC3D2E1F0;
}
/* Update the SHA-1 context with @len bytes of data. */
void
sha1_update(struct sha1_ctx *ctx, const void *data, size_t len)
{
unsigned buffered = ctx->bytecount % SHA1_BLOCK_SIZE;
size_t blocks;
ctx->bytecount += len;
if (buffered) {
unsigned remaining = SHA1_BLOCK_SIZE - buffered;
if (len < remaining) {
memcpy(&ctx->buffer[buffered], data, len);
return;
}
memcpy(&ctx->buffer[buffered], data, remaining);
sha1_blocks(ctx->h, ctx->buffer, 1);
data += remaining;
len -= remaining;
}
blocks = len / SHA1_BLOCK_SIZE;
if (blocks) {
sha1_blocks(ctx->h, data, blocks);
data += blocks * SHA1_BLOCK_SIZE;
len -= blocks * SHA1_BLOCK_SIZE;
}
if (len)
memcpy(ctx->buffer, data, len);
}
/* Finalize the SHA-1 operation and return the resulting message digest. */
void
sha1_final(struct sha1_ctx *ctx, u8 hash[SHA1_HASH_SIZE])
{
unsigned buffered = ctx->bytecount % SHA1_BLOCK_SIZE;
const be64 bitcount = cpu_to_be64(ctx->bytecount * 8);
ctx->buffer[buffered++] = 0x80;
if (buffered > SHA1_BLOCK_SIZE - 8) {
memset(&ctx->buffer[buffered], 0, SHA1_BLOCK_SIZE - buffered);
sha1_blocks(ctx->h, ctx->buffer, 1);
buffered = 0;
}
memset(&ctx->buffer[buffered], 0, SHA1_BLOCK_SIZE - 8 - buffered);
memcpy(&ctx->buffer[SHA1_BLOCK_SIZE - 8], &bitcount, 8);
sha1_blocks(ctx->h, ctx->buffer, 1);
put_unaligned_be32(ctx->h[0], &hash[0]);
put_unaligned_be32(ctx->h[1], &hash[4]);
put_unaligned_be32(ctx->h[2], &hash[8]);
put_unaligned_be32(ctx->h[3], &hash[12]);
put_unaligned_be32(ctx->h[4], &hash[16]);
}
/* Calculate the SHA-1 message digest of the given data. */
void
sha1(const void *data, size_t len, u8 hash[SHA1_HASH_SIZE])
{
struct sha1_ctx ctx;
sha1_init(&ctx);
sha1_update(&ctx, data, len);
sha1_final(&ctx, hash);
}
/* "Null" SHA-1 message digest containing all 0's */
const u8 zero_hash[SHA1_HASH_SIZE];
/* Build a hexadecimal string representation of a SHA-1 message digest. */
void
sprint_hash(const u8 hash[SHA1_HASH_SIZE], tchar strbuf[SHA1_HASH_STRING_LEN])
{
int i;
u8 high, low;
for (i = 0; i < SHA1_HASH_SIZE; i++) {
high = hash[i] >> 4;
low = hash[i] & 0xF;
strbuf[i * 2 + 0] = (high < 10 ? high + '0' : high - 10 + 'a');
strbuf[i * 2 + 1] = (low < 10 ? low + '0' : low - 10 + 'a');
}
strbuf[i * 2] = 0;
}
wimlib-1.14.5/src/blob_table.c 0000644 0001750 0001750 00000116447 15137020663 013417 0 ustar 00e e /*
* blob_table.c
*
* A blob table maps SHA-1 message digests to "blobs", which are nonempty
* sequences of binary data. Within a WIM file, blobs are single-instanced.
*
* This file also contains code to read and write the corresponding on-disk
* representation of this table in the WIM file format.
*/
/*
* Copyright (C) 2012-2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include /* for unlink() */
#include "wimlib/assert.h"
#include "wimlib/bitops.h"
#include "wimlib/blob_table.h"
#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/metadata.h"
#include "wimlib/ntfs_3g.h"
#include "wimlib/resource.h"
#include "wimlib/unaligned.h"
#include "wimlib/util.h"
#include "wimlib/win32.h"
#include "wimlib/write.h"
/* A hash table mapping SHA-1 message digests to blob descriptors */
struct blob_table {
struct hlist_head *array;
size_t num_blobs;
size_t mask; /* capacity - 1; capacity is a power of 2 */
};
struct blob_table *
new_blob_table(size_t capacity)
{
struct blob_table *table;
struct hlist_head *array;
capacity = roundup_pow_of_2(capacity);
table = MALLOC(sizeof(struct blob_table));
if (table == NULL)
goto oom;
array = CALLOC(capacity, sizeof(array[0]));
if (array == NULL) {
FREE(table);
goto oom;
}
table->num_blobs = 0;
table->mask = capacity - 1;
table->array = array;
return table;
oom:
ERROR("Failed to allocate memory for blob table "
"with capacity %zu", capacity);
return NULL;
}
static int
do_free_blob_descriptor(struct blob_descriptor *blob, void *_ignore)
{
free_blob_descriptor(blob);
return 0;
}
void
free_blob_table(struct blob_table *table)
{
if (table) {
for_blob_in_table(table, do_free_blob_descriptor, NULL);
FREE(table->array);
FREE(table);
}
}
struct blob_descriptor *
new_blob_descriptor(void)
{
STATIC_ASSERT(BLOB_NONEXISTENT == 0);
return CALLOC(1, sizeof(struct blob_descriptor));
}
struct blob_descriptor *
clone_blob_descriptor(const struct blob_descriptor *old)
{
struct blob_descriptor *new;
new = memdup(old, sizeof(struct blob_descriptor));
if (new == NULL)
return NULL;
switch (new->blob_location) {
case BLOB_IN_WIM:
list_add(&new->rdesc_node, &new->rdesc->blob_list);
break;
case BLOB_IN_FILE_ON_DISK:
#ifdef WITH_FUSE
case BLOB_IN_STAGING_FILE:
STATIC_ASSERT((void*)&old->file_on_disk ==
(void*)&old->staging_file_name);
#endif
new->file_on_disk = TSTRDUP(old->file_on_disk);
if (new->file_on_disk == NULL)
goto out_free;
break;
#ifdef _WIN32
case BLOB_IN_WINDOWS_FILE:
new->windows_file = clone_windows_file(old->windows_file);
break;
#endif
case BLOB_IN_ATTACHED_BUFFER:
new->attached_buffer = memdup(old->attached_buffer, old->size);
if (new->attached_buffer == NULL)
goto out_free;
break;
#ifdef WITH_NTFS_3G
case BLOB_IN_NTFS_VOLUME:
new->ntfs_loc = clone_ntfs_location(old->ntfs_loc);
if (!new->ntfs_loc)
goto out_free;
break;
#endif
}
return new;
out_free:
free_blob_descriptor(new);
return NULL;
}
/* Release a blob descriptor from its location, if any, and set its new location
* to BLOB_NONEXISTENT. */
void
blob_release_location(struct blob_descriptor *blob)
{
switch (blob->blob_location) {
case BLOB_IN_WIM: {
struct wim_resource_descriptor *rdesc = blob->rdesc;
list_del(&blob->rdesc_node);
if (list_empty(&rdesc->blob_list)) {
wim_decrement_refcnt(rdesc->wim);
FREE(rdesc);
}
break;
}
case BLOB_IN_FILE_ON_DISK:
#ifdef WITH_FUSE
case BLOB_IN_STAGING_FILE:
STATIC_ASSERT((void*)&blob->file_on_disk ==
(void*)&blob->staging_file_name);
#endif
case BLOB_IN_ATTACHED_BUFFER:
STATIC_ASSERT((void*)&blob->file_on_disk ==
(void*)&blob->attached_buffer);
FREE(blob->file_on_disk);
break;
#ifdef _WIN32
case BLOB_IN_WINDOWS_FILE:
free_windows_file(blob->windows_file);
break;
#endif
#ifdef WITH_NTFS_3G
case BLOB_IN_NTFS_VOLUME:
free_ntfs_location(blob->ntfs_loc);
break;
#endif
}
blob->blob_location = BLOB_NONEXISTENT;
}
void
free_blob_descriptor(struct blob_descriptor *blob)
{
if (blob) {
blob_release_location(blob);
FREE(blob);
}
}
/* Should this blob be retained even if it has no references? */
static bool
should_retain_blob(const struct blob_descriptor *blob)
{
return blob->blob_location == BLOB_IN_WIM;
}
static void
finalize_blob(struct blob_descriptor *blob)
{
if (!should_retain_blob(blob))
free_blob_descriptor(blob);
}
/*
* Decrements the reference count of the specified blob, which must be either
* (a) unhashed, or (b) inserted in the specified blob table.
*
* If the blob's reference count reaches 0, we may unlink it from @table and
* free it. However, we retain blobs with 0 reference count that originated
* from WIM files (BLOB_IN_WIM). We do this for two reasons:
*
* 1. This prevents information about valid blobs in a WIM file --- blobs which
* will continue to be present after appending to the WIM file --- from being
* lost merely because we dropped all references to them.
*
* 2. Blob reference counts we read from WIM files can't be trusted. It's
* possible that a WIM has reference counts that are too low; WIMGAPI
* sometimes creates WIMs where this is the case. It's also possible that
* blobs have been referenced from an external WIM; those blobs can
* potentially have any reference count at all, either lower or higher than
* would be expected for this WIM ("this WIM" meaning the owner of @table) if
* it were a standalone WIM.
*
* So we can't take the reference counts too seriously. But at least, we do
* recalculate by default when writing a new WIM file.
*/
void
blob_decrement_refcnt(struct blob_descriptor *blob, struct blob_table *table)
{
blob_subtract_refcnt(blob, table, 1);
}
void
blob_subtract_refcnt(struct blob_descriptor *blob, struct blob_table *table,
u32 count)
{
if (unlikely(blob->refcnt < count)) {
blob->refcnt = 0; /* See comment above */
return;
}
blob->refcnt -= count;
if (blob->refcnt != 0)
return;
if (blob->unhashed) {
list_del(&blob->unhashed_list);
#ifdef WITH_FUSE
/* If the blob has been extracted to a staging file for a FUSE
* mount, unlink the staging file. (Note that there still may
* be open file descriptors to it.) */
if (blob->blob_location == BLOB_IN_STAGING_FILE)
unlinkat(blob->staging_dir_fd,
blob->staging_file_name, 0);
#endif
} else {
if (!should_retain_blob(blob))
blob_table_unlink(table, blob);
}
/* If FUSE mounts are enabled, then don't actually free the blob
* descriptor until the last file descriptor to it has been closed. */
#ifdef WITH_FUSE
if (blob->num_opened_fds == 0)
#endif
finalize_blob(blob);
}
#ifdef WITH_FUSE
void
blob_decrement_num_opened_fds(struct blob_descriptor *blob)
{
wimlib_assert(blob->num_opened_fds != 0);
if (--blob->num_opened_fds == 0 && blob->refcnt == 0)
finalize_blob(blob);
}
#endif
static void
blob_table_insert_raw(struct blob_table *table, struct blob_descriptor *blob)
{
size_t i = blob->hash_short & table->mask;
hlist_add_head(&blob->hash_list, &table->array[i]);
}
static void
enlarge_blob_table(struct blob_table *table)
{
size_t old_capacity, new_capacity;
struct hlist_head *old_array, *new_array;
struct blob_descriptor *blob;
struct hlist_node *tmp;
size_t i;
old_capacity = table->mask + 1;
new_capacity = old_capacity * 2;
new_array = CALLOC(new_capacity, sizeof(struct hlist_head));
if (new_array == NULL)
return;
old_array = table->array;
table->array = new_array;
table->mask = new_capacity - 1;
for (i = 0; i < old_capacity; i++)
hlist_for_each_entry_safe(blob, tmp, &old_array[i], hash_list)
blob_table_insert_raw(table, blob);
FREE(old_array);
}
/* Insert a blob descriptor into the blob table. */
void
blob_table_insert(struct blob_table *table, struct blob_descriptor *blob)
{
blob_table_insert_raw(table, blob);
if (table->num_blobs++ > table->mask)
enlarge_blob_table(table);
}
/* Unlinks a blob descriptor from the blob table; does not free it. */
void
blob_table_unlink(struct blob_table *table, struct blob_descriptor *blob)
{
wimlib_assert(!blob->unhashed);
wimlib_assert(table->num_blobs != 0);
hlist_del(&blob->hash_list);
table->num_blobs--;
}
/* Given a SHA-1 message digest, return the corresponding blob descriptor from
* the specified blob table, or NULL if there is none. */
struct blob_descriptor *
lookup_blob(const struct blob_table *table, const u8 *hash)
{
size_t i;
struct blob_descriptor *blob;
i = load_size_t_unaligned(hash) & table->mask;
hlist_for_each_entry(blob, &table->array[i], hash_list)
if (hashes_equal(hash, blob->hash))
return blob;
return NULL;
}
/* Call a function on all blob descriptors in the specified blob table. Stop
* early and return nonzero if any call to the function returns nonzero. */
int
for_blob_in_table(struct blob_table *table,
int (*visitor)(struct blob_descriptor *, void *), void *arg)
{
struct blob_descriptor *blob;
struct hlist_node *tmp;
int ret;
for (size_t i = 0; i <= table->mask; i++) {
hlist_for_each_entry_safe(blob, tmp, &table->array[i],
hash_list)
{
ret = visitor(blob, arg);
if (ret)
return ret;
}
}
return 0;
}
/*
* This is a qsort() callback that sorts blobs into an order optimized for
* reading. Sorting is done primarily by blob location, then secondarily by a
* location-dependent order. For example, blobs in WIM resources are sorted
* such that the underlying WIM files will be read sequentially. This is
* especially important for WIM files containing solid resources.
*/
int
cmp_blobs_by_sequential_order(const void *p1, const void *p2)
{
const struct blob_descriptor *blob1, *blob2;
int v;
WIMStruct *wim1, *wim2;
blob1 = *(const struct blob_descriptor**)p1;
blob2 = *(const struct blob_descriptor**)p2;
v = (int)blob1->blob_location - (int)blob2->blob_location;
/* Different locations? Note: "unsafe compaction mode" requires that
* blobs in WIMs sort before all others. For the logic here to ensure
* this, BLOB_IN_WIM must have the lowest value among all defined
* blob_locations. Statically verify that the enum values haven't
* changed. */
STATIC_ASSERT(BLOB_NONEXISTENT == 0 && BLOB_IN_WIM == 1);
if (v)
return v;
switch (blob1->blob_location) {
case BLOB_IN_WIM:
wim1 = blob1->rdesc->wim;
wim2 = blob2->rdesc->wim;
/* Different WIM files? */
if (wim1 != wim2) {
/* Resources from the WIM file currently being compacted
* (if any) must always sort first. */
v = (int)wim2->being_compacted - (int)wim1->being_compacted;
if (v)
return v;
/* Different split WIMs? */
v = cmp_guids(wim1->hdr.guid, wim2->hdr.guid);
if (v)
return v;
/* Different part numbers in the same split WIM? */
v = (int)wim1->hdr.part_number - (int)wim2->hdr.part_number;
if (v)
return v;
/* Probably two WIMStructs for the same on-disk file.
* Just sort by pointer. */
return wim1 < wim2 ? -1 : 1;
}
/* Same WIM file */
/* Sort by increasing resource offset */
if (blob1->rdesc->offset_in_wim != blob2->rdesc->offset_in_wim)
return cmp_u64(blob1->rdesc->offset_in_wim,
blob2->rdesc->offset_in_wim);
/* The blobs are in the same solid resource. Sort by increasing
* offset in the resource. */
return cmp_u64(blob1->offset_in_res, blob2->offset_in_res);
case BLOB_IN_FILE_ON_DISK:
#ifdef WITH_FUSE
case BLOB_IN_STAGING_FILE:
#endif
/* Compare files by path: just a heuristic that will place files
* in the same directory next to each other. */
return tstrcmp(blob1->file_on_disk, blob2->file_on_disk);
#ifdef _WIN32
case BLOB_IN_WINDOWS_FILE:
return cmp_windows_files(blob1->windows_file, blob2->windows_file);
#endif
#ifdef WITH_NTFS_3G
case BLOB_IN_NTFS_VOLUME:
return cmp_ntfs_locations(blob1->ntfs_loc, blob2->ntfs_loc);
#endif
default:
/* No additional sorting order defined for this resource
* location (e.g. BLOB_IN_ATTACHED_BUFFER); simply compare
* everything equal to each other. */
return 0;
}
}
int
sort_blob_list(struct list_head *blob_list, size_t list_head_offset,
int (*compar)(const void *, const void*))
{
struct list_head *cur;
struct blob_descriptor **array;
size_t i;
size_t array_size;
size_t num_blobs = 0;
list_for_each(cur, blob_list)
num_blobs++;
if (num_blobs <= 1)
return 0;
array_size = num_blobs * sizeof(array[0]);
array = MALLOC(array_size);
if (array == NULL)
return WIMLIB_ERR_NOMEM;
cur = blob_list->next;
for (i = 0; i < num_blobs; i++) {
array[i] = (struct blob_descriptor*)((u8*)cur - list_head_offset);
cur = cur->next;
}
qsort(array, num_blobs, sizeof(array[0]), compar);
INIT_LIST_HEAD(blob_list);
for (i = 0; i < num_blobs; i++) {
list_add_tail((struct list_head*)
((u8*)array[i] + list_head_offset), blob_list);
}
FREE(array);
return 0;
}
/* Sort the specified list of blobs in an order optimized for sequential
* reading. */
int
sort_blob_list_by_sequential_order(struct list_head *blob_list,
size_t list_head_offset)
{
return sort_blob_list(blob_list, list_head_offset,
cmp_blobs_by_sequential_order);
}
static int
add_blob_to_array(struct blob_descriptor *blob, void *_pp)
{
struct blob_descriptor ***pp = _pp;
*(*pp)++ = blob;
return 0;
}
/* Iterate through the blob descriptors in the specified blob table in an order
* optimized for sequential reading. */
int
for_blob_in_table_sorted_by_sequential_order(struct blob_table *table,
int (*visitor)(struct blob_descriptor *, void *),
void *arg)
{
struct blob_descriptor **blob_array, **p;
size_t num_blobs = table->num_blobs;
int ret;
blob_array = MALLOC(num_blobs * sizeof(blob_array[0]));
if (!blob_array)
return WIMLIB_ERR_NOMEM;
p = blob_array;
for_blob_in_table(table, add_blob_to_array, &p);
wimlib_assert(p == blob_array + num_blobs);
qsort(blob_array, num_blobs, sizeof(blob_array[0]),
cmp_blobs_by_sequential_order);
ret = 0;
for (size_t i = 0; i < num_blobs; i++) {
ret = visitor(blob_array[i], arg);
if (ret)
break;
}
FREE(blob_array);
return ret;
}
/* On-disk format of a blob descriptor in a WIM file.
*
* Note: if the WIM file contains solid resource(s), then this structure is
* sometimes overloaded to describe a "resource" rather than a "blob". See the
* code for details. */
struct blob_descriptor_disk {
/* Size, offset, and flags of the blob. */
struct wim_reshdr_disk reshdr;
/* Which part of the split WIM this blob is in; indexed from 1. */
le16 part_number;
/* Reference count of this blob over all WIM images. (But see comment
* above blob_decrement_refcnt().) */
le32 refcnt;
/* SHA-1 message digest of the uncompressed data of this blob, or all
* zeroes if this blob is of zero length. */
u8 hash[SHA1_HASH_SIZE];
} __attribute__((packed));
/* Given a nonempty run of consecutive blob descriptors with the SOLID flag set,
* count how many specify resources (as opposed to blobs within those
* resources).
*
* Returns the resulting count. */
static size_t
count_solid_resources(const struct blob_descriptor_disk *entries, size_t max)
{
size_t count = 0;
do {
struct wim_reshdr reshdr;
get_wim_reshdr(&(entries++)->reshdr, &reshdr);
if (!(reshdr.flags & WIM_RESHDR_FLAG_SOLID)) {
/* Run was terminated by a stand-alone blob entry. */
break;
}
if (reshdr.uncompressed_size == SOLID_RESOURCE_MAGIC_NUMBER) {
/* This is a resource entry. */
count++;
}
} while (--max);
return count;
}
/*
* Given a run of consecutive blob descriptors with the SOLID flag set and
* having @num_rdescs resource entries, load resource information from them into
* the resource descriptors in the @rdescs array.
*
* Returns 0 on success, or a nonzero error code on failure.
*/
static int
do_load_solid_info(WIMStruct *wim, struct wim_resource_descriptor **rdescs,
size_t num_rdescs,
const struct blob_descriptor_disk *entries)
{
for (size_t i = 0; i < num_rdescs; i++) {
struct wim_reshdr reshdr;
struct alt_chunk_table_header_disk hdr;
struct wim_resource_descriptor *rdesc;
int ret;
/* Advance to next resource entry. */
do {
get_wim_reshdr(&(entries++)->reshdr, &reshdr);
} while (reshdr.uncompressed_size != SOLID_RESOURCE_MAGIC_NUMBER);
rdesc = rdescs[i];
wim_reshdr_to_desc(&reshdr, wim, rdesc);
/* For solid resources, the uncompressed size, compression type,
* and chunk size are stored in the resource itself, not in the
* blob table. */
ret = full_pread(&wim->in_fd, &hdr,
sizeof(hdr), reshdr.offset_in_wim);
if (ret) {
ERROR("Failed to read header of solid resource "
"(offset_in_wim=%"PRIu64")",
reshdr.offset_in_wim);
return ret;
}
rdesc->uncompressed_size = le64_to_cpu(hdr.res_usize);
/* Compression format numbers must be the same as in
* WIMGAPI to be compatible here. */
STATIC_ASSERT(WIMLIB_COMPRESSION_TYPE_NONE == 0);
STATIC_ASSERT(WIMLIB_COMPRESSION_TYPE_XPRESS == 1);
STATIC_ASSERT(WIMLIB_COMPRESSION_TYPE_LZX == 2);
STATIC_ASSERT(WIMLIB_COMPRESSION_TYPE_LZMS == 3);
rdesc->compression_type = le32_to_cpu(hdr.compression_format);
rdesc->chunk_size = le32_to_cpu(hdr.chunk_size);
}
return 0;
}
/*
* Given a nonempty run of consecutive blob descriptors with the SOLID flag set,
* allocate a 'struct wim_resource_descriptor' for each resource within that
* run.
*
* Returns 0 on success, or a nonzero error code on failure.
* Returns the pointers and count in *rdescs_ret and *num_rdescs_ret.
*/
static int
load_solid_info(WIMStruct *wim,
const struct blob_descriptor_disk *entries,
size_t num_remaining_entries,
struct wim_resource_descriptor ***rdescs_ret,
size_t *num_rdescs_ret)
{
size_t num_rdescs;
struct wim_resource_descriptor **rdescs;
size_t i;
int ret;
num_rdescs = count_solid_resources(entries, num_remaining_entries);
rdescs = CALLOC(num_rdescs, sizeof(rdescs[0]));
if (!rdescs)
return WIMLIB_ERR_NOMEM;
for (i = 0; i < num_rdescs; i++) {
rdescs[i] = MALLOC(sizeof(struct wim_resource_descriptor));
if (!rdescs[i]) {
ret = WIMLIB_ERR_NOMEM;
goto out_free_rdescs;
}
}
ret = do_load_solid_info(wim, rdescs, num_rdescs, entries);
if (ret)
goto out_free_rdescs;
wim->refcnt += num_rdescs;
*rdescs_ret = rdescs;
*num_rdescs_ret = num_rdescs;
return 0;
out_free_rdescs:
for (i = 0; i < num_rdescs; i++)
FREE(rdescs[i]);
FREE(rdescs);
return ret;
}
/* Given a 'struct blob_descriptor' allocated for an on-disk blob descriptor
* with the SOLID flag set, try to assign it to resource in the current solid
* run. */
static int
assign_blob_to_solid_resource(const struct wim_reshdr *reshdr,
struct blob_descriptor *blob,
struct wim_resource_descriptor **rdescs,
size_t num_rdescs)
{
u64 offset = reshdr->offset_in_wim;
/* XXX: This linear search will be slow in the degenerate case where the
* number of solid resources in the run is huge. */
blob->size = reshdr->size_in_wim;
for (size_t i = 0; i < num_rdescs; i++) {
if (offset + blob->size <= rdescs[i]->uncompressed_size) {
blob_set_is_located_in_wim_resource(blob, rdescs[i], offset);
return 0;
}
offset -= rdescs[i]->uncompressed_size;
}
ERROR("blob could not be assigned to a solid resource");
return WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
}
static void
free_solid_rdescs(struct wim_resource_descriptor **rdescs, size_t num_rdescs)
{
if (rdescs) {
for (size_t i = 0; i < num_rdescs; i++) {
if (list_empty(&rdescs[i]->blob_list)) {
rdescs[i]->wim->refcnt--;
FREE(rdescs[i]);
}
}
FREE(rdescs);
}
}
static int
cmp_blobs_by_offset_in_res(const void *p1, const void *p2)
{
const struct blob_descriptor *blob1, *blob2;
blob1 = *(const struct blob_descriptor**)p1;
blob2 = *(const struct blob_descriptor**)p2;
return cmp_u64(blob1->offset_in_res, blob2->offset_in_res);
}
/* Validate the size and location of a WIM resource. */
static int
validate_resource(struct wim_resource_descriptor *rdesc)
{
struct blob_descriptor *blob;
bool out_of_order;
u64 expected_next_offset;
int ret;
/* Verify that the resource itself has a valid offset and size. */
if (rdesc->offset_in_wim + rdesc->size_in_wim < rdesc->size_in_wim)
goto invalid_due_to_overflow;
/* Verify that each blob in the resource has a valid offset and size.
*/
expected_next_offset = 0;
out_of_order = false;
list_for_each_entry(blob, &rdesc->blob_list, rdesc_node) {
if (blob->offset_in_res + blob->size < blob->size ||
blob->offset_in_res + blob->size > rdesc->uncompressed_size)
goto invalid_due_to_overflow;
if (blob->offset_in_res >= expected_next_offset)
expected_next_offset = blob->offset_in_res + blob->size;
else
out_of_order = true;
}
/* If the blobs were not located at strictly increasing positions (not
* allowing for overlap), sort them. Then make sure that none overlap.
*/
if (out_of_order) {
ret = sort_blob_list(&rdesc->blob_list,
offsetof(struct blob_descriptor,
rdesc_node),
cmp_blobs_by_offset_in_res);
if (ret)
return ret;
expected_next_offset = 0;
list_for_each_entry(blob, &rdesc->blob_list, rdesc_node) {
if (blob->offset_in_res >= expected_next_offset)
expected_next_offset = blob->offset_in_res + blob->size;
else
goto invalid_due_to_overlap;
}
}
return 0;
invalid_due_to_overflow:
ERROR("Invalid blob table (offset overflow)");
return WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
invalid_due_to_overlap:
ERROR("Invalid blob table (blobs in solid resource overlap)");
return WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
}
static int
finish_solid_rdescs(struct wim_resource_descriptor **rdescs, size_t num_rdescs)
{
int ret = 0;
for (size_t i = 0; i < num_rdescs; i++) {
ret = validate_resource(rdescs[i]);
if (ret)
break;
}
free_solid_rdescs(rdescs, num_rdescs);
return ret;
}
/*
* read_blob_table() -
*
* Read the blob table from a WIM file. Usually, each entry in this table
* describes a "blob", or equivalently a "resource", that the WIM file contains,
* along with its location and SHA-1 message digest. Descriptors for
* non-metadata blobs will be saved in the in-memory blob table
* (wim->blob_table), whereas descriptors for metadata blobs will be saved in a
* special location per-image (the wim->image_metadata array).
*
* However, in WIM_VERSION_SOLID (3584) WIMs, a resource may contain multiple
* blobs that are compressed together. Such a resource is called a "solid
* resource". Solid resources are still described in the on-disk "blob table",
* although the format is not the most logical. A consecutive sequence of
* entries that all have flag WIM_RESHDR_FLAG_SOLID (0x10) set is a "solid run".
* A solid run describes a set of solid resources, each of which contains a set
* of blobs. In a solid run, a 'struct wim_reshdr_disk' with 'uncompressed_size
* = SOLID_RESOURCE_MAGIC_NUMBER (0x100000000)' specifies a solid resource,
* whereas any other 'struct wim_reshdr_disk' specifies a blob within a solid
* resource. There are some oddities in how we need to determine which solid
* resource a blob is actually in; see the code for details.
*
* Possible return values:
* WIMLIB_ERR_SUCCESS (0)
* WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY
* WIMLIB_ERR_NOMEM
*
* Or an error code caused by failure to read the blob table from the WIM
* file.
*/
int
read_blob_table(WIMStruct *wim)
{
int ret;
size_t num_entries;
void *buf = NULL;
struct blob_table *table = NULL;
struct blob_descriptor *cur_blob = NULL;
size_t num_duplicate_blobs = 0;
size_t num_empty_blobs = 0;
size_t num_wrong_part_blobs = 0;
u32 image_index = 0;
struct wim_resource_descriptor **cur_solid_rdescs = NULL;
size_t cur_num_solid_rdescs = 0;
/* Calculate the number of entries in the blob table. */
num_entries = wim->hdr.blob_table_reshdr.uncompressed_size /
sizeof(struct blob_descriptor_disk);
/* Read the blob table into a buffer. */
ret = wim_reshdr_to_data(&wim->hdr.blob_table_reshdr, wim, &buf);
if (ret)
goto out;
/* Allocate a hash table to map SHA-1 message digests into blob
* descriptors. This is the in-memory "blob table". */
table = new_blob_table(num_entries);
if (!table)
goto oom;
/* Allocate and initialize blob descriptors from the raw blob table
* buffer. */
for (size_t i = 0; i < num_entries; i++) {
const struct blob_descriptor_disk *disk_entry =
&((const struct blob_descriptor_disk*)buf)[i];
struct wim_reshdr reshdr;
u16 part_number;
/* Get the resource header */
get_wim_reshdr(&disk_entry->reshdr, &reshdr);
/* Ignore SOLID flag if it isn't supposed to be used in this WIM
* version. */
if (wim->hdr.wim_version == WIM_VERSION_DEFAULT)
reshdr.flags &= ~WIM_RESHDR_FLAG_SOLID;
/* Allocate a new 'struct blob_descriptor'. */
cur_blob = new_blob_descriptor();
if (!cur_blob)
goto oom;
/* Get the part number, reference count, and hash. */
part_number = le16_to_cpu(disk_entry->part_number);
cur_blob->refcnt = le32_to_cpu(disk_entry->refcnt);
copy_hash(cur_blob->hash, disk_entry->hash);
if (reshdr.flags & WIM_RESHDR_FLAG_SOLID) {
/* SOLID entry */
if (!cur_solid_rdescs) {
/* Starting new run */
ret = load_solid_info(wim, disk_entry,
num_entries - i,
&cur_solid_rdescs,
&cur_num_solid_rdescs);
if (ret)
goto out;
}
if (reshdr.uncompressed_size == SOLID_RESOURCE_MAGIC_NUMBER) {
/* Resource entry, not blob entry */
goto free_cur_blob_and_continue;
}
/* Blob entry */
ret = assign_blob_to_solid_resource(&reshdr,
cur_blob,
cur_solid_rdescs,
cur_num_solid_rdescs);
if (ret)
goto out;
} else {
/* Normal blob/resource entry; SOLID not set. */
struct wim_resource_descriptor *rdesc;
if (unlikely(cur_solid_rdescs)) {
/* This entry terminated a solid run. */
ret = finish_solid_rdescs(cur_solid_rdescs,
cur_num_solid_rdescs);
cur_solid_rdescs = NULL;
if (ret)
goto out;
}
if (unlikely(!(reshdr.flags & WIM_RESHDR_FLAG_COMPRESSED) &&
(reshdr.size_in_wim != reshdr.uncompressed_size)))
{
ERROR("Uncompressed resource has "
"size_in_wim != uncompressed_size");
ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
goto out;
}
/* Set up a resource descriptor for this blob. */
rdesc = MALLOC(sizeof(struct wim_resource_descriptor));
if (!rdesc)
goto oom;
wim_reshdr_to_desc_and_blob(&reshdr, wim, rdesc, cur_blob);
wim->refcnt++;
}
/* cur_blob is now a blob bound to a resource. */
/* Ignore entries with all zeroes in the hash field. */
if (unlikely(is_zero_hash(cur_blob->hash)))
goto free_cur_blob_and_continue;
/* Verify that the blob has nonzero size. */
if (unlikely(cur_blob->size == 0)) {
num_empty_blobs++;
goto free_cur_blob_and_continue;
}
/* Verify that the part number matches that of the underlying
* WIM file. */
if (unlikely(part_number != wim->hdr.part_number)) {
num_wrong_part_blobs++;
goto free_cur_blob_and_continue;
}
if (reshdr.flags & WIM_RESHDR_FLAG_METADATA) {
/* Blob table entry for a metadata resource. */
/* Metadata entries with no references must be ignored.
* See, for example, the WinPE WIMs from the WAIK v2.1.
*/
if (cur_blob->refcnt == 0)
goto free_cur_blob_and_continue;
if (cur_blob->refcnt != 1) {
/* We don't currently support this case due to
* the complications of multiple images sharing
* the same metadata resource or a metadata
* resource also being referenced by files. */
ERROR("Found metadata resource with refcnt != 1");
ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
goto out;
}
if (reshdr.flags & WIM_RESHDR_FLAG_SOLID) {
ERROR("Image metadata in solid resources "
"is unsupported.");
ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
goto out;
}
if (wim->hdr.part_number != 1) {
WARNING("Ignoring metadata resource found in a "
"non-first part of the split WIM");
goto free_cur_blob_and_continue;
}
/* The number of entries in the blob table with
* WIM_RESHDR_FLAG_METADATA set should be the same as
* the image_count field in the WIM header. */
if (image_index == wim->hdr.image_count) {
WARNING("Found more metadata resources than images");
goto free_cur_blob_and_continue;
}
/* Notice very carefully: We are assigning the metadata
* resources to images in the same order in which their
* blob table entries occur on disk. (This is also the
* behavior of Microsoft's software.) In particular,
* this overrides the actual locations of the metadata
* resources themselves in the WIM file as well as any
* information written in the XML data. */
wim->image_metadata[image_index] = new_unloaded_image_metadata(cur_blob);
if (!wim->image_metadata[image_index])
goto oom;
image_index++;
} else {
/* Blob table entry for a non-metadata blob. */
/* Ignore this blob if it's a duplicate. */
if (lookup_blob(table, cur_blob->hash)) {
num_duplicate_blobs++;
goto free_cur_blob_and_continue;
}
/* Insert the blob into the in-memory blob table, keyed
* by its SHA-1 message digest. */
blob_table_insert(table, cur_blob);
}
continue;
free_cur_blob_and_continue:
if (cur_solid_rdescs &&
cur_blob->blob_location == BLOB_IN_WIM)
blob_unset_is_located_in_wim_resource(cur_blob);
free_blob_descriptor(cur_blob);
}
cur_blob = NULL;
if (cur_solid_rdescs) {
/* End of blob table terminated a solid run. */
ret = finish_solid_rdescs(cur_solid_rdescs, cur_num_solid_rdescs);
cur_solid_rdescs = NULL;
if (ret)
goto out;
}
if (wim->hdr.part_number == 1 && image_index != wim->hdr.image_count) {
WARNING("Could not find metadata resources for all images");
wim->hdr.image_count = image_index;
}
if (num_duplicate_blobs > 0)
WARNING("Ignoring %zu duplicate blobs", num_duplicate_blobs);
if (num_empty_blobs > 0)
WARNING("Ignoring %zu empty blobs", num_empty_blobs);
if (num_wrong_part_blobs > 0) {
WARNING("Ignoring %zu blobs with wrong part number",
num_wrong_part_blobs);
}
wim->blob_table = table;
ret = 0;
goto out_free_buf;
oom:
ERROR("Not enough memory to read blob table!");
ret = WIMLIB_ERR_NOMEM;
out:
free_solid_rdescs(cur_solid_rdescs, cur_num_solid_rdescs);
free_blob_descriptor(cur_blob);
free_blob_table(table);
out_free_buf:
FREE(buf);
return ret;
}
static void
write_blob_descriptor(struct blob_descriptor_disk *disk_entry,
const struct wim_reshdr *out_reshdr,
u16 part_number, u32 refcnt, const u8 *hash)
{
put_wim_reshdr(out_reshdr, &disk_entry->reshdr);
disk_entry->part_number = cpu_to_le16(part_number);
disk_entry->refcnt = cpu_to_le32(refcnt);
copy_hash(disk_entry->hash, hash);
}
/* Note: the list of blob descriptors must be sorted so that all entries for the
* same solid resource are consecutive. In addition, blob descriptors for
* metadata resources must be in the same order as the indices of the underlying
* images. */
int
write_blob_table_from_blob_list(struct list_head *blob_list,
struct filedes *out_fd,
u16 part_number,
struct wim_reshdr *out_reshdr,
int write_resource_flags)
{
size_t table_size;
struct blob_descriptor *blob;
struct blob_descriptor_disk *table_buf;
struct blob_descriptor_disk *table_buf_ptr;
int ret;
u64 prev_res_offset_in_wim = ~0ULL;
u64 prev_uncompressed_size;
u64 logical_offset;
table_size = 0;
list_for_each_entry(blob, blob_list, blob_table_list) {
table_size += sizeof(struct blob_descriptor_disk);
if (blob->out_reshdr.flags & WIM_RESHDR_FLAG_SOLID &&
blob->out_res_offset_in_wim != prev_res_offset_in_wim)
{
table_size += sizeof(struct blob_descriptor_disk);
prev_res_offset_in_wim = blob->out_res_offset_in_wim;
}
}
table_buf = MALLOC(table_size);
if (table_buf == NULL) {
ERROR("Failed to allocate %zu bytes for temporary blob table",
table_size);
return WIMLIB_ERR_NOMEM;
}
table_buf_ptr = table_buf;
prev_res_offset_in_wim = ~0ULL;
prev_uncompressed_size = 0;
logical_offset = 0;
list_for_each_entry(blob, blob_list, blob_table_list) {
if (blob->out_reshdr.flags & WIM_RESHDR_FLAG_SOLID) {
struct wim_reshdr tmp_reshdr;
/* Eww. When WIMGAPI sees multiple solid resources, it
* expects the offsets to be adjusted as if there were
* really only one solid resource. */
if (blob->out_res_offset_in_wim != prev_res_offset_in_wim) {
/* Put the resource entry for solid resource */
tmp_reshdr.offset_in_wim = blob->out_res_offset_in_wim;
tmp_reshdr.size_in_wim = blob->out_res_size_in_wim;
tmp_reshdr.uncompressed_size = SOLID_RESOURCE_MAGIC_NUMBER;
tmp_reshdr.flags = WIM_RESHDR_FLAG_SOLID;
write_blob_descriptor(table_buf_ptr++, &tmp_reshdr,
part_number, 1, zero_hash);
logical_offset += prev_uncompressed_size;
prev_res_offset_in_wim = blob->out_res_offset_in_wim;
prev_uncompressed_size = blob->out_res_uncompressed_size;
}
tmp_reshdr = blob->out_reshdr;
tmp_reshdr.offset_in_wim += logical_offset;
write_blob_descriptor(table_buf_ptr++, &tmp_reshdr,
part_number, blob->out_refcnt, blob->hash);
} else {
write_blob_descriptor(table_buf_ptr++, &blob->out_reshdr,
part_number, blob->out_refcnt, blob->hash);
}
}
wimlib_assert((u8*)table_buf_ptr - (u8*)table_buf == table_size);
/* Write the blob table uncompressed. Although wimlib can handle a
* compressed blob table, MS software cannot. */
ret = write_wim_resource_from_buffer(table_buf,
table_size,
true,
out_fd,
WIMLIB_COMPRESSION_TYPE_NONE,
0,
out_reshdr,
NULL,
write_resource_flags);
FREE(table_buf);
return ret;
}
/* Allocate a blob descriptor for the contents of the buffer, or re-use an
* existing descriptor in @blob_table for an identical blob. */
struct blob_descriptor *
new_blob_from_data_buffer(const void *buffer, size_t size,
struct blob_table *blob_table)
{
u8 hash[SHA1_HASH_SIZE];
struct blob_descriptor *blob;
void *buffer_copy;
sha1(buffer, size, hash);
blob = lookup_blob(blob_table, hash);
if (blob)
return blob;
blob = new_blob_descriptor();
if (!blob)
return NULL;
buffer_copy = memdup(buffer, size);
if (!buffer_copy) {
free_blob_descriptor(blob);
return NULL;
}
blob_set_is_located_in_attached_buffer(blob, buffer_copy, size);
copy_hash(blob->hash, hash);
blob_table_insert(blob_table, blob);
return blob;
}
struct blob_descriptor *
after_blob_hashed(struct blob_descriptor *blob,
struct blob_descriptor **back_ptr,
struct blob_table *blob_table, struct wim_inode *inode)
{
struct blob_descriptor *duplicate_blob;
list_del(&blob->unhashed_list);
blob->unhashed = 0;
/* Look for a duplicate blob */
duplicate_blob = lookup_blob(blob_table, blob->hash);
if (duplicate_blob) {
/* We have a duplicate blob. Transfer the reference counts from
* this blob to the duplicate and update the reference to this
* blob (from a stream) to point to the duplicate. The caller
* is responsible for freeing @blob if needed. */
if (duplicate_blob->size != blob->size) {
tchar hash_str[SHA1_HASH_STRING_LEN];
sprint_hash(blob->hash, hash_str);
WARNING("SHA-1 collision at \"%"TS"\"\n"
" (hash=%"TS", size=%"PRIu64", other_size=%"PRIu64").\n"
" File will be corrupted!",
inode_any_full_path(inode), hash_str,
blob->size, duplicate_blob->size);
}
duplicate_blob->refcnt += blob->refcnt;
blob->refcnt = 0;
*back_ptr = duplicate_blob;
return duplicate_blob;
} else {
/* No duplicate blob, so we need to insert this blob into the
* blob table and treat it as a hashed blob. */
blob_table_insert(blob_table, blob);
return blob;
}
}
/*
* Calculate the SHA-1 message digest of a blob and move its descriptor from the
* list of unhashed blobs to the blob table, possibly joining it with an
* identical blob.
*
* @blob:
* The blob to hash
* @blob_table:
* The blob table in which the blob needs to be indexed
* @blob_ret:
* On success, a pointer to the resulting blob descriptor is written to
* this location. This will be the same as @blob if it was inserted into
* the blob table, or different if a duplicate blob was found.
*
* Returns 0 on success; nonzero if there is an error reading the blob data.
*/
int
hash_unhashed_blob(struct blob_descriptor *blob, struct blob_table *blob_table,
struct blob_descriptor **blob_ret)
{
struct blob_descriptor **back_ptr;
struct wim_inode *inode;
int ret;
back_ptr = retrieve_pointer_to_unhashed_blob(blob);
inode = blob->back_inode;
ret = sha1_blob(blob);
if (ret)
return ret;
*blob_ret = after_blob_hashed(blob, back_ptr, blob_table, inode);
return 0;
}
void
blob_to_wimlib_resource_entry(const struct blob_descriptor *blob,
struct wimlib_resource_entry *wentry)
{
memset(wentry, 0, sizeof(*wentry));
wentry->uncompressed_size = blob->size;
if (blob->blob_location == BLOB_IN_WIM) {
unsigned res_flags = blob->rdesc->flags;
wentry->part_number = blob->rdesc->wim->hdr.part_number;
if (res_flags & WIM_RESHDR_FLAG_SOLID) {
wentry->offset = blob->offset_in_res;
} else {
wentry->compressed_size = blob->rdesc->size_in_wim;
wentry->offset = blob->rdesc->offset_in_wim;
}
wentry->raw_resource_offset_in_wim = blob->rdesc->offset_in_wim;
wentry->raw_resource_compressed_size = blob->rdesc->size_in_wim;
wentry->raw_resource_uncompressed_size = blob->rdesc->uncompressed_size;
wentry->is_compressed = (res_flags & WIM_RESHDR_FLAG_COMPRESSED) != 0;
wentry->is_free = (res_flags & WIM_RESHDR_FLAG_FREE) != 0;
wentry->is_spanned = (res_flags & WIM_RESHDR_FLAG_SPANNED) != 0;
wentry->packed = (res_flags & WIM_RESHDR_FLAG_SOLID) != 0;
}
if (!blob->unhashed)
copy_hash(wentry->sha1_hash, blob->hash);
wentry->reference_count = blob->refcnt;
wentry->is_metadata = blob->is_metadata;
}
struct iterate_blob_context {
wimlib_iterate_lookup_table_callback_t cb;
void *user_ctx;
};
static int
do_iterate_blob(struct blob_descriptor *blob, void *_ctx)
{
struct iterate_blob_context *ctx = _ctx;
struct wimlib_resource_entry entry;
blob_to_wimlib_resource_entry(blob, &entry);
return (*ctx->cb)(&entry, ctx->user_ctx);
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_iterate_lookup_table(WIMStruct *wim, int flags,
wimlib_iterate_lookup_table_callback_t cb,
void *user_ctx)
{
if (flags != 0)
return WIMLIB_ERR_INVALID_PARAM;
struct iterate_blob_context ctx = {
.cb = cb,
.user_ctx = user_ctx,
};
if (wim_has_metadata(wim)) {
int ret;
for (int i = 0; i < wim->hdr.image_count; i++) {
struct blob_descriptor *blob;
struct wim_image_metadata *imd = wim->image_metadata[i];
ret = do_iterate_blob(imd->metadata_blob, &ctx);
if (ret)
return ret;
image_for_each_unhashed_blob(blob, imd) {
ret = do_iterate_blob(blob, &ctx);
if (ret)
return ret;
}
}
}
return for_blob_in_table(wim->blob_table, do_iterate_blob, &ctx);
}
wimlib-1.14.5/src/inode_fixup.c 0000644 0001750 0001750 00000014522 15137020663 013632 0 ustar 00e e /*
* inode_fixup.c
*/
/*
* Copyright (C) 2012, 2013, 2014 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/dentry.h"
#include "wimlib/error.h"
#include "wimlib/inode.h"
#include "wimlib/inode_table.h"
struct inode_fixup_params {
struct wim_inode_table inode_table;
unsigned long num_dir_hard_links;
unsigned long num_inconsistent_inodes;
};
#define MAX_DIR_HARD_LINK_WARNINGS 8
static bool
inodes_consistent(const struct wim_inode *inode_1,
const struct wim_inode *inode_2)
{
/* This certainly isn't the only thing we need to check to make sure the
* inodes are consistent. However, this seems to be the only thing that
* the MS implementation checks when working around its own bug.
*
* (Tested: If two dentries share the same hard link group ID, Windows
* 8.1 DISM will link them if they have the same unnamed stream hash,
* even if the dentries provide different timestamps, attributes,
* alternate data streams, and security IDs! And the one that gets used
* will change if you merely swap the filenames. But if you use
* different unnamed stream hashes with everything else the same, it
* doesn't link the dentries.)
*
* For non-buggy WIMs this function will always return true. */
return hashes_equal(inode_get_hash_of_unnamed_data_stream(inode_1),
inode_get_hash_of_unnamed_data_stream(inode_2));
}
static int
inode_table_insert(struct wim_dentry *dentry, void *_params)
{
struct inode_fixup_params *params = _params;
struct wim_inode_table *table = ¶ms->inode_table;
struct wim_inode *d_inode = dentry->d_inode;
size_t pos;
struct wim_inode *inode;
if (d_inode->i_ino == 0) {
hlist_add_head(&d_inode->i_hlist_node, &table->extra_inodes);
return 0;
}
/* Try adding this dentry to an existing inode. */
pos = hash_inode(table, d_inode->i_ino, 0);
hlist_for_each_entry(inode, &table->array[pos], i_hlist_node) {
if (inode->i_ino != d_inode->i_ino) {
continue;
}
if (unlikely(!inodes_consistent(inode, d_inode))) {
params->num_inconsistent_inodes++;
continue;
}
if (unlikely((d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) ||
(inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)))
{
params->num_dir_hard_links++;
if (params->num_dir_hard_links <=
MAX_DIR_HARD_LINK_WARNINGS)
{
WARNING("Unsupported directory hard link "
"\"%"TS"\" <=> \"%"TS"\"",
dentry_full_path(dentry),
inode_any_full_path(inode));
} else if (params->num_dir_hard_links ==
MAX_DIR_HARD_LINK_WARNINGS + 1)
{
WARNING("Suppressing additional warnings about "
"directory hard links...");
}
continue;
}
/* Transfer this dentry to the existing inode. */
d_disassociate(dentry);
d_associate(dentry, inode);
return 0;
}
/* Keep this dentry's inode. */
hlist_add_head(&d_inode->i_hlist_node, &table->array[pos]);
if (++table->filled > table->capacity)
enlarge_inode_table(table);
return 0;
}
static void
hlist_move_all(struct hlist_head *src, struct hlist_head *dest)
{
struct hlist_node *node;
while ((node = src->first) != NULL) {
hlist_del(node);
hlist_add_head(node, dest);
}
}
/* Move the inodes from the 'struct wim_inode_table' to the 'inode_list'. */
static void
build_inode_list(struct wim_inode_table *inode_table,
struct hlist_head *inode_list)
{
hlist_move_all(&inode_table->extra_inodes, inode_list);
for (size_t i = 0; i < inode_table->capacity; i++)
hlist_move_all(&inode_table->array[i], inode_list);
}
/* Re-assign inode numbers to the inodes in the list. */
static void
reassign_inode_numbers(struct hlist_head *inode_list)
{
struct wim_inode *inode;
u64 cur_ino = 1;
hlist_for_each_entry(inode, inode_list, i_hlist_node)
inode->i_ino = cur_ino++;
}
/*
* Given a WIM image's tree of dentries such that each dentry initially
* has a unique inode associated with it, determine the actual
* dentry/inode information. Following this, a single inode may be named
* by more than one dentry (usually called a hard link).
*
* The 'hard_link_group_id' field of the on-disk WIM dentry, which we
* have read into 'i_ino' of each dentry's initial inode, determines
* which dentries share the same inode. Ideally, dentries share the same
* inode if and only if they have the same value in this field. However,
* exceptions apply:
*
* - If 'hard_link_group_id' is 0, the corresponding dentry is the sole
* name for its inode.
* - Due to bugs in the Microsoft implementation, dentries with different
* 'hard_link_group_id' fields may, in fact, need to be interpreted as
* naming different inodes. This seems to mostly affect images in
* install.wim for Windows 7. I try to work around this in the same way
* the Microsoft implementation works around this.
*
* Returns 0 or WIMLIB_ERR_NOMEM. On success, the resulting inodes will be
* appended to the @inode_list, and they will have consistent numbers in their
* i_ino fields.
*/
int
dentry_tree_fix_inodes(struct wim_dentry *root, struct hlist_head *inode_list)
{
struct inode_fixup_params params;
int ret;
/* We use a hash table to map inode numbers to inodes. */
ret = init_inode_table(¶ms.inode_table, 64);
if (ret)
return ret;
params.num_dir_hard_links = 0;
params.num_inconsistent_inodes = 0;
for_dentry_in_tree(root, inode_table_insert, ¶ms);
/* Generate the resulting list of inodes, and if needed reassign
* the inode numbers. */
build_inode_list(¶ms.inode_table, inode_list);
destroy_inode_table(¶ms.inode_table);
if (unlikely(params.num_dir_hard_links))
WARNING("Ignoring %lu directory hard links",
params.num_dir_hard_links);
if (unlikely(params.num_inconsistent_inodes ||
params.num_dir_hard_links))
reassign_inode_numbers(inode_list);
return 0;
}
wimlib-1.14.5/src/add_image.c 0000644 0001750 0001750 00000011260 15137020663 013207 0 ustar 00e e /*
* add_image.c - Add an image to a WIMStruct.
*/
/*
* Copyright (C) 2012-2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib.h"
#include "wimlib/blob_table.h"
#include "wimlib/error.h"
#include "wimlib/metadata.h"
#include "wimlib/security.h"
#include "wimlib/xml.h"
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret)
{
struct wim_image_metadata *imd;
int ret;
if (wimlib_image_name_in_use(wim, name)) {
ERROR("There is already an image named \"%"TS"\" in the WIM!",
name);
return WIMLIB_ERR_IMAGE_NAME_COLLISION;
}
imd = new_empty_image_metadata();
if (!imd)
return WIMLIB_ERR_NOMEM;
ret = append_image_metadata(wim, imd);
if (ret)
goto err_put_imd;
ret = xml_add_image(wim->xml_info, name);
if (ret)
goto err_undo_append;
if (new_idx_ret)
*new_idx_ret = wim->hdr.image_count;
return 0;
err_undo_append:
wim->hdr.image_count--;
err_put_imd:
put_image_metadata(imd);
return ret;
}
/* Translate the 'struct wimlib_capture_source's passed to
* wimlib_add_image_multisource() into 'struct wimlib_update_command's for
* wimlib_update_image(). */
static struct wimlib_update_command *
capture_sources_to_add_cmds(const struct wimlib_capture_source *sources,
size_t num_sources,
int add_flags,
const tchar *config_file)
{
struct wimlib_update_command *add_cmds;
add_cmds = CALLOC(num_sources, sizeof(add_cmds[0]));
if (!add_cmds)
return NULL;
/* WIMLIB_ADD_FLAG_BOOT is handled by wimlib_add_image_multisource(),
* not wimlib_update_image(), so mask it out.
*
* However, WIMLIB_ADD_FLAG_WIMBOOT is handled by both. */
add_flags &= ~WIMLIB_ADD_FLAG_BOOT;
for (size_t i = 0; i < num_sources; i++) {
add_cmds[i].op = WIMLIB_UPDATE_OP_ADD;
add_cmds[i].add.fs_source_path = sources[i].fs_source_path;
add_cmds[i].add.wim_target_path = sources[i].wim_target_path;
add_cmds[i].add.add_flags = add_flags;
add_cmds[i].add.config_file = (tchar *)config_file;
}
return add_cmds;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_add_image_multisource(WIMStruct *wim,
const struct wimlib_capture_source *sources,
size_t num_sources,
const tchar *name,
const tchar *config_file,
int add_flags)
{
int ret;
struct wimlib_update_command *add_cmds;
/* Make sure no reserved fields are set. */
for (size_t i = 0; i < num_sources; i++)
if (sources[i].reserved != 0)
return WIMLIB_ERR_INVALID_PARAM;
/* Add the new image (initially empty). */
ret = wimlib_add_empty_image(wim, name, NULL);
if (ret)
return ret;
/* Translate the "capture sources" into generic update commands. */
ret = WIMLIB_ERR_NOMEM;
add_cmds = capture_sources_to_add_cmds(sources, num_sources,
add_flags, config_file);
if (!add_cmds)
goto out_delete_image;
/* Delegate the work to wimlib_update_image(). */
ret = wimlib_update_image(wim, wim->hdr.image_count, add_cmds,
num_sources, 0);
FREE(add_cmds);
if (ret)
goto out_delete_image;
/* If requested, mark the new image as WIMBoot-compatible. */
if (add_flags & WIMLIB_ADD_FLAG_WIMBOOT) {
ret = xml_set_wimboot(wim->xml_info, wim->hdr.image_count);
if (ret)
goto out_delete_image;
}
/* If requested, set this image as the WIM's bootable image. */
if (add_flags & WIMLIB_ADD_FLAG_BOOT)
wim->hdr.boot_idx = wim->hdr.image_count;
return 0;
out_delete_image:
/* Unsuccessful; rollback by removing the new image. */
delete_wim_image(wim, wim->hdr.image_count);
return ret;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_add_image(WIMStruct *wim,
const tchar *source,
const tchar *name,
const tchar *config_file,
int add_flags)
{
/* Use the more general wimlib_add_image_multisource(). */
const struct wimlib_capture_source capture_src = {
.fs_source_path = (tchar *)source,
.wim_target_path = WIMLIB_WIM_ROOT_PATH,
.reserved = 0,
};
return wimlib_add_image_multisource(wim, &capture_src, 1, name,
config_file, add_flags);
}
wimlib-1.14.5/src/pathlist.c 0000644 0001750 0001750 00000002552 15137020663 013151 0 ustar 00e e /*
* pathlist.c
*
* Utility function for reading path list files.
*/
/*
* Copyright (C) 2013 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/pathlist.h"
#include "wimlib/textfile.h"
int
read_path_list_file(const tchar *listfile,
tchar ***paths_ret, size_t *num_paths_ret,
void **mem_ret)
{
STRING_LIST(paths);
struct text_file_section tmp = {
.name = T(""),
.strings = &paths,
};
void *buf;
int ret;
ret = load_text_file(listfile, NULL, 0, &buf, &tmp, 1,
LOAD_TEXT_FILE_REMOVE_QUOTES |
LOAD_TEXT_FILE_ALLOW_STDIN, NULL);
if (ret)
return ret;
*paths_ret = paths.strings;
*num_paths_ret = paths.num_strings;
*mem_ret = buf;
return 0;
}
wimlib-1.14.5/src/avl_tree.c 0000644 0001750 0001750 00000056661 15137011205 013124 0 ustar 00e e /*
* avl_tree.c - intrusive, nonrecursive AVL tree data structure (self-balancing
* binary search tree), implementation file
*
* Copyright 2022 Eric Biggers
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/avl_tree.h"
/* Returns the left child (sign < 0) or the right child (sign > 0) of the
* specified AVL tree node.
* Note: for all calls of this, 'sign' is constant at compilation time,
* so the compiler can remove the conditional. */
static AVL_INLINE struct avl_tree_node *
avl_get_child(const struct avl_tree_node *parent, int sign)
{
if (sign < 0)
return parent->left;
else
return parent->right;
}
static AVL_INLINE struct avl_tree_node *
avl_tree_first_or_last_in_order(const struct avl_tree_node *root, int sign)
{
const struct avl_tree_node *first = root;
if (first)
while (avl_get_child(first, +sign))
first = avl_get_child(first, +sign);
return (struct avl_tree_node *)first;
}
/* Starts an in-order traversal of the tree: returns the least-valued node, or
* NULL if the tree is empty. */
struct avl_tree_node *
avl_tree_first_in_order(const struct avl_tree_node *root)
{
return avl_tree_first_or_last_in_order(root, -1);
}
/* Starts a *reverse* in-order traversal of the tree: returns the
* greatest-valued node, or NULL if the tree is empty. */
struct avl_tree_node *
avl_tree_last_in_order(const struct avl_tree_node *root)
{
return avl_tree_first_or_last_in_order(root, 1);
}
static AVL_INLINE struct avl_tree_node *
avl_tree_next_or_prev_in_order(const struct avl_tree_node *node, int sign)
{
const struct avl_tree_node *next;
if (avl_get_child(node, +sign))
for (next = avl_get_child(node, +sign);
avl_get_child(next, -sign);
next = avl_get_child(next, -sign))
;
else
for (next = avl_get_parent(node);
next && node == avl_get_child(next, +sign);
node = next, next = avl_get_parent(next))
;
return (struct avl_tree_node *)next;
}
/* Continues an in-order traversal of the tree: returns the next-greatest-valued
* node, or NULL if there is none. */
struct avl_tree_node *
avl_tree_next_in_order(const struct avl_tree_node *node)
{
return avl_tree_next_or_prev_in_order(node, 1);
}
/* Continues a *reverse* in-order traversal of the tree: returns the
* previous-greatest-valued node, or NULL if there is none. */
struct avl_tree_node *
avl_tree_prev_in_order(const struct avl_tree_node *node)
{
return avl_tree_next_or_prev_in_order(node, -1);
}
/* Starts a postorder traversal of the tree. */
struct avl_tree_node *
avl_tree_first_in_postorder(const struct avl_tree_node *root)
{
const struct avl_tree_node *first = root;
if (first)
while (first->left || first->right)
first = first->left ? first->left : first->right;
return (struct avl_tree_node *)first;
}
/* Continues a postorder traversal of the tree. @prev will not be deferenced as
* it's allowed that its memory has been freed; @prev_parent must be its saved
* parent node. Returns NULL if there are no more nodes (i.e. @prev was the
* root of the tree). */
struct avl_tree_node *
avl_tree_next_in_postorder(const struct avl_tree_node *prev,
const struct avl_tree_node *prev_parent)
{
const struct avl_tree_node *next = prev_parent;
if (next && prev == next->left && next->right)
for (next = next->right;
next->left || next->right;
next = next->left ? next->left : next->right)
;
return (struct avl_tree_node *)next;
}
/* Sets the left child (sign < 0) or the right child (sign > 0) of the
* specified AVL tree node.
* Note: for all calls of this, 'sign' is constant at compilation time,
* so the compiler can remove the conditional. */
static AVL_INLINE void
avl_set_child(struct avl_tree_node *parent, int sign,
struct avl_tree_node *child)
{
if (sign < 0)
parent->left = child;
else
parent->right = child;
}
/* Sets the parent and balance factor of the specified AVL tree node. */
static AVL_INLINE void
avl_set_parent_balance(struct avl_tree_node *node, struct avl_tree_node *parent,
int balance_factor)
{
node->parent_balance = (uintptr_t)parent | (balance_factor + 1);
}
/* Sets the parent of the specified AVL tree node. */
static AVL_INLINE void
avl_set_parent(struct avl_tree_node *node, struct avl_tree_node *parent)
{
node->parent_balance = (uintptr_t)parent | (node->parent_balance & 3);
}
/* Returns the balance factor of the specified AVL tree node --- that is, the
* height of its right subtree minus the height of its left subtree. */
static AVL_INLINE int
avl_get_balance_factor(const struct avl_tree_node *node)
{
return (int)(node->parent_balance & 3) - 1;
}
/* Adds @amount to the balance factor of the specified AVL tree node.
* The caller must ensure this still results in a valid balance factor
* (-1, 0, or 1). */
static AVL_INLINE void
avl_adjust_balance_factor(struct avl_tree_node *node, int amount)
{
node->parent_balance += amount;
}
static AVL_INLINE void
avl_replace_child(struct avl_tree_node **root_ptr,
struct avl_tree_node *parent,
struct avl_tree_node *old_child,
struct avl_tree_node *new_child)
{
if (parent) {
if (old_child == parent->left)
parent->left = new_child;
else
parent->right = new_child;
} else {
*root_ptr = new_child;
}
}
/*
* Template for performing a single rotation ---
*
* sign > 0: Rotate clockwise (right) rooted at A:
*
* P? P?
* | |
* A B
* / \ / \
* B C? => D? A
* / \ / \
* D? E? E? C?
*
* (nodes marked with ? may not exist)
*
* sign < 0: Rotate counterclockwise (left) rooted at A:
*
* P? P?
* | |
* A B
* / \ / \
* C? B => A D?
* / \ / \
* E? D? C? E?
*
* This updates pointers but not balance factors!
*/
static AVL_INLINE void
avl_rotate(struct avl_tree_node ** const root_ptr,
struct avl_tree_node * const A, const int sign)
{
struct avl_tree_node * const B = avl_get_child(A, -sign);
struct avl_tree_node * const E = avl_get_child(B, +sign);
struct avl_tree_node * const P = avl_get_parent(A);
avl_set_child(A, -sign, E);
avl_set_parent(A, B);
avl_set_child(B, +sign, A);
avl_set_parent(B, P);
if (E)
avl_set_parent(E, A);
avl_replace_child(root_ptr, P, A, B);
}
/*
* Template for performing a double rotation ---
*
* sign > 0: Rotate counterclockwise (left) rooted at B, then
* clockwise (right) rooted at A:
*
* P? P? P?
* | | |
* A A E
* / \ / \ / \
* B C? => E C? => B A
* / \ / \ / \ / \
* D? E B G? D? F?G? C?
* / \ / \
* F? G? D? F?
*
* (nodes marked with ? may not exist)
*
* sign < 0: Rotate clockwise (right) rooted at B, then
* counterclockwise (left) rooted at A:
*
* P? P? P?
* | | |
* A A E
* / \ / \ / \
* C? B => C? E => A B
* / \ / \ / \ / \
* E D? G? B C? G?F? D?
* / \ / \
* G? F? F? D?
*
* Returns a pointer to E and updates balance factors. Except for those
* two things, this function is equivalent to:
* avl_rotate(root_ptr, B, -sign);
* avl_rotate(root_ptr, A, +sign);
*
* See comment in avl_handle_subtree_growth() for explanation of balance
* factor updates.
*/
static AVL_INLINE struct avl_tree_node *
avl_do_double_rotate(struct avl_tree_node ** const root_ptr,
struct avl_tree_node * const B,
struct avl_tree_node * const A, const int sign)
{
struct avl_tree_node * const E = avl_get_child(B, +sign);
struct avl_tree_node * const F = avl_get_child(E, -sign);
struct avl_tree_node * const G = avl_get_child(E, +sign);
struct avl_tree_node * const P = avl_get_parent(A);
const int e = avl_get_balance_factor(E);
avl_set_child(A, -sign, G);
avl_set_parent_balance(A, E, ((sign * e >= 0) ? 0 : -e));
avl_set_child(B, +sign, F);
avl_set_parent_balance(B, E, ((sign * e <= 0) ? 0 : -e));
avl_set_child(E, +sign, A);
avl_set_child(E, -sign, B);
avl_set_parent_balance(E, P, 0);
if (G)
avl_set_parent(G, A);
if (F)
avl_set_parent(F, B);
avl_replace_child(root_ptr, P, A, E);
return E;
}
/*
* This function handles the growth of a subtree due to an insertion.
*
* @root_ptr
* Location of the tree's root pointer.
*
* @node
* A subtree that has increased in height by 1 due to an insertion.
*
* @parent
* Parent of @node; must not be NULL.
*
* @sign
* -1 if @node is the left child of @parent;
* +1 if @node is the right child of @parent.
*
* This function will adjust @parent's balance factor, then do a (single
* or double) rotation if necessary. The return value will be %true if
* the full AVL tree is now adequately balanced, or %false if the subtree
* rooted at @parent is now adequately balanced but has increased in
* height by 1, so the caller should continue up the tree.
*
* Note that if %false is returned, no rotation will have been done.
* Indeed, a single node insertion cannot require that more than one
* (single or double) rotation be done.
*/
static AVL_INLINE bool
avl_handle_subtree_growth(struct avl_tree_node ** const root_ptr,
struct avl_tree_node * const node,
struct avl_tree_node * const parent,
const int sign)
{
int old_balance_factor, new_balance_factor;
old_balance_factor = avl_get_balance_factor(parent);
if (old_balance_factor == 0) {
avl_adjust_balance_factor(parent, sign);
/* @parent is still sufficiently balanced (-1 or +1
* balance factor), but must have increased in height.
* Continue up the tree. */
return false;
}
new_balance_factor = old_balance_factor + sign;
if (new_balance_factor == 0) {
avl_adjust_balance_factor(parent, sign);
/* @parent is now perfectly balanced (0 balance factor).
* It cannot have increased in height, so there is
* nothing more to do. */
return true;
}
/* @parent is too left-heavy (new_balance_factor == -2) or
* too right-heavy (new_balance_factor == +2). */
/* Test whether @node is left-heavy (-1 balance factor) or
* right-heavy (+1 balance factor).
* Note that it cannot be perfectly balanced (0 balance factor)
* because here we are under the invariant that @node has
* increased in height due to the insertion. */
if (sign * avl_get_balance_factor(node) > 0) {
/* @node (B below) is heavy in the same direction @parent
* (A below) is heavy.
*
* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* The comment, diagram, and equations below assume sign < 0.
* The other case is symmetric!
* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*
* Do a clockwise rotation rooted at @parent (A below):
*
* A B
* / \ / \
* B C? => D A
* / \ / \ / \
* D E? F? G?E? C?
* / \
* F? G?
*
* Before the rotation:
* balance(A) = -2
* balance(B) = -1
* Let x = height(C). Then:
* height(B) = x + 2
* height(D) = x + 1
* height(E) = x
* max(height(F), height(G)) = x.
*
* After the rotation:
* height(D) = max(height(F), height(G)) + 1
* = x + 1
* height(A) = max(height(E), height(C)) + 1
* = max(x, x) + 1 = x + 1
* balance(B) = 0
* balance(A) = 0
*/
avl_rotate(root_ptr, parent, -sign);
/* Equivalent to setting @parent's balance factor to 0. */
avl_adjust_balance_factor(parent, -sign); /* A */
/* Equivalent to setting @node's balance factor to 0. */
avl_adjust_balance_factor(node, -sign); /* B */
} else {
/* @node (B below) is heavy in the direction opposite
* from the direction @parent (A below) is heavy.
*
* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* The comment, diagram, and equations below assume sign < 0.
* The other case is symmetric!
* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*
* Do a counterblockwise rotation rooted at @node (B below),
* then a clockwise rotation rooted at @parent (A below):
*
* A A E
* / \ / \ / \
* B C? => E C? => B A
* / \ / \ / \ / \
* D? E B G? D? F?G? C?
* / \ / \
* F? G? D? F?
*
* Before the rotation:
* balance(A) = -2
* balance(B) = +1
* Let x = height(C). Then:
* height(B) = x + 2
* height(E) = x + 1
* height(D) = x
* max(height(F), height(G)) = x
*
* After both rotations:
* height(A) = max(height(G), height(C)) + 1
* = x + 1
* balance(A) = balance(E{orig}) >= 0 ? 0 : -balance(E{orig})
* height(B) = max(height(D), height(F)) + 1
* = x + 1
* balance(B) = balance(E{orig} <= 0) ? 0 : -balance(E{orig})
*
* height(E) = x + 2
* balance(E) = 0
*/
avl_do_double_rotate(root_ptr, node, parent, -sign);
}
/* Height after rotation is unchanged; nothing more to do. */
return true;
}
/* Rebalance the tree after insertion of the specified node. */
void
avl_tree_rebalance_after_insert(struct avl_tree_node **root_ptr,
struct avl_tree_node *inserted)
{
struct avl_tree_node *node, *parent;
bool done;
inserted->left = NULL;
inserted->right = NULL;
node = inserted;
/* Adjust balance factor of new node's parent.
* No rotation will need to be done at this level. */
parent = avl_get_parent(node);
if (!parent)
return;
if (node == parent->left)
avl_adjust_balance_factor(parent, -1);
else
avl_adjust_balance_factor(parent, +1);
if (avl_get_balance_factor(parent) == 0)
/* @parent did not change in height. Nothing more to do. */
return;
/* The subtree rooted at @parent increased in height by 1. */
do {
/* Adjust balance factor of next ancestor. */
node = parent;
parent = avl_get_parent(node);
if (!parent)
return;
/* The subtree rooted at @node has increased in height by 1. */
if (node == parent->left)
done = avl_handle_subtree_growth(root_ptr, node,
parent, -1);
else
done = avl_handle_subtree_growth(root_ptr, node,
parent, +1);
} while (!done);
}
/*
* This function handles the shrinkage of a subtree due to a deletion.
*
* @root_ptr
* Location of the tree's root pointer.
*
* @parent
* A node in the tree, exactly one of whose subtrees has decreased
* in height by 1 due to a deletion. (This includes the case where
* one of the child pointers has become NULL, since we can consider
* the "NULL" subtree to have a height of 0.)
*
* @sign
* +1 if the left subtree of @parent has decreased in height by 1;
* -1 if the right subtree of @parent has decreased in height by 1.
*
* @left_deleted_ret
* If the return value is not NULL, this will be set to %true if the
* left subtree of the returned node has decreased in height by 1,
* or %false if the right subtree of the returned node has decreased
* in height by 1.
*
* This function will adjust @parent's balance factor, then do a (single
* or double) rotation if necessary. The return value will be NULL if
* the full AVL tree is now adequately balanced, or a pointer to the
* parent of @parent if @parent is now adequately balanced but has
* decreased in height by 1. Also in the latter case, *left_deleted_ret
* will be set.
*/
static AVL_INLINE struct avl_tree_node *
avl_handle_subtree_shrink(struct avl_tree_node ** const root_ptr,
struct avl_tree_node *parent,
const int sign,
bool * const left_deleted_ret)
{
struct avl_tree_node *node;
int old_balance_factor, new_balance_factor;
old_balance_factor = avl_get_balance_factor(parent);
if (old_balance_factor == 0) {
/* Prior to the deletion, the subtree rooted at
* @parent was perfectly balanced. It's now
* unbalanced by 1, but that's okay and its height
* hasn't changed. Nothing more to do. */
avl_adjust_balance_factor(parent, sign);
return NULL;
}
new_balance_factor = old_balance_factor + sign;
if (new_balance_factor == 0) {
/* The subtree rooted at @parent is now perfectly
* balanced, whereas before the deletion it was
* unbalanced by 1. Its height must have decreased
* by 1. No rotation is needed at this location,
* but continue up the tree. */
avl_adjust_balance_factor(parent, sign);
node = parent;
} else {
/* @parent is too left-heavy (new_balance_factor == -2) or
* too right-heavy (new_balance_factor == +2). */
node = avl_get_child(parent, sign);
/* The rotations below are similar to those done during
* insertion (see avl_handle_subtree_growth()), so full
* comments are not provided. The only new case is the
* one where @node has a balance factor of 0, and that is
* commented. */
if (sign * avl_get_balance_factor(node) >= 0) {
avl_rotate(root_ptr, parent, -sign);
if (avl_get_balance_factor(node) == 0) {
/*
* @node (B below) is perfectly balanced.
*
* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* The comment, diagram, and equations
* below assume sign < 0. The other case
* is symmetric!
* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*
* Do a clockwise rotation rooted at
* @parent (A below):
*
* A B
* / \ / \
* B C? => D A
* / \ / \ / \
* D E F? G?E C?
* / \
* F? G?
*
* Before the rotation:
* balance(A) = -2
* balance(B) = 0
* Let x = height(C). Then:
* height(B) = x + 2
* height(D) = x + 1
* height(E) = x + 1
* max(height(F), height(G)) = x.
*
* After the rotation:
* height(D) = max(height(F), height(G)) + 1
* = x + 1
* height(A) = max(height(E), height(C)) + 1
* = max(x + 1, x) + 1 = x + 2
* balance(A) = -1
* balance(B) = +1
*/
/* A: -2 => -1 (sign < 0)
* or +2 => +1 (sign > 0)
* No change needed --- that's the same as
* old_balance_factor. */
/* B: 0 => +1 (sign < 0)
* or 0 => -1 (sign > 0) */
avl_adjust_balance_factor(node, -sign);
/* Height is unchanged; nothing more to do. */
return NULL;
} else {
avl_adjust_balance_factor(parent, -sign);
avl_adjust_balance_factor(node, -sign);
}
} else {
node = avl_do_double_rotate(root_ptr, node,
parent, -sign);
}
}
parent = avl_get_parent(node);
if (parent)
*left_deleted_ret = (node == parent->left);
return parent;
}
/* Swaps node X, which must have 2 children, with its in-order successor, then
* unlinks node X. Returns the parent of X just before unlinking, without its
* balance factor having been updated to account for the unlink. */
static AVL_INLINE struct avl_tree_node *
avl_tree_swap_with_successor(struct avl_tree_node **root_ptr,
struct avl_tree_node *X,
bool *left_deleted_ret)
{
struct avl_tree_node *Y, *ret;
Y = X->right;
if (!Y->left) {
/*
* P? P? P?
* | | |
* X Y Y
* / \ / \ / \
* A Y => A X => A B?
* / \ / \
* (0) B? (0) B?
*
* [ X unlinked, Y returned ]
*/
ret = Y;
*left_deleted_ret = false;
} else {
struct avl_tree_node *Q;
do {
Q = Y;
Y = Y->left;
} while (Y->left);
/*
* P? P? P?
* | | |
* X Y Y
* / \ / \ / \
* A ... => A ... => A ...
* | | |
* Q Q Q
* / / /
* Y X B?
* / \ / \
* (0) B? (0) B?
*
*
* [ X unlinked, Q returned ]
*/
Q->left = Y->right;
if (Q->left)
avl_set_parent(Q->left, Q);
Y->right = X->right;
avl_set_parent(X->right, Y);
ret = Q;
*left_deleted_ret = true;
}
Y->left = X->left;
avl_set_parent(X->left, Y);
Y->parent_balance = X->parent_balance;
avl_replace_child(root_ptr, avl_get_parent(X), X, Y);
return ret;
}
/*
* Removes an item from the specified AVL tree.
*
* @root_ptr
* Location of the AVL tree's root pointer. Indirection is needed
* because the root node may change if the tree needed to be rebalanced
* because of the deletion or if @node was the root node.
*
* @node
* Pointer to the `struct avl_tree_node' embedded in the item to
* remove from the tree.
*
* Note: This function *only* removes the node and rebalances the tree.
* It does not free any memory.
*/
void
avl_tree_remove(struct avl_tree_node **root_ptr, struct avl_tree_node *node)
{
struct avl_tree_node *parent;
bool left_deleted = false;
if (node->left && node->right) {
/* @node is fully internal, with two children. Swap it
* with its in-order successor (which must exist in the
* right subtree of @node and can have, at most, a right
* child), then unlink @node. */
parent = avl_tree_swap_with_successor(root_ptr, node,
&left_deleted);
/* @parent is now the parent of what was @node's in-order
* successor. It cannot be NULL, since @node itself was
* an ancestor of its in-order successor.
* @left_deleted has been set to %true if @node's
* in-order successor was the left child of @parent,
* otherwise %false. */
} else {
struct avl_tree_node *child;
/* @node is missing at least one child. Unlink it. Set
* @parent to @node's parent, and set @left_deleted to
* reflect which child of @parent @node was. Or, if
* @node was the root node, simply update the root node
* and return. */
child = node->left ? node->left : node->right;
parent = avl_get_parent(node);
if (parent) {
if (node == parent->left) {
parent->left = child;
left_deleted = true;
} else {
parent->right = child;
left_deleted = false;
}
if (child)
avl_set_parent(child, parent);
} else {
if (child)
avl_set_parent(child, parent);
*root_ptr = child;
return;
}
}
/* Rebalance the tree. */
do {
if (left_deleted)
parent = avl_handle_subtree_shrink(root_ptr, parent,
+1, &left_deleted);
else
parent = avl_handle_subtree_shrink(root_ptr, parent,
-1, &left_deleted);
} while (parent);
}
wimlib-1.14.5/src/compress_parallel.c 0000644 0001750 0001750 00000031215 15137020663 015026 0 ustar 00e e /*
* compress_parallel.c
*
* Compress chunks of data (parallel version).
*/
/*
* Copyright (C) 2013-2023 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#include "wimlib/assert.h"
#include "wimlib/chunk_compressor.h"
#include "wimlib/error.h"
#include "wimlib/list.h"
#include "wimlib/threads.h"
#include "wimlib/util.h"
struct message_queue {
struct list_head list;
struct mutex lock;
struct condvar msg_avail_cond;
struct condvar space_avail_cond;
bool terminating;
};
struct compressor_thread_data {
struct thread thread;
struct message_queue *chunks_to_compress_queue;
struct message_queue *compressed_chunks_queue;
struct wimlib_compressor *compressor;
};
#define MAX_CHUNKS_PER_MSG 16
struct message {
u8 *uncompressed_chunks[MAX_CHUNKS_PER_MSG];
u8 *compressed_chunks[MAX_CHUNKS_PER_MSG];
u32 uncompressed_chunk_sizes[MAX_CHUNKS_PER_MSG];
u32 compressed_chunk_sizes[MAX_CHUNKS_PER_MSG];
size_t num_filled_chunks;
size_t num_alloc_chunks;
struct list_head list;
bool complete;
struct list_head submission_list;
};
struct parallel_chunk_compressor {
struct chunk_compressor base;
struct message_queue chunks_to_compress_queue;
struct message_queue compressed_chunks_queue;
struct compressor_thread_data *thread_data;
unsigned num_thread_data;
unsigned num_started_threads;
struct message *msgs;
size_t num_messages;
struct list_head available_msgs;
struct list_head submitted_msgs;
struct message *next_submit_msg;
struct message *next_ready_msg;
size_t next_chunk_idx;
};
static int
message_queue_init(struct message_queue *q)
{
if (!mutex_init(&q->lock))
goto err;
if (!condvar_init(&q->msg_avail_cond))
goto err_destroy_lock;
if (!condvar_init(&q->space_avail_cond))
goto err_destroy_msg_avail_cond;
INIT_LIST_HEAD(&q->list);
return 0;
err_destroy_msg_avail_cond:
condvar_destroy(&q->msg_avail_cond);
err_destroy_lock:
mutex_destroy(&q->lock);
err:
return WIMLIB_ERR_NOMEM;
}
static void
message_queue_destroy(struct message_queue *q)
{
if (q->list.next != NULL) {
mutex_destroy(&q->lock);
condvar_destroy(&q->msg_avail_cond);
condvar_destroy(&q->space_avail_cond);
}
}
static void
message_queue_put(struct message_queue *q, struct message *msg)
{
mutex_lock(&q->lock);
list_add_tail(&msg->list, &q->list);
condvar_signal(&q->msg_avail_cond);
mutex_unlock(&q->lock);
}
static struct message *
message_queue_get(struct message_queue *q)
{
struct message *msg;
mutex_lock(&q->lock);
while (list_empty(&q->list) && !q->terminating)
condvar_wait(&q->msg_avail_cond, &q->lock);
if (!q->terminating) {
msg = list_entry(q->list.next, struct message, list);
list_del(&msg->list);
} else
msg = NULL;
mutex_unlock(&q->lock);
return msg;
}
static void
message_queue_terminate(struct message_queue *q)
{
mutex_lock(&q->lock);
q->terminating = true;
condvar_broadcast(&q->msg_avail_cond);
mutex_unlock(&q->lock);
}
static int
init_message(struct message *msg, size_t num_chunks, u32 out_chunk_size)
{
msg->num_alloc_chunks = num_chunks;
for (size_t i = 0; i < num_chunks; i++) {
msg->compressed_chunks[i] = MALLOC(out_chunk_size - 1);
msg->uncompressed_chunks[i] = MALLOC(out_chunk_size);
if (msg->compressed_chunks[i] == NULL ||
msg->uncompressed_chunks[i] == NULL)
return WIMLIB_ERR_NOMEM;
}
return 0;
}
static void
destroy_message(struct message *msg)
{
for (size_t i = 0; i < msg->num_alloc_chunks; i++) {
FREE(msg->compressed_chunks[i]);
FREE(msg->uncompressed_chunks[i]);
}
}
static void
free_messages(struct message *msgs, size_t num_messages)
{
if (msgs) {
for (size_t i = 0; i < num_messages; i++)
destroy_message(&msgs[i]);
FREE(msgs);
}
}
static struct message *
allocate_messages(size_t count, size_t chunks_per_msg, u32 out_chunk_size)
{
struct message *msgs;
msgs = CALLOC(count, sizeof(struct message));
if (msgs == NULL)
return NULL;
for (size_t i = 0; i < count; i++) {
if (init_message(&msgs[i], chunks_per_msg, out_chunk_size)) {
free_messages(msgs, count);
return NULL;
}
}
return msgs;
}
static void
compress_chunks(struct message *msg, struct wimlib_compressor *compressor)
{
for (size_t i = 0; i < msg->num_filled_chunks; i++) {
wimlib_assert(msg->uncompressed_chunk_sizes[i] != 0);
msg->compressed_chunk_sizes[i] =
wimlib_compress(msg->uncompressed_chunks[i],
msg->uncompressed_chunk_sizes[i],
msg->compressed_chunks[i],
msg->uncompressed_chunk_sizes[i] - 1,
compressor);
}
}
static void *
compressor_thread_proc(void *arg)
{
struct compressor_thread_data *params = arg;
struct message *msg;
while ((msg = message_queue_get(params->chunks_to_compress_queue)) != NULL) {
compress_chunks(msg, params->compressor);
message_queue_put(params->compressed_chunks_queue, msg);
}
return NULL;
}
static void
parallel_chunk_compressor_destroy(struct chunk_compressor *_ctx)
{
struct parallel_chunk_compressor *ctx = (struct parallel_chunk_compressor *)_ctx;
unsigned i;
if (ctx == NULL)
return;
if (ctx->num_started_threads != 0) {
message_queue_terminate(&ctx->chunks_to_compress_queue);
for (i = 0; i < ctx->num_started_threads; i++)
thread_join(&ctx->thread_data[i].thread);
}
message_queue_destroy(&ctx->chunks_to_compress_queue);
message_queue_destroy(&ctx->compressed_chunks_queue);
if (ctx->thread_data != NULL)
for (i = 0; i < ctx->num_thread_data; i++)
wimlib_free_compressor(ctx->thread_data[i].compressor);
FREE(ctx->thread_data);
free_messages(ctx->msgs, ctx->num_messages);
FREE(ctx);
}
static void
submit_compression_msg(struct parallel_chunk_compressor *ctx)
{
struct message *msg = ctx->next_submit_msg;
msg->complete = false;
list_add_tail(&msg->submission_list, &ctx->submitted_msgs);
message_queue_put(&ctx->chunks_to_compress_queue, msg);
ctx->next_submit_msg = NULL;
}
static void *
parallel_chunk_compressor_get_chunk_buffer(struct chunk_compressor *_ctx)
{
struct parallel_chunk_compressor *ctx = (struct parallel_chunk_compressor *)_ctx;
struct message *msg;
if (ctx->next_submit_msg) {
msg = ctx->next_submit_msg;
} else {
if (list_empty(&ctx->available_msgs))
return NULL;
msg = list_entry(ctx->available_msgs.next, struct message, list);
list_del(&msg->list);
ctx->next_submit_msg = msg;
msg->num_filled_chunks = 0;
}
return msg->uncompressed_chunks[msg->num_filled_chunks];
}
static void
parallel_chunk_compressor_signal_chunk_filled(struct chunk_compressor *_ctx, u32 usize)
{
struct parallel_chunk_compressor *ctx = (struct parallel_chunk_compressor *)_ctx;
struct message *msg;
wimlib_assert(usize > 0);
wimlib_assert(usize <= ctx->base.out_chunk_size);
wimlib_assert(ctx->next_submit_msg);
msg = ctx->next_submit_msg;
msg->uncompressed_chunk_sizes[msg->num_filled_chunks] = usize;
if (++msg->num_filled_chunks == msg->num_alloc_chunks)
submit_compression_msg(ctx);
}
static bool
parallel_chunk_compressor_get_compression_result(struct chunk_compressor *_ctx,
const void **cdata_ret, u32 *csize_ret,
u32 *usize_ret)
{
struct parallel_chunk_compressor *ctx = (struct parallel_chunk_compressor *)_ctx;
struct message *msg;
if (ctx->next_submit_msg)
submit_compression_msg(ctx);
if (ctx->next_ready_msg) {
msg = ctx->next_ready_msg;
} else {
if (list_empty(&ctx->submitted_msgs))
return false;
while (!(msg = list_entry(ctx->submitted_msgs.next,
struct message,
submission_list))->complete)
message_queue_get(&ctx->compressed_chunks_queue)->complete = true;
ctx->next_ready_msg = msg;
ctx->next_chunk_idx = 0;
}
if (msg->compressed_chunk_sizes[ctx->next_chunk_idx]) {
*cdata_ret = msg->compressed_chunks[ctx->next_chunk_idx];
*csize_ret = msg->compressed_chunk_sizes[ctx->next_chunk_idx];
} else {
*cdata_ret = msg->uncompressed_chunks[ctx->next_chunk_idx];
*csize_ret = msg->uncompressed_chunk_sizes[ctx->next_chunk_idx];
}
*usize_ret = msg->uncompressed_chunk_sizes[ctx->next_chunk_idx];
if (++ctx->next_chunk_idx == msg->num_filled_chunks) {
list_del(&msg->submission_list);
list_add_tail(&msg->list, &ctx->available_msgs);
ctx->next_ready_msg = NULL;
}
return true;
}
int
new_parallel_chunk_compressor(int out_ctype, u32 out_chunk_size,
unsigned num_threads, u64 max_memory,
struct chunk_compressor **compressor_ret)
{
u64 approx_mem_required;
size_t chunks_per_msg;
size_t msgs_per_thread;
struct parallel_chunk_compressor *ctx;
unsigned i;
int ret;
unsigned desired_num_threads;
wimlib_assert(out_chunk_size > 0);
if (num_threads == 0)
num_threads = get_available_cpus();
if (num_threads == 1)
return -1;
if (max_memory == 0)
max_memory = get_available_memory();
desired_num_threads = num_threads;
if (out_chunk_size < ((u32)1 << 23)) {
/* Relatively small chunks. Use 2 messages per thread, each
* with at least 2 chunks. Use more chunks per message if there
* are lots of threads and/or the chunks are very small. */
chunks_per_msg = 2;
chunks_per_msg += num_threads * (65536 / out_chunk_size) / 16;
chunks_per_msg = max(chunks_per_msg, 2);
chunks_per_msg = min(chunks_per_msg, MAX_CHUNKS_PER_MSG);
msgs_per_thread = 2;
} else {
/* Big chunks: Just have one buffer per thread --- more would
* just waste memory. */
chunks_per_msg = 1;
msgs_per_thread = 1;
}
for (;;) {
approx_mem_required =
(u64)chunks_per_msg *
(u64)msgs_per_thread *
(u64)num_threads *
(u64)out_chunk_size
+ out_chunk_size
+ 1000000
+ num_threads * wimlib_get_compressor_needed_memory(out_ctype,
out_chunk_size,
0);
if (approx_mem_required <= max_memory)
break;
if (chunks_per_msg > 1)
chunks_per_msg--;
else if (msgs_per_thread > 1)
msgs_per_thread--;
else if (num_threads > 1)
num_threads--;
else
break;
}
if (num_threads < desired_num_threads) {
WARNING("Wanted to use %u threads, but limiting to %u "
"to fit in available memory!",
desired_num_threads, num_threads);
}
if (num_threads == 1)
return -2;
ret = WIMLIB_ERR_NOMEM;
ctx = CALLOC(1, sizeof(*ctx));
if (ctx == NULL)
goto err;
ctx->base.out_ctype = out_ctype;
ctx->base.out_chunk_size = out_chunk_size;
ctx->base.destroy = parallel_chunk_compressor_destroy;
ctx->base.get_chunk_buffer = parallel_chunk_compressor_get_chunk_buffer;
ctx->base.signal_chunk_filled = parallel_chunk_compressor_signal_chunk_filled;
ctx->base.get_compression_result = parallel_chunk_compressor_get_compression_result;
ctx->num_thread_data = num_threads;
ret = message_queue_init(&ctx->chunks_to_compress_queue);
if (ret)
goto err;
ret = message_queue_init(&ctx->compressed_chunks_queue);
if (ret)
goto err;
ret = WIMLIB_ERR_NOMEM;
ctx->thread_data = CALLOC(num_threads, sizeof(ctx->thread_data[0]));
if (ctx->thread_data == NULL)
goto err;
for (i = 0; i < num_threads; i++) {
struct compressor_thread_data *dat;
dat = &ctx->thread_data[i];
dat->chunks_to_compress_queue = &ctx->chunks_to_compress_queue;
dat->compressed_chunks_queue = &ctx->compressed_chunks_queue;
ret = wimlib_create_compressor(out_ctype, out_chunk_size,
WIMLIB_COMPRESSOR_FLAG_DESTRUCTIVE,
&dat->compressor);
if (ret)
goto err;
}
for (ctx->num_started_threads = 0;
ctx->num_started_threads < num_threads;
ctx->num_started_threads++)
{
if (!thread_create(&ctx->thread_data[ctx->num_started_threads].thread,
compressor_thread_proc,
&ctx->thread_data[ctx->num_started_threads]))
{
ret = WIMLIB_ERR_NOMEM;
if (ctx->num_started_threads >= 2)
break;
goto err;
}
}
ctx->base.num_threads = ctx->num_started_threads;
ret = WIMLIB_ERR_NOMEM;
ctx->num_messages = ctx->num_started_threads * msgs_per_thread;
ctx->msgs = allocate_messages(ctx->num_messages,
chunks_per_msg, out_chunk_size);
if (ctx->msgs == NULL)
goto err;
INIT_LIST_HEAD(&ctx->available_msgs);
for (size_t i = 0; i < ctx->num_messages; i++)
list_add_tail(&ctx->msgs[i].list, &ctx->available_msgs);
INIT_LIST_HEAD(&ctx->submitted_msgs);
*compressor_ret = &ctx->base;
return 0;
err:
parallel_chunk_compressor_destroy(&ctx->base);
return ret;
}
wimlib-1.14.5/src/decompress.c 0000644 0001750 0001750 00000005501 15137020663 013462 0 ustar 00e e /*
* decompress.c
*
* Generic functions for decompression, wrapping around actual decompression
* implementations.
*/
/*
* Copyright (C) 2013, 2014 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib.h"
#include "wimlib/decompressor_ops.h"
#include "wimlib/util.h"
struct wimlib_decompressor {
const struct decompressor_ops *ops;
size_t max_block_size;
void *private;
};
static const struct decompressor_ops * const decompressor_ops[] = {
[WIMLIB_COMPRESSION_TYPE_XPRESS] = &xpress_decompressor_ops,
[WIMLIB_COMPRESSION_TYPE_LZX] = &lzx_decompressor_ops,
[WIMLIB_COMPRESSION_TYPE_LZMS] = &lzms_decompressor_ops,
};
static bool
decompressor_ctype_valid(int ctype)
{
return (ctype >= 0 &&
ctype < ARRAY_LEN(decompressor_ops) &&
decompressor_ops[ctype] != NULL);
}
WIMLIBAPI int
wimlib_create_decompressor(enum wimlib_compression_type ctype,
size_t max_block_size,
struct wimlib_decompressor **dec_ret)
{
struct wimlib_decompressor *dec;
int ret;
ret = wimlib_global_init(0);
if (ret)
return ret;
if (!decompressor_ctype_valid(ctype))
return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
if (dec_ret == NULL)
return WIMLIB_ERR_INVALID_PARAM;
if (max_block_size == 0)
return WIMLIB_ERR_INVALID_PARAM;
dec = MALLOC(sizeof(*dec));
if (dec == NULL)
return WIMLIB_ERR_NOMEM;
dec->ops = decompressor_ops[ctype];
dec->max_block_size = max_block_size;
dec->private = NULL;
if (dec->ops->create_decompressor) {
ret = dec->ops->create_decompressor(max_block_size,
&dec->private);
if (ret) {
FREE(dec);
return ret;
}
}
*dec_ret = dec;
return 0;
}
WIMLIBAPI int
wimlib_decompress(const void *compressed_data, size_t compressed_size,
void *uncompressed_data, size_t uncompressed_size,
struct wimlib_decompressor *dec)
{
if (unlikely(uncompressed_size > dec->max_block_size))
return -2;
return dec->ops->decompress(compressed_data, compressed_size,
uncompressed_data, uncompressed_size,
dec->private);
}
WIMLIBAPI void
wimlib_free_decompressor(struct wimlib_decompressor *dec)
{
if (dec) {
if (dec->ops->free_decompressor)
dec->ops->free_decompressor(dec->private);
FREE(dec);
}
}
wimlib-1.14.5/src/registry.c 0000644 0001750 0001750 00000046567 15137020663 013207 0 ustar 00e e /*
* registry.c
*
* Extract information from Windows NT registry hives.
*/
/*
* Copyright (C) 2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include "wimlib/encoding.h"
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/registry.h"
#include "wimlib/util.h"
/* Registry hive file header */
struct regf {
#define REGF_MAGIC cpu_to_le32(0x66676572) /* "regf" */
le32 magic;
le32 f1[4];
#define REGF_MAJOR cpu_to_le32(1)
le32 major_version;
le32 minor_version;
le32 f2[2];
le32 root_key_offset; /* Offset, in hbin area, to root nk */
le32 total_hbin_size; /* Total size of all hbins */
le32 f3[1013];
u8 hbin_area[0]; /* Start of hbin area */
} __attribute__((packed));
/* Cell header */
struct cell {
/* The cell size in bytes, negated for in-use cells */
le32 size;
/* Magic characters which identify the cell type */
le16 magic;
} __attribute__((packed));
/* NK cell - represents a registry key */
struct nk {
#define NK_MAGIC cpu_to_le16(0x6B6E) /* "nk" */
struct cell base;
#define NK_COMPRESSED_NAME cpu_to_le16(0x0020)
le16 flags;
le64 unknown_0x08;
le32 unknown_0x10;
le32 parent_offset;
le32 num_subkeys;
le32 unknown_0x1C;
le32 subkey_list_offset;
le32 unknown_0x24;
le32 num_values;
le32 value_list_offset;
le32 unknown_0x30;
le32 unknown_0x34;
le16 unknown_0x38;
le16 unknown_0x3A;
le32 unknown_0x3C;
le32 unknown_0x40;
le32 unknown_0x44;
le32 unknown_0x48;
le16 name_size;
le16 unknown_0x4E;
char name[0];
} __attribute__((packed));
/* Subkey list cell. There are four types. LF, LH, and LI cells reference
* subkey NK cells directly, while RI cells reference other subkey lists. All
* contain a count followed by that many 32-bit offsets. But LF and LH cells
* contain a 32-bit hash along with each offset, while LI and RI cells only
* contain offsets. */
struct subkey_list {
#define LF_MAGIC cpu_to_le16(0x666C) /* "lf" */
#define LH_MAGIC cpu_to_le16(0x686C) /* "lh" */
#define LI_MAGIC cpu_to_le16(0x696C) /* "li" */
#define RI_MAGIC cpu_to_le16(0x6972) /* "ri" */
struct cell base;
le16 num_offsets;
le32 elements[0];
} __attribute__((packed));
/* Value list cell - contains a list of value references */
struct value_list {
le32 size;
le32 vk_offsets[0];
} __attribute__((packed));
/* VK cell - contains a value's data, or a reference to it */
struct vk {
#define VK_MAGIC cpu_to_le16(0x6B76)
struct cell base;
le16 name_size;
le32 data_size;
le32 data_offset;
#define REG_NONE cpu_to_le32(0)
#define REG_SZ cpu_to_le32(1)
#define REG_EXPAND_SZ cpu_to_le32(2)
#define REG_BINARY cpu_to_le32(3)
#define REG_DWORD cpu_to_le32(4)
#define REG_DWORD_LITTLE_ENDIAN cpu_to_le32(4)
#define REG_DWORD_BIG_ENDIAN cpu_to_le32(5)
#define REG_LINK cpu_to_le32(6)
#define REG_MULTI_SZ cpu_to_le32(7)
#define REG_RESOURCE_LIST cpu_to_le32(8)
#define REG_FULL_RESOURCE_DESCRIPTOR cpu_to_le32(9)
#define REG_RESOURCE_REQUIREMENTS_LIST cpu_to_le32(10)
#define REG_QWORD cpu_to_le32(11)
#define REG_QWORD_LITTLE_ENDIAN cpu_to_le32(11)
le32 data_type;
#define VK_COMPRESSED_NAME cpu_to_le16(0x0001)
le16 flags;
le16 unknown_0x16;
char name[0];
};
/* Data cell - contains a value's data */
struct data_cell {
le32 size;
u8 data[0];
};
/* Arbitrary limits for safety */
#define MAX_VALUES 65536
#define MAX_VALUE_SIZE 1048576
#define MAX_SUBKEYS 65536
#define MAX_SUBKEY_LIST_LEVELS 5
#define MAX_SUBKEY_LISTS 4096
static enum hive_status
translate_wimlib_error(int ret)
{
if (likely(!ret))
return HIVE_OK;
if (ret == WIMLIB_ERR_NOMEM)
return HIVE_OUT_OF_MEMORY;
return HIVE_UNSUPPORTED;
}
/* Compare a UTF-16LE name with a key or value name in the registry. The
* comparison is case insensitive. */
static inline bool
names_equal(const utf16lechar *name, size_t name_nchars,
const void *disk_name, size_t disk_name_size,
bool compressed)
{
if (compressed) {
/* ISO-8859-1 (LATIN1) on-disk */
const u8 *p = disk_name;
if (disk_name_size != name_nchars)
return false;
for (size_t i = 0; i < name_nchars; i++)
if (upcase[le16_to_cpu(name[i])] != upcase[p[i]])
return false;
return true;
} else {
/* UTF-16LE on disk */
disk_name_size /= 2;
if (disk_name_size != name_nchars)
return false;
return !cmp_utf16le_strings(name, name_nchars,
disk_name, disk_name_size, true);
}
}
/* Get a pointer to a cell, with alignment and bounds checking. Returns NULL if
* the requested information does not specify a properly aligned, sized, and
* in-use cell. */
static const void *
get_cell_pointer(const struct regf *regf, le32 offset, size_t wanted_size)
{
u32 total = le32_to_cpu(regf->total_hbin_size);
u32 offs = le32_to_cpu(offset);
const struct cell *cell;
u32 actual_size;
if ((offs > total) || (offs & 7) || (wanted_size > total - offs))
return NULL;
cell = (const struct cell *)®f->hbin_area[offs];
actual_size = -le32_to_cpu(cell->size);
if (actual_size > INT32_MAX) /* Cell unused, or size was INT32_MIN? */
return NULL;
if (wanted_size > actual_size) /* Cell too small? */
return NULL;
return cell;
}
/* Revalidate the cell with its full length. Returns true iff the cell is
* valid. */
static bool
revalidate_cell(const struct regf *regf, le32 offset, size_t wanted_size)
{
return get_cell_pointer(regf, offset, wanted_size) != NULL;
}
struct subkey_iteration_stats {
/* The number of additional levels of descendent subkey lists that may
* be visited (currently, i.e. at this point in the iteration) before
* our safety limit of MAX_SUBKEY_LIST_LEVELS is reached */
u32 levels_remaining;
/* The number of additional subkey lists that may be visited until our
* safety limit of MAX_SUBKEY_LISTS is reached */
u32 subkey_lists_remaining;
/* The number of subkeys remaining to be found. Since the number of
* subkeys is known from the parent nk cell, this should be 0 at the end
* of the iteration. */
u32 subkeys_remaining;
};
typedef enum hive_status (*subkey_cb_t)(const struct nk *, void *);
static enum hive_status
iterate_subkeys_recursive(const struct regf *regf, le32 subkey_list_offset,
subkey_cb_t cb, void *cb_ctx,
struct subkey_iteration_stats *stats)
{
const struct subkey_list *list;
unsigned num_offsets;
size_t extra_size;
unsigned increment;
size_t i = 0;
enum hive_status status;
if (stats->levels_remaining == 0 || stats->subkey_lists_remaining == 0)
return HIVE_CORRUPT;
stats->subkey_lists_remaining--;
list = get_cell_pointer(regf, subkey_list_offset,
sizeof(struct subkey_list));
if (!list)
return HIVE_CORRUPT;
num_offsets = le16_to_cpu(list->num_offsets);
extra_size = num_offsets * sizeof(list->elements[0]);
increment = 1;
if (list->base.magic == LF_MAGIC || list->base.magic == LH_MAGIC) {
/* Hashes are included */
extra_size *= 2;
increment = 2;
}
if (!revalidate_cell(regf, subkey_list_offset,
sizeof(struct subkey_list) + extra_size))
return HIVE_CORRUPT;
switch (list->base.magic) {
case LF_MAGIC:
case LH_MAGIC:
case LI_MAGIC:
/* Children are subkeys */
if (stats->subkeys_remaining < num_offsets)
return HIVE_CORRUPT;
stats->subkeys_remaining -= num_offsets;
while (num_offsets--) {
const struct nk *sub_nk;
sub_nk = get_cell_pointer(regf, list->elements[i],
sizeof(struct nk));
if (!sub_nk || sub_nk->base.magic != NK_MAGIC)
return HIVE_CORRUPT;
if (!revalidate_cell(regf, list->elements[i],
sizeof(struct nk) +
le16_to_cpu(sub_nk->name_size)))
return HIVE_CORRUPT;
status = (*cb)(sub_nk, cb_ctx);
if (status != HIVE_OK)
return status;
i += increment;
}
return HIVE_OK;
case RI_MAGIC:
/* Children are subkey lists */
status = HIVE_OK;
stats->levels_remaining--;
while (num_offsets--) {
status = iterate_subkeys_recursive(regf,
list->elements[i++],
cb, cb_ctx, stats);
if (status != HIVE_OK)
break;
}
stats->levels_remaining++;
return status;
default:
return HIVE_UNSUPPORTED;
}
}
/* Call @cb on each subkey cell of the key @nk. */
static enum hive_status
iterate_subkeys(const struct regf *regf, const struct nk *nk,
subkey_cb_t cb, void *cb_ctx)
{
u32 num_subkeys = le32_to_cpu(nk->num_subkeys);
struct subkey_iteration_stats stats;
enum hive_status status;
if (num_subkeys == 0)
return HIVE_OK;
if (num_subkeys > MAX_SUBKEYS)
return HIVE_CORRUPT;
stats.levels_remaining = MAX_SUBKEY_LIST_LEVELS;
stats.subkey_lists_remaining = MAX_SUBKEY_LISTS;
stats.subkeys_remaining = num_subkeys;
status = iterate_subkeys_recursive(regf, nk->subkey_list_offset,
cb, cb_ctx, &stats);
if (stats.subkeys_remaining != 0 && status == HIVE_OK)
status = HIVE_CORRUPT;
return status;
}
struct lookup_subkey_ctx {
const utf16lechar *key_name;
size_t key_name_nchars;
const struct nk *result;
};
static enum hive_status
lookup_subkey_cb(const struct nk *sub_nk, void *_ctx)
{
struct lookup_subkey_ctx *ctx = _ctx;
if (names_equal(ctx->key_name, ctx->key_name_nchars,
sub_nk->name, le16_to_cpu(sub_nk->name_size),
(sub_nk->flags & NK_COMPRESSED_NAME) != 0))
{
ctx->result = sub_nk;
return HIVE_ITERATION_STOPPED;
}
return HIVE_OK;
}
/*
* Given a registry key cell @nk, look up the next component of the key
* *key_namep. If found, return HIVE_OK, advance *key_namep past the key name
* component, and return the subkey cell in @sub_nk_ret. Otherwise, return
* another HIVE_* error code.
*/
static enum hive_status
lookup_subkey(const struct regf *regf, const utf16lechar **key_namep,
const struct nk *nk, const struct nk **sub_nk_ret)
{
const utf16lechar *key_name = *key_namep;
size_t key_name_nchars = 0;
struct lookup_subkey_ctx ctx;
enum hive_status status;
while (key_name[key_name_nchars] != cpu_to_le16('\0') &&
key_name[key_name_nchars] != cpu_to_le16('\\'))
key_name_nchars++;
ctx.key_name = key_name;
ctx.key_name_nchars = key_name_nchars;
ctx.result = NULL;
status = iterate_subkeys(regf, nk, lookup_subkey_cb, &ctx);
if (!ctx.result) {
if (status == HIVE_OK)
status = HIVE_KEY_NOT_FOUND;
return status;
}
key_name += key_name_nchars;
while (*key_name == cpu_to_le16('\\'))
key_name++;
*key_namep = key_name;
*sub_nk_ret = ctx.result;
return HIVE_OK;
}
/* Find the nk cell for the key named @key_name in the registry hive @regf. */
static enum hive_status
lookup_key(const struct regf *regf, const tchar *key_name,
const struct nk **nk_ret)
{
const struct nk *nk;
enum hive_status status;
const utf16lechar *key_uname, *key_unamep;
nk = get_cell_pointer(regf, regf->root_key_offset, sizeof(struct nk));
if (!nk || nk->base.magic != NK_MAGIC)
return HIVE_CORRUPT;
status = translate_wimlib_error(tstr_get_utf16le(key_name, &key_uname));
if (status != HIVE_OK)
return status;
key_unamep = key_uname;
while (*key_unamep) {
status = lookup_subkey(regf, &key_unamep, nk, &nk);
if (status != HIVE_OK)
goto out;
}
*nk_ret = nk;
status = HIVE_OK;
out:
tstr_put_utf16le(key_uname);
return status;
}
/* Find the vk cell for the value named @value_name of the key named @key_name
* in the registry hive @regf. */
static enum hive_status
lookup_value(const struct regf *regf, const tchar *key_name,
const tchar *value_name, const struct vk **vk_ret)
{
enum hive_status status;
const struct nk *nk;
size_t num_values;
const struct value_list *value_list;
const utf16lechar *value_uname;
size_t value_uname_nchars;
/* Look up the nk cell for the key. */
status = lookup_key(regf, key_name, &nk);
if (status != HIVE_OK)
return status;
num_values = le32_to_cpu(nk->num_values);
if (num_values == 0) /* No values? */
return HIVE_VALUE_NOT_FOUND;
if (num_values > MAX_VALUES)
return HIVE_CORRUPT;
value_list = get_cell_pointer(regf, nk->value_list_offset,
sizeof(struct value_list) +
(num_values *
sizeof(value_list->vk_offsets[0])));
if (!value_list)
return HIVE_CORRUPT;
/* Look for the value in the value list. */
status = translate_wimlib_error(
tstr_get_utf16le_and_len(value_name, &value_uname,
&value_uname_nchars));
if (status != HIVE_OK)
return status;
value_uname_nchars /= 2;
for (size_t i = 0; i < num_values; i++) {
const struct vk *vk;
size_t name_size;
status = HIVE_CORRUPT;
vk = get_cell_pointer(regf, value_list->vk_offsets[i],
sizeof(struct vk));
if (!vk || vk->base.magic != VK_MAGIC)
goto out;
name_size = le16_to_cpu(vk->name_size);
if (!revalidate_cell(regf, value_list->vk_offsets[i],
sizeof(struct vk) + name_size))
goto out;
if (names_equal(value_uname, value_uname_nchars,
vk->name, name_size,
(vk->flags & VK_COMPRESSED_NAME) != 0))
{
*vk_ret = vk;
status = HIVE_OK;
goto out;
}
}
status = HIVE_VALUE_NOT_FOUND;
out:
tstr_put_utf16le(value_uname);
return status;
}
/*
* Retrieve the data of the value named @value_name of the key named @key_name
* in the registry hive @regf. If the value was found, return HIVE_OK and
* return the data, its size, and its type in @data_ret, @data_size_ret, and
* @data_type_ret. Otherwise, return another HIVE_* error code.
*/
static enum hive_status
retrieve_value(const struct regf *regf, const tchar *key_name,
const tchar *value_name, void **data_ret,
size_t *data_size_ret, le32 *data_type_ret)
{
enum hive_status status;
const struct vk *vk;
size_t data_size;
bool is_inline;
const void *data;
/* Find the vk cell. */
status = lookup_value(regf, key_name, value_name, &vk);
if (status != HIVE_OK)
return status;
/* Extract the value data from the vk cell (for inline data) or from the
* data cell which it references (for non-inline data). */
data_size = le32_to_cpu(vk->data_size);
is_inline = (data_size & 0x80000000);
data_size &= 0x7FFFFFFF;
if (data_size > MAX_VALUE_SIZE)
return HIVE_CORRUPT;
if (is_inline) {
if (data_size > 4)
return HIVE_CORRUPT;
data = &vk->data_offset;
} else {
const struct data_cell *data_cell;
data_cell = get_cell_pointer(regf, vk->data_offset,
sizeof(struct data_cell));
if (!data_cell)
return HIVE_CORRUPT;
if (!revalidate_cell(regf, vk->data_offset,
sizeof(struct data_cell) + data_size))
return HIVE_UNSUPPORTED; /* Possibly a big data cell */
data = data_cell->data;
}
*data_ret = memdup(data, data_size);
if (!*data_ret)
return HIVE_OUT_OF_MEMORY;
*data_size_ret = data_size;
*data_type_ret = vk->data_type;
return HIVE_OK;
}
/* Validate the registry hive file given in memory as @hive_mem and @hive_size.
* If valid, return HIVE_OK. If invalid, return another HIVE_* error code. */
enum hive_status
hive_validate(const void *hive_mem, size_t hive_size)
{
const struct regf *regf = hive_mem;
STATIC_ASSERT(sizeof(struct regf) == 4096);
if (hive_size < sizeof(struct regf))
return HIVE_CORRUPT;
if (regf->magic != REGF_MAGIC || regf->major_version != REGF_MAJOR)
return HIVE_UNSUPPORTED;
if (le32_to_cpu(regf->total_hbin_size) > hive_size - sizeof(struct regf))
return HIVE_CORRUPT;
return HIVE_OK;
}
/* Get a string value from the registry hive file. */
enum hive_status
hive_get_string(const struct regf *regf, const tchar *key_name,
const tchar *value_name, tchar **value_ret)
{
void *data;
size_t data_size;
le32 data_type;
enum hive_status status;
/* Retrieve the raw value data. */
status = retrieve_value(regf, key_name, value_name,
&data, &data_size, &data_type);
if (status != HIVE_OK)
return status;
/* Interpret the data as a string, when possible. */
switch (data_type) {
case REG_SZ:
case REG_MULTI_SZ:
status = translate_wimlib_error(
utf16le_to_tstr(data, data_size, value_ret, &data_size));
break;
default:
status = HIVE_VALUE_IS_WRONG_TYPE;
break;
}
FREE(data);
return status;
}
/* Get a number value from the registry hive file. */
enum hive_status
hive_get_number(const struct regf *regf, const tchar *key_name,
const tchar *value_name, s64 *value_ret)
{
void *data;
size_t data_size;
le32 data_type;
enum hive_status status;
/* Retrieve the raw value data. */
status = retrieve_value(regf, key_name, value_name,
&data, &data_size, &data_type);
if (status != HIVE_OK)
return status;
/* Interpret the data as a number, when possible. */
switch (data_type) {
case REG_DWORD_LITTLE_ENDIAN:
if (data_size == 4) {
*value_ret = le32_to_cpu(*(le32 *)data);
status = HIVE_OK;
} else {
status = HIVE_CORRUPT;
}
break;
case REG_DWORD_BIG_ENDIAN:
if (data_size == 4) {
*value_ret = be32_to_cpu(*(be32 *)data);
status = HIVE_OK;
} else {
status = HIVE_CORRUPT;
}
break;
case REG_QWORD_LITTLE_ENDIAN:
if (data_size == 8) {
*value_ret = le64_to_cpu(*(le64 *)data);
status = HIVE_OK;
} else {
status = HIVE_CORRUPT;
}
break;
default:
status = HIVE_VALUE_IS_WRONG_TYPE;
break;
}
FREE(data);
return status;
}
static enum hive_status
append_subkey_name(const struct nk *sub_nk, void *_next_subkey_p)
{
size_t name_size = le16_to_cpu(sub_nk->name_size);
tchar *subkey;
tchar ***next_subkeyp = _next_subkey_p;
if (sub_nk->flags & NK_COMPRESSED_NAME) {
subkey = MALLOC((name_size + 1) * sizeof(tchar));
if (!subkey)
return HIVE_OUT_OF_MEMORY;
for (size_t i = 0; i < name_size; i++)
subkey[i] = sub_nk->name[i];
subkey[name_size] = '\0';
} else {
enum hive_status status;
status = translate_wimlib_error(
utf16le_to_tstr((utf16lechar *)sub_nk->name,
name_size, &subkey, NULL));
if (status != HIVE_OK)
return status;
}
**next_subkeyp = subkey;
++*next_subkeyp;
return HIVE_OK;
}
/* List the subkeys of the specified registry key. */
enum hive_status
hive_list_subkeys(const struct regf *regf, const tchar *key_name,
tchar ***subkeys_ret)
{
enum hive_status status;
const struct nk *nk;
tchar **subkeys;
tchar **next_subkey;
status = lookup_key(regf, key_name, &nk);
if (status != HIVE_OK)
return status;
if (le32_to_cpu(nk->num_subkeys) > MAX_SUBKEYS)
return HIVE_CORRUPT;
subkeys = CALLOC(le32_to_cpu(nk->num_subkeys) + 1, sizeof(subkeys[0]));
if (!subkeys)
return HIVE_OUT_OF_MEMORY;
next_subkey = subkeys;
status = iterate_subkeys(regf, nk, append_subkey_name, &next_subkey);
if (status == HIVE_OK)
*subkeys_ret = subkeys;
else
hive_free_subkeys_list(subkeys);
return status;
}
void
hive_free_subkeys_list(tchar **subkeys)
{
for (tchar **p = subkeys; *p; p++)
FREE(*p);
FREE(subkeys);
}
const char *
hive_status_to_string(enum hive_status status)
{
switch (status) {
case HIVE_OK:
return "HIVE_OK";
case HIVE_CORRUPT:
return "HIVE_CORRUPT";
case HIVE_UNSUPPORTED:
return "HIVE_UNSUPPORTED";
case HIVE_KEY_NOT_FOUND:
return "HIVE_KEY_NOT_FOUND";
case HIVE_VALUE_NOT_FOUND:
return "HIVE_VALUE_NOT_FOUND";
case HIVE_VALUE_IS_WRONG_TYPE:
return "HIVE_VALUE_IS_WRONG_TYPE";
case HIVE_OUT_OF_MEMORY:
return "HIVE_OUT_OF_MEMORY";
case HIVE_ITERATION_STOPPED:
return "HIVE_ITERATION_STOPPED";
}
return NULL;
}
wimlib-1.14.5/src/lzms_common.c 0000644 0001750 0001750 00000061046 15137020663 013661 0 ustar 00e e /*
* lzms_common.c - Common code for LZMS compression and decompression
*/
/*
* Copyright (C) 2013-2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/cpu_features.h"
#include "wimlib/lzms_common.h"
#include "wimlib/unaligned.h"
#ifdef __x86_64__
# include
#endif
/* Table: offset slot => offset slot base value */
const u32 lzms_offset_slot_base[LZMS_MAX_NUM_OFFSET_SYMS + 1] = {
0x00000001, 0x00000002, 0x00000003, 0x00000004,
0x00000005, 0x00000006, 0x00000007, 0x00000008,
0x00000009, 0x0000000d, 0x00000011, 0x00000015,
0x00000019, 0x0000001d, 0x00000021, 0x00000025,
0x00000029, 0x0000002d, 0x00000035, 0x0000003d,
0x00000045, 0x0000004d, 0x00000055, 0x0000005d,
0x00000065, 0x00000075, 0x00000085, 0x00000095,
0x000000a5, 0x000000b5, 0x000000c5, 0x000000d5,
0x000000e5, 0x000000f5, 0x00000105, 0x00000125,
0x00000145, 0x00000165, 0x00000185, 0x000001a5,
0x000001c5, 0x000001e5, 0x00000205, 0x00000225,
0x00000245, 0x00000265, 0x00000285, 0x000002a5,
0x000002c5, 0x000002e5, 0x00000325, 0x00000365,
0x000003a5, 0x000003e5, 0x00000425, 0x00000465,
0x000004a5, 0x000004e5, 0x00000525, 0x00000565,
0x000005a5, 0x000005e5, 0x00000625, 0x00000665,
0x000006a5, 0x00000725, 0x000007a5, 0x00000825,
0x000008a5, 0x00000925, 0x000009a5, 0x00000a25,
0x00000aa5, 0x00000b25, 0x00000ba5, 0x00000c25,
0x00000ca5, 0x00000d25, 0x00000da5, 0x00000e25,
0x00000ea5, 0x00000f25, 0x00000fa5, 0x00001025,
0x000010a5, 0x000011a5, 0x000012a5, 0x000013a5,
0x000014a5, 0x000015a5, 0x000016a5, 0x000017a5,
0x000018a5, 0x000019a5, 0x00001aa5, 0x00001ba5,
0x00001ca5, 0x00001da5, 0x00001ea5, 0x00001fa5,
0x000020a5, 0x000021a5, 0x000022a5, 0x000023a5,
0x000024a5, 0x000026a5, 0x000028a5, 0x00002aa5,
0x00002ca5, 0x00002ea5, 0x000030a5, 0x000032a5,
0x000034a5, 0x000036a5, 0x000038a5, 0x00003aa5,
0x00003ca5, 0x00003ea5, 0x000040a5, 0x000042a5,
0x000044a5, 0x000046a5, 0x000048a5, 0x00004aa5,
0x00004ca5, 0x00004ea5, 0x000050a5, 0x000052a5,
0x000054a5, 0x000056a5, 0x000058a5, 0x00005aa5,
0x00005ca5, 0x00005ea5, 0x000060a5, 0x000064a5,
0x000068a5, 0x00006ca5, 0x000070a5, 0x000074a5,
0x000078a5, 0x00007ca5, 0x000080a5, 0x000084a5,
0x000088a5, 0x00008ca5, 0x000090a5, 0x000094a5,
0x000098a5, 0x00009ca5, 0x0000a0a5, 0x0000a4a5,
0x0000a8a5, 0x0000aca5, 0x0000b0a5, 0x0000b4a5,
0x0000b8a5, 0x0000bca5, 0x0000c0a5, 0x0000c4a5,
0x0000c8a5, 0x0000cca5, 0x0000d0a5, 0x0000d4a5,
0x0000d8a5, 0x0000dca5, 0x0000e0a5, 0x0000e4a5,
0x0000eca5, 0x0000f4a5, 0x0000fca5, 0x000104a5,
0x00010ca5, 0x000114a5, 0x00011ca5, 0x000124a5,
0x00012ca5, 0x000134a5, 0x00013ca5, 0x000144a5,
0x00014ca5, 0x000154a5, 0x00015ca5, 0x000164a5,
0x00016ca5, 0x000174a5, 0x00017ca5, 0x000184a5,
0x00018ca5, 0x000194a5, 0x00019ca5, 0x0001a4a5,
0x0001aca5, 0x0001b4a5, 0x0001bca5, 0x0001c4a5,
0x0001cca5, 0x0001d4a5, 0x0001dca5, 0x0001e4a5,
0x0001eca5, 0x0001f4a5, 0x0001fca5, 0x000204a5,
0x00020ca5, 0x000214a5, 0x00021ca5, 0x000224a5,
0x000234a5, 0x000244a5, 0x000254a5, 0x000264a5,
0x000274a5, 0x000284a5, 0x000294a5, 0x0002a4a5,
0x0002b4a5, 0x0002c4a5, 0x0002d4a5, 0x0002e4a5,
0x0002f4a5, 0x000304a5, 0x000314a5, 0x000324a5,
0x000334a5, 0x000344a5, 0x000354a5, 0x000364a5,
0x000374a5, 0x000384a5, 0x000394a5, 0x0003a4a5,
0x0003b4a5, 0x0003c4a5, 0x0003d4a5, 0x0003e4a5,
0x0003f4a5, 0x000404a5, 0x000414a5, 0x000424a5,
0x000434a5, 0x000444a5, 0x000454a5, 0x000464a5,
0x000474a5, 0x000484a5, 0x000494a5, 0x0004a4a5,
0x0004b4a5, 0x0004c4a5, 0x0004e4a5, 0x000504a5,
0x000524a5, 0x000544a5, 0x000564a5, 0x000584a5,
0x0005a4a5, 0x0005c4a5, 0x0005e4a5, 0x000604a5,
0x000624a5, 0x000644a5, 0x000664a5, 0x000684a5,
0x0006a4a5, 0x0006c4a5, 0x0006e4a5, 0x000704a5,
0x000724a5, 0x000744a5, 0x000764a5, 0x000784a5,
0x0007a4a5, 0x0007c4a5, 0x0007e4a5, 0x000804a5,
0x000824a5, 0x000844a5, 0x000864a5, 0x000884a5,
0x0008a4a5, 0x0008c4a5, 0x0008e4a5, 0x000904a5,
0x000924a5, 0x000944a5, 0x000964a5, 0x000984a5,
0x0009a4a5, 0x0009c4a5, 0x0009e4a5, 0x000a04a5,
0x000a24a5, 0x000a44a5, 0x000a64a5, 0x000aa4a5,
0x000ae4a5, 0x000b24a5, 0x000b64a5, 0x000ba4a5,
0x000be4a5, 0x000c24a5, 0x000c64a5, 0x000ca4a5,
0x000ce4a5, 0x000d24a5, 0x000d64a5, 0x000da4a5,
0x000de4a5, 0x000e24a5, 0x000e64a5, 0x000ea4a5,
0x000ee4a5, 0x000f24a5, 0x000f64a5, 0x000fa4a5,
0x000fe4a5, 0x001024a5, 0x001064a5, 0x0010a4a5,
0x0010e4a5, 0x001124a5, 0x001164a5, 0x0011a4a5,
0x0011e4a5, 0x001224a5, 0x001264a5, 0x0012a4a5,
0x0012e4a5, 0x001324a5, 0x001364a5, 0x0013a4a5,
0x0013e4a5, 0x001424a5, 0x001464a5, 0x0014a4a5,
0x0014e4a5, 0x001524a5, 0x001564a5, 0x0015a4a5,
0x0015e4a5, 0x001624a5, 0x001664a5, 0x0016a4a5,
0x0016e4a5, 0x001724a5, 0x001764a5, 0x0017a4a5,
0x0017e4a5, 0x001824a5, 0x001864a5, 0x0018a4a5,
0x0018e4a5, 0x001924a5, 0x001964a5, 0x0019e4a5,
0x001a64a5, 0x001ae4a5, 0x001b64a5, 0x001be4a5,
0x001c64a5, 0x001ce4a5, 0x001d64a5, 0x001de4a5,
0x001e64a5, 0x001ee4a5, 0x001f64a5, 0x001fe4a5,
0x002064a5, 0x0020e4a5, 0x002164a5, 0x0021e4a5,
0x002264a5, 0x0022e4a5, 0x002364a5, 0x0023e4a5,
0x002464a5, 0x0024e4a5, 0x002564a5, 0x0025e4a5,
0x002664a5, 0x0026e4a5, 0x002764a5, 0x0027e4a5,
0x002864a5, 0x0028e4a5, 0x002964a5, 0x0029e4a5,
0x002a64a5, 0x002ae4a5, 0x002b64a5, 0x002be4a5,
0x002c64a5, 0x002ce4a5, 0x002d64a5, 0x002de4a5,
0x002e64a5, 0x002ee4a5, 0x002f64a5, 0x002fe4a5,
0x003064a5, 0x0030e4a5, 0x003164a5, 0x0031e4a5,
0x003264a5, 0x0032e4a5, 0x003364a5, 0x0033e4a5,
0x003464a5, 0x0034e4a5, 0x003564a5, 0x0035e4a5,
0x003664a5, 0x0036e4a5, 0x003764a5, 0x0037e4a5,
0x003864a5, 0x0038e4a5, 0x003964a5, 0x0039e4a5,
0x003a64a5, 0x003ae4a5, 0x003b64a5, 0x003be4a5,
0x003c64a5, 0x003ce4a5, 0x003d64a5, 0x003de4a5,
0x003ee4a5, 0x003fe4a5, 0x0040e4a5, 0x0041e4a5,
0x0042e4a5, 0x0043e4a5, 0x0044e4a5, 0x0045e4a5,
0x0046e4a5, 0x0047e4a5, 0x0048e4a5, 0x0049e4a5,
0x004ae4a5, 0x004be4a5, 0x004ce4a5, 0x004de4a5,
0x004ee4a5, 0x004fe4a5, 0x0050e4a5, 0x0051e4a5,
0x0052e4a5, 0x0053e4a5, 0x0054e4a5, 0x0055e4a5,
0x0056e4a5, 0x0057e4a5, 0x0058e4a5, 0x0059e4a5,
0x005ae4a5, 0x005be4a5, 0x005ce4a5, 0x005de4a5,
0x005ee4a5, 0x005fe4a5, 0x0060e4a5, 0x0061e4a5,
0x0062e4a5, 0x0063e4a5, 0x0064e4a5, 0x0065e4a5,
0x0066e4a5, 0x0067e4a5, 0x0068e4a5, 0x0069e4a5,
0x006ae4a5, 0x006be4a5, 0x006ce4a5, 0x006de4a5,
0x006ee4a5, 0x006fe4a5, 0x0070e4a5, 0x0071e4a5,
0x0072e4a5, 0x0073e4a5, 0x0074e4a5, 0x0075e4a5,
0x0076e4a5, 0x0077e4a5, 0x0078e4a5, 0x0079e4a5,
0x007ae4a5, 0x007be4a5, 0x007ce4a5, 0x007de4a5,
0x007ee4a5, 0x007fe4a5, 0x0080e4a5, 0x0081e4a5,
0x0082e4a5, 0x0083e4a5, 0x0084e4a5, 0x0085e4a5,
0x0086e4a5, 0x0087e4a5, 0x0088e4a5, 0x0089e4a5,
0x008ae4a5, 0x008be4a5, 0x008ce4a5, 0x008de4a5,
0x008fe4a5, 0x0091e4a5, 0x0093e4a5, 0x0095e4a5,
0x0097e4a5, 0x0099e4a5, 0x009be4a5, 0x009de4a5,
0x009fe4a5, 0x00a1e4a5, 0x00a3e4a5, 0x00a5e4a5,
0x00a7e4a5, 0x00a9e4a5, 0x00abe4a5, 0x00ade4a5,
0x00afe4a5, 0x00b1e4a5, 0x00b3e4a5, 0x00b5e4a5,
0x00b7e4a5, 0x00b9e4a5, 0x00bbe4a5, 0x00bde4a5,
0x00bfe4a5, 0x00c1e4a5, 0x00c3e4a5, 0x00c5e4a5,
0x00c7e4a5, 0x00c9e4a5, 0x00cbe4a5, 0x00cde4a5,
0x00cfe4a5, 0x00d1e4a5, 0x00d3e4a5, 0x00d5e4a5,
0x00d7e4a5, 0x00d9e4a5, 0x00dbe4a5, 0x00dde4a5,
0x00dfe4a5, 0x00e1e4a5, 0x00e3e4a5, 0x00e5e4a5,
0x00e7e4a5, 0x00e9e4a5, 0x00ebe4a5, 0x00ede4a5,
0x00efe4a5, 0x00f1e4a5, 0x00f3e4a5, 0x00f5e4a5,
0x00f7e4a5, 0x00f9e4a5, 0x00fbe4a5, 0x00fde4a5,
0x00ffe4a5, 0x0101e4a5, 0x0103e4a5, 0x0105e4a5,
0x0107e4a5, 0x0109e4a5, 0x010be4a5, 0x010de4a5,
0x010fe4a5, 0x0111e4a5, 0x0113e4a5, 0x0115e4a5,
0x0117e4a5, 0x0119e4a5, 0x011be4a5, 0x011de4a5,
0x011fe4a5, 0x0121e4a5, 0x0123e4a5, 0x0125e4a5,
0x0127e4a5, 0x0129e4a5, 0x012be4a5, 0x012de4a5,
0x012fe4a5, 0x0131e4a5, 0x0133e4a5, 0x0135e4a5,
0x0137e4a5, 0x013be4a5, 0x013fe4a5, 0x0143e4a5,
0x0147e4a5, 0x014be4a5, 0x014fe4a5, 0x0153e4a5,
0x0157e4a5, 0x015be4a5, 0x015fe4a5, 0x0163e4a5,
0x0167e4a5, 0x016be4a5, 0x016fe4a5, 0x0173e4a5,
0x0177e4a5, 0x017be4a5, 0x017fe4a5, 0x0183e4a5,
0x0187e4a5, 0x018be4a5, 0x018fe4a5, 0x0193e4a5,
0x0197e4a5, 0x019be4a5, 0x019fe4a5, 0x01a3e4a5,
0x01a7e4a5, 0x01abe4a5, 0x01afe4a5, 0x01b3e4a5,
0x01b7e4a5, 0x01bbe4a5, 0x01bfe4a5, 0x01c3e4a5,
0x01c7e4a5, 0x01cbe4a5, 0x01cfe4a5, 0x01d3e4a5,
0x01d7e4a5, 0x01dbe4a5, 0x01dfe4a5, 0x01e3e4a5,
0x01e7e4a5, 0x01ebe4a5, 0x01efe4a5, 0x01f3e4a5,
0x01f7e4a5, 0x01fbe4a5, 0x01ffe4a5, 0x0203e4a5,
0x0207e4a5, 0x020be4a5, 0x020fe4a5, 0x0213e4a5,
0x0217e4a5, 0x021be4a5, 0x021fe4a5, 0x0223e4a5,
0x0227e4a5, 0x022be4a5, 0x022fe4a5, 0x0233e4a5,
0x0237e4a5, 0x023be4a5, 0x023fe4a5, 0x0243e4a5,
0x0247e4a5, 0x024be4a5, 0x024fe4a5, 0x0253e4a5,
0x0257e4a5, 0x025be4a5, 0x025fe4a5, 0x0263e4a5,
0x0267e4a5, 0x026be4a5, 0x026fe4a5, 0x0273e4a5,
0x0277e4a5, 0x027be4a5, 0x027fe4a5, 0x0283e4a5,
0x0287e4a5, 0x028be4a5, 0x028fe4a5, 0x0293e4a5,
0x0297e4a5, 0x029be4a5, 0x029fe4a5, 0x02a3e4a5,
0x02a7e4a5, 0x02abe4a5, 0x02afe4a5, 0x02b3e4a5,
0x02bbe4a5, 0x02c3e4a5, 0x02cbe4a5, 0x02d3e4a5,
0x02dbe4a5, 0x02e3e4a5, 0x02ebe4a5, 0x02f3e4a5,
0x02fbe4a5, 0x0303e4a5, 0x030be4a5, 0x0313e4a5,
0x031be4a5, 0x0323e4a5, 0x032be4a5, 0x0333e4a5,
0x033be4a5, 0x0343e4a5, 0x034be4a5, 0x0353e4a5,
0x035be4a5, 0x0363e4a5, 0x036be4a5, 0x0373e4a5,
0x037be4a5, 0x0383e4a5, 0x038be4a5, 0x0393e4a5,
0x039be4a5, 0x03a3e4a5, 0x03abe4a5, 0x03b3e4a5,
0x03bbe4a5, 0x03c3e4a5, 0x03cbe4a5, 0x03d3e4a5,
0x03dbe4a5, 0x03e3e4a5, 0x03ebe4a5, 0x03f3e4a5,
0x03fbe4a5, 0x0403e4a5, 0x040be4a5, 0x0413e4a5,
0x041be4a5, 0x0423e4a5, 0x042be4a5, 0x0433e4a5,
0x043be4a5, 0x0443e4a5, 0x044be4a5, 0x0453e4a5,
0x045be4a5, 0x0463e4a5, 0x046be4a5, 0x0473e4a5,
0x047be4a5, 0x0483e4a5, 0x048be4a5, 0x0493e4a5,
0x049be4a5, 0x04a3e4a5, 0x04abe4a5, 0x04b3e4a5,
0x04bbe4a5, 0x04c3e4a5, 0x04cbe4a5, 0x04d3e4a5,
0x04dbe4a5, 0x04e3e4a5, 0x04ebe4a5, 0x04f3e4a5,
0x04fbe4a5, 0x0503e4a5, 0x050be4a5, 0x0513e4a5,
0x051be4a5, 0x0523e4a5, 0x052be4a5, 0x0533e4a5,
0x053be4a5, 0x0543e4a5, 0x054be4a5, 0x0553e4a5,
0x055be4a5, 0x0563e4a5, 0x056be4a5, 0x0573e4a5,
0x057be4a5, 0x0583e4a5, 0x058be4a5, 0x0593e4a5,
0x059be4a5, 0x05a3e4a5, 0x05abe4a5, 0x05b3e4a5,
0x05bbe4a5, 0x05c3e4a5, 0x05cbe4a5, 0x05d3e4a5,
0x05dbe4a5, 0x05e3e4a5, 0x05ebe4a5, 0x05f3e4a5,
0x05fbe4a5, 0x060be4a5, 0x061be4a5, 0x062be4a5,
0x063be4a5, 0x064be4a5, 0x065be4a5, 0x465be4a5,
/* The last entry is extra; it is equal to LZMS_MAX_MATCH_OFFSET + 1 and
* is here to aid binary search. */
};
/* Table: offset slot => number of extra offset bits */
const u8 lzms_extra_offset_bits[LZMS_MAX_NUM_OFFSET_SYMS] = {
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4,
4 , 4 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5,
5 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6,
7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7,
7 , 7 , 7 , 7 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8,
8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9,
9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9,
9 , 9 , 9 , 9 , 9 , 9 , 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 30,
};
/* Table: length slot => length slot base value */
const u32 lzms_length_slot_base[LZMS_NUM_LENGTH_SYMS + 1] = {
0x00000001, 0x00000002, 0x00000003, 0x00000004,
0x00000005, 0x00000006, 0x00000007, 0x00000008,
0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
0x0000000d, 0x0000000e, 0x0000000f, 0x00000010,
0x00000011, 0x00000012, 0x00000013, 0x00000014,
0x00000015, 0x00000016, 0x00000017, 0x00000018,
0x00000019, 0x0000001a, 0x0000001b, 0x0000001d,
0x0000001f, 0x00000021, 0x00000023, 0x00000027,
0x0000002b, 0x0000002f, 0x00000033, 0x00000037,
0x0000003b, 0x00000043, 0x0000004b, 0x00000053,
0x0000005b, 0x0000006b, 0x0000007b, 0x0000008b,
0x0000009b, 0x000000ab, 0x000000cb, 0x000000eb,
0x0000012b, 0x000001ab, 0x000002ab, 0x000004ab,
0x000008ab, 0x000108ab, 0x400108ab,
/* The last entry is extra; it is equal to LZMS_MAX_MATCH_LENGTH + 1 and
* is here to aid binary search. */
};
/* Table: length slot => number of extra length bits */
const u8 lzms_extra_length_bits[LZMS_NUM_LENGTH_SYMS] = {
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 1 , 1 , 1 , 1 , 2 , 2 ,
2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 ,
4 , 4 , 4 , 4 , 4 , 5 , 5 , 6 ,
7 , 8 , 9 , 10, 16, 30,
};
unsigned
lzms_get_slot(u32 value, const u32 slot_base_tab[], unsigned num_slots)
{
unsigned l = 0;
unsigned r = num_slots - 1;
for (;;) {
unsigned slot = (l + r) / 2;
if (value >= slot_base_tab[slot]) {
if (value < slot_base_tab[slot + 1])
return slot;
else
l = slot + 1;
} else {
r = slot - 1;
}
}
}
/* Return the number of offset slots used when processing a buffer having the
* specified uncompressed size. */
unsigned
lzms_get_num_offset_slots(size_t uncompressed_size)
{
if (uncompressed_size < 2)
return 0;
return 1 + lzms_get_offset_slot(uncompressed_size - 1);
}
void
lzms_init_probabilities(struct lzms_probabilites *probs)
{
struct lzms_probability_entry *entries =
(struct lzms_probability_entry *)probs;
size_t num_entries = sizeof(struct lzms_probabilites) /
sizeof(struct lzms_probability_entry);
for (size_t i = 0; i < num_entries; i++) {
entries[i].num_recent_zero_bits = LZMS_INITIAL_PROBABILITY;
entries[i].recent_bits = LZMS_INITIAL_RECENT_BITS;
}
}
void
lzms_init_symbol_frequencies(u32 freqs[], unsigned num_syms)
{
for (unsigned sym = 0; sym < num_syms; sym++)
freqs[sym] = 1;
}
void
lzms_dilute_symbol_frequencies(u32 freqs[], unsigned num_syms)
{
for (unsigned sym = 0; sym < num_syms; sym++)
freqs[sym] = (freqs[sym] >> 1) + 1;
}
#ifdef __x86_64__
static forceinline u8 *
find_next_opcode_sse4_2(u8 *p)
{
const __v16qi potential_opcodes = (__v16qi) {0x48, 0x4C, 0xE8, 0xE9, 0xF0, 0xFF};
__asm__(
" pcmpestri $0x0, (%[p]), %[potential_opcodes] \n"
" jc 2f \n"
"1: \n"
" add $0x10, %[p] \n"
" pcmpestri $0x0, (%[p]), %[potential_opcodes] \n"
" jnc 1b \n"
"2: \n"
#ifdef __ILP32__ /* x32 ABI (x86_64 with 32-bit pointers) */
" add %%ecx, %[p] \n"
#else
" add %%rcx, %[p] \n"
#endif
: [p] "+r" (p)
: [potential_opcodes] "x" (potential_opcodes), "a" (6), "d" (16)
: "rcx", "cc"
);
return p;
}
#endif /* __x86_64__ */
static forceinline u8 *
find_next_opcode_default(u8 *p)
{
/*
* The following table is used to accelerate the common case where the
* byte has nothing to do with x86 translation and must simply be
* skipped. This was faster than the following alternatives:
* - Jump table with 256 entries
* - Switch statement with default
*/
static const u8 is_potential_opcode[256] = {
[0x48] = 1, [0x4C] = 1, [0xE8] = 1,
[0xE9] = 1, [0xF0] = 1, [0xFF] = 1,
};
for (;;) {
if (is_potential_opcode[*p])
break;
p++;
if (is_potential_opcode[*p])
break;
p++;
if (is_potential_opcode[*p])
break;
p++;
if (is_potential_opcode[*p])
break;
p++;
}
return p;
}
static forceinline u8 *
translate_if_needed(u8 *data, u8 *p, s32 *last_x86_pos,
s32 last_target_usages[], bool undo)
{
s32 max_trans_offset;
s32 opcode_nbytes;
u16 target16;
s32 i;
max_trans_offset = LZMS_X86_MAX_TRANSLATION_OFFSET;
/*
* p[0] has one of the following values:
* 0x48 0x4C 0xE8 0xE9 0xF0 0xFF
*/
if (p[0] >= 0xF0) {
if (p[0] & 0x0F) {
/* 0xFF (instruction group) */
if (p[1] == 0x15) {
/* Call indirect relative */
opcode_nbytes = 2;
goto have_opcode;
}
} else {
/* 0xF0 (lock prefix) */
if (p[1] == 0x83 && p[2] == 0x05) {
/* Lock add relative */
opcode_nbytes = 3;
goto have_opcode;
}
}
} else if (p[0] <= 0x4C) {
/* 0x48 or 0x4C. In 64-bit code this is a REX prefix byte with
* W=1, R=[01], X=0, and B=0, and it will be followed by the
* actual opcode, then additional bytes depending on the opcode.
* We are most interested in several common instructions that
* access data relative to the instruction pointer. These use a
* 1-byte opcode, followed by a ModR/M byte, followed by a
* 4-byte displacement. */
/* Test: does the ModR/M byte indicate RIP-relative addressing?
* Note: there seems to be a mistake in the format here; the
* mask really should be 0xC7 instead of 0x07 so that both the
* MOD and R/M fields of ModR/M are tested, not just R/M. */
if ((p[2] & 0x07) == 0x05) {
/* Check for the LEA (load effective address) or MOV
* (move) opcodes. For MOV there are additional
* restrictions, although it seems they are only helpful
* due to the overly lax ModR/M test. */
if (p[1] == 0x8D ||
(p[1] == 0x8B && !(p[0] & 0x04) && !(p[2] & 0xF0)))
{
opcode_nbytes = 3;
goto have_opcode;
}
}
} else {
if (p[0] & 0x01) {
/* 0xE9: Jump relative. Theoretically this would be
* useful to translate, but in fact it's explicitly
* excluded. Most likely it creates too many false
* positives for the detection algorithm. */
p += 4;
} else {
/* 0xE8: Call relative. This is a common case, so it
* uses a reduced max_trans_offset. In other words, we
* have to be more confident that the data actually is
* x86 machine code before we'll do the translation. */
opcode_nbytes = 1;
max_trans_offset >>= 1;
goto have_opcode;
}
}
return p + 1;
have_opcode:
i = p - data;
p += opcode_nbytes;
if (undo) {
if (i - *last_x86_pos <= max_trans_offset) {
u32 n = get_unaligned_le32(p);
put_unaligned_le32(n - i, p);
}
target16 = i + get_unaligned_le16(p);
} else {
target16 = i + get_unaligned_le16(p);
if (i - *last_x86_pos <= max_trans_offset) {
u32 n = get_unaligned_le32(p);
put_unaligned_le32(n + i, p);
}
}
i += opcode_nbytes + sizeof(le32) - 1;
if (i - last_target_usages[target16] <= LZMS_X86_ID_WINDOW_SIZE)
*last_x86_pos = i;
last_target_usages[target16] = i;
return p + sizeof(le32);
}
/*
* Translate relative addresses embedded in x86 instructions into absolute
* addresses (@undo == %false), or undo this translation (@undo == %true).
*
* Absolute addresses are usually more compressible by LZ factorization.
*
* @last_target_usages must be a temporary array of length >= 65536.
*/
void
lzms_x86_filter(u8 data[restrict], s32 size,
s32 last_target_usages[restrict], bool undo)
{
/*
* Note: this filter runs unconditionally and uses a custom algorithm to
* detect data regions that probably contain x86 code.
*
* 'last_x86_pos' tracks the most recent position that has a good chance
* of being the start of an x86 instruction. When the filter detects a
* likely x86 instruction, it updates this variable and considers the
* next LZMS_X86_MAX_TRANSLATION_OFFSET bytes of data as valid for x86
* translations.
*
* If part of the data does not, in fact, contain x86 machine code, then
* 'last_x86_pos' will, very likely, eventually fall more than
* LZMS_X86_MAX_TRANSLATION_OFFSET bytes behind the current position.
* This results in x86 translations being disabled until the next likely
* x86 instruction is detected.
*
* To identify "likely x86 instructions", the algorithm attempts to
* track the position of the most recent potential relative-addressing
* instruction that referenced each possible memory address. If it
* finds two references to the same memory address within an
* LZMS_X86_ID_WINDOW_SIZE-byte sized window, then the second reference
* is flagged as a likely x86 instruction. Since the instructions
* considered for translation necessarily use relative addressing, the
* algorithm does a tentative translation into absolute addresses. In
* addition, so that memory addresses can be looked up in an array of
* reasonable size (in this code, 'last_target_usages'), only the
* low-order 2 bytes of each address are considered significant.
*/
u8 *p;
u8 *tail_ptr;
s32 last_x86_pos = -LZMS_X86_MAX_TRANSLATION_OFFSET - 1;
if (size <= 17)
return;
for (s32 i = 0; i < 65536; i++)
last_target_usages[i] = -(s32)LZMS_X86_ID_WINDOW_SIZE - 1;
/*
* Optimization: only check for end-of-buffer when we already have a
* byte that is a potential opcode for x86 translation. To do this,
* overwrite one of the bytes near the end of the buffer, and restore it
* later. The correctness of this optimization relies on two
* characteristics of compressed format:
*
* 1. No translation can follow an opcode beginning in the last 16
* bytes.
* 2. A translation following an opcode starting at the last possible
* position (17 bytes from the end) never extends more than 7 bytes.
* Consequently, we can overwrite any of the bytes starting at
* data[(size - 16) + 7] and have no effect on the result, as long
* as we restore those bytes later.
*/
/* Note: the very first byte must be ignored completely! */
p = data + 1;
tail_ptr = &data[size - 16];
#ifdef __x86_64__
if (cpu_features & X86_CPU_FEATURE_SSE4_2) {
u8 saved_byte = *tail_ptr;
*tail_ptr = 0xE8;
for (;;) {
u8 *new_p = find_next_opcode_sse4_2(p);
if (new_p >= tail_ptr - 8)
break;
p = new_p;
p = translate_if_needed(data, p, &last_x86_pos,
last_target_usages, undo);
}
*tail_ptr = saved_byte;
}
#endif
{
u8 saved_byte = *(tail_ptr + 8);
*(tail_ptr + 8) = 0xE8;
for (;;) {
p = find_next_opcode_default(p);
if (p >= tail_ptr)
break;
p = translate_if_needed(data, p, &last_x86_pos,
last_target_usages, undo);
}
*(tail_ptr + 8) = saved_byte;
}
}
wimlib-1.14.5/src/export_image.c 0000644 0001750 0001750 00000021023 15137020663 013776 0 ustar 00e e /*
* export_image.c
*/
/*
* Copyright (C) 2012-2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib.h"
#include "wimlib/blob_table.h"
#include "wimlib/error.h"
#include "wimlib/inode.h"
#include "wimlib/metadata.h"
#include "wimlib/xml.h"
static int
blob_set_not_exported(struct blob_descriptor *blob, void *_ignore)
{
blob->out_refcnt = 0;
blob->was_exported = 0;
return 0;
}
static int
blob_rollback_export(struct blob_descriptor *blob, void *_blob_table)
{
struct blob_table *blob_table = _blob_table;
blob->refcnt -= blob->out_refcnt;
if (blob->was_exported) {
blob_table_unlink(blob_table, blob);
free_blob_descriptor(blob);
}
return 0;
}
static int
inode_export_blobs(struct wim_inode *inode, struct blob_table *src_blob_table,
struct blob_table *dest_blob_table, bool gift)
{
unsigned i;
const u8 *hash;
struct blob_descriptor *src_blob, *dest_blob;
for (i = 0; i < inode->i_num_streams; i++) {
/* Retrieve SHA-1 message digest of blob to export. */
hash = stream_hash(&inode->i_streams[i]);
if (is_zero_hash(hash)) /* Empty stream? */
continue;
/* Search for the blob (via SHA-1 message digest) in the
* destination WIM. */
dest_blob = lookup_blob(dest_blob_table, hash);
if (!dest_blob) {
/* Blob not yet present in destination WIM. Search for
* it in the source WIM, then export it into the
* destination WIM. */
src_blob = stream_blob(&inode->i_streams[i],
src_blob_table);
if (!src_blob)
return blob_not_found_error(inode, hash);
if (gift) {
dest_blob = src_blob;
blob_table_unlink(src_blob_table, src_blob);
} else {
dest_blob = clone_blob_descriptor(src_blob);
if (!dest_blob)
return WIMLIB_ERR_NOMEM;
}
dest_blob->refcnt = 0;
dest_blob->out_refcnt = 0;
dest_blob->was_exported = 1;
blob_table_insert(dest_blob_table, dest_blob);
}
/* Blob is present in destination WIM (either pre-existing,
* already exported, or just exported above). Increment its
* reference count appropriately. Note: we use 'refcnt' for
* the raw reference count, but 'out_refcnt' for references
* arising just from the export operation; this is used to roll
* back a failed export if needed. */
dest_blob->refcnt += inode->i_nlink;
dest_blob->out_refcnt += inode->i_nlink;
}
return 0;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_export_image(WIMStruct *src_wim,
int src_image,
WIMStruct *dest_wim,
const tchar *dest_name,
const tchar *dest_description,
int export_flags)
{
int ret;
int start_src_image;
int end_src_image;
int orig_dest_image_count;
int image;
bool all_images = (src_image == WIMLIB_ALL_IMAGES);
/* Check for sane parameters. */
if (export_flags & ~(WIMLIB_EXPORT_FLAG_BOOT |
WIMLIB_EXPORT_FLAG_NO_NAMES |
WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS |
WIMLIB_EXPORT_FLAG_GIFT |
WIMLIB_EXPORT_FLAG_WIMBOOT))
return WIMLIB_ERR_INVALID_PARAM;
if (!src_wim || !dest_wim)
return WIMLIB_ERR_INVALID_PARAM;
if (!wim_has_metadata(src_wim) || !wim_has_metadata(dest_wim))
return WIMLIB_ERR_METADATA_NOT_FOUND;
if (all_images) {
/* Multi-image export. */
if ((!(export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES) &&
dest_name) ||
(!(export_flags & WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS) &&
dest_description))
{
ERROR("Image name and description must be "
"left NULL for multi-image export");
return WIMLIB_ERR_INVALID_PARAM;
}
start_src_image = 1;
end_src_image = src_wim->hdr.image_count;
} else {
start_src_image = src_image;
end_src_image = src_image;
}
orig_dest_image_count = dest_wim->hdr.image_count;
/* We don't yet support having a single WIMStruct contain duplicate
* 'image_metadata' structures, so we must forbid this from happening.
* A duplication is possible if 'src_wim == dest_wim', if the same image
* is exported to the same destination WIMStruct multiple times, or if
* an image is exported in an A => B => A manner. */
for (src_image = start_src_image;
src_image <= end_src_image; src_image++)
{
const struct wim_image_metadata *src_imd =
src_wim->image_metadata[src_image - 1];
for (int i = 0; i < dest_wim->hdr.image_count; i++)
if (dest_wim->image_metadata[i] == src_imd)
return WIMLIB_ERR_DUPLICATE_EXPORTED_IMAGE;
}
/* Blob checksums must be known before proceeding. */
ret = wim_checksum_unhashed_blobs(src_wim);
if (ret)
return ret;
ret = wim_checksum_unhashed_blobs(dest_wim);
if (ret)
return ret;
/* Enable rollbacks */
for_blob_in_table(dest_wim->blob_table, blob_set_not_exported, NULL);
/* Forbid exports where the destination WIM already contains image(s)
* with the requested name(s). However, allow multi-image exports where
* there is a duplication among the source names only. */
if (!(export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES)) {
for (src_image = start_src_image;
src_image <= end_src_image;
src_image++)
{
const tchar *name = dest_name ? dest_name :
wimlib_get_image_name(src_wim, src_image);
if (wimlib_image_name_in_use(dest_wim, name)) {
ERROR("There is already an image named \"%"TS"\" "
"in the destination WIM", name);
ret = WIMLIB_ERR_IMAGE_NAME_COLLISION;
goto out_rollback;
}
}
}
/* Export each requested image. */
for (src_image = start_src_image;
src_image <= end_src_image;
src_image++)
{
const tchar *next_dest_name, *next_dest_description;
struct wim_image_metadata *src_imd;
struct wim_inode *inode;
/* Determine destination image name and description. */
if (export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES)
next_dest_name = NULL;
else if (dest_name)
next_dest_name = dest_name;
else
next_dest_name = wimlib_get_image_name(src_wim, src_image);
if (export_flags & WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS)
next_dest_description = NULL;
else if (dest_description)
next_dest_description = dest_description;
else
next_dest_description = wimlib_get_image_description(src_wim, src_image);
/* Load metadata for source image into memory. */
ret = select_wim_image(src_wim, src_image);
if (ret)
goto out_rollback;
src_imd = wim_get_current_image_metadata(src_wim);
/* Iterate through inodes in the source image and export their
* blobs into the destination WIM. */
image_for_each_inode(inode, src_imd) {
ret = inode_export_blobs(inode,
src_wim->blob_table,
dest_wim->blob_table,
export_flags & WIMLIB_EXPORT_FLAG_GIFT);
if (ret)
goto out_rollback;
}
/* Export XML information into the destination WIM. */
ret = xml_export_image(src_wim->xml_info, src_image,
dest_wim->xml_info, next_dest_name,
next_dest_description,
export_flags & WIMLIB_EXPORT_FLAG_WIMBOOT);
if (ret)
goto out_rollback;
/* Reference the source image metadata from the destination WIM.
*/
ret = append_image_metadata(dest_wim, src_imd);
if (ret)
goto out_rollback;
src_imd->refcnt++;
}
/* Image export complete. Finish by setting any needed special metadata
* on the destination WIM. */
if (src_wim->hdr.flags & WIM_HDR_FLAG_RP_FIX)
dest_wim->hdr.flags |= WIM_HDR_FLAG_RP_FIX;
for (src_image = start_src_image;
src_image <= end_src_image;
src_image++)
{
int dst_image = orig_dest_image_count + 1 +
(src_image - start_src_image);
if ((export_flags & WIMLIB_EXPORT_FLAG_BOOT) &&
(!all_images || src_image == src_wim->hdr.boot_idx))
dest_wim->hdr.boot_idx = dst_image;
}
return 0;
out_rollback:
while ((image = xml_get_image_count(dest_wim->xml_info))
> orig_dest_image_count)
{
xml_delete_image(dest_wim->xml_info, image);
}
while (dest_wim->hdr.image_count > orig_dest_image_count)
{
put_image_metadata(dest_wim->image_metadata[
--dest_wim->hdr.image_count]);
}
for_blob_in_table(dest_wim->blob_table, blob_rollback_export,
dest_wim->blob_table);
return ret;
}
wimlib-1.14.5/src/error.c 0000644 0001750 0001750 00000025757 15137020663 012466 0 ustar 00e e /*
* error.c - logging and error code translation
*/
/*
* Copyright (C) 2012, 2013, 2014 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
/* Make sure the POSIX-compatible strerror_r() is declared, rather than the GNU
* version, which has a different return type. */
#ifdef _GNU_SOURCE
# define GNU_SOURCE_WAS_DEFINED
# undef _GNU_SOURCE
# ifndef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 200112L
# endif
#endif
#include
#ifdef GNU_SOURCE_WAS_DEFINED
# define _GNU_SOURCE
#endif
#include
#include
#include "wimlib.h"
#include "wimlib/error.h"
#include "wimlib/test_support.h"
#include "wimlib/util.h"
#include "wimlib/win32.h"
bool wimlib_print_errors = false;
FILE *wimlib_error_file = NULL; /* Set in wimlib_global_init() */
static bool wimlib_owns_error_file = false;
static void
wimlib_vmsg(const tchar *tag, const tchar *format, va_list va, bool perror)
{
if (!wimlib_print_errors)
return;
int errno_save = errno;
fflush(stdout);
tfputs(tag, wimlib_error_file);
tvfprintf(wimlib_error_file, format, va);
if (perror && errno_save != 0) {
tchar buf[64];
int res;
res = tstrerror_r(errno_save, buf, ARRAY_LEN(buf));
if (res) {
tsprintf(buf,
T("unknown error (errno=%d)"),
errno_save);
}
#ifdef _WIN32
if (errno_save == EBUSY)
tstrcpy(buf, T("Resource busy"));
#endif
tfprintf(wimlib_error_file, T(": %"TS), buf);
}
tputc(T('\n'), wimlib_error_file);
fflush(wimlib_error_file);
errno = errno_save;
}
void
wimlib_error(const tchar *format, ...)
{
va_list va;
va_start(va, format);
wimlib_vmsg(T("\r[ERROR] "), format, va, false);
va_end(va);
}
void
wimlib_error_with_errno(const tchar *format, ...)
{
va_list va;
va_start(va, format);
wimlib_vmsg(T("\r[ERROR] "), format, va, true);
va_end(va);
}
void
wimlib_warning(const tchar *format, ...)
{
va_list va;
va_start(va, format);
wimlib_vmsg(T("\r[WARNING] "), format, va, false);
va_end(va);
}
void
wimlib_warning_with_errno(const tchar *format, ...)
{
va_list va;
va_start(va, format);
wimlib_vmsg(T("\r[WARNING] "), format, va, true);
va_end(va);
}
void
print_byte_field(const u8 *field, size_t len, FILE *out)
{
while (len--)
tfprintf(out, T("%02hhx"), *field++);
}
WIMLIBAPI int
wimlib_set_print_errors(bool show_error_messages)
{
wimlib_print_errors = show_error_messages;
return 0;
}
WIMLIBAPI int
wimlib_set_error_file(FILE *fp)
{
if (wimlib_owns_error_file)
fclose(wimlib_error_file);
wimlib_error_file = fp;
wimlib_print_errors = (fp != NULL);
wimlib_owns_error_file = false;
return 0;
}
WIMLIBAPI int
wimlib_set_error_file_by_name(const tchar *path)
{
FILE *fp;
#ifdef _WIN32
fp = win32_open_logfile(path);
#else
fp = fopen(path, "a");
#endif
if (!fp)
return WIMLIB_ERR_OPEN;
wimlib_set_error_file(fp);
wimlib_owns_error_file = true;
return 0;
}
static const tchar * const error_strings[] = {
[WIMLIB_ERR_SUCCESS]
= T("Success"),
[WIMLIB_ERR_ALREADY_LOCKED]
= T("The WIM is already locked for writing"),
[WIMLIB_ERR_DECOMPRESSION]
= T("The WIM contains invalid compressed data"),
[WIMLIB_ERR_FUSE]
= T("An error was returned by fuse_main()"),
[WIMLIB_ERR_GLOB_HAD_NO_MATCHES]
= T("The provided file glob did not match any files"),
[WIMLIB_ERR_IMAGE_COUNT]
= T("Inconsistent image count among the metadata "
"resources, the WIM header, and/or the XML data"),
[WIMLIB_ERR_IMAGE_NAME_COLLISION]
= T("Tried to add an image with a name that is already in use"),
[WIMLIB_ERR_INSUFFICIENT_PRIVILEGES]
= T("The user does not have sufficient privileges"),
[WIMLIB_ERR_INTEGRITY]
= T("The WIM file is corrupted (failed integrity check)"),
[WIMLIB_ERR_INVALID_CAPTURE_CONFIG]
= T("The contents of the capture configuration file were invalid"),
[WIMLIB_ERR_INVALID_CHUNK_SIZE]
= T("The compression chunk size was unrecognized"),
[WIMLIB_ERR_INVALID_COMPRESSION_TYPE]
= T("The compression type was unrecognized"),
[WIMLIB_ERR_INVALID_HEADER]
= T("The WIM header was invalid"),
[WIMLIB_ERR_INVALID_IMAGE]
= T("Tried to select an image that does not exist in the WIM"),
[WIMLIB_ERR_INVALID_INTEGRITY_TABLE]
= T("The WIM's integrity table is invalid"),
[WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY]
= T("An entry in the WIM's lookup table is invalid"),
[WIMLIB_ERR_INVALID_METADATA_RESOURCE]
= T("The metadata resource is invalid"),
[WIMLIB_ERR_INVALID_OVERLAY]
= T("Conflicting files in overlay when creating a WIM image"),
[WIMLIB_ERR_INVALID_PARAM]
= T("An invalid parameter was given"),
[WIMLIB_ERR_INVALID_PART_NUMBER]
= T("The part number or total parts of the WIM is invalid"),
[WIMLIB_ERR_INVALID_PIPABLE_WIM]
= T("The pipable WIM is invalid"),
[WIMLIB_ERR_INVALID_REPARSE_DATA]
= T("The reparse data of a reparse point was invalid"),
[WIMLIB_ERR_INVALID_RESOURCE_HASH]
= T("The SHA-1 message digest of a WIM resource did not match the expected value"),
[WIMLIB_ERR_INVALID_UTF8_STRING]
= T("A string was not a valid UTF-8 string"),
[WIMLIB_ERR_INVALID_UTF16_STRING]
= T("A string was not a valid UTF-16 string"),
[WIMLIB_ERR_IS_DIRECTORY]
= T("One of the specified paths to delete was a directory"),
[WIMLIB_ERR_IS_SPLIT_WIM]
= T("The WIM is part of a split WIM, which is not supported for this operation"),
[WIMLIB_ERR_LINK]
= T("Failed to create a hard or symbolic link when extracting "
"a file from the WIM"),
[WIMLIB_ERR_METADATA_NOT_FOUND]
= T("The WIM does not contain image metadata; it only contains file data"),
[WIMLIB_ERR_MKDIR]
= T("Failed to create a directory"),
[WIMLIB_ERR_MQUEUE]
= T("Failed to create or use a POSIX message queue"),
[WIMLIB_ERR_NOMEM]
= T("Ran out of memory"),
[WIMLIB_ERR_NOTDIR]
= T("Expected a directory"),
[WIMLIB_ERR_NOTEMPTY]
= T("Directory was not empty"),
[WIMLIB_ERR_NOT_A_REGULAR_FILE]
= T("One of the specified paths to extract did not "
"correspond to a regular file"),
[WIMLIB_ERR_NOT_A_WIM_FILE]
= T("The file did not begin with the magic characters that "
"identify a WIM file"),
[WIMLIB_ERR_NO_FILENAME]
= T("The WIM is not identified with a filename"),
[WIMLIB_ERR_NOT_PIPABLE]
= T("The WIM was not captured such that it can be "
"applied from a pipe"),
[WIMLIB_ERR_NTFS_3G]
= T("NTFS-3G encountered an error (check errno)"),
[WIMLIB_ERR_OPEN]
= T("Failed to open a file"),
[WIMLIB_ERR_OPENDIR]
= T("Failed to open a directory"),
[WIMLIB_ERR_PATH_DOES_NOT_EXIST]
= T("The path does not exist in the WIM image"),
[WIMLIB_ERR_READ]
= T("Could not read data from a file"),
[WIMLIB_ERR_READLINK]
= T("Could not read the target of a symbolic link"),
[WIMLIB_ERR_RENAME]
= T("Could not rename a file"),
[WIMLIB_ERR_REPARSE_POINT_FIXUP_FAILED]
= T("Unable to complete reparse point fixup"),
[WIMLIB_ERR_RESOURCE_NOT_FOUND]
= T("A file resource needed to complete the operation was missing from the WIM"),
[WIMLIB_ERR_RESOURCE_ORDER]
= T("The components of the WIM were arranged in an unexpected order"),
[WIMLIB_ERR_SET_ATTRIBUTES]
= T("Failed to set attributes on extracted file"),
[WIMLIB_ERR_SET_REPARSE_DATA]
= T("Failed to set reparse data on extracted file"),
[WIMLIB_ERR_SET_SECURITY]
= T("Failed to set file owner, group, or other permissions on extracted file"),
[WIMLIB_ERR_SET_SHORT_NAME]
= T("Failed to set short name on extracted file"),
[WIMLIB_ERR_SET_TIMESTAMPS]
= T("Failed to set timestamps on extracted file"),
[WIMLIB_ERR_SPLIT_INVALID]
= T("The WIM is part of an invalid split WIM"),
[WIMLIB_ERR_STAT]
= T("Could not read the metadata for a file or directory"),
[WIMLIB_ERR_UNEXPECTED_END_OF_FILE]
= T("Unexpectedly reached the end of the file"),
[WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE]
= T("A Unicode string could not be represented in the current locale's encoding"),
[WIMLIB_ERR_UNKNOWN_VERSION]
= T("The WIM file is marked with an unknown version number"),
[WIMLIB_ERR_UNSUPPORTED]
= T("The requested operation is unsupported"),
[WIMLIB_ERR_UNSUPPORTED_FILE]
= T("A file in the directory tree to archive was not of a supported type"),
[WIMLIB_ERR_WIM_IS_READONLY]
= T("The WIM is read-only (file permissions, header flag, or split WIM)"),
[WIMLIB_ERR_WRITE]
= T("Failed to write data to a file"),
[WIMLIB_ERR_XML]
= T("The XML data of the WIM is invalid"),
[WIMLIB_ERR_WIM_IS_ENCRYPTED]
= T("The WIM file (or parts of it) is encrypted"),
[WIMLIB_ERR_WIMBOOT]
= T("Failed to set WIMBoot pointer data"),
[WIMLIB_ERR_ABORTED_BY_PROGRESS]
= T("The operation was aborted by the library user"),
[WIMLIB_ERR_UNKNOWN_PROGRESS_STATUS]
= T("The user-provided progress function returned an unrecognized value"),
[WIMLIB_ERR_MKNOD]
= T("Unable to create a special file (e.g. device node or socket)"),
[WIMLIB_ERR_MOUNTED_IMAGE_IS_BUSY]
= T("There are still files open on the mounted WIM image"),
[WIMLIB_ERR_NOT_A_MOUNTPOINT]
= T("There is not a WIM image mounted on the directory"),
[WIMLIB_ERR_NOT_PERMITTED_TO_UNMOUNT]
= T("The current user does not have permission to unmount the WIM image"),
[WIMLIB_ERR_FVE_LOCKED_VOLUME]
= T("The volume must be unlocked before it can be used"),
[WIMLIB_ERR_UNABLE_TO_READ_CAPTURE_CONFIG]
= T("The capture configuration file could not be read"),
[WIMLIB_ERR_WIM_IS_INCOMPLETE]
= T("The WIM file is incomplete"),
[WIMLIB_ERR_COMPACTION_NOT_POSSIBLE]
= T("The WIM file cannot be compacted because of its format, "
"its layout, or the write parameters specified by the user"),
[WIMLIB_ERR_IMAGE_HAS_MULTIPLE_REFERENCES]
= T("The WIM image cannot be modified because it is currently "
"referenced from multiple places"),
[WIMLIB_ERR_DUPLICATE_EXPORTED_IMAGE]
= T("The destination WIM already contains one of the source images"),
[WIMLIB_ERR_CONCURRENT_MODIFICATION_DETECTED]
= T("A file being added to a WIM image was concurrently modified"),
[WIMLIB_ERR_SNAPSHOT_FAILURE]
= T("Unable to create a filesystem snapshot"),
[WIMLIB_ERR_INVALID_XATTR]
= T("An extended attribute entry in the WIM image is invalid"),
[WIMLIB_ERR_SET_XATTR]
= T("Failed to set an extended attribute on an extracted file"),
#ifdef ENABLE_TEST_SUPPORT
[WIMLIB_ERR_IMAGES_ARE_DIFFERENT]
= T("A difference was detected between the two images being compared"),
#endif
};
WIMLIBAPI const tchar *
wimlib_get_error_string(enum wimlib_error_code _code)
{
unsigned int code = (unsigned int)_code;
if (code >= ARRAY_LEN(error_strings) || error_strings[code] == NULL)
return T("Unknown error");
return error_strings[code];
}
wimlib-1.14.5/src/lzx_common.c 0000644 0001750 0001750 00000023557 15137020663 013516 0 ustar 00e e /*
* lzx_common.c - Common code for LZX compression and decompression.
*/
/*
* Copyright (C) 2012-2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#ifdef __SSE2__
# include
#endif
#ifdef __AVX2__
# include
#endif
#include "wimlib/bitops.h"
#include "wimlib/endianness.h"
#include "wimlib/lzx_common.h"
#include "wimlib/unaligned.h"
#include "wimlib/util.h"
/* Mapping: offset slot => first match offset that uses that offset slot.
* The offset slots for repeat offsets map to "fake" offsets < 1. */
const s32 lzx_offset_slot_base[LZX_MAX_OFFSET_SLOTS + 1] = {
-2 , -1 , 0 , 1 , 2 , /* 0 --- 4 */
4 , 6 , 10 , 14 , 22 , /* 5 --- 9 */
30 , 46 , 62 , 94 , 126 , /* 10 --- 14 */
190 , 254 , 382 , 510 , 766 , /* 15 --- 19 */
1022 , 1534 , 2046 , 3070 , 4094 , /* 20 --- 24 */
6142 , 8190 , 12286 , 16382 , 24574 , /* 25 --- 29 */
32766 , 49150 , 65534 , 98302 , 131070 , /* 30 --- 34 */
196606 , 262142 , 393214 , 524286 , 655358 , /* 35 --- 39 */
786430 , 917502 , 1048574, 1179646, 1310718, /* 40 --- 44 */
1441790, 1572862, 1703934, 1835006, 1966078, /* 45 --- 49 */
2097150 /* extra */
};
/* Mapping: offset slot => how many extra bits must be read and added to the
* corresponding offset slot base to decode the match offset. */
const u8 lzx_extra_offset_bits[LZX_MAX_OFFSET_SLOTS] = {
0 , 0 , 0 , 0 , 1 ,
1 , 2 , 2 , 3 , 3 ,
4 , 4 , 5 , 5 , 6 ,
6 , 7 , 7 , 8 , 8 ,
9 , 9 , 10, 10, 11,
11, 12, 12, 13, 13,
14, 14, 15, 15, 16,
16, 17, 17, 17, 17,
17, 17, 17, 17, 17,
17, 17, 17, 17, 17,
};
/* Round the specified buffer size up to the next valid LZX window size, and
* return its order (log2). Or, if the buffer size is 0 or greater than the
* largest valid LZX window size, return 0. */
unsigned
lzx_get_window_order(size_t max_bufsize)
{
if (max_bufsize == 0 || max_bufsize > LZX_MAX_WINDOW_SIZE)
return 0;
return max(ilog2_ceil(max_bufsize), LZX_MIN_WINDOW_ORDER);
}
/* Given a valid LZX window order, return the number of symbols that will exist
* in the main Huffman code. */
unsigned
lzx_get_num_main_syms(unsigned window_order)
{
/* Note: one would expect that the maximum match offset would be
* 'window_size - LZX_MIN_MATCH_LEN', which would occur if the first two
* bytes were to match the last two bytes. However, the format
* disallows this case. This reduces the number of needed offset slots
* by 1. */
u32 window_size = (u32)1 << window_order;
u32 max_offset = window_size - LZX_MIN_MATCH_LEN - 1;
unsigned num_offset_slots = 30;
while (max_offset >= lzx_offset_slot_base[num_offset_slots])
num_offset_slots++;
return LZX_NUM_CHARS + (num_offset_slots * LZX_NUM_LEN_HEADERS);
}
static void
do_translate_target(void *target, s32 input_pos)
{
s32 abs_offset, rel_offset;
rel_offset = get_unaligned_le32(target);
if (rel_offset >= -input_pos && rel_offset < LZX_WIM_MAGIC_FILESIZE) {
if (rel_offset < LZX_WIM_MAGIC_FILESIZE - input_pos) {
/* "good translation" */
abs_offset = rel_offset + input_pos;
} else {
/* "compensating translation" */
abs_offset = rel_offset - LZX_WIM_MAGIC_FILESIZE;
}
put_unaligned_le32(abs_offset, target);
}
}
static void
undo_translate_target(void *target, s32 input_pos)
{
s32 abs_offset, rel_offset;
abs_offset = get_unaligned_le32(target);
if (abs_offset >= 0) {
if (abs_offset < LZX_WIM_MAGIC_FILESIZE) {
/* "good translation" */
rel_offset = abs_offset - input_pos;
put_unaligned_le32(rel_offset, target);
}
} else {
if (abs_offset >= -input_pos) {
/* "compensating translation" */
rel_offset = abs_offset + LZX_WIM_MAGIC_FILESIZE;
put_unaligned_le32(rel_offset, target);
}
}
}
/*
* Do or undo the 'E8' preprocessing used in LZX. Before compression, the
* uncompressed data is preprocessed by changing the targets of x86 CALL
* instructions from relative offsets to absolute offsets. After decompression,
* the translation is undone by changing the targets of x86 CALL instructions
* from absolute offsets to relative offsets.
*
* Note that despite its intent, E8 preprocessing can be done on any data even
* if it is not actually x86 machine code. In fact, E8 preprocessing appears to
* always be used in LZX-compressed resources in WIM files; there is no bit to
* indicate whether it is used or not, unlike in the LZX compressed format as
* used in cabinet files, where a bit is reserved for that purpose.
*
* E8 preprocessing is disabled in the last 6 bytes of the uncompressed data,
* which really means the 5-byte call instruction cannot start in the last 10
* bytes of the uncompressed data. This is one of the errors in the LZX
* documentation.
*
* E8 preprocessing does not appear to be disabled after the 32768th chunk of a
* WIM resource, which apparently is another difference from the LZX compression
* used in cabinet files.
*
* E8 processing is supposed to take the file size as a parameter, as it is used
* in calculating the translated jump targets. But in WIM files, this file size
* is always the same (LZX_WIM_MAGIC_FILESIZE == 12000000).
*/
static void
lzx_e8_filter(u8 *data, u32 size, void (*process_target)(void *, s32))
{
#if !defined(__SSE2__) && !defined(__AVX2__)
/*
* A worthwhile optimization is to push the end-of-buffer check into the
* relatively rare E8 case. This is possible if we replace the last six
* bytes of data with E8 bytes; then we are guaranteed to hit an E8 byte
* before reaching end-of-buffer. In addition, this scheme guarantees
* that no translation can begin following an E8 byte in the last 10
* bytes because a 4-byte offset containing E8 as its high byte is a
* large negative number that is not valid for translation. That is
* exactly what we need.
*/
u8 *tail;
u8 saved_bytes[6];
u8 *p;
if (size <= 10)
return;
tail = &data[size - 6];
memcpy(saved_bytes, tail, 6);
memset(tail, 0xE8, 6);
p = data;
for (;;) {
while (*p != 0xE8)
p++;
if (p >= tail)
break;
(*process_target)(p + 1, p - data);
p += 5;
}
memcpy(tail, saved_bytes, 6);
#else
/* SSE2 or AVX-2 optimized version for x86_64 */
u8 *p = data;
u64 valid_mask = ~0;
if (size <= 10)
return;
#ifdef __AVX2__
# define ALIGNMENT_REQUIRED 32
#else
# define ALIGNMENT_REQUIRED 16
#endif
/* Process one byte at a time until the pointer is properly aligned. */
while ((uintptr_t)p % ALIGNMENT_REQUIRED != 0) {
if (p >= data + size - 10)
return;
if (*p == 0xE8 && (valid_mask & 1)) {
(*process_target)(p + 1, p - data);
valid_mask &= ~0x1F;
}
p++;
valid_mask >>= 1;
valid_mask |= (u64)1 << 63;
}
if (data + size - p >= 64) {
/* Vectorized processing */
/* Note: we use a "trap" E8 byte to eliminate the need to check
* for end-of-buffer in the inner loop. This byte is carefully
* positioned so that it will never be changed by a previous
* translation before it is detected. */
u8 *trap = p + ((data + size - p) & ~31) - 32 + 4;
u8 saved_byte = *trap;
*trap = 0xE8;
for (;;) {
u32 e8_mask;
u8 *orig_p = p;
#ifdef __AVX2__
const __m256i e8_bytes = _mm256_set1_epi8(0xE8);
for (;;) {
__m256i bytes = *(const __m256i *)p;
__m256i cmpresult = _mm256_cmpeq_epi8(bytes, e8_bytes);
e8_mask = _mm256_movemask_epi8(cmpresult);
if (e8_mask)
break;
p += 32;
}
#else
const __m128i e8_bytes = _mm_set1_epi8(0xE8);
for (;;) {
/* Read the next 32 bytes of data and test them
* for E8 bytes. */
__m128i bytes1 = *(const __m128i *)p;
__m128i bytes2 = *(const __m128i *)(p + 16);
__m128i cmpresult1 = _mm_cmpeq_epi8(bytes1, e8_bytes);
__m128i cmpresult2 = _mm_cmpeq_epi8(bytes2, e8_bytes);
u32 mask1 = _mm_movemask_epi8(cmpresult1);
u32 mask2 = _mm_movemask_epi8(cmpresult2);
/* The masks have a bit set for each E8 byte.
* We stay in this fast inner loop as long as
* there are no E8 bytes. */
if (mask1 | mask2) {
e8_mask = mask1 | (mask2 << 16);
break;
}
p += 32;
}
#endif
/* Did we pass over data with no E8 bytes? */
if (p != orig_p)
valid_mask = ~0;
/* Are we nearing end-of-buffer? */
if (p == trap - 4)
break;
/* Process the E8 bytes. However, the AND with
* 'valid_mask' ensures we never process an E8 byte that
* was itself part of a translation target. */
while ((e8_mask &= valid_mask)) {
unsigned bit = bsf32(e8_mask);
(*process_target)(p + bit + 1, p + bit - data);
valid_mask &= ~((u64)0x1F << bit);
}
valid_mask >>= 32;
valid_mask |= 0xFFFFFFFF00000000;
p += 32;
}
*trap = saved_byte;
}
/* Approaching the end of the buffer; process one byte a time. */
while (p < data + size - 10) {
if (*p == 0xE8 && (valid_mask & 1)) {
(*process_target)(p + 1, p - data);
valid_mask &= ~0x1F;
}
p++;
valid_mask >>= 1;
valid_mask |= (u64)1 << 63;
}
#endif /* __SSE2__ || __AVX2__ */
}
void
lzx_preprocess(u8 *data, u32 size)
{
lzx_e8_filter(data, size, do_translate_target);
}
void
lzx_postprocess(u8 *data, u32 size)
{
lzx_e8_filter(data, size, undo_translate_target);
}
wimlib-1.14.5/src/write.c 0000644 0001750 0001750 00000320776 15137020663 012466 0 ustar 00e e /*
* write.c
*
* Support for writing WIM files; write a WIM file, overwrite a WIM file, write
* compressed file resources, etc.
*/
/*
* Copyright (C) 2012-2016 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK)
/* On BSD, this should be included before "wimlib/list.h" so that "wimlib/list.h" can
* override the LIST_HEAD macro. */
# include
#endif
#include
#include
#include
#include
#include "wimlib/alloca.h"
#include "wimlib/assert.h"
#include "wimlib/blob_table.h"
#include "wimlib/chunk_compressor.h"
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/file_io.h"
#include "wimlib/header.h"
#include "wimlib/inode.h"
#include "wimlib/integrity.h"
#include "wimlib/metadata.h"
#include "wimlib/paths.h"
#include "wimlib/progress.h"
#include "wimlib/resource.h"
#include "wimlib/solid.h"
#include "wimlib/win32.h" /* win32_rename_replacement() */
#include "wimlib/write.h"
#include "wimlib/xml.h"
/* wimlib internal flags used when writing resources. */
#define WRITE_RESOURCE_FLAG_RECOMPRESS 0x00000001
#define WRITE_RESOURCE_FLAG_PIPABLE 0x00000002
#define WRITE_RESOURCE_FLAG_SOLID 0x00000004
#define WRITE_RESOURCE_FLAG_SEND_DONE_WITH_FILE 0x00000008
#define WRITE_RESOURCE_FLAG_SOLID_SORT 0x00000010
static int
write_flags_to_resource_flags(int write_flags)
{
int write_resource_flags = 0;
if (write_flags & WIMLIB_WRITE_FLAG_RECOMPRESS)
write_resource_flags |= WRITE_RESOURCE_FLAG_RECOMPRESS;
if (write_flags & WIMLIB_WRITE_FLAG_PIPABLE)
write_resource_flags |= WRITE_RESOURCE_FLAG_PIPABLE;
if (write_flags & WIMLIB_WRITE_FLAG_SOLID)
write_resource_flags |= WRITE_RESOURCE_FLAG_SOLID;
if (write_flags & WIMLIB_WRITE_FLAG_SEND_DONE_WITH_FILE_MESSAGES)
write_resource_flags |= WRITE_RESOURCE_FLAG_SEND_DONE_WITH_FILE;
if ((write_flags & (WIMLIB_WRITE_FLAG_SOLID |
WIMLIB_WRITE_FLAG_NO_SOLID_SORT)) ==
WIMLIB_WRITE_FLAG_SOLID)
write_resource_flags |= WRITE_RESOURCE_FLAG_SOLID_SORT;
return write_resource_flags;
}
struct filter_context {
int write_flags;
WIMStruct *wim;
};
/*
* Determine whether the specified blob should be filtered out from the write.
*
* Return values:
*
* < 0 : The blob should be hard-filtered; that is, not included in the output
* WIM file at all.
* 0 : The blob should not be filtered out.
* > 0 : The blob should be soft-filtered; that is, it already exists in the
* WIM file and may not need to be written again.
*/
static int
blob_filtered(const struct blob_descriptor *blob,
const struct filter_context *ctx)
{
int write_flags;
WIMStruct *wim;
if (ctx == NULL)
return 0;
write_flags = ctx->write_flags;
wim = ctx->wim;
if (write_flags & WIMLIB_WRITE_FLAG_APPEND &&
blob->blob_location == BLOB_IN_WIM &&
blob->rdesc->wim == wim)
return 1;
if (write_flags & WIMLIB_WRITE_FLAG_SKIP_EXTERNAL_WIMS &&
blob->blob_location == BLOB_IN_WIM &&
blob->rdesc->wim != wim)
return -1;
return 0;
}
static bool
blob_hard_filtered(const struct blob_descriptor *blob,
struct filter_context *ctx)
{
return blob_filtered(blob, ctx) < 0;
}
static inline bool
may_soft_filter_blobs(const struct filter_context *ctx)
{
return ctx && (ctx->write_flags & WIMLIB_WRITE_FLAG_APPEND);
}
static inline bool
may_hard_filter_blobs(const struct filter_context *ctx)
{
return ctx && (ctx->write_flags & WIMLIB_WRITE_FLAG_SKIP_EXTERNAL_WIMS);
}
static inline bool
may_filter_blobs(const struct filter_context *ctx)
{
return (may_soft_filter_blobs(ctx) || may_hard_filter_blobs(ctx));
}
/* Return true if the specified blob is located in a WIM resource which can be
* reused in the output WIM file, without being recompressed. */
static bool
can_raw_copy(const struct blob_descriptor *blob, int write_resource_flags,
int out_ctype, u32 out_chunk_size)
{
const struct wim_resource_descriptor *rdesc;
/* Recompress everything if requested. */
if (write_resource_flags & WRITE_RESOURCE_FLAG_RECOMPRESS)
return false;
/* A blob not located in a WIM resource cannot be reused. */
if (blob->blob_location != BLOB_IN_WIM)
return false;
rdesc = blob->rdesc;
/* In the case of an in-place compaction, always reuse resources located
* in the WIM being compacted. */
if (rdesc->wim->being_compacted)
return true;
/* Otherwise, only reuse compressed resources. */
if (out_ctype == WIMLIB_COMPRESSION_TYPE_NONE ||
!(rdesc->flags & (WIM_RESHDR_FLAG_COMPRESSED |
WIM_RESHDR_FLAG_SOLID)))
return false;
/* When writing a pipable WIM, we can only reuse pipable resources; and
* when writing a non-pipable WIM, we can only reuse non-pipable
* resources. */
if (rdesc->is_pipable !=
!!(write_resource_flags & WRITE_RESOURCE_FLAG_PIPABLE))
return false;
/* When writing a solid WIM, we can only reuse solid resources; and when
* writing a non-solid WIM, we can only reuse non-solid resources. */
if (!!(rdesc->flags & WIM_RESHDR_FLAG_SOLID) !=
!!(write_resource_flags & WRITE_RESOURCE_FLAG_SOLID))
return false;
/* Note: it is theoretically possible to copy chunks of compressed data
* between non-solid, solid, and pipable resources. However, we don't
* currently implement this optimization because it would be complex and
* would usually go unused. */
if (rdesc->flags & WIM_RESHDR_FLAG_COMPRESSED) {
/* To re-use a non-solid resource, it must use the desired
* compression type and chunk size. */
return (rdesc->compression_type == out_ctype &&
rdesc->chunk_size == out_chunk_size);
} else {
/* Solid resource: Such resources may contain multiple blobs,
* and in general only a subset of them need to be written. As
* a heuristic, re-use the raw data if more than two-thirds the
* uncompressed size is being written. */
/* Note: solid resources contain a header that specifies the
* compression type and chunk size; therefore we don't need to
* check if they are compatible with @out_ctype and
* @out_chunk_size. */
/* Did we already decide to reuse the resource? */
if (rdesc->raw_copy_ok)
return true;
struct blob_descriptor *res_blob;
u64 write_size = 0;
list_for_each_entry(res_blob, &rdesc->blob_list, rdesc_node)
if (res_blob->will_be_in_output_wim)
write_size += res_blob->size;
return (write_size > rdesc->uncompressed_size * 2 / 3);
}
}
static u32
reshdr_flags_for_blob(const struct blob_descriptor *blob)
{
u32 reshdr_flags = 0;
if (blob->is_metadata)
reshdr_flags |= WIM_RESHDR_FLAG_METADATA;
return reshdr_flags;
}
static void
blob_set_out_reshdr_for_reuse(struct blob_descriptor *blob)
{
const struct wim_resource_descriptor *rdesc;
wimlib_assert(blob->blob_location == BLOB_IN_WIM);
rdesc = blob->rdesc;
if (rdesc->flags & WIM_RESHDR_FLAG_SOLID) {
blob->out_reshdr.offset_in_wim = blob->offset_in_res;
blob->out_reshdr.uncompressed_size = 0;
blob->out_reshdr.size_in_wim = blob->size;
blob->out_res_offset_in_wim = rdesc->offset_in_wim;
blob->out_res_size_in_wim = rdesc->size_in_wim;
blob->out_res_uncompressed_size = rdesc->uncompressed_size;
} else {
blob->out_reshdr.offset_in_wim = rdesc->offset_in_wim;
blob->out_reshdr.uncompressed_size = rdesc->uncompressed_size;
blob->out_reshdr.size_in_wim = rdesc->size_in_wim;
}
blob->out_reshdr.flags = rdesc->flags;
}
/* Write the header for a blob in a pipable WIM. */
static int
write_pwm_blob_header(const struct blob_descriptor *blob,
struct filedes *out_fd, bool compressed)
{
struct pwm_blob_hdr blob_hdr;
u32 reshdr_flags;
int ret;
wimlib_assert(!blob->unhashed);
blob_hdr.magic = cpu_to_le64(PWM_BLOB_MAGIC);
blob_hdr.uncompressed_size = cpu_to_le64(blob->size);
copy_hash(blob_hdr.hash, blob->hash);
reshdr_flags = reshdr_flags_for_blob(blob);
if (compressed)
reshdr_flags |= WIM_RESHDR_FLAG_COMPRESSED;
blob_hdr.flags = cpu_to_le32(reshdr_flags);
ret = full_write(out_fd, &blob_hdr, sizeof(blob_hdr));
if (ret)
ERROR_WITH_ERRNO("Error writing blob header to WIM file");
return ret;
}
struct write_blobs_progress_data {
wimlib_progress_func_t progfunc;
void *progctx;
union wimlib_progress_info progress;
u64 next_progress;
};
static int
do_write_blobs_progress(struct write_blobs_progress_data *progress_data,
u64 complete_size, u64 complete_compressed_size,
u32 complete_count, bool discarded)
{
union wimlib_progress_info *progress = &progress_data->progress;
int ret;
if (discarded) {
progress->write_streams.total_bytes -= complete_size;
progress->write_streams.total_streams -= complete_count;
if (progress_data->next_progress != ~(u64)0 &&
progress_data->next_progress > progress->write_streams.total_bytes)
{
progress_data->next_progress = progress->write_streams.total_bytes;
}
} else {
progress->write_streams.completed_bytes += complete_size;
progress->write_streams.completed_compressed_bytes +=
complete_compressed_size;
progress->write_streams.completed_streams += complete_count;
}
if (progress->write_streams.completed_bytes >= progress_data->next_progress) {
ret = call_progress(progress_data->progfunc,
WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
progress,
progress_data->progctx);
if (ret)
return ret;
set_next_progress(progress->write_streams.completed_bytes,
progress->write_streams.total_bytes,
&progress_data->next_progress);
}
return 0;
}
struct write_blobs_ctx {
/* File descriptor to which the blobs are being written. */
struct filedes *out_fd;
/* Blob table for the WIMStruct on whose behalf the blobs are being
* written. */
struct blob_table *blob_table;
/* Compression format to use. */
int out_ctype;
/* Maximum uncompressed chunk size in compressed resources to use. */
u32 out_chunk_size;
/* Flags that affect how the blobs will be written. */
int write_resource_flags;
/* Data used for issuing WRITE_STREAMS progress. */
struct write_blobs_progress_data progress_data;
struct filter_context *filter_ctx;
/* Pointer to the chunk_compressor implementation being used for
* compressing chunks of data, or NULL if chunks are being written
* uncompressed. */
struct chunk_compressor *compressor;
/* A buffer of size @out_chunk_size that has been loaned out from the
* chunk compressor and is currently being filled with the uncompressed
* data of the next chunk. */
u8 *cur_chunk_buf;
/* Number of bytes in @cur_chunk_buf that are currently filled. */
size_t cur_chunk_buf_filled;
/* List of blobs that currently have chunks being compressed. */
struct list_head blobs_being_compressed;
/* List of blobs in the solid resource. Blobs are moved here after
* @blobs_being_compressed only when writing a solid resource. */
struct list_head blobs_in_solid_resource;
/* Current uncompressed offset in the blob being written. */
u64 cur_write_blob_offset;
/* Uncompressed size of resource currently being written. */
u64 cur_write_res_size;
/* Array that is filled in with compressed chunk sizes as a resource is
* being written. */
u64 *chunk_csizes;
/* Index of next entry in @chunk_csizes to fill in. */
size_t chunk_index;
/* Number of entries in @chunk_csizes currently allocated. */
size_t num_alloc_chunks;
/* Offset in the output file of the start of the chunks of the resource
* currently being written. */
u64 chunks_start_offset;
};
/* Reserve space for the chunk table and prepare to accumulate the chunk table
* in memory. */
static int
begin_chunk_table(struct write_blobs_ctx *ctx, u64 res_expected_size)
{
u64 expected_num_chunks;
u64 expected_num_chunk_entries;
size_t reserve_size;
int ret;
/* Calculate the number of chunks and chunk entries that should be
* needed for the resource. These normally will be the final values,
* but in SOLID mode some of the blobs we're planning to write into the
* resource may be duplicates, and therefore discarded, potentially
* decreasing the number of chunk entries needed. */
expected_num_chunks = DIV_ROUND_UP(res_expected_size, ctx->out_chunk_size);
expected_num_chunk_entries = expected_num_chunks;
if (!(ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID))
expected_num_chunk_entries--;
/* Make sure the chunk_csizes array is long enough to store the
* compressed size of each chunk. */
if (expected_num_chunks > ctx->num_alloc_chunks) {
u64 new_length = expected_num_chunks + 50;
if ((size_t)new_length != new_length) {
ERROR("Resource size too large (%"PRIu64" bytes!",
res_expected_size);
return WIMLIB_ERR_NOMEM;
}
FREE(ctx->chunk_csizes);
ctx->chunk_csizes = MALLOC(new_length * sizeof(ctx->chunk_csizes[0]));
if (ctx->chunk_csizes == NULL) {
ctx->num_alloc_chunks = 0;
return WIMLIB_ERR_NOMEM;
}
ctx->num_alloc_chunks = new_length;
}
ctx->chunk_index = 0;
if (!(ctx->write_resource_flags & WRITE_RESOURCE_FLAG_PIPABLE)) {
/* Reserve space for the chunk table in the output file. In the
* case of solid resources this reserves the upper bound for the
* needed space, not necessarily the exact space which will
* prove to be needed. At this point, we just use @chunk_csizes
* for a buffer of 0's because the actual compressed chunk sizes
* are unknown. */
reserve_size = expected_num_chunk_entries *
get_chunk_entry_size(res_expected_size,
0 != (ctx->write_resource_flags &
WRITE_RESOURCE_FLAG_SOLID));
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID)
reserve_size += sizeof(struct alt_chunk_table_header_disk);
memset(ctx->chunk_csizes, 0, reserve_size);
ret = full_write(ctx->out_fd, ctx->chunk_csizes, reserve_size);
if (ret) {
ERROR_WITH_ERRNO("Error reserving space for chunk "
"table in WIM file");
return ret;
}
}
return 0;
}
static int
begin_write_resource(struct write_blobs_ctx *ctx, u64 res_expected_size)
{
int ret;
wimlib_assert(res_expected_size != 0);
if (ctx->compressor != NULL) {
ret = begin_chunk_table(ctx, res_expected_size);
if (ret)
return ret;
}
/* Output file descriptor is now positioned at the offset at which to
* write the first chunk of the resource. */
ctx->chunks_start_offset = ctx->out_fd->offset;
ctx->cur_write_blob_offset = 0;
ctx->cur_write_res_size = res_expected_size;
return 0;
}
static int
end_chunk_table(struct write_blobs_ctx *ctx, u64 res_actual_size,
u64 *res_start_offset_ret, u64 *res_store_size_ret)
{
size_t actual_num_chunks;
size_t actual_num_chunk_entries;
size_t chunk_entry_size;
int ret;
actual_num_chunks = ctx->chunk_index;
actual_num_chunk_entries = actual_num_chunks;
if (!(ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID))
actual_num_chunk_entries--;
chunk_entry_size = get_chunk_entry_size(res_actual_size,
0 != (ctx->write_resource_flags &
WRITE_RESOURCE_FLAG_SOLID));
typedef le64 __attribute__((may_alias)) aliased_le64_t;
typedef le32 __attribute__((may_alias)) aliased_le32_t;
if (chunk_entry_size == 4) {
aliased_le32_t *entries = (aliased_le32_t*)ctx->chunk_csizes;
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID) {
for (size_t i = 0; i < actual_num_chunk_entries; i++)
entries[i] = cpu_to_le32(ctx->chunk_csizes[i]);
} else {
u32 offset = ctx->chunk_csizes[0];
for (size_t i = 0; i < actual_num_chunk_entries; i++) {
u32 next_size = ctx->chunk_csizes[i + 1];
entries[i] = cpu_to_le32(offset);
offset += next_size;
}
}
} else {
aliased_le64_t *entries = (aliased_le64_t*)ctx->chunk_csizes;
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID) {
for (size_t i = 0; i < actual_num_chunk_entries; i++)
entries[i] = cpu_to_le64(ctx->chunk_csizes[i]);
} else {
u64 offset = ctx->chunk_csizes[0];
for (size_t i = 0; i < actual_num_chunk_entries; i++) {
u64 next_size = ctx->chunk_csizes[i + 1];
entries[i] = cpu_to_le64(offset);
offset += next_size;
}
}
}
size_t chunk_table_size = actual_num_chunk_entries * chunk_entry_size;
u64 res_start_offset;
u64 res_end_offset;
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_PIPABLE) {
ret = full_write(ctx->out_fd, ctx->chunk_csizes, chunk_table_size);
if (ret)
goto write_error;
res_end_offset = ctx->out_fd->offset;
res_start_offset = ctx->chunks_start_offset;
} else {
res_end_offset = ctx->out_fd->offset;
u64 chunk_table_offset;
chunk_table_offset = ctx->chunks_start_offset - chunk_table_size;
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID) {
struct alt_chunk_table_header_disk hdr;
hdr.res_usize = cpu_to_le64(res_actual_size);
hdr.chunk_size = cpu_to_le32(ctx->out_chunk_size);
hdr.compression_format = cpu_to_le32(ctx->out_ctype);
STATIC_ASSERT(WIMLIB_COMPRESSION_TYPE_XPRESS == 1);
STATIC_ASSERT(WIMLIB_COMPRESSION_TYPE_LZX == 2);
STATIC_ASSERT(WIMLIB_COMPRESSION_TYPE_LZMS == 3);
ret = full_pwrite(ctx->out_fd, &hdr, sizeof(hdr),
chunk_table_offset - sizeof(hdr));
if (ret)
goto write_error;
res_start_offset = chunk_table_offset - sizeof(hdr);
} else {
res_start_offset = chunk_table_offset;
}
ret = full_pwrite(ctx->out_fd, ctx->chunk_csizes,
chunk_table_size, chunk_table_offset);
if (ret)
goto write_error;
}
*res_start_offset_ret = res_start_offset;
*res_store_size_ret = res_end_offset - res_start_offset;
return 0;
write_error:
ERROR_WITH_ERRNO("Error writing chunk table to WIM file");
return ret;
}
/* Finish writing a WIM resource by writing or updating the chunk table (if not
* writing the data uncompressed) and loading its metadata into @out_reshdr. */
static int
end_write_resource(struct write_blobs_ctx *ctx, struct wim_reshdr *out_reshdr)
{
int ret;
u64 res_size_in_wim;
u64 res_uncompressed_size;
u64 res_offset_in_wim;
wimlib_assert(ctx->cur_write_blob_offset == ctx->cur_write_res_size ||
(ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID));
res_uncompressed_size = ctx->cur_write_res_size;
if (ctx->compressor) {
ret = end_chunk_table(ctx, res_uncompressed_size,
&res_offset_in_wim, &res_size_in_wim);
if (ret)
return ret;
} else {
res_offset_in_wim = ctx->chunks_start_offset;
res_size_in_wim = ctx->out_fd->offset - res_offset_in_wim;
}
out_reshdr->uncompressed_size = res_uncompressed_size;
out_reshdr->size_in_wim = res_size_in_wim;
out_reshdr->offset_in_wim = res_offset_in_wim;
return 0;
}
/* Call when no more data from the file at @path is needed. */
static int
done_with_file(const tchar *path, wimlib_progress_func_t progfunc, void *progctx)
{
union wimlib_progress_info info;
info.done_with_file.path_to_file = path;
return call_progress(progfunc, WIMLIB_PROGRESS_MSG_DONE_WITH_FILE,
&info, progctx);
}
static int
do_done_with_blob(struct blob_descriptor *blob,
wimlib_progress_func_t progfunc, void *progctx)
{
int ret;
struct wim_inode *inode;
const tchar *path;
tchar *cookie1;
tchar *cookie2;
if (!blob->may_send_done_with_file)
return 0;
inode = blob->file_inode;
wimlib_assert(inode != NULL);
wimlib_assert(inode->i_num_remaining_streams > 0);
if (--inode->i_num_remaining_streams > 0)
return 0;
path = blob_file_path(blob);
cookie1 = progress_get_streamless_path(path);
cookie2 = progress_get_win32_path(path);
ret = done_with_file(path, progfunc, progctx);
progress_put_win32_path(cookie2);
progress_put_streamless_path(cookie1);
return ret;
}
/* Handle WIMLIB_WRITE_FLAG_SEND_DONE_WITH_FILE_MESSAGES mode. */
static inline int
done_with_blob(struct blob_descriptor *blob, struct write_blobs_ctx *ctx)
{
if (likely(!(ctx->write_resource_flags &
WRITE_RESOURCE_FLAG_SEND_DONE_WITH_FILE)))
return 0;
return do_done_with_blob(blob, ctx->progress_data.progfunc,
ctx->progress_data.progctx);
}
/* Begin processing a blob for writing. */
static int
write_blob_begin_read(struct blob_descriptor *blob, void *_ctx)
{
struct write_blobs_ctx *ctx = _ctx;
int ret;
wimlib_assert(blob->size > 0);
/* As an optimization, we allow some blobs to be "unhashed", meaning
* their SHA-1 message digests are unknown. This is the case with blobs
* that are added by scanning a directory tree with wimlib_add_image(),
* for example. Since WIM uses single-instance blobs, we don't know
* whether such each such blob really need to written until it is
* actually checksummed, unless it has a unique size. In such cases we
* read and checksum the blob in this function, thereby advancing ahead
* of read_blob_list(), which will still provide the data again to
* write_blob_process_chunk(). This is okay because an unhashed blob
* cannot be in a WIM resource, which might be costly to decompress. */
if (ctx->blob_table != NULL && blob->unhashed && !blob->unique_size) {
struct blob_descriptor *new_blob;
ret = hash_unhashed_blob(blob, ctx->blob_table, &new_blob);
if (ret)
return ret;
if (new_blob != blob) {
/* Duplicate blob detected. */
if (new_blob->will_be_in_output_wim ||
blob_filtered(new_blob, ctx->filter_ctx))
{
/* The duplicate blob is already being included
* in the output WIM, or it would be filtered
* out if it had been. Skip writing this blob
* (and reading it again) entirely, passing its
* output reference count to the duplicate blob
* in the former case. */
ret = do_write_blobs_progress(&ctx->progress_data,
blob->size,
blob->size,
1, true);
list_del(&blob->write_blobs_list);
list_del(&blob->blob_table_list);
if (new_blob->will_be_in_output_wim)
new_blob->out_refcnt += blob->out_refcnt;
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID)
ctx->cur_write_res_size -= blob->size;
if (!ret)
ret = done_with_blob(blob, ctx);
free_blob_descriptor(blob);
if (ret)
return ret;
return BEGIN_BLOB_STATUS_SKIP_BLOB;
} else {
/* The duplicate blob can validly be written,
* but was not marked as such. Discard the
* current blob descriptor and use the
* duplicate, but actually freeing the current
* blob descriptor must wait until
* read_blob_list() has finished reading its
* data. */
list_replace(&blob->write_blobs_list,
&new_blob->write_blobs_list);
list_replace(&blob->blob_table_list,
&new_blob->blob_table_list);
blob->will_be_in_output_wim = 0;
new_blob->out_refcnt = blob->out_refcnt;
new_blob->will_be_in_output_wim = 1;
new_blob->may_send_done_with_file = 0;
blob = new_blob;
}
}
}
list_move_tail(&blob->write_blobs_list, &ctx->blobs_being_compressed);
return 0;
}
/* Rewrite a blob that was just written compressed (as a non-solid WIM resource)
* as uncompressed instead. */
static int
write_blob_uncompressed(struct blob_descriptor *blob, struct filedes *out_fd)
{
int ret;
u64 begin_offset = blob->out_reshdr.offset_in_wim;
u64 end_offset = out_fd->offset;
if (filedes_seek(out_fd, begin_offset) == -1)
return 0;
ret = extract_blob_to_fd(blob, out_fd, false);
if (ret) {
/* Error reading the uncompressed data. */
if (out_fd->offset == begin_offset &&
filedes_seek(out_fd, end_offset) != -1)
{
/* Nothing was actually written yet, and we successfully
* seeked to the end of the compressed resource, so
* don't issue a hard error; just keep the compressed
* resource instead. */
WARNING("Recovered compressed resource of "
"size %"PRIu64", continuing on.", blob->size);
return 0;
}
return ret;
}
wimlib_assert(out_fd->offset - begin_offset == blob->size);
/* We could ftruncate() the file to 'out_fd->offset' here, but there
* isn't much point. Usually we will only be truncating by a few bytes
* and will just overwrite the data immediately. */
blob->out_reshdr.size_in_wim = blob->size;
blob->out_reshdr.flags &= ~(WIM_RESHDR_FLAG_COMPRESSED |
WIM_RESHDR_FLAG_SOLID);
return 0;
}
/* Returns true if the specified blob, which was written as a non-solid
* resource, should be truncated from the WIM file and re-written uncompressed.
* blob->out_reshdr must be filled in from the initial write of the blob. */
static bool
should_rewrite_blob_uncompressed(const struct write_blobs_ctx *ctx,
const struct blob_descriptor *blob)
{
/* If the compressed data is smaller than the uncompressed data, prefer
* the compressed data. */
if (blob->out_reshdr.size_in_wim < blob->out_reshdr.uncompressed_size)
return false;
/* If we're not actually writing compressed data, then there's no need
* for re-writing. */
if (!ctx->compressor)
return false;
/* If writing a pipable WIM, everything we write to the output is final
* (it might actually be a pipe!). */
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_PIPABLE)
return false;
/* If the blob that would need to be re-read is located in a solid
* resource in another WIM file, then re-reading it would be costly. So
* don't do it.
*
* Exception: if the compressed size happens to be *exactly* the same as
* the uncompressed size, then the blob *must* be written uncompressed
* in order to remain compatible with the Windows Overlay Filesystem
* filter driver (WOF).
*
* TODO: we are currently assuming that the optimization for
* single-chunk resources in maybe_rewrite_blob_uncompressed() prevents
* this case from being triggered too often. To fully prevent excessive
* decompressions in degenerate cases, we really should obtain the
* uncompressed data by decompressing the compressed data we wrote to
* the output file.
*/
if (blob->blob_location == BLOB_IN_WIM &&
blob->size != blob->rdesc->uncompressed_size &&
blob->size != blob->out_reshdr.size_in_wim)
return false;
return true;
}
static int
maybe_rewrite_blob_uncompressed(struct write_blobs_ctx *ctx,
struct blob_descriptor *blob)
{
if (!should_rewrite_blob_uncompressed(ctx, blob))
return 0;
/* Regular (non-solid) WIM resources with exactly one chunk and
* compressed size equal to uncompressed size are exactly the same as
* the corresponding compressed data --- since there must be 0 entries
* in the chunk table and the only chunk must be stored uncompressed.
* In this case, there's no need to rewrite anything. */
if (ctx->chunk_index == 1 &&
blob->out_reshdr.size_in_wim == blob->out_reshdr.uncompressed_size)
{
blob->out_reshdr.flags &= ~WIM_RESHDR_FLAG_COMPRESSED;
return 0;
}
return write_blob_uncompressed(blob, ctx->out_fd);
}
/* Write the next chunk of (typically compressed) data to the output WIM,
* handling the writing of the chunk table. */
static int
write_chunk(struct write_blobs_ctx *ctx, const void *cchunk,
size_t csize, size_t usize)
{
int ret;
struct blob_descriptor *blob;
u32 completed_blob_count = 0;
blob = list_entry(ctx->blobs_being_compressed.next,
struct blob_descriptor, write_blobs_list);
if (ctx->cur_write_blob_offset == 0 &&
!(ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID))
{
/* Starting to write a new blob in non-solid mode. */
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_PIPABLE) {
ret = write_pwm_blob_header(blob, ctx->out_fd,
ctx->compressor != NULL);
if (ret)
return ret;
}
ret = begin_write_resource(ctx, blob->size);
if (ret)
return ret;
}
if (ctx->compressor != NULL) {
/* Record the compresed chunk size. */
wimlib_assert(ctx->chunk_index < ctx->num_alloc_chunks);
ctx->chunk_csizes[ctx->chunk_index++] = csize;
/* If writing a pipable WIM, before the chunk data write a chunk
* header that provides the compressed chunk size. */
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_PIPABLE) {
struct pwm_chunk_hdr chunk_hdr = {
.compressed_size = cpu_to_le32(csize),
};
ret = full_write(ctx->out_fd, &chunk_hdr,
sizeof(chunk_hdr));
if (ret)
goto write_error;
}
}
/* Write the chunk data. */
ret = full_write(ctx->out_fd, cchunk, csize);
if (ret)
goto write_error;
ctx->cur_write_blob_offset += usize;
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID) {
/* Wrote chunk in solid mode. It may have finished multiple
* blobs. */
struct blob_descriptor *next_blob;
while (blob && ctx->cur_write_blob_offset >= blob->size) {
ctx->cur_write_blob_offset -= blob->size;
if (ctx->cur_write_blob_offset)
next_blob = list_entry(blob->write_blobs_list.next,
struct blob_descriptor,
write_blobs_list);
else
next_blob = NULL;
ret = done_with_blob(blob, ctx);
if (ret)
return ret;
list_move_tail(&blob->write_blobs_list, &ctx->blobs_in_solid_resource);
completed_blob_count++;
blob = next_blob;
}
} else {
/* Wrote chunk in non-solid mode. It may have finished a
* blob. */
if (ctx->cur_write_blob_offset == blob->size) {
wimlib_assert(ctx->cur_write_blob_offset ==
ctx->cur_write_res_size);
ret = end_write_resource(ctx, &blob->out_reshdr);
if (ret)
return ret;
blob->out_reshdr.flags = reshdr_flags_for_blob(blob);
if (ctx->compressor != NULL)
blob->out_reshdr.flags |= WIM_RESHDR_FLAG_COMPRESSED;
ret = maybe_rewrite_blob_uncompressed(ctx, blob);
if (ret)
return ret;
wimlib_assert(blob->out_reshdr.uncompressed_size == blob->size);
ctx->cur_write_blob_offset = 0;
ret = done_with_blob(blob, ctx);
if (ret)
return ret;
list_del(&blob->write_blobs_list);
completed_blob_count++;
}
}
return do_write_blobs_progress(&ctx->progress_data, usize, csize,
completed_blob_count, false);
write_error:
ERROR_WITH_ERRNO("Error writing chunk data to WIM file");
return ret;
}
static int
prepare_chunk_buffer(struct write_blobs_ctx *ctx)
{
/* While we are unable to get a new chunk buffer due to too many chunks
* already outstanding, retrieve and write the next compressed chunk. */
while (!(ctx->cur_chunk_buf =
ctx->compressor->get_chunk_buffer(ctx->compressor)))
{
const void *cchunk;
u32 csize;
u32 usize;
bool bret;
int ret;
bret = ctx->compressor->get_compression_result(ctx->compressor,
&cchunk,
&csize,
&usize);
wimlib_assert(bret);
ret = write_chunk(ctx, cchunk, csize, usize);
if (ret)
return ret;
}
return 0;
}
/* Process the next chunk of data to be written to a WIM resource. */
static int
write_blob_process_chunk(const struct blob_descriptor *blob, u64 offset,
const void *chunk, size_t size, void *_ctx)
{
struct write_blobs_ctx *ctx = _ctx;
int ret;
const u8 *chunkptr, *chunkend;
wimlib_assert(size != 0);
if (ctx->compressor == NULL) {
/* Write chunk uncompressed. */
ret = write_chunk(ctx, chunk, size, size);
if (ret)
return ret;
return 0;
}
/* Submit the chunk for compression, but take into account that the
* @size the chunk was provided in may not correspond to the
* @out_chunk_size being used for compression. */
chunkptr = chunk;
chunkend = chunkptr + size;
do {
size_t needed_chunk_size;
size_t bytes_consumed;
if (!ctx->cur_chunk_buf) {
ret = prepare_chunk_buffer(ctx);
if (ret)
return ret;
}
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_SOLID) {
needed_chunk_size = ctx->out_chunk_size;
} else {
needed_chunk_size = min(ctx->out_chunk_size,
ctx->cur_chunk_buf_filled +
(blob->size - offset));
}
bytes_consumed = min(chunkend - chunkptr,
needed_chunk_size - ctx->cur_chunk_buf_filled);
memcpy(&ctx->cur_chunk_buf[ctx->cur_chunk_buf_filled],
chunkptr, bytes_consumed);
chunkptr += bytes_consumed;
offset += bytes_consumed;
ctx->cur_chunk_buf_filled += bytes_consumed;
if (ctx->cur_chunk_buf_filled == needed_chunk_size) {
ctx->compressor->signal_chunk_filled(ctx->compressor,
ctx->cur_chunk_buf_filled);
ctx->cur_chunk_buf = NULL;
ctx->cur_chunk_buf_filled = 0;
}
} while (chunkptr != chunkend);
return 0;
}
/* Finish processing a blob for writing. It may not have been completely
* written yet, as the chunk_compressor implementation may still have chunks
* buffered or being compressed. */
static int
write_blob_end_read(struct blob_descriptor *blob, int status, void *_ctx)
{
struct write_blobs_ctx *ctx = _ctx;
if (!blob->will_be_in_output_wim) {
/* The blob was a duplicate. Now that its data has finished
* being read, it is being discarded in favor of the duplicate
* entry. It therefore is no longer needed, and we can fire the
* DONE_WITH_FILE callback because the file will not be read
* again.
*
* Note: we can't yet fire DONE_WITH_FILE for non-duplicate
* blobs, since it needs to be possible to re-read the file if
* it does not compress to less than its original size. */
if (!status)
status = done_with_blob(blob, ctx);
free_blob_descriptor(blob);
} else if (!status && blob->unhashed && ctx->blob_table != NULL) {
/* The blob was not a duplicate and was previously unhashed.
* Since we passed COMPUTE_MISSING_BLOB_HASHES to
* read_blob_list(), blob->hash is now computed and valid. So
* turn this blob into a "hashed" blob. */
list_del(&blob->unhashed_list);
blob_table_insert(ctx->blob_table, blob);
blob->unhashed = 0;
}
return status;
}
/*
* Compute statistics about a list of blobs that will be written.
*
* Assumes the blobs are sorted such that all blobs located in each distinct WIM
* (specified by WIMStruct) are together.
*
* For compactions, also verify that there are no overlapping resources. This
* really should be checked earlier, but for now it's easiest to check here.
*/
static int
compute_blob_list_stats(struct list_head *blob_list,
struct write_blobs_ctx *ctx)
{
struct blob_descriptor *blob;
u64 total_bytes = 0;
u64 num_blobs = 0;
u64 total_parts = 0;
WIMStruct *prev_wim_part = NULL;
const struct wim_resource_descriptor *prev_rdesc = NULL;
list_for_each_entry(blob, blob_list, write_blobs_list) {
num_blobs++;
total_bytes += blob->size;
if (blob->blob_location == BLOB_IN_WIM) {
const struct wim_resource_descriptor *rdesc = blob->rdesc;
WIMStruct *wim = rdesc->wim;
if (prev_wim_part != wim) {
prev_wim_part = wim;
total_parts++;
}
if (unlikely(wim->being_compacted) && rdesc != prev_rdesc) {
if (prev_rdesc != NULL &&
rdesc->offset_in_wim <
prev_rdesc->offset_in_wim +
prev_rdesc->size_in_wim)
{
WARNING("WIM file contains overlapping "
"resources! Compaction is not "
"possible.");
return WIMLIB_ERR_RESOURCE_ORDER;
}
prev_rdesc = rdesc;
}
}
}
ctx->progress_data.progress.write_streams.total_bytes = total_bytes;
ctx->progress_data.progress.write_streams.total_streams = num_blobs;
ctx->progress_data.progress.write_streams.completed_bytes = 0;
ctx->progress_data.progress.write_streams.completed_streams = 0;
ctx->progress_data.progress.write_streams.compression_type = ctx->out_ctype;
ctx->progress_data.progress.write_streams.total_parts = total_parts;
ctx->progress_data.progress.write_streams.completed_parts = 0;
ctx->progress_data.next_progress = 0;
return 0;
}
/* Find blobs in @blob_list that can be copied to the output WIM in raw form
* rather than compressed. Delete these blobs from @blob_list and move them to
* @raw_copy_blobs. Return the total uncompressed size of the blobs that need
* to be compressed. */
static u64
find_raw_copy_blobs(struct list_head *blob_list, int write_resource_flags,
int out_ctype, u32 out_chunk_size,
struct list_head *raw_copy_blobs)
{
struct blob_descriptor *blob, *tmp;
u64 num_nonraw_bytes = 0;
INIT_LIST_HEAD(raw_copy_blobs);
/* Initialize temporary raw_copy_ok flag. */
list_for_each_entry(blob, blob_list, write_blobs_list)
if (blob->blob_location == BLOB_IN_WIM)
blob->rdesc->raw_copy_ok = 0;
list_for_each_entry_safe(blob, tmp, blob_list, write_blobs_list) {
if (can_raw_copy(blob, write_resource_flags,
out_ctype, out_chunk_size))
{
blob->rdesc->raw_copy_ok = 1;
list_move_tail(&blob->write_blobs_list, raw_copy_blobs);
} else {
num_nonraw_bytes += blob->size;
}
}
return num_nonraw_bytes;
}
/* Copy a raw compressed resource located in another WIM file to the WIM file
* being written. */
static int
write_raw_copy_resource(struct wim_resource_descriptor *in_rdesc,
struct filedes *out_fd)
{
u64 cur_read_offset;
u64 end_read_offset;
u8 buf[BUFFER_SIZE];
size_t bytes_to_read;
int ret;
struct filedes *in_fd;
struct blob_descriptor *blob;
u64 out_offset_in_wim;
/* Copy the raw data. */
cur_read_offset = in_rdesc->offset_in_wim;
end_read_offset = cur_read_offset + in_rdesc->size_in_wim;
out_offset_in_wim = out_fd->offset;
if (in_rdesc->is_pipable) {
if (cur_read_offset < sizeof(struct pwm_blob_hdr))
return WIMLIB_ERR_INVALID_PIPABLE_WIM;
cur_read_offset -= sizeof(struct pwm_blob_hdr);
out_offset_in_wim += sizeof(struct pwm_blob_hdr);
}
in_fd = &in_rdesc->wim->in_fd;
wimlib_assert(cur_read_offset != end_read_offset);
if (likely(!in_rdesc->wim->being_compacted) ||
in_rdesc->offset_in_wim > out_fd->offset) {
do {
bytes_to_read = min(sizeof(buf),
end_read_offset - cur_read_offset);
ret = full_pread(in_fd, buf, bytes_to_read,
cur_read_offset);
if (ret) {
ERROR_WITH_ERRNO("Error reading raw data "
"from WIM file");
return ret;
}
ret = full_write(out_fd, buf, bytes_to_read);
if (ret) {
ERROR_WITH_ERRNO("Error writing raw data "
"to WIM file");
return ret;
}
cur_read_offset += bytes_to_read;
} while (cur_read_offset != end_read_offset);
} else {
/* Optimization: the WIM file is being compacted and the
* resource being written is already in the desired location.
* Skip over the data instead of re-writing it. */
/* Due the earlier check for overlapping resources, it should
* never be the case that we already overwrote the resource. */
wimlib_assert(!(in_rdesc->offset_in_wim < out_fd->offset));
if (-1 == filedes_seek(out_fd, out_fd->offset + in_rdesc->size_in_wim))
return WIMLIB_ERR_WRITE;
}
list_for_each_entry(blob, &in_rdesc->blob_list, rdesc_node) {
if (blob->will_be_in_output_wim) {
blob_set_out_reshdr_for_reuse(blob);
if (in_rdesc->flags & WIM_RESHDR_FLAG_SOLID)
blob->out_res_offset_in_wim = out_offset_in_wim;
else
blob->out_reshdr.offset_in_wim = out_offset_in_wim;
}
}
return 0;
}
/* Copy a list of raw compressed resources located in other WIM file(s) to the
* WIM file being written. */
static int
write_raw_copy_resources(struct list_head *raw_copy_blobs,
struct filedes *out_fd,
struct write_blobs_progress_data *progress_data)
{
struct blob_descriptor *blob;
int ret;
list_for_each_entry(blob, raw_copy_blobs, write_blobs_list)
blob->rdesc->raw_copy_ok = 1;
list_for_each_entry(blob, raw_copy_blobs, write_blobs_list) {
u64 compressed_size = 0;
if (blob->rdesc->raw_copy_ok) {
/* Write each solid resource only one time. */
ret = write_raw_copy_resource(blob->rdesc, out_fd);
if (ret)
return ret;
blob->rdesc->raw_copy_ok = 0;
compressed_size = blob->rdesc->size_in_wim;
}
ret = do_write_blobs_progress(progress_data, blob->size,
compressed_size, 1, false);
if (ret)
return ret;
}
return 0;
}
/* Wait for and write all chunks pending in the compressor. */
static int
finish_remaining_chunks(struct write_blobs_ctx *ctx)
{
const void *cdata;
u32 csize;
u32 usize;
int ret;
if (ctx->compressor == NULL)
return 0;
if (ctx->cur_chunk_buf_filled != 0) {
ctx->compressor->signal_chunk_filled(ctx->compressor,
ctx->cur_chunk_buf_filled);
}
while (ctx->compressor->get_compression_result(ctx->compressor, &cdata,
&csize, &usize))
{
ret = write_chunk(ctx, cdata, csize, usize);
if (ret)
return ret;
}
return 0;
}
static void
validate_blob_list(struct list_head *blob_list)
{
struct blob_descriptor *blob;
list_for_each_entry(blob, blob_list, write_blobs_list) {
wimlib_assert(blob->will_be_in_output_wim);
wimlib_assert(blob->size != 0);
}
}
static void
init_done_with_file_info(struct list_head *blob_list)
{
struct blob_descriptor *blob;
list_for_each_entry(blob, blob_list, write_blobs_list) {
if (blob_is_in_file(blob)) {
blob->file_inode->i_num_remaining_streams = 0;
blob->may_send_done_with_file = 1;
} else {
blob->may_send_done_with_file = 0;
}
}
list_for_each_entry(blob, blob_list, write_blobs_list)
if (blob->may_send_done_with_file)
blob->file_inode->i_num_remaining_streams++;
}
/*
* Write a list of blobs to the output WIM file.
*
* @blob_list
* The list of blobs to write, specified by a list of 'struct blob_descriptor' linked
* by the 'write_blobs_list' member.
*
* @out_fd
* The file descriptor, opened for writing, to which to write the blobs.
*
* @write_resource_flags
* Flags to modify how the blobs are written:
*
* WRITE_RESOURCE_FLAG_RECOMPRESS:
* Force compression of all resources, even if they could otherwise
* be re-used by copying the raw data, due to being located in a WIM
* file with compatible compression parameters.
*
* WRITE_RESOURCE_FLAG_PIPABLE:
* Write the resources in the wimlib-specific pipable format, and
* furthermore do so in such a way that no seeking backwards in
* @out_fd will be performed (so it may be a pipe).
*
* WRITE_RESOURCE_FLAG_SOLID:
* Combine all the blobs into a single resource rather than writing
* them in separate resources. This flag is only valid if the WIM
* version number has been, or will be, set to WIM_VERSION_SOLID.
* This flag may not be combined with WRITE_RESOURCE_FLAG_PIPABLE.
*
* @out_ctype
* Compression format to use in the output resources, specified as one of
* the WIMLIB_COMPRESSION_TYPE_* constants. WIMLIB_COMPRESSION_TYPE_NONE
* is allowed.
*
* @out_chunk_size
* Compression chunk size to use in the output resources. It must be a
* valid chunk size for the specified compression format @out_ctype, unless
* @out_ctype is WIMLIB_COMPRESSION_TYPE_NONE, in which case this parameter
* is ignored.
*
* @num_threads
* Number of threads to use to compress data. If 0, a default number of
* threads will be chosen. The number of threads still may be decreased
* from the specified value if insufficient memory is detected.
*
* @blob_table
* If on-the-fly deduplication of unhashed blobs is desired, this parameter
* must be pointer to the blob table for the WIMStruct on whose behalf the
* blobs are being written. Otherwise, this parameter can be NULL.
*
* @filter_ctx
* If on-the-fly deduplication of unhashed blobs is desired, this parameter
* can be a pointer to a context for blob filtering used to detect whether
* the duplicate blob has been hard-filtered or not. If no blobs are
* hard-filtered or no blobs are unhashed, this parameter can be NULL.
*
* This function will write the blobs in @blob_list to resources in
* consecutive positions in the output WIM file, or to a single solid resource
* if WRITE_RESOURCE_FLAG_SOLID was specified in @write_resource_flags. In both
* cases, the @out_reshdr of the `struct blob_descriptor' for each blob written will be
* updated to specify its location, size, and flags in the output WIM. In the
* solid resource case, WIM_RESHDR_FLAG_SOLID will be set in the @flags field of
* each @out_reshdr, and furthermore @out_res_offset_in_wim and
* @out_res_size_in_wim of each @out_reshdr will be set to the offset and size,
* respectively, in the output WIM of the solid resource containing the
* corresponding blob.
*
* Each of the blobs to write may be in any location supported by the
* resource-handling code (specifically, read_blob_list()), such as the contents
* of external file that has been logically added to the output WIM, or a blob
* in another WIM file that has been imported, or even a blob in the "same" WIM
* file of which a modified copy is being written. In the case that a blob is
* already in a WIM file and uses compatible compression parameters, by default
* this function will re-use the raw data instead of decompressing it, then
* recompressing it; however, with WRITE_RESOURCE_FLAG_RECOMPRESS
* specified in @write_resource_flags, this is not done.
*
* As a further requirement, this function requires that the
* @will_be_in_output_wim member be set to 1 on all blobs in @blob_list as well
* as any other blobs not in @blob_list that will be in the output WIM file, but
* set to 0 on any other blobs in the output WIM's blob table or sharing a solid
* resource with a blob in @blob_list. Still furthermore, if on-the-fly
* deduplication of blobs is possible, then all blobs in @blob_list must also be
* linked by @blob_table_list along with any other blobs that have
* @will_be_in_output_wim set.
*
* This function handles on-the-fly deduplication of blobs for which SHA-1
* message digests have not yet been calculated. Such blobs may or may not need
* to be written. If @blob_table is non-NULL, then each blob in @blob_list that
* has @unhashed set but not @unique_size set is checksummed immediately before
* it would otherwise be read for writing in order to determine if it is
* identical to another blob already being written or one that would be filtered
* out of the output WIM using blob_filtered() with the context @filter_ctx.
* Each such duplicate blob will be removed from @blob_list, its reference count
* transferred to the pre-existing duplicate blob, its memory freed, and will
* not be written. Alternatively, if a blob in @blob_list is a duplicate with
* any blob in @blob_table that has not been marked for writing or would not be
* hard-filtered, it is freed and the pre-existing duplicate is written instead,
* taking ownership of the reference count and slot in the @blob_table_list.
*
* Returns 0 if every blob was either written successfully or did not need to be
* written; otherwise returns a non-zero error code.
*/
static int
write_blob_list(struct list_head *blob_list,
struct filedes *out_fd,
int write_resource_flags,
int out_ctype,
u32 out_chunk_size,
unsigned num_threads,
struct blob_table *blob_table,
struct filter_context *filter_ctx,
wimlib_progress_func_t progfunc,
void *progctx)
{
int ret;
struct write_blobs_ctx ctx;
struct list_head raw_copy_blobs;
u64 num_nonraw_bytes;
wimlib_assert((write_resource_flags &
(WRITE_RESOURCE_FLAG_SOLID |
WRITE_RESOURCE_FLAG_PIPABLE)) !=
(WRITE_RESOURCE_FLAG_SOLID |
WRITE_RESOURCE_FLAG_PIPABLE));
validate_blob_list(blob_list);
if (list_empty(blob_list))
return 0;
/* If needed, set auxiliary information so that we can detect when the
* library has finished using each external file. */
if (unlikely(write_resource_flags & WRITE_RESOURCE_FLAG_SEND_DONE_WITH_FILE))
init_done_with_file_info(blob_list);
memset(&ctx, 0, sizeof(ctx));
ctx.out_fd = out_fd;
ctx.blob_table = blob_table;
ctx.out_ctype = out_ctype;
ctx.out_chunk_size = out_chunk_size;
ctx.write_resource_flags = write_resource_flags;
ctx.filter_ctx = filter_ctx;
/*
* We normally sort the blobs to write by a "sequential" order that is
* optimized for reading. But when using solid compression, we instead
* sort the blobs by file extension and file name (when applicable; and
* we don't do this for blobs from solid resources) so that similar
* files are grouped together, which improves the compression ratio.
* This is somewhat of a hack since a blob does not necessarily
* correspond one-to-one with a filename, nor is there any guarantee
* that two files with similar names or extensions are actually similar
* in content. A potential TODO is to sort the blobs based on some
* measure of similarity of their actual contents.
*/
ret = sort_blob_list_by_sequential_order(blob_list,
offsetof(struct blob_descriptor,
write_blobs_list));
if (ret)
return ret;
ret = compute_blob_list_stats(blob_list, &ctx);
if (ret)
return ret;
if (write_resource_flags & WRITE_RESOURCE_FLAG_SOLID_SORT) {
ret = sort_blob_list_for_solid_compression(blob_list);
if (unlikely(ret))
WARNING("Failed to sort blobs for solid compression. Continuing anyways.");
}
ctx.progress_data.progfunc = progfunc;
ctx.progress_data.progctx = progctx;
num_nonraw_bytes = find_raw_copy_blobs(blob_list, write_resource_flags,
out_ctype, out_chunk_size,
&raw_copy_blobs);
/* Unless no data needs to be compressed, allocate a chunk_compressor to
* do compression. There are serial and parallel implementations of the
* chunk_compressor interface. We default to parallel using the
* specified number of threads, unless the upper bound on the number
* bytes needing to be compressed is less than a heuristic value. */
if (num_nonraw_bytes != 0 && out_ctype != WIMLIB_COMPRESSION_TYPE_NONE) {
if (num_nonraw_bytes > max(2000000, out_chunk_size)) {
ret = new_parallel_chunk_compressor(out_ctype,
out_chunk_size,
num_threads, 0,
&ctx.compressor);
if (ret > 0) {
WARNING("Couldn't create parallel chunk compressor: %"TS".\n"
" Falling back to single-threaded compression.",
wimlib_get_error_string(ret));
}
}
if (ctx.compressor == NULL) {
ret = new_serial_chunk_compressor(out_ctype, out_chunk_size,
&ctx.compressor);
if (ret)
goto out_destroy_context;
}
}
if (ctx.compressor)
ctx.progress_data.progress.write_streams.num_threads = ctx.compressor->num_threads;
else
ctx.progress_data.progress.write_streams.num_threads = 1;
ret = call_progress(ctx.progress_data.progfunc,
WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
&ctx.progress_data.progress,
ctx.progress_data.progctx);
if (ret)
goto out_destroy_context;
/* Copy any compressed resources for which the raw data can be reused
* without decompression. */
ret = write_raw_copy_resources(&raw_copy_blobs, ctx.out_fd,
&ctx.progress_data);
if (ret || num_nonraw_bytes == 0)
goto out_destroy_context;
INIT_LIST_HEAD(&ctx.blobs_being_compressed);
if (write_resource_flags & WRITE_RESOURCE_FLAG_SOLID) {
INIT_LIST_HEAD(&ctx.blobs_in_solid_resource);
ret = begin_write_resource(&ctx, num_nonraw_bytes);
if (ret)
goto out_destroy_context;
}
/* Read the list of blobs needing to be compressed, using the specified
* callbacks to execute processing of the data. */
struct read_blob_callbacks cbs = {
.begin_blob = write_blob_begin_read,
.continue_blob = write_blob_process_chunk,
.end_blob = write_blob_end_read,
.ctx = &ctx,
};
ret = read_blob_list(blob_list,
offsetof(struct blob_descriptor, write_blobs_list),
&cbs,
BLOB_LIST_ALREADY_SORTED |
VERIFY_BLOB_HASHES |
COMPUTE_MISSING_BLOB_HASHES);
if (ret)
goto out_destroy_context;
ret = finish_remaining_chunks(&ctx);
if (ret)
goto out_destroy_context;
if (write_resource_flags & WRITE_RESOURCE_FLAG_SOLID) {
struct wim_reshdr reshdr;
struct blob_descriptor *blob;
u64 offset_in_res;
ret = end_write_resource(&ctx, &reshdr);
if (ret)
goto out_destroy_context;
offset_in_res = 0;
list_for_each_entry(blob, &ctx.blobs_in_solid_resource, write_blobs_list) {
blob->out_reshdr.size_in_wim = blob->size;
blob->out_reshdr.flags = reshdr_flags_for_blob(blob) |
WIM_RESHDR_FLAG_SOLID;
blob->out_reshdr.uncompressed_size = 0;
blob->out_reshdr.offset_in_wim = offset_in_res;
blob->out_res_offset_in_wim = reshdr.offset_in_wim;
blob->out_res_size_in_wim = reshdr.size_in_wim;
blob->out_res_uncompressed_size = reshdr.uncompressed_size;
offset_in_res += blob->size;
}
wimlib_assert(offset_in_res == reshdr.uncompressed_size);
}
out_destroy_context:
FREE(ctx.chunk_csizes);
if (ctx.compressor)
ctx.compressor->destroy(ctx.compressor);
return ret;
}
static int
write_file_data_blobs(WIMStruct *wim,
struct list_head *blob_list,
int write_flags,
unsigned num_threads,
struct filter_context *filter_ctx)
{
int out_ctype;
u32 out_chunk_size;
int write_resource_flags;
write_resource_flags = write_flags_to_resource_flags(write_flags);
if (write_resource_flags & WRITE_RESOURCE_FLAG_SOLID) {
out_chunk_size = wim->out_solid_chunk_size;
out_ctype = wim->out_solid_compression_type;
} else {
out_chunk_size = wim->out_chunk_size;
out_ctype = wim->out_compression_type;
}
return write_blob_list(blob_list,
&wim->out_fd,
write_resource_flags,
out_ctype,
out_chunk_size,
num_threads,
wim->blob_table,
filter_ctx,
wim->progfunc,
wim->progctx);
}
/* Write the contents of the specified blob as a WIM resource. */
static int
write_wim_resource(struct blob_descriptor *blob,
struct filedes *out_fd,
int out_ctype,
u32 out_chunk_size,
int write_resource_flags)
{
LIST_HEAD(blob_list);
list_add(&blob->write_blobs_list, &blob_list);
blob->will_be_in_output_wim = 1;
return write_blob_list(&blob_list,
out_fd,
write_resource_flags & ~WRITE_RESOURCE_FLAG_SOLID,
out_ctype,
out_chunk_size,
1,
NULL,
NULL,
NULL,
NULL);
}
/* Write the contents of the specified buffer as a WIM resource. */
int
write_wim_resource_from_buffer(const void *buf,
size_t buf_size,
bool is_metadata,
struct filedes *out_fd,
int out_ctype,
u32 out_chunk_size,
struct wim_reshdr *out_reshdr,
u8 *hash_ret,
int write_resource_flags)
{
int ret;
struct blob_descriptor blob;
if (unlikely(buf_size == 0)) {
zero_reshdr(out_reshdr);
if (hash_ret)
copy_hash(hash_ret, zero_hash);
return 0;
}
blob_set_is_located_in_attached_buffer(&blob, (void *)buf, buf_size);
sha1(buf, buf_size, blob.hash);
blob.unhashed = 0;
blob.is_metadata = is_metadata;
ret = write_wim_resource(&blob, out_fd, out_ctype, out_chunk_size,
write_resource_flags);
if (ret)
return ret;
copy_reshdr(out_reshdr, &blob.out_reshdr);
if (hash_ret)
copy_hash(hash_ret, blob.hash);
return 0;
}
struct blob_size_table {
struct hlist_head *array;
size_t num_entries;
size_t capacity;
};
static int
init_blob_size_table(struct blob_size_table *tab, size_t capacity)
{
tab->array = CALLOC(capacity, sizeof(tab->array[0]));
if (tab->array == NULL)
return WIMLIB_ERR_NOMEM;
tab->num_entries = 0;
tab->capacity = capacity;
return 0;
}
static void
destroy_blob_size_table(struct blob_size_table *tab)
{
FREE(tab->array);
}
static int
blob_size_table_insert(struct blob_descriptor *blob, void *_tab)
{
struct blob_size_table *tab = _tab;
size_t pos;
struct blob_descriptor *same_size_blob;
pos = hash_u64(blob->size) % tab->capacity;
blob->unique_size = 1;
hlist_for_each_entry(same_size_blob, &tab->array[pos], hash_list_2) {
if (same_size_blob->size == blob->size) {
blob->unique_size = 0;
same_size_blob->unique_size = 0;
break;
}
}
hlist_add_head(&blob->hash_list_2, &tab->array[pos]);
tab->num_entries++;
return 0;
}
struct find_blobs_ctx {
WIMStruct *wim;
int write_flags;
struct list_head blob_list;
struct blob_size_table blob_size_tab;
};
static void
reference_blob_for_write(struct blob_descriptor *blob,
struct list_head *blob_list, u32 nref)
{
if (!blob->will_be_in_output_wim) {
blob->out_refcnt = 0;
list_add_tail(&blob->write_blobs_list, blob_list);
blob->will_be_in_output_wim = 1;
}
blob->out_refcnt += nref;
}
static int
fully_reference_blob_for_write(struct blob_descriptor *blob, void *_blob_list)
{
struct list_head *blob_list = _blob_list;
blob->will_be_in_output_wim = 0;
reference_blob_for_write(blob, blob_list, blob->refcnt);
return 0;
}
static int
inode_find_blobs_to_reference(const struct wim_inode *inode,
const struct blob_table *table,
struct list_head *blob_list)
{
wimlib_assert(inode->i_nlink > 0);
for (unsigned i = 0; i < inode->i_num_streams; i++) {
struct blob_descriptor *blob;
const u8 *hash;
blob = stream_blob(&inode->i_streams[i], table);
if (blob) {
reference_blob_for_write(blob, blob_list, inode->i_nlink);
} else {
hash = stream_hash(&inode->i_streams[i]);
if (!is_zero_hash(hash))
return blob_not_found_error(inode, hash);
}
}
return 0;
}
static int
do_blob_set_not_in_output_wim(struct blob_descriptor *blob, void *_ignore)
{
blob->will_be_in_output_wim = 0;
return 0;
}
static int
image_find_blobs_to_reference(WIMStruct *wim)
{
struct wim_image_metadata *imd;
struct wim_inode *inode;
struct blob_descriptor *blob;
struct list_head *blob_list;
int ret;
imd = wim_get_current_image_metadata(wim);
image_for_each_unhashed_blob(blob, imd)
blob->will_be_in_output_wim = 0;
blob_list = wim->private;
image_for_each_inode(inode, imd) {
ret = inode_find_blobs_to_reference(inode,
wim->blob_table,
blob_list);
if (ret)
return ret;
}
return 0;
}
static int
prepare_unfiltered_list_of_blobs_in_output_wim(WIMStruct *wim,
int image,
int blobs_ok,
struct list_head *blob_list_ret)
{
int ret;
INIT_LIST_HEAD(blob_list_ret);
if (blobs_ok && (image == WIMLIB_ALL_IMAGES ||
(image == 1 && wim->hdr.image_count == 1)))
{
/* Fast case: Assume that all blobs are being written and that
* the reference counts are correct. */
struct blob_descriptor *blob;
struct wim_image_metadata *imd;
unsigned i;
for_blob_in_table(wim->blob_table,
fully_reference_blob_for_write,
blob_list_ret);
for (i = 0; i < wim->hdr.image_count; i++) {
imd = wim->image_metadata[i];
image_for_each_unhashed_blob(blob, imd)
fully_reference_blob_for_write(blob, blob_list_ret);
}
} else {
/* Slow case: Walk through the images being written and
* determine the blobs referenced. */
for_blob_in_table(wim->blob_table,
do_blob_set_not_in_output_wim, NULL);
wim->private = blob_list_ret;
ret = for_image(wim, image, image_find_blobs_to_reference);
if (ret)
return ret;
}
return 0;
}
struct insert_other_if_hard_filtered_ctx {
struct blob_size_table *tab;
struct filter_context *filter_ctx;
};
static int
insert_other_if_hard_filtered(struct blob_descriptor *blob, void *_ctx)
{
struct insert_other_if_hard_filtered_ctx *ctx = _ctx;
if (!blob->will_be_in_output_wim &&
blob_hard_filtered(blob, ctx->filter_ctx))
blob_size_table_insert(blob, ctx->tab);
return 0;
}
static int
determine_blob_size_uniquity(struct list_head *blob_list,
struct blob_table *lt,
struct filter_context *filter_ctx)
{
int ret;
struct blob_size_table tab;
struct blob_descriptor *blob;
ret = init_blob_size_table(&tab, 9001);
if (ret)
return ret;
if (may_hard_filter_blobs(filter_ctx)) {
struct insert_other_if_hard_filtered_ctx ctx = {
.tab = &tab,
.filter_ctx = filter_ctx,
};
for_blob_in_table(lt, insert_other_if_hard_filtered, &ctx);
}
list_for_each_entry(blob, blob_list, write_blobs_list)
blob_size_table_insert(blob, &tab);
destroy_blob_size_table(&tab);
return 0;
}
static void
filter_blob_list_for_write(struct list_head *blob_list,
struct filter_context *filter_ctx)
{
struct blob_descriptor *blob, *tmp;
list_for_each_entry_safe(blob, tmp, blob_list, write_blobs_list) {
int status = blob_filtered(blob, filter_ctx);
if (status == 0) {
/* Not filtered. */
continue;
} else {
if (status > 0) {
/* Soft filtered. */
} else {
/* Hard filtered. */
blob->will_be_in_output_wim = 0;
list_del(&blob->blob_table_list);
}
list_del(&blob->write_blobs_list);
}
}
}
/*
* prepare_blob_list_for_write() -
*
* Prepare the list of blobs to write for writing a WIM containing the specified
* image(s) with the specified write flags.
*
* @wim
* The WIMStruct on whose behalf the write is occurring.
*
* @image
* Image(s) from the WIM to write; may be WIMLIB_ALL_IMAGES.
*
* @write_flags
* WIMLIB_WRITE_FLAG_* flags for the write operation:
*
* STREAMS_OK: For writes of all images, assume that all blobs in the blob
* table of @wim and the per-image lists of unhashed blobs should be taken
* as-is, and image metadata should not be searched for references. This
* does not exclude filtering with APPEND and SKIP_EXTERNAL_WIMS, below.
*
* APPEND: Blobs already present in @wim shall not be returned in
* @blob_list_ret.
*
* SKIP_EXTERNAL_WIMS: Blobs already present in a WIM file, but not @wim,
* shall be returned in neither @blob_list_ret nor @blob_table_list_ret.
*
* @blob_list_ret
* List of blobs, linked by write_blobs_list, that need to be written will
* be returned here.
*
* Note that this function assumes that unhashed blobs will be written; it
* does not take into account that they may become duplicates when actually
* hashed.
*
* @blob_table_list_ret
* List of blobs, linked by blob_table_list, that need to be included in
* the WIM's blob table will be returned here. This will be a superset of
* the blobs in @blob_list_ret.
*
* This list will be a proper superset of @blob_list_ret if and only if
* WIMLIB_WRITE_FLAG_APPEND was specified in @write_flags and some of the
* blobs that would otherwise need to be written were already located in
* the WIM file.
*
* All blobs in this list will have @out_refcnt set to the number of
* references to the blob in the output WIM. If
* WIMLIB_WRITE_FLAG_STREAMS_OK was specified in @write_flags, @out_refcnt
* may be as low as 0.
*
* @filter_ctx_ret
* A context for queries of blob filter status with blob_filtered() is
* returned in this location.
*
* In addition, @will_be_in_output_wim will be set to 1 in all blobs inserted
* into @blob_table_list_ret and to 0 in all blobs in the blob table of @wim not
* inserted into @blob_table_list_ret.
*
* Still furthermore, @unique_size will be set to 1 on all blobs in
* @blob_list_ret that have unique size among all blobs in @blob_list_ret and
* among all blobs in the blob table of @wim that are ineligible for being
* written due to filtering.
*
* Returns 0 on success; nonzero on read error, memory allocation error, or
* otherwise.
*/
static int
prepare_blob_list_for_write(WIMStruct *wim, int image,
int write_flags,
struct list_head *blob_list_ret,
struct list_head *blob_table_list_ret,
struct filter_context *filter_ctx_ret)
{
int ret;
struct blob_descriptor *blob;
filter_ctx_ret->write_flags = write_flags;
filter_ctx_ret->wim = wim;
ret = prepare_unfiltered_list_of_blobs_in_output_wim(
wim,
image,
write_flags & WIMLIB_WRITE_FLAG_STREAMS_OK,
blob_list_ret);
if (ret)
return ret;
INIT_LIST_HEAD(blob_table_list_ret);
list_for_each_entry(blob, blob_list_ret, write_blobs_list)
list_add_tail(&blob->blob_table_list, blob_table_list_ret);
ret = determine_blob_size_uniquity(blob_list_ret, wim->blob_table,
filter_ctx_ret);
if (ret)
return ret;
if (may_filter_blobs(filter_ctx_ret))
filter_blob_list_for_write(blob_list_ret, filter_ctx_ret);
return 0;
}
static int
write_file_data(WIMStruct *wim, int image, int write_flags,
unsigned num_threads,
struct list_head *blob_list_override,
struct list_head *blob_table_list_ret)
{
int ret;
struct list_head _blob_list;
struct list_head *blob_list;
struct blob_descriptor *blob;
struct filter_context _filter_ctx;
struct filter_context *filter_ctx;
if (blob_list_override == NULL) {
/* Normal case: prepare blob list from image(s) being written.
*/
blob_list = &_blob_list;
filter_ctx = &_filter_ctx;
ret = prepare_blob_list_for_write(wim, image, write_flags,
blob_list,
blob_table_list_ret,
filter_ctx);
if (ret)
return ret;
} else {
/* Currently only as a result of wimlib_split() being called:
* use blob list already explicitly provided. Use existing
* reference counts. */
blob_list = blob_list_override;
filter_ctx = NULL;
INIT_LIST_HEAD(blob_table_list_ret);
list_for_each_entry(blob, blob_list, write_blobs_list) {
blob->out_refcnt = blob->refcnt;
blob->will_be_in_output_wim = 1;
blob->unique_size = 0;
list_add_tail(&blob->blob_table_list, blob_table_list_ret);
}
}
return write_file_data_blobs(wim,
blob_list,
write_flags,
num_threads,
filter_ctx);
}
static int
write_metadata_resources(WIMStruct *wim, int image, int write_flags)
{
int ret;
int start_image;
int end_image;
int write_resource_flags;
if (write_flags & WIMLIB_WRITE_FLAG_NO_METADATA)
return 0;
write_resource_flags = write_flags_to_resource_flags(write_flags);
write_resource_flags &= ~WRITE_RESOURCE_FLAG_SOLID;
ret = call_progress(wim->progfunc,
WIMLIB_PROGRESS_MSG_WRITE_METADATA_BEGIN,
NULL, wim->progctx);
if (ret)
return ret;
if (image == WIMLIB_ALL_IMAGES) {
start_image = 1;
end_image = wim->hdr.image_count;
} else {
start_image = image;
end_image = image;
}
for (int i = start_image; i <= end_image; i++) {
struct wim_image_metadata *imd;
imd = wim->image_metadata[i - 1];
if (is_image_dirty(imd)) {
/* The image was modified from the original, or was
* newly added, so we have to build and write a new
* metadata resource. */
ret = write_metadata_resource(wim, i,
write_resource_flags);
} else if (is_image_unchanged_from_wim(imd, wim) &&
(write_flags & (WIMLIB_WRITE_FLAG_UNSAFE_COMPACT |
WIMLIB_WRITE_FLAG_APPEND)))
{
/* The metadata resource is already in the WIM file.
* For appends, we don't need to write it at all. For
* compactions, we re-write existing metadata resources
* along with the existing file resources, not here. */
if (write_flags & WIMLIB_WRITE_FLAG_APPEND)
blob_set_out_reshdr_for_reuse(imd->metadata_blob);
ret = 0;
} else {
/* The metadata resource is in a WIM file other than the
* one being written to. We need to rewrite it,
* possibly compressed differently; but rebuilding the
* metadata itself isn't necessary. */
ret = write_wim_resource(imd->metadata_blob,
&wim->out_fd,
wim->out_compression_type,
wim->out_chunk_size,
write_resource_flags);
}
if (ret)
return ret;
}
return call_progress(wim->progfunc,
WIMLIB_PROGRESS_MSG_WRITE_METADATA_END,
NULL, wim->progctx);
}
static int
open_wim_writable(WIMStruct *wim, const tchar *path, int open_flags)
{
int raw_fd = topen(path, open_flags | O_BINARY, 0644);
if (raw_fd < 0) {
ERROR_WITH_ERRNO("Failed to open \"%"TS"\" for writing", path);
return WIMLIB_ERR_OPEN;
}
filedes_init(&wim->out_fd, raw_fd);
return 0;
}
static int
close_wim_writable(WIMStruct *wim, int write_flags)
{
int ret = 0;
if (!(write_flags & WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR))
if (filedes_valid(&wim->out_fd))
if (filedes_close(&wim->out_fd))
ret = WIMLIB_ERR_WRITE;
filedes_invalidate(&wim->out_fd);
return ret;
}
static int
cmp_blobs_by_out_rdesc(const void *p1, const void *p2)
{
const struct blob_descriptor *blob1, *blob2;
blob1 = *(const struct blob_descriptor**)p1;
blob2 = *(const struct blob_descriptor**)p2;
if (blob1->out_reshdr.flags & WIM_RESHDR_FLAG_SOLID) {
if (blob2->out_reshdr.flags & WIM_RESHDR_FLAG_SOLID) {
if (blob1->out_res_offset_in_wim != blob2->out_res_offset_in_wim)
return cmp_u64(blob1->out_res_offset_in_wim,
blob2->out_res_offset_in_wim);
} else {
return 1;
}
} else {
if (blob2->out_reshdr.flags & WIM_RESHDR_FLAG_SOLID)
return -1;
}
return cmp_u64(blob1->out_reshdr.offset_in_wim,
blob2->out_reshdr.offset_in_wim);
}
static int
write_blob_table(WIMStruct *wim, int image, int write_flags,
struct list_head *blob_table_list)
{
int ret;
/* Set output resource metadata for blobs already present in WIM. */
if (write_flags & WIMLIB_WRITE_FLAG_APPEND) {
struct blob_descriptor *blob;
list_for_each_entry(blob, blob_table_list, blob_table_list) {
if (blob->blob_location == BLOB_IN_WIM &&
blob->rdesc->wim == wim)
{
blob_set_out_reshdr_for_reuse(blob);
}
}
}
ret = sort_blob_list(blob_table_list,
offsetof(struct blob_descriptor, blob_table_list),
cmp_blobs_by_out_rdesc);
if (ret)
return ret;
/* Add entries for metadata resources. */
if (!(write_flags & WIMLIB_WRITE_FLAG_NO_METADATA)) {
int start_image;
int end_image;
if (image == WIMLIB_ALL_IMAGES) {
start_image = 1;
end_image = wim->hdr.image_count;
} else {
start_image = image;
end_image = image;
}
/* Push metadata blob table entries onto the front of the list
* in reverse order, so that they're written in order.
*/
for (int i = end_image; i >= start_image; i--) {
struct blob_descriptor *metadata_blob;
metadata_blob = wim->image_metadata[i - 1]->metadata_blob;
wimlib_assert(metadata_blob->out_reshdr.flags & WIM_RESHDR_FLAG_METADATA);
metadata_blob->out_refcnt = 1;
list_add(&metadata_blob->blob_table_list, blob_table_list);
}
}
return write_blob_table_from_blob_list(blob_table_list,
&wim->out_fd,
wim->out_hdr.part_number,
&wim->out_hdr.blob_table_reshdr,
write_flags_to_resource_flags(write_flags));
}
/*
* Finish writing a WIM file: write the blob table, xml data, and integrity
* table, then overwrite the WIM header.
*
* The output file descriptor is closed on success, except when writing to a
* user-specified file descriptor (WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR set).
*/
static int
finish_write(WIMStruct *wim, int image, int write_flags,
struct list_head *blob_table_list)
{
int write_resource_flags;
off_t old_blob_table_end = 0;
struct integrity_table *old_integrity_table = NULL;
off_t new_blob_table_end;
u64 xml_totalbytes;
int ret;
write_resource_flags = write_flags_to_resource_flags(write_flags);
/* In the WIM header, there is room for the resource entry for a
* metadata resource labeled as the "boot metadata". This entry should
* be zeroed out if there is no bootable image (boot_idx 0). Otherwise,
* it should be a copy of the resource entry for the image that is
* marked as bootable. */
if (wim->out_hdr.boot_idx == 0) {
zero_reshdr(&wim->out_hdr.boot_metadata_reshdr);
} else {
copy_reshdr(&wim->out_hdr.boot_metadata_reshdr,
&wim->image_metadata[
wim->out_hdr.boot_idx - 1]->metadata_blob->out_reshdr);
}
/* If appending to a WIM file containing an integrity table, we'd like
* to re-use the information in the old integrity table instead of
* recalculating it. But we might overwrite the old integrity table
* when we expand the XML data. Read it into memory just in case. */
if ((write_flags & (WIMLIB_WRITE_FLAG_APPEND |
WIMLIB_WRITE_FLAG_CHECK_INTEGRITY)) ==
(WIMLIB_WRITE_FLAG_APPEND |
WIMLIB_WRITE_FLAG_CHECK_INTEGRITY)
&& wim_has_integrity_table(wim))
{
old_blob_table_end = wim->hdr.blob_table_reshdr.offset_in_wim +
wim->hdr.blob_table_reshdr.size_in_wim;
(void)read_integrity_table(wim,
old_blob_table_end - WIM_HEADER_DISK_SIZE,
&old_integrity_table);
/* If we couldn't read the old integrity table, we can still
* re-calculate the full integrity table ourselves. Hence the
* ignoring of the return value. */
}
/* Write blob table if needed. */
if (!(write_flags & WIMLIB_WRITE_FLAG_NO_NEW_BLOBS)) {
ret = write_blob_table(wim, image, write_flags,
blob_table_list);
if (ret)
goto out;
}
/* Write XML data. */
xml_totalbytes = wim->out_fd.offset;
if (write_flags & WIMLIB_WRITE_FLAG_USE_EXISTING_TOTALBYTES)
xml_totalbytes = WIM_TOTALBYTES_USE_EXISTING;
ret = write_wim_xml_data(wim, image, xml_totalbytes,
&wim->out_hdr.xml_data_reshdr,
write_resource_flags);
if (ret)
goto out;
/* Write integrity table if needed. */
if ((write_flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY) &&
wim->out_hdr.blob_table_reshdr.offset_in_wim != 0)
{
if (write_flags & WIMLIB_WRITE_FLAG_NO_NEW_BLOBS) {
/* The XML data we wrote may have overwritten part of
* the old integrity table, so while calculating the new
* integrity table we should temporarily update the WIM
* header to remove the integrity table reference. */
struct wim_header checkpoint_hdr;
memcpy(&checkpoint_hdr, &wim->out_hdr, sizeof(struct wim_header));
zero_reshdr(&checkpoint_hdr.integrity_table_reshdr);
checkpoint_hdr.flags |= WIM_HDR_FLAG_WRITE_IN_PROGRESS;
ret = write_wim_header(&checkpoint_hdr, &wim->out_fd, 0);
if (ret)
goto out;
}
new_blob_table_end = wim->out_hdr.blob_table_reshdr.offset_in_wim +
wim->out_hdr.blob_table_reshdr.size_in_wim;
ret = write_integrity_table(wim,
new_blob_table_end,
old_blob_table_end,
old_integrity_table);
if (ret)
goto out;
} else {
/* No integrity table. */
zero_reshdr(&wim->out_hdr.integrity_table_reshdr);
}
/* Now that all information in the WIM header has been determined, the
* preliminary header written earlier can be overwritten, the header of
* the existing WIM file can be overwritten, or the final header can be
* written to the end of the pipable WIM. */
wim->out_hdr.flags &= ~WIM_HDR_FLAG_WRITE_IN_PROGRESS;
if (write_flags & WIMLIB_WRITE_FLAG_PIPABLE)
ret = write_wim_header(&wim->out_hdr, &wim->out_fd, wim->out_fd.offset);
else
ret = write_wim_header(&wim->out_hdr, &wim->out_fd, 0);
if (ret)
goto out;
ret = WIMLIB_ERR_WRITE;
if (unlikely(write_flags & WIMLIB_WRITE_FLAG_UNSAFE_COMPACT)) {
/* Truncate any data the compaction freed up. */
if (ftruncate(wim->out_fd.fd, wim->out_fd.offset) &&
errno != EINVAL) /* allow compaction on untruncatable files,
e.g. block devices */
{
ERROR_WITH_ERRNO("Failed to truncate the output WIM file");
goto out;
}
}
/* Possibly sync file data to disk before closing. On POSIX systems, it
* is necessary to do this before using rename() to overwrite an
* existing file with a new file. Otherwise, data loss would occur if
* the system is abruptly terminated when the metadata for the rename
* operation has been written to disk, but the new file data has not.
*/
ret = WIMLIB_ERR_WRITE;
if (write_flags & WIMLIB_WRITE_FLAG_FSYNC) {
if (fsync(wim->out_fd.fd)) {
ERROR_WITH_ERRNO("Error syncing data to WIM file");
goto out;
}
}
ret = WIMLIB_ERR_WRITE;
if (close_wim_writable(wim, write_flags)) {
ERROR_WITH_ERRNO("Failed to close the output WIM file");
goto out;
}
ret = 0;
out:
free_integrity_table(old_integrity_table);
return ret;
}
#if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK)
/* Set advisory lock on WIM file (if not already done so) */
int
lock_wim_for_append(WIMStruct *wim)
{
if (wim->locked_for_append)
return 0;
if (!flock(wim->in_fd.fd, LOCK_EX | LOCK_NB)) {
wim->locked_for_append = 1;
return 0;
}
if (errno != EWOULDBLOCK)
return 0;
return WIMLIB_ERR_ALREADY_LOCKED;
}
/* Remove advisory lock on WIM file (if present) */
void
unlock_wim_for_append(WIMStruct *wim)
{
if (wim->locked_for_append) {
flock(wim->in_fd.fd, LOCK_UN);
wim->locked_for_append = 0;
}
}
#endif
/*
* write_pipable_wim():
*
* Perform the intermediate stages of creating a "pipable" WIM (i.e. a WIM
* capable of being applied from a pipe).
*
* Pipable WIMs are a wimlib-specific modification of the WIM format such that
* images can be applied from them sequentially when the file data is sent over
* a pipe. In addition, a pipable WIM can be written sequentially to a pipe.
* The modifications made to the WIM format for pipable WIMs are:
*
* - Magic characters in header are "WLPWM\0\0\0" (wimlib pipable WIM) instead
* of "MSWIM\0\0\0". This lets wimlib know that the WIM is pipable and also
* stops other software from trying to read the file as a normal WIM.
*
* - The header at the beginning of the file does not contain all the normal
* information; in particular it will have all 0's for the blob table and XML
* data resource entries. This is because this information cannot be
* determined until the blob table and XML data have been written.
* Consequently, wimlib will write the full header at the very end of the
* file. The header at the end, however, is only used when reading the WIM
* from a seekable file (not a pipe).
*
* - An extra copy of the XML data is placed directly after the header. This
* allows image names and sizes to be determined at an appropriate time when
* reading the WIM from a pipe. This copy of the XML data is ignored if the
* WIM is read from a seekable file (not a pipe).
*
* - Solid resources are not allowed. Each blob is always stored in its own
* resource.
*
* - The format of resources, or blobs, has been modified to allow them to be
* used before the "blob table" has been read. Each blob is prefixed with a
* `struct pwm_blob_hdr' that is basically an abbreviated form of `struct
* blob_descriptor_disk' that only contains the SHA-1 message digest,
* uncompressed blob size, and flags that indicate whether the blob is
* compressed. The data of uncompressed blobs then follows literally, while
* the data of compressed blobs follows in a modified format. Compressed
* blobs do not begin with a chunk table, since the chunk table cannot be
* written until all chunks have been compressed. Instead, each compressed
* chunk is prefixed by a `struct pwm_chunk_hdr' that gives its size.
* Furthermore, the chunk table is written at the end of the resource instead
* of the start. Note: chunk offsets are given in the chunk table as if the
* `struct pwm_chunk_hdr's were not present; also, the chunk table is only
* used if the WIM is being read from a seekable file (not a pipe).
*
* - Metadata blobs always come before non-metadata blobs. (This does not by
* itself constitute an incompatibility with normal WIMs, since this is valid
* in normal WIMs.)
*
* - At least up to the end of the blobs, all components must be packed as
* tightly as possible; there cannot be any "holes" in the WIM. (This does
* not by itself consititute an incompatibility with normal WIMs, since this
* is valid in normal WIMs.)
*
* Note: the blob table, XML data, and header at the end are not used when
* applying from a pipe. They exist to support functionality such as image
* application and export when the WIM is *not* read from a pipe.
*
* Layout of pipable WIM:
*
* ---------+----------+--------------------+----------------+--------------+-----------+--------+
* | Header | XML data | Metadata resources | File resources | Blob table | XML data | Header |
* ---------+----------+--------------------+----------------+--------------+-----------+--------+
*
* Layout of normal WIM:
*
* +--------+-----------------------------+-------------------------+
* | Header | File and metadata resources | Blob table | XML data |
* +--------+-----------------------------+-------------------------+
*
* An optional integrity table can follow the final XML data in both normal and
* pipable WIMs. However, due to implementation details, wimlib currently can
* only include an integrity table in a pipable WIM when writing it to a
* seekable file (not a pipe).
*
* Do note that since pipable WIMs are not supported by Microsoft's software,
* wimlib does not create them unless explicitly requested (with
* WIMLIB_WRITE_FLAG_PIPABLE) and as stated above they use different magic
* characters to identify the file.
*/
static int
write_pipable_wim(WIMStruct *wim, int image, int write_flags,
unsigned num_threads,
struct list_head *blob_list_override,
struct list_head *blob_table_list_ret)
{
int ret;
struct wim_reshdr xml_reshdr;
WARNING("Creating a pipable WIM, which will "
"be incompatible\n"
" with Microsoft's software (WIMGAPI/ImageX/DISM).");
/* At this point, the header at the beginning of the file has already
* been written. */
/*
* For efficiency, wimlib normally delays calculating each newly added
* stream's hash until while that stream being written, or just before
* it is written. However, when writing a pipable WIM (potentially to a
* pipe), we first have to write the metadata resources, which contain
* all the hashes. Moreover each blob is prefixed with its hash (struct
* pwm_blob_hdr). Thus, we have to calculate all the hashes before
* writing anything.
*/
ret = wim_checksum_unhashed_blobs(wim);
if (ret)
return ret;
/* Write extra copy of the XML data. */
ret = write_wim_xml_data(wim, image, WIM_TOTALBYTES_OMIT,
&xml_reshdr, WRITE_RESOURCE_FLAG_PIPABLE);
if (ret)
return ret;
/* Write metadata resources for the image(s) being included in the
* output WIM. */
ret = write_metadata_resources(wim, image, write_flags);
if (ret)
return ret;
/* Write file data needed for the image(s) being included in the output
* WIM, or file data needed for the split WIM part. */
return write_file_data(wim, image, write_flags,
num_threads, blob_list_override,
blob_table_list_ret);
/* The blob table, XML data, and header at end are handled by
* finish_write(). */
}
static bool
should_default_to_solid_compression(WIMStruct *wim, int write_flags)
{
return wim->out_hdr.wim_version == WIM_VERSION_SOLID &&
!(write_flags & (WIMLIB_WRITE_FLAG_SOLID |
WIMLIB_WRITE_FLAG_PIPABLE)) &&
wim_has_solid_resources(wim);
}
/* Update the images' filecount/bytecount stats (in the XML info) to take into
* account any recent modifications. */
static int
update_image_stats(WIMStruct *wim)
{
if (!wim_has_metadata(wim))
return 0;
for (int i = 0; i < wim->hdr.image_count; i++) {
struct wim_image_metadata *imd = wim->image_metadata[i];
if (imd->stats_outdated) {
int ret = xml_update_image_info(wim, i + 1);
if (ret)
return ret;
imd->stats_outdated = false;
}
}
return 0;
}
/* Write a standalone WIM or split WIM (SWM) part to a new file or to a file
* descriptor. */
int
write_wim_part(WIMStruct *wim,
const void *path_or_fd,
int image,
int write_flags,
unsigned num_threads,
unsigned part_number,
unsigned total_parts,
struct list_head *blob_list_override,
const u8 *guid)
{
int ret;
struct list_head blob_table_list;
/* Internally, this is always called with a valid part number and total
* parts. */
wimlib_assert(total_parts >= 1);
wimlib_assert(part_number >= 1 && part_number <= total_parts);
/* A valid image (or all images) must be specified. */
if (image != WIMLIB_ALL_IMAGES &&
(image < 1 || image > wim->hdr.image_count))
return WIMLIB_ERR_INVALID_IMAGE;
/* If we need to write metadata resources, make sure the ::WIMStruct has
* the needed information attached (e.g. is not a resource-only WIM,
* such as a non-first part of a split WIM). */
if (!wim_has_metadata(wim) &&
!(write_flags & WIMLIB_WRITE_FLAG_NO_METADATA))
return WIMLIB_ERR_METADATA_NOT_FOUND;
/* Check for contradictory flags. */
if ((write_flags & (WIMLIB_WRITE_FLAG_CHECK_INTEGRITY |
WIMLIB_WRITE_FLAG_NO_CHECK_INTEGRITY))
== (WIMLIB_WRITE_FLAG_CHECK_INTEGRITY |
WIMLIB_WRITE_FLAG_NO_CHECK_INTEGRITY))
return WIMLIB_ERR_INVALID_PARAM;
if ((write_flags & (WIMLIB_WRITE_FLAG_PIPABLE |
WIMLIB_WRITE_FLAG_NOT_PIPABLE))
== (WIMLIB_WRITE_FLAG_PIPABLE |
WIMLIB_WRITE_FLAG_NOT_PIPABLE))
return WIMLIB_ERR_INVALID_PARAM;
/* Only wimlib_overwrite() accepts UNSAFE_COMPACT. */
if (write_flags & WIMLIB_WRITE_FLAG_UNSAFE_COMPACT)
return WIMLIB_ERR_INVALID_PARAM;
/* Include an integrity table by default if no preference was given and
* the WIM already had an integrity table. */
if (!(write_flags & (WIMLIB_WRITE_FLAG_CHECK_INTEGRITY |
WIMLIB_WRITE_FLAG_NO_CHECK_INTEGRITY))) {
if (wim_has_integrity_table(wim))
write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
}
/* Write a pipable WIM by default if no preference was given and the WIM
* was already pipable. */
if (!(write_flags & (WIMLIB_WRITE_FLAG_PIPABLE |
WIMLIB_WRITE_FLAG_NOT_PIPABLE))) {
if (wim_is_pipable(wim))
write_flags |= WIMLIB_WRITE_FLAG_PIPABLE;
}
if ((write_flags & (WIMLIB_WRITE_FLAG_PIPABLE |
WIMLIB_WRITE_FLAG_SOLID))
== (WIMLIB_WRITE_FLAG_PIPABLE |
WIMLIB_WRITE_FLAG_SOLID))
{
ERROR("Solid compression is unsupported in pipable WIMs");
return WIMLIB_ERR_INVALID_PARAM;
}
/* Start initializing the new file header. */
memset(&wim->out_hdr, 0, sizeof(wim->out_hdr));
/* Set the magic number. */
if (write_flags & WIMLIB_WRITE_FLAG_PIPABLE)
wim->out_hdr.magic = PWM_MAGIC;
else
wim->out_hdr.magic = WIM_MAGIC;
/* Set the version number. */
if ((write_flags & WIMLIB_WRITE_FLAG_SOLID) ||
wim->out_compression_type == WIMLIB_COMPRESSION_TYPE_LZMS)
wim->out_hdr.wim_version = WIM_VERSION_SOLID;
else
wim->out_hdr.wim_version = WIM_VERSION_DEFAULT;
/* Default to solid compression if it is valid in the chosen WIM file
* format and the WIMStruct references any solid resources. This is
* useful when exporting an image from a solid WIM. */
if (should_default_to_solid_compression(wim, write_flags))
write_flags |= WIMLIB_WRITE_FLAG_SOLID;
/* Set the header flags. */
wim->out_hdr.flags = (wim->hdr.flags & (WIM_HDR_FLAG_RP_FIX |
WIM_HDR_FLAG_READONLY));
if (total_parts != 1)
wim->out_hdr.flags |= WIM_HDR_FLAG_SPANNED;
if (wim->out_compression_type != WIMLIB_COMPRESSION_TYPE_NONE) {
wim->out_hdr.flags |= WIM_HDR_FLAG_COMPRESSION;
switch (wim->out_compression_type) {
case WIMLIB_COMPRESSION_TYPE_XPRESS:
wim->out_hdr.flags |= WIM_HDR_FLAG_COMPRESS_XPRESS;
break;
case WIMLIB_COMPRESSION_TYPE_LZX:
wim->out_hdr.flags |= WIM_HDR_FLAG_COMPRESS_LZX;
break;
case WIMLIB_COMPRESSION_TYPE_LZMS:
wim->out_hdr.flags |= WIM_HDR_FLAG_COMPRESS_LZMS;
break;
}
}
/* Set the chunk size. */
wim->out_hdr.chunk_size = wim->out_chunk_size;
/* Set the GUID. */
if (write_flags & WIMLIB_WRITE_FLAG_RETAIN_GUID)
guid = wim->hdr.guid;
if (guid)
copy_guid(wim->out_hdr.guid, guid);
else
generate_guid(wim->out_hdr.guid);
/* Set the part number and total parts. */
wim->out_hdr.part_number = part_number;
wim->out_hdr.total_parts = total_parts;
/* Set the image count. */
if (image == WIMLIB_ALL_IMAGES)
wim->out_hdr.image_count = wim->hdr.image_count;
else
wim->out_hdr.image_count = 1;
/* Set the boot index. */
wim->out_hdr.boot_idx = 0;
if (total_parts == 1) {
if (image == WIMLIB_ALL_IMAGES)
wim->out_hdr.boot_idx = wim->hdr.boot_idx;
else if (image == wim->hdr.boot_idx)
wim->out_hdr.boot_idx = 1;
}
/* Update image stats if needed. */
ret = update_image_stats(wim);
if (ret)
return ret;
/* Set up the output file descriptor. */
if (write_flags & WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR) {
/* File descriptor was explicitly provided. */
filedes_init(&wim->out_fd, *(const int *)path_or_fd);
if (!filedes_is_seekable(&wim->out_fd)) {
/* The file descriptor is a pipe. */
ret = WIMLIB_ERR_INVALID_PARAM;
if (!(write_flags & WIMLIB_WRITE_FLAG_PIPABLE))
goto out_cleanup;
if (write_flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY) {
ERROR("Can't include integrity check when "
"writing pipable WIM to pipe!");
goto out_cleanup;
}
}
} else {
/* Filename of WIM to write was provided; open file descriptor
* to it. */
ret = open_wim_writable(wim, (const tchar*)path_or_fd,
O_TRUNC | O_CREAT | O_RDWR);
if (ret)
goto out_cleanup;
}
/* Write initial header. This is merely a "dummy" header since it
* doesn't have resource entries filled in yet, so it will be
* overwritten later (unless writing a pipable WIM). */
if (!(write_flags & WIMLIB_WRITE_FLAG_PIPABLE))
wim->out_hdr.flags |= WIM_HDR_FLAG_WRITE_IN_PROGRESS;
ret = write_wim_header(&wim->out_hdr, &wim->out_fd, wim->out_fd.offset);
wim->out_hdr.flags &= ~WIM_HDR_FLAG_WRITE_IN_PROGRESS;
if (ret)
goto out_cleanup;
/* Write file data and metadata resources. */
if (!(write_flags & WIMLIB_WRITE_FLAG_PIPABLE)) {
/* Default case: create a normal (non-pipable) WIM. */
ret = write_file_data(wim, image, write_flags,
num_threads,
blob_list_override,
&blob_table_list);
if (ret)
goto out_cleanup;
ret = write_metadata_resources(wim, image, write_flags);
if (ret)
goto out_cleanup;
} else {
/* Non-default case: create pipable WIM. */
ret = write_pipable_wim(wim, image, write_flags, num_threads,
blob_list_override,
&blob_table_list);
if (ret)
goto out_cleanup;
}
/* Write blob table, XML data, and (optional) integrity table. */
ret = finish_write(wim, image, write_flags, &blob_table_list);
out_cleanup:
(void)close_wim_writable(wim, write_flags);
return ret;
}
/* Write a standalone WIM to a file or file descriptor. */
static int
write_standalone_wim(WIMStruct *wim, const void *path_or_fd,
int image, int write_flags, unsigned num_threads)
{
return write_wim_part(wim, path_or_fd, image, write_flags,
num_threads, 1, 1, NULL, NULL);
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_write(WIMStruct *wim, const tchar *path,
int image, int write_flags, unsigned num_threads)
{
if (write_flags & ~WIMLIB_WRITE_MASK_PUBLIC)
return WIMLIB_ERR_INVALID_PARAM;
if (path == NULL || path[0] == T('\0'))
return WIMLIB_ERR_INVALID_PARAM;
return write_standalone_wim(wim, path, image, write_flags, num_threads);
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_write_to_fd(WIMStruct *wim, int fd,
int image, int write_flags, unsigned num_threads)
{
if (write_flags & ~WIMLIB_WRITE_MASK_PUBLIC)
return WIMLIB_ERR_INVALID_PARAM;
if (fd < 0)
return WIMLIB_ERR_INVALID_PARAM;
write_flags |= WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR;
return write_standalone_wim(wim, &fd, image, write_flags, num_threads);
}
/* Have there been any changes to images in the specified WIM, including updates
* as well as deletions and additions of entire images, but excluding changes to
* the XML document? */
static bool
any_images_changed(WIMStruct *wim)
{
if (wim->image_deletion_occurred)
return true;
for (int i = 0; i < wim->hdr.image_count; i++)
if (!is_image_unchanged_from_wim(wim->image_metadata[i], wim))
return true;
return false;
}
static int
check_resource_offset(struct blob_descriptor *blob, void *_wim)
{
const WIMStruct *wim = _wim;
off_t end_offset = *(const off_t*)wim->private;
if (blob->blob_location == BLOB_IN_WIM &&
blob->rdesc->wim == wim &&
blob->rdesc->offset_in_wim + blob->rdesc->size_in_wim > end_offset)
return WIMLIB_ERR_RESOURCE_ORDER;
return 0;
}
/* Make sure no file or metadata resources are located after the XML data (or
* integrity table if present)--- otherwise we can't safely append to the WIM
* file and we return WIMLIB_ERR_RESOURCE_ORDER. */
static int
check_resource_offsets(WIMStruct *wim, off_t end_offset)
{
int ret;
unsigned i;
wim->private = &end_offset;
ret = for_blob_in_table(wim->blob_table, check_resource_offset, wim);
if (ret)
return ret;
for (i = 0; i < wim->hdr.image_count; i++) {
ret = check_resource_offset(wim->image_metadata[i]->metadata_blob, wim);
if (ret)
return ret;
}
return 0;
}
static int
free_blob_if_invalidated(struct blob_descriptor *blob, void *_wim)
{
const WIMStruct *wim = _wim;
if (!blob->will_be_in_output_wim &&
blob->blob_location == BLOB_IN_WIM && blob->rdesc->wim == wim)
{
blob_table_unlink(wim->blob_table, blob);
free_blob_descriptor(blob);
}
return 0;
}
/*
* Overwrite a WIM, possibly appending new resources to it.
*
* A WIM looks like (or is supposed to look like) the following:
*
* Header (212 bytes)
* Resources for metadata and files (variable size)
* Blob table (variable size)
* XML data (variable size)
* Integrity table (optional) (variable size)
*
* If we are not adding any new files or metadata, then the blob table is
* unchanged--- so we only need to overwrite the XML data, integrity table, and
* header. This operation is potentially unsafe if the program is abruptly
* terminated while the XML data or integrity table are being overwritten, but
* before the new header has been written. To partially alleviate this problem,
* we write a temporary header after the XML data has been written. This may
* prevent the WIM from becoming corrupted if the program is terminated while
* the integrity table is being calculated (but no guarantees, due to write
* re-ordering...).
*
* If we are adding new blobs, including new file data as well as any metadata
* for any new images, then the blob table needs to be changed, and those blobs
* need to be written. In this case, we try to perform a safe update of the WIM
* file by writing the blobs *after* the end of the previous WIM, then writing
* the new blob table, XML data, and (optionally) integrity table following the
* new blobs. This will produce a layout like the following:
*
* Header (212 bytes)
* (OLD) Resources for metadata and files (variable size)
* (OLD) Blob table (variable size)
* (OLD) XML data (variable size)
* (OLD) Integrity table (optional) (variable size)
* (NEW) Resources for metadata and files (variable size)
* (NEW) Blob table (variable size)
* (NEW) XML data (variable size)
* (NEW) Integrity table (optional) (variable size)
*
* At all points, the WIM is valid as nothing points to the new data yet. Then,
* the header is overwritten to point to the new blob table, XML data, and
* integrity table, to produce the following layout:
*
* Header (212 bytes)
* Resources for metadata and files (variable size)
* Nothing (variable size)
* Resources for metadata and files (variable size)
* Blob table (variable size)
* XML data (variable size)
* Integrity table (optional) (variable size)
*
* This function allows an image to be appended to a large WIM very quickly, and
* is crash-safe except in the case of write re-ordering, but the disadvantage
* is that a small hole is left in the WIM where the old blob table, xml data,
* and integrity table were. (These usually only take up a small amount of
* space compared to the blobs, however.)
*
* Finally, this function also supports "compaction" overwrites as an
* alternative to the normal "append" overwrites described above. In a
* compaction, data is written starting immediately from the end of the header.
* All existing resources are written first, in order by file offset. New
* resources are written afterwards, and at the end any extra data is truncated
* from the file. The advantage of this approach is that is that the WIM file
* ends up fully optimized, without any holes remaining. The main disadavantage
* is that this operation is fundamentally unsafe and cannot be interrupted
* without data corruption. Consequently, compactions are only ever done when
* explicitly requested by the library user with the flag
* WIMLIB_WRITE_FLAG_UNSAFE_COMPACT. (Another disadvantage is that a compaction
* can be much slower than an append.)
*/
static int
overwrite_wim_inplace(WIMStruct *wim, int write_flags, unsigned num_threads)
{
int ret;
off_t old_wim_end;
struct list_head blob_list;
struct list_head blob_table_list;
struct filter_context filter_ctx;
/* Include an integrity table by default if no preference was given and
* the WIM already had an integrity table. */
if (!(write_flags & (WIMLIB_WRITE_FLAG_CHECK_INTEGRITY |
WIMLIB_WRITE_FLAG_NO_CHECK_INTEGRITY)))
if (wim_has_integrity_table(wim))
write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
/* Start preparing the updated file header. */
memcpy(&wim->out_hdr, &wim->hdr, sizeof(wim->out_hdr));
/* If using solid compression, the version number must be set to
* WIM_VERSION_SOLID. */
if (write_flags & WIMLIB_WRITE_FLAG_SOLID)
wim->out_hdr.wim_version = WIM_VERSION_SOLID;
/* Default to solid compression if it is valid in the chosen WIM file
* format and the WIMStruct references any solid resources. This is
* useful when updating a solid WIM. */
if (should_default_to_solid_compression(wim, write_flags))
write_flags |= WIMLIB_WRITE_FLAG_SOLID;
if (unlikely(write_flags & WIMLIB_WRITE_FLAG_UNSAFE_COMPACT)) {
/* In-place compaction */
WARNING("The WIM file \"%"TS"\" is being compacted in place.\n"
" Do *not* interrupt the operation, or else "
"the WIM file will be\n"
" corrupted!", wim->filename);
wim->being_compacted = 1;
old_wim_end = WIM_HEADER_DISK_SIZE;
ret = prepare_blob_list_for_write(wim, WIMLIB_ALL_IMAGES,
write_flags, &blob_list,
&blob_table_list, &filter_ctx);
if (ret)
goto out;
/* Prevent new files from being deduplicated with existing blobs
* in the WIM that we haven't decided to write. Such blobs will
* be overwritten during the compaction. */
for_blob_in_table(wim->blob_table, free_blob_if_invalidated, wim);
if (wim_has_metadata(wim)) {
/* Add existing metadata resources to be compacted along
* with the file resources. */
for (int i = 0; i < wim->hdr.image_count; i++) {
struct wim_image_metadata *imd = wim->image_metadata[i];
if (is_image_unchanged_from_wim(imd, wim)) {
fully_reference_blob_for_write(imd->metadata_blob,
&blob_list);
}
}
}
} else {
u64 old_blob_table_end, old_xml_begin, old_xml_end;
/* Set additional flags for append. */
write_flags |= WIMLIB_WRITE_FLAG_APPEND |
WIMLIB_WRITE_FLAG_STREAMS_OK;
/* Make sure there is no data after the XML data, except
* possibily an integrity table. If this were the case, then
* this data would be overwritten. */
old_xml_begin = wim->hdr.xml_data_reshdr.offset_in_wim;
old_xml_end = old_xml_begin + wim->hdr.xml_data_reshdr.size_in_wim;
if (wim->hdr.blob_table_reshdr.offset_in_wim == 0)
old_blob_table_end = WIM_HEADER_DISK_SIZE;
else
old_blob_table_end = wim->hdr.blob_table_reshdr.offset_in_wim +
wim->hdr.blob_table_reshdr.size_in_wim;
if (wim_has_integrity_table(wim) &&
wim->hdr.integrity_table_reshdr.offset_in_wim < old_xml_end) {
WARNING("Didn't expect the integrity table to be "
"before the XML data");
ret = WIMLIB_ERR_RESOURCE_ORDER;
goto out;
}
if (old_blob_table_end > old_xml_begin) {
WARNING("Didn't expect the blob table to be after "
"the XML data");
ret = WIMLIB_ERR_RESOURCE_ORDER;
goto out;
}
/* Set @old_wim_end, which indicates the point beyond which we
* don't allow any file and metadata resources to appear without
* returning WIMLIB_ERR_RESOURCE_ORDER (due to the fact that we
* would otherwise overwrite these resources). */
if (!any_images_changed(wim)) {
/* If no images have been modified, added, or deleted,
* then a new blob table does not need to be written.
* We shall write the new XML data and optional
* integrity table immediately after the blob table.
* Note that this may overwrite an existing integrity
* table. */
old_wim_end = old_blob_table_end;
write_flags |= WIMLIB_WRITE_FLAG_NO_NEW_BLOBS;
} else if (wim_has_integrity_table(wim)) {
/* Old WIM has an integrity table; begin writing new
* blobs after it. */
old_wim_end = wim->hdr.integrity_table_reshdr.offset_in_wim +
wim->hdr.integrity_table_reshdr.size_in_wim;
} else {
/* No existing integrity table; begin writing new blobs
* after the old XML data. */
old_wim_end = old_xml_end;
}
ret = check_resource_offsets(wim, old_wim_end);
if (ret)
goto out;
ret = prepare_blob_list_for_write(wim, WIMLIB_ALL_IMAGES,
write_flags, &blob_list,
&blob_table_list, &filter_ctx);
if (ret)
goto out;
if (write_flags & WIMLIB_WRITE_FLAG_NO_NEW_BLOBS)
wimlib_assert(list_empty(&blob_list));
}
/* Update image stats if needed. */
ret = update_image_stats(wim);
if (ret)
goto out;
ret = open_wim_writable(wim, wim->filename, O_RDWR);
if (ret)
goto out;
ret = lock_wim_for_append(wim);
if (ret)
goto out_close_wim;
/* Set WIM_HDR_FLAG_WRITE_IN_PROGRESS flag in header. */
wim->hdr.flags |= WIM_HDR_FLAG_WRITE_IN_PROGRESS;
ret = write_wim_header_flags(wim->hdr.flags, &wim->out_fd);
wim->hdr.flags &= ~WIM_HDR_FLAG_WRITE_IN_PROGRESS;
if (ret) {
ERROR_WITH_ERRNO("Error updating WIM header flags");
goto out_unlock_wim;
}
if (filedes_seek(&wim->out_fd, old_wim_end) == -1) {
ERROR_WITH_ERRNO("Can't seek to end of WIM");
ret = WIMLIB_ERR_WRITE;
goto out_restore_hdr;
}
ret = write_file_data_blobs(wim, &blob_list, write_flags,
num_threads, &filter_ctx);
if (ret)
goto out_truncate;
ret = write_metadata_resources(wim, WIMLIB_ALL_IMAGES, write_flags);
if (ret)
goto out_truncate;
ret = finish_write(wim, WIMLIB_ALL_IMAGES, write_flags,
&blob_table_list);
if (ret)
goto out_truncate;
unlock_wim_for_append(wim);
return 0;
out_truncate:
if (!(write_flags & (WIMLIB_WRITE_FLAG_NO_NEW_BLOBS |
WIMLIB_WRITE_FLAG_UNSAFE_COMPACT))) {
WARNING("Truncating \"%"TS"\" to its original size "
"(%"PRIu64" bytes)", wim->filename, old_wim_end);
if (ftruncate(wim->out_fd.fd, old_wim_end))
WARNING_WITH_ERRNO("Failed to truncate WIM file!");
}
out_restore_hdr:
(void)write_wim_header_flags(wim->hdr.flags, &wim->out_fd);
out_unlock_wim:
unlock_wim_for_append(wim);
out_close_wim:
(void)close_wim_writable(wim, write_flags);
out:
wim->being_compacted = 0;
return ret;
}
static int
overwrite_wim_via_tmpfile(WIMStruct *wim, int write_flags, unsigned num_threads)
{
size_t wim_name_len;
int ret;
/* Write the WIM to a temporary file in the same directory as the
* original WIM. */
wim_name_len = tstrlen(wim->filename);
tchar tmpfile[wim_name_len + 10];
tmemcpy(tmpfile, wim->filename, wim_name_len);
get_random_alnum_chars(tmpfile + wim_name_len, 9);
tmpfile[wim_name_len + 9] = T('\0');
ret = wimlib_write(wim, tmpfile, WIMLIB_ALL_IMAGES,
write_flags |
WIMLIB_WRITE_FLAG_FSYNC |
WIMLIB_WRITE_FLAG_RETAIN_GUID,
num_threads);
if (ret) {
tunlink(tmpfile);
return ret;
}
if (filedes_valid(&wim->in_fd)) {
filedes_close(&wim->in_fd);
filedes_invalidate(&wim->in_fd);
}
/* Rename the new WIM file to the original WIM file. Note: on Windows
* this actually calls win32_rename_replacement(), not _wrename(), so
* that removing the existing destination file can be handled. */
ret = trename(tmpfile, wim->filename);
if (ret) {
ERROR_WITH_ERRNO("Failed to rename `%"TS"' to `%"TS"'",
tmpfile, wim->filename);
#ifdef _WIN32
if (ret < 0)
#endif
{
tunlink(tmpfile);
}
return WIMLIB_ERR_RENAME;
}
union wimlib_progress_info progress;
progress.rename.from = tmpfile;
progress.rename.to = wim->filename;
return call_progress(wim->progfunc, WIMLIB_PROGRESS_MSG_RENAME,
&progress, wim->progctx);
}
/* Determine if the specified WIM file may be updated in-place rather than by
* writing and replacing it with an entirely new file. */
static bool
can_overwrite_wim_inplace(const WIMStruct *wim, int write_flags)
{
/* REBUILD flag forces full rebuild. */
if (write_flags & WIMLIB_WRITE_FLAG_REBUILD)
return false;
/* Image deletions cause full rebuild by default. */
if (wim->image_deletion_occurred &&
!(write_flags & WIMLIB_WRITE_FLAG_SOFT_DELETE))
return false;
/* Pipable WIMs cannot be updated in place, nor can a non-pipable WIM be
* turned into a pipable WIM in-place. */
if (wim_is_pipable(wim) || (write_flags & WIMLIB_WRITE_FLAG_PIPABLE))
return false;
/* The default compression type and compression chunk size selected for
* the output WIM must be the same as those currently used for the WIM.
*/
if (wim->compression_type != wim->out_compression_type)
return false;
if (wim->chunk_size != wim->out_chunk_size)
return false;
return true;
}
/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_overwrite(WIMStruct *wim, int write_flags, unsigned num_threads)
{
int ret;
u32 orig_hdr_flags;
if (write_flags & ~WIMLIB_WRITE_MASK_PUBLIC)
return WIMLIB_ERR_INVALID_PARAM;
if (!wim->filename)
return WIMLIB_ERR_NO_FILENAME;
if (unlikely(write_flags & WIMLIB_WRITE_FLAG_UNSAFE_COMPACT)) {
/*
* In UNSAFE_COMPACT mode:
* - RECOMPRESS is forbidden
* - REBUILD is ignored
* - SOFT_DELETE and NO_SOLID_SORT are implied
*/
if (write_flags & WIMLIB_WRITE_FLAG_RECOMPRESS)
return WIMLIB_ERR_COMPACTION_NOT_POSSIBLE;
write_flags &= ~WIMLIB_WRITE_FLAG_REBUILD;
write_flags |= WIMLIB_WRITE_FLAG_SOFT_DELETE;
write_flags |= WIMLIB_WRITE_FLAG_NO_SOLID_SORT;
}
orig_hdr_flags = wim->hdr.flags;
if (write_flags & WIMLIB_WRITE_FLAG_IGNORE_READONLY_FLAG)
wim->hdr.flags &= ~WIM_HDR_FLAG_READONLY;
ret = can_modify_wim(wim);
wim->hdr.flags = orig_hdr_flags;
if (ret)
return ret;
if (can_overwrite_wim_inplace(wim, write_flags)) {
ret = overwrite_wim_inplace(wim, write_flags, num_threads);
if (ret != WIMLIB_ERR_RESOURCE_ORDER)
return ret;
WARNING("Falling back to re-building entire WIM");
}
if (write_flags & WIMLIB_WRITE_FLAG_UNSAFE_COMPACT)
return WIMLIB_ERR_COMPACTION_NOT_POSSIBLE;
return overwrite_wim_via_tmpfile(wim, write_flags, num_threads);
}
wimlib-1.14.5/src/decompress_common.c 0000644 0001750 0001750 00000032111 15137011205 015017 0 ustar 00e e /*
* decompress_common.c
*
* Code for decompression shared among multiple compression formats.
*
* Copyright 2022 Eric Biggers
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#ifdef __SSE2__
# include
#endif
#include "wimlib/decompress_common.h"
/*
* make_huffman_decode_table() -
*
* Given an alphabet of symbols and the length of each symbol's codeword in a
* canonical prefix code, build a table for quickly decoding symbols that were
* encoded with that code.
*
* A _prefix code_ is an assignment of bitstrings called _codewords_ to symbols
* such that no whole codeword is a prefix of any other. A prefix code might be
* a _Huffman code_, which means that it is an optimum prefix code for a given
* list of symbol frequencies and was generated by the Huffman algorithm.
* Although the prefix codes processed here will ordinarily be "Huffman codes",
* strictly speaking the decoder cannot know whether a given code was actually
* generated by the Huffman algorithm or not.
*
* A prefix code is _canonical_ if and only if a longer codeword never
* lexicographically precedes a shorter codeword, and the lexicographic ordering
* of codewords of equal length is the same as the lexicographic ordering of the
* corresponding symbols. The advantage of using a canonical prefix code is
* that the codewords can be reconstructed from only the symbol => codeword
* length mapping. This eliminates the need to transmit the codewords
* explicitly. Instead, they can be enumerated in lexicographic order after
* sorting the symbols primarily by increasing codeword length and secondarily
* by increasing symbol value.
*
* However, the decoder's real goal is to decode symbols with the code, not just
* generate the list of codewords. Consequently, this function directly builds
* a table for efficiently decoding symbols using the code. The basic idea is
* that given the next 'max_codeword_len' bits of input, the decoder can look up
* the next decoded symbol by indexing a table containing '2^max_codeword_len'
* entries. A codeword with length 'max_codeword_len' will have exactly one
* entry in this table, whereas a codeword shorter than 'max_codeword_len' will
* have multiple entries in this table. Precisely, a codeword of length 'n'
* will have '2^(max_codeword_len - n)' entries. The index of each such entry,
* considered as a bitstring of length 'max_codeword_len', will contain the
* corresponding codeword as a prefix.
*
* That's the basic idea, but we extend it in two ways:
*
* - Often the maximum codeword length is too long for it to be efficient to
* build the full decode table whenever a new code is used. Instead, we build
* a "root" table using only '2^table_bits' entries, where 'table_bits <=
* max_codeword_len'. Then, a lookup of 'table_bits' bits produces either a
* symbol directly (for codewords not longer than 'table_bits'), or the index
* of a subtable which must be indexed with additional bits of input to fully
* decode the symbol (for codewords longer than 'table_bits').
*
* - Whenever the decoder decodes a symbol, it needs to know the codeword length
* so that it can remove the appropriate number of input bits. The obvious
* solution would be to simply retain the codeword lengths array and use the
* decoded symbol as an index into it. However, that would require two array
* accesses when decoding each symbol. Our strategy is to instead store the
* codeword length directly in the decode table entry along with the symbol.
*
* See MAKE_DECODE_TABLE_ENTRY() for full details on the format of decode table
* entries, and see read_huffsym() for full details on how symbols are decoded.
*
* @decode_table:
* The array in which to build the decode table. This must have been
* declared by the DECODE_TABLE() macro. This may alias @lens, since all
* @lens are consumed before the decode table is written to.
*
* @num_syms:
* The number of symbols in the alphabet.
*
* @table_bits:
* The log base 2 of the number of entries in the root table.
*
* @lens:
* An array of length @num_syms, indexed by symbol, that gives the length
* of the codeword, in bits, for each symbol. The length can be 0, which
* means that the symbol does not have a codeword assigned. In addition,
* @lens may alias @decode_table, as noted above.
*
* @max_codeword_len:
* The maximum codeword length permitted for this code. All entries in
* 'lens' must be less than or equal to this value.
*
* @working_space
* A temporary array that was declared with DECODE_TABLE_WORKING_SPACE().
*
* Returns 0 on success, or -1 if the lengths do not form a valid prefix code.
*/
int
make_huffman_decode_table(u16 decode_table[], unsigned num_syms,
unsigned table_bits, const u8 lens[],
unsigned max_codeword_len, u16 working_space[])
{
u16 * const len_counts = &working_space[0];
u16 * const offsets = &working_space[1 * (max_codeword_len + 1)];
u16 * const sorted_syms = &working_space[2 * (max_codeword_len + 1)];
s32 remainder = 1;
void *entry_ptr = decode_table;
unsigned codeword_len = 1;
unsigned sym_idx;
unsigned codeword;
unsigned subtable_pos;
unsigned subtable_bits;
unsigned subtable_prefix;
/* Count how many codewords have each length, including 0. */
for (unsigned len = 0; len <= max_codeword_len; len++)
len_counts[len] = 0;
for (unsigned sym = 0; sym < num_syms; sym++)
len_counts[lens[sym]]++;
/* It is already guaranteed that all lengths are <= max_codeword_len,
* but it cannot be assumed they form a complete prefix code. A
* codeword of length n should require a proportion of the codespace
* equaling (1/2)^n. The code is complete if and only if, by this
* measure, the codespace is exactly filled by the lengths. */
for (unsigned len = 1; len <= max_codeword_len; len++) {
remainder = (remainder << 1) - len_counts[len];
/* Do the lengths overflow the codespace? */
if (unlikely(remainder < 0))
return -1;
}
if (remainder != 0) {
/* The lengths do not fill the codespace; that is, they form an
* incomplete code. This is permitted only if the code is empty
* (contains no symbols). */
if (unlikely(remainder != 1U << max_codeword_len))
return -1;
/* The code is empty. When processing a well-formed stream, the
* decode table need not be initialized in this case. However,
* we cannot assume the stream is well-formed, so we must
* initialize the decode table anyway. Setting all entries to 0
* makes the decode table always produce symbol '0' without
* consuming any bits, which is good enough. */
memset(decode_table, 0, sizeof(decode_table[0]) << table_bits);
return 0;
}
/* Sort the symbols primarily by increasing codeword length and
* secondarily by increasing symbol value. */
/* Initialize 'offsets' so that 'offsets[len]' is the number of
* codewords shorter than 'len' bits, including length 0. */
offsets[0] = 0;
for (unsigned len = 0; len < max_codeword_len; len++)
offsets[len + 1] = offsets[len] + len_counts[len];
/* Use the 'offsets' array to sort the symbols. */
for (unsigned sym = 0; sym < num_syms; sym++)
sorted_syms[offsets[lens[sym]]++] = sym;
/*
* Fill the root table entries for codewords no longer than table_bits.
*
* The table will start with entries for the shortest codeword(s), which
* will have the most entries. From there, the number of entries per
* codeword will decrease. As an optimization, we may begin filling
* entries with SSE2 vector accesses (8 entries/store), then change to
* word accesses (2 or 4 entries/store), then change to 16-bit accesses
* (1 entry/store).
*/
sym_idx = offsets[0];
#ifdef __SSE2__
/* Fill entries one 128-bit vector (8 entries) at a time. */
for (unsigned stores_per_loop = (1U << (table_bits - codeword_len)) /
(sizeof(__m128i) / sizeof(decode_table[0]));
stores_per_loop != 0; codeword_len++, stores_per_loop >>= 1)
{
unsigned end_sym_idx = sym_idx + len_counts[codeword_len];
for (; sym_idx < end_sym_idx; sym_idx++) {
/* Note: unlike in the "word" version below, the __m128i
* type already has __attribute__((may_alias)), so using
* it to access an array of u16 will not violate strict
* aliasing. */
__m128i v = _mm_set1_epi16(
MAKE_DECODE_TABLE_ENTRY(sorted_syms[sym_idx],
codeword_len));
unsigned n = stores_per_loop;
do {
*(__m128i *)entry_ptr = v;
entry_ptr += sizeof(v);
} while (--n);
}
}
#endif /* __SSE2__ */
#ifdef __GNUC__
/* Fill entries one word (2 or 4 entries) at a time. */
for (unsigned stores_per_loop = (1U << (table_bits - codeword_len)) /
(WORDBYTES / sizeof(decode_table[0]));
stores_per_loop != 0; codeword_len++, stores_per_loop >>= 1)
{
unsigned end_sym_idx = sym_idx + len_counts[codeword_len];
for (; sym_idx < end_sym_idx; sym_idx++) {
/* Accessing the array of u16 as u32 or u64 would
* violate strict aliasing and would require compiling
* the code with -fno-strict-aliasing to guarantee
* correctness. To work around this problem, use the
* gcc 'may_alias' extension. */
typedef machine_word_t
__attribute__((may_alias)) aliased_word_t;
aliased_word_t v = repeat_u16(
MAKE_DECODE_TABLE_ENTRY(sorted_syms[sym_idx],
codeword_len));
unsigned n = stores_per_loop;
do {
*(aliased_word_t *)entry_ptr = v;
entry_ptr += sizeof(v);
} while (--n);
}
}
#endif /* __GNUC__ */
/* Fill entries one at a time. */
for (unsigned stores_per_loop = (1U << (table_bits - codeword_len));
stores_per_loop != 0; codeword_len++, stores_per_loop >>= 1)
{
unsigned end_sym_idx = sym_idx + len_counts[codeword_len];
for (; sym_idx < end_sym_idx; sym_idx++) {
u16 v = MAKE_DECODE_TABLE_ENTRY(sorted_syms[sym_idx],
codeword_len);
unsigned n = stores_per_loop;
do {
*(u16 *)entry_ptr = v;
entry_ptr += sizeof(v);
} while (--n);
}
}
/* If all symbols were processed, then no subtables are required. */
if (sym_idx == num_syms)
return 0;
/* At least one subtable is required. Process the remaining symbols. */
codeword = ((u16 *)entry_ptr - decode_table) << 1;
subtable_pos = 1U << table_bits;
subtable_bits = table_bits;
subtable_prefix = -1;
do {
while (len_counts[codeword_len] == 0) {
codeword_len++;
codeword <<= 1;
}
unsigned prefix = codeword >> (codeword_len - table_bits);
/* Start a new subtable if the first 'table_bits' bits of the
* codeword don't match the prefix for the previous subtable, or
* if this will be the first subtable. */
if (prefix != subtable_prefix) {
subtable_prefix = prefix;
/*
* Calculate the subtable length. If the codeword
* length exceeds 'table_bits' by n, then the subtable
* needs at least 2^n entries. But it may need more; if
* there are fewer than 2^n codewords of length
* 'table_bits + n' remaining, then n will need to be
* incremented to bring in longer codewords until the
* subtable can be filled completely. Note that it
* always will, eventually, be possible to fill the
* subtable, since it was previously verified that the
* code is complete.
*/
subtable_bits = codeword_len - table_bits;
remainder = (s32)1 << subtable_bits;
for (;;) {
remainder -= len_counts[table_bits +
subtable_bits];
if (remainder <= 0)
break;
subtable_bits++;
remainder <<= 1;
}
/* Create the entry that points from the root table to
* the subtable. This entry contains the index of the
* start of the subtable and the number of bits with
* which the subtable is indexed (the log base 2 of the
* number of entries it contains). */
decode_table[subtable_prefix] =
MAKE_DECODE_TABLE_ENTRY(subtable_pos,
subtable_bits);
}
/* Fill the subtable entries for this symbol. */
u16 entry = MAKE_DECODE_TABLE_ENTRY(sorted_syms[sym_idx],
codeword_len - table_bits);
unsigned n = 1U << (subtable_bits - (codeword_len -
table_bits));
do {
decode_table[subtable_pos++] = entry;
} while (--n);
len_counts[codeword_len]--;
codeword++;
} while (++sym_idx < num_syms);
return 0;
}
wimlib-1.14.5/src/wimboot.c 0000644 0001750 0001750 00000100256 15137020663 013001 0 ustar 00e e /*
* wimboot.c
*
* Support for creating WIMBoot pointer files.
*
* For general information about WIMBoot, see
* https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-8.1-and-8/dn594399(v=win.10)
*
* Note that WIMBoot pointer files are actually implemented on top of the
* Windows Overlay Filesystem filter (WOF). See wof.h for more info.
*/
/*
* Copyright (C) 2014-2021 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef _WIN32
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "wimlib/win32_common.h"
#include "wimlib/assert.h"
#include "wimlib/blob_table.h"
#include "wimlib/inode.h"
#include "wimlib/error.h"
#include "wimlib/util.h"
#include "wimlib/wimboot.h"
#include "wimlib/win32.h"
#include "wimlib/wof.h"
static HANDLE
open_file(const wchar_t *device_name, DWORD desiredAccess)
{
return CreateFile(device_name, desiredAccess,
FILE_SHARE_VALID_FLAGS, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
}
static BOOL
query_device(HANDLE h, DWORD code, void *out, DWORD out_size)
{
DWORD bytes_returned;
return DeviceIoControl(h, code, NULL, 0, out, out_size,
&bytes_returned, NULL);
}
/*
* Gets partition and drive information for the specified path.
*
* @path
* Absolute path which must begin with a drive letter. For example, if the
* path is D:\install.wim, this function will query information about the
* D: volume.
* @part_info_ret
* Partition info is returned here.
* @drive_info_ret
* Drive info is returned here. The contained partition info will not be
* valid.
*
* Returns 0 on success, or a positive error code on failure.
*/
static int
query_partition_and_disk_info(const wchar_t *path,
PARTITION_INFORMATION_EX *part_info,
DRIVE_LAYOUT_INFORMATION_EX *drive_info_ret)
{
wchar_t vol_name[] = L"\\\\.\\X:";
wchar_t disk_name[] = L"\\\\?\\PhysicalDriveXXXXXXXXXX";
HANDLE h = INVALID_HANDLE_VALUE;
VOLUME_DISK_EXTENTS *extents = NULL;
size_t extents_size;
DRIVE_LAYOUT_INFORMATION_EX *drive_info = NULL;
size_t drive_info_size;
int ret;
wimlib_assert(path[0] != L'\0' && path[1] == L':');
*(wcschr(vol_name, L'X')) = path[0];
h = open_file(vol_name, GENERIC_READ);
if (h == INVALID_HANDLE_VALUE) {
win32_error(GetLastError(), L"\"%ls\": Can't open volume device",
vol_name);
ret = WIMLIB_ERR_OPEN;
goto out;
}
if (!query_device(h, IOCTL_DISK_GET_PARTITION_INFO_EX,
part_info, sizeof(PARTITION_INFORMATION_EX)))
{
win32_error(GetLastError(),
L"\"%ls\": Can't get partition info", vol_name);
ret = WIMLIB_ERR_READ;
goto out;
}
extents_size = sizeof(VOLUME_DISK_EXTENTS);
for (;;) {
extents_size += 4 * sizeof(DISK_EXTENT);
extents = MALLOC(extents_size);
if (!extents) {
ret = WIMLIB_ERR_NOMEM;
goto out;
}
if (query_device(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
extents, extents_size))
break;
if (GetLastError() != ERROR_MORE_DATA) {
win32_error(GetLastError(),
L"\"%ls\": Can't get volume extent info",
vol_name);
ret = WIMLIB_ERR_READ;
goto out;
}
FREE(extents);
}
CloseHandle(h);
h = INVALID_HANDLE_VALUE;
if (extents->NumberOfDiskExtents != 1) {
ERROR("\"%ls\": This volume has %"PRIu32" disk extents, "
"but this code is untested for more than 1",
vol_name, (u32)extents->NumberOfDiskExtents);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out;
}
wsprintf(wcschr(disk_name, L'X'), L"%"PRIu32,
extents->Extents[0].DiskNumber);
h = open_file(disk_name, GENERIC_READ);
if (h == INVALID_HANDLE_VALUE) {
win32_error(GetLastError(),
L"\"%ls\": Can't open disk device", disk_name);
ret = WIMLIB_ERR_OPEN;
goto out;
}
drive_info_size = sizeof(DRIVE_LAYOUT_INFORMATION_EX);
for (;;) {
drive_info_size += 4 * sizeof(PARTITION_INFORMATION_EX);
drive_info = MALLOC(drive_info_size);
if (!drive_info) {
ret = WIMLIB_ERR_NOMEM;
goto out;
}
if (query_device(h, IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
drive_info, drive_info_size))
break;
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
win32_error(GetLastError(),
L"\"%ls\": Can't get disk info", disk_name);
ret = WIMLIB_ERR_READ;
goto out;
}
FREE(drive_info);
}
*drive_info_ret = *drive_info; /* doesn't include partitions */
CloseHandle(h);
h = INVALID_HANDLE_VALUE;
if (drive_info->PartitionStyle != part_info->PartitionStyle) {
ERROR("\"%ls\", \"%ls\": Inconsistent partition table type!",
vol_name, disk_name);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out;
}
if (part_info->PartitionStyle == PARTITION_STYLE_GPT) {
STATIC_ASSERT(sizeof(part_info->Gpt.PartitionId) ==
sizeof(drive_info->Gpt.DiskId));
if (!memcmp(&part_info->Gpt.PartitionId,
&drive_info->Gpt.DiskId,
sizeof(drive_info->Gpt.DiskId)))
{
ERROR("\"%ls\", \"%ls\": Partition GUID is the "
"same as the disk GUID???", vol_name, disk_name);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out;
}
}
if (part_info->PartitionStyle != PARTITION_STYLE_MBR &&
part_info->PartitionStyle != PARTITION_STYLE_GPT)
{
ERROR("\"%ls\": Unknown partition style 0x%08"PRIx32,
vol_name, (u32)part_info->PartitionStyle);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out;
}
ret = 0;
out:
FREE(extents);
FREE(drive_info);
if (h != INVALID_HANDLE_VALUE)
CloseHandle(h);
return ret;
}
/*
* Calculate the size of WimOverlay.dat with one entry added.
*
* @old_hdr
* Previous WimOverlay.dat contents, or NULL if file did not exist.
* @new_entry_2_size
* Size of entry_2 being added.
* @size_ret
* Size will be returned here.
*
* Returns 0 on success, or WIMLIB_ERR_UNSUPPORTED if size overflows 32 bits.
*/
static int
calculate_wimoverlay_dat_size(const struct WimOverlay_dat_header *old_hdr,
u32 new_entry_2_size, u32 *size_ret)
{
u64 size_64;
u32 size;
size_64 = sizeof(struct WimOverlay_dat_header);
if (old_hdr) {
for (u32 i = 0; i < old_hdr->num_entries; i++) {
size_64 += sizeof(struct WimOverlay_dat_entry_1);
size_64 += old_hdr->entry_1s[i].entry_2_length;
}
}
size_64 += sizeof(struct WimOverlay_dat_entry_1);
size_64 += new_entry_2_size;
size = size_64;
if (size_64 != size)
return WIMLIB_ERR_UNSUPPORTED;
*size_ret = size;
return 0;
}
/*
* Writes @size bytes of @contents to the named file @path.
*
* Returns 0 on success; WIMLIB_ERR_OPEN or WIMLIB_ERR_WRITE on failure.
*/
static int
write_wimoverlay_dat(const wchar_t *path, const void *contents, u32 size)
{
HANDLE h;
DWORD bytes_written;
h = CreateFile(path, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) {
win32_error(GetLastError(),
L"\"%ls\": Can't open file for writing", path);
return WIMLIB_ERR_OPEN;
}
SetLastError(0);
if (!WriteFile(h, contents, size, &bytes_written, NULL) ||
bytes_written != size)
{
win32_error(GetLastError(),
L"\"%ls\": Can't write file", path);
CloseHandle(h);
return WIMLIB_ERR_WRITE;
}
if (!CloseHandle(h)) {
win32_error(GetLastError(),
L"\"%ls\": Can't close handle", path);
return WIMLIB_ERR_WRITE;
}
return 0;
}
/*
* Generates the contents of WimOverlay.dat in memory, with one entry added.
*
* @buf
* Buffer large enough to hold the new contents.
* @old_hdr
* Old contents of WimOverlay.dat, or NULL if it did not exist.
* @wim_path
* Absolute path to the WIM file. It must begin with a drive letter; for
* example, D:\install.wim.
* @wim_guid
* GUID of the WIM, from the WIM header.
* @image
* Number of the image in the WIM to specify in the new entry.
* @new_data_source_id
* Data source ID to use for the new entry.
* @part_info
* Partition information for the WIM file.
* @disk_info
* Disk information for the WIM file.
* @new_entry_2_size
* Size, in bytes, of the new location information structure ('struct
* WimOverlay_dat_entry_2').
*
* Returns a pointer one past the last byte of @buf filled in.
*/
static u8 *
fill_in_wimoverlay_dat(u8 *buf,
const struct WimOverlay_dat_header *old_hdr,
const wchar_t *wim_path,
const u8 wim_guid[GUID_SIZE],
int image,
u64 new_data_source_id,
const PARTITION_INFORMATION_EX *part_info,
const DRIVE_LAYOUT_INFORMATION_EX *disk_info,
u32 new_entry_2_size)
{
struct WimOverlay_dat_header *new_hdr;
struct WimOverlay_dat_entry_1 *new_entry_1;
struct WimOverlay_dat_entry_2 *new_entry_2;
u32 entry_2_offset;
u8 *p = buf;
new_hdr = (struct WimOverlay_dat_header *)p;
/* Fill in new header */
new_hdr->magic = WIMOVERLAY_DAT_MAGIC;
new_hdr->wim_provider_version = WIM_PROVIDER_CURRENT_VERSION;
new_hdr->unknown_0x08 = 0x00000028;
new_hdr->num_entries = (old_hdr ? old_hdr->num_entries : 0) + 1;
new_hdr->next_data_source_id = (old_hdr ? old_hdr->next_data_source_id : 0) + 1;
p += sizeof(struct WimOverlay_dat_header);
/* Copy WIM-specific information for old entries */
entry_2_offset = sizeof(struct WimOverlay_dat_header) +
(new_hdr->num_entries * sizeof(struct WimOverlay_dat_entry_1));
if (old_hdr) {
for (u32 i = 0; i < old_hdr->num_entries; i++) {
new_entry_1 = (struct WimOverlay_dat_entry_1 *)p;
p = mempcpy(p, &old_hdr->entry_1s[i],
sizeof(struct WimOverlay_dat_entry_1));
new_entry_1->entry_2_offset = entry_2_offset;
entry_2_offset += new_entry_1->entry_2_length;
}
}
/* Generate WIM-specific information for new entry */
new_entry_1 = (struct WimOverlay_dat_entry_1 *)p;
new_entry_1->data_source_id = new_data_source_id;
new_entry_1->entry_2_offset = entry_2_offset;
new_entry_1->entry_2_length = new_entry_2_size;
new_entry_1->wim_type = WIM_BOOT_NOT_OS_WIM;
new_entry_1->wim_index = image;
STATIC_ASSERT(sizeof(new_entry_1->guid) == GUID_SIZE);
copy_guid(new_entry_1->guid, wim_guid);
p += sizeof(struct WimOverlay_dat_entry_1);
/* Copy WIM location information for old entries */
if (old_hdr) {
for (u32 i = 0; i < old_hdr->num_entries; i++) {
wimlib_assert(new_hdr->entry_1s[i].entry_2_offset == p - buf);
wimlib_assert(old_hdr->entry_1s[i].entry_2_length ==
new_hdr->entry_1s[i].entry_2_length);
p = mempcpy(p,
((const u8 *)old_hdr + old_hdr->entry_1s[i].entry_2_offset),
old_hdr->entry_1s[i].entry_2_length);
}
}
/* Generate WIM location information for new entry */
new_entry_2 = (struct WimOverlay_dat_entry_2 *)p;
new_entry_2->unknown_0x00 = 0x00000000;
new_entry_2->unknown_0x04 = 0x00000000;
new_entry_2->entry_2_length = new_entry_2_size;
new_entry_2->unknown_0x0C = 0x00000000;
new_entry_2->unknown_0x10 = 0x00000005;
new_entry_2->unknown_0x14 = 0x00000001;
new_entry_2->inner_struct_size = new_entry_2_size - 0x14;
new_entry_2->unknown_0x1C = 0x00000005;
new_entry_2->unknown_0x20 = 0x00000006;
new_entry_2->unknown_0x24 = 0x00000000;
new_entry_2->unknown_0x28 = 0x00000048;
new_entry_2->unknown_0x2C = 0x00000000;
new_entry_2->unknown_0x40 = 0x00000000;
if (part_info->PartitionStyle == PARTITION_STYLE_MBR) {
new_entry_2->partition.mbr.part_start_offset = part_info->StartingOffset.QuadPart;
new_entry_2->partition.mbr.padding = 0;
new_entry_2->partition_table_type = WIMOVERLAY_PARTITION_TYPE_MBR;
new_entry_2->disk.mbr.disk_id = disk_info->Mbr.Signature;
new_entry_2->disk.mbr.padding[0] = 0x00000000;
new_entry_2->disk.mbr.padding[1] = 0x00000000;
new_entry_2->disk.mbr.padding[2] = 0x00000000;
} else {
STATIC_ASSERT(sizeof(new_entry_2->partition.gpt.part_unique_guid) ==
sizeof(part_info->Gpt.PartitionId));
memcpy(new_entry_2->partition.gpt.part_unique_guid,
&part_info->Gpt.PartitionId,
sizeof(part_info->Gpt.PartitionId));
new_entry_2->partition_table_type = WIMOVERLAY_PARTITION_TYPE_GPT;
STATIC_ASSERT(sizeof(new_entry_2->disk.gpt.disk_guid) ==
sizeof(disk_info->Gpt.DiskId));
memcpy(new_entry_2->disk.gpt.disk_guid,
&disk_info->Gpt.DiskId,
sizeof(disk_info->Gpt.DiskId));
STATIC_ASSERT(sizeof(new_entry_2->disk.gpt.disk_guid) ==
sizeof(new_entry_2->partition.gpt.part_unique_guid));
}
new_entry_2->unknown_0x58[0] = 0x00000000;
new_entry_2->unknown_0x58[1] = 0x00000000;
new_entry_2->unknown_0x58[2] = 0x00000000;
new_entry_2->unknown_0x58[3] = 0x00000000;
wimlib_assert(wim_path[2] == L'\\');
return mempcpy(new_entry_2->wim_file_name,
wim_path + 2,
new_entry_2_size - sizeof(struct WimOverlay_dat_entry_2));
}
/*
* Prepares the new contents of WimOverlay.dat in memory, with one entry added.
*
* @old_hdr
* Old contents of WimOverlay.dat, or NULL if it did not exist.
* @wim_path
* Absolute path to the WIM file. It must begin with a drive letter; for
* example, D:\install.wim.
* @wim_guid
* GUID of the WIM, from the WIM header.
* @image
* Number of the image in the WIM to specify in the new entry.
* @new_contents_ret
* Location into which to return the new contents as a malloc()ed buffer on
* success.
* @new_contents_size_ret
* Location into which to return the size, in bytes, of the new contents on
* success.
* @new_data_source_id_ret
* Location into which to return the data source ID of the new entry on
* success.
*
* Returns 0 on success, or a positive error code on failure.
*/
static int
prepare_wimoverlay_dat(const struct WimOverlay_dat_header *old_hdr,
const wchar_t *wim_path,
const u8 wim_guid[GUID_SIZE],
int image,
void **new_contents_ret,
u32 *new_contents_size_ret,
u64 *new_data_source_id_ret)
{
int ret;
PARTITION_INFORMATION_EX part_info;
DRIVE_LAYOUT_INFORMATION_EX disk_info;
u64 new_data_source_id;
u32 new_entry_2_size;
u32 new_contents_size;
u8 *buf;
u8 *end;
ret = query_partition_and_disk_info(wim_path, &part_info, &disk_info);
if (ret)
return ret;
new_data_source_id = old_hdr ? old_hdr->next_data_source_id : 0;
new_entry_2_size = sizeof(struct WimOverlay_dat_entry_2) +
((wcslen(wim_path) - 2 + 1) * sizeof(wchar_t));
ret = calculate_wimoverlay_dat_size(old_hdr, new_entry_2_size,
&new_contents_size);
if (ret)
return ret;
buf = MALLOC(new_contents_size);
if (!buf)
return WIMLIB_ERR_NOMEM;
end = fill_in_wimoverlay_dat(buf, old_hdr, wim_path, wim_guid, image,
new_data_source_id,
&part_info, &disk_info, new_entry_2_size);
wimlib_assert(end - buf == new_contents_size);
*new_contents_ret = buf;
*new_contents_size_ret = new_contents_size;
*new_data_source_id_ret = new_data_source_id;
return 0;
}
static bool
valid_wim_filename(const struct WimOverlay_dat_entry_2 *entry, size_t name_len)
{
size_t i;
if (name_len % sizeof(wchar_t))
return false;
name_len /= sizeof(wchar_t);
if (name_len < 2)
return false;
for (i = 0; i < name_len && entry->wim_file_name[i] != 0; i++)
;
return i == name_len - 1;
}
/*
* Reads and validates a WimOverlay.dat file.
*
* @path
* Path to the WimOverlay.dat file, such as
* C:\System Volume Information\WimOverlay.dat
* @contents_ret
* Location into which to return the contents as a malloc()ed buffer on
* success. This can be cast to 'struct WimOverlay_dat_header', and its
* contents are guaranteed to be valid. Alternatively, if the file does
* not exist, NULL will be returned here.
*
* Returns 0 on success, or a positive error code on failure.
*/
static int
read_wimoverlay_dat(const wchar_t *path, void **contents_ret)
{
HANDLE h;
BY_HANDLE_FILE_INFORMATION info;
int ret;
void *contents;
const struct WimOverlay_dat_header *hdr;
DWORD bytes_read;
bool already_retried = false;
retry:
h = open_file(path, GENERIC_READ);
if (h == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
if (err == ERROR_FILE_NOT_FOUND) {
*contents_ret = NULL;
return 0;
}
if (err == ERROR_PATH_NOT_FOUND &&
func_RtlCreateSystemVolumeInformationFolder)
{
wchar_t volume_root_path[] = L"\\??\\X:\\";
*(wcschr(volume_root_path, L'X')) = path[0];
UNICODE_STRING str = {
.Length = sizeof(volume_root_path) - sizeof(wchar_t),
.MaximumLength = sizeof(volume_root_path),
.Buffer = volume_root_path,
};
NTSTATUS status;
DWORD err2;
status = (*func_RtlCreateSystemVolumeInformationFolder)(&str);
err2 = RtlNtStatusToDosError(status);
if (err2 == ERROR_SUCCESS) {
if (!already_retried) {
already_retried = true;
goto retry;
}
} else {
err = err2;
}
}
win32_error(err, L"\"%ls\": Can't open for reading", path);
return WIMLIB_ERR_OPEN;
}
if (!GetFileInformationByHandle(h, &info)) {
win32_error(GetLastError(), L"\"%ls\": Can't query metadata", path);
CloseHandle(h);
return WIMLIB_ERR_STAT;
}
contents = NULL;
if (!info.nFileSizeHigh)
contents = MALLOC(info.nFileSizeLow);
if (!contents) {
ERROR("\"%ls\": File is too large to fit into memory", path);
CloseHandle(h);
return WIMLIB_ERR_NOMEM;
}
SetLastError(0);
if (!ReadFile(h, contents, info.nFileSizeLow, &bytes_read, NULL) ||
bytes_read != info.nFileSizeLow)
{
win32_error(GetLastError(), L"\"%ls\": Can't read data", path);
CloseHandle(h);
ret = WIMLIB_ERR_READ;
goto out_free_contents;
}
CloseHandle(h);
if (info.nFileSizeLow < sizeof(struct WimOverlay_dat_header)) {
ERROR("\"%ls\": File is unexpectedly small (only %"PRIu32" bytes)",
path, (u32)info.nFileSizeLow);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_free_contents;
}
hdr = (const struct WimOverlay_dat_header *)contents;
if (hdr->magic != WIMOVERLAY_DAT_MAGIC ||
hdr->wim_provider_version != WIM_PROVIDER_CURRENT_VERSION ||
hdr->unknown_0x08 != 0x00000028)
{
ERROR("\"%ls\": Header contains unexpected data:", path);
if (wimlib_print_errors) {
print_byte_field((const u8 *)hdr,
sizeof(struct WimOverlay_dat_header),
wimlib_error_file);
fputc('\n', wimlib_error_file);
}
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_free_contents;
}
if ((u64)hdr->num_entries * sizeof(struct WimOverlay_dat_entry_1) >
info.nFileSizeLow - sizeof(struct WimOverlay_dat_header))
{
ERROR("\"%ls\": File is unexpectedly small "
"(only %"PRIu32" bytes, but has %"PRIu32" entries)",
path, (u32)info.nFileSizeLow, hdr->num_entries);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_free_contents;
}
for (u32 i = 0; i < hdr->num_entries; i++) {
const struct WimOverlay_dat_entry_1 *entry_1;
const struct WimOverlay_dat_entry_2 *entry_2;
u32 wim_file_name_length;
entry_1 = &hdr->entry_1s[i];
if (entry_1->data_source_id >= hdr->next_data_source_id) {
ERROR("\"%ls\": value of next_data_source_id "
"(0x%016"PRIx64") is unexpected, since entry "
"%"PRIu32" has data source ID 0x%016"PRIx64,
path, hdr->next_data_source_id,
i, entry_1->data_source_id);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_free_contents;
}
if (((u64)entry_1->entry_2_offset +
(u64)entry_1->entry_2_length) >
info.nFileSizeLow)
{
ERROR("\"%ls\": entry %"PRIu32" (2) "
"(data source ID 0x%016"PRIx64") "
"overflows file",
path, i, entry_1->data_source_id);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_free_contents;
}
if (entry_1->entry_2_length < sizeof(struct WimOverlay_dat_entry_2)) {
ERROR("\"%ls\": entry %"PRIu32" (2) "
"(data source ID 0x%016"PRIx64") "
"is too short",
path, i, entry_1->data_source_id);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_free_contents;
}
if (entry_1->entry_2_offset % 2 != 0) {
ERROR("\"%ls\": entry %"PRIu32" (2) "
"(data source ID 0x%016"PRIx64") "
"is misaligned",
path, i, entry_1->data_source_id);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_free_contents;
}
entry_2 = (const struct WimOverlay_dat_entry_2 *)
((const u8 *)hdr + entry_1->entry_2_offset);
wim_file_name_length = entry_1->entry_2_length -
sizeof(struct WimOverlay_dat_entry_2);
if (!valid_wim_filename(entry_2, wim_file_name_length)) {
ERROR("\"%ls\": entry %"PRIu32" (2) "
"(data source ID 0x%016"PRIx64") "
"has invalid WIM file name",
path, i, entry_1->data_source_id);
if (wimlib_print_errors) {
print_byte_field((const u8 *)entry_2->wim_file_name,
wim_file_name_length,
wimlib_error_file);
fputc('\n', wimlib_error_file);
}
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_free_contents;
}
if (entry_2->unknown_0x00 != 0x00000000 ||
entry_2->unknown_0x04 != 0x00000000 ||
entry_2->unknown_0x0C != 0x00000000 ||
entry_2->entry_2_length != entry_1->entry_2_length ||
entry_2->unknown_0x10 != 0x00000005 ||
entry_2->unknown_0x14 != 0x00000001 ||
entry_2->inner_struct_size != entry_1->entry_2_length - 0x14 ||
entry_2->unknown_0x1C != 0x00000005 ||
entry_2->unknown_0x20 != 0x00000006 ||
entry_2->unknown_0x24 != 0x00000000 ||
entry_2->unknown_0x28 != 0x00000048 ||
entry_2->unknown_0x2C != 0x00000000 ||
entry_2->unknown_0x40 != 0x00000000 ||
(entry_2->partition_table_type != WIMOVERLAY_PARTITION_TYPE_GPT &&
entry_2->partition_table_type != WIMOVERLAY_PARTITION_TYPE_MBR) ||
(entry_2->partition_table_type == WIMOVERLAY_PARTITION_TYPE_MBR &&
entry_2->partition.mbr.padding != 0) ||
(entry_2->partition_table_type == WIMOVERLAY_PARTITION_TYPE_GPT &&
entry_2->partition.mbr.padding == 0) ||
entry_2->unknown_0x58[0] != 0x00000000 ||
entry_2->unknown_0x58[1] != 0x00000000 ||
entry_2->unknown_0x58[2] != 0x00000000 ||
entry_2->unknown_0x58[3] != 0x00000000)
{
ERROR("\"%ls\": entry %"PRIu32" (2) "
"(data source ID 0x%016"PRIx64") "
"contains unexpected data!",
path, i, entry_1->data_source_id);
if (wimlib_print_errors) {
print_byte_field((const u8 *)entry_2,
entry_1->entry_2_length,
wimlib_error_file);
fputc('\n', wimlib_error_file);
}
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_free_contents;
}
}
*contents_ret = contents;
return 0;
out_free_contents:
FREE(contents);
return ret;
}
/*
* Update WimOverlay.dat manually in order to add a WIM data source to the
* target volume.
*
* THIS CODE IS EXPERIMENTAL AS I HAD TO REVERSE ENGINEER THE FILE FORMAT!
*
* @path
* Target drive. Must be a letter followed by a colon (e.g. D:).
* @wim_path
* Absolute path to the WIM file. It must begin with a drive letter; for
* example, D:\install.wim.
* @wim_guid
* GUID of the WIM, from the WIM header.
* @image
* Number of the image in the WIM to specify in the new entry.
* @data_source_id_ret
* On success, the allocated data source ID is returned here.
*/
static int
update_wimoverlay_manually(const wchar_t *drive, const wchar_t *wim_path,
const u8 wim_guid[GUID_SIZE],
int image, u64 *data_source_id_ret)
{
wchar_t path_main[] = L"A:\\System Volume Information\\WimOverlay.dat";
wchar_t path_backup[] = L"A:\\System Volume Information\\WimOverlay.backup";
wchar_t path_wimlib_backup[] = L"A:\\System Volume Information\\WimOverlay.wimlib_backup";
wchar_t path_new[] = L"A:\\System Volume Information\\WimOverlay.wimlib_new";
void *old_contents = NULL;
void *new_contents = NULL;
u32 new_contents_size = 0;
u64 new_data_source_id = -1;
int ret;
wimlib_assert(drive[0] != L'\0' &&
drive[1] == L':' &&
drive[2] == L'\0');
path_main[0] = drive[0];
path_backup[0] = drive[0];
path_wimlib_backup[0] = drive[0];
path_new[0] = drive[0];
ret = read_wimoverlay_dat(path_main, &old_contents);
if (ret)
goto out;
ret = prepare_wimoverlay_dat(old_contents, wim_path, wim_guid, image,
&new_contents, &new_contents_size,
&new_data_source_id);
FREE(old_contents);
if (ret)
goto out;
/* Write WimOverlay.wimlib_new */
ret = write_wimoverlay_dat(path_new,
new_contents, new_contents_size);
if (ret)
goto out_free_new_contents;
/* Write WimOverlay.backup */
ret = write_wimoverlay_dat(path_backup,
new_contents, new_contents_size);
if (ret)
goto out_free_new_contents;
if (old_contents) {
/* Rename WimOverlay.dat => WimOverlay.wimlib_backup */
ret = win32_rename_replacement(path_main, path_wimlib_backup);
if (ret) {
ERROR_WITH_ERRNO("Can't rename \"%ls\" => \"%ls\"",
path_main, path_wimlib_backup);
ret = WIMLIB_ERR_RENAME;
goto out_free_new_contents;
}
}
/* Rename WimOverlay.wimlib_new => WimOverlay.dat */
ret = win32_rename_replacement(path_new, path_main);
if (ret) {
ERROR_WITH_ERRNO("Can't rename \"%ls\" => \"%ls\"",
path_new, path_main);
ret = WIMLIB_ERR_RENAME;
}
out_free_new_contents:
FREE(new_contents);
out:
if (ret == WIMLIB_ERR_UNSUPPORTED) {
ERROR("Please report to developer ("PACKAGE_BUGREPORT").\n"
" If possible send the file \"%ls\".\n\n", path_main);
}
if (ret == 0)
*data_source_id_ret = new_data_source_id;
return ret;
}
/*
* Allocate a WOF data source ID for a WIM file.
*
* @wim_path
* Absolute path to the WIM file. This must include a drive letter and use
* backslash path separators.
* @wim_guid
* GUID of the WIM, from the WIM header.
* @image
* Number of the image in the WIM being applied.
* @target
* Path to the target directory.
* @data_source_id_ret
* On success, an identifier for the backing WIM file will be returned
* here.
*
* Returns 0 on success, or a positive error code on failure.
*/
int
wimboot_alloc_data_source_id(const wchar_t *wim_path,
const u8 wim_guid[GUID_SIZE],
int image, const wchar_t *target,
u64 *data_source_id_ret, bool *wof_running_ret)
{
tchar drive_path[7];
size_t wim_path_nchars;
size_t wim_file_name_length;
void *in;
size_t insize;
WOF_EXTERNAL_INFO *wof_info;
WIM_PROVIDER_ADD_OVERLAY_INPUT *wim_info;
wchar_t *WimFileName;
HANDLE h;
u64 data_source_id;
DWORD bytes_returned;
int ret;
const wchar_t *prefix = L"\\??\\";
const size_t prefix_nchars = 4;
bool tried_to_attach_wof = false;
ret = win32_get_drive_path(target, drive_path);
if (ret)
return ret;
wimlib_assert(!wcschr(wim_path, L'/'));
wimlib_assert(wim_path[0] != L'\0' && wim_path[1] == L':');
wim_path_nchars = wcslen(wim_path);
wim_file_name_length = sizeof(wchar_t) *
(wim_path_nchars + prefix_nchars);
insize = sizeof(*wof_info) + sizeof(*wim_info) + wim_file_name_length;
in = CALLOC(1, insize);
if (!in) {
ret = WIMLIB_ERR_NOMEM;
goto out;
}
wof_info = (WOF_EXTERNAL_INFO *)in;
wof_info->Version = WOF_CURRENT_VERSION;
wof_info->Provider = WOF_PROVIDER_WIM;
wim_info = (WIM_PROVIDER_ADD_OVERLAY_INPUT *)(wof_info + 1);
wim_info->WimType = WIM_BOOT_NOT_OS_WIM;
wim_info->WimIndex = image;
wim_info->WimFileNameOffset = sizeof(*wim_info);
wim_info->WimFileNameLength = wim_file_name_length;
WimFileName = (wchar_t *)(wim_info + 1);
wmemcpy(WimFileName, prefix, prefix_nchars);
wmemcpy(&WimFileName[prefix_nchars], wim_path, wim_path_nchars);
retry_ioctl:
h = open_file(drive_path, GENERIC_WRITE);
if (h == INVALID_HANDLE_VALUE) {
win32_error(GetLastError(),
L"Failed to open \"%ls\"", drive_path + 4);
ret = WIMLIB_ERR_OPEN;
goto out_free_in;
}
if (!DeviceIoControl(h, FSCTL_ADD_OVERLAY,
in, insize,
&data_source_id, sizeof(data_source_id),
&bytes_returned, NULL))
{
DWORD err = GetLastError();
if (err == ERROR_INVALID_FUNCTION) {
if (!tried_to_attach_wof) {
CloseHandle(h);
h = INVALID_HANDLE_VALUE;
tried_to_attach_wof = true;
if (win32_try_to_attach_wof(drive_path + 4))
goto retry_ioctl;
}
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_close_handle;
} else {
win32_error(err, L"Failed to add overlay source \"%ls\" "
"to volume \"%ls\"", wim_path, drive_path + 4);
ret = WIMLIB_ERR_WIMBOOT;
goto out_close_handle;
}
}
if (bytes_returned != sizeof(data_source_id)) {
ret = WIMLIB_ERR_WIMBOOT;
ERROR("Unexpected result size when adding "
"overlay source \"%ls\" to volume \"%ls\"",
wim_path, drive_path + 4);
goto out_close_handle;
}
*wof_running_ret = true;
*data_source_id_ret = data_source_id;
ret = 0;
out_close_handle:
CloseHandle(h);
out_free_in:
FREE(in);
out:
if (ret == WIMLIB_ERR_UNSUPPORTED) {
WARNING("WOF driver is not available; updating WimOverlay.dat directly.");
ret = update_wimoverlay_manually(drive_path + 4, wim_path,
wim_guid, image,
data_source_id_ret);
*wof_running_ret = false;
}
return ret;
}
/*
* Set WIMBoot information on the specified file.
*
* This turns it into a reparse point that redirects accesses to it, to the
* corresponding resource in the WIM archive.
*
* @h
* Open handle to the file, with GENERIC_WRITE access.
* @blob
* The blob for the unnamed data stream of the file.
* @data_source_id
* Allocated identifier for the WIM data source on the destination volume.
* @blob_table_hash
* SHA-1 message digest of the WIM's blob table.
* @wof_running
* %true if the WOF driver appears to be available and working; %false if
* not.
*
* Returns %true on success, or %false on failure with GetLastError() set.
*/
bool
wimboot_set_pointer(HANDLE h,
const struct blob_descriptor *blob,
u64 data_source_id,
const u8 blob_table_hash[SHA1_HASH_SIZE],
bool wof_running)
{
DWORD bytes_returned;
if (wof_running) {
/* The WOF driver is running. We can create the reparse point
* using FSCTL_SET_EXTERNAL_BACKING. */
unsigned int max_retries = 4;
struct {
WOF_EXTERNAL_INFO wof_info;
WIM_PROVIDER_EXTERNAL_INFO wim_info;
} in;
retry:
memset(&in, 0, sizeof(in));
in.wof_info.Version = WOF_CURRENT_VERSION;
in.wof_info.Provider = WOF_PROVIDER_WIM;
in.wim_info.Version = WIM_PROVIDER_CURRENT_VERSION;
in.wim_info.Flags = 0;
in.wim_info.DataSourceId.QuadPart = data_source_id;
copy_hash(in.wim_info.ResourceHash, blob->hash);
/* blob_table_hash is not necessary */
if (!DeviceIoControl(h, FSCTL_SET_EXTERNAL_BACKING,
&in, sizeof(in), NULL, 0,
&bytes_returned, NULL))
{
/* Try to track down sporadic errors */
if (wimlib_print_errors) {
WARNING("FSCTL_SET_EXTERNAL_BACKING failed (err=%u); data was %zu bytes:",
(u32)GetLastError(), sizeof(in));
print_byte_field((const u8 *)&in, sizeof(in), wimlib_error_file);
putc('\n', wimlib_error_file);
}
if (--max_retries) {
WARNING("Retrying after 100ms...");
Sleep(100);
goto retry;
}
WARNING("Too many retries; returning failure");
return false;
}
} else {
/* The WOF driver is running. We need to create the reparse
* point manually. */
struct {
struct {
le32 rptag;
le16 rpdatalen;
le16 rpreserved;
} hdr;
WOF_EXTERNAL_INFO wof_info;
struct wim_provider_rpdata wim_info;
} in;
STATIC_ASSERT(sizeof(in) == 8 +
sizeof(WOF_EXTERNAL_INFO) +
sizeof(struct wim_provider_rpdata));
in.hdr.rptag = WIM_IO_REPARSE_TAG_WOF;
in.hdr.rpdatalen = sizeof(in) - sizeof(in.hdr);
in.hdr.rpreserved = 0;
in.wof_info.Version = WOF_CURRENT_VERSION;
in.wof_info.Provider = WOF_PROVIDER_WIM;
in.wim_info.version = 2;
in.wim_info.flags = 0;
in.wim_info.data_source_id = data_source_id;
copy_hash(in.wim_info.unnamed_data_stream_hash, blob->hash);
copy_hash(in.wim_info.blob_table_hash, blob_table_hash);
in.wim_info.unnamed_data_stream_size = blob->size;
in.wim_info.unnamed_data_stream_size_in_wim = blob->rdesc->size_in_wim;
in.wim_info.unnamed_data_stream_offset_in_wim = blob->rdesc->offset_in_wim;
if (!DeviceIoControl(h, FSCTL_SET_REPARSE_POINT,
&in, sizeof(in), NULL, 0, &bytes_returned, NULL))
return false;
/* We also need to create an unnamed data stream of the correct
* size. Otherwise the file shows up as zero length. It can be
* a sparse stream containing all zeroes; its contents
* are unimportant. */
if (!DeviceIoControl(h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0,
&bytes_returned, NULL))
return false;
if (!SetFilePointerEx(h,
(LARGE_INTEGER){ .QuadPart = blob->size},
NULL, FILE_BEGIN))
return false;
if (!SetEndOfFile(h))
return false;
}
return true;
}
#endif /* _WIN32 */
wimlib-1.14.5/src/util.c 0000644 0001750 0001750 00000014366 15137020663 012304 0 ustar 00e e /*
* util.c - utility functions
*/
/*
* Copyright 2012-2023 Eric Biggers
*
* This file 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.
*
* This file 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 this file; if not, see https://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#include