]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/dird_conf.c
Clean up error message generation during update attributes -- should fix bug #1823
[bacula/bacula] / bacula / src / dird / dird_conf.c
index dccce907fd35d8e844c28810d03761ab5ba48fb6..2f2eb000d28ff2904ba3913aa16a7e3b0815e971 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2011 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
+   modify it under the terms of version three of the GNU Affero General Public
    License as published by the Free Software Foundation and included
    in the file LICENSE.
 
@@ -15,7 +15,7 @@
    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
+   You should have received a copy of the GNU Affero 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.
@@ -46,7 +46,6 @@
  *
  *     Kern Sibbald, January MM
  *
- *     Version $Id$
  */
 
 
@@ -75,6 +74,7 @@ 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_actiononpurge(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_runscript(LEX *lc, RES_ITEM *item, int index, int pass);
 static void store_runscript_when(LEX *lc, RES_ITEM *item, int index, int pass);
@@ -221,6 +221,7 @@ 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},
+   {"allowcompression",  store_bool, ITEM(res_store.AllowCompress), 0, ITEM_DEFAULT, true},
    {"heartbeatinterval", store_time, ITEM(res_store.heartbeat_interval), 0, ITEM_DEFAULT, 0},
    {"maximumconcurrentjobs", store_pint32, ITEM(res_store.MaxConcurrentJobs), 0, ITEM_DEFAULT, 1},
    {"sddport", store_pint32, ITEM(res_store.SDDport), 0, 0, 0}, /* deprecated */
