From: Michael Tremer <michael.tremer@ipfire.org>
To: development@lists.ipfire.org
Subject: Re: [PATCH 1/8] extrahd.cgi: Add various perl functions deal with block devices
Date: Sat, 01 Jul 2023 10:19:59 +0100 [thread overview]
Message-ID: <912D816E-EE89-4FF9-BF8C-258997AD5810@ipfire.org> (raw)
In-Reply-To: <E0689922-A5D5-4BDD-8EB2-7BFB48B4FE5D@ipfire.org>
[-- Attachment #1: Type: text/plain, Size: 10855 bytes --]
Stefan, could you please send a link to the CGI file so it can be downloaded easily without putting all these patches together?
> On 25 Jun 2023, at 04:43, jon <jon.murphy(a)ipfire.org> wrote:
>
> Stefan,
>
> I tried to apply this patch but it doesn’t seem to work.
>
> I notice there are no lines that begin with `-`.
>
> Does this patch start from a blank `extrahd.cgi` file?
>
>
> Jon
>
>
>
>> On Jun 22, 2023, at 11:01 PM, Stefan Schantl <stefan.schantl(a)ipfire.org> wrote:
>>
>> This functions are going to replace the former used scan/write to file/read from
>> file approach by directly collecting the required informations from the
>> kernel sysfs and devfs.
>>
>> Signed-off-by: Stefan Schantl <stefan.schantl(a)ipfire.org>
>> ---
>> html/cgi-bin/extrahd.cgi | 360 +++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 360 insertions(+)
>>
>> diff --git a/html/cgi-bin/extrahd.cgi b/html/cgi-bin/extrahd.cgi
>> index 36c0efc2e..44065a8a1 100644
>> --- a/html/cgi-bin/extrahd.cgi
>> +++ b/html/cgi-bin/extrahd.cgi
>> @@ -255,3 +255,363 @@ END
>>
>> &Header::closebigbox();
>> &Header::closepage();
>> +
>> +#
>> +## Function which return an array with all available block devices.
>> +#
>> +sub get_block_devices () {
>> + my @devices;
>> +
>> + # Open directory from kernel sysfs.
>> + opendir(DEVICES, "/sys/block");
>> +
>> + # Loop through the directory.
>> + while(readdir(DEVICES)) {
>> + # Skip . and ..
>> + next if($_ =~ /^\.$/);
>> + next if($_ =~ /^\..$/);
>> +
>> + # Skip any loopback and ram devices.
>> + next if($_ =~ "^loop");
>> + next if($_ =~ "^ram");
>> +
>> + # Add the device to the array of found devices.
>> + push(@devices, $_);
>> + }
>> +
>> + # Close directory handle.
>> + closedir(DEVICES);
>> +
>> + # Return the devices array.
>> + return @devices;
>> +}
>> +
>> +#
>> +## Function which return all partitions of a given block device.
>> +#
>> +sub get_device_partitions ($) {
>> + my ($device) = @_;
>> +
>> + # Array to store the known partitions for the given
>> + # device.
>> + my @partitions;
>> +
>> + # Assign device directory.
>> + my $device_dir = "$sysfs_block_dir/$device";
>> +
>> + # Abort and return nothing if the device dir does not exist.
>> + return unless(-d "$device_dir");
>> +
>> + opendir(DEVICE, "$sysfs_block_dir/$device");
>> + while(readdir(DEVICE)) {
>> + next unless($_ =~ "^$device");
>> +
>> + push(@partitions, $_);
>> + }
>> +
>> + closedir(DEVICE);
>> +
>> + @partitions = sort(@partitions);
>> +
>> + return @partitions;
>> +}
>> +
>> +#
>> +## Returns the vendor of a given block device.
>> +#
>> +sub get_device_vendor ($) {
>> + my ($device) = @_;
>> +
>> + # Assign device directory.
>> + my $device_dir = "$sysfs_block_dir/$device";
>> +
>> + # Abort and return nothing if the device dir does not exist
>> + # or no vendor file exists.
>> + return unless(-d "$device_dir");
>> + return unless(-f "$device_dir/device/vendor");
>> +
>> + # Open and read-in the device vendor.
>> + open(VENDOR, "$device_dir/device/vendor");
>> + my $vendor = <VENDOR>;
>> + close(VENDOR);
>> +
>> + # Abort and return nothing if no vendor could be read.
>> + return unless($vendor);
>> +
>> + # Remove any newlines from the vendor string.
>> + chomp($vendor);
>> +
>> + # Return the omited vendor.
>> + return $vendor;
>> +}
>> +
>> +#
>> +## Returns the model name (string) of a given block device.
>> +#
>> +sub get_device_model ($) {
>> + my ($device) = @_;
>> +
>> + # Assign device directory.
>> + my $device_dir = "$sysfs_block_dir/$device";
>> +
>> + # Abort and return nothing if the device dir does not exist
>> + # or no model file exists.
>> + return unless(-d "$device_dir");
>> + return unless(-f "$device_dir/device/model");
>> +
>> + # Open and read-in the device model.
>> + open(MODEL, "$device_dir/device/model");
>> + my $model = <MODEL>;
>> + close(MODEL);
>> +
>> + # Abort and return nothing if no model could be read.
>> + return unless($model);
>> +
>> + # Remove any newlines from the model string.
>> + chomp($model);
>> +
>> + # Return the model string.
>> + return $model;
>> +}
>> +
>> +#
>> +## Returns the size of a given device in bytes.
>> +#
>> +sub get_device_size ($) {
>> + my ($device) = @_;
>> +
>> + # Assign device directory.
>> + my $device_dir = "$sysfs_block_dir/$device";
>> +
>> + # Abort and return nothing if the device dir does not exist
>> + # or no size file exists.
>> + return unless(-d "$device_dir");
>> + return unless(-f "$device_dir/size");
>> +
>> + # Open and read-in the device size.
>> + open(SIZE, "$device_dir/size");
>> + my $size = <SIZE>;
>> + close(SIZE);
>> +
>> + # Abort and return nothing if the size could not be read.
>> + return unless($size);
>> +
>> + # Remove any newlines for the size string.
>> + chomp($size);
>> +
>> + # The omited size only contains the amount of blocks from the
>> + # given device. To convert this into bytes we have to multiply this
>> + # value with 512 bytes for each block. This is a static value used by
>> + # the linux kernel.
>> + $size = $size * 512;
>> +
>> + # Return the size in bytes.
>> + return $size;
>> +}
>> +
>> +#
>> +## Function which returns all currently mounted devices as a hash.
>> +## example: "sda1" -> "/boot"
>> +#
>> +sub get_mountpoints () {
>> + my %mounts;
>> +
>> + # Open and read-in the current mounts from the
>> + # kernel file system.
>> + open(MOUNT, "/proc/mounts");
>> +
>> + # Loop through the known mounts.
>> + while(<MOUNT>) {
>> + # Skip mounts which does not belong to a device.
>> + next unless ($_ =~ "^/dev");
>> +
>> + # Cut the line into pieces and assign nice variables.
>> + my ($dev, $mpoint, $fs, $options, $a, $b) = split(/ /, $_);
>> +
>> + # Split the device name.
>> + my @tmp = split("/", $dev);
>> +
>> + # Assign the plain device name to a new variable.
>> + # It is the last element of the array.
>> + my $device = $tmp[-1];
>> +
>> + # Add the mountpoint to the hash of mountpoints.
>> + $mounts{"$device"} = $mpoint;
>> + }
>> +
>> + # Close file handle.
>> + close(MOUNT);
>> +
>> + # Return the hash of known mountpoints.
>> + return %mounts;
>> +}
>> +
>> +sub get_swaps () {
>> + my @swaps;
>> +
>> + # Open and read the swaps file.
>> + open(SWAP, "/proc/swaps");
>> +
>> + # Loop though the file content.
>> + while(<SWAP>) {
>> + # Skip lines which does not belong to a device.
>> + next unless ($_ =~ "^/dev");
>> +
>> + # Split the line and assign nice variables.
>> + my ($dev, $type, $size, $used, $prio) = split(/ /, $_);
>> +
>> + # Cut the device line into pieces.
>> + my @tmp = split("/", $dev);
>> +
>> + my $device = @tmp[-1];
>> +
>> + # Add the found swap to the array of swaps.
>> + push(@swaps, $device);
>> + }
>> +
>> + # Close file handle.
>> + close(SWAP);
>> +
>> + # Sort the array.
>> + @swaps = sort(@swaps);
>> +
>> + # Return the array.
>> + return @swaps;
>> +}
>> +
>> +#
>> +## Function with returns the mounted devices and the used filesystems as a hash.
>> +## Example: "sda1" -> "ext4"
>> +#
>> +sub get_mountedfs () {
>> + my %mountedfs;
>> +
>> + # Open and read the current mounts from the kernel
>> + # file system.
>> + open(MOUNT, "/proc/mounts");
>> +
>> + # Loop through the known mounts.
>> + while(<MOUNT>) {
>> + # Skip mounts which does not belong to a device.
>> + next unless ($_ =~ "^/dev");
>> +
>> + # Split line and assign nice variables.
>> + my ($dev, $mpoint, $fs, $options, $a, $b) = split(/ /, $_);
>> +
>> + # Cut the device line into pieces.
>> + my @tmp = split("/", $dev);
>> +
>> + # Assign the plain device name to a variable
>> + # It is the last element of the temporary array.
>> + my $device = $tmp[-1];
>> +
>> + # Convert the filesystem into lower case format.
>> + $fs = lc($fs);
>> +
>> + # Add the mounted file system.
>> + $mountedfs{$device} = $fs;
>> + }
>> +
>> + # Close file handle.
>> + close(MOUNT);
>> +
>> + # Return the hash with the mounted filesystems.
>> + return %mountedfs;
>> +}
>> +
>> +#
>> +## Function which returns all known UUID's as a hash.
>> +## Example: "sda1" -> "1234-5678-abcd"
>> +#
>> +sub get_uuids () {
>> + my %uuids;
>> +
>> + # Directory where the uuid mappings can be found.
>> + my $uuid_dir = "/dev/disk/by-uuid";
>> +
>> + # Open uuid directory and read-in the current known uuids.
>> + opendir(UUIDS, "$uuid_dir");
>> +
>> + # Loop through the uuids.
>> + foreach my $uuid (readdir(UUIDS)) {
>> + # Skip . and ..
>> + next if($uuid eq "." or $uuid eq "..");
>> +
>> + # Skip everything which is not a symbolic link.
>> + next unless(-l "$uuid_dir/$uuid");
>> +
>> + # Resolve the target of the symbolic link.
>> + my $target = readlink("$uuid_dir/$uuid");
>> +
>> + # Split the link target into pieces.
>> + my @tmp = split("/", $target);
>> +
>> + # Assign the last element of the array to the dev variable.
>> + my $dev = "$tmp[-1]";
>> +
>> + # Add the device and uuid to the hash of uuids.
>> + $uuids{$dev} = $uuid;
>> + }
>> +
>> + # Close directory handle.
>> + closedir(UUIDS);
>> +
>> + # Return the hash of uuids.
>> + return %uuids;
>> +}
>> +
>> +#
>> +## Returns the device name of a given uuid.
>> +#
>> +sub device_by_uuid ($) {
>> + my ($uuid) = @_;
>> +
>> + # Reverse the main uuids hash.
>> + my %uuids = reverse %uuids;
>> +
>> + # Lookup and return the device name.
>> + return $uuids{$uuid};
>> +}
>> +
>> +#
>> +## Returns "True" in case a given path is a known mountpoint.
>> +#
>> +sub is_mounted ($) {
>> + my ($mpoint) = @_;
>> +
>> + my %mountpoints = reverse %mountpoints;
>> +
>> + # Return "True" if the requested mountpoint is known and
>> + # therefore mounted.
>> + return 1 if($mountpoints{$mpoint});
>> +}
>> +
>> +#
>> +## Returns "True" if a given mountpoint is a subdirectory of one
>> +## of the directories specified by the valid_mount_dirs array abouve.
>> +#
>> +sub is_valid_dir ($) {
>> + my ($mpoint) = @_;
>> +
>> + # Split the given mountpoint into pieces and store them
>> + # in a temporay array.
>> + my @tmp = split("/", $mpoint);
>> +
>> + # Exit and return nothing if the temporary array is empty.
>> + return unless(@tmp);
>> +
>> + # Build the root path based on the given mount point.
>> + my $root_path = "/" . @tmp[1];
>> +
>> + # Check if the root path is valid.
>> + return 1 if(grep /$root_path/, @valid_mount_dirs);
>> +}
>> +
>> +#
>> +# Returns "True" if a device is used as swap.
>> +#
>> +sub is_swap ($) {
>> + my ($device) = @_;
>> +
>> + return 1 if(grep /$device/, @swaps);
>> +}
>> --
>> 2.39.2
>>
>>
>
next prev parent reply other threads:[~2023-07-01 9:19 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-23 4:01 Stefan Schantl
2023-06-23 4:01 ` [PATCH 2/8] extrahd.cgi: Refactor code to use new introduced perl functions Stefan Schantl
2023-06-23 4:01 ` [PATCH 3/8] extrahd.cgi: Abort if a device could not be umounted Stefan Schantl
2023-06-23 4:01 ` [PATCH 4/8] extrahd.cgi: Store configured drives in a hash Stefan Schantl
2023-06-23 4:01 ` [PATCH 5/8] extrahd.cgi: Add is_configured function Stefan Schantl
2023-06-23 4:01 ` [PATCH 6/8] extrahd.cgi: Display mount status next to the corresponding drive Stefan Schantl
2023-06-23 4:01 ` [PATCH 7/8] extrahd.cgi: Re-order sanity check logic Stefan Schantl
2023-06-23 4:01 ` [PATCH 8/8] extrahd.cgi: Add missing translation strings Stefan Schantl
2023-06-25 3:43 ` [PATCH 1/8] extrahd.cgi: Add various perl functions deal with block devices jon
2023-07-01 9:19 ` Michael Tremer [this message]
2023-07-01 14:54 ` Stefan Schantl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=912D816E-EE89-4FF9-BF8C-258997AD5810@ipfire.org \
--to=michael.tremer@ipfire.org \
--cc=development@lists.ipfire.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox