ProFTPD Developer's Guide: Writing Quotatab Submodules

ProFTPD Version 1.2


Table of Contents

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:

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

Table of Contents



Author: $Author: castaglia $
Last Updated: $Date: 2002/09/25 15:57:50 $


© Copyright 2000-2002 TJ Saunders
All Rights Reserved