]> git.sur5r.net Git - bacula/bacula/commitdiff
Add comment= option to restore and run commands
authorEric Bollengier <eric@eb.homelinux.org>
Mon, 18 Jan 2010 15:19:29 +0000 (16:19 +0100)
committerEric Bollengier <eric@eb.homelinux.org>
Mon, 2 Aug 2010 14:49:23 +0000 (16:49 +0200)
bacula/src/cats/sql_create.c
bacula/src/dird/job.c
bacula/src/dird/protos.h
bacula/src/dird/ua.h
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_input.c
bacula/src/dird/ua_restore.c
bacula/src/dird/ua_run.c
bacula/src/dird/ua_status.c
bacula/src/jcr.h

index 736db4420f1a00568e6dc30f0c8ccd3b0417d29b..c7c7e71070b1bca87417b63579c825874ed805d2 100644 (file)
@@ -66,10 +66,12 @@ static int db_create_filename_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar);
 bool
 db_create_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
 {
+   POOL_MEM buf;
    char dt[MAX_TIME_LENGTH];
    time_t stime;
    struct tm tm;
    bool ok;
+   int len;
    utime_t JobTDate;
    char ed1[30],ed2[30];
 
@@ -82,13 +84,18 @@ db_create_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
    strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm);
    JobTDate = (utime_t)stime;
 
+   len = strlen(jcr->comment);
+   buf.check_size(len*2+1);
+   db_escape_string(jcr, mdb, buf.c_str(), jcr->comment, len);
+
    /* Must create it */
    Mmsg(mdb->cmd,
-"INSERT INTO Job (Job,Name,Type,Level,JobStatus,SchedTime,JobTDate,ClientId) "
-"VALUES ('%s','%s','%c','%c','%c','%s',%s,%s)",
+"INSERT INTO Job (Job,Name,Type,Level,JobStatus,SchedTime,JobTDate,"
+                 "ClientId,Comment) "
+"VALUES ('%s','%s','%c','%c','%c','%s',%s,%s,'%s')",
            jr->Job, jr->Name, (char)(jr->JobType), (char)(jr->JobLevel),
            (char)(jr->JobStatus), dt, edit_uint64(JobTDate, ed1),
-           edit_int64(jr->ClientId, ed2));
+           edit_int64(jr->ClientId, ed2), buf.c_str());
 
    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
       Mmsg2(&mdb->errmsg, _("Create DB Job record %s failed. ERR=%s\n"),
index 0860e7d69b115263547ae6ffd06f7726da113d0a..331cfd10c71391f462e98886bb31fbda23132875 100644 (file)
@@ -140,7 +140,10 @@ bool setup_job(JCR *jcr)
       goto bail_out;
    }
    Dmsg0(150, "DB opened\n");
-
+   if (!jcr->comment) {
+      jcr->comment = get_pool_memory(PM_MESSAGE);
+      *jcr->comment = '\0';
+   }
    if (!jcr->fname) {
       jcr->fname = get_pool_memory(PM_FNAME);
    }
@@ -965,6 +968,10 @@ void dird_free_jcr_pointers(JCR *jcr)
       bnet_close(jcr->store_bsock);
       jcr->store_bsock = NULL;
    }
