/[BackupPC]/upstream/2.1.0/bin/BackupPC_link
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/2.1.0/bin/BackupPC_link

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Wed Jun 22 19:12:04 2005 UTC (17 years ago) by dpavlin
File size: 7917 byte(s)
import of version 2.1.0

1 #!/bin/perl
2 #============================================================= -*-perl-*-
3 #
4 # BackupPC_link: link new backup into pool
5 #
6 # DESCRIPTION
7 #
8 # BackupPC_link inspects every file in a new backup and
9 # checks if an existing file from any previous backup is
10 # identical. If so, the file is removed and replaced by
11 # a hardlink to the existing file. If the file is new,
12 # a hardlink to the file is made in the pool area, so that
13 # this file is available for checking against future backups.
14 #
15 # Then, for incremental backups, hardlinks are made in the
16 # backup directories to all files that were not extracted during
17 # the incremental backups. The means the incremental dump looks
18 # like a complete image of the PC.
19 #
20 # AUTHOR
21 # Craig Barratt <cbarratt@users.sourceforge.net>
22 #
23 # COPYRIGHT
24 # Copyright (C) 2001-2003 Craig Barratt
25 #
26 # This program is free software; you can redistribute it and/or modify
27 # it under the terms of the GNU General Public License as published by
28 # the Free Software Foundation; either version 2 of the License, or
29 # (at your option) any later version.
30 #
31 # This program is distributed in the hope that it will be useful,
32 # but WITHOUT ANY WARRANTY; without even the implied warranty of
33 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 # GNU General Public License for more details.
35 #
36 # You should have received a copy of the GNU General Public License
37 # along with this program; if not, write to the Free Software
38 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 #
40 #========================================================================
41 #
42 # Version 2.1.0, released 20 Jun 2004.
43 #
44 # See http://backuppc.sourceforge.net.
45 #
46 #========================================================================
47
48 use strict;
49 no utf8;
50 use lib "__INSTALLDIR__/lib";
51 use BackupPC::Lib;
52 use BackupPC::Attrib;
53 use BackupPC::PoolWrite;
54
55 use File::Find;
56 use File::Path;
57 use Digest::MD5;
58
59 ###########################################################################
60 # Initialize
61 ###########################################################################
62
63 die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
64 my $TopDir = $bpc->TopDir();
65 my $BinDir = $bpc->BinDir();
66 my %Conf = $bpc->Conf();
67
68 $bpc->ChildInit();
69
70 if ( @ARGV != 1 ) {
71 print("usage: $0 <host>\n");
72 exit(1);
73 }
74 if ( $ARGV[0] !~ /^([\w\.\s-]+)$/ ) {
75 print("$0: bad host name '$ARGV[0]'\n");
76 exit(1);
77 }
78 my $host = $1;
79 my $Dir = "$TopDir/pc/$host";
80 my($CurrDumpDir, $Compress);
81
82 #
83 # Re-read config file, so we can include the PC-specific config
84 #
85 $bpc->ConfigRead($host);
86 %Conf = $bpc->Conf();
87
88 ###########################################################################
89 # Process any backups that haven't been linked
90 ###########################################################################
91 my $md5 = Digest::MD5->new;
92 my($nFilesNew, $sizeNew, $sizeNewComp);
93 my($nFilesExist, $sizeExist, $sizeExistComp);
94 while ( 1 ) {
95 my @Backups = $bpc->BackupInfoRead($host);
96 $nFilesNew = $sizeNew = $sizeNewComp = 0;
97 $nFilesExist = $sizeExist = $sizeExistComp = 0;
98 my($num);
99 for ( $num = 0 ; $num < @Backups ; $num++ ) {
100 last if ( $Backups[$num]{nFilesNew} eq ""
101 || -f "$Dir/NewFileList.$Backups[$num]{num}" );
102 }
103 last if ( $num >= @Backups );
104 #
105 # Process list of new files left by BackupPC_dump
106 #
107 $CurrDumpDir = "$Dir/$Backups[$num]{num}";
108 $Compress = $Backups[$num]{compress};
109 if ( open(NEW, "<", "$Dir/NewFileList.$Backups[$num]{num}") ) {
110 binmode(NEW);
111 while ( <NEW> ) {
112 chomp;
113 next if ( !/(\w+) (\d+) (.*)/ );
114 LinkNewFile($1, $2, "$CurrDumpDir/$3");
115 }
116 close(NEW);
117 }
118 unlink("$Dir/NewFileList.$Backups[$num]{num}")
119 if ( -f "$Dir/NewFileList.$Backups[$num]{num}" );
120
121 #
122 # See if we should fill in this dump. We only need to fill
123 # in incremental dumps. We can only fill in the incremental
124 # dump if there is an existing filled in dump with the same
125 # type of compression (on or off). Eg, we can't fill in
126 # a compressed incremental if the most recent filled in dump
127 # is not compressed.
128 #
129 my $noFill = 1;
130 my $fillFromNum;
131 if ( $Backups[$num]{type} ne "incr" ) {
132 $noFill = 0
133 } elsif ( $Conf{IncrFill} ) {
134 my $i;
135 for ( $i = $num - 1 ; $i >= 0 ; $i-- ) {
136 last if ( !$Backups[$i]{noFill}
137 && ($Backups[$i]{compress} ? 1 : 0)
138 == ($Compress ? 1 : 0) );
139 }
140 my $prevDump = "$Dir/$Backups[$i]{num}";
141 if ( $i >= 0 && -d $prevDump ) {
142 find({wanted => \&FillIncr, no_chdir => 1}, $prevDump);
143 $noFill = 0;
144 $fillFromNum = $Backups[$i]{num};
145 }
146 }
147 #
148 # Update the backup info file in $TopDir/pc/$host/backups
149 #
150 @Backups = $bpc->BackupInfoRead($host);
151 $Backups[$num]{nFilesExist} += $nFilesExist;
152 $Backups[$num]{sizeExist} += $sizeExist;
153 $Backups[$num]{sizeExistComp} += $sizeExistComp;
154 $Backups[$num]{nFilesNew} += $nFilesNew;
155 $Backups[$num]{sizeNew} += $sizeNew;
156 $Backups[$num]{sizeNewComp} += $sizeNewComp;
157 $Backups[$num]{noFill} = $noFill;
158 $Backups[$num]{fillFromNum} = $fillFromNum;
159 $bpc->BackupInfoWrite($host, @Backups);
160 }
161
162 ###########################################################################
163 # Subroutines
164 ###########################################################################
165
166 #
167 # Fill in an incremental dump by making hardlinks to the previous
168 # dump.
169 #
170 sub FillIncr
171 {
172 my($name) = $File::Find::name;
173 my($newName);
174
175 $name = $1 if ( $name =~ /(.*)/ );
176 return if ( $name !~ m{\Q$Dir\E/(\d+)/(.*)} );
177 $newName = "$CurrDumpDir/$2";
178 if ( -d $name && -d $newName ) {
179 #
180 # Merge the file attributes.
181 #
182 my $newAttr = BackupPC::Attrib->new({ compress => $Compress });
183 my $attr = BackupPC::Attrib->new({ compress => $Compress });
184 $newAttr->read($newName) if ( -f $newAttr->fileName($newName) );
185 $attr->read($name) if ( -f $attr->fileName($name) );
186 $newAttr->merge($attr);
187 #
188 # Now write it out, adding a link to the pool if necessary
189 #
190 my $data = $newAttr->writeData;
191 my $origSize = length($data);
192 my $fileName = $newAttr->fileName($newName);
193 my $poolWrite = BackupPC::PoolWrite->new($bpc, $fileName,
194 length($data), $Compress);
195 $poolWrite->write(\$data);
196 my($exists, $digest, $outSize, $errs) = $poolWrite->close;
197 if ( @$errs ) {
198 print("log ", join("", @$errs));
199 }
200 if ( $exists ) {
201 $nFilesExist++;
202 $sizeExist += $origSize;
203 $sizeExistComp += $outSize;
204 } elsif ( $outSize > 0 ) {
205 $nFilesNew++;
206 $sizeNew += $origSize;
207 $sizeNewComp += -s $outSize;
208 LinkNewFile($digest, $origSize, $fileName);
209 }
210 } elsif ( -f $name && !-f $newName ) {
211 #
212 # Exists in the older filled backup, and not in the new, so link it
213 #
214 link($name, $newName);
215 }
216 }
217
218 #
219 # Add a link in the pool to a new file
220 #
221 sub LinkNewFile
222 {
223 my($d, $size, $fileName) = @_;
224 my $res = $bpc->MakeFileLink($fileName, $d, 1, $Compress);
225 if ( $res == 1 ) {
226 $nFilesExist++;
227 $sizeExist += $size;
228 $sizeExistComp += -s $fileName;
229 } elsif ( $res == 2 ) {
230 $nFilesNew++;
231 $sizeNew += $size;
232 $sizeNewComp += -s $fileName;
233 } elsif ( $res != 0 && $res != -1 ) {
234 print("log BackupPC_link got error $res when calling"
235 . " MakeFileLink($fileName, $d, 1)\n");
236 }
237 }

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.26