# quota-lib.pl
# Common functions for quota management.

do '../web-lib.pl';
&init_config();
do "$gconfig{'os_type'}-lib.pl";
%access = &get_module_acl();
&foreign_require("mount", "mount-lib.pl");

# list_filesystems()
# Returns a list of details of local filesystems on which quotas are supported
#  directory device type options quotacan quotanow
sub list_filesystems
{
local $f;
local @mtab = &foreign_call("mount", "list_mounted");
foreach $f (&foreign_call("mount", "list_mounts")) {
	$fmap{$f->[0],$f->[1]} = $f;
	}
map { $_->[4] = &quota_can($_, $fmap{$_->[0],$_->[1]}) } @mtab;
map { $_->[5] = &quota_now($_, $fmap{$_->[0],$_->[1]}) } @mtab;
return grep { $_->[4] } @mtab;
}

# parse_options(type, options)
# Convert an options string for some filesystem into the associative
# array %options
sub parse_options
{
local($_);
undef(%options);
if ($_[0] ne "-") {
	foreach (split(/,/, $_[0])) {
		if (/^([^=]+)=(.*)$/) { $options{$1} = $2; }
		else { $options{$_} = ""; }
		}
	}
}

# user_quota(user, filesystem)
# Returns an array of  ublocks, sblocks, hblocks, ufiles, sfiles, hfiles
# for some user, or an empty array if no quota has been assigned
sub user_quota
{
local (%user, $n, $i);
$n = &filesystem_users($_[1]);
for($i=0; $i<$n; $i++) {
	if ($user{$i,'user'} eq $_[0]) {
		return ( $user{$i,'ublocks'}, $user{$i,'sblocks'},
			 $user{$i,'hblocks'}, $user{$i,'ufiles'},
			 $user{$i,'sfiles'},  $user{$i,'hfiles'} );
		}
	}
return ();
}

# group_quota(group, filesystem)
# Returns an array of  ublocks, sblocks, hblocks, ufiles, sfiles, hfiles
# for some group, or an empty array if no quota has been assigned
sub group_quota
{
local (%group, $n, $i);
$n = &filesystem_groups($_[1]);
for($i=0; $i<$n; $i++) {
	if ($group{$i,'group'} eq $_[0]) {
		return ( $group{$i,'ublocks'}, $group{$i,'sblocks'},
			 $group{$i,'hblocks'}, $group{$i,'ufiles'},
			 $group{$i,'sfiles'},  $group{$i,'hfiles'} );
		}
	}
return ();
}

# edit_user_quota(user, filesys, sblocks, hblocks, sfiles, hfiles)
sub edit_user_quota
{
$ENV{'EDITOR'} = $ENV{'VISUAL'} = "$module_root_directory/edquota.pl";
$ENV{'QUOTA_USER'} = $_[0];
$ENV{'QUOTA_FILESYS'} = $_[1];
$ENV{'QUOTA_SBLOCKS'} = $_[2];
$ENV{'QUOTA_HBLOCKS'} = $_[3];
$ENV{'QUOTA_SFILES'} = $_[4];
$ENV{'QUOTA_HFILES'} = $_[5];
&system_logged("$config{'user_edquota_command'} $_[0] >/dev/null 2>&1");
}

# edit_group_quota(group, filesys, sblocks, hblocks, sfiles, hfiles)
sub edit_group_quota
{
$ENV{'EDITOR'} = $ENV{'VISUAL'} = "$module_root_directory/edquota.pl";
$ENV{'QUOTA_GROUP'} = $_[0];
$ENV{'QUOTA_FILESYS'} = $_[1];
$ENV{'QUOTA_SBLOCKS'} = $_[2];
$ENV{'QUOTA_HBLOCKS'} = $_[3];
$ENV{'QUOTA_SFILES'} = $_[4];
$ENV{'QUOTA_HFILES'} = $_[5];
&system_logged("$config{'group_edquota_command'} $_[0]");
}

