]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/filed/job.c
Clear delta sequence when not using in plugin
[bacula/bacula] / bacula / src / filed / job.c
index 7eeb9f7715c10706380ea2fe39d75fab8c61ba11..e81f608342c3203ca1079fa4f0d21b4e3cdb9e32 100644 (file)
@@ -6,7 +6,7 @@
    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
    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.
 
    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.
 
    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.
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
@@ -89,8 +89,12 @@ static int runbefore_cmd(JCR *jcr);
 static int runafter_cmd(JCR *jcr);
 static int runbeforenow_cmd(JCR *jcr);
 static int restore_object_cmd(JCR *jcr);
 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 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 */
 
 
 /* Exported functions */
 
@@ -126,6 +130,10 @@ static struct s_cmds cmds[] = {
    {"Run",          runscript_cmd, 0},
    {"accurate",     accurate_cmd,  0},
    {"restoreobject", restore_object_cmd, 0},
    {"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 */
 };
 
    {NULL,       NULL}                  /* list terminator */
 };
 
@@ -137,7 +145,7 @@ static char sessioncmd[]  = "session %127s %ld %ld %ld %ld %ld %ld\n";
 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 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\n";
 static char endrestoreobjectcmd[] = "restoreobject end\n";
 static char verifycmd[]   = "verify level=%30s";
 static char estimatecmd[] = "estimate listing=%d";
 static char endrestoreobjectcmd[] = "restoreobject end\n";
 static char verifycmd[]   = "verify level=%30s";
 static char estimatecmd[] = "estimate listing=%d";
@@ -394,9 +402,28 @@ void *handle_client_request(void *dirp)
    free_jcr(jcr);                     /* destroy JCR record */
    Dmsg0(100, "Done with free_jcr\n");
    Dsm_check(1);
    free_jcr(jcr);                     /* destroy JCR record */
    Dmsg0(100, "Done with free_jcr\n");
    Dsm_check(1);
+   garbage_collect_memory_pool();
    return NULL;
 }
 
    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.
 /**
  * Hello from Director he must identify himself and provide his
  *  password.
@@ -425,13 +452,13 @@ static int cancel_cmd(JCR *jcr)
       if (!(cjcr=get_jcr_by_full_name(Job))) {
          dir->fsend(_("2901 Job %s not found.\n"), Job);
       } else {
       if (!(cjcr=get_jcr_by_full_name(Job))) {
          dir->fsend(_("2901 Job %s not found.\n"), Job);
       } else {
+         generate_plugin_event(cjcr, bEventCancelCommand, NULL);
+         set_jcr_job_status(cjcr, JS_Canceled);
          if (cjcr->store_bsock) {
             cjcr->store_bsock->set_timed_out();
             cjcr->store_bsock->set_terminated();
          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);
       }
          free_jcr(cjcr);
          dir->fsend(_("2001 Job %s marked to be canceled.\n"), Job);
       }
@@ -629,7 +656,6 @@ static int runscript_cmd(JCR *jcr)
 static int restore_object_cmd(JCR *jcr)
 {
    BSOCK *dir = jcr->dir_bsock;
 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;
 
    int32_t FileIndex;
    restore_object_pkt rop;
 
@@ -639,20 +665,21 @@ static int restore_object_cmd(JCR *jcr)
    Dmsg1(100, "Enter restoreobject_cmd: %s", dir->msg);
    if (strcmp(dir->msg, endrestoreobjectcmd) == 0) {
       generate_plugin_event(jcr, bEventRestoreObject, NULL);
    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);
    }
 
    if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len, 
       return dir->fsend(OKRestoreObject);
    }
 
    if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len, 
-              &rop.object_index, &rop.object_type, &FileIndex) != 5) {
+              &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;
    }
 
       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);
+   Dmsg6(100, "Recv object: JobId=%u objlen=%d full_len=%d objinx=%d objtype=%d FI=%d\n",
+         rop.JobId, rop.object_len, rop.object_full_len, 
+         rop.object_index, rop.object_type, FileIndex);
    /* Read Object name */
    if (dir->recv() < 0) {
       goto bail_out;
    /* Read Object name */
    if (dir->recv() < 0) {
       goto bail_out;
@@ -664,9 +691,28 @@ static int restore_object_cmd(JCR *jcr)
    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;
    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);
+   /* Special Job meta data */
    if (strcmp(rop.object_name, "job_metadata.xml") == 0) {
       Dmsg0(100, "got job metadata\n");
       free_and_null_pool_memory(jcr->job_metadata);
    if (strcmp(rop.object_name, "job_metadata.xml") == 0) {
       Dmsg0(100, "got job metadata\n");
       free_and_null_pool_memory(jcr->job_metadata);
@@ -680,17 +726,15 @@ static int restore_object_cmd(JCR *jcr)
    if (rop.object_name) {
       free(rop.object_name);
    }
    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);
    }
 
    }
 