+   if (jcr->comment) {
+      free_pool_memory(jcr->comment);
+      jcr->comment = NULL;
+   }
    if (jcr->fname) {
       Dmsg0(200, "Free JCR fname\n");
       free_pool_memory(jcr->fname);
index 6d99a859d8b25617ad4427eaec2b89d8621bf38b..9f84950337e4fa98c77423513f2415f91ecdf941 100644 (file)
@@ -211,6 +211,7 @@ bool get_yesno(UAContext *ua, const char *prompt);
 bool is_yesno(char *val, int *ret);
 int get_enabled(UAContext *ua, const char *val);
 void parse_ua_args(UAContext *ua);
+bool is_comment_legal(UAContext *ua, const char *name);
 
 /* ua_label.c */
 bool is_volume_name_legal(UAContext *ua, const char *name);
index 31ca5b49e4303c2718dd94b34338b5744f207823..522ac87a7bf4a86d6ab73789c55930dc0f8fac1c 100644 (file)
@@ -112,6 +112,7 @@ struct RESTORE_CTX {
    POOL *pool;
    int restore_jobs;
    uint32_t selected_files;
+   char *comment;
    char *where;
    char *RegexWhere;
    RBSR *bsr;
index 34d25595c6ca14ee00ee8260081e3d306a9a7fa8..2a8ebec0ef24f3c8040f495b52411afb7d7b13b7 100644 (file)
@@ -157,7 +157,7 @@ static struct cmdstruct commands[] = {                                      /* C
  { NT_("query"),      querycmd,      _("Query catalog"),              NT_(""),              false},
  { NT_("restore"),    restore_cmd,   _("Restore files"), 
    NT_("where=</path> client=<client> storage=<storage> bootstrap=<file>"
-       "\n\tjobid=<jobid> done select all"), false},
+       "\n\tcomment=<text> jobid=<jobid> done select all"), false},
 
  { NT_("relabel"),    relabel_cmd,   _("Relabel a tape"), 
    NT_("storage=<storage-name> oldvolume=<old-volume-name>\n\tvolume=<newvolume-name> pool=<pool>"), false},
@@ -166,7 +166,7 @@ static struct cmdstruct commands[] = {                                      /* C
  { NT_("reload"),     reload_cmd,    _("Reload conf file"), NT_(""),                  true},
  { NT_("run"),        run_cmd,       _("Run a job"), 
    NT_("job=<job-name> client=<client-name>\n\tfileset=<FileSet-name> level=<level-keyword>\n\tstorage=<storage-name>"
-       "where=<directory-prefix>\n\twhen=<universal-time-specification>\n\tyes"), false}, /* need to be check */
+       "where=<directory-prefix>\n\twhen=<universal-time-specification>\n\tcomment=<text> yes"), false}, 
 
  { NT_("status"),     status_cmd,    _("Report status"), 
    NT_("all | dir=<dir-name> | director | client=<client-name> | storage=<storage-name> slots | days=nnn"), true},
index b87c73a2bc7d498f97a68b4444ab06307a2a5275..ef081144df204041210f8553c84e1924454e24af 100644 (file)
@@ -192,3 +192,39 @@ void parse_ua_args(UAContext *ua)
 {
    parse_args(ua->cmd, &ua->args, &ua->argc, ua->argk, ua->argv, MAX_CMD_ARGS);
 }
+
+/*
+ * Check if the comment has legal characters
+ * If ua is non-NULL send the message
+ */
+bool is_comment_legal(UAContext *ua, const char *name)
+{
+   int len;
+   const char *p;
+   const char *forbid = "'<>&\\\"";
+
+   /* Restrict the characters permitted in the comment */
+   for (p=name; *p; p++) {
+      if (!strchr(forbid, (int)(*p))) {
+         continue;
+      }
+      if (ua) {
+         ua->error_msg(_("Illegal character \"%c\" in a comment.\n"), *p);
+      }
+      return 0;
+   }
+   len = strlen(name);
+   if (len >= MAX_NAME_LENGTH) {
+      if (ua) {
+         ua->error_msg(_("Comment too long.\n"));
+      }
+      return 0;
+   }
+   if (len == 0) {
+      if (ua) {
+         ua->error_msg(_("Comment must be at least one character long.\n"));
+      }
+      return 0;
+   }
+   return 1;
+}
index 653804a5025034e813a472186a8059c83f109f28..c2348d89f924a3195d2c51105cf07a5be4a96367 100644 (file)
@@ -79,6 +79,7 @@ static void get_and_display_basejobs(UAContext *ua, RESTORE_CTX *rx);
 int restore_cmd(UAContext *ua, const char *cmd)
 {
    RESTORE_CTX rx;                    /* restore context */
+   POOL_MEM buf;
    JOB *job;
    int i;
    JCR *jcr = ua->jcr;
@@ -95,6 +96,14 @@ int restore_cmd(UAContext *ua, const char *cmd)
    rx.query = get_pool_memory(PM_FNAME);
    rx.bsr = new_bsr();
 
+   i = find_arg_with_value(ua, "comment");
+   if (i >= 0) {
+      rx.comment = ua->argv[i];
+      if (!is_comment_legal(ua, rx.comment)) {
+         goto bail_out;
+      }
+   }
+
    i = find_arg_with_value(ua, "where");
    if (i >= 0) {
       rx.where = ua->argv[i];
@@ -227,37 +236,31 @@ int restore_cmd(UAContext *ua, const char *cmd)
 
    escaped_bsr_name = escape_filename(jcr->RestoreBootstrap);
 
+   Mmsg(ua->cmd,
+        "run job=\"%s\" client=\"%s\" restoreclient=\"%s\" storage=\"%s\""
+        " bootstrap=\"%s\" files=%u catalog=\"%s\"",
+        job->name(), rx.ClientName, rx.RestoreClientName,
+        rx.store?rx.store->name():"",
+        escaped_bsr_name ? escaped_bsr_name : jcr->RestoreBootstrap,
+        rx.selected_files, ua->catalog->name());
+
    /* Build run command */
+   pm_strcpy(buf, "");
    if (rx.RegexWhere) {
       escaped_where_name = escape_filename(rx.RegexWhere);
-      Mmsg(ua->cmd,
-          "run job=\"%s\" client=\"%s\" restoreclient=\"%s\" storage=\"%s\""
-          " bootstrap=\"%s\" regexwhere=\"%s\" files=%u catalog=\"%s\"",
-          job->name(), rx.ClientName, rx.RestoreClientName, 
-          rx.store?rx.store->name():"",
-          escaped_bsr_name ? escaped_bsr_name : jcr->RestoreBootstrap,
-          escaped_where_name ? escaped_where_name : rx.RegexWhere,
-          rx.selected_files, ua->catalog->name());
+      Mmsg(buf, " regexwhere=\"%s\"", 
+           escaped_where_name ? escaped_where_name : rx.RegexWhere);
 
    } else if (rx.where) {
       escaped_where_name = escape_filename(rx.where);
-      Mmsg(ua->cmd,
-          "run job=\"%s\" client=\"%s\" restoreclient=\"%s\" storage=\"%s\""
-          " bootstrap=\"%s\" where=\"%s\" files=%u catalog=\"%s\"",
-          job->name(), rx.ClientName, rx.RestoreClientName,
-          rx.store?rx.store->name():"",
-          escaped_bsr_name ? escaped_bsr_name : jcr->RestoreBootstrap,
-          escaped_where_name ? escaped_where_name : rx.where,
-          rx.selected_files, ua->catalog->name());
+      Mmsg(buf," where=\"%s\"", 
+           escaped_where_name ? escaped_where_name : rx.where);
+   }
+   pm_strcat(ua->cmd, buf);
 
-   } else {
-      Mmsg(ua->cmd,
-          "run job=\"%s\" client=\"%s\" restoreclient=\"%s\" storage=\"%s\""
-          " bootstrap=\"%s\" files=%u catalog=\"%s\"",
-          job->name(), rx.ClientName, rx.RestoreClientName,
-          rx.store?rx.store->name():"",
-          escaped_bsr_name ? escaped_bsr_name : jcr->RestoreBootstrap,
-          rx.selected_files, ua->catalog->name());
+   if (rx.comment) {
+      Mmsg(buf, " comment=\"%s\"", rx.comment);
+      pm_strcat(ua->cmd, buf);
    }
 
    if (escaped_bsr_name != NULL) {
@@ -452,6 +455,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
       "regexwhere",   /* 18 */
       "restoreclient", /* 19 */
       "copies",        /* 20 */
+      "comment",       /* 21 */
       NULL
    };
 
index 5a25811eb483bf3e64f85efa1bf7d7742927e59e..be7b5e89a0fe51d1cda8d641cab4cbc238025e3f 100644 (file)
@@ -41,7 +41,7 @@ class run_ctx {
 public:
    char *job_name, *level_name, *jid, *store_name, *pool_name;
    char *where, *fileset_name, *client_name, *bootstrap, *regexwhere;
-   char *restore_client_name;
+   char *restore_client_name, *comment;
    const char *replace;
    char *when, *verify_job_name, *catalog_name;
    char *previous_job_name;
@@ -438,6 +438,12 @@ static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc)
       jcr->catalog = rc.catalog;
       pm_strcpy(jcr->catalog_source, _("User input"));
    }
+
+   if (!jcr->comment) {
+      jcr->comment = get_pool_memory(PM_MESSAGE);
+   }
+   pm_strcpy(jcr->comment, rc.comment);
+
    if (rc.where) {
       if (jcr->where) {
          free(jcr->where);
@@ -1012,6 +1018,7 @@ static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
       "restoreclient",                /* 24 */
       "pluginoptions",                /* 25 */
       "spooldata",                    /* 26 */
+      "comment",                      /* 27 */
       NULL};
 
 #define YES_POS 14
@@ -1026,7 +1033,7 @@ static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
    rc.verify_job_name = NULL;
    rc.previous_job_name = NULL;
    rc.spool_data_set = 0;
-
+   rc.comment = NULL;
 
    for (i=1; i<ua->argc; i++) {
       Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
@@ -1244,6 +1251,9 @@ static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
                   ua->send_msg(_("Invalid spooldata flag.\n"));
                }
                break;
+            case 27: /* comment */
+               rc.comment = ua->argv[i];
+               kw_ok = true;
             default:
                break;
             }
@@ -1269,7 +1279,11 @@ static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
    } /* end argc loop */
              
    Dmsg0(800, "Done scan.\n");
-
+   if (rc.comment) {
+      if (!is_comment_legal(ua, rc.comment)) {
+         return false;
+      }
+   }
    if (rc.catalog_name) {
        rc.catalog = GetCatalogResWithName(rc.catalog_name);
        if (rc.catalog == NULL) {
index 3ff5f30be5283a031591c6fa703e44c298c5bd43..deda34f7424c7449d1bc345fb3772a4a4492bcec 100644 (file)
@@ -786,11 +786,17 @@ static void list_running_jobs(UAContext *ua)
       }
 
       if (ua->api) {
-         ua->send_msg(_("%6d\t%-6s\t%-20s\t%s\n"),
-            jcr->JobId, level, jcr->Job, msg);
+         bash_spaces(jcr->comment);
+         ua->send_msg(_("%6d\t%-6s\t%-20s\t%s\t%s\n"),
+                      jcr->JobId, level, jcr->Job, msg, jcr->comment);
+         unbash_spaces(jcr->comment);
       } else {
          ua->send_msg(_("%6d %-6s  %-20s %s\n"),
             jcr->JobId, level, jcr->Job, msg);
+         /* Display comments if any */
+         if (*jcr->comment) {
+            ua->send_msg(_("               %-30s\n"), jcr->comment);
+         }
       }
 
       if (pool_mem) {
index 4513e800f6b9648ebb9643eb161e8367ec9a9376..1ab775986777fd97d3b057a25061cc56ee6064fa 100644 (file)
@@ -274,6 +274,7 @@ public:
    save_pkt *plugin_sp;               /* plugin save packet */
    char *plugin_options;              /* user set options for plugin */
    bool cmd_plugin;                   /* Set when processing a command Plugin = */
+   POOLMEM *comment;                  /* Comment for this Job */
 
    /* Daemon specific part of JCR */
    /* This should be empty in the library */