/*
* Amanda, The Advanced Maryland Automatic Network Disk Archiver
* Copyright (c) 1991-2000 University of Maryland at College Park
* Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
* Copyright (c) 2013-2016 Carbonite, Inc. All Rights Reserved.
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of U.M. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. U.M. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: James da Silva, Systems Design and Analysis Group
* Computer Science Department
* University of Maryland at College Park
*/
/*
* $Id: conffile.c,v 1.156 2006/07/26 15:17:37 martinea Exp $
*
* read configuration file
*/
#include "amanda.h"
#include "amutil.h"
#include "conffile.h"
#include "clock.h"
#include <glib.h>
/*
* Lexical analysis
*/
/* This module implements its own quixotic lexer and parser, present for historical
* reasons. If this were written from scratch, it would use flex/bison. */
/* An enumeration of the various tokens that might appear in a configuration file.
*
* - CONF_UNKNOWN has special meaning as an unrecognized token.
* - CONF_ANY can be used to request any token, rather than requiring a specific
* token.
*/
typedef enum {
CONF_UNKNOWN, CONF_ANY, CONF_COMMA,
CONF_LBRACE, CONF_RBRACE, CONF_NL,
CONF_END, CONF_IDENT, CONF_INT,
CONF_INT64, CONF_BOOL, CONF_REAL,
CONF_STRING, CONF_TIME, CONF_SIZE,
/* config parameters */
CONF_INCLUDEFILE, CONF_ORG, CONF_MAILTO,
CONF_DUMPUSER, CONF_TAPECYCLE, CONF_TAPEDEV,
CONF_CHANGERDEV, CONF_CHANGERFILE, CONF_LABELSTR,
CONF_BUMPPERCENT, CONF_BUMPSIZE, CONF_BUMPDAYS,
CONF_BUMPMULT, CONF_ETIMEOUT, CONF_DTIMEOUT,
CONF_CTIMEOUT, CONF_TAPELIST,
CONF_DEVICE_OUTPUT_BUFFER_SIZE,
CONF_DISKFILE, CONF_INFOFILE, CONF_LOGDIR,
CONF_LOGFILE, CONF_DISKDIR, CONF_DISKSIZE,
CONF_INDEXDIR, CONF_NETUSAGE, CONF_INPARALLEL,
CONF_DUMPORDER, CONF_TIMEOUT, CONF_TPCHANGER,
CONF_RUNTAPES, CONF_DEFINE, CONF_DUMPTYPE,
CONF_TAPETYPE, CONF_INTERFACE, CONF_PRINTER,
CONF_MAILER,
CONF_AUTOFLUSH, CONF_RESERVE, CONF_MAXDUMPSIZE,
CONF_COLUMNSPEC, CONF_AMRECOVER_DO_FSF, CONF_AMRECOVER_CHECK_LABEL,
CONF_AMRECOVER_CHANGER, CONF_LABEL_NEW_TAPES, CONF_USETIMESTAMPS,
CONF_CHANGER,
CONF_TAPERALGO, CONF_FIRST, CONF_FIRSTFIT,
CONF_LARGEST, CONF_LARGESTFIT, CONF_SMALLEST,
CONF_LAST, CONF_DISPLAYUNIT, CONF_RESERVED_UDP_PORT,
CONF_RESERVED_TCP_PORT, CONF_UNRESERVED_TCP_PORT,
CONF_TAPERFLUSH,
CONF_FLUSH_THRESHOLD_DUMPED,
CONF_FLUSH_THRESHOLD_SCHEDULED,
CONF_DEVICE_PROPERTY, CONF_PROPERTY, CONF_PLUGIN,
CONF_APPLICATION, CONF_APPLICATION_TOOL,
CONF_SCRIPT, CONF_SCRIPT_TOOL,
CONF_EXECUTE_ON, CONF_EXECUTE_WHERE, CONF_SEND_AMREPORT_ON,
CONF_DEVICE, CONF_ORDER, CONF_SINGLE_EXECUTION,
CONF_DATA_PATH, CONF_AMANDA, CONF_DIRECTTCP,
CONF_TAPER_PARALLEL_WRITE, CONF_INTERACTIVITY, CONF_TAPERSCAN,
CONF_MAX_DLE_BY_VOLUME, CONF_EJECT_VOLUME, CONF_TMPDIR,
CONF_REPORT_USE_MEDIA, CONF_REPORT_NEXT_MEDIA, CONF_REPORT_FORMAT,
CONF_RETRY_DUMP, CONF_TAPEPOOL,
CONF_POLICY, CONF_STORAGE, CONF_VAULT_STORAGE,
CONF_CMDFILE, CONF_REST_API_PORT, CONF_REST_SSL_CERT,
CONF_REST_SSL_KEY, CONF_ACTIVE_STORAGE,
/* storage setting */
CONF_SET_NO_REUSE, CONF_ERASE_VOLUME,
CONF_ERASE_ON_FAILURE, CONF_COMPRESS_INDEX, CONF_SORT_INDEX,
CONF_ERASE_ON_FULL,
/* execute on */
CONF_PRE_AMCHECK, CONF_POST_AMCHECK,
CONF_PRE_DLE_AMCHECK, CONF_PRE_HOST_AMCHECK,
CONF_POST_DLE_AMCHECK, CONF_POST_HOST_AMCHECK,
CONF_PRE_ESTIMATE, CONF_POST_ESTIMATE,
CONF_PRE_DLE_ESTIMATE, CONF_PRE_HOST_ESTIMATE,
CONF_POST_DLE_ESTIMATE, CONF_POST_HOST_ESTIMATE,
CONF_PRE_BACKUP, CONF_POST_BACKUP,
CONF_PRE_DLE_BACKUP, CONF_PRE_HOST_BACKUP,
CONF_POST_DLE_BACKUP, CONF_POST_HOST_BACKUP,
CONF_PRE_RECOVER, CONF_POST_RECOVER,
CONF_PRE_LEVEL_RECOVER, CONF_POST_LEVEL_RECOVER,
CONF_INTER_LEVEL_RECOVER,
/* kerberos 5 */
CONF_KRB5KEYTAB, CONF_KRB5PRINCIPAL,
/* holding disk */
CONF_COMMENT, CONF_DIRECTORY, CONF_USE,
CONF_CHUNKSIZE,
/* dump type */
/*COMMENT,*/ CONF_PROGRAM, CONF_DUMPCYCLE,
CONF_RUNSPERCYCLE, CONF_MAXCYCLE, CONF_MAXDUMPS,
CONF_OPTIONS, CONF_PRIORITY, CONF_FREQUENCY,
CONF_INDEX, CONF_MAXPROMOTEDAY, CONF_STARTTIME,
CONF_COMPRESS, CONF_ENCRYPT, CONF_AUTH,
CONF_STRATEGY, CONF_ESTIMATE, CONF_SKIP_INCR,
CONF_SKIP_FULL, CONF_RECORD, CONF_HOLDING,
CONF_EXCLUDE, CONF_INCLUDE, CONF_KENCRYPT,
CONF_IGNORE, CONF_COMPRATE, CONF_TAPE_SPLITSIZE,
CONF_SPLIT_DISKBUFFER, CONF_FALLBACK_SPLITSIZE,CONF_SRVCOMPPROG,
CONF_CLNTCOMPPROG, CONF_SRV_ENCRYPT, CONF_CLNT_ENCRYPT,
CONF_SRV_DECRYPT_OPT, CONF_CLNT_DECRYPT_OPT, CONF_AMANDAD_PATH,
CONF_CLIENT_USERNAME, CONF_CLIENT_PORT, CONF_ALLOW_SPLIT,
CONF_MAX_WARNINGS, CONF_TAG,
CONF_SSL_FINGERPRINT_FILE, CONF_SSL_CERT_FILE, CONF_SSL_KEY_FILE,
CONF_SSL_CA_CERT_FILE, CONF_SSL_CIPHER_LIST, CONF_SSL_CHECK_HOST,
CONF_SSL_CHECK_CERTIFICATE_HOST, CONF_SSL_DIR,
CONF_SSL_CHECK_FINGERPRINT,
/* tape type */
/*COMMENT,*/ CONF_BLOCKSIZE,
CONF_LBL_TEMPL, CONF_FILEMARK, CONF_LENGTH,
CONF_SPEED, CONF_READBLOCKSIZE,
/* client conf */
CONF_CONF, CONF_INDEX_SERVER, CONF_TAPE_SERVER,
CONF_SSH_KEYS, CONF_GNUTAR_LIST_DIR, CONF_AMANDATES,
CONF_AMDUMP_SERVER, CONF_HOSTNAME,
/* protocol config */
CONF_REP_TRIES, CONF_CONNECT_TRIES, CONF_REQ_TRIES,
/* debug config */
CONF_DEBUG_DAYS,
CONF_DEBUG_AMANDAD, CONF_DEBUG_AMIDXTAPED, CONF_DEBUG_AMINDEXD,
CONF_DEBUG_AMRECOVER, CONF_DEBUG_AUTH, CONF_DEBUG_EVENT,
CONF_DEBUG_HOLDING, CONF_DEBUG_PROTOCOL, CONF_DEBUG_PLANNER,
CONF_DEBUG_DRIVER, CONF_DEBUG_DUMPER, CONF_DEBUG_CHUNKER,
CONF_DEBUG_TAPER, CONF_DEBUG_SELFCHECK, CONF_DEBUG_SENDSIZE,
CONF_DEBUG_SENDBACKUP, CONF_DEBUG_RECOVERY,
/* network interface */
/* COMMENT, */ /* USE, */
CONF_SRC_IP,
/* dump options (obsolete) */
CONF_EXCLUDE_FILE, CONF_EXCLUDE_LIST,
/* compress, estimate, encryption */
CONF_NONE, CONF_FAST, CONF_BEST,
CONF_SERVER, CONF_CLIENT, CONF_CALCSIZE,
CONF_CUSTOM,
/* autolabel */
CONF_AUTOLABEL, CONF_ANY_VOLUME, CONF_OTHER_CONFIG,
CONF_NON_AMANDA, CONF_VOLUME_ERROR, CONF_EMPTY,
CONF_META_AUTOLABEL,
/* labelstr */
CONF_MATCH_AUTOLABEL,
/* part_cache_type */
CONF_PART_SIZE, CONF_PART_CACHE_TYPE, CONF_PART_CACHE_DIR,
CONF_PART_CACHE_MAX_SIZE, CONF_DISK, CONF_MEMORY,
/* host-limit */
CONF_RECOVERY_LIMIT, CONF_SAME_HOST, CONF_DUMP_LIMIT,
/* holdingdisk */
CONF_NEVER, CONF_AUTO, CONF_REQUIRED,
/* send_amreport */
CONF_ALL, CONF_STRANGE, CONF_ERROR,
/* priority */
CONF_LOW, CONF_MEDIUM, CONF_HIGH,
/* dump strategy */
CONF_SKIP, CONF_STANDARD, CONF_NOFULL,
CONF_NOINC, CONF_HANOI, CONF_INCRONLY,
/* exclude list */
CONF_LIST, CONF_EFILE, CONF_APPEND,
CONF_OPTIONAL,
/* property */
CONF_HIDDEN, CONF_VISIBLE,
/* numbers */
CONF_AMINFINITY, CONF_MULT1, CONF_MULT7,
CONF_MULT1K, CONF_MULT1M, CONF_MULT1G,
CONF_MULT1T,
/* boolean */
CONF_ATRUE, CONF_AFALSE,
CONF_CLIENT_NAME,
/* retention */
CONF_RETENTION_TAPES, CONF_RETENTION_DAYS, CONF_RETENTION_RECOVER,
CONF_RETENTION_FULL,
/* dump_selection */
CONF_DUMP_SELECTION,
CONF_FULL, CONF_INCR, CONF_OTHER,
/* storage */
CONF_VAULT,
/* internal */
CONF_PREFERED_IDENT,
} tok_t;
/* A keyword table entry, mapping the given keyword to the given token.
* Note that punctuation, integers, and quoted strings are handled
* internally to the lexer, so they do not appear here. */
typedef struct {
char *keyword;
tok_t token;
} keytab_t;
/* The current keyword table, used by all token-related functions */
static keytab_t *keytable = NULL;
/* Has a token been "ungotten", and if so, what was it? */
static int token_pushed;
static tok_t pushed_tok;
/* The current token and its value. Note that, unlike most other val_t*,
* tokenval's v.s points to statically allocated memory which cannot be
* free()'d. */
static tok_t tok;
static val_t tokenval;
/* The current input information: file, filename, line, and character
* (which points somewhere within current_line) */
static FILE *current_file = NULL;
static char *current_filename = NULL;
static char *current_line = NULL;
static char *current_char = NULL;
static char *current_block = NULL;
static int current_line_num = 0; /* (technically, managed by the parser) */
/* A static buffer for storing tokens while they are being scanned. */
static char tkbuf[4096];
/* Return a token formated for output */
static char *str_keyword(keytab_t *kt);
/* Look up the name of the given token in the current keytable */
static char *get_token_name(tok_t);
/* Look up a token in keytable, given a string, returning CONF_UNKNOWN
* for unrecognized strings. Search is case-insensitive. */
static tok_t lookup_keyword(char *str);
/* Get the next token. If exp is anything but CONF_ANY, and the next token
* does not match, then a parse error is flagged. This function reads from the
* current_* static variables, recognizes keywords against the keytable static
* variable, and places its result in tok and tokenval. */
static void get_conftoken(tok_t exp);
/* "Unget" the current token; this supports a 1-token lookahead. */
static void unget_conftoken(void);
/* Tokenizer character-by-character access. */
static int conftoken_getc(void);
static int conftoken_ungetc(int c);
static void merge_proplist_foreach_fn(gpointer key_p,
gpointer value_p,
gpointer user_data_p);
static void copy_proplist_foreach_fn(gpointer key_p,
gpointer value_p,
gpointer user_data_p);
static gboolean is_valid_label(char *template);
/*
* Parser
*/
/* A parser table entry. Read as "<token> introduces parameter <parm>,
* the data for which will be read by <read_function> and validated by
* <validate_function> (if not NULL). <type> is only used in formatting
* config overwrites. */
typedef struct conf_var_s {
tok_t token;
conftype_t type;
void (*read_function) (struct conf_var_s *, val_t*);
int parm;
void (*validate_function) (struct conf_var_s *, val_t *);
} conf_var_t;
/* This is a list of filenames that are used in 'seen_t' structs. */
static GSList *seen_filenames = NULL;
/* get a copy of filename that's stored in seen_filenames so that it won't go
* away until config_uninit. */
static char *get_seen_filename(char *filename);
/* If allow_overwrites is true, the a parameter which has already been
* seen will simply overwrite the old value, rather than triggering an
* error. Note that this does not apply to all parameters, e.g.,
* device_property */
static int allow_overwrites;
/* subsection structs
*
* The 'seen' fields in these structs are useless outside this module;
* they are only used to generate error messages for multiply defined
* subsections.
*/
struct tapetype_s {
struct tapetype_s *next;
seen_t seen;
char *name;
val_t value[TAPETYPE_TAPETYPE];
};
struct dumptype_s {
struct dumptype_s *next;
seen_t seen;
char *name;
val_t value[DUMPTYPE_DUMPTYPE];
};
struct interface_s {
struct interface_s *next;
seen_t seen;
char *name;
val_t value[INTER_INTER];
};
struct holdingdisk_s {
seen_t seen;
char *name;
val_t value[HOLDING_HOLDING];
};
struct application_s {
struct application_s *next;
seen_t seen;
char *name;
val_t value[APPLICATION_APPLICATION];
};
struct pp_script_s {
struct pp_script_s *next;
seen_t seen;
char *name;
val_t value[PP_SCRIPT_PP_SCRIPT];
};
struct device_config_s {
struct device_config_s *next;
seen_t seen;
char *name;
val_t value[DEVICE_CONFIG_DEVICE_CONFIG];
};
struct changer_config_s {
struct changer_config_s *next;
seen_t seen;
char *name;
val_t value[CHANGER_CONFIG_CHANGER_CONFIG];
};
struct interactivity_s {
struct interactivity_s *next;
seen_t seen;
char *name;
val_t value[INTERACTIVITY_INTERACTIVITY];
};
struct taperscan_s {
struct taperscan_s *next;
seen_t seen;
char *name;
val_t value[TAPERSCAN_TAPERSCAN];
};
struct policy_s {
struct policy_s *next;
seen_t seen;
char *name;
val_t value[POLICY_POLICY];
};
struct storage_s {
struct storage_s *next;
seen_t seen;
char *name;
val_t value[STORAGE_STORAGE];
};
/* The current parser table */
static conf_var_t *parsetable = NULL;
static gboolean generate_errors = TRUE;
/* Read and parse a configuration file, recursively reading any included
* files. This function sets the keytable and parsetable appropriately
* according to is_client.
*
* @param filename: configuration file to read
* @param is_client: true if this is a client
* @param missing_ok: is it OK if the file is missing?
*/
static void read_conffile(char *filename,
gboolean is_client,
gboolean missing_ok);
/* Read and process a line of input from the current file, using the
* current keytable and parsetable. For blocks, this recursively
* reads the entire block.
*
* @param is_client: true if this is a client
* @returns: true on success, false on EOF
*/
static gboolean read_confline(gboolean is_client);
/* Handle an invalid token, recognizing deprecated tokens as such,
* and producing an appropriate error message.
*
* @param token: the identifier
*/
static void handle_invalid_keyword(const char * token);
/* Check whether token is deprecated, and issue a warning if it
* is. This consults the global variables 'tok' and 'tokenval'
*/
static void handle_deprecated_keyword(void);
/* Read a brace-delimited block using the given parse table. This
* function is used to read brace-delimited subsections in the config
* files and also (via read_dumptype) to read dumptypes from
* the disklist.
*
* This function implements "inheritance" as follows: if a bare
* identifier occurs within the braces, it calls copy_function (if
* not NULL), which looks up an existing subsection using the
* identifier from tokenval and copies any values not already seen
* into valarray.
*
* @param read_var: the parse table to use
* @param valarray: the (pre-initialized) val_t array to fill in
* @param errormsg: error message to display for unrecognized keywords
* @param read_brace: if true, read the opening brace
* @param copy_function: function to copy configuration from
* another subsection into this one.
*/
static void read_block(conf_var_t *read_var, val_t *valarray,
char *errormsg, int read_brace,
void (*copy_function)(void),
char *type, char *name);
/* For each subsection type, we have a global and four functions:
* - foocur is a temporary struct used to assemble new subsections
* - get_foo is called after reading "DEFINE FOO", and
* is responsible for reading the entire block, using
* read_block()
* - init_foo_defaults initializes a new subsection struct
* to its default values
* - save_foo copies foocur to a newly allocated struct and
* inserts that into the relevant list.
* - copy_foo implements inheritance as described in read_block()
*/
static holdingdisk_t hdcur;
static void get_holdingdisk(int is_define);
static void init_holdingdisk_defaults(void);
static void save_holdingdisk(void);
static void copy_holdingdisk(void);
static dumptype_t dpcur;
static void get_dumptype(void);
static void init_dumptype_defaults(void);
static void save_dumptype(void);
static void copy_dumptype(void);
static tapetype_t tpcur;
static void get_tapetype(void);
static void init_tapetype_defaults(void);
static void save_tapetype(void);
static void copy_tapetype(void);
static interface_t ifcur;
static void get_interface(void);
static void init_interface_defaults(void);
static void save_interface(void);
static void copy_interface(void);
static application_t apcur;
static void get_application(void);
static void init_application_defaults(void);
static void save_application(void);
static void copy_application(void);
static pp_script_t pscur;
static void get_pp_script(void);
static void init_pp_script_defaults(void);
static void save_pp_script(void);
static void copy_pp_script(void);
static device_config_t dccur;
static void get_device_config(void);
static void init_device_config_defaults(void);
static void save_device_config(void);
static void copy_device_config(void);
static changer_config_t cccur;
static void get_changer_config(void);
static void init_changer_config_defaults(void);
static void save_changer_config(void);
static void copy_changer_config(void);
static interactivity_t ivcur;
static void get_interactivity(void);
static void init_interactivity_defaults(void);
static void save_interactivity(void);
static void copy_interactivity(void);
static taperscan_t tscur;
static void get_taperscan(void);
static void init_taperscan_defaults(void);
static void save_taperscan(void);
static void copy_taperscan(void);
static policy_s pocur;
static void get_policy(void);
static void init_policy_defaults(void);
static void save_policy(void);
static void copy_policy(void);
static storage_t stcur;
static void get_storage(void);
static void init_storage_defaults(void);
static void save_storage(void);
static void copy_storage(void);
/* read_functions -- these fit into the read_function slot in a parser
* table entry, and are responsible for calling get_conftoken as necessary
* to consume their arguments, and setting their second argument with the
* result. The first argument is a copy of the parser table entry, if
* needed. */
static void read_int(conf_var_t *, val_t *);
static void read_int64(conf_var_t *, val_t *);
static void read_real(conf_var_t *, val_t *);
static void read_str(conf_var_t *, val_t *);
static void read_str_list(conf_var_t *, val_t *);
static void read_ident(conf_var_t *, val_t *);
static void read_time(conf_var_t *, val_t *);
static void read_size(conf_var_t *, val_t *);
static void read_bool(conf_var_t *, val_t *);
static void read_no_yes_all(conf_var_t *, val_t *);
static void read_compress(conf_var_t *, val_t *);
static void read_encrypt(conf_var_t *, val_t *);
static void read_holding(conf_var_t *, val_t *);
static void read_estimatelist(conf_var_t *, val_t *);
static void read_strategy(conf_var_t *, val_t *);
static void read_taperalgo(conf_var_t *, val_t *);
static void read_send_amreport_on(conf_var_t *, val_t *);
static void read_data_path(conf_var_t *, val_t *);
static void read_priority(conf_var_t *, val_t *);
static void read_rate(conf_var_t *, val_t *);
static void read_exinclude(conf_var_t *, val_t *);
static void read_intrange(conf_var_t *, val_t *);
static void read_dapplication(conf_var_t *, val_t *);
static void read_dinteractivity(conf_var_t *, val_t *);
static void read_dtaperscan(conf_var_t *, val_t *);
static void read_dpolicy(conf_var_t *, val_t *);
//static void read_dstorage(conf_var_t *, val_t *);
static void read_dpp_script(conf_var_t *, val_t *);
static void read_hidden_property(conf_var_t *, val_t *);
static void read_visible_property(conf_var_t *, val_t *);
static void read_property(val_t *val, property_t *property);
static void read_execute_on(conf_var_t *, val_t *);
static void read_execute_where(conf_var_t *, val_t *);
static void read_holdingdisk(conf_var_t *, val_t *);
static void read_int_or_str(conf_var_t *, val_t *);
static void read_autolabel(conf_var_t *, val_t *);
static void read_labelstr(conf_var_t *, val_t *);
static void read_part_cache_type(conf_var_t *, val_t *);
static void read_host_limit(conf_var_t *, val_t *);
static void read_storage_identlist(conf_var_t *, val_t *);
static void read_dump_selection(conf_var_t *, val_t *);
static void read_vault_list(conf_var_t *np G_GNUC_UNUSED, val_t *val);
static application_t *read_application(char *name, FILE *from, char *fname,
int *linenum);
static pp_script_t *read_pp_script(char *name, FILE *from, char *fname,
int *linenum);
static device_config_t *read_device_config(char *name, FILE *from, char *fname,
int *linenum);
static changer_config_t *read_changer_config(char *name, FILE *from,
char *fname, int *linenum);
static interactivity_t *read_interactivity(char *name, FILE *from,
char *fname, int *linenum);
static taperscan_t *read_taperscan(char *name, FILE *from, char *fname,
int *linenum);
static policy_s *read_policy(char *name, FILE *from, char *fname,
int *linenum);
static storage_t *read_storage(char *name, FILE *from, char *fname,
int *linenum);
/* Functions to get various types of values. These are called by
* read_functions to take care of any variations in the way that these
* values can be written: integers can have units, boolean values can be
* specified with a number of names, etc. They form utility functions
* for the read_functions, below. */
static gint64 get_multiplier(gint64 val, confunit_t unit);
static time_t get_time(void);
static int get_int(confunit_t unit);
static ssize_t get_size(confunit_t unit);
static gint64 get_int64(confunit_t unit);
static int get_bool(void);
static int get_no_yes_all(void);
/* Check the given 'seen', flagging an error if this value has already
* been seen and allow_overwrites is false. Also marks the value as
* seen on the current line.
*
* @param seen: (in/out) seen value to adjust
*/
static void ckseen(seen_t *seen);
/* validate_functions -- these fit into the validate_function slot in
* a parser table entry. They call conf_parserror if the value in their
* second argument is invalid. */
static void validate_name(tok_t token, val_t *val);
static void validate_no_space_dquote(conf_var_t *, val_t *);
static void validate_nonnegative(conf_var_t *, val_t *);
static void validate_non_zero(conf_var_t *, val_t *);
static void validate_positive(conf_var_t *, val_t *);
static void validate_runspercycle(conf_var_t *, val_t *);
static void validate_bumppercent(conf_var_t *, val_t *);
static void validate_bumpmult(conf_var_t *, val_t *);
static void validate_displayunit(conf_var_t *, val_t *);
static void validate_reserve(conf_var_t *, val_t *);
static void validate_use(conf_var_t *, val_t *);
static void validate_chunksize(conf_var_t *, val_t *);
static void validate_blocksize(conf_var_t *, val_t *);
static void validate_debug(conf_var_t *, val_t *);
static void validate_port_range(val_t *, int, int);
static void validate_reserved_port_range(conf_var_t *, val_t *);
static void validate_unreserved_port_range(conf_var_t *, val_t *);
static void validate_program(conf_var_t *, val_t *);
static void validate_dump_limit(conf_var_t *, val_t *);
static void validate_columnspec(conf_var_t *, val_t *);
static void validate_tmpdir(conf_var_t *, val_t *);
static void validate_deprecated_changerfile(conf_var_t *, val_t *);
gint compare_pp_script_order(gconstpointer a, gconstpointer b);
static void free_dump_selection(gpointer p);
static void free_vault(gpointer p);
/*
* Initialization
*/
/* The name of the configuration under which this application is running.
* This variable is initialized by config_init.
*/
static char *config_name = NULL;
/* The directory containing the configuration for this application. This
* variable is initialized by config_init
*/
static char *config_dir = NULL;
/* The most recently read top-level configuration file. This variable is
* initialized by config_init
*/
static char *config_filename = NULL;
/* Has the config been initialized? */
static gboolean config_initialized = FALSE;
/* Are we running a client? (true if last init was
* with CONFIG_INIT_CLIENT) */
static gboolean config_client = FALSE;
/* What config overwrites to use? */
static config_overrides_t *config_overrides = NULL;
/* All global parameters */
static val_t conf_data[CNF_CNF];
/* Linked list of holding disks */
static GSList *holdinglist = NULL;
static dumptype_t *dumplist = NULL;
static tapetype_t *tapelist = NULL;
static interface_t *interface_list = NULL;
static application_t *application_list = NULL;
static pp_script_t *pp_script_list = NULL;
static device_config_t *device_config_list = NULL;
static changer_config_t *changer_config_list = NULL;
static interactivity_t *interactivity_list = NULL;
static taperscan_t *taperscan_list = NULL;
static policy_s *policy_list = NULL;
static storage_t *storage_list = NULL;
/* storage for derived values */
static long int unit_divisor = 1;
char *prepend_prefix = NULL;
int debug_amandad = 0;
int debug_recovery = 0;
int debug_amidxtaped = 0;
int debug_amindexd = 0;
int debug_amrecover = 0;
int debug_auth = 0;
int debug_event = 0;
int debug_holding = 0;
int debug_protocol = 0;
int debug_planner = 0;
int debug_driver = 0;
int debug_dumper = 0;
int debug_chunker = 0;
int debug_taper = 0;
int debug_selfcheck = 0;
int debug_sendsize = 0;
int debug_sendbackup = 0;
/* Reset all configuration values to their defaults (which, in many
* cases, come from --with-foo options at build time) */
static void init_defaults(void);
/* Update all dervied values based on the current configuration. This
* function can be called multiple times, once after each adjustment
* to the current configuration.
*
* @param is_client: are we running a client?
*/
static void update_derived_values(gboolean is_client);
static cfgerr_level_t apply_config_overrides(config_overrides_t *co,
char *key_ovr);
/* per-type conf_init functions, used as utilities for init_defaults
* and for each subsection's init_foo_defaults.
*
* These set the value's type and seen flags, as well as copying
* the relevant value into the 'v' field.
*/
static void conf_init_int(val_t *val, confunit_t unit, int i);
static void conf_init_int64(val_t *val, confunit_t unit, gint64 l);
static void conf_init_real(val_t *val, float r);
static void conf_init_str(val_t *val, char *s);
static void conf_init_ident(val_t *val, char *s);
static void conf_init_identlist(val_t *val, char *s);
static void conf_init_str_list(val_t *val, char *s);
static void conf_init_time(val_t *val, time_t t);
static void conf_init_size(val_t *val, confunit_t unit, ssize_t sz);
static void conf_init_bool(val_t *val, int i);
static void conf_init_no_yes_all(val_t *val, int i);
static void conf_init_compress(val_t *val, comp_t i);
static void conf_init_encrypt(val_t *val, encrypt_t i);
static void conf_init_data_path(val_t *val, data_path_t i);
static void conf_init_holding(val_t *val, dump_holdingdisk_t i);
static void conf_init_estimatelist(val_t *val, estimate_t i);
static void conf_init_execute_on(val_t *, int);
static void conf_init_execute_where(val_t *, int);
static void conf_init_send_amreport(val_t *val, send_amreport_t i);
static void conf_init_strategy(val_t *val, strategy_t);
static void conf_init_taperalgo(val_t *val, taperalgo_t i);
static void conf_init_priority(val_t *val, int i);
static void conf_init_rate(val_t *val, float r1, float r2);
static void conf_init_exinclude(val_t *val); /* to empty list */
static void conf_init_intrange(val_t *val, int i1, int i2);
static void conf_init_proplist(val_t *val); /* to empty list */
static void conf_init_application(val_t *val);
static void conf_init_autolabel(val_t *val);
static void conf_init_labelstr(val_t *val);
static void conf_init_part_cache_type(val_t *val, part_cache_type_t i);
static void conf_init_host_limit(val_t *val);
static void conf_init_host_limit_server(val_t *val);
static void conf_init_dump_selection(val_t *val);
static void conf_init_vault_list(val_t *val);
/*
* Command-line Handling
*/
typedef struct config_override_s {
char *key;
char *value;
gboolean applied;
} config_override_t;
struct config_overrides_s {
int n_allocated;
int n_used;
config_override_t *ovr;
};
/*
* val_t Management
*/
static void merge_val_t(val_t *, val_t *);
static void copy_val_t(val_t *, val_t *);
static void free_val_t(val_t *);
/*
* Utilities
*/
/* memory handling */
void free_property_t(gpointer p);
/* Utility functions/structs for val_t_display_strs */
static char *exinclude_display_str(val_t *val, int file);
static void proplist_display_str_foreach_fn(gpointer key_p, gpointer value_p, gpointer user_data_p);
static void val_t_print_token(gboolean print_default, gboolean print_source, FILE *output, char *prefix, char *format, keytab_t *kt, val_t *val);
/* Given a key name as used in config overwrites, return a pointer to the corresponding
* conf_var_t in the current parsetable, and the val_t representing that value. This
* function will access subsections if key has the form TYPE:SUBSEC:KEYWORD. Returns
* false if the value does not exist.
*
* Assumes keytable and parsetable are set correctly, which is generally OK after
* config_init has been called.
*
* @param key: the key to look up
* @param parm: (result) the parse table entry
* @param val: (result) the parameter value
* @returns: true on success
*/
static int parm_key_info(char *key, conf_var_t **parm, val_t **val);
/*
* Error handling
*/
/* Have we seen a parse error yet? Parsing continues after an error, so this
* flag is checked after the parse is complete.
*/
static cfgerr_level_t cfgerr_level;
static GSList *cfgerr_errors = NULL;
static void conf_error_common(cfgerr_level_t level, const char * format, va_list argp);
static void conf_parserror(const char *format, ...)
__attribute__ ((format (printf, 1, 2)));
static void conf_parswarn(const char *format, ...)
__attribute__ ((format (printf, 1, 2)));
/*
* Tables
*/
/* First, the keyword tables for client and server */
keytab_t client_keytab[] = {
{ "AMANDAD_PATH", CONF_AMANDAD_PATH },
{ "AMANDATES", CONF_AMANDATES },
{ "AMDUMP_SERVER", CONF_AMDUMP_SERVER },
{ "APPEND", CONF_APPEND },
{ "APPLICATION", CONF_APPLICATION },
{ "APPLICATION_TOOL", CONF_APPLICATION_TOOL },
{ "AUTH", CONF_AUTH },
{ "CLIENT", CONF_CLIENT },
{ "CLIENT_NAME", CONF_CLIENT_NAME },
{ "CLIENT_USERNAME", CONF_CLIENT_USERNAME },
{ "CLIENT_PORT", CONF_CLIENT_PORT },
{ "CTIMEOUT", CONF_CTIMEOUT },
{ "COMMENT", CONF_COMMENT },
{ "CONF", CONF_CONF },
{ "CONNECT_TRIES", CONF_CONNECT_TRIES },
{ "DEBUG_AMANDAD", CONF_DEBUG_AMANDAD },
{ "DEBUG_AMIDXTAPED", CONF_DEBUG_AMIDXTAPED },
{ "DEBUG_AMINDEXD", CONF_DEBUG_AMINDEXD },
{ "DEBUG_AMRECOVER", CONF_DEBUG_AMRECOVER },
{ "DEBUG_AUTH", CONF_DEBUG_AUTH },
{ "DEBUG_CHUNKER", CONF_DEBUG_CHUNKER },
{ "DEBUG_DAYS", CONF_DEBUG_DAYS },
{ "DEBUG_DRIVER", CONF_DEBUG_DRIVER },
{ "DEBUG_DUMPER", CONF_DEBUG_DUMPER },
{ "DEBUG_EVENT", CONF_DEBUG_EVENT },
{ "DEBUG_HOLDING", CONF_DEBUG_HOLDING },
{ "DEBUG_PLANNER", CONF_DEBUG_PLANNER },
{ "DEBUG_PROTOCOL", CONF_DEBUG_PROTOCOL },
{ "DEBUG_RECOVERY", CONF_DEBUG_RECOVERY },
{ "DEBUG_SELFCHECK", CONF_DEBUG_SELFCHECK },
{ "DEBUG_SENDBACKUP", CONF_DEBUG_SENDBACKUP },
{ "DEBUG_SENDSIZE", CONF_DEBUG_SENDSIZE },
{ "DEBUG_TAPER", CONF_DEBUG_TAPER },
{ "DEFINE", CONF_DEFINE },
{ "EXECUTE_ON", CONF_EXECUTE_ON },
{ "EXECUTE_WHERE", CONF_EXECUTE_WHERE },
{ "GNUTAR_LIST_DIR", CONF_GNUTAR_LIST_DIR },
{ "HIDDEN", CONF_HIDDEN },
{ "HOSTNAME", CONF_HOSTNAME },
{ "INCLUDEFILE", CONF_INCLUDEFILE },
{ "INDEX_SERVER", CONF_INDEX_SERVER },
{ "INTER_LEVEL_RECOVER", CONF_INTER_LEVEL_RECOVER },
{ "KRB5KEYTAB", CONF_KRB5KEYTAB },
{ "KRB5PRINCIPAL", CONF_KRB5PRINCIPAL },
{ "MAILER", CONF_MAILER },
{ "ORDER", CONF_ORDER },
{ "PLUGIN", CONF_PLUGIN },
{ "PRE_AMCHECK", CONF_PRE_AMCHECK },
{ "PRE_DLE_AMCHECK", CONF_PRE_DLE_AMCHECK },
{ "PRE_HOST_AMCHECK", CONF_PRE_HOST_AMCHECK },
{ "PRE_ESTIMATE", CONF_PRE_ESTIMATE },
{ "PRE_DLE_ESTIMATE", CONF_PRE_DLE_ESTIMATE },
{ "PRE_HOST_ESTIMATE", CONF_PRE_HOST_ESTIMATE },
{ "PRE_BACKUP", CONF_PRE_BACKUP },
{ "PRE_DLE_BACKUP", CONF_PRE_DLE_BACKUP },
{ "PRE_HOST_BACKUP", CONF_PRE_HOST_BACKUP },
{ "PRE_RECOVER", CONF_PRE_RECOVER },
{ "PRE_LEVEL_RECOVER", CONF_PRE_LEVEL_RECOVER },
{ "POST_AMCHECK", CONF_POST_AMCHECK },
{ "POST_DLE_AMCHECK", CONF_POST_DLE_AMCHECK },
{ "POST_HOST_AMCHECK", CONF_POST_HOST_AMCHECK },
{ "POST_ESTIMATE", CONF_POST_ESTIMATE },
{ "POST_DLE_ESTIMATE", CONF_POST_DLE_ESTIMATE },
{ "POST_HOST_ESTIMATE", CONF_POST_HOST_ESTIMATE },
{ "POST_BACKUP", CONF_POST_BACKUP },
{ "POST_DLE_BACKUP", CONF_POST_DLE_BACKUP },
{ "POST_HOST_BACKUP", CONF_POST_HOST_BACKUP },
{ "POST_RECOVER", CONF_POST_RECOVER },
{ "POST_LEVEL_RECOVER", CONF_POST_LEVEL_RECOVER },
{ "PRIORITY", CONF_PRIORITY },
{ "PROPERTY", CONF_PROPERTY },
{ "REP_TRIES", CONF_REP_TRIES },
{ "REQ_TRIES", CONF_REQ_TRIES },
{ "RESERVED_UDP_PORT", CONF_RESERVED_UDP_PORT },
{ "RESERVED_TCP_PORT", CONF_RESERVED_TCP_PORT },
{ "SCRIPT", CONF_SCRIPT },
{ "SCRIPT_TOOL", CONF_SCRIPT_TOOL },
{ "SERVER", CONF_SERVER },
{ "SSL_CA_CERT_FILE", CONF_SSL_CA_CERT_FILE },
{ "SSL_CERT_FILE", CONF_SSL_CERT_FILE },
{ "SSL_CHECK_CERTIFICATE_HOST", CONF_SSL_CHECK_CERTIFICATE_HOST },
{ "SSL_CHECK_FINGERPRINT", CONF_SSL_CHECK_FINGERPRINT },
{ "SSL_CHECK_HOST", CONF_SSL_CHECK_HOST },
{ "SSL_CIPHER_LIST", CONF_SSL_CIPHER_LIST },
{ "SSL_DIR", CONF_SSL_DIR },
{ "SSL_FINGERPRINT_FILE", CONF_SSL_FINGERPRINT_FILE },
{ "SSH_KEYS", CONF_SSH_KEYS },
{ "SSL_KEY_FILE", CONF_SSL_KEY_FILE },
{ "TAPE_SERVER", CONF_TAPE_SERVER },
{ "TAPEDEV", CONF_TAPEDEV },
{ "UNRESERVED_TCP_PORT", CONF_UNRESERVED_TCP_PORT },
{ "VISIBLE", CONF_VISIBLE },
{ NULL, CONF_IDENT },
{ NULL, CONF_UNKNOWN }
};
keytab_t server_keytab[] = {
{ "ACTIVE_STORAGE", CONF_ACTIVE_STORAGE },
{ "ALL", CONF_ALL },
{ "ALLOW_SPLIT", CONF_ALLOW_SPLIT },
{ "AMANDA", CONF_AMANDA },
{ "AMANDAD_PATH", CONF_AMANDAD_PATH },
{ "AMRECOVER_CHANGER", CONF_AMRECOVER_CHANGER },
{ "AMRECOVER_CHECK_LABEL", CONF_AMRECOVER_CHECK_LABEL },
{ "AMRECOVER_DO_FSF", CONF_AMRECOVER_DO_FSF },
{ "VAULT_STORAGE", CONF_VAULT_STORAGE },
{ "ANY", CONF_ANY_VOLUME },
{ "APPEND", CONF_APPEND },
{ "AUTH", CONF_AUTH },
{ "AUTO", CONF_AUTO },
{ "AUTOFLUSH", CONF_AUTOFLUSH },
{ "AUTOLABEL", CONF_AUTOLABEL },
{ "APPLICATION", CONF_APPLICATION },
{ "APPLICATION_TOOL", CONF_APPLICATION_TOOL },
{ "BEST", CONF_BEST },
{ "BLOCKSIZE", CONF_BLOCKSIZE },
{ "BUMPDAYS", CONF_BUMPDAYS },
{ "BUMPMULT", CONF_BUMPMULT },
{ "BUMPPERCENT", CONF_BUMPPERCENT },
{ "BUMPSIZE", CONF_BUMPSIZE },
{ "CALCSIZE", CONF_CALCSIZE },
{ "CHANGER", CONF_CHANGER },
{ "CHANGERDEV", CONF_CHANGERDEV },
{ "CHANGERFILE", CONF_CHANGERFILE },
{ "CHUNKSIZE", CONF_CHUNKSIZE },
{ "CLIENT", CONF_CLIENT },
{ "CLIENT_CUSTOM_COMPRESS", CONF_CLNTCOMPPROG },
{ "CLIENT_DECRYPT_OPTION", CONF_CLNT_DECRYPT_OPT },
{ "CLIENT_ENCRYPT", CONF_CLNT_ENCRYPT },
{ "CLIENT_NAME", CONF_CLIENT_NAME },
{ "CLIENT_PORT", CONF_CLIENT_PORT },
{ "CLIENT_USERNAME", CONF_CLIENT_USERNAME },
{ "COLUMNSPEC", CONF_COLUMNSPEC },
{ "COMMAND_FILE", CONF_CMDFILE },
{ "COMMENT", CONF_COMMENT },
{ "COMPRATE", CONF_COMPRATE },
{ "COMPRESS", CONF_COMPRESS },
{ "COMPRESS_INDEX", CONF_COMPRESS_INDEX },
{ "CONNECT_TRIES", CONF_CONNECT_TRIES },
{ "CTIMEOUT", CONF_CTIMEOUT },
{ "CUSTOM", CONF_CUSTOM },
{ "DATA_PATH", CONF_DATA_PATH },
{ "DEBUG_DAYS" , CONF_DEBUG_DAYS },
{ "DEBUG_AMANDAD" , CONF_DEBUG_AMANDAD },
{ "DEBUG_RECOVERY" , CONF_DEBUG_RECOVERY },
{ "DEBUG_AMIDXTAPED" , CONF_DEBUG_AMIDXTAPED },
{ "DEBUG_AMINDEXD" , CONF_DEBUG_AMINDEXD },
{ "DEBUG_AMRECOVER" , CONF_DEBUG_AMRECOVER },
{ "DEBUG_AUTH" , CONF_DEBUG_AUTH },
{ "DEBUG_EVENT" , CONF_DEBUG_EVENT },
{ "DEBUG_HOLDING" , CONF_DEBUG_HOLDING },
{ "DEBUG_PROTOCOL" , CONF_DEBUG_PROTOCOL },
{ "DEBUG_PLANNER" , CONF_DEBUG_PLANNER },
{ "DEBUG_DRIVER" , CONF_DEBUG_DRIVER },
{ "DEBUG_DUMPER" , CONF_DEBUG_DUMPER },
{ "DEBUG_CHUNKER" , CONF_DEBUG_CHUNKER },
{ "DEBUG_TAPER" , CONF_DEBUG_TAPER },
{ "DEBUG_SELFCHECK" , CONF_DEBUG_SELFCHECK },
{ "DEBUG_SENDSIZE" , CONF_DEBUG_SENDSIZE },
{ "DEBUG_SENDBACKUP" , CONF_DEBUG_SENDBACKUP },
{ "DEFINE", CONF_DEFINE },
{ "DEVICE", CONF_DEVICE },
{ "DEVICE_PROPERTY", CONF_DEVICE_PROPERTY },
{ "DIRECTORY", CONF_DIRECTORY },
{ "DIRECTTCP", CONF_DIRECTTCP },
{ "DISK", CONF_DISK },
{ "DISKFILE", CONF_DISKFILE },
{ "DISPLAYUNIT", CONF_DISPLAYUNIT },
{ "DTIMEOUT", CONF_DTIMEOUT },
{ "DUMPCYCLE", CONF_DUMPCYCLE },
{ "DUMPORDER", CONF_DUMPORDER },
{ "DUMPTYPE", CONF_DUMPTYPE },
{ "DUMPUSER", CONF_DUMPUSER },
{ "DUMP_LIMIT", CONF_DUMP_LIMIT },
{ "DUMP_SELECTION", CONF_DUMP_SELECTION },
{ "EJECT_VOLUME", CONF_EJECT_VOLUME },
{ "ERASE_VOLUME", CONF_ERASE_VOLUME },
{ "ERASE_ON_FAILURE", CONF_ERASE_ON_FAILURE },
{ "ERASE_ON_FULL", CONF_ERASE_ON_FULL },
{ "EMPTY", CONF_EMPTY },
{ "ENCRYPT", CONF_ENCRYPT },
{ "ERROR", CONF_ERROR },
{ "ESTIMATE", CONF_ESTIMATE },
{ "ETIMEOUT", CONF_ETIMEOUT },
{ "EXCLUDE", CONF_EXCLUDE },
{ "EXCLUDE_FILE", CONF_EXCLUDE_FILE },
{ "EXCLUDE_LIST", CONF_EXCLUDE_LIST },
{ "EXECUTE_ON", CONF_EXECUTE_ON },
{ "EXECUTE_WHERE", CONF_EXECUTE_WHERE },
{ "FALLBACK_SPLITSIZE", CONF_FALLBACK_SPLITSIZE },
{ "FAST", CONF_FAST },
{ "FILE", CONF_EFILE },
{ "FILEMARK", CONF_FILEMARK },
{ "FIRST", CONF_FIRST },
{ "FIRSTFIT", CONF_FIRSTFIT },
{ "FULL", CONF_FULL },
{ "HANOI", CONF_HANOI },
{ "HIDDEN", CONF_HIDDEN },
{ "HIGH", CONF_HIGH },
{ "HOLDINGDISK", CONF_HOLDING },
{ "IGNORE", CONF_IGNORE },
{ "INCLUDE", CONF_INCLUDE },
{ "INCLUDEFILE", CONF_INCLUDEFILE },
{ "INCR", CONF_INCR },
{ "INCRONLY", CONF_INCRONLY },
{ "INDEX", CONF_INDEX },
{ "INDEXDIR", CONF_INDEXDIR },
{ "INFOFILE", CONF_INFOFILE },
{ "INPARALLEL", CONF_INPARALLEL },
{ "INTERACTIVITY", CONF_INTERACTIVITY },
{ "INTERFACE", CONF_INTERFACE },
{ "KENCRYPT", CONF_KENCRYPT },
{ "KRB5KEYTAB", CONF_KRB5KEYTAB },
{ "KRB5PRINCIPAL", CONF_KRB5PRINCIPAL },
{ "LABELSTR", CONF_LABELSTR },
{ "LABEL_NEW_TAPES", CONF_LABEL_NEW_TAPES },
{ "LARGEST", CONF_LARGEST },
{ "LARGESTFIT", CONF_LARGESTFIT },
{ "LAST", CONF_LAST },
{ "LBL_TEMPL", CONF_LBL_TEMPL },
{ "LENGTH", CONF_LENGTH },
{ "LIST", CONF_LIST },
{ "LOGDIR", CONF_LOGDIR },
{ "LOW", CONF_LOW },
{ "MAILER", CONF_MAILER },
{ "MAILTO", CONF_MAILTO },
{ "READBLOCKSIZE", CONF_READBLOCKSIZE },
{ "MATCH_AUTOLABEL", CONF_MATCH_AUTOLABEL },
{ "MAX_DLE_BY_VOLUME", CONF_MAX_DLE_BY_VOLUME },
{ "MAXDUMPS", CONF_MAXDUMPS },
{ "MAXDUMPSIZE", CONF_MAXDUMPSIZE },
{ "MAXPROMOTEDAY", CONF_MAXPROMOTEDAY },
{ "MAX_WARNINGS", CONF_MAX_WARNINGS },
{ "MEMORY", CONF_MEMORY },
{ "MEDIUM", CONF_MEDIUM },
{ "META_AUTOLABEL", CONF_META_AUTOLABEL },
{ "NETUSAGE", CONF_NETUSAGE },
{ "NEVER", CONF_NEVER },
{ "NOFULL", CONF_NOFULL },
{ "NOINC", CONF_NOINC },
{ "NONE", CONF_NONE },
{ "NON_AMANDA", CONF_NON_AMANDA },
{ "OPTIONAL", CONF_OPTIONAL },
{ "ORDER", CONF_ORDER },
{ "ORG", CONF_ORG },
{ "OTHER", CONF_OTHER },
{ "OTHER_CONFIG", CONF_OTHER_CONFIG },
{ "PART_CACHE_DIR", CONF_PART_CACHE_DIR },
{ "PART_CACHE_MAX_SIZE", CONF_PART_CACHE_MAX_SIZE },
{ "PART_CACHE_TYPE", CONF_PART_CACHE_TYPE },
{ "PART_SIZE", CONF_PART_SIZE },
{ "PLUGIN", CONF_PLUGIN },
{ "PRE_AMCHECK", CONF_PRE_AMCHECK },
{ "POLICY", CONF_POLICY },
{ "PRE_DLE_AMCHECK", CONF_PRE_DLE_AMCHECK },
{ "PRE_HOST_AMCHECK", CONF_PRE_HOST_AMCHECK },
{ "POST_AMCHECK", CONF_POST_AMCHECK },
{ "POST_DLE_AMCHECK", CONF_POST_DLE_AMCHECK },
{ "POST_HOST_AMCHECK", CONF_POST_HOST_AMCHECK },
{ "PRE_ESTIMATE", CONF_PRE_ESTIMATE },
{ "PRE_DLE_ESTIMATE", CONF_PRE_DLE_ESTIMATE },
{ "PRE_HOST_ESTIMATE", CONF_PRE_HOST_ESTIMATE },
{ "POST_ESTIMATE", CONF_POST_ESTIMATE },
{ "POST_DLE_ESTIMATE", CONF_POST_DLE_ESTIMATE },
{ "POST_HOST_ESTIMATE", CONF_POST_HOST_ESTIMATE },
{ "POST_BACKUP", CONF_POST_BACKUP },
{ "POST_DLE_BACKUP", CONF_POST_DLE_BACKUP },
{ "POST_HOST_BACKUP", CONF_POST_HOST_BACKUP },
{ "PRE_BACKUP", CONF_PRE_BACKUP },
{ "PRE_DLE_BACKUP", CONF_PRE_DLE_BACKUP },
{ "PRE_HOST_BACKUP", CONF_PRE_HOST_BACKUP },
{ "PRE_RECOVER", CONF_PRE_RECOVER },
{ "POST_RECOVER", CONF_POST_RECOVER },
{ "PRE_LEVEL_RECOVER", CONF_PRE_LEVEL_RECOVER },
{ "POST_LEVEL_RECOVER", CONF_POST_LEVEL_RECOVER },
{ "INTER_LEVEL_RECOVER", CONF_INTER_LEVEL_RECOVER },
{ "PRINTER", CONF_PRINTER },
{ "PRIORITY", CONF_PRIORITY },
{ "PROGRAM", CONF_PROGRAM },
{ "PROPERTY", CONF_PROPERTY },
{ "RECORD", CONF_RECORD },
{ "RECOVERY_LIMIT", CONF_RECOVERY_LIMIT },
{ "REP_TRIES", CONF_REP_TRIES },
{ "REPORT_FORMAT", CONF_REPORT_FORMAT },
{ "REPORT_NEXT_MEDIA", CONF_REPORT_NEXT_MEDIA },
{ "REPORT_USE_MEDIA", CONF_REPORT_USE_MEDIA },
{ "REQ_TRIES", CONF_REQ_TRIES },
{ "REQUIRED", CONF_REQUIRED },
{ "RESERVE", CONF_RESERVE },
{ "RESERVED_UDP_PORT", CONF_RESERVED_UDP_PORT },
{ "RESERVED_TCP_PORT", CONF_RESERVED_TCP_PORT },
{ "REST_API_PORT", CONF_REST_API_PORT },
{ "REST_SSL_CERT", CONF_REST_SSL_CERT },
{ "REST_SSL_KEY", CONF_REST_SSL_KEY },
{ "RETRY_DUMP", CONF_RETRY_DUMP },
{ "RETENTION_DAYS", CONF_RETENTION_DAYS },
{ "RETENTION_FULL", CONF_RETENTION_FULL },
{ "RETENTION_RECOVER", CONF_RETENTION_RECOVER },
{ "RETENTION_TAPES", CONF_RETENTION_TAPES },
{ "RUNSPERCYCLE", CONF_RUNSPERCYCLE },
{ "RUNTAPES", CONF_RUNTAPES },
{ "SAME_HOST", CONF_SAME_HOST },
{ "SCRIPT", CONF_SCRIPT },
{ "SCRIPT_TOOL", CONF_SCRIPT_TOOL },
{ "SEND_AMREPORT_ON", CONF_SEND_AMREPORT_ON },
{ "SERVER", CONF_SERVER },
{ "SERVER_CUSTOM_COMPRESS", CONF_SRVCOMPPROG },
{ "SERVER_DECRYPT_OPTION", CONF_SRV_DECRYPT_OPT },
{ "SERVER_ENCRYPT", CONF_SRV_ENCRYPT },
{ "SET_NO_REUSE", CONF_SET_NO_REUSE },
{ "SKIP", CONF_SKIP },
{ "SKIP_FULL", CONF_SKIP_FULL },
{ "SKIP_INCR", CONF_SKIP_INCR },
{ "SINGLE_EXECUTION", CONF_SINGLE_EXECUTION },
{ "SMALLEST", CONF_SMALLEST },
{ "SORT_INDEX", CONF_SORT_INDEX },
{ "SPEED", CONF_SPEED },
{ "SPLIT_DISKBUFFER", CONF_SPLIT_DISKBUFFER },
{ "SRC_IP", CONF_SRC_IP },
{ "SSH_KEYS", CONF_SSH_KEYS },
{ "SSL_CA_CERT_FILE", CONF_SSL_CA_CERT_FILE },
{ "SSL_CERT_FILE", CONF_SSL_CERT_FILE },
{ "SSL_CHECK_CERTIFICATE_HOST", CONF_SSL_CHECK_CERTIFICATE_HOST },
{ "SSL_CIPHER_LIST", CONF_SSL_CIPHER_LIST },
{ "SSL_DIR", CONF_SSL_DIR },
{ "SSL_FINGERPRINT_FILE", CONF_SSL_FINGERPRINT_FILE },
{ "SSL_CHECK_HOST", CONF_SSL_CHECK_HOST },
{ "SSL_CHECK_CERTIFICATE_HOST", CONF_SSL_CHECK_CERTIFICATE_HOST },
{ "SSL_CHECK_FINGERPRINT", CONF_SSL_CHECK_FINGERPRINT },
{ "SSL_KEY_FILE", CONF_SSL_KEY_FILE },
{ "STANDARD", CONF_STANDARD },
{ "STARTTIME", CONF_STARTTIME },
{ "STORAGE", CONF_STORAGE },
{ "STRANGE", CONF_STRANGE },
{ "STRATEGY", CONF_STRATEGY },
{ "DEVICE_OUTPUT_BUFFER_SIZE", CONF_DEVICE_OUTPUT_BUFFER_SIZE },
{ "TAG", CONF_TAG },
{ "TAPECYCLE", CONF_TAPECYCLE },
{ "TAPEDEV", CONF_TAPEDEV },
{ "TAPELIST", CONF_TAPELIST },
{ "TAPEPOOL", CONF_TAPEPOOL },
{ "TAPERALGO", CONF_TAPERALGO },
{ "TAPERSCAN", CONF_TAPERSCAN },
{ "TAPER_PARALLEL_WRITE", CONF_TAPER_PARALLEL_WRITE },
{ "FLUSH_THRESHOLD_DUMPED", CONF_FLUSH_THRESHOLD_DUMPED },
{ "FLUSH_THRESHOLD_SCHEDULED", CONF_FLUSH_THRESHOLD_SCHEDULED },
{ "TAPERFLUSH", CONF_TAPERFLUSH },
{ "TAPETYPE", CONF_TAPETYPE },
{ "TAPE_SPLITSIZE", CONF_TAPE_SPLITSIZE },
{ "TMPDIR", CONF_TMPDIR },
{ "TPCHANGER", CONF_TPCHANGER },
{ "UNRESERVED_TCP_PORT", CONF_UNRESERVED_TCP_PORT },
{ "USE", CONF_USE },
{ "USETIMESTAMPS", CONF_USETIMESTAMPS },
{ "VAULT", CONF_VAULT },
{ "VISIBLE", CONF_VISIBLE },
{ "VOLUME_ERROR", CONF_VOLUME_ERROR },
{ NULL, CONF_IDENT },
{ NULL, CONF_UNKNOWN }
};
/* A keyword table for recognizing unit suffixes. No distinction is made for kinds
* of suffixes: 1024 weeks = 7 k. */
keytab_t numb_keytable[] = {
{ "B", CONF_MULT1 },
{ "BPS", CONF_MULT1 },
{ "BYTE", CONF_MULT1 },
{ "BYTES", CONF_MULT1 },
{ "DAY", CONF_MULT1 },
{ "DAYS", CONF_MULT1 },
{ "INF", CONF_AMINFINITY },
{ "K", CONF_MULT1K },
{ "KB", CONF_MULT1K },
{ "KBPS", CONF_MULT1K },
{ "KBYTE", CONF_MULT1K },
{ "KBYTES", CONF_MULT1K },
{ "KILOBYTE", CONF_MULT1K },
{ "KILOBYTES", CONF_MULT1K },
{ "KPS", CONF_MULT1K },
{ "M", CONF_MULT1M },
{ "MB", CONF_MULT1M },
{ "MBPS", CONF_MULT1M },
{ "MBYTE", CONF_MULT1M },
{ "MBYTES", CONF_MULT1M },
{ "MEG", CONF_MULT1M },
{ "MEGABYTE", CONF_MULT1M },
{ "MEGABYTES", CONF_MULT1M },
{ "G", CONF_MULT1G },
{ "GB", CONF_MULT1G },
{ "GBPS", CONF_MULT1G },
{ "GBYTE", CONF_MULT1G },
{ "GBYTES", CONF_MULT1G },
{ "GIG", CONF_MULT1G },
{ "GIGABYTE", CONF_MULT1G },
{ "GIGABYTES", CONF_MULT1G },
{ "T", CONF_MULT1T },
{ "TB", CONF_MULT1T },
{ "TBPS", CONF_MULT1T },
{ "TBYTE", CONF_MULT1T },
{ "TBYTES", CONF_MULT1T },
{ "TERA", CONF_MULT1T },
{ "TERABYTE", CONF_MULT1T },
{ "TERABYTES", CONF_MULT1T },
{ "MPS", CONF_MULT1M },
{ "TAPE", CONF_MULT1 },
{ "TAPES", CONF_MULT1 },
{ "WEEK", CONF_MULT7 },
{ "WEEKS", CONF_MULT7 },
{ NULL, CONF_IDENT }
};
/* Boolean keywords -- all the ways to say "true" and "false" in amanda.conf */
keytab_t bool_keytable[] = {
{ "Y", CONF_ATRUE },
{ "YES", CONF_ATRUE },
{ "T", CONF_ATRUE },
{ "TRUE", CONF_ATRUE },
{ "ON", CONF_ATRUE },
{ "N", CONF_AFALSE },
{ "NO", CONF_AFALSE },
{ "F", CONF_AFALSE },
{ "FALSE", CONF_AFALSE },
{ "OFF", CONF_AFALSE },
{ NULL, CONF_IDENT }
};
/* no_yes_all keywords -- all the ways to say "true" and "false" in amanda.conf */
keytab_t no_yes_all_keytable[] = {
{ "Y", CONF_ATRUE },
{ "YES", CONF_ATRUE },
{ "T", CONF_ATRUE },
{ "TRUE", CONF_ATRUE },
{ "ON", CONF_ATRUE },
{ "N", CONF_AFALSE },
{ "NO", CONF_AFALSE },
{ "F", CONF_AFALSE },
{ "FALSE", CONF_AFALSE },
{ "OFF", CONF_AFALSE },
{ "ALL", CONF_ALL },
{ NULL, CONF_IDENT }
};
/* Now, the parser tables for client and server global parameters, and for
* each of the server subsections */
conf_var_t client_var [] = {
{ CONF_CONF , CONFTYPE_STR , read_str , CNF_CONF , NULL },
{ CONF_AMDUMP_SERVER , CONFTYPE_STR , read_str , CNF_AMDUMP_SERVER , NULL },
{ CONF_INDEX_SERVER , CONFTYPE_STR , read_str , CNF_INDEX_SERVER , NULL },
{ CONF_TAPE_SERVER , CONFTYPE_STR , read_str , CNF_TAPE_SERVER , NULL },
{ CONF_TAPEDEV , CONFTYPE_STR , read_str , CNF_TAPEDEV , NULL },
{ CONF_AUTH , CONFTYPE_STR , read_str , CNF_AUTH , NULL },
{ CONF_SSH_KEYS , CONFTYPE_STR , read_str , CNF_SSH_KEYS , NULL },
{ CONF_AMANDAD_PATH , CONFTYPE_STR , read_str , CNF_AMANDAD_PATH , NULL },
{ CONF_CLIENT_USERNAME , CONFTYPE_STR , read_str , CNF_CLIENT_USERNAME , NULL },
{ CONF_CLIENT_PORT , CONFTYPE_STR , read_int_or_str, CNF_CLIENT_PORT , NULL },
{ CONF_CTIMEOUT , CONFTYPE_INT , read_int , CNF_CTIMEOUT , validate_positive },
{ CONF_SSL_DIR , CONFTYPE_STR , read_str , CNF_SSL_DIR , NULL },
{ CONF_SSL_CHECK_FINGERPRINT, CONFTYPE_BOOLEAN, read_bool , CNF_SSL_CHECK_FINGERPRINT , NULL },
{ CONF_SSL_FINGERPRINT_FILE, CONFTYPE_STR , read_str , CNF_SSL_FINGERPRINT_FILE , NULL },
{ CONF_SSL_CERT_FILE , CONFTYPE_STR , read_str , CNF_SSL_CERT_FILE , NULL },
{ CONF_SSL_KEY_FILE , CONFTYPE_STR , read_str , CNF_SSL_KEY_FILE , NULL },
{ CONF_SSL_CA_CERT_FILE , CONFTYPE_STR , read_str , CNF_SSL_CA_CERT_FILE , NULL },
{ CONF_SSL_CIPHER_LIST , CONFTYPE_STR , read_str , CNF_SSL_CIPHER_LIST , NULL },
{ CONF_SSL_CHECK_HOST , CONFTYPE_BOOLEAN , read_bool , CNF_SSL_CHECK_HOST , NULL },
{ CONF_SSL_CHECK_CERTIFICATE_HOST, CONFTYPE_BOOLEAN, read_bool, CNF_SSL_CHECK_CERTIFICATE_HOST , NULL },
{ CONF_GNUTAR_LIST_DIR , CONFTYPE_STR , read_str , CNF_GNUTAR_LIST_DIR , NULL },
{ CONF_AMANDATES , CONFTYPE_STR , read_str , CNF_AMANDATES , NULL },
{ CONF_MAILER , CONFTYPE_STR , read_str , CNF_MAILER , NULL },
{ CONF_KRB5KEYTAB , CONFTYPE_STR , read_str , CNF_KRB5KEYTAB , NULL },
{ CONF_KRB5PRINCIPAL , CONFTYPE_STR , read_str , CNF_KRB5PRINCIPAL , NULL },
{ CONF_CONNECT_TRIES , CONFTYPE_INT , read_int , CNF_CONNECT_TRIES , validate_positive },
{ CONF_REP_TRIES , CONFTYPE_INT , read_int , CNF_REP_TRIES , validate_positive },
{ CONF_REQ_TRIES , CONFTYPE_INT , read_int , CNF_REQ_TRIES , validate_positive },
{ CONF_DEBUG_DAYS , CONFTYPE_INT , read_int , CNF_DEBUG_DAYS , NULL },
{ CONF_DEBUG_AMANDAD , CONFTYPE_INT , read_int , CNF_DEBUG_AMANDAD , validate_debug },
{ CONF_DEBUG_RECOVERY , CONFTYPE_INT , read_int , CNF_DEBUG_RECOVERY , validate_debug },
{ CONF_DEBUG_AMIDXTAPED , CONFTYPE_INT , read_int , CNF_DEBUG_AMIDXTAPED , validate_debug },
{ CONF_DEBUG_AMINDEXD , CONFTYPE_INT , read_int , CNF_DEBUG_AMINDEXD , validate_debug },
{ CONF_DEBUG_AMRECOVER , CONFTYPE_INT , read_int , CNF_DEBUG_AMRECOVER , validate_debug },
{ CONF_DEBUG_AUTH , CONFTYPE_INT , read_int , CNF_DEBUG_AUTH , validate_debug },
{ CONF_DEBUG_EVENT , CONFTYPE_INT , read_int , CNF_DEBUG_EVENT , validate_debug },
{ CONF_DEBUG_HOLDING , CONFTYPE_INT , read_int , CNF_DEBUG_HOLDING , validate_debug },
{ CONF_DEBUG_PROTOCOL , CONFTYPE_INT , read_int , CNF_DEBUG_PROTOCOL , validate_debug },
{ CONF_DEBUG_PLANNER , CONFTYPE_INT , read_int , CNF_DEBUG_PLANNER , validate_debug },
{ CONF_DEBUG_DRIVER , CONFTYPE_INT , read_int , CNF_DEBUG_DRIVER , validate_debug },
{ CONF_DEBUG_DUMPER , CONFTYPE_INT , read_int , CNF_DEBUG_DUMPER , validate_debug },
{ CONF_DEBUG_CHUNKER , CONFTYPE_INT , read_int , CNF_DEBUG_CHUNKER , validate_debug },
{ CONF_DEBUG_TAPER , CONFTYPE_INT , read_int , CNF_DEBUG_TAPER , validate_debug },
{ CONF_DEBUG_SELFCHECK , CONFTYPE_INT , read_int , CNF_DEBUG_SELFCHECK , validate_debug },
{ CONF_DEBUG_SENDSIZE , CONFTYPE_INT , read_int , CNF_DEBUG_SENDSIZE , validate_debug },
{ CONF_DEBUG_SENDBACKUP , CONFTYPE_INT , read_int , CNF_DEBUG_SENDBACKUP , validate_debug },
{ CONF_RESERVED_UDP_PORT , CONFTYPE_INTRANGE, read_intrange, CNF_RESERVED_UDP_PORT , validate_reserved_port_range },
{ CONF_RESERVED_TCP_PORT , CONFTYPE_INTRANGE, read_intrange, CNF_RESERVED_TCP_PORT , validate_reserved_port_range },
{ CONF_UNRESERVED_TCP_PORT, CONFTYPE_INTRANGE, read_intrange, CNF_UNRESERVED_TCP_PORT, validate_unreserved_port_range },
{ CONF_PROPERTY , CONFTYPE_PROPLIST, read_hidden_property, CNF_PROPERTY , NULL },
{ CONF_APPLICATION , CONFTYPE_STR , read_dapplication, DUMPTYPE_APPLICATION, NULL },
{ CONF_SCRIPT , CONFTYPE_STR , read_dpp_script, DUMPTYPE_SCRIPTLIST, NULL },
{ CONF_HOSTNAME , CONFTYPE_STR , read_str , CNF_HOSTNAME , NULL },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , CNF_CNF , NULL }
};
conf_var_t server_var [] = {
{ CONF_ORG , CONFTYPE_STR , read_str , CNF_ORG , NULL },
{ CONF_MAILTO , CONFTYPE_STR , read_str , CNF_MAILTO , NULL },
{ CONF_DUMPUSER , CONFTYPE_STR , read_str , CNF_DUMPUSER , NULL },
{ CONF_PRINTER , CONFTYPE_STR , read_str , CNF_PRINTER , NULL },
{ CONF_MAILER , CONFTYPE_STR , read_str , CNF_MAILER , NULL },
{ CONF_TAPEDEV , CONFTYPE_STR , read_str , CNF_TAPEDEV , NULL },
{ CONF_DEVICE_PROPERTY , CONFTYPE_PROPLIST , read_visible_property, CNF_DEVICE_PROPERTY , NULL },
{ CONF_PROPERTY , CONFTYPE_PROPLIST , read_hidden_property, CNF_PROPERTY , NULL },
{ CONF_TPCHANGER , CONFTYPE_STR , read_str , CNF_TPCHANGER , NULL },
{ CONF_CHANGERDEV , CONFTYPE_STR , read_str , CNF_CHANGERDEV , NULL },
{ CONF_CHANGERFILE , CONFTYPE_STR , read_str , CNF_CHANGERFILE , validate_deprecated_changerfile },
{ CONF_LABELSTR , CONFTYPE_LABELSTR , read_labelstr , CNF_LABELSTR , validate_no_space_dquote },
{ CONF_TAPELIST , CONFTYPE_STR , read_str , CNF_TAPELIST , NULL },
{ CONF_DISKFILE , CONFTYPE_STR , read_str , CNF_DISKFILE , NULL },
{ CONF_INFOFILE , CONFTYPE_STR , read_str , CNF_INFOFILE , NULL },
{ CONF_LOGDIR , CONFTYPE_STR , read_str , CNF_LOGDIR , NULL },
{ CONF_INDEXDIR , CONFTYPE_STR , read_str , CNF_INDEXDIR , NULL },
{ CONF_TAPETYPE , CONFTYPE_IDENT , read_ident , CNF_TAPETYPE , NULL },
{ CONF_HOLDING , CONFTYPE_IDENTLIST, read_holdingdisk , CNF_HOLDINGDISK , NULL },
{ CONF_DUMPCYCLE , CONFTYPE_INT , read_int , CNF_DUMPCYCLE , validate_nonnegative },
{ CONF_RUNSPERCYCLE , CONFTYPE_INT , read_int , CNF_RUNSPERCYCLE , validate_runspercycle },
{ CONF_RUNTAPES , CONFTYPE_INT , read_int , CNF_RUNTAPES , validate_nonnegative },
{ CONF_TAPECYCLE , CONFTYPE_INT , read_int , CNF_TAPECYCLE , validate_positive },
{ CONF_BUMPDAYS , CONFTYPE_INT , read_int , CNF_BUMPDAYS , validate_nonnegative },
{ CONF_BUMPSIZE , CONFTYPE_INT64 , read_int64 , CNF_BUMPSIZE , validate_positive },
{ CONF_BUMPPERCENT , CONFTYPE_INT , read_int , CNF_BUMPPERCENT , validate_bumppercent },
{ CONF_BUMPMULT , CONFTYPE_REAL , read_real , CNF_BUMPMULT , validate_bumpmult },
{ CONF_NETUSAGE , CONFTYPE_INT , read_int , CNF_NETUSAGE , validate_positive },
{ CONF_INPARALLEL , CONFTYPE_INT , read_int , CNF_INPARALLEL , validate_positive },
{ CONF_DUMPORDER , CONFTYPE_STR , read_str , CNF_DUMPORDER , NULL },
{ CONF_MAXDUMPS , CONFTYPE_INT , read_int , CNF_MAXDUMPS , validate_positive },
{ CONF_MAX_DLE_BY_VOLUME , CONFTYPE_INT , read_int , CNF_MAX_DLE_BY_VOLUME , validate_positive },
{ CONF_ETIMEOUT , CONFTYPE_INT , read_int , CNF_ETIMEOUT , validate_non_zero },
{ CONF_DTIMEOUT , CONFTYPE_INT , read_int , CNF_DTIMEOUT , validate_positive },
{ CONF_CTIMEOUT , CONFTYPE_INT , read_int , CNF_CTIMEOUT , validate_positive },
{ CONF_DEVICE_OUTPUT_BUFFER_SIZE, CONFTYPE_SIZE , read_size , CNF_DEVICE_OUTPUT_BUFFER_SIZE, NULL },
{ CONF_COLUMNSPEC , CONFTYPE_STR , read_str , CNF_COLUMNSPEC , validate_columnspec },
{ CONF_TAPERALGO , CONFTYPE_TAPERALGO, read_taperalgo , CNF_TAPERALGO , NULL },
{ CONF_TAPER_PARALLEL_WRITE , CONFTYPE_INT , read_int , CNF_TAPER_PARALLEL_WRITE , NULL },
{ CONF_SEND_AMREPORT_ON , CONFTYPE_SEND_AMREPORT_ON, read_send_amreport_on, CNF_SEND_AMREPORT_ON , NULL },
{ CONF_FLUSH_THRESHOLD_DUMPED, CONFTYPE_INT , read_int , CNF_FLUSH_THRESHOLD_DUMPED, validate_nonnegative },
{ CONF_FLUSH_THRESHOLD_SCHEDULED, CONFTYPE_INT , read_int , CNF_FLUSH_THRESHOLD_SCHEDULED, validate_nonnegative },
{ CONF_TAPERFLUSH , CONFTYPE_INT , read_int , CNF_TAPERFLUSH , validate_nonnegative },
{ CONF_DISPLAYUNIT , CONFTYPE_STR , read_str , CNF_DISPLAYUNIT , validate_displayunit },
{ CONF_AUTOFLUSH , CONFTYPE_NO_YES_ALL,read_no_yes_all , CNF_AUTOFLUSH , NULL },
{ CONF_RESERVE , CONFTYPE_INT , read_int , CNF_RESERVE , validate_reserve },
{ CONF_MAXDUMPSIZE , CONFTYPE_INT64 , read_int64 , CNF_MAXDUMPSIZE , NULL },
{ CONF_KRB5KEYTAB , CONFTYPE_STR , read_str , CNF_KRB5KEYTAB , NULL },
{ CONF_KRB5PRINCIPAL , CONFTYPE_STR , read_str , CNF_KRB5PRINCIPAL , NULL },
{ CONF_LABEL_NEW_TAPES , CONFTYPE_STR , read_str , CNF_LABEL_NEW_TAPES , NULL },
{ CONF_AUTOLABEL , CONFTYPE_AUTOLABEL, read_autolabel , CNF_AUTOLABEL , validate_no_space_dquote },
{ CONF_META_AUTOLABEL , CONFTYPE_STR , read_str , CNF_META_AUTOLABEL , validate_no_space_dquote },
{ CONF_EJECT_VOLUME , CONFTYPE_BOOLEAN , read_bool , CNF_EJECT_VOLUME , NULL },
{ CONF_TMPDIR , CONFTYPE_STR , read_str , CNF_TMPDIR , validate_tmpdir },
{ CONF_USETIMESTAMPS , CONFTYPE_BOOLEAN , read_bool , CNF_USETIMESTAMPS , NULL },
{ CONF_AMRECOVER_DO_FSF , CONFTYPE_BOOLEAN , read_bool , CNF_AMRECOVER_DO_FSF , NULL },
{ CONF_AMRECOVER_CHANGER , CONFTYPE_STR , read_str , CNF_AMRECOVER_CHANGER , NULL },
{ CONF_AMRECOVER_CHECK_LABEL, CONFTYPE_BOOLEAN , read_bool , CNF_AMRECOVER_CHECK_LABEL, NULL },
{ CONF_CONNECT_TRIES , CONFTYPE_INT , read_int , CNF_CONNECT_TRIES , validate_positive },
{ CONF_REP_TRIES , CONFTYPE_INT , read_int , CNF_REP_TRIES , validate_positive },
{ CONF_REQ_TRIES , CONFTYPE_INT , read_int , CNF_REQ_TRIES , validate_positive },
{ CONF_DEBUG_DAYS , CONFTYPE_INT , read_int , CNF_DEBUG_DAYS , NULL },
{ CONF_DEBUG_AMANDAD , CONFTYPE_INT , read_int , CNF_DEBUG_AMANDAD , validate_debug },
{ CONF_DEBUG_RECOVERY , CONFTYPE_INT , read_int , CNF_DEBUG_RECOVERY , validate_debug },
{ CONF_DEBUG_AMIDXTAPED , CONFTYPE_INT , read_int , CNF_DEBUG_AMIDXTAPED , validate_debug },
{ CONF_DEBUG_AMINDEXD , CONFTYPE_INT , read_int , CNF_DEBUG_AMINDEXD , validate_debug },
{ CONF_DEBUG_AMRECOVER , CONFTYPE_INT , read_int , CNF_DEBUG_AMRECOVER , validate_debug },
{ CONF_DEBUG_AUTH , CONFTYPE_INT , read_int , CNF_DEBUG_AUTH , validate_debug },
{ CONF_DEBUG_EVENT , CONFTYPE_INT , read_int , CNF_DEBUG_EVENT , validate_debug },
{ CONF_DEBUG_HOLDING , CONFTYPE_INT , read_int , CNF_DEBUG_HOLDING , validate_debug },
{ CONF_DEBUG_PROTOCOL , CONFTYPE_INT , read_int , CNF_DEBUG_PROTOCOL , validate_debug },
{ CONF_DEBUG_PLANNER , CONFTYPE_INT , read_int , CNF_DEBUG_PLANNER , validate_debug },
{ CONF_DEBUG_DRIVER , CONFTYPE_INT , read_int , CNF_DEBUG_DRIVER , validate_debug },
{ CONF_DEBUG_DUMPER , CONFTYPE_INT , read_int , CNF_DEBUG_DUMPER , validate_debug },
{ CONF_DEBUG_CHUNKER , CONFTYPE_INT , read_int , CNF_DEBUG_CHUNKER , validate_debug },
{ CONF_DEBUG_TAPER , CONFTYPE_INT , read_int , CNF_DEBUG_TAPER , validate_debug },
{ CONF_DEBUG_SELFCHECK , CONFTYPE_INT , read_int , CNF_DEBUG_SELFCHECK , validate_debug },
{ CONF_DEBUG_SENDSIZE , CONFTYPE_INT , read_int , CNF_DEBUG_SENDSIZE , validate_debug },
{ CONF_DEBUG_SENDBACKUP , CONFTYPE_INT , read_int , CNF_DEBUG_SENDBACKUP , validate_debug },
{ CONF_RESERVED_UDP_PORT , CONFTYPE_INTRANGE , read_intrange , CNF_RESERVED_UDP_PORT , validate_reserved_port_range },
{ CONF_RESERVED_TCP_PORT , CONFTYPE_INTRANGE , read_intrange , CNF_RESERVED_TCP_PORT , validate_reserved_port_range },
{ CONF_UNRESERVED_TCP_PORT , CONFTYPE_INTRANGE , read_intrange , CNF_UNRESERVED_TCP_PORT , validate_unreserved_port_range },
{ CONF_RECOVERY_LIMIT , CONFTYPE_HOST_LIMIT, read_host_limit , CNF_RECOVERY_LIMIT , NULL },
{ CONF_INTERACTIVITY , CONFTYPE_STR , read_dinteractivity, CNF_INTERACTIVITY , NULL },
{ CONF_TAPERSCAN , CONFTYPE_STR , read_dtaperscan , CNF_TAPERSCAN , NULL },
{ CONF_REPORT_USE_MEDIA , CONFTYPE_BOOLEAN , read_bool , CNF_REPORT_USE_MEDIA , NULL },
{ CONF_REPORT_NEXT_MEDIA , CONFTYPE_BOOLEAN , read_bool , CNF_REPORT_NEXT_MEDIA , NULL },
{ CONF_REPORT_FORMAT , CONFTYPE_STR_LIST , read_str_list , CNF_REPORT_FORMAT , NULL },
{ CONF_ACTIVE_STORAGE , CONFTYPE_IDENTLIST, read_storage_identlist, CNF_ACTIVE_STORAGE , NULL },
{ CONF_STORAGE , CONFTYPE_IDENTLIST, read_storage_identlist, CNF_STORAGE , NULL },
{ CONF_VAULT_STORAGE , CONFTYPE_IDENTLIST, read_storage_identlist, CNF_VAULT_STORAGE , NULL },
{ CONF_CMDFILE , CONFTYPE_STR , read_str , CNF_CMDFILE , NULL },
{ CONF_REST_API_PORT , CONFTYPE_INT , read_int , CNF_REST_API_PORT , validate_positive },
{ CONF_REST_SSL_CERT , CONFTYPE_STR , read_str , CNF_REST_SSL_CERT , NULL },
{ CONF_REST_SSL_KEY , CONFTYPE_STR , read_str , CNF_REST_SSL_KEY , NULL },
{ CONF_SSL_DIR , CONFTYPE_STR , read_str , CNF_SSL_DIR , NULL },
{ CONF_COMPRESS_INDEX , CONFTYPE_BOOLEAN , read_bool , CNF_COMPRESS_INDEX , NULL },
{ CONF_SORT_INDEX , CONFTYPE_BOOLEAN , read_bool , CNF_SORT_INDEX , NULL },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , CNF_CNF , NULL }
};
conf_var_t tapetype_var [] = {
{ CONF_COMMENT , CONFTYPE_STR , read_str , TAPETYPE_COMMENT , NULL },
{ CONF_LBL_TEMPL , CONFTYPE_STR , read_str , TAPETYPE_LBL_TEMPL , NULL },
{ CONF_BLOCKSIZE , CONFTYPE_SIZE , read_size , TAPETYPE_BLOCKSIZE , validate_blocksize },
{ CONF_READBLOCKSIZE , CONFTYPE_SIZE , read_size , TAPETYPE_READBLOCKSIZE , validate_blocksize },
{ CONF_LENGTH , CONFTYPE_INT64 , read_int64 , TAPETYPE_LENGTH , validate_nonnegative },
{ CONF_FILEMARK , CONFTYPE_INT64 , read_int64 , TAPETYPE_FILEMARK , NULL },
{ CONF_SPEED , CONFTYPE_INT , read_int , TAPETYPE_SPEED , validate_nonnegative },
{ CONF_PART_SIZE , CONFTYPE_INT64 , read_int64 , TAPETYPE_PART_SIZE , validate_nonnegative },
{ CONF_PART_CACHE_TYPE , CONFTYPE_PART_CACHE_TYPE, read_part_cache_type, TAPETYPE_PART_CACHE_TYPE , NULL },
{ CONF_PART_CACHE_DIR , CONFTYPE_STR , read_str , TAPETYPE_PART_CACHE_DIR , NULL },
{ CONF_PART_CACHE_MAX_SIZE , CONFTYPE_INT64 , read_int64 , TAPETYPE_PART_CACHE_MAX_SIZE, validate_nonnegative },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , TAPETYPE_TAPETYPE , NULL }
};
conf_var_t dumptype_var [] = {
{ CONF_COMMENT , CONFTYPE_STR , read_str , DUMPTYPE_COMMENT , NULL },
{ CONF_AUTH , CONFTYPE_STR , read_str , DUMPTYPE_AUTH , NULL },
{ CONF_BUMPDAYS , CONFTYPE_INT , read_int , DUMPTYPE_BUMPDAYS , validate_nonnegative },
{ CONF_BUMPMULT , CONFTYPE_REAL , read_real , DUMPTYPE_BUMPMULT , validate_bumpmult },
{ CONF_BUMPSIZE , CONFTYPE_INT64 , read_int64 , DUMPTYPE_BUMPSIZE , validate_positive },
{ CONF_BUMPPERCENT , CONFTYPE_INT , read_int , DUMPTYPE_BUMPPERCENT , validate_bumppercent },
{ CONF_COMPRATE , CONFTYPE_REAL , read_rate , DUMPTYPE_COMPRATE , NULL },
{ CONF_COMPRESS , CONFTYPE_INT , read_compress , DUMPTYPE_COMPRESS , NULL },
{ CONF_ENCRYPT , CONFTYPE_INT , read_encrypt , DUMPTYPE_ENCRYPT , NULL },
{ CONF_DUMPCYCLE , CONFTYPE_INT , read_int , DUMPTYPE_DUMPCYCLE , validate_nonnegative },
{ CONF_EXCLUDE , CONFTYPE_EXINCLUDE , read_exinclude , DUMPTYPE_EXCLUDE , NULL },
{ CONF_INCLUDE , CONFTYPE_EXINCLUDE , read_exinclude , DUMPTYPE_INCLUDE , NULL },
{ CONF_IGNORE , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_IGNORE , NULL },
{ CONF_HOLDING , CONFTYPE_HOLDING , read_holding , DUMPTYPE_HOLDINGDISK , NULL },
{ CONF_INDEX , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_INDEX , NULL },
{ CONF_KENCRYPT , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_KENCRYPT , NULL },
{ CONF_MAXDUMPS , CONFTYPE_INT , read_int , DUMPTYPE_MAXDUMPS , validate_positive },
{ CONF_MAXPROMOTEDAY , CONFTYPE_INT , read_int , DUMPTYPE_MAXPROMOTEDAY , validate_nonnegative },
{ CONF_PRIORITY , CONFTYPE_PRIORITY , read_priority , DUMPTYPE_PRIORITY , NULL },
{ CONF_PROGRAM , CONFTYPE_STR , read_str , DUMPTYPE_PROGRAM , validate_program },
{ CONF_PROPERTY , CONFTYPE_PROPLIST ,read_hidden_property, DUMPTYPE_PROPERTY , NULL },
{ CONF_RECORD , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_RECORD , NULL },
{ CONF_SKIP_FULL , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_SKIP_FULL , NULL },
{ CONF_SKIP_INCR , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_SKIP_INCR , NULL },
{ CONF_STARTTIME , CONFTYPE_TIME , read_time , DUMPTYPE_STARTTIME , NULL },
{ CONF_STRATEGY , CONFTYPE_INT , read_strategy , DUMPTYPE_STRATEGY , NULL },
{ CONF_TAPE_SPLITSIZE , CONFTYPE_INT64 , read_int64 , DUMPTYPE_TAPE_SPLITSIZE , validate_nonnegative },
{ CONF_SPLIT_DISKBUFFER , CONFTYPE_STR , read_str , DUMPTYPE_SPLIT_DISKBUFFER , NULL },
{ CONF_ESTIMATE , CONFTYPE_ESTIMATELIST, read_estimatelist, DUMPTYPE_ESTIMATELIST , NULL },
{ CONF_SRV_ENCRYPT , CONFTYPE_STR , read_str , DUMPTYPE_SRV_ENCRYPT , NULL },
{ CONF_CLNT_ENCRYPT , CONFTYPE_STR , read_str , DUMPTYPE_CLNT_ENCRYPT , NULL },
{ CONF_AMANDAD_PATH , CONFTYPE_STR , read_str , DUMPTYPE_AMANDAD_PATH , NULL },
{ CONF_CLIENT_USERNAME , CONFTYPE_STR , read_str , DUMPTYPE_CLIENT_USERNAME , NULL },
{ CONF_CLIENT_PORT , CONFTYPE_STR , read_int_or_str , DUMPTYPE_CLIENT_PORT , NULL },
{ CONF_SSH_KEYS , CONFTYPE_STR , read_str , DUMPTYPE_SSH_KEYS , NULL },
{ CONF_SRVCOMPPROG , CONFTYPE_STR , read_str , DUMPTYPE_SRVCOMPPROG , NULL },
{ CONF_CLNTCOMPPROG , CONFTYPE_STR , read_str , DUMPTYPE_CLNTCOMPPROG , NULL },
{ CONF_FALLBACK_SPLITSIZE , CONFTYPE_INT64 , read_int64 , DUMPTYPE_FALLBACK_SPLITSIZE , NULL },
{ CONF_SRV_DECRYPT_OPT , CONFTYPE_STR , read_str , DUMPTYPE_SRV_DECRYPT_OPT , NULL },
{ CONF_CLNT_DECRYPT_OPT , CONFTYPE_STR , read_str , DUMPTYPE_CLNT_DECRYPT_OPT , NULL },
{ CONF_APPLICATION , CONFTYPE_STR , read_dapplication, DUMPTYPE_APPLICATION , NULL },
{ CONF_SCRIPT , CONFTYPE_STR , read_dpp_script , DUMPTYPE_SCRIPTLIST , NULL },
{ CONF_DATA_PATH , CONFTYPE_DATA_PATH , read_data_path , DUMPTYPE_DATA_PATH , NULL },
{ CONF_ALLOW_SPLIT , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_ALLOW_SPLIT , NULL },
{ CONF_MAX_WARNINGS , CONFTYPE_INT , read_int , DUMPTYPE_MAX_WARNINGS , validate_nonnegative },
{ CONF_RECOVERY_LIMIT , CONFTYPE_HOST_LIMIT , read_host_limit , DUMPTYPE_RECOVERY_LIMIT , NULL },
{ CONF_DUMP_LIMIT , CONFTYPE_HOST_LIMIT , read_host_limit , DUMPTYPE_DUMP_LIMIT , validate_dump_limit },
{ CONF_RETRY_DUMP , CONFTYPE_INT , read_int , DUMPTYPE_RETRY_DUMP , validate_positive },
{ CONF_TAG , CONFTYPE_STR_LIST , read_str_list , DUMPTYPE_TAG , NULL },
{ CONF_SSL_FINGERPRINT_FILE , CONFTYPE_STR , read_str , DUMPTYPE_SSL_FINGERPRINT_FILE , NULL },
{ CONF_SSL_CERT_FILE , CONFTYPE_STR , read_str , DUMPTYPE_SSL_CERT_FILE , NULL },
{ CONF_SSL_KEY_FILE , CONFTYPE_STR , read_str , DUMPTYPE_SSL_KEY_FILE , NULL },
{ CONF_SSL_CA_CERT_FILE , CONFTYPE_STR , read_str , DUMPTYPE_SSL_CA_CERT_FILE , NULL },
{ CONF_SSL_CIPHER_LIST , CONFTYPE_STR , read_str , DUMPTYPE_SSL_CIPHER_LIST , NULL },
{ CONF_SSL_CHECK_HOST , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_SSL_CHECK_HOST , NULL },
{ CONF_SSL_CHECK_CERTIFICATE_HOST, CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_SSL_CHECK_CERTIFICATE_HOST, NULL },
{ CONF_SSL_CHECK_FINGERPRINT , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_SSL_CHECK_FINGERPRINT , NULL },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , DUMPTYPE_DUMPTYPE , NULL }
};
conf_var_t holding_var [] = {
{ CONF_DIRECTORY, CONFTYPE_STR , read_str , HOLDING_DISKDIR , NULL },
{ CONF_COMMENT , CONFTYPE_STR , read_str , HOLDING_COMMENT , NULL },
{ CONF_USE , CONFTYPE_INT64 , read_int64 , HOLDING_DISKSIZE , validate_use },
{ CONF_CHUNKSIZE, CONFTYPE_INT64 , read_int64 , HOLDING_CHUNKSIZE, validate_chunksize },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , HOLDING_HOLDING , NULL }
};
conf_var_t interface_var [] = {
{ CONF_COMMENT, CONFTYPE_STR , read_str , INTER_COMMENT , NULL },
{ CONF_USE , CONFTYPE_INT , read_int , INTER_MAXUSAGE, validate_positive },
{ CONF_SRC_IP , CONFTYPE_STR , read_str , INTER_SRC_IP , NULL },
{ CONF_UNKNOWN, CONFTYPE_INT , NULL , INTER_INTER , NULL }
};
conf_var_t application_var [] = {
{ CONF_COMMENT , CONFTYPE_STR , read_str , APPLICATION_COMMENT , NULL },
{ CONF_PLUGIN , CONFTYPE_STR , read_str , APPLICATION_PLUGIN , NULL },
{ CONF_PROPERTY , CONFTYPE_PROPLIST, read_visible_property, APPLICATION_PROPERTY , NULL },
{ CONF_CLIENT_NAME, CONFTYPE_STR , read_str , APPLICATION_CLIENT_NAME, NULL },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , APPLICATION_APPLICATION, NULL }
};
conf_var_t pp_script_var [] = {
{ CONF_COMMENT , CONFTYPE_STR , read_str , PP_SCRIPT_COMMENT , NULL },
{ CONF_PLUGIN , CONFTYPE_STR , read_str , PP_SCRIPT_PLUGIN , NULL },
{ CONF_PROPERTY , CONFTYPE_PROPLIST , read_visible_property, PP_SCRIPT_PROPERTY , NULL },
{ CONF_EXECUTE_ON , CONFTYPE_EXECUTE_ON , read_execute_on , PP_SCRIPT_EXECUTE_ON , NULL },
{ CONF_EXECUTE_WHERE , CONFTYPE_EXECUTE_WHERE, read_execute_where, PP_SCRIPT_EXECUTE_WHERE , NULL },
{ CONF_ORDER , CONFTYPE_INT , read_int , PP_SCRIPT_ORDER , NULL },
{ CONF_SINGLE_EXECUTION, CONFTYPE_BOOLEAN , read_bool , PP_SCRIPT_SINGLE_EXECUTION, NULL },
{ CONF_CLIENT_NAME , CONFTYPE_STR , read_str , PP_SCRIPT_CLIENT_NAME , NULL },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , PP_SCRIPT_PP_SCRIPT , NULL }
};
conf_var_t device_config_var [] = {
{ CONF_COMMENT , CONFTYPE_STR , read_str , DEVICE_CONFIG_COMMENT , NULL },
{ CONF_DEVICE_PROPERTY , CONFTYPE_PROPLIST , read_visible_property, DEVICE_CONFIG_DEVICE_PROPERTY, NULL },
{ CONF_TAPEDEV , CONFTYPE_STR , read_str , DEVICE_CONFIG_TAPEDEV , NULL },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , DEVICE_CONFIG_DEVICE_CONFIG , NULL }
};
conf_var_t changer_config_var [] = {
{ CONF_COMMENT , CONFTYPE_STR , read_str , CHANGER_CONFIG_COMMENT , NULL },
{ CONF_TAPEDEV , CONFTYPE_STR , read_str , CHANGER_CONFIG_TAPEDEV , NULL },
{ CONF_TPCHANGER , CONFTYPE_STR , read_str , CHANGER_CONFIG_TPCHANGER , NULL },
{ CONF_CHANGERDEV , CONFTYPE_STR , read_str , CHANGER_CONFIG_CHANGERDEV , NULL },
{ CONF_CHANGERFILE , CONFTYPE_STR , read_str , CHANGER_CONFIG_CHANGERFILE , NULL },
{ CONF_PROPERTY , CONFTYPE_PROPLIST , read_visible_property, CHANGER_CONFIG_PROPERTY , NULL },
{ CONF_DEVICE_PROPERTY , CONFTYPE_PROPLIST , read_visible_property, CHANGER_CONFIG_DEVICE_PROPERTY, NULL },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , CHANGER_CONFIG_CHANGER_CONFIG , NULL }
};
conf_var_t interactivity_var [] = {
{ CONF_COMMENT , CONFTYPE_STR , read_str , INTERACTIVITY_COMMENT , NULL },
{ CONF_PLUGIN , CONFTYPE_STR , read_str , INTERACTIVITY_PLUGIN , NULL },
{ CONF_PROPERTY , CONFTYPE_PROPLIST , read_visible_property, INTERACTIVITY_PROPERTY , NULL },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , INTERACTIVITY_INTERACTIVITY , NULL }
};
conf_var_t taperscan_var [] = {
{ CONF_COMMENT , CONFTYPE_STR , read_str , TAPERSCAN_COMMENT , NULL },
{ CONF_PLUGIN , CONFTYPE_STR , read_str , TAPERSCAN_PLUGIN , NULL },
{ CONF_PROPERTY , CONFTYPE_PROPLIST , read_visible_property, TAPERSCAN_PROPERTY , NULL },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , TAPERSCAN_TAPERSCAN , NULL }
};
conf_var_t policy_var [] = {
{ CONF_COMMENT , CONFTYPE_STR , read_str , POLICY_COMMENT , NULL },
{ CONF_RETENTION_TAPES , CONFTYPE_INT , read_int , POLICY_RETENTION_TAPES , NULL },
{ CONF_RETENTION_DAYS , CONFTYPE_INT , read_int , POLICY_RETENTION_DAYS , NULL },
{ CONF_RETENTION_RECOVER, CONFTYPE_INT , read_int , POLICY_RETENTION_RECOVER, NULL },
{ CONF_RETENTION_FULL , CONFTYPE_INT , read_int , POLICY_RETENTION_FULL , NULL },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , POLICY_POLICY , NULL }
};
conf_var_t storage_var [] = {
{ CONF_COMMENT , CONFTYPE_STR , read_str , STORAGE_COMMENT , NULL },
{ CONF_POLICY , CONFTYPE_STR , read_dpolicy , STORAGE_POLICY , NULL },
{ CONF_TAPEDEV , CONFTYPE_STR , read_str , STORAGE_TAPEDEV , NULL },
{ CONF_TPCHANGER , CONFTYPE_STR , read_str , STORAGE_TPCHANGER , NULL },
{ CONF_LABELSTR , CONFTYPE_LABELSTR , read_labelstr , STORAGE_LABELSTR , validate_no_space_dquote },
{ CONF_AUTOLABEL , CONFTYPE_AUTOLABEL , read_autolabel , STORAGE_AUTOLABEL , validate_no_space_dquote },
{ CONF_META_AUTOLABEL , CONFTYPE_STR , read_str , STORAGE_META_AUTOLABEL , validate_no_space_dquote },
{ CONF_TAPEPOOL , CONFTYPE_STR , read_str , STORAGE_TAPEPOOL , validate_no_space_dquote },
{ CONF_RUNTAPES , CONFTYPE_INT , read_int , STORAGE_RUNTAPES , NULL },
{ CONF_TAPERSCAN , CONFTYPE_STR , read_str , STORAGE_TAPERSCAN , NULL },
{ CONF_TAPETYPE , CONFTYPE_STR , read_str , STORAGE_TAPETYPE , NULL },
{ CONF_MAX_DLE_BY_VOLUME , CONFTYPE_INT , read_int , STORAGE_MAX_DLE_BY_VOLUME , NULL },
{ CONF_TAPERALGO , CONFTYPE_TAPERALGO , read_taperalgo , STORAGE_TAPERALGO , NULL },
{ CONF_TAPER_PARALLEL_WRITE , CONFTYPE_INT , read_int , STORAGE_TAPER_PARALLEL_WRITE , NULL },
{ CONF_EJECT_VOLUME , CONFTYPE_BOOLEAN , read_bool , STORAGE_EJECT_VOLUME , NULL },
{ CONF_ERASE_VOLUME , CONFTYPE_BOOLEAN , read_bool , STORAGE_ERASE_VOLUME , NULL },
{ CONF_DEVICE_OUTPUT_BUFFER_SIZE, CONFTYPE_SIZE , read_size , STORAGE_DEVICE_OUTPUT_BUFFER_SIZE, NULL },
{ CONF_AUTOFLUSH , CONFTYPE_NO_YES_ALL , read_no_yes_all , STORAGE_AUTOFLUSH , NULL },
{ CONF_FLUSH_THRESHOLD_DUMPED , CONFTYPE_INT , read_int , STORAGE_FLUSH_THRESHOLD_DUMPED , validate_nonnegative },
{ CONF_FLUSH_THRESHOLD_SCHEDULED, CONFTYPE_INT , read_int , STORAGE_FLUSH_THRESHOLD_SCHEDULED, validate_nonnegative },
{ CONF_TAPERFLUSH , CONFTYPE_INT , read_int , STORAGE_TAPERFLUSH , validate_nonnegative },
{ CONF_REPORT_USE_MEDIA , CONFTYPE_BOOLEAN , read_bool , STORAGE_REPORT_USE_MEDIA , NULL },
{ CONF_REPORT_NEXT_MEDIA , CONFTYPE_BOOLEAN , read_bool , STORAGE_REPORT_NEXT_MEDIA , NULL },
{ CONF_INTERACTIVITY , CONFTYPE_STR , read_dinteractivity, STORAGE_INTERACTIVITY , NULL },
{ CONF_SET_NO_REUSE , CONFTYPE_BOOLEAN , read_bool , STORAGE_SET_NO_REUSE , NULL },
{ CONF_DUMP_SELECTION , CONFTYPE_DUMP_SELECTION, read_dump_selection, STORAGE_DUMP_SELECTION , NULL },
{ CONF_ERASE_ON_FAILURE , CONFTYPE_BOOLEAN , read_bool , STORAGE_ERASE_ON_FAILURE , NULL },
{ CONF_ERASE_ON_FULL , CONFTYPE_BOOLEAN , read_bool , STORAGE_ERASE_ON_FULL , NULL },
{ CONF_VAULT , CONFTYPE_VAULT_LIST , read_vault_list , STORAGE_VAULT_LIST , NULL },
{ CONF_UNKNOWN , CONFTYPE_INT , NULL , STORAGE_STORAGE , NULL }
};
/*
* Lexical Analysis Implementation
*/
static char *
get_token_name(
tok_t token)
{
keytab_t *kt;
if (keytable == NULL) {
error(_("keytable == NULL"));
/*NOTREACHED*/
}
for(kt = keytable; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == token) break;
if(kt->token == CONF_UNKNOWN)
return("");
return(kt->keyword);
}
static tok_t
lookup_keyword(
char * str)
{
keytab_t *kwp;
char *str1 = g_strdup(str);
char *p = str1;
/* Fold '-' to '_' in the token. Note that this modifies str1
* in place. */
while (*p) {
if (*p == '-') *p = '_';
p++;
}
for(kwp = keytable; kwp->keyword != NULL; kwp++) {
if (strcasecmp(kwp->keyword, str1) == 0) break;
}
amfree(str1);
return kwp->token;
}
static void
get_conftoken(
tok_t exp)
{
int ch, d;
gint64 int64;
char *buf;
char *tmps;
int token_overflow;
int inquote = 0;
int escape = 0;
int sign;
gboolean prefered_ident = FALSE;
if (exp == CONF_PREFERED_IDENT) {
exp = CONF_IDENT;
prefered_ident = TRUE;
}
if (token_pushed) {
token_pushed = 0;
tok = pushed_tok;
/*
** If it looked like a keyword before then look it
** up again in the current keyword table.
*/
switch(tok) {
case CONF_INT64: case CONF_SIZE:
case CONF_INT: case CONF_REAL: case CONF_STRING:
case CONF_LBRACE: case CONF_RBRACE: case CONF_COMMA:
case CONF_NL: case CONF_END: case CONF_UNKNOWN:
case CONF_TIME:
break; /* not a keyword */
default:
if (exp == CONF_IDENT) {
tok = CONF_IDENT;
tokenval.type = CONFTYPE_IDENT;
} else {
tok = lookup_keyword(tokenval.v.s);
}
break;
}
}
else {
ch = conftoken_getc();
/* note that we're explicitly assuming this file is ASCII. Someday
* maybe we'll support UTF-8? */
while(ch != EOF && ch != '\n' && g_ascii_isspace(ch))
ch = conftoken_getc();
if (ch == '#') { /* comment - eat everything but eol/eof */
while((ch = conftoken_getc()) != EOF && ch != '\n') {
(void)ch; /* Quiet empty loop complaints */
}
}
if (isalpha(ch)) { /* identifier */
buf = tkbuf;
token_overflow = 0;
do {
if (buf < tkbuf+sizeof(tkbuf)-1) {
*buf++ = (char)ch;
} else {
*buf = '\0';
if (!token_overflow) {
conf_parserror(_("token too long: %.20s..."), tkbuf);
}
token_overflow = 1;
}
ch = conftoken_getc();
} while(isalnum(ch) || ch == '_' || ch == '-');
if (ch != EOF && conftoken_ungetc(ch) == EOF) {
if (ferror(current_file)) {
conf_parserror(_("Pushback of '%c' failed: %s"),
ch, strerror(ferror(current_file)));
} else {
conf_parserror(_("Pushback of '%c' failed: EOF"), ch);
}
}
*buf = '\0';
tokenval.v.s = tkbuf;
if (token_overflow) {
tok = CONF_UNKNOWN;
} else if (exp == CONF_IDENT) {
tok = CONF_IDENT;
tokenval.type = CONFTYPE_IDENT;
} else {
tok = lookup_keyword(tokenval.v.s);
}
}
else if (isdigit(ch)) { /* integer */
sign = 1;
negative_number: /* look for goto negative_number below sign is set there */
int64 = 0;
do {
int64 = int64 * 10 + (ch - '0');
ch = conftoken_getc();
} while (isdigit(ch));
if (ch != '.') {
if (exp == CONF_INT) {
tok = CONF_INT;
tokenval.v.i = sign * (int)int64;
} else if (exp != CONF_REAL) {
tok = CONF_INT64;
tokenval.v.int64 = (gint64)sign * int64;
} else {
/* automatically convert to real when expected */
tokenval.v.r = (double)sign * (double)int64;
tok = CONF_REAL;
}
} else {
/* got a real number, not an int */
tokenval.v.r = sign * (double) int64;
int64 = 0;
d = 1;
ch = conftoken_getc();
while (isdigit(ch)) {
int64 = int64 * 10 + (ch - '0');
d = d * 10;
ch = conftoken_getc();
}
tokenval.v.r += sign * ((double)int64) / d;
tok = CONF_REAL;
}
if (ch != EOF && conftoken_ungetc(ch) == EOF) {
if (ferror(current_file)) {
conf_parserror(_("Pushback of '%c' failed: %s"),
ch, strerror(ferror(current_file)));
} else {
conf_parserror(_("Pushback of '%c' failed: EOF"), ch);
}
}
} else switch(ch) {
case '"': /* string */
buf = tkbuf;
token_overflow = 0;
inquote = 1;
*buf++ = (char)ch;
while (inquote && ((ch = conftoken_getc()) != EOF)) {
if (ch == '\n') {
if (!escape) {
conf_parserror(_("string not terminated"));
conftoken_ungetc(ch);
break;
}
escape = 0;
buf--; /* Consume escape in buffer */
} else if (ch == '\\' && !escape) {
escape = 1;
} else {
if (ch == '"') {
if (!escape)
inquote = 0;
}
escape = 0;
}
if(buf >= &tkbuf[sizeof(tkbuf) - 1]) {
if (!token_overflow) {
conf_parserror(_("string too long: %.20s..."), tkbuf);
}
token_overflow = 1;
break;
}
*buf++ = (char)ch;
}
*buf = '\0';
/*
* A little manuver to leave a fully unquoted, unallocated string
* in tokenval.v.s
*/
tmps = unquote_string(tkbuf);
g_strlcpy(tkbuf, tmps, sizeof(tkbuf));
amfree(tmps);
tokenval.v.s = tkbuf;
tok = (token_overflow) ? CONF_UNKNOWN :
(exp == CONF_IDENT) ? CONF_IDENT : CONF_STRING;
break;
case '-':
ch = conftoken_getc();
if (isdigit(ch)) {
sign = -1;
goto negative_number;
}
else {
if (ch != EOF && conftoken_ungetc(ch) == EOF) {
if (ferror(current_file)) {
conf_parserror(_("Pushback of '%c' failed: %s"),
ch, strerror(ferror(current_file)));
} else {
conf_parserror(_("Pushback of '%c' failed: EOF"), ch);
}
}
tok = CONF_UNKNOWN;
}
break;
case ',':
tok = CONF_COMMA;
break;
case '{':
tok = CONF_LBRACE;
break;
case '}':
tok = CONF_RBRACE;
break;
case '\n':
tok = CONF_NL;
break;
case EOF:
tok = CONF_END;
break;
default:
tok = CONF_UNKNOWN;
break;
}
}
if (exp != CONF_ANY && tok != exp) {
char *str;
keytab_t *kwp;
switch(exp) {
case CONF_LBRACE:
str = "\"{\"";
break;
case CONF_RBRACE:
str = "\"}\"";
break;
case CONF_COMMA:
str = "\",\"";
break;
case CONF_NL:
str = _("end of line");
break;
case CONF_END:
str = _("end of file");
break;
case CONF_INT:
str = _("an integer");
break;
case CONF_REAL:
str = _("a real number");
break;
case CONF_STRING:
str = _("a quoted string");
break;
case CONF_IDENT:
str = _("an identifier");
break;
default:
for(kwp = keytable; kwp->keyword != NULL; kwp++) {
if (exp == kwp->token)
break;
}
if (kwp->keyword == NULL)
str = _("token not");
else
str = str_keyword(kwp);
break;
}
if (!prefered_ident || exp != CONF_IDENT) {
conf_parserror(_("%s is expected"), str);
tok = exp;
if (tok == CONF_INT)
tokenval.v.i = 0;
else
tokenval.v.s = "";
}
}
}
static void
unget_conftoken(void)
{
assert(!token_pushed);
token_pushed = 1;
pushed_tok = tok;
tok = CONF_UNKNOWN;
}
static int
conftoken_getc(void)
{
int c;
if (current_line == NULL)
c = getc(current_file);
else if (*current_char == '\0')
return -1;
else
c = (*current_char++);
if (c >= -1 && c <= 255)
return c;
else
return 0;
}
static int
conftoken_ungetc(
int c)
{
if(current_line == NULL)
return ungetc(c, current_file);
else if(current_char > current_line) {
if(c == -1)
return c;
current_char--;
if(*current_char != c) {
error(_("*current_char != c : %c %c"), *current_char, c);
/* NOTREACHED */
}
} else {
error(_("current_char == current_line"));
/* NOTREACHED */
}
return c;
}
/*
* Parser Implementation
*/
static void
read_conffile(
char *filename,
gboolean is_client,
gboolean missing_ok)
{
/* Save global locations. */
FILE *save_file = current_file;
char *save_filename = current_filename;
int save_line_num = current_line_num;
int rc;
if (is_client) {
keytable = client_keytab;
parsetable = client_var;
} else {
keytable = server_keytab;
parsetable = server_var;
}
filename = config_dir_relative(filename);
current_filename = get_seen_filename(filename);
amfree(filename);
if ((current_file = fopen(current_filename, "r")) == NULL) {
if (!missing_ok || errno != ENOENT)
conf_parserror(_("could not open conf file '%s': %s"),
current_filename, strerror(errno));
goto finish;
}
g_debug("reading config file %s", current_filename);
current_line_num = 0;
do {
/* read_confline() can invoke us recursively via "includefile" */
rc = read_confline(is_client);
} while (rc != 0);
afclose(current_file);
finish:
/* Restore servers */
current_line_num = save_line_num;
current_file = save_file;
current_filename = save_filename;
}
static gboolean
read_confline(
gboolean is_client)
{
conf_var_t *np;
current_line_num += 1;
get_conftoken(CONF_ANY);
handle_deprecated_keyword();
switch(tok) {
case CONF_INCLUDEFILE:
get_conftoken(CONF_STRING);
read_conffile(tokenval.v.s, is_client, FALSE);
break;
case CONF_DEFINE:
if (is_client) {
get_conftoken(CONF_ANY);
/* "application" and "script" are now preferred, but accept
* "application-tool" and "script-tool" too, for backward compatibility */
if(tok == CONF_APPLICATION_TOOL || tok == CONF_APPLICATION) get_application();
else if(tok == CONF_SCRIPT_TOOL || tok == CONF_SCRIPT) get_pp_script();
else conf_parserror(_("APPLICATION or SCRIPT expected"));
} else {
get_conftoken(CONF_ANY);
if(tok == CONF_DUMPTYPE) get_dumptype();
else if(tok == CONF_TAPETYPE) get_tapetype();
else if(tok == CONF_INTERFACE) get_interface();
else if(tok == CONF_APPLICATION_TOOL || tok == CONF_APPLICATION) get_application();
else if(tok == CONF_SCRIPT_TOOL || tok == CONF_SCRIPT) get_pp_script();
else if(tok == CONF_DEVICE) get_device_config();
else if(tok == CONF_CHANGER) get_changer_config();
else if(tok == CONF_HOLDING) get_holdingdisk(1);
else if(tok == CONF_INTERACTIVITY) get_interactivity();
else if(tok == CONF_TAPERSCAN) get_taperscan();
else if(tok == CONF_POLICY) get_policy();
else if(tok == CONF_STORAGE) get_storage();
else conf_parserror(_("DUMPTYPE, INTERFACE, TAPETYPE, HOLDINGDISK, APPLICATION, SCRIPT, DEVICE, CHANGER, INTERACTIVITY, TAPERSCAN, POLICY or STORAGE expected"));
current_block = NULL;
}
break;
case CONF_NL: /* empty line */
break;
case CONF_END: /* end of file */
return 0;
/* These should never be at the begining of a line */
case CONF_LBRACE:
case CONF_RBRACE:
case CONF_IDENT:
case CONF_INT:
case CONF_INT64:
case CONF_BOOL:
case CONF_REAL:
case CONF_STRING:
case CONF_TIME:
case CONF_SIZE:
conf_parserror("error: not a keyword.");
break;
/* if it's not a known punctuation mark, then check the parse table and use the
* read_function we find there. */
default:
{
for(np = parsetable; np->token != CONF_UNKNOWN; np++)
if(np->token == tok) break;
if(np->token == CONF_UNKNOWN) {
handle_invalid_keyword(tokenval.v.s);
} else {
np->read_function(np, &conf_data[np->parm]);
if(np->validate_function)
np->validate_function(np, &conf_data[np->parm]);
}
}
}
if(tok != CONF_NL)
get_conftoken(CONF_NL);
return 1;
}
static void
handle_deprecated_keyword(void)
{
/* Procedure for deprecated keywords:
*
* 1) At time of deprecation, add to warning_deprecated below. Note the
* version in which deprecation will expire. The keyword will still be
* parsed, and can still be used from other parts of Amanda, during this
* time.
* 2) After it has expired, move the keyword (as a string) to
* error_deprecated below. Remove the token (CONF_XXX) and
* config parameter (CNF_XXX) from the rest of the module.
* Note the date of the move.
*/
static struct { tok_t tok; gboolean warned; }
warning_deprecated[] = {
{ CONF_LABEL_NEW_TAPES, 0 }, /* exp in Amanda-3.2 */
{ CONF_AMRECOVER_DO_FSF, 0 }, /* exp in Amanda-3.3 */
{ CONF_AMRECOVER_CHECK_LABEL, 0 }, /* exp in Amanda-3.3 */
{ CONF_TAPE_SPLITSIZE, 0 }, /* exp. in Amanda-3.3 */
{ CONF_SPLIT_DISKBUFFER, 0 }, /* exp. in Amanda-3.3 */
{ CONF_FALLBACK_SPLITSIZE, 0 }, /* exp. in Amanda-3.3 */
{ CONF_USETIMESTAMPS, 0 }, /* exp. in Amanda-3.4 */
{ 0, 0 },
}, *dep;
for (dep = warning_deprecated; dep->tok; dep++) {
if (tok == dep->tok) {
if (!dep->warned)
conf_parswarn(_("warning: Keyword %s is deprecated."),
tokenval.v.s);
dep->warned = 1;
break;
}
}
}
static void
handle_invalid_keyword(
const char * token)
{
static const char * error_deprecated[] = {
"rawtapedev",
"tapebufs", /* deprecated: 2007-10-15; invalid: 2010-04-14 */
"file-pad", /* deprecated: 2008-07-01; invalid: 2010-04-14 */
NULL
};
const char ** s;
char *folded_token, *p;
/* convert '_' to '-' in TOKEN */
folded_token = g_strdup(token);
for (p = folded_token; *p; p++) {
if (*p == '_') *p = '-';
}
for (s = error_deprecated; *s != NULL; s ++) {
if (g_ascii_strcasecmp(*s, folded_token) == 0) {
conf_parserror(_("error: Keyword %s is deprecated."),
token);
g_free(folded_token);
return;
}
}
g_free(folded_token);
if (*s == NULL) {
conf_parserror(_("configuration keyword expected"));
}
for (;;) {
int c = conftoken_getc();
if (c == '\n' || c == -1) {
conftoken_ungetc(c);
return;
}
}
g_assert_not_reached();
}
static char *
get_seen_filename(
char *filename)
{
GSList *iter;
char *istr;
for (iter = seen_filenames; iter; iter = iter->next) {
istr = iter->data;
if (istr == filename || g_str_equal(istr, filename))
return istr;
}
istr = g_strdup(filename);
seen_filenames = g_slist_prepend(seen_filenames, istr);
return istr;
}
static void
read_block(
conf_var_t *read_var,
val_t *valarray,
char *errormsg,
int read_brace,
void (*copy_function)(void),
char *type,
char *name)
{
conf_var_t *np;
int done;
char *key_ovr;
int i;
int save_line_num;
if(read_brace) {
get_conftoken(CONF_LBRACE);
get_conftoken(CONF_NL);
}
done = 0;
do {
current_line_num += 1;
get_conftoken(CONF_ANY);
handle_deprecated_keyword();
switch(tok) {
case CONF_RBRACE:
done = 1;
break;
case CONF_NL: /* empty line */
break;
case CONF_END: /* end of file */
done = 1;
break;
/* inherit from a "parent" */
case CONF_IDENT:
case CONF_STRING:
if(copy_function)
copy_function();
else
conf_parserror(_("ident not expected"));
break;
default:
{
for(np = read_var; np->token != CONF_UNKNOWN; np++)
if(np->token == tok) break;
if(np->token == CONF_UNKNOWN)
conf_parserror("%d %s", tok, errormsg);
else {
np->read_function(np, &valarray[np->parm]);
if(np->validate_function)
np->validate_function(np, &valarray[np->parm]);
}
}
}
if(tok != CONF_NL && tok != CONF_END && tok != CONF_RBRACE)
get_conftoken(CONF_NL);
} while(!done);
if (!config_overrides)
return;
save_line_num = current_line_num;
key_ovr = g_strjoin(NULL, type, ":", name, NULL);
for (i = 0; i < config_overrides->n_used; i++) {
config_override_t *co = &config_overrides->ovr[i];
char *key = co->key;
char *keyword;
char *value;
if (strncasecmp(key_ovr, key, strlen(key_ovr)) != 0)
continue;
if (strlen(key) <= strlen(key_ovr) + 1)
continue;
keyword = key + strlen(key_ovr) + 1;
value = co->value;
tok = lookup_keyword(keyword);
if (tok == CONF_UNKNOWN)
continue;
/* find the var in read_var */
for (np = read_var; np->token != CONF_UNKNOWN; np++)
if (np->token == tok) break;
if (np->token == CONF_UNKNOWN)
continue;
/* now set up a fake line and use the relevant read_function to
* parse it. This is sneaky! */
if (np->type == CONFTYPE_STR) {
current_line = quote_string_always(value);
} else {
current_line = g_strdup(value);
}
current_char = current_line;
token_pushed = 0;
current_line_num = -2;
allow_overwrites = 1;
co->applied = TRUE;
np->read_function(np, &valarray[np->parm]);
if (np->validate_function)
np->validate_function(np, &valarray[np->parm]);
amfree(current_line);
current_char = NULL;
}
current_line_num = save_line_num;
token_pushed = 0;
amfree(key_ovr);
}
static void
read_holdingdisk(
conf_var_t *np G_GNUC_UNUSED,
val_t *val G_GNUC_UNUSED)
{
assert (val == &conf_data[CNF_HOLDINGDISK]);
get_holdingdisk(0);
}
static void
get_holdingdisk(
int is_define)
{
int save_overwrites;
char *saved_block;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_holdingdisk_defaults();
get_conftoken(CONF_IDENT);
hdcur.name = g_strdup(tokenval.v.s);
validate_name(CONF_HOLDING, &tokenval);
current_block = g_strconcat("holdingdisk ", hdcur.name, NULL);
hdcur.seen.block = current_block;
hdcur.seen.filename = current_filename;
hdcur.seen.linenum = current_line_num;
get_conftoken(CONF_ANY);
if (tok == CONF_LBRACE) {
holdingdisk_t *hd;
hd = lookup_holdingdisk(hdcur.name);
if (hd) {
conf_parserror(_("holding disk '%s' already defined"),
hdcur.name);
} else {
unget_conftoken();
read_block(holding_var, hdcur.value,
_("holding disk parameter expected"), 1, copy_holdingdisk,
"HOLDINGDISK", hdcur.name);
get_conftoken(CONF_NL);
save_holdingdisk();
if (!is_define) {
conf_data[CNF_HOLDINGDISK].v.identlist = g_slist_append(
conf_data[CNF_HOLDINGDISK].v.identlist,
g_strdup(hdcur.name));
}
}
} else { /* use the already defined holding disk */
unget_conftoken();
if (is_define) {
conf_parserror(_("holdingdisk definition must specify holdingdisk parameters"));
}
do {
identlist_t il;
for (il = conf_data[CNF_HOLDINGDISK].v.identlist; il != NULL;
il = il->next) {
if (g_str_equal((char *)il->data, hdcur.name)) {
break;
}
}
if (il) {
conf_parserror(_("holding disk '%s' already in use"),
hdcur.name);
} else {
conf_data[CNF_HOLDINGDISK].v.identlist = g_slist_append(
conf_data[CNF_HOLDINGDISK].v.identlist,
g_strdup(hdcur.name));
}
amfree(hdcur.name);
get_conftoken(CONF_ANY);
if (tok == CONF_IDENT || tok == CONF_STRING) {
hdcur.name = g_strdup(tokenval.v.s);
} else if (tok != CONF_NL) {
conf_parserror(_("IDENT or NL expected"));
}
} while (tok == CONF_IDENT || tok == CONF_STRING);
amfree(hdcur.seen.block);
}
allow_overwrites = save_overwrites;
current_block = saved_block;
}
static void
init_holdingdisk_defaults(
void)
{
hdcur.name = NULL;
hdcur.seen.filename = NULL;
hdcur.seen.block = NULL;
conf_init_str(&hdcur.value[HOLDING_COMMENT] , "");
conf_init_str(&hdcur.value[HOLDING_DISKDIR] , "");
conf_init_int64(&hdcur.value[HOLDING_DISKSIZE] , CONF_UNIT_K, (gint64)0);
/* 1 Gb = 1M counted in 1Kb blocks */
conf_init_int64(&hdcur.value[HOLDING_CHUNKSIZE], CONF_UNIT_K, (gint64)1024*1024);
}
static void
save_holdingdisk(
void)
{
holdingdisk_t *hp;
hp = g_malloc(sizeof(holdingdisk_t));
*hp = hdcur;
holdinglist = g_slist_append(holdinglist, hp);
}
static void
copy_holdingdisk(
void)
{
holdingdisk_t *hp;
int i;
hp = lookup_holdingdisk(tokenval.v.s);
if (hp == NULL) {
conf_parserror(_("holdingdisk parameter expected"));
return;
}
for(i=0; i < HOLDING_HOLDING; i++) {
if(hp->value[i].seen.linenum) {
merge_val_t(&hdcur.value[i], &hp->value[i]);
}
}
}
/* WARNING:
* This function is called both from this module and from diskfile.c. Modify
* with caution. */
dumptype_t *
read_dumptype(
char *name,
FILE *from,
char *fname,
int *linenum)
{
int save_overwrites;
FILE *saved_conf = NULL;
char *saved_fname = NULL;
char *saved_block;
if (from) {
saved_conf = current_file;
current_file = from;
}
if (fname) {
saved_fname = current_filename;
current_filename = get_seen_filename(fname);
}
if (linenum)
current_line_num = *linenum;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_dumptype_defaults();
if (name) {
dpcur.name = name;
} else {
get_conftoken(CONF_IDENT);
dpcur.name = g_strdup(tokenval.v.s);
validate_name(CONF_DUMPTYPE, &tokenval);
}
current_block = g_strconcat("dumptype ", dpcur.name, NULL);
dpcur.seen.block = current_block;
dpcur.seen.filename = current_filename;
dpcur.seen.linenum = current_line_num;
read_block(dumptype_var, dpcur.value,
_("dumptype parameter expected"),
(name == NULL), copy_dumptype,
"DUMPTYPE", dpcur.name);
if(!name) /* !name => reading disklist, not conffile */
get_conftoken(CONF_NL);
/* XXX - there was a stupidity check in here for skip-incr and
** skip-full. This check should probably be somewhere else. */
save_dumptype();
allow_overwrites = save_overwrites;
current_block = saved_block;
if (linenum)
*linenum = current_line_num;
if (fname)
current_filename = saved_fname;
if (from)
current_file = saved_conf;
return lookup_dumptype(dpcur.name);
}
static void
get_dumptype(void)
{
read_dumptype(NULL, NULL, NULL, NULL);
}
static void
init_dumptype_defaults(void)
{
dpcur.name = NULL;
dpcur.seen.filename = NULL;
dpcur.seen.block = NULL;
conf_init_str (&dpcur.value[DUMPTYPE_COMMENT] , "");
conf_init_str (&dpcur.value[DUMPTYPE_PROGRAM] , "DUMP");
conf_init_str (&dpcur.value[DUMPTYPE_SRVCOMPPROG] , "");
conf_init_str (&dpcur.value[DUMPTYPE_CLNTCOMPPROG] , "");
conf_init_str (&dpcur.value[DUMPTYPE_SRV_ENCRYPT] , "");
conf_init_str (&dpcur.value[DUMPTYPE_CLNT_ENCRYPT] , "");
conf_init_str (&dpcur.value[DUMPTYPE_AMANDAD_PATH] , "");
conf_init_str (&dpcur.value[DUMPTYPE_CLIENT_USERNAME] , "");
conf_init_str (&dpcur.value[DUMPTYPE_CLIENT_PORT] , "");
conf_init_str (&dpcur.value[DUMPTYPE_SSL_FINGERPRINT_FILE], "");
conf_init_str (&dpcur.value[DUMPTYPE_SSL_CERT_FILE] , "");
conf_init_str (&dpcur.value[DUMPTYPE_SSL_KEY_FILE] , "");
conf_init_str (&dpcur.value[DUMPTYPE_SSL_CA_CERT_FILE] , "");
conf_init_str (&dpcur.value[DUMPTYPE_SSL_CIPHER_LIST] , "");
conf_init_bool (&dpcur.value[DUMPTYPE_SSL_CHECK_HOST], 1);
conf_init_bool (&dpcur.value[DUMPTYPE_SSL_CHECK_CERTIFICATE_HOST], 1);
conf_init_bool (&dpcur.value[DUMPTYPE_SSL_CHECK_FINGERPRINT], 1);
conf_init_str (&dpcur.value[DUMPTYPE_SSH_KEYS] , "");
conf_init_str (&dpcur.value[DUMPTYPE_AUTH] , "BSDTCP");
conf_init_exinclude(&dpcur.value[DUMPTYPE_EXCLUDE]);
conf_init_exinclude(&dpcur.value[DUMPTYPE_INCLUDE]);
conf_init_priority (&dpcur.value[DUMPTYPE_PRIORITY] , 1);
conf_init_int (&dpcur.value[DUMPTYPE_DUMPCYCLE] , CONF_UNIT_NONE, conf_data[CNF_DUMPCYCLE].v.i);
conf_init_int (&dpcur.value[DUMPTYPE_MAXDUMPS] , CONF_UNIT_NONE, conf_data[CNF_MAXDUMPS].v.i);
conf_init_int (&dpcur.value[DUMPTYPE_MAXPROMOTEDAY] , CONF_UNIT_NONE, 10000);
conf_init_int (&dpcur.value[DUMPTYPE_BUMPPERCENT] , CONF_UNIT_NONE, conf_data[CNF_BUMPPERCENT].v.i);
conf_init_int64 (&dpcur.value[DUMPTYPE_BUMPSIZE] , CONF_UNIT_K , conf_data[CNF_BUMPSIZE].v.int64);
conf_init_int (&dpcur.value[DUMPTYPE_BUMPDAYS] , CONF_UNIT_NONE, conf_data[CNF_BUMPDAYS].v.i);
conf_init_real (&dpcur.value[DUMPTYPE_BUMPMULT] , conf_data[CNF_BUMPMULT].v.r);
conf_init_time (&dpcur.value[DUMPTYPE_STARTTIME] , (time_t)0);
conf_init_strategy (&dpcur.value[DUMPTYPE_STRATEGY] , DS_STANDARD);
conf_init_estimatelist(&dpcur.value[DUMPTYPE_ESTIMATELIST] , ES_CLIENT);
conf_init_compress (&dpcur.value[DUMPTYPE_COMPRESS] , COMP_FAST);
conf_init_encrypt (&dpcur.value[DUMPTYPE_ENCRYPT] , ENCRYPT_NONE);
conf_init_data_path(&dpcur.value[DUMPTYPE_DATA_PATH] , DATA_PATH_AMANDA);
conf_init_str (&dpcur.value[DUMPTYPE_SRV_DECRYPT_OPT] , "-d");
conf_init_str (&dpcur.value[DUMPTYPE_CLNT_DECRYPT_OPT] , "-d");
conf_init_rate (&dpcur.value[DUMPTYPE_COMPRATE] , 0.50, 0.50);
conf_init_int64 (&dpcur.value[DUMPTYPE_TAPE_SPLITSIZE] , CONF_UNIT_K, (gint64)0);
conf_init_int64 (&dpcur.value[DUMPTYPE_FALLBACK_SPLITSIZE], CONF_UNIT_K, (gint64)10 * 1024);
conf_init_str (&dpcur.value[DUMPTYPE_SPLIT_DISKBUFFER] , NULL);
conf_init_bool (&dpcur.value[DUMPTYPE_RECORD] , 1);
conf_init_bool (&dpcur.value[DUMPTYPE_SKIP_INCR] , 0);
conf_init_bool (&dpcur.value[DUMPTYPE_SKIP_FULL] , 0);
conf_init_holding (&dpcur.value[DUMPTYPE_HOLDINGDISK] , HOLD_AUTO);
conf_init_bool (&dpcur.value[DUMPTYPE_KENCRYPT] , 0);
conf_init_bool (&dpcur.value[DUMPTYPE_IGNORE] , 0);
conf_init_bool (&dpcur.value[DUMPTYPE_INDEX] , 1);
conf_init_application(&dpcur.value[DUMPTYPE_APPLICATION]);
conf_init_identlist(&dpcur.value[DUMPTYPE_SCRIPTLIST], NULL);
conf_init_proplist(&dpcur.value[DUMPTYPE_PROPERTY]);
conf_init_bool (&dpcur.value[DUMPTYPE_ALLOW_SPLIT] , 1);
conf_init_int (&dpcur.value[DUMPTYPE_MAX_WARNINGS] , CONF_UNIT_NONE, 20);
conf_init_host_limit(&dpcur.value[DUMPTYPE_RECOVERY_LIMIT]);
conf_init_host_limit_server(&dpcur.value[DUMPTYPE_DUMP_LIMIT]);
conf_init_int (&dpcur.value[DUMPTYPE_RETRY_DUMP] , CONF_UNIT_NONE, 2);
conf_init_str_list (&dpcur.value[DUMPTYPE_TAG] , NULL);
}
static void
save_dumptype(void)
{
dumptype_t *dp, *dp1;;
dp = lookup_dumptype(dpcur.name);
if(dp != (dumptype_t *)0) {
if (dp->seen.linenum == -1) {
conf_parserror(_("dumptype %s is defined by default and cannot be redefined"), dp->name);
} else {
conf_parserror(_("dumptype %s already defined at %s:%d"), dp->name,
dp->seen.filename, dp->seen.linenum);
}
return;
}
dp = g_malloc(sizeof(dumptype_t));
*dp = dpcur;
dp->next = NULL;
/* add at end of list */
if(!dumplist)
dumplist = dp;
else {
dp1 = dumplist;
while (dp1->next != NULL) {
dp1 = dp1->next;
}
dp1->next = dp;
}
}
static void
copy_dumptype(void)
{
dumptype_t *dt;
int i;
dt = lookup_dumptype(tokenval.v.s);
if(dt == NULL) {
conf_parserror(_("dumptype parameter expected"));
return;
}
for(i=0; i < DUMPTYPE_DUMPTYPE; i++) {
if(dt->value[i].seen.linenum) {
merge_val_t(&dpcur.value[i], &dt->value[i]);
if (i == DUMPTYPE_SCRIPTLIST) {
/* sort in 'order' */
dpcur.value[i].v.identlist = g_slist_sort(dpcur.value[i].v.identlist, &compare_pp_script_order);
}
}
}
}
static void
get_tapetype(void)
{
int save_overwrites;
char *saved_block;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_tapetype_defaults();
get_conftoken(CONF_IDENT);
tpcur.name = g_strdup(tokenval.v.s);
validate_name(CONF_TAPETYPE, &tokenval);
current_block = g_strconcat("tapetype ", tpcur.name, NULL);
tpcur.seen.block = current_block;
tpcur.seen.filename = current_filename;
tpcur.seen.linenum = current_line_num;
read_block(tapetype_var, tpcur.value,
_("tapetype parameter expected"), 1, copy_tapetype,
"TAPETYPE", tpcur.name);
get_conftoken(CONF_NL);
if (tapetype_get_readblocksize(&tpcur) <
tapetype_get_blocksize(&tpcur)) {
conf_init_size(&tpcur.value[TAPETYPE_READBLOCKSIZE], CONF_UNIT_K,
tapetype_get_blocksize(&tpcur));
}
save_tapetype();
allow_overwrites = save_overwrites;
current_block = saved_block;
}
static void
init_tapetype_defaults(void)
{
tpcur.name = NULL;
tpcur.seen.filename = NULL;
tpcur.seen.block = NULL;
conf_init_str(&tpcur.value[TAPETYPE_COMMENT] , "");
conf_init_str(&tpcur.value[TAPETYPE_LBL_TEMPL] , "");
conf_init_size (&tpcur.value[TAPETYPE_BLOCKSIZE] , CONF_UNIT_K, DISK_BLOCK_KB);
conf_init_size (&tpcur.value[TAPETYPE_READBLOCKSIZE], CONF_UNIT_K, DISK_BLOCK_KB);
conf_init_int64 (&tpcur.value[TAPETYPE_LENGTH] , CONF_UNIT_K, ((gint64)2000));
conf_init_int64 (&tpcur.value[TAPETYPE_FILEMARK] , CONF_UNIT_K, (gint64)1);
conf_init_int (&tpcur.value[TAPETYPE_SPEED] , CONF_UNIT_NONE, 200);
conf_init_int64(&tpcur.value[TAPETYPE_PART_SIZE], CONF_UNIT_K, 0);
conf_init_part_cache_type(&tpcur.value[TAPETYPE_PART_CACHE_TYPE], PART_CACHE_TYPE_NONE);
conf_init_str(&tpcur.value[TAPETYPE_PART_CACHE_DIR], "");
conf_init_int64(&tpcur.value[TAPETYPE_PART_CACHE_MAX_SIZE], CONF_UNIT_K, 0);
}
static void
save_tapetype(void)
{
tapetype_t *tp, *tp1;
tp = lookup_tapetype(tpcur.name);
if(tp != (tapetype_t *)0) {
amfree(tpcur.name);
conf_parserror(_("tapetype %s already defined at %s:%d"),
tp->name, tp->seen.filename, tp->seen.linenum);
return;
}
tp = g_malloc(sizeof(tapetype_t));
*tp = tpcur;
/* add at end of list */
if(!tapelist)
tapelist = tp;
else {
tp1 = tapelist;
while (tp1->next != NULL) {
tp1 = tp1->next;
}
tp1->next = tp;
}
}
static void
copy_tapetype(void)
{
tapetype_t *tp;
int i;
tp = lookup_tapetype(tokenval.v.s);
if(tp == NULL) {
conf_parserror(_("tape type parameter expected"));
return;
}
for(i=0; i < TAPETYPE_TAPETYPE; i++) {
if(tp->value[i].seen.linenum) {
merge_val_t(&tpcur.value[i], &tp->value[i]);
}
}
}
static void
get_interface(void)
{
int save_overwrites;
char *saved_block;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_interface_defaults();
get_conftoken(CONF_IDENT);
ifcur.name = g_strdup(tokenval.v.s);
validate_name(CONF_INTERFACE, &tokenval);
current_block = g_strconcat("interface ", ifcur.name, NULL);
ifcur.seen.block = current_block;
ifcur.seen.filename = current_filename;
ifcur.seen.linenum = current_line_num;
read_block(interface_var, ifcur.value,
_("interface parameter expected"), 1, copy_interface,
"INTERFACE", ifcur.name);
get_conftoken(CONF_NL);
save_interface();
allow_overwrites = save_overwrites;
current_block = saved_block;
return;
}
static void
init_interface_defaults(void)
{
ifcur.name = NULL;
ifcur.seen.filename = NULL;
ifcur.seen.block = NULL;
conf_init_str(&ifcur.value[INTER_COMMENT] , "");
conf_init_int(&ifcur.value[INTER_MAXUSAGE], CONF_UNIT_K, 80000);
conf_init_str(&ifcur.value[INTER_SRC_IP], "NULL");
}
static void
save_interface(void)
{
interface_t *ip, *ip1;
ip = lookup_interface(ifcur.name);
if(ip != (interface_t *)0) {
conf_parserror(_("interface %s already defined at %s:%d"),
ip->name, ip->seen.filename, ip->seen.linenum);
return;
}
ip = g_malloc(sizeof(interface_t));
*ip = ifcur;
/* add at end of list */
if(!interface_list) {
interface_list = ip;
} else {
ip1 = interface_list;
while (ip1->next != NULL) {
ip1 = ip1->next;
}
ip1->next = ip;
}
}
static void
copy_interface(void)
{
interface_t *ip;
int i;
ip = lookup_interface(tokenval.v.s);
if(ip == NULL) {
conf_parserror(_("interface parameter expected"));
return;
}
for(i=0; i < INTER_INTER; i++) {
if(ip->value[i].seen.linenum) {
merge_val_t(&ifcur.value[i], &ip->value[i]);
}
}
}
static application_t *
read_application(
char *name,
FILE *from,
char *fname,
int *linenum)
{
int save_overwrites;
FILE *saved_conf = NULL;
char *saved_fname = NULL;
char *saved_block;
if (from) {
saved_conf = current_file;
current_file = from;
}
if (fname) {
saved_fname = current_filename;
current_filename = get_seen_filename(fname);
}
if (linenum)
current_line_num = *linenum;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_application_defaults();
if (name) {
apcur.name = name;
} else {
get_conftoken(CONF_IDENT);
apcur.name = g_strdup(tokenval.v.s);
validate_name(CONF_APPLICATION, &tokenval);
}
current_block = g_strconcat("application ", apcur.name, NULL);
apcur.seen.block = current_block;
apcur.seen.filename = current_filename;
apcur.seen.linenum = current_line_num;
read_block(application_var, apcur.value,
_("application parameter expected"),
(name == NULL), *copy_application,
"APPLICATION", apcur.name);
if(!name)
get_conftoken(CONF_NL);
save_application();
allow_overwrites = save_overwrites;
current_block = saved_block;
if (linenum)
*linenum = current_line_num;
if (fname)
current_filename = saved_fname;
if (from)
current_file = saved_conf;
return lookup_application(apcur.name);
}
static void
get_application(
void)
{
read_application(NULL, NULL, NULL, NULL);
}
static void
init_application_defaults(
void)
{
apcur.name = NULL;
apcur.seen.filename = NULL;
apcur.seen.block = NULL;
conf_init_str(&apcur.value[APPLICATION_COMMENT] , "");
conf_init_str(&apcur.value[APPLICATION_PLUGIN] , "");
conf_init_proplist(&apcur.value[APPLICATION_PROPERTY]);
conf_init_str(&apcur.value[APPLICATION_CLIENT_NAME] , "");
}
static void
save_application(
void)
{
application_t *ap, *ap1;
ap = lookup_application(apcur.name);
if(ap != (application_t *)0) {
conf_parserror(_("application %s already defined at %s:%d"),
ap->name, ap->seen.filename, ap->seen.linenum);
return;
}
ap = g_malloc(sizeof(application_t));
*ap = apcur;
ap->next = NULL;
/* add at end of list */
if (!application_list)
application_list = ap;
else {
ap1 = application_list;
while (ap1->next != NULL) {
ap1 = ap1->next;
}
ap1->next = ap;
}
}
static void
copy_application(void)
{
application_t *ap;
int i;
ap = lookup_application(tokenval.v.s);
if(ap == NULL) {
conf_parserror(_("application parameter expected"));
return;
}
for(i=0; i < APPLICATION_APPLICATION; i++) {
if(ap->value[i].seen.linenum) {
merge_val_t(&apcur.value[i], &ap->value[i]);
}
}
}
static interactivity_t *
read_interactivity(
char *name,
FILE *from,
char *fname,
int *linenum)
{
int save_overwrites;
FILE *saved_conf = NULL;
char *saved_fname = NULL;
char *saved_block;
if (from) {
saved_conf = current_file;
current_file = from;
}
if (fname) {
saved_fname = current_filename;
current_filename = get_seen_filename(fname);
}
if (linenum)
current_line_num = *linenum;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_interactivity_defaults();
if (name) {
ivcur.name = name;
} else {
get_conftoken(CONF_IDENT);
ivcur.name = g_strdup(tokenval.v.s);
validate_name(CONF_INTERACTIVITY, &tokenval);
}
current_block = g_strconcat("interactivity ", ivcur.name, NULL);
ivcur.seen.block = current_block;
ivcur.seen.filename = current_filename;
ivcur.seen.linenum = current_line_num;
read_block(interactivity_var, ivcur.value,
_("interactivity parameter expected"),
(name == NULL), *copy_interactivity,
"INTERACTIVITY", ivcur.name);
if(!name)
get_conftoken(CONF_NL);
save_interactivity();
allow_overwrites = save_overwrites;
current_block = saved_block;
if (linenum)
*linenum = current_line_num;
if (fname)
current_filename = saved_fname;
if (from)
current_file = saved_conf;
return lookup_interactivity(ivcur.name);
}
static void
get_interactivity(
void)
{
read_interactivity(NULL, NULL, NULL, NULL);
}
static void
init_interactivity_defaults(
void)
{
ivcur.name = NULL;
ivcur.seen.filename = NULL;
ivcur.seen.block = NULL;
conf_init_str(&ivcur.value[INTERACTIVITY_COMMENT] , "");
conf_init_str(&ivcur.value[INTERACTIVITY_PLUGIN] , "");
conf_init_proplist(&ivcur.value[INTERACTIVITY_PROPERTY]);
}
static void
save_interactivity(
void)
{
interactivity_t *iv, *iv1;
iv = lookup_interactivity(ivcur.name);
if (iv != (interactivity_t *)0) {
conf_parserror(_("interactivity %s already defined at %s:%d"),
iv->name, iv->seen.filename, iv->seen.linenum);
return;
}
iv = g_malloc(sizeof(interactivity_t));
*iv = ivcur;
iv->next = NULL;
/* add at end of list */
if (!interactivity_list)
interactivity_list = iv;
else {
iv1 = interactivity_list;
while (iv1->next != NULL) {
iv1 = iv1->next;
}
iv1->next = iv;
}
}
static void
copy_interactivity(void)
{
interactivity_t *iv;
int i;
iv = lookup_interactivity(tokenval.v.s);
if (iv == NULL) {
conf_parserror(_("interactivity parameter expected"));
return;
}
for (i=0; i < INTERACTIVITY_INTERACTIVITY; i++) {
if(iv->value[i].seen.linenum) {
merge_val_t(&ivcur.value[i], &iv->value[i]);
}
}
}
static taperscan_t *
read_taperscan(
char *name,
FILE *from,
char *fname,
int *linenum)
{
int save_overwrites;
FILE *saved_conf = NULL;
char *saved_fname = NULL;
char *saved_block;
if (from) {
saved_conf = current_file;
current_file = from;
}
if (fname) {
saved_fname = current_filename;
current_filename = get_seen_filename(fname);
}
if (linenum)
current_line_num = *linenum;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_taperscan_defaults();
if (name) {
tscur.name = name;
} else {
get_conftoken(CONF_IDENT);
tscur.name = g_strdup(tokenval.v.s);
validate_name(CONF_TAPERSCAN, &tokenval);
}
current_block = g_strconcat("taperscan ", tscur.name, NULL);
tscur.seen.block = current_block;
tscur.seen.filename = current_filename;
tscur.seen.linenum = current_line_num;
read_block(taperscan_var, tscur.value,
_("taperscan parameter expected"),
(name == NULL), *copy_taperscan,
"TAPERSCAN", tscur.name);
if(!name)
get_conftoken(CONF_NL);
save_taperscan();
allow_overwrites = save_overwrites;
current_block = saved_block;
if (linenum)
*linenum = current_line_num;
if (fname)
current_filename = saved_fname;
if (from)
current_file = saved_conf;
return lookup_taperscan(tscur.name);
}
static void
get_taperscan(
void)
{
read_taperscan(NULL, NULL, NULL, NULL);
}
static void
init_taperscan_defaults(
void)
{
tscur.name = NULL;
tscur.seen.filename = NULL;
tscur.seen.block = NULL;
conf_init_str(&tscur.value[TAPERSCAN_COMMENT] , "");
conf_init_str(&tscur.value[TAPERSCAN_PLUGIN] , "");
conf_init_proplist(&tscur.value[TAPERSCAN_PROPERTY]);
}
static void
save_taperscan(
void)
{
taperscan_t *ts, *ts1;
ts = lookup_taperscan(tscur.name);
if (ts != (taperscan_t *)0) {
conf_parserror(_("taperscan %s already defined at %s:%d"),
ts->name, ts->seen.filename, ts->seen.linenum);
return;
}
ts = g_malloc(sizeof(taperscan_t));
*ts = tscur;
ts->next = NULL;
/* add at end of list */
if (!taperscan_list)
taperscan_list = ts;
else {
ts1 = taperscan_list;
while (ts1->next != NULL) {
ts1 = ts1->next;
}
ts1->next = ts;
}
}
static void
copy_taperscan(void)
{
taperscan_t *ts;
int i;
ts = lookup_taperscan(tokenval.v.s);
if (ts == NULL) {
conf_parserror(_("taperscan parameter expected"));
return;
}
for (i=0; i < TAPERSCAN_TAPERSCAN; i++) {
if(ts->value[i].seen.linenum) {
merge_val_t(&tscur.value[i], &ts->value[i]);
}
}
}
static policy_s *
read_policy(
char *name,
FILE *from,
char *fname,
int *linenum)
{
int save_overwrites;
FILE *saved_conf = NULL;
char *saved_fname = NULL;
char *saved_block;
if (from) {
saved_conf = current_file;
current_file = from;
}
if (fname) {
saved_fname = current_filename;
current_filename = get_seen_filename(fname);
}
if (linenum)
current_line_num = *linenum;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_policy_defaults();
if (name) {
pocur.name = name;
} else {
get_conftoken(CONF_IDENT);
pocur.name = g_strdup(tokenval.v.s);
validate_name(CONF_POLICY, &tokenval);
}
current_block = g_strconcat("policy ", pocur.name, NULL);
pocur.seen.block = current_block;
pocur.seen.filename = current_filename;
pocur.seen.linenum = current_line_num;
read_block(policy_var, pocur.value,
_("policy parameter expected"),
(name == NULL), *copy_policy,
"POLICY", pocur.name);
if(!name)
get_conftoken(CONF_NL);
save_policy();
allow_overwrites = save_overwrites;
current_block = saved_block;
if (linenum)
*linenum = current_line_num;
if (fname)
current_filename = saved_fname;
if (from)
current_file = saved_conf;
return lookup_policy(pocur.name);
}
static void
get_policy(
void)
{
read_policy(NULL, NULL, NULL, NULL);
}
static void
init_policy_defaults(
void)
{
pocur.name = NULL;
pocur.seen.filename = NULL;
pocur.seen.block = NULL;
conf_init_str(&pocur.value[POLICY_COMMENT] , "");
conf_init_int(&pocur.value[POLICY_RETENTION_TAPES] , CONF_UNIT_NONE, 0);
conf_init_int(&pocur.value[POLICY_RETENTION_DAYS] , CONF_UNIT_NONE, 0);
conf_init_int(&pocur.value[POLICY_RETENTION_RECOVER], CONF_UNIT_NONE, 0);
conf_init_int(&pocur.value[POLICY_RETENTION_FULL] , CONF_UNIT_NONE, 0);
}
static void
save_policy(
void)
{
policy_s *po, *po1;
po = lookup_policy(pocur.name);
if (po != (policy_s *)0) {
conf_parserror(_("policy %s already defined at %s:%d"),
po->name, po->seen.filename, po->seen.linenum);
return;
}
po = g_malloc(sizeof(policy_s));
*po = pocur;
po->next = NULL;
/* add at end of list */
if (!policy_list)
policy_list = po;
else {
po1 = policy_list;
while (po1->next != NULL) {
po1 = po1->next;
}
po1->next = po;
}
}
static void
copy_policy(void)
{
policy_s *po;
int i;
po = lookup_policy(tokenval.v.s);
if (po == NULL) {
conf_parserror(_("policy parameter expected"));
return;
}
for (i=0; i < POLICY_POLICY; i++) {
if(po->value[i].seen.linenum) {
merge_val_t(&pocur.value[i], &po->value[i]);
}
}
}
static storage_t *
read_storage(
char *name,
FILE *from,
char *fname,
int *linenum)
{
int save_overwrites;
FILE *saved_conf = NULL;
char *saved_fname = NULL;
char *saved_block;
if (from) {
saved_conf = current_file;
current_file = from;
}
if (fname) {
saved_fname = current_filename;
current_filename = get_seen_filename(fname);
}
if (linenum)
current_line_num = *linenum;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_storage_defaults();
if (name) {
stcur.name = name;
} else {
get_conftoken(CONF_IDENT);
stcur.name = g_strdup(tokenval.v.s);
validate_name(CONF_STORAGE, &tokenval);
}
current_block = g_strconcat("storage ", stcur.name, NULL);
stcur.seen.block = current_block;
stcur.seen.filename = current_filename;
stcur.seen.linenum = current_line_num;
read_block(storage_var, stcur.value,
_("storage parameter expected"),
(name == NULL), *copy_storage,
"STORAGE", stcur.name);
if(!name)
get_conftoken(CONF_NL);
save_storage();
allow_overwrites = save_overwrites;
current_block = saved_block;
if (linenum)
*linenum = current_line_num;
if (fname)
current_filename = saved_fname;
if (from)
current_file = saved_conf;
return lookup_storage(stcur.name);
}
static void
get_storage(
void)
{
read_storage(NULL, NULL, NULL, NULL);
}
static void
init_storage_defaults(
void)
{
stcur.name = NULL;
stcur.seen.filename = NULL;
stcur.seen.block = NULL;
conf_init_str (&stcur.value[STORAGE_COMMENT] , "");
conf_init_str (&stcur.value[STORAGE_POLICY] , "");
conf_init_str (&stcur.value[STORAGE_TAPEDEV] , "");
conf_init_str (&stcur.value[STORAGE_TPCHANGER] , "");
conf_init_labelstr (&stcur.value[STORAGE_LABELSTR]);
conf_init_str (&stcur.value[STORAGE_META_AUTOLABEL] , "");
conf_init_autolabel (&stcur.value[STORAGE_AUTOLABEL]);
conf_init_str (&stcur.value[STORAGE_TAPEPOOL] , NULL);
conf_init_int (&stcur.value[STORAGE_RUNTAPES] , CONF_UNIT_NONE, 1);
conf_init_str (&stcur.value[STORAGE_TAPERSCAN] , NULL);
conf_init_str (&stcur.value[STORAGE_TAPETYPE] , "DEFAULT_TAPE");
conf_init_int (&stcur.value[STORAGE_MAX_DLE_BY_VOLUME] , CONF_UNIT_NONE, 1000000000);
conf_init_taperalgo (&stcur.value[STORAGE_TAPERALGO] , 0);
conf_init_int (&stcur.value[STORAGE_TAPER_PARALLEL_WRITE] , CONF_UNIT_NONE, 0);
conf_init_bool (&stcur.value[STORAGE_EJECT_VOLUME] , 0);
conf_init_bool (&stcur.value[STORAGE_ERASE_VOLUME] , 0);
conf_init_size (&stcur.value[STORAGE_DEVICE_OUTPUT_BUFFER_SIZE], CONF_UNIT_NONE, 0);
conf_init_no_yes_all (&stcur.value[STORAGE_AUTOFLUSH] , 0);
conf_init_int (&stcur.value[STORAGE_FLUSH_THRESHOLD_DUMPED] , CONF_UNIT_NONE, 0);
conf_init_int (&stcur.value[STORAGE_FLUSH_THRESHOLD_SCHEDULED], CONF_UNIT_NONE, 0);
conf_init_int (&stcur.value[STORAGE_TAPERFLUSH] , CONF_UNIT_NONE, 0);
conf_init_bool (&stcur.value[STORAGE_REPORT_USE_MEDIA] , TRUE);
conf_init_bool (&stcur.value[STORAGE_REPORT_NEXT_MEDIA] , TRUE);
conf_init_str (&stcur.value[STORAGE_INTERACTIVITY] , NULL);
conf_init_bool (&stcur.value[STORAGE_SET_NO_REUSE] , FALSE);
conf_init_dump_selection(&stcur.value[STORAGE_DUMP_SELECTION]);
conf_init_bool (&stcur.value[STORAGE_ERASE_ON_FAILURE] , 0);
conf_init_bool (&stcur.value[STORAGE_ERASE_ON_FULL] , 0);
conf_init_vault_list (&stcur.value[STORAGE_VAULT_LIST]);
}
static void
save_storage(
void)
{
storage_t *st, *st1;
st = lookup_storage(stcur.name);
if (st != (storage_t *)0) {
conf_parserror(_("storage %s already defined at %s:%d"),
st->name, st->seen.filename, st->seen.linenum);
return;
}
st = g_malloc(sizeof(storage_t));
*st = stcur;
st->next = NULL;
/* add at end of list */
if (!storage_list)
storage_list = st;
else {
st1 = storage_list;
while (st1->next != NULL) {
st1 = st1->next;
}
st1->next = st;
}
}
static void
copy_storage(void)
{
storage_t *st;
int i;
st = lookup_storage(tokenval.v.s);
if (st == NULL) {
conf_parserror(_("storage parameter expected"));
return;
}
for (i=0; i < STORAGE_STORAGE; i++) {
if(st->value[i].seen.linenum) {
merge_val_t(&stcur.value[i], &st->value[i]);
}
}
}
static pp_script_t *
read_pp_script(
char *name,
FILE *from,
char *fname,
int *linenum)
{
int save_overwrites;
FILE *saved_conf = NULL;
char *saved_fname = NULL;
char *saved_block;
if (from) {
saved_conf = current_file;
current_file = from;
}
if (fname) {
saved_fname = current_filename;
current_filename = get_seen_filename(fname);
}
if (linenum)
current_line_num = *linenum;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_pp_script_defaults();
if (name) {
pscur.name = name;
} else {
get_conftoken(CONF_IDENT);
pscur.name = g_strdup(tokenval.v.s);
validate_name(CONF_SCRIPT, &tokenval);
}
current_block = g_strconcat("script ", pscur.name, NULL);
pscur.seen.block = current_block;
pscur.seen.filename = current_filename;
pscur.seen.linenum = current_line_num;
read_block(pp_script_var, pscur.value,
_("script parameter expected"),
(name == NULL), *copy_pp_script,
"SCRIPT", pscur.name);
if(!name)
get_conftoken(CONF_NL);
save_pp_script();
allow_overwrites = save_overwrites;
current_block = saved_block;
if (linenum)
*linenum = current_line_num;
if (fname)
current_filename = saved_fname;
if (from)
current_file = saved_conf;
return lookup_pp_script(pscur.name);
}
static void
get_pp_script(
void)
{
read_pp_script(NULL, NULL, NULL, NULL);
}
static void
init_pp_script_defaults(
void)
{
pscur.name = NULL;
pscur.seen.filename = NULL;
pscur.seen.block = NULL;
conf_init_str(&pscur.value[PP_SCRIPT_COMMENT] , "");
conf_init_str(&pscur.value[PP_SCRIPT_PLUGIN] , "");
conf_init_proplist(&pscur.value[PP_SCRIPT_PROPERTY]);
conf_init_execute_on(&pscur.value[PP_SCRIPT_EXECUTE_ON], 0);
conf_init_execute_where(&pscur.value[PP_SCRIPT_EXECUTE_WHERE], EXECUTE_WHERE_CLIENT);
conf_init_int(&pscur.value[PP_SCRIPT_ORDER], CONF_UNIT_NONE, 5000);
conf_init_bool(&pscur.value[PP_SCRIPT_SINGLE_EXECUTION], 0);
conf_init_str(&pscur.value[PP_SCRIPT_CLIENT_NAME], "");
}
static void
save_pp_script(
void)
{
pp_script_t *ps, *ps1;
ps = lookup_pp_script(pscur.name);
if(ps != (pp_script_t *)0) {
conf_parserror(_("script %s already defined at %s:%d"),
ps->name, ps->seen.filename, ps->seen.linenum);
return;
}
ps = g_malloc(sizeof(pp_script_t));
*ps = pscur;
ps->next = NULL;
/* add at end of list */
if (!pp_script_list)
pp_script_list = ps;
else {
ps1 = pp_script_list;
while (ps1->next != NULL) {
ps1 = ps1->next;
}
ps1->next = ps;
}
}
static void
copy_pp_script(void)
{
pp_script_t *ps;
int i;
ps = lookup_pp_script(tokenval.v.s);
if(ps == NULL) {
conf_parserror(_("script parameter expected"));
return;
}
for(i=0; i < PP_SCRIPT_PP_SCRIPT; i++) {
if(ps->value[i].seen.linenum) {
merge_val_t(&pscur.value[i], &ps->value[i]);
}
}
}
static device_config_t *
read_device_config(
char *name,
FILE *from,
char *fname,
int *linenum)
{
int save_overwrites;
char *saved_block;
FILE *saved_conf = NULL;
char *saved_fname = NULL;
if (from) {
saved_conf = current_file;
current_file = from;
}
if (fname) {
saved_fname = current_filename;
current_filename = get_seen_filename(fname);
}
if (linenum)
current_line_num = *linenum;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_device_config_defaults();
if (name) {
dccur.name = name;
} else {
get_conftoken(CONF_IDENT);
dccur.name = g_strdup(tokenval.v.s);
validate_name(CONF_DEVICE, &tokenval);
}
current_block = g_strconcat("device ", dccur.name, NULL);
dccur.seen.block = current_block;
dccur.seen.filename = current_filename;
dccur.seen.linenum = current_line_num;
read_block(device_config_var, dccur.value,
_("device parameter expected"),
(name == NULL), *copy_device_config,
"DEVICE", dccur.name);
if(!name)
get_conftoken(CONF_NL);
save_device_config();
allow_overwrites = save_overwrites;
current_block = saved_block;
if (linenum)
*linenum = current_line_num;
if (fname)
current_filename = saved_fname;
if (from)
current_file = saved_conf;
return lookup_device_config(dccur.name);
}
static void
get_device_config(
void)
{
read_device_config(NULL, NULL, NULL, NULL);
}
static void
init_device_config_defaults(
void)
{
dccur.name = NULL;
dccur.seen.filename = NULL;
dccur.seen.block = NULL;
conf_init_str(&dccur.value[DEVICE_CONFIG_COMMENT] , "");
conf_init_str(&dccur.value[DEVICE_CONFIG_TAPEDEV] , "");
conf_init_proplist(&dccur.value[DEVICE_CONFIG_DEVICE_PROPERTY]);
}
static void
save_device_config(
void)
{
device_config_t *dc, *dc1;
dc = lookup_device_config(dccur.name);
if(dc != (device_config_t *)0) {
conf_parserror(_("device %s already defined at %s:%d"),
dc->name, dc->seen.filename, dc->seen.linenum);
return;
}
dc = g_malloc(sizeof(device_config_t));
*dc = dccur;
dc->next = NULL;
/* add at end of list */
if (!device_config_list)
device_config_list = dc;
else {
dc1 = device_config_list;
while (dc1->next != NULL) {
dc1 = dc1->next;
}
dc1->next = dc;
}
}
static void
copy_device_config(void)
{
device_config_t *dc;
int i;
dc = lookup_device_config(tokenval.v.s);
if(dc == NULL) {
conf_parserror(_("device parameter expected"));
return;
}
for(i=0; i < DEVICE_CONFIG_DEVICE_CONFIG; i++) {
if(dc->value[i].seen.linenum) {
merge_val_t(&dccur.value[i], &dc->value[i]);
}
}
}
static changer_config_t *
read_changer_config(
char *name,
FILE *from,
char *fname,
int *linenum)
{
int save_overwrites;
char *saved_block;
FILE *saved_conf = NULL;
char *saved_fname = NULL;
if (from) {
saved_conf = current_file;
current_file = from;
}
if (fname) {
saved_fname = current_filename;
current_filename = fname;
}
if (linenum)
current_line_num = *linenum;
saved_block = current_block;
save_overwrites = allow_overwrites;
allow_overwrites = 1;
init_changer_config_defaults();
if (name) {
cccur.name = name;
} else {
get_conftoken(CONF_IDENT);
cccur.name = g_strdup(tokenval.v.s);
validate_name(CONF_CHANGER, &tokenval);
}
current_block = g_strconcat("changer ", cccur.name, NULL);
cccur.seen.block = current_block;
cccur.seen.filename = current_filename;
cccur.seen.linenum = current_line_num;
read_block(changer_config_var, cccur.value,
_("changer parameter expected"),
(name == NULL), *copy_changer_config,
"CHANGER", cccur.name);
if(!name)
get_conftoken(CONF_NL);
save_changer_config();
allow_overwrites = save_overwrites;
current_block = saved_block;
if (linenum)
*linenum = current_line_num;
if (fname)
current_filename = saved_fname;
if (from)
current_file = saved_conf;
return lookup_changer_config(cccur.name);
}
static void
get_changer_config(
void)
{
read_changer_config(NULL, NULL, NULL, NULL);
}
static void
init_changer_config_defaults(
void)
{
cccur.name = NULL;
cccur.seen.filename = NULL;
cccur.seen.block = NULL;
conf_init_str(&cccur.value[CHANGER_CONFIG_COMMENT] , "");
conf_init_str(&cccur.value[CHANGER_CONFIG_TAPEDEV] , "");
conf_init_str(&cccur.value[CHANGER_CONFIG_TPCHANGER] , "");
conf_init_str(&cccur.value[CHANGER_CONFIG_CHANGERDEV] , "");
conf_init_str(&cccur.value[CHANGER_CONFIG_CHANGERFILE] , "");
conf_init_proplist(&cccur.value[CHANGER_CONFIG_PROPERTY]);
conf_init_proplist(&cccur.value[CHANGER_CONFIG_DEVICE_PROPERTY]);
}
static void
save_changer_config(
void)
{
changer_config_t *dc, *dc1;
dc = lookup_changer_config(cccur.name);
if(dc != (changer_config_t *)0) {
conf_parserror(_("changer %s already defined at %s:%d"),
dc->name, dc->seen.filename, dc->seen.linenum);
return;
}
dc = g_malloc(sizeof(changer_config_t));
*dc = cccur;
dc->next = NULL;
/* add at end of list */
if (!changer_config_list)
changer_config_list = dc;
else {
dc1 = changer_config_list;
while (dc1->next != NULL) {
dc1 = dc1->next;
}
dc1->next = dc;
}
}
static void
copy_changer_config(void)
{
changer_config_t *dc;
int i;
dc = lookup_changer_config(tokenval.v.s);
if(dc == NULL) {
conf_parserror(_("changer parameter expected"));
return;
}
for(i=0; i < CHANGER_CONFIG_CHANGER_CONFIG; i++) {
if(dc->value[i].seen.linenum) {
merge_val_t(&cccur.value[i], &dc->value[i]);
}
}
}
/* Read functions */
static void
read_int(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
val_t__int(val) = get_int(val->unit);
}
static void
read_int64(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
val_t__int64(val) = get_int64(val->unit);
}
static void
read_real(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
get_conftoken(CONF_REAL);
val_t__real(val) = tokenval.v.r;
}
static void
read_str(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
get_conftoken(CONF_STRING);
g_free(val->v.s);
val->v.s = g_strdup(tokenval.v.s);
}
static void
read_str_list(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
get_conftoken(CONF_ANY);
if (tok == CONF_APPEND) {
get_conftoken(CONF_ANY);
} else {
free_val_t(val);
val->v.identlist = NULL;
ckseen(&val->seen);
}
while (tok == CONF_STRING) {
val->v.identlist = g_slist_append(val->v.identlist,
g_strdup(tokenval.v.s));
get_conftoken(CONF_ANY);
}
if (tok != CONF_NL && tok != CONF_END) {
conf_parserror(_("string expected"));
unget_conftoken();
}
}
static void
read_ident(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
get_conftoken(CONF_IDENT);
g_free(val->v.s);
val->v.s = g_strdup(tokenval.v.s);
}
static void
read_storage_identlist(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
free_val_t(val);
ckseen(&val->seen);
val->v.identlist = NULL;
get_conftoken(CONF_PREFERED_IDENT);
while (tok == CONF_STRING || tok == CONF_IDENT) {
if (strlen(tokenval.v.s) == 0) {
free_val_t(val);
} else {
val->v.identlist = g_slist_append(val->v.identlist,
g_strdup(tokenval.v.s));
}
get_conftoken(CONF_PREFERED_IDENT);
}
if (tok != CONF_NL && tok != CONF_END) {
conf_parserror(_("string expected"));
unget_conftoken();
}
}
static void
read_dump_selection(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
dump_selection_t *ds = g_new0(dump_selection_t, 1);
dump_selection_list_t dsl;
gboolean found = FALSE;
ds->tag = NULL;
ds->tag_type = TAG_ALL;
ds->level = LEVEL_ALL;
ckseen(&val->seen);
get_conftoken(CONF_ANY);
if (tok == CONF_STRING) {
ds->tag_type = TAG_NAME;
ds->tag = g_strdup(tokenval.v.s);
} else if (tok == CONF_ALL) {
ds->tag_type = TAG_ALL;
} else if (tok == CONF_OTHER) {
ds->tag_type = TAG_OTHER;
} else if (tok == CONF_NL || tok == CONF_END) {
free_val_t(val);
val->v.dump_selection = NULL;
ckseen(&val->seen);
return;
} else {
conf_parserror(_("string, ALL or OTHER expected"));
}
get_conftoken(CONF_ANY);
if (tok == CONF_ALL) {
ds->level = LEVEL_ALL;
} else if (tok == CONF_FULL) {
ds->level = LEVEL_FULL;
} else if (tok == CONF_INCR) {
ds->level = LEVEL_INCR;
} else {
conf_parserror(_("ALL, FULL or INCR expected"));
}
get_conftoken(CONF_ANY);
if (tok != CONF_NL && tok != CONF_END) {
conf_parserror(_("string expected"));
unget_conftoken();
}
//replace if already exists
for (dsl = val->v.dump_selection ; dsl != NULL ; dsl = dsl->next) {
dump_selection_t *ds1 = dsl->data;
if (ds->tag_type == ds1->tag_type) {
if (ds->tag_type != TAG_NAME || g_str_equal(ds->tag, ds1->tag)) {
ds1->level = ds->level;
found = TRUE;
}
}
}
if (!found) {
val->v.dump_selection = g_slist_append(val->v.dump_selection, ds);
if (ds->tag_type == TAG_NAME && strlen(ds->tag) == 0) {
free_val_t(val);
}
} else {
g_free(ds->tag);
g_free(ds);
}
}
static void
read_time(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
val_t__time(val) = get_time();
}
static void
read_size(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
val_t__size(val) = get_size(val->unit);
}
static void
read_bool(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
val_t__boolean(val) = get_bool();
}
static void
read_no_yes_all(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
val_t__int(val) = get_no_yes_all();
}
static void
read_compress(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
int serv, clie, none, fast, best, custom;
int done;
comp_t comp;
ckseen(&val->seen);
serv = clie = none = fast = best = custom = 0;
done = 0;
do {
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_NONE: none = 1; break;
case CONF_FAST: fast = 1; break;
case CONF_BEST: best = 1; break;
case CONF_CLIENT: clie = 1; break;
case CONF_SERVER: serv = 1; break;
case CONF_CUSTOM: custom=1; break;
case CONF_NL: done = 1; break;
case CONF_END: done = 1; break;
default:
done = 1;
serv = clie = 1; /* force an error */
}
} while(!done);
if(serv + clie == 0) clie = 1; /* default to client */
if(none + fast + best + custom == 0) fast = 1; /* default to fast */
comp = -1;
if(!serv && clie) {
if(none && !fast && !best && !custom) comp = COMP_NONE;
if(!none && fast && !best && !custom) comp = COMP_FAST;
if(!none && !fast && best && !custom) comp = COMP_BEST;
if(!none && !fast && !best && custom) comp = COMP_CUST;
}
if(serv && !clie) {
if(none && !fast && !best && !custom) comp = COMP_NONE;
if(!none && fast && !best && !custom) comp = COMP_SERVER_FAST;
if(!none && !fast && best && !custom) comp = COMP_SERVER_BEST;
if(!none && !fast && !best && custom) comp = COMP_SERVER_CUST;
}
if((int)comp == -1) {
conf_parserror(_("NONE, CLIENT FAST, CLIENT BEST, CLIENT CUSTOM, SERVER FAST, SERVER BEST or SERVER CUSTOM expected"));
comp = COMP_NONE;
}
val_t__compress(val) = (int)comp;
}
static void
read_encrypt(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
encrypt_t encrypt;
ckseen(&val->seen);
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_NONE:
encrypt = ENCRYPT_NONE;
break;
case CONF_CLIENT:
encrypt = ENCRYPT_CUST;
break;
case CONF_SERVER:
encrypt = ENCRYPT_SERV_CUST;
break;
default:
conf_parserror(_("NONE, CLIENT or SERVER expected"));
encrypt = ENCRYPT_NONE;
break;
}
val_t__encrypt(val) = (int)encrypt;
}
static void
read_holding(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
dump_holdingdisk_t holding;
ckseen(&val->seen);
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_NEVER:
holding = HOLD_NEVER;
break;
case CONF_AUTO:
holding = HOLD_AUTO;
break;
case CONF_REQUIRED:
holding = HOLD_REQUIRED;
break;
default: /* can be a BOOLEAN */
unget_conftoken();
holding = (dump_holdingdisk_t)get_bool();
if (holding == 0)
holding = HOLD_NEVER;
else if (holding == 1 || holding == 2)
holding = HOLD_AUTO;
else
conf_parserror(_("NEVER, AUTO or REQUIRED expected"));
break;
}
val_t__holding(val) = (int)holding;
}
static void
read_estimatelist(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
estimatelist_t estimates = NULL;
ckseen(&val->seen);
get_conftoken(CONF_ANY);
do {
switch(tok) {
case CONF_CLIENT:
estimates = g_slist_append(estimates, GINT_TO_POINTER(ES_CLIENT));
break;
case CONF_SERVER:
estimates = g_slist_append(estimates, GINT_TO_POINTER(ES_SERVER));
break;
case CONF_CALCSIZE:
estimates = g_slist_append(estimates, GINT_TO_POINTER(ES_CALCSIZE));
break;
default:
conf_parserror(_("CLIENT, SERVER or CALCSIZE expected"));
}
get_conftoken(CONF_ANY);
if (tok == CONF_NL)
break;
} while (1);
g_slist_free(val->v.estimatelist);
val_t__estimatelist(val) = estimates;
}
static void
read_strategy(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
int strat;
ckseen(&val->seen);
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_SKIP:
strat = DS_SKIP;
break;
case CONF_STANDARD:
strat = DS_STANDARD;
break;
case CONF_NOFULL:
strat = DS_NOFULL;
break;
case CONF_NOINC:
strat = DS_NOINC;
break;
case CONF_HANOI:
strat = DS_HANOI;
break;
case CONF_INCRONLY:
strat = DS_INCRONLY;
break;
default:
conf_parserror(_("dump strategy expected"));
strat = DS_STANDARD;
}
val_t__strategy(val) = strat;
}
static void
read_taperalgo(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_FIRST: val_t__taperalgo(val) = ALGO_FIRST; break;
case CONF_FIRSTFIT: val_t__taperalgo(val) = ALGO_FIRSTFIT; break;
case CONF_LARGEST: val_t__taperalgo(val) = ALGO_LARGEST; break;
case CONF_LARGESTFIT: val_t__taperalgo(val) = ALGO_LARGESTFIT; break;
case CONF_SMALLEST: val_t__taperalgo(val) = ALGO_SMALLEST; break;
case CONF_LAST: val_t__taperalgo(val) = ALGO_LAST; break;
default:
conf_parserror(_("FIRST, FIRSTFIT, LARGEST, LARGESTFIT, SMALLEST or LAST expected"));
}
}
static void
read_send_amreport_on(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_ALL: val_t__send_amreport(val) = SEND_AMREPORT_ALL; break;
case CONF_STRANGE: val_t__send_amreport(val) = SEND_AMREPORT_STRANGE; break;
case CONF_ERROR: val_t__send_amreport(val) = SEND_AMREPORT_ERROR; break;
case CONF_NEVER: val_t__send_amreport(val) = SEND_AMREPORT_NEVER; break;
default:
conf_parserror(_("ALL, STRANGE, ERROR or NEVER expected"));
}
}
static void
read_data_path(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_AMANDA : val_t__data_path(val) = DATA_PATH_AMANDA ; break;
case CONF_DIRECTTCP: val_t__data_path(val) = DATA_PATH_DIRECTTCP; break;
default:
conf_parserror(_("AMANDA or DIRECTTCP expected"));
}
}
static void
read_priority(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
int pri;
ckseen(&val->seen);
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_LOW: pri = PRIORITY_LOW; break;
case CONF_MEDIUM: pri = PRIORITY_MEDIUM; break;
case CONF_HIGH: pri = PRIORITY_HIGH; break;
case CONF_INT: pri = tokenval.v.i; break;
default:
conf_parserror(_("LOW, MEDIUM, HIGH or integer expected"));
pri = 0;
}
val_t__priority(val) = pri;
}
static void
read_rate(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
get_conftoken(CONF_REAL);
val_t__rate(val)[0] = tokenval.v.r;
val_t__rate(val)[1] = tokenval.v.r;
val->seen = tokenval.seen;
if(tokenval.v.r < 0) {
conf_parserror(_("full compression rate must be >= 0"));
}
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_NL:
return;
case CONF_END:
return;
case CONF_COMMA:
break;
default:
unget_conftoken();
}
get_conftoken(CONF_REAL);
val_t__rate(val)[1] = tokenval.v.r;
if(tokenval.v.r < 0) {
conf_parserror(_("incremental compression rate must be >= 0"));
}
}
static void
read_exinclude(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
int file, got_one = 0;
am_sl_t *exclude;
int optional = 0;
get_conftoken(CONF_ANY);
if(tok == CONF_LIST) {
file = 0;
get_conftoken(CONF_ANY);
exclude = val_t__exinclude(val).sl_list;
}
else {
file = 1;
if(tok == CONF_EFILE) get_conftoken(CONF_ANY);
exclude = val_t__exinclude(val).sl_file;
}
ckseen(&val->seen);
if(tok == CONF_OPTIONAL) {
get_conftoken(CONF_ANY);
optional = 1;
}
if(tok == CONF_APPEND) {
get_conftoken(CONF_ANY);
}
else {
free_sl(exclude);
exclude = NULL;
}
while(tok == CONF_STRING) {
exclude = append_sl(exclude, tokenval.v.s);
got_one = 1;
get_conftoken(CONF_ANY);
}
unget_conftoken();
if(got_one == 0) { free_sl(exclude); exclude = NULL; }
if (file == 0)
val_t__exinclude(val).sl_list = exclude;
else
val_t__exinclude(val).sl_file = exclude;
val_t__exinclude(val).optional = optional;
}
static void
read_intrange(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
get_conftoken(CONF_INT);
val_t__intrange(val)[0] = tokenval.v.i;
val_t__intrange(val)[1] = tokenval.v.i;
val->seen = tokenval.seen;
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_NL:
return;
case CONF_END:
return;
case CONF_COMMA:
break;
default:
unget_conftoken();
}
get_conftoken(CONF_INT);
val_t__intrange(val)[1] = tokenval.v.i;
}
static void
read_hidden_property(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
property_t *property = malloc(sizeof(property_t));
property->append = 0;
property->visible = 0;
property->priority = 0;
property->values = NULL;
read_property(val, property);
}
static void
read_visible_property(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
property_t *property = malloc(sizeof(property_t));
property->append = 0;
property->visible = 1;
property->priority = 0;
property->values = NULL;
read_property(val, property);
}
static void
read_property(
val_t *val,
property_t *property)
{
char *key;
gboolean set_seen = TRUE;
property_t *old_property;
get_conftoken(CONF_ANY);
if (tok == CONF_PRIORITY) {
property->priority = 1;
get_conftoken(CONF_ANY);
}
if (tok == CONF_APPEND) {
property->append = 1;
get_conftoken(CONF_ANY);
}
if (tok == CONF_HIDDEN) {
property->visible = 0;
get_conftoken(CONF_ANY);
} else if (tok == CONF_VISIBLE) {
property->visible = 1;
get_conftoken(CONF_ANY);
}
if (tok != CONF_STRING) {
amfree(property);
conf_parserror(_("key expected"));
amfree(property);
return;
}
key = amandaify_property_name(tokenval.v.s);
get_conftoken(CONF_ANY);
if (tok == CONF_NL || tok == CONF_END) {
g_hash_table_remove(val->v.proplist, key);
unget_conftoken();
amfree(property);
return;
}
if (tok != CONF_STRING) {
amfree(property);
conf_parserror(_("value expected"));
return;
}
if(val->seen.linenum == 0) {
ckseen(&val->seen); // first property
}
old_property = g_hash_table_lookup(val->v.proplist, key);
if (property->append) {
/* old_property will be freed by g_hash_table_insert, so
* steal its values */
if (old_property) {
if (old_property->priority)
property->priority = 1;
property->values = old_property->values;
old_property->values = NULL;
set_seen = FALSE;
}
}
while(tok == CONF_STRING) {
property->values = g_slist_append(property->values,
g_strdup(tokenval.v.s));
get_conftoken(CONF_ANY);
}
unget_conftoken();
g_hash_table_insert(val->v.proplist, key, property);
if (set_seen) {
property->seen.linenum = 0;
property->seen.filename = NULL;
property->seen.block = NULL;
ckseen(&property->seen);
}
}
static void
read_dapplication(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
application_t *application;
amfree(val->v.s);
get_conftoken(CONF_ANY);
if (tok == CONF_LBRACE) {
current_line_num -= 1;
application = read_application(custom_escape(g_strjoin(NULL, "custom(DUMPTYPE:",
dpcur.name, ")", ".",
anonymous_value(),NULL)),
NULL, NULL, NULL);
current_line_num -= 1;
val->v.s = g_strdup(application->name);
} else if (tok == CONF_STRING) {
application = lookup_application(tokenval.v.s);
if (strlen(tokenval.v.s) != 0) {
if (application == NULL) {
conf_parserror(_("Unknown application named: %s"), tokenval.v.s);
return;
}
val->v.s = g_strdup(application->name);
}
} else {
conf_parserror(_("application name expected: %d %d"), tok, CONF_STRING);
return;
}
ckseen(&val->seen);
}
static void
read_dinteractivity(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
interactivity_t *interactivity;
amfree(val->v.s);
get_conftoken(CONF_ANY);
if (tok == CONF_LBRACE) {
current_line_num -= 1;
interactivity = read_interactivity(custom_escape(g_strjoin(NULL, "custom(iv)", ".",
anonymous_value(),NULL)),
NULL, NULL, NULL);
current_line_num -= 1;
val->v.s = g_strdup(interactivity->name);
} else if (tok == CONF_STRING) {
if (strlen(tokenval.v.s) != 0) {
interactivity = lookup_interactivity(tokenval.v.s);
if (interactivity == NULL) {
conf_parserror(_("Unknown interactivity named: %s"), tokenval.v.s);
return;
}
val->v.s = g_strdup(interactivity->name);
}
} else {
conf_parserror(_("interactivity name expected: %d %d"), tok, CONF_STRING);
return;
}
ckseen(&val->seen);
}
static void
read_dtaperscan(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
taperscan_t *taperscan;
amfree(val->v.s);
get_conftoken(CONF_ANY);
if (tok == CONF_LBRACE) {
current_line_num -= 1;
taperscan = read_taperscan(custom_escape(g_strjoin(NULL, "custom(ts)", ".",
anonymous_value(),NULL)),
NULL, NULL, NULL);
current_line_num -= 1;
val->v.s = g_strdup(taperscan->name);
} else if (tok == CONF_STRING) {
if (strlen(tokenval.v.s) != 0) {
taperscan = lookup_taperscan(tokenval.v.s);
if (taperscan == NULL) {
conf_parserror(_("Unknown taperscan named: %s"), tokenval.v.s);
return;
}
val->v.s = g_strdup(taperscan->name);
}
} else {
conf_parserror(_("taperscan name expected: %d %d"), tok, CONF_STRING);
return;
}
ckseen(&val->seen);
}
static void
read_dpolicy(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
policy_s *policy;
amfree(val->v.s);
get_conftoken(CONF_ANY);
if (tok == CONF_LBRACE) {
current_line_num -= 1;
policy = read_policy(custom_escape(g_strjoin(NULL, "custom(po)", ".",
anonymous_value(),NULL)),
NULL, NULL, NULL);
current_line_num -= 1;
val->v.s = g_strdup(policy->name);
} else if (tok == CONF_STRING) {
if (strlen(tokenval.v.s) != 0) {
policy = lookup_policy(tokenval.v.s);
if (policy == NULL) {
conf_parserror(_("Unknown policy named: %s"), tokenval.v.s);
return;
}
val->v.s = g_strdup(policy->name);
}
} else {
conf_parserror(_("policy name expected: %d %d"), tok, CONF_STRING);
return;
}
ckseen(&val->seen);
}
/*
static void
read_dstorage(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
storage_t *storage;
get_conftoken(CONF_ANY);
if (tok == CONF_LBRACE) {
current_line_num -= 1;
storage = read_storage(custom_escape(g_strjoin(NULL, "custom(po)", ".",
anonymous_value(),NULL)),
NULL, NULL, NULL);
current_line_num -= 1;
} else if (tok == CONF_STRING) {
storage = lookup_storage(tokenval.v.s);
if (storage == NULL) {
conf_parserror(_("Unknown storage named: %s"), tokenval.v.s);
return;
}
} else {
conf_parserror(_("storage name expected: %d %d"), tok, CONF_STRING);
return;
}
amfree(val->v.s);
val->v.s = g_strdup(storage->name);
ckseen(&val->seen);
}
*/
static void
read_dpp_script(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
pp_script_t *pp_script;
get_conftoken(CONF_ANY);
if (tok == CONF_LBRACE) {
current_line_num -= 1;
pp_script = read_pp_script(custom_escape(g_strjoin(NULL, "custom(DUMPTYPE:", dpcur.name,
")", ".", anonymous_value(),NULL)),
NULL, NULL, NULL);
current_line_num -= 1;
val->v.identlist = g_slist_insert_sorted(val->v.identlist,
g_strdup(pp_script->name), &compare_pp_script_order);
} else if (tok == CONF_STRING || tok == CONF_IDENT) {
while (tok == CONF_STRING || tok == CONF_IDENT) {
if (strlen(tokenval.v.s) == 0) {
slist_free_full(val->v.identlist, g_free);
val->v.identlist = NULL;
} else {
pp_script = lookup_pp_script(tokenval.v.s);
if (pp_script == NULL) {
conf_parserror(_("Unknown pp_script named: %s"), tokenval.v.s);
return;
}
val->v.identlist = g_slist_insert_sorted(val->v.identlist,
g_strdup(pp_script->name), &compare_pp_script_order);
}
get_conftoken(CONF_ANY);
}
unget_conftoken();
} else {
conf_parserror(_("pp_script name expected: %d %d"), tok, CONF_STRING);
return;
}
ckseen(&val->seen);
}
static void
read_execute_on(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
get_conftoken(CONF_ANY);
val->v.i = 0;
do {
switch(tok) {
case CONF_PRE_AMCHECK: val->v.i |= EXECUTE_ON_PRE_AMCHECK; break;
case CONF_PRE_DLE_AMCHECK: val->v.i |= EXECUTE_ON_PRE_DLE_AMCHECK; break;
case CONF_PRE_HOST_AMCHECK: val->v.i |= EXECUTE_ON_PRE_HOST_AMCHECK; break;
case CONF_POST_DLE_AMCHECK: val->v.i |= EXECUTE_ON_POST_DLE_AMCHECK; break;
case CONF_POST_HOST_AMCHECK: val->v.i |= EXECUTE_ON_POST_HOST_AMCHECK; break;
case CONF_POST_AMCHECK: val->v.i |= EXECUTE_ON_POST_AMCHECK; break;
case CONF_PRE_ESTIMATE: val->v.i |= EXECUTE_ON_PRE_ESTIMATE; break;
case CONF_PRE_DLE_ESTIMATE: val->v.i |= EXECUTE_ON_PRE_DLE_ESTIMATE; break;
case CONF_PRE_HOST_ESTIMATE: val->v.i |= EXECUTE_ON_PRE_HOST_ESTIMATE; break;
case CONF_POST_DLE_ESTIMATE: val->v.i |= EXECUTE_ON_POST_DLE_ESTIMATE; break;
case CONF_POST_HOST_ESTIMATE: val->v.i |= EXECUTE_ON_POST_HOST_ESTIMATE; break;
case CONF_POST_ESTIMATE: val->v.i |= EXECUTE_ON_POST_ESTIMATE; break;
case CONF_PRE_BACKUP: val->v.i |= EXECUTE_ON_PRE_BACKUP; break;
case CONF_PRE_DLE_BACKUP: val->v.i |= EXECUTE_ON_PRE_DLE_BACKUP; break;
case CONF_PRE_HOST_BACKUP: val->v.i |= EXECUTE_ON_PRE_HOST_BACKUP; break;
case CONF_POST_BACKUP: val->v.i |= EXECUTE_ON_POST_BACKUP; break;
case CONF_POST_DLE_BACKUP: val->v.i |= EXECUTE_ON_POST_DLE_BACKUP; break;
case CONF_POST_HOST_BACKUP: val->v.i |= EXECUTE_ON_POST_HOST_BACKUP; break;
case CONF_PRE_RECOVER: val->v.i |= EXECUTE_ON_PRE_RECOVER; break;
case CONF_POST_RECOVER: val->v.i |= EXECUTE_ON_POST_RECOVER; break;
case CONF_PRE_LEVEL_RECOVER: val->v.i |= EXECUTE_ON_PRE_LEVEL_RECOVER; break;
case CONF_POST_LEVEL_RECOVER: val->v.i |= EXECUTE_ON_POST_LEVEL_RECOVER; break;
case CONF_INTER_LEVEL_RECOVER: val->v.i |= EXECUTE_ON_INTER_LEVEL_RECOVER; break;
default:
conf_parserror(_("Execute-on expected"));
}
get_conftoken(CONF_ANY);
if (tok != CONF_COMMA) {
unget_conftoken();
break;
}
get_conftoken(CONF_ANY);
} while (1);
}
static void
read_execute_where(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_CLIENT: val->v.i = EXECUTE_WHERE_CLIENT; break;
case CONF_SERVER: val->v.i = EXECUTE_WHERE_SERVER; break;
default:
conf_parserror(_("CLIENT or SERVER expected"));
}
}
static void
read_int_or_str(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_INT:
amfree(val->v.s);
val->v.s = g_strdup_printf("%d", tokenval.v.i);
break;
case CONF_SIZE:
amfree(val->v.s);
val->v.s = g_strdup_printf("%zu", tokenval.v.size);
break;
case CONF_INT64:
amfree(val->v.s);
val->v.s = g_strdup_printf("%jd", (intmax_t)tokenval.v.int64);
break;
case CONF_STRING:
g_free(val->v.s);
val->v.s = g_strdup(tokenval.v.s);
break;
default:
conf_parserror(_("an integer or a quoted string is expected"));
}
}
static void
read_autolabel(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
int data = 0;
ckseen(&val->seen);
get_conftoken(CONF_ANY);
if (tok == CONF_STRING) {
data++;
g_free(val->v.autolabel.template);
val->v.autolabel.template = g_strdup(tokenval.v.s);
get_conftoken(CONF_ANY);
}
val->v.autolabel.autolabel = 0;
while (tok != CONF_NL && tok != CONF_END) {
data++;
if (tok == CONF_ANY_VOLUME)
val->v.autolabel.autolabel |= AL_OTHER_CONFIG | AL_NON_AMANDA |
AL_VOLUME_ERROR | AL_EMPTY;
else if (tok == CONF_OTHER_CONFIG)
val->v.autolabel.autolabel |= AL_OTHER_CONFIG;
else if (tok == CONF_NON_AMANDA)
val->v.autolabel.autolabel |= AL_NON_AMANDA;
else if (tok == CONF_VOLUME_ERROR)
val->v.autolabel.autolabel |= AL_VOLUME_ERROR;
else if (tok == CONF_EMPTY)
val->v.autolabel.autolabel |= AL_EMPTY;
else {
conf_parserror(_("ANY, NEW-VOLUME, OTHER-CONFIG, NON-AMANDA, VOLUME-ERROR or EMPTY is expected"));
}
get_conftoken(CONF_ANY);
}
if (data == 0) {
amfree(val->v.autolabel.template);
val->v.autolabel.autolabel = 0;
} else if (val->v.autolabel.autolabel == 0) {
val->v.autolabel.autolabel = AL_VOLUME_ERROR | AL_EMPTY;
}
}
static void
read_labelstr(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
ckseen(&val->seen);
get_conftoken(CONF_ANY);
if (tok == CONF_STRING) {
g_free(val->v.labelstr.template);
val->v.labelstr.template = g_strdup(tokenval.v.s);
val->v.labelstr.match_autolabel = FALSE;
get_conftoken(CONF_ANY);
if (g_strcasecmp(val->v.labelstr.template, "match-autolabel") == 0 ||
g_strcasecmp(val->v.labelstr.template, "match_autolabel") == 0) {
conf_parswarn("warning: labelstr is set to \"%s\", you probably want the %s keyword, without the double quote", val->v.labelstr.template, val->v.labelstr.template);
}
} else if (tok == CONF_MATCH_AUTOLABEL) {
g_free(val->v.labelstr.template);
val->v.labelstr.template = NULL;
val->v.labelstr.match_autolabel = TRUE;
} else {
conf_parserror(_("labelstr template or MATCH_AUTOLABEL expected"));
}
}
static void
read_part_cache_type(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
part_cache_type_t part_cache_type;
ckseen(&val->seen);
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_NONE:
part_cache_type = PART_CACHE_TYPE_NONE;
break;
case CONF_DISK:
part_cache_type = PART_CACHE_TYPE_DISK;
break;
case CONF_MEMORY:
part_cache_type = PART_CACHE_TYPE_MEMORY;
break;
default:
conf_parserror(_("NONE, DISK or MEMORY expected"));
part_cache_type = PART_CACHE_TYPE_NONE;
break;
}
val_t__part_cache_type(val) = (int)part_cache_type;
}
static void
read_host_limit(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
host_limit_t *rl = &val_t__host_limit(val);
ckseen(&val->seen);
rl->match_pats = NULL;
rl->same_host = FALSE;
rl->server = FALSE;
while (1) {
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_STRING:
rl->match_pats = g_slist_append(rl->match_pats, g_strdup(tokenval.v.s));
break;
case CONF_SAME_HOST:
rl->same_host = TRUE;
break;
case CONF_SERVER:
rl->server = TRUE;
break;
case CONF_NL:
case CONF_END:
return;
default:
conf_parserror("SAME-HOST or a string expected");
break;
}
}
}
static void
read_vault_list(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
int nb_vault = 0;
ckseen(&val->seen);
get_conftoken(CONF_ANY);
while (tok == CONF_STRING || tok == CONF_IDENT) {
char *storage = g_strdup(tokenval.v.s);
int days = get_int(CONF_UNIT_NONE);
vault_list_t vl;
gboolean found = FALSE;
// Check if the vault is already in the list (Will only update days)
for (vl = val->v.vault_list ; vl != NULL ; vl = vl->next) {
vault_el_t *v = vl->data;
if (g_str_equal(storage, v->storage)) {
v->days = days;
found = TRUE;
nb_vault++;
}
}
if (!found) {
vault_el_t *vault = g_new(vault_el_t, 1);
nb_vault++;
vault->storage = storage;
vault->days = days;
val->v.vault_list = g_slist_append(val->v.vault_list, vault);
}
if (tok != CONF_NL && tok != CONF_END) {
get_conftoken(CONF_ANY);
}
}
if (nb_vault == 0) {
slist_free_full(val->v.vault_list, free_vault);
val->v.vault_list =NULL;
}
}
/* get_* functions */
/* these functions use precompiler conditionals to skip useless size checks
* when casting from one type to another. SIZEOF_GINT64 is pretty simple to
* calculate; the others are calculated by configure. */
#define SIZEOF_GINT64 8
static time_t
get_time(void)
{
time_t hhmm;
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_INT:
#if SIZEOF_TIME_T < SIZEOF_INT
if ((gint64)tokenval.v.i >= (gint64)TIME_MAX)
conf_parserror(_("value too large"));
#endif
hhmm = (time_t)tokenval.v.i;
break;
case CONF_SIZE:
#if SIZEOF_TIME_T < SIZEOF_SSIZE_T
if ((gint64)tokenval.v.size >= (gint64)TIME_MAX)
conf_parserror(_("value too large"));
#endif
hhmm = (time_t)tokenval.v.size;
break;
case CONF_INT64:
#if SIZEOF_TIME_T < SIZEOF_GINT64
if ((gint64)tokenval.v.int64 >= (gint64)TIME_MAX)
conf_parserror(_("value too large"));
#endif
hhmm = (time_t)tokenval.v.int64;
break;
case CONF_AMINFINITY:
hhmm = TIME_MAX;
break;
default:
conf_parserror(_("a time is expected"));
hhmm = 0;
break;
}
return hhmm;
}
static int
get_int(
confunit_t unit)
{
int val;
keytab_t *save_kt;
save_kt = keytable;
keytable = numb_keytable;
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_INT:
val = tokenval.v.i;
break;
case CONF_SIZE:
#if SIZEOF_INT < SIZEOF_SSIZE_T
if ((gint64)tokenval.v.size > (gint64)INT_MAX)
conf_parserror(_("value too large"));
if ((gint64)tokenval.v.size < (gint64)INT_MIN)
conf_parserror(_("value too small"));
#endif
val = (int)tokenval.v.size;
break;
case CONF_INT64:
#if SIZEOF_INT < SIZEOF_GINT64
if (tokenval.v.int64 > (gint64)INT_MAX)
conf_parserror(_("value too large"));
if (tokenval.v.int64 < (gint64)INT_MIN)
conf_parserror(_("value too small"));
#endif
val = (int)tokenval.v.int64;
break;
case CONF_AMINFINITY:
val = INT_MAX;
break;
default:
conf_parserror(_("an integer is expected"));
val = 0;
break;
}
/* get multiplier, if any */
val = get_multiplier(val, unit);
keytable = save_kt;
return val;
}
static ssize_t
get_size(
confunit_t unit)
{
ssize_t val;
keytab_t *save_kt;
save_kt = keytable;
keytable = numb_keytable;
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_SIZE:
val = tokenval.v.size;
break;
case CONF_INT:
#if SIZEOF_SIZE_T < SIZEOF_INT
if ((gint64)tokenval.v.i > (gint64)SSIZE_MAX)
conf_parserror(_("value too large"));
if ((gint64)tokenval.v.i < (gint64)SSIZE_MIN)
conf_parserror(_("value too small"));
#endif
val = (ssize_t)tokenval.v.i;
break;
case CONF_INT64:
#if SIZEOF_SIZE_T < SIZEOF_GINT64
if (tokenval.v.int64 > (gint64)SSIZE_MAX)
conf_parserror(_("value too large"));
if (tokenval.v.int64 < (gint64)SSIZE_MIN)
conf_parserror(_("value too small"));
#endif
val = (ssize_t)tokenval.v.int64;
break;
case CONF_AMINFINITY:
val = (ssize_t)SSIZE_MAX;
break;
default:
conf_parserror(_("an integer is expected"));
val = 0;
break;
}
/* get multiplier, if any */
val = get_multiplier(val, unit);
keytable = save_kt;
return val;
}
static gint64
get_int64(
confunit_t unit)
{
gint64 val;
keytab_t *save_kt;
save_kt = keytable;
keytable = numb_keytable;
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_INT:
val = (gint64)tokenval.v.i;
break;
case CONF_SIZE:
val = (gint64)tokenval.v.size;
break;
case CONF_INT64:
val = tokenval.v.int64;
break;
case CONF_AMINFINITY:
val = G_MAXINT64;
break;
default:
conf_parserror(_("an integer is expected"));
val = 0;
break;
}
/* get multiplier, if any */
val = get_multiplier(val, unit);
keytable = save_kt;
return val;
}
gint64
get_multiplier(
gint64 val,
confunit_t unit)
{
/* get multiplier, if any */
get_conftoken(CONF_ANY);
if (tok == CONF_NL || tok == CONF_END) { /* no multiplier */
// val = val;
} else if (tok == CONF_MULT1 && unit == CONF_UNIT_K) {
val /= 1024;
} else if (tok == CONF_MULT1 ||
(tok == CONF_MULT1K && unit == CONF_UNIT_K)) {
val *= 1; /* multiply by one */
} else if (tok == CONF_MULT7) {
if (val > G_MAXINT64/7 || val < ((gint64)G_MININT64)/7)
conf_parserror(_("value too large"));
val *= 7;
} else if (tok == CONF_MULT1K ||
(tok == CONF_MULT1M && unit == CONF_UNIT_K)) {
if (val > G_MAXINT64/1024 || val < ((gint64)G_MININT64)/1024)
conf_parserror(_("value too large"));
val *= 1024;
} else if (tok == CONF_MULT1M ||
(tok == CONF_MULT1G && unit == CONF_UNIT_K)) {
if (val > G_MAXINT64/(1024*1024) || val < ((gint64)G_MININT64)/(1024*1024))
conf_parserror(_("value too large"));
val *= 1024*1024;
} else if (tok == CONF_MULT1G ||
(tok == CONF_MULT1T && unit == CONF_UNIT_K)) {
if (val > G_MAXINT64/(1024*1024*1024) || val < ((gint64)G_MININT64)/(1024*1024*1024))
conf_parserror(_("value too large"));
val *= 1024*1024*1024;
} else if (tok == CONF_MULT1T) {
if (val > G_MAXINT64/(1024*1024*1024*1024LL) || val < ((gint64)G_MININT64)/(1024*1024*1024*1024LL))
conf_parserror(_("value too large"));
val *= 1024*1024*1024*1024LL;
} else {
// val *= 1;
unget_conftoken();
}
return val;
}
static int
get_bool(void)
{
int val;
keytab_t *save_kt;
save_kt = keytable;
keytable = bool_keytable;
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_INT:
if (tokenval.v.i != 0)
val = 1;
else
val = 0;
break;
case CONF_SIZE:
if (tokenval.v.size != (size_t)0)
val = 1;
else
val = 0;
break;
case CONF_INT64:
if (tokenval.v.int64 != (gint64)0)
val = 1;
else
val = 0;
break;
case CONF_ATRUE:
val = 1;
break;
case CONF_AFALSE:
val = 0;
break;
case CONF_NL:
unget_conftoken();
val = 2; /* no argument - most likely TRUE */
break;
default:
unget_conftoken();
val = 3; /* a bad argument - most likely TRUE */
conf_parserror(_("YES, NO, TRUE, FALSE, ON, OFF, 0, 1 expected"));
break;
}
keytable = save_kt;
return val;
}
static int
get_no_yes_all(void)
{
int val;
keytab_t *save_kt;
save_kt = keytable;
keytable = no_yes_all_keytable;
get_conftoken(CONF_ANY);
switch(tok) {
case CONF_INT:
val = tokenval.v.i;
break;
case CONF_SIZE:
val = tokenval.v.size;
break;
case CONF_INT64:
val = tokenval.v.int64;
break;
case CONF_ALL:
val = 2;
break;
case CONF_ATRUE:
val = 1;
break;
case CONF_AFALSE:
val = 0;
break;
case CONF_NL:
unget_conftoken();
val = 3; /* no argument - most likely TRUE */
break;
default:
unget_conftoken();
val = 3; /* a bad argument - most likely TRUE */
conf_parserror(_("%d: YES, NO, ALL, TRUE, FALSE, ON, OFF, 0, 1, 2 expected"), tok);
break;
}
if (val > 2 || val < 0)
val = 1;
keytable = save_kt;
return val;
}
void
ckseen(
seen_t *seen)
{
if (seen->linenum && !allow_overwrites && current_line_num != -2) {
conf_parserror(_("duplicate parameter; previous definition %s:%d"),
seen->filename, seen->linenum);
}
seen->block = current_block;
seen->filename = current_filename;
seen->linenum = current_line_num;
}
/* Validation functions */
static void
validate_name(
tok_t token,
val_t *val)
{
switch (val->type) {
case CONFTYPE_STR:
case CONFTYPE_IDENT:
{
char *str = val_t__str(val);
if (str && strchr(str, ' '))
conf_parserror("%s must not contains space", get_token_name(token));
if (str && strchr(str, '"'))
conf_parserror("%s must not contains double quotes", get_token_name(token));
break;
}
default:
conf_parserror("validate_no_space_dquote invalid type %d\n", val->type);
}
}
static void
validate_no_space_dquote(
struct conf_var_s *np,
val_t *val)
{
switch (val->type) {
case CONFTYPE_STR:
{
char *str = val_t__str(val);
if (str && strchr(str, ' '))
conf_parserror("%s must not contains space", get_token_name(np->token));
if (str && strchr(str, '"'))
conf_parserror("%s must not contains double quotes", get_token_name(np->token));
break;
}
case CONFTYPE_AUTOLABEL:
{
autolabel_t *autolabel = val_t__autolabel(val);
if (autolabel->template && strchr(autolabel->template, ' '))
conf_parserror("%s template must not contains space", get_token_name(np->token));
if (autolabel->template && strchr(autolabel->template, '"'))
conf_parserror("%s template must not contains double quotes", get_token_name(np->token));
break;
}
case CONFTYPE_LABELSTR:
{
labelstr_s *labelstr = val_t__labelstr(val);
if (labelstr->template && strchr(labelstr->template, '"'))
conf_parserror("%s template must not contains double quotes", get_token_name(np->token));
if (labelstr->template && strchr(labelstr->template, ' '))
conf_parserror("%s template must not contains space", get_token_name(np->token));
break;
}
default:
conf_parserror("validate_no_space_dquote invalid type %d\n", val->type);
}
}
static void
validate_nonnegative(
struct conf_var_s *np,
val_t *val)
{
switch(val->type) {
case CONFTYPE_INT:
if(val_t__int(val) < 0)
conf_parserror(_("%s must be nonnegative"), get_token_name(np->token));
break;
case CONFTYPE_INT64:
if(val_t__int64(val) < 0)
conf_parserror(_("%s must be nonnegative"), get_token_name(np->token));
break;
case CONFTYPE_SIZE:
// Can't be negative
//if(val_t__size(val) < 0)
// conf_parserror(_("%s must be positive"), get_token_name(np->token));
break;
default:
conf_parserror(_("validate_nonnegative invalid type %d\n"), val->type);
}
}
static void
validate_non_zero(
struct conf_var_s *np,
val_t *val)
{
switch(val->type) {
case CONFTYPE_INT:
if(val_t__int(val) == 0)
conf_parserror(_("%s must not be 0"), get_token_name(np->token));
break;
case CONFTYPE_INT64:
if(val_t__int64(val) == 0)
conf_parserror(_("%s must not be 0"), get_token_name(np->token));
break;
case CONFTYPE_TIME:
if(val_t__time(val) == 0)
conf_parserror(_("%s must not be 0"), get_token_name(np->token));
break;
case CONFTYPE_SIZE:
if(val_t__size(val) == 0)
conf_parserror(_("%s must not be 0"), get_token_name(np->token));
break;
default:
conf_parserror(_("validate_non_zero invalid type %d\n"), val->type);
}
}
static void
validate_positive(
struct conf_var_s *np,
val_t *val)
{
switch(val->type) {
case CONFTYPE_INT:
if(val_t__int(val) < 1)
conf_parserror(_("%s must be positive"), get_token_name(np->token));
break;
case CONFTYPE_INT64:
if(val_t__int64(val) < 1)
conf_parserror(_("%s must be positive"), get_token_name(np->token));
break;
case CONFTYPE_TIME:
if(val_t__time(val) < 1)
conf_parserror(_("%s must be positive"), get_token_name(np->token));
break;
case CONFTYPE_SIZE:
if(val_t__size(val) < 1)
conf_parserror(_("%s must be positive"), get_token_name(np->token));
break;
default:
conf_parserror(_("validate_positive invalid type %d\n"), val->type);
}
}
static void
validate_runspercycle(
struct conf_var_s *np G_GNUC_UNUSED,
val_t *val)
{
if(val_t__int(val) < -1)
conf_parserror(_("runspercycle must be >= -1"));
}
static void
validate_bumppercent(
struct conf_var_s *np G_GNUC_UNUSED,
val_t *val)
{
if(val_t__int(val) < 0 || val_t__int(val) > 100)
conf_parserror(_("bumppercent must be between 0 and 100"));
}
static void
validate_bumpmult(
struct conf_var_s *np G_GNUC_UNUSED,
val_t *val)
{
if(val_t__real(val) < 0.999) {
conf_parserror(_("bumpmult must one or more"));
}
}
static void
validate_displayunit(
struct conf_var_s *np G_GNUC_UNUSED,
val_t *val G_GNUC_UNUSED)
{
char *s = val_t__str(val);
if (strlen(s) == 1) {
switch (s[0]) {
case 'K':
case 'M':
case 'G':
case 'T':
return; /* all good */
/* lower-case values should get folded to upper case */
case 'k':
case 'm':
case 'g':
case 't':
s[0] = toupper(s[0]);
return;
default: /* bad */
break;
}
}
conf_parserror(_("displayunit must be k,m,g or t."));
}
static void
validate_reserve(
struct conf_var_s *np G_GNUC_UNUSED,
val_t *val)
{
if(val_t__int(val) < 0 || val_t__int(val) > 100)
conf_parserror(_("reserve must be between 0 and 100"));
}
static void
validate_use(
struct conf_var_s *np G_GNUC_UNUSED,
val_t *val)
{
val_t__int64(val) = am_floor(val_t__int64(val), DISK_BLOCK_KB);
}
static void
validate_chunksize(
struct conf_var_s *np G_GNUC_UNUSED,
val_t *val)
{
/* NOTE: this function modifies the target value (rounding) */
if(val_t__int64(val) == 0) {
val_t__int64(val) = ((G_MAXINT64 / 1024) - (2 * DISK_BLOCK_KB));
}
else if(val_t__int64(val) < 0) {
conf_parserror(_("Negative chunksize (%lld) is no longer supported"), (long long)val_t__int64(val));
}
val_t__int64(val) = am_floor(val_t__int64(val), (gint64)DISK_BLOCK_KB);
if (val_t__int64(val) < 2*DISK_BLOCK_KB) {
conf_parserror("chunksize must be at least %dkb", 2*DISK_BLOCK_KB);
}
}
static void
validate_blocksize(
struct conf_var_s *np G_GNUC_UNUSED,
val_t *val)
{
if(val_t__size(val) < DISK_BLOCK_KB) {
conf_parserror(_("Tape blocksize must be at least %d KBytes"),
DISK_BLOCK_KB);
}
}
static void
validate_debug(
struct conf_var_s *np G_GNUC_UNUSED,
val_t *val)
{
if(val_t__int(val) < 0 || val_t__int(val) > 9) {
conf_parserror(_("Debug must be between 0 and 9"));
}
}
static void
validate_port_range(
val_t *val,
int smallest,
int largest)
{
int i;
/* check both values are in range */
for (i = 0; i < 2; i++) {
if(val_t__intrange(val)[0] < smallest || val_t__intrange(val)[0] > largest) {
conf_parserror(_("portrange must be in the range %d to %d, inclusive"), smallest, largest);
}
}
/* and check they're in the right order and not equal */
if (val_t__intrange(val)[0] > val_t__intrange(val)[1]) {
conf_parserror(_("portranges must be in order from low to high"));
}
}
static void
validate_reserved_port_range(
struct conf_var_s *np G_GNUC_UNUSED,
val_t *val)
{
validate_port_range(val, 1, IPPORT_RESERVED-1);
}
static void
validate_unreserved_port_range(
struct conf_var_s *np G_GNUC_UNUSED,
val_t *val)
{
validate_port_range(val, IPPORT_RESERVED, 65535);
}
/*
* Columnspec validation
*/
/*
* The list of lowercase string values valid for the first element of a
* columnspec.
*/
static const char *colspec_valid_names[] = {
"hostname",
"disk",
"level",
"origkb",
"outkb",
"compress",
"dumptime",
"dumprate",
"tapetime",
"taperate"
};
/*
* Validate one columnspec element. We do modify the string inline, but that's
* OK: the caller won't use it anyway.
*
* One element is of the form:
*
* xxxxx=int1:int2:int3
*
* where: xxxxx is a string which can only be (case insensitive) one of the values in
* the colspec_valid_names array above. Other numbers are ALL optionals, there
* may be none at all. Save for int2, they MUST be positive. See amanda.conf(5).
*
* Yeah, today, nobody ever uses that, but... Ahwell.
*/
static void validate_one_columnspec(const char *element)
{
gchar *p, *token;
gchar **strings, **ptr;
guint i, nr_valid_names = G_N_ELEMENTS(colspec_valid_names);
p = strchr(element, '=');
if (!p) {
conf_parserror("invalid columnspec: %s", element);
return;
}
/*
* OK, at this point we at least have a first element. See if we know about
* it.
*/
*p++ = '\0';
token = g_ascii_strdown(element, -1);
for (i = 0; i < nr_valid_names; i++)
if (g_str_equal(colspec_valid_names[i], token)) /* We have a match */
break;
g_free(token);
if (i == nr_valid_names) { /* No match! Bye... */
conf_parserror("invalid column name: '%s'", element);
return;
}
/*
* Now we must check for numbers. As mentioned above, ALL are optional. If
* the second number is present, it is the only one which can be negative.
*/
i = 0;
token = p;
strings = g_strsplit(p, ":", 3);
for (ptr = strings; *ptr; ptr++) {
p = *ptr;
/*
* Check for a potentially negative number - it is only valid in the
* second position.
*/
if (++i == 2 && *p == '-')
p++;
for (; *p; p++)
if (!g_ascii_isdigit(*p)) {
conf_parserror("invalid format: %s", token);
goto out;
}
}
out:
g_strfreev(strings);
}
/*
* Validate a columnspec input. We split the string against ',' and use
* validate_one_columnspec() above to validate each substring returned.
*/
static void validate_columnspec(conf_var_t *var G_GNUC_UNUSED, val_t *value)
{
gchar *input = val_t_to_str(value);
gchar **elements, **ptr;
elements = g_strsplit(input, ",", 0);
for (ptr = elements; *ptr; ptr++)
validate_one_columnspec(*ptr);
g_strfreev(elements);
}
/*
* Validate tmpdir, the directory must exist and be writable by the user.
*/
static void validate_tmpdir(conf_var_t *var G_GNUC_UNUSED, val_t *value)
{
struct stat stat_buf;
gchar *tmpdir = val_t_to_str(value);
if (stat(tmpdir, &stat_buf)) {
conf_parserror(_("invalid TMPDIR: directory '%s': %s."),
tmpdir, strerror(errno));
} else if (!S_ISDIR(stat_buf.st_mode)) {
conf_parserror(_("invalid TMPDIR: '%s' is not a directory."),
tmpdir);
} else {
gchar *dir = g_strconcat(tmpdir, "/.", NULL);
if (access(dir, R_OK|W_OK) == -1) {
conf_parserror(_("invalid TMPDIR: '%s': can not read/write: %s."),
tmpdir, strerror(errno));
}
g_free(dir);
}
}
/* global changerfile deprecated in 3.4 */
/* global changerfile must be removed in 3.4.5 */
static void validate_deprecated_changerfile(conf_var_t *var G_GNUC_UNUSED,
val_t *value G_GNUC_UNUSED)
{
conf_parswarn(_("warning: Global changerfile is deprecated, it must be set in the changer section"));
}
gboolean
config_is_initialized(void)
{
return config_initialized;
}
/*
* Initialization Implementation
*/
cfgerr_level_t
config_init_with_global(
config_init_flags flags,
char *arg_config_name)
{
cfgerr_level_t cfgerr_level;
cfgerr_level = config_init(flags|CONFIG_INIT_GLOBAL|CONFIG_OVERRDIDE_NO_ERROR, arg_config_name);
//cfgerr_level = config_init(flags|CONFIG_INIT_GLOBAL, arg_config_name);
if (config_errors(NULL) >= CFGERR_WARNINGS) {
return cfgerr_level;
}
return config_init(flags|CONFIG_INIT_OVERLAY, arg_config_name);
}
cfgerr_level_t
config_init(
config_init_flags flags,
char *arg_config_name)
{
generate_errors = TRUE;
if (!(flags & CONFIG_INIT_OVERLAY)) {
/* Clear out anything that's already in there */
config_uninit();
/* and set everything to default values */
init_defaults();
allow_overwrites = FALSE;
} else {
if (!config_initialized) {
error(_("Attempt to overlay configuration with no existing configuration"));
/* NOTREACHED */
}
allow_overwrites = TRUE;
}
/* store away our client-ness for later reference */
config_client = flags & CONFIG_INIT_CLIENT;
/* if we're using an explicit name, but the name is '.', then we're using the
* current directory */
if ((flags & CONFIG_INIT_EXPLICIT_NAME) && arg_config_name) {
if (g_str_equal(arg_config_name, "."))
flags = (flags & (~CONFIG_INIT_EXPLICIT_NAME)) | CONFIG_INIT_USE_CWD;
}
if (flags & CONFIG_INIT_GLOBAL) {
amfree(config_name);
g_free(config_dir);
config_dir = g_strdup(CONFIG_DIR);
} else if ((flags & CONFIG_INIT_EXPLICIT_NAME) && arg_config_name) {
g_free(config_name);
config_name = g_strdup(arg_config_name);
g_free(config_dir);
config_dir = g_strconcat(CONFIG_DIR, "/", arg_config_name, NULL);
} else if (flags & CONFIG_INIT_USE_CWD) {
char *cwd;
char *filename;
struct stat statbuf;
cwd = get_original_cwd();
if (!cwd) {
/* (this isn't a config error, so it's always fatal) */
error(_("Cannot determine current working directory"));
/* NOTREACHED */
}
filename = g_strconcat(cwd, "/amanda.conf", NULL);
if (stat(filename, &statbuf) == 0) {
config_dir = g_strconcat(cwd, "/", NULL);
if ((config_name = strrchr(cwd, '/')) != NULL) {
config_name = g_strdup(config_name + 1);
}
} else {
amfree(config_name);
amfree(config_dir);
}
g_free(filename);
} else {
/* ok, then, we won't read anything (for e.g., amrestore) */
amfree(config_name);
amfree(config_dir);
}
/* setup for apply_config_overrides */
if (flags & CONFIG_INIT_CLIENT) {
keytable = client_keytab;
parsetable = client_var;
} else {
keytable = server_keytab;
parsetable = server_var;
}
if (config_overrides) {
int i;
for (i = 0; i < config_overrides->n_used; i++) {
config_overrides->ovr[i].applied = FALSE;
}
}
/* apply config overrides to default setting */
generate_errors = FALSE;
apply_config_overrides(config_overrides, NULL);
generate_errors = TRUE;
/* If we have a config_dir, we can try reading something */
if (config_dir) {
if (flags & CONFIG_INIT_CLIENT) {
g_free(config_filename);
config_filename = g_strconcat(config_dir, "/amanda-client.conf",
NULL);
} else {
g_free(config_filename);
config_filename = g_strconcat(config_dir, "/amanda.conf", NULL);
}
read_conffile(config_filename,
flags & CONFIG_INIT_CLIENT,
flags & (CONFIG_INIT_CLIENT|CONFIG_INIT_GLOBAL));
} else {
amfree(config_filename);
}
if (getconf_linenum(CNF_ACTIVE_STORAGE) <= 0) {
// default to the configured CNF_STORAGE
copy_val_t(&conf_data[CNF_ACTIVE_STORAGE], &conf_data[CNF_STORAGE]);
}
/* apply config overrides to default setting */
generate_errors = !(flags & CONFIG_OVERRDIDE_NO_ERROR);
apply_config_overrides(config_overrides, NULL);
generate_errors = TRUE;
if (!(flags & CONFIG_INIT_GLOBAL) || !arg_config_name) {
if (config_overrides) {
int i;
for (i = 0; i < config_overrides->n_used; i++) {
if (config_overrides->ovr[i].applied == FALSE) {
conf_parserror(_("unknown parameter '%s'"),
config_overrides->ovr[i].key);
}
}
}
update_derived_values(flags & CONFIG_INIT_CLIENT);
}
return cfgerr_level;
}
void
config_uninit(void)
{
GSList *hp;
holdingdisk_t *hd;
dumptype_t *dp, *dpnext;
tapetype_t *tp, *tpnext;
interface_t *ip, *ipnext;
application_t *ap, *apnext;
pp_script_t *pp, *ppnext;
device_config_t *dc, *dcnext;
changer_config_t *cc, *ccnext;
interactivity_t *iv, *ivnext;
taperscan_t *ts, *tsnext;
policy_s *po, *ponext;
storage_t *st, *stnext;
int i;
if (!config_initialized) return;
for(hp=holdinglist; hp != NULL; hp = hp->next) {
hd = hp->data;
amfree(hd->name);
for(i=0; i<HOLDING_HOLDING; i++) {
free_val_t(&hd->value[i]);
}
g_free(hd->seen.block);
}
slist_free_full(holdinglist, g_free);
holdinglist = NULL;
for(dp=dumplist; dp != NULL; dp = dpnext) {
amfree(dp->name);
for(i=0; i<DUMPTYPE_DUMPTYPE; i++) {
free_val_t(&dp->value[i]);
}
g_free(dp->seen.block);
dpnext = dp->next;
amfree(dp);
}
dumplist = NULL;
for(tp=tapelist; tp != NULL; tp = tpnext) {
amfree(tp->name);
for(i=0; i<TAPETYPE_TAPETYPE; i++) {
free_val_t(&tp->value[i]);
}
g_free(tp->seen.block);
tpnext = tp->next;
amfree(tp);
}
tapelist = NULL;
for(ip=interface_list; ip != NULL; ip = ipnext) {
amfree(ip->name);
for(i=0; i<INTER_INTER; i++) {
free_val_t(&ip->value[i]);
}
g_free(ip->seen.block);
ipnext = ip->next;
amfree(ip);
}
interface_list = NULL;
for(ap=application_list; ap != NULL; ap = apnext) {
amfree(ap->name);
for(i=0; i<APPLICATION_APPLICATION; i++) {
free_val_t(&ap->value[i]);
}
g_free(ap->seen.block);
apnext = ap->next;
amfree(ap);
}
application_list = NULL;
for(pp=pp_script_list; pp != NULL; pp = ppnext) {
amfree(pp->name);
for(i=0; i<PP_SCRIPT_PP_SCRIPT; i++) {
free_val_t(&pp->value[i]);
}
g_free(pp->seen.block);
ppnext = pp->next;
amfree(pp);
}
pp_script_list = NULL;
for(dc=device_config_list; dc != NULL; dc = dcnext) {
amfree(dc->name);
for(i=0; i<DEVICE_CONFIG_DEVICE_CONFIG; i++) {
free_val_t(&dc->value[i]);
}
g_free(dc->seen.block);
dcnext = dc->next;
amfree(dc);
}
device_config_list = NULL;
for(cc=changer_config_list; cc != NULL; cc = ccnext) {
amfree(cc->name);
for(i=0; i<CHANGER_CONFIG_CHANGER_CONFIG; i++) {
free_val_t(&cc->value[i]);
}
g_free(cc->seen.block);
ccnext = cc->next;
amfree(cc);
}
changer_config_list = NULL;
for(iv=interactivity_list; iv != NULL; iv = ivnext) {
amfree(iv->name);
for(i=0; i<INTERACTIVITY_INTERACTIVITY; i++) {
free_val_t(&iv->value[i]);
}
g_free(iv->seen.block);
ivnext = iv->next;
amfree(iv);
}
interactivity_list = NULL;
for(ts=taperscan_list; ts != NULL; ts = tsnext) {
amfree(ts->name);
for(i=0; i<TAPERSCAN_TAPERSCAN; i++) {
free_val_t(&ts->value[i]);
}
g_free(ts->seen.block);
tsnext = ts->next;
amfree(ts);
}
taperscan_list = NULL;
for(po=policy_list; po != NULL; po = ponext) {
amfree(po->name);
for(i=0; i<POLICY_POLICY; i++) {
free_val_t(&po->value[i]);
}
g_free(po->seen.block);
ponext = po->next;
amfree(po);
}
policy_list = NULL;
for(st=storage_list; st != NULL; st = stnext) {
amfree(st->name);
for(i=0; i<STORAGE_STORAGE; i++) {
free_val_t(&st->value[i]);
}
g_free(st->seen.block);
stnext = st->next;
amfree(st);
}
storage_list = NULL;
for(i=0; i<CNF_CNF; i++)
free_val_t(&conf_data[i]);
if (config_overrides) {
free_config_overrides(config_overrides);
config_overrides = NULL;
}
amfree(config_name);
amfree(config_dir);
amfree(config_filename);
slist_free_full(seen_filenames, g_free);
seen_filenames = NULL;
config_client = FALSE;
config_clear_errors();
config_initialized = FALSE;
}
static void
init_defaults(
void)
{
assert(!config_initialized);
/* defaults for exported variables */
conf_init_str(&conf_data[CNF_ORG], DEFAULT_CONFIG);
conf_init_str(&conf_data[CNF_CONF], DEFAULT_CONFIG);
conf_init_str(&conf_data[CNF_AMDUMP_SERVER], DEFAULT_SERVER);
conf_init_str(&conf_data[CNF_INDEX_SERVER], DEFAULT_SERVER);
conf_init_str(&conf_data[CNF_TAPE_SERVER], DEFAULT_TAPE_SERVER);
conf_init_str(&conf_data[CNF_AUTH], "bsdtcp");
conf_init_str(&conf_data[CNF_SSH_KEYS], "");
conf_init_str(&conf_data[CNF_AMANDAD_PATH], "");
conf_init_str(&conf_data[CNF_CLIENT_USERNAME], "");
conf_init_str(&conf_data[CNF_CLIENT_PORT], "");
conf_init_str(&conf_data[CNF_SSL_DIR], CONFIG_DIR "/ssl");
conf_init_bool(&conf_data[CNF_SSL_CHECK_FINGERPRINT], 1);
conf_init_str(&conf_data[CNF_SSL_FINGERPRINT_FILE], "");
conf_init_str(&conf_data[CNF_SSL_CERT_FILE] , "");
conf_init_str(&conf_data[CNF_SSL_KEY_FILE] , "");
conf_init_str(&conf_data[CNF_SSL_CA_CERT_FILE] , "");
conf_init_str(&conf_data[CNF_SSL_CIPHER_LIST] , "");
conf_init_bool(&conf_data[CNF_SSL_CHECK_HOST] , 1);
conf_init_bool(&conf_data[CNF_SSL_CHECK_CERTIFICATE_HOST], 1);
conf_init_str(&conf_data[CNF_GNUTAR_LIST_DIR], GNUTAR_LISTED_INCREMENTAL_DIR);
conf_init_str(&conf_data[CNF_AMANDATES], DEFAULT_AMANDATES_FILE);
conf_init_str(&conf_data[CNF_MAILTO], "");
conf_init_str(&conf_data[CNF_DUMPUSER], CLIENT_LOGIN);
conf_init_str(&conf_data[CNF_TAPEDEV], DEFAULT_TAPE_DEVICE);
conf_init_proplist(&conf_data[CNF_DEVICE_PROPERTY]);
conf_init_proplist(&conf_data[CNF_PROPERTY]);
conf_init_str(&conf_data[CNF_CHANGERDEV], NULL);
conf_init_str(&conf_data[CNF_CHANGERFILE] , "changer");
conf_init_str (&conf_data[CNF_TAPELIST] , "tapelist");
conf_init_str (&conf_data[CNF_DISKFILE] , "disklist");
conf_init_str (&conf_data[CNF_INFOFILE] , "/usr/adm/amanda/curinfo");
conf_init_str (&conf_data[CNF_LOGDIR] , "/usr/adm/amanda");
conf_init_str (&conf_data[CNF_INDEXDIR] , "/usr/adm/amanda/index");
conf_init_ident (&conf_data[CNF_TAPETYPE] , "DEFAULT_TAPE");
conf_init_identlist(&conf_data[CNF_HOLDINGDISK] , NULL);
conf_init_int (&conf_data[CNF_DUMPCYCLE] , CONF_UNIT_NONE, 10);
conf_init_int (&conf_data[CNF_RUNSPERCYCLE] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_TAPECYCLE] , CONF_UNIT_NONE, 15);
conf_init_int (&conf_data[CNF_NETUSAGE] , CONF_UNIT_K , 80000);
conf_init_int (&conf_data[CNF_INPARALLEL] , CONF_UNIT_NONE, 10);
conf_init_str (&conf_data[CNF_DUMPORDER] , "ttt");
conf_init_int (&conf_data[CNF_BUMPPERCENT] , CONF_UNIT_NONE, 0);
conf_init_int64 (&conf_data[CNF_BUMPSIZE] , CONF_UNIT_K , (gint64)10*1024);
conf_init_real (&conf_data[CNF_BUMPMULT] , 1.5);
conf_init_int (&conf_data[CNF_BUMPDAYS] , CONF_UNIT_NONE, 2);
conf_init_str (&conf_data[CNF_TPCHANGER] , "");
conf_init_int (&conf_data[CNF_RUNTAPES] , CONF_UNIT_NONE, 1);
conf_init_int (&conf_data[CNF_MAXDUMPS] , CONF_UNIT_NONE, 1);
conf_init_int (&conf_data[CNF_MAX_DLE_BY_VOLUME] , CONF_UNIT_NONE, 1000000000);
conf_init_int (&conf_data[CNF_ETIMEOUT] , CONF_UNIT_NONE, 300);
conf_init_int (&conf_data[CNF_DTIMEOUT] , CONF_UNIT_NONE, 1800);
conf_init_int (&conf_data[CNF_CTIMEOUT] , CONF_UNIT_NONE, 30);
conf_init_size (&conf_data[CNF_DEVICE_OUTPUT_BUFFER_SIZE], CONF_UNIT_NONE, 40*32768);
conf_init_str (&conf_data[CNF_PRINTER] , "");
conf_init_str (&conf_data[CNF_MAILER] , DEFAULT_MAILER);
conf_init_no_yes_all(&conf_data[CNF_AUTOFLUSH] , 0);
conf_init_int (&conf_data[CNF_RESERVE] , CONF_UNIT_NONE, 100);
conf_init_int64 (&conf_data[CNF_MAXDUMPSIZE] , CONF_UNIT_K , (gint64)-1);
conf_init_str (&conf_data[CNF_COLUMNSPEC] , "");
conf_init_bool (&conf_data[CNF_AMRECOVER_DO_FSF] , 1);
conf_init_str (&conf_data[CNF_AMRECOVER_CHANGER] , "");
conf_init_bool (&conf_data[CNF_AMRECOVER_CHECK_LABEL], 1);
conf_init_taperalgo(&conf_data[CNF_TAPERALGO] , 0);
conf_init_int (&conf_data[CNF_TAPER_PARALLEL_WRITE] , CONF_UNIT_NONE, 1);
conf_init_int (&conf_data[CNF_FLUSH_THRESHOLD_DUMPED] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_FLUSH_THRESHOLD_SCHEDULED], CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_TAPERFLUSH] , CONF_UNIT_NONE, 0);
conf_init_str (&conf_data[CNF_DISPLAYUNIT] , "K");
conf_init_str (&conf_data[CNF_KRB5KEYTAB] , "/.amanda-v5-keytab");
conf_init_str (&conf_data[CNF_KRB5PRINCIPAL] , "service/amanda");
conf_init_str (&conf_data[CNF_LABEL_NEW_TAPES] , "");
conf_init_bool (&conf_data[CNF_EJECT_VOLUME] , 0);
conf_init_bool (&conf_data[CNF_REPORT_USE_MEDIA] , TRUE);
conf_init_bool (&conf_data[CNF_REPORT_NEXT_MEDIA] , TRUE);
conf_init_str_list (&conf_data[CNF_REPORT_FORMAT] , NULL);
conf_init_bool (&conf_data[CNF_COMPRESS_INDEX] , TRUE);
conf_init_bool (&conf_data[CNF_SORT_INDEX] , FALSE);
conf_init_str (&conf_data[CNF_TMPDIR] , AMANDA_TMPDIR);
conf_init_identlist(&conf_data[CNF_ACTIVE_STORAGE] , NULL);
conf_init_identlist(&conf_data[CNF_STORAGE] , NULL);
conf_init_identlist(&conf_data[CNF_VAULT_STORAGE] , NULL);
conf_init_str (&conf_data[CNF_CMDFILE] , "command_file");
conf_init_int (&conf_data[CNF_REST_API_PORT] , CONF_UNIT_NONE, 0);
conf_init_str (&conf_data[CNF_REST_SSL_CERT] , NULL);
conf_init_str (&conf_data[CNF_REST_SSL_KEY] , NULL);
conf_init_bool (&conf_data[CNF_USETIMESTAMPS] , 1);
conf_init_int (&conf_data[CNF_CONNECT_TRIES] , CONF_UNIT_NONE, 3);
conf_init_int (&conf_data[CNF_REP_TRIES] , CONF_UNIT_NONE, 5);
conf_init_int (&conf_data[CNF_REQ_TRIES] , CONF_UNIT_NONE, 3);
conf_init_int (&conf_data[CNF_DEBUG_DAYS] , CONF_UNIT_NONE, AMANDA_DEBUG_DAYS);
conf_init_int (&conf_data[CNF_DEBUG_AMANDAD] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_RECOVERY] , CONF_UNIT_NONE, 1);
conf_init_int (&conf_data[CNF_DEBUG_AMIDXTAPED] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_AMINDEXD] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_AMRECOVER] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_AUTH] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_EVENT] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_HOLDING] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_PROTOCOL] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_PLANNER] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_DRIVER] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_DUMPER] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_CHUNKER] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_TAPER] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_SELFCHECK] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_SENDSIZE] , CONF_UNIT_NONE, 0);
conf_init_int (&conf_data[CNF_DEBUG_SENDBACKUP] , CONF_UNIT_NONE, 0);
#ifdef UDPPORTRANGE
conf_init_intrange (&conf_data[CNF_RESERVED_UDP_PORT] , UDPPORTRANGE);
#else
conf_init_intrange (&conf_data[CNF_RESERVED_UDP_PORT] , 512, IPPORT_RESERVED-1);
#endif
#ifdef LOW_TCPPORTRANGE
conf_init_intrange (&conf_data[CNF_RESERVED_TCP_PORT] , LOW_TCPPORTRANGE);
#else
conf_init_intrange (&conf_data[CNF_RESERVED_TCP_PORT] , 512, IPPORT_RESERVED-1);
#endif
#ifdef TCPPORTRANGE
conf_init_intrange (&conf_data[CNF_UNRESERVED_TCP_PORT] , TCPPORTRANGE);
#else
conf_init_intrange (&conf_data[CNF_UNRESERVED_TCP_PORT] , IPPORT_RESERVED, 65535);
#endif
conf_init_send_amreport (&conf_data[CNF_SEND_AMREPORT_ON], SEND_AMREPORT_ALL);
conf_init_autolabel(&conf_data[CNF_AUTOLABEL]);
conf_init_labelstr(&conf_data[CNF_LABELSTR]);
conf_init_str(&conf_data[CNF_META_AUTOLABEL], NULL);
conf_init_host_limit(&conf_data[CNF_RECOVERY_LIMIT]);
conf_init_str(&conf_data[CNF_INTERACTIVITY], NULL);
conf_init_str(&conf_data[CNF_TAPERSCAN], NULL);
conf_init_str(&conf_data[CNF_HOSTNAME], NULL);
/* reset internal variables */
config_clear_errors();
cfgerr_level = CFGERR_OK;
allow_overwrites = 0;
token_pushed = 0;
/* create some predefined dumptypes for backwards compatability */
init_dumptype_defaults();
dpcur.name = g_strdup("NO-COMPRESS");
dpcur.seen.linenum = -1;
free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]);
val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_NONE;
val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]).linenum = -1;
save_dumptype();
init_dumptype_defaults();
dpcur.name = g_strdup("COMPRESS-FAST");
dpcur.seen.linenum = -1;
free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]);
val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_FAST;
val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]).linenum = -1;
save_dumptype();
init_dumptype_defaults();
dpcur.name = g_strdup("COMPRESS-BEST");
dpcur.seen.linenum = -1;
free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]);
val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_BEST;
val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]).linenum = -1;
save_dumptype();
init_dumptype_defaults();
dpcur.name = g_strdup("COMPRESS-CUST");
dpcur.seen.linenum = -1;
free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]);
val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_CUST;
val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]).linenum = -1;
save_dumptype();
init_dumptype_defaults();
dpcur.name = g_strdup("SRVCOMPRESS");
dpcur.seen.linenum = -1;
free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]);
val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_SERVER_FAST;
val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]).linenum = -1;
save_dumptype();
init_dumptype_defaults();
dpcur.name = g_strdup("BSD-AUTH");
dpcur.seen.linenum = -1;
free_val_t(&dpcur.value[DUMPTYPE_AUTH]);
val_t__str(&dpcur.value[DUMPTYPE_AUTH]) = g_strdup("BSD");
val_t__seen(&dpcur.value[DUMPTYPE_AUTH]).linenum = -1;
save_dumptype();
init_dumptype_defaults();
dpcur.name = g_strdup("BSDTCP-AUTH");
dpcur.seen.linenum = -1;
free_val_t(&dpcur.value[DUMPTYPE_AUTH]);
val_t__str(&dpcur.value[DUMPTYPE_AUTH]) = g_strdup("BSDTCP");
val_t__seen(&dpcur.value[DUMPTYPE_AUTH]).linenum = -1;
save_dumptype();
init_dumptype_defaults();
dpcur.name = g_strdup("NO-RECORD");
dpcur.seen.linenum = -1;
free_val_t(&dpcur.value[DUMPTYPE_RECORD]);
val_t__int(&dpcur.value[DUMPTYPE_RECORD]) = 0;
val_t__seen(&dpcur.value[DUMPTYPE_RECORD]).linenum = -1;
save_dumptype();
init_dumptype_defaults();
dpcur.name = g_strdup("NO-HOLD");
dpcur.seen.linenum = -1;
free_val_t(&dpcur.value[DUMPTYPE_HOLDINGDISK]);
val_t__holding(&dpcur.value[DUMPTYPE_HOLDINGDISK]) = HOLD_NEVER;
val_t__seen(&dpcur.value[DUMPTYPE_HOLDINGDISK]).linenum = -1;
save_dumptype();
init_dumptype_defaults();
dpcur.name = g_strdup("NO-FULL");
dpcur.seen.linenum = -1;
free_val_t(&dpcur.value[DUMPTYPE_STRATEGY]);
val_t__strategy(&dpcur.value[DUMPTYPE_STRATEGY]) = DS_NOFULL;
val_t__seen(&dpcur.value[DUMPTYPE_STRATEGY]).linenum = -1;
save_dumptype();
/* And we're initialized! */
config_initialized = 1;
}
char **
get_config_options(
int first)
{
char **config_options;
char **config_option;
int n_config_overrides = 0;
int i;
if (config_overrides)
n_config_overrides = config_overrides->n_used;
config_options = g_malloc((first+n_config_overrides+1)*sizeof(char *));
config_option = config_options + first;
for (i = 0; i < n_config_overrides; i++) {
char *key = config_overrides->ovr[i].key;
char *value = config_overrides->ovr[i].value;
*config_option = g_strjoin(NULL, "-o", key, "=", value, NULL);
config_option++;
}
*config_option = NULL; /* add terminating sentinel */
return config_options;
}
static void
update_derived_values(
gboolean is_client)
{
interface_t *ip;
identlist_t il;
holdingdisk_t *hd;
policy_s *po;
storage_t *st;
changer_config_t *dc;
labelstr_s *labelstr;
char *conf_name;
autolabel_t *autolabel;
char *meta_autolabel;
char *org;
char *st_name;
conf_name = get_config_name();
if (!conf_name)
conf_name = "default";
if (!is_client) {
/* Add a 'default' interface if one doesn't already exist */
if (!(ip = lookup_interface("default"))) {
init_interface_defaults();
ifcur.name = g_strdup("default");
ifcur.seen = val_t__seen(getconf(CNF_NETUSAGE));
save_interface();
ip = lookup_interface("default");
}
/* .. and set its maxusage from 'netusage' */
if (!interface_seen(ip, INTER_MAXUSAGE)) {
val_t *v;
v = interface_getconf(ip, INTER_COMMENT);
free_val_t(v);
val_t__str(v) = g_strdup(_("implicit from NETUSAGE"));
val_t__seen(v) = val_t__seen(getconf(CNF_NETUSAGE));
v = interface_getconf(ip, INTER_MAXUSAGE);
free_val_t(v);
val_t__int(v) = getconf_int(CNF_NETUSAGE);
val_t__seen(v) = val_t__seen(getconf(CNF_NETUSAGE));
}
/* Check the tapetype is defined */
if (lookup_tapetype(getconf_str(CNF_TAPETYPE)) == NULL) {
/* Create a default tapetype so that other code has
* something to refer to, but don't pretend it's real */
if (!getconf_seen(CNF_TAPETYPE) &&
g_str_equal(getconf_str(CNF_TAPETYPE), "DEFAULT_TAPE") &&
!lookup_tapetype("DEFAULT_TAPE")) {
init_tapetype_defaults();
tpcur.name = g_strdup("DEFAULT_TAPE");
tpcur.seen = val_t__seen(getconf(CNF_TAPETYPE));
save_tapetype();
} else {
conf_parserror(_("tapetype %s is not defined"),
getconf_str(CNF_TAPETYPE));
}
}
/* Check the holdingdisk are defined */
for (il = getconf_identlist(CNF_HOLDINGDISK);
il != NULL; il = il->next) {
hd = lookup_holdingdisk(il->data);
if (!hd) {
conf_parserror(_("holdingdisk %s is not defined"),
(char *)il->data);
}
}
if ((getconf_seen(CNF_LABEL_NEW_TAPES) > 0 &&
getconf_seen(CNF_AUTOLABEL) > 0) ||
(getconf_seen(CNF_LABEL_NEW_TAPES) < 0 &&
getconf_seen(CNF_AUTOLABEL) < 0)) {
conf_parserror(_("Can't specify both label-new-tapes and autolabel"));
}
if ((getconf_seen(CNF_LABEL_NEW_TAPES) != 0 &&
getconf_seen(CNF_AUTOLABEL) == 0) ||
(getconf_seen(CNF_LABEL_NEW_TAPES) < 0 &&
getconf_seen(CNF_AUTOLABEL) >= 0)) {
autolabel_t *autolabel = &(conf_data[CNF_AUTOLABEL].v.autolabel);
g_free(autolabel->template);
autolabel->template = g_strdup(getconf_str(CNF_LABEL_NEW_TAPES));
if (!autolabel->template || autolabel->template == '\0') {
g_free(autolabel->template);
autolabel->template = NULL;
autolabel->autolabel = 0;
} else {
autolabel->autolabel = AL_VOLUME_ERROR | AL_EMPTY;
}
}
if (!getconf_seen(CNF_REPORT_USE_MEDIA) &&
getconf_seen(CNF_MAX_DLE_BY_VOLUME)) {
conf_init_bool(&conf_data[CNF_REPORT_USE_MEDIA], FALSE);
}
if (!getconf_seen(CNF_REPORT_NEXT_MEDIA) &&
getconf_seen(CNF_MAX_DLE_BY_VOLUME)) {
conf_init_bool(&conf_data[CNF_REPORT_NEXT_MEDIA], FALSE);
}
labelstr = &(conf_data[CNF_LABELSTR].v.labelstr);
autolabel = &(conf_data[CNF_AUTOLABEL].v.autolabel);
if (getconf_seen(CNF_LABELSTR) && labelstr->match_autolabel &&
!getconf_seen(CNF_AUTOLABEL)) {
conf_parserror(_("AUTOLABEL not set and LABELSTR set to MATCH-AUTOLABEL"));
} else if (labelstr->match_autolabel && !getconf_seen(CNF_AUTOLABEL)) {
g_free(labelstr->template);
labelstr->template = g_strdup(".*");
labelstr->match_autolabel = FALSE;
} else if (labelstr->match_autolabel) {
g_free(labelstr->template);
labelstr->template = g_strdup(autolabel->template);
}
il = getconf_identlist(CNF_STORAGE);
if (il) {
st_name = il->data;
} else {
st_name = NULL;
}
/* create a default policy */
if (!(lookup_policy(conf_name))) {
init_policy_defaults();
pocur.name = g_strdup(conf_name);
free_val_t(&pocur.value[POLICY_COMMENT]);
val_t__str(&pocur.value[POLICY_COMMENT]) = g_strdup(_("implicit from global config"));
save_policy();
}
if (!getconf_seen(CNF_STORAGE) && (!st_name || *st_name == '\0')) {
/* create a default storage */
if (!(lookup_storage(conf_name))) {
init_storage_defaults();
stcur.name = g_strdup(conf_name);
free_val_t(&stcur.value[STORAGE_COMMENT]);
val_t__str(&stcur.value[STORAGE_COMMENT]) = g_strdup(_("implicit from global config"));
save_storage();
}
/* set the default storage */
il = g_slist_append(NULL, g_strdup(conf_name));
val_t__identlist(&conf_data[CNF_STORAGE]) = il;
}
/* Set default retention_tapes if it is not set */
for (po = policy_list; po != NULL; po = po->next) {
if (!policy_seen(po, POLICY_RETENTION_TAPES)) {
free_val_t(&po->value[POLICY_RETENTION_TAPES]);
copy_val_t(&po->value[POLICY_RETENTION_TAPES], &conf_data[CNF_TAPECYCLE]);
po->value[POLICY_RETENTION_TAPES].v.i--; // reduce by 1
}
}
/* Update many changer setting */
for (dc = changer_config_list; dc != NULL; dc = dc->next) {
char *changern = changer_config_name(dc);
if (changer_config_seen(dc, CHANGER_CONFIG_CHANGERFILE)) {
char *changerfile = changer_config_get_changerfile(dc);
char *tpchanger = changer_config_get_tpchanger(dc);
char *cf;
if ((cf = strstr(changerfile, "$t"))) {
char *new_cf = g_malloc(strlen(changerfile)+strlen(changern)-1);
int len = cf - changerfile;
strncpy(new_cf, changerfile, len);
strcpy(new_cf+len, changern);
strcpy(new_cf+len+strlen(changern), cf+2);
strncpy(new_cf+len+strlen(changern)+strlen(cf+2),"\0",1);
free_val_t(&dc->value[CHANGER_CONFIG_CHANGERFILE]);
conf_init_str(&dc->value[CHANGER_CONFIG_CHANGERFILE], new_cf);
g_free(new_cf);
}
if ((cf = strstr(tpchanger, "$t"))) {
char *new_tp = g_malloc(strlen(tpchanger)+strlen(changern)-1);
int len = cf - tpchanger;
strncpy(new_tp, tpchanger, len);
strcpy(new_tp+len, changern);
strcpy(new_tp+len+strlen(changern), cf+2);
strncpy(new_tp+len+strlen(changern)+strlen(cf+2),"\0",1);
free_val_t(&dc->value[CHANGER_CONFIG_TPCHANGER]);
conf_init_str(&dc->value[CHANGER_CONFIG_TPCHANGER], new_tp);
g_free(new_tp);
}
}
}
/* Set many storage default if they are not set */
for (st = storage_list; st != NULL; st = st->next) {
labelstr = storage_get_labelstr(st);
autolabel = storage_get_autolabel(st);
meta_autolabel = storage_get_meta_autolabel(st);
org = getconf_str(CNF_ORG);
if (storage_seen(st, STORAGE_LABELSTR) && labelstr->match_autolabel &&
!storage_seen(st, STORAGE_AUTOLABEL)) {
conf_parserror(_("AUTOLABEL not set and LABELSTR set to MATCH-AUTOLABEL"));
} else if (labelstr->match_autolabel && !storage_seen(st, STORAGE_AUTOLABEL)) {
g_free(labelstr->template);
labelstr->template = g_strdup(".*");
labelstr->match_autolabel = FALSE;
} else if (labelstr->match_autolabel) {
g_free(labelstr->template);
labelstr->template = g_strdup(autolabel->template);
}
if (meta_autolabel) {
if (strstr(meta_autolabel, "$o") && !is_valid_label(org)) {
conf_parserror("ORG must not contains space if '$0' is in meta_autolabel");
}
}
if (autolabel && autolabel->template) {
if (strstr(autolabel->template, "$o") && !is_valid_label(org)) {
conf_parserror("ORG must not contains space if '$0' is in autolabel");
}
}
if (!storage_seen(st, STORAGE_POLICY)) {
free_val_t(&st->value[STORAGE_POLICY]);
conf_init_str(&st->value[STORAGE_POLICY], conf_name);
}
if (!storage_seen(st, STORAGE_TAPEDEV)) {
free_val_t(&st->value[STORAGE_TAPEDEV]);
copy_val_t(&st->value[STORAGE_TAPEDEV], &conf_data[CNF_TAPEDEV]);
}
if (!storage_seen(st, STORAGE_TPCHANGER)) {
free_val_t(&st->value[STORAGE_TPCHANGER]);
copy_val_t(&st->value[STORAGE_TPCHANGER], &conf_data[CNF_TPCHANGER]);
}
if (!storage_seen(st, STORAGE_LABELSTR)) {
free_val_t(&st->value[STORAGE_LABELSTR]);
copy_val_t(&st->value[STORAGE_LABELSTR], &conf_data[CNF_LABELSTR]);
}
if (!storage_seen(st, STORAGE_AUTOLABEL)) {
free_val_t(&st->value[STORAGE_AUTOLABEL]);
copy_val_t(&st->value[STORAGE_AUTOLABEL], &conf_data[CNF_AUTOLABEL]);
}
if (!storage_seen(st, STORAGE_META_AUTOLABEL)) {
free_val_t(&st->value[STORAGE_META_AUTOLABEL]);
copy_val_t(&st->value[STORAGE_META_AUTOLABEL], &conf_data[CNF_META_AUTOLABEL]);
}
if (!storage_seen(st, STORAGE_RUNTAPES)) {
copy_val_t(&st->value[STORAGE_RUNTAPES], &conf_data[CNF_RUNTAPES]);
}
if (!storage_seen(st, STORAGE_TAPERSCAN)) {
free_val_t(&st->value[STORAGE_TAPERSCAN]);
copy_val_t(&st->value[STORAGE_TAPERSCAN], &conf_data[CNF_TAPERSCAN]);
}
if (!storage_seen(st, STORAGE_TAPETYPE)) {
free_val_t(&st->value[STORAGE_TAPETYPE]);
copy_val_t(&st->value[STORAGE_TAPETYPE], &conf_data[CNF_TAPETYPE]);
}
if (!storage_seen(st, STORAGE_MAX_DLE_BY_VOLUME)) {
copy_val_t(&st->value[STORAGE_MAX_DLE_BY_VOLUME], &conf_data[CNF_MAX_DLE_BY_VOLUME]);
}
if (!storage_seen(st, STORAGE_TAPERALGO)) {
copy_val_t(&st->value[STORAGE_TAPERALGO], &conf_data[CNF_TAPERALGO]);
}
if (!storage_seen(st, STORAGE_TAPER_PARALLEL_WRITE)) {
copy_val_t(&st->value[STORAGE_TAPER_PARALLEL_WRITE], &conf_data[CNF_TAPER_PARALLEL_WRITE]);
}
if (!storage_seen(st, STORAGE_EJECT_VOLUME)) {
copy_val_t(&st->value[STORAGE_EJECT_VOLUME], &conf_data[CNF_EJECT_VOLUME]);
}
if (!storage_seen(st, STORAGE_DEVICE_OUTPUT_BUFFER_SIZE)) {
copy_val_t(&st->value[STORAGE_DEVICE_OUTPUT_BUFFER_SIZE], &conf_data[CNF_DEVICE_OUTPUT_BUFFER_SIZE]);
}
if (!storage_seen(st, STORAGE_AUTOFLUSH)) {
copy_val_t(&st->value[STORAGE_AUTOFLUSH], &conf_data[CNF_AUTOFLUSH]);
}
if (!storage_seen(st, STORAGE_FLUSH_THRESHOLD_DUMPED)) {
copy_val_t(&st->value[STORAGE_FLUSH_THRESHOLD_DUMPED], &conf_data[CNF_FLUSH_THRESHOLD_DUMPED]);
}
if (!storage_seen(st, STORAGE_FLUSH_THRESHOLD_SCHEDULED)) {
copy_val_t(&st->value[STORAGE_FLUSH_THRESHOLD_SCHEDULED], &conf_data[CNF_FLUSH_THRESHOLD_SCHEDULED]);
}
if (!storage_seen(st, STORAGE_TAPERFLUSH)) {
copy_val_t(&st->value[STORAGE_TAPERFLUSH], &conf_data[CNF_TAPERFLUSH]);
}
if (!storage_seen(st, STORAGE_REPORT_USE_MEDIA)) {
copy_val_t(&st->value[STORAGE_REPORT_USE_MEDIA], &conf_data[CNF_REPORT_USE_MEDIA]);
}
if (!storage_seen(st, STORAGE_REPORT_NEXT_MEDIA)) {
copy_val_t(&st->value[STORAGE_REPORT_NEXT_MEDIA], &conf_data[CNF_REPORT_NEXT_MEDIA]);
}
if (!storage_seen(st, STORAGE_INTERACTIVITY)) {
free_val_t(&st->value[STORAGE_INTERACTIVITY]);
copy_val_t(&st->value[STORAGE_INTERACTIVITY], &conf_data[CNF_INTERACTIVITY]);
}
if (!storage_seen(st, STORAGE_TAPEPOOL)) {
free_val_t(&st->value[STORAGE_TAPEPOOL]);
conf_init_str(&st->value[STORAGE_TAPEPOOL], conf_name);
} else {
char *pool = storage_get_tapepool(st);
gboolean freepool = FALSE;
char *p;
if ((p = strstr(pool, "$o"))) {
char *org = getconf_str(CNF_ORG);
char *new_pool = g_malloc(strlen(pool)+strlen(org)-1);
int len = p - pool;
strncpy(new_pool, pool, len);
strcpy(new_pool+len, org);
strcpy(new_pool+len+strlen(org), p+2);
strncpy(new_pool+len+strlen(org)+strlen(p+2),"\0",1);
free_val_t(&st->value[STORAGE_TAPEPOOL]);
conf_init_str(&st->value[STORAGE_TAPEPOOL], new_pool);
pool = new_pool;
freepool = TRUE;
}
if ((p = strstr(pool, "$c"))) {
char *new_pool = g_malloc(strlen(pool)+strlen(conf_name)-1);
int len = p - pool;
strncpy(new_pool, pool, len);
strcpy(new_pool+len, conf_name);
strcpy(new_pool+len+strlen(conf_name), p+2);
strncpy(new_pool+len+strlen(conf_name)+strlen(p+2),"\0",1);
free_val_t(&st->value[STORAGE_TAPEPOOL]);
conf_init_str(&st->value[STORAGE_TAPEPOOL], new_pool);
if (freepool)
g_free(pool);
pool = new_pool;
freepool = TRUE;
}
if ((p = strstr(pool, "$r"))) {
char *storagen = storage_name(st);
char *new_pool = g_malloc(strlen(pool)+strlen(storagen)-1);
int len = p - pool;
strncpy(new_pool, pool, len);
strcpy(new_pool+len, storagen);
strcpy(new_pool+len+strlen(storagen), p+2);
strncpy(new_pool+len+strlen(storagen)+strlen(p+2),"\0",1);
free_val_t(&st->value[STORAGE_TAPEPOOL]);
conf_init_str(&st->value[STORAGE_TAPEPOOL], new_pool);
if (freepool)
g_free(pool);
pool = new_pool;
freepool = TRUE;
}
if (freepool) {
g_free(pool);
}
}
}
for (il = getconf_identlist(CNF_STORAGE); il != NULL; il = il->next) {
if (!lookup_storage(il->data)) {
conf_parserror(_("storage '%s' is not defined"), (char *)il->data);
}
}
// Add all storage to active-storage
for (il = getconf_identlist(CNF_STORAGE); il != NULL; il = il->next) {
identlist_t asl;
int found = FALSE;
for (asl = getconf_identlist(CNF_ACTIVE_STORAGE); asl != NULL; asl = asl->next) {
if (strcmp(il->data, asl->data) == 0) {
found = TRUE;
}
}
if (!found) {
conf_data[CNF_ACTIVE_STORAGE].v.identlist = g_slist_append(conf_data[CNF_ACTIVE_STORAGE].v.identlist, g_strdup(il->data));
}
}
for (il = getconf_identlist(CNF_ACTIVE_STORAGE); il != NULL; il = il->next) {
if (!lookup_storage(il->data)) {
conf_parserror(_("storage '%s' is not defined"), (char *)il->data);
}
}
/* Always TRUE */
conf_init_bool(&conf_data[CNF_USETIMESTAMPS], 1);
}
/* fill in the debug_* values */
debug_amandad = getconf_int(CNF_DEBUG_AMANDAD);
debug_recovery = getconf_int(CNF_DEBUG_RECOVERY);
debug_amidxtaped = getconf_int(CNF_DEBUG_AMIDXTAPED);
debug_amindexd = getconf_int(CNF_DEBUG_AMINDEXD);
debug_amrecover = getconf_int(CNF_DEBUG_AMRECOVER);
debug_auth = getconf_int(CNF_DEBUG_AUTH);
debug_event = getconf_int(CNF_DEBUG_EVENT);
debug_holding = getconf_int(CNF_DEBUG_HOLDING);
debug_protocol = getconf_int(CNF_DEBUG_PROTOCOL);
debug_planner = getconf_int(CNF_DEBUG_PLANNER);
debug_driver = getconf_int(CNF_DEBUG_DRIVER);
debug_dumper = getconf_int(CNF_DEBUG_DUMPER);
debug_chunker = getconf_int(CNF_DEBUG_CHUNKER);
debug_taper = getconf_int(CNF_DEBUG_TAPER);
debug_selfcheck = getconf_int(CNF_DEBUG_SELFCHECK);
debug_sendsize = getconf_int(CNF_DEBUG_SENDSIZE);
debug_sendbackup = getconf_int(CNF_DEBUG_SENDBACKUP);
/* And finally, display unit */
switch (getconf_str(CNF_DISPLAYUNIT)[0]) {
case 'k':
case 'K':
unit_divisor = 1;
break;
case 'm':
case 'M':
unit_divisor = 1024;
break;
case 'g':
case 'G':
unit_divisor = 1024*1024;
break;
case 't':
case 'T':
unit_divisor = 1024*1024*1024;
break;
default:
error(_("Invalid displayunit missed by validate_displayunit"));
/* NOTREACHED */
}
}
static void
conf_init_int(
val_t *val,
confunit_t unit,
int i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_INT;
val->unit = unit;
val_t__int(val) = i;
}
static void
conf_init_int64(
val_t *val,
confunit_t unit,
gint64 l)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_INT64;
val->unit = unit;
val_t__int64(val) = l;
}
static void
conf_init_real(
val_t *val,
float r)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_REAL;
val->unit = CONF_UNIT_NONE;
val_t__real(val) = r;
}
static void
conf_init_str(
val_t *val,
char *s)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_STR;
val->unit = CONF_UNIT_NONE;
if(s)
val->v.s = g_strdup(s);
else
val->v.s = NULL;
}
static void
conf_init_ident(
val_t *val,
char *s)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_IDENT;
val->unit = CONF_UNIT_NONE;
if(s)
val->v.s = g_strdup(s);
else
val->v.s = NULL;
}
static void
conf_init_identlist(
val_t *val,
char *s)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_IDENTLIST;
val->unit = CONF_UNIT_NONE;
val->v.identlist = NULL;
if (s)
val->v.identlist = g_slist_append(val->v.identlist, g_strdup(s));
}
static void
conf_init_str_list(
val_t *val,
char *s)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_STR_LIST;
val->unit = CONF_UNIT_NONE;
val->v.identlist = NULL;
if (s)
val->v.identlist = g_slist_append(val->v.identlist, g_strdup(s));
}
static void
conf_init_time(
val_t *val,
time_t t)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_TIME;
val->unit = CONF_UNIT_NONE;
val_t__time(val) = t;
}
static void
conf_init_size(
val_t *val,
confunit_t unit,
ssize_t sz)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_SIZE;
val->unit = unit;
val_t__size(val) = sz;
}
static void
conf_init_bool(
val_t *val,
int i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_BOOLEAN;
val->unit = CONF_UNIT_NONE;
val_t__boolean(val) = i;
}
static void
conf_init_no_yes_all(
val_t *val,
int i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_NO_YES_ALL;
val->unit = CONF_UNIT_NONE;
val_t__int(val) = i;
}
static void
conf_init_compress(
val_t *val,
comp_t i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_COMPRESS;
val->unit = CONF_UNIT_NONE;
val_t__compress(val) = (int)i;
}
static void
conf_init_encrypt(
val_t *val,
encrypt_t i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_ENCRYPT;
val->unit = CONF_UNIT_NONE;
val_t__encrypt(val) = (int)i;
}
static void
conf_init_part_cache_type(
val_t *val,
part_cache_type_t i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_PART_CACHE_TYPE;
val->unit = CONF_UNIT_NONE;
val_t__part_cache_type(val) = (int)i;
}
static void
conf_init_host_limit(
val_t *val)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_HOST_LIMIT;
val->unit = CONF_UNIT_NONE;
val_t__host_limit(val).match_pats = NULL;
val_t__host_limit(val).same_host = FALSE;
val_t__host_limit(val).server = FALSE;
}
static void
conf_init_host_limit_server(
val_t *val)
{
conf_init_host_limit(val);
val_t__host_limit(val).server = TRUE;
}
static void
conf_init_data_path(
val_t *val,
data_path_t i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_DATA_PATH;
val->unit = CONF_UNIT_NONE;
val_t__data_path(val) = (int)i;
}
static void
conf_init_holding(
val_t *val,
dump_holdingdisk_t i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_HOLDING;
val->unit = CONF_UNIT_NONE;
val_t__holding(val) = (int)i;
}
static void
conf_init_estimatelist(
val_t *val,
estimate_t i)
{
GSList *estimates = NULL;
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_ESTIMATELIST;
val->unit = CONF_UNIT_NONE;
estimates = g_slist_append(estimates, GINT_TO_POINTER(i));
val_t__estimatelist(val) = estimates;
}
static void
conf_init_strategy(
val_t *val,
strategy_t i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->unit = CONF_UNIT_NONE;
val->type = CONFTYPE_STRATEGY;
val_t__strategy(val) = i;
}
static void
conf_init_taperalgo(
val_t *val,
taperalgo_t i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_TAPERALGO;
val->unit = CONF_UNIT_NONE;
val_t__taperalgo(val) = i;
}
static void
conf_init_priority(
val_t *val,
int i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_PRIORITY;
val->unit = CONF_UNIT_NONE;
val_t__priority(val) = i;
}
static void
conf_init_rate(
val_t *val,
float r1,
float r2)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_RATE;
val->unit = CONF_UNIT_NONE;
val_t__rate(val)[0] = r1;
val_t__rate(val)[1] = r2;
}
static void
conf_init_exinclude(
val_t *val)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_EXINCLUDE;
val->unit = CONF_UNIT_NONE;
val_t__exinclude(val).optional = 0;
val_t__exinclude(val).sl_list = NULL;
val_t__exinclude(val).sl_file = NULL;
}
static void
conf_init_intrange(
val_t *val,
int i1,
int i2)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_INTRANGE;
val->unit = CONF_UNIT_NONE;
val_t__intrange(val)[0] = i1;
val_t__intrange(val)[1] = i2;
}
static void
conf_init_autolabel(
val_t *val) {
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_AUTOLABEL;
val->unit = CONF_UNIT_NONE;
val->v.autolabel.template = NULL;
val->v.autolabel.autolabel = 0;
}
static void
conf_init_labelstr(
val_t *val) {
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_LABELSTR;
val->unit = CONF_UNIT_NONE;
val->v.labelstr.template = NULL;
val->v.labelstr.match_autolabel = TRUE;
}
void
free_property_t(
gpointer p)
{
property_t *propery = (property_t *)p;
slist_free_full(propery->values, g_free);
amfree(propery);
}
static void
conf_init_proplist(
val_t *val)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_PROPLIST;
val->unit = CONF_UNIT_NONE;
val_t__proplist(val) =
g_hash_table_new_full(g_str_amanda_hash, g_str_amanda_equal,
&g_free, &free_property_t);
}
static void
conf_init_execute_on(
val_t *val,
int i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_EXECUTE_ON;
val->unit = CONF_UNIT_NONE;
val->v.i = i;
}
static void
conf_init_execute_where(
val_t *val,
int i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_EXECUTE_WHERE;
val->unit = CONF_UNIT_NONE;
val->v.i = i;
}
static void
conf_init_send_amreport(
val_t *val,
send_amreport_t i)
{
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_SEND_AMREPORT_ON;
val->unit = CONF_UNIT_NONE;
val->v.i = i;
}
static void conf_init_application(val_t *val) {
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_APPLICATION;
val->unit = CONF_UNIT_NONE;
val->v.s = NULL;
}
static void conf_init_dump_selection(val_t *val) {
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_DUMP_SELECTION;
val->unit = CONF_UNIT_NONE;
val->v.dump_selection = NULL;
}
static void conf_init_vault_list(val_t *val) {
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
val->type = CONFTYPE_VAULT_LIST;
val->unit = CONF_UNIT_NONE;
val->v.vault_list = NULL;
}
/*
* Config access implementation
*/
val_t *
getconf(confparm_key key)
{
assert(key < CNF_CNF);
return &conf_data[key];
}
GSList *
getconf_list(
char *listname)
{
tapetype_t *tp;
dumptype_t *dp;
interface_t *ip;
holdingdisk_t *hd;
GSList *hp;
application_t *ap;
pp_script_t *pp;
device_config_t *dc;
changer_config_t *cc;
interactivity_t *iv;
taperscan_t *ts;
policy_s *po;
storage_t *st;
GSList *rv = NULL;
if (strcasecmp(listname,"tapetype") == 0) {
for(tp = tapelist; tp != NULL; tp=tp->next) {
rv = g_slist_append(rv, tp->name);
}
} else if (strcasecmp(listname,"dumptype") == 0) {
for(dp = dumplist; dp != NULL; dp=dp->next) {
rv = g_slist_append(rv, dp->name);
}
} else if (strcasecmp(listname,"holdingdisk") == 0) {
for(hp = holdinglist; hp != NULL; hp=hp->next) {
hd = hp->data;
rv = g_slist_append(rv, hd->name);
}
} else if (strcasecmp(listname,"interface") == 0) {
for(ip = interface_list; ip != NULL; ip=ip->next) {
rv = g_slist_append(rv, ip->name);
}
} else if (strcasecmp(listname,"application_tool") == 0
|| strcasecmp(listname,"application-tool") == 0
|| strcasecmp(listname,"application") == 0) {
for(ap = application_list; ap != NULL; ap=ap->next) {
rv = g_slist_append(rv, ap->name);
}
} else if (strcasecmp(listname,"script_tool") == 0
|| strcasecmp(listname,"script-tool") == 0
|| strcasecmp(listname,"script") == 0) {
for(pp = pp_script_list; pp != NULL; pp=pp->next) {
rv = g_slist_append(rv, pp->name);
}
} else if (strcasecmp(listname,"device") == 0) {
for(dc = device_config_list; dc != NULL; dc=dc->next) {
rv = g_slist_append(rv, dc->name);
}
} else if (strcasecmp(listname,"changer") == 0) {
for(cc = changer_config_list; cc != NULL; cc=cc->next) {
rv = g_slist_append(rv, cc->name);
}
} else if (strcasecmp(listname,"interactivity") == 0) {
for(iv = interactivity_list; iv != NULL; iv=iv->next) {
rv = g_slist_append(rv, iv->name);
}
} else if (strcasecmp(listname,"taperscan") == 0) {
for(ts = taperscan_list; ts != NULL; ts=ts->next) {
rv = g_slist_append(rv, ts->name);
}
} else if (strcasecmp(listname,"policy") == 0) {
for(po = policy_list; po != NULL; po=po->next) {
rv = g_slist_append(rv, po->name);
}
} else if (strcasecmp(listname,"storage") == 0) {
for(st = storage_list; st != NULL; st=st->next) {
rv = g_slist_append(rv, st->name);
}
}
return rv;
}
val_t *
getconf_byname(
char *key)
{
val_t *rv = NULL;
if (!parm_key_info(key, NULL, &rv))
return NULL;
return rv;
}
char *
confparm_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = server_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
tapetype_t *
lookup_tapetype(
char *str)
{
tapetype_t *p;
for(p = tapelist; p != NULL; p = p->next) {
if(strcasecmp(p->name, str) == 0) return p;
}
return NULL;
}
val_t *
tapetype_getconf(
tapetype_t *ttyp,
tapetype_key key)
{
assert(ttyp != NULL);
assert(key < TAPETYPE_TAPETYPE);
return &ttyp->value[key];
}
static void
validate_program(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
if (!g_str_equal(val->v.s, "DUMP") &&
!g_str_equal(val->v.s, "GNUTAR") &&
!g_str_equal(val->v.s, "STAR") &&
!g_str_equal(val->v.s, "APPLICATION"))
conf_parserror("program must be \"DUMP\", \"GNUTAR\", \"STAR\" or \"APPLICATION\"");
}
static void
validate_dump_limit(
conf_var_t *np G_GNUC_UNUSED,
val_t *val)
{
if (val->v.host_limit.match_pats) {
conf_parserror("dump-limit can't specify hostname");
}
}
char *
tapetype_name(
tapetype_t *ttyp)
{
assert(ttyp != NULL);
return ttyp->name;
}
char *
tapetype_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = tapetype_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
dumptype_t *
lookup_dumptype(
char *str)
{
dumptype_t *p;
for(p = dumplist; p != NULL; p = p->next) {
if(strcasecmp(p->name, str) == 0) return p;
}
return NULL;
}
val_t *
dumptype_getconf(
dumptype_t *dtyp,
dumptype_key key)
{
assert(dtyp != NULL);
assert(key < DUMPTYPE_DUMPTYPE);
return &dtyp->value[key];
}
char *
dumptype_name(
dumptype_t *dtyp)
{
assert(dtyp != NULL);
return dtyp->name;
}
char *
dumptype_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = dumptype_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
interface_t *
lookup_interface(
char *str)
{
interface_t *p;
for(p = interface_list; p != NULL; p = p->next) {
if(strcasecmp(p->name, str) == 0) return p;
}
return NULL;
}
val_t *
interface_getconf(
interface_t *iface,
interface_key key)
{
assert(iface != NULL);
assert(key < INTER_INTER);
return &iface->value[key];
}
char *
interface_name(
interface_t *iface)
{
assert(iface != NULL);
return iface->name;
}
char *
interface_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = interface_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
holdingdisk_t *
lookup_holdingdisk(
char *str)
{
GSList *hp;
holdingdisk_t *hd;
for (hp = holdinglist; hp != NULL; hp = hp->next) {
hd = hp->data;
if (strcasecmp(hd->name, str) == 0) return hd;
}
return NULL;
}
GSList *
getconf_holdingdisks(
void)
{
return holdinglist;
}
val_t *
holdingdisk_getconf(
holdingdisk_t *hdisk,
holdingdisk_key key)
{
assert(hdisk != NULL);
assert(key < HOLDING_HOLDING);
return &hdisk->value[key];
}
char *
holdingdisk_name(
holdingdisk_t *hdisk)
{
assert(hdisk != NULL);
return hdisk->name;
}
char *
holdingdisk_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = holding_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
application_t *
lookup_application(
char *str)
{
application_t *p;
for(p = application_list; p != NULL; p = p->next) {
if(strcasecmp(p->name, str) == 0) return p;
}
return NULL;
}
val_t *
application_getconf(
application_t *ap,
application_key key)
{
assert(ap != NULL);
assert(key < APPLICATION_APPLICATION);
return &ap->value[key];
}
char *
application_name(
application_t *ap)
{
assert(ap != NULL);
return ap->name;
}
char *
application_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = application_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
interactivity_t *
lookup_interactivity(
char *str)
{
interactivity_t *p;
for(p = interactivity_list; p != NULL; p = p->next) {
if(strcasecmp(p->name, str) == 0) return p;
}
return NULL;
}
val_t *
interactivity_getconf(
interactivity_t *iv,
interactivity_key key)
{
assert(iv != NULL);
assert(key < INTERACTIVITY_INTERACTIVITY);
return &iv->value[key];
}
char *
interactivity_name(
interactivity_t *iv)
{
assert(iv != NULL);
return iv->name;
}
char *
interactivity_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = interactivity_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
taperscan_t *
lookup_taperscan(
char *str)
{
taperscan_t *p;
for(p = taperscan_list; p != NULL; p = p->next) {
if(strcasecmp(p->name, str) == 0) return p;
}
return NULL;
}
val_t *
taperscan_getconf(
taperscan_t *ts,
taperscan_key key)
{
assert(ts != NULL);
assert(key < TAPERSCAN_TAPERSCAN);
return &ts->value[key];
}
char *
taperscan_name(
taperscan_t *ts)
{
assert(ts != NULL);
return ts->name;
}
char *
taperscan_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = taperscan_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
policy_s *
lookup_policy(
char *str)
{
policy_s *p;
for(p = policy_list; p != NULL; p = p->next) {
if(strcasecmp(p->name, str) == 0) return p;
}
return NULL;
}
val_t *
policy_getconf(
policy_s *po,
policy_key key)
{
assert(po != NULL);
assert(key < POLICY_POLICY);
return &po->value[key];
}
char *
policy_name(
policy_s *po)
{
assert(po != NULL);
return po->name;
}
char *
policy_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = policy_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
storage_t *
get_first_storage(void)
{
return storage_list;
}
storage_t *
get_next_storage(storage_t *st)
{
return st->next;
}
char **
get_storage_list(void)
{
int count = 0;
storage_t *p;
char **result;
char **r;
for(p = storage_list; p != NULL; p = p->next) {
count++;
};
result = g_new0(char *, count+1);
for (r = result, p = storage_list; p != NULL; p = p->next, r++) {
*r = g_strdup(p->name);
}
*r = NULL;
return result;
}
storage_t *
lookup_storage(
char *str)
{
storage_t *p;
for(p = storage_list; p != NULL; p = p->next) {
if(strcasecmp(p->name, str) == 0) return p;
}
return NULL;
}
val_t *
storage_getconf(
storage_t *st,
storage_key key)
{
assert(st != NULL);
assert(key < STORAGE_STORAGE);
return &st->value[key];
}
char *
storage_name(
storage_t *st)
{
assert(st != NULL);
return st->name;
}
char *
storage_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = storage_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
pp_script_t *
lookup_pp_script(
char *str)
{
pp_script_t *pps;
for(pps = pp_script_list; pps != NULL; pps = pps->next) {
if(strcasecmp(pps->name, str) == 0) return pps;
}
return NULL;
}
val_t *
pp_script_getconf(
pp_script_t *pps,
pp_script_key key)
{
assert(pps != NULL);
assert(key < PP_SCRIPT_PP_SCRIPT);
return &pps->value[key];
}
char *
pp_script_name(
pp_script_t *pps)
{
assert(pps != NULL);
return pps->name;
}
char *
pp_script_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = pp_script_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
device_config_t *
lookup_device_config(
char *str)
{
device_config_t *devconf;
for(devconf = device_config_list; devconf != NULL; devconf = devconf->next) {
if(strcasecmp(devconf->name, str) == 0) return devconf;
}
return NULL;
}
val_t *
device_config_getconf(
device_config_t *devconf,
device_config_key key)
{
assert(devconf != NULL);
assert(key < DEVICE_CONFIG_DEVICE_CONFIG);
return &devconf->value[key];
}
char *
device_config_name(
device_config_t *devconf)
{
assert(devconf != NULL);
return devconf->name;
}
char *
device_config_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = device_config_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
char **
get_changer_list(void)
{
int count = 0;
changer_config_t *p;
char **result;
char **r;
for(p = changer_config_list; p != NULL; p = p->next) {
count++;
};
result = g_new0(char *, count+1);
for (r = result, p = changer_config_list; p != NULL; p = p->next, r++) {
*r = g_strdup(p->name);
}
*r = NULL;
return result;
}
changer_config_t *
lookup_changer_config(
char *str)
{
changer_config_t *devconf;
for(devconf = changer_config_list; devconf != NULL; devconf = devconf->next) {
if(strcasecmp(devconf->name, str) == 0) return devconf;
}
return NULL;
}
val_t *
changer_config_getconf(
changer_config_t *devconf,
changer_config_key key)
{
assert(devconf != NULL);
assert(key < CHANGER_CONFIG_CHANGER_CONFIG);
return &devconf->value[key];
}
char *
changer_config_name(
changer_config_t *devconf)
{
assert(devconf != NULL);
return devconf->name;
}
char *
changer_config_key_to_name(
int parm)
{
conf_var_t *np;
keytab_t *kt;
for (np = changer_config_var; np->token != CONF_UNKNOWN; np++) {
if (np->parm == parm) {
for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if (kt->token == np->token) {
return kt->keyword;
}
}
}
}
return NULL;
}
long int
getconf_unit_divisor(void)
{
return unit_divisor;
}
/*
* Command-line Handling Implementation
*/
config_overrides_t *
new_config_overrides(
int size_estimate)
{
config_overrides_t *co;
if (size_estimate <= 0)
size_estimate = 10;
co = g_malloc(sizeof(*co));
co->ovr = g_malloc(sizeof(*co->ovr) * size_estimate);
co->n_allocated = size_estimate;
co->n_used = 0;
return co;
}
void
free_config_overrides(
config_overrides_t *co)
{
int i;
if (!co) return;
for (i = 0; i < co->n_used; i++) {
amfree(co->ovr[i].key);
amfree(co->ovr[i].value);
}
amfree(co->ovr);
amfree(co);
}
void add_config_override(
config_overrides_t *co,
char *key,
char *value)
{
/* reallocate if necessary */
if (co->n_used == co->n_allocated) {
co->n_allocated *= 2;
co->ovr = realloc(co->ovr, co->n_allocated * sizeof(*co->ovr));
if (!co->ovr) {
error(_("Cannot realloc; out of memory"));
/* NOTREACHED */
}
}
co->ovr[co->n_used].key = g_strdup(key);
co->ovr[co->n_used].value = g_strdup(value);
co->n_used++;
}
void
add_config_override_opt(
config_overrides_t *co,
char *optarg)
{
char *value;
assert(optarg != NULL);
value = strchr(optarg, '=');
if (value == NULL) {
error(_("Must specify a value for %s."), optarg);
/* NOTREACHED */
}
*value = '\0';
add_config_override(co, optarg, value+1);
*value = '=';
}
config_overrides_t *
extract_commandline_config_overrides(
int *argc,
char ***argv)
{
int i, j, moveup;
config_overrides_t *co = new_config_overrides(*argc/2);
i = 0;
while (i<*argc) {
if(g_str_has_prefix((*argv)[i], "-o")) {
if(strlen((*argv)[i]) > 2) {
add_config_override_opt(co, (*argv)[i]+2);
moveup = 1;
}
else {
if (i+1 >= *argc) error(_("expect something after -o"));
add_config_override_opt(co, (*argv)[i+1]);
moveup = 2;
}
/* move up remaining argment array */
for (j = i; j+moveup<*argc; j++) {
(*argv)[j] = (*argv)[j+moveup];
}
*argc -= moveup;
} else {
i++;
}
}
return co;
}
void
set_config_overrides(
config_overrides_t *co)
{
int i;
config_overrides = co;
for (i = 0; i < co->n_used; i++) {
g_debug("config_overrides: %s %s", co->ovr[i].key, co->ovr[i].value);
}
return;
}
static cfgerr_level_t
apply_config_overrides(
config_overrides_t *co,
char *key_ovr)
{
int i;
if(!co) return cfgerr_level;
assert(keytable != NULL);
assert(parsetable != NULL);
for (i = 0; i < co->n_used; i++) {
char *key = co->ovr[i].key;
char *value = co->ovr[i].value;
val_t *key_val;
conf_var_t *key_parm;
if (key_ovr && strncasecmp(key_ovr, key, strlen(key_ovr)) != 0) {
continue;
}
if (!parm_key_info(key, &key_parm, &key_val)) {
/* not an error, only default config is loaded */
continue;
}
/* now set up a fake line and use the relevant read_function to
* parse it. This is sneaky! */
if (key_parm->type == CONFTYPE_STR) {
current_line = quote_string_always(value);
} else {
current_line = g_strdup(value);
}
current_char = current_line;
token_pushed = 0;
current_line_num = -2;
allow_overwrites = 1;
co->ovr[i].applied = TRUE;
key_parm->read_function(key_parm, key_val);
if ((key_parm)->validate_function)
key_parm->validate_function(key_parm, key_val);
amfree(current_line);
current_char = NULL;
token_pushed = 0;
}
return cfgerr_level;
}
/*
* val_t Management Implementation
*/
int
val_t_to_int(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_INT) {
error(_("val_t_to_int: val.type is not CONFTYPE_INT"));
/*NOTREACHED*/
}
return val_t__int(val);
}
gint64
val_t_to_int64(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_INT64) {
error(_("val_t_to_int64: val.type is not CONFTYPE_INT64"));
/*NOTREACHED*/
}
return val_t__int64(val);
}
float
val_t_to_real(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_REAL) {
error(_("val_t_to_real: val.type is not CONFTYPE_REAL"));
/*NOTREACHED*/
}
return val_t__real(val);
}
char *
val_t_to_str(
val_t *val)
{
assert(config_initialized);
/* support CONFTYPE_IDENT, too */
if (val->type != CONFTYPE_STR && val->type != CONFTYPE_IDENT) {
error(_("val_t_to_str: val.type is not CONFTYPE_STR nor CONFTYPE_IDENT"));
/*NOTREACHED*/
}
return val_t__str(val);
}
char *
val_t_to_ident(
val_t *val)
{
assert(config_initialized);
/* support CONFTYPE_STR, too */
if (val->type != CONFTYPE_STR && val->type != CONFTYPE_IDENT) {
error(_("val_t_to_ident: val.type is not CONFTYPE_IDENT nor CONFTYPE_STR"));
/*NOTREACHED*/
}
return val_t__str(val);
}
identlist_t
val_t_to_identlist(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_IDENTLIST) {
error(_("val_t_to_ident: val.type is not CONFTYPE_IDENTLIST"));
/*NOTREACHED*/
}
return val_t__identlist(val);
}
identlist_t
val_t_to_str_list(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_STR_LIST) {
error(_("val_t_to_ident: val.type is not CONFTYPE_STR_LIST"));
/*NOTREACHED*/
}
return val_t__identlist(val);
}
time_t
val_t_to_time(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_TIME) {
error(_("val_t_to_time: val.type is not CONFTYPE_TIME"));
/*NOTREACHED*/
}
return val_t__time(val);
}
ssize_t
val_t_to_size(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_SIZE) {
error(_("val_t_to_size: val.type is not CONFTYPE_SIZE"));
/*NOTREACHED*/
}
return val_t__size(val);
}
int
val_t_to_boolean(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_BOOLEAN) {
error(_("val_t_to_bool: val.type is not CONFTYPE_BOOLEAN"));
/*NOTREACHED*/
}
return val_t__boolean(val);
}
int
val_t_to_no_yes_all(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_NO_YES_ALL) {
error(_("val_t_to_no_yes_all: val.type is not CONFTYPE_NO_YES_ALL"));
/*NOTREACHED*/
}
return val_t__no_yes_all(val);
}
comp_t
val_t_to_compress(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_COMPRESS) {
error(_("val_t_to_compress: val.type is not CONFTYPE_COMPRESS"));
/*NOTREACHED*/
}
return val_t__compress(val);
}
encrypt_t
val_t_to_encrypt(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_ENCRYPT) {
error(_("val_t_to_encrypt: val.type is not CONFTYPE_ENCRYPT"));
/*NOTREACHED*/
}
return val_t__encrypt(val);
}
part_cache_type_t
val_t_to_part_cache_type(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_PART_CACHE_TYPE) {
error(_("val_t_to_part_cache_type: val.type is not CONFTYPE_PART_CACHE_TYPE"));
/*NOTREACHED*/
}
return val_t__part_cache_type(val);
}
host_limit_t *
val_t_to_host_limit(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_HOST_LIMIT) {
error(_("val_t_to_host_limit: val.type is not CONFTYPE_HOST_LIMIT"));
/*NOTREACHED*/
}
return &val_t__host_limit(val);
}
dump_selection_list_t
val_t_to_dump_selection(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_DUMP_SELECTION) {
error(_("val_t_to_dump_selection: val.type is not CONFTYPE_DUMP_SELECTION"));
/*NOTREACHED*/
}
return val_t__dump_selection(val);
}
vault_list_t
val_t_to_vault_list(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_VAULT_LIST) {
error(_("val_t_to_vault_list: val.type is not CONFTYPE_VAULT_LIST"));
/*NOTREACHED*/
}
return val_t__vault_list(val);
}
dump_holdingdisk_t
val_t_to_holding(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_HOLDING) {
error(_("val_t_to_hold: val.type is not CONFTYPE_HOLDING"));
/*NOTREACHED*/
}
return val_t__holding(val);
}
estimatelist_t
val_t_to_estimatelist(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_ESTIMATELIST) {
error(_("val_t_to_estimatelist: val.type is not CONFTYPE_ESTIMATELIST"));
/*NOTREACHED*/
}
return val_t__estimatelist(val);
}
strategy_t
val_t_to_strategy(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_STRATEGY) {
error(_("val_t_to_strategy: val.type is not CONFTYPE_STRATEGY"));
/*NOTREACHED*/
}
return val_t__strategy(val);
}
taperalgo_t
val_t_to_taperalgo(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_TAPERALGO) {
error(_("val_t_to_taperalgo: val.type is not CONFTYPE_TAPERALGO"));
/*NOTREACHED*/
}
return val_t__taperalgo(val);
}
send_amreport_t
val_t_to_send_amreport(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_SEND_AMREPORT_ON) {
error(_("val_t_to_send_amreport: val.type is not CONFTYPE_SEND_AMREPORT_ON"));
/*NOTREACHED*/
}
return val_t__send_amreport(val);
}
data_path_t
val_t_to_data_path(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_DATA_PATH) {
error(_("val_t_to_data_path: val.type is not CONFTYPE_DATA_PATH"));
/*NOTREACHED*/
}
return val_t__data_path(val);
}
int
val_t_to_priority(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_PRIORITY) {
error(_("val_t_to_priority: val.type is not CONFTYPE_PRIORITY"));
/*NOTREACHED*/
}
return val_t__priority(val);
}
float *
val_t_to_rate(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_RATE) {
error(_("val_t_to_rate: val.type is not CONFTYPE_RATE"));
/*NOTREACHED*/
}
return val_t__rate(val);
}
exinclude_t
val_t_to_exinclude(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_EXINCLUDE) {
error(_("val_t_to_exinclude: val.type is not CONFTYPE_EXINCLUDE"));
/*NOTREACHED*/
}
return val_t__exinclude(val);
}
int *
val_t_to_intrange(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_INTRANGE) {
error(_("val_t_to_intrange: val.type is not CONFTYPE_INTRANGE"));
/*NOTREACHED*/
}
return val_t__intrange(val);
}
proplist_t
val_t_to_proplist(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_PROPLIST) {
error(_("val_t_to_proplist: val.type is not CONFTYPE_PROPLIST"));
/*NOTREACHED*/
}
return val_t__proplist(val);
}
autolabel_t *
val_t_to_autolabel(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_AUTOLABEL) {
error(_("val_t_to_autolabel: val.type is not CONFTYPE_AUTOLABEL"));
/*NOTREACHED*/
}
return val_t__autolabel(val);
}
labelstr_s *
val_t_to_labelstr(
val_t *val)
{
assert(config_initialized);
if (val->type != CONFTYPE_LABELSTR) {
error(_("val_t_to_labelstr: val.type is not CONFTYPE_LABELSTR"));
/*NOTREACHED*/
}
return val_t__labelstr(val);
}
static void
merge_val_t(
val_t *valdst,
val_t *valsrc)
{
if (valsrc->type == CONFTYPE_PROPLIST) {
if (valsrc->v.proplist) {
if (valdst->v.proplist == NULL ||
g_hash_table_size(valdst->v.proplist) == 0) {
valdst->seen.block = current_block;
valdst->seen.filename = current_filename;
valdst->seen.linenum = current_line_num;
}
if (valdst->v.proplist == NULL) {
valdst->v.proplist = g_hash_table_new_full(g_str_amanda_hash,
g_str_amanda_equal,
&g_free,
&free_property_t);
g_hash_table_foreach(valsrc->v.proplist,
©_proplist_foreach_fn,
valdst->v.proplist);
} else {
g_hash_table_foreach(valsrc->v.proplist,
&merge_proplist_foreach_fn,
valdst->v.proplist);
}
}
} else if (valsrc->type == CONFTYPE_IDENTLIST ||
valsrc->type == CONFTYPE_STR_LIST) {
if (valsrc->v.identlist) {
identlist_t il;
for (il = valsrc->v.identlist; il != NULL; il = il->next) {
valdst->v.identlist = g_slist_append(valdst->v.identlist,
g_strdup((char *)il->data));
}
}
} else {
free_val_t(valdst);
copy_val_t(valdst, valsrc);
}
}
static void
copy_val_t(
val_t *valdst,
val_t *valsrc)
{
GSList *ia;
valdst->type = valsrc->type;
valdst->seen = valsrc->seen;
switch(valsrc->type) {
case CONFTYPE_INT:
case CONFTYPE_BOOLEAN:
case CONFTYPE_NO_YES_ALL:
case CONFTYPE_COMPRESS:
case CONFTYPE_ENCRYPT:
case CONFTYPE_HOLDING:
case CONFTYPE_EXECUTE_ON:
case CONFTYPE_EXECUTE_WHERE:
case CONFTYPE_SEND_AMREPORT_ON:
case CONFTYPE_DATA_PATH:
case CONFTYPE_STRATEGY:
case CONFTYPE_TAPERALGO:
case CONFTYPE_PRIORITY:
case CONFTYPE_PART_CACHE_TYPE:
valdst->v.i = valsrc->v.i;
break;
case CONFTYPE_SIZE:
valdst->v.size = valsrc->v.size;
break;
case CONFTYPE_INT64:
valdst->v.int64 = valsrc->v.int64;
break;
case CONFTYPE_REAL:
valdst->v.r = valsrc->v.r;
break;
case CONFTYPE_RATE:
valdst->v.rate[0] = valsrc->v.rate[0];
valdst->v.rate[1] = valsrc->v.rate[1];
break;
case CONFTYPE_IDENT:
case CONFTYPE_STR:
valdst->v.s = g_strdup(valsrc->v.s);
break;
case CONFTYPE_IDENTLIST:
case CONFTYPE_STR_LIST:
valdst->v.identlist = NULL;
for (ia = valsrc->v.identlist; ia != NULL; ia = ia->next) {
valdst->v.identlist = g_slist_append(valdst->v.identlist,
g_strdup(ia->data));
}
break;
case CONFTYPE_HOST_LIMIT:
valdst->v.host_limit = valsrc->v.host_limit;
valdst->v.host_limit.match_pats = NULL;
for (ia = valsrc->v.host_limit.match_pats; ia != NULL; ia = ia->next) {
valdst->v.host_limit.match_pats =
g_slist_append(valdst->v.host_limit.match_pats, g_strdup(ia->data));
}
break;
case CONFTYPE_TIME:
valdst->v.t = valsrc->v.t;
break;
case CONFTYPE_ESTIMATELIST: {
estimatelist_t estimates = valsrc->v.estimatelist;
estimatelist_t dst_estimates = NULL;
while (estimates != NULL) {
dst_estimates = g_slist_append(dst_estimates, estimates->data);
estimates = estimates->next;
}
valdst->v.estimatelist = dst_estimates;
break;
}
case CONFTYPE_EXINCLUDE:
valdst->v.exinclude.optional = valsrc->v.exinclude.optional;
valdst->v.exinclude.sl_list = duplicate_sl(valsrc->v.exinclude.sl_list);
valdst->v.exinclude.sl_file = duplicate_sl(valsrc->v.exinclude.sl_file);
break;
case CONFTYPE_INTRANGE:
valdst->v.intrange[0] = valsrc->v.intrange[0];
valdst->v.intrange[1] = valsrc->v.intrange[1];
break;
case CONFTYPE_PROPLIST:
if (valsrc->v.proplist) {
valdst->v.proplist = g_hash_table_new_full(g_str_amanda_hash,
g_str_amanda_equal,
&g_free,
&free_property_t);
g_hash_table_foreach(valsrc->v.proplist,
©_proplist_foreach_fn,
valdst->v.proplist);
} else {
valdst->v.proplist = NULL;
}
break;
case CONFTYPE_APPLICATION:
valdst->v.s = g_strdup(valsrc->v.s);
break;
case CONFTYPE_AUTOLABEL:
valdst->v.autolabel.template = g_strdup(valsrc->v.autolabel.template);
valdst->v.autolabel.autolabel = valsrc->v.autolabel.autolabel;
break;
case CONFTYPE_LABELSTR:
valdst->v.labelstr.template = g_strdup(valsrc->v.labelstr.template);
valdst->v.labelstr.match_autolabel = valsrc->v.labelstr.match_autolabel;
break;
case CONFTYPE_DUMP_SELECTION:
valdst->v.dump_selection= NULL;
for (ia = valsrc->v.dump_selection; ia != NULL; ia = ia->next) {
dump_selection_t *src_dump_s = ia->data;
dump_selection_t *dst_dump_s = g_new0(dump_selection_t, 1);
dst_dump_s->tag_type = src_dump_s->tag_type;
dst_dump_s->tag = g_strdup(src_dump_s->tag);
dst_dump_s->level = src_dump_s->level;
valdst->v.dump_selection =
g_slist_append(valdst->v.dump_selection, dst_dump_s);
}
break;
case CONFTYPE_VAULT_LIST:
valdst->v.vault_list= NULL;
for (ia = valsrc->v.vault_list; ia != NULL; ia = ia->next) {
vault_el_t *src_vault_s = ia->data;
vault_el_t *dst_vault_s = g_new0(vault_el_t, 1);
dst_vault_s->storage = g_strdup(src_vault_s->storage);
dst_vault_s->days = src_vault_s->days;
valdst->v.vault_list =
g_slist_append(valdst->v.vault_list, dst_vault_s);
}
break;
}
}
static void
merge_proplist_foreach_fn(
gpointer key_p,
gpointer value_p,
gpointer user_data_p)
{
char *property_s = key_p;
property_t *property = value_p;
proplist_t proplist = user_data_p;
GSList *elem = NULL;
int new_prop = 0;
property_t *new_property = g_hash_table_lookup(proplist, property_s);
if (new_property && !property->append) {
g_hash_table_remove(proplist, property_s);
new_property = NULL;
}
if (!new_property) {
new_property = malloc(sizeof(property_t));
new_property->seen = property->seen;
new_property->append = property->append;
new_property->visible = property->visible;
new_property->priority = property->priority;
new_property->values = NULL;
new_prop = 1;
}
for(elem = property->values;elem != NULL; elem=elem->next) {
new_property->values = g_slist_append(new_property->values,
g_strdup(elem->data));
}
if (new_prop)
g_hash_table_insert(proplist, g_strdup(property_s), new_property);
}
static void
copy_proplist_foreach_fn(
gpointer key_p,
gpointer value_p,
gpointer user_data_p)
{
char *property_s = key_p;
property_t *property = value_p;
proplist_t proplist = user_data_p;
GSList *elem = NULL;
property_t *new_property = malloc(sizeof(property_t));
new_property->append = property->append;
new_property->visible = property->visible;
new_property->priority = property->priority;
new_property->seen = property->seen;
new_property->values = NULL;
for(elem = property->values;elem != NULL; elem=elem->next) {
new_property->values = g_slist_append(new_property->values,
g_strdup(elem->data));
}
g_hash_table_insert(proplist, g_strdup(property_s), new_property);
}
static void
free_dump_selection(
gpointer p)
{
dump_selection_t *dump_s = p;
g_free(dump_s->tag);
g_free(dump_s);
}
static void
free_vault(
gpointer p)
{
vault_el_t *vault_s = p;
g_free(vault_s->storage);
}
static void
free_val_t(
val_t *val)
{
switch(val->type) {
case CONFTYPE_INT:
case CONFTYPE_BOOLEAN:
case CONFTYPE_NO_YES_ALL:
case CONFTYPE_COMPRESS:
case CONFTYPE_ENCRYPT:
case CONFTYPE_HOLDING:
case CONFTYPE_EXECUTE_WHERE:
case CONFTYPE_EXECUTE_ON:
case CONFTYPE_SEND_AMREPORT_ON:
case CONFTYPE_DATA_PATH:
case CONFTYPE_STRATEGY:
case CONFTYPE_SIZE:
case CONFTYPE_TAPERALGO:
case CONFTYPE_PRIORITY:
case CONFTYPE_INT64:
case CONFTYPE_REAL:
case CONFTYPE_RATE:
case CONFTYPE_INTRANGE:
case CONFTYPE_PART_CACHE_TYPE:
break;
case CONFTYPE_IDENT:
case CONFTYPE_STR:
case CONFTYPE_APPLICATION:
amfree(val->v.s);
break;
case CONFTYPE_IDENTLIST:
case CONFTYPE_STR_LIST:
slist_free_full(val->v.identlist, g_free);
break;
case CONFTYPE_HOST_LIMIT:
slist_free_full(val->v.host_limit.match_pats, g_free);
break;
case CONFTYPE_TIME:
break;
case CONFTYPE_ESTIMATELIST:
g_slist_free(val->v.estimatelist);
break;
case CONFTYPE_EXINCLUDE:
free_sl(val_t__exinclude(val).sl_list);
free_sl(val_t__exinclude(val).sl_file);
break;
case CONFTYPE_PROPLIST:
g_hash_table_destroy(val_t__proplist(val));
break;
case CONFTYPE_AUTOLABEL:
amfree(val->v.autolabel.template);
break;
case CONFTYPE_LABELSTR:
amfree(val->v.labelstr.template);
break;
case CONFTYPE_DUMP_SELECTION:
slist_free_full(val->v.dump_selection, free_dump_selection);
break;
case CONFTYPE_VAULT_LIST:
slist_free_full(val->v.vault_list, free_vault);
break;
}
val->seen.linenum = 0;
val->seen.filename = NULL;
val->seen.block = NULL;
}
/*
* Utilities Implementation
*/
char *
generic_get_security_conf(
char *string,
void *arg G_GNUC_UNUSED)
{
char *result = NULL;
if(!string || !*string)
return(NULL);
if (g_str_equal(string, "krb5principal")) {
result = getconf_str(CNF_KRB5PRINCIPAL);
} else if (g_str_equal(string, "krb5keytab")) {
result = getconf_str(CNF_KRB5KEYTAB);
}
if (result && strlen(result) == 0)
result = NULL;
return(result);
}
char *
generic_client_get_security_conf(
char *string,
void *arg G_GNUC_UNUSED)
{
char *result = NULL;
if(!string || !*string)
return(NULL);
if (g_str_equal(string, "conf")) {
result = getconf_str(CNF_CONF);
} else if (g_str_equal(string, "amdump_server")) {
result = getconf_str(CNF_AMDUMP_SERVER);
} else if (g_str_equal(string, "index_server")) {
result = getconf_str(CNF_INDEX_SERVER);
} else if (g_str_equal(string, "tape_server")) {
result = getconf_str(CNF_TAPE_SERVER);
} else if (g_str_equal(string, "tapedev")) {
result = getconf_str(CNF_TAPEDEV);
} else if (g_str_equal(string, "auth")) {
result = getconf_str(CNF_AUTH);
} else if (g_str_equal(string, "ssh_keys")) {
result = getconf_str(CNF_SSH_KEYS);
} else if (g_str_equal(string, "amandad_path")) {
result = getconf_str(CNF_AMANDAD_PATH);
} else if (g_str_equal(string, "client_username")) {
result = getconf_str(CNF_CLIENT_USERNAME);
} else if (g_str_equal(string, "client_port")) {
result = getconf_str(CNF_CLIENT_PORT);
} else if (g_str_equal(string, "gnutar_list_dir")) {
result = getconf_str(CNF_GNUTAR_LIST_DIR);
} else if (g_str_equal(string, "amandates")) {
result = getconf_str(CNF_AMANDATES);
} else if (g_str_equal(string, "krb5principal")) {
result = getconf_str(CNF_KRB5PRINCIPAL);
} else if (g_str_equal(string, "krb5keytab")) {
result = getconf_str(CNF_KRB5KEYTAB);
} else if (g_str_equal(string, "ssl_dir")) {
result = getconf_str(CNF_SSL_DIR);
} else if (g_str_equal(string, "ssl_fingerprint_file")) {
result = getconf_str(CNF_SSL_FINGERPRINT_FILE);
} else if (g_str_equal(string, "ssl_cert_file")) {
result = getconf_str(CNF_SSL_CERT_FILE);
} else if (g_str_equal(string, "ssl_key_file")) {
result = getconf_str(CNF_SSL_KEY_FILE);
} else if (g_str_equal(string, "ssl_ca_cert_file")) {
result = getconf_str(CNF_SSL_CA_CERT_FILE);
} else if (g_str_equal(string, "ssl_cipher_list")) {
result = getconf_str(CNF_SSL_CIPHER_LIST);
} else if (g_str_equal(string, "ssl_check_host")) {
if (getconf_boolean(CNF_SSL_CHECK_HOST))
result = "1";
else
result = "0";
} else if (g_str_equal(string, "ssl_check_certificate_host")) {
if (getconf_boolean(CNF_SSL_CHECK_CERTIFICATE_HOST))
result = "1";
else
result = "0";
} else if (g_str_equal(string, "ssl_check_fingerprint")) {
if (getconf_boolean(CNF_SSL_CHECK_FINGERPRINT))
result = "1";
else
result = "0";
}
if (result && strlen(result) == 0)
result = NULL;
return(result);
}
void
dump_configuration(
gboolean print_default,
gboolean print_source)
{
tapetype_t *tp;
dumptype_t *dp;
interface_t *ip;
holdingdisk_t *hd;
GSList *hp;
application_t *ap;
pp_script_t *ps;
device_config_t *dc;
changer_config_t *cc;
interactivity_t *iv;
taperscan_t *ts;
policy_s *po;
storage_t *st;
int i;
conf_var_t *np;
keytab_t *kt;
char *prefix;
if (config_client) {
error(_("Don't know how to dump client configurations."));
/* NOTREACHED */
}
g_printf(_("# AMANDA CONFIGURATION FROM FILE '%s':\n\n"), config_filename);
for(np=server_var; np->token != CONF_UNKNOWN; np++) {
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if (np->token == kt->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("server bad token"));
val_t_print_token(print_default, print_source, stdout, NULL, "%-21s ", kt, &conf_data[np->parm]);
}
for(hp = holdinglist; hp != NULL; hp = hp->next) {
hd = hp->data;
g_printf("\nDEFINE HOLDINGDISK %s {\n", hd->name);
for(i=0; i < HOLDING_HOLDING; i++) {
for(np=holding_var; np->token != CONF_UNKNOWN; np++) {
if(np->parm == i)
break;
}
if(np->token == CONF_UNKNOWN)
error(_("holding bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) {
if(kt->token == np->token)
break;
}
if(kt->token == CONF_UNKNOWN)
error(_("holding bad token"));
val_t_print_token(print_default, print_source, stdout, NULL, " %-9s ", kt, &hd->value[i]);
}
g_printf("}\n");
}
for(tp = tapelist; tp != NULL; tp = tp->next) {
if(tp->seen.linenum == -1)
prefix = "#";
else
prefix = "";
g_printf("\n%sDEFINE TAPETYPE %s {\n", prefix, tp->name);
for(i=0; i < TAPETYPE_TAPETYPE; i++) {
for(np=tapetype_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("tapetype bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("tapetype bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-9s ", kt, &tp->value[i]);
}
g_printf("%s}\n", prefix);
}
for(dp = dumplist; dp != NULL; dp = dp->next) {
if (strncmp_const(dp->name, "custom(") != 0) { /* don't dump disklist-derived dumptypes */
if(dp->seen.linenum == -1)
prefix = "#";
else
prefix = "";
g_printf("\n%sDEFINE DUMPTYPE %s {\n", prefix, dp->name);
for(i=0; i < DUMPTYPE_DUMPTYPE; i++) {
for(np=dumptype_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("dumptype bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("dumptype bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-19s ", kt, &dp->value[i]);
}
g_printf("%s}\n", prefix);
}
}
for(ip = interface_list; ip != NULL; ip = ip->next) {
seen_t *netusage_seen = &val_t__seen(getconf(CNF_NETUSAGE));
if (ip->seen.linenum == netusage_seen->linenum &&
ip->seen.filename && netusage_seen->filename &&
g_str_equal(ip->seen.filename, netusage_seen->filename))
prefix = "#";
else
prefix = "";
g_printf("\n%sDEFINE INTERFACE %s {\n", prefix, ip->name);
for(i=0; i < INTER_INTER; i++) {
for(np=interface_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("interface bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("interface bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-19s ", kt, &ip->value[i]);
}
g_printf("%s}\n",prefix);
}
for(ap = application_list; ap != NULL; ap = ap->next) {
if(g_str_equal(ap->name, "default"))
prefix = "#";
else
prefix = "";
g_printf("\n%sDEFINE APPLICATION %s {\n", prefix, ap->name);
for(i=0; i < APPLICATION_APPLICATION; i++) {
for(np=application_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("application bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("application bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-19s ", kt, &ap->value[i]);
}
g_printf("%s}\n",prefix);
}
for(ps = pp_script_list; ps != NULL; ps = ps->next) {
if(g_str_equal(ps->name, "default"))
prefix = "#";
else
prefix = "";
g_printf("\n%sDEFINE SCRIPT %s {\n", prefix, ps->name);
for(i=0; i < PP_SCRIPT_PP_SCRIPT; i++) {
for(np=pp_script_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("script bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("script bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-19s ", kt, &ps->value[i]);
}
g_printf("%s}\n",prefix);
}
for(dc = device_config_list; dc != NULL; dc = dc->next) {
prefix = "";
g_printf("\n%sDEFINE DEVICE %s {\n", prefix, dc->name);
for(i=0; i < DEVICE_CONFIG_DEVICE_CONFIG; i++) {
for(np=device_config_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("device bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("device bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-19s ", kt, &dc->value[i]);
}
g_printf("%s}\n",prefix);
}
for(cc = changer_config_list; cc != NULL; cc = cc->next) {
prefix = "";
g_printf("\n%sDEFINE CHANGER %s {\n", prefix, cc->name);
for(i=0; i < CHANGER_CONFIG_CHANGER_CONFIG; i++) {
for(np=changer_config_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("changer bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("changer bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-19s ", kt, &cc->value[i]);
}
g_printf("%s}\n",prefix);
}
for(iv = interactivity_list; iv != NULL; iv = iv->next) {
prefix = "";
g_printf("\n%sDEFINE INTERACTIVITY %s {\n", prefix, iv->name);
for(i=0; i < INTERACTIVITY_INTERACTIVITY; i++) {
for(np=interactivity_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("interactivity bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("interactivity bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-19s ", kt, &iv->value[i]);
}
g_printf("%s}\n",prefix);
}
for(ts = taperscan_list; ts != NULL; ts = ts->next) {
prefix = "";
g_printf("\n%sDEFINE TAPERSCAN %s {\n", prefix, ts->name);
for(i=0; i < TAPERSCAN_TAPERSCAN; i++) {
for(np=taperscan_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("taperscan bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("taperscan bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-19s ", kt, &ts->value[i]);
}
g_printf("%s}\n",prefix);
}
for(po = policy_list; po != NULL; po = po->next) {
prefix = "";
g_printf("\n%sDEFINE POLICY %s {\n", prefix, po->name);
for(i=0; i < POLICY_POLICY; i++) {
for(np=policy_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("policy bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("policy bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-19s ", kt, &po->value[i]);
}
g_printf("%s}\n",prefix);
}
for(st = storage_list; st != NULL; st = st->next) {
prefix = "";
g_printf("\n%sDEFINE STORAGE %s {\n", prefix, st->name);
for(i=0; i < STORAGE_STORAGE; i++) {
for(np=storage_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("storage bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("storage bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-19s ", kt, &st->value[i]);
}
g_printf("%s}\n",prefix);
}
}
void dump_dumptype(
dumptype_t *dp,
char *prefix,
gboolean print_default,
gboolean print_source)
{
int i;
conf_var_t *np;
keytab_t *kt;
for(i=0; i < DUMPTYPE_DUMPTYPE; i++) {
for(np=dumptype_var; np->token != CONF_UNKNOWN; np++)
if(np->parm == i) break;
if(np->token == CONF_UNKNOWN)
error(_("dumptype bad value"));
for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
if(kt->token == np->token) break;
if(kt->token == CONF_UNKNOWN)
error(_("dumptype bad token"));
val_t_print_token(print_default, print_source, stdout, prefix, " %-19s ", kt, &dp->value[i]);
}
}
static void
val_t_print_token(
gboolean print_default,
gboolean print_source,
FILE *output,
char *prefix,
char *format,
keytab_t *kt,
val_t *val)
{
char **dispstrs, **dispstr;
if (print_default == 0 && !val_t_seen(val)) {
return;
}
dispstrs = val_t_display_strs(val, 1, print_source, TRUE);
/* For most configuration types, this outputs
* PREFIX KEYWORD DISPSTR
* for each of the display strings. For identifiers, however, it
* simply prints the first line of the display string.
*/
/* Print the keyword for anything that is not itself an identifier */
if (kt->token != CONF_IDENT) {
for(dispstr=dispstrs; *dispstr!=NULL; dispstr++) {
if (prefix)
g_fprintf(output, "%s", prefix);
g_fprintf(output, format, str_keyword(kt));
g_fprintf(output, "%s\n", *dispstr);
}
} else {
/* for identifiers, assume there's at most one display string */
assert(g_strv_length(dispstrs) <= 1);
if (*dispstrs) {
g_fprintf(output, "%s\n", *dispstrs);
}
}
g_strfreev(dispstrs);
}
typedef struct proplist_display_str_foreach_user_data {
char **msg;
gboolean print_source;
} proplist_display_str_foreach_user_data;
char *source_string(seen_t *seen);
char *source_string(
seen_t *seen)
{
char *buf;
if (seen->linenum) {
if (seen->block) {
buf = g_strdup_printf(" (%s file %s line %d)",
seen->block, seen->filename, seen->linenum);
} else {
buf = g_strdup_printf(" (file %s line %d)",
seen->filename, seen->linenum);
}
} else {
buf = g_strdup(" (default)");
}
return buf;
}
char **
val_t_display_strs(
val_t *val,
int str_need_quote,
gboolean print_source,
gboolean print_unit)
{
gboolean add_source = TRUE;
int i;
char **buf;
buf = malloc(3*sizeof(char *));
buf[0] = NULL;
buf[1] = NULL;
buf[2] = NULL;
switch(val->type) {
case CONFTYPE_INT:
buf[0] = g_strdup_printf("%d ", val_t__int(val));
i = strlen(buf[0]) - 1;
if (print_unit && val->unit == CONF_UNIT_K) {
buf[0][i] = 'K';
} else {
buf[0][i] = '\0';
}
break;
case CONFTYPE_SIZE:
buf[0] = g_strdup_printf("%zu ", (ssize_t)val_t__size(val));
i = strlen(buf[0]) - 1;
if (print_unit && val->unit == CONF_UNIT_K) {
buf[0][i] = 'K';
} else {
buf[0][i] = '\0';
}
break;
case CONFTYPE_INT64:
buf[0] = g_strdup_printf("%lld ", (long long)val_t__int64(val));
i = strlen(buf[0]) - 1;
if (print_unit && val->unit == CONF_UNIT_K) {
buf[0][i] = 'K';
} else {
buf[0][i] = '\0';
}
break;
case CONFTYPE_REAL:
buf[0] = g_strdup_printf("%0.5f", val_t__real(val));
break;
case CONFTYPE_RATE:
buf[0] = g_strdup_printf("%0.5f %0.5f", val_t__rate(val)[0], val_t__rate(val)[1]);
break;
case CONFTYPE_INTRANGE:
buf[0] = g_strdup_printf("%d,%d", val_t__intrange(val)[0], val_t__intrange(val)[1]);
break;
case CONFTYPE_IDENT:
if(val->v.s) {
buf[0] = g_strdup(val->v.s);
} else {
buf[0] = g_strdup("");
}
break;
case CONFTYPE_IDENTLIST:
{
GSList *ia;
int first = 1;
buf[0] = NULL;
if (!val->v.identlist) {
strappend(buf[0], "\"\"");
} else {
for (ia = val->v.identlist; ia != NULL; ia = ia->next) {
if (first) {
buf[0] = g_strdup(ia->data);
first = 0;
} else {
strappend(buf[0], " ");
strappend(buf[0], ia->data);
}
}
}
}
break;
case CONFTYPE_STR_LIST:
{
GSList *ia;
int first = 1;
buf[0] = NULL;
for (ia = val->v.identlist; ia != NULL; ia = ia->next) {
if (first) {
buf[0] = quote_string_always(ia->data);
first = 0;
} else {
char *qdata = quote_string_always(ia->data);
strappend(buf[0], " ");
strappend(buf[0], qdata);
g_free(qdata);
}
}
}
break;
case CONFTYPE_STR:
if(str_need_quote) {
if(val->v.s) {
buf[0] = quote_string_always(val->v.s);
} else {
buf[0] = g_strdup("\"\"");
}
} else {
if(val->v.s) {
buf[0] = g_strdup(val->v.s);
} else {
buf[0] = g_strdup("");
}
}
break;
case CONFTYPE_AUTOLABEL:
{
autolabel_set_t autolabel = val->v.autolabel.autolabel;
char *template = quote_string_always(val->v.autolabel.template);
GString *strbuf = g_string_new(template);
g_free(template);
if (autolabel & AL_OTHER_CONFIG)
g_string_append(strbuf, " OTHER-CONFIG");
if (autolabel & AL_NON_AMANDA)
g_string_append(strbuf, " NON-AMANDA");
if (autolabel & AL_VOLUME_ERROR)
g_string_append(strbuf, " VOLUME-ERROR");
if (autolabel & AL_EMPTY)
g_string_append(strbuf, " EMPTY");
buf[0] = g_string_free(strbuf, FALSE);
}
break;
case CONFTYPE_LABELSTR:
{
if (val->v.labelstr.match_autolabel) {
buf[0] = g_strdup("MATCH-AUTOLABEL");
} else {
buf[0] = quote_string_always(val->v.labelstr.template);
}
}
break;
case CONFTYPE_TIME:
buf[0] = g_strdup_printf("%2d%02d",
(int)val_t__time(val)/100, (int)val_t__time(val) % 100);
break;
case CONFTYPE_EXINCLUDE: {
buf[0] = exinclude_display_str(val, 0);
buf[1] = exinclude_display_str(val, 1);
break;
}
case CONFTYPE_BOOLEAN:
if(val_t__boolean(val))
buf[0] = g_strdup("yes");
else
buf[0] = g_strdup("no");
break;
case CONFTYPE_NO_YES_ALL:
switch(val_t__no_yes_all(val)) {
case 0:
buf[0] = g_strdup("no");
break;
case 1:
buf[0] = g_strdup("yes");
break;
case 2:
buf[0] = g_strdup("all");
break;
}
break;
case CONFTYPE_STRATEGY:
switch(val_t__strategy(val)) {
case DS_SKIP:
buf[0] = g_strdup("SKIP");
break;
case DS_STANDARD:
buf[0] = g_strdup("STANDARD");
break;
case DS_NOFULL:
buf[0] = g_strdup("NOFULL");
break;
case DS_NOINC:
buf[0] = g_strdup("NOINC");
break;
case DS_HANOI:
buf[0] = g_strdup("HANOI");
break;
case DS_INCRONLY:
buf[0] = g_strdup("INCRONLY");
break;
}
break;
case CONFTYPE_COMPRESS:
switch(val_t__compress(val)) {
case COMP_NONE:
buf[0] = g_strdup("NONE");
break;
case COMP_FAST:
buf[0] = g_strdup("CLIENT FAST");
break;
case COMP_BEST:
buf[0] = g_strdup("CLIENT BEST");
break;
case COMP_CUST:
buf[0] = g_strdup("CLIENT CUSTOM");
break;
case COMP_SERVER_FAST:
buf[0] = g_strdup("SERVER FAST");
break;
case COMP_SERVER_BEST:
buf[0] = g_strdup("SERVER BEST");
break;
case COMP_SERVER_CUST:
buf[0] = g_strdup("SERVER CUSTOM");
break;
}
break;
case CONFTYPE_ESTIMATELIST: {
estimatelist_t es = val_t__estimatelist(val);
buf[0] = g_strdup("");
while (es) {
switch((estimate_t)GPOINTER_TO_INT(es->data)) {
case ES_CLIENT:
strappend(buf[0], "CLIENT");
break;
case ES_SERVER:
strappend(buf[0], "SERVER");
break;
case ES_CALCSIZE:
strappend(buf[0], "CALCSIZE");
break;
case ES_ES:
break;
}
es = es->next;
if (es)
strappend(buf[0], " ");
}
break;
}
case CONFTYPE_EXECUTE_WHERE:
switch(val->v.i) {
case EXECUTE_WHERE_CLIENT:
buf[0] = g_strdup("CLIENT");
break;
case EXECUTE_WHERE_SERVER:
buf[0] = g_strdup("SERVER");
break;
}
break;
case CONFTYPE_SEND_AMREPORT_ON:
switch(val->v.i) {
case SEND_AMREPORT_ALL:
buf[0] = g_strdup("ALL");
break;
case SEND_AMREPORT_STRANGE:
buf[0] = g_strdup("STRANGE");
break;
case SEND_AMREPORT_ERROR:
buf[0] = g_strdup("ERROR");
break;
case SEND_AMREPORT_NEVER:
buf[0] = g_strdup("NEVER");
break;
}
break;
case CONFTYPE_DATA_PATH:
buf[0] = g_strdup(data_path_to_string(val->v.i));
break;
case CONFTYPE_ENCRYPT:
switch(val_t__encrypt(val)) {
case ENCRYPT_NONE:
buf[0] = g_strdup("NONE");
break;
case ENCRYPT_CUST:
buf[0] = g_strdup("CLIENT");
break;
case ENCRYPT_SERV_CUST:
buf[0] = g_strdup("SERVER");
break;
}
break;
case CONFTYPE_PART_CACHE_TYPE:
switch(val_t__part_cache_type(val)) {
case PART_CACHE_TYPE_NONE:
buf[0] = g_strdup("NONE");
break;
case PART_CACHE_TYPE_DISK:
buf[0] = g_strdup("DISK");
break;
case PART_CACHE_TYPE_MEMORY:
buf[0] = g_strdup("MEMORY");
break;
}
break;
case CONFTYPE_HOST_LIMIT: {
GSList *iter = val_t__host_limit(val).match_pats;
if (val_t__host_limit(val).same_host)
buf[0] = g_strdup("SAME-HOST ");
else
buf[0] = g_strdup("");
if (val_t__host_limit(val).server)
strappend(buf[0], "SERVER ");
while (iter) {
char *qbuf = quote_string_always((char *)iter->data);
strappend(buf[0], qbuf);
strappend(buf[0], " ");
amfree(qbuf);
iter = iter->next;
}
break;
}
case CONFTYPE_HOLDING:
switch(val_t__holding(val)) {
case HOLD_NEVER:
buf[0] = g_strdup("NEVER");
break;
case HOLD_AUTO:
buf[0] = g_strdup("AUTO");
break;
case HOLD_REQUIRED:
buf[0] = g_strdup("REQUIRED");
break;
}
break;
case CONFTYPE_TAPERALGO:
buf[0] = g_strdup_printf("%s", taperalgo2str(val_t__taperalgo(val)));
break;
case CONFTYPE_PRIORITY:
switch(val_t__priority(val)) {
case PRIORITY_LOW:
buf[0] = g_strdup("LOW");
break;
case PRIORITY_MEDIUM:
buf[0] = g_strdup("MEDIUM");
break;
case PRIORITY_HIGH:
buf[0] = g_strdup("HIGH");
break;
default:
buf[0] = g_strdup_printf("%d", val_t__priority(val));
break;
}
break;
case CONFTYPE_PROPLIST: {
int nb_property;
proplist_display_str_foreach_user_data user_data;
nb_property = g_hash_table_size(val_t__proplist(val));
g_free(buf);
buf = g_new0(char *, nb_property+1);
user_data.msg = buf;
user_data.print_source = print_source;
g_hash_table_foreach(val_t__proplist(val),
proplist_display_str_foreach_fn,
&user_data);
add_source = FALSE;
break;
}
case CONFTYPE_APPLICATION: {
if (val->v.s) {
buf[0] = quote_string_always(val->v.s);
} else {
buf[0] = g_strdup("");
}
break;
}
case CONFTYPE_EXECUTE_ON:
buf[0] = execute_on_to_string(val->v.i, ", ");
break;
case CONFTYPE_DUMP_SELECTION: {
int nb_selection = g_slist_length(val_t__dump_selection(val));
dump_selection_list_t dsl;
int i = 0;
g_free(buf);
buf = malloc((nb_selection+1)*sizeof(char*));
buf[nb_selection] = NULL;
for (dsl = val->v.dump_selection ; dsl != NULL ; dsl = dsl->next) {
dump_selection_t *ds = dsl->data;
char *tag = NULL;
char *level = NULL;
switch (ds->tag_type) {
case TAG_NAME:
tag = quote_string_always(ds->tag);
break;
case TAG_ALL:
tag = "ALL";
break;
case TAG_OTHER:
tag = "OTHER";
break;
}
switch (ds->level) {
case LEVEL_ALL:
level = "ALL";
break;
case LEVEL_FULL:
level = "FULL";
break;
case LEVEL_INCR:
level = "INCR";
break;
}
buf[i++] = g_strdup_printf("%s %s", tag, level);
if (ds->tag_type == TAG_NAME) {
g_free(tag);
}
}
break;
}
case CONFTYPE_VAULT_LIST: {
int nb_selection = g_slist_length(val_t__vault_list(val));
vault_list_t vl;
int i = 0;
g_free(buf);
buf = malloc((nb_selection+1)*sizeof(char*));
buf[nb_selection] = NULL;
for (vl = val->v.vault_list ; vl != NULL ; vl = vl->next) {
vault_el_t *v = vl->data;
char *s = quote_string_always(v->storage);
buf[i++] = g_strdup_printf("%s %d", s, v->days);
g_free(s);
}
break;
}
}
/* add source */
if (print_source && add_source) {
char **buf1;
for (buf1 = buf; *buf1 != NULL; buf1++) {
char *ss = source_string(&val->seen);
char *buf2 = g_strjoin("", *buf1, ss, NULL);
g_free(*buf1);
g_free(ss);
*buf1 = buf2;
}
}
return buf;
}
int
val_t_to_execute_on(
val_t *val)
{
if (val->type != CONFTYPE_EXECUTE_ON) {
error(_("get_conftype_execute_on: val.type is not CONFTYPE_EXECUTE_ON"));
/*NOTREACHED*/
}
return val_t__execute_on(val);
}
execute_where_t
val_t_to_execute_where(
val_t *val)
{
if (val->type != CONFTYPE_EXECUTE_WHERE) {
error(_("get_conftype_execute_where: val.type is not CONFTYPE_EXECUTE_WHERE"));
/*NOTREACHED*/
}
return val->v.i;
}
char *
val_t_to_application(
val_t *val)
{
if (val->type != CONFTYPE_APPLICATION) {
error(_("get_conftype_applicaiton: val.type is not CONFTYPE_APPLICATION"));
/*NOTREACHED*/
}
return val->v.s;
}
static void
proplist_display_str_foreach_fn(
gpointer key_p,
gpointer value_p,
gpointer user_data_p)
{
property_t *property = value_p;
GSList *value;
proplist_display_str_foreach_user_data *user_data = user_data_p;
char ***msg = (char ***)&user_data->msg;
GPtrArray *array = g_ptr_array_new();
gchar **strings;
/* What to do with property->append? it should be printed only on client */
if (property->visible)
g_ptr_array_add(array, g_strdup("visible"));
else
g_ptr_array_add(array, g_strdup("hidden"));
if (property->priority)
g_ptr_array_add(array, g_strdup("priority"));
g_ptr_array_add(array, quote_string_always(key_p));
for (value = property->values; value; value = value->next)
g_ptr_array_add(array, quote_string_always((char *)value->data));
if (user_data->print_source) {
g_ptr_array_add(array, source_string(&property->seen));
}
g_ptr_array_add(array, NULL);
strings = (gchar **)g_ptr_array_free(array, FALSE);
**msg = g_strjoinv(" ", strings);
g_strfreev(strings);
(*msg)++;
}
static char *
exinclude_display_str(
val_t *val,
int file)
{
am_sl_t *sl;
sle_t *excl;
char *rval;
GPtrArray *array = g_ptr_array_new();
gchar **strings;
assert(val->type == CONFTYPE_EXINCLUDE);
if (file == 0) {
sl = val_t__exinclude(val).sl_list;
g_ptr_array_add(array, g_strdup("LIST"));
} else {
sl = val_t__exinclude(val).sl_file;
g_ptr_array_add(array, g_strdup("FILE"));
}
if (val_t__exinclude(val).optional == 1)
g_ptr_array_add(array, g_strdup("OPTIONAL"));
if (sl != NULL)
for(excl = sl->first; excl; excl = excl->next)
g_ptr_array_add(array, quote_string_always(excl->name));
g_ptr_array_add(array, NULL);
strings = (gchar **)g_ptr_array_free(array, FALSE);
rval = g_strjoinv(" ", strings);
g_strfreev(strings);
return rval;
}
char *
taperalgo2str(
taperalgo_t taperalgo)
{
if(taperalgo == ALGO_FIRST) return "FIRST";
if(taperalgo == ALGO_FIRSTFIT) return "FIRSTFIT";
if(taperalgo == ALGO_LARGEST) return "LARGEST";
if(taperalgo == ALGO_LARGESTFIT) return "LARGESTFIT";
if(taperalgo == ALGO_SMALLEST) return "SMALLEST";
if(taperalgo == ALGO_LAST) return "LAST";
return "UNKNOWN";
}
char *
config_dir_relative(
char *filename)
{
char *cdir = NULL;
if (*filename == '/' || config_dir == NULL) {
cdir = g_strdup(filename);
} else {
if (config_dir[strlen(config_dir)-1] == '/') {
cdir = g_strjoin(NULL, config_dir, filename, NULL);
} else {
cdir = g_strjoin(NULL, config_dir, "/", filename, NULL);
}
}
if (prepend_prefix) {
char *cdir1 = g_strconcat(prepend_prefix, "/", cdir, NULL);
g_free(cdir);
cdir = cdir1;
}
return cdir;
}
static int
parm_key_info(
char *key,
conf_var_t **parm,
val_t **val)
{
conf_var_t *np;
keytab_t *kt;
char *s;
char ch;
char *subsec_type;
char *subsec_name;
char *subsec_key;
tapetype_t *tp;
dumptype_t *dp;
interface_t *ip;
holdingdisk_t *hp;
application_t *ap;
pp_script_t *pp;
device_config_t *dc;
changer_config_t *cc;
taperscan_t *ts;
policy_s *po;
storage_t *st;
interactivity_t *iv;
int success = FALSE;
/* WARNING: assumes globals keytable and parsetable are set correctly. */
assert(keytable != NULL);
assert(parsetable != NULL);
/* make a copy we can stomp on */
key = g_strdup(key);
/* uppercase the key */
for (s = key; (ch = *s) != 0; s++) {
if (islower((int)ch))
*s = (char)toupper(ch);
}
subsec_name = strchr(key, ':');
if (subsec_name) {
subsec_type = key;
*subsec_name = '\0';
subsec_name++;
/* convert subsec_type '-' to '_' */
for (s = subsec_type; (ch = *s) != 0; s++) {
if (*s == '-') *s = '_';
}
subsec_key = strrchr(subsec_name,':');
if(!subsec_key) goto out; /* failure */
*subsec_key = '\0';
subsec_key++;
/* convert subsec_key '-' to '_' */
for (s = subsec_key; (ch = *s) != 0; s++) {
if (*s == '-') *s = '_';
}
/* If the keyword doesn't exist, there's no need to look up the
* subsection -- we know it's invalid */
for(kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if(kt->keyword && g_str_equal(kt->keyword, subsec_key))
break;
}
if(kt->token == CONF_UNKNOWN) goto out;
/* Otherwise, figure out which kind of subsection we're dealing with,
* and parse against that. */
if (g_str_equal(subsec_type, "TAPETYPE")) {
tp = lookup_tapetype(subsec_name);
if (!tp) goto out;
for(np = tapetype_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &tp->value[np->parm];
if (parm) *parm = np;
success = TRUE;
} else if (g_str_equal(subsec_type, "DUMPTYPE")) {
dp = lookup_dumptype(subsec_name);
if (!dp) goto out;
for(np = dumptype_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &dp->value[np->parm];
if (parm) *parm = np;
success = TRUE;
} else if (g_str_equal(subsec_type, "HOLDINGDISK")) {
hp = lookup_holdingdisk(subsec_name);
if (!hp) goto out;
for(np = holding_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &hp->value[np->parm];
if (parm) *parm = np;
success = TRUE;
} else if (g_str_equal(subsec_type, "INTERFACE")) {
ip = lookup_interface(subsec_name);
if (!ip) goto out;
for(np = interface_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &ip->value[np->parm];
if (parm) *parm = np;
success = TRUE;
/* accept the old name here, too */
} else if (g_str_equal(subsec_type, "APPLICATION_TOOL")
|| g_str_equal(subsec_type, "APPLICATION")) {
ap = lookup_application(subsec_name);
if (!ap) goto out;
for(np = application_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &ap->value[np->parm];
if (parm) *parm = np;
success = TRUE;
/* accept the old name here, too */
} else if (g_str_equal(subsec_type, "SCRIPT_TOOL")
|| g_str_equal(subsec_type, "SCRIPT")) {
pp = lookup_pp_script(subsec_name);
if (!pp) goto out;
for(np = pp_script_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &pp->value[np->parm];
if (parm) *parm = np;
success = TRUE;
} else if (g_str_equal(subsec_type, "DEVICE")) {
dc = lookup_device_config(subsec_name);
if (!dc) goto out;
for(np = device_config_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &dc->value[np->parm];
if (parm) *parm = np;
success = TRUE;
} else if (g_str_equal(subsec_type, "CHANGER")) {
cc = lookup_changer_config(subsec_name);
if (!cc) goto out;
for(np = changer_config_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &cc->value[np->parm];
if (parm) *parm = np;
success = TRUE;
} else if (g_str_equal(subsec_type, "INTERACTIVITY")) {
iv = lookup_interactivity(subsec_name);
if (!iv) goto out;
for(np = interactivity_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &iv->value[np->parm];
if (parm) *parm = np;
success = TRUE;
} else if (g_str_equal(subsec_type, "TAPERSCAN")) {
ts = lookup_taperscan(subsec_name);
if (!ts) goto out;
for(np = taperscan_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &ts->value[np->parm];
if (parm) *parm = np;
success = TRUE;
} else if (g_str_equal(subsec_type, "POLICY")) {
po = lookup_policy(subsec_name);
if (!po) goto out;
for(np = policy_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &po->value[np->parm];
if (parm) *parm = np;
success = TRUE;
} else if (g_str_equal(subsec_type, "STORAGE")) {
st = lookup_storage(subsec_name);
if (!st) goto out;
for(np = storage_var; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if (np->token == CONF_UNKNOWN) goto out;
if (val) *val = &st->value[np->parm];
if (parm) *parm = np;
success = TRUE;
}
/* No delimiters -- we're referencing a global config parameter */
} else {
/* convert key '-' to '_' */
for (s = key; (ch = *s) != 0; s++) {
if (*s == '-') *s = '_';
}
/* look up the keyword */
for(kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
if(kt->keyword && g_str_equal(kt->keyword, key))
break;
}
if(kt->token == CONF_UNKNOWN) goto out;
/* and then look that up in the parse table */
for(np = parsetable; np->token != CONF_UNKNOWN; np++) {
if(np->token == kt->token)
break;
}
if(np->token == CONF_UNKNOWN) goto out;
if (val) *val = &conf_data[np->parm];
if (parm) *parm = np;
success = TRUE;
}
out:
amfree(key);
return success;
}
gint64
find_multiplier(
char * str)
{
keytab_t * table_entry;
str = g_strdup(str);
g_strstrip(str);
if (*str == '\0') {
g_free(str);
return 1;
}
for (table_entry = numb_keytable; table_entry->keyword != NULL;
table_entry ++) {
if (strcasecmp(str, table_entry->keyword) == 0) {
g_free(str);
switch (table_entry->token) {
case CONF_MULT1K:
return 1024;
case CONF_MULT1M:
return 1024*1024;
case CONF_MULT1G:
return 1024*1024*1024;
case CONF_MULT1T:
return (gint64)1024*1024*1024*1024;
case CONF_MULT7:
return 7;
case CONF_AMINFINITY:
return G_MAXINT64;
case CONF_MULT1:
case CONF_IDENT:
return 1;
default:
/* Should not happen. */
return 0;
}
}
}
/* None found; this is an error. */
g_free(str);
return 0;
}
int
string_to_boolean(
const char *str)
{
keytab_t * table_entry;
if (str == NULL || *str == '\0') {
return -1;
}
/* 0 and 1 are not in the table, as they are parsed as ints */
if (g_str_equal(str, "0"))
return 0;
if (g_str_equal(str, "1"))
return 1;
for (table_entry = bool_keytable; table_entry->keyword != NULL;
table_entry ++) {
if (strcasecmp(str, table_entry->keyword) == 0) {
switch (table_entry->token) {
case CONF_ATRUE:
return 1;
case CONF_AFALSE:
return 0;
default:
return -1;
}
}
}
return -1;
}
/*
* Error Handling Implementaiton
*/
void config_add_error(
cfgerr_level_t level,
char * errmsg)
{
cfgerr_level = max(cfgerr_level, level);
g_debug("%s", errmsg);
cfgerr_errors = g_slist_append(cfgerr_errors, errmsg);
}
static void conf_error_common(
cfgerr_level_t level,
const char * format,
va_list argp)
{
char *msg = NULL;
char *errstr = NULL;
if (!generate_errors)
return;
msg = g_strdup_vprintf(format, argp);
if(current_line)
errstr = g_strdup_printf(_("argument '%s': %s"),
current_line, msg);
else if (current_filename && current_line_num > 0)
errstr = g_strdup_printf(_("'%s', line %d: %s"),
current_filename, current_line_num, msg);
else
errstr = g_strdup_printf(_("parse error: %s"), msg);
amfree(msg);
config_add_error(level, errstr);
}
G_GNUC_PRINTF(1, 2)
static void conf_parserror(const char *format, ...)
{
va_list argp;
arglist_start(argp, format);
conf_error_common(CFGERR_ERRORS, format, argp);
arglist_end(argp);
}
G_GNUC_PRINTF(1, 2)
static void conf_parswarn(const char *format, ...)
{
va_list argp;
arglist_start(argp, format);
conf_error_common(CFGERR_WARNINGS, format, argp);
arglist_end(argp);
}
cfgerr_level_t
config_errors(GSList **errstr)
{
if (errstr)
*errstr = cfgerr_errors;
return cfgerr_level;
}
void
config_clear_errors(void)
{
slist_free_full(cfgerr_errors, g_free);
cfgerr_errors = NULL;
cfgerr_level = CFGERR_OK;
}
void
config_print_errors(void)
{
GSList *iter;
for (iter = cfgerr_errors; iter; iter = g_slist_next(iter)) {
g_fprintf(stderr, "%s\n", (char *)iter->data);
}
}
void
config_print_errors_as_message(void)
{
GSList *iter;
for (iter = cfgerr_errors; iter; iter = g_slist_next(iter)) {
g_fprintf(stdout,
" {\n" \
" \"source_filename\" : \"%s\",\n" \
" \"source_line\" : \"%d\",\n" \
" \"severity\" : \"error\",\n" \
" \"code\" : \"%d\",\n" \
" \"message\" : \"%s\"\n" \
" \"process\" : \"%s\"\n" \
" \"running_on\" : \"%s\"\n" \
" \"component\" : \"%s\"\n" \
" \"module\" : \"%s\"\n" \
" },\n", AMANDA_FILE, __LINE__, 1500016 , get_pname(), get_running_on(), get_pcomponent(), get_pmodule(), (char *)iter->data);
}
}
/* Get the config name */
char *get_config_name(void)
{
return config_name;
}
/* Get the config directory */
char *get_config_dir(void)
{
return config_dir;
}
/* Get the config filename */
char *get_config_filename(void)
{
return config_filename;
}
char *
get_running_on(void)
{
if (!config_client) {
return "amanda-server";
} else {
return "amanda-client";
}
}
char *
anonymous_value(void)
{
static char number[NUM_STR_SIZE];
static int value=1;
g_snprintf(number, sizeof(number), "%d", value);
value++;
return number;
}
gint compare_pp_script_order(
gconstpointer a,
gconstpointer b)
{
return pp_script_get_order(lookup_pp_script((char *)a)) > pp_script_get_order(lookup_pp_script((char *)b));
}
char *
data_path_to_string(
data_path_t data_path)
{
switch (data_path) {
case DATA_PATH_AMANDA : return "AMANDA";
case DATA_PATH_DIRECTTCP: return "DIRECTTCP";
}
error(_("datapath is not DATA_PATH_AMANDA or DATA_PATH_DIRECTTCP"));
/* NOTREACHED */
}
data_path_t
data_path_from_string(
char *data)
{
if (g_str_equal(data, "AMANDA"))
return DATA_PATH_AMANDA;
if (g_str_equal(data, "DIRECTTCP"))
return DATA_PATH_DIRECTTCP;
error(_("datapath is not AMANDA or DIRECTTCP :%s:"), data);
/* NOTREACHED */
}
gchar *
amandaify_property_name(
const gchar *name)
{
gchar *ret, *cur_r;
const gchar *cur_o;
if (!name) return NULL;
ret = g_malloc0(strlen(name)+1);
cur_r = ret;
for (cur_o = name; *cur_o; cur_o++) {
if ('_' == *cur_o)
*cur_r = '-';
else
*cur_r = g_ascii_tolower(*cur_o);
cur_r++;
}
return ret;
}
static char keyword_str[1024];
static char *
str_keyword(
keytab_t *kt)
{
char *p = kt->keyword;
char *s = keyword_str;
while(*p != '\0') {
if (*p == '_') {
*s = '-';
} else {
*s = *p;
}
p++;
s++;
}
*s = '\0';
return keyword_str;
}
/*
* The CONFTYPE_EXECUTE_ON keywork has LOTS of flags in it, and two call sites
* need to build a string out of it.
*
* In order to avoid having to modify both call sites in case one flag is added,
* create a helper function which gives back a string to the caller. The array
* defined below MUST be kept in sync with conffile.h!
*/
static keytab_t execute_on_strings[] = {
{ "PRE-AMCHECK", EXECUTE_ON_PRE_AMCHECK },
{ "PRE-DLE-AMCHECK", EXECUTE_ON_PRE_DLE_AMCHECK },
{ "PRE-HOST-AMCHECK", EXECUTE_ON_PRE_HOST_AMCHECK },
{ "POST-DLE-AMCHECK", EXECUTE_ON_POST_DLE_AMCHECK },
{ "POST-HOST-AMCHECK", EXECUTE_ON_POST_HOST_AMCHECK },
{ "POST-AMCHECK", EXECUTE_ON_POST_AMCHECK },
{ "PRE-ESTIMATE", EXECUTE_ON_PRE_ESTIMATE },
{ "PRE-DLE-ESTIMATE", EXECUTE_ON_PRE_DLE_ESTIMATE },
{ "PRE-HOST-ESTIMATE", EXECUTE_ON_PRE_HOST_ESTIMATE },
{ "POST-DLE-ESTIMATE", EXECUTE_ON_POST_DLE_ESTIMATE },
{ "POST-HOST-ESTIMATE", EXECUTE_ON_POST_HOST_ESTIMATE },
{ "POST-ESTIMATE", EXECUTE_ON_POST_ESTIMATE },
{ "PRE-BACKUP", EXECUTE_ON_PRE_BACKUP },
{ "PRE-DLE-BACKUP", EXECUTE_ON_PRE_DLE_BACKUP },
{ "PRE-HOST-BACKUP", EXECUTE_ON_PRE_HOST_BACKUP },
{ "POST-BACKUP", EXECUTE_ON_POST_BACKUP },
{ "POST-DLE-BACKUP", EXECUTE_ON_POST_DLE_BACKUP },
{ "POST-HOST-BACKUP", EXECUTE_ON_POST_HOST_BACKUP },
{ "PRE-RECOVER", EXECUTE_ON_PRE_RECOVER },
{ "POST-RECOVER", EXECUTE_ON_POST_RECOVER },
{ "PRE-LEVEL-RECOVER", EXECUTE_ON_PRE_LEVEL_RECOVER },
{ "POST-LEVEL-RECOVER", EXECUTE_ON_POST_LEVEL_RECOVER },
{ "INTER-LEVEL-RECOVER", EXECUTE_ON_INTER_LEVEL_RECOVER },
{ NULL, 0 }
};
char *execute_on_to_string(int flags, char *separator)
{
char *ret;
GPtrArray *array = g_ptr_array_new();
gchar **strings;
keytab_t *entry;
for (entry = execute_on_strings; entry->token; entry++)
if (flags & entry->token)
g_ptr_array_add(array, entry->keyword);
g_ptr_array_add(array, NULL);
strings = (gchar **)g_ptr_array_free(array, FALSE);
ret = g_strjoinv(separator, strings);
/*
* We MUST NOT free the strings in the array...
*/
g_free(strings);
return ret;
}
char *
custom_escape(
char *str)
{
char *s;
for (s = str; *s != '\0'; s++) {
if (*s == '/') *s = '_';
}
return str;
}
val_t *
getconf_human(
confparm_key key)
{
return getconf(key);
}
val_t *
dumptype_getconf_human(
dumptype_t *dtyp,
dumptype_key key)
{
return dumptype_getconf(dtyp, key);
}
val_t *
tapetype_getconf_human(
tapetype_t *typ,
tapetype_key key)
{
return tapetype_getconf(typ, key);
}
val_t *
application_getconf_human(
application_t *typ,
application_key key)
{
return application_getconf(typ, key);
}
val_t *
device_config_getconf_human(
device_config_t *typ,
device_config_key key)
{
return device_config_getconf(typ, key);
}
val_t *
changer_config_getconf_human(
changer_config_t *typ,
changer_config_key key)
{
return changer_config_getconf(typ, key);
}
val_t *
storage_getconf_human(
storage_t *typ,
storage_key key)
{
return storage_getconf(typ, key);
}
val_t *
pp_script_getconf_human(
pp_script_t *typ,
pp_script_key key)
{
return pp_script_getconf(typ, key);
}
val_t *
holdingdisk_getconf_human(
holdingdisk_t *typ,
holdingdisk_key key)
{
return holdingdisk_getconf(typ, key);
}
val_t *
interface_getconf_human(
interface_t *typ,
interface_key key)
{
return interface_getconf(typ, key);
}
val_t *
interactivity_getconf_human(
interactivity_t *typ,
interactivity_key key)
{
return interactivity_getconf(typ, key);
}
val_t *
taperscan_getconf_human(
taperscan_t *typ,
taperscan_key key)
{
return taperscan_getconf(typ, key);
}
val_t *
policy_getconf_human(
policy_s *typ,
policy_key key)
{
return policy_getconf(typ, key);
}
static gboolean
is_valid_label(
char *template)
{
char *t;
for (t=template; *t != '\0'; t++) {
if (*t <= 32 || *t == '"')
return FALSE;
}
return TRUE;
}