Exemplo n.º 1
0
/*
 * Get response from FD or SD to a command we
 * sent. Check that the response agrees with what we expect.
 *
 *  Returns: false on failure
 *           true  on success
 */
bool response(JCR *jcr, BSOCK *bs, char *resp, const char *cmd, e_prtmsg prtmsg)
{
   int n;

   if (is_bnet_error(bs)) {
      return false;
   }
   if ((n = bget_dirmsg(bs)) >= 0) {
      if (bstrcmp(bs->msg, resp)) {
         return true;
      }
      if (prtmsg == DISPLAY_ERROR) {
         Jmsg(jcr, M_FATAL, 0, _("Bad response to %s command: wanted %s, got %s\n"),
            cmd, resp, bs->msg);
      }
      return false;
   }
   Jmsg(jcr, M_FATAL, 0, _("Socket error on %s command: ERR=%s\n"),
         cmd, bnet_strerror(bs));
   return false;
}
Exemplo n.º 2
0
Arquivo: mac.c Projeto: AlD/bareos
/*
 * Get response from Storage daemon to a command we sent.
 * Check that the response is OK.
 *
 * Returns: false on failure
 *          true on success
 */
static bool response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
{
   if (sd->errors) {
      return false;
                  }
   if (bget_msg(sd) > 0) {
      Dmsg1(110, "<stored: %s", sd->msg);
      if (bstrcmp(sd->msg, resp)) {
         return true;
      }
   }
   if (job_canceled(jcr)) {
      return false;                   /* if canceled avoid useless error messages */
   }
   if (is_bnet_error(sd)) {
      Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
            cmd, bnet_strerror(sd));
   } else {
      Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
            cmd, resp, sd->msg);
   }
   return false;
}
Exemplo n.º 3
0
/*
 * This routine is called only during a Verify
 */
