IMP Quota command driver, was Re: [dev] Bounties
Etienne Goyer
etienne.goyer at linuxquebec.com
Fri Jan 30 09:07:02 PST 2004
Hi,
Following the discussion of last week concerning the command Quota
driver in IMP, I tried my hand at supporting the new style of output
that is not currently supported. I did not include a patch, as it was
bigger than the file itself; thus I attached the command.php file
instead.
This modified command driver Work For Me (TM), in my test setup. The
code is quite convulated and I am not really satisfied about it. I plan
on fixing that up once I receive feedback on my current approach to the
problem.
AJ, if you want to try it out, just replace
horde/imp/lib/Quota/command.php with the attached one (make a backup
first !). You will need to edit you horde/imp/config/servers.php
config; the quota section of your server description should look like
this :
'quota' => array(
'driver' => 'command',
'params' => array(
'new_quota' => true,
'quota_path' => 'sudo quota',
'partition' => '/dev/sda2'
),
),
Replace the 'partition' value with the partition name for which you want
to retrieve for. I suggest you use sudo to run quota, in which case the
following must be added to your /etc/sudoers (do 'visudo' to edit it) :
Cmnd_Alias QUOTA = /usr/bin/quota
apache ALL= (ALL)NOPASSWD: QUOTA
Let me know if work for you or not. I'll try to help you along if it
does'nt.
Thanks everybody, I await your comments.
On Fri, Jan 23, 2004 at 02:40:34PM -0500, AJ wrote:
> Let me try to explain the difference, because I don't have access to an
> old style quota binary either.
> Here is some output from the NEW quota command:
>
> Disk quotas for user test1 (uid 503):
> Filesystem blocks quota limit grace files quota limit
> /dev/hda2 2724 6000 6000 32 0 0
>
> /dev/hda1 1 6400 6400 1 0 0
>
> The problem is under the filesystem heading. Here, it displays it as a
> device. With the old style command, it displays it as the actual
> filesystem, i.e. /home
> From what I can tell (I may be wrong), the command.php quota driver
> looks in the passwd file for the user's home directory and tries to find
> that in the quota output, which will fail for the new quota binaries.
> This is the problem. Did that help at all? I hope :)
--
Etienne Goyer Linux Québec Technologies Inc.
http://www.LinuxQuebec.com etienne.goyer at linuxquebec.com
Kernel Preemption is a bad idea. Who are the users to think their
trivial tasks are more important than the kernel's ?
-------------- next part --------------
<?php
/**
* Implementation of the Quota API for IMAP servers with a unix quota command.
* This requires a modified "quota" command that allows the httpd server
* account to get quotas for other users. You could use sudo, in which case
* you must have something similar to this in /etc/sudoers :
*
* Cmnd_Alias QUOTA = /usr/bin/quota
* apache ALL= (ALL)NOPASSWD: QUOTA
*
* It also requires that your web server and imap server be the same server or
* at least have shared authentication and file servers (e.g. via NIS/NFS). And
* last, it (as written) requires the POSIX PHP extensions.
*
* You must configure this in horde/imp/config/servers.php. You must
* pass the path to your quota and grep commands as parameters. An example
* config would be something like:
*
* 'quota' => array(
* 'driver' => 'command',
* 'params' => array(
* 'quota_path' => '/usr/bin/quota',
* 'grep_path' => '/bin/grep'
* )
* )
*
* If your quota is relatively recent, its output may look like this :
*
* Disk quotas for user egoyer (uid 500):
* Filesystem blocks quota limit grace files quota limit grace
* /dev/sda2 17 0 10240 8 0 0
*
* If this is the case, you need to use new style of quota parsing. Your
* configuration should look like this :
*
* 'quota' => array(
* 'driver' => 'command',
* 'params' => array(
* 'new_quota' => true,
* 'quota_path' => 'sudo /usr/sbin/quota',
* 'partition' => '/dev/sda2'
* ),
* )
*
* The partition argument must be the partition name of the filesystem you want
* to get quota for.
*
* $Horde: imp/lib/Quota/command.php,v 1.9 2003/09/30 18:33:34 slusarz Exp $
*
* Copyright 2002-2003 Eric Jon Rostetter <eric.rostetter at physics.utexas.edu>
*
* See the enclosed file COPYING for license information (GPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
*
* @author Eric Rostetter <eric.rostetter at physics.utexas.edu>
* @version $Revision: 1.9 $
* @since IMP 4.0
* @package imp.quota
*/
class IMP_Quota_command extends IMP_Quota {
/**
* Constructor
*
* @access public
*
* @param optional array $params Hash containing connection parameters.
*/
function IMP_Quota_command($params = array())
{
$this->_params = array(
'quota_path' => 'quota',
'grep_path' => 'grep'
);
$this->_params = array_merge($this->_params, $params);
}
/**
* Get quota information (used/allocated), in bytes.
*
* @access public
*
* @return mixed An associative array.
* 'limit' = Maximum quota allowed
* 'usage' = Currently used portion of quota (in bytes)
* Returns PEAR_Error on failure.
*/
function getQuota()
{
global $imp;
$imap_user = strtolower($imp['user']);
$passwd_array = posix_getpwnam($imap_user);
$homedir = split('/', $passwd_array['dir']);
if (isset($this->_params['new_quota'])) {
if (!isset($this->_params['partition'])) {
return PEAR::raiseError(_("You must specify the partition to retrieve quota for"), 'horde.error');
}
$cmd = $this->_params['quota_path'] . " $imap_user";
exec($cmd, $cmd_output, $rc);
// Output should be one line for header, then one line per partition for
// for which there is a quota
if ($rc == 0) {
if ((count($cmd_output) == 1) and
preg_match("/Disk quotas for user .+ \(uid \d+\): none/", $cmd_output[0])) {
// No quota fo this user
return array('usage' => 0, 'limit' => 0); // FIXME : is this corrct ?
} else if (count($cmd_output > 1)) { // Parse quota output
// Throw away header
array_shift($cmd_output);
$wrap = false;
$pattern = '/\s*' . str_replace('/', '\/', $this->_params['partition']) . '/';
foreach ($cmd_output as $line) {
$line = preg_replace('/^\s*/', '//', $line);
if ($wrap === true) {
// Partition name wrapped, this line is the output we are looking for
$fields = preg_split('/\s+/', $line);
if (isset($fields[0]) and isset($fields[2])) {
// FIXME this assume 1024 bytes per blocks
return array('usage' => $fields[0] * 1024, 'limit' => $fields[2] * 1024);
} else {
return PEAR::raiseError(_("Unable to retrieve quota"), 'horde.error');
}
}
if (preg_match($pattern, $line)) {
// When partition name is longer that 15 chars, fields goes on the next line
if (strlen($this->_params['partition']) > 15) {
$wrap = true;
} else {
$fields = preg_split('/\s+/', $line);
if (isset($fields[1]) and isset($fields[3])) {
// FIXME this assume 1024 bytes per blocks
return array('usage' => $fields[1] * 1024, 'limit' => $fields[3] * 1024);
} else {
return PEAR::raiseError(_("Unable to retrieve quota"), 'horde.error');
}
}
}
}
}
}
} else {
$cmdline = $this->_params['quota_path'] . " -u $imap_user | " .
$this->_params['grep_path'] . " $homedir[1]";
$junk = exec($cmdline, $quota_data, $return_code);
if (($return_code == 0) && (count($quota_data) == 1)) {
$quota = split("[[:blank:]]+", trim($quota_data[0]));
return array('usage' => $quota[1] * 1024, 'limit' => $quota[2] * 1024);
}
}
return PEAR::raiseError(_("Unable to retrieve quota"), 'horde.error');
}
}
More information about the dev
mailing list