Writing submodules for the mod_quotatab module adds to the
number of different data sources (tables) from which the module can obtain its
quota information. The submodule is primarily a collection of functions
that know how to deal with that table (so that mod_quotatab
does not have to), and a way of telling mod_quotatab to use
those table-specific routines.
These submodule callbacks are listed here, along with the types of table (limit or tally) submodules the callbacks apply:
mod_quotatab treats a limit table as a read-only
object, and will never attempt to change its contents.mod_quotatab.mod_quotatab. This callback is necessary, but most
submodules will probably need the callback to simply return
TRUE. Its main purpose is to support verifying the
header on "file"-based quota tables.
The key function that a submodule uses to indicate its existence, and its
willingness to handle a new table format, to mod_quotatab is
the quotatab_register() function:
int quotatab_register(const char *srctype, quota_table_t *(*tab_open)(pool *, quota_tabtype_t, const char *), unsigned int srcflags);This function registers the submodule's open routine, associating it with a given string srctype, so that when
mod_quotatab
see that source type in a QuotaLimitTable or
QuotaTallyTable configuration directive, it can invoke the
submodule's routine.
Example mod_quotatab submodule code:
#include "mod_quotatab.h"
static int exampletab_close(quota_table_t *exampletab) {
int res = 0;
/* Close/clean up after any table-used resources here.
*/
return res;
}
static int exampletab_create(quota_table_t *exampletab) {
int res = 0;
/* Create a new entry in the tally table here.
*/
return res;
}
static unsigned char exampletab_lookup(quota_table_t *exampletab,
const char *name, quota_type_t quota_type) {
unsigned char res = FALSE;
/* Lookup an entry in the limit table that matches the given name and
* quota type here. If found, read the data into the current limit
* structure and return TRUE, otherwise, return FALSE.
*/
return res;
}
static int exampletab_read(quota_table_t *exampletab) {
int res = 0;
/* Read the current session's quota information from the tally table
* into the tally structure. This is done before every update, so that
* the most current tallies are used (eg in the case of multiple users
* in a group, all sharing the same group quota, simultaneously logged
* in). Return -1 if there was an error reading the data.
*/
return res;
}
static int exampletab_rlock(quota_table_t *exampletab) {
int res = 0;
/* Obtain a read-lock on the table. Return 0 if successful, -1 otherwise
* (and set errno appropriately).
*/
return res;
}
static int exampletab_unlock(quota_table_t *exampletab) {
int res = 0;
/* Release a lock, either read- or write-lock, on the given table. Return
* 0 if successful, -1 otherwise (and set errno appropriately).
*/
return res;
}
static unsigned char exampletab_verify(quota_table_t *exampletab) {
unsigned char res = FALSE;
/* After a table is opened, a verification check is done to see that
* that table format meets any special requirements. Return TRUE
* if the table is OK, FALSE if it fails verification.
*/
return res;
}
static int exampletab_write(quota_table_t *exampletab) {
int res = 0;
/* Write the current tally data from the tally structure out to the
* tally table. Return -1 if there was an error writing to the table,
* 0 otherwise.
*/
return res;
}
static int exampletab_wlock(quota_table_t *exampletab) {
int res = 0;
/* Obtain a write-lock on the table. Return 0 if successful, -1
* otherwise (and set errno appropriately).
*/
return res;
}
static quota_table_t *exampletab_open(pool *parent_pool,
quota_tabtype_t tab_type, const char *srcinfo) {
quota_table_t *tab = NULL;
/* The pool pointer passed into this function will always be mod_quotatab's
* static module-specific pool. Allocate a sub-pool from that pool for
* the new table's use.
*/
pool *tab_pool = make_sub_pool(parent_pool);
tab = (quota_table_t *) pcalloc(tab_pool, sizeof(quota_table_t));
tab->tab_pool = tab_pool;
tab->tab_type = tab_type;
/* Now, perform whatever table-opening operations are necessary, depending
* on the table type (tab_type) being opened. The srcinfo string
* given is the submodule-specific string set in the configuration
* file, as part of the Quota{Limit,Tally}Table directives parameters.
*
* If, for some reason, an error occurs while opening this table,
* set errno appropriately and return NULL to signal failure.
*/
/* Once done with all the prep work, make sure the table structure
* function pointer callbacks are filled.
*/
tab->tab_close = exampletab_close;
tab->tab_create = exampletab_create;
tab->tab_lookup = exampletab_lookup;
tab->tab_read = exampletab_read;
tab->tab_verify = exampletab_verify;
tab->tab_write = exampletab_write;
tab->tab_rlock = exampletab_rlock;
tab->tab_unlock = exampletab_unlock;
tab->tab_wlock = exampletab_wlock;
return tab;
}
static int exampletab_init(void) {
/* Initialize the quota source objects for this submodule's type
* ("example"). The registered type is the string that should
* appear as the src-type portion of the Quota{Limit,Tally}Table
* directives parameters (the part before the colon).
*/
quotatab_register("example", exampletab_open,
QUOTATAB_LIMIT_SRC|QUOTATAB_TALLY_SRC);
/* Notice how the third argument to the registration function is an
* OR of QUOTATAB_LIMIT_SRC and QUOTATAB_TALLY_SRC? These flags
* tell mod_quotatab that this submodule can be used for both
* limit tables and tally tables. If a submodule only supported
* one table or the other (for example, LDAP would be great at
* providing quota limit information, but is ill-suited for writes
* and thus not a good tally table format), it would use only the
* flag for the supported table type.
*/
return 0;
}
module quotatab_example_module = {
NULL, NULL,
/* Module API version 2.0 */
0x20,
/* Module name */
"quotatab_example",
/* Module configuration handler table */
NULL,
/* Module command handler table */
NULL,
/* Module authentication handler table */
NULL,
/* Module initialization function */
exampletab_init,
/* Module child initialization function */
NULL
};