#include "bacula.h"
#include "dird.h"
-
/* Imported functions */
extern void print_bsr(UAContext *ua, RBSR *bsr);
static void insert_one_file_or_dir(UAContext *ua, RESTORE_CTX *rx, char *date, bool dir);
static int get_client_name(UAContext *ua, RESTORE_CTX *rx);
static int get_date(UAContext *ua, char *date, int date_len);
-static int count_handler(void *ctx, int num_fields, char **row);
+static int restore_count_handler(void *ctx, int num_fields, char **row);
static bool insert_table_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *table);
/*
JCR *jcr = ua->jcr;
char *escaped_bsr_name = NULL;
char *escaped_where_name = NULL;
+ bool where_use_regexp = false;
+ char *strip_prefix, *add_prefix, *add_suffix, *regexp;
+ strip_prefix = add_prefix = add_suffix = regexp = NULL;
memset(&rx, 0, sizeof(rx));
rx.path = get_pool_memory(PM_FNAME);
i = find_arg_with_value(ua, "where");
if (i >= 0) {
rx.where = ua->argv[i];
+ }
+
+ i = find_arg_with_value(ua, "strip_prefix");
+ if (i >= 0) {
+ strip_prefix = ua->argv[i];
+ }
+
+ i = find_arg_with_value(ua, "add_prefix");
+ if (i >= 0) {
+ add_prefix = ua->argv[i];
+ }
+
+ i = find_arg_with_value(ua, "add_suffix");
+ if (i >= 0) {
+ add_suffix = ua->argv[i];
+ }
+
+ i = find_arg(ua, "where_use_regexp");
+ if (i >= 0) {
+ where_use_regexp = true;
+ }
+
+ i = find_arg_with_value(ua, "regexwhere");
+ if (i >= 0) {
+ where_use_regexp = true;
+ rx.where = ua->argv[i];
+ }
+
+ if (strip_prefix || add_suffix || add_prefix) {
+ int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
+ regexp = (char *) bmalloc (len * sizeof(char));
+
+ bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
+ where_use_regexp = true;
+
+ rx.where = regexp;
+ }
+
+ if (rx.where) {
if (!acl_access_ok(ua, Where_ACL, rx.where)) {
ua->error_msg(_("\"where\" specification not authorized.\n"));
goto bail_out;
Mmsg(ua->cmd,
"run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\""
- " where=\"%s\" files=%d catalog=\"%s\"",
+ " %swhere=\"%s\" files=%d catalog=\"%s\"",
job->name(), rx.ClientName, rx.store?rx.store->name():"",
escaped_bsr_name ? escaped_bsr_name : jcr->RestoreBootstrap,
+ where_use_regexp ? "regex" : "",
escaped_where_name ? escaped_where_name : rx.where,
rx.selected_files, ua->catalog->name());
} else {
if (escaped_where_name != NULL) {
bfree(escaped_where_name);
}
+
+ if (regexp) {
+ bfree(regexp);
+ }
if (find_arg(ua, NT_("yes")) > 0) {
pm_strcat(ua->cmd, " yes"); /* pass it on to the run command */
bfree(escaped_where_name);
}
+ if (regexp) {
+ bfree(regexp);
+ }
+
free_rx(&rx);
return 0;
char *p;
char date[MAX_TIME_LENGTH];
bool have_date = false;
+ /* Include current second if using current time */
+ utime_t now = time(NULL) + 1;
JobId_t JobId;
JOB_DBR jr = { (JobId_t)-1 };
bool done = false;
const char *kw[] = {
/* These keywords are handled in a for loop */
- "jobid", /* 0 */
- "current", /* 1 */
- "before", /* 2 */
- "file", /* 3 */
- "directory", /* 4 */
- "select", /* 5 */
- "pool", /* 6 */
- "all", /* 7 */
+ "jobid", /* 0 */
+ "current", /* 1 */
+ "before", /* 2 */
+ "file", /* 3 */
+ "directory", /* 4 */
+ "select", /* 5 */
+ "pool", /* 6 */
+ "all", /* 7 */
/* The keyword below are handled by individual arg lookups */
- "client", /* 8 */
- "storage", /* 9 */
- "fileset", /* 10 */
- "where", /* 11 */
- "yes", /* 12 */
- "bootstrap", /* 13 */
- "done", /* 14 */
+ "client", /* 8 */
+ "storage", /* 9 */
+ "fileset", /* 10 */
+ "where", /* 11 */
+ "yes", /* 12 */
+ "bootstrap", /* 13 */
+ "done", /* 14 */
+ "strip_prefix", /* 15 */
+ "add_prefix", /* 16 */
+ "add_suffix", /* 17 */
+ "where_use_regexp",/* 18 */
+ "regexwhere", /* 19 like where + where_use_regexp */
NULL
};
done = true;
break;
case 1: /* current */
- bstrutime(date, sizeof(date), time(NULL));
+ /*
+ * Note, we add one second here just to include any job
+ * that may have finished within the current second,
+ * which happens a lot in scripting small jobs.
+ */
+ bstrutime(date, sizeof(date), now);
have_date = true;
break;
case 2: /* before */
return 0;
}
if (!have_date) {
- bstrutime(date, sizeof(date), time(NULL));
+ bstrutime(date, sizeof(date), now);
}
if (!get_client_name(ua, rx)) {
return 0;
return 2;
case 5: /* select */
if (!have_date) {
- bstrutime(date, sizeof(date), time(NULL));
+ bstrutime(date, sizeof(date), now);
}
if (!select_backups_before_date(ua, rx, date)) {
return 0;
done = false;
break;
case 4: /* Select the most recent backups */
- bstrutime(date, sizeof(date), time(NULL));
+ bstrutime(date, sizeof(date), now);
if (!select_backups_before_date(ua, rx, date)) {
return 0;
}
}
break;
case 6: /* Enter files */
- bstrutime(date, sizeof(date), time(NULL));
+ bstrutime(date, sizeof(date), now);
if (!get_client_name(ua, rx)) {
return 0;
}
return 2;
case 8: /* Find JobIds for current backup */
- bstrutime(date, sizeof(date), time(NULL));
+ bstrutime(date, sizeof(date), now);
if (!select_backups_before_date(ua, rx, date)) {
return 0;
}
if (*rx->JobIds == 0 || *rx->JobIds == '.') {
return 0; /* nothing entered, return */
}
- bstrutime(date, sizeof(date), time(NULL));
+ bstrutime(date, sizeof(date), now);
if (!get_client_name(ua, rx)) {
return 0;
}
}
if (!rx->found) {
ua->error_msg(_("No database record found for: %s\n"), file);
+// ua->error_msg("Query=%s\n", rx->query);
return true;
}
return true;
if (get_next_jobid_from_list(&p, &JobId) > 0) {
/* Use first JobId as estimate of the number of files to restore */
Mmsg(rx->query, uar_count_files, edit_int64(JobId, ed1));
- if (!db_sql_query(ua->db, rx->query, count_handler, (void *)rx)) {
+ if (!db_sql_query(ua->db, rx->query, restore_count_handler, (void *)rx)) {
ua->error_msg("%s\n", db_strerror(ua->db));
}
if (rx->found) {
return 1;
}
-static int count_handler(void *ctx, int num_fields, char **row)
+static int restore_count_handler(void *ctx, int num_fields, char **row)
{
RESTORE_CTX *rx = (RESTORE_CTX *)ctx;
rx->JobId = str_to_int64(row[0]);