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