xcrypt 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Rakefile +106 -0
- data/ext/libxcrypt/AUTHORS +38 -0
- data/ext/libxcrypt/COPYING.LIB +502 -0
- data/ext/libxcrypt/ChangeLog +239 -0
- data/ext/libxcrypt/INSTALL +380 -0
- data/ext/libxcrypt/LICENSING +152 -0
- data/ext/libxcrypt/Makefile.am +704 -0
- data/ext/libxcrypt/Makefile.in +4110 -0
- data/ext/libxcrypt/NEWS +630 -0
- data/ext/libxcrypt/README +1 -0
- data/ext/libxcrypt/README.md +179 -0
- data/ext/libxcrypt/THANKS +13 -0
- data/ext/libxcrypt/TODO +1 -0
- data/ext/libxcrypt/TODO.md +100 -0
- data/ext/libxcrypt/aclocal.m4 +2617 -0
- data/ext/libxcrypt/autogen.sh +33 -0
- data/ext/libxcrypt/autom4te.cache/output.0 +19884 -0
- data/ext/libxcrypt/autom4te.cache/output.1 +19884 -0
- data/ext/libxcrypt/autom4te.cache/output.2 +19884 -0
- data/ext/libxcrypt/autom4te.cache/output.3 +19885 -0
- data/ext/libxcrypt/autom4te.cache/requests +714 -0
- data/ext/libxcrypt/autom4te.cache/traces.0 +4088 -0
- data/ext/libxcrypt/autom4te.cache/traces.1 +1060 -0
- data/ext/libxcrypt/autom4te.cache/traces.2 +4088 -0
- data/ext/libxcrypt/autom4te.cache/traces.3 +1060 -0
- data/ext/libxcrypt/build-aux/ci/ci-log-dependency-versions +79 -0
- data/ext/libxcrypt/build-aux/ci/ci-log-logfiles +22 -0
- data/ext/libxcrypt/build-aux/ci/clang-gcov-wrapper +2 -0
- data/ext/libxcrypt/build-aux/ci/configure-wrapper +10 -0
- data/ext/libxcrypt/build-aux/ci/summarize-coverage +24 -0
- data/ext/libxcrypt/build-aux/m4/ax_append_compile_flags.m4 +46 -0
- data/ext/libxcrypt/build-aux/m4/ax_append_flag.m4 +50 -0
- data/ext/libxcrypt/build-aux/m4/ax_check_compile_flag.m4 +53 -0
- data/ext/libxcrypt/build-aux/m4/ax_check_vscript.m4 +142 -0
- data/ext/libxcrypt/build-aux/m4/ax_gcc_func_attribute.m4 +246 -0
- data/ext/libxcrypt/build-aux/m4/ax_require_defined.m4 +37 -0
- data/ext/libxcrypt/build-aux/m4/ax_valgrind_check.m4 +239 -0
- data/ext/libxcrypt/build-aux/m4/libtool.m4 +8488 -0
- data/ext/libxcrypt/build-aux/m4/ltoptions.m4 +467 -0
- data/ext/libxcrypt/build-aux/m4/ltsugar.m4 +124 -0
- data/ext/libxcrypt/build-aux/m4/ltversion.m4 +24 -0
- data/ext/libxcrypt/build-aux/m4/lt~obsolete.m4 +99 -0
- data/ext/libxcrypt/build-aux/m4/pkg_compat.m4 +88 -0
- data/ext/libxcrypt/build-aux/m4/zw_alignment.m4 +90 -0
- data/ext/libxcrypt/build-aux/m4/zw_automodern.m4 +307 -0
- data/ext/libxcrypt/build-aux/m4/zw_detect_asan.m4 +24 -0
- data/ext/libxcrypt/build-aux/m4/zw_endianness.m4 +152 -0
- data/ext/libxcrypt/build-aux/m4/zw_ld_wrap.m4 +47 -0
- data/ext/libxcrypt/build-aux/m4/zw_prog_perl.m4 +40 -0
- data/ext/libxcrypt/build-aux/m4/zw_simple_warnings.m4 +150 -0
- data/ext/libxcrypt/build-aux/m4/zw_static_assert.m4 +68 -0
- data/ext/libxcrypt/build-aux/m4-autogen/compile +364 -0
- data/ext/libxcrypt/build-aux/m4-autogen/config.guess +1815 -0
- data/ext/libxcrypt/build-aux/m4-autogen/config.sub +2354 -0
- data/ext/libxcrypt/build-aux/m4-autogen/depcomp +792 -0
- data/ext/libxcrypt/build-aux/m4-autogen/install-sh +541 -0
- data/ext/libxcrypt/build-aux/m4-autogen/ltmain.sh +11524 -0
- data/ext/libxcrypt/build-aux/m4-autogen/missing +236 -0
- data/ext/libxcrypt/build-aux/m4-autogen/test-driver +160 -0
- data/ext/libxcrypt/build-aux/scripts/BuildCommon.pm +712 -0
- data/ext/libxcrypt/build-aux/scripts/check-perlcritic-config +76 -0
- data/ext/libxcrypt/build-aux/scripts/compute-symver-floor +116 -0
- data/ext/libxcrypt/build-aux/scripts/expand-selected-hashes +80 -0
- data/ext/libxcrypt/build-aux/scripts/gen-crypt-h +131 -0
- data/ext/libxcrypt/build-aux/scripts/gen-crypt-hashes-h +141 -0
- data/ext/libxcrypt/build-aux/scripts/gen-crypt-symbol-vers-h +150 -0
- data/ext/libxcrypt/build-aux/scripts/gen-libcrypt-map +67 -0
- data/ext/libxcrypt/build-aux/scripts/move-if-change +84 -0
- data/ext/libxcrypt/build-aux/scripts/skip-if-exec-format-error +78 -0
- data/ext/libxcrypt/codecov.yml +4 -0
- data/ext/libxcrypt/config.h.in +303 -0
- data/ext/libxcrypt/configure +19885 -0
- data/ext/libxcrypt/configure.ac +549 -0
- data/ext/libxcrypt/doc/crypt.3 +512 -0
- data/ext/libxcrypt/doc/crypt.5 +343 -0
- data/ext/libxcrypt/doc/crypt_checksalt.3 +106 -0
- data/ext/libxcrypt/doc/crypt_gensalt.3 +285 -0
- data/ext/libxcrypt/doc/crypt_gensalt_ra.3 +1 -0
- data/ext/libxcrypt/doc/crypt_gensalt_rn.3 +1 -0
- data/ext/libxcrypt/doc/crypt_preferred_method.3 +68 -0
- data/ext/libxcrypt/doc/crypt_r.3 +1 -0
- data/ext/libxcrypt/doc/crypt_ra.3 +1 -0
- data/ext/libxcrypt/doc/crypt_rn.3 +1 -0
- data/ext/libxcrypt/lib/alg-des-tables.c +3858 -0
- data/ext/libxcrypt/lib/alg-des.c +269 -0
- data/ext/libxcrypt/lib/alg-des.h +74 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-const.h +313 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-core.c +238 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-core.h +51 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-hmac.c +78 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-hmac.h +46 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-precalc.h +1426 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-ref.h +67 -0
- data/ext/libxcrypt/lib/alg-hmac-sha1.c +140 -0
- data/ext/libxcrypt/lib/alg-hmac-sha1.h +35 -0
- data/ext/libxcrypt/lib/alg-md4.c +270 -0
- data/ext/libxcrypt/lib/alg-md4.h +43 -0
- data/ext/libxcrypt/lib/alg-md5.c +291 -0
- data/ext/libxcrypt/lib/alg-md5.h +43 -0
- data/ext/libxcrypt/lib/alg-sha1.c +288 -0
- data/ext/libxcrypt/lib/alg-sha1.h +34 -0
- data/ext/libxcrypt/lib/alg-sha256.c +630 -0
- data/ext/libxcrypt/lib/alg-sha256.h +123 -0
- data/ext/libxcrypt/lib/alg-sha512.c +311 -0
- data/ext/libxcrypt/lib/alg-sha512.h +81 -0
- data/ext/libxcrypt/lib/alg-sm3-hmac.c +113 -0
- data/ext/libxcrypt/lib/alg-sm3-hmac.h +42 -0
- data/ext/libxcrypt/lib/alg-sm3.c +449 -0
- data/ext/libxcrypt/lib/alg-sm3.h +63 -0
- data/ext/libxcrypt/lib/alg-yescrypt-common.c +713 -0
- data/ext/libxcrypt/lib/alg-yescrypt-opt.c +1568 -0
- data/ext/libxcrypt/lib/alg-yescrypt-platform.c +106 -0
- data/ext/libxcrypt/lib/alg-yescrypt.h +360 -0
- data/ext/libxcrypt/lib/byteorder.h +164 -0
- data/ext/libxcrypt/lib/crypt-bcrypt.c +1061 -0
- data/ext/libxcrypt/lib/crypt-des-obsolete.c +215 -0
- data/ext/libxcrypt/lib/crypt-des.c +491 -0
- data/ext/libxcrypt/lib/crypt-gensalt-static.c +40 -0
- data/ext/libxcrypt/lib/crypt-gost-yescrypt.c +182 -0
- data/ext/libxcrypt/lib/crypt-md5.c +232 -0
- data/ext/libxcrypt/lib/crypt-nthash.c +134 -0
- data/ext/libxcrypt/lib/crypt-obsolete.h +40 -0
- data/ext/libxcrypt/lib/crypt-pbkdf1-sha1.c +260 -0
- data/ext/libxcrypt/lib/crypt-port.h +514 -0
- data/ext/libxcrypt/lib/crypt-scrypt.c +247 -0
- data/ext/libxcrypt/lib/crypt-sha256.c +308 -0
- data/ext/libxcrypt/lib/crypt-sha512.c +323 -0
- data/ext/libxcrypt/lib/crypt-sm3-yescrypt.c +189 -0
- data/ext/libxcrypt/lib/crypt-sm3.c +308 -0
- data/ext/libxcrypt/lib/crypt-static.c +44 -0
- data/ext/libxcrypt/lib/crypt-sunmd5.c +314 -0
- data/ext/libxcrypt/lib/crypt-yescrypt.c +177 -0
- data/ext/libxcrypt/lib/crypt.c +421 -0
- data/ext/libxcrypt/lib/crypt.h.in +249 -0
- data/ext/libxcrypt/lib/gen-des-tables.c +363 -0
- data/ext/libxcrypt/lib/hashes.conf +59 -0
- data/ext/libxcrypt/lib/libcrypt.map.in +48 -0
- data/ext/libxcrypt/lib/libcrypt.minver +97 -0
- data/ext/libxcrypt/lib/libxcrypt.pc.in +15 -0
- data/ext/libxcrypt/lib/util-base64.c +26 -0
- data/ext/libxcrypt/lib/util-gensalt-sha.c +88 -0
- data/ext/libxcrypt/lib/util-get-random-bytes.c +154 -0
- data/ext/libxcrypt/lib/util-make-failure-token.c +48 -0
- data/ext/libxcrypt/lib/util-xbzero.c +43 -0
- data/ext/libxcrypt/lib/util-xstrcpy.c +42 -0
- data/ext/libxcrypt/lib/xcrypt.h.in +58 -0
- data/ext/libxcrypt/libxcrypt.spec.rpkg +481 -0
- data/ext/libxcrypt/rpkg.conf +2 -0
- data/ext/libxcrypt/rpkg.macros +86 -0
- data/ext/libxcrypt/test/TestCommon.pm +326 -0
- data/ext/libxcrypt/test/alg-des.c +80 -0
- data/ext/libxcrypt/test/alg-gost3411-2012-hmac.c +90 -0
- data/ext/libxcrypt/test/alg-gost3411-2012.c +191 -0
- data/ext/libxcrypt/test/alg-hmac-sha1.c +187 -0
- data/ext/libxcrypt/test/alg-md4.c +111 -0
- data/ext/libxcrypt/test/alg-md5.c +134 -0
- data/ext/libxcrypt/test/alg-pbkdf-hmac-sha256.c +269 -0
- data/ext/libxcrypt/test/alg-sha1.c +111 -0
- data/ext/libxcrypt/test/alg-sha256.c +141 -0
- data/ext/libxcrypt/test/alg-sha512.c +170 -0
- data/ext/libxcrypt/test/alg-sm3-hmac.c +149 -0
- data/ext/libxcrypt/test/alg-sm3.c +168 -0
- data/ext/libxcrypt/test/alg-yescrypt.c +466 -0
- data/ext/libxcrypt/test/badsalt.c +726 -0
- data/ext/libxcrypt/test/badsetting.c +350 -0
- data/ext/libxcrypt/test/byteorder.c +254 -0
- data/ext/libxcrypt/test/checksalt.c +265 -0
- data/ext/libxcrypt/test/compile-strong-alias.c +43 -0
- data/ext/libxcrypt/test/crypt-badargs.c +392 -0
- data/ext/libxcrypt/test/crypt-gost-yescrypt.c +149 -0
- data/ext/libxcrypt/test/crypt-nested-call.c +180 -0
- data/ext/libxcrypt/test/crypt-sm3-yescrypt.c +149 -0
- data/ext/libxcrypt/test/crypt-too-long-phrase.c +157 -0
- data/ext/libxcrypt/test/des-cases.h +196 -0
- data/ext/libxcrypt/test/des-obsolete.c +206 -0
- data/ext/libxcrypt/test/des-obsolete_r.c +207 -0
- data/ext/libxcrypt/test/explicit-bzero.c +334 -0
- data/ext/libxcrypt/test/gensalt-bcrypt_x.c +54 -0
- data/ext/libxcrypt/test/gensalt-extradata.c +246 -0
- data/ext/libxcrypt/test/gensalt-nested-call.c +126 -0
- data/ext/libxcrypt/test/gensalt-nthash.c +65 -0
- data/ext/libxcrypt/test/gensalt.c +599 -0
- data/ext/libxcrypt/test/getrandom-fallbacks.c +295 -0
- data/ext/libxcrypt/test/getrandom-interface.c +211 -0
- data/ext/libxcrypt/test/ka-table-gen.py +945 -0
- data/ext/libxcrypt/test/ka-table.inc +5849 -0
- data/ext/libxcrypt/test/ka-tester.c +240 -0
- data/ext/libxcrypt/test/preferred-method.c +133 -0
- data/ext/libxcrypt/test/short-outbuf.c +119 -0
- data/ext/libxcrypt/test/special-char-salt.c +1160 -0
- data/ext/libxcrypt/test/symbols-compat.pl +137 -0
- data/ext/libxcrypt/test/symbols-renames.pl +107 -0
- data/ext/libxcrypt/test/symbols-static.pl +87 -0
- data/ext/xcrypt/xcrypt.c +9 -0
- data/lib/xcrypt/ffi.rb +76 -0
- data/lib/xcrypt/version.rb +5 -0
- data/lib/xcrypt.rb +89 -0
- metadata +267 -0
|
@@ -0,0 +1,712 @@
|
|
|
1
|
+
# Written by Zack Weinberg <zackw at panix.com> in 2017 and 2020.
|
|
2
|
+
# To the extent possible under law, Zack Weinberg has waived all
|
|
3
|
+
# copyright and related or neighboring rights to this work.
|
|
4
|
+
#
|
|
5
|
+
# See https://creativecommons.org/publicdomain/zero/1.0/ for further
|
|
6
|
+
# details.
|
|
7
|
+
|
|
8
|
+
package BuildCommon;
|
|
9
|
+
|
|
10
|
+
use v5.14; # implicit use strict, use feature ':5.14'
|
|
11
|
+
use warnings FATAL => 'all';
|
|
12
|
+
use utf8;
|
|
13
|
+
use open qw(:utf8);
|
|
14
|
+
no if $] >= 5.022, warnings => 'experimental::re_strict';
|
|
15
|
+
use if $] >= 5.022, re => 'strict';
|
|
16
|
+
|
|
17
|
+
use Cwd qw(realpath);
|
|
18
|
+
use File::Spec::Functions qw(
|
|
19
|
+
catfile
|
|
20
|
+
catpath
|
|
21
|
+
file_name_is_absolute
|
|
22
|
+
path
|
|
23
|
+
splitpath
|
|
24
|
+
);
|
|
25
|
+
use FindBin ();
|
|
26
|
+
use POSIX ();
|
|
27
|
+
|
|
28
|
+
our @EXPORT_OK;
|
|
29
|
+
use Exporter qw(import);
|
|
30
|
+
|
|
31
|
+
BEGIN {
|
|
32
|
+
@EXPORT_OK = qw(
|
|
33
|
+
enabled_set
|
|
34
|
+
ensure_C_locale
|
|
35
|
+
error
|
|
36
|
+
parse_hashes_conf
|
|
37
|
+
parse_version_map_in
|
|
38
|
+
popen
|
|
39
|
+
sh_split
|
|
40
|
+
sh_quote
|
|
41
|
+
subprocess_error
|
|
42
|
+
which
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
# Utilities for dealing with subprocesses.
|
|
48
|
+
#
|
|
49
|
+
|
|
50
|
+
# Diagnostics: report some kind of catastrophic internal error.
|
|
51
|
+
# Exit code 99 tells the Automake test driver to mark a test as
|
|
52
|
+
# 'errored' rather than 'failed'.
|
|
53
|
+
sub error { ## no critic (Subroutines::RequireArgUnpacking)
|
|
54
|
+
my $msg = join q{ }, @_;
|
|
55
|
+
print {*STDERR} $FindBin::Script, ': ERROR: ', $msg, "\n";
|
|
56
|
+
exit 99;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# Like 'error', but the problem was with a subprocess, detected upon
|
|
60
|
+
# trying to start the program named as @_.
|
|
61
|
+
sub invocation_error { ## no critic (Subroutines::RequireArgUnpacking)
|
|
62
|
+
my $err = "$!";
|
|
63
|
+
my $cmd = join q{ }, @_;
|
|
64
|
+
error("failed to invoke $cmd: $err");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Like 'error', but the problem was with a subprocess, detected upon
|
|
68
|
+
# termination of the program named as @_; interpret both $! and $?
|
|
69
|
+
# appropriately.
|
|
70
|
+
sub subprocess_error { ## no critic (Subroutines::RequireArgUnpacking)
|
|
71
|
+
my $syserr = $!;
|
|
72
|
+
my $status = $?;
|
|
73
|
+
my $cmd = join q{ }, @_;
|
|
74
|
+
if ($syserr) {
|
|
75
|
+
error("system error with pipe to $cmd: $syserr");
|
|
76
|
+
|
|
77
|
+
} elsif ($status == 0) {
|
|
78
|
+
return;
|
|
79
|
+
|
|
80
|
+
} elsif (($status & 0xFF) == 0) {
|
|
81
|
+
# we wouldn't be here if the exit status was zero
|
|
82
|
+
error("$cmd: exit " . ($status >> 8));
|
|
83
|
+
|
|
84
|
+
} else {
|
|
85
|
+
my $sig = ($status & 0x7F);
|
|
86
|
+
# Neither Perl core nor the POSIX module exposes strsignal.
|
|
87
|
+
# This is the least terrible kludge I can presently find;
|
|
88
|
+
# it decodes the numbers to their <signal.h> constant names
|
|
89
|
+
# (e.g. "SIGKILL" instead of "Killed" for signal 9).
|
|
90
|
+
# Linear search through POSIX's hundreds of symbols is
|
|
91
|
+
# acceptable because this function terminates the process,
|
|
92
|
+
# so it can only ever be called once per run.
|
|
93
|
+
my $signame;
|
|
94
|
+
while (my ($name, $glob) = each %{'POSIX::'}) {
|
|
95
|
+
if ($name =~ /^SIG(?!_|RT)/ && (${$glob} // -1) == $sig) {
|
|
96
|
+
$signame = $name;
|
|
97
|
+
last;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
$signame //= "signal $sig";
|
|
101
|
+
error("$cmd: killed by $signame");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
# Split a string into words, exactly the way the Bourne shell would do
|
|
106
|
+
# it, with the default setting of IFS, when the string is the result
|
|
107
|
+
# of a variable expansion. If any of the resulting words would be
|
|
108
|
+
# changed by filename expansion, throw an exception, otherwise return
|
|
109
|
+
# a list of the words.
|
|
110
|
+
#
|
|
111
|
+
# Note: the word splitting process does *not* look for nested
|
|
112
|
+
# quotation, substitutions, or operators. For instance, if a
|
|
113
|
+
# shell variable was set with
|
|
114
|
+
# var='"ab cd"'
|
|
115
|
+
# then './a.out $var' would pass two arguments to a.out:
|
|
116
|
+
# '"ab' and 'cd"'.
|
|
117
|
+
sub sh_split {
|
|
118
|
+
my @words = split /[ \t\n]+/, shift;
|
|
119
|
+
for my $w (@words) {
|
|
120
|
+
die "sh_split: '$w' could be changed by filename expansion"
|
|
121
|
+
if $w =~ / (?<! \\) [\[?*] /ax;
|
|
122
|
+
}
|
|
123
|
+
return @words;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Quote a string, or list of strings, so that they will pass
|
|
127
|
+
# unmolested through the shell. Avoids adding quotation whenever
|
|
128
|
+
# possible. Algorithm copied from Python's shlex.quote.
|
|
129
|
+
sub sh_quote { ## no critic (Subroutines::RequireArgUnpacking)
|
|
130
|
+
my @quoted;
|
|
131
|
+
for my $w (@_) {
|
|
132
|
+
if ($w =~ m{[^\w@%+=:,./-]}a) {
|
|
133
|
+
my $q = $w;
|
|
134
|
+
$q =~ s/'/'\\''/g;
|
|
135
|
+
$q =~ s/^/'/;
|
|
136
|
+
$q =~ s/$/'/;
|
|
137
|
+
push @quoted, $q;
|
|
138
|
+
} else {
|
|
139
|
+
push @quoted, $w;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return wantarray ? @quoted : $quoted[0];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
# Emit a logging message for the execution of a subprocess whose
|
|
146
|
+
# argument vector is @_.
|
|
147
|
+
sub log_execution { ## no critic (Subroutines::RequireArgUnpacking)
|
|
148
|
+
print {*STDERR} '+ ', join(q{ }, sh_quote(@_)), "\n";
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
# Run, and log execution of, a subprocess. @_ should be one of the
|
|
153
|
+
# open modes that creates a pipe, followed by an argument vector.
|
|
154
|
+
# An anonymous filehandle for the pipe is returned.
|
|
155
|
+
# Calls invocation_error() if open() fails.
|
|
156
|
+
# Does *not* call which(); do that yourself if you need it.
|
|
157
|
+
sub popen {
|
|
158
|
+
my ($mode, @args) = @_;
|
|
159
|
+
die "popen: inappropriate mode argument '$mode'"
|
|
160
|
+
unless $mode eq '-|' || $mode eq '|-';
|
|
161
|
+
die 'popen: no command to execute'
|
|
162
|
+
if scalar(@args) == 0;
|
|
163
|
+
|
|
164
|
+
log_execution(@args);
|
|
165
|
+
open my $fh, $mode, @args
|
|
166
|
+
or invocation_error($args[0]);
|
|
167
|
+
return $fh;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# Force use of the C locale for this process and all subprocesses.
|
|
171
|
+
# This is necessary because subprocesses' output may be locale-
|
|
172
|
+
# dependent. If the C.UTF-8 locale is available, it is used,
|
|
173
|
+
# otherwise the plain C locale. Note that we do *not*
|
|
174
|
+
# 'use locale' here or anywhere else!
|
|
175
|
+
sub ensure_C_locale {
|
|
176
|
+
use POSIX qw(setlocale LC_ALL);
|
|
177
|
+
|
|
178
|
+
for my $k (keys %ENV) {
|
|
179
|
+
if ($k eq 'LANG' || $k eq 'LANGUAGE' || $k =~ /^LC_/) {
|
|
180
|
+
delete $ENV{$k};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (defined(setlocale(LC_ALL, 'C.UTF-8'))) {
|
|
184
|
+
$ENV{LC_ALL} = 'C.UTF-8'; ## no critic (RequireLocalizedPunctuationVars)
|
|
185
|
+
} elsif (defined(setlocale(LC_ALL, 'C'))) {
|
|
186
|
+
$ENV{LC_ALL} = 'C'; ## no critic (RequireLocalizedPunctuationVars)
|
|
187
|
+
} else {
|
|
188
|
+
error("could not set 'C' locale: $!");
|
|
189
|
+
}
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# Clean up $ENV{PATH}, and return the cleaned path as a list.
|
|
194
|
+
sub clean_PATH {
|
|
195
|
+
state @path;
|
|
196
|
+
if (!@path) {
|
|
197
|
+
for my $d (path()) {
|
|
198
|
+
# Discard all entries that are not absolute paths.
|
|
199
|
+
next unless file_name_is_absolute($d);
|
|
200
|
+
# Discard all entries that are not directories, or don't
|
|
201
|
+
# exist. (This is not just for tidiness; realpath()
|
|
202
|
+
# behaves unpredictably if called on a nonexistent
|
|
203
|
+
# pathname.)
|
|
204
|
+
next unless -d $d;
|
|
205
|
+
# Resolve symlinks in all remaining entries.
|
|
206
|
+
$d = realpath($d);
|
|
207
|
+
# Discard duplicates.
|
|
208
|
+
push @path, $d unless grep { $_ eq $d } @path;
|
|
209
|
+
}
|
|
210
|
+
error('nothing left after cleaning PATH')
|
|
211
|
+
unless @path;
|
|
212
|
+
|
|
213
|
+
# File::Spec knows internally whether $PATH is colon-separated
|
|
214
|
+
# or semicolon-separated, but it won't tell us. Assume it's
|
|
215
|
+
# colon-separated unless the first element of $PATH has a
|
|
216
|
+
# colon in it (and is therefore probably a DOS-style absolute
|
|
217
|
+
# path, with a drive letter).
|
|
218
|
+
my $newpath;
|
|
219
|
+
if ($path[0] =~ /:/) {
|
|
220
|
+
$newpath = join ';', @path;
|
|
221
|
+
} else {
|
|
222
|
+
$newpath = join ':', @path;
|
|
223
|
+
}
|
|
224
|
+
$ENV{PATH} = $newpath; ## no critic (RequireLocalizedPunctuationVars)
|
|
225
|
+
}
|
|
226
|
+
return @path;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
# Locate a program that we need.
|
|
230
|
+
# $_[0] is the name of the program along with any options that are
|
|
231
|
+
# required to use it correctly. Split this into an argument list,
|
|
232
|
+
# exactly as /bin/sh would do it, and then search $PATH for the
|
|
233
|
+
# executable. If we find it, return a list whose first element is
|
|
234
|
+
# the absolute pathname of the executable, followed by any options.
|
|
235
|
+
# Otherwise return an empty list.
|
|
236
|
+
sub which {
|
|
237
|
+
my ($command) = @_;
|
|
238
|
+
my @PATH = clean_PATH();
|
|
239
|
+
|
|
240
|
+
# Split the command name from any options attached to it.
|
|
241
|
+
my ($cmd, @options) = sh_split($command);
|
|
242
|
+
my ($vol, $path, $file) = splitpath($cmd);
|
|
243
|
+
|
|
244
|
+
if ($file eq 'false') {
|
|
245
|
+
# Special case: the command 'false' is never considered to be
|
|
246
|
+
# available. Autoconf sets config variables like $CC and $NM to
|
|
247
|
+
# 'false' if it can't find the requested tool.
|
|
248
|
+
return ();
|
|
249
|
+
|
|
250
|
+
} elsif ($file ne $cmd) {
|
|
251
|
+
# $cmd was not a bare filename. Do not do path search, but do
|
|
252
|
+
# verify that $cmd exists and is executable, then convert it
|
|
253
|
+
# to a canonical absolute path.
|
|
254
|
+
#
|
|
255
|
+
# Note: the result of realpath() is unspecified if its
|
|
256
|
+
# argument does not exist, so we must test its existence
|
|
257
|
+
# first.
|
|
258
|
+
#
|
|
259
|
+
# Note: if $file is a symlink, we must *not* resolve that
|
|
260
|
+
# symlink, because that may change the name of the program,
|
|
261
|
+
# which in turn may change what the program does.
|
|
262
|
+
# For instance, suppose $CC is /usr/lib/ccache/cc, and this
|
|
263
|
+
# 'cc' is a symlink to /usr/bin/ccache. Resolving the symlink
|
|
264
|
+
# will cause ccache to be invoked as 'ccache' instead of 'cc'
|
|
265
|
+
# and it will error out because it's no longer being told
|
|
266
|
+
# it's supposed to run the compiler.
|
|
267
|
+
if (-f -x $cmd) {
|
|
268
|
+
return (catfile(realpath(catpath($vol, $path, q{})), $file),
|
|
269
|
+
@options);
|
|
270
|
+
} else {
|
|
271
|
+
return ();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
} else {
|
|
275
|
+
for my $d (@PATH) {
|
|
276
|
+
my $cand = catfile($d, $cmd);
|
|
277
|
+
if (-f -x $cand) {
|
|
278
|
+
# @PATH came from clean_PATH, so all of the directories
|
|
279
|
+
# have already been canonicalized. If the last element
|
|
280
|
+
# of $cand is a symlink, we should *not* resolve it (see
|
|
281
|
+
# above). Therefore, we do not call realpath here.
|
|
282
|
+
return ($cand, @options);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return ();
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
#
|
|
291
|
+
# Code shared among scripts that work from hashes.conf
|
|
292
|
+
#
|
|
293
|
+
|
|
294
|
+
use Class::Struct HashSpec => [
|
|
295
|
+
name => '$',
|
|
296
|
+
prefix => '$',
|
|
297
|
+
nrbytes => '$',
|
|
298
|
+
is_strong => '$',
|
|
299
|
+
];
|
|
300
|
+
use Class::Struct HashesConfData => [
|
|
301
|
+
hashes => '*%',
|
|
302
|
+
groups => '*%',
|
|
303
|
+
max_namelen => '$',
|
|
304
|
+
max_nrbyteslen => '$',
|
|
305
|
+
max_prefixlen => '$',
|
|
306
|
+
default_candidates => '*@',
|
|
307
|
+
];
|
|
308
|
+
|
|
309
|
+
# The canonical list of flags that can appear in the fourth field
|
|
310
|
+
# of a hashes.conf entry. Alphabetical, except for STRONG and
|
|
311
|
+
# DEFAULT.
|
|
312
|
+
my %VALID_FLAGS = (
|
|
313
|
+
STRONG => 1,
|
|
314
|
+
DEFAULT => 1,
|
|
315
|
+
ALT => 1,
|
|
316
|
+
DEBIAN => 1,
|
|
317
|
+
EULER => 1,
|
|
318
|
+
FEDORA => 1,
|
|
319
|
+
FREEBSD => 1,
|
|
320
|
+
GLIBC => 1,
|
|
321
|
+
KYLIN => 1,
|
|
322
|
+
NETBSD => 1,
|
|
323
|
+
OPENBSD => 1,
|
|
324
|
+
OSX => 1,
|
|
325
|
+
OWL => 1,
|
|
326
|
+
SOLARIS => 1,
|
|
327
|
+
SUSE => 1,
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
sub parse_hashes_conf {
|
|
331
|
+
my $fname = shift;
|
|
332
|
+
my $error = 0;
|
|
333
|
+
|
|
334
|
+
my $err = sub {
|
|
335
|
+
my ($line, $msg) = @_;
|
|
336
|
+
if (!defined $msg) {
|
|
337
|
+
$msg = $line;
|
|
338
|
+
$line = $.;
|
|
339
|
+
}
|
|
340
|
+
print {*STDERR} "$fname:$line: error: $msg\n";
|
|
341
|
+
$error = 1;
|
|
342
|
+
};
|
|
343
|
+
my $note = sub {
|
|
344
|
+
my ($line, $msg) = @_;
|
|
345
|
+
if (!defined $msg) {
|
|
346
|
+
$msg = $line;
|
|
347
|
+
$line = $.;
|
|
348
|
+
}
|
|
349
|
+
print {*STDERR} "$fname:$line: note: $msg\n";
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
open my $fh, '<', $fname
|
|
353
|
+
or die "$fname: $!\n";
|
|
354
|
+
|
|
355
|
+
my %line_of;
|
|
356
|
+
my %hashes;
|
|
357
|
+
my %groups;
|
|
358
|
+
my $max_namelen = 0;
|
|
359
|
+
my $max_nrbyteslen = 0;
|
|
360
|
+
my $max_prefixlen = 0;
|
|
361
|
+
my @default_candidates;
|
|
362
|
+
local $_;
|
|
363
|
+
while (<$fh>) {
|
|
364
|
+
next if /^#/;
|
|
365
|
+
chomp;
|
|
366
|
+
s/\s+$//;
|
|
367
|
+
next if $_ eq q{};
|
|
368
|
+
|
|
369
|
+
my @fields = split;
|
|
370
|
+
if (scalar(@fields) != 4) {
|
|
371
|
+
$err->('wrong number of fields');
|
|
372
|
+
next;
|
|
373
|
+
}
|
|
374
|
+
my ($name, $h_prefix, $nrbytes, $flags) = @fields;
|
|
375
|
+
my $default_cand = 0;
|
|
376
|
+
my $is_strong = 0;
|
|
377
|
+
my @grps;
|
|
378
|
+
|
|
379
|
+
if ($name eq ':') {
|
|
380
|
+
$err->('method name cannot be blank');
|
|
381
|
+
$name = "_missing_$.";
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
# No two hashing method names can be the same.
|
|
385
|
+
if (exists $line_of{$name}) {
|
|
386
|
+
$err->("method name '$name' reused");
|
|
387
|
+
$note->($line_of{$name}, 'previous use was here');
|
|
388
|
+
} else {
|
|
389
|
+
$line_of{$name} = $.;
|
|
390
|
+
if ($max_namelen < length $name) {
|
|
391
|
+
$max_namelen = length $name;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
$h_prefix = q{} if $h_prefix eq ':';
|
|
396
|
+
if ($max_prefixlen < length $h_prefix) {
|
|
397
|
+
$max_prefixlen = length $h_prefix;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if ($nrbytes !~ /^[0-9]+$/ || $nrbytes == 0) {
|
|
401
|
+
$err->('nrbytes must be a positive integer');
|
|
402
|
+
$nrbytes = 1;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if ($max_nrbyteslen < length $nrbytes) {
|
|
406
|
+
$max_nrbyteslen = length $nrbytes;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
$flags = q{} if $flags eq ':';
|
|
410
|
+
for (split /,/, $flags) {
|
|
411
|
+
if (!exists $VALID_FLAGS{$_}) {
|
|
412
|
+
$err->("unrecognized flag $_");
|
|
413
|
+
} elsif ($_ eq 'DEFAULT') {
|
|
414
|
+
$default_cand = 1;
|
|
415
|
+
} else {
|
|
416
|
+
push @grps, lc;
|
|
417
|
+
if ($_ eq 'STRONG') {
|
|
418
|
+
$is_strong = 1;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if ($default_cand && !$is_strong) {
|
|
423
|
+
$err->('weak hash marked as default candidate');
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
next if $error;
|
|
427
|
+
|
|
428
|
+
my $entry = HashSpec->new(
|
|
429
|
+
name => $name,
|
|
430
|
+
prefix => $h_prefix,
|
|
431
|
+
nrbytes => $nrbytes,
|
|
432
|
+
is_strong => $is_strong,
|
|
433
|
+
);
|
|
434
|
+
$hashes{$name} = $entry;
|
|
435
|
+
for my $g (@grps) {
|
|
436
|
+
push @{$groups{$g}}, $entry;
|
|
437
|
+
}
|
|
438
|
+
if ($default_cand) {
|
|
439
|
+
push @default_candidates, $entry;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
# No hash prefix can be a prefix of any other hash prefix, except
|
|
444
|
+
# for the empty prefix.
|
|
445
|
+
for my $p (values %hashes) {
|
|
446
|
+
my $pp = $p->prefix;
|
|
447
|
+
next if $pp eq q{};
|
|
448
|
+
my $mpp = qr/^\Q$pp\E/;
|
|
449
|
+
for my $q (values %hashes) {
|
|
450
|
+
next if $p->name eq $q->name;
|
|
451
|
+
my $pq = $q->prefix;
|
|
452
|
+
next if $pq eq q{};
|
|
453
|
+
if ($pq =~ $mpp) {
|
|
454
|
+
$err->(
|
|
455
|
+
$line_of{$q->name},
|
|
456
|
+
"prefix collision: '$pq' begins with '$pp'",
|
|
457
|
+
);
|
|
458
|
+
$note->(
|
|
459
|
+
$line_of{$p->name},
|
|
460
|
+
"'$pp' used for hash '" . $p->name . q{'},
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
die "errors while parsing '$fname'\n" if $error;
|
|
467
|
+
return HashesConfData->new(
|
|
468
|
+
hashes => \%hashes,
|
|
469
|
+
groups => \%groups,
|
|
470
|
+
max_namelen => $max_namelen,
|
|
471
|
+
max_nrbyteslen => $max_nrbyteslen,
|
|
472
|
+
max_prefixlen => $max_prefixlen,
|
|
473
|
+
default_candidates => \@default_candidates,
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
sub enabled_set {
|
|
478
|
+
return map { $_ => 1 }
|
|
479
|
+
grep { $_ ne q{} }
|
|
480
|
+
split /,/,
|
|
481
|
+
shift;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
#
|
|
485
|
+
# Code shared among scripts that work from libcrypt.map.in
|
|
486
|
+
#
|
|
487
|
+
|
|
488
|
+
use Class::Struct VersionedSymbol => [
|
|
489
|
+
name => '$',
|
|
490
|
+
included => '$',
|
|
491
|
+
compat_only => '$',
|
|
492
|
+
versions => '*@',
|
|
493
|
+
];
|
|
494
|
+
|
|
495
|
+
use Class::Struct SymbolVersionMap => [
|
|
496
|
+
symbols => '*@',
|
|
497
|
+
versions => '*@',
|
|
498
|
+
basemap => '$',
|
|
499
|
+
max_symlen => '$',
|
|
500
|
+
];
|
|
501
|
+
|
|
502
|
+
# Process command-line arguments to a program that works from a
|
|
503
|
+
# .map.in file. These are the name of the .map.in file plus var=value
|
|
504
|
+
# settings for SYMVER_MIN, SYMVER_FLOOR, and COMPAT_ABI, in any order.
|
|
505
|
+
sub parse_symver_args {
|
|
506
|
+
my (@args) = @_;
|
|
507
|
+
my $usage_error = sub {
|
|
508
|
+
print {*STDERR}
|
|
509
|
+
"${FindBin::Script}: usage: ",
|
|
510
|
+
'SYMVER_MIN=value SYMVER_FLOOR=value ',
|
|
511
|
+
'COMPAT_ABI=value libcrypt.map.in',
|
|
512
|
+
"\n";
|
|
513
|
+
exit 1;
|
|
514
|
+
};
|
|
515
|
+
$usage_error->() if scalar(@args) != 4;
|
|
516
|
+
|
|
517
|
+
my $map_in;
|
|
518
|
+
my $SYMVER_MIN;
|
|
519
|
+
my $SYMVER_FLOOR;
|
|
520
|
+
my $COMPAT_ABI;
|
|
521
|
+
local $_;
|
|
522
|
+
for (@args) {
|
|
523
|
+
if (/^SYMVER_MIN=(.+)$/) {
|
|
524
|
+
$usage_error->() if defined $SYMVER_MIN;
|
|
525
|
+
$SYMVER_MIN = $1;
|
|
526
|
+
} elsif (/^SYMVER_FLOOR=(.+)$/) {
|
|
527
|
+
$usage_error->() if defined $SYMVER_FLOOR;
|
|
528
|
+
$SYMVER_FLOOR = $1;
|
|
529
|
+
} elsif (/^COMPAT_ABI=(.+)$/) {
|
|
530
|
+
$usage_error->() if defined $COMPAT_ABI;
|
|
531
|
+
$COMPAT_ABI = $1;
|
|
532
|
+
} else {
|
|
533
|
+
$usage_error->() if defined $map_in;
|
|
534
|
+
$map_in = $_;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
return $map_in, $SYMVER_MIN, $SYMVER_FLOOR, $COMPAT_ABI;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
# Read a .map.in file and compute the set of symbol versions to be
|
|
541
|
+
# included in this build of the library.
|
|
542
|
+
#
|
|
543
|
+
# All compat symbol versions that do not match COMPAT_ABI are ignored.
|
|
544
|
+
# All symbol versions lower than SYMVER_MIN are discarded from the output.
|
|
545
|
+
# All symbol versions lower than SYMVER_FLOOR are replaced with SYMVER_FLOOR.
|
|
546
|
+
# SYMVER_FLOOR must be greater than or equal to SYMVER_MIN.
|
|
547
|
+
#
|
|
548
|
+
# The ordering of symbol versions is entirely controlled by the %chain
|
|
549
|
+
# directive, which must therefore list both all of the versions
|
|
550
|
+
# actually used for symbols, and all of the versions that might be
|
|
551
|
+
# used as SYMVER_MIN or SYMVER_FLOOR.
|
|
552
|
+
sub parse_version_map_in { ## no critic (Subroutines::RequireArgUnpacking)
|
|
553
|
+
my ($map_in, $SYMVER_MIN, $SYMVER_FLOOR, $COMPAT_ABI) =
|
|
554
|
+
parse_symver_args(@_);
|
|
555
|
+
|
|
556
|
+
my %symbols;
|
|
557
|
+
my %vorder;
|
|
558
|
+
my $vmax = 0;
|
|
559
|
+
my $error;
|
|
560
|
+
my $max_symlen = 0;
|
|
561
|
+
open my $fh, '<', $map_in
|
|
562
|
+
or die "$map_in: $!\n";
|
|
563
|
+
|
|
564
|
+
local $_;
|
|
565
|
+
while (<$fh>) {
|
|
566
|
+
next if /^#/;
|
|
567
|
+
chomp;
|
|
568
|
+
s/\s+$//;
|
|
569
|
+
next if $_ eq q{};
|
|
570
|
+
|
|
571
|
+
my @vers = split;
|
|
572
|
+
my $sym = shift @vers;
|
|
573
|
+
if ($sym eq '%chain') {
|
|
574
|
+
for my $v (@vers) {
|
|
575
|
+
if (exists $vorder{$v}) {
|
|
576
|
+
print {*STDERR}
|
|
577
|
+
"$map_in:$.: error: '$v' used twice in %chain\n";
|
|
578
|
+
$error = 1;
|
|
579
|
+
next;
|
|
580
|
+
}
|
|
581
|
+
$vorder{$v} = $vmax;
|
|
582
|
+
$vmax++;
|
|
583
|
+
}
|
|
584
|
+
next;
|
|
585
|
+
}
|
|
586
|
+
if (exists $symbols{$sym}) {
|
|
587
|
+
print {*STDERR}
|
|
588
|
+
"$map_in:$.: error: more than one entry for '$sym'\n";
|
|
589
|
+
$error = 1;
|
|
590
|
+
next;
|
|
591
|
+
}
|
|
592
|
+
if ($max_symlen < length $sym) {
|
|
593
|
+
$max_symlen = length $sym;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
# Dash in the second field means there is no default version
|
|
597
|
+
# for this symbol.
|
|
598
|
+
my $compat_only = 0;
|
|
599
|
+
if ($vers[0] eq '-') {
|
|
600
|
+
$compat_only = 1;
|
|
601
|
+
shift @vers;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
my @enabled_vers;
|
|
605
|
+
for my $v (@vers) {
|
|
606
|
+
# Each $v is a symbol version name followed by zero
|
|
607
|
+
# or more compatibility tags, separated by colons.
|
|
608
|
+
# If there are no tags, the symbol version is available
|
|
609
|
+
# unconditionally; if there are any tags, the symbol
|
|
610
|
+
# version is available if COMPAT_ABI is equal to 'yes'
|
|
611
|
+
# or equal to one of the tags.
|
|
612
|
+
my @tags = split /:/, $v;
|
|
613
|
+
$v = shift @tags;
|
|
614
|
+
my $enabled = 1;
|
|
615
|
+
if (@tags && $COMPAT_ABI ne 'yes') {
|
|
616
|
+
$enabled = 0;
|
|
617
|
+
for my $t (@tags) {
|
|
618
|
+
if ($t eq $COMPAT_ABI) {
|
|
619
|
+
$enabled = 1;
|
|
620
|
+
last;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
push @enabled_vers, $v if $enabled;
|
|
625
|
+
}
|
|
626
|
+
$symbols{$sym} = VersionedSymbol->new(
|
|
627
|
+
name => $sym,
|
|
628
|
+
included => 1,
|
|
629
|
+
compat_only => $compat_only,
|
|
630
|
+
versions => \@enabled_vers,
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
my $symver_min_idx;
|
|
635
|
+
my $symver_floor_idx;
|
|
636
|
+
if (!%vorder) {
|
|
637
|
+
print {*STDERR} "$map_in: error: missing %chain directive\n";
|
|
638
|
+
$error = 1;
|
|
639
|
+
} else {
|
|
640
|
+
$symver_min_idx = $vorder{$SYMVER_MIN} // -2;
|
|
641
|
+
$symver_floor_idx = $vorder{$SYMVER_FLOOR} // -1;
|
|
642
|
+
if ($symver_min_idx < 0) {
|
|
643
|
+
print {*STDERR}
|
|
644
|
+
"$map_in: error: SYMVER_MIN ($SYMVER_MIN) ",
|
|
645
|
+
"not found in %chain directives\n";
|
|
646
|
+
$error = 1;
|
|
647
|
+
}
|
|
648
|
+
if ($symver_floor_idx < 0) {
|
|
649
|
+
print {*STDERR}
|
|
650
|
+
"$map_in: error: SYMVER_FLOOR ($SYMVER_FLOOR) ",
|
|
651
|
+
"not found in %chain directives\n";
|
|
652
|
+
$error = 1;
|
|
653
|
+
}
|
|
654
|
+
if ($symver_floor_idx < $symver_min_idx) {
|
|
655
|
+
print {*STDERR}
|
|
656
|
+
"$map_in: error: SYMVER_FLOOR ($SYMVER_FLOOR) ",
|
|
657
|
+
"is lower than SYMVER_MIN ($SYMVER_MIN)\n";
|
|
658
|
+
$error = 1;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
die "errors processing '$map_in'\n" if $error;
|
|
662
|
+
|
|
663
|
+
# For each symbol, remove all of its versions below SYMVER_MIN,
|
|
664
|
+
# and replace all of its versions below SYMVER_FLOOR with a single
|
|
665
|
+
# instance of SYMVER_FLOOR. If none are left, mark the symbol as
|
|
666
|
+
# not included. Otherwise, sort its 'versions' array in
|
|
667
|
+
# _descending_ order of symbol version. As we do this, keep track
|
|
668
|
+
# of all the symbol versions that are actually used.
|
|
669
|
+
my %used_versions;
|
|
670
|
+
for my $sym (values %symbols) {
|
|
671
|
+
my %pruned_versions;
|
|
672
|
+
for my $v (@{$sym->versions}) {
|
|
673
|
+
if (!exists $vorder{$v}) {
|
|
674
|
+
print {*STDERR}
|
|
675
|
+
"$map_in: error: version '$v' for symbol '",
|
|
676
|
+
$sym->name, "' not found in %chain\n";
|
|
677
|
+
$error = 1;
|
|
678
|
+
next;
|
|
679
|
+
}
|
|
680
|
+
if ($vorder{$v} < $symver_min_idx) {
|
|
681
|
+
next;
|
|
682
|
+
} elsif ($vorder{$v} < $symver_floor_idx) {
|
|
683
|
+
$pruned_versions{$SYMVER_FLOOR} = 1;
|
|
684
|
+
$used_versions{$SYMVER_FLOOR} = 1;
|
|
685
|
+
} else {
|
|
686
|
+
$pruned_versions{$v} = 1;
|
|
687
|
+
$used_versions{$v} = 1;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
if (%pruned_versions) {
|
|
691
|
+
@{$sym->versions} =
|
|
692
|
+
sort { -($vorder{$a} <=> $vorder{$b}) }
|
|
693
|
+
keys %pruned_versions;
|
|
694
|
+
} else {
|
|
695
|
+
$sym->included(0);
|
|
696
|
+
@{$sym->versions} = ();
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
# Sort the set of used symbol versions in _ascending_ order.
|
|
701
|
+
my @vchain = sort { $vorder{$a} <=> $vorder{$b} } keys %used_versions;
|
|
702
|
+
|
|
703
|
+
my (undef, undef, $basemap) = splitpath($map_in);
|
|
704
|
+
return SymbolVersionMap->new(
|
|
705
|
+
symbols => [sort { $a->name cmp $b->name } values %symbols],
|
|
706
|
+
versions => \@vchain,
|
|
707
|
+
basemap => $basemap,
|
|
708
|
+
max_symlen => $max_symlen,
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
1;
|