From 3ea8f1d1d1024b67043a1debb012339a62105d04 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 28 Apr 2004 17:02:48 +0000 Subject: [PATCH] Finish inc options scan code git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1320 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/dird/dird_conf.c | 15 +- bacula/src/dird/dird_conf.h | 295 ++++++++++++++++++------------------ bacula/src/dird/fd_cmds.c | 5 +- bacula/src/dird/inc_conf.c | 76 +++++++--- 4 files changed, 220 insertions(+), 171 deletions(-) diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index d28007fa0c..0511dc946f 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -569,8 +569,14 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ... for (j=0; jnum_opts; j++) { FOPTS *fo = incexe->opts_list[j]; sendit(sock, " O %s\n", fo->opts); - for (k=0; kmatch.size(); k++) { - sendit(sock, " W %s\n", fo->match.get(j)); + for (k=0; kregex.size(); k++) { + sendit(sock, " R %s\n", fo->regex.get(k)); + } + for (k=0; kwild.size(); k++) { + sendit(sock, " W %s\n", fo->wild.get(k)); + } + for (k=0; kbase.size(); k++) { + sendit(sock, " B %s\n", fo->base.get(k)); } sendit(sock, " N\n"); } @@ -723,8 +729,9 @@ static void free_incexe(INCEXE *incexe) incexe->name_list.destroy(); for (int i=0; inum_opts; i++) { FOPTS *fopt = incexe->opts_list[i]; - fopt->match.destroy(); - fopt->base_list.destroy(); + fopt->regex.destroy(); + fopt->wild.destroy(); + fopt->base.destroy(); free(fopt); } if (incexe->opts_list) { diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index f246e9434e..7d8b0d6b3e 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -44,7 +44,7 @@ enum { R_CONSOLE, R_JOBDEFS, R_FIRST = R_DIRECTOR, - R_LAST = R_JOBDEFS /* keep this updated */ + R_LAST = R_JOBDEFS /* keep this updated */ }; @@ -61,16 +61,16 @@ enum { /* Used for certain KeyWord tables */ -struct s_kw { +struct s_kw { char *name; - int token; + int token; }; /* Job Level keyword structure */ struct s_jl { - char *level_name; /* level keyword */ - int level; /* level */ - int job_type; /* JobType permitting this level */ + char *level_name; /* level keyword */ + int level; /* level */ + int job_type; /* JobType permitting this level */ }; /* Job Type keyword structure */ @@ -88,24 +88,24 @@ struct POOL; struct RUN; /* - * Director Resource + * Director Resource * */ struct DIRRES { - RES hdr; - int DIRport; /* where we listen -- UA port server port */ - char *DIRaddr; /* bind address */ - char *password; /* Password for UA access */ - int enable_ssl; /* Use SSL for UA */ - char *query_file; /* SQL query file */ - char *working_directory; /* WorkingDirectory */ - char *pid_directory; /* PidDirectory */ - char *subsys_directory; /* SubsysDirectory */ - int require_ssl; /* Require SSL for all connections */ - MSGS *messages; /* Daemon message handler */ - uint32_t MaxConcurrentJobs; /* Max concurrent jobs for whole director */ - utime_t FDConnectTimeout; /* timeout for connect in seconds */ - utime_t SDConnectTimeout; /* timeout in seconds */ + RES hdr; + int DIRport; /* where we listen -- UA port server port */ + char *DIRaddr; /* bind address */ + char *password; /* Password for UA access */ + int enable_ssl; /* Use SSL for UA */ + char *query_file; /* SQL query file */ + char *working_directory; /* WorkingDirectory */ + char *pid_directory; /* PidDirectory */ + char *subsys_directory; /* SubsysDirectory */ + int require_ssl; /* Require SSL for all connections */ + MSGS *messages; /* Daemon message handler */ + uint32_t MaxConcurrentJobs; /* Max concurrent jobs for whole director */ + utime_t FDConnectTimeout; /* timeout for connect in seconds */ + utime_t SDConnectTimeout; /* timeout in seconds */ }; @@ -122,17 +122,17 @@ enum { Command_ACL, FileSet_ACL, Catalog_ACL, - Num_ACL /* keep last */ + Num_ACL /* keep last */ }; /* * Console Resource */ struct CONRES { - RES hdr; - char *password; /* UA server password */ - int enable_ssl; /* Use SSL */ - alist *ACL_lists[Num_ACL]; /* pointers to ACLs */ + RES hdr; + char *password; /* UA server password */ + int enable_ssl; /* Use SSL */ + alist *ACL_lists[Num_ACL]; /* pointers to ACLs */ }; @@ -141,11 +141,11 @@ struct CONRES { * */ struct CAT { - RES hdr; + RES hdr; - int db_port; /* Port -- not yet implemented */ - char *db_address; /* host name for remote access */ - char *db_socket; /* Socket for local access */ + int db_port; /* Port -- not yet implemented */ + char *db_address; /* host name for remote access */ + char *db_socket; /* Socket for local access */ char *db_password; char *db_user; char *db_name; @@ -157,18 +157,18 @@ struct CAT { * */ struct CLIENT { - RES hdr; + RES hdr; - int FDport; /* Where File daemon listens */ - int AutoPrune; /* Do automatic pruning? */ - utime_t FileRetention; /* file retention period in seconds */ - utime_t JobRetention; /* job retention period in seconds */ + int FDport; /* Where File daemon listens */ + int AutoPrune; /* Do automatic pruning? */ + utime_t FileRetention; /* file retention period in seconds */ + utime_t JobRetention; /* job retention period in seconds */ char *address; char *password; - CAT *catalog; /* Catalog resource */ - uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ - uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ - int enable_ssl; /* Use SSL */ + CAT *catalog; /* Catalog resource */ + uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ + uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ + int enable_ssl; /* Use SSL */ }; /* @@ -176,18 +176,18 @@ struct CLIENT { * */ struct STORE { - RES hdr; + RES hdr; - int SDport; /* port where Directors connect */ - int SDDport; /* data port for File daemon */ + int SDport; /* port where Directors connect */ + int SDDport; /* data port for File daemon */ char *address; char *password; char *media_type; char *dev_name; - int autochanger; /* set if autochanger */ - uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ - uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ - int enable_ssl; /* Use SSL */ + int autochanger; /* set if autochanger */ + uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ + uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ + int enable_ssl; /* Use SSL */ }; @@ -195,66 +195,67 @@ struct STORE { * Job Resource */ struct JOB { - RES hdr; - - int JobType; /* job type (backup, verify, restore */ - int level; /* default backup/verify level */ - int Priority; /* Job priority */ - int RestoreJobId; /* What -- JobId to restore */ - char *RestoreWhere; /* Where on disk to restore -- directory */ - char *RestoreBootstrap; /* Bootstrap file */ - char *RunBeforeJob; /* Run program before Job */ - char *RunAfterJob; /* Run program after Job */ - char *RunAfterFailedJob; /* Run program after Job that errs */ - char *ClientRunBeforeJob; /* Run client program before Job */ - char *ClientRunAfterJob; /* Run client program after Job */ - char *WriteBootstrap; /* Where to write bootstrap Job updates */ - int replace; /* How (overwrite, ..) */ - utime_t MaxRunTime; /* max run time in seconds */ - utime_t MaxWaitTime; /* max blocking time in seconds */ - utime_t MaxStartDelay; /* max start delay in seconds */ - int PrefixLinks; /* prefix soft links with Where path */ - int PruneJobs; /* Force pruning of Jobs */ - int PruneFiles; /* Force pruning of Files */ - int PruneVolumes; /* Force pruning of Volumes */ - int SpoolAttributes; /* Set to spool attributes in SD */ - int spool_data; /* Set to spool data in SD */ - uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ - int RescheduleOnError; /* Set to reschedule on error */ - int RescheduleTimes; /* Number of times to reschedule job */ - utime_t RescheduleInterval; /* Reschedule interval */ - utime_t JobRetention; /* job retention period in seconds */ + RES hdr; + + int JobType; /* job type (backup, verify, restore */ + int level; /* default backup/verify level */ + int Priority; /* Job priority */ + int RestoreJobId; /* What -- JobId to restore */ + char *RestoreWhere; /* Where on disk to restore -- directory */ + char *RestoreBootstrap; /* Bootstrap file */ + char *RunBeforeJob; /* Run program before Job */ + char *RunAfterJob; /* Run program after Job */ + char *RunAfterFailedJob; /* Run program after Job that errs */ + char *ClientRunBeforeJob; /* Run client program before Job */ + char *ClientRunAfterJob; /* Run client program after Job */ + char *WriteBootstrap; /* Where to write bootstrap Job updates */ + int replace; /* How (overwrite, ..) */ + utime_t MaxRunTime; /* max run time in seconds */ + utime_t MaxWaitTime; /* max blocking time in seconds */ + utime_t MaxStartDelay; /* max start delay in seconds */ + int PrefixLinks; /* prefix soft links with Where path */ + int PruneJobs; /* Force pruning of Jobs */ + int PruneFiles; /* Force pruning of Files */ + int PruneVolumes; /* Force pruning of Volumes */ + int SpoolAttributes; /* Set to spool attributes in SD */ + int spool_data; /* Set to spool data in SD */ + uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ + int RescheduleOnError; /* Set to reschedule on error */ + int RescheduleTimes; /* Number of times to reschedule job */ + utime_t RescheduleInterval; /* Reschedule interval */ + utime_t JobRetention; /* job retention period in seconds */ - MSGS *messages; /* How and where to send messages */ - SCHED *schedule; /* When -- Automatic schedule */ - CLIENT *client; /* Who to backup */ - FILESET *fileset; /* What to backup -- Fileset */ - STORE *storage; /* Where is device -- Storage daemon */ - POOL *pool; /* Where is media -- Media Pool */ - POOL *full_pool; /* Pool for Full backups */ - POOL *inc_pool; /* Pool for Incremental backups */ - POOL *dif_pool; /* Pool for Differental backups */ - JOB *verify_job; /* Job name to verify */ - JOB *jobdefs; /* Job defaults */ - uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ + MSGS *messages; /* How and where to send messages */ + SCHED *schedule; /* When -- Automatic schedule */ + CLIENT *client; /* Who to backup */ + FILESET *fileset; /* What to backup -- Fileset */ + STORE *storage; /* Where is device -- Storage daemon */ + POOL *pool; /* Where is media -- Media Pool */ + POOL *full_pool; /* Pool for Full backups */ + POOL *inc_pool; /* Pool for Incremental backups */ + POOL *dif_pool; /* Pool for Differental backups */ + JOB *verify_job; /* Job name to verify */ + JOB *jobdefs; /* Job defaults */ + uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ }; #define MAX_FOPTS 30 /* File options structure */ struct FOPTS { - char opts[MAX_FOPTS]; /* options string */ - alist match; /* match string(s) */ - alist base_list; /* list of base names */ + char opts[MAX_FOPTS]; /* options string */ + alist regex; /* regex string(s) */ + alist wild; /* wild card strings */ + alist base; /* list of base names */ }; /* This is either an include item or an exclude item */ struct INCEXE { - FOPTS *current_opts; /* points to current options structure */ - FOPTS **opts_list; /* options list */ - int num_opts; /* number of options items */ - alist name_list; /* filename list -- holds char * */ + FOPTS *current_opts; /* points to current options structure */ + FOPTS **opts_list; /* options list */ + int num_opts; /* number of options items */ + alist name_list; /* filename list -- holds char * */ }; /* @@ -262,16 +263,16 @@ struct INCEXE { * */ struct FILESET { - RES hdr; + RES hdr; - int new_include; /* Set if new include used */ - INCEXE **include_items; /* array of incexe structures */ - int num_includes; /* number in array */ + bool new_include; /* Set if new include used */ + INCEXE **include_items; /* array of incexe structures */ + int num_includes; /* number in array */ INCEXE **exclude_items; int num_excludes; - int have_MD5; /* set if MD5 initialized */ - struct MD5Context md5c; /* MD5 of include/exclude */ - char MD5[30]; /* base 64 representation of MD5 */ + bool have_MD5; /* set if MD5 initialized */ + struct MD5Context md5c; /* MD5 of include/exclude */ + char MD5[30]; /* base 64 representation of MD5 */ }; @@ -280,7 +281,7 @@ struct FILESET { * */ struct SCHED { - RES hdr; + RES hdr; RUN *run; }; @@ -289,14 +290,14 @@ struct SCHED { * Counter Resource */ struct COUNTER { - RES hdr; - - int32_t MinValue; /* Minimum value */ - int32_t MaxValue; /* Maximum value */ - int32_t CurrentValue; /* Current value */ - COUNTER *WrapCounter; /* Wrap counter name */ - CAT *Catalog; /* Where to store */ - bool created; /* Created in DB */ + RES hdr; + + int32_t MinValue; /* Minimum value */ + int32_t MaxValue; /* Maximum value */ + int32_t CurrentValue; /* Current value */ + COUNTER *WrapCounter; /* Wrap counter name */ + CAT *Catalog; /* Where to store */ + bool created; /* Created in DB */ }; /* @@ -304,26 +305,26 @@ struct COUNTER { * */ struct POOL { - RES hdr; - - char *pool_type; /* Pool type */ - char *label_format; /* Label format string */ - char *cleaning_prefix; /* Cleaning label prefix */ - int use_catalog; /* maintain catalog for media */ - int catalog_files; /* maintain file entries in catalog */ - int use_volume_once; /* write on volume only once */ - int accept_any_volume; /* accept any volume */ - int purge_oldest_volume; /* purge oldest volume */ - int recycle_oldest_volume; /* attempt to recycle oldest volume */ - int recycle_current_volume; /* attempt recycle of current volume */ - uint32_t max_volumes; /* max number of volumes */ - utime_t VolRetention; /* volume retention period in seconds */ - utime_t VolUseDuration; /* duration volume can be used */ - uint32_t MaxVolJobs; /* Maximum jobs on the Volume */ - uint32_t MaxVolFiles; /* Maximum files on the Volume */ - uint64_t MaxVolBytes; /* Maximum bytes on the Volume */ - int AutoPrune; /* default for pool auto prune */ - int Recycle; /* default for media recycle yes/no */ + RES hdr; + + char *pool_type; /* Pool type */ + char *label_format; /* Label format string */ + char *cleaning_prefix; /* Cleaning label prefix */ + int use_catalog; /* maintain catalog for media */ + int catalog_files; /* maintain file entries in catalog */ + int use_volume_once; /* write on volume only once */ + int accept_any_volume; /* accept any volume */ + int purge_oldest_volume; /* purge oldest volume */ + int recycle_oldest_volume; /* attempt to recycle oldest volume */ + int recycle_current_volume; /* attempt recycle of current volume */ + uint32_t max_volumes; /* max number of volumes */ + utime_t VolRetention; /* volume retention period in seconds */ + utime_t VolUseDuration; /* duration volume can be used */ + uint32_t MaxVolJobs; /* Maximum jobs on the Volume */ + uint32_t MaxVolFiles; /* Maximum files on the Volume */ + uint64_t MaxVolBytes; /* Maximum bytes on the Volume */ + int AutoPrune; /* default for pool auto prune */ + int Recycle; /* default for media recycle yes/no */ }; @@ -335,37 +336,37 @@ union URES { CONRES res_con; CLIENT res_client; STORE res_store; - CAT res_cat; - JOB res_job; + CAT res_cat; + JOB res_job; FILESET res_fs; SCHED res_sch; POOL res_pool; MSGS res_msgs; COUNTER res_counter; - RES hdr; + RES hdr; }; /* Run structure contained in Schedule Resource */ struct RUN { - RUN *next; /* points to next run record */ - int level; /* level override */ - int Priority; /* priority override */ + RUN *next; /* points to next run record */ + int level; /* level override */ + int Priority; /* priority override */ int job_type; - bool spool_data; /* Data spooling override */ - bool spool_data_set; /* Data spooling override given */ - POOL *pool; /* Pool override */ - POOL *full_pool; /* Pool override */ - POOL *inc_pool; /* Pool override */ - POOL *dif_pool; /* Pool override */ - STORE *storage; /* Storage override */ - MSGS *msgs; /* Messages override */ + bool spool_data; /* Data spooling override */ + bool spool_data_set; /* Data spooling override given */ + POOL *pool; /* Pool override */ + POOL *full_pool; /* Pool override */ + POOL *inc_pool; /* Pool override */ + POOL *dif_pool; /* Pool override */ + STORE *storage; /* Storage override */ + MSGS *msgs; /* Messages override */ char *since; int level_no; - int minute; /* minute to run job */ - time_t last_run; /* last time run */ - time_t next_run; /* next time to run */ + int minute; /* minute to run job */ + time_t last_run; /* last time run */ + time_t next_run; /* next time to run */ char hour[nbytes_for_bits(24)]; /* bit set for each hour */ char mday[nbytes_for_bits(31)]; /* bit set for each day of month */ char month[nbytes_for_bits(12)]; /* bit set for each month */ diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index 2432151218..b47e223796 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -38,6 +38,7 @@ /* Commands sent to File daemon */ static char inc[] = "include\n"; static char exc[] = "exclude\n"; +static char incopts[] = "incopts\n"; /* new include with options */ static char jobcmd[] = "JobId=%d Job=%s SDid=%u SDtime=%u Authorization=%s\n"; static char levelcmd[] = "level = %s%s mtime_only=%d\n"; static char runbefore[] = "RunBeforeJob %s\n"; @@ -247,8 +248,8 @@ static int send_list(JCR *jcr, int list) } if (ie->num_opts) { fo = ie->opts_list[0]; - for (int j=0; jmatch.size(); j++) { - Dmsg1(100, "Match=%s\n", fo->match.get(j)); + for (int j=0; jregex.size(); j++) { + Dmsg1(100, "Regex=%s\n", fo->regex.get(j)); } } for (int j=0; jname_list.size(); j++) { diff --git a/bacula/src/dird/inc_conf.c b/bacula/src/dird/inc_conf.c index 2c1413217e..3e9e3d5f74 100644 --- a/bacula/src/dird/inc_conf.c +++ b/bacula/src/dird/inc_conf.c @@ -34,7 +34,8 @@ void store_inc(LEX *lc, RES_ITEM *item, int index, int pass); static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass); -static void store_match(LEX *lc, RES_ITEM *item, int index, int pass); +static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass); +static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass); static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass); static void store_fname(LEX *lc, RES_ITEM *item, int index, int pass); static void options_res(LEX *lc, RES_ITEM *item, int index, int pass); @@ -59,6 +60,7 @@ static INCEXE res_incexe; */ static RES_ITEM newinc_items[] = { {"file", store_fname, NULL, 0, 0, 0}, + {"include", store_fname, NULL, 0, 0, 0}, {"options", options_res, NULL, 0, 0, 0}, {NULL, NULL, NULL, 0, 0, 0} }; @@ -76,8 +78,9 @@ static RES_ITEM options_items[] = { {"readfifo", store_opts, NULL, 0, 0, 0}, {"replace", store_opts, NULL, 0, 0, 0}, {"portable", store_opts, NULL, 0, 0, 0}, - {"match", store_match, NULL, 0, 0, 0}, + {"regex", store_regex, NULL, 0, 0, 0}, {"base", store_base, NULL, 0, 0, 0}, + {"wild", store_wild, NULL, 0, 0, 0}, {NULL, NULL, NULL, 0, 0, 0} }; @@ -422,24 +425,25 @@ static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass) } -/* Store Match info */ -static void store_match(LEX *lc, RES_ITEM *item, int index, int pass) +/* Store regex info */ +static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass) { int token; if (pass == 1) { - /* Pickup Match string + /* Pickup regex string */ token = lex_get_token(lc, T_ALL); switch (token) { case T_IDENTIFIER: case T_UNQUOTED_STRING: case T_QUOTED_STRING: - setup_current_opts(); - res_incexe.current_opts->match.append(bstrdup(lc->str)); + res_incexe.current_opts->regex.append(bstrdup(lc->str)); + Dmsg3(200, "set regex %p size=%d %s\n", + res_incexe.current_opts, res_incexe.current_opts->regex.size(),lc->str); break; default: - scan_err1(lc, _("Expected a filename, got: %s\n"), lc->str); + scan_err1(lc, _("Expected a regex string, got: %s\n"), lc->str); } } else { /* pass 2 */ lex_get_token(lc, T_ALL); @@ -453,17 +457,46 @@ static void store_base(LEX *lc, RES_ITEM *item, int index, int pass) int token; if (pass == 1) { - setup_current_opts(); /* * Pickup Base Job Name */ token = lex_get_token(lc, T_NAME); - res_incexe.current_opts->base_list.append(bstrdup(lc->str)); + res_incexe.current_opts->base.append(bstrdup(lc->str)); + } else { /* pass 2 */ + lex_get_token(lc, T_ALL); + } + scan_to_eol(lc); +} + + +/* Store Wild-card info */ +static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass) +{ + int token; + + if (pass == 1) { + /* + * Pickup Wild-card string + */ + token = lex_get_token(lc, T_ALL); + switch (token) { + case T_IDENTIFIER: + case T_UNQUOTED_STRING: + case T_QUOTED_STRING: + res_incexe.current_opts->wild.append(bstrdup(lc->str)); + Dmsg3(200, "set wild %p size=%d %s\n", + res_incexe.current_opts, res_incexe.current_opts->wild.size(),lc->str); + break; + default: + scan_err1(lc, _("Expected a wild-card string, got: %s\n"), lc->str); + } } else { /* pass 2 */ lex_get_token(lc, T_ALL); } scan_to_eol(lc); } + + /* * Store Filename info. Note, for minor efficiency reasons, we * always increase the name buffer by 10 items because we expect @@ -513,6 +546,10 @@ static void options_res(LEX *lc, RES_ITEM *item, int index, int pass) scan_err1(lc, "Expecting open brace. Got %s", lc->str); } + if (pass == 1) { + setup_current_opts(); + } + while ((token = lex_get_token(lc, T_ALL)) != T_EOF) { if (token == T_EOL) { continue; @@ -567,7 +604,6 @@ static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass) /* Now scan for the value */ scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts)); if (pass == 1) { - setup_current_opts(); bstrncat(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS); Dmsg2(100, "new pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts); } @@ -579,13 +615,17 @@ static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass) /* If current_opts not defined, create first entry */ static void setup_current_opts(void) { - if (res_incexe.current_opts == NULL) { - res_incexe.current_opts = (FOPTS *)malloc(sizeof(FOPTS)); - memset(res_incexe.current_opts, 0, sizeof(FOPTS)); - res_incexe.current_opts->match.init(1, true); - res_incexe.current_opts->base_list.init(1, true); - res_incexe.num_opts = 1; + FOPTS *fo = (FOPTS *)malloc(sizeof(FOPTS)); + memset(fo, 0, sizeof(FOPTS)); + fo->regex.init(1, true); + fo->wild.init(1, true); + fo->base.init(1, true); + res_incexe.current_opts = fo; + if (res_incexe.num_opts == 0) { res_incexe.opts_list = (FOPTS **)malloc(sizeof(FOPTS *)); - res_incexe.opts_list[0] = res_incexe.current_opts; + } else { + res_incexe.opts_list = (FOPTS **)realloc(res_incexe.opts_list, + sizeof(FOPTS *) * (res_incexe.num_opts + 1)); } + res_incexe.opts_list[res_incexe.num_opts++] = fo; } -- 2.39.5