<commit_before># raid-lib.pl
# Functions for managing RAID

BEGIN { push(@INC, ".."); };
use WebminCore;
&init_config();
&foreign_require("fdisk");

open(MODE, "$module_config_directory/mode");
chop($raid_mode = <MODE>);
close(MODE);
$raid_mode ||= "mdadm";

%container = ( 'raiddev', 1,
	       'device', 1 );

# get_raid_levels()
# Returns a list of allowed RAID levels
sub get_raid_levels
{
if ($raid_mode eq "mdadm") {
	return ( 0, 1, 4, 5, 6, 10 );
	}
else {
	return ( 0, 1, 4, 5 );
	}
}

# get_mdstat()
# Read information about active RAID devices. Returns a hash indexed by
# device name (like /dev/md0), with each value being an array reference
# containing  status  level  disks  blocks  resync  disk-info
sub get_mdstat
{
# Read the mdstat file
local %mdstat;
local $lastdev;
open(MDSTAT, $config{'mdstat'});
while(<MDSTAT>) {
	if (/^(md\d+)\s*:\s+(\S+)\s+(\S+)\s+(.*)\s+(\d+)\s+blocks\s*(.*)resync=(\d+)/) {
		$mdstat{$lastdev = "/dev/$1"} = [ $2, $3, $4, $5, $7, $6 ];
		}
	elsif (/^(md\d+)\s*:\s+(\S+)\s+(\S+)\s+(.*)\s+(\d+)\s+blocks\s*(.*)/) {
		$mdstat{$lastdev = "/dev/$1"} = [ $2, $3, $4, $5, undef, $6 ];
		}
	elsif (/^(md\d+)\s*:\s+(\S+)\s+(\S+)\s+(.*)/) {
		$mdstat{$lastdev = "/dev/$1"} = [ $2, $3, $4 ];
		$_ = <MDSTAT>;
		if (/\s+(\d+)\s+blocks\s*(.*)resync=(\d+)/) {
			$mdstat{$lastdev}->[3] = $1;
			$mdstat{$lastdev}->[4] = $3;
			$mdstat{$lastdev}->[5] = $2;
			}
		elsif (/\s+(\d+)\s+blocks\s*(.*)/) {
			$mdstat{$lastdev}->[3] = $1;
			$mdstat{$lastdev}->[5] = $2;
			}
		}
	}
close(MDSTAT);
return %mdstat;
}

