#include "bacula.h"
#include "dird.h"
-
/* Imported functions */
extern void print_bsr(UAContext *ua, RBSR *bsr);
char *date);
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_restore_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;
+ 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_with_value(ua, "regexwhere");
+ if (i >= 0) {
+ rx.RegexWhere = 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);
+ rx.RegexWhere = regexp;
+ }
+
+ /* TODO: add acl for regexwhere ? */
+
+ if (rx.RegexWhere) {
+ if (!acl_access_ok(ua, Where_ACL, rx.RegexWhere)) {
+ ua->error_msg(_("\"RegexWhere\" specification not authorized.\n"));
+ goto bail_out;
+ }
+ }
+
+ if (rx.where) {
if (!acl_access_ok(ua, Where_ACL, rx.where)) {
ua->error_msg(_("\"where\" specification not authorized.\n"));
goto bail_out;
ua->error_msg(_("No Client resource found!\n"));
goto bail_out;
}
+ get_restore_client_name(ua, rx);
escaped_bsr_name = escape_filename(jcr->RestoreBootstrap);
- escaped_where_name = escape_filename(rx.where);
/* Build run command */
- if (rx.where) {
- if (!acl_access_ok(ua, Where_ACL, rx.where)) {
- ua->error_msg(_("\"where\" specification not authorized.\n"));
- goto bail_out;
- }
+ 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=%d 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());
+ } else if (rx.where) {
+ escaped_where_name = escape_filename(rx.where);
Mmsg(ua->cmd,
- "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\""
- " where=\"%s\" files=%d catalog=\"%s\"",
- job->name(), rx.ClientName, rx.store?rx.store->name():"",
+ "run job=\"%s\" client=\"%s\" restoreclient=\"%s\" storage=\"%s\""
+ " bootstrap=\"%s\" where=\"%s\" files=%d 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());
+
} else {
Mmsg(ua->cmd,
- "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\""
- " files=%d catalog=\"%s\"",
- job->name(), rx.ClientName, rx.store?rx.store->name():"",
+ "run job=\"%s\" client=\"%s\" restoreclient=\"%s\" storage=\"%s\""
+ " bootstrap=\"%s\" files=%d 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 (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;
return true;
}
+/*
+ * This gets the client name from which the backup was made
+ */
static int get_client_name(UAContext *ua, RESTORE_CTX *rx)
{
/* If no client name specified yet, get it now */
CLIENT_DBR cr;
/* try command line argument */
int i = find_arg_with_value(ua, NT_("client"));
+ if (i < 0) {
+ i = find_arg_with_value(ua, NT_("backupclient"));
+ }
if (i >= 0) {
if (!has_value(ua, i)) {
return 0;
return 1;
}
+/*
+ * This is where we pick up a client name to restore to.
+ */
+static int get_restore_client_name(UAContext *ua, RESTORE_CTX &rx)
+{
+ /* Start with same name as backup client */
+ bstrncpy(rx.RestoreClientName, rx.ClientName, sizeof(rx.RestoreClientName));
+
+ /* try command line argument */
+ int i = find_arg_with_value(ua, NT_("restoreclient"));
+ if (i >= 0) {
+ if (!has_value(ua, i)) {
+ return 0;
+ }
+ bstrncpy(rx.RestoreClientName, ua->argv[i], sizeof(rx.RestoreClientName));
+ return 1;
+ }
+ return 1;
+}
+
+
/*
* The first step in the restore process is for the user to
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 */
+ "regexwhere", /* 18 */
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 ((ffd = fopen(p, "rb")) == NULL) {
berrno be;
ua->error_msg(_("Cannot open file %s: ERR=%s\n"),
- p, be.strerror());
+ p, be.bstrerror());
break;
}
while (fgets(file, sizeof(file), ffd)) {
}
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]);