-   free_memory(msg);
    Dmsg1(100, "Send: %s", OKRestoreObject);
    return 1;
 
 bail_out:
    dir->fsend(_("2909 Bad RestoreObject command.\n"));
    Dmsg1(100, "Send: %s", OKRestoreObject);
    return 1;
 
 bail_out:
    dir->fsend(_("2909 Bad RestoreObject command.\n"));
-   free_memory(msg);
    return 0;
 
 }
    return 0;
 
 }
@@ -717,39 +761,30 @@ static bool init_fileset(JCR *jcr)
    return true;
 }
 
    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.
  */
 }
 
 /**
  * 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;
    char *p;
    BPIPE *bpipe;
    POOLMEM *fn;
@@ -776,11 +811,7 @@ void add_file_to_fileset(JCR *jcr, const char *fname, findFILESET *fileset,
       free_pool_memory(fn);
       while (fgets(buf, sizeof(buf), bpipe->rfd)) {
          strip_trailing_junk(buf);
       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;
       }
       if ((stat=close_bpipe(bpipe)) != 0) {
          berrno be;
@@ -794,43 +825,36 @@ void add_file_to_fileset(JCR *jcr, const char *fname, findFILESET *fileset,
       p++;                      /* skip over < */
       if ((ffd = fopen(p, "rb")) == NULL) {
          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);
             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:
       }
       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;
    }
 }
 
       break;
    }
 }
 
+void set_incexe(JCR *jcr, findINCEXE *incexe)
+{
+   findFILESET *fileset = jcr->ff->fileset;
+   fileset->incexe = incexe;
+}
+
+
 /**
  * Define a new Exclude block in the FileSet
  */
 /**
  * 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));
 
    /* New exclude */
    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
@@ -839,16 +863,15 @@ findFILESET *new_exclude(JCR *jcr)
    fileset->incexe->name_list.init();
    fileset->incexe->plugin_list.init();
    fileset->exclude_list.append(fileset->incexe);
    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
  */
 }
 
 /**
  * Define a new Include block in the FileSet
  */
-findFILESET *new_include(JCR *jcr)
+findINCEXE *new_include(JCR *jcr)
 {
 {
-   FF_PKT *ff = jcr->ff;
-   findFILESET *fileset = ff->fileset;
+   findFILESET *fileset = jcr->ff->fileset;
 
    /* New include */
    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
 
    /* New include */
    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
@@ -857,19 +880,88 @@ findFILESET *new_include(JCR *jcr)
    fileset->incexe->name_list.init(); /* for dlist;  was 1,true for alist */
    fileset->incexe->plugin_list.init();
    fileset->include_list.append(fileset->incexe);
    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;
+   return fileset->incexe;
 }
 
 }
 