# edit_user_grace(filesystem, btime, bunits, ftime, funits)
# Change the grace times for blocks and files on some filesystem
sub edit_user_grace
{
$ENV{'EDITOR'} = $ENV{'VISUAL'} = "$module_root_directory/edgrace.pl";
$ENV{'QUOTA_FILESYS'} = $_[0];
$ENV{'QUOTA_BTIME'} = $_[1];
$ENV{'QUOTA_BUNITS'} = $_[2];
$ENV{'QUOTA_FTIME'} = $_[3];
$ENV{'QUOTA_FUNITS'} = $_[4];
&system_logged($config{'user_grace_command'});
}

# edit_group_grace(filesystem, btime, bunits, ftime, funits)
# Change the grace times for blocks and files on some filesystem
sub edit_group_grace
{
$ENV{'EDITOR'} = $ENV{'VISUAL'} = "$module_root_directory/edgrace.pl";
$ENV{'QUOTA_FILESYS'} = $_[0];
$ENV{'QUOTA_BTIME'} = $_[1];
$ENV{'QUOTA_BUNITS'} = $_[2];
$ENV{'QUOTA_FTIME'} = $_[3];
$ENV{'QUOTA_FUNITS'} = $_[4];
&system_logged($config{'group_grace_command'});
}

# quota_input(name)
sub quota_input
{
printf "<td nowrap><input type=radio name=$_[0]_def value=1 %s> $text{'quota_unlimited'}\n",
	$_[1]==0 ? "checked" : "";
printf "<input type=radio name=$_[0]_def value=0 %s>\n",
	$_[1]==0 ? "" : "checked";
printf "<input name=$_[0] size=8 value=\"%s\"></td> </tr>\n",
	$_[1]==0 ? "" : $_[1];
}

# can_edit_filesys(filesys)
sub can_edit_filesys
{
local $fs;
foreach $fs (split(/\s+/, $access{'filesys'})) {
	return 1 if ($fs eq "*" || $fs eq $_[0]);
	}
return 0;
}

# can_edit_user(user)
sub can_edit_user
{
if ($access{'umode'} == 0) {
	return 1;
	}
elsif ($access{'umode'} == 3) {
	local @u = getpwnam($_[0]);
	return $access{'users'} == $u[3];
	}
elsif ($access{'umode'} == 4) {
	local @u = getpwnam($_[0]);
	return (!$access{'umin'} || $u[2] >= $access{'umin'}) &&
	       (!$access{'umax'} || $u[2] <= $access{'umax'});
	}
else {
	local ($u, %ucan);
	map { $ucan{$_}++ } split(/\s+/, $access{'users'});
	return $access{'umode'} == 1 && $ucan{$_[0]} ||
	       $access{'umode'} == 2 && !$ucan{$_[0]};
	}
}

# can_edit_group(group)
sub can_edit_group
{
return 1 if ($access{'gmode'} == 0);
return 0 if ($access{'gmode'} == 3);
local ($g, %gcan);
map { $gcan{$_}++ } split(/\s+/, $access{'groups'});
return $access{'gmode'} == 1 && $gcan{$_[0]} ||
       $access{'gmode'} == 2 && !$gcan{$_[0]};
}

# filesystem_info(filesystem, &hash, count)
sub filesystem_info
{
local @fs = &free_space($_[0]);
if ($_[1]) {
	local $bt = 0;
	local $ft = 0;
	local $i;
	for($i=0; $i<$_[2]; $i++) {
		$bt += $_[1]->{$i,'hblocks'};
		$ft += $_[1]->{$i,'hfiles'};
		}
	return ( "$fs[0] total / $fs[1] free / $bt granted",
		 "$fs[2] total / $fs[3] free / $ft granted" );
	}
else {
	return ( "$fs[0] total / $fs[1] free",
		 "$fs[2] total / $fs[3] free" );
	}
}

1;

