From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bernhard Bitsch To: development@lists.ipfire.org Subject: Re: [PATCHv2 02/12] extrahd.cgi: Refactor code to use new introduced perl functions. Date: Wed, 02 Aug 2023 13:48:03 +0200 Message-ID: <5f643930-1155-e42e-2418-0a92f3167cc5@ipfire.org> In-Reply-To: <20230801154839.2373-2-stefan.schantl@ipfire.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1052213502817072217==" List-Id: --===============1052213502817072217== Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Reviewed-by: Bernhard Bitsch Am 01.08.2023 um 17:48 schrieb Stefan Schantl: > This also gets rid of allmost all unsafe system calls. >=20 > Signed-off-by: Stefan Schantl > --- > html/cgi-bin/extrahd.cgi | 336 ++++++++++++++++++++++++--------------- > 1 file changed, 208 insertions(+), 128 deletions(-) >=20 > diff --git a/html/cgi-bin/extrahd.cgi b/html/cgi-bin/extrahd.cgi > index 5aadf15e8..bafdb9fc9 100644 > --- a/html/cgi-bin/extrahd.cgi > +++ b/html/cgi-bin/extrahd.cgi > @@ -29,33 +29,51 @@ require "${General::swroot}/lang.pl"; > require "${General::swroot}/header.pl"; > =20 > my %extrahdsettings =3D (); > -my $message =3D ""; > my $errormessage =3D ""; > -my $size =3D ""; > -my $ok =3D "true"; > -my @tmp =3D (); > -my @tmpline =3D (); > -my $tmpentry =3D ""; > -my @devices =3D (); > -my @deviceline =3D (); > -my $deviceentry =3D ""; > -my @scans =3D (); > -my @scanline =3D (); > -my $scanentry =3D ""; > -my @partitions =3D (); > -my @partitionline =3D (); > -my $partitionentry =3D ""; > + > +# SYSFS directory which contains all block device data. > +my $sysfs_block_dir =3D "/sys/class/block"; > + > +# Array which contains the valid mount directories. > +# Only mounting to subdirectories inside them is allowed. > +my @valid_mount_dirs =3D ( > + "/data", > + "/media", > + "/mnt", > +); > + > +# Array which contains the supported file systems. > +my @supported_filesystems =3D ( > + "auto", > + "ext3", > + "ext4", > + "xfs", > + "vfat", > + "ntfs-3g" > +); > + > +# Grab all available block devices. > +my @devices =3D &get_block_devices(); > + > +# Grab all known UUID's. > +my %uuids =3D &get_uuids(); > + > +# Grab all mountpoints. > +my %mountpoints =3D &get_mountpoints(); > + > +# Omit the file system types of the mounted devices. > +my %filesystems =3D &get_mountedfs(); > + > +# Gather all used swap devices. > +my @swaps =3D &get_swaps(); > + > +# The config file which contains the configured devices. > my $devicefile =3D "/var/ipfire/extrahd/devices"; > -my $scanfile =3D "/var/ipfire/extrahd/scan"; > -my $partitionsfile =3D "/var/ipfire/extrahd/partitions"; > =20 > #workaround to suppress a warning when a variable is used only once > my @dummy =3D ( ${Header::colourgreen}, ${Header::colourred} ); > undef (@dummy); > =20 > -&General::system("/usr/local/bin/extrahdctrl", "scanhd", "ide"); > -&General::system("/usr/local/bin/extrahdctrl", "scanhd", "partitions"); > - > &Header::showhttpheaders(); > =20 > ### Values that have to be initialized > @@ -65,7 +83,6 @@ $extrahdsettings{'DEVICE'} =3D ''; > $extrahdsettings{'ACTION'} =3D ''; > $extrahdsettings{'UUID'} =3D ''; > =20 > -&General::readhash("${General::swroot}/extrahd/settings", \%extrahdsetting= s); > &Header::getcgihash(\%extrahdsettings); > =20 > &Header::openpage('ExtraHD', 1, ''); > @@ -74,52 +91,88 @@ $extrahdsettings{'UUID'} =3D ''; > #########################################################################= ################################################### > #########################################################################= ################################################### > =20 > -if ($extrahdsettings{'ACTION'} eq $Lang::tr{'add'}) > -{ > +# > +## Add a new device. > +# > +if ($extrahdsettings{'ACTION'} eq $Lang::tr{'add'}) { > + # Open device file for reading. > open( FILE, "< $devicefile" ) or die "Unable to read $devicefile"; > - @devices =3D ; > + my @devices =3D ; > close FILE; > - foreach $deviceentry (sort @devices) > - { > - @deviceline =3D split( /\;/, $deviceentry ); > - if ( "$extrahdsettings{'PATH'}" eq "$deviceline[2]" ) { > - $ok =3D "false"; > + > + # Loop through the entries line-by-line. > + foreach my $entry (sort @devices) { > + # Split the line into pieces and assign nice variables. > + my ($uuid, $fs, $path) =3D split( /\;/, $entry ); > + > + # Check if the path is allready used. > + if ( "$extrahdsettings{'PATH'}" eq "$path" ) { > $errormessage =3D "$Lang::tr{'extrahd you cant mount'} $extrahdsetting= s{'DEVICE'} $Lang::tr{'extrahd to'} $extrahdsettings{'PATH'}$Lang::tr{'extrah= d because there is already a device mounted'}."; > } > - if ( "$extrahdsettings{'PATH'}" eq "/" ) { > - $ok =3D "false"; > - $errormessage =3D "$Lang::tr{'extrahd you cant mount'} $extrahdsettings= {'DEVICE'} $Lang::tr{'extrahd to root'}."; > + > + # Check if the uuid is allready used. > + if ("$extrahdsettings{'DEVICE'} eq $uuid") { > + $errormessage =3D "$extrahdsettings{'DEVICE'} is allready mounted."; > } > } > =20 > - if ( "$ok" eq "true" ) { > + # Check if a valid mount path has been choosen. > + unless(&is_valid_dir("$extrahdsettings{'PATH'}")) { > + $errormessage =3D "$Lang::tr{'extrahd you cant mount'} $extrahdsettings{= 'DEVICE'} $Lang::tr{'extrahd to root'}."; > + } > + > + # Check if the given path allready is mounted somewhere. > + if(&is_mounted("$extrahdsettings{'PATH'}")) { > + $errormessage =3D "$Lang::tr{'extrahd you cant mount'} $extrahdsettings{= 'DEVICE'} $Lang::tr{'extrahd to'} $extrahdsettings{'PATH'}$Lang::tr{'extrahd = because there is already a device mounted'}."; > + } > + > + # Check if there was an error message. > + unless($errormessage) { > + # Re-open the device file for writing. > open(FILE, ">> $devicefile" ) or die "Unable to write $devicefile"; > - print FILE < -UUID=3D$extrahdsettings{'UUID'};$extrahdsettings{'FS'};$extrahdsettings{'P= ATH'}; > -END > -; > - &General::system("/usr/local/bin/extrahdctrl", "mount", "$extrahdsettings= {'PATH'}"); > + > + # Write the config line. > + print FILE "UUID=3D$extrahdsettings{'UUID'};$extrahdsettings{'FS'};$extr= ahdsettings{'PATH'};\n"; > + > + # Close file handle. > + close(FILE); > + > + # Call helper binary to mount the device. > + &General::system("/usr/local/bin/extrahdctrl", "mount", "$extrahdsetting= s{'PATH'}"); > } > -} > -elsif ($extrahdsettings{'ACTION'} eq $Lang::tr{'delete'}) > -{ > - if ( ! &General::system("/usr/local/bin/extrahdctrl", "umount", "$extrahd= settings{'PATH'}")) { > - open( FILE, "< $devicefile" ) or die "Unable to read $devicefile"; > - @tmp =3D ; > - close FILE; > - open( FILE, "> $devicefile" ) or die "Unable to write $devicefile"; > - foreach $deviceentry (sort @tmp) > - { > - @tmpline =3D split( /\;/, $deviceentry ); > - if ( $tmpline[2] ne $extrahdsettings{'PATH'} ) > - { > - print FILE $deviceentry; > - } > +=09 > +# > +# Remove an existing one. > +# > +} elsif ($extrahdsettings{'ACTION'} eq $Lang::tr{'delete'}) { > + # Call helper binary to unmount the device. > + &General::system("/usr/local/bin/extrahdctrl", "umount", "$extrahdsetting= s{'PATH'}"); > + > + # Open the device file for reading. > + open(FILE, "< $devicefile" ) or die "Unable to read $devicefile"; > + > + # Read the file content into a temporary array. > + my @tmp =3D ; > + > + # Close file handle. > + close(FILE); > + > + # Re-open device file for writing. > + open(FILE, "> $devicefile" ) or die "Unable to write $devicefile"; > + > + # Loop through the previous read file content. > + foreach my $line (sort @tmp) { > + # Split line content and assign nice variables. > + my ($uuid, $fs, $path) =3D split( /\;/, $line ); > + > + # Write the line in case it does not contain our element to delete. > + if ($path ne $extrahdsettings{'PATH'}) { > + print FILE "$line"; > } > - close FILE; > - } else { > - $errormessage =3D "$Lang::tr{'extrahd cant umount'} $extrahdsettings{'PA= TH'}$Lang::tr{'extrahd maybe the device is in use'}?"; > } > + > + # Close file handle. > + close(FILE); > } > =20 > if ($errormessage) { > @@ -132,34 +185,38 @@ if ($errormessage) { > #########################################################################= ################################################### > #########################################################################= ################################################### > =20 > - open( FILE, "< $devicefile" ) or die "Unable to read $devicefile"; > - @devices =3D ; > - close FILE; > print < > END > ; > - foreach $deviceentry (sort @devices) > - { > - @deviceline =3D split( /\;/, $deviceentry ); > - my $color=3D"$Header::colourred"; > + # Re-read mountpoints. > + %mountpoints =3D &get_mountpoints(); > =20 > - # Use safe system_output to get mountpoint details. > - my @mountpoint =3D &General::system_output("/bin/mountpoint", "$deviceli= ne[2]"); > + # Read-in the device config file. > + open( FILE, "< $devicefile" ) or die "Unable to read $devicefile"; > + my @configfile =3D ; > + close FILE; > + > + # Loop through the file content. > + foreach my $entry (sort @configfile) { > + my ($uuid, $fs, $path) =3D split( /\;/, $entry ); > + my $color=3D"$Header::colourred"; > =20 > - if ( ! grep(/not/, @mountpoint)) { > + # Check if the device is currently mounted. > + if (&is_mounted($path)) { > $color=3D$Header::colourgreen; > } > + > print < > - > - > - > + > + > + > > @@ -170,78 +227,101 @@ END >
 