void get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId)
{
   BSOCK   *fd;
   int n, len;
   FILE_DBR fdbr;
   struct stat statf;                 /* file stat */
   struct stat statc;                 /* catalog stat */
   char buf[MAXSTRING];
   POOLMEM *fname = get_pool_memory(PM_MESSAGE);
   int do_Digest = CRYPTO_DIGEST_NONE;
   int32_t file_index = 0;

   memset(&fdbr, 0, sizeof(FILE_DBR));
   fd = jcr->file_bsock;
   fdbr.JobId = JobId;
   jcr->FileIndex = 0;

   Dmsg0(20, "bdird: waiting to receive file attributes\n");
   /*
    * Get Attributes and Signature from File daemon
    * We expect:
    *   FileIndex
    *   Stream
    *   Options or Digest (MD5/SHA1)
    *   Filename
    *   Attributes
    *   Link name  ???
    */
   while ((n=bget_dirmsg(fd)) >= 0 && !job_canceled(jcr)) {
      int stream;
      char *attr, *p, *fn;
      char Opts_Digest[MAXSTRING];        /* Verify Opts or MD5/SHA1 digest */

      if (job_canceled(jcr)) {
         return;
      }
      fname = check_pool_memory_size(fname, fd->msglen);
      jcr->fname = check_pool_memory_size(jcr->fname, fd->msglen);
      Dmsg1(200, "Atts+Digest=%s\n", fd->msg);
      if ((len = sscanf(fd->msg, "%ld %d %100s", &file_index, &stream,
            fname)) != 3) {
         Jmsg3(jcr, M_FATAL, 0, _("bird<filed: bad attributes, expected 3 fields got %d\n"
" mslen=%d msg=%s\n"), len, fd->msglen, fd->msg);
         return;
      }
      /*
       * We read the Options or Signature into fname
       *  to prevent overrun, now copy it to proper location.
       */
      bstrncpy(Opts_Digest, fname, sizeof(Opts_Digest));
      p = fd->msg;
      skip_nonspaces(&p);             /* skip FileIndex */
      skip_spaces(&p);
      skip_nonspaces(&p);             /* skip Stream */
      skip_spaces(&p);
      skip_nonspaces(&p);             /* skip Opts_Digest */
      p++;                            /* skip space */
      fn = fname;
      while (*p != 0) {
         *fn++ = *p++;                /* copy filename */
      }
      *fn = *p++;                     /* term filename and point to attribs */
      attr = p;
      /*
       * Got attributes stream, decode it
       */
      if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_UNIX_ATTRIBUTES_EX) {
         int32_t LinkFIf, LinkFIc;
         Dmsg2(400, "file_index=%d attr=%s\n", file_index, attr);
         jcr->JobFiles++;
         jcr->FileIndex = file_index;    /* remember attribute file_index */
         jcr->previous_jr.FileIndex = file_index;
         decode_stat(attr, &statf, &LinkFIf);  /* decode file stat packet */
         do_Digest = CRYPTO_DIGEST_NONE;
         jcr->fn_printed = false;
         pm_strcpy(jcr->fname, fname);  /* move filename into JCR */

         Dmsg2(040, "dird<filed: stream=%d %s\n", stream, jcr->fname);
         Dmsg1(020, "dird<filed: attr=%s\n", attr);

         /*
          * Find equivalent record in the database
          */
         fdbr.FileId = 0;
         if (!db_get_file_attributes_record(jcr, jcr->db, jcr->fname,
              &jcr->previous_jr, &fdbr)) {
            Jmsg(jcr, M_INFO, 0, _("New file: %s\n"), jcr->fname);
            Dmsg1(020, _("File not in catalog: %s\n"), jcr->fname);
            set_jcr_job_status(jcr, JS_Differences);
            continue;
         } else {
            /*
             * mark file record as visited by stuffing the
             * current JobId, which is unique, into the MarkId field.
             */
            db_mark_file_record(jcr, jcr->db, fdbr.FileId, jcr->JobId);
         }

         Dmsg3(400, "Found %s in catalog. inx=%d Opts=%s\n", jcr->fname,
            file_index, Opts_Digest);
         decode_stat(fdbr.LStat, &statc, &LinkFIc); /* decode catalog stat */
         /*
          * Loop over options supplied by user and verify the
          * fields he requests.
          */
         for (p=Opts_Digest; *p; p++) {
            char ed1[30], ed2[30];
            switch (*p) {
            case 'i':                /* compare INODEs */
               if (statc.st_ino != statf.st_ino) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_ino   differ. Cat: %s File: %s\n"),
                     edit_uint64((uint64_t)statc.st_ino, ed1),
                     edit_uint64((uint64_t)statf.st_ino, ed2));
                  set_jcr_job_status(jcr, JS_Differences);
               }
               break;
            case 'p':                /* permissions bits */
               if (statc.st_mode != statf.st_mode) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_mode  differ. Cat: %x File: %x\n"),
                     (uint32_t)statc.st_mode, (uint32_t)statf.st_mode);
                  set_jcr_job_status(jcr, JS_Differences);
               }
               break;
            case 'n':                /* number of links */
               if (statc.st_nlink != statf.st_nlink) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_nlink differ. Cat: %d File: %d\n"),
                     (uint32_t)statc.st_nlink, (uint32_t)statf.st_nlink);
                  set_jcr_job_status(jcr, JS_Differences);
               }
               break;
            case 'u':                /* user id */
               if (statc.st_uid != statf.st_uid) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_uid   differ. Cat: %u File: %u\n"),
                     (uint32_t)statc.st_uid, (uint32_t)statf.st_uid);
                  set_jcr_job_status(jcr, JS_Differences);
               }
               break;
            case 'g':                /* group id */
               if (statc.st_gid != statf.st_gid) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_gid   differ. Cat: %u File: %u\n"),
                     (uint32_t)statc.st_gid, (uint32_t)statf.st_gid);
                  set_jcr_job_status(jcr, JS_Differences);
               }
               break;
            case 's':                /* size */
               if (statc.st_size != statf.st_size) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_size  differ. Cat: %s File: %s\n"),
                     edit_uint64((uint64_t)statc.st_size, ed1),
                     edit_uint64((uint64_t)statf.st_size, ed2));
                  set_jcr_job_status(jcr, JS_Differences);
               }
               break;
            case 'a':                /* access time */
               if (statc.st_atime != statf.st_atime) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_atime differs\n"));
                  set_jcr_job_status(jcr, JS_Differences);
               }
               break;
            case 'm':
               if (statc.st_mtime != statf.st_mtime) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_mtime differs\n"));
                  set_jcr_job_status(jcr, JS_Differences);
               }
               break;
            case 'c':                /* ctime */
               if (statc.st_ctime != statf.st_ctime) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_ctime differs\n"));
                  set_jcr_job_status(jcr, JS_Differences);
               }
               break;
            case 'd':                /* file size decrease */
               if (statc.st_size > statf.st_size) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_size  decrease. Cat: %s File: %s\n"),
                     edit_uint64((uint64_t)statc.st_size, ed1),
                     edit_uint64((uint64_t)statf.st_size, ed2));
                  set_jcr_job_status(jcr, JS_Differences);
               }
               break;
            case '5':                /* compare MD5 */
               Dmsg1(500, "set Do_MD5 for %s\n", jcr->fname);
               do_Digest = CRYPTO_DIGEST_MD5;
               break;
            case '1':                 /* compare SHA1 */
               do_Digest = CRYPTO_DIGEST_SHA1;
               break;
            case ':':
            case 'V':
            default:
               break;
            }
         }
      /*
       * Got Digest Signature from Storage daemon
       *  It came across in the Opts_Digest field.
       */
      } else if (crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) {
         Dmsg2(400, "stream=Digest inx=%d Digest=%s\n", file_index, Opts_Digest);
         /*
          * When ever we get a digest it MUST have been
          * preceded by an attributes record, which sets attr_file_index
          */
         if (jcr->FileIndex != (uint32_t)file_index) {
            Jmsg2(jcr, M_FATAL, 0, _("MD5/SHA1 index %d not same as attributes %d\n"),
               file_index, jcr->FileIndex);
            return;
         }
         if (do_Digest != CRYPTO_DIGEST_NONE) {
            db_escape_string(jcr, jcr->db, buf, Opts_Digest, strlen(Opts_Digest));
            if (strcmp(buf, fdbr.Digest) != 0) {
               prt_fname(jcr);
               Jmsg(jcr, M_INFO, 0, _("      %s differs. File=%s Cat=%s\n"),
                    stream_to_ascii(stream), buf, fdbr.Digest);
               set_jcr_job_status(jcr, JS_Differences);
            }
            do_Digest = CRYPTO_DIGEST_NONE;
         }
      }
      jcr->JobFiles = file_index;
   }
   if (is_bnet_error(fd)) {
      berrno be;
      Jmsg2(jcr, M_FATAL, 0, _("bdird<filed: bad attributes from filed n=%d : %s\n"),
                        n, be.bstrerror());
      return;
   }

   /* Now find all the files that are missing -- i.e. all files in
    *  the database where the MarkId != current JobId
    */
   jcr->fn_printed = false;
   bsnprintf(buf, sizeof(buf),
      "SELECT Path.Path,Filename.Name FROM File,Path,Filename "
      "WHERE File.JobId=%d "
      "AND File.MarkId!=%d AND File.PathId=Path.PathId "
      "AND File.FilenameId=Filename.FilenameId",
         JobId, jcr->JobId);
   /* missing_handler is called for each file found */
   db_sql_query(jcr->db, buf, missing_handler, (void *)jcr);
   if (jcr->fn_printed) {
      set_jcr_job_status(jcr, JS_Differences);
   }
   free_pool_memory(fname);
}
Exemplo n.º 4
0
/*
 * Here we wait for the File daemon to signal termination,
 *   then we wait for the Storage daemon.  When both
 *   are done, we return the job status.
 * Also used by restore.c
 */
