Current Path : /bin/ |
Linux info 3.0 #1337 SMP Tue Jan 01 00:00:00 CEST 2000 all GNU/Linux
|
Current File : //bin/quotaget |
#!/usr/bin/perl
#
# quotaget - display quota information in an easily parseable format
#
# see POD below for more details
#
# Author: Daniel Hermann
#
# DH-2010-06-18: first version
#
use strict;
use warnings;
use Getopt::Long;
use Pod::Usage;
use File::Basename qw\basename\;
use Quota;
use POSIX qw\getuid\;
my $CALLNAME=basename($0);
##
## Command Line Options
##
my $help = '';
my $debug = '';
my $legacy = 'yes';
my @users;
my @filesystems;
my $result = GetOptions("user=s" => \@users,
"filesystem-list=s" => \@filesystems,
"help" => \$help,
"debug" => \$debug,
"legacy!" => \$legacy)
or pod2usage(2);
pod2usage(0) if ($help);
foreach my $arg (@ARGV) {
push(@filesystems, $arg);
}
##
## Assemble mountpoint and user information
##
# find mountpoints with quotas from /proc/mounts
my %mountpoints;
open(my $mounts,"<","/proc/mounts") or die "$CALLNAME: cannot open /proc/mounts";
while(<$mounts>) {
next if not /(usrquota|usrjquota)/;
my ($dev, $mntpnt, $fstype, $rest) = split(" ");
if (-e $mntpnt) { # ignore mountpoints that don't exist (e.g. in chroot)
$mountpoints{$dev} = $mntpnt;
$mountpoints{$mntpnt} = $mntpnt; # for failsafe mapping $mntpnt -> $dev
}
# if multiple lines for the same device exist in /proc/mounts,
# only the last entry is registered in $mountpoints{$dev}
}
close($mounts);
# if no user was specified on the command line, we put the current uid
# in the array
my $no_user_specified;
if ($#users eq -1) {
push(@users, getuid());
$no_user_specified = 1;
}
# resolve user names to uids (if necessary)
my %uids;
foreach my $user (@users) {
if ($user =~ /^\d*$/) { # a uid was already given
$uids{$user} = $user;
} else {
if (!($uids{$user} = getpwnam($user))) {
print STDERR "$CALLNAME: user $user does not exist.\n";
exit (($legacy)?1:2);
}
}
}
# Quota::query needs formatted device names
my @fs_queryargs;
if ($#filesystems eq -1) { # no filesystems provided on CL
if ($#users eq -1) {
# neither users nor filesystems were provided
print STDERR "$CALLNAME: No filesystem specified.\n";
exit (($legacy)?1:2);
}
# use all mountpoints with quota enabled
foreach my $mntpnt (values %mountpoints) {
if (my $qcarg = Quota::getqcarg($mntpnt)) {
push(@fs_queryargs, $qcarg);
} else {
# ignore mountpoints that cannot be resolved with getqcarg()
}
}
} else { # filesystems given on CL
foreach my $fs (@filesystems) {
my $mntpnt = $mountpoints{$fs};
if (defined $mntpnt) {
if (my $qcarg = Quota::getqcarg($mntpnt)) {
push(@fs_queryargs, $qcarg);
} else {
print STDERR "No quota on $fs\n";
exit 2;
}
}
}
}
if ($#fs_queryargs eq -1) { # Quota::getqcarg was unable to resolve mntpnts
print STDERR "$CALLNAME: No quota on specified filesystems.\n";
exit 2;
}
# remove duplicate entries
@fs_queryargs = keys %{{ map { $_ => 1 } @fs_queryargs }};
## second possible way to remove duplicate entries
#undef %saw;
#my @fs_queryargs = grep { !$saw{$_}++ } @fs_queryargs;
if ($debug) {
print "DEBUG: filesystem queryargs:";
foreach my $fs (@fs_queryargs) {
print " ", $fs;
}
print "\n";
print "DEBUG: users:";
foreach my $user (@users) {
print " ", $user;
}
print "\n";
}
##
## Produce output
##
my $num_dev = $#fs_queryargs + 1;
my $over_quota = '';
# one line for each combination user<->fs
foreach my $fs (@fs_queryargs) {
my $dev = $fs;
$dev =~ s/\(.*\)//;
foreach my $user (@users) {
my $devformat = (($legacy)?"%15s":"%s:");
printf("%s:", $user) unless ($legacy || $no_user_specified);
printf($devformat, $dev) unless ($legacy && ($num_dev<2));
my ($curblocks, $bsoft, $bhard, $btime,
$curinodes, $isoft, $ihard, $itime)
= Quota::query($fs, $uids{$user});
if (!defined($curblocks)) {
print Quota::strerr(), "\n";
} else {
printf("%Lu:%Lu:%Lu:%Lu:%Lu:%Lu:%Lu:%Lu\n",
$bhard, $bsoft, $curblocks,
$ihard,$isoft,$curinodes,
$btime,$itime);
if ($btime || $itime) { $over_quota = 1; }
}
}
}
# Return 1 (over quota) or 0 (not over quota) (unless in legacy mode)
if ($over_quota) {
if ($legacy && $no_user_specified) { exit 0 }
else { exit 1; }
}
1;
__END__
=head1 NAME
quotaget - display quota information in an easily parseable format
=head1 SYNOPSIS
quotaget [options] [-u|--user user]
[[--filesystem-list|-f] filesystem] ...
-u, --user display quota for user
-f, --filesystem-list display quota information only for given
filesystem
Options:
-h, --help brief help message
--legacy|nolegacy do (not) mimic old quotaget (default: legacy)
--debug print out some debug messages
=head1 DESCRIPTION
B<This tool> displays quota information (similarly available with
B<quota>) in such a way that it is more easily parseable in scripts
than the output of B<quota>.
If only one or more filesystems are specified using B<-f>, the quota
are printed for the current process' real userid. A different userid
can be specified with B<-u>.
In legacy mode (which is the default), this tool tries to reproduce
the behaviour of the old quotaget implementation as close as possible.
=head1 EXIT STATUS
B<quotaget> returns 0 if everything is okay (no errors, not over
quota). If the user is over quota on one or more filesystems, 1 is
returned. In case of an error, the return value is >=2.
Note: In legacy mode (which currently is the default mode), the error
code may be 0 even if an overquota condition is detected. It may also
be 1 not only in cases of overquota but also in some error
conditions. Not nice.
=head1 AUTHOR
Written by Daniel Hermann <daniel.hermann@1und1.de>.
=head1 COPYRIGHT
(C) 2010, 1&1 Internet AG
=cut