/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2010 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.
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.
#include "bacula.h"
#include "filed.h"
+#include "ch.h"
#if defined(WIN32_VSS)
#include "vss.h"
static int runafter_cmd(JCR *jcr);
static int runbeforenow_cmd(JCR *jcr);
static int restore_object_cmd(JCR *jcr);
-static void set_options(findFOPTS *fo, const char *opts);
+static int set_options(findFOPTS *fo, const char *opts);
static void set_storage_auth_key(JCR *jcr, char *key);
+static int sm_dump_cmd(JCR *jcr);
+#ifdef DEVELOPER
+static int exit_cmd(JCR *jcr);
+#endif
/* Exported functions */
{"Run", runscript_cmd, 0},
{"accurate", accurate_cmd, 0},
{"restoreobject", restore_object_cmd, 0},
+ {"sm_dump", sm_dump_cmd, 0},
+#ifdef DEVELOPER
+ {"exit", exit_cmd, 0},
+#endif
{NULL, NULL} /* list terminator */
};
static char restorecmd[] = "restore replace=%c prelinks=%d where=%s\n";
static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
-static char restoreobjcmd[] = "restoreobject JobId=%u ObjLen=%d ObjInx=%d ObjType=%d FI=%d\n";
+static char restoreobjcmd[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d,%s";
+static char restoreobjcmd1[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d\n";
static char endrestoreobjectcmd[] = "restoreobject end\n";
static char verifycmd[] = "verify level=%30s";
static char estimatecmd[] = "estimate listing=%d";
static char OKstore[] = "2000 OK storage\n";
static char OKstoreend[] = "2000 OK storage end\n";
static char OKjob[] = "2000 OK Job %s (%s) %s,%s,%s";
-static char OKsetdebug[] = "2000 OK setdebug=%d\n";
+static char OKsetdebug[] = "2000 OK setdebug=%d trace=%d hangup=%d\n";
static char BADjob[] = "2901 Bad Job\n";
static char EndJob[] = "2800 End Job TermCode=%d JobFiles=%u ReadBytes=%s"
" JobBytes=%s Errors=%u VSS=%d Encrypt=%d\n";
findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
for (j=0; j<incexe->opts_list.size(); j++) {
findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
+ if (fo->plugin) {
+ free(fo->plugin);
+ }
for (k=0; k<fo->regex.size(); k++) {
regfree((regex_t *)fo->regex.get(k));
}
Dmsg0(100, "Done with term_find_files\n");
free_jcr(jcr); /* destroy JCR record */
Dmsg0(100, "Done with free_jcr\n");
- Dsm_check(1);
+ Dsm_check(100);
+ garbage_collect_memory_pool();
return NULL;
}
+static int sm_dump_cmd(JCR *jcr)
+{
+ close_memory_pool();
+ sm_dump(false, true);
+ jcr->dir_bsock->fsend("2000 sm_dump OK\n");
+ return 1;
+}
+
+#ifdef DEVELOPER
+static int exit_cmd(JCR *jcr)
+{
+ jcr->dir_bsock->fsend("2000 exit OK\n");
+ terminate_filed(0);
+ return 0;
+}
+#endif
+
+
/**
* Hello from Director he must identify himself and provide his
* password.
if (!(cjcr=get_jcr_by_full_name(Job))) {
dir->fsend(_("2901 Job %s not found.\n"), Job);
} else {
+ generate_plugin_event(cjcr, bEventCancelCommand, NULL);
+ cjcr->setJobStatus(JS_Canceled);
if (cjcr->store_bsock) {
cjcr->store_bsock->set_timed_out();
cjcr->store_bsock->set_terminated();
- pthread_kill(cjcr->my_thread_id, TIMEOUT_SIGNAL);
+ cjcr->my_thread_send_signal(TIMEOUT_SIGNAL);
}
- generate_plugin_event(cjcr, bEventCancelCommand, NULL);
- set_jcr_job_status(cjcr, JS_Canceled);
free_jcr(cjcr);
dir->fsend(_("2001 Job %s marked to be canceled.\n"), Job);
}
return 1;
}
-
/**
* Set debug level as requested by the Director
*
static int setdebug_cmd(JCR *jcr)
{
BSOCK *dir = jcr->dir_bsock;
- int level, trace_flag;
-
- Dmsg1(110, "setdebug_cmd: %s", dir->msg);
- if (sscanf(dir->msg, "setdebug=%d trace=%d", &level, &trace_flag) != 2 || level < 0) {
- pm_strcpy(jcr->errmsg, dir->msg);
- dir->fsend(_("2991 Bad setdebug command: %s\n"), jcr->errmsg);
- return 0;
+ int32_t level, trace, hangup;
+ int scan;
+
+ Dmsg1(50, "setdebug_cmd: %s", dir->msg);
+ scan = sscanf(dir->msg, "setdebug=%d trace=%d hangup=%d",
+ &level, &trace, &hangup);
+ if (scan != 3) {
+ Dmsg2(20, "sscanf failed: msg=%s scan=%d\n", dir->msg, scan);
+ if (sscanf(dir->msg, "setdebug=%d trace=%d", &level, &trace) != 2) {
+ pm_strcpy(jcr->errmsg, dir->msg);
+ dir->fsend(_("2991 Bad setdebug command: %s\n"), jcr->errmsg);
+ return 0;
+ } else {
+ hangup = -1;
+ }
}
- debug_level = level;
- set_trace(trace_flag);
- return dir->fsend(OKsetdebug, level);
+ if (level >= 0) {
+ debug_level = level;
+ }
+ set_trace(trace);
+ set_hangup(hangup);
+ Dmsg3(50, "level=%d trace=%d hangup=%d\n", level, get_trace(), get_hangup());
+ return dir->fsend(OKsetdebug, level, get_trace(), get_hangup());
}
Mmsg(jcr->errmsg, "JobId=%d Job=%s", jcr->JobId, jcr->Job);
new_plugins(jcr); /* instantiate plugins for this jcr */
generate_plugin_event(jcr, bEventJobStart, (void *)jcr->errmsg);
+#ifdef HAVE_WIN32
+ return dir->fsend(OKjob, VERSION, LSMDATE, win_os, DISTNAME, DISTVER);
+#else
return dir->fsend(OKjob, VERSION, LSMDATE, HOST_OS, DISTNAME, DISTVER);
+#endif
+}
+
+extern "C" char *job_code_callback_filed(JCR *jcr, const char* param)
+{
+ switch (param[0]) {
+ case 'D':
+ if (jcr->director) {
+ return jcr->director->hdr.name;
+ }
+ break;
+ }
+ return NULL;
+
}
static int runbefore_cmd(JCR *jcr)
/* Run the command now */
script = new_runscript();
+ script->set_job_code_callback(job_code_callback_filed);
script->set_command(cmd);
script->when = SCRIPT_Before;
ok = script->run(jcr, "ClientRunBeforeJob");
unbash_spaces(msg);
cmd = new_runscript();
+ cmd->set_job_code_callback(job_code_callback_filed);
cmd->set_command(msg);
cmd->on_success = true;
cmd->on_failure = false;
int on_success, on_failure, fail_on_error;
RUNSCRIPT *cmd = new_runscript() ;
+ cmd->set_job_code_callback(job_code_callback_filed);
Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
/* Note, we cannot sscanf into bools */
return dir->fsend(OKRunScript);
}
+/*
+ * This reads data sent from the Director from the
+ * RestoreObject table that allows us to get objects
+ * that were backed up (VSS .xml data) and are needed
+ * before starting the restore.
+ */
static int restore_object_cmd(JCR *jcr)
{
BSOCK *dir = jcr->dir_bsock;
- POOLMEM *msg = get_memory(dir->msglen+1);
int32_t FileIndex;
restore_object_pkt rop;
memset(&rop, 0, sizeof(rop));
rop.pkt_size = sizeof(rop);
rop.pkt_end = sizeof(rop);
+
Dmsg1(100, "Enter restoreobject_cmd: %s", dir->msg);
if (strcmp(dir->msg, endrestoreobjectcmd) == 0) {
generate_plugin_event(jcr, bEventRestoreObject, NULL);
- free_memory(msg);
return dir->fsend(OKRestoreObject);
}
+ rop.plugin_name = (char *) malloc (dir->msglen);
+ *rop.plugin_name = 0;
+
if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len,
- &rop.object_index, &rop.object_type, &FileIndex) != 5) {
- Dmsg0(5, "Bad restore object command\n");
- pm_strcpy(jcr->errmsg, dir->msg);
- Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
- goto bail_out;
+ &rop.object_full_len, &rop.object_index,
+ &rop.object_type, &rop.object_compression, &FileIndex,
+ rop.plugin_name) != 8) {
+
+ /* Old version, no plugin_name */
+ if (sscanf(dir->msg, restoreobjcmd1, &rop.JobId, &rop.object_len,
+ &rop.object_full_len, &rop.object_index,
+ &rop.object_type, &rop.object_compression, &FileIndex) != 7) {
+ Dmsg0(5, "Bad restore object command\n");
+ pm_strcpy(jcr->errmsg, dir->msg);
+ Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
+ goto bail_out;
+ }
}
- Dmsg5(100, "Recv object: JobId=%u objlen=%d objinx=%d objtype=%d FI=%d\n",
- rop.JobId, rop.object_len, rop.object_index, rop.object_type, FileIndex);
+ unbash_spaces(rop.plugin_name);
+
+ Dmsg7(100, "Recv object: JobId=%u objlen=%d full_len=%d objinx=%d objtype=%d "
+ "FI=%d plugin_name=%s\n",
+ rop.JobId, rop.object_len, rop.object_full_len,
+ rop.object_index, rop.object_type, FileIndex, rop.plugin_name);
/* Read Object name */
if (dir->recv() < 0) {
goto bail_out;
if (dir->recv() < 0) {
goto bail_out;
}
+ /* Transfer object from message buffer, and get new message buffer */
rop.object = dir->msg;
- Dmsg2(100, "Recv Object: len=%d Object=%s\n", dir->msglen, dir->msg);
-
+ dir->msg = get_pool_memory(PM_MESSAGE);
+
+ /* If object is compressed, uncompress it */
+ if (rop.object_compression == 1) { /* zlib level 9 */
+ int stat;
+ int out_len = rop.object_full_len + 100;
+ POOLMEM *obj = get_memory(out_len);
+ Dmsg2(100, "Inflating from %d to %d\n", rop.object_len, rop.object_full_len);
+ stat = Zinflate(rop.object, rop.object_len, obj, out_len);
+ Dmsg1(100, "Zinflate stat=%d\n", stat);
+ if (out_len != rop.object_full_len) {
+ Jmsg3(jcr, M_ERROR, 0, ("Decompression failed. Len wanted=%d got=%d. Object=%s\n"),
+ rop.object_full_len, out_len, rop.object_name);
+ }
+ free_pool_memory(rop.object); /* release compressed object */
+ rop.object = obj; /* new uncompressed object */
+ rop.object_len = out_len;
+ }
+ Dmsg2(100, "Recv Object: len=%d Object=%s\n", rop.object_len, rop.object);
+ /* we still need to do this to detect a vss restore */
if (strcmp(rop.object_name, "job_metadata.xml") == 0) {
Dmsg0(100, "got job metadata\n");
- free_and_null_pool_memory(jcr->job_metadata);
- jcr->job_metadata = rop.object;
- rop.object = NULL;
- } else {
- /* pass to plugin */
- generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop);
+ //free_and_null_pool_memory(jcr->job_metadata);
+ jcr->job_metadata = rop.object; /* this is like a boolean in the restore case */
+ // rop.object = NULL; /* but not this */
}
+
+ generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop);
if (rop.object_name) {
free(rop.object_name);
}
- if (!rop.object) {
- dir->msg = get_pool_memory(PM_MESSAGE);
+ if (rop.object) {
+ free_pool_memory(rop.object);
+ }
+ if (rop.plugin_name) {
+ free(rop.plugin_name);
}
- free_memory(msg);
Dmsg1(100, "Send: %s", OKRestoreObject);
return 1;
bail_out:
dir->fsend(_("2909 Bad RestoreObject command.\n"));
- free_memory(msg);
return 0;
}
return true;
}
-static findFOPTS *start_options(FF_PKT *ff)
+static void append_file(JCR *jcr, findINCEXE *incexe,
+ const char *buf, bool is_file)
{
- int state = ff->fileset->state;
- findINCEXE *incexe = ff->fileset->incexe;
+ if (is_file) {
+ incexe->name_list.append(new_dlistString(buf));
- if (state != state_options) {
- ff->fileset->state = state_options;
- findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
- memset(fo, 0, sizeof(findFOPTS));
- fo->regex.init(1, true);
- fo->regexdir.init(1, true);
- fo->regexfile.init(1, true);
- fo->wild.init(1, true);
- fo->wilddir.init(1, true);
- fo->wildfile.init(1, true);
- fo->wildbase.init(1, true);
- fo->base.init(1, true);
- fo->fstype.init(1, true);
- fo->drivetype.init(1, true);
- incexe->current_opts = fo;
- incexe->opts_list.append(fo);
- }
- return incexe->current_opts;
+ } else if (me->plugin_directory) {
+ generate_plugin_event(jcr, bEventPluginCommand, (void *)buf);
+ incexe->plugin_list.append(new_dlistString(buf));
+ } else {
+ Jmsg(jcr, M_FATAL, 0,
+ _("Plugin Directory not defined. Cannot use plugin: \"%s\"\n"),
+ buf);
+ }
}
/**
* Add fname to include/exclude fileset list. First check for
* | and < and if necessary perform command.
*/
-void add_file_to_fileset(JCR *jcr, const char *fname, findFILESET *fileset,
- bool is_file)
+void add_file_to_fileset(JCR *jcr, const char *fname, bool is_file)
{
+ findFILESET *fileset = jcr->ff->fileset;
char *p;
BPIPE *bpipe;
POOLMEM *fn;
case '|':
p++; /* skip over | */
fn = get_pool_memory(PM_FNAME);
- fn = edit_job_codes(jcr, fn, p, "");
+ fn = edit_job_codes(jcr, fn, p, "", job_code_callback_filed);
bpipe = open_bpipe(fn, 0, "r");
if (!bpipe) {
berrno be;
free_pool_memory(fn);
while (fgets(buf, sizeof(buf), bpipe->rfd)) {
strip_trailing_junk(buf);
- if (is_file) {
- fileset->incexe->name_list.append(new_dlistString(buf));
- } else {
- fileset->incexe->plugin_list.append(new_dlistString(buf));
- }
+ append_file(jcr, fileset->incexe, buf, is_file);
}
if ((stat=close_bpipe(bpipe)) != 0) {
berrno be;
p++; /* skip over < */
if ((ffd = fopen(p, "rb")) == NULL) {
berrno be;
- Jmsg(jcr, M_FATAL, 0, _("Cannot open FileSet input file: %s. ERR=%s\n"),
+ Jmsg(jcr, M_FATAL, 0,
+ _("Cannot open FileSet input file: %s. ERR=%s\n"),
p, be.bstrerror());
return;
}
while (fgets(buf, sizeof(buf), ffd)) {
strip_trailing_junk(buf);
- Dmsg1(100, "%s\n", buf);
- if (is_file) {
- fileset->incexe->name_list.append(new_dlistString(buf));
- } else {
- fileset->incexe->plugin_list.append(new_dlistString(buf));
- }
+ append_file(jcr, fileset->incexe, buf, is_file);
}
fclose(ffd);
break;
default:
- if (is_file) {
- fileset->incexe->name_list.append(new_dlistString(fname));
- } else {
- if (me->plugin_directory) {
- fileset->incexe->plugin_list.append(new_dlistString(fname));
- } else {
- Jmsg(jcr, M_FATAL, 0, _("Plugin Directory not defined. Cannot use plugin: \"%\"\n"),
- fname);
- }
- }
+ append_file(jcr, fileset->incexe, fname, is_file);
break;
}
}
+void set_incexe(JCR *jcr, findINCEXE *incexe)
+{
+ findFILESET *fileset = jcr->ff->fileset;
+ fileset->incexe = incexe;
+}
+
+
/**
* Define a new Exclude block in the FileSet
*/
-findFILESET *new_exclude(JCR *jcr)
+findINCEXE *new_exclude(JCR *jcr)
{
- FF_PKT *ff = jcr->ff;
- findFILESET *fileset = ff->fileset;
+ findFILESET *fileset = jcr->ff->fileset;
/* New exclude */
fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
fileset->incexe->name_list.init();
fileset->incexe->plugin_list.init();
fileset->exclude_list.append(fileset->incexe);
- return fileset;
+ return fileset->incexe;
+}
+
+/**
+ * Define a new Include block in the FileSet
+ */
+findINCEXE *new_include(JCR *jcr)
+{
+ findFILESET *fileset = jcr->ff->fileset;
+
+ /* New include */
+ fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
+ memset(fileset->incexe, 0, sizeof(findINCEXE));
+ fileset->incexe->opts_list.init(1, true);
+ fileset->incexe->name_list.init(); /* for dlist; was 1,true for alist */
+ fileset->incexe->plugin_list.init();
+ fileset->include_list.append(fileset->incexe);
+ return fileset->incexe;
+}
+
+/**
+ * Define a new preInclude block in the FileSet
+ * That is the include is prepended to the other
+ * Includes. This is used for plugin exclusions.
+ */
+findINCEXE *new_preinclude(JCR *jcr)
+{
+ findFILESET *fileset = jcr->ff->fileset;
+
+ /* New pre-include */
+ fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
+ memset(fileset->incexe, 0, sizeof(findINCEXE));
+ fileset->incexe->opts_list.init(1, true);
+ fileset->incexe->name_list.init(); /* for dlist; was 1,true for alist */
+ fileset->incexe->plugin_list.init();
+ fileset->include_list.prepend(fileset->incexe);
+ return fileset->incexe;
}
+static findFOPTS *start_options(FF_PKT *ff)
+{
+ int state = ff->fileset->state;
+ findINCEXE *incexe = ff->fileset->incexe;
+
+ if (state != state_options) {
+ ff->fileset->state = state_options;
+ findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
+ memset(fo, 0, sizeof(findFOPTS));
+ fo->regex.init(1, true);
+ fo->regexdir.init(1, true);
+ fo->regexfile.init(1, true);
+ fo->wild.init(1, true);
+ fo->wilddir.init(1, true);
+ fo->wildfile.init(1, true);
+ fo->wildbase.init(1, true);
+ fo->base.init(1, true);
+ fo->fstype.init(1, true);
+ fo->drivetype.init(1, true);
+ incexe->current_opts = fo;
+ incexe->opts_list.append(fo);
+ }
+ return incexe->current_opts;
+}
+
+/*
+ * Used by plugins to define a new options block
+ */
+void new_options(JCR *jcr, findINCEXE *incexe)
+{
+ if (!incexe) {
+ incexe = jcr->ff->fileset->incexe;
+ }
+ findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
+ memset(fo, 0, sizeof(findFOPTS));
+ fo->regex.init(1, true);
+ fo->regexdir.init(1, true);
+ fo->regexfile.init(1, true);
+ fo->wild.init(1, true);
+ fo->wilddir.init(1, true);
+ fo->wildfile.init(1, true);
+ fo->wildbase.init(1, true);
+ fo->base.init(1, true);
+ fo->fstype.init(1, true);
+ fo->drivetype.init(1, true);
+ incexe->current_opts = fo;
+ incexe->opts_list.prepend(fo);
+ jcr->ff->fileset->state = state_options;
+}
+
+/**
+ * Add a regex to the current fileset
+ */
+int add_regex_to_fileset(JCR *jcr, const char *item, int type)
+{
+ findFOPTS *current_opts = start_options(jcr->ff);
+ regex_t *preg;
+ int rc;
+ char prbuf[500];
+
+ preg = (regex_t *)malloc(sizeof(regex_t));
+ if (current_opts->flags & FO_IGNORECASE) {
+ rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
+ } else {
+ rc = regcomp(preg, item, REG_EXTENDED);
+ }
+ if (rc != 0) {
+ regerror(rc, preg, prbuf, sizeof(prbuf));
+ regfree(preg);
+ free(preg);
+ Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
+ return state_error;
+ }
+ if (type == ' ') {
+ current_opts->regex.append(preg);
+ } else if (type == 'D') {
+ current_opts->regexdir.append(preg);
+ } else if (type == 'F') {
+ current_opts->regexfile.append(preg);
+ } else {
+ return state_error;
+ }
+ return state_options;
+}
+
+/**
+ * Add a wild card to the current fileset
+ */
+int add_wild_to_fileset(JCR *jcr, const char *item, int type)
+{
+ findFOPTS *current_opts = start_options(jcr->ff);
+
+ if (type == ' ') {
+ current_opts->wild.append(bstrdup(item));
+ } else if (type == 'D') {
+ current_opts->wilddir.append(bstrdup(item));
+ } else if (type == 'F') {
+ current_opts->wildfile.append(bstrdup(item));
+ } else if (type == 'B') {
+ current_opts->wildbase.append(bstrdup(item));
+ } else {
+ return state_error;
+ }
+ return state_options;
+}
+
+
+/**
+ * Add options to the current fileset
+ */
+int add_options_to_fileset(JCR *jcr, const char *item)
+{
+ findFOPTS *current_opts = start_options(jcr->ff);
+
+ set_options(current_opts, item);
+ return state_options;
+}
static void add_fileset(JCR *jcr, const char *item)
{
}
switch (code) {
case 'I':
- /* New include */
- fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
- memset(fileset->incexe, 0, sizeof(findINCEXE));
- fileset->incexe->opts_list.init(1, true);
- fileset->incexe->name_list.init(); /* for dlist; was 1,true for alist */
- fileset->incexe->plugin_list.init();
- fileset->include_list.append(fileset->incexe);
+ (void)new_include(jcr);
break;
case 'E':
- fileset = new_exclude(jcr);
+ (void)new_exclude(jcr);
break;
- case 'N':
+ case 'N': /* null */
state = state_none;
break;
- case 'F':
+ case 'F': /* file = */
/* File item to include or exclude list */
state = state_include;
- add_file_to_fileset(jcr, item, fileset, true);
+ add_file_to_fileset(jcr, item, true);
break;
- case 'P':
+ case 'P': /* plugin */
/* Plugin item to include list */
state = state_include;
- add_file_to_fileset(jcr, item, fileset, false);
+ add_file_to_fileset(jcr, item, false);
break;
- case 'R':
- current_opts = start_options(ff);
- regex_t *preg;
- int rc;
- char prbuf[500];
- preg = (regex_t *)malloc(sizeof(regex_t));
- if (current_opts->flags & FO_IGNORECASE) {
- rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
- } else {
- rc = regcomp(preg, item, REG_EXTENDED);
- }
- if (rc != 0) {
- regerror(rc, preg, prbuf, sizeof(prbuf));
- regfree(preg);
- free(preg);
- Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
- state = state_error;
- break;
- }
- state = state_options;
- if (subcode == ' ') {
- current_opts->regex.append(preg);
- } else if (subcode == 'D') {
- current_opts->regexdir.append(preg);
- } else if (subcode == 'F') {
- current_opts->regexfile.append(preg);
- } else {
- state = state_error;
- }
+ case 'R': /* regex */
+ state = add_regex_to_fileset(jcr, item, subcode);
break;
case 'B':
current_opts = start_options(ff);
current_opts->base.append(bstrdup(item));
state = state_options;
break;
- case 'X':
+ case 'X': /* Filetype or Drive type */
current_opts = start_options(ff);
state = state_options;
if (subcode == ' ') {
state = state_error;
}
break;
- case 'W':
- current_opts = start_options(ff);
- state = state_options;
- if (subcode == ' ') {
- current_opts->wild.append(bstrdup(item));
- } else if (subcode == 'D') {
- current_opts->wilddir.append(bstrdup(item));
- } else if (subcode == 'F') {
- current_opts->wildfile.append(bstrdup(item));
- } else if (subcode == 'B') {
- current_opts->wildbase.append(bstrdup(item));
- } else {
- state = state_error;
- }
+ case 'W': /* wild cards */
+ state = add_wild_to_fileset(jcr, item, subcode);
break;
- case 'O':
- current_opts = start_options(ff);
- set_options(current_opts, item);
- state = state_options;
+ case 'O': /* Options */
+ state = add_options_to_fileset(jcr, item);
break;
- case 'Z':
+ case 'Z': /* ignore dir */
state = state_include;
fileset->incexe->ignoredir = bstrdup(item);
break;
case 'D':
current_opts = start_options(ff);
-// current_opts->reader = bstrdup(item);
+// current_opts->reader = bstrdup(item); /* deprecated */
state = state_options;
break;
case 'T':
current_opts = start_options(ff);
-// current_opts->writer = bstrdup(item);
+// current_opts->writer = bstrdup(item); /* deprecated */
+ state = state_options;
+ break;
+ case 'G': /* Plugin command for this Option block */
+ current_opts = start_options(ff);
+ current_opts->plugin = bstrdup(item);
state = state_options;
break;
default:
}
}
dlistString *node;
- foreach_dlist(node, incexe->name_list) {
+ foreach_dlist(node, &incexe->name_list) {
Dmsg1(400, "F %s\n", node->c_str());
}
foreach_dlist(node, &incexe->plugin_list) {
* "compile" time in filed/job.c, and keep only a bit mask
* and the Verify options.
*/
-static void set_options(findFOPTS *fo, const char *opts)
+static int set_options(findFOPTS *fo, const char *opts)
{
int j;
const char *p;
break;
case 'R': /* Resource forks and Finder Info */
fo->flags |= FO_HFSPLUS;
+ break;
case 'r': /* read fifo */
fo->flags |= FO_READFIFO;
break;
case 'W':
fo->flags |= FO_ENHANCEDWILD;
break;
- case 'Z': /* gzip compression */
- fo->flags |= FO_GZIP;
- fo->GZIP_level = *++p - '0';
+ case 'Z': /* compression */
+ p++; /* skip Z */
+ if (*p >= '0' && *p <= '9') {
+ fo->flags |= FO_COMPRESS;
+ fo->Compress_algo = COMPRESS_GZIP;
+ fo->Compress_level = *p - '0';
+ }
+ else if (*p == 'o') {
+ fo->flags |= FO_COMPRESS;
+ fo->Compress_algo = COMPRESS_LZO1X;
+ fo->Compress_level = 1; /* not used with LZO */
+ }
break;
case 'K':
fo->flags |= FO_NOATIME;
break;
}
}
+ return state_options;
}
static int fileset_cmd(JCR *jcr)
{
BSOCK *dir = jcr->dir_bsock;
+ int rtnstat;
#if defined(WIN32_VSS)
int vss = 0;
if (!term_fileset(jcr)) {
return 0;
}
- return dir->fsend(OKinc);
+ rtnstat = dir->fsend(OKinc);
+ generate_plugin_event(jcr, bEventEndFileSet);
+ return rtnstat;
}
static void free_bootstrap(JCR *jcr)
while (dir->recv() >= 0)
{ }
free_bootstrap(jcr);
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ jcr->setJobStatus(JS_ErrorTerminated);
return 0;
}
int mtime_only;
level = get_memory(dir->msglen+1);
- Dmsg1(100, "level_cmd: %s", dir->msg);
+ Dmsg1(10, "level_cmd: %s", dir->msg);
/* keep compatibility with older directors */
if (strstr(dir->msg, "accurate")) {
jcr->accurate = true;
}
+ if (strstr(dir->msg, "rerunning")) {
+ jcr->rerunning = true;
+ }
if (sscanf(dir->msg, "level = %s ", level) != 1) {
goto bail_out;
}
/* Base backup requested? */
if (strcmp(level, "base") == 0) {
- jcr->set_JobLevel(L_BASE);
+ jcr->setJobLevel(L_BASE);
/* Full backup requested? */
} else if (strcmp(level, "full") == 0) {
- jcr->set_JobLevel(L_FULL);
+ jcr->setJobLevel(L_FULL);
} else if (strstr(level, "differential")) {
- jcr->set_JobLevel(L_DIFFERENTIAL);
+ jcr->setJobLevel(L_DIFFERENTIAL);
free_memory(level);
return 1;
} else if (strstr(level, "incremental")) {
- jcr->set_JobLevel(L_INCREMENTAL);
+ jcr->setJobLevel(L_INCREMENTAL);
free_memory(level);
return 1;
/*
utime_t since_time, adj;
btime_t his_time, bt_start, rt=0, bt_adj=0;
if (jcr->getJobLevel() == L_NONE) {
- jcr->set_JobLevel(L_SINCE); /* if no other job level set, do it now */
+ jcr->setJobLevel(L_SINCE); /* if no other job level set, do it now */
}
- if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
- buf, &mtime_only) != 2) {
- goto bail_out;
+ if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d prev_job=%127s",
+ buf, &mtime_only, jcr->PrevJob) != 3) {
+ if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
+ buf, &mtime_only) != 2) {
+ goto bail_out;
+ }
}
since_time = str_to_uint64(buf); /* this is the since time */
- Dmsg1(100, "since_time=%lld\n", since_time);
+ Dmsg2(100, "since_time=%lld prev_job=%s\n", since_time, jcr->PrevJob);
char ed1[50], ed2[50];
/*
* Sync clocks by polling him for the time. We take
if (buf) {
free_memory(buf);
}
- generate_plugin_event(jcr, bEventLevel, (void *)jcr->getJobLevel());
+ generate_plugin_event(jcr, bEventLevel, (void*)(intptr_t)jcr->getJobLevel());
return dir->fsend(OKlevel);
bail_out:
/* Try to connect for 1 hour at 10 second intervals */
sd->set_source_address(me->FDsrc_addr);
+
if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
_("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
sd->destroy();
BSOCK *sd = jcr->store_bsock;
int ok = 0;
int SDJobStatus;
+ int32_t FileIndex;
#if defined(WIN32_VSS)
// capture state here, if client is backed up by multiple directors
P(vss_mutex);
}
#endif
+
+ if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
+ jcr->JobFiles = FileIndex;
+ Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
+ }
/**
* Validate some options given to the backup make sense for the compiled in
goto cleanup;
}
- set_jcr_job_status(jcr, JS_Blocked);
- jcr->set_JobType(JT_BACKUP);
+ jcr->setJobStatus(JS_Blocked);
+ jcr->setJobType(JT_BACKUP);
Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
if (sd == NULL) {
if (g_pVSSClient->InitializeForBackup(jcr)) {
generate_plugin_event(jcr, bEventVssBackupAddComponents);
/* tell vss which drives to snapshot */
- char szWinDriveLetters[27];
+ char szWinDriveLetters[27];
+ *szWinDriveLetters=0;
+ /* Plugin driver can return drive letters */
+ generate_plugin_event(jcr, bEventVssPrepareSnapshot, szWinDriveLetters);
if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) {
Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters);
if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) {
- Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshots failed.\n"));
- jcr->JobErrors++;
+ Jmsg(jcr, M_FATAL, 0, _("CreateSGenerate VSS snapshots failed.\n"));
} else {
/* tell user if snapshot creation of a specific drive failed */
int i;
for (i=0; i < (int)strlen(szWinDriveLetters); i++) {
if (islower(szWinDriveLetters[i])) {
- Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed. VSS support is disabled on this drive.\n"), szWinDriveLetters[i]);
- jcr->JobErrors++;
+ Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed.\n"), szWinDriveLetters[i]);
}
}
/* inform user about writer states */
- for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++)
+ for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {
if (g_pVSSClient->GetWriterState(i) < 1) {
- Jmsg(jcr, M_WARNING, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));
- jcr->JobErrors++;
+ Jmsg(jcr, M_INFO, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));
}
+ }
}
} else {
- Jmsg(jcr, M_INFO, 0, _("No drive letters found for generating VSS snapshots.\n"));
+ Jmsg(jcr, M_FATAL, 0, _("No drive letters found for generating VSS snapshots.\n"));
}
} else {
- berrno be;
- Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
+ Jmsg(jcr, M_FATAL, 0, _("VSS was not initialized properly.\n"));
}
run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
}
*/
Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
if (!blast_data_to_storage_daemon(jcr, NULL)) {
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ jcr->setJobStatus(JS_ErrorTerminated);
bnet_suppress_error_messages(sd, 1);
Dmsg0(110, "Error in blast_data.\n");
} else {
- set_jcr_job_status(jcr, JS_Terminated);
+ jcr->setJobStatus(JS_Terminated);
/* Note, the above set status will not override an error */
if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
bnet_suppress_error_messages(sd, 1);
* Expect to get response to append_data from Storage daemon
*/
if (!response(jcr, sd, OK_append, "Append Data")) {
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ jcr->setJobStatus(JS_ErrorTerminated);
goto cleanup;
}
sd->fsend(append_end, jcr->Ticket);
/* Get end OK */
if (!response(jcr, sd, OK_end, "Append End")) {
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ jcr->setJobStatus(JS_ErrorTerminated);
goto cleanup;
}
#if defined(WIN32_VSS)
if (jcr->VSS) {
Win32ConvCleanupCache();
+ g_pVSSClient->DestroyWriterInfo();
V(vss_mutex);
}
#endif
BSOCK *sd = jcr->store_bsock;
char level[100];
- jcr->set_JobType(JT_VERIFY);
+ jcr->setJobType(JT_VERIFY);
if (sscanf(dir->msg, verifycmd, level) != 1) {
dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
return 0;
}
if (strcasecmp(level, "init") == 0) {
- jcr->set_JobLevel(L_VERIFY_INIT);
+ jcr->setJobLevel(L_VERIFY_INIT);
} else if (strcasecmp(level, "catalog") == 0){
- jcr->set_JobLevel(L_VERIFY_CATALOG);
+ jcr->setJobLevel(L_VERIFY_CATALOG);
} else if (strcasecmp(level, "volume") == 0){
- jcr->set_JobLevel(L_VERIFY_VOLUME_TO_CATALOG);
+ jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
} else if (strcasecmp(level, "data") == 0){
- jcr->set_JobLevel(L_VERIFY_DATA);
+ jcr->setJobLevel(L_VERIFY_DATA);
} else if (strcasecmp(level, "disk_to_catalog") == 0) {
- jcr->set_JobLevel(L_VERIFY_DISK_TO_CATALOG);
+ jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
} else {
dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
return 0;
dir->fsend(OKverify);
generate_daemon_event(jcr, "JobStart");
- generate_plugin_event(jcr, bEventLevel, (void *)jcr->getJobLevel());
+ generate_plugin_event(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
generate_plugin_event(jcr, bEventStartVerifyJob);
Dmsg1(110, "filed>dird: %s", dir->msg);
return 0; /* return and terminate command loop */
}
+#if 0
#ifdef WIN32_VSS
static bool vss_restore_init_callback(JCR *jcr, int init_type)
{
}
}
#endif
+#endif
/**
* Do a Restore for Director
Dmsg0(100, "restore command\n");
#if defined(WIN32_VSS)
- /* TODO: this should be given from the director */
- enable_vss = 1;
+ /**
+ * No need to enable VSS for restore if we do not have plugin
+ * data to restore
+ */
+ enable_vss = jcr->job_metadata != NULL;
+ jcr->job_metadata = NULL;
Dmsg2(50, "g_pVSSClient = %p, enable_vss = %d\n", g_pVSSClient, enable_vss);
// capture state here, if client is backed up by multiple directors
Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
unbash_spaces(args);
+ /* Keep track of newly created directories to apply them correct attributes */
+ if (replace == REPLACE_NEVER) {
+ jcr->keep_path_list = true;
+ }
+
if (use_regexwhere) {
jcr->where_bregexp = get_bregexps(args);
if (!jcr->where_bregexp) {
dir->fsend(OKrestore);
Dmsg1(110, "filed>dird: %s", dir->msg);
- jcr->set_JobType(JT_RESTORE);
+ jcr->setJobType(JT_RESTORE);
- set_jcr_job_status(jcr, JS_Blocked);
+ jcr->setJobStatus(JS_Blocked);
if (!open_sd_read_session(jcr)) {
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ jcr->setJobStatus(JS_ErrorTerminated);
goto bail_out;
}
- set_jcr_job_status(jcr, JS_Running);
+ jcr->setJobStatus(JS_Running);
/**
* Do restore of files and data
#if defined(WIN32_VSS)
/* START VSS ON WIN32 */
if (jcr->VSS) {
- if (g_pVSSClient->InitializeForRestore(jcr, vss_restore_init_callback,
- (WCHAR *)jcr->job_metadata)) {
- /* inform user about writer states */
- int i;
- for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {
- int msg_type = M_INFO;
- if (g_pVSSClient->GetWriterState(i) < 1) {
- msg_type = M_WARNING;
- jcr->JobErrors++;
- }
- if (g_pVSSClient->GetWriterState(i) < 1) {
- Jmsg(jcr, M_WARNING, 0, _("VSS Writer (PreRestore): %s\n"), g_pVSSClient->GetWriterInfo(i));
- jcr->JobErrors++;
- }
- }
- } else {
+ if (!g_pVSSClient->InitializeForRestore(jcr)) {
berrno be;
Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
}
- free_and_null_pool_memory(jcr->job_metadata);
+ //free_and_null_pool_memory(jcr->job_metadata);
run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
}
#endif
do_restore(jcr);
stop_dir_heartbeat(jcr);
- set_jcr_job_status(jcr, JS_Terminated);
+ jcr->setJobStatus(JS_Terminated);
if (jcr->JobStatus != JS_Terminated) {
bnet_suppress_error_messages(sd, 1);
}
#if defined(WIN32_VSS)
/* STOP VSS ON WIN32 */
/* tell vss to close the restore session */
- Dmsg0(0, "About to call CloseRestore\n");
+ Dmsg0(100, "About to call CloseRestore\n");
if (jcr->VSS) {
- Dmsg0(0, "Really about to call CloseRestore\n");
+#if 0
+ generate_plugin_event(jcr, bEventVssBeforeCloseRestore);
+#endif
+ Dmsg0(100, "Really about to call CloseRestore\n");
if (g_pVSSClient->CloseRestore()) {
- Dmsg0(0, "CloseRestore success\n");
+ Dmsg0(100, "CloseRestore success\n");
+#if 0
/* inform user about writer states */
for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
int msg_type = M_INFO;
if (g_pVSSClient->GetWriterState(i) < 1) {
- msg_type = M_WARNING;
- jcr->JobErrors++;
+ //msg_type = M_WARNING;
+ //jcr->JobErrors++;
}
Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
}
+#endif
}
else
- Dmsg1(0, "CloseRestore fail - %08x\n", errno);
+ Dmsg1(100, "CloseRestore fail - %08x\n", errno);
V(vss_mutex);
}
#endif
bfree_and_null(jcr->where);
if (jcr->JobErrors) {
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ jcr->setJobStatus(JS_ErrorTerminated);
}
Dmsg0(100, "Done in job.c\n");
ret = 0; /* we stop here */
}
+ if (job_canceled(jcr)) {
+ ret = 0; /* we stop here */
+ }
+
return ret;
}
}
free_runscripts(jcr->RunScripts);
delete jcr->RunScripts;
+ free_path_list(jcr);
if (jcr->JobId != 0)
write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
berrno be;
Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
jcr->RestoreBootstrap, be.bstrerror());
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ jcr->setJobStatus(JS_ErrorTerminated);
goto bail_out;
}
sd->msglen = pm_strcpy(sd->msg, bootstrap);
sd->signal(BNET_EOD);
fclose(bs);
if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ jcr->setJobStatus(JS_ErrorTerminated);
goto bail_out;
}
stat = 1;