/*
** Copyright (C) 2006-2010 by Carnegie Mellon University.
**
** @OPENSOURCE_HEADER_START@
**
** Use of the SILK system and related source code is subject to the terms
** of the following licenses:
**
** GNU Public License (GPL) Rights pursuant to Version 2, June 1991
** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
**
** NO WARRANTY
**
** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
** DELIVERABLES UNDER THIS LICENSE.
**
** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
** Mellon University, its trustees, officers, employees, and agents from
** all claims or demands made against them (and any related losses,
** expenses, or attorney's fees) arising out of, or relating to Licensee's
** and/or its sub licensees' negligent use or willful misuse of or
** negligent conduct or willful misconduct regarding the Software,
** facilities, or other rights or assistance granted by Carnegie Mellon
** University under this License, including, but not limited to, any
** claims of product liability, personal injury, death, damage to
** property, or violation of any laws or regulations.
**
** Carnegie Mellon University Software Engineering Institute authored
** documents are sponsored by the U.S. Department of Defense under
** Contract F19628-00-C-0003. Carnegie Mellon University retains
** copyrights in all material produced under this contract. The U.S.
** Government retains a non-exclusive, royalty-free license to publish or
** reproduce these documents, or allow others to do so, for U.S.
** Government purposes only pursuant to the copyright license under the
** contract clause at 252.227.7013.
**
** @OPENSOURCE_HEADER_END@
*/
#ifndef _SKSITE_H
#define _SKSITE_H

#include <silk/silk.h>

RCSIDENTVAR(rcsID_SKSITE_H, "$SiLK: sksite.h 15604 2010-04-08 19:01:04Z mthomas $");

#include <silk/rwrec.h>
#include <silk/skvector.h>


/*
**  sksite.h
**
**  An interface to site-specific settings.
**
*/


/* Add an option for processing the silk.conf configuration file */
#define SK_SITE_FLAG_CONFIG_FILE  0x01


/** Configuration and Initialization **********************************/

/*
 * Initialize everything *except* the sensor configuration from the
 * config file.
 */
int sksiteInitialize(int levels);

/*
 * Register options according to the value of 'flags'.
 *
 * The parameter 'flags' is the bitsize-OR of the the SK_SITE_FLAG_*
 * values listed above.
 */
int sksiteOptionsRegister(uint32_t flags);

/*
 * Print usage information for any options that were registered by
 * sksiteOptionsRegister().
 */
void sksiteOptionsUsage(FILE *fh);

/*
 * Read the configuration file from the default location, or the
 * location set with sksiteSetConfigPath.  If this is called more
 * than once, nothing will happen on later calls.
 *
 * Returns 0 if the configuration has properly loaded; or non-zero
 * otherwise.  Returns -1 to indicate errors parsing the file, or -2
 * if the site configuration file cannot be found.
 *
 * If verbose is 1, this function will report failures to open the
 * file as errors.  If verbose is 0, only parsing failures will be
 * reported.  (For example, if you intend to try opening several
 * files in a row to find the correct file, verbose should be 0 to
 * avoid several reports of open failures.)
 *
 * NOTE: This function should be called single-threaded.
 */
int sksiteConfigure(int verbose);

/*
 * Set the configuration file path.  Attempting to call this after the
 * config file has been read will result in an non-zero return value.
 */
int sksiteSetConfigPath(const char *filename);

/*
 * Return the config file path, setting it to the default location
 * if it has not yet been set.
 */
const char *sksiteGetConfigPath(void);

/*
 * Destroy all the data structures and deallocate all memory
 * associated with the site.
 */
void sksiteTeardown(void);

/** Iterators *********************************************************/

/*
 *    Iterators for the various types of things.  These take a pointer to
 *    an iterator, and a pointer to a pointer of the type being iterated
 *    over.  If the iterator is empty, 0 is returned.  Otherwise, *out_X_id
 *    is set to the next valid ID and 1 is returned.
 */


typedef struct sensor_iter_st {
    /* position in the vector */
    int                 si_index;
    /* vector of candidates */
    sk_vector_t        *si_vector;
    /* 1 if vector contains pointers, 0 if it contains IDs */
    int                 si_contains_pointers;
} sensor_iter_t;

typedef struct class_iter_st {
    /* position in the vector */
    int                 ci_index;
    /* vector of candidates */
    sk_vector_t        *ci_vector;
    /* 1 if vector contains pointers, 0 if it contains IDs */
    int                 ci_contains_pointers;
} class_iter_t;

