chiark / gitweb /
Portability fix: Fix on libcs where st_mtime is not a macro (ie, ones lacking st_mtim.)
[chiark-utils.git] / backup / increm
1 #!/usr/bin/perl
2 # increm
3 # Do an incremental backup; ONLY for invocation by full !
4 #
5 # This file is part of chiark backup, a system for backing up GNU/Linux and
6 # other UN*X-compatible machines, as used on chiark.greenend.org.uk.
7 #
8 # chiark backup is:
9 #  Copyright (C) 1997-1998,2000-2001,2007
10 #                     Ian Jackson <ian@chiark.greenend.org.uk>
11 #  Copyright (C) 1999 Peter Maydell <pmaydell@chiark.greenend.org.uk>
12 #
13 # This is free software; you can redistribute it and/or modify it under the
14 # terms of the GNU General Public License as published by the Free Software
15 # Foundation; either version 3, or (at your option) any later version.
16 #
17 # This is distributed in the hope that it will be useful, but WITHOUT ANY
18 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
20 # details.
21 #
22 # You should have received a copy of the GNU General Public License along
23 # with this program; if not, consult the Free Software Foundation's
24 # website at www.fsf.org, or the GNU Project website at www.gnu.org.
25
26 # We are invoked by full if the tape description file says that it is
27 # for an incremental backup.  We expect two commandline argument which
28 # is the ID string of the tape to use, and the description (which
29 # includes ID and function).
30
31 BEGIN {
32     $etc= '/etc/chiark-backup';
33     require "$etc/settings.pl";
34     require 'backuplib.pl';
35 }
36
37 $|=1;
38
39 @ARGV==2 or die;
40 ($tapeid,$tapedesc)= @ARGV;
41
42 print "Running incremental onto $tapedesc ...\n" or die $!;
43
44 # Just check that we weren't passed a bogus ID (the tape description
45 # file for incrementals is just 'incremental\nend\n')
46 open T,"$etc/tape.$tapeid" or die "Tape $tapeid not found: $!\n";
47 close T;
48
49 # This is only used for the 'next FULL backup is X' message at the end.
50 open NF,"next-full" or die $!;
51 chomp($next= <NF>);
52 close NF or die $!;
53
54 setstatus "FAILED during incremental";
55
56 # Read the number of the incremental involved
57 # (ie, (how many files are already on the tape) - 1)
58 open A,"increm-advance" or die $!;
59 chomp($advance= <A>);
60 close A or die $!;
61
62 # better be a decimal number
63 $advance =~ m/^\d+$/ or die "$advance ?";
64
65 # Get a list of all filesystems
66 readfsys('all');
67 openlog();
68
69 # Rewind the tape and if we are the first incremental on the tape then
70 # write the TAPEID record, otherwise skip forward to the correct point.
71 # (full will already have checked that this is the right tape before
72 # it invoked us, so no need to read the existing TAPEID record first.)
73 runsystem("mt -f $ntape rewind");
74 if ($advance == 1) {
75     writetapeid($tapeid,$tapedesc);
76 } else {
77     runsystem("mt -f $ntape fsf $advance");
78     $currenttapefilenumber= $advance;
79 }
80
81 sub closepipes () {
82     close(DUMPOR); close(BUFOR);
83     close(DUMPOW); close(BUFOW);
84     close(GZOR); close(GZOW);
85 }
86
87 setstatus "PROBLEMS during incremental dump";
88
89 for $tf (@fsys) {
90
91     parsefsys();
92     prepfsys();
93     
94     $bufir='DUMPOR';
95     $ddcmd= "$nasty dd ibs=$softblocksizebytes obs=$blocksizebytes of=$ntape";
96
97     pipe(DUMPOR,DUMPOW) or die $!;
98     pipe(BUFOR,BUFOW) or die $!;
99
100     $gz= $gzi if length $gzi;
101     if ($gz) {
102         $bufir='GZOR';
103         pipe(GZOR,GZOW) or die $!;
104         $ddcmd .= " conv=sync";
105     }
106
107     if ($dopt{'noinc'}) {
108         pboth("Incrementals of $atf_print ($prefix) suppressed in config.\n");
109     }
110
111     if ($tm eq 'dump') {
112         $dumplabel= $pcstr.$atf_print.'$';
113         $dumpcmd= "dump 1Lbfu $dumplabel $softblocksizekb - $atf";
114     } elsif ($tm eq 'gtar') {
115         $dumpcmd= "tar NCcfl $fsidfile $atf - .";
116     } else {
117         pboth("Not dumping $atf_print ($prefix) - not supported.\n");
118         next;
119     }
120
121     nexttapefile("inc $prefix:$atf_print");
122     
123     # Same trick as full uses to do a pipeline whilst keeping track
124     # of all exit statuses:
125     #   dump </dev/null | writebuffer | dd >/dev/null
126     startprocess '</dev/null','>&DUMPOW',"$nice ".$rstr.$dumpcmd;
127     if ($gz) {
128         startprocess '<&DUMPOR','>&GZOW',"$nice gzip -v$gz";
129     }
130     startprocess "<&$bufir",'>&BUFOW',"$nasty writebuffer";
131     startprocess '<&BUFOR','>/dev/null',"$nasty $ddcmd";
132     closepipes();
133     endprocesses();
134     # advance is a file counter, so it needs to be updated for each 
135     # dump we do to tape.
136     $advance++;
137
138     finfsys();
139 }
140
141 # Rewind the tape, and increment the counter of incremental backups.
142 runsystem("mt -f $tape rewind");
143 open IAN,">increm-advance.new" or die $!;
144 print IAN "$advance\n" or die $!;
145 close IAN or die $!;
146 rename 'increm-advance.new','increm-advance' or die $!;
147
148 pboth("Next FULL dump tape is $next\n");
149
150 setstatus "INCREMENTAL successful: $tapedesc, next full is $next";
151 exit 0;