]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/filed/job.c
Use dcr more in SD + int to bool conversions
[bacula/bacula] / bacula / src / filed / job.c
index dbc02531d4d82515fbe2f0b7d27a93518617b56f..09ea2129587a713dc7ab5a38bbe22bdf91dc39f3 100644 (file)
@@ -58,12 +58,13 @@ static int send_bootstrap_file(JCR *jcr);
 static int runbefore_cmd(JCR *jcr);
 static int runafter_cmd(JCR *jcr);
 static int run_cmd(JCR *jcr, char *cmd, const char *name);
+static void set_options(findFOPTS *fo, const char *opts);
 
 
 /* Exported functions */
 
 struct s_cmds {
-   char *cmd;
+   const char *cmd;
    int (*func)(JCR *);
 };
 
@@ -160,7 +161,8 @@ static char read_close[]   = "read close session %d\n";
  */
 void *handle_client_request(void *dirp)
 {
-   int i, found, quit;
+   int i; 
+   bool found, quit;
    JCR *jcr;
    BSOCK *dir = (BSOCK *)dirp;
 
@@ -177,7 +179,7 @@ void *handle_client_request(void *dirp)
 
    /**********FIXME******* add command handler error code */
 
-   for (quit=0; !quit;) {
+   for (quit=false; !quit;) {
 
       /* Read command */
       if (bnet_recv(dir) < 0) {
@@ -185,24 +187,25 @@ void *handle_client_request(void *dirp)
       }
       dir->msg[dir->msglen] = 0;
       Dmsg1(100, "<dird: %s", dir->msg);
-      found = FALSE;
+      found = false;
       for (i=0; cmds[i].cmd; i++) {
         if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) {
            if (!jcr->authenticated && cmds[i].func != hello_cmd) {
               bnet_fsend(dir, no_auth);
               break;
            }
-           found = TRUE;                /* indicate command found */
+           found = true;                /* indicate command found */
+            Dmsg1(100, "Executing %s command.\n", cmds[i].cmd);
            if (!cmds[i].func(jcr)) {    /* do command */
-              quit = TRUE;              /* error or fully terminated,  get out */
-               Dmsg0(20, "Command error or Job done.\n");
+              quit = true;              /* error or fully terminated,  get out */
+               Dmsg0(20, "Quit command loop due to command error or Job done.\n");
            }
            break;
         }
       }
       if (!found) {                  /* command not found */
         bnet_fsend(dir, errmsg);
-        quit = TRUE;
+        quit = true;
         break;
       }
    }
@@ -223,12 +226,15 @@ void *handle_client_request(void *dirp)
    FF_PKT *ff = (FF_PKT *)jcr->ff;
    findFILESET *fileset = ff->fileset;
    if (fileset) {
-      int i, j;
+      int i, j, k;
       /* Delete FileSet Include lists */
       for (i=0; i<fileset->include_list.size(); i++) {
         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);
+           for (k=0; k<fo->regex.size(); k++) {
+              regfree((regex_t *)fo->regex.get(k));
+           }
            fo->regex.destroy();
            fo->wild.destroy();
            fo->base.destroy();
@@ -272,7 +278,7 @@ static int hello_cmd(JCR *jcr)
       return 0;
    }
    Dmsg0(120, "OK Authenticate\n");
-   jcr->authenticated = TRUE;
+   jcr->authenticated = true;
    return 1;
 }
 
@@ -437,6 +443,11 @@ static int run_cmd(JCR *jcr, char *cmd, const char *name)
    ecmd = edit_job_codes(jcr, ecmd, cmd, "");
    bpipe = open_bpipe(ecmd, 0, "r");
    free_pool_memory(ecmd);
+   if (bpipe == NULL) {
+      Jmsg(jcr, M_FATAL, 0, _("%s could not execute\n"), name);
+      set_jcr_job_status(jcr, JS_FatalError);
+      return 0;
+   }
    while (fgets(line, sizeof(line), bpipe->rfd)) {
       Jmsg(jcr, M_INFO, 0, _("%s: %s"), name, line);
    }
@@ -585,7 +596,7 @@ static bool init_fileset(JCR *jcr)
    return true;
 }
 
-static findFOPTS *set_options(FF_PKT *ff)
+static findFOPTS *start_options(FF_PKT *ff)
 {
    int state = ff->fileset->state;
    findINCEXE *incexe = ff->fileset->incexe;
@@ -604,6 +615,61 @@ static findFOPTS *set_options(FF_PKT *ff)
 
 }
 
