]> git.ipfire.org Git - ipfire-2.x.git/blame - html/cgi-bin/extrahd.cgi
suricata: Change midstream policy to "pass-flow"
[ipfire-2.x.git] / html / cgi-bin / extrahd.cgi
CommitLineData
aa2870e6 1#!/usr/bin/perl
70df8302
MT
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
569c9ac6 5# Copyright (C) 2023 IPFire Team <info@ipfire.org> #
70df8302
MT
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
aa2870e6
MT
21
22use strict;
23# enable only the following on debugging purpose
cb5e9c6c
CS
24#use warnings;
25#use CGI::Carp 'fatalsToBrowser';
aa2870e6
MT
26
27require '/var/ipfire/general-functions.pl';
28require "${General::swroot}/lang.pl";
29require "${General::swroot}/header.pl";
30
31my %extrahdsettings = ();
aa2870e6 32my $errormessage = "";
56ce3e19 33
d0a6f9bd
SS
34# Hash to store the configured drives.
35my %configured_drives;
36
56ce3e19
SS
37# SYSFS directory which contains all block device data.
38my $sysfs_block_dir = "/sys/class/block";
39
40# Array which contains the valid mount directories.
41# Only mounting to subdirectories inside them is allowed.
42my @valid_mount_dirs = (
43 "/data",
44 "/media",
45 "/mnt",
46);
47
56ce3e19
SS
48# Grab all available block devices.
49my @devices = &get_block_devices();
50
51# Grab all known UUID's.
52my %uuids = &get_uuids();
53
15d9c996
SS
54# Detect device mapper devices.
55my %device_mapper = &get_device_mapper();
56
57# Grab members of group devices (RAID, LVM)
58my %grouped_devices = &collect_grouped_devices();
59
56ce3e19
SS
60# Grab all mountpoints.
61my %mountpoints = &get_mountpoints();
62
63# Omit the file system types of the mounted devices.
64my %filesystems = &get_mountedfs();
65
66# Gather all used swap devices.
67my @swaps = &get_swaps();
68
69# The config file which contains the configured devices.
aa2870e6 70my $devicefile = "/var/ipfire/extrahd/devices";
d5f061e9
MF
71
72#workaround to suppress a warning when a variable is used only once
73my @dummy = ( ${Header::colourgreen}, ${Header::colourred} );
74undef (@dummy);
75
aa2870e6
MT
76&Header::showhttpheaders();
77
78### Values that have to be initialized
79$extrahdsettings{'PATH'} = '';
80$extrahdsettings{'FS'} = '';
81$extrahdsettings{'DEVICE'} = '';
82$extrahdsettings{'ACTION'} = '';
784d72a2 83$extrahdsettings{'UUID'} = '';
aa2870e6 84
aa2870e6
MT
85&Header::getcgihash(\%extrahdsettings);
86
87&Header::openpage('ExtraHD', 1, '');
88&Header::openbigbox('100%', 'left', '', $errormessage);
89
90############################################################################################################################
91############################################################################################################################
92
56ce3e19
SS
93#
94## Add a new device.
95#
96if ($extrahdsettings{'ACTION'} eq $Lang::tr{'add'}) {
72dfa1b0
SS
97 # Check if a mount path has been given.
98 if (not $extrahdsettings{'PATH'}) {
99 $errormessage = "$Lang::tr{'extrahd no mount point given'}.";
100
7907c1e0 101 # Check if a valid mount path has been choosen.
72dfa1b0
SS
102 } elsif(not &is_valid_dir("$extrahdsettings{'PATH'}")) {
103 $errormessage = "$Lang::tr{'extrahd you cant mount'} $extrahdsettings{'DEVICE'} $Lang::tr{'extrahd to'} $extrahdsettings{'PATH'} $Lang::tr{'extrahd because it is outside the allowed mount path'}.";
56ce3e19
SS
104
105 # Check if the given path allready is mounted somewhere.
72dfa1b0
SS
106 } elsif(&is_mounted("$extrahdsettings{'PATH'}")) {
107 $errormessage = "$Lang::tr{'extrahd you cant mount'} $extrahdsettings{'DEVICE'} $Lang::tr{'extrahd to'} $extrahdsettings{'PATH'} $Lang::tr{'extrahd because there is already a device mounted'}.";
56ce3e19
SS
108 }
109
7907c1e0
SS
110 # Check against may previously configured drives.
111 unless ($errormessage) {
112 # Open device file for reading.
113 open( FILE, "< $devicefile" ) or die "Unable to read $devicefile";
114 my @devices = <FILE>;
115 close FILE;
116
117 # Loop through the entries line-by-line.
118 foreach my $entry (sort @devices) {
119 # Split the line into pieces and assign nice variables.
120 my ($uuid, $fs, $path) = split( /\;/, $entry );
121
66cb52cb
SS
122 # Remove tailing UUID= from uuid string.
123 $uuid =~ s{^UUID=}{};
124
7907c1e0
SS
125 # Check if the path is allready used.
126 if ( "$extrahdsettings{'PATH'}" eq "$path" ) {
72dfa1b0 127 $errormessage = "$Lang::tr{'extrahd you cant mount'} $extrahdsettings{'DEVICE'} $Lang::tr{'extrahd to'} $extrahdsettings{'PATH'} $Lang::tr{'extrahd because there is already a device mounted'}.";
7907c1e0
SS
128 }
129
130 # Check if the uuid is allready used.
66cb52cb 131 if ("$extrahdsettings{'UUID'}" eq "$uuid") {
7907c1e0
SS
132 $errormessage = "$extrahdsettings{'DEVICE'} is allready mounted.";
133 }
134 }
135 }
136
137 # Go further if there was no error message.
56ce3e19
SS
138 unless($errormessage) {
139 # Re-open the device file for writing.
aa2870e6 140 open(FILE, ">> $devicefile" ) or die "Unable to write $devicefile";
56ce3e19
SS
141
142 # Write the config line.
143 print FILE "UUID=$extrahdsettings{'UUID'};$extrahdsettings{'FS'};$extrahdsettings{'PATH'};\n";
144
145 # Close file handle.
146 close(FILE);
147
148 # Call helper binary to mount the device.
149 &General::system("/usr/local/bin/extrahdctrl", "mount", "$extrahdsettings{'PATH'}");
aa2870e6 150 }
56ce3e19
SS
151
152#
153# Remove an existing one.
154#
155} elsif ($extrahdsettings{'ACTION'} eq $Lang::tr{'delete'}) {
156 # Call helper binary to unmount the device.
94aeac8a
SS
157 unless(&General::system("/usr/local/bin/extrahdctrl", "umount", "$extrahdsettings{'PATH'}")) {
158 # Open the device file for reading.
159 open(FILE, "< $devicefile" ) or die "Unable to read $devicefile";
56ce3e19 160
94aeac8a
SS
161 # Read the file content into a temporary array.
162 my @tmp = <FILE>;
56ce3e19 163
94aeac8a
SS
164 # Close file handle.
165 close(FILE);
56ce3e19 166
94aeac8a
SS
167 # Re-open device file for writing.
168 open(FILE, "> $devicefile" ) or die "Unable to write $devicefile";
56ce3e19 169
94aeac8a
SS
170 # Loop through the previous read file content.
171 foreach my $line (sort @tmp) {
172 # Split line content and assign nice variables.
173 my ($uuid, $fs, $path) = split( /\;/, $line );
56ce3e19 174
94aeac8a
SS
175 # Write the line in case it does not contain our element to delete.
176 if ($path ne $extrahdsettings{'PATH'}) {
177 print FILE "$line";
178 }
aa2870e6 179 }
56ce3e19 180
94aeac8a
SS
181 # Close file handle.
182 close(FILE);
183 } else {
184 $errormessage = "$Lang::tr{'extrahd cant umount'} $extrahdsettings{'PATH'}$Lang::tr{'extrahd maybe the device is in use'}?";
185 }
aa2870e6
MT
186}
187
188if ($errormessage) {
189 &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
190 print "<class name='base'>$errormessage\n";
191 print "&nbsp;</class>\n";
192 &Header::closebox();
193}
194
195############################################################################################################################
196############################################################################################################################
197
d0a6f9bd
SS
198&Header::openbox('100%', 'center', $Lang::tr{'extrahd detected drives'});
199
56ce3e19
SS
200 # Re-read mountpoints.
201 %mountpoints = &get_mountpoints();
3a69c4fb 202
56ce3e19
SS
203 # Read-in the device config file.
204 open( FILE, "< $devicefile" ) or die "Unable to read $devicefile";
56ce3e19
SS
205
206 # Loop through the file content.
d0a6f9bd
SS
207 while (<FILE>) {
208 # Cut the line into pieces.
209 my ($uuid, $fs, $path) = split( /\;/, $_ );
56ce3e19 210
d0a6f9bd
SS
211 # Add the found entry to the hash of configured drives.
212 $configured_drives{$uuid} = $path;
aa2870e6 213 }
56ce3e19 214
d0a6f9bd
SS
215 # Close the file handle.
216 close(FILE);
217
aa2870e6
MT
218 print <<END
219 <table border='0' width='600' cellspacing="0">
220END
221;
56ce3e19
SS
222 foreach my $device (sort @devices) {
223 # Grab the device details.
224 my $vendor = &get_device_vendor($device);
225 my $model = &get_device_model($device);
226 my $bsize = &get_device_size($device);
227
228 # Convert size into human-readable format.
229 my $size = &General::formatBytes($bsize);
230
231 print <<END
232 <tr><td colspan="5">&nbsp;</td></tr>
233 <tr><td align='left' colspan="2"><b>/dev/$device</b></td>
234 <td align='center' colspan="2">$vendor $model</td>
235
236 <td align='center'>$Lang::tr{'size'} $size</td>
237 <td>&nbsp;</td></tr>
238 <tr><td colspan="5">&nbsp;</td></tr>
aa2870e6
MT
239END
240;
20730a6f 241
56ce3e19
SS
242 # Grab the known partitions of the current block device.
243 my @partitions = &get_device_partitions($device);
244
15d9c996
SS
245 # Check if the block device has any partitions for display.
246 if (@partitions) {
247 # Loop through the partitions.
248 foreach my $partition (@partitions) {
249 # Call function to display the row in the WUI.
250 &print_row($partition);
251 }
252 }
253
254 # Also print rows for devices with an UUID.
255 &print_row($device) if($uuids{$device});
256 }
56ce3e19 257
15d9c996
SS
258 print <<END
259 <tr><td align="center" colspan="5">&nbsp;</td></tr>
260 <tr><td align="center" colspan="5">&nbsp;</td></tr>
261 <tr><td align="center" colspan="5">$Lang::tr{'extrahd install or load driver'}</td></tr>
262 </table>
263END
264;
56ce3e19 265
15d9c996 266&Header::closebox();
56ce3e19 267
15d9c996
SS
268&Header::closebigbox();
269&Header::closepage();
480c5253 270
56ce3e19 271
15d9c996
SS
272#
273# Function to print a table row with device data on the WUI.
274#
275sub print_row ($) {
276 my ($partition) = @_;
d0a6f9bd 277
15d9c996 278 my $disabled;
d0a6f9bd 279
15d9c996
SS
280 # Omit the partition size.
281 my $bsize = &get_device_size($partition);
d0a6f9bd 282
15d9c996
SS
283 # Convert into human-readable format.
284 my $size = &General::formatBytes($bsize);
d0a6f9bd 285
15d9c996
SS
286 # Try to omit the used filesystem.
287 my $fs = $filesystems{$partition};
56ce3e19 288
15d9c996
SS
289 # Get the mountpoint.
290 my $mountpoint = $mountpoints{$partition};
56ce3e19 291
15d9c996
SS
292 # Generate partition string.
293 my $partition_string = "/dev/$partition";
56ce3e19 294
15d9c996
SS
295 # Check if the given partition is managed by device mapper.
296 if (exists($device_mapper{$partition})) {
297 # Alter the partition string to used one by the device mapper.
298 $partition_string = "$device_mapper{$partition}";
299 }
300
301 # Check if the device is part of a group.
302 my $grouped_device = &is_grouped_member($partition);
303
304 # If no mountpoint could be determined try to grab from
305 # configured drives.
306 unless($mountpoint) {
307 my $uuid = $uuids{$partition};
308
309 # Build uuid string.
310 $uuid = "UUID=" . $uuid;
311
312 # Try to obtain a possible moutpoint from configured drives.
313 $mountpoint = $configured_drives{$uuid} if ($configured_drives{$uuid});
314 }
315
316 # Check if the mountpoint is used as root or boot device.
317 if ($mountpoint eq "/" or $mountpoint =~ "^/boot") {
318 $disabled = "disabled";
319
320 # Check if it is mounted.
321 } elsif(&is_mounted($mountpoint)) {
322 $disabled = "disabled";
323
324 # Check if the device is used as swap.
325 } elsif (&is_swap($partition)) {
326 $disabled = "disabled";
327 $mountpoint = "swap";
328 $fs = "swap";
329
330 # Check if the device is part of a group.
331 } elsif ($grouped_device) {
332 $disabled = "disabled";
333 $mountpoint = "/dev/$grouped_device";
334 $mountpoint = $device_mapper{$grouped_device} if (exists($device_mapper{$grouped_device}));
335 }
336
337 print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>\n";
338
339 # Only display UUID details if an UUID could be obtained.
340 if ( $uuids{$partition} ) {
341 print "<tr><td align='left' colspan=5><strong>UUID=$uuids{$partition}</strong></td></tr>\n";
aa2870e6
MT
342 }
343
344 print <<END
15d9c996
SS
345
346 <tr>
347 <td align="list">$partition_string</td>
348 <td align="center">$Lang::tr{'size'} $size</td>
349 <td align="center">$fs</td>
350 <td align="center"><input type='text' name='PATH' value='$mountpoint' $disabled></td>
351 <td align="center">
352 <input type='hidden' name='DEVICE' value='$partition_string' />
353 <input type='hidden' name='UUID' value='$uuids{$partition}' />
aa2870e6
MT
354END
355;
15d9c996
SS
356 # Check if the mountpoint refers to a known configured drive.
357 if(&is_configured($mountpoint)) {
358 print "<input type='hidden' name='ACTION' value='$Lang::tr{'delete'}'>\n";
359 print "<input type='hidden' name='PATH' value='$mountpoint'>\n";
360
361 # Check if the device is mounted properly.
362 if(&is_mounted($mountpoint)) {
363 print "<img src='/images/updbooster/updxl-led-green.gif' alt='$Lang::tr{'extrahd mounted'}' title='$Lang::tr{'extrahd mounted'}'>&nbsp;\n";
364 } else {
365 print "<img src='/images/updbooster/updxl-led-red.gif' alt='$Lang::tr{'extrahd not mounted'}' title='$Lang::tr{'extrahd not mounted'}'>&nbsp;\n";
366 }
aa2870e6 367
15d9c996
SS
368 print "<input type='image' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' src='/images/delete.gif'>\n";
369 } else {
370 unless($disabled) {
371 print "<input type='hidden' name='ACTION' value='$Lang::tr{'add'}'>\n";
372 print "<input type='hidden' name='FS' value='auto'>\n";
373 print "<img src='/images/updbooster/updxl-led-gray.gif' alt='$Lang::tr{'extrahd not configured'}' title='$Lang::tr{'extrahd not configured'}'>&nbsp;\n";
374 print "<input type='image' alt='$Lang::tr{'add'}' title='$Lang::tr{'add'}' src='/images/add.gif'>\n";
375 }
376 }
377
378 print <<END
379 </form></td></tr>
380END
381;
382}
a2c88aad
SS
383
384#
385## Function which return an array with all available block devices.
386#
387sub get_block_devices () {
388 my @devices;
389
390 # Open directory from kernel sysfs.
391 opendir(DEVICES, "/sys/block");
392
393 # Loop through the directory.
394 while(readdir(DEVICES)) {
395 # Skip . and ..
396 next if($_ =~ /^\.$/);
397 next if($_ =~ /^\..$/);
398
399 # Skip any loopback and ram devices.
400 next if($_ =~ "^loop");
401 next if($_ =~ "^ram");
402
403 # Add the device to the array of found devices.
404 push(@devices, $_);
405 }
406
407 # Close directory handle.
408 closedir(DEVICES);
409
410 # Return the devices array.
411 return @devices;
412}
413
414#
415## Function which return all partitions of a given block device.
416#
417sub get_device_partitions ($) {
418 my ($device) = @_;
419
420 # Array to store the known partitions for the given
421 # device.
422 my @partitions;
423
424 # Assign device directory.
425 my $device_dir = "$sysfs_block_dir/$device";
426
427 # Abort and return nothing if the device dir does not exist.
428 return unless(-d "$device_dir");
429
430 opendir(DEVICE, "$sysfs_block_dir/$device");
431 while(readdir(DEVICE)) {
432 next unless($_ =~ "^$device");
433
434 push(@partitions, $_);
435 }
436
437 closedir(DEVICE);
438
439 @partitions = sort(@partitions);
440
441 return @partitions;
442}
443
444#
445## Returns the vendor of a given block device.
446#
447sub get_device_vendor ($) {
448 my ($device) = @_;
449
450 # Assign device directory.
451 my $device_dir = "$sysfs_block_dir/$device";
452
453 # Abort and return nothing if the device dir does not exist
454 # or no vendor file exists.
455 return unless(-d "$device_dir");
456 return unless(-f "$device_dir/device/vendor");
457
458 # Open and read-in the device vendor.
459 open(VENDOR, "$device_dir/device/vendor");
460 my $vendor = <VENDOR>;
461 close(VENDOR);
462
463 # Abort and return nothing if no vendor could be read.
464 return unless($vendor);
465
466 # Remove any newlines from the vendor string.
467 chomp($vendor);
468
469 # Return the omited vendor.
470 return $vendor;
471}
472
473#
474## Returns the model name (string) of a given block device.
475#
476sub get_device_model ($) {
477 my ($device) = @_;
478
479 # Assign device directory.
480 my $device_dir = "$sysfs_block_dir/$device";
481
482 # Abort and return nothing if the device dir does not exist
483 # or no model file exists.
484 return unless(-d "$device_dir");
485 return unless(-f "$device_dir/device/model");
486
487 # Open and read-in the device model.
488 open(MODEL, "$device_dir/device/model");
489 my $model = <MODEL>;
490 close(MODEL);
491
492 # Abort and return nothing if no model could be read.
493 return unless($model);
494
495 # Remove any newlines from the model string.
496 chomp($model);
497
498 # Return the model string.
499 return $model;
500}
501
502#
503## Returns the size of a given device in bytes.
504#
505sub get_device_size ($) {
506 my ($device) = @_;
507
508 # Assign device directory.
509 my $device_dir = "$sysfs_block_dir/$device";
510
511 # Abort and return nothing if the device dir does not exist
512 # or no size file exists.
513 return unless(-d "$device_dir");
514 return unless(-f "$device_dir/size");
515
516 # Open and read-in the device size.
517 open(SIZE, "$device_dir/size");
518 my $size = <SIZE>;
519 close(SIZE);
520
521 # Abort and return nothing if the size could not be read.
522 return unless($size);
523
524 # Remove any newlines for the size string.
525 chomp($size);
526
527 # The omited size only contains the amount of blocks from the
528 # given device. To convert this into bytes we have to multiply this
529 # value with 512 bytes for each block. This is a static value used by
530 # the linux kernel.
531 $size = $size * 512;
532
533 # Return the size in bytes.
534 return $size;
535}
536
15d9c996
SS
537#
538## Function which tries to detect if a block device is a device mapper device and returns the alias a
539## a hash. Example: "dm-0" -> "/dev/mapper/GROUP-DEVICE"
540#
541sub get_device_mapper () {
542 my %mapper_devices = ();
543
544 # Loop through all known block devices.
545 foreach my $block_device (@devices) {
546 # Generate device directory.
547 my $device_dir = "$sysfs_block_dir/$block_device";
548
549 # Skip the device if it is not managed by device mapper
550 # In this case the "bd" is not present.
551 next unless (-e "$device_dir/dm");
552
553 # Grab the group and volume name.
554 open(NAME, "$device_dir/dm/name") if (-e "$device_dir/dm/name");
555 my $name = <NAME>;
556 close(NAME);
557
558 # Skip device if no name could be determined.
559 next unless($name);
560
561 # Remove any newlines from the name string.
562 chomp($name);
563
564 # Generate path to the dev node in devfs.
565 my $dev_path = "/dev/mapper/$name";
566
567 # Store the device and the omited mapper name in the hash.
568 $mapper_devices{$block_device} = $dev_path;
569 }
570
571 # Return the hash of omited device mapper devices.
572 return %mapper_devices;
573}
574
575#
576## Function which will collect grouped devices and their members as array in a hash and returns them.
577## For example: "sda1" -> "dm-0" in case /dev/sda1 is assigned to a device mapper group.
578#
579sub collect_grouped_devices () {
580 my %grouped_devices = ();
581
582 # Loop through the array of known block devices.
583 foreach my $device (@devices) {
584 # Generate device directory.
585 my $device_dir = "$sysfs_block_dir/$device";
586
587 # Skip device if it has no members.
588 # In this case the "slaves" directory does not exist.
589 next unless (-e "$device_dir/slaves");
590
591 # Tempoarary array to store the members of a group.
592 my @members = ();
593
594 # Grab all members.
595 opendir(MEMBERS, "$device_dir/slaves");
596 while(readdir(MEMBERS)) {
597 next if($_ eq ".");
598 next if($_ eq "..");
599
600 # Add the found member to the array of members.
601 push(@members, $_);
602 }
603
604 closedir(MEMBERS);
605
606 # Skip the device if no members could be grabbed.
607 next unless (@members);
608
609 # Add the array of found members as value to the hash of grouped devices.
610 $grouped_devices{$device} = [ @members ];
611 }
612
613 # Return the hash of found grouped devices and their members.
614 return %grouped_devices;
615}
616
a2c88aad
SS
617#
618## Function which returns all currently mounted devices as a hash.
619## example: "sda1" -> "/boot"
620#
621sub get_mountpoints () {
622 my %mounts;
623
624 # Open and read-in the current mounts from the
625 # kernel file system.
626 open(MOUNT, "/proc/mounts");
627
628 # Loop through the known mounts.
629 while(<MOUNT>) {
630 # Skip mounts which does not belong to a device.
631 next unless ($_ =~ "^/dev");
632
633 # Cut the line into pieces and assign nice variables.
634 my ($dev, $mpoint, $fs, $options, $a, $b) = split(/ /, $_);
635
636 # Split the device name.
637 my @tmp = split("/", $dev);
638
639 # Assign the plain device name to a new variable.
640 # It is the last element of the array.
641 my $device = $tmp[-1];
642
643 # Add the mountpoint to the hash of mountpoints.
644 $mounts{"$device"} = $mpoint;
645 }
646
647 # Close file handle.
648 close(MOUNT);
649
650 # Return the hash of known mountpoints.
651 return %mounts;
652}
653
654sub get_swaps () {
655 my @swaps;
656
657 # Open and read the swaps file.
658 open(SWAP, "/proc/swaps");
659
660 # Loop though the file content.
661 while(<SWAP>) {
662 # Skip lines which does not belong to a device.
663 next unless ($_ =~ "^/dev");
664
665 # Split the line and assign nice variables.
666 my ($dev, $type, $size, $used, $prio) = split(/ /, $_);
667
668 # Cut the device line into pieces.
669 my @tmp = split("/", $dev);
670
671 my $device = @tmp[-1];
672
673 # Add the found swap to the array of swaps.
674 push(@swaps, $device);
675 }
676
677 # Close file handle.
678 close(SWAP);
679
680 # Sort the array.
681 @swaps = sort(@swaps);
682
683 # Return the array.
684 return @swaps;
685}
686
687#
688## Function with returns the mounted devices and the used filesystems as a hash.
689## Example: "sda1" -> "ext4"
690#
691sub get_mountedfs () {
692 my %mountedfs;
693
694 # Open and read the current mounts from the kernel
695 # file system.
696 open(MOUNT, "/proc/mounts");
697
698 # Loop through the known mounts.
699 while(<MOUNT>) {
700 # Skip mounts which does not belong to a device.
701 next unless ($_ =~ "^/dev");
702
703 # Split line and assign nice variables.
704 my ($dev, $mpoint, $fs, $options, $a, $b) = split(/ /, $_);
705
706 # Cut the device line into pieces.
707 my @tmp = split("/", $dev);
708
709 # Assign the plain device name to a variable
710 # It is the last element of the temporary array.
711 my $device = $tmp[-1];
712
713 # Convert the filesystem into lower case format.
714 $fs = lc($fs);
715
716 # Add the mounted file system.
717 $mountedfs{$device} = $fs;
718 }
719
720 # Close file handle.
721 close(MOUNT);
722
723 # Return the hash with the mounted filesystems.
724 return %mountedfs;
725}
726
727#
728## Function which returns all known UUID's as a hash.
729## Example: "sda1" -> "1234-5678-abcd"
730#
731sub get_uuids () {
732 my %uuids;
733
734 # Directory where the uuid mappings can be found.
735 my $uuid_dir = "/dev/disk/by-uuid";
736
737 # Open uuid directory and read-in the current known uuids.
738 opendir(UUIDS, "$uuid_dir");
739
740 # Loop through the uuids.
741 foreach my $uuid (readdir(UUIDS)) {
742 # Skip . and ..
743 next if($uuid eq "." or $uuid eq "..");
744
745 # Skip everything which is not a symbolic link.
746 next unless(-l "$uuid_dir/$uuid");
747
748 # Resolve the target of the symbolic link.
749 my $target = readlink("$uuid_dir/$uuid");
750
751 # Split the link target into pieces.
752 my @tmp = split("/", $target);
753
754 # Assign the last element of the array to the dev variable.
755 my $dev = "$tmp[-1]";
756
757 # Add the device and uuid to the hash of uuids.
758 $uuids{$dev} = $uuid;
759 }
760
761 # Close directory handle.
762 closedir(UUIDS);
763
764 # Return the hash of uuids.
765 return %uuids;
766}
767
768#
769## Returns the device name of a given uuid.
770#
771sub device_by_uuid ($) {
772 my ($uuid) = @_;
773
774 # Reverse the main uuids hash.
775 my %uuids = reverse %uuids;
776
777 # Lookup and return the device name.
778 return $uuids{$uuid};
779}
780
781#
782## Returns "True" in case a given path is a known mountpoint.
783#
784sub is_mounted ($) {
785 my ($mpoint) = @_;
786
787 my %mountpoints = reverse %mountpoints;
788
789 # Return "True" if the requested mountpoint is known and
790 # therefore mounted.
791 return 1 if($mountpoints{$mpoint});
792}
793
794#
795## Returns "True" if a given mountpoint is a subdirectory of one
796## of the directories specified by the valid_mount_dirs array abouve.
797#
798sub is_valid_dir ($) {
799 my ($mpoint) = @_;
800
19a3b883
SS
801 # Do not allow "/mnt" or "/media" as mount points.
802 return if($mpoint eq "/mnt");
803 return if($mpoint eq "/media");
804
a2c88aad
SS
805 # Split the given mountpoint into pieces and store them
806 # in a temporay array.
807 my @tmp = split("/", $mpoint);
808
809 # Exit and return nothing if the temporary array is empty.
810 return unless(@tmp);
811
812 # Build the root path based on the given mount point.
813 my $root_path = "/" . @tmp[1];
814
815 # Check if the root path is valid.
816 return 1 if(grep /$root_path/, @valid_mount_dirs);
817}
818
819#
820# Returns "True" if a device is used as swap.
821#
822sub is_swap ($) {
823 my ($device) = @_;
824
825 return 1 if(grep /$device/, @swaps);
826}
0aa77c2f
SS
827
828#
829## Returns "True" if a drive is a configured one.
830#
831sub is_configured ($) {
832 my ($path) = @_;
833
834 # Loop through the hash of configured drives.
835 foreach my $uuid (keys %configured_drives) {
836 return 1 if($configured_drives{$uuid} eq "$path");
837 }
838}
15d9c996
SS
839
840#
841## Retruns the device name of the grouped device,if a given device is a group member.
842#
843sub is_grouped_member ($) {
844 my ($device) = @_;
845
846 # Loop through the hash of found grouped devices.
847 foreach my $grouped_device(keys %grouped_devices) {
848 # The found members are stored as arrays.
849 my @members = @{ $grouped_devices{$grouped_device} };
850
851 # Loop through array of members and check if the given
852 # device is part of it.
853 foreach my $member (@members) {
854 return $grouped_device if ($member eq $device);
855 }
856 }
857}