typedef struct sensorgroup_iter_st {
    /* position in the vector */
    int                 gi_index;
    /* vector of candidates */
    sk_vector_t        *gi_vector;
    /* 1 if vector contains pointers, 0 if it contains IDs */
    int                 gi_contains_pointers;
} sensorgroup_iter_t;

typedef struct flowtype_iter_st {
    /* position in the vector */
    int                 fi_index;
    /* vector of candidates */
    sk_vector_t        *fi_vector;
    /* 1 if vector contains pointers, 0 if it contains IDs */
    int                 fi_contains_pointers;
} flowtype_iter_t;

/*
 *    Return the next value in iterator 'iter' in 'out_sensor_id'.  If
 *    the iterator is finished, returns 0, otherwise returns 1.
 *    Other iterators work identically.
 */
int sksiteSensorIteratorNext(
    sensor_iter_t *iter,
    sensorID_t *out_sensor_id);

int sksiteClassIteratorNext(
    class_iter_t *iter,
    classID_t *out_class_id);

int sksiteSensorgroupIteratorNext(
    sensorgroup_iter_t *iter,
    sensorgroupID_t *out_sensorgroup_id);

int sksiteFlowtypeIteratorNext(
    flowtype_iter_t *iter,
    flowtypeID_t *out_flowtype_id);

/** Sensors ***********************************************************/

/*
 *   Create the sensor 'sensor_name' with id 'sensor_id'.  It is an error
 *   to create a sensor with an ID that is already allocated.  If any
 *   error occurs (sensor ID already in use, illegal sensor name,
 *   out of memory), returns -1.  Otherwise returns 0 on success.
 */
int sksiteSensorCreate(
    sensorID_t sensor_id,
    const char *sensor_name);

/*
 *   Find the sensor ID for a sensor given its name.  Returns
 *   SK_INVALID_SENSOR if no sensor is found with the given name.
 */
sensorID_t sksiteSensorLookup(
    const char *sensor_name);

/*
 *   Return 1 if a sensor with the given sensor ID exists, 0 if no
 *   such sensor has been defined.
 */
int sksiteSensorExists(
    sensorID_t sensor_id);

/*
 *   Returns the minimum sensor ID that has been allocated to a
 *   sensor.  Returns (sensorID_t)(-1) if no sensors yet exist.
 */
sensorID_t sksiteSensorGetMinID(void);

/*
 *   Returns the maximum sensor ID that has been allocated to a
 *   sensor.  Add one to this value to get the lowest ID that is
 *   certain not to have been allocated.  (Note that not all IDs up to
 *   the maximum must have been allocated.)  Returns (sensorID_t)(-1)
 *   if no sensors yet exist.
 */
sensorID_t sksiteSensorGetMaxID(void);

/*
 *   Returns the length of the longest currently known sensor name, or
 *   a minimum value.  This result is suitable for choosing the size
 *   of a display column for sensor names and/or IDs.
 */
size_t sksiteSensorGetMaxNameStrLen(void);

/*
 *   Get the name of the sensor with the given sensor ID into the
 *   given buffer of size buffer_size.  If the name is longer than
 *   buffer_size, the value returns is truncated with a '\0' in the
 *   final position.
 *
 *   Returns the number of characters that would have been written if
 *   the buffer had been long enough.
 */
int sksiteSensorGetName(
    char *buffer,
    size_t buffer_size,
    sensorID_t sensor_id);

/*
 *   Returns 1 if the sensor with ID sensor_id is defined to be in the
 *   class with ID class_id.  Returns 0 otherwise.
 */
int sksiteIsSensorInClass(
    sensorID_t sensor_id,
    classID_t class_id);

/*
 *   Sets iter to be an iterator that loops over all defined sensors.
 */
void sksiteSensorIterator(
    sensor_iter_t  *iter);

/*
 *   Sets iter to be an iterator that loops over all of the classes that
 *   are possessed by the given sensor.
 */
void sksiteSensorClassIterator(
    sensorID_t sensor_id,
    class_iter_t *iter);

/*
 *   Returns 0 if the given name is a legal sensor name containing
 *   no illegal characters and of the proper length.  Returns -1 if
 *   the name does not begin with an alpha character, -2 if the name
 *   is too short, -3 if it is too long.  A positive return value
 *   indicates that the character at position n is invalid.
 */