-int add_regex_to_fileset(JCR *jcr, const char *item, int subcode)
+/**
+ * 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)
 {
 {
-   FF_PKT *ff = jcr->ff;
-   int state;
-   findFOPTS *current_opts;
+   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];
 
    regex_t *preg;
    int rc;
    char prbuf[500];
 
-   current_opts = start_options(ff);
    preg = (regex_t *)malloc(sizeof(regex_t));
    if (current_opts->flags & FO_IGNORECASE) {
       rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
    preg = (regex_t *)malloc(sizeof(regex_t));
    if (current_opts->flags & FO_IGNORECASE) {
       rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
@@ -881,23 +973,53 @@ int add_regex_to_fileset(JCR *jcr, const char *item, int subcode)
       regfree(preg);
       free(preg);
       Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
       regfree(preg);
       free(preg);
       Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
-      state = state_error;
-      return state;
+      return state_error;
    }
    }
-   state = state_options;
-   if (subcode == ' ') {
+   if (type == ' ') {
       current_opts->regex.append(preg);
       current_opts->regex.append(preg);
-   } else if (subcode == 'D') {
+   } else if (type == 'D') {
       current_opts->regexdir.append(preg);
       current_opts->regexdir.append(preg);
-   } else if (subcode == 'F') {
+   } else if (type == 'F') {
       current_opts->regexfile.append(preg);
    } else {
       current_opts->regexfile.append(preg);
    } else {
-      state = state_error;
+      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;
+   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)
 {
    FF_PKT *ff = jcr->ff;
 static void add_fileset(JCR *jcr, const char *item)
 {
    FF_PKT *ff = jcr->ff;
@@ -938,25 +1060,25 @@ static void add_fileset(JCR *jcr, const char *item)
    }
    switch (code) {
    case 'I':
    }
    switch (code) {
    case 'I':
-      fileset = new_include(jcr);
+      (void)new_include(jcr);
       break;
    case 'E':
       break;
    case 'E':
-      fileset = new_exclude(jcr);
+      (void)new_exclude(jcr);
       break;
       break;
-   case 'N':
+   case 'N':                             /* null */
       state = state_none;
       break;
       state = state_none;
       break;
-   case 'F':
+   case 'F':                             /* file = */
       /* File item to include or exclude list */
       state = state_include;
       /* 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;
       break;
-   case 'P':
+   case 'P':                              /* plugin */
       /* Plugin item to include list */
       state = state_include;
       /* Plugin item to include list */
       state = state_include;
-      add_file_to_fileset(jcr, item, fileset, false);
+      add_file_to_fileset(jcr, item, false);
       break;
       break;
-   case 'R':
+   case 'R':                              /* regex */
       state = add_regex_to_fileset(jcr, item, subcode);
       break;
    case 'B':
       state = add_regex_to_fileset(jcr, item, subcode);
       break;
    case 'B':
@@ -964,7 +1086,7 @@ static void add_fileset(JCR *jcr, const char *item)
       current_opts->base.append(bstrdup(item));
       state = state_options;
       break;
       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 == ' ') {
       current_opts = start_options(ff);
       state = state_options;
       if (subcode == ' ') {
@@ -975,38 +1097,24 @@ static void add_fileset(JCR *jcr, const char *item)
          state = state_error;
       }
       break;
          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;
       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;
       break;
-   case 'Z':
+   case 'Z':                                /* ignore dir */
       state = state_include;
       fileset->incexe->ignoredir = bstrdup(item);
       break;
    case 'D':
       current_opts = start_options(ff);
       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);
       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;
    default:
       state = state_options;
       break;
    default:
@@ -1126,7 +1234,7 @@ static bool term_fileset(JCR *jcr)
  *  "compile" time in filed/job.c, and keep only a bit mask
  *  and the Verify options.
  */
  *  "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;
 {
    int j;
    const char *p;
@@ -1168,6 +1276,7 @@ static void set_options(findFOPTS *fo, const char *opts)
          break;
       case 'R':                 /* Resource forks and Finder Info */
          fo->flags |= FO_HFSPLUS;
          break;
       case 'R':                 /* Resource forks and Finder Info */
          fo->flags |= FO_HFSPLUS;
+         break;
       case 'r':                 /* read fifo */
          fo->flags |= FO_READFIFO;
          break;
       case 'r':                 /* read fifo */
          fo->flags |= FO_READFIFO;
          break;
@@ -1282,6 +1391,7 @@ static void set_options(findFOPTS *fo, const char *opts)
          break;
       }
    }
          break;
       }
    }
+   return state_options;
 }
 
 
 }
 
 
