SecBSD's official ports repository
This commit is contained in:
commit
2c0afcbbf3
64331 changed files with 5339189 additions and 0 deletions
327
infrastructure/lib/OpenBSD/TrackFile.pm
Normal file
327
infrastructure/lib/OpenBSD/TrackFile.pm
Normal file
|
@ -0,0 +1,327 @@
|
|||
#! /usr/bin/perl
|
||||
# $OpenBSD: TrackFile.pm,v 1.9 2023/05/16 13:59:17 espie Exp $
|
||||
# Copyright (c) 2018-2022 Marc Espie <espie@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
use v5.36;
|
||||
# This is a set of utility classes for update-plist
|
||||
|
||||
# so in order to put objects in the right plist part, we need to track
|
||||
# destination file: objects are annotated with an "OpenBSD::TrackedFile"
|
||||
# which consists ultimately of all the items that are going to end up in
|
||||
# that specific file
|
||||
|
||||
package OpenBSD::TrackedFile;
|
||||
# the actual OpenBSD::TrackedFile(s) will be created by the next (factory) class
|
||||
sub new($class, $name, $ext)
|
||||
{
|
||||
bless {name => $name, # the actual filename proper
|
||||
ext => $ext, # extension like -new since update-plist
|
||||
# creates new files for people to diff
|
||||
items => [], # list of items for 1st pass
|
||||
items2 => [] # actual list of items that get written
|
||||
}, $class;
|
||||
}
|
||||
|
||||
sub add($self, $item)
|
||||
{
|
||||
push(@{$self->{items}}, $item);
|
||||
}
|
||||
|
||||
# this is the internal method that gets called through prepare_restate
|
||||
sub add2($self, $item, $p)
|
||||
{
|
||||
if ($item->NoDuplicateNames) {
|
||||
my $s = $p->subst->remove_ignored_vars($item->{prepared});
|
||||
my $s2 = $p->subst->do($s);
|
||||
if (defined (my $k = $item->keyword)) {
|
||||
$s2 =~ s/^\@\Q$k\E\s//;
|
||||
}
|
||||
$p->{stash}{$s2}++;
|
||||
|
||||
my $comment = $p->subst->{maybe_comment};
|
||||
|
||||
if ($s ne $item->{prepared} &&
|
||||
$item->{prepared} !~ m/^\Q$comment\E/) {
|
||||
$item->{candidate_for_comment} = $s2;
|
||||
}
|
||||
}
|
||||
push(@{$self->{items2}}, $item);
|
||||
}
|
||||
|
||||
sub fh($self)
|
||||
{
|
||||
if (!defined $self->{fh}) {
|
||||
my $full = $self->name.$self->{ext};
|
||||
open($self->{fh}, '>', $full) or die "Can't open $full: $!";
|
||||
}
|
||||
return $self->{fh};
|
||||
}
|
||||
|
||||
sub name($self)
|
||||
{
|
||||
return $self->{name};
|
||||
}
|
||||
|
||||
# iterating through the list for preparing
|
||||
sub next_item($self)
|
||||
{
|
||||
if (@{$self->{items}} != 0) {
|
||||
return shift @{$self->{items}};
|
||||
} else {
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
# iterating through the list for writing
|
||||
sub next_item2($self)
|
||||
{
|
||||
if (@{$self->{items2}} != 0) {
|
||||
return shift @{$self->{items2}};
|
||||
} else {
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
# this is the factory class that is responsible for (physically) dispatching
|
||||
# items into the right plist fragment
|
||||
package OpenBSD::TrackFile;
|
||||
|
||||
# the base factory creates a "default" destination
|
||||
sub new($class, $default, $ext)
|
||||
{
|
||||
my $self = bless {ext => $ext}, $class;
|
||||
$self->{known}{$default} =
|
||||
$self->{default} =
|
||||
OpenBSD::TrackedFile->new($default, $self->{ext});
|
||||
return $self;
|
||||
}
|
||||
|
||||
# each new fragment creates a new OpenBSD::TrackedFile
|
||||
# (unless it already exists)
|
||||
sub file($self, $name)
|
||||
{
|
||||
$self->{known}{$name} //=
|
||||
OpenBSD::TrackedFile->new($name, $self->{ext});
|
||||
return $self->{known}{$name};
|
||||
}
|
||||
|
||||
sub default($self)
|
||||
{
|
||||
return $self->{default};
|
||||
}
|
||||
|
||||
# and this is the actual method that writes every object: responsible for
|
||||
# handling each and every file, and also passing offstate changes (@mode and
|
||||
# the likes) to prepare_restate to avoid too much duplication
|
||||
sub write_all($self, $p)
|
||||
{
|
||||
# we mimic the way pkg_create writes files
|
||||
|
||||
# first pass is just going to scan through the list and queue actual
|
||||
# stuff we want to write
|
||||
for my $i (@{$p->{base_plists}}) {
|
||||
$p->{restate} = {};
|
||||
|
||||
my @stack = ();
|
||||
push(@stack, $self->file($i));
|
||||
|
||||
|
||||
while (my $file = pop @stack) {
|
||||
while (my $j = $file->next_item) {
|
||||
my $filename = $j->prepare_restate($file, $p);
|
||||
if (defined $filename) {
|
||||
push(@stack, $file);
|
||||
$file = $self->file($filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# second pass writes out the resulting "restated" data
|
||||
for my $i (@{$p->{base_plists}}) {
|
||||
$p->{restate} = {};
|
||||
|
||||
my @stack = ();
|
||||
push(@stack, $self->file($i));
|
||||
|
||||
|
||||
while (my $file = pop @stack) {
|
||||
while (my $j = $file->next_item2) {
|
||||
my $filename = $j->write_restate($file, $p);
|
||||
if (defined $filename) {
|
||||
push(@stack, $file);
|
||||
$file = $self->file($filename);
|
||||
}
|
||||
}
|
||||
close($file->fh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
package OpenBSD::PackingElement;
|
||||
# the actual methods that keep state (@mode/@owner/@group) and do
|
||||
# backsubstitution and writing.
|
||||
# part of the state is the current fragment, so it should return the
|
||||
# new filename when it changes
|
||||
# Note that this is not called as a visitor, but directly by the FileTracker
|
||||
# on the lists it builds
|
||||
# The methods are split into a "restate" and a "backsubst" level so that
|
||||
# subclasses may concentrate on that part of the job
|
||||
|
||||
|
||||
# this is the actual writer.
|
||||
sub write_restate($o, $file, $p)
|
||||
{
|
||||
$o->write_backsubst($file, $p);
|
||||
return undef;
|
||||
}
|
||||
|
||||
# this just prepares data for the second pass
|
||||
sub prepare_restate($o, $file, $p)
|
||||
{
|
||||
$o->prepare_backsubst($file, $p);
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub prepare_backsubst($o, $file, $p)
|
||||
{
|
||||
my $s = $p->subst->do_backsubst($o->fullstring, $o->unsubst, $o);
|
||||
$o->{prepared} = $s;
|
||||
$file->add2($o, $p);
|
||||
}
|
||||
|
||||
# default backsubstitution and writing.
|
||||
sub write_backsubst($o, $file, $p)
|
||||
{
|
||||
if (defined (my $s = $o->{candidate_for_comment})) {
|
||||
if ($p->{stash}{$s} > 1) {
|
||||
$o->{prepared} =
|
||||
$p->subst->{maybe_comment}.$o->{prepared};
|
||||
}
|
||||
}
|
||||
print {$file->fh} $o->{prepared}, "\n";
|
||||
}
|
||||
|
||||
package OpenBSD::PackingElement::SpecialFile;
|
||||
sub write_restate($, $, $)
|
||||
{
|
||||
}
|
||||
|
||||
sub prepare_restate($, $, $)
|
||||
{
|
||||
}
|
||||
|
||||
package OpenBSD::PackingElement::Fragment;
|
||||
# while writing, change file accordingly
|
||||
sub write_restate($self, $file, $p)
|
||||
{
|
||||
# don't do backsubst on fragments, pkg_create does not!
|
||||
$self->write($file->fh);
|
||||
my $base = $file->name;
|
||||
my $frag = $self->frag;
|
||||
$base =~ s/PFRAG\./PFRAG.$frag-/ or
|
||||
$base =~ s/PLIST/PFRAG.$frag/;
|
||||
return $base if $p->{tracker}{known}{$base};
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub prepare_restate($self, $file, $p)
|
||||
{
|
||||
# don't do backsubst on fragments, pkg_create does not!
|
||||
$file->add2($self, $p);
|
||||
my $base = $file->name;
|
||||
my $frag = $self->frag;
|
||||
$base =~ s/PFRAG\./PFRAG.$frag-/ or
|
||||
$base =~ s/PLIST/PFRAG.$frag/;
|
||||
return $base if $p->{tracker}{known}{$base};
|
||||
return undef;
|
||||
}
|
||||
|
||||
package OpenBSD::PackingElement::FileObject;
|
||||
sub write_restate($self, $f, $p)
|
||||
{
|
||||
# TODO there should be some more code matching the mode to the original
|
||||
# file that was copied
|
||||
for my $k (qw(mode owner group)) {
|
||||
my $s = "\@$k";
|
||||
if (defined $self->{$k}) {
|
||||
if (defined $p->{restate}{$k}) {
|
||||
if ($p->{restate}{$k} eq $self->{$k}) {
|
||||
next;
|
||||
}
|
||||
}
|
||||
if ($k eq 'mode') {
|
||||
$s .= " ".$self->{$k};
|
||||
} else {
|
||||
$s .= " ".
|
||||
$p->subst->do_backsubst($self->{$k});
|
||||
}
|
||||
} else {
|
||||
if (!defined $p->{restate}{$k}) {
|
||||
next;
|
||||
}
|
||||
}
|
||||
$p->{restate}{$k} = $self->{$k};
|
||||
print {$f->fh} $s, "\n";
|
||||
}
|
||||
$self->write_backsubst($f, $p);
|
||||
return undef;
|
||||
}
|
||||
|
||||
package OpenBSD::PackingElement::FileBase;
|
||||
sub write_backsubst($self, $f, $p)
|
||||
{
|
||||
if (defined $self->{nochecksum}) {
|
||||
print {$f->fh} "\@comment no checksum\n";
|
||||
}
|
||||
if (defined $self->{nodebug}) {
|
||||
print {$f->fh} "\@comment no debug\n";
|
||||
}
|
||||
$self->SUPER::write_backsubst($f, $p);
|
||||
}
|
||||
|
||||
package OpenBSD::PackingElement::LoginClass;
|
||||
use File::Basename;
|
||||
|
||||
sub prepare_backsubst($self, $f, $p)
|
||||
{
|
||||
$self->SUPER::prepare_backsubst($f, $p);
|
||||
if (!defined $self->{mytags}) {
|
||||
my $n = OpenBSD::PackingElement::Sample->new(
|
||||
"/etc/login.conf.d/".basename($self->name));
|
||||
$n->prepare_backsubst($f, $p);
|
||||
}
|
||||
}
|
||||
|
||||
package OpenBSD::PackingElement::Lib;
|
||||
sub prepare_backsubst($self, $f, $p)
|
||||
{
|
||||
if ($self->name =~ m,^(.*?)lib([^\/]+)\.so\.(\d+\.\d+)$,) {
|
||||
my ($path, $name, $version) = ($1, $2, $3);
|
||||
my $k = "LIB${name}_VERSION";
|
||||
# XXX redo backsubst on the variable name
|
||||
my $s = $p->subst->do_backsubst(
|
||||
"\@lib ${path}lib$name.so.\$\{$k\}", $self->unsubst, $self);
|
||||
$self->check_lib_version($version, $name,
|
||||
$p->subst->value($k));
|
||||
$self->{prepared} = $s;
|
||||
$f->add2($self, $p);
|
||||
} else {
|
||||
$self->SUPER::write_backsubst($f, $p);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
Loading…
Add table
Add a link
Reference in a new issue