summaryrefslogtreecommitdiff
path: root/Build/source/texk
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2016-04-13 22:30:20 +0000
committerKarl Berry <karl@freefriends.org>2016-04-13 22:30:20 +0000
commitb9b0dce9293c9bd6d12ff53d088dfdb8fd33fef5 (patch)
treef968612769077b5f00a5d7bbc1bae35c7466d607 /Build/source/texk
parentb9b417030377e161a8e9a259bb04cd5bc27773dd (diff)
doc,regen,sync
git-svn-id: svn://tug.org/texlive/trunk@40492 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk')
-rw-r--r--Build/source/texk/tests/TeXLive/TLConfig.pm25
-rw-r--r--Build/source/texk/tests/TeXLive/TLUtils.pm240
-rwxr-xr-xBuild/source/texk/texlive/linked_scripts/texlive/fmtutil.pl20
-rwxr-xr-xBuild/source/texk/texlive/linked_scripts/texlive/tlmgr.pl180
4 files changed, 381 insertions, 84 deletions
diff --git a/Build/source/texk/tests/TeXLive/TLConfig.pm b/Build/source/texk/tests/TeXLive/TLConfig.pm
index 4d35866893d..972f708f893 100644
--- a/Build/source/texk/tests/TeXLive/TLConfig.pm
+++ b/Build/source/texk/tests/TeXLive/TLConfig.pm
@@ -5,7 +5,7 @@
package TeXLive::TLConfig;
-my $svnrev = '$Revision: 40251 $';
+my $svnrev = '$Revision: 40475 $';
my $_modulerevision;
if ($svnrev =~ m/: ([0-9]+) /) {
$_modulerevision = $1;
@@ -49,6 +49,9 @@ BEGIN {
$NetworkTimeout
$PartialEngineSupport
$F_OK $F_WARNING $F_ERROR $F_NOPOSTACTION
+ $ChecksumLength
+ $ChecksumProgram
+ $ChecksumExtension
);
@EXPORT = @EXPORT_OK;
}
@@ -57,9 +60,10 @@ BEGIN {
# network packages, and in menu names, and other places.
$ReleaseYear = 2016;
-# users can upgrade from this year to the current year; maybe a spread
-# of more than one year will be useful at some point, but not now.
-$MinRelease = 2013; # upgrade from 2013 to 2015 should work, we'll see
+# users can upgrade from this year to the current year; might be the
+# same as the release year, or any number of releases earlier.
+# Generally not tested.
+$MinRelease = 2013;
# users can NOT upgrade due to internal changes, force a full installation
#$MinRelease = $ReleaseYear;
@@ -193,7 +197,7 @@ our %TLPDBSettings = (
our $WindowsMainMenuName = "TeX Live $ReleaseYear";
# Comma-separated list of engines which do not exist on all platforms.
-our $PartialEngineSupport = "luajittex";
+our $PartialEngineSupport = "luajittex,mfluajit";
# timeout for network connections (wget, LWP) in seconds
our $NetworkTimeout = 30;
@@ -211,6 +215,17 @@ our $F_ERROR = 2;
# all fine, but no need to run post actions
our $F_NOPOSTACTION = 4;
+# The length of a checksum generated by tlchecksum and contained in
+# texlive.tlpdb.checksum. Needs to be in agreement with the hash
+# method used in TLUtils::tlchecksum and TLUtils::tldigest
+$ChecksumLength = 128;
+
+# The program generating the checksum for the file given as first
+# argument
+$ChecksumProgram = "sha512sum";
+
+# The extension of the checksum file
+$ChecksumExtension = "sha512";
1;
diff --git a/Build/source/texk/tests/TeXLive/TLUtils.pm b/Build/source/texk/tests/TeXLive/TLUtils.pm
index ac14adf3f3e..bc4ab402d9d 100644
--- a/Build/source/texk/tests/TeXLive/TLUtils.pm
+++ b/Build/source/texk/tests/TeXLive/TLUtils.pm
@@ -5,7 +5,7 @@
package TeXLive::TLUtils;
-my $svnrev = '$Revision: 40251 $';
+my $svnrev = '$Revision: 40460 $';
my $_modulerevision;
if ($svnrev =~ m/: ([0-9]+) /) {
$_modulerevision = $1;
@@ -98,6 +98,10 @@ C<TeXLive::TLUtils> -- utilities used in TeX Live infrastructure
TeXLive::TLUtils::give_ctan_mirror();
TeXLive::TLUtils::give_ctan_mirror_base();
TeXLive::TLUtils::tlmd5($path);
+ TeXLive::TLUtils::tlchecksum($path);
+ TeXLive::TLUtils::setup_gpg();
+ TeXLive::TLUtils::verify_checksum($file, $url);
+ TeXLive::TLUtils::verify_signature($file, $url);
TeXLive::TLUtils::compare_tlpobjs($tlpA, $tlpB);
TeXLive::TLUtils::compare_tlpdbs($tlpdbA, $tlpdbB);
TeXLive::TLUtils::report_tlpdb_differences(\%ret);
@@ -172,6 +176,10 @@ BEGIN {
&create_mirror_list
&extract_mirror_entry
&tlmd5
+ &tlchecksum
+ &setup_gpg
+ &verify_checksum
+ &verify_signature
&wsystem
&xsystem
&run_cmd
@@ -198,6 +206,7 @@ BEGIN {
use Cwd;
use Digest::MD5;
+use Digest::SHA;
use Getopt::Long;
use File::Temp;
@@ -1957,7 +1966,7 @@ not agree. Does nothing if neither of the check arguments is given.
sub check_file {
my ($xzfile, $checksum, $size) = @_;
if ($checksum) {
- if (tlmd5($xzfile) ne $checksum) {
+ if (tlchecksum($xzfile) ne $checksum) {
tlwarn("TLUtils::check_file: found $xzfile, but hashsums differ, removing it.\n");
unlink($xzfile);
return;
@@ -2239,7 +2248,7 @@ sub setup_programs {
# Return 0 if failure, 1 if success.
#
sub setup_unix_one {
- my ($p, $def, $arg) = @_;
+ my ($p, $def, $arg, $donotwarn) = @_;
our $tmp;
my $test_fallback = 0;
if (-r $def) {
@@ -2313,9 +2322,13 @@ sub setup_unix_one {
if ($ret == 0) {
debug("Using system $p (tested).\n");
} else {
- tlwarn("$0: Initialization failed (in setup_unix_one):\n");
- tlwarn("$0: could not find a usable $p.\n");
- tlwarn("$0: Please install $p and try again.\n");
+ if ($donotwarn) {
+ debug("$0: initialization of $p failed but ignored!\n");
+ } else {
+ tlwarn("$0: Initialization failed (in setup_unix_one):\n");
+ tlwarn("$0: could not find a usable $p.\n");
+ tlwarn("$0: Please install $p and try again.\n");
+ }
return 0;
}
} else {
@@ -3578,6 +3591,221 @@ sub tlmd5 {
}
}
+sub tldigest {
+ return (Digest::SHA::sha512_hex(shift));
+}
+sub tl_short_digest {
+ return (Digest::MD5::md5_hex(shift));
+}
+
+sub tlchecksum {
+ my ($file) = @_;
+ if (-r $file) {
+ open(FILE, $file) || die "open($file) failed: $!";
+ binmode(FILE);
+ my $cshash = Digest::SHA->new(512)->addfile(*FILE)->hexdigest;
+ close(FILE);
+ return $cshash;
+ } else {
+ tlwarn("tlchecksum: given file not readable: $file\n");
+ return "";
+ }
+}
+
+sub tlchecksum_data {
+ my ($data) = @_;
+ my $cshash = Digest::SHA->new(512)->add($data)->hexdigest;
+ return $cshash;
+}
+
+
+=pod
+
+=item C<< setup_gpg() >>
+
+Tries to set up gpg command line C<$::gpg> used for
+verification of downloads.
+
+Returns 1/0 on success/failure.
+
+=cut
+
+sub setup_gpg {
+ my $master = shift;
+ # first search for a gpg binary
+ return 0 if (!setup_unix_one( 'gpg' , '/no/such/path', '--version', 1));
+ # ok, we found one
+ # Set up the gpg invocation:
+ $::gpg = "$::progs{'gpg'} ";
+ my $gpghome = ($ENV{'TL_GNUPGHOME'} ? $ENV{'TL_GNUPGHOME'} :
+ "$master/tlpkg/gpg" );
+ $gpghome =~ s!/!\\!g if win32();
+ my $gpghome_quote = "\"$gpghome\"";
+ # mind the final space for following args
+ $::gpg .= "--homedir $gpghome_quote ";
+ if ($ENV{'TL_GNUPGARGS'}) {
+ $::gpg .= $ENV{'TL_GNUPGARGS'};
+ } else {
+ $::gpg .= "--no-secmem-warning --no-permission-warning ";
+ }
+ debug("gpg command line: $::gpg\n");
+ return 1;
+}
+
+=pod
+
+=item C<< slurp_file($file) >>
+
+Reads the whole file and returns the content in a scalar.
+
+=cut
+
+sub slurp_file {
+ my $file = shift;
+ my $file_data = do {
+ local $/ = undef;
+ open my $fh, "<", $file || die "open($file) failed: $!";
+ <$fh>;
+ };
+ return($file_data);
+}
+
+
+=pod
+
+=item C<< verify_checksum($file, $checksum_url) >>
+
+Verifies that C<$file> has checksum C<$checksum_url>.
+
+Returns 0 on success, -1 on connection error, 1 on checksum error.
+In case of errors returns an informal message as second argument.
+
+=cut
+
+sub verify_checksum {
+ my ($file, $checksum_url) = @_;
+ my $checksum_file = download_to_temp_or_file($checksum_url);
+ # next step is verification of tlpdb checksum with checksum file
+ # existenc of checksum_file was checked above
+ if (!$checksum_file) {
+ return(-1, "download did not succeed: $checksum_url");
+ }
+ # check the signature
+ my ($ret, $msg) = verify_signature($checksum_file, $checksum_url);
+ return ($ret, $msg) if ($ret != 0);
+
+ # verify local data
+ open $cs_fh, "<$checksum_file" or die("cannot read file: $!");
+ if (read ($cs_fh, $remote_digest, $ChecksumLength) != $ChecksumLength) {
+ close($cs_fh);
+ return(1, "incomplete read from $checksum_file");
+ } else {
+ close($cs_fh);
+ ddebug("found remote digest: $remote_digest\n");
+ }
+ $local_digest = tlchecksum($file);
+ ddebug("local_digest = $local_digest\n");
+ if ($local_digest ne $remote_digest) {
+ return(1, "digest disagree");
+ }
+
+ # we are still here, so checksum also succeeded
+ debug("checksum of local copy identical with remote hash\n");
+
+ return(0);
+}
+
+=pod
+
+=item C<< download_to_temp_or_file($url) >>
+
+If C<$url> tries to download the file into a temporary file.
+In both cases returns the local file.
+
+Returns the local file name if succeeded, otherwise undef.
+
+=cut
+
+sub download_to_temp_or_file {
+ my $url = shift;
+ my ($url_fh, $url_file);
+ if ($url =~ m,^(http|ftp|file)://,) {
+ ($url_fh, $url_file) = File::Temp::tempfile(UNLINK => 1);
+ # now $url_fh filehandle is open, the file created
+ # TLUtils::download_file will just overwrite what is there
+ # on windows that doesn't work, so we close the fh immediately
+ # this creates a short loophole, but much better than before anyway
+ close($url_fh);
+ $ret = download_file($url, $url_file);
+ } else {
+ $url_file = $url;
+ $ret = 1;
+ }
+ if ($ret && (-r "$url_file")) {
+ return $url_file;
+ }
+ return;
+}
+
+=pod
+
+=item C<< verify_signature($file, $url) >>
+
+Verifies a download of C<$url> into C<$file> by cheking the
+gpg signature in C<$url.asc>.
+
+Returns 0 on success, -1 on connection error, 1 on checksum error.
+In case of errors returns an informal message as second argument.
+
+=cut
+
+sub verify_signature {
+ my ($file, $url) = @_;
+ my $signature_url = "$url.asc";
+
+ # if we have $::gpg set, we try to verify cryptographic signatures
+ if ($::gpg) {
+ my $signature_file = download_to_temp_or_file($signature_url);
+ if ($signature_file) {
+ if (TeXLive::TLUtils::gpg_verify_signature($file, $signature_file)) {
+ info("cryptographic signature of $url verified\n");
+ } else {
+ return(1, <<GPGERROR);
+cryptograpic verification of
+ $file
+against
+ $signature_url
+failed. Please report to texlive\@tug.org
+GPGERROR
+ }
+ } else {
+ debug("no access to cryptographic signature $signature_url\n");
+ }
+ } else {
+ debug("gpg prog not defined, no checking of signatures\n");
+ }
+ return (0);
+}
+
+sub gpg_verify_signature {
+ my ($file, $sig) = @_;
+ my ($file_quote, $sig_quote);
+ if (win32()) {
+ $file =~ s!/!\\!g;
+ $sig =~ s!/!\\!g;
+ }
+ $file_quote = "\"$file\"";
+ $sig_quote = "\"$sig\"";
+ my ($out, $ret) = run_cmd("$::gpg --verify $sig_quote $file_quote 2>&1");
+ if ($ret == 0) {
+ debug("verification succeeded, output:\n$out\n");
+ return 1;
+ } else {
+ tlwarn("verification failed, output:\n$out\n");
+ return 0;
+ }
+}
+
#
# compare_tlpobjs
# returns a hash
diff --git a/Build/source/texk/texlive/linked_scripts/texlive/fmtutil.pl b/Build/source/texk/texlive/linked_scripts/texlive/fmtutil.pl
index 831b40b2e7e..05b9022488b 100755
--- a/Build/source/texk/texlive/linked_scripts/texlive/fmtutil.pl
+++ b/Build/source/texk/texlive/linked_scripts/texlive/fmtutil.pl
@@ -1,5 +1,5 @@
#!/usr/bin/env perl
-# $Id: fmtutil.pl 39813 2016-02-22 05:25:37Z preining $
+# $Id: fmtutil.pl 40475 2016-04-12 20:56:58Z karl $
# fmtutil - utility to maintain format files.
# (Maintained in TeX Live:Master/texmf-dist/scripts/texlive.)
#
@@ -24,11 +24,11 @@ BEGIN {
TeX::Update->import();
}
-my $svnid = '$Id: fmtutil.pl 39813 2016-02-22 05:25:37Z preining $';
-my $lastchdate = '$Date: 2016-02-22 06:25:37 +0100 (Mon, 22 Feb 2016) $';
+my $svnid = '$Id: fmtutil.pl 40475 2016-04-12 20:56:58Z karl $';
+my $lastchdate = '$Date: 2016-04-12 22:56:58 +0200 (Tue, 12 Apr 2016) $';
$lastchdate =~ s/^\$Date:\s*//;
$lastchdate =~ s/ \(.*$//;
-my $svnrev = '$Revision: 39813 $';
+my $svnrev = '$Revision: 40475 $';
$svnrev =~ s/^\$Revision:\s*//;
$svnrev =~ s/\s*\$$//;
my $version = "r$svnrev ($lastchdate)";
@@ -502,7 +502,7 @@ sub rebuild_one_format {
my $addargs = $alldata->{'merged'}{$fmt}{$eng}{'args'};
# running parameters
- my $texengine;
+ my $enginedir;
my $jobswitch = "-jobname=$fmt";
my $prgswitch = "-progname=" ;
my $recorderswitch = ($opts{'recorder'} ? "-recorder" : "");
@@ -533,15 +533,15 @@ sub rebuild_one_format {
if ($eng eq "mpost") {
$fmtfile .= ".mem" ;
$kpsefmt = "mp" ;
- $texengine = "metapost"; # the directory, not the executable
- } elsif ($eng =~ m/^mf(w|-nowin)?$/) {
+ $enginedir = "metapost"; # the directory, not the executable
+ } elsif ($eng =~ m/^mf(lua(jit)?)?(w|-nowin)?$/) {
$fmtfile .= ".base" ;
$kpsefmt = "mf" ;
- $texengine = "metafont";
+ $enginedir = "metafont";
} else {
$fmtfile .= ".fmt" ;
$kpsefmt = "tex" ;
- $texengine = $eng;
+ $enginedir = $eng;
}
# check for existence of ini file before doing anything else
@@ -663,7 +663,7 @@ sub rebuild_one_format {
if ($opts{'no-engine-subdir'}) {
$fulldestdir = $opts{'fmtdir'};
} else {
- $fulldestdir = "$opts{'fmtdir'}/$texengine";
+ $fulldestdir = "$opts{'fmtdir'}/$enginedir";
}
TeXLive::TLUtils::mkdirhier($fulldestdir);
diff --git a/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl b/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl
index 84adda21eca..4acb2998709 100755
--- a/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl
+++ b/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl
@@ -1,13 +1,13 @@
#!/usr/bin/env perl
-# $Id: tlmgr.pl 40376 2016-04-10 00:31:57Z preining $
+# $Id: tlmgr.pl 40467 2016-04-12 06:14:51Z preining $
#
# Copyright 2008-2016 Norbert Preining
# This file is licensed under the GNU General Public License version 2
# or any later version.
#
-my $svnrev = '$Revision: 40376 $';
-my $datrev = '$Date: 2016-04-10 02:31:57 +0200 (Sun, 10 Apr 2016) $';
+my $svnrev = '$Revision: 40467 $';
+my $datrev = '$Date: 2016-04-12 08:14:51 +0200 (Tue, 12 Apr 2016) $';
my $tlmgrrevision;
my $prg;
if ($svnrev =~ m/: ([0-9]+) /) {
@@ -74,9 +74,16 @@ BEGIN {
# if not in bootstrapping mode => kpsewhich exists, so use it to get $Master
chomp($Master = `kpsewhich -var-value=SELFAUTOPARENT`);
}
- $::installerdir = $Master;
- #
+ # if we have no directory in which to find our modules,
+ # no point in going on.
+ if (! $Master) {
+ die ("Could not determine directory of tlmgr executable, "
+ . "maybe shared library woes?\nCheck for error messages above");
+ }
+
+ $::installerdir = $Master; # for config.guess et al., see TLUtils.pm
+
# make Perl find our packages first:
unshift (@INC, "$Master/tlpkg");
unshift (@INC, "$Master/texmf-dist/scripts/texlive");
@@ -129,22 +136,6 @@ our $common_fmtutil_args =
$::gui_mode = 0;
$::machinereadable = 0;
-my %globaloptions = (
- "gui" => 1,
- "gui-lang" => "=s",
- "debug-translation" => 1,
- "location|repository|repo" => "=s",
- "machine-readable" => 1,
- "package-logfile" => "=s",
- "persistent-downloads" => "!",
- "no-execute-actions" => 1,
- "pin-file" => "=s",
- "pause" => 1,
- "print-platform|print-arch" => 1,
- "version" => 1,
- "help" => 1,
- "h|?" => 1);
-
my %action_specification = (
'_include_tlpobj' => {
"run-post" => 0,
@@ -347,6 +338,7 @@ sub main {
"print-platform|print-arch" => 1,
"usermode|user-mode" => 1,
"usertree|user-tree" => "=s",
+ "verify-downloads" => "!",
"version" => 1,
);
@@ -630,6 +622,21 @@ for the full story.\n";
}
}
+ #
+ # setup gpg if available
+ # first line: --(no-)verify-downloads was passed in (opts defined)
+ # second line: not passed in but in config
+ if ((defined($opts{"verify-downloads"}) && $opts{"verify-downloads"})
+ ||
+ (!defined($opts{"verify-downloads"}) && $config{"verify-downloads"})) {
+ if (TeXLive::TLUtils::setup_gpg($Master)) {
+ log("Trying to verify cryptographic signatures!\n")
+ } else {
+ tlwarn("Setting up gpg did not succeed!\n");
+ }
+ }
+
+
my $ret = execute_action($action, @ARGV);
# F_ERROR stops processing immediately, and prevents postactions from
@@ -2130,7 +2137,7 @@ sub write_w32_updater {
push (@rst_info, "$pkg ^($oldrev^)");
next if ($opts{"dry-run"});
# create backup; make_container expects file name in a format: some-name.r[0-9]+
- my ($size, $md5, $fullname) = $localtlp->make_container("tar", $root, $temp, "__BACKUP_$pkg.r$oldrev");
+ my ($size, $checksum, $fullname) = $localtlp->make_container("tar", $root, $temp, "__BACKUP_$pkg.r$oldrev");
if ($size <= 0) {
tlwarn("$prg: Creation of backup container of $pkg failed.\n");
return 1; # backup failed? abort
@@ -5499,11 +5506,16 @@ sub action_init_usertree {
#
sub action_conf {
my $arg = shift @ARGV;
+ my $ret = $F_OK;
+
if (!defined($arg)) {
texconfig_conf_mimic();
- return;
- }
- if ($arg eq "tlmgr" || $arg eq "texmf" || $arg eq "updmap") {
+
+ } elsif ($arg !~ /^(tlmgr|texmf|updmap)$/) {
+ warn "$prg: unknown conf arg: $arg (try tlmgr or texmf or updmap)\n";
+ $ret = $F_ERROR;
+
+ } else {
my ($fn,$cf);
if ($opts{'conffile'}) {
$fn = $opts{'conffile'} ;
@@ -5531,6 +5543,7 @@ sub action_conf {
}
} else {
info("$arg config file $fn not present\n");
+ $ret = $F_WARNING;
}
} else {
if (!defined($val)) {
@@ -5540,6 +5553,7 @@ sub action_conf {
$cf->delete_key($key);
} else {
info("$arg $key not defined, cannot remove ($fn)\n");
+ $ret = $F_WARNING;
}
} else {
if (defined($cf->value($key))) {
@@ -5561,6 +5575,7 @@ sub action_conf {
} else {
if (defined($opts{'delete'})) {
warning("$arg --delete and value for key $key given, don't know what to do!\n");
+ $ret = $F_ERROR;
} else {
info("setting $arg $key to $val (in $fn)\n");
$cf->value($key, $val);
@@ -5570,8 +5585,6 @@ sub action_conf {
if ($cf->is_changed) {
$cf->save;
}
- } else {
- warn "$prg: unknown conf arg: $arg (try tlmgr or texmf or updmap)\n";
}
}
@@ -5839,7 +5852,7 @@ sub setup_one_remotetlpdb {
my $local_copy_tlpdb_used = 0;
if ($location =~ m;^(http|ftp)://;) {
# first check that the saved tlpdb is present at all
- my $loc_digest = Digest::MD5::md5_hex($location);
+ my $loc_digest = TeXLive::TLUtils::tl_short_digest($location);
my $loc_copy_of_remote_tlpdb =
"$Master/$InfraLocation/texlive.tlpdb.$loc_digest";
ddebug("loc_digest = $loc_digest\n");
@@ -5848,11 +5861,11 @@ sub setup_one_remotetlpdb {
ddebug("loc copy found!\n");
# we found the tlpdb matching the current location
# check for the remote hash
- my $path = "$location/$InfraLocation/$DatabaseName.md5";
+ my $path = "$location/$InfraLocation/$DatabaseName.$TeXLive::TLConfig::ChecksumExtension";
ddebug("remote path of digest = $path\n");
- my $fh = TeXLive::TLUtils::download_file($path, "|");
- my $rem_digest;
- if (read ($fh, $rem_digest, 32) != 32) {
+
+ my ($ret, $msg) = TeXLive::TLUtils::verify_checksum($loc_copy_of_remote_tlpdb, $path);
+ if ($ret < 0) {
info(<<END_NO_INTERNET);
No connection to the internet.
Unable to download the checksum of the remote TeX Live database,
@@ -5865,25 +5878,20 @@ http://tug.org/texlive/doc/install-tl.html
END_NO_INTERNET
# above text duplicated in install-tl
-
$remotetlpdb = TeXLive::TLPDB->new(root => $location,
tlpdbfile => $loc_copy_of_remote_tlpdb);
$local_copy_tlpdb_used = 1;
+ } elsif ($ret > 0) {
+ # no problem, checksum is wrong, we need to get new tlpdb
} else {
- ddebug("found remote digest: $rem_digest\n");
- my $rem_copy_digest = TeXLive::TLUtils::tlmd5($loc_copy_of_remote_tlpdb);
- ddebug("rem_copy_digest = $rem_copy_digest\n");
- if ($rem_copy_digest eq $rem_digest) {
- debug("md5 of local copy identical with remote hash\n");
- $remotetlpdb = TeXLive::TLPDB->new(root => $location,
- tlpdbfile => $loc_copy_of_remote_tlpdb);
- $local_copy_tlpdb_used = 1;
- }
+ $remotetlpdb = TeXLive::TLPDB->new(root => $location,
+ tlpdbfile => $loc_copy_of_remote_tlpdb);
+ $local_copy_tlpdb_used = 1;
}
}
}
if (!$local_copy_tlpdb_used) {
- $remotetlpdb = TeXLive::TLPDB->new(root => $location);
+ $remotetlpdb = TeXLive::TLPDB->new(root => $location, verify => 1);
}
if (!defined($remotetlpdb)) {
return(undef, $loadmediasrcerror . $location);
@@ -5959,9 +5967,9 @@ FROZEN
# save remote database if it is a net location
# make sure that the writeout of the tlpdb is done in UNIX mode
- # since otherwise the sha256 will change.
+ # since otherwise the checksum will change.
if (!$local_copy_tlpdb_used && $location =~ m;^(http|ftp)://;) {
- my $loc_digest = Digest::MD5::md5_hex($location);
+ my $loc_digest = TeXLive::TLUtils::tl_short_digest($location);
my $loc_copy_of_remote_tlpdb =
"$Master/$InfraLocation/texlive.tlpdb.$loc_digest";
my $tlfh;
@@ -6016,6 +6024,8 @@ sub load_config_file {
#
# by default we remove packages
$config{"auto-remove"} = 1;
+ #
+ $config{"verify-downloads"} = 1;
# loads system config file, this cannot be changes with tlmgr
chomp (my $TEXMFSYSCONFIG = `kpsewhich -var-value=TEXMFSYSCONFIG`);
@@ -6068,6 +6078,15 @@ sub load_options_from_config {
tlwarn("$prg: $fn: Unknown value for auto-remove: $val\n");
}
+ } elsif ($key eq "verify-downloads") {
+ if ($val eq "0") {
+ $config{"verify-downloads"} = 0;
+ } elsif ($val eq "1") {
+ $config{"verify-downloads"} = 1;
+ } else {
+ tlwarn("$prg: $fn: Unknown value for verify-downloads: $val\n");
+ }
+
} elsif ($sysmode) {
# keys here are only allowed in sys mode
if ($key eq "allowed-actions") {
@@ -6430,6 +6449,15 @@ Activates user mode for this run of C<tlmgr>; see L<USER MODE> below.
Uses I<dir> for the tree in user mode; see L<USER MODE> below.
+=item B<--verify-downloads>
+
+=item B<--no-verify-downloads>
+
+Enables or disables cryptographic verification of downloaded database files.
+A working GnuPG (C<gpg>) binary needs to be present in the path, otherwise
+this option has no effect. See L<CRYPTOGRAPHIC VERIFICATION> below for details.
+
+
=back
The standard options for TeX Live programs are also accepted:
@@ -6545,7 +6573,8 @@ Live Database are present.
=item B<runfiles>
-List those filenames that are occurring more than one time in the runfiles.
+List those filenames that are occurring more than one time in the
+runfiles sections.
=back
@@ -6569,12 +6598,13 @@ like the C<texconfig conf> call, but works on all supported platforms.
With either C<conf texmf>, C<conf tlmgr>, or C<conf updmap> given in
addition, shows all key/value pairs (i.e., all settings) as saved in
-C<ROOT/texmf.cnf>, the tlmgr configuration file (see below), or the
+C<ROOT/texmf.cnf>, the C<tlmgr> configuration file (see below), or the
first found (via kpsewhich) C<updmap.cfg> file, respectively.
If I<key> is given in addition, shows the value of only that I<key> in
-the respective file. If option I<--delete> is also given, the
-configuration file -- it is removed, not just commented out!
+the respective file. If option I<--delete> is also given, the value in
+the given configuration file is entirely removed (not just commented
+out).
If I<value> is given in addition, I<key> is set to I<value> in the
respective file. I<No error checking is done!>
@@ -6582,9 +6612,13 @@ respective file. I<No error checking is done!>
In all cases the file used can be explicitly specified via the option
C<--conffile I<file>>, in case one wants to operate on a different file.
-Practical application: if the execution of (some or all) system commands
-via C<\write18> was left enabled during installation, you can disable
-it afterwards:
+The PATH value shown is that used by C<tlmgr>. The directory in which
+the C<tlmgr> executable is found is automatically prepended to the PATH
+value inherited from the environment.
+
+Practical application of changing configuration values: if the execution
+of (some or all) system commands via C<\write18> was left enabled during
+installation, you can disable it afterwards:
tlmgr conf texmf shell_escape 0
@@ -6726,7 +6760,7 @@ location in C<TEXMFLOCAL>).
=item B<--rebuild-sys>
-tells tlmgr to run necessary programs after config files have been
+tells C<tlmgr> to run necessary programs after config files have been
regenerated. These are:
C<fmtutil-sys --all> after C<generate fmtutil>,
C<fmtutil-sys --byhyphen .../language.dat> after C<generate language.dat>,
@@ -6790,10 +6824,8 @@ dependencies in a similar way.
=item B<--only-installed>
-If this options is given, the installation source will
-not be used; only locally installed packages, collections, or schemes
-are listed.
-(Does not work for listing of packages for now)
+If this option is given, the installation source will not be used; only
+locally installed packages, collections, or schemes are listed.
=back
@@ -6931,7 +6963,9 @@ is not likely to be of interest except perhaps to developers.
The C<docfiles> and C<srcfiles> options control the installation of
their respective files of a package. By default both are enabled (1).
-This can be disabled (set to 0) if disk space is (very) limited.
+Either or both can be disabled (set to 0) if disk space is limited or
+for minimal testing installations, etc. When disabled, the respective
+files are not downloaded at all.
The options C<autobackup> and C<backupdir> determine the defaults for
the actions C<update>, C<backup> and C<restore>. These three actions
@@ -7212,7 +7246,7 @@ Otherwise, if neither I<pkg> nor I<rev> are given, list the available
backup revisions for all packages. With I<pkg> given but no I<rev>,
list all available backup revisions of I<pkg>.
-When listing available packages tlmgr shows the revision, and in
+When listing available packages, C<tlmgr> shows the revision, and in
parenthesis the creation time if available (in format yyyy-mm-dd hh:mm).
If (and only if) both I<pkg> and a valid revision number I<rev> are
@@ -7484,6 +7518,25 @@ fallback information, but if you don't like them accumulating (e.g.,
on each run C<mirror.ctan.org> might resolve to a new host, resulting in
a different hash), it's harmless to delete them.
+=head1 CRYPTOGRAPHIC VERIFICATION
+
+If a working GnuPG binary (C<gpg>) is found, by default verification of
+downloaded files is performed. This can be supressed by specifying
+C<--no-verify-downloads> on the command line, or adding an entry
+C<verify-downloads = 0> to a tlmgr config file.
+
+Verification is performed as follows: For each C<texlive.tlpdb> loaded
+for a repository, the respective checksum C<texlive.tlpdb.sha512> is
+always downloaded, too, and C<tlmgr> confirms whether the checksum
+of the download tlpdb file agrees with the download data. This is done
+in any case.
+
+If cryptographic verification is done, then a signature of the checksum
+file is downloaded and the signature verified. The signature is done with
+the TeX Live Distribution GPG key 0x06BAB6BC, which in turn is signed
+by Karl Berry's key 0x9DEB46C0 and Norbert Preining's key 0x6CACA448.
+All of these keys are obtainable from the standard key servers.
+
=head1 USER MODE
C<tlmgr> provides a restricted way, called ``user mode'', to manage
@@ -7585,12 +7638,13 @@ ignored. All other lines must look like
where the allowed keys are C<gui-expertmode> (value 0 or 1),
C<persistent-downloads> (value 0 or 1), C<auto-remove> (value 0 or 1),
+C<verify-downloads> (value 0 or 1),
and C<gui-lang> (value as with the command-line option).
-C<persistent-downloads>, C<gui-lang>, and C<auto-remove> correspond to
-the respective command line options of the same name. C<gui-expertmode>
-switches between the full GUI and a simplified GUI with only the
-important and mostly used settings.
+C<persistent-downloads>, C<gui-lang>, C<auto-remove>, and C<verify-downloads>
+correspond to the respective command line options of the same name.
+C<gui-expertmode> switches between the full GUI and a simplified GUI
+with only the important and mostly used settings.
In addition, the system-wide config file can contain the key
C<allowed-actions>. The value is a comma-separated list of actions that