# get_raidtab()
# Parse the raid config file into a list of devices
sub get_raidtab
{
local ($raiddev, $device, %mdstat);
return \@get_raidtab_cache if (scalar(@get_raidtab_cache));
%mdstat = &get_mdstat();

if ($raid_mode eq "raidtools") {
	# Read the raidtab file
	local $lnum = 0;
	open(RAID, $config{'raidtab'});
	while(<RAID>) {
		s/\r|\n//g;
		s/#.*$//;
		if (/^\s*(\S+)\s+(\S+)/) {
			local $dir = { 'name' => lc($1),
				       'value' => $2,
				       'line' => $lnum,
				       'eline' => $lnum };
			if ($dir->{'name'} =~ /^(raid|spare|parity|failed)-disk$/) {
				push(@{$device->{'members'}}, $dir);
				$device->{'eline'} = $lnum;
				$raiddev->{'eline'} = $lnum;
				}
			elsif ($dir->{'name'} eq 'raiddev') {
				$dir->{'index'} = scalar(@get_raidtab_cache);
				push(@get_raidtab_cache, $dir);
				}
			else {
				push(@{$raiddev->{'members'}}, $dir);
				$raiddev->{'eline'} = $lnum;
				}
			if ($dir->{'name'} eq 'device') {
				$device = $dir;
				}
			elsif ($dir->{'name'} eq 'raiddev') {
				$raiddev = $dir;
				local $m = $mdstat{$dir->{'value'}};
				$dir->{'active'} = $m->[0] =~ /^active/;
				$dir->{'level'} = $m->[1] =~ /raid(\d+)/ ? $1 : $m->[1];
				$dir->{'devices'} = [
					map { /(\S+)\[\d+\](\((.)\))?/;
					      $3 eq 'F' ? () : ("/dev/$1") }
					    split(/\s+/, $m->[2]) ];
				$dir->{'size'} = $m->[3];
				$dir->{'resync'} = $m->[4];
				$dir->{'errors'} = &disk_errors($m->[5]);
				}
			}
		$lnum++;
		}
	close(RAID);
	}
else {
	# Fake up the same format from mdadm output
	local $m;
	foreach $m (sort { $a cmp $b } keys %mdstat) {
		local $md = { 'value' => $m,
			      'members' => [ ],
			      'index' => scalar(@get_raidtab_cache) };
		local $mdstat = $mdstat{$md->{'value'}};
		$md->{'active'} = $mdstat->[0] =~ /^active/;
		$md->{'level'} = $mdstat->[1] =~ /raid(\d+)/ ? $1 : $mdstat->[1];
		$md->{'devices'} = [
			map { /(\S+)\[\d+\](\((.)\))?/;
			      $3 eq 'F' ? () : (&convert_to_hd("/dev/$1")) }
			    split(/\s+/, $mdstat->[2]) ];
		$md->{'size'} = $mdstat->[3];
		$md->{'resync'} = $mdstat->[4];
		$md->{'errors'} = &disk_errors($mdstat->[5]);
		open(MDSTAT, "mdadm --detail $m |");
		while(<MDSTAT>) {
			if (/^\s*Raid\s+Level\s*:\s*(\S+)/) {
				local $lvl = $1;
				$lvl =~ s/^raid//;
				push(@{$md->{'members'}}, { 'name' => 'raid-level',
							    'value' => $lvl });
				}
			elsif (/^\s*Persistence\s*:\s*(.*)/) {
				push(@{$md->{'members'}},
					{ 'name' => 'persistent-superblock',
					  'value' => $1 =~ /is\s+persistent/ });
				}
			elsif (/^\s*State\s*:\s*(.*)/) {
				$md->{'state'} = $1;
				}
			elsif ((/^\s*Rebuild\s+Status\s*:\s*([0-9\.]+)\s*\%/) || (/^\s*Reshape\s+Status\s*:\s*(\d+)\s*\%/)) {
				$md->{'rebuild'} = $1;
				}
			elsif (/^\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+|\-)\s+(.*\S)\s+(\/\S+)/) {
				# A device line
				local $device = { 'name' => 'device',
						  'value' => $6,
						  'members' => [ ] };
				push(@{$device->{'members'}},
				     { 'name' => $5 eq 'spare' ? 'spare-disk'<commit_msg>Fix parsing of resync status, thanks to <NAME><commit_after># raid-lib.pl
# Functions for managing RAID

BEGIN { push(@INC, ".."); };
use WebminCore;
&init_config();
&foreign_require("fdisk");

open(MODE, "$module_config_directory/mode");
chop($raid_mode = <MODE>);
close(MODE);
$raid_mode ||= "mdadm";

%container = ( 'raiddev', 1,
	       'device', 1 );

# get_raid_levels()
# Returns a list of allowed RAID levels
sub get_raid_levels
{
if ($raid_mode eq "mdadm") {
	return ( 0, 1, 4, 5, 6, 10 );
	}
else {
	return ( 0, 1, 4, 5 );
	}
}

# get_mdstat()
# Read information about active RAID devices. Returns a hash indexed by
# device name (like /dev/md0), with each value being an array reference
# containing  status  level  disks  blocks  resync  disk-info
sub get_mdstat
{
# Read the mdstat file
local %mdstat;
local $lastdev;
open(MDSTAT, $config{'mdstat'});
while(<MDSTAT>) {
	if (/^(md\d+)\s*:\s+(\S+)\s+(\S+)\s+(.*)\s+(\d+)\s+blocks\s*(.*)resync=(\d+)/) {
		$mdstat{$lastdev = "/dev/$1"} = [ $2, $3, $4, $5, $7, $6 ];
		}
	elsif (/^(md\d+)\s*:\s+(\S+)\s+(\S+)\s+(.*)\s+(\d+)\s+blocks\s*(.*)/) {
		$mdstat{$lastdev = "/dev/$1"} = [ $2, $3, $4, $5, undef, $6 ];
		}
	elsif (/^(md\d+)\s*:\s+(\S+)\s+(\S+)\s+(.*)/) {
		$mdstat{$lastdev = "/dev/$1"} = [ $2, $3, $4 ];
		$_ = <MDSTAT>;
		if (/\s+(\d+)\s+blocks\s*(.*)resync=(\d+)/) {
			$mdstat{$lastdev}->[3] = $1;
			$mdstat{$lastdev}->[4] = $3;
			$mdstat{$lastdev}->[5] = $2;
			}
		elsif (/\s+(\d+)\s+blocks\s*(.*)/) {
			$mdstat{$lastdev}->[3] = $1;
			$mdstat{$lastdev}->[5] = $2;
			}
		}
	}
close(MDSTAT);
return %mdstat;
}

# get_raidtab()
# Parse the raid config file into a list of devices
sub get_raidtab
{
local ($raiddev, $device, %mdstat);
return \@get_raidtab_cache if (scalar(@get_raidtab_cache));
%mdstat = &get_mdstat();

if ($raid_mode eq "raidtools") {
	# Read the raidtab file
	local $lnum = 0;
	open(RAID, $config{'raidtab'});
	while(<RAID>) {
		s/\r|\n//g;
		s/#.*$//;
		if (/^\s*(\S+)\s+(\S+)/) {
			local $dir = { 'name' => lc($1),
				       'value' => $2,
				       'line' => $lnum,
				       'eline' => $lnum };
			if ($dir->{'name'} =~ /^(raid|spare|parity|failed)-disk$/) {
				push(@{$device->{'members'}}, $dir);
				$device->{'eline'} = $lnum;
				$raiddev->{'eline'} = $lnum;
				}
			elsif ($dir->{'name'} eq 'raiddev') {
				$dir->{'index'} = scalar(@get_raidtab_cache);
				push(@get_raidtab_cache, $dir);
				}
			else {
				push(@{$raiddev->{'members'}}, $dir);
				$raiddev->{'eline'} = $lnum;
				}
			if ($dir->{'name'} eq 'device') {
				$device = $dir;
				}
			elsif ($dir->{'name'} eq 'raiddev') {
				$raiddev = $dir;
				local $m = $mdstat{$dir->{'value'}};
				$dir->{'active'} = $m->[0] =~ /^active/;
				$dir->{'level'} = $m->[1] =~ /raid(\d+)/ ? $1 : $m->[1];
				$dir->{'devices'} = [
					map { /(\S+)\[\d+\](\((.)\))?/;
					      $3 eq 'F' ? () : ("/dev/$1") }
					    split(/\s+/, $m->[2]) ];
				$dir->{'size'} = $m->[3];
				$dir->{'resync'} = $m->[4];
				$dir->{'errors'} = &disk_errors($m->[5]);
				}
			}
		$lnum++;
		}
	close(RAID);
	}
else {
	# Fake up the same format from mdadm output
	local $m;
	foreach $m (sort { $a cmp $b } keys %mdstat) {
		local $md = { 'value' => $m,
			      'members' => [ ],
			      'index' => scalar(@get_raidtab_cache) };
		local $mdstat = $mdstat{$md->{'value'}};
		$md->{'active'} = $mdstat->[0] =~ /^active/;
		$md->{'level'} = $mdstat->[1] =~ /raid(\d+)/ ? $1 : $mdstat->[1];
		$md->{'devices'} = [
			map { /(\S+)\[\d+\](\((.)\))?/;
			      $3 eq 'F' ? () : (&convert_to_hd("/dev/$1")) }
			    split(/\s+/, $mdstat->[2]) ];
		$md->{'size'} = $mdstat->[3];
		$md->{'resync'} = $mdstat->[4];
		$md->{'errors'} = &disk_errors($mdstat->[5]);
		open(MDSTAT, "mdadm --detail $m |");
		while(<MDSTAT>) {
			if (/^\s*Raid\s+Level\s*:\s*(\S+)/) {
				local $lvl = $1;
				$lvl =~ s/^raid//;
				push(@{$md->{'members'}}, { 'name' => 'raid-level',
							    'value' => $lvl });
				}
			elsif (/^\s*Persistence\s*:\s*(.*)/) {
				push(@{$md->{'members'}},
					{ 'name' => 'persistent-superblock',
					  'value' => $1 =~ /is\s+persistent/ });
				}
			elsif (/^\s*State\s*:\s*(.*)/) {
				$md->{'state'} = $1;
				}
			elsif ((/^\s*Rebuild\s+Status\s*:\s*([0-9\.]+)\s*\%/) || (/^\s*Reshape\s+Status\s*:\s*([0-9\.]+)\s*\%/) || (/^\s*Resync\s+Status\s*:\s*([0-9\.]+)\s*\%/)) {
				$md->{'rebuild'} = $1;
				}
			elsif (/^\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+|\-)\s+(.*\S)\s+(\/\S+)/) {
				# A device line
				local $device = { 'name' => 'device',
						  'value' => $6,
						  'members' => [ ] };
				push(@{$device->{'members'}},
				     { 'name' => $5 eq 'spare' ? 'spare-disk'
{'fraction_non_alphanumeric': 0.31108930323846906, 'fraction_numerical': 0.01613782575509759, 'mean_word_length': 2.776039522437217, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 140, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6766902', 'n_tokens_mistral': 4628, 'n_tokens_neox': 4053, 'n_words': 719}