1 |
wellsi |
1.1 |
diff -urN e-smith-backup-2.4.0.old/root/usr/share/perl5/vendor_perl/esmith/BlockDevices.pm e-smith-backup-2.4.0/root/usr/share/perl5/vendor_perl/esmith/BlockDevices.pm |
2 |
|
|
--- e-smith-backup-2.4.0.old/root/usr/share/perl5/vendor_perl/esmith/BlockDevices.pm 1969-12-31 16:00:00.000000000 -0800 |
3 |
|
|
+++ e-smith-backup-2.4.0/root/usr/share/perl5/vendor_perl/esmith/BlockDevices.pm 2016-01-09 16:32:40.000000000 -0800 |
4 |
|
|
@@ -0,0 +1,503 @@ |
5 |
|
|
+#---------------------------------------------------------------------- |
6 |
|
|
+# Copyright 2015 Ian Wells |
7 |
|
|
+# This program is free software; you can redistribute it and/or |
8 |
|
|
+# modify it under the same terms as Perl itself. |
9 |
|
|
+#---------------------------------------------------------------------- |
10 |
|
|
+ |
11 |
|
|
+package esmith::BlockDevices; |
12 |
|
|
+ |
13 |
|
|
+use strict; |
14 |
|
|
+use warnings; |
15 |
|
|
+use English '-no_match_vars'; |
16 |
|
|
+use Carp; |
17 |
|
|
+use File::Path qw(make_path remove_tree); |
18 |
|
|
+use POSIX qw(:sys_wait_h strftime); |
19 |
|
|
+use Locale::gettext; |
20 |
|
|
+use File::stat; |
21 |
|
|
+use v5.10.1; |
22 |
|
|
+use Taint::Util; |
23 |
|
|
+use Readonly; |
24 |
|
|
+use File::Find; |
25 |
|
|
+ |
26 |
|
|
+use vars qw($VERSION @ISA @EXPORT_OK); |
27 |
|
|
+ |
28 |
|
|
+@ISA = qw(Exporter); |
29 |
|
|
+ |
30 |
|
|
+=head1 NAME |
31 |
|
|
+ |
32 |
|
|
+esmith::BlockDevices - Module to handle block devices |
33 |
|
|
+ |
34 |
|
|
+=head1 SYNOPSIS |
35 |
|
|
+ |
36 |
|
|
+ use esmith::BlockDevices; |
37 |
|
|
+ my $devices = BlockDevices->new (); |
38 |
|
|
+ |
39 |
|
|
+=head1 DESCRIPTION |
40 |
|
|
+ |
41 |
|
|
+This module provides an abstracted interface to the |
42 |
|
|
+block devices used for backup/restore |
43 |
|
|
+ |
44 |
|
|
+=cut |
45 |
|
|
+ |
46 |
|
|
+my $EMPTY = q{}; |
47 |
|
|
+ |
48 |
|
|
+sub new |
49 |
|
|
+{ |
50 |
|
|
+ my $class = shift; |
51 |
|
|
+ my $self = { |
52 |
|
|
+ _blox => $EMPTY, |
53 |
|
|
+ mount => $EMPTY, |
54 |
|
|
+ _fstype => $EMPTY, |
55 |
|
|
+ allowmount => $EMPTY, |
56 |
|
|
+ @_, |
57 |
|
|
+ }; |
58 |
|
|
+ bless $self, $class; |
59 |
|
|
+ return $self; |
60 |
|
|
+} |
61 |
|
|
+ |
62 |
|
|
+sub lsblk |
63 |
|
|
+{ |
64 |
|
|
+#ToDo add some comments |
65 |
|
|
+ my %blox; # a hash to hold the device information |
66 |
|
|
+ |
67 |
|
|
+ my $short = qx(/bin/lsblk -sdn -o KNAME); |
68 |
|
|
+ my @long = qx(/bin/lsblk -P -b -o KNAME,MAJ:MIN,RM,RO,TYPE,MOUNTPOINT,FSTYPE,LABEL,UUID,MODEL,SIZE,STATE,MODE,OWNER,GROUP); |
69 |
|
|
+ # Not all of this information may be needed currently, but it does not affect the processing time |
70 |
|
|
+ untaint ($short); |
71 |
|
|
+ untaint (@long); |
72 |
|
|
+ |
73 |
|
|
+ my $devicemodel= $EMPTY; |
74 |
|
|
+ |
75 |
|
|
+ for (@long) |
76 |
|
|
+ { |
77 |
|
|
+ my @line = split /\"\s/s; |
78 |
|
|
+ my $name; |
79 |
|
|
+ if ($line[0] =~ /KNAME=\"(.*)/s) |
80 |
|
|
+ { |
81 |
|
|
+ $name = $1; |
82 |
|
|
+ } |
83 |
|
|
+ else {carp 'Could not match KNAME'; last;} # should never occur. |
84 |
|
|
+ |
85 |
|
|
+ $blox{$name}{tip} = ($short =~ m/^$name$/sm) ? 1 : 0; |
86 |
|
|
+ |
87 |
|
|
+ for (@line) |
88 |
|
|
+ { |
89 |
|
|
+ my ($key,$value) = split /=/s; |
90 |
|
|
+ $value =~ s/\"//sg; |
91 |
|
|
+ $blox{$name}{$key} = trim($value); |
92 |
|
|
+ } |
93 |
|
|
+ if ($blox{$name}{TYPE} =~ /rom|disk/s) |
94 |
|
|
+ { |
95 |
|
|
+ $devicemodel = $blox{$name}{MODEL}; |
96 |
|
|
+ } |
97 |
|
|
+ else |
98 |
|
|
+ { |
99 |
|
|
+ $blox{$name}{MODEL} = trim($devicemodel); |
100 |
|
|
+ } |
101 |
|
|
+ $blox{$name}{SIZEH} = scaleIt($blox{$name}{SIZE}); |
102 |
|
|
+ } |
103 |
|
|
+ return \%blox; |
104 |
|
|
+} |
105 |
|
|
+ |
106 |
|
|
+sub findValidFS |
107 |
|
|
+{ |
108 |
|
|
+# Find all filesystem types that are supported |
109 |
|
|
+ my %fs; # a hash to hold the supported filesystem type information |
110 |
|
|
+ |
111 |
|
|
+ my @cmd = `cat /proc/filesystems`; |
112 |
|
|
+ foreach (@cmd) |
113 |
|
|
+ { |
114 |
|
|
+ if (/.*\/(.*?)\.ko/s){$fs {$1}=$1;} |
115 |
|
|
+ } |
116 |
|
|
+ @cmd = `ls -1 /lib/modules/\$(uname -r)/kernel/fs/*/*ko`; |
117 |
|
|
+ foreach (@cmd) |
118 |
|
|
+ { |
119 |
|
|
+ if (/.*\/(.*?)\.ko/s){$fs {$1}=$1;} |
120 |
|
|
+ } |
121 |
|
|
+ return \%fs; |
122 |
|
|
+} |
123 |
|
|
+ |
124 |
|
|
+sub scanBlocks |
125 |
|
|
+{ |
126 |
|
|
+ # Scan all the block devices |
127 |
|
|
+ # This takes some seconds on systems with many filesystems |
128 |
|
|
+ my ($self) = @_; |
129 |
|
|
+ $self->{_blox} = lsblk; |
130 |
|
|
+ $self->{_fstype} = findValidFS; |
131 |
|
|
+ return; |
132 |
|
|
+} |
133 |
|
|
+ |
134 |
|
|
+sub list |
135 |
|
|
+{ |
136 |
|
|
+ my ($self) = @_; |
137 |
|
|
+ my @dirs=(); |
138 |
|
|
+ my $hashref = $self->{_blox}; |
139 |
|
|
+ |
140 |
|
|
+ foreach my $drive (keys %{$hashref}) |
141 |
|
|
+ { |
142 |
|
|
+ push @dirs, $drive; |
143 |
|
|
+ } |
144 |
|
|
+ |
145 |
|
|
+ return @dirs; |
146 |
|
|
+} |
147 |
|
|
+ |
148 |
|
|
+sub checkBackupDriveSize |
149 |
|
|
+{ |
150 |
|
|
+ my ($self,$drive, $size) = @_; |
151 |
|
|
+ my $hashref = $self->{_blox}; |
152 |
|
|
+ my $sz = $EMPTY; |
153 |
|
|
+ my $mntdir = $self->{mount}; |
154 |
|
|
+ Readonly my $VFAT_LIMIT => 2147483648; |
155 |
|
|
+ Readonly my $KBYTE => 1024; |
156 |
|
|
+ |
157 |
|
|
+ # size > drive size |
158 |
|
|
+ if ($size > $hashref->{$drive}{SIZE}) |
159 |
|
|
+ { |
160 |
|
|
+ return 1; # filesystem too small |
161 |
|
|
+ } |
162 |
|
|
+ |
163 |
|
|
+ # FAT32 drive and size > 2G |
164 |
|
|
+ if (($size > $VFAT_LIMIT) && ($hashref->{$drive}{FSTYPE} eq 'vfat')) |
165 |
|
|
+ { |
166 |
|
|
+ return 2; # filesystem vfat limit |
167 |
|
|
+ } |
168 |
|
|
+ |
169 |
|
|
+#ToDo add a check here to see if mounting is allowed by db value |
170 |
|
|
+ |
171 |
|
|
+ # check mount and find actual size |
172 |
|
|
+ if ($self->mountable ($drive)) # Only check filesystems that appear mountable |
173 |
|
|
+ { |
174 |
|
|
+ $self->mount ($drive); |
175 |
|
|
+ my $filesize = -s "$mntdir/smeserver.tgz"; |
176 |
|
|
+ |
177 |
|
|
+ # Check free disk space |
178 |
|
|
+ my $df = qx(/bin/df -P \"$mntdir\"); |
179 |
|
|
+ if ($df =~ /(\S+)\s+(\S+)\s+(\S+)\s+(\d*%)/s) |
180 |
|
|
+ { |
181 |
|
|
+ my $dsize = ($3 * $KBYTE) + ($filesize //= 0); |
182 |
|
|
+ if ($size > $dsize) # not enough space |
183 |
|
|
+ { |
184 |
|
|
+ $sz = 3; # filesystem has too little free space |
185 |
|
|
+ } |
186 |
|
|
+ } |
187 |
|
|
+ else # fail (never seen in testing) |
188 |
|
|
+ { |
189 |
|
|
+ $sz = 4; # Failed to get disk size |
190 |
|
|
+ } |
191 |
|
|
+ $self->unmount; |
192 |
|
|
+ } |
193 |
|
|
+ return $sz; |
194 |
|
|
+} |
195 |
|
|
+ |
196 |
|
|
+# Check each block device |
197 |
|
|
+# Return two arrays, valid drives, invalid drives |
198 |
|
|
+sub checkBackupDrives |
199 |
|
|
+{ |
200 |
|
|
+ my ($self,$bsize) = @_; |
201 |
|
|
+ my @valid = (); |
202 |
|
|
+ my @invalid = (); |
203 |
|
|
+ $self->scanBlocks; # scan all block devices |
204 |
|
|
+ my $hashref = $self->{_blox}; |
205 |
|
|
+ my $allowmount = $self->{'allowmount'}; # Are mounted drives allowed in $checks. |
206 |
|
|
+ my $checks = 'UU RO FS'; # These checks are always valid |
207 |
|
|
+ $checks .= ' MO' if ($allowmount eq 'enabled'); |
208 |
|
|
+ $checks .= ' SZ' if ($bsize); # Only run the size check when a valid size is given |
209 |
|
|
+ |
210 |
|
|
+ foreach my $drive (keys %{$hashref}) |
211 |
|
|
+ { |
212 |
|
|
+ $hashref->{$drive}{REASON} = $EMPTY; # Reason for a filesystem being (in)valid |
213 |
|
|
+ next unless $hashref->{$drive}{tip}; #Ignore drives that have child filesystems |
214 |
|
|
+ |
215 |
|
|
+ # drives mounted on /, /boot, or [SWAP] are never valid for backups |
216 |
|
|
+ next if ($hashref->{$drive}{MOUNTPOINT} =~ /^\/boot$|^\[SWAP\]$|^\/$/s ); |
217 |
|
|
+ |
218 |
|
|
+ # validate each filesystem against the checks |
219 |
|
|
+ foreach my $check (split / /s, $checks) |
220 |
|
|
+ { |
221 |
|
|
+ for ($check) |
222 |
|
|
+ { |
223 |
|
|
+ if (/^UU/si) # No UUID |
224 |
|
|
+ { |
225 |
|
|
+ $hashref->{$drive}{REASON} .='UU ' unless $self->uuid ($drive); last; |
226 |
|
|
+ } |
227 |
|
|
+ if (/^RO/si) # Read Only |
228 |
|
|
+ { |
229 |
|
|
+ $hashref->{$drive}{REASON} .='RO ' if $self->readonly ($drive); last; |
230 |
|
|
+ } |
231 |
|
|
+ if (/^FS/si) # Invalid filesystem |
232 |
|
|
+ { |
233 |
|
|
+ $hashref->{$drive}{REASON} .='FS ' unless $self->validFS ($drive); last; |
234 |
|
|
+ } |
235 |
|
|
+ if (/^MO/si) # Mounted |
236 |
|
|
+ { |
237 |
|
|
+ $hashref->{$drive}{REASON} .='MO ' if $self->mountpoint ($drive); last; |
238 |
|
|
+ } |
239 |
|
|
+ if (/^SZ/si) # filesystem size, this includes mounting to check free space |
240 |
|
|
+ { |
241 |
|
|
+ $hashref->{$drive}{REASON} .='SZ ' if $self->checkBackupDriveSize ($drive, $bsize); |
242 |
|
|
+ #ToDo the return value contains the reason why there is insufficient space, but this is not used yet. |
243 |
|
|
+ last; |
244 |
|
|
+ } |
245 |
|
|
+ { carp "not supported yet in checkBackupDrives: $check"; } # Should never be seen |
246 |
|
|
+ } |
247 |
|
|
+ } |
248 |
|
|
+ if ($hashref->{$drive}{REASON}) |
249 |
|
|
+ { |
250 |
|
|
+ push @invalid, $drive; |
251 |
|
|
+ } |
252 |
|
|
+ else |
253 |
|
|
+ { |
254 |
|
|
+ push @valid, $drive; |
255 |
|
|
+ } |
256 |
|
|
+ } |
257 |
|
|
+ return (\@valid, \@invalid); |
258 |
|
|
+} |
259 |
|
|
+ |
260 |
|
|
+sub findBackup |
261 |
|
|
+{ |
262 |
|
|
+ my ($self, $kname, $foundref, $maxDepth, $count) = @_; |
263 |
|
|
+ my $hashref = $self->{_blox}; |
264 |
|
|
+ my $mountpoint = $self->{'mount'}; |
265 |
|
|
+ my $file = 'smeserver.tgz'; |
266 |
|
|
+ |
267 |
|
|
+ $self->mount ($kname); |
268 |
|
|
+ sleep 1; |
269 |
|
|
+ |
270 |
|
|
+ # start with the absolute path |
271 |
|
|
+ my $findRoot = Cwd::realpath($mountpoint); |
272 |
|
|
+ |
273 |
|
|
+ # determine the depth of our beginning directory |
274 |
|
|
+ my $begDepth = 1 + grep { length } File::Spec->splitdir($findRoot); |
275 |
|
|
+ |
276 |
|
|
+ find ( |
277 |
|
|
+ { |
278 |
|
|
+ preprocess => sub |
279 |
|
|
+ { @_ if (scalar File::Spec->splitdir($File::Find::dir) - $begDepth) <= $maxDepth }, |
280 |
|
|
+ wanted => sub |
281 |
|
|
+ { |
282 |
|
|
+ if (($_ =~ m/^$file/s) && ($File::Find::name =~ qr|^([-+@\w\s./:\\]+)$| )) # if matching the backup name |
283 |
|
|
+ { |
284 |
|
|
+ $$count++; |
285 |
|
|
+ my $sb = stat $1; |
286 |
|
|
+ ${$foundref}{$$count}{count}=$$count; |
287 |
|
|
+ ${$foundref}{$$count}{device}=$kname; |
288 |
|
|
+ ${$foundref}{$$count}{path} = $1; |
289 |
|
|
+ ${$foundref}{$$count}{path} =~ s/$mountpoint//; #strip off the mountpoint |
290 |
|
|
+ ${$foundref}{$$count}{path} =~ s/$file//; #strip off the filename |
291 |
|
|
+ ${$foundref}{$$count}{size}=$sb->size; # size in bytes |
292 |
|
|
+ ${$foundref}{$$count}{sizeH}=scaleIt($sb->size); # human readable size |
293 |
|
|
+ ${$foundref}{$$count}{time}=strftime '%d %b %g %H:%M', localtime $sb->mtime; |
294 |
|
|
+ } |
295 |
|
|
+ }, |
296 |
|
|
+ untaint => 1, |
297 |
|
|
+ untaint_pattern => qr|^([-+@\w\s./:\\]+)$|, |
298 |
|
|
+ untaint_skip =>1, |
299 |
|
|
+ }, |
300 |
|
|
+ $findRoot |
301 |
|
|
+ ); |
302 |
|
|
+ |
303 |
|
|
+ $self->unmount; |
304 |
|
|
+ return; |
305 |
|
|
+} |
306 |
|
|
+ |
307 |
|
|
+sub desc # brief description of a filesystem |
308 |
|
|
+{ |
309 |
|
|
+ my ($self,$kname) = @_; |
310 |
|
|
+ my $hashref = $self->{_blox}; |
311 |
|
|
+ |
312 |
|
|
+ my $model = $hashref->{$kname}{MODEL}; |
313 |
|
|
+ my $label = $hashref->{$kname}{LABEL} || gettext('no label'); |
314 |
|
|
+ my $size = $hashref->{$kname}{SIZEH}; |
315 |
|
|
+ |
316 |
|
|
+ return "$label $model $size"; |
317 |
|
|
+} |
318 |
|
|
+ |
319 |
|
|
+ |
320 |
|
|
+# Given the KNAME check if the filesystem.could be mountable |
321 |
|
|
+# Check that there are no children, i.e. a tip |
322 |
|
|
+# Check that it has a UUID, Filesystem, |
323 |
|
|
+sub mountable |
324 |
|
|
+{ |
325 |
|
|
+ my ($self,$kname) = @_; |
326 |
|
|
+ my $hashref = $self->{_blox}; |
327 |
|
|
+ return ($hashref->{$kname}{tip} && $hashref->{$kname}{UUID} && _isFS ($hashref->{$kname}{FSTYPE})) ? 1 : $EMPTY; |
328 |
|
|
+} |
329 |
|
|
+ |
330 |
|
|
+# Given the KNAME check if the filesystem.is read-only |
331 |
|
|
+# returns 1 for Read-Only and $EMPTY for R-W |
332 |
|
|
+sub readonly |
333 |
|
|
+{ |
334 |
|
|
+ my ($self,$kname) = @_; |
335 |
|
|
+ my $hashref = $self->{_blox}; |
336 |
|
|
+ return ($hashref->{$kname}{RO}) ? 1 : $EMPTY; |
337 |
|
|
+} |
338 |
|
|
+ |
339 |
|
|
+sub mountpoint |
340 |
|
|
+{ |
341 |
|
|
+ my ($self,$kname) = @_; |
342 |
|
|
+ my $hashref = $self->{_blox}; |
343 |
|
|
+ return ($hashref->{$kname}{MOUNTPOINT}); |
344 |
|
|
+} |
345 |
|
|
+ |
346 |
|
|
+sub uuid |
347 |
|
|
+{ |
348 |
|
|
+ my ($self,$kname) = @_; |
349 |
|
|
+ my $hashref = $self->{_blox}; |
350 |
|
|
+ return ($hashref->{$kname}{UUID}); |
351 |
|
|
+} |
352 |
|
|
+ |
353 |
|
|
+sub model |
354 |
|
|
+{ |
355 |
|
|
+ my ($self,$kname) = @_; |
356 |
|
|
+ my $hashref = $self->{_blox}; |
357 |
|
|
+ return ($hashref->{$kname}{MODEL}); |
358 |
|
|
+} |
359 |
|
|
+ |
360 |
|
|
+# Given the KNAME return the label |
361 |
|
|
+# returns 'no label' if none found |
362 |
|
|
+sub label |
363 |
|
|
+{ |
364 |
|
|
+ my ($self,$kname) = @_; |
365 |
|
|
+ my $hashref = $self->{_blox}; |
366 |
|
|
+ return ($hashref->{$kname}{LABEL}) || gettext('no label'); |
367 |
|
|
+} |
368 |
|
|
+ |
369 |
|
|
+sub size |
370 |
|
|
+{ |
371 |
|
|
+ my ($self,$kname) = @_; |
372 |
|
|
+ my $hashref = $self->{_blox}; |
373 |
|
|
+ return ($hashref->{$kname}{SIZE}); |
374 |
|
|
+} |
375 |
|
|
+ |
376 |
|
|
+# Given a filesystem.(eg sr0) check if it's filesystem type is allowed |
377 |
|
|
+sub validFS |
378 |
|
|
+{ |
379 |
|
|
+ my ($self,$kname) = @_; |
380 |
|
|
+ my $hashref = $self->{_blox}; |
381 |
|
|
+ my $fsref = $self->{_fstype}; |
382 |
|
|
+ return ($fsref->{$hashref->{$kname}{FSTYPE}}) || $EMPTY; |
383 |
|
|
+} |
384 |
|
|
+ |
385 |
|
|
+# Given a filesystem.type (eg vfat) check if it is allowed |
386 |
|
|
+sub _isFS |
387 |
|
|
+{ |
388 |
|
|
+ my ($filesystem) = @_; |
389 |
|
|
+ return $EMPTY unless $filesystem; |
390 |
|
|
+ |
391 |
|
|
+ my $fsref = findValidFS; |
392 |
|
|
+ return ($fsref->{$filesystem}) || $EMPTY; |
393 |
|
|
+} |
394 |
|
|
+ |
395 |
|
|
+# Return the reason string which indicates why a drive is (in)valid |
396 |
|
|
+sub reason |
397 |
|
|
+{ |
398 |
|
|
+ my ($self,$kname) = @_; |
399 |
|
|
+ my $hashref = $self->{_blox}; |
400 |
|
|
+ return ($hashref->{$kname}{REASON}); |
401 |
|
|
+} |
402 |
|
|
+ |
403 |
|
|
+# Given the KNAME mount the filesystem, example |
404 |
|
|
+# system ('/bin/mount', '-t', 'vfat', '-U', '9891-4C8A', '/tmp/mnt'); |
405 |
|
|
+sub mount |
406 |
|
|
+{ |
407 |
|
|
+ my ($self, $kname) = @_; |
408 |
|
|
+ my $hashref = $self->{_blox}; |
409 |
|
|
+ |
410 |
|
|
+ $self->createMountpoint; |
411 |
|
|
+ |
412 |
|
|
+ system ('/bin/mount', '-t', $hashref->{$kname}{FSTYPE}, '-U', $hashref->{$kname}{UUID}, $self->{mount}) == 0 |
413 |
|
|
+ or croak (gettext('Failed to mount')." $self->{mount},$hashref->{$kname}{FSTYPE},$hashref->{$kname}{UUID}: $?"); |
414 |
|
|
+ return; |
415 |
|
|
+} |
416 |
|
|
+ |
417 |
|
|
+# Unmount the block device |
418 |
|
|
+sub unmount |
419 |
|
|
+{ |
420 |
|
|
+ my $self = shift; |
421 |
|
|
+ system('/bin/umount', $self->{mount}) == 0 |
422 |
|
|
+ or croak (gettext('Failed to unmount')." $self->{mount}: $?"); |
423 |
|
|
+ return; |
424 |
|
|
+} |
425 |
|
|
+ |
426 |
|
|
+# Create the mountpoint directory |
427 |
|
|
+# Error if already mounted |
428 |
|
|
+sub createMountpoint |
429 |
|
|
+{ |
430 |
|
|
+ my $self = shift; |
431 |
|
|
+ my $mount = $self->{mount}; |
432 |
|
|
+ |
433 |
|
|
+ # Check if the mountpoint is in use |
434 |
|
|
+ if (!checkMount ($mount)) |
435 |
|
|
+ { |
436 |
|
|
+ # Try to unmount, will die if fails |
437 |
|
|
+ $self->unmount; |
438 |
|
|
+ } |
439 |
|
|
+ |
440 |
|
|
+ if ($mount && ! -d $mount) |
441 |
|
|
+ { |
442 |
|
|
+ eval {make_path($mount)}; |
443 |
|
|
+ croak (gettext('Error while creating')." $mount $EVAL_ERROR".gettext('Maybe insufficient permissions.')) if $EVAL_ERROR; |
444 |
|
|
+ } |
445 |
|
|
+ return; |
446 |
|
|
+} |
447 |
|
|
+ |
448 |
|
|
+sub destroy |
449 |
|
|
+{ |
450 |
|
|
+# cleanup, unmount and remove mountpoint |
451 |
|
|
+ |
452 |
|
|
+ my $self = shift; |
453 |
|
|
+ my $mount = $self->{mount}; |
454 |
|
|
+ |
455 |
|
|
+ |
456 |
|
|
+ # Check if the mountpoint is in use |
457 |
|
|
+ if (!checkMount ($mount)) |
458 |
|
|
+ { |
459 |
|
|
+ $self->unmount; |
460 |
|
|
+ } |
461 |
|
|
+ |
462 |
|
|
+ if ($mount && -d $mount) |
463 |
|
|
+ { |
464 |
|
|
+ eval {remove_tree($mount)}; |
465 |
|
|
+ croak (gettext('Error while deleting')." $mount $EVAL_ERROR") if $EVAL_ERROR; |
466 |
|
|
+ } |
467 |
|
|
+ return; |
468 |
|
|
+} |
469 |
|
|
+ |
470 |
|
|
+ |
471 |
|
|
+### The following subroutines are not specific to block devices |
472 |
|
|
+sub scaleIt { |
473 |
|
|
+ Readonly my $KBYTE => 1024; |
474 |
|
|
+ my( $size, $n ) =( shift, 0 ); |
475 |
|
|
+ ++$n and $size /= $KBYTE until $size < $KBYTE; |
476 |
|
|
+ if ($size >= 1000){++$n ; $size /= $KBYTE;} |
477 |
|
|
+ return sprintf "%.3g %s", |
478 |
|
|
+ $size, ( qw[ bytes KB MB GB TB] )[ $n ]; |
479 |
|
|
+} |
480 |
|
|
+ |
481 |
|
|
+sub checkMount |
482 |
|
|
+{ |
483 |
|
|
+ # check if $mountdir is mounted |
484 |
|
|
+ my $mountdir = shift; |
485 |
|
|
+ $|=1; # Auto-flush |
486 |
|
|
+ |
487 |
|
|
+ # copy STDOUT to another filehandle |
488 |
|
|
+ open (my $STDOLD, '>&', STDOUT); |
489 |
|
|
+ |
490 |
|
|
+ open(STDOUT, ">/dev/null"); |
491 |
|
|
+ if ( open(MOUNTDIR, "|-", "/bin/findmnt", $mountdir)){;} |
492 |
|
|
+ |
493 |
|
|
+ # restore STDOUT |
494 |
|
|
+ open (STDOUT, '>&', $STDOLD); |
495 |
|
|
+ |
496 |
|
|
+ return (!close(MOUNTDIR)); |
497 |
|
|
+} |
498 |
|
|
+ |
499 |
|
|
+# remove leading and trailing spaces from a string |
500 |
|
|
+# this should be moved to a util library. |
501 |
|
|
+sub trim |
502 |
|
|
+{ |
503 |
|
|
+ my ($string) = @_; |
504 |
|
|
+ $string =~ s/^\s+|\s+$//g; |
505 |
|
|
+ return $string; |
506 |
|
|
+} |
507 |
|
|
+1; |
508 |
|
|
diff -urN e-smith-backup-2.4.0.old/root/usr/share/perl5/vendor_perl/esmith/console/perform_backup.pm e-smith-backup-2.4.0/root/usr/share/perl5/vendor_perl/esmith/console/perform_backup.pm |
509 |
|
|
--- e-smith-backup-2.4.0.old/root/usr/share/perl5/vendor_perl/esmith/console/perform_backup.pm 2016-02-06 18:23:27.978666800 -0800 |
510 |
|
|
+++ e-smith-backup-2.4.0/root/usr/share/perl5/vendor_perl/esmith/console/perform_backup.pm 2016-01-09 16:32:40.000000000 -0800 |
511 |
|
|
@@ -6,8 +6,14 @@ |
512 |
|
|
use esmith::util; |
513 |
|
|
use Locale::gettext; |
514 |
|
|
use esmith::Backup; |
515 |
|
|
-#use Filesys::DiskFree; |
516 |
|
|
-#use Sys::Filesystem; |
517 |
|
|
+use Carp; |
518 |
|
|
+use feature qw( say ); |
519 |
|
|
+use esmith::BlockDevices; |
520 |
|
|
+use POSIX qw(:sys_wait_h strftime); |
521 |
|
|
+use File::stat; |
522 |
|
|
+use Taint::Util; |
523 |
|
|
+ |
524 |
|
|
+my $EMPTY = q{}; |
525 |
|
|
|
526 |
|
|
sub new |
527 |
|
|
{ |
528 |
|
|
@@ -21,7 +27,7 @@ |
529 |
|
|
} |
530 |
|
|
|
531 |
|
|
sub name |
532 |
|
|
-{ |
533 |
|
|
+{ |
534 |
|
|
return $_[0]->{name}; |
535 |
|
|
} |
536 |
|
|
|
537 |
|
|
@@ -42,22 +48,10 @@ |
538 |
|
|
return sub { |
539 |
|
|
my $fh = shift; |
540 |
|
|
my @backup_list = esmith::Backup->restore_list; |
541 |
|
|
- |
542 |
|
|
- unless (open(DU, "-|")) |
543 |
|
|
- { |
544 |
|
|
- open(STDERR, ">/dev/null"); |
545 |
|
|
- exec qw(/usr/bin/du -sb), map { "/$_" } @backup_list; |
546 |
|
|
- } |
547 |
|
|
- my $backup_size = 0; |
548 |
|
|
- while (<DU>) |
549 |
|
|
- { |
550 |
|
|
- next unless (/^(\d+)/); |
551 |
|
|
- $backup_size += $1; |
552 |
|
|
- } |
553 |
|
|
- close DU; |
554 |
|
|
+ my $backup_size = backupSize (@backup_list); |
555 |
|
|
|
556 |
|
|
open(OLDSTDOUT, ">&STDOUT"); |
557 |
|
|
- unless (open(STDOUT, ">/mnt/bootstrap-console-backup/smeserver.tgz")) |
558 |
|
|
+ unless (open(STDOUT, ">$device/smeserver.tgz")) |
559 |
|
|
{ |
560 |
|
|
return gettext("Could not create backup file on device").": $!\n"; |
561 |
|
|
} |
562 |
|
|
@@ -74,7 +68,7 @@ |
563 |
|
|
my $status = 0; |
564 |
|
|
|
565 |
|
|
my $gzip = open(GZIP, "|-"); |
566 |
|
|
- return "could not run gzip" unless defined $gzip; |
567 |
|
|
+ return "could not run gzip" unless defined $gzip; |
568 |
|
|
unless ($gzip) |
569 |
|
|
{ |
570 |
|
|
close $fh; |
571 |
|
|
@@ -127,140 +121,130 @@ |
572 |
|
|
{ |
573 |
|
|
my ($self, $console, $db) = @_; |
574 |
|
|
my @backup_list = esmith::Backup->restore_list; |
575 |
|
|
+ my $compressionLevel = $db->get_prop('backupconsole', 'CompressionLevel') || '-6'; |
576 |
|
|
+ my $mountpoint = $db->get_prop('backupconsole', 'Mountpoint') || '/mnt/bootstrap-console-backup'; |
577 |
|
|
+ my $allowMounted = $db->get_prop('backupconsole', 'AllowMounted') || 'disabled'; ### For future use |
578 |
|
|
|
579 |
|
|
$ENV{PATH} = "/bin:/usr/bin"; |
580 |
|
|
$ENV{HOME} = "/root"; |
581 |
|
|
|
582 |
|
|
- my $compressionLevel = $db->get_prop("backupconsole", "CompressionLevel") || "-6"; |
583 |
|
|
+ my $devices = esmith::BlockDevices->new ('mount' => $mountpoint, 'allowmount' => $allowMounted); |
584 |
|
|
+ |
585 |
|
|
+ INITIATE_BACKUP: |
586 |
|
|
my ($rc, $choice) = $console->yesno_page |
587 |
|
|
( |
588 |
|
|
- title => gettext("Create Backup to removable media"), |
589 |
|
|
+ title => gettext('Create Backup to removable media'), |
590 |
|
|
defaultno => 1, |
591 |
|
|
- text => |
592 |
|
|
- gettext("Do you wish to create backup on removable media?"), |
593 |
|
|
- ); |
594 |
|
|
- return unless $rc == 0; |
595 |
|
|
- INITIATE_BACKUP: |
596 |
|
|
- ($rc, $choice) = $console->yesno_page |
597 |
|
|
- ( |
598 |
|
|
- title => gettext("Insert media to use for backup"), |
599 |
|
|
- left => gettext("Next"), |
600 |
|
|
- right => gettext("Cancel"), |
601 |
|
|
- text => |
602 |
|
|
- gettext("Insert removable media, then hit the enter key."), |
603 |
|
|
- ); |
604 |
|
|
- return unless $rc == 0; |
605 |
|
|
- sleep(3); |
606 |
|
|
- my @dirs = (); |
607 |
|
|
- my @labels = (); |
608 |
|
|
- foreach my $udi (qx(hal-find-by-property --key volume.fsusage --string filesystem)) { |
609 |
|
|
- $udi =~ m/^(\S+)/; |
610 |
|
|
- |
611 |
|
|
- my $is_readonly = qx(hal-get-property --udi $1 --key volume.is_mounted_read_only); |
612 |
|
|
- |
613 |
|
|
- if ($is_readonly eq "false\n") { |
614 |
|
|
- |
615 |
|
|
- my $is_mounted = qx(hal-get-property --udi $1 --key volume.is_mounted); |
616 |
|
|
- |
617 |
|
|
- if ($is_mounted eq "false\n") { |
618 |
|
|
- my $blkdev = qx(hal-get-property --udi $1 --key block.device); |
619 |
|
|
- $blkdev =~ m/^(\S+)/; |
620 |
|
|
- push @dirs, $1; |
621 |
|
|
- } |
622 |
|
|
- if ($is_mounted eq "false\n") { |
623 |
|
|
- my $vollbl = qx(hal-get-property --udi $1 --key volume.label); |
624 |
|
|
- $vollbl =~ m/^(\S+)/; |
625 |
|
|
- if ($vollbl =~ /^\s/) {$vollbl = 'nolabel';} |
626 |
|
|
- chomp $vollbl; |
627 |
|
|
- push @labels, lc($vollbl); |
628 |
|
|
- } |
629 |
|
|
- } |
630 |
|
|
- } |
631 |
|
|
- unless ($dirs[0]) |
632 |
|
|
+ text => gettext('Do you want to create a backup on removable media?')."\n\n". |
633 |
|
|
+ gettext('Insert removable media before proceeding.')."\n". |
634 |
|
|
+ gettext('It may take many seconds to scan for media.'), |
635 |
|
|
+ ); |
636 |
|
|
+ if ($rc != 0) |
637 |
|
|
{ |
638 |
|
|
- ($rc, $choice) = $console->message_page |
639 |
|
|
- ( |
640 |
|
|
- title => gettext("Writable backup medium not found"), |
641 |
|
|
- right => gettext("Back"), |
642 |
|
|
- text => |
643 |
|
|
- gettext("No removable and/or writable media or device found"), |
644 |
|
|
- ); |
645 |
|
|
- goto INITIATE_BACKUP; |
646 |
|
|
+ $devices->destroy; |
647 |
|
|
+ return; |
648 |
|
|
} |
649 |
|
|
- mkdir("/mnt/bootstrap-console-backup"); |
650 |
|
|
|
651 |
|
|
- my $device = $dirs[0]; |
652 |
|
|
- if (defined $dirs[1]) |
653 |
|
|
- { |
654 |
|
|
- my $count=1; |
655 |
|
|
- my @args = map { $count++ . '.' => $_ } @dirs; |
656 |
|
|
+ ### determine which filesystems are valid or not for backups |
657 |
|
|
+ # check expected backup size |
658 |
|
|
+ my $backup_size = backupSize (@backup_list); |
659 |
|
|
|
660 |
|
|
- my ($rc, $choice) = $console->menu_page |
661 |
|
|
- ( |
662 |
|
|
- title => gettext("Choose device to use for backup"), |
663 |
|
|
- text => ("@dirs \n @labels"), |
664 |
|
|
- argsref => \@args, |
665 |
|
|
- left => gettext("Cancel"), |
666 |
|
|
- right => gettext("OK"), |
667 |
|
|
- ); |
668 |
|
|
- goto INITIATE_BACKUP unless ($rc == 0); |
669 |
|
|
- my %args_hash = ( @args ); |
670 |
|
|
- $device = $args_hash{$choice}; |
671 |
|
|
- } |
672 |
|
|
- unless ( system("/bin/mount", "$device", "/mnt/bootstrap-console-backup") == '0' ) |
673 |
|
|
+ # validate each filesystem |
674 |
|
|
+ my ($valid, $invalid) = $devices->checkBackupDrives ($backup_size); |
675 |
|
|
+ my $text = $EMPTY; |
676 |
|
|
+ |
677 |
|
|
+ if (${$invalid}[0]) # If there are filesystems that are not valid. |
678 |
|
|
{ |
679 |
|
|
- ($rc, $choice) = $console->message_page |
680 |
|
|
- ( |
681 |
|
|
- title => gettext("No mountable backup medium"), |
682 |
|
|
- right => gettext("Back"), |
683 |
|
|
- text => |
684 |
|
|
- gettext("Unable to mount removable media, please check the file system format (default : Vfat,Ext2,Ext3,Ext4)"), |
685 |
|
|
- ); |
686 |
|
|
- goto INITIATE_BACKUP; |
687 |
|
|
+ $text .= gettext ('These filesystems are not valid:')."\n"; |
688 |
|
|
+ foreach my $drive (sort @{$invalid}) |
689 |
|
|
+ { |
690 |
|
|
+ $text .= "$drive ".$devices->desc($drive).' '.gettext ('Reason').': '.$devices->reason($drive)."\n"; |
691 |
|
|
+ } |
692 |
|
|
+ $text .= "\n"; |
693 |
|
|
} |
694 |
|
|
|
695 |
|
|
- use File::stat; |
696 |
|
|
- my $st = stat("/mnt/bootstrap-console-backup/smeserver.tgz"); |
697 |
|
|
- if ($st) |
698 |
|
|
+ unless (${$valid}[0]) # Unless a device is found show error page |
699 |
|
|
{ |
700 |
|
|
-# TODO |
701 |
|
|
-# old backup exists - what do we want to do with it? |
702 |
|
|
- my $size = $st->size; |
703 |
|
|
- } |
704 |
|
|
+ my $title = gettext('No valid backup device found').' '.gettext('size').' '.esmith::BlockDevices::scaleIt($backup_size); |
705 |
|
|
+ $text .= "\n$title, ".gettext('please try again'); |
706 |
|
|
+ ($rc, $choice) = $console->yesno_page |
707 |
|
|
+ ( |
708 |
|
|
+ title => $title, |
709 |
|
|
+ text => $text, |
710 |
|
|
+ left => gettext('Try again'), |
711 |
|
|
+ right => gettext('Cancel'), |
712 |
|
|
+ ); |
713 |
|
|
+ if ($rc == 0) # Try Again |
714 |
|
|
+ { |
715 |
|
|
+ goto INITIATE_BACKUP; |
716 |
|
|
+ } |
717 |
|
|
+ else |
718 |
|
|
+ { |
719 |
|
|
+ $devices->destroy; |
720 |
|
|
+ return; |
721 |
|
|
+ } |
722 |
|
|
+ } |
723 |
|
|
+ $text .= gettext ('The following are valid for backup').' '; |
724 |
|
|
+ $text .= gettext ('size').' '.esmith::BlockDevices::scaleIt($backup_size); |
725 |
|
|
|
726 |
|
|
+ #ToDo when valid + invalid > 13 then may need to limit the information |
727 |
|
|
+ my @args = map { $_ => $devices->desc($_) } @{$valid}; |
728 |
|
|
+ |
729 |
|
|
+ # Display the available backup destinations. |
730 |
|
|
+ ($rc, $choice) = $console->menu_page |
731 |
|
|
+ ( |
732 |
|
|
+ title => gettext('Choose device to use for backup').' '.gettext('size').' '.esmith::BlockDevices::scaleIt($backup_size), |
733 |
|
|
+ text => $text, |
734 |
|
|
+ argsref => \@args, |
735 |
|
|
+ left => gettext('Cancel'), |
736 |
|
|
+ right => gettext('OK'), |
737 |
|
|
+ ); |
738 |
|
|
+ goto INITIATE_BACKUP unless ($rc == 0); |
739 |
|
|
+ untaint $choice; |
740 |
|
|
+ $devices->mount ($choice); # mount the chosen filesystem |
741 |
|
|
+ |
742 |
|
|
$console->infobox( |
743 |
|
|
- title => gettext("Preparing for backup"), |
744 |
|
|
- text => gettext("Please stand by while the system is prepared for backup..."), |
745 |
|
|
+ title => gettext('Preparing for backup'), |
746 |
|
|
+ text => gettext('Please stand by while the system is prepared for backup...'), |
747 |
|
|
); |
748 |
|
|
|
749 |
|
|
- my $backup_size = 0; |
750 |
|
|
- system("/sbin/e-smith/signal-event", "pre-backup"); |
751 |
|
|
+ system("/sbin/e-smith/signal-event", 'pre-backup'); |
752 |
|
|
+ |
753 |
|
|
+ $console->gauge(make_backup_callback($mountpoint,$compressionLevel), 'title' => gettext('Creating backup file')); |
754 |
|
|
+ |
755 |
|
|
+ $devices->destroy; |
756 |
|
|
+ |
757 |
|
|
+ system("/sbin/e-smith/signal-event", 'post-backup'); |
758 |
|
|
+ $console->message_page |
759 |
|
|
+ ( |
760 |
|
|
+ title => gettext('Backup complete'), |
761 |
|
|
+ text => gettext('Remove backup media.'), |
762 |
|
|
+ ); |
763 |
|
|
+ return; |
764 |
|
|
+} |
765 |
|
|
+ |
766 |
|
|
+ |
767 |
|
|
+sub backupSize |
768 |
|
|
+{ |
769 |
|
|
+ my $size; |
770 |
|
|
+ |
771 |
|
|
unless (open(DU, "-|")) |
772 |
|
|
{ |
773 |
|
|
open(STDERR, ">/dev/null"); |
774 |
|
|
- exec qw(/usr/bin/du -sb), map { "/$_" } @backup_list; |
775 |
|
|
+ exec qw(/usr/bin/du -sb), map { "/$_" } @_; |
776 |
|
|
} |
777 |
|
|
while (<DU>) |
778 |
|
|
{ |
779 |
|
|
next unless (/^(\d+)/); |
780 |
|
|
- $backup_size += $1; |
781 |
|
|
+ $size += $1; |
782 |
|
|
} |
783 |
|
|
close DU; |
784 |
|
|
- |
785 |
|
|
- $console->gauge(make_backup_callback("/mnt/bootstrap-console-backup",$compressionLevel), 'title' => gettext("Creating backup file")); |
786 |
|
|
- |
787 |
|
|
- system("/bin/umount", "/mnt/bootstrap-console-backup"); |
788 |
|
|
- rmdir("/mnt/bootstrap-console-backup"); |
789 |
|
|
- system("/sbin/e-smith/signal-event", "post-backup"); |
790 |
|
|
- ($rc, $choice) = $console->message_page |
791 |
|
|
- ( |
792 |
|
|
- title => gettext("Backup complete"), |
793 |
|
|
- text => |
794 |
|
|
- gettext("Remove removable media, then hit the enter key."), |
795 |
|
|
- ); |
796 |
|
|
+ |
797 |
|
|
+ return $size; |
798 |
|
|
} |
799 |
|
|
|
800 |
|
|
#use esmith::console; |
801 |
|
|
#esmith::console::perform_backup->new->doit(esmith::console->new, |
802 |
|
|
# esmith::ConfigDB->open); |
803 |
|
|
1; |
804 |
|
|
+ |
805 |
|
|
diff -urN e-smith-backup-2.4.0.old/root/usr/share/perl5/vendor_perl/esmith/console/perform_restore.pm e-smith-backup-2.4.0/root/usr/share/perl5/vendor_perl/esmith/console/perform_restore.pm |
806 |
|
|
--- e-smith-backup-2.4.0.old/root/usr/share/perl5/vendor_perl/esmith/console/perform_restore.pm 2016-02-06 18:23:27.839666800 -0800 |
807 |
|
|
+++ e-smith-backup-2.4.0/root/usr/share/perl5/vendor_perl/esmith/console/perform_restore.pm 2016-01-09 16:32:40.000000000 -0800 |
808 |
|
|
@@ -4,6 +4,12 @@ |
809 |
|
|
use esmith::ConfigDB; |
810 |
|
|
use esmith::console; |
811 |
|
|
use Locale::gettext; |
812 |
|
|
+use Carp; |
813 |
|
|
+use feature qw( say ); |
814 |
|
|
+use esmith::BlockDevices; |
815 |
|
|
+use Taint::Util; |
816 |
|
|
+ |
817 |
|
|
+my $EMPTY = q{}; |
818 |
|
|
|
819 |
|
|
sub new |
820 |
|
|
{ |
821 |
|
|
@@ -16,9 +22,8 @@ |
822 |
|
|
return $self; |
823 |
|
|
} |
824 |
|
|
|
825 |
|
|
- |
826 |
|
|
sub name |
827 |
|
|
-{ |
828 |
|
|
+{ |
829 |
|
|
return $_[0]->{name}; |
830 |
|
|
} |
831 |
|
|
|
832 |
|
|
@@ -30,124 +35,154 @@ |
833 |
|
|
sub doit |
834 |
|
|
{ |
835 |
|
|
my ($self, $console, $db) = @_; |
836 |
|
|
- if ($db->get_prop('bootstrap-console', 'Run') eq 'yes') # called from bootstrap console |
837 |
|
|
+ my $compressionLevel = $db->get_prop('backupconsole', 'CompressionLevel') || '-6'; |
838 |
|
|
+ my $mountpoint = $db->get_prop('backupconsole', 'Mountpoint') || '/mnt/bootstrap-console-backup'; |
839 |
|
|
+ my $allowMounted = $db->get_prop('backupconsole', 'AllowMounted') || 'disabled'; ### For future use |
840 |
|
|
+ my $restoreMaxDepth = $db->get_prop('backupconsole', 'MaxDepth') || 1; ### For future use |
841 |
|
|
+ my %found; |
842 |
|
|
+ my $backupcount = 0; |
843 |
|
|
+ my $backupdrive; # Which filesystem holds the backup |
844 |
|
|
+ my $backupfile; # full path to the backup |
845 |
|
|
+ my ($time, $size); # time and size of chosen backup |
846 |
|
|
+ |
847 |
|
|
+ if ($db->get_prop('bootstrap-console', 'Run') eq 'yes') # called from bootstrap console |
848 |
|
|
{ |
849 |
|
|
return if ($db->get_value('PasswordSet') eq 'yes'); # too late |
850 |
|
|
} |
851 |
|
|
return if ($db->get_prop('bootstrap-console', 'Restore') eq 'disabled'); |
852 |
|
|
+ |
853 |
|
|
+ my $devices = esmith::BlockDevices->new ('mount' => $mountpoint, 'allowmount' => $allowMounted); |
854 |
|
|
+ |
855 |
|
|
+ INITIATE_RESTORE: |
856 |
|
|
my ($rc, $choice) = $console->yesno_page |
857 |
|
|
( |
858 |
|
|
title => gettext("Restore From Backup"), |
859 |
|
|
defaultno => 1, |
860 |
|
|
- text => |
861 |
|
|
- gettext("Do you wish to restore from backup?"), |
862 |
|
|
- ); |
863 |
|
|
- return unless $rc == 0; |
864 |
|
|
- mkdir("/mnt/bootstrap-console-backup"); |
865 |
|
|
- system("/etc/init.d/messagebus", "start"); |
866 |
|
|
- system("/etc/init.d/haldaemon", "start"); |
867 |
|
|
- INITIATE_RESTORE: |
868 |
|
|
- ($rc, $choice) = $console->yesno_page |
869 |
|
|
- ( |
870 |
|
|
- title => gettext("Insert media containing backup"), |
871 |
|
|
- left => gettext("Next"), |
872 |
|
|
- right => gettext("Cancel"), |
873 |
|
|
- text => |
874 |
|
|
- gettext("Insert removable media containing your backup file, then hit the enter key."), |
875 |
|
|
- ); |
876 |
|
|
- unless ($rc == 0) { |
877 |
|
|
- system("/etc/init.d/haldaemon", "stop"); |
878 |
|
|
- system("/etc/init.d/messagebus", "stop"); |
879 |
|
|
- rmdir("/mnt/bootstrap-console-backup"); |
880 |
|
|
+ text => gettext('Do you wish to restore from backup?')."\n\n". |
881 |
|
|
+ gettext('Insert removable media before proceeding.')."\n". |
882 |
|
|
+ gettext('It may take many seconds to scan for media.'), |
883 |
|
|
+ ); # Buttons are Yes & No |
884 |
|
|
+ if ($rc != 0) # choice was not Yes |
885 |
|
|
+ { |
886 |
|
|
+ $devices->destroy; |
887 |
|
|
return; |
888 |
|
|
} |
889 |
|
|
- sleep(3); |
890 |
|
|
- my @dirs; |
891 |
|
|
- @dirs = (); |
892 |
|
|
- foreach my $udi (qx(hal-find-by-property --key volume.fsusage --string filesystem)) { |
893 |
|
|
- $udi =~ m/^(\S+)/; |
894 |
|
|
- my $is_mounted = qx(hal-get-property --udi $1 --key volume.is_mounted); |
895 |
|
|
- |
896 |
|
|
- if ($is_mounted eq "false\n") { |
897 |
|
|
- my $blkdev = qx(hal-get-property --udi $1 --key block.device); |
898 |
|
|
- $blkdev =~ m/^(\S+)/; |
899 |
|
|
- push @dirs, $1; |
900 |
|
|
+ |
901 |
|
|
+ ### determine which filesystems are valid or not for backups |
902 |
|
|
+ |
903 |
|
|
+ # validate each filesystem |
904 |
|
|
+ my ($valid, $invalid) = $devices->checkBackupDrives ($EMPTY); |
905 |
|
|
+ my $text = $EMPTY; |
906 |
|
|
+ |
907 |
|
|
+ if (${$valid}[0]) # There are filesystems that could hold a backup. |
908 |
|
|
+ { |
909 |
|
|
+ $text .= gettext ('These filesystems could hold backups')."\n"; |
910 |
|
|
+ foreach my $drive (sort @{$valid}) |
911 |
|
|
+ { |
912 |
|
|
+ $text .= "$drive ".$devices->desc($drive)."\n"; |
913 |
|
|
+ $devices->findBackup ($drive, \%found, $restoreMaxDepth, \$backupcount); |
914 |
|
|
} |
915 |
|
|
+ $text .= "\n"; |
916 |
|
|
} |
917 |
|
|
- unless ($dirs[0]) |
918 |
|
|
+ |
919 |
|
|
+ unless ($backupcount) # Unless a valid backup is found show error page |
920 |
|
|
{ |
921 |
|
|
- ($rc, $choice) = $console->message_page |
922 |
|
|
- ( |
923 |
|
|
- title => gettext("Backup medium not found"), |
924 |
|
|
- right => "Try again", |
925 |
|
|
- text => |
926 |
|
|
- gettext("No removable media or device found"), |
927 |
|
|
- ); |
928 |
|
|
- goto INITIATE_RESTORE; |
929 |
|
|
- } |
930 |
|
|
- my $device = $dirs[0]; |
931 |
|
|
- if (defined $dirs[1]) |
932 |
|
|
- { |
933 |
|
|
- my $count=1; |
934 |
|
|
- # FIXME use better regexp |
935 |
|
|
- my @args = map { /(.*)/; $count++ . '.' => $1 } @dirs; |
936 |
|
|
+ if (${$invalid}[0]) # If there are filesystems that are not valid. |
937 |
|
|
+ { |
938 |
|
|
+ $text .= gettext ('These filesystems are not valid:')."\n"; |
939 |
|
|
+ foreach my $drive (sort @{$invalid}) |
940 |
|
|
+ { |
941 |
|
|
+ $text .= "$drive ".$devices->desc($drive).' '.gettext ('Reason').': '.$devices->reason($drive)."\n"; |
942 |
|
|
+ } |
943 |
|
|
+ $text .= "\n"; |
944 |
|
|
+ } |
945 |
|
|
+ my $title = gettext('No valid backup device found'); |
946 |
|
|
+ $text .= "\n$title, ".gettext('please try again'); |
947 |
|
|
+ ($rc, $choice) = $console->yesno_page |
948 |
|
|
+ ( |
949 |
|
|
+ title => $title, |
950 |
|
|
+ text => $text, |
951 |
|
|
+ left => gettext('Try again'), |
952 |
|
|
+ right => gettext('Cancel'), |
953 |
|
|
+ ); |
954 |
|
|
+ if ($rc == 0) # Try Again |
955 |
|
|
+ { |
956 |
|
|
+ goto INITIATE_RESTORE; |
957 |
|
|
+ } |
958 |
|
|
+ else |
959 |
|
|
+ { |
960 |
|
|
+ $devices->destroy; |
961 |
|
|
+ return; |
962 |
|
|
+ } |
963 |
|
|
+ } |
964 |
|
|
|
965 |
|
|
- my ($rc, $choice) = $console->menu_page |
966 |
|
|
- ( |
967 |
|
|
- title => gettext("Choose device to restore from"), |
968 |
|
|
- text => gettext("Please select which device contains the backup file you wish to restore from."), |
969 |
|
|
- argsref => \@args, |
970 |
|
|
- left => gettext("Cancel"), |
971 |
|
|
- right => gettext("OK"), |
972 |
|
|
- ); |
973 |
|
|
+ # %found contains $backupcount backups. |
974 |
|
|
+ if ($backupcount == 1) |
975 |
|
|
+ { |
976 |
|
|
+ # One backup found, so simple yes/no choice |
977 |
|
|
+ $backupdrive = $found{1}{device}; # Find the (only) device that a backup was found on |
978 |
|
|
+ $backupfile = $found{1}{path}; # find the actual backup |
979 |
|
|
+ $time = gettext('Date') .' '. $found{1}{time}; |
980 |
|
|
+ $size = gettext('Size') .' '. $found{1}{sizeH}; |
981 |
|
|
+ |
982 |
|
|
+ ($rc, $choice) = $console->yesno_page |
983 |
|
|
+ ( |
984 |
|
|
+ title => gettext('Start restore from backup'), |
985 |
|
|
+ text => |
986 |
|
|
+ gettext('Backup found on device'). |
987 |
|
|
+ "\n$backupdrive ".$devices->desc($backupdrive)."\n\n". |
988 |
|
|
+ gettext('Backup details'). |
989 |
|
|
+ "\n$backupfile $size $time\n\n\n". |
990 |
|
|
+ gettext('Do you wish to restore from this file?'), |
991 |
|
|
+ ); |
992 |
|
|
goto INITIATE_RESTORE unless ($rc == 0); |
993 |
|
|
- my %args_hash = ( @args ); |
994 |
|
|
- $device = $args_hash{$choice}; |
995 |
|
|
+ $size = $found{1}{size}; |
996 |
|
|
} |
997 |
|
|
- system("/bin/mount", "$device", "/mnt/bootstrap-console-backup"); |
998 |
|
|
- sleep(1); |
999 |
|
|
- |
1000 |
|
|
- unless (-f "/mnt/bootstrap-console-backup/smeserver.tgz") |
1001 |
|
|
+ else # Multiple backups found so display a choice |
1002 |
|
|
{ |
1003 |
|
|
- system("/bin/umount", "$device"); |
1004 |
|
|
- ($rc, $choice) = $console->message_page |
1005 |
|
|
- ( |
1006 |
|
|
- title => gettext("Backup file not found"), |
1007 |
|
|
- right => "Try again", |
1008 |
|
|
- text => |
1009 |
|
|
- gettext("No backup file found"), |
1010 |
|
|
- ); |
1011 |
|
|
- goto INITIATE_RESTORE; |
1012 |
|
|
- } |
1013 |
|
|
- use File::stat; |
1014 |
|
|
- my $st = stat("/mnt/bootstrap-console-backup/smeserver.tgz"); |
1015 |
|
|
- my $size = $st->size; |
1016 |
|
|
- |
1017 |
|
|
- ($rc, $choice) = $console->yesno_page |
1018 |
|
|
- ( |
1019 |
|
|
- title => gettext("Start restore from backup"), |
1020 |
|
|
- text => |
1021 |
|
|
- gettext("Backup file found:") . " smeserver.tgz ($device) " . |
1022 |
|
|
- gettext("size") . " $size " . gettext("bytes") . |
1023 |
|
|
- "\n\n" . |
1024 |
|
|
- gettext("Do you wish to restore from this file?"), |
1025 |
|
|
- ); |
1026 |
|
|
- unless ($rc == 0) { |
1027 |
|
|
- system("/bin/umount", "$device"); |
1028 |
|
|
- goto INITIATE_RESTORE; |
1029 |
|
|
+ $text = gettext ('Backups found on these devices')."\n"; |
1030 |
|
|
+ foreach my $backupfound (sort keys %found) |
1031 |
|
|
+ { |
1032 |
|
|
+ $backupdrive = $found{$backupfound}{device}; |
1033 |
|
|
+ if (($backupfound == 1) || ($found{$backupfound}{device} ne $found{$backupfound-1}{device})) |
1034 |
|
|
+ { |
1035 |
|
|
+ $text.= "$backupdrive ".$devices->desc($backupdrive)."\n"; |
1036 |
|
|
+ } |
1037 |
|
|
+ } |
1038 |
|
|
+ my @args = map { $_ => "$found{$_}{device} $found{$_}{path} $found{$_}{sizeH} $found{$_}{time}" } sort keys %found; |
1039 |
|
|
+ ($rc, $choice) = $console->menu_page |
1040 |
|
|
+ ( |
1041 |
|
|
+ title => gettext('Start restore from backup'), |
1042 |
|
|
+ text => |
1043 |
|
|
+ "$text\n". |
1044 |
|
|
+ gettext ('Please select the backup that you wish to restore from.'), |
1045 |
|
|
+ argsref => \@args, |
1046 |
|
|
+ left => gettext('Cancel'), |
1047 |
|
|
+ right => gettext('OK'), |
1048 |
|
|
+ ); |
1049 |
|
|
+ goto INITIATE_RESTORE unless ($rc == 0); |
1050 |
|
|
+ untaint $choice; |
1051 |
|
|
+ $backupdrive = $found{$choice}{device}; |
1052 |
|
|
+ $size = $found{$choice}{size}; |
1053 |
|
|
} |
1054 |
|
|
+ |
1055 |
|
|
+ $devices->mount ($backupdrive); # mount the chosen filesystem |
1056 |
|
|
+ sleep(1); # Some mounts take time to become active |
1057 |
|
|
+ |
1058 |
|
|
+ ###ToDo This section has no error checking |
1059 |
|
|
+ ###ToDo 'Restoring data is not localized |
1060 |
|
|
+ # Execute the restore |
1061 |
|
|
system("/sbin/e-smith/signal-event", "pre-restore"); |
1062 |
|
|
- system("(cd / ; cat /mnt/bootstrap-console-backup/smeserver.tgz | |
1063 |
|
|
+ system("(cd / ; cat $mountpoint/smeserver.tgz | |
1064 |
|
|
pv -n -s $size | |
1065 |
|
|
gunzip | |
1066 |
|
|
tar xf - > /dev/null ) 2>&1 | |
1067 |
|
|
dialog --backtitle 'Restoring data' --guage 'Progress' 7 70"); |
1068 |
|
|
- system("/bin/umount", "$device"); |
1069 |
|
|
- system("/etc/init.d/haldaemon", "stop"); |
1070 |
|
|
- system("/etc/init.d/messagebus", "stop"); |
1071 |
|
|
- rmdir("/mnt/bootstrap-console-backup"); |
1072 |
|
|
+ |
1073 |
|
|
+ # Restore complete, now clean-up |
1074 |
|
|
+ $devices->destroy; |
1075 |
|
|
system("/sbin/e-smith/signal-event", "post-upgrade"); |
1076 |
|
|
- |
1077 |
|
|
+ |
1078 |
|
|
unless ( $self->{bootstrap} ) |
1079 |
|
|
{ |
1080 |
|
|
$db->set_prop("bootstrap-console", "Run", "yes"); |