@@ -1291,6 +1401,7 @@ static void set_options(findFOPTS *fo, const char *opts)
 static int fileset_cmd(JCR *jcr)
 {
    BSOCK *dir = jcr->dir_bsock;
 static int fileset_cmd(JCR *jcr)
 {
    BSOCK *dir = jcr->dir_bsock;
+   int rtnstat;
 
 #if defined(WIN32_VSS)
    int vss = 0;
 
 #if defined(WIN32_VSS)
    int vss = 0;
@@ -1310,7 +1421,9 @@ static int fileset_cmd(JCR *jcr)
    if (!term_fileset(jcr)) {
       return 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)
 }
 
 static void free_bootstrap(JCR *jcr)
@@ -1709,30 +1822,29 @@ static int backup_cmd(JCR *jcr)
         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)) {               
         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++;
+               berrno be;
+               Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshots failed. ERR=%s\n"), be.bstrerror());
             } 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])) {
             } 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 */
                   }
                }
                /* 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) {
                   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 {
             }
         } 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;
         }
       } 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. ERR=%s\n"), be.bstrerror());
       } 
       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
    }
       } 
       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
    }
@@ -1795,6 +1907,7 @@ cleanup:
 #if defined(WIN32_VSS)
    if (jcr->VSS) {
       Win32ConvCleanupCache();
 #if defined(WIN32_VSS)
    if (jcr->VSS) {
       Win32ConvCleanupCache();
+      g_pVSSClient->DestroyWriterInfo();
       V(vss_mutex);
    }
 #endif
       V(vss_mutex);
    }
 #endif
@@ -1916,8 +2029,11 @@ static int restore_cmd(JCR *jcr)
    Dmsg0(100, "restore command\n");
 #if defined(WIN32_VSS)
 
    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;
 
    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(50, "g_pVSSClient = %p, enable_vss = %d\n", g_pVSSClient, enable_vss);
    // capture state here, if client is backed up by multiple directors
@@ -1993,20 +2109,21 @@ static int restore_cmd(JCR *jcr)
    if (jcr->VSS) {
       if (g_pVSSClient->InitializeForRestore(jcr, vss_restore_init_callback,
             (WCHAR *)jcr->job_metadata)) {
    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++) {
          /* 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) {
             if (g_pVSSClient->GetWriterState(i) < 1) {
-               Jmsg(jcr, M_WARNING, 0, _("VSS Writer (PreRestore): %s\n"), g_pVSSClient->GetWriterInfo(i));
-               jcr->JobErrors++;
+               Jmsg(jcr, M_INFO, 0, _("VSS Writer (PreRestore): %s\n"), g_pVSSClient->GetWriterInfo(i));
+               //jcr->JobErrors++;
             }
          }
       } else {
             }
          }
       } else {
+/*
+   int fd = open("C:\\eric.xml", O_CREAT | O_WRONLY | O_TRUNC, 0777);
+   write(fd, (WCHAR *)jcr->job_metadata, wcslen((WCHAR *)jcr->job_metadata) * sizeof(WCHAR));
+   close(fd);
+*/
          berrno be;
          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
       }
          berrno be;
          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
       }
@@ -2037,23 +2154,24 @@ static int restore_cmd(JCR *jcr)
 #if defined(WIN32_VSS)
    /* STOP VSS ON WIN32 */
    /* tell vss to close the restore session */
 #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) {
    if (jcr->VSS) {
-      Dmsg0(0, "Really about to call CloseRestore\n");
+      generate_plugin_event(jcr, bEventVssBeforeCloseRestore);
+      Dmsg0(100, "Really about to call CloseRestore\n");
       if (g_pVSSClient->CloseRestore()) {
       if (g_pVSSClient->CloseRestore()) {
-         Dmsg0(0, "CloseRestore success\n");
+         Dmsg0(100, "CloseRestore success\n");
          /* 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) {
          /* 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));
          }
       }
       else
             }
             Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
          }
       }
       else
-         Dmsg1(0, "CloseRestore fail - %08x\n", errno);
+         Dmsg1(100, "CloseRestore fail - %08x\n", errno);
       V(vss_mutex);
    }
 #endif
       V(vss_mutex);
    }
 #endif
@@ -2077,6 +2195,10 @@ bail_out:
       ret = 0;     /* we stop here */
    }
 
       ret = 0;     /* we stop here */
    }
 
+   if (job_canceled(jcr)) {
+      ret = 0;     /* we stop here */
+   }
+
    return ret;
 }
 
    return ret;
 }