int wait_for_job_termination(JCR *jcr, int timeout)
{
   int32_t n = 0;
   BSOCK *fd = jcr->file_bsock;
   bool fd_ok = false;
   uint32_t JobFiles, JobErrors;
   uint32_t JobWarnings = 0;
   uint64_t ReadBytes = 0;
   uint64_t JobBytes = 0;
   int VSS = 0;
   int Encrypt = 0;
   btimer_t *tid=NULL;

   set_jcr_job_status(jcr, JS_Running);

   if (fd) {
      if (timeout) {
         tid = start_bsock_timer(fd, timeout); /* TODO: New timeout directive??? */
      }
      /* Wait for Client to terminate */
      while ((n = bget_dirmsg(fd)) >= 0) {
         if (!fd_ok && 
             (sscanf(fd->msg, EndJob, &jcr->FDJobStatus, &JobFiles,
                     &ReadBytes, &JobBytes, &JobErrors, &VSS, &Encrypt) == 7 ||
              sscanf(fd->msg, OldEndJob, &jcr->FDJobStatus, &JobFiles,
                     &ReadBytes, &JobBytes, &JobErrors) == 5)) {
            fd_ok = true;
            set_jcr_job_status(jcr, jcr->FDJobStatus);
            Dmsg1(100, "FDStatus=%c\n", (char)jcr->JobStatus);
         } else {
            Jmsg(jcr, M_WARNING, 0, _("Unexpected Client Job message: %s\n"),
                 fd->msg);
         }
         if (job_canceled(jcr)) {
            break;
         }
      }
      if (tid) {
         stop_bsock_timer(tid);
      }

      if (is_bnet_error(fd)) {
         Jmsg(jcr, M_FATAL, 0, _("Network error with FD during %s: ERR=%s\n"),
              job_type_to_str(jcr->get_JobType()), fd->bstrerror());
      }
      fd->signal(BNET_TERMINATE);   /* tell Client we are terminating */
   }

   /* Force cancel in SD if failing */
   if (job_canceled(jcr) || !fd_ok) {
      cancel_storage_daemon_job(jcr);
   }

   /* Note, the SD stores in jcr->JobFiles/ReadBytes/JobBytes/JobErrors */
   wait_for_storage_daemon_termination(jcr);

   /* Return values from FD */
   if (fd_ok) {
      jcr->JobFiles = JobFiles;
      jcr->JobErrors += JobErrors;       /* Keep total errors */
      jcr->ReadBytes = ReadBytes;
      jcr->JobBytes = JobBytes;
      jcr->JobWarnings = JobWarnings;
      jcr->VSS = VSS;
      jcr->Encrypt = Encrypt;
   } else {
      Jmsg(jcr, M_FATAL, 0, _("No Job status returned from FD.\n"));
   }

// Dmsg4(100, "fd_ok=%d FDJS=%d JS=%d SDJS=%d\n", fd_ok, jcr->FDJobStatus,
//   jcr->JobStatus, jcr->SDJobStatus);

   /* Return the first error status we find Dir, FD, or SD */
   if (!fd_ok || is_bnet_error(fd)) { /* if fd not set, that use !fd_ok */
      jcr->FDJobStatus = JS_ErrorTerminated;
   }
   if (jcr->JobStatus != JS_Terminated) {
      return jcr->JobStatus;
   }
   if (jcr->FDJobStatus != JS_Terminated) {
      return jcr->FDJobStatus;
   }
   return jcr->SDJobStatus;
}