int sksiteSensorNameIsLegal(
    const char *name);

/*
 *   Returns the number of classes that the given sensor belongs to.
 */
int sksiteSensorGetClassCount(
    sensorID_t sensor_id);

/*
 *   Returns the description of the sensor.  These are specified in
 *   the silk.conf file and are solely for use by the end-user; the
 *   description can be printed with mapsid.  Returns NULL if no
 *   sensor has the ID 'sensor_id' or if the description has not been
 *   set.
 */
const char *sksiteSensorGetDescription(
    sensorID_t          sensor_id);

/*
 *   Sets the description of the given sensor, removing any previous
 *   description.  Returns -1 if 'sensor_id' is not a valid sensor or
 *   on memory allocation errror.  Specify 'sensor_description' as
 *   NULL to clear the current description.
 */
int sksiteSensorSetDescription(
    sensorID_t          sensor_id,
    const char         *sensor_description);

/** Classes ***********************************************************/

/*
 *   Create the class 'class_name' with id 'class_id'.  It is an error
 *   to create a class with an ID that is already allocated.  If any
 *   error occurs (class ID already in use, out of memory), returns
 *   -1.  Otherwise returns 0 on success.
 */
int sksiteClassCreate(
    classID_t class_id,
    const char *class_name);

/*
 *   Sets the default class for fglobbing.  Returns 0 on success.
 */
int sksiteClassSetDefault(
    classID_t class_id);

/*
 *   Returns the default class for fglobbing.
 */
classID_t sksiteClassGetDefault(void);

/*
 *   Find the class ID for a class given its name.  Returns
 *   SK_INVALID_CLASS if no class is found with the given name.
 */
classID_t sksiteClassLookup(
    const char *class_name);

/*
 *   Return 1 if a class with the given class ID exists, 0 if no
 *   such class has been defined.
 */
int sksiteClassExists(
    classID_t class_id);

/*
 *   Returns the maximum class ID that has been allocated to a
 *   class.  Add one to this value to get the lowest ID that is
 *   certain not to have been allocated.  (Note that not all IDs up to
 *   the maximum must have been allocated.)  Returns (classID_t)(-1)
 *   if no classes yet exist.
 */
classID_t sksiteClassGetMaxID(void);

/*
 *   Returns the length of the longest currently known class name, or
 *   a minimum value.  This result is suitable for choosing the size
 *   of a display column for class names and/or IDs.
 */
size_t sksiteClassGetMaxNameStrLen(void);

/*
 *   Get the name of the class with the given class ID into the
 *   given buffer of size buffer_size.  If the name is longer than
 *   buffer_size, the value returns is truncated with a '\0' in the
 *   final position.
 *
 *   Returns the number of characters that would have been written if
 *   the buffer had been long enough.
 */
int sksiteClassGetName(
    char *buffer,
    size_t buffer_size,
    classID_t class_id);

/*
 *   Adds the given sensor to the given class.  Returns 0 on success,
 *   -1 if an error occurred.
 */
int sksiteClassAddSensor(
    classID_t class_id,
    sensorID_t sensor_id);

/*
 *   Adds every sensor in the given sensorgroup to the given class.
 *   Returns 0 on success, -1 if an error occurred.
 */
int sksiteClassAddSensorgroup(
    classID_t class_id,
    sensorgroupID_t sensorgroup_id);

/*
 *   Sets iter to be an iterator that loops over all defined classes.
 */
void sksiteClassIterator(
    class_iter_t *iter);

/*
 *   Sets iter to be an iterator that loops over all sensors in the
 *   given class.
 */
void sksiteClassSensorIterator(
    classID_t class_id,
    sensor_iter_t *iter);

/*
 *   Sets iter to be an iterator that loops over all flowtypes in the
 *   given class.
 */
void sksiteClassFlowtypeIterator(
    classID_t class_id,
    flowtype_iter_t *iter);

/*
 *   Sets iter to be an iterator that loops over all default flowtypes
 *   for the given class.
 */
void sksiteClassDefaultFlowtypeIterator(
    classID_t class_id,
    flowtype_iter_t *iter);

/*
 *   Returns the number of sensors in the given class.
 */
int sksiteClassGetSensorCount(
    classID_t class_id);

