X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fconffile.c;h=19d87da4718f099fa7caf5cc50f1491cf607672e;hb=b116e9366c7b2ea2c2eb53b0a13df4090e176235;hp=b25484566f18790c3307973dc34e01d9560e704c;hpb=a6127998ee6dcab6bb034f6ca985b07804a86f9a;p=debian%2Famanda diff --git a/common-src/conffile.c b/common-src/conffile.c index b254845..19d87da 100644 --- a/common-src/conffile.c +++ b/common-src/conffile.c @@ -35,6 +35,7 @@ #include "util.h" #include "conffile.h" #include "clock.h" +#include /* * Lexical analysis @@ -53,7 +54,7 @@ typedef enum { CONF_UNKNOWN, CONF_ANY, CONF_COMMA, CONF_LBRACE, CONF_RBRACE, CONF_NL, CONF_END, CONF_IDENT, CONF_INT, - CONF_AM64, CONF_BOOL, CONF_REAL, + CONF_INT64, CONF_BOOL, CONF_REAL, CONF_STRING, CONF_TIME, CONF_SIZE, /* config parameters */ @@ -62,7 +63,7 @@ typedef enum { CONF_CHANGERDEV, CONF_CHANGERFILE, CONF_LABELSTR, CONF_BUMPPERCENT, CONF_BUMPSIZE, CONF_BUMPDAYS, CONF_BUMPMULT, CONF_ETIMEOUT, CONF_DTIMEOUT, - CONF_CTIMEOUT, CONF_TAPEBUFS, CONF_TAPELIST, + CONF_CTIMEOUT, CONF_TAPELIST, CONF_DEVICE_OUTPUT_BUFFER_SIZE, CONF_DISKFILE, CONF_INFOFILE, CONF_LOGDIR, CONF_LOGFILE, CONF_DISKDIR, CONF_DISKSIZE, @@ -70,9 +71,11 @@ typedef enum { 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, @@ -81,7 +84,24 @@ typedef enum { CONF_TAPERFLUSH, CONF_FLUSH_THRESHOLD_DUMPED, CONF_FLUSH_THRESHOLD_SCHEDULED, - CONF_DEVICE_PROPERTY, + 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_DATA_PATH, CONF_AMANDA, CONF_DIRECTTCP, + CONF_TAPER_PARALLEL_WRITE, + + /* execute on */ + CONF_PRE_DLE_AMCHECK, CONF_PRE_HOST_AMCHECK, + CONF_POST_DLE_AMCHECK, CONF_POST_HOST_AMCHECK, + CONF_PRE_DLE_ESTIMATE, CONF_PRE_HOST_ESTIMATE, + CONF_POST_DLE_ESTIMATE, CONF_POST_HOST_ESTIMATE, + 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, @@ -103,10 +123,10 @@ typedef enum { 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_USERNAME, CONF_CLIENT_PORT, CONF_ALLOW_SPLIT, /* tape type */ - /*COMMENT,*/ CONF_BLOCKSIZE, CONF_FILE_PAD, + /*COMMENT,*/ CONF_BLOCKSIZE, CONF_LBL_TEMPL, CONF_FILEMARK, CONF_LENGTH, CONF_SPEED, CONF_READBLOCKSIZE, @@ -118,12 +138,13 @@ typedef enum { 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_SENDBACKUP, CONF_DEBUG_RECOVERY, /* network interface */ /* COMMENT, */ /* USE, */ @@ -136,9 +157,23 @@ typedef enum { 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, + + /* part_cache_type */ + CONF_PART_SIZE, CONF_PART_CACHE_TYPE, CONF_PART_CACHE_DIR, + CONF_PART_CACHE_MAX_SIZE, CONF_DISK, CONF_MEMORY, + + /* recovery-limit */ + CONF_RECOVERY_LIMIT, CONF_SAME_HOST, + /* holdingdisk */ CONF_NEVER, CONF_AUTO, CONF_REQUIRED, + /* send_amreport */ + CONF_ALL, CONF_STRANGE, CONF_ERROR, + /* priority */ CONF_LOW, CONF_MEDIUM, CONF_HIGH, @@ -153,6 +188,7 @@ typedef enum { /* numbers */ CONF_AMINFINITY, CONF_MULT1, CONF_MULT7, CONF_MULT1K, CONF_MULT1M, CONF_MULT1G, + CONF_MULT1T, /* boolean */ CONF_ATRUE, CONF_AFALSE @@ -210,6 +246,13 @@ static void unget_conftoken(void); 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); + /* * Parser */ @@ -226,6 +269,13 @@ typedef struct conf_var_s { 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., @@ -240,7 +290,7 @@ static int allow_overwrites; */ struct tapetype_s { struct tapetype_s *next; - int seen; + seen_t seen; char *name; val_t value[TAPETYPE_TAPETYPE]; @@ -248,7 +298,7 @@ struct tapetype_s { struct dumptype_s { struct dumptype_s *next; - int seen; + seen_t seen; char *name; val_t value[DUMPTYPE_DUMPTYPE]; @@ -256,20 +306,51 @@ struct dumptype_s { struct interface_s { struct interface_s *next; - int seen; + seen_t seen; char *name; val_t value[INTER_INTER]; }; struct holdingdisk_s { - struct holdingdisk_s *next; - int seen; + 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; + int seen; + char *name; + + val_t value[CHANGER_CONFIG_CHANGER_CONFIG]; +}; + /* The current parser table */ static conf_var_t *parsetable = NULL; @@ -279,27 +360,33 @@ static conf_var_t *parsetable = NULL; * * @param filename: configuration file to read * @param is_client: true if this is a client - * @returns: false if an error occurred + * @param missing_ok: is it OK if the file is missing? */ -static gboolean read_conffile(char *filename, - gboolean is_client); +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 or error + * @returns: true on success, false on EOF */ static gboolean read_confline(gboolean is_client); -/* Handle an invalid token, by issuing a warning or an error, depending - * on how long the token has been deprecated. +/* 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 @@ -320,7 +407,8 @@ static void handle_invalid_keyword(const char * token); */ static void read_block(conf_var_t *read_var, val_t *valarray, char *errormsg, int read_brace, - void (*copy_function)(void)); + 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 @@ -334,10 +422,10 @@ static void read_block(conf_var_t *read_var, val_t *valarray, * - copy_foo implements inheritance as described in read_block() */ static holdingdisk_t hdcur; -static void get_holdingdisk(void); +static void get_holdingdisk(int is_define); static void init_holdingdisk_defaults(void); static void save_holdingdisk(void); -/* (holdingdisks don't support inheritance) */ +static void copy_holdingdisk(void); static dumptype_t dpcur; static void get_dumptype(void); @@ -357,30 +445,66 @@ 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); + /* read_functions -- these fit into the read_function slot in a parser * table entry, and are responsible for calling getconf_token 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_am64(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_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_size_byte(conf_var_t *, val_t *); static void read_bool(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_estimate(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_dpp_script(conf_var_t *, val_t *); static void read_property(conf_var_t *, val_t *); +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_part_cache_type(conf_var_t *, val_t *); +static void read_recovery_limit(conf_var_t *, val_t *); /* Functions to get various types of values. These are called by * read_functions to take care of any variations in the way that these @@ -390,7 +514,8 @@ static void read_property(conf_var_t *, val_t *); static time_t get_time(void); static int get_int(void); static ssize_t get_size(void); -static off_t get_am64_t(void); +static ssize_t get_size_byte(void); +static gint64 get_int64(void); static int get_bool(void); /* Check the given 'seen', flagging an error if this value has already @@ -399,12 +524,13 @@ static int get_bool(void); * * @param seen: (in/out) seen value to adjust */ -static void ckseen(int *seen); +static void ckseen(seen_t *seen); /* validate_functions -- these fit into the validate_function solt in * a parser table entry. They call conf_parserror if the value in their * second argument is invalid. */ 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 *); @@ -419,19 +545,27 @@ 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 *); +gint compare_pp_script_order(gconstpointer a, gconstpointer b); /* * Initialization */ -/* Name of the current configuration (part of API) */ -char *config_name = NULL; +/* The name of the configuration under which this application is running. + * This variable is initialized by config_init. + */ +static char *config_name = NULL; -/* Current configuration directory (part of API) */ -char *config_dir = NULL; +/* The directory containing the configuration for this application. This + * variable is initialized by config_init + */ +static char *config_dir = NULL; -/* Current toplevel configuration file (part of API) */ -char *config_filename = 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; @@ -440,22 +574,27 @@ static gboolean config_initialized = FALSE; * with CONFIG_INIT_CLIENT) */ static gboolean config_client = FALSE; -/* What config overwrites are applied? */ -static config_overwrites_t *applied_config_overwrites = NULL; +/* 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 holdingdisk_t *holdinglist = NULL; +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; /* storage for derived values */ static long int unit_divisor = 1; int debug_amandad = 0; +int debug_recovery = 0; int debug_amidxtaped = 0; int debug_amindexd = 0; int debug_amrecover = 0; @@ -484,6 +623,9 @@ static void init_defaults(void); */ 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. * @@ -491,17 +633,22 @@ static void update_derived_values(gboolean is_client); * the relevant value into the 'v' field. */ static void conf_init_int(val_t *val, int i); -static void conf_init_am64(val_t *val, off_t l); +static void conf_init_int64(val_t *val, 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_time(val_t *val, time_t t); static void conf_init_size(val_t *val, ssize_t sz); static void conf_init_bool(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_estimate(val_t *val, estimate_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); @@ -509,26 +656,32 @@ 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_part_cache_type(val_t *val, part_cache_type_t i); +static void conf_init_recovery_limit(val_t *val); /* * Command-line Handling */ -typedef struct config_overwrite_s { - char *key; - char *value; -} config_overwrite_t; +typedef struct config_override_s { + char *key; + char *value; + gboolean applied; +} config_override_t; -struct config_overwrites_s { +struct config_overrides_s { int n_allocated; int n_used; - config_overwrite_t *ovr; + 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 *); @@ -536,6 +689,8 @@ 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); @@ -564,8 +719,10 @@ static int parm_key_info(char *key, conf_var_t **parm, val_t **val); /* Have we seen a parse error yet? Parsing continues after an error, so this * flag is checked after the parse is complete. */ -static gboolean got_parserror; +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))); @@ -582,11 +739,11 @@ keytab_t client_keytab[] = { { "INDEX_SERVER", CONF_INDEX_SERVER }, { "TAPE_SERVER", CONF_TAPE_SERVER }, { "TAPEDEV", CONF_TAPEDEV }, - { "DEVICE-PROPERTY", CONF_DEVICE_PROPERTY }, { "AUTH", CONF_AUTH }, { "SSH_KEYS", CONF_SSH_KEYS }, { "AMANDAD_PATH", CONF_AMANDAD_PATH }, { "CLIENT_USERNAME", CONF_CLIENT_USERNAME }, + { "CLIENT_PORT", CONF_CLIENT_PORT }, { "GNUTAR_LIST_DIR", CONF_GNUTAR_LIST_DIR }, { "AMANDATES", CONF_AMANDATES }, { "KRB5KEYTAB", CONF_KRB5KEYTAB }, @@ -595,7 +752,10 @@ keytab_t client_keytab[] = { { "CONNECT_TRIES", CONF_CONNECT_TRIES }, { "REP_TRIES", CONF_REP_TRIES }, { "REQ_TRIES", CONF_REQ_TRIES }, + { "CLIENT", CONF_CLIENT }, + { "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 }, @@ -611,21 +771,61 @@ keytab_t client_keytab[] = { { "DEBUG_SELFCHECK", CONF_DEBUG_SELFCHECK }, { "DEBUG_SENDSIZE", CONF_DEBUG_SENDSIZE }, { "DEBUG_SENDBACKUP", CONF_DEBUG_SENDBACKUP }, - { "RESERVED-UDP-PORT", CONF_RESERVED_UDP_PORT }, - { "RESERVED-TCP-PORT", CONF_RESERVED_TCP_PORT }, - { "UNRESERVED-TCP-PORT", CONF_UNRESERVED_TCP_PORT }, - { NULL, CONF_UNKNOWN }, + { "EXECUTE_ON", CONF_EXECUTE_ON }, + { "EXECUTE_WHERE", CONF_EXECUTE_WHERE }, + { "RESERVED_UDP_PORT", CONF_RESERVED_UDP_PORT }, + { "RESERVED_TCP_PORT", CONF_RESERVED_TCP_PORT }, + { "UNRESERVED_TCP_PORT", CONF_UNRESERVED_TCP_PORT }, + { "DEFINE", CONF_DEFINE }, + { "COMMENT", CONF_COMMENT }, + { "MAILER", CONF_MAILER }, + { "ORDER", CONF_ORDER }, + { "SCRIPT", CONF_SCRIPT }, + { "SCRIPT_TOOL", CONF_SCRIPT_TOOL }, + { "PLUGIN", CONF_PLUGIN }, + { "PRE_DLE_AMCHECK", CONF_PRE_DLE_AMCHECK }, + { "PRE_HOST_AMCHECK", CONF_PRE_HOST_AMCHECK }, + { "POST_DLE_AMCHECK", CONF_POST_DLE_AMCHECK }, + { "POST_HOST_AMCHECK", CONF_POST_HOST_AMCHECK }, + { "PRE_DLE_ESTIMATE", CONF_PRE_DLE_ESTIMATE }, + { "PRE_HOST_ESTIMATE", CONF_PRE_HOST_ESTIMATE }, + { "POST_DLE_ESTIMATE", CONF_POST_DLE_ESTIMATE }, + { "POST_HOST_ESTIMATE", CONF_POST_HOST_ESTIMATE }, + { "POST_DLE_BACKUP", CONF_POST_DLE_BACKUP }, + { "POST_HOST_BACKUP", CONF_POST_HOST_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 }, + { "PRIORITY", CONF_PRIORITY }, + { "PROPERTY", CONF_PROPERTY }, + { "APPLICATION", CONF_APPLICATION }, + { "APPLICATION_TOOL", CONF_APPLICATION_TOOL }, + { "SERVER", CONF_SERVER }, + { "APPEND", CONF_APPEND }, + { NULL, CONF_IDENT }, + { NULL, CONF_UNKNOWN } }; keytab_t server_keytab[] = { + { "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 }, + { "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 }, @@ -633,6 +833,7 @@ keytab_t server_keytab[] = { { "BUMPPERCENT", CONF_BUMPPERCENT }, { "BUMPSIZE", CONF_BUMPSIZE }, { "CALCSIZE", CONF_CALCSIZE }, + { "CHANGER", CONF_CHANGER }, { "CHANGERDEV", CONF_CHANGERDEV }, { "CHANGERFILE", CONF_CHANGERFILE }, { "CHUNKSIZE", CONF_CHUNKSIZE }, @@ -648,7 +849,10 @@ keytab_t server_keytab[] = { { "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 }, @@ -665,8 +869,11 @@ keytab_t server_keytab[] = { { "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 }, @@ -674,16 +881,19 @@ keytab_t server_keytab[] = { { "DUMPORDER", CONF_DUMPORDER }, { "DUMPTYPE", CONF_DUMPTYPE }, { "DUMPUSER", CONF_DUMPUSER }, + { "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 }, + { "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 }, - { "FILE-PAD", CONF_FILE_PAD }, { "FILEMARK", CONF_FILEMARK }, { "FIRST", CONF_FIRST }, { "FIRSTFIT", CONF_FIRSTFIT }, @@ -707,65 +917,101 @@ keytab_t server_keytab[] = { { "LARGEST", CONF_LARGEST }, { "LARGESTFIT", CONF_LARGESTFIT }, { "LAST", CONF_LAST }, - { "LBL-TEMPL", CONF_LBL_TEMPL }, + { "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 }, { "MAXDUMPS", CONF_MAXDUMPS }, { "MAXDUMPSIZE", CONF_MAXDUMPSIZE }, { "MAXPROMOTEDAY", CONF_MAXPROMOTEDAY }, + { "MEMORY", CONF_MEMORY }, { "MEDIUM", CONF_MEDIUM }, { "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_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_DLE_AMCHECK", CONF_PRE_DLE_AMCHECK }, + { "PRE_HOST_AMCHECK", CONF_PRE_HOST_AMCHECK }, + { "POST_DLE_AMCHECK", CONF_POST_DLE_AMCHECK }, + { "POST_HOST_AMCHECK", CONF_POST_HOST_AMCHECK }, + { "PRE_DLE_ESTIMATE", CONF_PRE_DLE_ESTIMATE }, + { "PRE_HOST_ESTIMATE", CONF_PRE_HOST_ESTIMATE }, + { "POST_DLE_ESTIMATE", CONF_POST_DLE_ESTIMATE }, + { "POST_HOST_ESTIMATE", CONF_POST_HOST_ESTIMATE }, + { "POST_DLE_BACKUP", CONF_POST_DLE_BACKUP }, + { "POST_HOST_BACKUP", CONF_POST_HOST_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 }, { "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 }, + { "RESERVED_UDP_PORT", CONF_RESERVED_UDP_PORT }, + { "RESERVED_TCP_PORT", CONF_RESERVED_TCP_PORT }, { "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 }, + { "CLIENT_PORT", CONF_CLIENT_PORT }, { "SERVER", CONF_SERVER }, { "SERVER_CUSTOM_COMPRESS", CONF_SRVCOMPPROG }, { "SERVER_DECRYPT_OPTION", CONF_SRV_DECRYPT_OPT }, { "SERVER_ENCRYPT", CONF_SRV_ENCRYPT }, { "SKIP", CONF_SKIP }, - { "SKIP-FULL", CONF_SKIP_FULL }, - { "SKIP-INCR", CONF_SKIP_INCR }, + { "SKIP_FULL", CONF_SKIP_FULL }, + { "SKIP_INCR", CONF_SKIP_INCR }, { "SMALLEST", CONF_SMALLEST }, { "SPEED", CONF_SPEED }, { "SPLIT_DISKBUFFER", CONF_SPLIT_DISKBUFFER }, { "SSH_KEYS", CONF_SSH_KEYS }, { "STANDARD", CONF_STANDARD }, { "STARTTIME", CONF_STARTTIME }, + { "STRANGE", CONF_STRANGE }, { "STRATEGY", CONF_STRATEGY }, - { "TAPEBUFS", CONF_TAPEBUFS }, { "DEVICE_OUTPUT_BUFFER_SIZE", CONF_DEVICE_OUTPUT_BUFFER_SIZE }, { "TAPECYCLE", CONF_TAPECYCLE }, { "TAPEDEV", CONF_TAPEDEV }, { "TAPELIST", CONF_TAPELIST }, { "TAPERALGO", CONF_TAPERALGO }, - { "FLUSH-THRESHOLD-DUMPED", CONF_FLUSH_THRESHOLD_DUMPED }, - { "FLUSH-THRESHOLD-SCHEDULED", CONF_FLUSH_THRESHOLD_SCHEDULED }, + { "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 }, { "TPCHANGER", CONF_TPCHANGER }, - { "UNRESERVED-TCP-PORT", CONF_UNRESERVED_TCP_PORT }, + { "UNRESERVED_TCP_PORT", CONF_UNRESERVED_TCP_PORT }, { "USE", CONF_USE }, { "USETIMESTAMPS", CONF_USETIMESTAMPS }, + { "VOLUME_ERROR", CONF_VOLUME_ERROR }, { NULL, CONF_IDENT }, { NULL, CONF_UNKNOWN } }; @@ -804,6 +1050,14 @@ keytab_t numb_keytable[] = { { "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 }, @@ -838,14 +1092,18 @@ conf_var_t client_var [] = { { 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_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 }, @@ -864,6 +1122,9 @@ conf_var_t client_var [] = { { 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_property, CNF_PROPERTY , NULL }, + { CONF_APPLICATION , CONFTYPE_STR , read_dapplication, DUMPTYPE_APPLICATION, NULL }, + { CONF_SCRIPT , CONFTYPE_STR , read_dpp_script, DUMPTYPE_SCRIPTLIST, NULL }, { CONF_UNKNOWN , CONFTYPE_INT , NULL , CNF_CNF , NULL } }; @@ -872,8 +1133,10 @@ conf_var_t server_var [] = { { 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_property , CNF_DEVICE_PROPERTY , NULL }, + { CONF_PROPERTY , CONFTYPE_PROPLIST , read_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 , NULL }, @@ -884,35 +1147,38 @@ conf_var_t server_var [] = { { 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_positive }, - { CONF_BUMPSIZE , CONFTYPE_AM64 , read_am64 , CNF_BUMPSIZE , validate_positive }, + { 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_inparallel }, { CONF_DUMPORDER , CONFTYPE_STR , read_str , CNF_DUMPORDER , NULL }, { CONF_MAXDUMPS , CONFTYPE_INT , read_int , CNF_MAXDUMPS , validate_positive }, - { CONF_ETIMEOUT , CONFTYPE_INT , read_int , CNF_ETIMEOUT , NULL }, + { 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_TAPEBUFS , CONFTYPE_INT , read_int , CNF_TAPEBUFS , validate_positive }, - { CONF_DEVICE_OUTPUT_BUFFER_SIZE, CONFTYPE_SIZE , read_size , CNF_DEVICE_OUTPUT_BUFFER_SIZE, validate_positive }, + { CONF_DEVICE_OUTPUT_BUFFER_SIZE, CONFTYPE_SIZE , read_size_byte , CNF_DEVICE_OUTPUT_BUFFER_SIZE, validate_positive }, { CONF_COLUMNSPEC , CONFTYPE_STR , read_str , CNF_COLUMNSPEC , NULL }, { 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_BOOLEAN , read_bool , CNF_AUTOFLUSH , NULL }, { CONF_RESERVE , CONFTYPE_INT , read_int , CNF_RESERVE , validate_reserve }, - { CONF_MAXDUMPSIZE , CONFTYPE_AM64 , read_am64 , CNF_MAXDUMPSIZE , NULL }, + { 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 , NULL }, { 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 }, @@ -920,7 +1186,9 @@ conf_var_t server_var [] = { { 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 }, @@ -939,27 +1207,31 @@ conf_var_t server_var [] = { { 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_RECOVERY_LIMIT, read_recovery_limit, CNF_RECOVERY_LIMIT, 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_AM64 , read_am64 , TAPETYPE_LENGTH , validate_nonnegative }, - { CONF_FILEMARK , CONFTYPE_AM64 , read_am64 , TAPETYPE_FILEMARK , NULL }, - { CONF_SPEED , CONFTYPE_INT , read_int , TAPETYPE_SPEED , validate_nonnegative }, - { CONF_FILE_PAD , CONFTYPE_BOOLEAN , read_bool , TAPETYPE_FILE_PAD , NULL }, - { CONF_UNKNOWN , CONFTYPE_INT , NULL , TAPETYPE_TAPETYPE , NULL } + { 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_SECURITY_DRIVER , NULL }, + { CONF_AUTH , CONFTYPE_STR , read_str , DUMPTYPE_AUTH , NULL }, { CONF_BUMPDAYS , CONFTYPE_INT , read_int , DUMPTYPE_BUMPDAYS , NULL }, { CONF_BUMPMULT , CONFTYPE_REAL , read_real , DUMPTYPE_BUMPMULT , NULL }, - { CONF_BUMPSIZE , CONFTYPE_AM64 , read_am64 , DUMPTYPE_BUMPSIZE , NULL }, + { CONF_BUMPSIZE , CONFTYPE_INT64 , read_int64 , DUMPTYPE_BUMPSIZE , NULL }, { CONF_BUMPPERCENT , CONFTYPE_INT , read_int , DUMPTYPE_BUMPPERCENT , NULL }, { CONF_COMPRATE , CONFTYPE_REAL , read_rate , DUMPTYPE_COMPRATE , NULL }, { CONF_COMPRESS , CONFTYPE_INT , read_compress , DUMPTYPE_COMPRESS , NULL }, @@ -974,33 +1246,40 @@ conf_var_t dumptype_var [] = { { 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 , NULL }, + { CONF_PROGRAM , CONFTYPE_STR , read_str , DUMPTYPE_PROGRAM , validate_program }, + { CONF_PROPERTY , CONFTYPE_PROPLIST , read_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_AM64 , read_am64 , DUMPTYPE_TAPE_SPLITSIZE , validate_nonnegative }, + { 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_INT , read_estimate , DUMPTYPE_ESTIMATE , 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_AM64 , read_am64 , DUMPTYPE_FALLBACK_SPLITSIZE, 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_RECOVERY_LIMIT , CONFTYPE_RECOVERY_LIMIT, read_recovery_limit, DUMPTYPE_RECOVERY_LIMIT, 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_AM64 , read_am64 , HOLDING_DISKSIZE , validate_use }, - { CONF_CHUNKSIZE, CONFTYPE_AM64 , read_am64 , HOLDING_CHUNKSIZE, validate_chunksize }, + { 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 } }; @@ -1011,6 +1290,41 @@ conf_var_t interface_var [] = { }; +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_property, APPLICATION_PROPERTY , 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_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_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_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_property , CHANGER_CONFIG_PROPERTY , NULL }, + { CONF_DEVICE_PROPERTY , CONFTYPE_PROPLIST , read_property , CHANGER_CONFIG_DEVICE_PROPERTY, NULL }, + { CONF_UNKNOWN , CONFTYPE_INT , NULL , CHANGER_CONFIG_CHANGER_CONFIG , NULL } +}; + /* * Lexical Analysis Implementation */ @@ -1039,10 +1353,21 @@ lookup_keyword( char * str) { keytab_t *kwp; + char *str1 = stralloc(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, str) == 0) break; + if (strcasecmp(kwp->keyword, str1) == 0) break; } + + amfree(str1); return kwp->token; } @@ -1051,7 +1376,7 @@ get_conftoken( tok_t exp) { int ch, d; - off_t am64; + gint64 int64; char *buf; char *tmps; int token_overflow; @@ -1068,7 +1393,7 @@ get_conftoken( ** up again in the current keyword table. */ switch(tok) { - case CONF_AM64: case CONF_SIZE: + 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: @@ -1086,7 +1411,9 @@ get_conftoken( else { ch = conftoken_getc(); - while(ch != EOF && ch != '\n' && isspace(ch)) + /* 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') { @@ -1130,36 +1457,36 @@ get_conftoken( sign = 1; negative_number: /* look for goto negative_number below sign is set there */ - am64 = 0; + int64 = 0; do { - am64 = am64 * 10 + (ch - '0'); + 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)am64; + tokenval.v.i = sign * (int)int64; } else if (exp != CONF_REAL) { - tok = CONF_AM64; - tokenval.v.am64 = (off_t)sign * am64; + tok = CONF_INT64; + tokenval.v.int64 = (gint64)sign * int64; } else { /* automatically convert to real when expected */ - tokenval.v.r = (double)sign * (double)am64; + tokenval.v.r = (double)sign * (double)int64; tok = CONF_REAL; } } else { /* got a real number, not an int */ - tokenval.v.r = sign * (double) am64; - am64 = 0; + tokenval.v.r = sign * (double) int64; + int64 = 0; d = 1; ch = conftoken_getc(); while (isdigit(ch)) { - am64 = am64 * 10 + (ch - '0'); + int64 = int64 * 10 + (ch - '0'); d = d * 10; ch = conftoken_getc(); } - tokenval.v.r += sign * ((double)am64) / d; + tokenval.v.r += sign * ((double)int64) / d; tok = CONF_REAL; } @@ -1183,7 +1510,7 @@ negative_number: /* look for goto negative_number below sign is set there */ break; escape = 0; buf--; /* Consume escape in buffer */ - } else if (ch == '\\') { + } else if (ch == '\\' && !escape) { escape = 1; } else { if (ch == '"') { @@ -1367,10 +1694,11 @@ conftoken_ungetc( * Parser Implementation */ -static gboolean +static void read_conffile( char *filename, - gboolean is_client) + gboolean is_client, + gboolean missing_ok) { /* Save global locations. */ FILE *save_file = current_file; @@ -1385,12 +1713,14 @@ read_conffile( keytable = server_keytab; parsetable = server_var; } - current_filename = config_dir_relative(filename); + filename = config_dir_relative(filename); + current_filename = get_seen_filename(filename); + amfree(filename); if ((current_file = fopen(current_filename, "r")) == NULL) { - g_fprintf(stderr, _("could not open conf file \"%s\": %s\n"), current_filename, - strerror(errno)); - got_parserror = TRUE; + if (!missing_ok) + conf_parserror(_("could not open conf file \"%s\": %s"), + current_filename, strerror(errno)); goto finish; } @@ -1404,14 +1734,11 @@ read_conffile( afclose(current_file); finish: - amfree(current_filename); /* Restore servers */ current_line_num = save_line_num; current_file = save_file; current_filename = save_filename; - - return !got_parserror; } static gboolean @@ -1422,30 +1749,32 @@ read_confline( current_line_num += 1; get_conftoken(CONF_ANY); + handle_deprecated_keyword(); + switch(tok) { case CONF_INCLUDEFILE: get_conftoken(CONF_STRING); - if (!read_conffile(tokenval.v.s, is_client)) - return 0; - break; - - case CONF_HOLDING: - if (is_client) { - handle_invalid_keyword(tokenval.v.s); - } else { - get_holdingdisk(); - } + read_conffile(tokenval.v.s, is_client, FALSE); break; case CONF_DEFINE: if (is_client) { - handle_invalid_keyword(tokenval.v.s); + get_conftoken(CONF_ANY); + /* accept application-tool here, 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-TOOL or SCRIPT-TOOL 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 conf_parserror(_("DUMPTYPE, INTERFACE or TAPETYPE expected")); + 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 conf_parserror(_("DUMPTYPE, INTERFACE, TAPETYPE, HOLDINGDISK, APPLICATION-TOOL, SCRIPT-TOOL, DEVICE, or CHANGER expected")); } break; @@ -1477,43 +1806,71 @@ read_confline( } static void -handle_invalid_keyword( - const char * token) +handle_deprecated_keyword(void) { /* Procedure for deprecated keywords: - * 1) At time of deprecation, add to warning_deprecated below. - * Note the date of deprecation. - * 2) After two years, move the keyword to error_deprecated below. + * + * 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. - * 3) After two more years, drop the token entirely. */ + */ - static const char * warning_deprecated[] = { - "rawtapedev", /* 2007-01-23 */ - "tapebufs", /* 2007-10-15 */ - "netusage", /* historical since 1997-08-11, deprecated 2007-10-23 */ - NULL - }; + 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 */ + { 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; - for (s = warning_deprecated; *s != NULL; s ++) { - if (strcmp(*s, token) == 0) { - conf_parswarn(_("warning: Keyword %s is deprecated."), - token); - break; - } + /* convert '_' to '-' in TOKEN */ + folded_token = g_strdup(token); + for (p = folded_token; *p; p++) { + if (*p == '_') *p = '-'; } - if (*s == NULL) { - for (s = error_deprecated; *s != NULL; s ++) { - if (strcmp(*s, token) == 0) { - conf_parserror(_("error: Keyword %s is deprecated."), - token); - return; - } - } + + 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")); } @@ -1529,16 +1886,38 @@ handle_invalid_keyword( 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 || 0 == strcmp(istr, filename)) + return istr; + } + + istr = stralloc(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)) + void (*copy_function)(void), + char *type, + char *name) { conf_var_t *np; - int done; + int done; + char *key_ovr; + int i; if(read_brace) { get_conftoken(CONF_LBRACE); @@ -1549,6 +1928,8 @@ read_block( do { current_line_num += 1; get_conftoken(CONF_ANY); + handle_deprecated_keyword(); + switch(tok) { case CONF_RBRACE: done = 1; @@ -1573,7 +1954,7 @@ read_block( if(np->token == tok) break; if(np->token == CONF_UNKNOWN) - conf_parserror(errormsg); + conf_parserror("%s", errormsg); else { np->read_function(np, &valarray[np->parm]); if(np->validate_function) @@ -1584,11 +1965,78 @@ read_block( if(tok != CONF_NL && tok != CONF_END && tok != CONF_RBRACE) get_conftoken(CONF_NL); } while(!done); + + if (!config_overrides) + return; + + key_ovr = vstralloc(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; + keytab_t *kt; + + if (key_ovr && 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; + + /* find the token in keytable */ + for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) { + if (kt->keyword && strcasecmp(kt->keyword, keyword) == 0) + break; + } + if (kt->token == CONF_UNKNOWN) + continue; + + /* find the var in read_var */ + for (np = read_var; np->token != CONF_UNKNOWN; np++) + if (np->token == kt->token) 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 = stralloc(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; + } + 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( - void) + int is_define) { int save_overwrites; @@ -1599,12 +2047,60 @@ get_holdingdisk( get_conftoken(CONF_IDENT); hdcur.name = stralloc(tokenval.v.s); - hdcur.seen = current_line_num; + hdcur.seen.filename = current_filename; + hdcur.seen.linenum = current_line_num; - read_block(holding_var, hdcur.value, - _("holding disk parameter expected"), 1, NULL); - get_conftoken(CONF_NL); - save_holdingdisk(); + 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, + stralloc(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 (strcmp((char *)il->data, hdcur.name) == 0) { + 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, + stralloc(hdcur.name)); + } + amfree(hdcur.name); + get_conftoken(CONF_ANY); + if (tok == CONF_IDENT || tok == CONF_STRING) { + hdcur.name = stralloc(tokenval.v.s); + } else if (tok != CONF_NL) { + conf_parserror(_("IDENT or NL expected")); + } + } while (tok == CONF_IDENT || tok == CONF_STRING); + } allow_overwrites = save_overwrites; } @@ -1615,9 +2111,9 @@ init_holdingdisk_defaults( { conf_init_str(&hdcur.value[HOLDING_COMMENT] , ""); conf_init_str(&hdcur.value[HOLDING_DISKDIR] , ""); - conf_init_am64(&hdcur.value[HOLDING_DISKSIZE] , (off_t)0); + conf_init_int64(&hdcur.value[HOLDING_DISKSIZE] , (gint64)0); /* 1 Gb = 1M counted in 1Kb blocks */ - conf_init_am64(&hdcur.value[HOLDING_CHUNKSIZE], (off_t)1024*1024); + conf_init_int64(&hdcur.value[HOLDING_CHUNKSIZE], (gint64)1024*1024); } static void @@ -1628,8 +2124,29 @@ save_holdingdisk( hp = alloc(sizeof(holdingdisk_t)); *hp = hdcur; - hp->next = holdinglist; - holdinglist = hp; + 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]); + } + } + } @@ -1654,7 +2171,7 @@ read_dumptype( if (fname) { saved_fname = current_filename; - current_filename = fname; + current_filename = get_seen_filename(fname); } if (linenum) @@ -1670,11 +2187,13 @@ read_dumptype( get_conftoken(CONF_IDENT); dpcur.name = stralloc(tokenval.v.s); } - dpcur.seen = current_line_num; + dpcur.seen.filename = current_filename; + dpcur.seen.linenum = current_line_num; read_block(dumptype_var, dpcur.value, _("dumptype parameter expected"), - (name == NULL), copy_dumptype); + (name == NULL), copy_dumptype, + "DUMPTYPE", dpcur.name); if(!name) /* !name => reading disklist, not conffile */ get_conftoken(CONF_NL); @@ -1714,10 +2233,11 @@ init_dumptype_defaults(void) 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] , "X"); - conf_init_str (&dpcur.value[DUMPTYPE_CLIENT_USERNAME] , "X"); - conf_init_str (&dpcur.value[DUMPTYPE_SSH_KEYS] , "X"); - conf_init_str (&dpcur.value[DUMPTYPE_SECURITY_DRIVER] , "BSD"); + 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_SSH_KEYS] , ""); + conf_init_str (&dpcur.value[DUMPTYPE_AUTH] , "BSD"); conf_init_exinclude(&dpcur.value[DUMPTYPE_EXCLUDE]); conf_init_exinclude(&dpcur.value[DUMPTYPE_INCLUDE]); conf_init_priority (&dpcur.value[DUMPTYPE_PRIORITY] , 1); @@ -1725,19 +2245,20 @@ init_dumptype_defaults(void) conf_init_int (&dpcur.value[DUMPTYPE_MAXDUMPS] , conf_data[CNF_MAXDUMPS].v.i); conf_init_int (&dpcur.value[DUMPTYPE_MAXPROMOTEDAY] , 10000); conf_init_int (&dpcur.value[DUMPTYPE_BUMPPERCENT] , conf_data[CNF_BUMPPERCENT].v.i); - conf_init_am64 (&dpcur.value[DUMPTYPE_BUMPSIZE] , conf_data[CNF_BUMPSIZE].v.am64); + conf_init_int64 (&dpcur.value[DUMPTYPE_BUMPSIZE] , conf_data[CNF_BUMPSIZE].v.int64); conf_init_int (&dpcur.value[DUMPTYPE_BUMPDAYS] , 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_estimate (&dpcur.value[DUMPTYPE_ESTIMATE] , ES_CLIENT); + 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_am64 (&dpcur.value[DUMPTYPE_TAPE_SPLITSIZE] , (off_t)0); - conf_init_am64 (&dpcur.value[DUMPTYPE_FALLBACK_SPLITSIZE], (off_t)10 * 1024); + conf_init_int64 (&dpcur.value[DUMPTYPE_TAPE_SPLITSIZE] , (gint64)0); + conf_init_int64 (&dpcur.value[DUMPTYPE_FALLBACK_SPLITSIZE], (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); @@ -1746,6 +2267,11 @@ init_dumptype_defaults(void) 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_recovery_limit(&dpcur.value[DUMPTYPE_RECOVERY_LIMIT]); } static void @@ -1756,7 +2282,12 @@ save_dumptype(void) dp = lookup_dumptype(dpcur.name); if(dp != (dumptype_t *)0) { - conf_parserror(_("dumptype %s already defined on line %d"), dp->name, dp->seen); + 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; } @@ -1789,9 +2320,12 @@ copy_dumptype(void) } for(i=0; i < DUMPTYPE_DUMPTYPE; i++) { - if(dt->value[i].seen) { - free_val_t(&dpcur.value[i]); - copy_val_t(&dpcur.value[i], &dt->value[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); + } } } } @@ -1808,10 +2342,12 @@ get_tapetype(void) get_conftoken(CONF_IDENT); tpcur.name = stralloc(tokenval.v.s); - tpcur.seen = current_line_num; + tpcur.seen.filename = current_filename; + tpcur.seen.linenum = current_line_num; read_block(tapetype_var, tpcur.value, - _("tapetype parameter expected"), 1, copy_tapetype); + _("tapetype parameter expected"), 1, copy_tapetype, + "TAPETYPE", tpcur.name); get_conftoken(CONF_NL); if (tapetype_get_readblocksize(&tpcur) < @@ -1830,11 +2366,14 @@ init_tapetype_defaults(void) conf_init_str(&tpcur.value[TAPETYPE_COMMENT] , ""); conf_init_str(&tpcur.value[TAPETYPE_LBL_TEMPL] , ""); conf_init_size (&tpcur.value[TAPETYPE_BLOCKSIZE] , DISK_BLOCK_KB); - conf_init_size (&tpcur.value[TAPETYPE_READBLOCKSIZE], MAX_TAPE_BLOCK_KB); - conf_init_am64 (&tpcur.value[TAPETYPE_LENGTH] , ((off_t)2000 * 1024)); - conf_init_am64 (&tpcur.value[TAPETYPE_FILEMARK] , (off_t)1000); + conf_init_size (&tpcur.value[TAPETYPE_READBLOCKSIZE], DISK_BLOCK_KB); + conf_init_int64 (&tpcur.value[TAPETYPE_LENGTH] , ((gint64)2000)); + conf_init_int64 (&tpcur.value[TAPETYPE_FILEMARK] , (gint64)1); conf_init_int (&tpcur.value[TAPETYPE_SPEED] , 200); - conf_init_bool (&tpcur.value[TAPETYPE_FILE_PAD] , 1); + conf_init_int64(&tpcur.value[TAPETYPE_PART_SIZE], 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], 0); } static void @@ -1846,12 +2385,14 @@ save_tapetype(void) if(tp != (tapetype_t *)0) { amfree(tpcur.name); - conf_parserror(_("tapetype %s already defined on line %d"), tp->name, tp->seen); + conf_parserror(_("tapetype %s already defined at %s:%d"), + tp->name, tp->seen.filename, tp->seen.linenum); return; } tp = alloc(sizeof(tapetype_t)); *tp = tpcur; + /* add at end of list */ if(!tapelist) tapelist = tp; @@ -1878,9 +2419,8 @@ copy_tapetype(void) } for(i=0; i < TAPETYPE_TAPETYPE; i++) { - if(tp->value[i].seen) { - free_val_t(&tpcur.value[i]); - copy_val_t(&tpcur.value[i], &tp->value[i]); + if(tp->value[i].seen.linenum) { + merge_val_t(&tpcur.value[i], &tp->value[i]); } } } @@ -1897,10 +2437,12 @@ get_interface(void) get_conftoken(CONF_IDENT); ifcur.name = stralloc(tokenval.v.s); - ifcur.seen = current_line_num; + ifcur.seen.filename = current_filename; + ifcur.seen.linenum = current_line_num; read_block(interface_var, ifcur.value, - _("interface parameter expected"), 1, copy_interface); + _("interface parameter expected"), 1, copy_interface, + "INTERFACE", ifcur.name); get_conftoken(CONF_NL); save_interface(); @@ -1925,8 +2467,8 @@ save_interface(void) ip = lookup_interface(ifcur.name); if(ip != (interface_t *)0) { - conf_parserror(_("interface %s already defined on line %d"), ip->name, - ip->seen); + conf_parserror(_("interface %s already defined at %s:%d"), + ip->name, ip->seen.filename, ip->seen.linenum); return; } @@ -1958,73 +2500,583 @@ copy_interface(void) } for(i=0; i < INTER_INTER; i++) { - if(ip->value[i].seen) { - free_val_t(&ifcur.value[i]); - copy_val_t(&ifcur.value[i], &ip->value[i]); + if(ip->value[i].seen.linenum) { + merge_val_t(&ifcur.value[i], &ip->value[i]); } } } -/* Read functions */ -static void -read_int( - conf_var_t *np G_GNUC_UNUSED, - val_t *val) +application_t * +read_application( + char *name, + FILE *from, + char *fname, + int *linenum) { - ckseen(&val->seen); - val_t__int(val) = get_int(); -} + int save_overwrites; + FILE *saved_conf = NULL; + char *saved_fname = NULL; -static void -read_am64( - conf_var_t *np G_GNUC_UNUSED, - val_t *val) -{ - ckseen(&val->seen); - val_t__am64(val) = get_am64_t(); + 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; + + save_overwrites = allow_overwrites; + allow_overwrites = 1; + + init_application_defaults(); + if (name) { + apcur.name = name; + } else { + get_conftoken(CONF_IDENT); + apcur.name = stralloc(tokenval.v.s); + } + 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; + + 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 -read_real( - conf_var_t *np G_GNUC_UNUSED, - val_t *val) +get_application( + void) { - ckseen(&val->seen); - get_conftoken(CONF_REAL); - val_t__real(val) = tokenval.v.r; + read_application(NULL, NULL, NULL, NULL); } static void -read_str( - conf_var_t *np G_GNUC_UNUSED, - val_t *val) +init_application_defaults( + void) { - ckseen(&val->seen); - get_conftoken(CONF_STRING); - val->v.s = newstralloc(val->v.s, tokenval.v.s); + apcur.name = NULL; + conf_init_str(&apcur.value[APPLICATION_COMMENT] , ""); + conf_init_str(&apcur.value[APPLICATION_PLUGIN] , ""); + conf_init_proplist(&apcur.value[APPLICATION_PROPERTY]); } static void -read_ident( - conf_var_t *np G_GNUC_UNUSED, - val_t *val) +save_application( + void) { - ckseen(&val->seen); - get_conftoken(CONF_IDENT); - val->v.s = newstralloc(val->v.s, tokenval.v.s); + 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 = alloc(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 -read_time( - conf_var_t *np G_GNUC_UNUSED, - val_t *val) +copy_application(void) { - ckseen(&val->seen); - val_t__time(val) = get_time(); -} + application_t *ap; + int i; -static void + 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]); + } + } +} + +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; + + 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; + + save_overwrites = allow_overwrites; + allow_overwrites = 1; + + init_pp_script_defaults(); + if (name) { + pscur.name = name; + } else { + get_conftoken(CONF_IDENT); + pscur.name = stralloc(tokenval.v.s); + } + 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; + + 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; + 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], ES_CLIENT); + conf_init_int(&pscur.value[PP_SCRIPT_ORDER], 5000); +} + +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 = alloc(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]); + } + } +} + +device_config_t * +read_device_config( + char *name, + FILE *from, + char *fname, + int *linenum) +{ + int save_overwrites; + 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; + + save_overwrites = allow_overwrites; + allow_overwrites = 1; + + init_device_config_defaults(); + if (name) { + dccur.name = name; + } else { + get_conftoken(CONF_IDENT); + dccur.name = stralloc(tokenval.v.s); + } + 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; + + 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; + 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 = alloc(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]); + } + } +} + +changer_config_t * +read_changer_config( + char *name, + FILE *from, + char *fname, + int *linenum) +{ + int save_overwrites; + 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; + + save_overwrites = allow_overwrites; + allow_overwrites = 1; + + init_changer_config_defaults(); + if (name) { + cccur.name = name; + } else { + get_conftoken(CONF_IDENT); + cccur.name = stralloc(tokenval.v.s); + } + cccur.seen = 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; + + 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; + 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 on line %d"), + dc->name, dc->seen); + return; + } + + dc = alloc(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(); +} + +static void +read_int64( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + ckseen(&val->seen); + val_t__int64(val) = get_int64(); +} + +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); + val->v.s = newstralloc(val->v.s, tokenval.v.s); +} + +static void +read_ident( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + ckseen(&val->seen); + get_conftoken(CONF_IDENT); + val->v.s = newstralloc(val->v.s, tokenval.v.s); +} + +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) @@ -2033,6 +3085,15 @@ read_size( val_t__size(val) = get_size(); } +static void +read_size_byte( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + ckseen(&val->seen); + val_t__size(val) = get_size_byte(); +} + static void read_bool( conf_var_t *np G_GNUC_UNUSED, @@ -2171,30 +3232,34 @@ read_holding( } static void -read_estimate( +read_estimatelist( conf_var_t *np G_GNUC_UNUSED, val_t *val) { - int estime; + estimatelist_t estimates = NULL; ckseen(&val->seen); get_conftoken(CONF_ANY); - switch(tok) { - case CONF_CLIENT: - estime = ES_CLIENT; - break; - case CONF_SERVER: - estime = ES_SERVER; - break; - case CONF_CALCSIZE: - estime = ES_CALCSIZE; - break; - default: - conf_parserror(_("CLIENT, SERVER or CALCSIZE expected")); - estime = ES_CLIENT; - } - val_t__estimate(val) = estime; + 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); + val_t__estimatelist(val) = estimates; } static void @@ -2253,6 +3318,40 @@ read_taperalgo( } } +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__send_amreport(val) = DATA_PATH_AMANDA ; break; + case CONF_DIRECTTCP: val_t__send_amreport(val) = DATA_PATH_DIRECTTCP; break; + default: + conf_parserror(_("AMANDA or DIRECTTCP expected")); + } +} + static void read_priority( conf_var_t *np G_GNUC_UNUSED, @@ -2376,36 +3475,346 @@ read_intrange( case CONF_NL: return; - case CONF_END: - 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_property( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + char *key; + property_t *property = malloc(sizeof(property_t)); + property_t *old_property; + property->append = 0; + property->priority = 0; + property->values = NULL; + + 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_STRING) { + conf_parserror(_("key expected")); + 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(); + return; + } + if (tok != CONF_STRING) { + conf_parserror(_("value expected")); + return; + } + + if(val->seen.linenum == 0) { + val->seen.filename = current_filename; + val->seen.linenum = current_line_num; + } + + 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; + } + } + while(tok == CONF_STRING) { + property->values = g_slist_append(property->values, + strdup(tokenval.v.s)); + get_conftoken(CONF_ANY); + } + unget_conftoken(); + g_hash_table_insert(val->v.proplist, key, property); +} + + +static void +read_dapplication( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + application_t *application; + + get_conftoken(CONF_ANY); + if (tok == CONF_LBRACE) { + current_line_num -= 1; + application = read_application(vstralloc("custom(DUMPTYPE:", + dpcur.name, ")", ".", + anonymous_value(),NULL), + NULL, NULL, NULL); + current_line_num -= 1; + } else if (tok == CONF_STRING) { + application = lookup_application(tokenval.v.s); + if (application == NULL) { + conf_parserror(_("Unknown application named: %s"), tokenval.v.s); + return; + } + } else { + conf_parserror(_("application name expected: %d %d"), tok, CONF_STRING); + return; + } + amfree(val->v.s); + val->v.s = stralloc(application->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(vstralloc("custom(DUMPTYPE:", dpcur.name, + ")", ".", anonymous_value(),NULL), + NULL, NULL, NULL); + current_line_num -= 1; + val->v.identlist = g_slist_insert_sorted(val->v.identlist, + stralloc(pp_script->name), &compare_pp_script_order); + } else if (tok == CONF_STRING || tok == CONF_IDENT) { + while (tok == CONF_STRING || tok == CONF_IDENT) { + 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, + stralloc(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_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_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_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_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 = ES_CLIENT; break; + case CONF_SERVER: val->v.i = ES_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: + val->v.s = newstralloc(val->v.s, tokenval.v.s); + break; + default: + conf_parserror(_("CLIENT or SERVER 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++; + val->v.autolabel.template = newstralloc(val->v.autolabel.template, + 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_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_COMMA: - break; + case CONF_DISK: + part_cache_type = PART_CACHE_TYPE_DISK; + break; - default: - unget_conftoken(); - } + case CONF_MEMORY: + part_cache_type = PART_CACHE_TYPE_MEMORY; + break; - get_conftoken(CONF_INT); - val_t__intrange(val)[1] = tokenval.v.i; + 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_property( +read_recovery_limit( conf_var_t *np G_GNUC_UNUSED, val_t *val) { - char *key, *value; - get_conftoken(CONF_STRING); - key = strdup(tokenval.v.s); - get_conftoken(CONF_STRING); - value = strdup(tokenval.v.s); + recovery_limit_t *rl = &val_t__recovery_limit(val); + ckseen(&val->seen); + + 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_NL: + case CONF_END: + return; - g_hash_table_insert(val_t__proplist(val), key, value); + default: + conf_parserror("SAME-HOST or a string expected"); + break; + } + } } /* 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) { @@ -2415,7 +3824,7 @@ get_time(void) switch(tok) { case CONF_INT: #if SIZEOF_TIME_T < SIZEOF_INT - if ((off_t)tokenval.v.i >= (off_t)TIME_MAX) + if ((gint64)tokenval.v.i >= (gint64)TIME_MAX) conf_parserror(_("value too large")); #endif hhmm = (time_t)tokenval.v.i; @@ -2423,18 +3832,18 @@ get_time(void) case CONF_SIZE: #if SIZEOF_TIME_T < SIZEOF_SSIZE_T - if ((off_t)tokenval.v.size >= (off_t)TIME_MAX) + if ((gint64)tokenval.v.size >= (gint64)TIME_MAX) conf_parserror(_("value too large")); #endif hhmm = (time_t)tokenval.v.size; break; - case CONF_AM64: -#if SIZEOF_TIME_T < SIZEOF_LONG_LONG - if ((off_t)tokenval.v.am64 >= (off_t)TIME_MAX) + 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.am64; + hhmm = (time_t)tokenval.v.int64; break; case CONF_AMINFINITY: @@ -2466,22 +3875,22 @@ get_int(void) case CONF_SIZE: #if SIZEOF_INT < SIZEOF_SSIZE_T - if ((off_t)tokenval.v.size > (off_t)INT_MAX) + if ((gint64)tokenval.v.size > (gint64)INT_MAX) conf_parserror(_("value too large")); - if ((off_t)tokenval.v.size < (off_t)INT_MIN) + if ((gint64)tokenval.v.size < (gint64)INT_MIN) conf_parserror(_("value too small")); #endif val = (int)tokenval.v.size; break; - case CONF_AM64: -#if SIZEOF_INT < SIZEOF_LONG_LONG - if (tokenval.v.am64 > (off_t)INT_MAX) + case CONF_INT64: +#if SIZEOF_INT < SIZEOF_GINT64 + if (tokenval.v.int64 > (gint64)INT_MAX) conf_parserror(_("value too large")); - if (tokenval.v.am64 < (off_t)INT_MIN) + if (tokenval.v.int64 < (gint64)INT_MIN) conf_parserror(_("value too small")); #endif - val = (int)tokenval.v.am64; + val = (int)tokenval.v.int64; break; case CONF_AMINFINITY: @@ -2527,6 +3936,14 @@ get_int(void) val *= 1024 * 1024; break; + case CONF_MULT1T: + if (val > (INT_MAX / (1024 * 1024 * 1024))) + conf_parserror(_("value too large")); + if (val < (INT_MIN / (1024 * 1024 * 1024))) + conf_parserror(_("value too small")); + val *= 1024 * 1024 * 1024; + break; + default: /* it was not a multiplier */ unget_conftoken(); break; @@ -2554,22 +3971,22 @@ get_size(void) case CONF_INT: #if SIZEOF_SIZE_T < SIZEOF_INT - if ((off_t)tokenval.v.i > (off_t)SSIZE_MAX) + if ((gint64)tokenval.v.i > (gint64)SSIZE_MAX) conf_parserror(_("value too large")); - if ((off_t)tokenval.v.i < (off_t)SSIZE_MIN) + if ((gint64)tokenval.v.i < (gint64)SSIZE_MIN) conf_parserror(_("value too small")); #endif val = (ssize_t)tokenval.v.i; break; - case CONF_AM64: -#if SIZEOF_SIZE_T < SIZEOF_LONG_LONG - if (tokenval.v.am64 > (off_t)SSIZE_MAX) + case CONF_INT64: +#if SIZEOF_SIZE_T < SIZEOF_GINT64 + if (tokenval.v.int64 > (gint64)SSIZE_MAX) conf_parserror(_("value too large")); - if (tokenval.v.am64 < (off_t)SSIZE_MIN) + if (tokenval.v.int64 < (gint64)SSIZE_MIN) conf_parserror(_("value too small")); #endif - val = (ssize_t)tokenval.v.am64; + val = (ssize_t)tokenval.v.int64; break; case CONF_AMINFINITY: @@ -2615,6 +4032,111 @@ get_size(void) val *= (ssize_t)(1024 * 1024); break; + case CONF_MULT1T: + if (val > (INT_MAX / (1024 * 1024 * 1024))) + conf_parserror(_("value too large")); + if (val < (INT_MIN / (1024 * 1024 * 1024))) + conf_parserror(_("value too small")); + val *= 1024 * 1024 * 1024; + break; + + default: /* it was not a multiplier */ + unget_conftoken(); + break; + } + + keytable = save_kt; + return val; +} + +static ssize_t +get_size_byte(void) +{ + 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 */ + get_conftoken(CONF_ANY); + + switch(tok) { + case CONF_NL: /* multiply by one */ + case CONF_MULT1: + break; + case CONF_MULT1K: + if (val > (ssize_t)(SSIZE_MAX / (ssize_t)1024)) + conf_parserror(_("value too large")); + if (val < (ssize_t)(SSIZE_MIN / (ssize_t)1024)) + conf_parserror(_("value too small")); + val *= (ssize_t)1024; + + case CONF_MULT7: + if (val > (ssize_t)(SSIZE_MAX / 7)) + conf_parserror(_("value too large")); + if (val < (ssize_t)(SSIZE_MIN / 7)) + conf_parserror(_("value too small")); + val *= (ssize_t)7; + break; + + case CONF_MULT1M: + if (val > (ssize_t)(SSIZE_MAX / (ssize_t)1024 * 1024)) + conf_parserror(_("value too large")); + if (val < (ssize_t)(SSIZE_MIN / (ssize_t)1024 * 1024)) + conf_parserror(_("value too small")); + val *= (ssize_t)(1024 * 1024); + break; + + case CONF_MULT1G: + if (val > (ssize_t)(SSIZE_MAX / (1024 * 1024 * 1024))) + conf_parserror(_("value too large")); + if (val < (ssize_t)(SSIZE_MIN / (1024 * 1024 * 1024))) + conf_parserror(_("value too small")); + val *= (ssize_t)(1024 * 1024 * 1024); + break; + + case CONF_MULT1T: + conf_parserror(_("value too large")); + break; + default: /* it was not a multiplier */ unget_conftoken(); break; @@ -2624,10 +4146,10 @@ get_size(void) return val; } -static off_t -get_am64_t(void) +static gint64 +get_int64(void) { - off_t val; + gint64 val; keytab_t *save_kt; save_kt = keytable; @@ -2637,19 +4159,19 @@ get_am64_t(void) switch(tok) { case CONF_INT: - val = (off_t)tokenval.v.i; + val = (gint64)tokenval.v.i; break; case CONF_SIZE: - val = (off_t)tokenval.v.size; + val = (gint64)tokenval.v.size; break; - case CONF_AM64: - val = tokenval.v.am64; + case CONF_INT64: + val = tokenval.v.int64; break; case CONF_AMINFINITY: - val = AM64_MAX; + val = G_MAXINT64; break; default: @@ -2668,23 +4190,29 @@ get_am64_t(void) break; case CONF_MULT7: - if (val > AM64_MAX/7 || val < AM64_MIN/7) + if (val > G_MAXINT64/7 || val < ((gint64)G_MININT64)/7) conf_parserror(_("value too large")); val *= 7; break; case CONF_MULT1M: - if (val > AM64_MAX/1024 || val < AM64_MIN/1024) + if (val > G_MAXINT64/1024 || val < ((gint64)G_MININT64)/1024) conf_parserror(_("value too large")); val *= 1024; break; case CONF_MULT1G: - if (val > AM64_MAX/(1024*1024) || val < AM64_MIN/(1024*1024)) + if (val > G_MAXINT64/(1024*1024) || val < ((gint64)G_MININT64)/(1024*1024)) conf_parserror(_("value too large")); val *= 1024*1024; break; + case CONF_MULT1T: + if (val > G_MAXINT64/(1024*1024*1024) || val < ((gint64)G_MININT64)/(1024*1024*1024)) + conf_parserror(_("value too large")); + val *= 1024*1024*1024; + break; + default: /* it was not a multiplier */ unget_conftoken(); break; @@ -2721,8 +4249,8 @@ get_bool(void) val = 0; break; - case CONF_AM64: - if (tokenval.v.am64 != (off_t)0) + case CONF_INT64: + if (tokenval.v.int64 != (gint64)0) val = 1; else val = 0; @@ -2743,7 +4271,7 @@ get_bool(void) default: unget_conftoken(); val = 3; /* a bad argument - most likely TRUE */ - conf_parserror(_("YES, NO, TRUE, FALSE, ON, OFF expected")); + conf_parserror(_("YES, NO, TRUE, FALSE, ON, OFF, 0, 1 expected")); break; } @@ -2753,12 +4281,14 @@ get_bool(void) void ckseen( - int *seen) + seen_t *seen) { - if (*seen && !allow_overwrites && current_line_num != -2) { - conf_parserror(_("duplicate parameter, prev def on line %d"), *seen); + if (seen->linenum && !allow_overwrites && current_line_num != -2) { + conf_parserror(_("duplicate parameter; previous definition %s:%d"), + seen->filename, seen->linenum); } - *seen = current_line_num; + seen->filename = current_filename; + seen->linenum = current_line_num; } /* Validation functions */ @@ -2773,8 +4303,8 @@ validate_nonnegative( if(val_t__int(val) < 0) conf_parserror(_("%s must be nonnegative"), get_token_name(np->token)); break; - case CONFTYPE_AM64: - if(val_t__am64(val) < 0) + case CONFTYPE_INT64: + if(val_t__int64(val) < 0) conf_parserror(_("%s must be nonnegative"), get_token_name(np->token)); break; case CONFTYPE_SIZE: @@ -2786,6 +4316,33 @@ validate_nonnegative( } } +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, @@ -2796,8 +4353,8 @@ validate_positive( if(val_t__int(val) < 1) conf_parserror(_("%s must be positive"), get_token_name(np->token)); break; - case CONFTYPE_AM64: - if(val_t__am64(val) < 1) + case CONFTYPE_INT64: + if(val_t__int64(val) < 1) conf_parserror(_("%s must be positive"), get_token_name(np->token)); break; case CONFTYPE_TIME: @@ -2894,7 +4451,7 @@ validate_use( struct conf_var_s *np G_GNUC_UNUSED, val_t *val) { - val_t__am64(val) = am_floor(val_t__am64(val), DISK_BLOCK_KB); + val_t__int64(val) = am_floor(val_t__int64(val), DISK_BLOCK_KB); } static void @@ -2903,14 +4460,14 @@ validate_chunksize( val_t *val) { /* NOTE: this function modifies the target value (rounding) */ - if(val_t__am64(val) == 0) { - val_t__am64(val) = ((AM64_MAX / 1024) - (2 * DISK_BLOCK_KB)); + if(val_t__int64(val) == 0) { + val_t__int64(val) = ((G_MAXINT64 / 1024) - (2 * DISK_BLOCK_KB)); } - else if(val_t__am64(val) < 0) { - conf_parserror(_("Negative chunksize (%lld) is no longer supported"), (long long)val_t__am64(val)); + else if(val_t__int64(val) < 0) { + conf_parserror(_("Negative chunksize (%lld) is no longer supported"), (long long)val_t__int64(val)); } - val_t__am64(val) = am_floor(val_t__am64(val), (off_t)DISK_BLOCK_KB); - if (val_t__am64(val) < 2*DISK_BLOCK_KB) { + 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); } } @@ -2976,7 +4533,7 @@ validate_unreserved_port_range( * Initialization Implementation */ -gboolean +cfgerr_level_t config_init( config_init_flags flags, char *arg_config_name) @@ -3001,6 +4558,13 @@ config_init( /* 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 (0 == strcmp(arg_config_name, ".")) + flags = (flags & (~CONFIG_INIT_EXPLICIT_NAME)) | CONFIG_INIT_USE_CWD; + } + if ((flags & CONFIG_INIT_EXPLICIT_NAME) && arg_config_name) { config_name = newstralloc(config_name, arg_config_name); config_dir = newvstralloc(config_dir, CONFIG_DIR, "/", arg_config_name, NULL); @@ -3029,6 +4593,25 @@ config_init( 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 */ + apply_config_overrides(config_overrides, NULL); + /* If we have a config_dir, we can try reading something */ if (config_dir) { if (flags & CONFIG_INIT_CLIENT) { @@ -3037,49 +4620,60 @@ config_init( config_filename = newvstralloc(config_filename, config_dir, "/amanda.conf", NULL); } - /* try to read the file, and handle parse errors */ - if (!read_conffile(config_filename, flags & CONFIG_INIT_CLIENT)) { - if (flags & CONFIG_INIT_FATAL) { - error(_("errors processing config file \"%s\""), config_filename); - /* NOTREACHED */ - } else { - g_warning(_("errors processing config file \"%s\" (non-fatal)"), config_filename); - return FALSE; - } - } + read_conffile(config_filename, + flags & CONFIG_INIT_CLIENT, + flags & CONFIG_INIT_CLIENT); } else { amfree(config_filename); } + /* apply config overrides to default setting */ + apply_config_overrides(config_overrides, NULL); + + 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 TRUE; + return cfgerr_level; } void config_uninit(void) { - holdingdisk_t *hp, *hpnext; + 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; int i; if (!config_initialized) return; - for(hp=holdinglist; hp != NULL; hp = hpnext) { - amfree(hp->name); - for(i=0; ivalue[i]); + for(hp=holdinglist; hp != NULL; hp = hp->next) { + hd = hp->data; + amfree(hd->name); + for(i=0; ivalue[i]); } - hpnext = hp->next; - amfree(hp); } + g_slist_free_full(holdinglist); holdinglist = NULL; for(dp=dumplist; dp != NULL; dp = dpnext) { amfree(dp->name); - for(i=0; ivalue[i]); } dpnext = dp->next; @@ -3089,7 +4683,7 @@ config_uninit(void) for(tp=tapelist; tp != NULL; tp = tpnext) { amfree(tp->name); - for(i=0; ivalue[i]); } tpnext = tp->next; @@ -3099,7 +4693,7 @@ config_uninit(void) for(ip=interface_list; ip != NULL; ip = ipnext) { amfree(ip->name); - for(i=0; ivalue[i]); } ipnext = ip->next; @@ -3107,19 +4701,65 @@ config_uninit(void) } interface_list = NULL; - for(i=0; iname); + for(i=0; ivalue[i]); + } + apnext = ap->next; + amfree(ap); + } + application_list = NULL; + + for(pp=pp_script_list; pp != NULL; pp = ppnext) { + amfree(pp->name); + for(i=0; ivalue[i]); + } + ppnext = pp->next; + amfree(pp); + } + pp_script_list = NULL; + + for(dc=device_config_list; dc != NULL; dc = dcnext) { + amfree(dc->name); + for(i=0; ivalue[i]); + } + dcnext = dc->next; + amfree(dc); + } + device_config_list = NULL; + + for(cc=changer_config_list; cc != NULL; cc = ccnext) { + amfree(cc->name); + for(i=0; ivalue[i]); + } + ccnext = cc->next; + amfree(cc); + } + + changer_config_list = NULL; + + for(i=0; in_used; + if (config_overrides) + n_config_overrides = config_overrides->n_used; - config_options = alloc((first+n_applied_config_overwrites+1)*SIZEOF(char *)); + config_options = alloc((first+n_config_overrides+1)*SIZEOF(char *)); config_option = config_options + first; - for (i = 0; i < n_applied_config_overwrites; i++) { - char *key = applied_config_overwrites->ovr[i].key; - char *value = applied_config_overwrites->ovr[i].value; + for (i = 0; i < n_config_overrides; i++) { + char *key = config_overrides->ovr[i].key; + char *value = config_overrides->ovr[i].value; *config_option = vstralloc("-o", key, "=", value, NULL); config_option++; } @@ -3344,14 +4986,16 @@ static void update_derived_values( gboolean is_client) { - interface_t *ip; + interface_t *ip; + identlist_t il; + holdingdisk_t *hd; if (!is_client) { /* Add a 'default' interface if one doesn't already exist */ if (!(ip = lookup_interface("default"))) { init_interface_defaults(); ifcur.name = stralloc("default"); - ifcur.seen = getconf_seen(CNF_NETUSAGE); + ifcur.seen = val_t__seen(getconf(CNF_NETUSAGE)); save_interface(); ip = lookup_interface("default"); @@ -3364,33 +5008,65 @@ update_derived_values( v = interface_getconf(ip, INTER_COMMENT); free_val_t(v); val_t__str(v) = stralloc(_("implicit from NETUSAGE")); - val_t__seen(v) = getconf_seen(CNF_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) = getconf_seen(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 */ + /* 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) && - strcmp(getconf_str(CNF_TAPETYPE), "EXABYTE") == 0 && - !lookup_tapetype("EXABYTE")) { + strcmp(getconf_str(CNF_TAPETYPE), "DEFAULT_TAPE") == 0 && + !lookup_tapetype("DEFAULT_TAPE")) { init_tapetype_defaults(); - tpcur.name = stralloc("EXABYTE"); - tpcur.seen = -1; + tpcur.name = stralloc("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); + autolabel->template = g_strdup(getconf_str(CNF_LABEL_NEW_TAPES)); + if (!autolabel->template || autolabel->template == '\0') { + autolabel->template = NULL; + autolabel->autolabel = 0; + } else { + autolabel->autolabel = AL_VOLUME_ERROR | AL_EMPTY; + } + } } /* 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); @@ -3440,19 +5116,21 @@ conf_init_int( val_t *val, int i) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_INT; val_t__int(val) = i; } static void -conf_init_am64( +conf_init_int64( val_t *val, - off_t l) + gint64 l) { - val->seen = 0; - val->type = CONFTYPE_AM64; - val_t__am64(val) = l; + val->seen.linenum = 0; + val->seen.filename = NULL; + val->type = CONFTYPE_INT64; + val_t__int64(val) = l; } static void @@ -3460,7 +5138,8 @@ conf_init_real( val_t *val, float r) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_REAL; val_t__real(val) = r; } @@ -3470,7 +5149,8 @@ conf_init_str( val_t *val, char *s) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_STR; if(s) val->v.s = stralloc(s); @@ -3483,7 +5163,8 @@ conf_init_ident( val_t *val, char *s) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_IDENT; if(s) val->v.s = stralloc(s); @@ -3491,12 +5172,26 @@ conf_init_ident( val->v.s = NULL; } +static void +conf_init_identlist( + val_t *val, + char *s) +{ + val->seen.linenum = 0; + val->seen.filename = NULL; + val->type = CONFTYPE_IDENTLIST; + val->v.identlist = NULL; + if (s) + val->v.identlist = g_slist_append(val->v.identlist, stralloc(s)); +} + static void conf_init_time( val_t *val, time_t t) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_TIME; val_t__time(val) = t; } @@ -3506,7 +5201,8 @@ conf_init_size( val_t *val, ssize_t sz) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_SIZE; val_t__size(val) = sz; } @@ -3516,7 +5212,8 @@ conf_init_bool( val_t *val, int i) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_BOOLEAN; val_t__boolean(val) = i; } @@ -3526,7 +5223,8 @@ conf_init_compress( val_t *val, comp_t i) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_COMPRESS; val_t__compress(val) = (int)i; } @@ -3536,29 +5234,67 @@ conf_init_encrypt( val_t *val, encrypt_t i) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_ENCRYPT; 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->type = CONFTYPE_PART_CACHE_TYPE; + val_t__part_cache_type(val) = (int)i; +} + +static void +conf_init_recovery_limit( + val_t *val) +{ + val->seen.linenum = 0; + val->seen.filename = NULL; + val->type = CONFTYPE_RECOVERY_LIMIT; + val_t__recovery_limit(val).match_pats = NULL; + val_t__recovery_limit(val).same_host = FALSE; +} + +static void +conf_init_data_path( + val_t *val, + data_path_t i) +{ + val->seen.linenum = 0; + val->seen.filename = NULL; + val->type = CONFTYPE_DATA_PATH; + val_t__data_path(val) = (int)i; +} + static void conf_init_holding( val_t *val, dump_holdingdisk_t i) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_HOLDING; val_t__holding(val) = (int)i; } static void -conf_init_estimate( +conf_init_estimatelist( val_t *val, estimate_t i) { - val->seen = 0; - val->type = CONFTYPE_ESTIMATE; - val_t__estimate(val) = i; + GSList *estimates = NULL; + val->seen.linenum = 0; + val->seen.filename = NULL; + val->type = CONFTYPE_ESTIMATELIST; + estimates = g_slist_append(estimates, GINT_TO_POINTER(i)); + val_t__estimatelist(val) = estimates; } static void @@ -3566,7 +5302,8 @@ conf_init_strategy( val_t *val, strategy_t i) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_STRATEGY; val_t__strategy(val) = i; } @@ -3576,7 +5313,8 @@ conf_init_taperalgo( val_t *val, taperalgo_t i) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_TAPERALGO; val_t__taperalgo(val) = i; } @@ -3586,7 +5324,8 @@ conf_init_priority( val_t *val, int i) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_PRIORITY; val_t__priority(val) = i; } @@ -3597,45 +5336,110 @@ conf_init_rate( float r1, float r2) { - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; val->type = CONFTYPE_RATE; val_t__rate(val)[0] = r1; val_t__rate(val)[1] = r2; } static void -conf_init_exinclude( - val_t *val) +conf_init_exinclude( + val_t *val) +{ + val->seen.linenum = 0; + val->seen.filename = NULL; + val->type = CONFTYPE_EXINCLUDE; + 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->type = CONFTYPE_INTRANGE; + 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->type = CONFTYPE_AUTOLABEL; + val->v.autolabel.template = NULL; + val->v.autolabel.autolabel = 0; +} + +void +free_property_t( + gpointer p) +{ + property_t *propery = (property_t *)p; + g_slist_free_full(propery->values); + amfree(propery); +} + +static void +conf_init_proplist( + val_t *val) +{ + val->seen.linenum = 0; + val->seen.filename = NULL; + val->type = CONFTYPE_PROPLIST; + 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->type = CONFTYPE_EXECUTE_ON; + val->v.i = i; +} + +static void +conf_init_execute_where( + val_t *val, + int i) { - val->seen = 0; - val->type = CONFTYPE_EXINCLUDE; - val_t__exinclude(val).optional = 0; - val_t__exinclude(val).sl_list = NULL; - val_t__exinclude(val).sl_file = NULL; + val->seen.linenum = 0; + val->seen.filename = NULL; + val->type = CONFTYPE_EXECUTE_WHERE; + val->v.i = i; } static void -conf_init_intrange( +conf_init_send_amreport( val_t *val, - int i1, - int i2) + send_amreport_t i) { - val->seen = 0; - val->type = CONFTYPE_INTRANGE; - val_t__intrange(val)[0] = i1; - val_t__intrange(val)[1] = i2; + val->seen.linenum = 0; + val->seen.filename = NULL; + val->type = CONFTYPE_SEND_AMREPORT_ON; + val->v.i = i; } -static void -conf_init_proplist( - val_t *val) -{ - val->seen = 0; - val->type = CONFTYPE_PROPLIST; - val_t__proplist(val) = - g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); +static void conf_init_application(val_t *val) { + val->seen.linenum = 0; + val->seen.filename = NULL; + val->type = CONFTYPE_APPLICATION; + val->v.s = NULL; } + /* * Config access implementation */ @@ -3654,7 +5458,12 @@ getconf_list( tapetype_t *tp; dumptype_t *dp; interface_t *ip; - holdingdisk_t *hp; + holdingdisk_t *hd; + GSList *hp; + application_t *ap; + pp_script_t *pp; + device_config_t *dc; + changer_config_t *cc; GSList *rv = NULL; if (strcasecmp(listname,"tapetype") == 0) { @@ -3667,12 +5476,33 @@ getconf_list( } } else if (strcasecmp(listname,"holdingdisk") == 0) { for(hp = holdinglist; hp != NULL; hp=hp->next) { - rv = g_slist_append(rv, hp->name); + 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); + } } return rv; } @@ -3711,6 +5541,18 @@ tapetype_getconf( return &ttyp->value[key]; } +static void +validate_program( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + if (strcmp(val->v.s, "DUMP") != 0 && + strcmp(val->v.s, "GNUTAR") != 0 && + strcmp(val->v.s, "STAR") != 0 && + strcmp(val->v.s, "APPLICATION") != 0) + conf_parserror("program must be \"DUMP\", \"GNUTAR\", \"STAR\" or \"APPLICATION\""); +} + char * tapetype_name( tapetype_t *ttyp) @@ -3783,29 +5625,23 @@ holdingdisk_t * lookup_holdingdisk( char *str) { - holdingdisk_t *p; + GSList *hp; + holdingdisk_t *hd; - for(p = holdinglist; p != NULL; p = p->next) { - if(strcasecmp(p->name, str) == 0) return p; + for (hp = holdinglist; hp != NULL; hp = hp->next) { + hd = hp->data; + if (strcasecmp(hd->name, str) == 0) return hd; } return NULL; } -holdingdisk_t * +GSList * getconf_holdingdisks( void) { return holdinglist; } -holdingdisk_t * -holdingdisk_next( - holdingdisk_t *hdisk) -{ - if (hdisk) return hdisk->next; - return NULL; -} - val_t * holdingdisk_getconf( holdingdisk_t *hdisk, @@ -3824,6 +5660,126 @@ holdingdisk_name( return hdisk->name; } +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; +} + +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; +} + +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; +} + +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; +} + long int getconf_unit_divisor(void) { @@ -3834,11 +5790,14 @@ getconf_unit_divisor(void) * Command-line Handling Implementation */ -config_overwrites_t * -new_config_overwrites( +config_overrides_t * +new_config_overrides( int size_estimate) { - config_overwrites_t *co; + config_overrides_t *co; + + if (size_estimate <= 0) + size_estimate = 10; co = alloc(sizeof(*co)); co->ovr = alloc(sizeof(*co->ovr) * size_estimate); @@ -3849,8 +5808,8 @@ new_config_overwrites( } void -free_config_overwrites( - config_overwrites_t *co) +free_config_overrides( + config_overrides_t *co) { int i; @@ -3863,8 +5822,8 @@ free_config_overwrites( amfree(co); } -void add_config_overwrite( - config_overwrites_t *co, +void add_config_override( + config_overrides_t *co, char *key, char *value) { @@ -3884,42 +5843,42 @@ void add_config_overwrite( } void -add_config_overwrite_opt( - config_overwrites_t *co, +add_config_override_opt( + config_overrides_t *co, char *optarg) { char *value; assert(optarg != NULL); - value = index(optarg, '='); + value = strchr(optarg, '='); if (value == NULL) { error(_("Must specify a value for %s."), optarg); /* NOTREACHED */ } *value = '\0'; - add_config_overwrite(co, optarg, value+1); + add_config_override(co, optarg, value+1); *value = '='; } -config_overwrites_t * -extract_commandline_config_overwrites( +config_overrides_t * +extract_commandline_config_overrides( int *argc, char ***argv) { int i, j, moveup; - config_overwrites_t *co = new_config_overwrites(*argc/2); + config_overrides_t *co = new_config_overrides(*argc/2); i = 0; while (i<*argc) { if(strncmp((*argv)[i],"-o",2) == 0) { if(strlen((*argv)[i]) > 2) { - add_config_overwrite_opt(co, (*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_overwrite_opt(co, (*argv)[i+1]); + add_config_override_opt(co, (*argv)[i+1]); moveup = 2; } @@ -3937,12 +5896,28 @@ extract_commandline_config_overwrites( } void -apply_config_overwrites( - config_overwrites_t *co) +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; + if(!co) return cfgerr_level; assert(keytable != NULL); assert(parsetable != NULL); @@ -3952,24 +5927,28 @@ apply_config_overwrites( 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)) { - error(_("unknown parameter '%s'"), key); + /* 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 = vstralloc("\"", value, "\"", NULL); + current_line = quote_string_always(value); } else { - current_line = stralloc(""); + current_line = stralloc(value); } current_char = current_line; token_pushed = 0; current_line_num = -2; allow_overwrites = 1; - got_parserror = 0; + co->ovr[i].applied = TRUE; key_parm->read_function(key_parm, key_val); if ((key_parm)->validate_function) @@ -3977,27 +5956,9 @@ apply_config_overwrites( amfree(current_line); current_char = NULL; - - if (got_parserror) { - error(_("parse error in configuration overwrites")); - /* NOTREACHED */ - } } - /* merge these overwrites with previous overwrites, if necessary */ - if (applied_config_overwrites) { - for (i = 0; i < co->n_used; i++) { - char *key = co->ovr[i].key; - char *value = co->ovr[i].value; - - add_config_overwrite(applied_config_overwrites, key, value); - } - free_config_overwrites(co); - } else { - applied_config_overwrites = co; - } - - update_derived_values(config_client); + return cfgerr_level; } /* @@ -4008,6 +5969,7 @@ 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*/ @@ -4015,21 +5977,23 @@ val_t_to_int( return val_t__int(val); } -off_t -val_t_to_am64( +gint64 +val_t_to_int64( val_t *val) { - if (val->type != CONFTYPE_AM64) { - error(_("val_t_to_am64: val.type is not CONFTYPE_AM64")); + assert(config_initialized); + if (val->type != CONFTYPE_INT64) { + error(_("val_t_to_int64: val.type is not CONFTYPE_INT64")); /*NOTREACHED*/ } - return val_t__am64(val); + 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*/ @@ -4041,6 +6005,7 @@ 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")); @@ -4053,6 +6018,7 @@ 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")); @@ -4061,10 +6027,23 @@ val_t_to_ident( 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); +} + 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*/ @@ -4076,6 +6055,7 @@ 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*/ @@ -4087,6 +6067,7 @@ 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*/ @@ -4098,6 +6079,7 @@ 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*/ @@ -4109,6 +6091,7 @@ 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*/ @@ -4116,10 +6099,35 @@ val_t_to_encrypt( 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); +} + +recovery_limit_t * +val_t_to_recovery_limit( + val_t *val) +{ + assert(config_initialized); + if (val->type != CONFTYPE_RECOVERY_LIMIT) { + error(_("val_t_to_recovery_limit: val.type is not CONFTYPE_RECOVERY_LIMIT")); + /*NOTREACHED*/ + } + return &val_t__recovery_limit(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*/ @@ -4127,21 +6135,23 @@ val_t_to_holding( return val_t__holding(val); } -estimate_t -val_t_to_estimate( +estimatelist_t +val_t_to_estimatelist( val_t *val) { - if (val->type != CONFTYPE_ESTIMATE) { - error(_("val_t_to_extimate: val.type is not CONFTYPE_ESTIMATE")); + assert(config_initialized); + if (val->type != CONFTYPE_ESTIMATELIST) { + error(_("val_t_to_estimatelist: val.type is not CONFTYPE_ESTIMATELIST")); /*NOTREACHED*/ } - return val_t__estimate(val); + 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*/ @@ -4153,6 +6163,7 @@ 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*/ @@ -4160,10 +6171,35 @@ val_t_to_taperalgo( 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*/ @@ -4175,6 +6211,7 @@ 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*/ @@ -4186,6 +6223,7 @@ 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*/ @@ -4198,6 +6236,7 @@ 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*/ @@ -4209,6 +6248,7 @@ 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*/ @@ -4216,12 +6256,61 @@ val_t_to_proplist( 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); +} + +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) { + 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) { + 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, + stralloc((char *)il->data)); + } + } + } else { + free_val_t(valdst); + copy_val_t(valdst, valsrc); + } +} + static void copy_val_t( val_t *valdst, val_t *valsrc) { - if(valsrc->seen) { + GSList *ia; + + if(valsrc->seen.linenum) { valdst->type = valsrc->type; valdst->seen = valsrc->seen; switch(valsrc->type) { @@ -4230,10 +6319,14 @@ copy_val_t( case CONFTYPE_COMPRESS: case CONFTYPE_ENCRYPT: case CONFTYPE_HOLDING: - case CONFTYPE_ESTIMATE: + 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; @@ -4241,8 +6334,8 @@ copy_val_t( valdst->v.size = valsrc->v.size; break; - case CONFTYPE_AM64: - valdst->v.am64 = valsrc->v.am64; + case CONFTYPE_INT64: + valdst->v.int64 = valsrc->v.int64; break; case CONFTYPE_REAL: @@ -4259,10 +6352,38 @@ copy_val_t( valdst->v.s = stralloc(valsrc->v.s); break; + case CONFTYPE_IDENTLIST: + valdst->v.identlist = NULL; + for (ia = valsrc->v.identlist; ia != NULL; ia = ia->next) { + valdst->v.identlist = g_slist_append(valdst->v.identlist, + stralloc(ia->data)); + } + break; + + case CONFTYPE_RECOVERY_LIMIT: + valdst->v.recovery_limit = valsrc->v.recovery_limit; + valdst->v.recovery_limit.match_pats = NULL; + for (ia = valsrc->v.recovery_limit.match_pats; ia != NULL; ia = ia->next) { + valdst->v.recovery_limit.match_pats = + g_slist_append(valdst->v.recovery_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); @@ -4275,12 +6396,86 @@ copy_val_t( break; case CONFTYPE_PROPLIST: - g_assert_not_reached(); - break; + 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 = stralloc(valsrc->v.s); + break; + + case CONFTYPE_AUTOLABEL: + valdst->v.autolabel.template = stralloc(valsrc->v.autolabel.template); + valdst->v.autolabel.autolabel = valsrc->v.autolabel.autolabel; + 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->append = property->append; + 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, + stralloc(elem->data)); + } + if (new_prop) + g_hash_table_insert(proplist, stralloc(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->priority = property->priority; + new_property->values = NULL; + + for(elem = property->values;elem != NULL; elem=elem->next) { + new_property->values = g_slist_append(new_property->values, + stralloc(elem->data)); + } + g_hash_table_insert(proplist, stralloc(property_s), new_property); +} + static void free_val_t( val_t *val) @@ -4291,25 +6486,42 @@ free_val_t( case CONFTYPE_COMPRESS: case CONFTYPE_ENCRYPT: case CONFTYPE_HOLDING: - case CONFTYPE_ESTIMATE: + 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_AM64: + 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: + g_slist_free_full(val->v.identlist); + break; + + case CONFTYPE_RECOVERY_LIMIT: + g_slist_free_full(val->v.recovery_limit.match_pats); + 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); @@ -4318,8 +6530,13 @@ free_val_t( case CONFTYPE_PROPLIST: g_hash_table_destroy(val_t__proplist(val)); break; + + case CONFTYPE_AUTOLABEL: + amfree(val->v.autolabel.template); + break; } - val->seen = 0; + val->seen.linenum = 0; + val->seen.filename = NULL; } /* @@ -4369,6 +6586,8 @@ generic_client_get_security_conf( return(getconf_str(CNF_AMANDAD_PATH)); } else if(strcmp(string, "client_username")==0) { return(getconf_str(CNF_CLIENT_USERNAME)); + } else if(strcmp(string, "client_port")==0) { + return(getconf_str(CNF_CLIENT_PORT)); } else if(strcmp(string, "gnutar_list_dir")==0) { return(getconf_str(CNF_GNUTAR_LIST_DIR)); } else if(strcmp(string, "amandates")==0) { @@ -4387,7 +6606,12 @@ dump_configuration(void) tapetype_t *tp; dumptype_t *dp; interface_t *ip; - holdingdisk_t *hp; + holdingdisk_t *hd; + GSList *hp; + application_t *ap; + pp_script_t *ps; + device_config_t *dc; + changer_config_t *cc; int i; conf_var_t *np; keytab_t *kt; @@ -4411,7 +6635,8 @@ dump_configuration(void) } for(hp = holdinglist; hp != NULL; hp = hp->next) { - g_printf("\nHOLDINGDISK %s {\n", hp->name); + 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) @@ -4427,13 +6652,13 @@ dump_configuration(void) if(kt->token == CONF_UNKNOWN) error(_("holding bad token")); - val_t_print_token(stdout, NULL, " %-9s ", kt, &hp->value[i]); + val_t_print_token(stdout, NULL, " %-9s ", kt, &hd->value[i]); } g_printf("}\n"); } for(tp = tapelist; tp != NULL; tp = tp->next) { - if(tp->seen == -1) + if(tp->seen.linenum == -1) prefix = "#"; else prefix = ""; @@ -4456,7 +6681,7 @@ dump_configuration(void) for(dp = dumplist; dp != NULL; dp = dp->next) { if (strncmp_const(dp->name, "custom(") != 0) { /* don't dump disklist-derived dumptypes */ - if(dp->seen == -1) + if(dp->seen.linenum == -1) prefix = "#"; else prefix = ""; @@ -4472,34 +6697,118 @@ dump_configuration(void) if(kt->token == CONF_UNKNOWN) error(_("dumptype bad token")); - val_t_print_token(stdout, prefix, " %-19s ", kt, &dp->value[i]); - } - g_printf("%s}\n", prefix); + val_t_print_token(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 && + 0 == strcmp(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(stdout, prefix, " %-19s ", kt, &ip->value[i]); + } + g_printf("%s}\n",prefix); + } + + for(ap = application_list; ap != NULL; ap = ap->next) { + if(strcmp(ap->name,"default") == 0) + 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(stdout, prefix, " %-19s ", kt, &ap->value[i]); } + g_printf("%s}\n",prefix); } - for(ip = interface_list; ip != NULL; ip = ip->next) { - if(strcmp(ip->name,"default") == 0) + for(ps = pp_script_list; ps != NULL; ps = ps->next) { + if(strcmp(ps->name,"default") == 0) 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++) + 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(_("interface bad value")); + 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(_("interface bad token")); + error(_("script bad token")); - val_t_print_token(stdout, prefix, " %-19s ", kt, &ip->value[i]); + val_t_print_token(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(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(stdout, prefix, " %-19s ", kt, &cc->value[i]); + } + g_printf("%s}\n",prefix); + } } static void @@ -4558,8 +6867,8 @@ val_t_display_strs( buf[0] = vstrallocf("%zd", (ssize_t)val_t__size(val)); break; - case CONFTYPE_AM64: - buf[0] = vstrallocf("%lld", (long long)val_t__am64(val)); + case CONFTYPE_INT64: + buf[0] = vstrallocf("%lld", (long long)val_t__int64(val)); break; case CONFTYPE_REAL: @@ -4582,10 +6891,28 @@ val_t_display_strs( } break; + case CONFTYPE_IDENTLIST: + { + GSList *ia; + int first = 1; + + buf[0] = NULL; + for (ia = val->v.identlist; ia != NULL; ia = ia->next) { + if (first) { + buf[0] = stralloc(ia->data); + first = 0; + } else { + strappend(buf[0], " "); + strappend(buf[0], ia->data); + } + } + } + break; + case CONFTYPE_STR: if(str_need_quote) { if(val->v.s) { - buf[0] = vstrallocf("\"%s\"", val->v.s); + buf[0] = quote_string_always(val->v.s); } else { buf[0] = stralloc("\"\""); } @@ -4598,6 +6925,24 @@ val_t_display_strs( } break; + case CONFTYPE_AUTOLABEL: + { + buf[0] = quote_string_always(val->v.autolabel.template); + if (val->v.autolabel.autolabel & AL_OTHER_CONFIG) { + buf[0] = vstrextend(&buf[0], " OTHER-CONFIG", NULL); + } + if (val->v.autolabel.autolabel & AL_NON_AMANDA) { + buf[0] = vstrextend(&buf[0], " NON-AMANDA", NULL); + } + if (val->v.autolabel.autolabel & AL_VOLUME_ERROR) { + buf[0] = vstrextend(&buf[0], " VOLUME-ERROR", NULL); + } + if (val->v.autolabel.autolabel & AL_EMPTY) { + buf[0] = vstrextend(&buf[0], " EMPTY", NULL); + } + } + break; + case CONFTYPE_TIME: buf[0] = vstrallocf("%2d%02d", (int)val_t__time(val)/100, (int)val_t__time(val) % 100); @@ -4676,8 +7021,35 @@ val_t_display_strs( } break; - case CONFTYPE_ESTIMATE: - switch(val_t__estimate(val)) { + case CONFTYPE_ESTIMATELIST: { + estimatelist_t es = val_t__estimatelist(val); + buf[0] = stralloc(""); + 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 ES_CLIENT: buf[0] = vstrallocf("CLIENT"); break; @@ -4685,13 +7057,30 @@ val_t_display_strs( case ES_SERVER: buf[0] = vstrallocf("SERVER"); break; + } + break; - case ES_CALCSIZE: - buf[0] = vstrallocf("CALCSIZE"); + case CONFTYPE_SEND_AMREPORT_ON: + switch(val->v.i) { + case SEND_AMREPORT_ALL: + buf[0] = vstrallocf("ALL"); + break; + case SEND_AMREPORT_STRANGE: + buf[0] = vstrallocf("STRANGE"); + break; + case SEND_AMREPORT_ERROR: + buf[0] = vstrallocf("ERROR"); + break; + case SEND_AMREPORT_NEVER: + buf[0] = vstrallocf("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: @@ -4708,6 +7097,38 @@ val_t_display_strs( } break; + case CONFTYPE_PART_CACHE_TYPE: + switch(val_t__part_cache_type(val)) { + case PART_CACHE_TYPE_NONE: + buf[0] = vstrallocf("NONE"); + break; + + case PART_CACHE_TYPE_DISK: + buf[0] = vstrallocf("DISK"); + break; + + case PART_CACHE_TYPE_MEMORY: + buf[0] = vstrallocf("MEMORY"); + break; + } + break; + + case CONFTYPE_RECOVERY_LIMIT: { + GSList *iter = val_t__recovery_limit(val).match_pats; + + if(val_t__recovery_limit(val).same_host) + buf[0] = stralloc("SAME-HOST "); + else + buf[0] = stralloc(""); + + while (iter) { + strappend(buf[0], (char *)iter->data); + strappend(buf[0], " "); + iter = iter->next; + } + break; + } + case CONFTYPE_HOLDING: switch(val_t__holding(val)) { case HOLD_NEVER: @@ -4753,24 +7174,158 @@ val_t_display_strs( buf = malloc((nb_property+1)*SIZEOF(char*)); buf[nb_property] = NULL; mybuf = buf; - g_hash_table_foreach(val_t__proplist(val), proplist_display_str_foreach_fn, &mybuf); + g_hash_table_foreach(val_t__proplist(val), + proplist_display_str_foreach_fn, + &mybuf); break; } + + case CONFTYPE_APPLICATION: { + if (val->v.s) { + buf[0] = quote_string_always(val->v.s); + } else { + buf[0] = stralloc(""); + } + break; + } + + case CONFTYPE_EXECUTE_ON: + buf[0] = stralloc(""); + if (val->v.i != 0) { + char *sep = ""; + if (val->v.i & EXECUTE_ON_PRE_DLE_AMCHECK) { + buf[0] = vstrextend(&buf[0], sep, "PRE-DLE-AMCHECK", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_PRE_HOST_AMCHECK) { + buf[0] = vstrextend(&buf[0], sep, "PRE-HOST-AMCHECK", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_POST_DLE_AMCHECK) { + buf[0] = vstrextend(&buf[0], sep, "POST-DLE-AMCHECK", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_POST_HOST_AMCHECK) { + buf[0] = vstrextend(&buf[0], sep, "POST-HOST-AMCHECK", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_PRE_DLE_ESTIMATE) { + buf[0] = vstrextend(&buf[0], sep, "PRE-DLE-ESTIMATE", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_PRE_HOST_ESTIMATE) { + buf[0] = vstrextend(&buf[0], sep, "PRE-HOST-ESTIMATE", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_POST_DLE_ESTIMATE) { + buf[0] = vstrextend(&buf[0], sep, "POST-DLE-ESTIMATE", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_POST_HOST_ESTIMATE) { + buf[0] = vstrextend(&buf[0], sep, "POST-HOST-ESTIMATE", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_PRE_DLE_BACKUP) { + buf[0] = vstrextend(&buf[0], sep, "PRE-DLE-BACKUP", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_PRE_HOST_BACKUP) { + buf[0] = vstrextend(&buf[0], sep, "PRE-HOST-BACKUP", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_POST_DLE_BACKUP) { + buf[0] = vstrextend(&buf[0], sep, "POST-DLE-BACKUP", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_POST_HOST_BACKUP) { + buf[0] = vstrextend(&buf[0], sep, "POST-HOST-BACKUP", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_PRE_RECOVER) { + buf[0] = vstrextend(&buf[0], sep, "PRE-RECOVER", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_POST_RECOVER) { + buf[0] = vstrextend(&buf[0], sep, "POST-RECOVER", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_PRE_LEVEL_RECOVER) { + buf[0] = vstrextend(&buf[0], sep, "PRE-LEVEL-RECOVER", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_POST_LEVEL_RECOVER) { + buf[0] = vstrextend(&buf[0], sep, "POST-LEVEL-RECOVER", NULL); + sep = ", "; + } + if (val->v.i & EXECUTE_ON_INTER_LEVEL_RECOVER) { + buf[0] = vstrextend(&buf[0], sep, "INTER-LEVEL-RECOVER", NULL); + sep = ", "; + } + } + break; + } 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); +} + +int +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) { - char *property_s = key_p; - char *value_s = value_p; - char ***msg = (char ***)user_data_p; + char *property_s = quote_string_always(key_p); + property_t *property = value_p; + GSList *value; + char ***msg = (char ***)user_data_p; - **msg = vstralloc("\"", property_s, "\" \"", value_s, "\"", NULL); + /* What to do with property->append? it should be printed only on client */ + if (property->priority) { + **msg = vstralloc("priority ", property_s, NULL); + amfree(property_s); + } else { + **msg = property_s; + property_s = NULL; + } + for(value=property->values; value != NULL; value = value->next) { + char *qstr = quote_string_always((char *)value->data); + **msg = vstrextend(*msg, " ", qstr, NULL); + amfree(qstr); + } (*msg)++; } @@ -4801,7 +7356,9 @@ exinclude_display_str( if (sl != NULL) { for(excl = sl->first; excl != NULL; excl = excl->next) { - vstrextend(&rval, " \"", excl->name, "\"", NULL); + char *qstr = quote_string_always(excl->name); + vstrextend(&rval, " ", qstr, NULL); + amfree(qstr); } } @@ -4853,6 +7410,10 @@ parm_key_info( dumptype_t *dp; interface_t *ip; holdingdisk_t *hp; + application_t *ap; + pp_script_t *pp; + device_config_t *dc; + changer_config_t *cc; int success = FALSE; /* WARNING: assumes globals keytable and parsetable are set correctly. */ @@ -4863,9 +7424,8 @@ parm_key_info( key = stralloc(key); /* uppercase the key */ - s = key; for (s = key; (ch = *s) != 0; s++) { - if(islower((int)ch)) + if (islower((int)ch)) *s = (char)toupper(ch); } @@ -4876,12 +7436,22 @@ parm_key_info( *subsec_name = '\0'; subsec_name++; + /* convert subsec_type '-' to '_' */ + for (s = subsec_type; (ch = *s) != 0; s++) { + if (*s == '-') *s = '_'; + } + subsec_key = strchr(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++) { @@ -4940,10 +7510,67 @@ parm_key_info( if (val) *val = &ip->value[np->parm]; if (parm) *parm = np; success = TRUE; - } + /* accept the old name here, too */ + } else if (strcmp(subsec_type, "APPLICATION_TOOL") == 0 + || strcmp(subsec_type, "APPLICATION") == 0) { + 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 (strcmp(subsec_type, "SCRIPT_TOOL") == 0 + || strcmp(subsec_type, "SCRIPT") == 0) { + 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 (strcmp(subsec_type, "DEVICE") == 0) { + 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 (strcmp(subsec_type, "CHANGER") == 0) { + 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; + } /* 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 && strcmp(kt->keyword, key) == 0) @@ -4970,20 +7597,21 @@ out: gint64 find_multiplier( - char * casestr) + char * str) { keytab_t * table_entry; - char * str = g_utf8_strup(casestr, -1); + + 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 (strcmp(casestr, table_entry->keyword) == 0) { + if (strcasecmp(str, table_entry->keyword) == 0) { g_free(str); switch (table_entry->token) { case CONF_MULT1K: @@ -4992,6 +7620,8 @@ find_multiplier( 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: @@ -5011,22 +7641,72 @@ find_multiplier( 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 (0 == strcmp(str, "0")) + return 0; + if (0 == strcmp(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 */ -static void print_parse_problem(const char * format, va_list argp) { - const char *xlated_fmt = gettext(format); +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 = g_strdup_vprintf(format, argp); + char *errstr = NULL; if(current_line) - g_fprintf(stderr, _("argument \"%s\": "), current_line); + errstr = g_strdup_printf(_("argument \"%s\": %s"), + current_line, msg); else if (current_filename && current_line_num > 0) - g_fprintf(stderr, "\"%s\", line %d: ", current_filename, current_line_num); + errstr = g_strdup_printf(_("\"%s\", line %d: %s"), + current_filename, current_line_num, msg); else - g_fprintf(stderr, _("parse error: ")); - - g_vfprintf(stderr, xlated_fmt, argp); - fputc('\n', stderr); + errstr = g_strdup_printf(_("parse error: %s"), msg); + amfree(msg); + + config_add_error(level, errstr); } printf_arglist_function(void conf_parserror, const char *, format) @@ -5034,16 +7714,125 @@ printf_arglist_function(void conf_parserror, const char *, format) va_list argp; arglist_start(argp, format); - print_parse_problem(format, argp); + conf_error_common(CFGERR_ERRORS, format, argp); arglist_end(argp); - - got_parserror = TRUE; } printf_arglist_function(void conf_parswarn, const char *, format) { va_list argp; arglist_start(argp, format); - print_parse_problem(format, argp); + 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) +{ + g_slist_free_full(cfgerr_errors); + + 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); + } +} + +/* 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 * +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 (strcmp(data, "AMANDA") == 0) + return DATA_PATH_AMANDA; + if (strcmp(data, "DIRECTTCP") == 0) + 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; +} +