$deviceline[0]$deviceline[1]$deviceline[2]
$uuid$fs$path >
> - > - > - > + > + > + > > >
> END > ; > + > &Header::openbox('100%', 'center', $Lang::tr{'extrahd detected drives'}); > print < > END > ; > - open( FILE, "< $scanfile" ) or die "Unable to read $scanfile"; > - @scans =3D ; > - close FILE; > - open( FILE, "< $partitionsfile" ) or die "Unable to read $partitionsfile"; > - @partitions =3D ; > - close FILE; > - foreach $scanentry (sort @scans) > - { > - @scanline =3D split( /\;/, $scanentry ); > - # remove wrong entries like usb controller name > - if ($scanline[1] ne "\n") > - { > - print < - > - > - > + foreach my $device (sort @devices) { > + # Grab the device details. > + my $vendor =3D &get_device_vendor($device); > + my $model =3D &get_device_model($device); > + my $bsize =3D &get_device_size($device); > + > + # Convert size into human-readable format. > + my $size =3D &General::formatBytes($bsize); > + > + print < + > + > + > + > + > + > + > END > ; > =20 > - } > - foreach $partitionentry (sort @partitions) > - { > - @partitionline =3D split( /\;/, $partitionentry ); > - if ( "$partitionline[0]" eq "$scanline[0]" ) { > - $size =3D int($partitionline[1] / 1024); > - print < - > - > - > + # Grab the known partitions of the current block device. > + my @partitions =3D &get_device_partitions($device); > + > + foreach my $partition (@partitions) { > + my $disabled; > + > + # Omit the partition size. > + my $bsize =3D &get_device_size($partition); > + > + # Convert into human-readable format. > + my $size =3D &General::formatBytes($bsize); > + > + # Get the mountpoint. > + my $mountpoint =3D $mountpoints{$partition}; > + > + if ($mountpoint eq "/" or $mountpoint =3D~ "^/boot") { > + $disabled =3D "disabled"; > + } elsif(&is_mounted($mountpoint)) { > + $disabled =3D "disabled"; > + } > + > + # Omit the used filesystem. > + my $fs =3D $filesystems{$partition}; > + > + # Check if the device is used as swap. > + if (&is_swap($partition)) { > + $disabled =3D "disabled"; > + $mountpoint =3D "swap"; > + } > + > + print < + > +
> +
> + > + > + > + > - > - > - > - > - > + # Mark the used filesystem as selected. > + if ($filesystem eq $fs) { > + $selected =3D "selected"; > + } > + > + print "\n= "; > + } > + > + print < + > + > > END > -; > +; unless($disabled) { > + print"\n"; > + } > =20 > + print < + > END > -; > - } > - } > +; } > + > } > =20 > print <
 
/dev/$scanline[0]$scanline[1]
 
/dev/$device$vendor $model$Lang::tr{'size'} $size 
 
$Lang::tr{'size'} $size MB 
 
UUID=3D$uuids{$partition}
/dev/$partition$Lang::tr{'size'} $size
UUID=3D$partitionline[2]
/dev/$partitionline[0]$Lang::tr{'size'} $size MB > - > - > + > + > > - > -