/*
 *   Adds the given flowtype to the list of default flowtypes for the
 *   given class.  The flowtype should be a part of this class already.
 *   (i.e. it should have been created with class class_id.)
 *
 *   Returns 0 on success, -1 on any error.
 */
int sksiteClassAddDefaultFlowtype(
    classID_t class_id,
    flowtypeID_t flowtype_id);

/** Sensorgroups ******************************************************/

/*
 *   Create the group 'sensorgroup_name' with id 'sensorgroup_id'.  It
 *   is an error to create a group with an ID that is already
 *   allocated.  If any error occurs (class ID already in use, out of
 *   memory), returns -1.  Otherwise returns 0 on success.
 */
int sksiteSensorgroupCreate(
    sensorgroupID_t sensorgroup_id,
    const char *sensorgroup_name);

/*
 *   Find the sensorgroup ID for a group given its name.  Returns
 *   SK_INVALID_SENSORGROUP if no group is found with the given name.
 */
sensorgroupID_t sksiteSensorgroupLookup(
    const char *sensorgroup_name);

/*
 *   Return 1 if a sensorgroup with the given ID exists, 0 if no such
 *   group has been defined.
 */
int sksiteSensorgroupExists(
    sensorgroupID_t sensorgroup_id);

/*
 *   Returns the maximum ID that has been allocated to a sensorgroup.
 *   Add one to this value to get the lowest ID that is certain not to
 *   have been allocated.  (Note that not all IDs up to the maximum
 *   must have been allocated.)  Returns (sensorgroupID_t)(-1) if no
 *   classes yet exist.
 */
sensorgroupID_t sksiteSensorgroupGetMaxID(void);

/*
 *   Returns the length of the longest currently known group name, or
 *   a minimum value.  This result is suitable for choosing the size
 *   of a display column for group names and/or IDs.
 */
size_t sksiteSensorgroupGetMaxNameStrLen(void);

/*
 *   Get the name of the group with the given ID into the given buffer
 *   of size buffer_size.  If the name is longer than buffer_size, the
 *   value returns is truncated with a '\0' in the final position.
 *
 *   Returns the number of characters that would have been written if
 *   the buffer had been long enough.
 */
int sksiteSensorgroupGetName(
    char *buffer,
    size_t buffer_size,
    sensorgroupID_t sensorgroup_id);

/*
 *   Adds the given sensor to the given class.  Returns 0 on success,
 *   -1 if an error occurred.
 */
int sksiteSensorgroupAddSensor(
    sensorgroupID_t sensorgroup_id,
    sensorID_t sensor_id);

/*
 *   Adds every sensor in the given sensorgroup to the given class.
 *   Returns 0 on success, -1 if an error occurred.
 */
int sksiteSensorgroupAddSensorgroup(
    sensorgroupID_t dest,
    sensorgroupID_t src);

/*
 *   Sets iter to be an iterator that loops over all defined
 *   sensorgroups.
 */
void sksiteSensorgroupIterator(
    sensorgroup_iter_t *iter);

/*
 *   Sets iter to be an iterator that loops over all sensors in the
 *   given sensorgroup.
 */
void sksiteSensorgroupSensorIterator(
    sensorgroupID_t sensorgroup_id,
    sensorgroup_iter_t *iter);

/** Flowtypes *********************************************************/

/*
 *   Flowtypes represent individual class/type pairs.  Flowtype IDs
 *   are actually recorded in files, while class IDs and types are
 *   not.
 */

/*
 *   Create the flowtype 'flowtype_name' with id 'flowtype_id'.
 *   Associate it with the given class ID and type name.  It is an
 *   error to create a flowtype with an ID that is already allocated.
 *   If any error occurs (class ID already in use, out of memory),
 *   returns -1.  Otherwise returns 0 on success.
 */
int sksiteFlowtypeCreate(
    flowtypeID_t flowtype_id,
    const char *flowtype_name,
    classID_t class_id,
    const char *type_name);

/*
 *   Find the flowtype ID for a flowtype given its name.  Returns
 *   SK_INVALID_FLOWTYPE if no flowtype is found with the given name.
 */
flowtypeID_t sksiteFlowtypeLookup(
    const char *flowtype_name);

/*
 *   Find the flowtype ID for a flowtype given its class and type.
 *   Returns SK_INVALID_FLOWTYPE if no flowtype is found with the
 *   given class and type.
 */