@@ -255,6 +256,7 @@ static RES_ITEM cat_items[] = {
    {"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},
+   {"disablebatchinsert", store_bool, ITEM(res_cat.disable_batch_insert), 0, ITEM_DEFAULT, false},
    {NULL, NULL, {0}, 0, 0, 0}
 };
 
@@ -306,15 +308,15 @@ RES_ITEM job_items[] = {
    {"maxstartdelay",store_time, ITEM(res_job.MaxStartDelay), 0, 0, 0},
    {"maxfullinterval",  store_time, ITEM(res_job.MaxFullInterval), 0, 0, 0},
    {"maxdiffinterval",  store_time, ITEM(res_job.MaxDiffInterval), 0, 0, 0},
-   {"jobretention", store_time, ITEM(res_job.JobRetention),  0, 0, 0},
    {"prefixlinks", store_bool, ITEM(res_job.PrefixLinks), 0, ITEM_DEFAULT, false},
    {"prunejobs",   store_bool, ITEM(res_job.PruneJobs), 0, ITEM_DEFAULT, false},
    {"prunefiles",  store_bool, ITEM(res_job.PruneFiles), 0, ITEM_DEFAULT, false},
    {"prunevolumes",store_bool, ITEM(res_job.PruneVolumes), 0, ITEM_DEFAULT, false},
+   {"purgemigrationjob",  store_bool, ITEM(res_job.PurgeMigrateJob), 0, ITEM_DEFAULT, false},
    {"enabled",     store_bool, ITEM(res_job.enabled), 0, ITEM_DEFAULT, true},
    {"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},
+   {"spoolsize",   store_size64, 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},
@@ -325,7 +327,7 @@ RES_ITEM job_items[] = {
    {"maximumconcurrentjobs", store_pint32, ITEM(res_job.MaxConcurrentJobs), 0, ITEM_DEFAULT, 1},
    {"rescheduleonerror", store_bool, ITEM(res_job.RescheduleOnError), 0, ITEM_DEFAULT, false},
    {"rescheduleinterval", store_time, ITEM(res_job.RescheduleInterval), 0, ITEM_DEFAULT, 60 * 30},
-   {"rescheduletimes",    store_pint32, ITEM(res_job.RescheduleTimes), 0, 0, 0},
+   {"rescheduletimes",    store_pint32, ITEM(res_job.RescheduleTimes), 0, 0, 5},
    {"priority",           store_pint32, ITEM(res_job.Priority), 0, ITEM_DEFAULT, 10},
    {"allowmixedpriority", store_bool, ITEM(res_job.allow_mixed_priority), 0, ITEM_DEFAULT, false},
    {"writepartafterjob",  store_bool, ITEM(res_job.write_part_after_job), 0, ITEM_DEFAULT, true},
@@ -333,8 +335,9 @@ RES_ITEM job_items[] = {
    {"runscript",          store_runscript, ITEM(res_job.RunScripts), 0, ITEM_NO_EQUALS, 0},
    {"selectiontype",      store_migtype, ITEM(res_job.selection_type), 0, 0, 0},
    {"accurate",           store_bool, ITEM(res_job.accurate), 0,0,0},
-   {"allowduplicatejobs", store_bool, ITEM(res_job.AllowDuplicateJobs), 0, ITEM_DEFAULT, false},
+   {"allowduplicatejobs", store_bool, ITEM(res_job.AllowDuplicateJobs), 0, ITEM_DEFAULT, true},
    {"allowhigherduplicates",   store_bool, ITEM(res_job.AllowHigherDuplicates), 0, ITEM_DEFAULT, true},
+   {"cancellowerlevelduplicates", store_bool, ITEM(res_job.CancelLowerLevelDuplicates), 0, ITEM_DEFAULT, false},
    {"cancelqueuedduplicates",  store_bool, ITEM(res_job.CancelQueuedDuplicates), 0, ITEM_DEFAULT, false},
    {"cancelrunningduplicates", store_bool, ITEM(res_job.CancelRunningDuplicates), 0, ITEM_DEFAULT, false},
    {"pluginoptions", store_str, ITEM(res_job.PluginOptions), 0, 0, 0},
@@ -362,9 +365,9 @@ static RES_ITEM fs_items[] = {
  *   name          handler     value                 code flags    default_value
  */
 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},
+   {"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, {0}, 0, 0, 0}
 };
 
@@ -382,18 +385,19 @@ static RES_ITEM pool_items[] = {
    {"usecatalog",      store_bool,    ITEM(res_pool.use_catalog),    0, ITEM_DEFAULT, true},
    {"usevolumeonce",   store_bool,    ITEM(res_pool.use_volume_once), 0, 0,   0},
    {"purgeoldestvolume", store_bool,  ITEM(res_pool.purge_oldest_volume), 0, 0, 0},
+   {"actiononpurge",   store_actiononpurge, ITEM(res_pool.action_on_purge), 0, 0, 0},
    {"recycleoldestvolume", store_bool,  ITEM(res_pool.recycle_oldest_volume), 0, 0, 0},
    {"recyclecurrentvolume", store_bool, ITEM(res_pool.recycle_current_volume), 0, 0, 0},
    {"maximumvolumes",  store_pint32,    ITEM(res_pool.max_volumes),   0, 0,        0},
    {"maximumvolumejobs", store_pint32,  ITEM(res_pool.MaxVolJobs),    0, 0,       0},
    {"maximumvolumefiles", store_pint32, ITEM(res_pool.MaxVolFiles),   0, 0,       0},
-   {"maximumvolumebytes", store_size, ITEM(res_pool.MaxVolBytes),   0, 0,       0},
+   {"maximumvolumebytes", store_size64, ITEM(res_pool.MaxVolBytes),   0, 0,       0},
    {"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},
    {"migrationtime",  store_time,     ITEM(res_pool.MigrationTime), 0, 0, 0},
-   {"migrationhighbytes", store_size, ITEM(res_pool.MigrationHighBytes), 0, 0, 0},
-   {"migrationlowbytes", store_size,  ITEM(res_pool.MigrationLowBytes), 0, 0, 0},
+   {"migrationhighbytes", store_size64, ITEM(res_pool.MigrationHighBytes), 0, 0, 0},
+   {"migrationlowbytes", store_size64,  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},
@@ -402,6 +406,9 @@ static RES_ITEM pool_items[] = {
    {"scratchpool",   store_res,       ITEM(res_pool.ScratchPool), 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},
+   {"fileretention", store_time,      ITEM(res_pool.FileRetention), 0, 0, 0},
+   {"jobretention",  store_time,      ITEM(res_pool.JobRetention),  0, 0, 0},
+
    {NULL, NULL, {0}, 0, 0, 0}
 };
 
@@ -547,6 +554,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
    bool recurse = true;
    char ed1[100], ed2[100], ed3[100];
    DEVICE *dev;
+   UAContext *ua = (UAContext *)sock;
 
    if (res == NULL) {
       sendit(sock, _("No %s resource defined\n"), res_to_str(type));
@@ -592,6 +600,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       break;
 
    case R_CLIENT:
+      if (!acl_access_ok(ua, Client_ACL, res->res_client.hdr.name)) {
+         break;
+      }
       sendit(sock, _("Client: name=%s address=%s FDport=%d MaxJobs=%u\n"),
          res->res_client.hdr.name, res->res_client.address, res->res_client.FDport,
          res->res_client.MaxConcurrentJobs);
@@ -619,6 +630,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       break;
 
    case R_STORAGE:
+      if (!acl_access_ok(ua, Storage_ACL, res->res_store.hdr.name)) {
+         break;
+      }
       sendit(sock, _("Storage: name=%s address=%s SDport=%d MaxJobs=%u\n"
 "      DeviceName=%s MediaType=%s StorageId=%s\n"),
          res->res_store.hdr.name, res->res_store.address, res->res_store.SDport,
@@ -629,6 +643,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       break;
 
    case R_CATALOG:
+      if (!acl_access_ok(ua, Catalog_ACL, res->res_cat.hdr.name)) {
+         break;
+      }
       sendit(sock, _("Catalog: name=%s address=%s DBport=%d db_name=%s\n"
 "      db_driver=%s db_user=%s MutliDBConn=%d\n"),
          res->res_cat.hdr.name, NPRT(res->res_cat.db_address),
@@ -639,6 +656,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
 
    case R_JOB:
    case R_JOBDEFS:
+      if (!acl_access_ok(ua, Job_ACL, res->res_job.hdr.name)) {
+         break;
+      }
       sendit(sock, _("%s: name=%s JobType=%d level=%s Priority=%d Enabled=%d\n"),
          type == R_JOB ? _("Job") : _("JobDefs"),
          res->res_job.hdr.name, res->res_job.JobType,
@@ -694,6 +714,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       if (res->res_job.MaxStartDelay) {
          sendit(sock, _("  --> MaxStartDelay=%u\n"), res->res_job.MaxStartDelay);
       }
+      if (res->res_job.MaxRunSchedTime) {
+         sendit(sock, _("  --> MaxRunSchedTime=%u\n"), res->res_job.MaxRunSchedTime);
+      }
       if (res->res_job.storage) {
          STORE *store;
          foreach_alist(store, res->res_job.storage) {
@@ -757,6 +780,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
    case R_FILESET:
    {
       int i, j, k;
+      if (!acl_access_ok(ua, FileSet_ACL, res->res_fs.hdr.name)) {
+         break;
+      }
       sendit(sock, _("FileSet: name=%s\n"), res->res_fs.hdr.name);
       for (i=0; i<res->res_fs.num_includes; i++) {
          INCEXE *incexe = res->res_fs.include_items[i];
@@ -844,6 +870,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
    }
 
    case R_SCHEDULE:
+      if (!acl_access_ok(ua, Schedule_ACL, res->res_sch.hdr.name)) {
+         break;
+      }
       if (res->res_sch.run) {
          int i;
          RUN *run = res->res_sch.run;
@@ -932,6 +961,9 @@ next_run:
       break;
 
    case R_POOL:
+      if (!acl_access_ok(ua, Pool_ACL, res->res_pool.hdr.name)) {
+         break;
+      }
       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 cat_files=%d\n"),
@@ -946,9 +978,10 @@ 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\n"), 
+      sendit(sock, _("      RecyleOldest=%d PurgeOldest=%d ActionOnPurge=%d\n"), 
               res->res_pool.recycle_oldest_volume,
-              res->res_pool.purge_oldest_volume);
+              res->res_pool.purge_oldest_volume,
+              res->res_pool.action_on_purge);
       sendit(sock, _("      MaxVolJobs=%d MaxVolFiles=%d MaxVolBytes=%s\n"),
               res->res_pool.MaxVolJobs, 
               res->res_pool.MaxVolFiles,
@@ -957,6 +990,9 @@ next_run:
               edit_utime(res->res_pool.MigrationTime, ed1, sizeof(ed1)),
               edit_uint64(res->res_pool.MigrationHighBytes, ed2),
               edit_uint64(res->res_pool.MigrationLowBytes, ed3));
+      sendit(sock, _("      JobRetention=%s FileRetention=%s\n"),
+         edit_utime(res->res_pool.JobRetention, ed1, sizeof(ed1)),
+         edit_utime(res->res_pool.FileRetention, ed2, sizeof(ed2)));
       if (res->res_pool.NextPool) {
          sendit(sock, _("      NextPool=%s\n"), res->res_pool.NextPool->name());
       }
@@ -1607,6 +1643,20 @@ void save_resource(int type, RES_ITEM *items, int pass)
    }
 }
 
+static void store_actiononpurge(LEX *lc, RES_ITEM *item, int index, int pass)
+{
+   uint32_t *destination = (uint32_t*)item->value;
+   lex_get_token(lc, T_NAME);
+   if (strcasecmp(lc->str, "truncate") == 0) {
+      *destination = (*destination) | ON_PURGE_TRUNCATE;
+   } else {
+      scan_err2(lc, _("Expected one of: %s, got: %s"), "Truncate", lc->str);
+      return;
+   }
+   scan_to_eol(lc);
+   set_bit(index, res_all.hdr.item_present);
+}
+
 /*
  * Store Device. Note, the resource is created upon the
  *  first reference. The details of the resource are obtained
@@ -1614,14 +1664,13 @@ void save_resource(int type, RES_ITEM *items, int pass)
  */
 static void store_device(LEX *lc, RES_ITEM *item, int index, int pass)
 {
-   int token;
    URES *res;
    int rindex = R_DEVICE - r_first;
    int size = sizeof(DEVICE);
    bool found = false;
 
    if (pass == 1) {
-      token = lex_get_token(lc, T_NAME);
+      lex_get_token(lc, T_NAME);
       if (!res_head[rindex]) {
          res = (URES *)malloc(size);
          memset(res, 0, size);
@@ -1661,9 +1710,9 @@ static void store_device(LEX *lc, RES_ITEM *item, int index, int pass)
  */
 void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass)
 {
-   int token, i;
+   int i;
 
-   token = lex_get_token(lc, T_NAME);
+   lex_get_token(lc, T_NAME);
    /* Store the type both pass 1 and pass 2 */
    for (i=0; migtypes[i].type_name; i++) {
       if (strcasecmp(lc->str, migtypes[i].type_name) == 0) {
@@ -1687,9 +1736,9 @@ void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass)
  */
 void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass)
 {
-   int token, i;
+   int i;
 
-   token = lex_get_token(lc, T_NAME);
+   lex_get_token(lc, T_NAME);
    /* Store the type both pass 1 and pass 2 */
    for (i=0; jobtypes[i].type_name; i++) {
       if (strcasecmp(lc->str, jobtypes[i].type_name) == 0) {
@@ -1711,9 +1760,9 @@ void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass)
  */
 void store_level(LEX *lc, RES_ITEM *item, int index, int pass)
 {
-   int token, i;
+   int i;
 
-   token = lex_get_token(lc, T_NAME);
+   lex_get_token(lc, T_NAME);
    /* Store the level pass 2 so that type is defined */
    for (i=0; joblevels[i].level_name; i++) {
       if (strcasecmp(lc->str, joblevels[i].level_name) == 0) {
@@ -1732,8 +1781,8 @@ void store_level(LEX *lc, RES_ITEM *item, int index, int pass)
 
 void store_replace(LEX *lc, RES_ITEM *item, int index, int pass)
 {
-   int token, i;
-   token = lex_get_token(lc, T_NAME);
+   int i;
+   lex_get_token(lc, T_NAME);
    /* Scan Replacement options */
    for (i=0; ReplaceOptions[i].name; i++) {
       if (strcasecmp(lc->str, ReplaceOptions[i].name) == 0) {
@@ -1758,7 +1807,7 @@ void store_acl(LEX *lc, RES_ITEM *item, int index, int pass)
    int token;
 
    for (;;) {
-      token = lex_get_token(lc, T_STRING);
+      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));
@@ -1838,7 +1887,7 @@ static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass)
       /* Each runscript command takes 2 entries in commands list */
       pm_strcpy(c, lc->str);
       ((RUNSCRIPT*) item->value)->commands->prepend(c); /* command line */
-      ((RUNSCRIPT*) item->value)->commands->prepend((void *)item->code); /* command type */
+      ((RUNSCRIPT*) item->value)->commands->prepend((void *)(intptr_t)item->code); /* command type */
    }
    scan_to_eol(lc);
 }
@@ -1850,7 +1899,7 @@ 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_job_code_callback(job_code_callback_director);
 
       script->set_command(lc->str);
 
@@ -1997,7 +2046,7 @@ static void store_runscript(LEX *lc, RES_ITEM *item, int index, int pass)
        *  - POOLMEM command string (ex: /bin/true) 
        *  - int command type (ex: SHELL_CMD)
        */
-      res_runscript.set_job_code_callback(job_code_callback_filesetname);
+      res_runscript.set_job_code_callback(job_code_callback_director);
       while ((c=(char*)res_runscript.commands->pop()) != NULL) {
          t = (intptr_t)res_runscript.commands->pop();
          RUNSCRIPT *script = new_runscript();
@@ -2023,13 +2072,40 @@ static void store_runscript(LEX *lc, RES_ITEM *item, int index, int pass)
 }
 
 /* callback function for edit_job_codes */
-extern "C" char *job_code_callback_filesetname(JCR *jcr, const char* param)
+/* See ../lib/util.c, function edit_job_codes, for more remaining codes */
+extern "C" char *job_code_callback_director(JCR *jcr, const char* param)
 {
-   if (param[0] == 'f') {
-      return jcr->fileset->name();
-   } else {
-      return NULL;
+   static char yes[] = "yes";
+   static char no[] = "no";
+   switch (param[0]) {
+      case 'f':
+         if (jcr->fileset) {
+            return jcr->fileset->name();
+         }
+         break;
+      case 'h':
+         if (jcr->client) {
+            return jcr->client->address;
+         }
+         break;
+      case 'p':
+         if (jcr->pool) {
+            return jcr->pool->name();
+         }
+         break;
+      case 'w':
+         if (jcr->wstore) {
+            return jcr->wstore->name();
+         }
+         break;
+      case 'x':
+         return jcr->spool_data ? yes : no;
+         break;
+      case 'D':
+         return my_name;
+         break;
    }
+   return NULL;
 }
 
 bool parse_dir_config(CONFIG *config, const char *configfile, int exit_code)