167d43fbcSespie# ex:ts=8 sw=4: 2*c14c30adSespie# $OpenBSD: PackingList.pm,v 1.153 2023/11/23 09:44:08 espie Exp $ 36f05d20cSespie# 445019a4aSespie# Copyright (c) 2003-2014 Marc Espie <espie@openbsd.org> 56f05d20cSespie# 667d43fbcSespie# Permission to use, copy, modify, and distribute this software for any 767d43fbcSespie# purpose with or without fee is hereby granted, provided that the above 867d43fbcSespie# copyright notice and this permission notice appear in all copies. 96f05d20cSespie# 1067d43fbcSespie# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1167d43fbcSespie# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1267d43fbcSespie# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1367d43fbcSespie# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1467d43fbcSespie# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1567d43fbcSespie# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1667d43fbcSespie# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 176f05d20cSespie 18039cbdaaSespieuse v5.36; 19d76faf42Sespie 20d76faf42Sespiepackage OpenBSD::PackingList::State; 21d76faf42Sespiemy $dot = '.'; 22d76faf42Sespie 23039cbdaaSespiesub new($class) 24d76faf42Sespie{ 25d76faf42Sespie bless { default_owner=>'root', 26d76faf42Sespie default_group=>'bin', 27d76faf42Sespie default_mode=> 0444, 28652240a2Sespie owners => {}, 29652240a2Sespie groups => {}, 30d76faf42Sespie cwd=>\$dot}, $class; 31d76faf42Sespie} 32d76faf42Sespie 33039cbdaaSespiesub cwd($self) 34d76faf42Sespie{ 35039cbdaaSespie return ${$self->{cwd}}; 36d76faf42Sespie} 37d76faf42Sespie 38039cbdaaSespiesub set_cwd($self, $p) 39d76faf42Sespie{ 40d76faf42Sespie require File::Spec; 41d76faf42Sespie 42d76faf42Sespie $p = File::Spec->canonpath($p); 43d76faf42Sespie $self->{cwd} = \$p; 44d76faf42Sespie} 45d76faf42Sespie 46e451b54dSespiepackage OpenBSD::PackingList::hashpath; 47039cbdaaSespiesub match($h, $plist) 48e451b54dSespie{ 4908fe6b3eSespie my $f = $plist->fullpkgpath2; 502d3b5332Sespie if (!defined $f) { 512d3b5332Sespie return 0; 522d3b5332Sespie } 53a38c9a10Sespie for my $i (@{$h->{$f->{dir}}}) { 542d3b5332Sespie if ($i->match($f)) { 552d3b5332Sespie return 1; 562d3b5332Sespie } 572d3b5332Sespie } 582d3b5332Sespie return 0; 59e451b54dSespie} 60e451b54dSespie 61039cbdaaSespiesub partial_match($h, $subdir) 625c50b308Sespie{ 635c50b308Sespie for my $dir (keys %$h) { 645c50b308Sespie return 1 if $dir =~ m/\b\Q$subdir\E\b/; 655c50b308Sespie } 665c50b308Sespie return 0; 675c50b308Sespie} 685c50b308Sespie 695790075aSespiepackage OpenBSD::Composite; 705790075aSespie 71d1b1b3a5Sespie# convert call to $self->sub(@args) into $self->visit(sub, @args) 725790075aSespiesub AUTOLOAD 735790075aSespie{ 745790075aSespie our $AUTOLOAD; 755790075aSespie my $fullsub = $AUTOLOAD; 765790075aSespie (my $sub = $fullsub) =~ s/.*:://o; 775790075aSespie return if $sub eq 'DESTROY'; # special case 785790075aSespie my $self = $_[0]; 795790075aSespie # verify it makes sense 805790075aSespie if ($self->element_class->can($sub)) { 815790075aSespie no strict "refs"; 825790075aSespie # create the sub to avoid regenerating further calls 835790075aSespie *$fullsub = sub { 845790075aSespie my $self = shift; 855790075aSespie $self->visit($sub, @_); 865790075aSespie }; 875790075aSespie # and jump to it 885790075aSespie goto &$fullsub; 895790075aSespie } else { 905790075aSespie die "Can't call $sub on ".ref($self); 915790075aSespie } 925790075aSespie} 935790075aSespie 946f05d20cSespiepackage OpenBSD::PackingList; 955790075aSespieour @ISA = qw(OpenBSD::Composite); 966f05d20cSespie 976f05d20cSespieuse OpenBSD::PackingElement; 986f05d20cSespieuse OpenBSD::PackageInfo; 996f05d20cSespie 100039cbdaaSespiesub element_class($) { "OpenBSD::PackingElement" } 1015790075aSespie 102039cbdaaSespiesub new($class) 1036f05d20cSespie{ 104e39fac1bSespie my $plist = bless {state => OpenBSD::PackingList::State->new, 105e39fac1bSespie infodir => \(my $d)}, $class; 106435cc565Sespie OpenBSD::PackingElement::File->add($plist, CONTENTS); 107435cc565Sespie return $plist; 1086f05d20cSespie} 1096f05d20cSespie 110039cbdaaSespiesub set_infodir($self, $dir) 111e39fac1bSespie{ 112cc24e6f2Sespie $dir .= '/' unless $dir =~ m/\/$/o; 113e39fac1bSespie ${$self->{infodir}} = $dir; 114e39fac1bSespie} 115e39fac1bSespie 116039cbdaaSespiesub make_shallow_copy($plist, $h) 11726205b33Sespie{ 118d1b1b3a5Sespie my $copy = ref($plist)->new; 1192786dca3Sespie $copy->set_infodir($plist->infodir); 1206a5fab34Sespie $plist->copy_shallow_if($copy, $h); 12126205b33Sespie return $copy; 12226205b33Sespie} 12326205b33Sespie 124039cbdaaSespiesub make_deep_copy($plist, $h) 1256a5fab34Sespie{ 126d1b1b3a5Sespie my $copy = ref($plist)->new; 1272786dca3Sespie $copy->set_infodir($plist->infodir); 1286a5fab34Sespie $plist->copy_deep_if($copy, $h); 1296a5fab34Sespie return $copy; 1306a5fab34Sespie} 13126205b33Sespie 132039cbdaaSespiesub infodir($self) 133c0956bedSespie{ 1343f2ef483Sespie return ${$self->{infodir}}; 135c0956bedSespie} 136c0956bedSespie 137039cbdaaSespiesub zap_wrong_annotations($self) 138f0c4f0f9Sespie{ 139f0c4f0f9Sespie my $pkgname = $self->pkgname; 140f0c4f0f9Sespie if (defined $pkgname && $pkgname =~ m/^(?:\.libs\d*|partial)\-/) { 141f0c4f0f9Sespie delete $self->{'manual-installation'}; 14212460683Sespie delete $self->{'firmware'}; 14312460683Sespie delete $self->{'digital-signature'}; 144af6d27c8Sespie delete $self->{'signer'}; 145f0c4f0f9Sespie } 146f0c4f0f9Sespie} 147f0c4f0f9Sespie 148039cbdaaSespiesub conflict_list($self) 149ec33acfdSespie{ 150ec33acfdSespie require OpenBSD::PkgCfl; 151ec33acfdSespie 152d7d1cba4Sespie return OpenBSD::PkgCfl->make_conflict_list($self); 153ec33acfdSespie} 154ec33acfdSespie 155039cbdaaSespiesub read($a, $u, $code = \&defaultCode) 1566f05d20cSespie{ 157039cbdaaSespie $code //= \&defaultCode; # XXX callers may pass undef for now 1586f05d20cSespie my $plist; 1596f05d20cSespie if (ref $a) { 1606f05d20cSespie $plist = $a; 1616f05d20cSespie } else { 16246034630Sespie $plist = $a->new; 163d1b1b3a5Sespie } 16409568254Sespie &$code($u, 165039cbdaaSespie sub($line) { 1662c486618Sespie return if $line =~ m/^\s*$/o; 1672c486618Sespie OpenBSD::PackingElement->create($line, $plist); 168f7e1ce99Sespie }); 169f0c4f0f9Sespie $plist->zap_wrong_annotations; 1706f05d20cSespie return $plist; 1716f05d20cSespie} 1726f05d20cSespie 173039cbdaaSespiesub defaultCode($fh, $cont) 1746f05d20cSespie{ 175f7e1ce99Sespie while (<$fh>) { 176f7e1ce99Sespie &$cont($_); 177f7e1ce99Sespie } 1786f05d20cSespie} 1796f05d20cSespie 180039cbdaaSespiesub SharedItemsOnly($fh, $cont) 1816f05d20cSespie{ 182f7e1ce99Sespie while (<$fh>) { 1830dbdd4adSespie next unless m/^\@(?:cwd|dir|fontdir|ghost|mandir|newuser|newgroup|name)\b/o || m/^\@(?:sample|extra)\b.*\/$/o || m/^[^\@].*\/$/o; 184f7e1ce99Sespie &$cont($_); 185f7e1ce99Sespie } 1866f05d20cSespie} 1876f05d20cSespie 188039cbdaaSespiesub UpdatePlistOnly($fh, $cont) 1896e58fb23Sespie{ 1906e58fb23Sespie while (<$fh>) { 1916e58fb23Sespie next unless m/^\@(?:cwd|dir|fontdir|ghost|mandir|depend)\b/o || m/^\@(?:sample|extra)\b.*\/$/o || m/^[^\@].*\/$/o; 1926e58fb23Sespie &$cont($_); 1936e58fb23Sespie } 1946e58fb23Sespie} 1956e58fb23Sespie 196039cbdaaSespiesub DirrmOnly # forwarder 19758be51c0Sespie{ 19858be51c0Sespie &OpenBSD::PackingList::SharedItemsOnly; 19958be51c0Sespie} 20058be51c0Sespie 201039cbdaaSespiesub LibraryOnly($fh, $cont) 2022d9bc31aSespie{ 2032d9bc31aSespie while (<$fh>) { 204dd2410cfSespie next unless m/^\@(?:cwd|lib|name|comment\s+subdir\=)\b/o; 2052d9bc31aSespie &$cont($_); 2062d9bc31aSespie } 2072d9bc31aSespie} 2082d9bc31aSespie 209039cbdaaSespiesub FilesOnly($fh, $cont) 2106f05d20cSespie{ 211f7e1ce99Sespie while (<$fh>) { 212130b115fSespie next unless m/^\@(?:cwd|name|info|man|file|lib|shell|sample|bin|rcscript|so|static-lib)\b/o || !m/^\@/o; 213f7e1ce99Sespie &$cont($_); 214f7e1ce99Sespie } 215f7e1ce99Sespie} 216f7e1ce99Sespie 217039cbdaaSespiesub PrelinkStuffOnly($fh, $cont) 2186a8d296fSespie{ 2196a8d296fSespie while (<$fh>) { 220d13585a8Sespie next unless m/^\@(?:cwd|bin|lib|name|define-tag|libset|depend|wantlib|comment\s+ubdir\=)\b/o; 2216a8d296fSespie &$cont($_); 2226a8d296fSespie } 2236a8d296fSespie} 2246a8d296fSespie 225039cbdaaSespiesub DependOnly($fh, $cont) 22638727c08Sespie{ 22738727c08Sespie while (<$fh>) { 228b78ce643Sespie if (m/^\@(?:libset|depend|wantlib|define-tag)\b/o) { 22928790261Sespie &$cont($_); 230dd2410cfSespie # XXX optimization 231368a866dSespie } elsif (m/^\@(?:newgroup|newuser|cwd)\b/o) { 23228790261Sespie last; 23328790261Sespie } 23428790261Sespie } 23538727c08Sespie} 23638727c08Sespie 237039cbdaaSespiesub ExtraInfoOnly($fh, $cont) 238737fdd9bSespie{ 239737fdd9bSespie while (<$fh>) { 240e18e832dSespie if (m/^\@(?:name|pkgpath|comment\s+(?:subdir|pkgpath)\=|option)\b/o) { 241987c5975Sespie &$cont($_); 242dd2410cfSespie # XXX optimization 243b78ce643Sespie } elsif (m/^\@(?:libset|depend|wantlib|newgroup|newuser|cwd)\b/o) { 2447522c6eaSespie last; 2457522c6eaSespie } 2467522c6eaSespie } 247737fdd9bSespie} 248737fdd9bSespie 249039cbdaaSespiesub UpdateInfoOnly($fh, $cont) 2509b5ce663Sespie{ 2519b5ce663Sespie while (<$fh>) { 252efe01a68Sespie # if old alwaysupdate, all info is sig 253efe01a68Sespie # if new, we don't need the rest 254efe01a68Sespie if (m/^\@option\s+always-update$/o) { 2559131f929Sespie &$cont($_); 2569131f929Sespie while (<$fh>) { 2579131f929Sespie &$cont($_); 2589131f929Sespie } 2593b9b0d1bSespie return; 2609131f929Sespie } 261b78ce643Sespie if (m/^\@(?:name|libset|depend|wantlib|conflict|option|pkgpath|url|version|arch|comment\s+(?:subdir|pkgpath)\=)\b/o) { 2629b5ce663Sespie &$cont($_); 263dd2410cfSespie # XXX optimization 264dd2410cfSespie } elsif (m/^\@(?:newgroup|newuser|cwd)\b/o) { 265dd2410cfSespie last; 266dd2410cfSespie } 2679b5ce663Sespie } 2689b5ce663Sespie} 2699b5ce663Sespie 270039cbdaaSespiesub ConflictOnly($fh, $cont) 271f7e1ce99Sespie{ 272f7e1ce99Sespie while (<$fh>) { 273dd2410cfSespie if (m/^\@(?:name|conflict|option)\b/o) { 27428790261Sespie &$cont($_); 275dd2410cfSespie # XXX optimization 276b78ce643Sespie } elsif (m/^\@(?:libset|depend|wantlib|newgroup|newuser|cwd)\b/o) { 27728790261Sespie last; 27828790261Sespie } 27928790261Sespie } 280f7e1ce99Sespie} 281f7e1ce99Sespie 282039cbdaaSespiesub fromfile($a, $fname, $code = \&defaultCode) 2836f05d20cSespie{ 284b9b2024bSespie open(my $fh, '<', $fname) or return; 2858433647eSespie my $plist; 2868433647eSespie eval { 2878433647eSespie $plist = $a->read($fh, $code); 2888433647eSespie }; 2898433647eSespie if ($@) { 2908433647eSespie chomp $@; 291cc24e6f2Sespie $@ =~ s/\.$/,/o; 2928433647eSespie die "$@ in $fname, "; 2938433647eSespie } 2946f05d20cSespie close($fh); 2956f05d20cSespie return $plist; 2966f05d20cSespie} 2976f05d20cSespie 298039cbdaaSespiesub tofile($self, $fname) 2996f05d20cSespie{ 300b9b2024bSespie open(my $fh, '>', $fname) or return; 301f0c4f0f9Sespie $self->zap_wrong_annotations; 3026f05d20cSespie $self->write($fh); 303b9b2024bSespie close($fh) or return; 3046f05d20cSespie return 1; 3056f05d20cSespie} 3066f05d20cSespie 307039cbdaaSespiesub save($self) 308c0956bedSespie{ 309c0956bedSespie $self->tofile($self->infodir.CONTENTS); 310c0956bedSespie} 311c0956bedSespie 312039cbdaaSespiesub add2list($plist, $object) 3136f05d20cSespie{ 314f04afe28Sespie my $category = $object->category; 3156f05d20cSespie push @{$plist->{$category}}, $object; 3166f05d20cSespie} 3176f05d20cSespie 318039cbdaaSespiesub addunique($plist, $object) 3196f05d20cSespie{ 320f04afe28Sespie my $category = $object->category; 3216f05d20cSespie if (defined $plist->{$category}) { 32233efc49fSespie die "Duplicate $category in plist ".($plist->pkgname // "?"); 3236f05d20cSespie } 3246f05d20cSespie $plist->{$category} = $object; 3256f05d20cSespie} 3266f05d20cSespie 327039cbdaaSespiesub has($plist, $name) 32810d7f8b4Sespie{ 32910d7f8b4Sespie return defined $plist->{$name}; 33010d7f8b4Sespie} 33110d7f8b4Sespie 332039cbdaaSespiesub get($plist, $name) 33310d7f8b4Sespie{ 33410d7f8b4Sespie return $plist->{$name}; 33510d7f8b4Sespie} 33610d7f8b4Sespie 337039cbdaaSespiesub set_pkgname($self, $name) 33826205b33Sespie{ 33926205b33Sespie if (defined $self->{name}) { 340e451b54dSespie $self->{name}->set_name($name); 34126205b33Sespie } else { 34226205b33Sespie OpenBSD::PackingElement::Name->add($self, $name); 34326205b33Sespie } 34426205b33Sespie} 34526205b33Sespie 346039cbdaaSespiesub pkgname($self) 3476f05d20cSespie{ 348c9089320Snaddy if (defined $self->{name}) { 349e451b54dSespie return $self->{name}->name; 350c9089320Snaddy } else { 351c9089320Snaddy return undef; 352c9089320Snaddy } 3536f05d20cSespie} 3546f05d20cSespie 355039cbdaaSespiesub localbase($self) 356dccc2276Sespie{ 357e95d9ee4Sespie if (defined $self->{localbase}) { 358e451b54dSespie return $self->{localbase}->name; 359e95d9ee4Sespie } else { 360e95d9ee4Sespie return '/usr/local'; 361e95d9ee4Sespie } 362dccc2276Sespie} 363dccc2276Sespie 364039cbdaaSespiesub is_signed($self) 36511ccabebSespie{ 36687317f7eSespie return defined $self->{'digital-signature'}; 36711ccabebSespie} 3682063c02eSespie 369039cbdaaSespiesub fullpkgpath($self) 370a4f5498fSespie{ 37189955da4Sespie if (defined $self->{extrainfo} && $self->{extrainfo}{subdir} ne '') { 37289955da4Sespie return $self->{extrainfo}{subdir}; 37308fe6b3eSespie } else { 37408fe6b3eSespie return undef; 37508fe6b3eSespie } 37608fe6b3eSespie} 37708fe6b3eSespie 378039cbdaaSespiesub fullpkgpath2($self) 37908fe6b3eSespie{ 38089955da4Sespie if (defined $self->{extrainfo} && $self->{extrainfo}{subdir} ne '') { 38189955da4Sespie return $self->{extrainfo}{path}; 382a4f5498fSespie } else { 383a4f5498fSespie return undef; 384a4f5498fSespie } 385a4f5498fSespie} 38608fe6b3eSespie 387039cbdaaSespiesub pkgpath($self) 388e451b54dSespie{ 389e451b54dSespie if (!defined $self->{_hashpath}) { 390e451b54dSespie my $h = $self->{_hashpath} = 391e451b54dSespie bless {}, "OpenBSD::PackingList::hashpath"; 39208fe6b3eSespie my $f = $self->fullpkgpath2; 3932d3b5332Sespie if (defined $f) { 3942d3b5332Sespie push(@{$h->{$f->{dir}}}, $f); 395e451b54dSespie } 396e451b54dSespie if (defined $self->{pkgpath}) { 397e451b54dSespie for my $i (@{$self->{pkgpath}}) { 39889955da4Sespie push(@{$h->{$i->{path}{dir}}}, $i->{path}); 399e451b54dSespie } 400e451b54dSespie } 401e451b54dSespie } 402e451b54dSespie return $self->{_hashpath}; 403e451b54dSespie} 404e451b54dSespie 405039cbdaaSespiesub match_pkgpath($self, $plist2) 406e451b54dSespie{ 40731e751cfSespie return $self->pkgpath->match($plist2) || 40831e751cfSespie $plist2->pkgpath->match($self); 409e451b54dSespie} 410e451b54dSespie 4119b5ce663Sespieour @unique_categories = 412*c14c30adSespie (qw(name url version signer digital-signature no-default-conflict manual-installation firmware always-update updatedb is-branch extrainfo localbase arch)); 4139b5ce663Sespie 4149b5ce663Sespieour @list_categories = 415b78ce643Sespie (qw(conflict pkgpath ask-update libset depend 416b82ff443Sespie wantlib define-tag groups users items)); 4179b5ce663Sespie 4189b5ce663Sespieour @cache_categories = 419b78ce643Sespie (qw(libset depend wantlib)); 4209b5ce663Sespie 421039cbdaaSespiesub visit($self, $method, @l) 4222063c02eSespie{ 4232063c02eSespie if (defined $self->{cvstags}) { 4242063c02eSespie for my $item (@{$self->{cvstags}}) { 42567cc0ba0Sespie $item->$method(@l) unless $item->{deleted}; 4262063c02eSespie } 4272063c02eSespie } 4282063c02eSespie 42967cc0ba0Sespie # XXX unique and info files really get deleted, so there's no need 43067cc0ba0Sespie # to remove them later. 4319b5ce663Sespie for my $unique_item (@unique_categories) { 43267cc0ba0Sespie $self->{$unique_item}->$method(@l) 43367cc0ba0Sespie if defined $self->{$unique_item}; 4342063c02eSespie } 4352063c02eSespie 4362063c02eSespie for my $special (OpenBSD::PackageInfo::info_names()) { 4372063c02eSespie $self->{$special}->$method(@l) if defined $self->{$special}; 4382063c02eSespie } 4392063c02eSespie 4409b5ce663Sespie for my $listname (@list_categories) { 4412063c02eSespie if (defined $self->{$listname}) { 4422063c02eSespie for my $item (@{$self->{$listname}}) { 44367cc0ba0Sespie $item->$method(@l) if !$item->{deleted}; 4442063c02eSespie } 4452063c02eSespie } 4462063c02eSespie } 4472063c02eSespie} 4482063c02eSespie 44951f6b09fSespiemy $plist_cache = {}; 45051f6b09fSespie 451039cbdaaSespiesub from_installation($o, $pkgname, $code = \&defaultCode) 45218f9a590Sespie{ 45318f9a590Sespie require OpenBSD::PackageInfo; 45418f9a590Sespie 455f5939716Sespie $code //= \&defaultCode; 4563571b10fSespie if ($code == \&DependOnly && defined $plist_cache->{$pkgname}) { 4573571b10fSespie return $plist_cache->{$pkgname}; 4583571b10fSespie } 4598ee98284Sespie my $filename = OpenBSD::PackageInfo::installed_contents($pkgname); 4608ee98284Sespie my $plist = $o->fromfile($filename, $code); 4613571b10fSespie if (defined $plist && $code == \&DependOnly) { 4623571b10fSespie $plist_cache->{$pkgname} = $plist; 4633571b10fSespie } 4643fdb0aa4Sespie if (defined $plist) { 465e39fac1bSespie $plist->set_infodir(OpenBSD::PackageInfo::installed_info($pkgname)); 4663fdb0aa4Sespie } 4678ee98284Sespie if (!defined $plist) { 4688ee98284Sespie print STDERR "Warning: couldn't read packing-list from installed package $pkgname\n"; 4698ee98284Sespie unless (-e $filename) { 4708ee98284Sespie print STDERR "File $filename does not exist\n"; 4718ee98284Sespie } 4728ee98284Sespie } 47351f6b09fSespie return $plist; 47418f9a590Sespie} 47518f9a590Sespie 476039cbdaaSespiesub to_cache($self) 477f0b76557Sespie{ 478b1674f53Sespie return if defined $plist_cache->{$self->pkgname}; 4792bfe9404Sespie my $plist = OpenBSD::PackingList->new; 4809b5ce663Sespie for my $c (@cache_categories) { 481bd99e8b0Sespie if (defined $self->{$c}) { 482bd99e8b0Sespie $plist->{$c} = $self->{$c}; 483bd99e8b0Sespie } 484bd99e8b0Sespie } 485e39fac1bSespie $plist_cache->{$self->pkgname} = $plist; 486f0b76557Sespie} 487f0b76557Sespie 488039cbdaaSespiesub to_installation($self) 48918f9a590Sespie{ 49018f9a590Sespie require OpenBSD::PackageInfo; 49118f9a590Sespie 49238599eebSespie return if $main::not; 49338599eebSespie 494f04afe28Sespie $self->tofile(OpenBSD::PackageInfo::installed_contents($self->pkgname)); 49551f6b09fSespie} 49651f6b09fSespie 497039cbdaaSespiesub signature($self) 49851f6b09fSespie{ 499e1eeb5e0Sespie require OpenBSD::Signature; 500e1eeb5e0Sespie return OpenBSD::Signature->from_plist($self); 501fc9f0195Sespie} 502fc9f0195Sespie 5036f05d20cSespie1; 504