File: //usr/share/perl5/vendor_perl/Amavis/DB.pm
# SPDX-License-Identifier: GPL-2.0-or-later
package Amavis::DB;
use strict;
use re 'taint';
use warnings;
use warnings FATAL => qw(utf8 void);
# use warnings 'extra'; no warnings 'experimental::re_strict'; use re 'strict';
BEGIN {
require Exporter;
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
$VERSION = '2.412';
@ISA = qw(Exporter);
}
use BerkeleyDB;
use Amavis::Conf qw($db_home $daemon_chroot_dir);
use Amavis::Util qw(untaint ll do_log);
use Amavis::DB::SNMP;
# create new databases, then close them (called by the parent process)
# (called only if $db_home is nonempty)
#
sub init($$) {
my($predelete_nanny, $predelete_snmp) = @_;
my $name = $db_home;
$name = "$daemon_chroot_dir $name" if $daemon_chroot_dir ne '';
if ($predelete_nanny || $predelete_snmp) { # delete existing db files first?
local(*DIR);
opendir(DIR,$db_home) or die "db_init: Can't open directory $name: $!";
# modifying a directory while traversing it can cause surprises, avoid;
# avoid slurping the whole directory contents into memory
my($f, @rmfiles);
while (defined($f = readdir(DIR))) {
next if $f eq '.' || $f eq '..';
if ($f =~ /^(__db\.)?nanny\.db\z/) {
push(@rmfiles, $f) if $predelete_nanny;
} elsif ($f =~ /^(__db\.)?snmp\.db\z/) {
push(@rmfiles, $f) if $predelete_snmp;
} elsif ($f =~ /^__db\.\d+\z/s) {
push(@rmfiles, $f) if $predelete_nanny && $predelete_snmp;
} elsif ($f =~ /^(?:cache-expiry|cache)\.db\z/s) {
push(@rmfiles, $f); # old databases, no longer used since 2.7.0-pre9
}
}
closedir(DIR) or die "db_init: Error closing directory $name: $!";
do_log(1, 'Deleting db files %s in %s', join(',',@rmfiles), $name);
for my $f (@rmfiles) {
my $fname = $db_home . '/' . untaint($f);
unlink($fname) or die "db_init: Can't delete file $fname: $!";
}
undef @rmfiles; # release storage
}
$! = 0; my $env = BerkeleyDB::Env->new(-Home=>$db_home, -Mode=>0640,
-Flags=> DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL);
defined $env
or die "BDB can't create db env. at $db_home: $BerkeleyDB::Error, $!.";
do_log(1, 'Creating db in %s/; BerkeleyDB %s, libdb %s',
$name, BerkeleyDB->VERSION, $BerkeleyDB::db_version);
$! = 0; my $dbs = BerkeleyDB::Hash->new(
-Filename=>'snmp.db', -Flags=>DB_CREATE, -Env=>$env );
defined $dbs or die "db_init: BDB no dbS: $BerkeleyDB::Error, $!.";
$! = 0; my $dbn = BerkeleyDB::Hash->new(
-Filename=>'nanny.db', -Flags=>DB_CREATE, -Env=>$env );
defined $dbn or die "db_init: BDB no dbN: $BerkeleyDB::Error, $!.";
Amavis::DB::SNMP::put_initial_snmp_data($dbs) if $predelete_snmp;
for my $db ($dbs, $dbn) {
$db->db_close==0 or die "db_init: BDB db_close: $BerkeleyDB::Error, $!.";
}
}
# open an existing databases environment (called by each child process)
#
sub new {
my $class = $_[0]; my $env;
if (defined $db_home) {
$! = 0; $env = BerkeleyDB::Env->new(
-Home=>$db_home, -Mode=>0640, -Flags=> DB_INIT_CDB | DB_INIT_MPOOL);
defined $env
or die "BDB can't connect db env. at $db_home: $BerkeleyDB::Error, $!.";
}
bless \$env, $class;
}
sub get_db_env { my $self = $_[0]; $$self }
1;