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 };