From mboxrd@z Thu Jan 1 00:00:00 1970 From: Michael Tremer 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 Message-ID: <912D816E-EE89-4FF9-BF8C-258997AD5810@ipfire.org> In-Reply-To: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1602217428305750933==" List-Id: --===============1602217428305750933== Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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 wrote: >=20 > Stefan, >=20 > I tried to apply this patch but it doesn=E2=80=99t seem to work. >=20 > I notice there are no lines that begin with `-`. >=20 > Does this patch start from a blank `extrahd.cgi` file? >=20 >=20 > Jon >=20 >=20 >=20 >> On Jun 22, 2023, at 11:01 PM, Stefan Schantl = wrote: >>=20 >> This functions are going to replace the former used scan/write to file/rea= d from >> file approach by directly collecting the required informations from the >> kernel sysfs and devfs. >>=20 >> Signed-off-by: Stefan Schantl >> --- >> html/cgi-bin/extrahd.cgi | 360 +++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 360 insertions(+) >>=20 >> 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 >>=20 >> &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($_ =3D~ /^\.$/); >> + next if($_ =3D~ /^\..$/); >> + >> + # Skip any loopback and ram devices. >> + next if($_ =3D~ "^loop"); >> + next if($_ =3D~ "^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) =3D @_; >> + >> + # Array to store the known partitions for the given >> + # device. >> + my @partitions; >> + >> + # Assign device directory. >> + my $device_dir =3D "$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($_ =3D~ "^$device"); >> + >> + push(@partitions, $_); >> + } >> + >> + closedir(DEVICE); >> + >> + @partitions =3D sort(@partitions); >> + >> + return @partitions; >> +} >> + >> +# >> +## Returns the vendor of a given block device. >> +# >> +sub get_device_vendor ($) { >> + my ($device) =3D @_; >> + >> + # Assign device directory. >> + my $device_dir =3D "$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 =3D ; >> + 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) =3D @_; >> + >> + # Assign device directory. >> + my $device_dir =3D "$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 =3D ; >> + 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) =3D @_; >> + >> + # Assign device directory. >> + my $device_dir =3D "$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 =3D ; >> + 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 =3D $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() { >> + # Skip mounts which does not belong to a device. >> + next unless ($_ =3D~ "^/dev"); >> + >> + # Cut the line into pieces and assign nice variables. >> + my ($dev, $mpoint, $fs, $options, $a, $b) =3D split(/ /, $_); >> + >> + # Split the device name. >> + my @tmp =3D split("/", $dev); >> + >> + # Assign the plain device name to a new variable. >> + # It is the last element of the array. >> + my $device =3D $tmp[-1]; >> + >> + # Add the mountpoint to the hash of mountpoints. >> + $mounts{"$device"} =3D $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() { >> + # Skip lines which does not belong to a device. >> + next unless ($_ =3D~ "^/dev"); >> + >> + # Split the line and assign nice variables. >> + my ($dev, $type, $size, $used, $prio) =3D split(/ /, $_); >> + >> + # Cut the device line into pieces. >> + my @tmp =3D split("/", $dev); >> + >> + my $device =3D @tmp[-1]; >> + >> + # Add the found swap to the array of swaps. >> + push(@swaps, $device); >> + } >> + >> + # Close file handle. >> + close(SWAP); >> + >> + # Sort the array. >> + @swaps =3D 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() { >> + # Skip mounts which does not belong to a device. >> + next unless ($_ =3D~ "^/dev"); >> + >> + # Split line and assign nice variables. >> + my ($dev, $mpoint, $fs, $options, $a, $b) =3D split(/ /, $_); >> + >> + # Cut the device line into pieces. >> + my @tmp =3D split("/", $dev); >> + >> + # Assign the plain device name to a variable >> + # It is the last element of the temporary array. >> + my $device =3D $tmp[-1]; >> + >> + # Convert the filesystem into lower case format. >> + $fs =3D lc($fs); >> + >> + # Add the mounted file system. >> + $mountedfs{$device} =3D $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 =3D "/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 =3D readlink("$uuid_dir/$uuid"); >> + >> + # Split the link target into pieces. >> + my @tmp =3D split("/", $target); >> + >> + # Assign the last element of the array to the dev variable. >> + my $dev =3D "$tmp[-1]"; >> + >> + # Add the device and uuid to the hash of uuids. >> + $uuids{$dev} =3D $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) =3D @_; >> + >> + # Reverse the main uuids hash. >> + my %uuids =3D 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) =3D @_; >> + >> + my %mountpoints =3D 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) =3D @_; >> + >> + # Split the given mountpoint into pieces and store them >> + # in a temporay array. >> + my @tmp =3D 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 =3D "/" . @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) =3D @_; >> + >> + return 1 if(grep /$device/, @swaps); >> +} >> --=20 >> 2.39.2 >>=20 >>=20 >=20 --===============1602217428305750933==--