#931729 apt-mirror: [SSUse of uninitialized value $lines{"Files:"} in split at /usr/bin/apt-mirror line 829 #931729
- Package:
- apt-mirror
- Source:
- apt-mirror
- Submitter:
- Tobias Köck
- Date:
- 2026-04-15 08:27:02 UTC
- Severity:
- normal
Dear Maintainer,
Begin time: Tue Jul 9 17:56:00 2019
[1]... [0]...
End time: Tue Jul 9 17:56:00 2019
Processing indexes: [SSUse of uninitialized value $lines{"Files:"} in
split at /usr/bin/apt-mirror line 829, <STREAM> line 1.
Use of uninitialized value $lines{"Files:"} in split at
/usr/bin/apt-mirror line 829, <STREAM> line 2.
Use of uninitialized value $lines{"Files:"} in split at
/usr/bin/apt-mirror line 829, <STREAM> line 3.
Use of uninitialized value $lines{"Files:"} in split at
/usr/bin/apt-mirror line 829, <STREAM> line 4.
SSSSSSSPPPPPPPPPPPPPPPPPP]
0 bytes will be downloaded into archive.
To solve a problem I wrote about earlier,
in the text of the program "apt-mirror 0.5.4-1" commented line
775 sub process_index
776 {
...
814 if ( exists $lines{"Filename:"} )
{ # Packages index
$skipclean{ remove_double_slashes( $path . "/" . $lines{"Filename:"} ) } = 1;
print FILES_ALL remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n";
print FILES_MD5 $lines{"MD5sum:"} . " " . remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n" if defined $lines{"MD5sum:"};
print FILES_SHA1 $lines{"SHA1:"} . " " . remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n" if defined $lines{"SHA1:"};
print FILES_SHA256 $lines{"SHA256:"} . " " . remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n" if defined $lines{"SHA256:"};
if ( need_update( $mirror . "/" . $lines{"Filename:"}, $lines{"Size:"} ) )
{
print FILES_NEW remove_double_slashes( $uri . "/" . $lines{"Filename:"} ) . "\n";
add_url_to_download( $uri . "/" . $lines{"Filename:"}, $lines{"Size:"} );
}
}
827 #else # my comment
elsif ( exists $lines{"Files:"} ) # my insert
{ # Sources index
foreach ( split( /\n/, $lines{"Files:"} ) )
{
After this change everything works fine and the message
Processing indexes: [SSSSSUse of uninitialized value $lines{"Files:"} in split at /usr/bin/apt-mirror line 829, <STREAM> line 1.
Use of uninitialized value $lines{"Files:"} in split at /usr/bin/apt-mirror line 829, <STREAM> line 2.
PPPPP]
no longer appears.
To solve a problem I wrote about earlier,
in the text of the program "apt-mirror 0.5.4-1" commented or added new lines.
I marked my changes with comments:
# *** my comment
# *** my insert
#-------------------------------------------------------------------------------
sub need_update
{
my $filename = shift;
my $size_on_server = shift;
my ( undef, undef, undef, undef, undef, undef, undef, $size ) = _stat($filename);
return 1 unless ($size);
return 0 if $size_on_server == $size;
unlink( $filename ) || die("apt-mirror: unlink error: $! for file: $filename"); # *** my insert
return 1;
}
#-------------------------------------------------------------------------------
sub process_index
{
...
if ( exists $lines{"Filename:"} )
{ # Packages index
$skipclean{ remove_double_slashes( $path . "/" . $lines{"Filename:"} ) } = 1;
print FILES_ALL remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n";
print FILES_MD5 $lines{"MD5sum:"} . " " . remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n" if defined $lines{"MD5sum:"};
print FILES_SHA1 $lines{"SHA1:"} . " " . remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n" if defined $lines{"SHA1:"};
print FILES_SHA256 $lines{"SHA256:"} . " " . remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n" if defined $lines{"SHA256:"};
if ( need_update( $mirror . "/" . $lines{"Filename:"}, $lines{"Size:"} ) )
{
print FILES_NEW remove_double_slashes( $uri . "/" . $lines{"Filename:"} ) . "\n";
add_url_to_download( $uri . "/" . $lines{"Filename:"}, $lines{"Size:"} );
}
}
#else # *** my comment
elsif ( exists $lines{"Files:"} ) # *** my insert
{ # Sources index
foreach ( split( /\n/, $lines{"Files:"} ) )
{
...
}
######################################################################################
## Main download
chdir get_variable("mirror_path") or die("apt-mirror: can't chdir to mirror");
my $need_bytes = 0;
foreach ( values %urls_to_download )
{
$need_bytes += $_;
}
if ($need_bytes > 0) { # *** my insert
my $size_output = format_bytes($need_bytes);
print "$size_output will be downloaded into archive.\n";
download_urls( "archive", sort keys %urls_to_download );
} # *** my insert
######################################################################################
String with "unlink" in "sub need_update" is very important, since "wget" does
not a re-change a package if it is not fully downloaded on previous runs
of "apt-mirror". For example, if in the previous run "apt-mirror" pressed "Ctrl+C".
After this change everything works fine and the message:
Processing indexes: [SSSSSUse of uninitialized value $lines{"Files:"} in split at /usr/bin/apt-mirror line 829, <STREAM> line 1.
Use of uninitialized value $lines{"Files:"} in split at /usr/bin/apt-mirror line 829, <STREAM> line 2.
PPPPP]
no longer appears. And messages for re-download the not completely
downloaded packages also do not occur.
I offer version 2 of the correction:
To solve a problem I wrote about earlier,
in the text of the program "apt-mirror 0.5.4-1" commented or added new lines.
I marked my changes with comments:
# *** my comment
# *** my insert
#-------------------------------------------------------------------------------
# I agree with Justin Pasher (932379@bugs.debian.org) and with Stephan Seitz (932112@bugs.debian.org),
# if you look a little lower in the text of the program "apt-mirror",
# you can see a similar code, but for all 3 archive formats:
#
# sub find_dep11_files_in_release
# ...
# if ( $filename =~ m{^$component/dep11/(Components-${arch}\.ml|icons-[^./]+\.tar)\.(gz|bz2|xz)$} )
#
#So maybe better:
sub find_translation_files_in_release
{
...
# if ( $filename =~ m{^$component/i18n/Translation-[^./]*\.bz2$} ) # my comment
if ( $filename =~ m{^$component/i18n/Translation-[^./]*\.(gz|bz2|xz)$} ) # my insert
# In order not to think about it anymore, especially since all the rest of the text supports all 3 formats.
#-------------------------------------------------------------------------------
sub need_update
{
my $filename = shift;
my $size_on_server = shift;
my ( undef, undef, undef, undef, undef, undef, undef, $size ) = _stat($filename);
// $size may have a value "undef", if the file on client side is apsent.
# return 1 unless ($size); # *** my comment 2
return 1 unless (defined $size); # *** my insert 2
return 1 if ($size <= 0); # *** my insert 2
return 0 if $size_on_server == $size;
unlink( $filename ) || die("apt-mirror: unlink error: $! for file: $filename"); # *** my insert
return 1;
}
#-------------------------------------------------------------------------------
sub process_index
{
...
if ( exists $lines{"Filename:"} )
{ # Packages index
$skipclean{ remove_double_slashes( $path . "/" . $lines{"Filename:"} ) } = 1;
print FILES_ALL remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n";
print FILES_MD5 $lines{"MD5sum:"} . " " . remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n" if defined lines{"MD5sum:"};
print FILES_SHA1 $lines{"SHA1:"} . " " . remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n" if defined $lines{"SHA1:"};
print FILES_SHA256 $lines{"SHA256:"} . " " . remove_double_slashes( $path . "/" . $lines{"Filename:"} ) . "\n" if defined $lines{"SHA256:"};
if ( need_update( $mirror . "/" . $lines{"Filename:"}, $lines{"Size:"} ) )
{
print FILES_NEW remove_double_slashes( $uri . "/" . $lines{"Filename:"} ) . "\n";
add_url_to_download( $uri . "/" . $lines{"Filename:"}, $lines{"Size:"} );
}
}
#else # *** my comment
elsif ( exists $lines{"Files:"} ) # *** my insert
{ # Sources index
foreach ( split( /\n/, $lines{"Files:"} ) )
{
...
}
######################################################################################
## Main download
chdir get_variable("mirror_path") or die("apt-mirror: can't chdir to mirror");
my $need_bytes = 0;
foreach ( values %urls_to_download )
{
$need_bytes += $_;
}
if ($need_bytes > 0) { # *** my insert
my $size_output = format_bytes($need_bytes);
print "$size_output will be downloaded into archive.\n";
download_urls( "archive", sort keys %urls_to_download );
} # *** my insert
######################################################################################
String with "unlink" in "sub need_update" is very important, since "wget" does
not a re-change a package if it is not fully downloaded on previous runs
of "apt-mirror". For example, if in the previous run "apt-mirror" pressed "Ctrl+C".
After this change everything works fine and the message:
Processing indexes: [SSSSSUse of uninitialized value $lines{"Files:"} in split at /usr/bin/apt-mirror line 829, <STREAM> line 1.
Use of uninitialized value $lines{"Files:"} in split at /usr/bin/apt-mirror line 829, <STREAM> line 2.
PPPPP]
больше не возникает. Да и сообщения из-за повторного скачивания неполностью
скаченных пакетов тоже не возникают.
no longer appears. And messages for re-download the not completely
downloaded packages also do not occur.
The real problem here is that process_index() assumes that "Files:" is still used. According to Debian Policy 4.5.0.3 <https://www.debian.org/doc/debian-policy/ch-controlfields.html#debian-source-control-files-dsc> and <https://manpages.debian.org/testing/dpkg-dev/dsc.5.en.html> "Files:" is still "mandatory, but reality looks different: As this example lacks the "Files:" entry, it is not mirrored by "apt-mirror". The real fix is to try "Checksums-Sha256", "Checksum-Sha1" and "Files:" in that order and use the first existing one. Philipp
Hello! FYI this (and some other) bug is fixed in the apt-mirror2 [1] - Python/asyncio reimplementation of the apt-mirror [1] https://gitlab.com/apt-mirror2/apt-mirror2
**** MSG FOR THE MAINTAINER ****
Hi Maintainer:
I ran into the same error "Use of uninitialized value $lines{"Files:"}". The
problem is in the subroutine "process_index". This subroutine parses two
different text files: "Packages" (found in the binary packages), and "Sources"
(found in the source code packages). Although the parsing logic for the Packages
file has been updated so that the md5sum is an optional field, the parsing logic
for the Sources file (found in the source code packages) has NOT been updated.
So it assumes that every package must contain the "Files:" section containing
md5sums.
This means that the error occurs only if you're mirroring the source code (using
deb-src).
I reproduced this problem with a Devuan repository and a Debian repository:
- Devuan test, mirror.list
deb-src http://deb.devuan.org/merged daedalus-security main
This downloads the file from:
http://deb.devuan.org/merged/dists/daedalus-security/main/source/Sources.gz
- Debian test, mirror.list
deb-src http://deb.devuan.org/merged daedalus-security main
This downloads the file from:
http://deb.debian.org/debian/dists/bookworm-updates/main/source/Sources.xz
If you look open the Sources file in each test, you'll see that neither of their
package descriptions contain "Files:" (md5sums), nor "Checksums-Sha1", only
"Checksums-Sha256".
* A Solution
My solution is to rewrite the entire else block to handle any combination of the
presence/absence of the 3 section names: "Files:", "Checksums-Sha1:",
"Checksums-Sha256:":
else
{ # Sources index
#The sections "Files:", "Checksums-Sha1:", and "Checksums-Sha256" contain
1 or more lines with 3
#space-separated fields: md5/sha1/sha256 checksum, file size in bytes,
file name
#There's no guarantee that all 3 sections will be defined, or that they
will have the same list of files.
#Use a hash to keep track of the file names and their sizes. Then update
the ALL and NEW files afterwards.
my %package_files;
my %sections = (
"Files:" => *FILES_MD5 ,
"Checksums-Sha1:" => *FILES_SHA1 ,
"Checksums-Sha256:" => *FILES_SHA256,
);
foreach my $section_name (keys %sections)
{
if (!defined($lines{$section_name})) { next; }
foreach ( split( /\n/, $lines{$section_name} ) )
{
next if $_ eq '';
my @file = split;
die("apt-mirror: invalid Sources format") if @file != 3;
print { $sections{$section_name} } $file[0] . " " .
remove_double_slashes( $path . "/" . $lines{"Directory:"} . "/" . $file[2] ) . "\n";
$package_files{$file[2]} = $file[1];
}
}
my $file_size_bytes;
my $file_path;
foreach my $file_name (keys %package_files)
{
$file_size_bytes = $package_files{$file_name};
$file_path = remove_double_slashes( $path . "/" .
$lines{"Directory:"} . "/" . $file_name );
$skipclean{ $file_path } = 1;
print FILES_ALL $file_path . "\n";
if ( need_update( $mirror . "/" . $lines{"Directory:"} . "/" .
$file_name, $file_size_bytes ) )
{
print FILES_NEW remove_double_slashes( $uri . "/" .
$lines{"Directory:"} . "/" . $file_name ) . "\n";
add_url_to_download( $uri . "/" . $lines{"Directory:"} . "/" .
$file_name, $file_size_bytes );
}
}
}
I tested this solution with the 2 deb-src URLs mentioned above, and this code
runs without errors and correctly appends the SHA256 sums to the file "SHA256",
since that's the section defined in those two repositories.
**** MSG FOR READERS AT bugs.debian.org ****
If you're reading this on bugs.debian.org, and you want to try my fix, you can
make a copy of the script and try the changes. That way, if anything goes wrong,
the original apt-mirror script is still available.
- Copy the apt-mirror script into another directory, such as /opt, which is
usually empty.
- In a text editor, search for the string "sub process_index". This the
beginning of the "process_index" subroutine.
- Within this subroutine, look for the "else" block of code with the comment
"# Sources index". This block of code parses the "Sources" file.
- Replace the entire "else" block with the code mentioned above.
- To run the updated apt-mirror:
/opt/apt-mirror <your apt-mirror config file>
- To run the originally installed apt-mirror script:
apt-mirror <your apt-mirror config file>
Since apt-mirror2 hasn't been backported to Bookworm/Bullseye yet, and there has been no release > 0.5.4 if apt-mirror upstream (resulting in this package not having been updated for three and a half years), I went and converted the previous contribution into a proper diff. For me, applied to /usr/bin/apt-mirror, it works. (this would mean that the patch has to be applied last, after the two ones already present). Best, S