flowtypeID_t sksiteFlowtypeLookupByClassType(
    const char         *class_name,
    const char         *type);

/*
 *   Find the flowtype ID for a flowtype given its class and type.
 *   Returns SK_INVALID_FLOWTYPE if no flowtype is found with the
 *   given class and type.
 */
flowtypeID_t sksiteFlowtypeLookupByClassIDType(
    classID_t           class_id,
    const char         *type);

/*
 *   Return 1 if a flowtype with the given ID exists, 0 if no such
 *   flowtype has been defined.
 */
int sksiteFlowtypeExists(
    flowtypeID_t flowtype_id);

/*
 *   Returns the maximum flowtype ID that has been allocated.  Add one
 *   to this value to get the lowest ID that is certain not to have
 *   been allocated.  (Note that not all IDs up to the maximum must
 *   have been allocated.)  Returns (flowtypeID_t)(-1) if no flowtypes
 *   yet exist.
 */
flowtypeID_t sksiteFlowtypeGetMaxID(void);

/*
 *   Get the class name of the flowtype with the given ID into the
 *   given buffer of size buffer_size.  If the name is longer than
 *   buffer_size, the value returns is truncated with a '\0' in the
 *   final position.
 *
 *   Returns the number of characters that would have been written if
 *   the buffer had been long enough.
 */
int sksiteFlowtypeGetClass(
    char               *buffer,
    size_t              buffer_size,
    flowtypeID_t        flowtype_id);

/*
 *   Returns the class ID of this flowtype's class.  Returns
 *   SK_INVALID_CLASS if the flowtype does not exist.
 */
classID_t sksiteFlowtypeGetClassID(
    flowtypeID_t        flowtype_id);

/*
 *   Returns the length of the longest currently known flowtype name,
 *   or a minimum value.  This result is suitable for choosing the
 *   size of a display column for flowtype names and/or IDs.
 */
size_t sksiteFlowtypeGetMaxNameStrLen(void);

/*
 *   Get the name of the flowtype with the given ID into the given
 *   buffer of size buffer_size.  If the name is longer than
 *   buffer_size, the value returns is truncated with a '\0' in the
 *   final position.
 *
 *   Returns the number of characters that would have been written if
 *   the buffer had been long enough.
 */
int sksiteFlowtypeGetName(
    char *buffer,
    size_t buffer_size,
    flowtypeID_t flowtype_id);

/*
 *   Returns the length of the longest currently known flowtype type,
 *   or a minimum value.  This result is suitable for choosing the
 *   size of a display column for flowtype types.
 */
size_t sksiteFlowtypeGetMaxTypeStrLen(void);

/*
 *   Get the type of the flowtype with the given ID into the given
 *   buffer of size buffer_size.  If the name is longer than
 *   buffer_size, the value returns is truncated with a '\0' in the
 *   final position.
 *
 *   Returns the number of characters that would have been written if
 *   the buffer had been long enough.
 */
int sksiteFlowtypeGetType(
    char *buffer,
    size_t buffer_size,
    flowtypeID_t flowtype_id);

/*
 *   Sets iter to be an iterator that loops over all defined flowtypes.
 */
void sksiteFlowtypeIterator(
    flowtype_iter_t *iter);

/*
 *   Asserts that the given flowtype exists, and is associated with
 *   the given class name and class type.  If this is not the case, an
 *   error message is printed and the program abort()s.  The
 *   'pack_logic_file' is the path to the file doing the assertion.
 */
void sksiteFlowtypeAssert(
    const char     *pack_logic_file,
    flowtypeID_t    flowtype_id,
    const char     *class_name,
    const char     *type);

/** File Formats ******************************************************/

/*
 *   Get the name of the file format with the given ID into the given
 *   buffer of size buffer_size.  If the name is longer than
 *   buffer_size, the value returns is truncated with a '\0' in the
 *   final position.
 *
 *   Returns the number of characters that would have been written if
 *   the buffer had been long enough.
 */
int sksiteFileformatGetName(
    char *buffer,
    size_t buffer_size,
    fileFormat_t id);

/*
 *    Return 1 if 'id' is a valid file output format, or 0 if it is
 *    not.
 */
int sksiteFileformatIsValid(
    fileFormat_t        id);

/*
 *    Returns the file output format associated with the name.  If the
 *    name is unknown, will return an invalid file format.
 */
