1 # Copyright © 2008-2011 Raphaël Hertzog <hertzog@debian.org>
2 # Copyright © 2008-2019 Guillem Jover <guillem@debian.org>
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <https://www.gnu.org/licenses/>.
21 Dpkg::Source::Package - manipulate Debian source packages
25 This module provides a class that can manipulate Debian source
26 packages. While it supports both the extraction and the creation
27 of source packages, the only API that is officially supported
28 is the one that supports the extraction of the source package.
32 package Dpkg
::Source
::Package
2.02;
38 get_default_diff_ignore_regex
39 set_default_diff_ignore_regex
40 get_default_tar_ignore_pattern
43 use Exporter
qw(import);
44 use POSIX
qw(:errno_h :sys_wait_h);
47 use File
::Copy
qw(cp);
52 use Dpkg
::ErrorHandling
;
56 use Dpkg
::Compression
;
57 use Dpkg
::Path
qw(check_files_are_the_same check_directory_traversal);
58 use Dpkg
::Vendor
qw(run_vendor_hook);
59 use Dpkg
::Source
::Format
;
61 use Dpkg
::OpenPGP
::ErrorCodes
;
63 my $diff_ignore_default_regex = '
64 # Ignore general backup files
66 # Ignore emacs recovery files
68 # Ignore vi swap files
70 # Ignore baz-style junk files or directories
71 (?:^|/),,.*(?:$|/.*$)|
72 # File-names that should be ignored (never directories)
73 (?:^|/)(?:DEADJOE|\.arch-inventory|\.(?:bzr|cvs|hg|git|mtn-)ignore)$|
74 # File or directory names that should be ignored
75 (?:^|/)(?:CVS|RCS|\.deps|\{arch\}|\.arch-ids|\.svn|
76 \.hg(?:tags|sigs)?|_darcs|\.git(?:attributes|modules|review)?|
77 \.mailmap|\.shelf|_MTN|\.be|\.bzr(?:\.backup|tags)?)(?:$|/.*$)
79 # Take out comments and newlines
80 $diff_ignore_default_regex =~ s/^#.*$//mg;
81 $diff_ignore_default_regex =~ s/\n//sg;
83 no warnings
'qw'; ## no critic (TestingAndDebugging::ProhibitNoWarnings)
84 my @tar_ignore_default_pattern = qw(
128 =item $string = get_default_diff_ignore_regex()
130 Returns the default diff ignore regex.
134 sub get_default_diff_ignore_regex
{
135 return $diff_ignore_default_regex;
138 =item set_default_diff_ignore_regex($string)
140 Set a regex as the new default diff ignore regex.
144 sub set_default_diff_ignore_regex
{
147 $diff_ignore_default_regex = $regex;
150 =item @array = get_default_tar_ignore_pattern()
152 Returns the default tar ignore pattern, as an array.
156 sub get_default_tar_ignore_pattern
{
157 return @tar_ignore_default_pattern;
166 =item $p = Dpkg::Source::Package->new(%opts, options => {})
168 Creates a new object corresponding to a source package. When the key
169 B<filename> is set to a F<.dsc> file, it will be used to initialize the
170 source package with its description. Otherwise if the B<format> key is
171 set to a valid value, the object will be initialized for that format
174 The B<options> key is a hash ref which supports the following options:
178 =item skip_debianization
180 If set to 1, do not apply Debian changes on the extracted source package.
184 If set to 1, do not apply Debian-specific patches. This options is
185 specific for source packages using format "2.0" and "3.0 (quilt)".
187 =item require_valid_signature
189 If set to 1, the check_signature() method will be stricter and will error
190 out if the signature can't be verified.
192 =item require_strong_checksums
194 If set to 1, the check_checksums() method will be stricter and will error
195 out if there is no strong checksum.
197 =item copy_orig_tarballs
199 If set to 1, the extraction will copy the upstream tarballs next the
200 target directory. This is useful if you want to be able to rebuild the
201 source package after its extraction.
209 my ($this, %args) = @_;
210 my $class = ref($this) || $this;
212 fields
=> Dpkg
::Control
->new(type
=> CTRL_DSC
),
213 format
=> Dpkg
::Source
::Format
->new(),
215 checksums
=> Dpkg
::Checksums
->new(),
216 openpgp
=> Dpkg
::OpenPGP
->new(needs
=> { api
=> 'verify' }),
219 if (exists $args{options
}) {
220 $self->{options
} = $args{options
};
222 if (exists $args{filename
}) {
223 $self->initialize($args{filename
});
224 $self->init_options();
225 } elsif ($args{format
}) {
226 $self->{fields
}{Format
} = $args{format
};
227 $self->upgrade_object_type(0);
228 $self->init_options();
231 if ($self->{options
}{require_valid_signature
}) {
232 $self->{report_verify
} = \
&error
;
234 $self->{report_verify
} = \
&warning
;
242 # Use full ignore list by default
243 # note: this function is not called by V1 packages
244 $self->{options
}{diff_ignore_regex
} ||= $diff_ignore_default_regex;
245 $self->{options
}{diff_ignore_regex
} .= '|(?:^|/)debian/source/local-.*$';
246 $self->{options
}{diff_ignore_regex
} .= '|(?:^|/)debian/files(?:\.new)?$';
247 if (defined $self->{options
}{tar_ignore
}) {
248 $self->{options
}{tar_ignore
} = [ @tar_ignore_default_pattern ]
249 unless @
{$self->{options
}{tar_ignore
}};
251 $self->{options
}{tar_ignore
} = [ @tar_ignore_default_pattern ];
253 push @
{$self->{options
}{tar_ignore
}},
254 'debian/source/local-options',
255 'debian/source/local-patch-header',
258 $self->{options
}{copy_orig_tarballs
} //= 0;
260 # Skip debianization while specific to some formats has an impact
261 # on code common to all formats
262 $self->{options
}{skip_debianization
} //= 0;
263 $self->{options
}{skip_patches
} //= 0;
265 # Set default validation checks.
266 $self->{options
}{require_valid_signature
} //= 0;
267 $self->{options
}{require_strong_checksums
} //= 0;
269 # Set default compressor for new formats.
270 $self->{options
}{compression
} //= 'xz';
271 $self->{options
}{comp_level
} //= compression_get_level
($self->{options
}{compression
});
272 $self->{options
}{comp_ext
} //= compression_get_file_extension
($self->{options
}{compression
});
276 my ($self, $filename) = @_;
277 my ($fn, $dir) = fileparse
($filename);
278 error
(g_
('%s is not the name of a file'), $filename) unless $fn;
279 $self->{basedir
} = $dir || './';
280 $self->{filename
} = $fn;
283 my $fields = $self->{fields
};
284 $fields->load($filename);
285 $self->{is_signed
} = $fields->get_option('is_pgp_signed');
287 foreach my $f (qw(Source Version Files)) {
288 unless (defined($fields->{$f})) {
289 error
(g_
('missing critical source control field %s'), $f);
293 $self->{checksums
}->add_from_control($fields, use_files_for_md5
=> 1);
295 $self->upgrade_object_type(0);
298 sub upgrade_object_type
{
299 my ($self, $update_format) = @_;
300 $update_format //= 1;
302 my $format = $self->{fields
}{'Format'} // '1.0';
303 my ($major, $minor, $variant) = $self->{format
}->set($format);
305 my $module = "Dpkg::Source::Package::V$major";
306 $module .= '::' . ucfirst $variant if defined $variant;
309 \
$minor = \
$${module
}::CURRENT_MINOR_VERSION
;
312 error
(g_
("source package format '%s' is not supported: %s"),
315 if ($update_format) {
316 $self->{format
}->set_from_parts($major, $minor, $variant);
317 $self->{fields
}{'Format'} = $self->{format
}->get();
320 $module->prerequisites() if $module->can('prerequisites');
321 bless $self, $module;
324 =item $p->get_filename()
326 Returns the filename of the DSC file.
332 return File
::Spec
->catfile($self->{basedir
}, $self->{filename
});
335 =item $p->get_files()
337 Returns the list of files referenced by the source package. The filenames
338 usually do not have any path information.
344 return $self->{checksums
}->get_files();
347 =item $p->check_checksums()
349 Verify the checksums embedded in the DSC file. It requires the presence of
350 the other files constituting the source package. If any inconsistency is
351 discovered, it immediately errors out. It will make sure at least one strong
354 If the object has been created with the "require_strong_checksums" option,
355 then any problem will result in a fatal error.
359 sub check_checksums
{
361 my $checksums = $self->{checksums
};
362 my $warn_on_weak = 0;
364 # add_from_file verify the checksums if they are already existing
365 foreach my $file ($checksums->get_files()) {
366 if (not $checksums->has_strong_checksums($file)) {
367 if ($self->{options
}{require_strong_checksums
}) {
368 error
(g_
('source package uses only weak checksums'));
373 my $pathname = File
::Spec
->catfile($self->{basedir
}, $file);
374 $checksums->add_from_file($pathname, key
=> $file);
377 warning
(g_
('source package uses only weak checksums')) if $warn_on_weak;
381 my ($self, $with_revision) = @_;
382 my $f = $self->{fields
};
383 unless (exists $f->{'Source'} and exists $f->{'Version'}) {
384 error
(g_
('%s and %s fields are required to compute the source basename'),
385 'Source', 'Version');
387 my $v = Dpkg
::Version
->new($f->{'Version'});
388 my $vs = $v->as_string(omit_epoch
=> 1, omit_revision
=> !$with_revision);
389 return $f->{'Source'} . '_' . $vs;
392 sub find_original_tarballs
{
393 my ($self, %opts) = @_;
394 $opts{extension
} //= compression_get_file_extension_regex
();
395 $opts{include_main
} //= 1;
396 $opts{include_supplementary
} //= 1;
397 my $basename = $self->get_basename();
399 foreach my $dir ('.', $self->{basedir
}, $self->{options
}{origtardir
}) {
400 next unless defined($dir) and -d
$dir;
401 opendir(my $dir_dh, $dir) or syserr
(g_
('cannot opendir %s'), $dir);
402 push @tar, map { File
::Spec
->catfile($dir, $_) } grep {
403 ($opts{include_main
} and
404 /^\Q$basename\E\.orig\.tar\.$opts{extension}$/) or
405 ($opts{include_supplementary
} and
406 /^\Q$basename\E\.orig-[[:alnum:]-]+\.tar\.$opts{extension}$/)
413 =item $p->get_upstream_signing_key($dir)
415 Get the filename for the upstream key.
419 sub get_upstream_signing_key
{
420 my ($self, $dir) = @_;
422 return "$dir/debian/upstream/signing-key.asc";
425 =item $p->armor_original_tarball_signature($bin, $asc)
427 Convert a signature from binary to ASCII armored form. If the signature file
428 does not exist, it is a no-op. If the signature file is already ASCII armored
429 then simply copy it, otherwise convert it from binary to ASCII armored form.
433 sub armor_original_tarball_signature
{
434 my ($self, $bin, $asc) = @_;
437 return $self->{openpgp
}->armor('SIGNATURE', $bin, $asc);
443 =item $p->check_original_tarball_signature($dir, @asc)
445 Verify the original upstream tarball signatures @asc using the upstream
446 public keys. It requires the origin upstream tarballs, their signatures
447 and the upstream signing key, as found in an unpacked source tree $dir.
448 If any inconsistency is discovered, it immediately errors out.
452 sub check_original_tarball_signature
{
453 my ($self, $dir, @asc) = @_;
455 my $upstream_key = $self->get_upstream_signing_key($dir);
456 if (not -e
$upstream_key) {
457 warning
(g_
('upstream tarball signatures but no upstream signing key'));
461 foreach my $asc (@asc) {
462 my $datafile = $asc =~ s/\.asc$//r;
464 info
(g_
('verifying %s'), $asc);
465 my $rc = $self->{openpgp
}->verify($datafile, $asc, $upstream_key);
467 $self->{report_verify
}->(g_
('cannot verify upstream tarball signature for %s: %s'),
468 $datafile, openpgp_errorcode_to_string
($rc));
473 =item $bool = $p->is_signed()
475 Returns 1 if the DSC files contains an embedded OpenPGP signature.
482 return $self->{is_signed
};
485 =item $p->check_signature()
487 Implement the same OpenPGP signature check that dpkg-source does.
488 In case of problems, it prints a warning or errors out.
490 If the object has been created with the "require_valid_signature" option,
491 then any problem will result in a fatal error.
495 sub check_signature
{
497 my $dsc = $self->get_filename();
500 push @certs, $self->{openpgp
}->get_trusted_keyrings();
502 foreach my $vendor_keyring (run_vendor_hook
('package-keyrings')) {
503 if (-r
$vendor_keyring) {
504 push @certs, $vendor_keyring;
508 my $rc = $self->{openpgp
}->inline_verify($dsc, undef, @certs);
510 $self->{report_verify
}->(g_
('cannot verify inline signature for %s: %s'),
511 $dsc, openpgp_errorcode_to_string
($rc));
515 sub describe_cmdline_options
{
519 sub parse_cmdline_options
{
520 my ($self, @opts) = @_;
521 foreach my $option (@opts) {
522 if (not $self->parse_cmdline_option($option)) {
523 warning
(g_
('%s is not a valid option for %s'), $option, ref $self);
528 sub parse_cmdline_option
{
532 =item $p->extract($targetdir)
534 Extracts the source package in the target directory $targetdir. Beware
535 that if $targetdir already exists, it will be erased (as long as the
536 no_overwrite_dir option is set).
541 my ($self, $newdirectory) = @_;
543 my ($ok, $error) = version_check
($self->{fields
}{'Version'});
545 if ($self->{options
}{ignore_bad_version
}) {
553 if ($self->{options
}{copy_orig_tarballs
}) {
554 my $basename = $self->get_basename();
555 my ($dirname, $destdir) = fileparse
($newdirectory);
557 my $ext = compression_get_file_extension_regex
();
558 foreach my $orig (grep { /^\Q$basename\E\.orig(-[[:alnum:]-]+)?\.tar\.$ext$/ }
561 my $src = File
::Spec
->catfile($self->{basedir
}, $orig);
562 my $dst = File
::Spec
->catfile($destdir, $orig);
563 if (not check_files_are_the_same
($src, $dst, 1)) {
565 or syserr
(g_
('cannot copy %s to %s'), $src, $dst);
571 $self->do_extract($newdirectory);
573 # Check for directory traversals.
574 if (not $self->{options
}{skip_debianization
} and not $self->{no_check
}) {
575 # We need to add a trailing slash to handle the debian directory
576 # possibly being a symlink.
577 check_directory_traversal
($newdirectory, "$newdirectory/debian/");
580 # Store format if non-standard so that next build keeps the same format
581 if ($self->{fields
}{'Format'} and
582 $self->{fields
}{'Format'} ne '1.0' and
583 not $self->{options
}{skip_debianization
})
585 my $srcdir = File
::Spec
->catdir($newdirectory, 'debian', 'source');
586 my $format_file = File
::Spec
->catfile($srcdir, 'format');
587 unless (-e
$format_file) {
588 mkdir($srcdir) unless -e
$srcdir;
589 $self->{format
}->save($format_file);
593 # Make sure debian/rules is executable
594 my $rules = File
::Spec
->catfile($newdirectory, 'debian', 'rules');
595 my @s = lstat($rules);
596 if (not scalar(@s)) {
597 unless ($! == ENOENT
) {
598 syserr
(g_
('cannot stat %s'), $rules);
600 warning
(g_
('%s does not exist'), $rules)
601 unless $self->{options
}{skip_debianization
};
603 chmod($s[2] | 0111, $rules)
604 or syserr
(g_
('cannot make %s executable'), $rules);
606 warning
(g_
('%s is not a plain file'), $rules);
611 croak
'Dpkg::Source::Package does not know how to unpack a ' .
612 'source package; use one of the subclasses';
615 # Function used specifically during creation of a source package
618 my ($self, $dir) = @_;
622 my ($self, @args) = @_;
624 $self->do_build(@args);
628 my ($self, $dir) = @_;
632 croak
'Dpkg::Source::Package does not know how to build a ' .
633 'source package; use one of the subclasses';
637 my ($self, $dir) = @_;
638 return (0, 'can_build() has not been overridden');
642 my ($self, $filename) = @_;
643 my ($fn, $dir) = fileparse
($filename);
644 if ($self->{checksums
}->has_file($fn)) {
645 croak
"tried to add file '$fn' twice";
647 $self->{checksums
}->add_from_file($filename, key
=> $fn);
648 $self->{checksums
}->export_to_control($self->{fields
},
649 use_files_for_md5
=> 1);
653 my ($self, @args) = @_;
655 $self->do_commit(@args);
659 my ($self, $dir) = @_;
660 info
(g_
("'%s' is not supported by the source format '%s'"),
661 'dpkg-source --commit', $self->{fields
}{'Format'});
665 my ($self, %opts) = @_;
666 my $fields = $self->{fields
};
668 foreach my $f (keys %{$opts{override
}}) {
669 $fields->{$f} = $opts{override
}{$f};
672 unless ($opts{nocheck
}) {
673 foreach my $f (qw(Source Version Architecture)) {
674 unless (defined($fields->{$f})) {
675 error
(g_
('missing information for critical output field %s'), $f);
678 foreach my $f (qw(Maintainer Standards-Version)) {
679 unless (defined($fields->{$f})) {
680 warning
(g_
('missing information for output field %s'), $f);
685 foreach my $f (keys %{$opts{remove
}}) {
686 delete $fields->{$f};
689 my $filename = $opts{filename
};
690 $filename //= $self->get_basename(1) . '.dsc';
691 open(my $dsc_fh, '>', $filename)
692 or syserr
(g_
('cannot write %s'), $filename);
693 $fields->apply_substvars($opts{substvars
});
694 $fields->output($dsc_fh);
702 =head2 Version 2.02 (dpkg 1.21.10)
704 New method: $p->armor_original_tarball_signature().
706 =head2 Version 2.01 (dpkg 1.20.1)
708 New method: $p->get_upstream_signing_key().
710 =head2 Version 2.00 (dpkg 1.20.0)
712 New method: $p->check_original_tarball_signature().
714 Remove variable: $diff_ignore_default_regexp.
716 Hide variable: @tar_ignore_default_pattern.
718 =head2 Version 1.03 (dpkg 1.19.3)
720 New option: format in new().
722 =head2 Version 1.02 (dpkg 1.18.7)
724 New option: require_strong_checksums in $p->check_checksums().
726 =head2 Version 1.01 (dpkg 1.17.2)
728 New functions: $p->get_default_diff_ignore_regex(),
729 $p->set_default_diff_ignore_regex(), $p->get_default_tar_ignore_pattern().
731 Deprecated variables: $diff_ignore_default_regexp, @tar_ignore_default_pattern
733 =head2 Version 1.00 (dpkg 1.16.1)
735 Mark the module as public.