X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fdird_conf.c;h=e31f5c718cc37c2526f5ebfaeed85fb4e0354d82;hb=bbc3b07dfe6c4862dbf215b0c50e6fb707f1918c;hp=8a2ae6ef78dcb7540f255a05d8cc12eeab7829b5;hpb=8a4849053924f27f3c86c31623bad3602ae5dc58;p=bacula%2Fbacula diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 8a2ae6ef78..e31f5c718c 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ /* * Main configuration file parser for Bacula Directors, * some parts may be split into separate files such as @@ -21,20 +48,7 @@ * * Version $Id$ */ -/* - Copyright (C) 2000-2006 Kern Sibbald - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - version 2 as amended with additional clauses defined in the - file LICENSE in the main source directory. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - the file LICENSE for additional details. - - */ #include "bacula.h" #include "dird.h" @@ -60,8 +74,8 @@ void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass); void store_level(LEX *lc, RES_ITEM *item, int index, int pass); void store_replace(LEX *lc, RES_ITEM *item, int index, int pass); void store_acl(LEX *lc, RES_ITEM *item, int index, int pass); +void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); static void store_device(LEX *lc, RES_ITEM *item, int index, int pass); -static void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); static void store_runscript(LEX *lc, RES_ITEM *item, int index, int pass); static void store_runscript_when(LEX *lc, RES_ITEM *item, int index, int pass); static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass); @@ -72,7 +86,13 @@ static void store_short_runscript(LEX *lc, RES_ITEM *item, int index, int pass); * then move it to allocated memory when the resource * scan is complete. */ +#if defined(_MSC_VER) +extern "C" { // work around visual compiler mangling variables + URES res_all; +} +#else URES res_all; +#endif int res_all_size = sizeof(res_all); @@ -94,6 +114,7 @@ static RES_ITEM dir_items[] = { {"diraddresses",store_addresses, ITEM(res_dir.DIRaddrs), 0, ITEM_DEFAULT, 9101}, {"queryfile", store_dir, ITEM(res_dir.query_file), 0, ITEM_REQUIRED, 0}, {"workingdirectory", store_dir, ITEM(res_dir.working_directory), 0, ITEM_REQUIRED, 0}, + {"plugindirectory", store_dir, ITEM(res_dir.plugin_directory), 0, 0, 0}, {"scriptsdirectory", store_dir, ITEM(res_dir.scripts_directory), 0, 0, 0}, {"piddirectory",store_dir, ITEM(res_dir.pid_directory), 0, ITEM_REQUIRED, 0}, {"subsysdirectory", store_dir, ITEM(res_dir.subsys_directory), 0, 0, 0}, @@ -101,6 +122,8 @@ static RES_ITEM dir_items[] = { {"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0}, {"fdconnecttimeout", store_time,ITEM(res_dir.FDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30}, {"sdconnecttimeout", store_time,ITEM(res_dir.SDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30}, + {"heartbeatinterval", store_time, ITEM(res_dir.heartbeat_interval), 0, ITEM_DEFAULT, 0}, + {"tlsauthenticate", store_bool, ITEM(res_dir.tls_authenticate), 0, 0, 0}, {"tlsenable", store_bool, ITEM(res_dir.tls_enable), 0, 0, 0}, {"tlsrequire", store_bool, ITEM(res_dir.tls_require), 0, 0, 0}, {"tlsverifypeer", store_bool, ITEM(res_dir.tls_verify_peer), 0, ITEM_DEFAULT, true}, @@ -110,7 +133,7 @@ static RES_ITEM dir_items[] = { {"tlskey", store_dir, ITEM(res_dir.tls_keyfile), 0, 0, 0}, {"tlsdhfile", store_dir, ITEM(res_dir.tls_dhfile), 0, 0, 0}, {"tlsallowedcn", store_alist_str, ITEM(res_dir.tls_allowed_cns), 0, 0, 0}, - {NULL, NULL, NULL, 0, 0, 0} + {NULL, NULL, {0}, 0, 0, 0} }; /* @@ -131,6 +154,8 @@ static RES_ITEM con_items[] = { {"commandacl", store_acl, ITEM(res_con.ACL_lists), Command_ACL, 0, 0}, {"filesetacl", store_acl, ITEM(res_con.ACL_lists), FileSet_ACL, 0, 0}, {"catalogacl", store_acl, ITEM(res_con.ACL_lists), Catalog_ACL, 0, 0}, + {"whereacl", store_acl, ITEM(res_con.ACL_lists), Where_ACL, 0, 0}, + {"tlsauthenticate", store_bool, ITEM(res_con.tls_authenticate), 0, 0, 0}, {"tlsenable", store_bool, ITEM(res_con.tls_enable), 0, 0, 0}, {"tlsrequire", store_bool, ITEM(res_con.tls_require), 0, 0, 0}, {"tlsverifypeer", store_bool, ITEM(res_con.tls_verify_peer), 0, ITEM_DEFAULT, true}, @@ -140,7 +165,7 @@ static RES_ITEM con_items[] = { {"tlskey", store_dir, ITEM(res_con.tls_keyfile), 0, 0, 0}, {"tlsdhfile", store_dir, ITEM(res_con.tls_dhfile), 0, 0, 0}, {"tlsallowedcn", store_alist_str, ITEM(res_con.tls_allowed_cns), 0, 0, 0}, - {NULL, NULL, NULL, 0, 0, 0} + {NULL, NULL, {0}, 0, 0, 0} }; @@ -161,15 +186,18 @@ static RES_ITEM cli_items[] = { {"catalog", store_res, ITEM(res_client.catalog), R_CATALOG, ITEM_REQUIRED, 0}, {"fileretention", store_time, ITEM(res_client.FileRetention), 0, ITEM_DEFAULT, 60*60*24*60}, {"jobretention", store_time, ITEM(res_client.JobRetention), 0, ITEM_DEFAULT, 60*60*24*180}, + {"heartbeatinterval", store_time, ITEM(res_client.heartbeat_interval), 0, ITEM_DEFAULT, 0}, {"autoprune", store_bool, ITEM(res_client.AutoPrune), 0, ITEM_DEFAULT, true}, {"maximumconcurrentjobs", store_pint, ITEM(res_client.MaxConcurrentJobs), 0, ITEM_DEFAULT, 1}, + {"tlsauthenticate", store_bool, ITEM(res_client.tls_authenticate), 0, 0, 0}, {"tlsenable", store_bool, ITEM(res_client.tls_enable), 0, 0, 0}, {"tlsrequire", store_bool, ITEM(res_client.tls_require), 0, 0, 0}, {"tlscacertificatefile", store_dir, ITEM(res_client.tls_ca_certfile), 0, 0, 0}, {"tlscacertificatedir", store_dir, ITEM(res_client.tls_ca_certdir), 0, 0, 0}, {"tlscertificate", store_dir, ITEM(res_client.tls_certfile), 0, 0, 0}, {"tlskey", store_dir, ITEM(res_client.tls_keyfile), 0, 0, 0}, - {NULL, NULL, NULL, 0, 0, 0} + {"tlsallowedcn", store_alist_str, ITEM(res_client.tls_allowed_cns), 0, 0, 0}, + {NULL, NULL, {0}, 0, 0, 0} }; /* Storage daemon resource @@ -188,15 +216,17 @@ static RES_ITEM store_items[] = { {"mediatype", store_strname, ITEM(res_store.media_type), 0, ITEM_REQUIRED, 0}, {"autochanger", store_bool, ITEM(res_store.autochanger), 0, ITEM_DEFAULT, 0}, {"enabled", store_bool, ITEM(res_store.enabled), 0, ITEM_DEFAULT, true}, + {"heartbeatinterval", store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 0}, {"maximumconcurrentjobs", store_pint, ITEM(res_store.MaxConcurrentJobs), 0, ITEM_DEFAULT, 1}, {"sddport", store_pint, ITEM(res_store.SDDport), 0, 0, 0}, /* deprecated */ + {"tlsauthenticate", store_bool, ITEM(res_store.tls_authenticate), 0, 0, 0}, {"tlsenable", store_bool, ITEM(res_store.tls_enable), 0, 0, 0}, {"tlsrequire", store_bool, ITEM(res_store.tls_require), 0, 0, 0}, {"tlscacertificatefile", store_dir, ITEM(res_store.tls_ca_certfile), 0, 0, 0}, {"tlscacertificatedir", store_dir, ITEM(res_store.tls_ca_certdir), 0, 0, 0}, {"tlscertificate", store_dir, ITEM(res_store.tls_certfile), 0, 0, 0}, {"tlskey", store_dir, ITEM(res_store.tls_keyfile), 0, 0, 0}, - {NULL, NULL, NULL, 0, 0, 0} + {NULL, NULL, {0}, 0, 0, 0} }; /* @@ -215,10 +245,11 @@ static RES_ITEM cat_items[] = { {"dbpassword", store_str, ITEM(res_cat.db_password), 0, 0, 0}, {"user", store_str, ITEM(res_cat.db_user), 0, 0, 0}, {"dbname", store_str, ITEM(res_cat.db_name), 0, ITEM_REQUIRED, 0}, + {"dbdriver", store_str, ITEM(res_cat.db_driver), 0, 0, 0}, {"dbsocket", store_str, ITEM(res_cat.db_socket), 0, 0, 0}, /* Turned off for the moment */ {"multipleconnections", store_bit, ITEM(res_cat.mult_db_connections), 0, 0, 0}, - {NULL, NULL, NULL, 0, 0, 0} + {NULL, NULL, {0}, 0, 0, 0} }; /* @@ -236,17 +267,20 @@ RES_ITEM job_items[] = { {"pool", store_res, ITEM(res_job.pool), R_POOL, ITEM_REQUIRED, 0}, {"fullbackuppool", store_res, ITEM(res_job.full_pool), R_POOL, 0, 0}, {"incrementalbackuppool", store_res, ITEM(res_job.inc_pool), R_POOL, 0, 0}, - {"differentialbackuppool", store_res, ITEM(res_job.dif_pool), R_POOL, 0, 0}, + {"differentialbackuppool", store_res, ITEM(res_job.diff_pool), R_POOL, 0, 0}, {"client", store_res, ITEM(res_job.client), R_CLIENT, ITEM_REQUIRED, 0}, {"fileset", store_res, ITEM(res_job.fileset), R_FILESET, ITEM_REQUIRED, 0}, {"schedule", store_res, ITEM(res_job.schedule), R_SCHEDULE, 0, 0}, {"verifyjob", store_res, ITEM(res_job.verify_job), R_JOB, 0, 0}, {"jobtoverify", store_res, ITEM(res_job.verify_job), R_JOB, 0, 0}, {"jobdefs", store_res, ITEM(res_job.jobdefs), R_JOBDEFS, 0, 0}, - {"nextpool", store_res, ITEM(res_job.next_pool), R_POOL, 0, 0}, {"run", store_alist_str, ITEM(res_job.run_cmds), 0, 0, 0}, /* Root of where to restore files */ {"where", store_dir, ITEM(res_job.RestoreWhere), 0, 0, 0}, + {"regexwhere", store_str, ITEM(res_job.RegexWhere), 0, 0, 0}, + {"stripprefix", store_str, ITEM(res_job.strip_prefix), 0, 0, 0}, + {"addprefix", store_str, ITEM(res_job.add_prefix), 0, 0, 0}, + {"addsuffix", store_str, ITEM(res_job.add_suffix), 0, 0, 0}, /* Where to find bootstrap during restore */ {"bootstrap",store_dir, ITEM(res_job.RestoreBootstrap), 0, 0, 0}, /* Where to write bootstrap file during backup */ @@ -265,8 +299,10 @@ RES_ITEM job_items[] = { {"prunefiles", store_bool, ITEM(res_job.PruneFiles), 0, ITEM_DEFAULT, false}, {"prunevolumes",store_bool, ITEM(res_job.PruneVolumes), 0, ITEM_DEFAULT, false}, {"enabled", store_bool, ITEM(res_job.enabled), 0, ITEM_DEFAULT, true}, + {"optimizejobscheduling",store_bool, ITEM(res_job.OptimizeJobScheduling), 0, ITEM_DEFAULT, false}, {"spoolattributes",store_bool, ITEM(res_job.SpoolAttributes), 0, ITEM_DEFAULT, false}, {"spooldata", store_bool, ITEM(res_job.spool_data), 0, ITEM_DEFAULT, false}, + {"spoolsize", store_size, ITEM(res_job.spool_size), 0, 0, 0}, {"rerunfailedlevels", store_bool, ITEM(res_job.rerun_failed_levels), 0, ITEM_DEFAULT, false}, {"prefermountedvolumes", store_bool, ITEM(res_job.PreferMountedVolumes), 0, ITEM_DEFAULT, true}, {"runbeforejob", store_short_runscript, ITEM(res_job.RunScripts), 0, 0, 0}, @@ -279,11 +315,12 @@ RES_ITEM job_items[] = { {"rescheduleinterval", store_time, ITEM(res_job.RescheduleInterval), 0, ITEM_DEFAULT, 60 * 30}, {"rescheduletimes", store_pint, ITEM(res_job.RescheduleTimes), 0, 0, 0}, {"priority", store_pint, ITEM(res_job.Priority), 0, ITEM_DEFAULT, 10}, - {"writepartafterjob", store_bool, ITEM(res_job.write_part_after_job), 0, ITEM_DEFAULT, false}, + {"writepartafterjob", store_bool, ITEM(res_job.write_part_after_job), 0, ITEM_DEFAULT, true}, {"selectionpattern", store_str, ITEM(res_job.selection_pattern), 0, 0, 0}, - {"selectiontype", store_migtype, ITEM(res_job.selection_type), 0, 0, 0}, {"runscript", store_runscript, ITEM(res_job.RunScripts), 0, ITEM_NO_EQUALS, 0}, - {NULL, NULL, NULL, 0, 0, 0} + {"selectiontype", store_migtype, ITEM(res_job.selection_type), 0, 0, 0}, + {"accurate", store_bool, ITEM(res_job.accurate), 0,0,0}, + {NULL, NULL, {0}, 0, 0, 0} }; /* FileSet resource @@ -293,11 +330,11 @@ RES_ITEM job_items[] = { static RES_ITEM fs_items[] = { {"name", store_name, ITEM(res_fs.hdr.name), 0, ITEM_REQUIRED, 0}, {"description", store_str, ITEM(res_fs.hdr.desc), 0, 0, 0}, - {"include", store_inc, NULL, 0, ITEM_NO_EQUALS, 0}, - {"exclude", store_inc, NULL, 1, ITEM_NO_EQUALS, 0}, + {"include", store_inc, {0}, 0, ITEM_NO_EQUALS, 0}, + {"exclude", store_inc, {0}, 1, ITEM_NO_EQUALS, 0}, {"ignorefilesetchanges", store_bool, ITEM(res_fs.ignore_fs_changes), 0, ITEM_DEFAULT, false}, - {"enablevss", store_bool, ITEM(res_fs.enable_vss), 0, ITEM_DEFAULT, false}, - {NULL, NULL, NULL, 0, 0, 0} + {"enablevss", store_bool, ITEM(res_fs.enable_vss), 0, ITEM_DEFAULT, true}, + {NULL, NULL, {0}, 0, 0, 0} }; /* Schedule -- see run_conf.c */ @@ -309,7 +346,7 @@ static RES_ITEM sch_items[] = { {"name", store_name, ITEM(res_sch.hdr.name), 0, ITEM_REQUIRED, 0}, {"description", store_str, ITEM(res_sch.hdr.desc), 0, 0, 0}, {"run", store_run, ITEM(res_sch.run), 0, 0, 0}, - {NULL, NULL, NULL, 0, 0, 0} + {NULL, NULL, {0}, 0, 0, 0} }; /* Pool resource @@ -332,7 +369,6 @@ static RES_ITEM pool_items[] = { {"maximumvolumejobs", store_pint, ITEM(res_pool.MaxVolJobs), 0, 0, 0}, {"maximumvolumefiles", store_pint, ITEM(res_pool.MaxVolFiles), 0, 0, 0}, {"maximumvolumebytes", store_size, ITEM(res_pool.MaxVolBytes), 0, 0, 0}, - {"acceptanyvolume", store_bool, ITEM(res_pool.accept_any_volume), 0, ITEM_DEFAULT, true}, {"catalogfiles", store_bool, ITEM(res_pool.catalog_files), 0, ITEM_DEFAULT, true}, {"volumeretention", store_time, ITEM(res_pool.VolRetention), 0, ITEM_DEFAULT, 60*60*24*365}, {"volumeuseduration", store_time, ITEM(res_pool.VolUseDuration), 0, 0, 0}, @@ -341,9 +377,12 @@ static RES_ITEM pool_items[] = { {"migrationlowbytes", store_size, ITEM(res_pool.MigrationLowBytes), 0, 0, 0}, {"nextpool", store_res, ITEM(res_pool.NextPool), R_POOL, 0, 0}, {"storage", store_alist_res, ITEM(res_pool.storage), R_STORAGE, 0, 0}, - {"autoprune", store_bool, ITEM(res_pool.AutoPrune), 0, ITEM_DEFAULT, true}, - {"recycle", store_bool, ITEM(res_pool.Recycle), 0, ITEM_DEFAULT, true}, - {NULL, NULL, NULL, 0, 0, 0} + {"autoprune", store_bool, ITEM(res_pool.AutoPrune), 0, ITEM_DEFAULT, true}, + {"recycle", store_bool, ITEM(res_pool.Recycle), 0, ITEM_DEFAULT, true}, + {"recyclepool", store_res, ITEM(res_pool.RecyclePool), R_POOL, 0, 0}, + {"copypool", store_alist_res, ITEM(res_pool.CopyPool), R_POOL, 0, 0}, + {"catalog", store_res, ITEM(res_pool.Catalog), R_CATALOG, 0, 0}, + {NULL, NULL, {0}, 0, 0, 0} }; /* @@ -357,7 +396,7 @@ static RES_ITEM counter_items[] = { {"maximum", store_pint, ITEM(res_counter.MaxValue), 0, ITEM_DEFAULT, INT32_MAX}, {"wrapcounter", store_res, ITEM(res_counter.WrapCounter), R_COUNTER, 0, 0}, {"catalog", store_res, ITEM(res_counter.Catalog), R_CATALOG, 0, 0}, - {NULL, NULL, NULL, 0, 0, 0} + {NULL, NULL, {0}, 0, 0, 0} }; @@ -532,6 +571,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm dump_resource(-R_CATALOG, (RES *)res->res_client.catalog, sendit, sock); } break; + case R_DEVICE: dev = &res->res_dev; char ed1[50]; @@ -544,6 +584,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm edit_uint64(dev->PoolId, ed1), dev->VolumeName, dev->MediaType); break; + case R_STORAGE: sendit(sock, _("Storage: name=%s address=%s SDport=%d MaxJobs=%u\n" " DeviceName=%s MediaType=%s StorageId=%s\n"), @@ -553,13 +594,16 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm res->res_store.media_type, edit_int64(res->res_store.StorageId, ed1)); break; + case R_CATALOG: sendit(sock, _("Catalog: name=%s address=%s DBport=%d db_name=%s\n" -" db_user=%s MutliDBConn=%d\n"), +" db_driver=%s db_user=%s MutliDBConn=%d\n"), res->res_cat.hdr.name, NPRT(res->res_cat.db_address), - res->res_cat.db_port, res->res_cat.db_name, NPRT(res->res_cat.db_user), + res->res_cat.db_port, res->res_cat.db_name, + NPRT(res->res_cat.db_driver), NPRT(res->res_cat.db_user), res->res_cat.mult_db_connections); break; + case R_JOB: case R_JOBDEFS: sendit(sock, _("%s: name=%s JobType=%d level=%s Priority=%d Enabled=%d\n"), @@ -572,6 +616,12 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm res->res_job.RescheduleOnError, res->res_job.RescheduleTimes, edit_uint64_with_commas(res->res_job.RescheduleInterval, ed1), res->res_job.spool_data, res->res_job.write_part_after_job); + if (res->res_job.spool_size) { + sendit(sock, _(" SpoolSize=%s\n"), edit_uint64(res->res_job.spool_size, ed1)); + } + if (res->res_job.JobType == JT_BACKUP) { + sendit(sock, _(" Accurate=%d\n"), res->res_job.accurate); + } if (res->res_job.JobType == JT_MIGRATE) { sendit(sock, _(" SelectionType=%d\n"), res->res_job.selection_type); } @@ -587,8 +637,11 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm sendit(sock, _(" --> ")); dump_resource(-R_SCHEDULE, (RES *)res->res_job.schedule, sendit, sock); } - if (res->res_job.RestoreWhere) { - sendit(sock, _(" --> Where=%s\n"), NPRT(res->res_job.RestoreWhere)); + if (res->res_job.RestoreWhere && !res->res_job.RegexWhere) { + sendit(sock, _(" --> Where=%s\n"), NPRT(res->res_job.RestoreWhere)); + } + if (res->res_job.RegexWhere) { + sendit(sock, _(" --> RegexWhere=%s\n"), NPRT(res->res_job.RegexWhere)); } if (res->res_job.RestoreBootstrap) { sendit(sock, _(" --> Bootstrap=%s\n"), NPRT(res->res_job.RestoreBootstrap)); @@ -611,7 +664,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm sendit(sock, _(" --> Target=%s\n"), NPRT(script->target)); sendit(sock, _(" --> RunOnSuccess=%u\n"), script->on_success); sendit(sock, _(" --> RunOnFailure=%u\n"), script->on_failure); - sendit(sock, _(" --> AbortJobOnError=%u\n"), script->abort_on_error); + sendit(sock, _(" --> FailJobOnError=%u\n"), script->fail_on_error); sendit(sock, _(" --> RunWhen=%u\n"), script->when); } } @@ -627,9 +680,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm sendit(sock, _(" --> ")); dump_resource(-R_POOL, (RES *)res->res_job.inc_pool, sendit, sock); } - if (res->res_job.dif_pool) { + if (res->res_job.diff_pool) { sendit(sock, _(" --> ")); - dump_resource(-R_POOL, (RES *)res->res_job.dif_pool, sendit, sock); + dump_resource(-R_POOL, (RES *)res->res_job.diff_pool, sendit, sock); } if (res->res_job.verify_job) { sendit(sock, _(" --> ")); @@ -649,6 +702,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm dump_resource(-R_MSGS, (RES *)res->res_job.messages, sendit, sock); } break; + case R_FILESET: { int i, j, k; @@ -658,6 +712,15 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm for (j=0; jnum_opts; j++) { FOPTS *fo = incexe->opts_list[j]; sendit(sock, " O %s\n", fo->opts); + + bool enhanced_wild = false; + for (k=0; fo->opts[k]!='\0'; k++) { + if (fo->opts[k]=='W') { + enhanced_wild = true; + break; + } + } + for (k=0; kregex.size(); k++) { sendit(sock, " R %s\n", fo->regex.get(k)); } @@ -676,12 +739,21 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm for (k=0; kwildfile.size(); k++) { sendit(sock, " WF %s\n", fo->wildfile.get(k)); } + for (k=0; kwildbase.size(); k++) { + sendit(sock, " W%c %s\n", enhanced_wild ? 'B' : 'F', fo->wildbase.get(k)); + } for (k=0; kbase.size(); k++) { sendit(sock, " B %s\n", fo->base.get(k)); } for (k=0; kfstype.size(); k++) { sendit(sock, " X %s\n", fo->fstype.get(k)); } + for (k=0; kdrivetype.size(); k++) { + sendit(sock, " XD %s\n", fo->drivetype.get(k)); + } + if (fo->plugin) { + sendit(sock, " G %s\n", fo->plugin); + } if (fo->reader) { sendit(sock, " D %s\n", fo->reader); } @@ -696,6 +768,13 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm if (incexe->name_list.size()) { sendit(sock, " N\n"); } + for (j=0; jplugin_list.size(); j++) { + sendit(sock, " P %s\n", incexe->plugin_list.get(j)); + } + if (incexe->plugin_list.size()) { + sendit(sock, " N\n"); + } + } for (i=0; ires_fs.num_excludes; i++) { @@ -709,6 +788,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm } break; } + case R_SCHEDULE: if (res->res_sch.run) { int i; @@ -796,12 +876,13 @@ next_run: sendit(sock, _("Schedule: name=%s\n"), res->res_sch.hdr.name); } break; + case R_POOL: sendit(sock, _("Pool: name=%s PoolType=%s\n"), res->res_pool.hdr.name, res->res_pool.pool_type); - sendit(sock, _(" use_cat=%d use_once=%d acpt_any=%d cat_files=%d\n"), + sendit(sock, _(" use_cat=%d use_once=%d cat_files=%d\n"), res->res_pool.use_catalog, res->res_pool.use_volume_once, - res->res_pool.accept_any_volume, res->res_pool.catalog_files); + res->res_pool.catalog_files); sendit(sock, _(" max_vols=%d auto_prune=%d VolRetention=%s\n"), res->res_pool.max_volumes, res->res_pool.AutoPrune, edit_utime(res->res_pool.VolRetention, ed1, sizeof(ed1))); @@ -811,17 +892,25 @@ next_run: NPRT(res->res_pool.label_format)); sendit(sock, _(" CleaningPrefix=%s LabelType=%d\n"), NPRT(res->res_pool.cleaning_prefix), res->res_pool.LabelType); - sendit(sock, _(" RecyleOldest=%d PurgeOldest=%d MaxVolJobs=%d MaxVolFiles=%d\n"), + sendit(sock, _(" RecyleOldest=%d PurgeOldest=%d\n"), res->res_pool.recycle_oldest_volume, - res->res_pool.purge_oldest_volume, - res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles); + res->res_pool.purge_oldest_volume); + sendit(sock, _(" MaxVolJobs=%d MaxVolFiles=%d MaxVolBytes=%s\n"), + res->res_pool.MaxVolJobs, + res->res_pool.MaxVolFiles, + edit_uint64(res->res_pool.MaxVolFiles, ed1)); sendit(sock, _(" MigTime=%s MigHiBytes=%s MigLoBytes=%s\n"), edit_utime(res->res_pool.MigrationTime, ed1, sizeof(ed1)), edit_uint64(res->res_pool.MigrationHighBytes, ed2), edit_uint64(res->res_pool.MigrationLowBytes, ed3)); if (res->res_pool.NextPool) { - sendit(sock, _(" --> ")); - dump_resource(-R_POOL, (RES *)res->res_pool.NextPool, sendit, sock); + sendit(sock, _(" NextPool=%s\n"), res->res_pool.NextPool->name()); + } + if (res->res_pool.RecyclePool) { + sendit(sock, _(" RecyclePool=%s\n"), res->res_pool.RecyclePool->name()); + } + if (res->res_pool.Catalog) { + sendit(sock, _(" Catalog=%s\n"), res->res_pool.Catalog->name()); } if (res->res_pool.storage) { STORE *store; @@ -830,7 +919,16 @@ next_run: dump_resource(-R_STORAGE, (RES *)store, sendit, sock); } } + if (res->res_pool.CopyPool) { + POOL *copy; + foreach_alist(copy, res->res_pool.CopyPool) { + sendit(sock, _(" --> ")); + dump_resource(-R_POOL, (RES *)copy, sendit, sock); + } + } + break; + case R_MSGS: sendit(sock, _("Messages: name=%s\n"), res->res_msgs.hdr.name); if (res->res_msgs.mail_cmd) @@ -838,6 +936,7 @@ next_run: if (res->res_msgs.operator_cmd) sendit(sock, _(" opcmd=%s\n"), res->res_msgs.operator_cmd); break; + default: sendit(sock, _("Unknown resource type %d in dump_resource.\n"), type); break; @@ -853,6 +952,7 @@ next_run: static void free_incexe(INCEXE *incexe) { incexe->name_list.destroy(); + incexe->plugin_list.destroy(); for (int i=0; inum_opts; i++) { FOPTS *fopt = incexe->opts_list[i]; fopt->regex.destroy(); @@ -861,8 +961,13 @@ static void free_incexe(INCEXE *incexe) fopt->wild.destroy(); fopt->wilddir.destroy(); fopt->wildfile.destroy(); + fopt->wildbase.destroy(); fopt->base.destroy(); fopt->fstype.destroy(); + fopt->drivetype.destroy(); + if (fopt->plugin) { + free(fopt->plugin); + } if (fopt->reader) { free(fopt->reader); } @@ -1004,6 +1109,9 @@ void free_resource(RES *sres, int type) if (res->res_client.tls_keyfile) { free(res->res_client.tls_keyfile); } + if (res->res_client.tls_allowed_cns) { + delete res->res_client.tls_allowed_cns; + } break; case R_STORAGE: if (res->res_store.address) { @@ -1047,6 +1155,9 @@ void free_resource(RES *sres, int type) if (res->res_cat.db_name) { free(res->res_cat.db_name); } + if (res->res_cat.db_driver) { + free(res->res_cat.db_driver); + } if (res->res_cat.db_password) { free(res->res_cat.db_password); } @@ -1097,6 +1208,18 @@ void free_resource(RES *sres, int type) if (res->res_job.RestoreWhere) { free(res->res_job.RestoreWhere); } + if (res->res_job.RegexWhere) { + free(res->res_job.RegexWhere); + } + if (res->res_job.strip_prefix) { + free(res->res_job.strip_prefix); + } + if (res->res_job.add_prefix) { + free(res->res_job.add_prefix); + } + if (res->res_job.add_suffix) { + free(res->res_job.add_suffix); + } if (res->res_job.RestoreBootstrap) { free(res->res_job.RestoreBootstrap); } @@ -1210,7 +1333,9 @@ void save_resource(int type, RES_ITEM *items, int pass) } /* Explicitly copy resource pointers from this pass (res_all) */ res->res_pool.NextPool = res_all.res_pool.NextPool; + res->res_pool.RecyclePool = res_all.res_pool.RecyclePool; res->res_pool.storage = res_all.res_pool.storage; + res->res_pool.Catalog = res_all.res_pool.Catalog; break; case R_CONSOLE: if ((res = (URES *)GetResWithName(R_CONSOLE, res_all.res_con.hdr.name)) == NULL) { @@ -1247,11 +1372,41 @@ void save_resource(int type, RES_ITEM *items, int pass) res->res_job.pool = res_all.res_job.pool; res->res_job.full_pool = res_all.res_job.full_pool; res->res_job.inc_pool = res_all.res_job.inc_pool; - res->res_job.dif_pool = res_all.res_job.dif_pool; + res->res_job.diff_pool = res_all.res_job.diff_pool; res->res_job.verify_job = res_all.res_job.verify_job; res->res_job.jobdefs = res_all.res_job.jobdefs; res->res_job.run_cmds = res_all.res_job.run_cmds; res->res_job.RunScripts = res_all.res_job.RunScripts; + + /* TODO: JobDefs where/regexwhere doesn't work well (but this + * is not very useful) + * We have to set_bit(index, res_all.hdr.item_present); + * or something like that + */ + + /* we take RegexWhere before all other options */ + if (!res->res_job.RegexWhere + && + (res->res_job.strip_prefix || + res->res_job.add_suffix || + res->res_job.add_prefix)) + { + int len = bregexp_get_build_where_size(res->res_job.strip_prefix, + res->res_job.add_prefix, + res->res_job.add_suffix); + res->res_job.RegexWhere = (char *) bmalloc (len * sizeof(char)); + bregexp_build_where(res->res_job.RegexWhere, len, + res->res_job.strip_prefix, + res->res_job.add_prefix, + res->res_job.add_suffix); + /* TODO: test bregexp */ + } + + if (res->res_job.RegexWhere && res->res_job.RestoreWhere) { + free(res->res_job.RestoreWhere); + res->res_job.RestoreWhere = NULL; + } + break; case R_COUNTER: if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) { @@ -1266,6 +1421,7 @@ void save_resource(int type, RES_ITEM *items, int pass) Emsg1(M_ERROR_TERM, 0, _("Cannot find Client resource %s\n"), res_all.res_client.hdr.name); } res->res_client.catalog = res_all.res_client.catalog; + res->res_client.tls_allowed_cns = res_all.res_client.tls_allowed_cns; break; case R_SCHEDULE: /* @@ -1340,7 +1496,7 @@ void save_resource(int type, RES_ITEM *items, int pass) error = true; break; default: - printf(_("Unknown resource type %d in save_resrouce.\n"), type); + printf(_("Unknown resource type %d in save_resource.\n"), type); error = true; break; } @@ -1353,20 +1509,21 @@ void save_resource(int type, RES_ITEM *items, int pass) Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type), res->res_dir.hdr.name, rindex); } else { - RES *next; + RES *next, *last; if (res->res_dir.hdr.name == NULL) { Emsg1(M_ERROR_TERM, 0, _("Name item is required in %s resource, but not found.\n"), resources[rindex]); } /* Add new res to end of chain */ - for (next=res_head[rindex]; next->next; next=next->next) { + for (last=next=res_head[rindex]; next; next=next->next) { + last = next; if (strcmp(next->name, res->res_dir.hdr.name) == 0) { Emsg2(M_ERROR_TERM, 0, _("Attempt to define second %s resource named \"%s\" is not permitted.\n"), resources[rindex].name, res->res_dir.hdr.name); } } - next->next = (RES *)res; + last->next = (RES *)res; Dmsg4(900, _("Inserting %s res: %s index=%d pass=%d\n"), res_to_str(type), res->res_dir.hdr.name, rindex, pass); } @@ -1425,7 +1582,7 @@ static void store_device(LEX *lc, RES_ITEM *item, int index, int pass) * Store JobType (backup, verify, restore) * */ -static void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass) +void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass) { int token, i; @@ -1524,7 +1681,7 @@ void store_acl(LEX *lc, RES_ITEM *item, int index, int pass) int token; for (;;) { - token = lex_get_token(lc, T_NAME); + token = lex_get_token(lc, T_STRING); if (pass == 1) { if (((alist **)item->value)[item->code] == NULL) { ((alist **)item->value)[item->code] = New(alist(10, owned_by_alist)); @@ -1542,6 +1699,8 @@ void store_acl(LEX *lc, RES_ITEM *item, int index, int pass) set_bit(index, res_all.hdr.item_present); } +/* We build RunScripts items here */ +static RUNSCRIPT res_runscript; /* Store a runscript->when in a bit field */ static void store_runscript_when(LEX *lc, RES_ITEM *item, int index, int pass) @@ -1569,33 +1728,33 @@ static void store_runscript_target(LEX *lc, RES_ITEM *item, int index, int pass) if (pass == 2) { if (strcmp(lc->str, "%c") == 0) { - ((RUNSCRIPT*) item->value)->set_target(lc->str); - } else if (strcmp(lc->str, "yes") == 0) { - ((RUNSCRIPT*) item->value)->set_target("%c"); - } else if (strcmp(lc->str, "no") == 0) { - /* store nothing, run on director */ + ((RUNSCRIPT*) item->value)->set_target(lc->str); + } else if (strcasecmp(lc->str, "yes") == 0) { + ((RUNSCRIPT*) item->value)->set_target("%c"); + } else if (strcasecmp(lc->str, "no") == 0) { + ((RUNSCRIPT*) item->value)->set_target(""); } else { - RES *res = GetResWithName(R_CLIENT, lc->str); - if (res == NULL) { - scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"), - lc->str, lc->line_no, lc->line); - } + RES *res = GetResWithName(R_CLIENT, lc->str); + if (res == NULL) { + scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"), + lc->str, lc->line_no, lc->line); + } - ((RUNSCRIPT*) item->value)->set_target(lc->str); + ((RUNSCRIPT*) item->value)->set_target(lc->str); } } scan_to_eol(lc); } -/* Store a runscript->command in a bit field - * +/* + * Store a runscript->command as a string */ static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass) { lex_get_token(lc, T_STRING); if (pass == 2) { - ((RUNSCRIPT*) item->value)->set_command(lc->str); + ((RUNSCRIPT*)item->value)->set_command(lc->str, item->code); } scan_to_eol(lc); } @@ -1607,33 +1766,41 @@ static void store_short_runscript(LEX *lc, RES_ITEM *item, int index, int pass) if (pass == 2) { RUNSCRIPT *script = new_runscript(); + script->set_job_code_callback(job_code_callback_filesetname); script->set_command(lc->str); + /* TODO: remove all script->old_proto with bacula 1.42 */ + if (strcmp(item->name, "runbeforejob") == 0) { - script->when = SCRIPT_Before; - script->abort_on_error = true; + script->when = SCRIPT_Before; + script->fail_on_error = true; + script->set_target(""); } else if (strcmp(item->name, "runafterjob") == 0) { - script->when = SCRIPT_After; - script->on_success = true; - script->on_failure = false; - + script->when = SCRIPT_After; + script->on_success = true; + script->on_failure = false; + script->set_target(""); + } else if (strcmp(item->name, "clientrunafterjob") == 0) { - script->when = SCRIPT_After; - script->set_target("%c"); - script->on_success = true; - script->on_failure = false; + script->old_proto = true; + script->when = SCRIPT_After; + script->set_target("%c"); + script->on_success = true; + script->on_failure = false; } else if (strcmp(item->name, "clientrunbeforejob") == 0) { - script->when = SCRIPT_Before; - script->set_target("%c"); - script->abort_on_error = true; + script->old_proto = true; + script->when = SCRIPT_Before; + script->set_target("%c"); + script->fail_on_error = true; } else if (strcmp(item->name, "runafterfailedjob") == 0) { - script->when = SCRIPT_After; - script->on_failure = true; - script->on_success = false; + script->when = SCRIPT_After; + script->on_failure = true; + script->on_success = false; + script->set_target(""); } if (*runscripts == NULL) { @@ -1647,22 +1814,37 @@ static void store_short_runscript(LEX *lc, RES_ITEM *item, int index, int pass) scan_to_eol(lc); } -static RUNSCRIPT res_runscript; +/* Store a bool in a bit field without modifing res_all.hdr + * We can also add an option to store_bool to skip res_all.hdr + */ +void store_runscript_bool(LEX *lc, RES_ITEM *item, int index, int pass) +{ + lex_get_token(lc, T_NAME); + if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) { + *(bool *)(item->value) = true; + } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) { + *(bool *)(item->value) = false; + } else { + scan_err2(lc, _("Expect %s, got: %s"), "YES, NO, TRUE, or FALSE", lc->str); /* YES and NO must not be translated */ + } + scan_to_eol(lc); +} /* * new RunScript items - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM runscript_items[] = { - {"command", store_runscript_cmd, (char **)&res_runscript, 0, ITEM_REQUIRED, 0}, - {"target", store_runscript_target, (char **)&res_runscript, 0, 0, 0}, - {"runsonsuccess", store_bool, (char **)&res_runscript.on_success, 0, 0, 0}, - {"runsonfailure", store_bool, (char **)&res_runscript.on_failure, 0, 0, 0}, - {"abortjobonerror", store_bool, (char **)&res_runscript.abort_on_error, 0, 0, 0}, - {"runswhen", store_runscript_when, (char **)&res_runscript.when, 0, 0, 0}, - {"runsonclient", store_runscript_target, (char **)&res_runscript, 0, 0, 0}, /* TODO */ - - {NULL, NULL, NULL, 0, 0, 0} + {"command", store_runscript_cmd, {(char **)&res_runscript}, SHELL_CMD, 0, 0}, + {"console", store_runscript_cmd, {(char **)&res_runscript}, CONSOLE_CMD, 0, 0}, + {"target", store_runscript_target,{(char **)&res_runscript}, 0, 0, 0}, + {"runsonsuccess", store_runscript_bool, {(char **)&res_runscript.on_success},0, 0, 0}, + {"runsonfailure", store_runscript_bool, {(char **)&res_runscript.on_failure},0, 0, 0}, + {"failjobonerror",store_runscript_bool, {(char **)&res_runscript.fail_on_error},0, 0, 0}, + {"abortjobonerror",store_runscript_bool, {(char **)&res_runscript.fail_on_error},0, 0, 0}, + {"runswhen", store_runscript_when, {(char **)&res_runscript.when}, 0, 0, 0}, + {"runsonclient", store_runscript_target,{(char **)&res_runscript}, 0, 0, 0}, /* TODO */ + {NULL, NULL, {0}, 0, 0, 0} }; /* @@ -1679,7 +1861,7 @@ static void store_runscript(LEX *lc, RES_ITEM *item, int index, int pass) Dmsg1(200, "store_runscript: begin store_runscript pass=%i\n", pass); - res_runscript.reset_default(); /* setting on_success, on_failure, abort_on_error */ + res_runscript.reset_default(); /* setting on_success, on_failure, fail_on_error */ token = lex_get_token(lc, T_SKIP_EOL); @@ -1715,11 +1897,18 @@ static void store_runscript(LEX *lc, RES_ITEM *item, int index, int pass) if (pass == 2) { if (res_runscript.command == NULL) { - scan_err2(lc, _("%s item is required in %s resource, but not found.\n"), - "command", "runscript"); + scan_err2(lc, _("%s item is required in %s resource, but not found.\n"), + "command", "runscript"); + } + + /* run on client by default */ + if (res_runscript.target == NULL) { + res_runscript.set_target("%c"); } + RUNSCRIPT *script = new_runscript(); memcpy(script, &res_runscript, sizeof(RUNSCRIPT)); + script->set_job_code_callback(job_code_callback_filesetname); if (*runscripts == NULL) { *runscripts = New(alist(10, not_owned_by_alist)); @@ -1732,3 +1921,13 @@ static void store_runscript(LEX *lc, RES_ITEM *item, int index, int pass) scan_to_eol(lc); set_bit(index, res_all.hdr.item_present); } + +/* callback function for edit_job_codes */ +extern "C" char *job_code_callback_filesetname(JCR *jcr, const char* param) +{ + if (param[0] == 'f') { + return jcr->fileset->name(); + } else { + return NULL; + } +}