fileFormat_t sksiteFileformatFromName(
    const char *name);


/** Compression Methods ***********************************************/

/*
 *    Given the compress method 'id', write the name of that method
 *    into 'out_buffer' whose length is 'bufsize'.  The function
 *    returns a pointer to 'out_buffer', or NULL for an invalid
 *    compression method.
 */
int sksiteCompmethodGetName(
    char *buffer,
    size_t buffer_size,
    sk_compmethod_t id);

/*
 *    Return 1 if the compression method 'id' is available, or 0
 *    otherwise.
 *
 *    Since compression is supported by external libraries, a value
 *    may be valid but unavailable when SiLK is built without support
 *    for an external library.
 */
int sksiteCompmethodIsAvailable(
    sk_compmethod_t     id);

/*
 *    Return 1 if 'id' is a valid compression method, or 0 if it is
 *    not.  See also sksiteCompmethodIsAvailable().
 */
int sksiteCompmethodIsValid(
    sk_compmethod_t     id);

/*
 *    Return the generically "best" compression method from all those
 *    that are available.
 */
sk_compmethod_t sksiteCompmethodGetBest(void);

/*
 *    Return the default compression method.
 */
sk_compmethod_t sksiteCompmethodGetDefault(void);

/*
 *    Sets the default compression method.  Returns 0 on success, -1
 *    if the method is not available.
 */
int sksiteCompmethodSetDefault(
    sk_compmethod_t     compression_method);

/*
 *    Add an option that will allow the user to set the compression
 *    method of binary output files.  After skOptionsParse() sucessfully
 *    returns, the variable pointed to by 'compression_method' will
 *    contain the compression method to use.
 *
 *    If the user does not exercise the compression-method option,
 *    'compression_method' will be set to the default compression
 *    method.
 */
int sksiteCompmethodOptionsRegister(
    sk_compmethod_t    *compression_method);

/*
 *    Include the compression method option in the list of options for
 *    --help output.
 */
void sksiteCompmethodOptionsUsage(
    FILE               *fh);

/** Paths *************************************************************/

/*
 *    Fill 'buffer' with the data root directory.  'buffer' is a
 *    character arra whose length is 'bufsize'.  Returns a pointer to
 *    'buffer', or NULL if 'buffer' is too small to hold the root
 *    directory.
 */
char *sksiteGetRootDir(
    char           *buffer,
    size_t          bufsize);

/*
 *    Sets the data root directory to 'rootdir', overriding the value
 *    that was set when SiLK was configured.  Returns 0 on success, or
 *    -1 if 'rootdir' is NULL, the empty string, or longer than
 *    PATH_MAX characters.
 */
int sksiteSetRootDir(
    const char      *rootdir);

/*
 *   Sets the path format for output files, overriding the current
 *   value.  Returns 0 on success, or -1 if 'format' is NULL, the empty
 *   string, or longer than PATH_MAX characters.
 *
 *   NOTE: At the moment, all path formats are required to end in %x,
 *   so that filenames have the default format.  This restriction may
 *   be lifted in the future.
 *
 *   The following strings have special meaning in path formats:
 *
 *     %C - Class name
 *     %F - Flowtype name
 *     %H - Hour, two digits, zero-padded
 *     %N - Sensor name
 *     %T - Type name
 *     %Y - Year, four digits, zero-padded
 *     %d - Day of month, two digits, zero-padded
 *     %f - Flowtype ID
 *     %m - Month of year, two digits, zero-padded
 *     %n - Sensor ID
 *     %x - Default filename, which is the same as "%F-%N_%Y%m%d.%H"
 *     %% - a single percent sign
 *
 *   The default path format is "%T/%Y/%m/%d/%x"
 */
int sksiteSetPathFormat(
    const char     *format);


/*
 *    Fill 'buffer' with the 'packing-logic' value read from the site
 *    configuration file.  'buffer' is a character array whose length
 *    is 'bufsize'.  Returns NULL if the packing-logic value was not
 *    set.  Otherwise, returns a pointer to 'buffer', or NULL if
 *    'buffer' is too small to hold the value.
 */
char *sksiteGetPackingLogicPath(
    char               *buffer,
    size_t              bufsize);


/*
 *    Set the packing-logic value to 'pathname'.  The packer,
 *    rwflowpack, may use this value to determine into which class and
 *    type a flow belongs.  Return 0 on success, or -1 on failure.
 */