+/*
+ * Add fname to include/exclude fileset list. First check for
+ * | and < and if necessary perform command.
+ */
+static void add_file_to_fileset(JCR *jcr, const char *fname, findFILESET *fileset)
+{
+   char *p;
+   BPIPE *bpipe;
+   POOLMEM *fn;
+   FILE *ffd;
+   char buf[1000];
+   int stat;
+
+   p = (char *)fname;
+   switch (*p) {
+   case '|':
+      p++;                           /* skip over | */
+      fn = get_pool_memory(PM_FNAME);
+      fn = edit_job_codes(jcr, fn, p, "");
+      bpipe = open_bpipe(fn, 0, "r");
+      free_pool_memory(fn);
+      if (!bpipe) {
+         Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
+           p, strerror(errno));
+        return;
+      }
+      while (fgets(buf, sizeof(buf), bpipe->rfd)) {
+        strip_trailing_junk(buf);
+        fileset->incexe->name_list.append(bstrdup(buf));
+      }
+      if ((stat=close_bpipe(bpipe)) != 0) {
+         Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. RtnStat=%d ERR=%s\n"),
+           p, stat, strerror(errno));
+        return;
+      }
+      break;
+   case '<':
+      p++;                     /* skip over < */
+      if ((ffd = fopen(p, "r")) == NULL) {
+         Jmsg(jcr, M_FATAL, 0, _("Cannot open FileSet input file: %s. ERR=%s\n"),
+           p, strerror(errno));
+        return;
+      }
+      while (fgets(buf, sizeof(buf), ffd)) {
+        strip_trailing_junk(buf);
+        fileset->incexe->name_list.append(bstrdup(buf));
+      }
+      fclose(ffd);
+      break;
+   default:
+      fileset->incexe->name_list.append(bstrdup(fname));
+      break;
+   }
+}
+
    
 static void add_fileset(JCR *jcr, const char *item)
 {
@@ -612,6 +678,7 @@ static void add_fileset(JCR *jcr, const char *item)
    int state = fileset->state;
    findFOPTS *current_opts;
 
+   Dmsg1(100, "%s\n", item);
    int code = item[0];
    if (item[1] == ' ') {              /* If string follows */
       item += 2;                     /* point to string */
@@ -641,28 +708,41 @@ static void add_fileset(JCR *jcr, const char *item)
       state = state_none;
       break;
    case 'F':
-      /* File item */
+      /* File item to either include/include list */
       state = state_include;
-      fileset->incexe->name_list.append(bstrdup(item));
+      add_file_to_fileset(jcr, item, fileset);
       break;
    case 'R':
-      current_opts = set_options(ff);
-      current_opts->regex.append(bstrdup(item));
+      current_opts = start_options(ff);
+      regex_t *preg;
+      int rc;
+      char prbuf[500];
+      preg = (regex_t *)malloc(sizeof(regex_t));
+      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;
+      }
+      current_opts->regex.append(preg);
       state = state_options;
       break;
    case 'B':
-      current_opts = set_options(ff);
+      current_opts = start_options(ff);
       current_opts->base.append(bstrdup(item));
       state = state_options;
       break;
    case 'W':
-      current_opts = set_options(ff);
+      current_opts = start_options(ff);
       current_opts->wild.append(bstrdup(item));
       state = state_options;
       break;
    case 'O':   
-      current_opts = set_options(ff);
-      bstrncpy(current_opts->opts, item, MAX_FOPTS);
+      current_opts = start_options(ff);
+      set_options(current_opts, item);
       state = state_options;
       break;
    default:
@@ -684,7 +764,6 @@ static bool term_fileset(JCR *jcr)
       Dmsg0(400, "I\n");
       for (j=0; j<incexe->opts_list.size(); j++) {
         findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
-         Dmsg1(400, "O %s\n", fo->opts);
         for (k=0; k<fo->regex.size(); k++) {
             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
         }
@@ -704,7 +783,6 @@ static bool term_fileset(JCR *jcr)
       Dmsg0(400, "E\n");
       for (j=0; j<incexe->opts_list.size(); j++) {
         findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
-         Dmsg1(400, "O %s\n", fo->opts);
         for (k=0; k<fo->regex.size(); k++) {
             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
         }
@@ -719,12 +797,83 @@ static bool term_fileset(JCR *jcr)
          Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j));
       }
    }
-
-
    return ff->fileset->state != state_error;
 }
 
 
