#931729 apt-mirror: [SSUse of uninitialized value $lines{"Files:"} in split at /usr/bin/apt-mirror line 829

#931729#5
Date:
2019-07-09 16:58:49 UTC
From:
To:
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.

#931729#10
Date:
2019-08-15 14:23:09 UTC
From:
To:

#931729#15
Date:
2019-09-03 18:10:08 UTC
From:
To:
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.

#931729#20
Date:
2019-09-05 05:48:55 UTC
From:
To:
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.

#931729#25
Date:
2019-10-11 21:52:18 UTC
From:
To:
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.

#931729#30
Date:
2020-09-30 06:18:07 UTC
From:
To:
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

#931729#35
Date:
2024-02-04 16:21:13 UTC
From:
To:
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

#931729#40
Date:
2025-08-31 21:01:41 UTC
From:
To:
**** 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>

#931729#45
Date:
2026-04-15 08:24:42 UTC
From:
To:
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