From 3f7f507605d77ece782e847a5a1606197268f220 Mon Sep 17 00:00:00 2001 From: ianmdlvl Date: Sun, 7 Oct 2001 16:12:21 +0000 Subject: [PATCH 1/1] Found on davenant in /usr/local/lib (in use on anarres). --- backup/Makefile | 2 + backup/backuplib.pl | 92 ++++++++++++++++++++++++ backup/bringup | 5 ++ backup/checkallused | 121 +++++++++++++++++++++++++++++++ backup/driver | 29 ++++++++ backup/full | 166 +++++++++++++++++++++++++++++++++++++++++++ backup/increm | 84 ++++++++++++++++++++++ backup/junk | 34 +++++++++ backup/loaded | 15 ++++ backup/old-increm | 58 +++++++++++++++ backup/readbuffer | Bin 0 -> 20766 bytes backup/readbuffer.c | 94 ++++++++++++++++++++++++ backup/takedown | 33 +++++++++ backup/writebuffer | Bin 0 -> 13742 bytes backup/writebuffer.c | 81 +++++++++++++++++++++ 15 files changed, 814 insertions(+) create mode 100644 backup/Makefile create mode 100644 backup/backuplib.pl create mode 100755 backup/bringup create mode 100755 backup/checkallused create mode 100755 backup/driver create mode 100755 backup/full create mode 100755 backup/increm create mode 100644 backup/junk create mode 100755 backup/loaded create mode 100755 backup/old-increm create mode 100755 backup/readbuffer create mode 100644 backup/readbuffer.c create mode 100755 backup/takedown create mode 100755 backup/writebuffer create mode 100644 backup/writebuffer.c diff --git a/backup/Makefile b/backup/Makefile new file mode 100644 index 0000000..1315c88 --- /dev/null +++ b/backup/Makefile @@ -0,0 +1,2 @@ +CC=gcc +CFLAGS=-Wall -Wwrite-strings -Wmissing-prototypes -Wstrict-prototypes -Wpointer-arith -O2 -g diff --git a/backup/backuplib.pl b/backup/backuplib.pl new file mode 100644 index 0000000..d412c94 --- /dev/null +++ b/backup/backuplib.pl @@ -0,0 +1,92 @@ +# + +sub printdate () { + print scalar(localtime),"\n"; +} + +sub setstatus ($) { + open S, ">this-status.new" or die $!; + print S $_[0],"\n" or die $!; + close S or die $!; + rename "this-status.new","this-status" or die $!; +} + +sub startprocess ($$$) { + my ($i,$o,$c) = @_; + print LOG " $c\n" or die $!; + print " $c\n" or die $!; + defined($p= fork) or die $!; + if ($p) { $processes{$p}= $c; return; } + open STDIN,"$i" or die "$c stdin $i: $!"; + open STDOUT,"$o" or die "$c stdout $o: $!"; + &closepipes; + exec $c; die "$c: $!"; +} + +sub endprocesses () { + while (keys %processes) { + $p= waitpid(-1,0) or die "wait: $!"; + if (!exists $processes{$p}) { warn "unknown pid exited: $p, code $?\n"; next; } + $c= $processes{$p}; + delete $processes{$p}; + $? && die "error: command gave code $?: $c\n"; + } + print LOG " ok\n" or die $!; + print " ok\n" or die $!; +} + +sub killprocesses { + for $p (keys %processes) { + kill 15,$p or warn "kill process $p: $!"; + } + undef %processes; +} + +sub readfsys ($) { + my ($fsnm) = @_; + open F, "$etc/fsys.$fsnm" or die "Filesystems $fsnm unknown ($!).\n"; + for (;;) { + $_= or die; chomp; s/\s*$//; + last if m/^end$/; + next unless m/\S/; + next if m/^\#/; + if (m/^prefix\s+(\w+)\s+(\S.*\S)$/) { + $prefix{$1}= $2; + next; + } elsif (m/^prefix\-df\s+(\w+)\s+(\S.*\S)$/) { + $prefixdf{$1}= $2; + next; + } + push @fsys,$_; + } + close F or die $!; +} + +sub parsefsys () { + if ($tf =~ m,^(/\S*)\s+(\w+)$,) { + $atf= $1; + $tm= $2; + $prefix= ''; + stat $atf or die "stat $atf: $!"; + -d _ or die "not a dir: $atf"; + $rstr= ''; + } elsif ($tf =~ m,^(/\S*)\s+(\w+)\s+(\w+)$,) { + $atf= $1; + $tm= $2; + $prefix= $3; + defined($prefix{$prefix}) or die "prefix $prefix in $tf ?\n"; + $rstr= $prefix{$prefix}.' '; + } +} + +sub openlog () { + unlink 'log'; + $u= umask(007); + open LOG, ">log" or die $!; + umask $u; + select(LOG); $|=1; select(STDOUT); +} + +$SIG{'__DIE__'}= 'killprocesses'; + +1; diff --git a/backup/bringup b/backup/bringup new file mode 100755 index 0000000..6bcd5d5 --- /dev/null +++ b/backup/bringup @@ -0,0 +1,5 @@ +#!/bin/sh + +runlevel=`sed -ne '/^id:/ s/.*:\([0-9]\):.*/\1/p' /etc/inittab` +telinit $runlevel +chvt 11 diff --git a/backup/checkallused b/backup/checkallused new file mode 100755 index 0000000..fd613f3 --- /dev/null +++ b/backup/checkallused @@ -0,0 +1,121 @@ +#!/usr/bin/perl + +BEGIN { + $etc= '/etc/backup'; + require "$etc/settings.pl"; + require 'backuplib.pl'; +} + +$|=1; + +open X,'last-tape' or die $!; +chomp($tape= ); +close X or die $!; + +while (!defined $tapedone{$tape}) { + open X,"$etc/tape.$tape" or die "$tape $!"; + $fsg=''; $next=''; + for (;;) { + $_= or die $1; chomp; s/\s*$//; + last if m/^end$/; + next unless m/\S/; + next if m/^\#/; + if (m/^filesystems (\w+)$/) { $fsg= $1; } + elsif (m/^next (\w+)$/) { $next=$1; } + else { die "$tape $_ ?"; } + } + length $fsg or die "$tape $!"; + length $next or die "$tape $!"; + push @{$fsgdone{$fsg}}, $tape; + $tapedone{$tape}=1; + $tape= $next; +} + +for $fsg (sort keys %fsgdone) { + print "filesystem group $fsg: ".join(' ',@{$fsgdone{$fsg}}).":\n "; + @fsys= (); + readfsys($fsg); + for $tf (@fsys) { + parsefsys(); + $pstr= $prefix ne '' ? "$prefix:$atf" : $atf; + &e("dumped twice ($backed{$pstr}, $fsg): $pstr") + if defined $backed{$pstr}; + $backed{$pstr}= $fsg; + print " $pstr"; + } + print "\n"; +} + +print "incremental group:\n "; +@fsys= (); +readfsys('all'); +for $tf (@fsys) { + parsefsys(); + $pstr= $prefix ne '' ? "$prefix:$atf" : $atf; + $incrd{$pstr}= $fsg; + print " $pstr"; +} +print "\n"; + +for $pfx ('', sort keys %prefix) { + $rstr= length($pfx) ? $prefix{$pfx}.' ' : ''; + $dfstr= exists($prefixdf{$pfx}) ? $prefixdf{$pfx} : + 'df --no-sync -xiso9660 -xnfs -xproc'; + $cmd= "$rstr $dfstr"; + open X, "$cmd |" or die $!; + $_= ; m/^Filesystem/ or die "$cmd => $_ ?"; + $ppstr= length($pfx) ? $pfx : ''; + $pstr= length($pfx) ? "$pfx:" : ''; + print "mount points: $ppstr:"; + while () { + chomp; + next if m,^procfs\s,; + m,^/dev/(\S+)\s.*\s(/\S*)\s*$, or die "$_ ?"; + ($dev,$mp) = ($1,$2); + $mounted{"$pstr$mp"}="$pstr$dev"; print " $1-$2"; + if (defined($backto= $backed{"$pstr$mp"})) { + if (m,^/dev/\S+\s+\d+\s+(\d+)\s,) { + $usedkb{$backto} += $1; + } else { + $usedkb{$backto} += 0; + $unkkb{$backto} .= " + $pstr$mp"; + } + } + } + print "\n"; + $!=0; close(X); $? and die "$cmd $? $!"; +} + +foreach $fsg (keys %usedkb) { + print "filesystem group $fsg: $usedkb{$fsg} 1K-blocks$unkkb{$fsg}\n"; +} + +open Z,"$etc/expected-diffs" or die $!; +for (;;) { + $_= or die; chomp; s/\s*$//; + last if m/^end$/; + next unless m/^\S/; + next if m/^\#/; + if (s/^\!//) { + &e("expected not to be dumped, but not a mount point: $_") + unless defined($mounted{$_}); + print "filesystem expected not to be dumped: $_\n"; + delete $mounted{$_}; + } else { + &e("non-filesystem expected to be dumped is mounted: $_ on $mounted{$_}") + if defined($mounted{$_}); + $mounted{$_}= 'expected-diffs'; + print "non-filesystem expected to be dumped: $_\n"; + } +} + +for $fs (sort keys %backed) { length($mounted{$fs}) || &e("dumped ($backed{$fs}), not a mount point: $fs"); } +for $fs (sort keys %incrd) { length($mounted{$fs}) || &e("increm'd ($incrd{$fs}), not a mount point: $fs"); } +for $fs (sort keys %mounted) { length($backed{$fs}) || &e("mount point ($mounted{$fs}), not dumped: $fs"); } +for $fs (sort keys %mounted) { length($incrd{$fs}) || &e("mount point ($mounted{$fs}), not increm'd: $fs"); } + +$emsg.= "configuration ok\n" unless $e; +print STDERR $emsg; +exit($e); + +sub e { $emsg.="** @_\n"; $e=1; } diff --git a/backup/driver b/backup/driver new file mode 100755 index 0000000..5060e2f --- /dev/null +++ b/backup/driver @@ -0,0 +1,29 @@ +#!/bin/sh + +cd /var/local/backup +PATH=/usr/local/lib/backup:$PATH export PATH + +if [ "x$1" != test ]; then + stty sane + stty -isig +fi + +rm -f this-status p p2 +echo 'FAILED to start dump script' >this-status + +full 2>&1 | tee this-log + +status=`cat this-status 2>/dev/null` + +cat <); +$tapeid =~ m/[^0-9a-zA-Z]/ and die "Bad TAPEID ($&).\n"; +$tapeid =~ m/[0-9a-zA-Z]/ or die "Empty TAPEID.\n"; +close T; + +setstatus "FAILED at tape identity check"; + +if (open L, "last-tape") { + chomp($lasttape= ); + close L; +} else { + undef $lasttape; +} + +die "Tape $tapeid same as last time.\n" if $tapeid eq $lasttape; + +undef $fsys; +open D, "$etc/tape.$tapeid" or die "Unknown tape $tapeid ($!).\n"; +for (;;) { + $_= or die; chomp; s/\s+$//; + last if m/^end$/; + next unless m/\S/; + next if m/^\#/; + if (m/^filesystems (\w+)$/) { + $fsys= $1; + } elsif (m/^next (\w+)$/) { + $next= $1; + } elsif (m/^incremental$/) { + $incremental= 1; + } else { + die "unknown entry in tape $tapeid at line $.: $_\n"; + } +} +close D or die $!; + +if ($incremental) { + die "incremental tape $tapeid has next or filesystems\n" + if defined($next) || defined($fsys); + print STDERR "Incremental tape $tapeid.\n\n"; + setstatus "FAILED during incremental startup"; + exec "increm $tapeid"; + die $!; +} + +readfsys("$fsys"); +openlog(); + +$doing= "dump of $fsys to tape $tapeid in drive $tape"; +print LOG "$doing:\n" or die $!; + +system "mt -f $tape rewind"; $? and die $?; +system "mt -f $tape retension"; $? and die $?; + +open T, ">TAPEID" or die $!; +print T "$tapeid\n" or die $!; +close T or die $!; + +system "tar -b$blocksize -vvcf TAPEID.tar TAPEID"; $? and die $?; +system "dd if=TAPEID.tar of=$ntape bs=${blocksize}b count=10"; $? and die $?; + +unlink 'this-md5sums'; + +print "Doing $doing ...\n" or die $!; + +unlink 'p'; +system 'mknod p p'; $? and die $?; + +setstatus "FAILED during dump"; + +sub closepipes () { + close(DUMPOR); close(TEEOR); close(BUFOR); close(FINDOR); + close(DUMPOW); close(TEEOW); close(BUFOW); close(FINDOW); +} + +for $tf (@fsys) { + printdate(); + pipe(FINDOR,FINDOW) or die $!; + pipe(DUMPOR,DUMPOW) or die $!; + pipe(TEEOR,TEEOW) or die $!; + pipe(BUFOR,BUFOW) or die $!; + parsefsys(); + if ($tm eq 'dump') { + $dumpcmd= "dump 0bfu $softblocksizekb - $atf"; + $dumpin= '&FINDOW',$rstr."find $atf -xdev -noleaf -print0"; + $dumpcmd= "cpio -Hustar -o0C$softblocksizebytes"; + $dumpin= '<&FINDOR'; + } + startprocess '>this-md5sums','md5sum'; + startprocess $dumpin,'>&DUMPOW',$rstr.$dumpcmd; + startprocess '<&DUMPOR','>&TEEOW','tee p'; + startprocess '<&TEEOR','>&BUFOW','writebuffer'; + startprocess '<&BUFOR','>/dev/null' + ,"dd ibs=$softblocksizebytes obs=$blocksizebytes of=$ntape"; + closepipes(); + endprocesses(); +} + +setstatus "FAILED during check"; + +system "mt -f $tape rewind"; $? and die $?; +system "mt -f $ntape fsf 1"; $? and die $?; + +open S,"this-md5sums" or die $!; +for $tf (@fsys) { + printdate(); + chomp($orgsum= ); + $orgsum =~ m/^[0-9a-fA-F]{32}$/i or die "orgsum \`$orgsum' ?"; + chomp($csum= `readbuffer <$ntape | md5sum`); + $orgsum eq $csum or die "MISMATCH $tf $csum $orgsum\n"; + print "checksum ok $csum\t$tf\n" or die $!; + print LOG "checksum ok $csum\t$tf\n" or die $!; +} +printdate(); +system "mt -f $tape rewind"; $? and die $?; + +setstatus "FAILED during cleanup"; + +open IAN,">increm-advance.new" or die $!; +print IAN "1\n" or die $!; +close IAN or die $!; + +open TN,">next-full.new" or die $!; +print TN "$next\n" or die $!; +close TN or die $!; + +unlink 'last-tape','next-full'; +rename 'TAPEID','last-tape' or die $!; +rename 'this-md5sums',"md5sums.$fsys" or die $!; +rename 'log',"log.$fsys" or die $!; +rename 'next-full.new',"next-full" or die $!; +rename 'increm-advance.new',"increm-advance" or die $!; + +print "$doing completed.\nNext dump tape is $next.\n" or die $!; + +setstatus "Successful ($tapeid $fsys, next $next)"; +exit 0; diff --git a/backup/increm b/backup/increm new file mode 100755 index 0000000..e4ebbf7 --- /dev/null +++ b/backup/increm @@ -0,0 +1,84 @@ +#!/usr/bin/perl + +BEGIN { + $etc= '/etc/backup'; + require "$etc/settings.pl"; + require 'backuplib.pl'; +} + +$|=1; + +@ARGV==1 or die; +$tapeid= $ARGV[0]; + +print "Running incremental (tape $tapeid) ...\n" or die $!; + +open T,"$etc/tape.$tapeid" or die "Tape $tapeid not found: $!\n"; +close T; + +open NF,"next-full" or die $!; +chomp($next= ); +close NF or die $!; + +setstatus "FAILED during incremental"; + +open A,"increm-advance" or die $!; +chomp($advance= ); +close A or die $!; + +$advance =~ m/^\d+$/ or die "$advance ?"; + +system "mt -f $tape rewind"; $? and die $?; +system "mt -f $tape retension"; $? and die $?; + +if ($advance == 1) { + open TI,">TAPEID" or die $!; + print TI "$tapeid" or die $!; + close TI or die $!; + + system "tar -b$blocksize -vvcf TAPEID.tar TAPEID"; $? and die $?; + system "dd if=TAPEID.tar of=$ntape bs=${blocksize}b count=10"; $? and die $?; +} else { + system "mt -f $ntape fsf $advance"; $? and die $?; +} + +readfsys('all'); +openlog(); + +sub closepipes () { + close(DUMPOR); close(BUFOR); + close(DUMPOW); close(BUFOW); +} + +setstatus "PROBLEMS during incremental dump"; + +for $tf (@fsys) { + pipe(DUMPOR,DUMPOW) or die $!; + pipe(BUFOR,BUFOW) or die $!; + parsefsys(); + if ($tm ne 'dump') { + print "Not dumping $atf ($prefix) - not \`dump'.\n" or die $!; + print LOG "Not dumping $atf ($prefix) - not \`dump'.\n" or die $!; + next; + } + startprocess '&DUMPOW',$rstr."dump 1bfu $softblocksizekb - $atf"; + startprocess '<&DUMPOR','>&BUFOW','writebuffer'; + startprocess '<&BUFOR','>/dev/null' + ,"dd ibs=$softblocksizebytes obs=$blocksizebytes of=$ntape"; + closepipes(); + endprocesses(); + $advance++; +} + +system "mt -f $tape rewind"; $? and die $?; + +open IAN,">increm-advance.new" or die $!; +print IAN "$advance\n" or die $!; +close IAN or die $!; +rename 'increm-advance.new','increm-advance' or die $!; + +print LOG "Next FULL dump tape is $next\n" or die $!; +print "Next FULL dump tape is $next\n" or die $!; + +setstatus "INCREMENTAL successful (next full is $next)"; +exit 0; diff --git a/backup/junk b/backup/junk new file mode 100644 index 0000000..92769e4 --- /dev/null +++ b/backup/junk @@ -0,0 +1,34 @@ + + +timestamp () { + echo "Checking timestamp of last full dump of $1;" + if ! test lfull.$which -ot lfull.$1 + then + which=$1 + fi +} + +ok=1 + +for dsk in `cat allincs` +do + which='.' + . inc.$dsk + if test -f "lfull.$which" + then + echo "Using timestamp of last full dump of $which." + else + echo >&2 "No full dump of $which done yet." + exit 1 + fi + + since="`cat lfull.$which`" + doing="incremental of $filesys to $device + files changed since dump of $which at `cat lfull.$which`" + + rm -f log + (umask 007; >log) + + echo Doing "$doing" ... + + diff --git a/backup/loaded b/backup/loaded new file mode 100755 index 0000000..7a8335f --- /dev/null +++ b/backup/loaded @@ -0,0 +1,15 @@ +#!/bin/sh +# +# State that we have loaded a tape + +set -e +cd /var/local/backup + +if test -f "/etc/backup/tape.$1" +then + echo "$1" >really-TAPEID + echo "Will assume tape is $1 unless I discover otherwise." +else + echo "Will only use tape if it has a TAPEID." + rm -f really-TAPEID +fi diff --git a/backup/old-increm b/backup/old-increm new file mode 100755 index 0000000..b036b89 --- /dev/null +++ b/backup/old-increm @@ -0,0 +1,58 @@ +#!/bin/sh + +set -e +false +dir=/var/local/backup +device=/dev/sda4 +blocksize=2048 +filesystems=all + +cd $dir +PATH=/usr/local/lib/backup:$PATH export PATH + +echo "FAILED during startup of incremental" >this-status + +timestamp='.' +for tsfs in `cat all-fsys-n` +do + echo "Checking timestamp of last full dump of $tsfs;" + if ! test "lfull.$timestamp" -ot "lfull.$tsfs" + then + timestamp="$tsfs" + fi +done + +if test -f "lfull.$timestamp" +then + echo "Using timestamp of last full dump of $timestamp." +else + echo >&2 "No full dump of $timestamp done yet." + exit 1 +fi + +rm -f this-fulldump +since="`cat lfull.$timestamp`" +doing="incremental since dump of $timestamp at `cat lfull.$timestamp` to $device" + +>increm-log +chmod 660 increm-log + +echo Doing "$doing" ... +echo "$doing": >>increm-log +cat fsys.all +echo "tar -lvvc \"-N$since\" -T$dir/fsys.all -f - \\" +echo " 2>>increm-log | dd of=$device bs=${blocksize}b" +echo "FAILED during incremental" >this-status +cd / +tar -lvvc "-N$since" -T$dir/fsys.all -f - 2>>$dir/increm-log \ + | dd of=$device bs=${blocksize}b +cd $dir + +echo "FAILED during cleanup" >this-status + +test -f this-fulldump && mv this-fulldump "lfull.$filesystems" +echo "$doing" completed. + +echo "Next dump tape to use would be `cat next-full`". + +echo "INCREMENTAL successful" >this-status diff --git a/backup/readbuffer b/backup/readbuffer new file mode 100755 index 0000000000000000000000000000000000000000..7b867265120e0ec5590d7f9ce889017195689214 GIT binary patch literal 20766 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 Uv-|O%XY(py2exQy{fgZG0 +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER 16*1024*1024 +#define WAITEMPTY ((BUFFER*1)/4) + +static inline int min(int a, int b) { return a<=b ? a : b; } + +static void nonblock(int fd) { + int r; + r= fcntl(fd,F_GETFL,0); if (r == -1) { perror("fcntl getfl"); exit(1); } + r |= O_NDELAY; + if (fcntl(fd,F_SETFL,r) == -1) { perror("fcntl setfl"); exit(1); } +} + +int main(int argc, const char *const *argv) { + static unsigned char buf[BUFFER]; + + unsigned char *wp, *rp; + int used,r,reading,seeneof; + fd_set readfds; + fd_set writefds; + + used=0; wp=rp=buf; reading=1; seeneof=0; + nonblock(0); nonblock(1); + if (argv[1] && !strcmp(argv[1],"--mlock")) { + if (mlock(buf,sizeof(buf))) { perror("mlock"); exit(1); } + argv++; argc--; + } + if (argv[1]) { fputs("usage: readbuffer [--mlock]\n",stderr); exit(1); } + while (!seeneof || used) { + FD_ZERO(&readfds); + if (reading) { + if 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 EKdiF;aR2}S literal 0 HcmV?d00001 diff --git a/backup/writebuffer.c b/backup/writebuffer.c new file mode 100644 index 0000000..c4fa9e7 --- /dev/null +++ b/backup/writebuffer.c @@ -0,0 +1,81 @@ +/**/ + +#include +#include +#include +#include +#include +#include + +#define BUFFER 16*1024*1024 +#define WAITFILL ((BUFFER*3)/4) + +static inline int min(int a, int b) { return a<=b ? a : b; } + +static void nonblock(int fd) { + int r; + r= fcntl(fd,F_GETFL,0); if (r == -1) { perror("fcntl getfl"); exit(1); } + r |= O_NDELAY; + if (fcntl(fd,F_SETFL,r) == -1) { perror("fcntl setfl"); exit(1); } +} + +int main(void) { + static unsigned char buf[BUFFER]; + + unsigned char *wp, *rp; + int used,r,writing,seeneof; + fd_set readfds; + fd_set writefds; + + used=0; wp=rp=buf; writing=0; seeneof=0; + nonblock(0); nonblock(1); + while (!seeneof || used) { + FD_ZERO(&readfds); if (!seeneof && used+1 WAITFILL) writing=1; + } + if (FD_ISSET(1,&writefds) && used) { + r= write(1,wp,min(used,buf+BUFFER-wp)); + if (r<=0) { + if (!(errno == EAGAIN || errno == EINTR)) { perror("write"); exit(1); } +/*fprintf(stderr,"\t write transient error\n");*/ + } else { +/*fprintf(stderr,"\t wrote %d\n",r);*/ + used-= r; + wp+= r; + if (wp == buf+BUFFER) wp=buf; + } + } + } + exit(0); +} -- 2.30.2