+/*
+ * As an optimization, we should do this during
+ *  "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)
+{
+   int j;
+   const char *p;
+
+   for (p=opts; *p; p++) {
+      switch (*p) {
+      case 'a':                 /* alway replace */
+      case '0':                 /* no option */
+        break;
+      case 'e':
+        fo->flags |= FO_EXCLUDE;
+        break;
+      case 'f':
+        fo->flags |= FO_MULTIFS;
+        break;
+      case 'h':                 /* no recursion */
+        fo->flags |= FO_NO_RECURSION;
+        break;
+      case 'M':                 /* MD5 */
+        fo->flags |= FO_MD5;
+        break;
+      case 'n':
+        fo->flags |= FO_NOREPLACE;
+        break;
+      case 'p':                 /* use portable data format */
+        fo->flags |= FO_PORTABLE;
+        break;
+      case 'r':                 /* read fifo */
+        fo->flags |= FO_READFIFO;
+        break;
+      case 'S':
+        fo->flags |= FO_SHA1;
+        break;
+      case 's':
+        fo->flags |= FO_SPARSE;
+        break;
+      case 'm':
+        fo->flags |= FO_MTIMEONLY;
+        break;
+      case 'k':
+        fo->flags |= FO_KEEPATIME;
+        break;
+      case 'V':                  /* verify options */
+        /* Copy Verify Options */
+         for (j=0; *p && *p != ':'; p++) {
+           fo->VerifyOpts[j] = *p;
+           if (j < (int)sizeof(fo->VerifyOpts) - 1) {
+              j++;
+           }
+        }
+        fo->VerifyOpts[j] = 0;
+        break;
+      case 'w':
+        fo->flags |= FO_IF_NEWER;
+        break;
+      case 'Z':                 /* gzip compression */
+        fo->flags |= FO_GZIP;
+         fo->GZIP_level = *++p - '0';
+         Dmsg1(200, "Compression level=%d\n", fo->GZIP_level);
+        break;
+      default:
+         Emsg1(M_ERROR, 0, "Unknown include/exclude option: %c\n", *p);
+        break;
+      }
+   }
+} 
+
 
 /*
  * Director is passing his Fileset   
@@ -885,7 +1034,7 @@ static int level_cmd(JCR *jcr)
         his_time = str_to_uint64(buf);
         rt = get_current_btime() - bt_start; /* compute round trip time */
         bt_adj -= his_time - bt_start - rt/2;
-         Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
+         Dmsg2(200, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
       }
 
       bt_adj = bt_adj / 8;           /* compute average time */
@@ -899,7 +1048,7 @@ static int level_cmd(JCR *jcr)
 
       Dmsg2(100, "adj = %d since_time=%d\n", (int)adj, (int)since_time);
       jcr->incremental = 1;          /* set incremental or decremental backup */
-      jcr->mtime = since_time;       /* set since time */
+      jcr->mtime = (time_t)since_time; /* set since time */
    } else {
       Jmsg1(jcr, M_FATAL, 0, "Unknown backup level: %s\n", level);
       free_memory(level);
@@ -961,11 +1110,14 @@ static int storage_cmd(JCR *jcr)
    Dmsg3(110, "Open storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port, enable_ssl);
    /* Open command communications with Storage daemon */
    /* Try to connect for 1 hour at 10 second intervals */
-   sd = bnet_connect(jcr, 10, me->SDConnectTimeout, _("Storage daemon"), 
+   sd = bnet_connect(jcr, 10, (int)me->SDConnectTimeout, _("Storage daemon"), 
                     jcr->stored_addr, NULL, stored_port, 1);
+   Dmsg0(110, "Connection OK to SD.\n");
    if (sd == NULL) {
       Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
          jcr->stored_addr, stored_port);
+      Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
+         jcr->stored_addr, stored_port);
       return 0;
    }
 
@@ -1047,6 +1199,7 @@ static int backup_cmd(JCR *jcr)
    if (!blast_data_to_storage_daemon(jcr, NULL)) {
       set_jcr_job_status(jcr, JS_ErrorTerminated);
       bnet_suppress_error_messages(sd, 1);
+      Dmsg0(110, "Error in blast_data.\n");
    } else {
       set_jcr_job_status(jcr, JS_Terminated);
       if (jcr->JobStatus != JS_Terminated) {
@@ -1092,10 +1245,10 @@ static int backup_cmd(JCR *jcr)
    }
 
 cleanup:
-
    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles, 
       edit_uint64(jcr->ReadBytes, ed1), 
       edit_uint64(jcr->JobBytes, ed2), jcr->Errors);   
+   Dmsg1(110, "End FD msg: %s\n", dir->msg);
 
    return 0;                         /* return and stop command loop */
 }
@@ -1386,7 +1539,7 @@ static int send_bootstrap_file(JCR *jcr)
    FILE *bs;
    char buf[2000];
    BSOCK *sd = jcr->store_bsock;
-   char *bootstrap = "bootstrap\n";
+   const char *bootstrap = "bootstrap\n";
    int stat = 0;
 
    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);