--- a/update-serial Thu Nov 04 22:23:10 2010 +0100
+++ b/update-serial Thu Nov 04 22:26:18 2010 +0100
@@ -17,106 +17,99 @@
use strict;
use warnings;
+use File::Copy;
use File::Basename;
-use File::Copy;
+use Getopt::Long;
+use Pod::Usage;
#my $dnssec_sign = "../dnstools/dnssec-sign";
my $master_dir = "/etc/bind/master";
-
-my $ME = basename $0;
-my @tmpfiles;
-my $verbose = 0;
-my $opt_yes = 0;
-my @Zones;
-my $file;
+my $opt_verbose = 0;
+my $opt_reload = 0;
+my $opt_dnssec = 0;
-sub cleanup() { unlink @tmpfiles; }
+{
+ my @cleanup;
+ sub cleanup(@) {
+ return push @cleanup, @_ if @_;
+ unlink @cleanup;
+ }
+}
+
END { cleanup(); }
-@ARGV and $ARGV[0] eq "-y" and $opt_yes = 1, shift;
-@Zones = @ARGV ? @ARGV : glob("$master_dir/*");
-
+sub next_serial($);
MAIN: {
- my $changed;
- my ($dd, $mm, $yy) =(localtime())[3..5];
- my $date;
- $mm++;
- foreach ($dd, $mm) { s/^\d$/0$&/; }
- $yy += 1900;
- $date = "$yy$mm$dd";
+ GetOptions(
+ "verbose!" => \$opt_verbose,
+ "yes|reload!" => \$opt_reload,
+ "dnssec!" => \$opt_dnssec,
+ ) or pod2usage();
- while (my $file = shift @Zones) {
-
- my $file_basename = basename($file);
+ -d $master_dir or die "directory $master_dir not found\n" if not @ARGV;
+ my @files = map { (-d) ? glob("$_/*") : $_ } @ARGV ? @ARGV : $master_dir;
- $file =~ s#($master_dir)(/.*)#$1$2$2#;
- local (*I, *O);
- my $done = 0;
+ my $changed = 0;
+ foreach my $file (@files) {
+
+ $file = undef, next if basename($file) !~ /\./;
+ $file = undef, next if $file =~ /\.bak|~$/;
- my $new = "$file.$$.tmp";
- my $bak = "$file.bak";
- my $stamp = $master_dir . "/.stamp/" . basename($file);
+ # zone file could be
+ # $master_dir/xxx.de
+ # or $master_dir/xxx.de/xxx.de
+ $file = "$file/" . basename($file) if -d $file;
- $file =~ /(\.bak|~)$/ and next;
- $file !~ /\./ and next;
+ my $stamp_file = dirname($file) . "/.stamp/" . basename($file);
+ print "$file:" if $opt_verbose;
- $verbose && print "$file:";
-
-
- if (-f $stamp && ((stat($stamp))[9] >= (stat($file))[9])) {
- $verbose && print " fresh, skipping.\n";
+ if (stat $stamp_file and (stat _)[9] >= (stat $file)[9]) {
+ print " fresh, skipping." if $opt_verbose;
next;
}
- $done = 0;
- push @tmpfiles, $new;
- open(*I, "<$file") or die("Can't open < $file: $!\n");
- open(*O, ">$new") or die("Can't open > $new: $!\n");
+ $_ = dirname($stamp_file);
+ mkdir or die "mkdir $_: $!\n" if not -d;
+
+ my $now = time;
- while (<I>) {
- /^\s+((\d+)(\d{2}))\s*;\s*serial/i and do { # PATTERN
- my ($sdate, $scount, $serial) = ($2, $3, $1);
- $done = 1;
- print " [$file] serial $sdate$scount";
+ open(my $in, "+<", $file) or do {
+ print "?? $!";
+ next;
+ };
- if ($date eq $sdate) { $scount++; }
- else { $sdate = $date; $scount = "00"; }
-
- print " bumping to $sdate$scount";
- s/$serial/$sdate$scount/;
+ $_ = join "", <$in>;
- # dnssec - new sign
- system "cd ../dnstools && ./dnssec-sign $file_basename";
- #die "$dnssec_sign not found ($!)" if $? == -1;
- exit 1 if $?;
- };
- print O;
- }
-
- close(O); close(I);
-
- if ($done) {
- # copy($file, $bak) or die("Can't copy $file -> $bak: $!\n");
+ # this pattern is too complicated
+ s/^(?!;)(?<pre> # skip lines starting with comment
+ (?:\S+)? # label
+ (?:\s+\d+.)? # ttl
+ (?:\s+in)? # class
+ \s+soa # everything before the SOA
+ \s+\S+ # ns
+ \s+\S+ # hostmaster
+ (?:\s*\()?
+ \s+)
+ (?<serial>\d{10}) # serial
+ /$+{pre} . next_serial($+{serial})/exims or next;
- open(I, "<$new") or die("Can't open <$new: $!\n");
- open(O, ">$file") or die("Can't open >$file: $!\n");
- while (<I>) { print O or die("Can't write to $file: $!\n"); }
- close(I) or die("Can't close $new: $!\n");
- close(O) or die("Can't close $file: $!\n");
+ print "$+{serial} ⇒ @{[next_serial($+{serial})]}" if $opt_verbose;
- unlink $new;
+ copy($file => "$file~") or die("Can't copy $file -> $file~: $!\n");
+ seek($in, 0, 0) or die "Can't seek in $file: $!\n";
+ truncate($in, 0) or die "Can't truncate $file: $!\n";
+ print $in $_;
- open(O, ">$stamp") or die("Can't open >$stamp: $!\n");
- close(O);
- $changed++;
- } else {
- print " $file: no serial number found: no zone file?";
- }
- print "\n";
+ open(my $out, ">$stamp_file");
+ close($out);
+
+ $changed++;
+ } continue {
+ print "\n" if $opt_verbose and defined $file;
}
if ($changed) {
@@ -127,7 +120,7 @@
-f $_ and $pidfile = $_ and last; }
if ($pidfile) {
- if ($opt_yes) { $_ = "y"; print "** Nameserver will be reloaded\n"; }
+ if ($opt_reload) { $_ = "y"; print "** Nameserver will be reloaded\n"; }
else { print "** Reload now? [Y/n]: "; $_ = <STDIN>; }
/^y|^$/i and system "rndc reload";
} else {