int sksiteSetPackingLogicPath(
    const char         *pathname);


/*
 *    Fill in 'buffer', a C-array of size 'bufsize', with the complete
 *    path of the file having the specified 'flowtype', 'sensor', and
 *    'timestamp'.  The name will be of the form specified by the
 *    current path format.
 *
 *    When 'suffix' is non-NULL and not the empty string, it will be
 *    appended to the name of the generated file.  If 'suffix' does
 *    not begin with a period ("."), one will be added between the
 *    filename and the suffix.
 *
 *    When 'reldir_begin' is non-NULL, its value is set to the
 *    beginning of the relative directory; i.e., to the character
 *    following the '/' that ends the root-directory.
 *
 *    When 'filename_begin' is non-NULL, its value is set to the
 *    beginning of the filename; i.e., to the character following the
 *    final '/'.
 */
char *sksiteGeneratePathname(
    char           *buffer,
    size_t          bufsize,
    flowtypeID_t    flowtype,
    sensorID_t      sensor,
    sktime_t        timestamp,
    const char     *suffix,
    char          **reldir_begin,
    char          **filename_begin);


/*
 *    Extract the flowtype, sensor, and timestamp from 'filename', the
 *    name of a SiLK Flow file, and put the values into
 *    'out_flowtype', 'out_sensor' and 'out_timestamp', respectively.
 *    Any of those values may be NULL, indicating that the caller does
 *    not want the value returned.  The function returns the flowtype,
 *    or SK_INVALID_FLOWTYPE if the name is not in the proper form.
 *
 *    The standard format for the name of a SiLK flow file is:
 *
 *    flowtypeString-SensorName_YYYYMMDD.HH[.*]
 *
 *    with a hyphen separating the flowtype from the sensor, and an
 *    underscore separating the sensor from the time.  The filename
 *    may include a suffix made up of a period and additional text.
 *    When 'filename' has a suffix and 'out_suffix' is non-NULL,
 *    'out_suffix' will be set to the location of the '.' in
 *    'filename' that begins the suffix.
 *
 *    The function will take the basename of 'filename', so 'filename'
 *    may include directory components.
 *
 */
flowtypeID_t sksiteParseFilename(
    flowtypeID_t   *out_flowtype,
    sensorID_t     *out_sensor,
    sktime_t       *out_timestamp,
    const char    **out_suffix,
    const char     *filename);

/*
 *    Extract the flowtype, sensor, and timestamp from 'filename', the
 *    name of a SiLK Flow file, and use those values to fill in
 *    'buffer', a C-array of size 'bufsize', with the complete path of
 *    the file having that flowtype, sensor, and timestamp.
 *
 *    Returns a pointer to 'buffer' on success, or NULL if an error
 *    occurs or if the filename is not of the expected form.
 *
 *    When 'suffix' is NULL and 'filename' has a suffix, the path name
 *    put into 'buffer' will have the same suffix appended.  To have
 *    the suffix removed from the new path, pass in the empty string
 *    as the value of 'suffix'.
 *
 *    The parameters 'buffer' and 'filename' may point to the same
 *    location.
 *
 *    This function works as a convenience wrapper around
 *    sksiteParseFilename() and sksiteGeneratePathname().  See the
 *    documentation of those functions for additional information.
 */
char *sksiteParseGeneratePath(
    char           *buffer,
    size_t          bufsize,
    const char     *filename,
    const char     *suffix,
    char          **reldir_begin,
    char          **filename_begin);

/** Special Support Functions *****************************************/

/*
 *    Treats 'string' as a comma separated list of tokens representing
 *    the NAMES of sensors---does not accept sensor IDs.  For each
 *    token that is a valid sensor name, the function appends an
 *    element to the 'out_sensors' vector, where the element holds the
 *    sensorID_t that the token maps to.
 *
 *    Returns the number of matches found, 0 for no matches, or -1 for
 *    memory error, NULL input, or if the vector's element's size is
 *    not sizeof(sensorID_t).
 *
 *    If out_sensors is NULL, the function still returns the number of
 *    matches found.
 */
int sksiteParseSensorList(
    sk_vector_t        *out_sensors,
    const char         *string);

#endif /* _SKSITE_H */


/*
** Local Variables:
** mode:c
** indent-tabs-mode:nil
** c-basic-offset:4
** End:
*/
