Пример #1
40
/*
 * Read Data and send to File Daemon
 *
 * Returns: false on failure
 *          true  on success
 */
bool do_read_data(JCR *jcr)
{
   BSOCK *fd = jcr->file_bsock;
   DCR *dcr = jcr->read_dcr;
   bool ok = true;

   Dmsg0(20, "Start read data.\n");

   if (!bnet_set_buffer_size(fd, dcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) {
      return false;
   }

   if (jcr->NumReadVolumes == 0) {
      Jmsg(jcr, M_FATAL, 0, _("No Volume names found for restore.\n"));
      fd->fsend(FD_error);
      return false;
   }

   Dmsg2(200, "Found %d volumes names to restore. First=%s\n",
         jcr->NumReadVolumes, jcr->VolList->VolumeName);

   /*
    * Ready device for reading
    */
   if (!acquire_device_for_read(dcr)) {
      fd->fsend(FD_error);
      return false;
   }

   /*
    * Let any SD plugin know now its time to setup the record translation infra.
    */
   if (generate_plugin_event(jcr, bsdEventSetupRecordTranslation, dcr) != bRC_OK) {
      jcr->setJobStatus(JS_ErrorTerminated);
      return false;
   }

   /*
    * Tell File daemon we will send data
    */
   fd->fsend(OK_data);
   jcr->sendJobStatus(JS_Running);
   ok = read_records(dcr, record_cb, mount_next_read_volume);

   /*
    * Send end of data to FD
    */
   fd->signal(BNET_EOD);

   if (!release_device(jcr->read_dcr)) {
      ok = false;
   }

   Dmsg0(30, "Done reading.\n");
   return ok;
}
Пример #2
11
/*
 *  Read Data and send to File Daemon
 *   Returns: false on failure
 *            true  on success
 */
bool do_read_data(JCR *jcr)
{
   BSOCK *fd = jcr->file_bsock;
   bool ok = true;
   DCR *dcr = jcr->read_dcr;

   Dmsg0(20, "Start read data.\n");

   if (!bnet_set_buffer_size(fd, dcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) {
      return false;
   }

   if (jcr->NumReadVolumes == 0) {
      Jmsg(jcr, M_FATAL, 0, _("No Volume names found for restore.\n"));
      fd->fsend(FD_error);
      return false;
   }

   Dmsg2(200, "Found %d volumes names to restore. First=%s\n", jcr->NumReadVolumes,
      jcr->VolList->VolumeName);

   /* Ready device for reading */
   if (!acquire_device_for_read(dcr)) {
      fd->fsend(FD_error);
      return false;
   }

   /* Tell File daemon we will send data */
   fd->fsend(OK_data);
   jcr->sendJobStatus(JS_Running);
   ok = read_records(dcr, record_cb, mount_next_read_volume);

   /* Send end of data to FD */
   fd->signal(BNET_EOD);

   if (!release_device(jcr->read_dcr)) {
      ok = false;
   }

   Dmsg0(30, "Done reading.\n");
   return ok;
}
Пример #3
0
/*
 * Execute a command from the UA
 */
bool do_a_dot_command(UAContext *ua)
{
   int i;
   int len;
   bool ok = false;
   bool found = false;
   BSOCK *user = ua->UA_sock;

   Dmsg1(1400, "Dot command: %s\n", user->msg);
   if (ua->argc == 0) {
      return false;
   }

   len = strlen(ua->argk[0]);
   if (len == 1) {
      if (ua->api) user->signal(BNET_CMD_BEGIN);
      if (ua->api) user->signal(BNET_CMD_OK);
      return true;                    /* no op */
   }
   for (i=0; i<comsize; i++) {     /* search for command */
      if (bstrncasecmp(ua->argk[0],  _(commands[i].key), len)) {
         /* Check if this command is authorized in RunScript */
         if (ua->runscript && !commands[i].use_in_rs) {
            ua->error_msg(_("Can't use %s command in a runscript"), ua->argk[0]);
            break;
         }
         bool gui = ua->gui;
         /* Check if command permitted, but "quit" is always OK */
         if (!bstrcmp(ua->argk[0], NT_(".quit")) &&
             !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
            break;
         }
         Dmsg1(100, "Cmd: %s\n", ua->cmd);
         ua->gui = true;
         if (ua->api) user->signal(BNET_CMD_BEGIN);
         ok = (*commands[i].func)(ua, ua->cmd);   /* go execute command */
         if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
         ua->gui = gui;
         found = true;
         break;
      }
   }
   if (!found) {
      ua->error_msg("%s%s", ua->argk[0], _(": is an invalid command.\n"));
      ok = false;
   }
   return ok;
}
Пример #4
0
/*
 * Cancel a running job on a storage daemon. Used by the interactive cancel
 * command to cancel a JobId on a Storage Daemon this can be used when the
 * Director already removed the Job and thinks it finished but the Storage
 * Daemon still thinks its active.
 */
bool cancel_storage_daemon_job(UAContext *ua, STORERES *store, char *JobId)
{
   BSOCK *sd;
   JCR *control_jcr;

   control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);

   control_jcr->res.wstore = store;
   if (!connect_to_storage_daemon(control_jcr, 10, me->SDConnectTimeout, true)) {
      ua->error_msg(_("Failed to connect to Storage daemon.\n"));
   }

   Dmsg0(200, "Connected to storage daemon\n");
   sd = control_jcr->store_bsock;
   sd->fsend("cancel Job=%s\n", JobId);
   while (sd->recv() >= 0) {
      ua->send_msg("%s", sd->msg);
   }
   sd->signal(BNET_TERMINATE);
   sd->close();
   control_jcr->store_bsock = NULL;

   free_jcr(control_jcr);

   return true;
}
Пример #5
0
static void do_client_cmd(UAContext *ua, CLIENTRES *client, const char *cmd)
{
   BSOCK *fd;

   /* Connect to File daemon */

   ua->jcr->res.client = client;
   /* Try to connect for 15 seconds */
   ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
      client->name(), client->address, client->FDport);
   if (!connect_to_file_daemon(ua->jcr, 1, 15, false, false)) {
      ua->error_msg(_("Failed to connect to Client.\n"));
      return;
   }
   Dmsg0(120, "Connected to file daemon\n");
   fd = ua->jcr->file_bsock;
   fd->fsend("%s", cmd);
   if (fd->recv() >= 0) {
      ua->send_msg("%s", fd->msg);
   }
   fd->signal(BNET_TERMINATE);
   fd->close();
   ua->jcr->file_bsock = NULL;
   return;
}
Пример #6
0
/*
 * resolve a host on a storage daemon
 */
bool do_storage_resolve(UAContext *ua, STORERES *store)
{
   BSOCK *sd;
   USTORERES lstore;

   lstore.store = store;
   pm_strcpy(lstore.store_source, _("unknown source"));
   set_wstorage(ua->jcr, &lstore);

   if (!(sd = open_sd_bsock(ua))) {
      return false;
   }

   for (int i = 1; i < ua->argc; i++) {
       if (!*ua->argk[i]) {
          continue;
       }

       sd->fsend("resolve %s", ua->argk[i]);
       while (sd->recv() >= 0) {
          ua->send_msg("%s", sd->msg);
       }
   }

   sd->signal(BNET_TERMINATE);
   sd->close();
   ua->jcr->store_bsock = NULL;

   return true;
}
Пример #7
0
/*
 * Run a File daemon Job -- File daemon already authorized
 *  Director sends us this command.
 *
 * Basic task here is:
 * - Read a command from the File daemon
 * - Execute it
 *
 */
void run_job(JCR *jcr)
{
   BSOCK *dir = jcr->dir_bsock;
   char ec1[30];

   dir->set_jcr(jcr);
   Dmsg1(120, "Start run Job=%s\n", jcr->Job);
   dir->fsend(Job_start, jcr->Job);
   jcr->start_time = time(NULL);
   jcr->run_time = jcr->start_time;
   jcr->sendJobStatus(JS_Running);

   do_fd_commands(jcr);

   jcr->end_time = time(NULL);
   dequeue_messages(jcr);             /* send any queued messages */
   jcr->setJobStatus(JS_Terminated);

   generate_plugin_event(jcr, bsdEventJobEnd);

   dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
              edit_uint64(jcr->JobBytes, ec1), jcr->JobErrors);
   dir->signal(BNET_EOD);             /* send EOD to Director daemon */

   free_plugins(jcr);                 /* release instantiated plugins */
}
Пример #8
0
/**
 * Save OSX specific resource forks and finder info.
 */
static inline bool save_rsrc_and_finder(b_save_ctx &bsctx)
{
   char flags[FOPTS_BYTES];
   int rsrc_stream;
   BSOCK *sd = bsctx.jcr->store_bsock;
   bool retval = false;

   if (bsctx.ff_pkt->hfsinfo.rsrclength > 0) {
      if (bopen_rsrc(&bsctx.ff_pkt->bfd, bsctx.ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
         bsctx.ff_pkt->ff_errno = errno;
         berrno be;
         Jmsg(bsctx.jcr, M_NOTSAVED, -1,
              _("     Cannot open resource fork for \"%s\": ERR=%s.\n"),
              bsctx.ff_pkt->fname, be.bstrerror());
         bsctx.jcr->JobErrors++;
         if (is_bopen(&bsctx.ff_pkt->bfd)) {
            bclose(&bsctx.ff_pkt->bfd);
         }
      } else {
         int status;

         memcpy(flags, bsctx.ff_pkt->flags, sizeof(flags));
         clear_bit(FO_COMPRESS, bsctx.ff_pkt->flags);
         clear_bit(FO_SPARSE, bsctx.ff_pkt->flags);
         clear_bit(FO_OFFSETS, bsctx.ff_pkt->flags);
         rsrc_stream = bit_is_set(FO_ENCRYPT, flags) ? STREAM_ENCRYPTED_MACOS_FORK_DATA :
                                                       STREAM_MACOS_FORK_DATA;

         status = send_data(bsctx.jcr, rsrc_stream, bsctx.ff_pkt,
                            bsctx.digest, bsctx.signing_digest);

         memcpy(bsctx.ff_pkt->flags, flags, sizeof(flags));
         bclose(&bsctx.ff_pkt->bfd);
         if (!status) {
            goto bail_out;
         }
      }
   }

   Dmsg1(300, "Saving Finder Info for \"%s\"\n", bsctx.ff_pkt->fname);
   sd->fsend("%ld %d 0", bsctx.jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES);
   Dmsg1(300, "filed>stored:header %s", sd->msg);
   pm_memcpy(sd->msg, bsctx.ff_pkt->hfsinfo.fndrinfo, 32);
   sd->msglen = 32;
   if (bsctx.digest) {
      crypto_digest_update(bsctx.digest, (uint8_t *)sd->msg, sd->msglen);
   }
   if (bsctx.signing_digest) {
      crypto_digest_update(bsctx.signing_digest, (uint8_t *)sd->msg, sd->msglen);
   }
   sd->send();
   sd->signal(BNET_EOD);

   retval = true;

bail_out:
   return retval;
}
Пример #9
0
/*
 * Terminate the signing digest and send it to the Storage daemon
 */
static inline bool terminate_signing_digest(b_save_ctx &bsctx)
{
   uint32_t size = 0;
   bool retval = false;
   SIGNATURE *signature = NULL;
   BSOCK *sd = bsctx.jcr->store_bsock;

   if ((signature = crypto_sign_new(bsctx.jcr)) == NULL) {
      Jmsg(bsctx.jcr, M_FATAL, 0, _("Failed to allocate memory for crypto signature.\n"));
      goto bail_out;
   }

   if (!crypto_sign_add_signer(signature, bsctx.signing_digest, bsctx.jcr->crypto.pki_keypair)) {
      Jmsg(bsctx.jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
      goto bail_out;
   }

   /*
    * Get signature size
    */
   if (!crypto_sign_encode(signature, NULL, &size)) {
      Jmsg(bsctx.jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
      goto bail_out;
   }

   /*
    * Grow the bsock buffer to fit our message if necessary
    */
   if (sizeof_pool_memory(sd->msg) < (int32_t)size) {
      sd->msg = realloc_pool_memory(sd->msg, size);
   }

   /*
    * Send our header
    */
   sd->fsend("%ld %ld 0", bsctx.jcr->JobFiles, STREAM_SIGNED_DIGEST);
   Dmsg1(300, "filed>stored:header %s", sd->msg);

   /*
    * Encode signature data
    */
   if (!crypto_sign_encode(signature, (uint8_t *)sd->msg, &size)) {
      Jmsg(bsctx.jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
      goto bail_out;
   }

   sd->msglen = size;
   sd->send();
   sd->signal(BNET_EOD);              /* end of checksum */
   retval = true;

bail_out:
   if (signature) {
      crypto_sign_free(signature);
   }
   return retval;
}
Пример #10
0
/*
 * Now talk to the SD and do what he says
 */
static void do_sd_commands(JCR *jcr)
{
   int i, status;
   bool found, quit;
   BSOCK *sd = jcr->store_bsock;

   sd->set_jcr(jcr);
   quit = false;
   while (!quit) {
      /*
       * Read command coming from the Storage daemon
       */
      status = sd->recv();
      if (is_bnet_stop(sd)) {         /* hardeof or error */
         break;                       /* connection terminated */
      }
      if (status <= 0) {
         continue;                    /* ignore signals and zero length msgs */
      }

      Dmsg1(110, "<stored: %s", sd->msg);
      found = false;
      for (i = 0; sd_cmds[i].cmd; i++) {
         if (bstrncmp(sd_cmds[i].cmd, sd->msg, strlen(sd_cmds[i].cmd))) {
            found = true;               /* indicate command found */
            jcr->errmsg[0] = 0;
            if (!sd_cmds[i].func(jcr)) {    /* do command */
               /*
                * Note sd->msg command may be destroyed by comm activity
                */
               if (!job_canceled(jcr)) {
                  if (jcr->errmsg[0]) {
                     Jmsg1(jcr, M_FATAL, 0, _("Command error with SD, hanging up. %s\n"),
                           jcr->errmsg);
                  } else {
                     Jmsg0(jcr, M_FATAL, 0, _("Command error with SD, hanging up.\n"));
                  }
                  jcr->setJobStatus(JS_ErrorTerminated);
               }
               quit = true;
            }
            break;
         }
      }

      if (!found) {                   /* command not found */
         if (!job_canceled(jcr)) {
            Jmsg1(jcr, M_FATAL, 0, _("SD command not found: %s\n"), sd->msg);
            Dmsg1(110, "<stored: Command not found: %s\n", sd->msg);
         }
         sd->fsend(serrmsg);
         break;
      }
   }
   sd->signal(BNET_TERMINATE);        /* signal to SD job is done */
}
Пример #11
0
/*
 * This is an information message that should probably be put
 *  into the status line of a GUI program.
 */
void UAContext::info_msg(const char *fmt, ...)
{
   BSOCK *bs = UA_sock;
   va_list arg_ptr;

   if (bs && api) bs->signal(BNET_INFO_MSG);
   va_start(arg_ptr, fmt);
   bmsg(this, fmt, arg_ptr);
   va_end(arg_ptr);
}
Пример #12
0
/*
 * Now talk to the FD and do what he says
 */
void do_fd_commands(JCR *jcr)
{
   int i;
   bool found, quit;
   BSOCK *fd = jcr->file_bsock;

   fd->set_jcr(jcr);
   for (quit=false; !quit;) {
      int status;

      /* Read command coming from the File daemon */
      status = fd->recv();
      if (is_bnet_stop(fd)) {         /* hardeof or error */
         break;                       /* connection terminated */
      }
      if (status <= 0) {
         continue;                    /* ignore signals and zero length msgs */
      }
      Dmsg1(110, "<filed: %s", fd->msg);
      found = false;
      for (i=0; fd_cmds[i].cmd; i++) {
         if (bstrncmp(fd_cmds[i].cmd, fd->msg, strlen(fd_cmds[i].cmd))) {
            found = true;               /* indicate command found */
            jcr->errmsg[0] = 0;
            if (!fd_cmds[i].func(jcr)) {    /* do command */
               /* Note fd->msg command may be destroyed by comm activity */
               if (!job_canceled(jcr)) {
                  if (jcr->errmsg[0]) {
                     Jmsg1(jcr, M_FATAL, 0, _("Command error with FD, hanging up. %s\n"),
                           jcr->errmsg);
                  } else {
                     Jmsg0(jcr, M_FATAL, 0, _("Command error with FD, hanging up.\n"));
                  }
                  jcr->setJobStatus(JS_ErrorTerminated);
               }
               quit = true;
            }
            break;
         }
      }
      if (!found) {                   /* command not found */
         if (!job_canceled(jcr)) {
            Jmsg1(jcr, M_FATAL, 0, _("FD command not found: %s\n"), fd->msg);
            Dmsg1(110, "<filed: Command not found: %s\n", fd->msg);
         }
         fd->fsend(ferrmsg);
         break;
      }
   }
   fd->signal(BNET_TERMINATE);        /* signal to FD job is done */
}
Пример #13
0
void cancel_storage_daemon_job(JCR *jcr)
{
   if (jcr->sd_canceled) { 
      return;                   /* cancel only once */
   }

   UAContext *ua = new_ua_context(jcr);
   JCR *control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);
   BSOCK *sd;

   ua->jcr = control_jcr;
   if (jcr->store_bsock) {
      if (!ua->jcr->wstorage) {
         if (jcr->rstorage) {
            copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); 
         } else {
            copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
         }
      } else {
         USTORE store;
         if (jcr->rstorage) {
            store.store = jcr->rstore;
         } else {
            store.store = jcr->wstore;
         }
         set_wstorage(ua->jcr, &store);
      }

      if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
         goto bail_out;
      }
      Dmsg0(200, "Connected to storage daemon\n");
      sd = ua->jcr->store_bsock;
      sd->fsend("cancel Job=%s\n", jcr->Job);
      while (sd->recv() >= 0) {
      }
      sd->signal(BNET_TERMINATE);
      sd->close();
      ua->jcr->store_bsock = NULL;
      jcr->sd_canceled = true;
      jcr->store_bsock->set_timed_out();
      jcr->store_bsock->set_terminated();
      sd_msg_thread_send_signal(jcr, TIMEOUT_SIGNAL);
      jcr->my_thread_send_signal(TIMEOUT_SIGNAL);
   }
bail_out:
   free_jcr(control_jcr);
   free_ua_context(ua);
}
Пример #14
0
/*
 * Cancel a running job on a storage daemon. The silent flag sets
 * if we need to be silent or not e.g. when doing an interactive cancel
 * or a system invoked one.
 */
bool cancel_storage_daemon_job(UAContext *ua, JCR *jcr, bool silent)
{
   BSOCK *sd;
   USTORERES store;

   if (!ua->jcr->wstorage) {
      if (jcr->rstorage) {
         copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
      } else {
         copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
      }
   } else {
      if (jcr->rstorage) {
         store.store = jcr->res.rstore;
      } else {
         store.store = jcr->res.wstore;
      }
      set_wstorage(ua->jcr, &store);
   }

   if (!connect_to_storage_daemon(ua->jcr, 10, me->SDConnectTimeout, true)) {
      if (!silent) {
         ua->error_msg(_("Failed to connect to Storage daemon.\n"));
      }
      return false;
   }
   Dmsg0(200, "Connected to storage daemon\n");
   sd = ua->jcr->store_bsock;
   sd->fsend(canceljobcmd, jcr->Job);
   while (sd->recv() >= 0) {
      if (!silent) {
         ua->send_msg("%s", sd->msg);
      }
   }
   sd->signal(BNET_TERMINATE);
   sd->close();
   delete ua->jcr->store_bsock;
   ua->jcr->store_bsock = NULL;
   if (silent) {
      jcr->sd_canceled = true;
   }
   jcr->store_bsock->set_timed_out();
   jcr->store_bsock->set_terminated();
   sd_msg_thread_send_signal(jcr, TIMEOUT_SIGNAL);
   jcr->my_thread_send_signal(TIMEOUT_SIGNAL);

   return true;
}
Пример #15
0
/*
 * Get the status of a remote storage daemon.
 */
void do_native_storage_status(UAContext *ua, STORERES *store, char *cmd)
{
   BSOCK *sd;
   USTORERES lstore;

   lstore.store = store;
   pm_strcpy(lstore.store_source, _("unknown source"));
   set_wstorage(ua->jcr, &lstore);

   /*
    * Try connecting for up to 15 seconds
    */
   if (!ua->api) {
      ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"),
                   store->name(), store->address, store->SDport);
   }

   if (!connect_to_storage_daemon(ua->jcr, 10, me->SDConnectTimeout, false)) {
      ua->send_msg(_("\nFailed to connect to Storage daemon %s.\n====\n"),
                   store->name());
      if (ua->jcr->store_bsock) {
         ua->jcr->store_bsock->close();
         delete ua->jcr->store_bsock;
         ua->jcr->store_bsock = NULL;
      }
      return;
   }

   Dmsg0(20, _("Connected to storage daemon\n"));
   sd = ua->jcr->store_bsock;
   if (cmd) {
      sd->fsend(dotstatuscmd, cmd);
   } else {
      sd->fsend(statuscmd);
   }

   while (sd->recv() >= 0) {
      ua->send_msg("%s", sd->msg);
   }

   sd->signal( BNET_TERMINATE);
   sd->close();
   delete ua->jcr->store_bsock;
   ua->jcr->store_bsock = NULL;

   return;
}
Пример #16
0
bool finish_cmd(JCR *jcr)
{
   BSOCK *dir = jcr->dir_bsock;
   char ec1[30];

   /*
    * See if the Job has a certain protocol. Some protocols allow the
    * finish cmd some do not (Native backup for example does NOT)
    */
   switch (jcr->getJobProtocol()) {
   case PT_NDMP:
      Dmsg1(200, "Finish_cmd: %s", jcr->dir_bsock->msg);

      jcr->end_time = time(NULL);
      dequeue_messages(jcr);             /* send any queued messages */
      jcr->setJobStatus(JS_Terminated);

      switch (jcr->getJobType()) {
      case JT_BACKUP:
         end_of_ndmp_backup(jcr);
         break;
      case JT_RESTORE:
         end_of_ndmp_restore(jcr);
         break;
      default:
         break;
      }

      generate_plugin_event(jcr, bsdEventJobEnd);

      dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
                 edit_uint64(jcr->JobBytes, ec1), jcr->JobErrors);
      dir->signal(BNET_EOD);             /* send EOD to Director daemon */

      free_plugins(jcr);                 /* release instantiated plugins */

      Dmsg2(800, "Done jid=%d %p\n", jcr->JobId, jcr);

      return false;                      /* Continue DIR session ? */
   default:
      Dmsg1(200, "Finish_cmd: %s", jcr->dir_bsock->msg);
      Jmsg2(jcr, M_FATAL, 0, _("Hey!!!! JobId %u Job %s tries to use finish cmd while not part of protocol.\n"),
            (uint32_t)jcr->JobId, jcr->Job);
      return false;                      /* Continue DIR session ? */
   }
}
Пример #17
0
/*
 *   Read Close session command
 *      Close the read session
 */
static bool read_close_session(JCR *jcr)
{
   BSOCK *fd = jcr->file_bsock;

   Dmsg1(120, "Read close session: %s\n", fd->msg);
   if (!jcr->session_opened) {
      fd->fsend(NOT_opened);
      return false;
   }
   /* Send final close msg to File daemon */
   fd->fsend(OK_close, jcr->JobStatus);
   Dmsg1(160, ">filed: %s\n", fd->msg);

   fd->signal(BNET_EOD);            /* send EOD to File daemon */

   jcr->session_opened = false;
   return true;
}
Пример #18
0
/*
 *   Append Close session command
 *      Close the append session and send back Statistics
 *         (need to fix statistics)
 */
static bool append_close_session(JCR *jcr)
{
   BSOCK *fd = jcr->file_bsock;

   Dmsg1(120, "<filed: %s", fd->msg);
   if (!jcr->session_opened) {
      pm_strcpy(jcr->errmsg, _("Attempt to close non-open session.\n"));
      fd->fsend(NOT_opened);
      return false;
   }
   /* Send final statistics to File daemon */
   fd->fsend(OK_close, jcr->JobStatus);
   Dmsg1(120, ">filed: %s", fd->msg);

   fd->signal(BNET_EOD);              /* send EOD to File daemon */

   jcr->session_opened = false;
   return true;
}
Пример #19
0
/*
 * Run a File daemon Job -- File daemon already authorized
 *  Director sends us this command.
 *
 * Basic task here is:
 * - Read a command from the File daemon
 * - Execute it
 *
 */
void run_job(JCR *jcr)
{
   BSOCK *dir = jcr->dir_bsock;
   char ec1[30];

   dir->set_jcr(jcr);
   Dmsg1(120, "Start run Job=%s\n", jcr->Job);
   dir->fsend(Job_start, jcr->Job);
   jcr->start_time = time(NULL);
   jcr->run_time = jcr->start_time;
   set_jcr_job_status(jcr, JS_Running);
   dir_send_job_status(jcr);          /* update director */
   do_fd_commands(jcr);
   jcr->end_time = time(NULL);
   dequeue_messages(jcr);             /* send any queued messages */
   set_jcr_job_status(jcr, JS_Terminated);
   generate_daemon_event(jcr, "JobEnd");
   dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
      edit_uint64(jcr->JobBytes, ec1), jcr->JobErrors);
   dir->signal(BNET_EOD);             /* send EOD to Director daemon */
   return;
}
Пример #20
0
/*
 * Terminate any digest and send it to Storage daemon
 */
static inline bool terminate_digest(b_save_ctx &bsctx)
{
   uint32_t size;
   bool retval = false;
   BSOCK *sd = bsctx.jcr->store_bsock;

   sd->fsend("%ld %d 0", bsctx.jcr->JobFiles, bsctx.digest_stream);
   Dmsg1(300, "filed>stored:header %s", sd->msg);

   size = CRYPTO_DIGEST_MAX_SIZE;

   /*
    * Grow the bsock buffer to fit our message if necessary
    */
   if (sizeof_pool_memory(sd->msg) < (int32_t)size) {
      sd->msg = realloc_pool_memory(sd->msg, size);
   }

   if (!crypto_digest_finalize(bsctx.digest, (uint8_t *)sd->msg, &size)) {
      Jmsg(bsctx.jcr, M_FATAL, 0, _("An error occurred finalizing signing the stream.\n"));
      goto bail_out;
   }

   /*
    * Keep the checksum if this file is a hardlink
    */
   if (bsctx.ff_pkt->linked) {
      ff_pkt_set_link_digest(bsctx.ff_pkt, bsctx.digest_stream, sd->msg, size);
   }

   sd->msglen = size;
   sd->send();
   sd->signal(BNET_EOD);              /* end of checksum */
   retval = true;

bail_out:
   return retval;
}
Пример #21
0
/**
 * Find all the requested files and send them
 * to the Storage daemon.
 *
 * Note, we normally carry on a one-way
 * conversation from this point on with the SD, simply blasting
 * data to him.  To properly know what is going on, we
 * also run a "heartbeat" monitor which reads the socket and
 * reacts accordingly (at the moment it has nothing to do
 * except echo the heartbeat to the Director).
 */
bool blast_data_to_storage_daemon(JCR *jcr, char *addr, crypto_cipher_t cipher)
{
   BSOCK *sd;
   bool ok = true;

   sd = jcr->store_bsock;

   jcr->setJobStatus(JS_Running);

   Dmsg1(300, "filed: opened data connection %d to stored\n", sd->m_fd);

   LockRes();
   CLIENTRES *client = (CLIENTRES *)GetNextRes(R_CLIENT, NULL);
   UnlockRes();
   uint32_t buf_size;
   if (client) {
      buf_size = client->max_network_buffer_size;
   } else {
      buf_size = 0;                   /* use default */
   }
   if (!sd->set_buffer_size(buf_size, BNET_SETBUF_WRITE)) {
      jcr->setJobStatus(JS_ErrorTerminated);
      Jmsg(jcr, M_FATAL, 0, _("Cannot set buffer size FD->SD.\n"));
      return false;
   }

   jcr->buf_size = sd->msglen;

   if (!adjust_compression_buffers(jcr)) {
      return false;
   }

   if (!crypto_session_start(jcr, cipher)) {
      return false;
   }

   set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime);

   /**
    * In accurate mode, we overload the find_one check function
    */
   if (jcr->accurate) {
      set_find_changed_function((FF_PKT *)jcr->ff, accurate_check_file);
   }

   start_heartbeat_monitor(jcr);

   if (have_acl) {
      jcr->acl_data = (acl_data_t *)malloc(sizeof(acl_data_t));
      memset(jcr->acl_data, 0, sizeof(acl_data_t));
      jcr->acl_data->u.build = (acl_build_data_t *)malloc(sizeof(acl_build_data_t));
      memset(jcr->acl_data->u.build, 0, sizeof(acl_build_data_t));
      jcr->acl_data->u.build->content = get_pool_memory(PM_MESSAGE);
   }

   if (have_xattr) {
      jcr->xattr_data = (xattr_data_t *)malloc(sizeof(xattr_data_t));
      memset(jcr->xattr_data, 0, sizeof(xattr_data_t));
      jcr->xattr_data->u.build = (xattr_build_data_t *)malloc(sizeof(xattr_build_data_t));
      memset(jcr->xattr_data->u.build, 0, sizeof(xattr_build_data_t));
      jcr->xattr_data->u.build->content = get_pool_memory(PM_MESSAGE);
   }

   /**
    * Subroutine save_file() is called for each file
    */
   if (!find_files(jcr, (FF_PKT *)jcr->ff, save_file, plugin_save)) {
      ok = false;                     /* error */
      jcr->setJobStatus(JS_ErrorTerminated);
   }

   if (have_acl && jcr->acl_data->u.build->nr_errors > 0) {
      Jmsg(jcr, M_WARNING, 0, _("Encountered %ld acl errors while doing backup\n"),
           jcr->acl_data->u.build->nr_errors);
   }
   if (have_xattr && jcr->xattr_data->u.build->nr_errors > 0) {
      Jmsg(jcr, M_WARNING, 0, _("Encountered %ld xattr errors while doing backup\n"),
           jcr->xattr_data->u.build->nr_errors);
   }

   close_vss_backup_session(jcr);

   accurate_finish(jcr);              /* send deleted or base file list to SD */

   stop_heartbeat_monitor(jcr);

   sd->signal(BNET_EOD);            /* end of sending data */

   if (have_acl && jcr->acl_data) {
      free_pool_memory(jcr->acl_data->u.build->content);
      free(jcr->acl_data->u.build);
      free(jcr->acl_data);
      jcr->acl_data = NULL;
   }

   if (have_xattr && jcr->xattr_data) {
      free_pool_memory(jcr->xattr_data->u.build->content);
      free(jcr->xattr_data->u.build);
      free(jcr->xattr_data);
      jcr->xattr_data = NULL;
   }

   if (jcr->big_buf) {
      free(jcr->big_buf);
      jcr->big_buf = NULL;
   }

   cleanup_compression(jcr);
   crypto_session_end(jcr);

   Dmsg1(100, "end blast_data ok=%d\n", ok);
   return ok;
}
Пример #22
0
/**
 * Called here by find() for each file included.
 *   This is a callback. The original is find_files() above.
 *
 *  Send the file and its data to the Storage daemon.
 *
 *  Returns: 1 if OK
 *           0 if error
 *          -1 to ignore file/directory (not used here)
 */
int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
{
   bool do_read = false;
   bool plugin_started = false;
   bool do_plugin_set = false;
   int status, data_stream;
   int rtnstat = 0;
   b_save_ctx bsctx;
   bool has_file_data = false;
   struct save_pkt sp;          /* use by option plugin */
   BSOCK *sd = jcr->store_bsock;

   if (jcr->is_canceled() || jcr->is_incomplete()) {
      return 0;
   }

   jcr->num_files_examined++;         /* bump total file count */

   switch (ff_pkt->type) {
   case FT_LNKSAVED:                  /* Hard linked, file already saved */
      Dmsg2(130, "FT_LNKSAVED hard link: %s => %s\n", ff_pkt->fname, ff_pkt->link);
      break;
   case FT_REGE:
      Dmsg1(130, "FT_REGE saving: %s\n", ff_pkt->fname);
      has_file_data = true;
      break;
   case FT_REG:
      Dmsg1(130, "FT_REG saving: %s\n", ff_pkt->fname);
      has_file_data = true;
      break;
   case FT_LNK:
      Dmsg2(130, "FT_LNK saving: %s -> %s\n", ff_pkt->fname, ff_pkt->link);
      break;
   case FT_RESTORE_FIRST:
      Dmsg1(100, "FT_RESTORE_FIRST saving: %s\n", ff_pkt->fname);
      break;
   case FT_PLUGIN_CONFIG:
      Dmsg1(100, "FT_PLUGIN_CONFIG saving: %s\n", ff_pkt->fname);
      break;
   case FT_DIRBEGIN:
      jcr->num_files_examined--;      /* correct file count */
      return 1;                       /* not used */
   case FT_NORECURSE:
      Jmsg(jcr, M_INFO, 1, _("     Recursion turned off. Will not descend from %s into %s\n"),
           ff_pkt->top_fname, ff_pkt->fname);
      ff_pkt->type = FT_DIREND;       /* Backup only the directory entry */
      break;
   case FT_NOFSCHG:
      /* Suppress message for /dev filesystems */
      if (!is_in_fileset(ff_pkt)) {
         Jmsg(jcr, M_INFO, 1, _("     %s is a different filesystem. Will not descend from %s into it.\n"),
              ff_pkt->fname, ff_pkt->top_fname);
      }
      ff_pkt->type = FT_DIREND;       /* Backup only the directory entry */
      break;
   case FT_INVALIDFS:
      Jmsg(jcr, M_INFO, 1, _("     Disallowed filesystem. Will not descend from %s into %s\n"),
           ff_pkt->top_fname, ff_pkt->fname);
      ff_pkt->type = FT_DIREND;       /* Backup only the directory entry */
      break;
   case FT_INVALIDDT:
      Jmsg(jcr, M_INFO, 1, _("     Disallowed drive type. Will not descend into %s\n"),
           ff_pkt->fname);
      break;
   case FT_REPARSE:
   case FT_JUNCTION:
   case FT_DIREND:
      Dmsg1(130, "FT_DIREND: %s\n", ff_pkt->link);
      break;
   case FT_SPEC:
      Dmsg1(130, "FT_SPEC saving: %s\n", ff_pkt->fname);
      if (S_ISSOCK(ff_pkt->statp.st_mode)) {
        Jmsg(jcr, M_SKIPPED, 1, _("     Socket file skipped: %s\n"), ff_pkt->fname);
        return 1;
      }
      break;
   case FT_RAW:
      Dmsg1(130, "FT_RAW saving: %s\n", ff_pkt->fname);
      has_file_data = true;
      break;
   case FT_FIFO:
      Dmsg1(130, "FT_FIFO saving: %s\n", ff_pkt->fname);
      break;
   case FT_NOACCESS: {
      berrno be;
      Jmsg(jcr, M_NOTSAVED, 0, _("     Could not access \"%s\": ERR=%s\n"),
           ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
      jcr->JobErrors++;
      return 1;
   }
   case FT_NOFOLLOW: {
      berrno be;
      Jmsg(jcr, M_NOTSAVED, 0, _("     Could not follow link \"%s\": ERR=%s\n"),
           ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
      jcr->JobErrors++;
      return 1;
   }
   case FT_NOSTAT: {
      berrno be;
      Jmsg(jcr, M_NOTSAVED, 0, _("     Could not stat \"%s\": ERR=%s\n"),
           ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
      jcr->JobErrors++;
      return 1;
   }
   case FT_DIRNOCHG:
   case FT_NOCHG:
      Jmsg(jcr, M_SKIPPED, 1, _("     Unchanged file skipped: %s\n"), ff_pkt->fname);
      return 1;
   case FT_ISARCH:
      Jmsg(jcr, M_NOTSAVED, 0, _("     Archive file not saved: %s\n"), ff_pkt->fname);
      return 1;
   case FT_NOOPEN: {
      berrno be;
      Jmsg(jcr, M_NOTSAVED, 0, _("     Could not open directory \"%s\": ERR=%s\n"),
           ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
      jcr->JobErrors++;
      return 1;
   }
   case FT_DELETED:
      Dmsg1(130, "FT_DELETED: %s\n", ff_pkt->fname);
      break;
   default:
      Jmsg(jcr, M_NOTSAVED, 0,  _("     Unknown file type %d; not saved: %s\n"),
           ff_pkt->type, ff_pkt->fname);
      jcr->JobErrors++;
      return 1;
   }

   Dmsg1(130, "filed: sending %s to stored\n", ff_pkt->fname);

   /*
    * Setup backup signing context.
    */
   memset(&bsctx, 0, sizeof(b_save_ctx));
   bsctx.digest_stream = STREAM_NONE;
   bsctx.jcr = jcr;
   bsctx.ff_pkt = ff_pkt;

   /*
    * Digests and encryption are only useful if there's file data
    */
   if (has_file_data) {
      if (!setup_encryption_digests(bsctx)) {
         goto good_rtn;
      }
   }

   /*
    * Initialize the file descriptor we use for data and other streams.
    */
   binit(&ff_pkt->bfd);
   if (bit_is_set(FO_PORTABLE, ff_pkt->flags)) {
      set_portable_backup(&ff_pkt->bfd); /* disable Win32 BackupRead() */
   }

   /*
    * Option and cmd plugin are not compatible together
    */
   if (ff_pkt->cmd_plugin) {
      do_plugin_set = true;
   } else if (ff_pkt->opt_plugin) {
      /*
       * Ask the option plugin what to do with this file
       */
      switch (plugin_option_handle_file(jcr, ff_pkt, &sp)) {
      case bRC_OK:
         Dmsg2(10, "Option plugin %s will be used to backup %s\n", ff_pkt->plugin, ff_pkt->fname);
         jcr->opt_plugin = true;
         jcr->plugin_sp = &sp;
         plugin_update_ff_pkt(ff_pkt, &sp);
         do_plugin_set = true;
         break;
      case bRC_Skip:
         Dmsg2(10, "Option plugin %s decided to skip %s\n", ff_pkt->plugin, ff_pkt->fname);
         goto good_rtn;
      case bRC_Core:
         Dmsg2(10, "Option plugin %s decided to let bareos handle %s\n", ff_pkt->plugin, ff_pkt->fname);
         break;
      default:
         goto bail_out;
      }
   }

   if (do_plugin_set) {
      /*
       * Tell bfile that it needs to call plugin
       */
      if (!set_cmd_plugin(&ff_pkt->bfd, jcr)) {
         goto bail_out;
      }
      send_plugin_name(jcr, sd, true);      /* signal start of plugin data */
      plugin_started = true;
   }

   /*
    * Send attributes -- must be done after binit()
    */
   if (!encode_and_send_attributes(jcr, ff_pkt, data_stream)) {
      goto bail_out;
   }

   /*
    * Meta data only for restore object
    */
   if (IS_FT_OBJECT(ff_pkt->type)) {
      goto good_rtn;
   }

   /*
    * Meta data only for deleted files
    */
   if (ff_pkt->type == FT_DELETED) {
      goto good_rtn;
   }

   /*
    * Set up the encryption context and send the session data to the SD
    */
   if (has_file_data && jcr->crypto.pki_encrypt) {
      if (!crypto_session_send(jcr, sd)) {
         goto bail_out;
      }
   }

   /*
    * For a command plugin use the setting from the plugins savepkt no_read field
    * which is saved in the ff_pkt->no_read variable. do_read is the inverted
    * value of this variable as no_read == TRUE means do_read == FALSE
    */
   if (ff_pkt->cmd_plugin) {
      do_read = !ff_pkt->no_read;
   } else {
      /*
       * Open any file with data that we intend to save, then save it.
       *
       * Note, if is_win32_backup, we must open the Directory so that
       * the BackupRead will save its permissions and ownership streams.
       */
      if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode)) {
#ifdef HAVE_WIN32
         do_read = !is_portable_backup(&ff_pkt->bfd) || ff_pkt->statp.st_size > 0;
#else
         do_read = ff_pkt->statp.st_size > 0;
#endif
      } else if (ff_pkt->type == FT_RAW ||
                 ff_pkt->type == FT_FIFO ||
                 ff_pkt->type == FT_REPARSE ||
                 ff_pkt->type == FT_JUNCTION ||
                (!is_portable_backup(&ff_pkt->bfd) &&
                 ff_pkt->type == FT_DIREND)) {
         do_read = true;
      }
   }

   Dmsg2(150, "type=%d do_read=%d\n", ff_pkt->type, do_read);
   if (do_read) {
      btimer_t *tid;
      int noatime;

      if (ff_pkt->type == FT_FIFO) {
         tid = start_thread_timer(jcr, pthread_self(), 60);
      } else {
         tid = NULL;
      }

      noatime = bit_is_set(FO_NOATIME, ff_pkt->flags) ? O_NOATIME : 0;
      ff_pkt->bfd.reparse_point = (ff_pkt->type == FT_REPARSE ||
                                   ff_pkt->type == FT_JUNCTION);

      if (bopen(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY | noatime, 0, ff_pkt->statp.st_rdev) < 0) {
         ff_pkt->ff_errno = errno;
         berrno be;
         Jmsg(jcr, M_NOTSAVED, 0,
              _("     Cannot open \"%s\": ERR=%s.\n"),
              ff_pkt->fname, be.bstrerror());
         jcr->JobErrors++;
         if (tid) {
            stop_thread_timer(tid);
            tid = NULL;
         }
         goto good_rtn;
      }

      if (tid) {
         stop_thread_timer(tid);
         tid = NULL;
      }

      status = send_data(jcr, data_stream, ff_pkt, bsctx.digest, bsctx.signing_digest);

      if (bit_is_set(FO_CHKCHANGES, ff_pkt->flags)) {
         has_file_changed(jcr, ff_pkt);
      }

      bclose(&ff_pkt->bfd);

      if (!status) {
         goto bail_out;
      }
   }

   if (have_darwin_os) {
      /*
       * Regular files can have resource forks and Finder Info
       */
      if (ff_pkt->type != FT_LNKSAVED &&
         (S_ISREG(ff_pkt->statp.st_mode) &&
          bit_is_set(FO_HFSPLUS, ff_pkt->flags))) {
         if (!save_rsrc_and_finder(bsctx)) {
            goto bail_out;
         }
      }
   }

   /*
    * Save ACLs when requested and available for anything not being a symlink.
    */
   if (have_acl) {
      if (bit_is_set(FO_ACL, ff_pkt->flags) && ff_pkt->type != FT_LNK) {
         if (!do_backup_acl(jcr, ff_pkt)) {
            goto bail_out;
         }
      }
   }

   /*
    * Save Extended Attributes when requested and available for all files.
    */
   if (have_xattr) {
      if (bit_is_set(FO_XATTR, ff_pkt->flags)) {
         if (!do_backup_xattr(jcr, ff_pkt)) {
            goto bail_out;
         }
      }
   }

   /*
    * Terminate the signing digest and send it to the Storage daemon
    */
   if (bsctx.signing_digest) {
      if (!terminate_signing_digest(bsctx)) {
         goto bail_out;
      }
   }

   /*
    * Terminate any digest and send it to Storage daemon
    */
   if (bsctx.digest) {
      if (!terminate_digest(bsctx)) {
         goto bail_out;
      }
   }

   /*
    * Check if original file has a digest, and send it
    */
   if (ff_pkt->type == FT_LNKSAVED && ff_pkt->digest) {
      Dmsg2(300, "Link %s digest %d\n", ff_pkt->fname, ff_pkt->digest_len);
      sd->fsend("%ld %d 0", jcr->JobFiles, ff_pkt->digest_stream);

      sd->msg = check_pool_memory_size(sd->msg, ff_pkt->digest_len);
      memcpy(sd->msg, ff_pkt->digest, ff_pkt->digest_len);
      sd->msglen = ff_pkt->digest_len;
      sd->send();

      sd->signal(BNET_EOD);              /* end of hardlink record */
   }

good_rtn:
   rtnstat = jcr->is_canceled() ? 0 : 1; /* good return if not canceled */

bail_out:
   if (jcr->is_incomplete() || jcr->is_canceled()) {
      rtnstat = 0;
   }
   if (plugin_started) {
      send_plugin_name(jcr, sd, false); /* signal end of plugin data */
   }
   if (ff_pkt->opt_plugin) {
      jcr->plugin_sp = NULL;            /* sp is local to this function */
      jcr->opt_plugin = false;
   }
   if (bsctx.digest) {
      crypto_digest_free(bsctx.digest);
   }
   if (bsctx.signing_digest) {
      crypto_digest_free(bsctx.signing_digest);
   }

   return rtnstat;
}
Пример #23
0
/*
 * Run a Storage daemon replicate Job -- Wait for remote Storage daemon
 * to connect and authenticate it we then will get a wakeup sign using
 * the job_start_wait conditional
 *
 * Director sends us this command.
 *
 * Basic task here is:
 * - Read a command from the Storage daemon
 * - Execute it
 */
bool do_listen_run(JCR *jcr)
{
   char ec1[30];
   int errstat = 0;
   struct timeval tv;
   struct timezone tz;
   struct timespec timeout;
   BSOCK *dir = jcr->dir_bsock;

   jcr->sendJobStatus(JS_WaitSD);          /* wait for SD to connect */

   gettimeofday(&tv, &tz);
   timeout.tv_nsec = tv.tv_usec * 1000;
   timeout.tv_sec = tv.tv_sec + me->client_wait;

   Dmsg3(50, "%s waiting %d sec for SD to contact SD key=%s\n",
         jcr->Job, (int)(timeout.tv_sec-time(NULL)), jcr->sd_auth_key);
   Dmsg2(800, "Wait SD for jid=%d %p\n", jcr->JobId, jcr);

   /*
    * Wait for the Storage daemon to contact us to start the Job,
    * when he does, we will be released, unless the 30 minutes expires.
    */
   P(mutex);
   while (!jcr->authenticated && !job_canceled(jcr)) {
      errstat = pthread_cond_timedwait(&jcr->job_start_wait, &mutex, &timeout);
      if (errstat == ETIMEDOUT || errstat == EINVAL || errstat == EPERM) {
         break;
      }
      Dmsg1(800, "=== Auth cond errstat=%d\n", errstat);
   }
   Dmsg3(50, "Auth=%d canceled=%d errstat=%d\n", jcr->authenticated,
         job_canceled(jcr), errstat);
   V(mutex);
   Dmsg2(800, "Auth fail or cancel for jid=%d %p\n", jcr->JobId, jcr);

   Dmsg1(120, "Start run Job=%s\n", jcr->Job);

   dir->fsend(Job_start, jcr->Job);
   jcr->start_time = time(NULL);
   jcr->run_time = jcr->start_time;
   jcr->sendJobStatus(JS_Running);

   /*
    * See if we need to limit the inbound bandwidth.
    */
   if (me->max_bandwidth_per_job && jcr->store_bsock) {
      jcr->store_bsock->set_bwlimit(me->max_bandwidth_per_job);
      if (me->allow_bw_bursting) {
         jcr->store_bsock->set_bwlimit_bursting();
      }
   }

   do_sd_commands(jcr);

   jcr->end_time = time(NULL);
   dequeue_messages(jcr);             /* send any queued messages */
   jcr->setJobStatus(JS_Terminated);

   generate_plugin_event(jcr, bsdEventJobEnd);

   dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
              edit_uint64(jcr->JobBytes, ec1), jcr->JobErrors);

   dir->signal(BNET_EOD);             /* send EOD to Director daemon */

   free_plugins(jcr);                 /* release instantiated plugins */

   /*
    * After a listen cmd we are done e.g. return false.
    */
   return false;
}
Пример #24
0
Файл: mac.c Проект: AlD/bareos
/*
 * Called here for each record from read_records()
 * This function is used when we do a external clone of a Job e.g.
 * this SD is the reading SD. And a remote SD is the writing SD.
 *
 * Returns: true if OK
 *           false if error
 */
static bool clone_record_to_remote_sd(DCR *dcr, DEV_RECORD *rec)
{
   POOLMEM *msgsave;
   JCR *jcr = dcr->jcr;
   char buf1[100], buf2[100];
   BSOCK *sd = jcr->store_bsock;
   bool send_eod, send_header;

#ifdef xxx
   Dmsg5(000, "on entry     JobId=%d FI=%s SessId=%d Strm=%s len=%d\n",
         jcr->JobId, FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
         stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);
#endif

   /*
    * If label discard it
    */
   if (rec->FileIndex < 0) {
      return true;
   }

   /*
    * See if this is the first record being processed.
    */
   if (rec->last_FileIndex == 0) {
      /*
       * Initialize the last counters so we can compare
       * things in the next run through here.
       */
      rec->last_VolSessionId = rec->VolSessionId;
      rec->last_VolSessionTime = rec->VolSessionTime;
      rec->last_FileIndex = rec->FileIndex;
      rec->last_Stream = rec->Stream;
      jcr->JobFiles = 1;

      /*
       * Need to send both a new header only.
       */
      send_eod = false;
      send_header = true;
   } else {
      /*
       * See if we are changing file or stream type.
       */
      if (rec->VolSessionId != rec->last_VolSessionId ||
          rec->VolSessionTime != rec->last_VolSessionTime ||
          rec->FileIndex != rec->last_FileIndex ||
          rec->Stream != rec->last_Stream) {
         /*
          * See if we are changing the FileIndex e.g.
          * start processing the next file in the backup stream.
          */
         if (rec->FileIndex != rec->last_FileIndex) {
            jcr->JobFiles++;
         }

         /*
          * Keep track of the new state.
          */
         rec->last_VolSessionId = rec->VolSessionId;
         rec->last_VolSessionTime = rec->VolSessionTime;
         rec->last_FileIndex = rec->FileIndex;
         rec->last_Stream = rec->Stream;

         /*
          * Need to send both a EOD and a new header.
          */
         send_eod = true;
         send_header = true;
      } else {
         send_eod = false;
         send_header = false;
      }
   }

   /*
    * Send a EOD when needed.
    */
   if (send_eod) {
      if (!sd->signal(BNET_EOD)) { /* indicate end of file data */
         if (!jcr->is_job_canceled()) {
            Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
                  sd->bstrerror());
         }
         return false;
      }
   }

   /*
    * Send a header when needed.
    */
   if (send_header) {
      if (!sd->fsend("%ld %d 0", rec->FileIndex, rec->Stream)) {
         if (!jcr->is_job_canceled()) {
            Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
                  sd->bstrerror());
         }
         return false;
      }
   }

   /*
    * Send the record data.
    * We don't want to copy the data from the record to the socket structure
    * so we save the original msg pointer and use the record data pointer for
    * sending and restore the original msg pointer when done.
    */
   msgsave = sd->msg;
   sd->msg = rec->data;
   sd->msglen = rec->data_len;

   if (!sd->send()) {
      sd->msg = msgsave;
      sd->msglen = 0;
      if (!jcr->is_job_canceled()) {
         Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
               sd->bstrerror());
      }
      return false;
   }

   jcr->JobBytes += sd->msglen;
   sd->msg = msgsave;

   Dmsg5(500, "wrote_record JobId=%d FI=%s SessId=%d Strm=%s len=%d\n",
         jcr->JobId, FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
         stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);

   return true;
}
Пример #25
0
bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream)
{
   BSOCK *sd = jcr->store_bsock;
   POOL_MEM attribs(PM_NAME),
            attribsExBuf(PM_NAME);
   char *attribsEx = NULL;
   int attr_stream;
   int comp_len;
   bool status;
   int hangup = get_hangup();
#ifdef FD_NO_SEND_TEST
   return true;
#endif

   Dmsg1(300, "encode_and_send_attrs fname=%s\n", ff_pkt->fname);
   /** Find what data stream we will use, then encode the attributes */
   if ((data_stream = select_data_stream(ff_pkt, me->compatible)) == STREAM_NONE) {
      /* This should not happen */
      Jmsg0(jcr, M_FATAL, 0, _("Invalid file flags, no supported data stream type.\n"));
      return false;
   }
   encode_stat(attribs.c_str(), &ff_pkt->statp, sizeof(ff_pkt->statp), ff_pkt->LinkFI, data_stream);

   /** Now possibly extend the attributes */
   if (IS_FT_OBJECT(ff_pkt->type)) {
      attr_stream = STREAM_RESTORE_OBJECT;
   } else {
      attribsEx = attribsExBuf.c_str();
      attr_stream = encode_attribsEx(jcr, attribsEx, ff_pkt);
   }

   Dmsg3(300, "File %s\nattribs=%s\nattribsEx=%s\n", ff_pkt->fname, attribs.c_str(), attribsEx);

   jcr->lock();
   jcr->JobFiles++;                    /* increment number of files sent */
   ff_pkt->FileIndex = jcr->JobFiles;  /* return FileIndex */
   pm_strcpy(jcr->last_fname, ff_pkt->fname);
   jcr->unlock();

   /*
    * Debug code: check if we must hangup
    */
   if (hangup && (jcr->JobFiles > (uint32_t)hangup)) {
      jcr->setJobStatus(JS_Incomplete);
      Jmsg1(jcr, M_FATAL, 0, "Debug hangup requested after %d files.\n", hangup);
      set_hangup(0);
      return false;
   }

   /**
    * Send Attributes header to Storage daemon
    *    <file-index> <stream> <info>
    */
   if (!sd->fsend("%ld %d 0", jcr->JobFiles, attr_stream)) {
      if (!jcr->is_canceled() && !jcr->is_incomplete()) {
         Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror());
      }
      return false;
   }
   Dmsg1(300, ">stored: attrhdr %s", sd->msg);

   /**
    * Send file attributes to Storage daemon
    *   File_index
    *   File type
    *   Filename (full path)
    *   Encoded attributes
    *   Link name (if type==FT_LNK or FT_LNKSAVED)
    *   Encoded extended-attributes (for Win32)
    *   Delta Sequence Number
    *
    * or send Restore Object to Storage daemon
    *   File_index
    *   File_type
    *   Object_index
    *   Object_len  (possibly compressed)
    *   Object_full_len (not compressed)
    *   Object_compression
    *   Plugin_name
    *   Object_name
    *   Binary Object data
    *
    * For a directory, link is the same as fname, but with trailing
    * slash. For a linked file, link is the link.
    */
   if (!IS_FT_OBJECT(ff_pkt->type) && ff_pkt->type != FT_DELETED) { /* already stripped */
      strip_path(ff_pkt);
   }
   switch (ff_pkt->type) {
   case FT_JUNCTION:
   case FT_LNK:
   case FT_LNKSAVED:
      Dmsg3(300, "Link %d %s to %s\n", jcr->JobFiles, ff_pkt->fname, ff_pkt->link);
      status = sd->fsend("%ld %d %s%c%s%c%s%c%s%c%u%c", jcr->JobFiles,
                         ff_pkt->type, ff_pkt->fname, 0, attribs.c_str(), 0,
                         ff_pkt->link, 0, attribsEx, 0, ff_pkt->delta_seq, 0);
      break;
   case FT_DIREND:
   case FT_REPARSE:
      /* Here link is the canonical filename (i.e. with trailing slash) */
      status = sd->fsend("%ld %d %s%c%s%c%c%s%c%u%c", jcr->JobFiles,
                         ff_pkt->type, ff_pkt->link, 0, attribs.c_str(), 0, 0,
                         attribsEx, 0, ff_pkt->delta_seq, 0);
      break;
   case FT_PLUGIN_CONFIG:
   case FT_RESTORE_FIRST:
      comp_len = ff_pkt->object_len;
      ff_pkt->object_compression = 0;

      if (ff_pkt->object_len > 1000) {
         /*
          * Big object, compress it
          */
         comp_len = compressBound(ff_pkt->object_len);
         POOLMEM *comp_obj = get_memory(comp_len);
         /*
          * FIXME: check Zdeflate error
          */
         Zdeflate(ff_pkt->object, ff_pkt->object_len, comp_obj, comp_len);
         if (comp_len < ff_pkt->object_len) {
            ff_pkt->object = comp_obj;
            ff_pkt->object_compression = 1;    /* zlib level 9 compression */
         } else {
            /*
             * Uncompressed object smaller, use it
             */
            comp_len = ff_pkt->object_len;
         }
         Dmsg2(100, "Object compressed from %d to %d bytes\n", ff_pkt->object_len, comp_len);
      }

      sd->msglen = Mmsg(sd->msg, "%d %d %d %d %d %d %s%c%s%c",
                        jcr->JobFiles, ff_pkt->type, ff_pkt->object_index,
                        comp_len, ff_pkt->object_len, ff_pkt->object_compression,
                        ff_pkt->fname, 0, ff_pkt->object_name, 0);
      sd->msg = check_pool_memory_size(sd->msg, sd->msglen + comp_len + 2);
      memcpy(sd->msg + sd->msglen, ff_pkt->object, comp_len);

      /*
       * Note we send one extra byte so Dir can store zero after object
       */
      sd->msglen += comp_len + 1;
      status = sd->send();
      if (ff_pkt->object_compression) {
         free_and_null_pool_memory(ff_pkt->object);
      }
      break;
   case FT_REG:
      status = sd->fsend("%ld %d %s%c%s%c%c%s%c%d%c", jcr->JobFiles,
                         ff_pkt->type, ff_pkt->fname, 0, attribs.c_str(), 0, 0,
                         attribsEx, 0, ff_pkt->delta_seq, 0);
      break;
   default:
      status = sd->fsend("%ld %d %s%c%s%c%c%s%c%u%c", jcr->JobFiles,
                         ff_pkt->type, ff_pkt->fname, 0, attribs.c_str(), 0, 0,
                         attribsEx, 0, ff_pkt->delta_seq, 0);
      break;
   }

   if (!IS_FT_OBJECT(ff_pkt->type) && ff_pkt->type != FT_DELETED) {
      unstrip_path(ff_pkt);
   }

   Dmsg2(300, ">stored: attr len=%d: %s\n", sd->msglen, sd->msg);
   if (!status && !jcr->is_job_canceled()) {
      Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror());
   }

   sd->signal(BNET_EOD);            /* indicate end of attributes data */

   return status;
}
Пример #26
0
/**
 * Send data read from an already open file descriptor.
 *
 * We return 1 on sucess and 0 on errors.
 *
 * ***FIXME***
 * We use ff_pkt->statp.st_size when FO_SPARSE to know when to stop reading.
 * Currently this is not a problem as the only other stream, resource forks,
 * are not handled as sparse files.
 */
static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt,
                     DIGEST *digest, DIGEST *signing_digest)
{
   b_ctx bctx;
   BSOCK *sd = jcr->store_bsock;
#ifdef FD_NO_SEND_TEST
   return 1;
#endif

   /*
    * Setup backup context.
    */
   memset(&bctx, 0, sizeof(b_ctx));
   bctx.jcr = jcr;
   bctx.ff_pkt = ff_pkt;
   bctx.msgsave = sd->msg; /* save the original sd buffer */
   bctx.rbuf = sd->msg; /* read buffer */
   bctx.wbuf = sd->msg; /* write buffer */
   bctx.rsize = jcr->buf_size; /* read buffer size */
   bctx.cipher_input = (uint8_t *)bctx.rbuf; /* encrypt uncompressed data */
   bctx.digest = digest; /* encryption digest */
   bctx.signing_digest = signing_digest; /* signing digest */

   Dmsg1(300, "Saving data, type=%d\n", ff_pkt->type);

   if (!setup_compression_context(bctx)) {
      goto bail_out;
   }

   if (!setup_encryption_context(bctx)) {
      goto bail_out;
   }

   /*
    * Send Data header to Storage daemon
    *    <file-index> <stream> <info>
    */
   if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
      if (!jcr->is_job_canceled()) {
         Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror());
      }
      goto bail_out;
   }
   Dmsg1(300, ">stored: datahdr %s", sd->msg);

   /*
    * Make space at beginning of buffer for fileAddr because this
    *   same buffer will be used for writing if compression is off.
    */
   if (bit_is_set(FO_SPARSE, ff_pkt->flags) || bit_is_set(FO_OFFSETS, ff_pkt->flags)) {
      bctx.rbuf += OFFSET_FADDR_SIZE;
      bctx.rsize -= OFFSET_FADDR_SIZE;
#ifdef HAVE_FREEBSD_OS
      /*
       * To read FreeBSD partitions, the read size must be a multiple of 512.
       */
      bctx.rsize = (bctx.rsize / 512) * 512;
#endif
   }

   /*
    * A RAW device read on win32 only works if the buffer is a multiple of 512
    */
#ifdef HAVE_WIN32
   if (S_ISBLK(ff_pkt->statp.st_mode)) {
      bctx.rsize = (bctx.rsize / 512) * 512;
   }

   if (ff_pkt->statp.st_rdev & FILE_ATTRIBUTE_ENCRYPTED) {
      if (!send_encrypted_data(bctx)) {
         goto bail_out;
      }
   } else {
      if (!send_plain_data(bctx)) {
         goto bail_out;
      }
   }
#else
   if (!send_plain_data(bctx)) {
      goto bail_out;
   }
#endif

   if (sd->msglen < 0) { /* error */
      berrno be;
      Jmsg(jcr, M_ERROR, 0, _("Read error on file %s. ERR=%s\n"), ff_pkt->fname, be.bstrerror(ff_pkt->bfd.berrno));
      if (jcr->JobErrors++ > 1000) { /* insanity check */
         Jmsg(jcr, M_FATAL, 0, _("Too many errors. JobErrors=%d.\n"), jcr->JobErrors);
      }
   } else if (bit_is_set(FO_ENCRYPT, ff_pkt->flags)) {
      /*
       * For encryption, we must call finalize to push out any buffered data.
       */
      if (!crypto_cipher_finalize(bctx.cipher_ctx,
                                  (uint8_t *)jcr->crypto.crypto_buf,
                                  &bctx.encrypted_len)) {
         /*
          * Padding failed. Shouldn't happen.
          */
         Jmsg(jcr, M_FATAL, 0, _("Encryption padding error\n"));
         goto bail_out;
      }

      /*
       * Note, on SSL pre-0.9.7, there is always some output
       */
      if (bctx.encrypted_len > 0) {
         sd->msglen = bctx.encrypted_len; /* set encrypted length */
         sd->msg = jcr->crypto.crypto_buf; /* set correct write buffer */
         if (!sd->send()) {
            if (!jcr->is_job_canceled()) {
               Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror());
            }
            goto bail_out;
         }
         Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
         jcr->JobBytes += sd->msglen; /* count bytes saved possibly compressed/encrypted */
         sd->msg = bctx.msgsave; /* restore bnet buffer */
      }
   }

   if (!sd->signal(BNET_EOD)) { /* indicate end of file data */
      if (!jcr->is_job_canceled()) {
         Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror());
      }
      goto bail_out;
   }

   /*
    * Free the cipher context
    */
   if (bctx.cipher_ctx) {
      crypto_cipher_free(bctx.cipher_ctx);
   }

   return 1;

bail_out:
   /*
    * Free the cipher context
    */
   if (bctx.cipher_ctx) {
      crypto_cipher_free(bctx.cipher_ctx);
   }

   sd->msg = bctx.msgsave; /* restore bnet buffer */
   sd->msglen = 0;

   return 0;
}
Пример #27
0
/*
 * Handle Director User Agent commands
 */
static void *handle_UA_client_request(void *arg)
{
   int status;
   UAContext *ua;
   JCR *jcr;
   BSOCK *user = (BSOCK *)arg;

   pthread_detach(pthread_self());

   jcr = new_control_jcr("-Console-", JT_CONSOLE);

   ua = new_ua_context(jcr);
   ua->UA_sock = user;
   set_jcr_in_tsd(INVALID_JCR);

   user->recv();             /* Get first message */
   if (!authenticate_user_agent(ua)) {
      goto getout;
   }

   while (!ua->quit) {
      if (ua->api) {
         user->signal(BNET_MAIN_PROMPT);
      }

      status = user->recv();
      if (status >= 0) {
         pm_strcpy(ua->cmd, ua->UA_sock->msg);
         parse_ua_args(ua);

         if (ua->argc > 0 && ua->argk[0][0] == '.') {
            do_a_dot_command(ua);
         } else {
            do_a_command(ua);
         }

         dequeue_messages(ua->jcr);

         if (!ua->quit) {
            if (console_msg_pending && acl_access_ok(ua, Command_ACL, "messages")) {
               if (ua->auto_display_messages) {
                  pm_strcpy(ua->cmd, "messages");
                  qmessages_cmd(ua, ua->cmd);
                  ua->user_notified_msg_pending = false;
               } else if (!ua->gui && !ua->user_notified_msg_pending && console_msg_pending) {
                  if (ua->api) {
                     user->signal(BNET_MSGS_PENDING);
                  } else {
                     bsendmsg(ua, _("You have messages.\n"));
                  }
                  ua->user_notified_msg_pending = true;
               }
            }
            if (!ua->api) {
               user->signal(BNET_EOD); /* send end of command */
            }
         }
      } else if (is_bnet_stop(user)) {
         ua->quit = true;
      } else { /* signal */
         user->signal(BNET_POLL);
      }
   }

getout:
   close_db(ua);
   free_ua_context(ua);
   free_jcr(jcr);
   user->close();
   delete user;

   return NULL;
}
Пример #28
0
Файл: mac.c Проект: AlD/bareos
/*
 * Read Data and commit to new job.
 */
bool do_mac_run(JCR *jcr)
{
   DEVICE *dev;
   char ec1[50];
   const char *Type;
   bool ok = true;
   BSOCK *dir = jcr->dir_bsock;

   switch(jcr->getJobType()) {
   case JT_MIGRATE:
      Type = "Migration";
      break;
   case JT_ARCHIVE:
      Type = "Archive";
      break;
   case JT_COPY:
      Type = "Copy";
      break;
   case JT_BACKUP:
      Type = "Virtual Backup";
      break;
   default:
      Type = "Unknown";
      break;
   }

   Dmsg0(20, "Start read data.\n");

   if (jcr->NumReadVolumes == 0) {
      Jmsg(jcr, M_FATAL, 0, _("No Volume names found for %s.\n"), Type);
      goto bail_out;
   }

   /*
    * Check autoinflation/autodeflation settings.
    */
   check_auto_xflation(jcr);

   /*
    * See if we perform both read and write or read only.
    */
   if (jcr->remote_replicate) {
      BSOCK *sd;

      if (!jcr->read_dcr) {
         Jmsg(jcr, M_FATAL, 0, _("Read device not properly initialized.\n"));
         goto bail_out;
      }

      Dmsg1(100, "read_dcr=%p\n", jcr->read_dcr);
      Dmsg3(200, "Found %d volumes names for %s. First=%s\n",
            jcr->NumReadVolumes, Type, jcr->VolList->VolumeName);

      /*
       * Ready devices for reading.
       */
      if (!acquire_device_for_read(jcr->read_dcr)) {
         ok = false;
         goto bail_out;
      }

      Dmsg2(200, "===== After acquire pos %u:%u\n", jcr->read_dcr->dev->file, jcr->read_dcr->dev->block_num);

      jcr->sendJobStatus(JS_Running);

      /*
       * Set network buffering.
       */
      sd = jcr->store_bsock;
      if (!sd->set_buffer_size(me->max_network_buffer_size, BNET_SETBUF_WRITE)) {
         Jmsg(jcr, M_FATAL, 0, _("Cannot set buffer size SD->SD.\n"));
         ok = false;
         goto bail_out;
      }

      /*
       * Let the remote SD know we are about to start the replication.
       */
      sd->fsend(start_replicate);
      Dmsg1(110, ">stored: %s", sd->msg);

      /*
       * Expect to receive back the Ticket number.
       */
      if (bget_msg(sd) >= 0) {
         Dmsg1(110, "<stored: %s", sd->msg);
         if (sscanf(sd->msg, OK_start_replicate, &jcr->Ticket) != 1) {
            Jmsg(jcr, M_FATAL, 0, _("Bad response to start replicate: %s\n"), sd->msg);
            goto bail_out;
         }
         Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
      } else {
         Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to start replicate command\n"));
         goto bail_out;
      }

      /*
       * Let the remote SD know we are now really going to send the data.
       */
      sd->fsend(replicate_data, jcr->Ticket);
      Dmsg1(110, ">stored: %s", sd->msg);

      /*
       * Expect to get response to the replicate data cmd from Storage daemon
       */
      if (!response(jcr, sd, OK_data, "replicate data")) {
         ok = false;
         goto bail_out;
      }

      /*
       * Read all data and send it to remote SD.
       */
      ok = read_records(jcr->read_dcr, clone_record_to_remote_sd, mount_next_read_volume);

      /*
       * Send the last EOD to close the last data transfer and a next EOD to
       * signal the remote we are done.
       */
      if (!sd->signal(BNET_EOD) || !sd->signal(BNET_EOD)) {
         if (!jcr->is_job_canceled()) {
            Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
                  sd->bstrerror());
         }
         goto bail_out;
      }

      /*
       * Expect to get response that the replicate data succeeded.
       */
      if (!response(jcr, sd, OK_replicate, "replicate data")) {
         ok = false;
         goto bail_out;
      }

      /*
       * End replicate session.
       */
      sd->fsend(end_replicate);
      Dmsg1(110, ">stored: %s", sd->msg);

      /*
       * Expect to get response to the end replicate cmd from Storage daemon
       */
      if (!response(jcr, sd, OK_end_replicate, "end replicate")) {
         ok = false;
         goto bail_out;
      }

      /* Inform Storage daemon that we are done */
      sd->signal(BNET_TERMINATE);
   } else {
      if (!jcr->read_dcr || !jcr->dcr) {
         Jmsg(jcr, M_FATAL, 0, _("Read and write devices not properly initialized.\n"));
         goto bail_out;
      }

      Dmsg2(100, "read_dcr=%p write_dcr=%p\n", jcr->read_dcr, jcr->dcr);
      Dmsg3(200, "Found %d volumes names for %s. First=%s\n",
            jcr->NumReadVolumes, Type, jcr->VolList->VolumeName);

      /*
       * Ready devices for reading and writing.
       */
      if (!acquire_device_for_read(jcr->read_dcr) ||
          !acquire_device_for_append(jcr->dcr)) {
         ok = false;
         goto bail_out;
      }

      Dmsg2(200, "===== After acquire pos %u:%u\n", jcr->dcr->dev->file, jcr->dcr->dev->block_num);

      jcr->sendJobStatus(JS_Running);

      if (!begin_data_spool(jcr->dcr) ) {
         ok = false;
         goto bail_out;
      }

      if (!begin_attribute_spool(jcr)) {
         ok = false;
         goto bail_out;
      }

      jcr->dcr->VolFirstIndex = jcr->dcr->VolLastIndex = 0;
      jcr->run_time = time(NULL);
      set_start_vol_position(jcr->dcr);
      jcr->JobFiles = 0;

      /*
       * Read all data and make a local clone of it.
       */
      ok = read_records(jcr->read_dcr, clone_record_internally, mount_next_read_volume);
   }

bail_out:
   if (!ok) {
      jcr->setJobStatus(JS_ErrorTerminated);
   }

   if (!jcr->remote_replicate && jcr->dcr) {
      /*
       * Don't use time_t for job_elapsed as time_t can be 32 or 64 bits,
       *   and the subsequent Jmsg() editing will break
       */
      int32_t job_elapsed;

      dev = jcr->dcr->dev;
      Dmsg1(100, "ok=%d\n", ok);
      if (ok || dev->can_write()) {
         /*
          * Flush out final partial block of this session
          */
         if (!jcr->dcr->write_block_to_device()) {
            Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
                  dev->print_name(), dev->bstrerror());
            Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
            ok = false;
         }
         Dmsg2(200, "Flush block to device pos %u:%u\n", dev->file, dev->block_num);
      }

      if (!ok) {
         discard_data_spool(jcr->dcr);
      } else {
         /*
          * Note: if commit is OK, the device will remain blocked
          */
         commit_data_spool(jcr->dcr);
      }

      job_elapsed = time(NULL) - jcr->run_time;
      if (job_elapsed <= 0) {
         job_elapsed = 1;
      }

      Jmsg(jcr, M_INFO, 0, _("Elapsed time=%02d:%02d:%02d, Transfer rate=%s Bytes/second\n"),
           job_elapsed / 3600, job_elapsed % 3600 / 60, job_elapsed % 60,
           edit_uint64_with_suffix(jcr->JobBytes / job_elapsed, ec1));

      /*
       * Release the device -- and send final Vol info to DIR
       */
      release_device(jcr->dcr);

      if (!ok || job_canceled(jcr)) {
         discard_attribute_spool(jcr);
      } else {
         commit_attribute_spool(jcr);
      }
   }

   if (jcr->read_dcr) {
      if (!release_device(jcr->read_dcr)) {
         ok = false;
      }
   }

   jcr->sendJobStatus();              /* update director */

   Dmsg0(30, "Done reading.\n");
   jcr->end_time = time(NULL);
   dequeue_messages(jcr);             /* send any queued messages */
   if (ok) {
      jcr->setJobStatus(JS_Terminated);
   }

   generate_plugin_event(jcr, bsdEventJobEnd);
   dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
              edit_uint64(jcr->JobBytes, ec1), jcr->JobErrors);
   Dmsg4(100, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, ec1);

   dir->signal(BNET_EOD);             /* send EOD to Director daemon */
   free_plugins(jcr);                 /* release instantiated plugins */

   return false;                      /* Continue DIR session ? */
}
Пример #29
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;
}
Пример #30
0
/*
 * Implement Bareos bconsole command  purge action
 *     purge action= pool= volume= storage= devicetype=
 */
static int action_on_purge_cmd(UAContext *ua, const char *cmd)
{
   bool allpools = false;
   int drive = -1;
   int nb = 0;
   uint32_t *results = NULL;
   const char *action = "all";
   STORERES *store = NULL;
   POOLRES *pool = NULL;
   MEDIA_DBR mr;
   POOL_DBR pr;
   BSOCK *sd = NULL;

   memset(&pr, 0, sizeof(pr));

   /* Look at arguments */
   for (int i=1; i<ua->argc; i++) {
      if (bstrcasecmp(ua->argk[i], NT_("allpools"))) {
         allpools = true;

      } else if (bstrcasecmp(ua->argk[i], NT_("volume")) &&
                 is_name_valid(ua->argv[i], NULL)) {
         bstrncpy(mr.VolumeName, ua->argv[i], sizeof(mr.VolumeName));

      } else if (bstrcasecmp(ua->argk[i], NT_("devicetype")) &&
                 ua->argv[i]) {
         bstrncpy(mr.MediaType, ua->argv[i], sizeof(mr.MediaType));

      } else if (bstrcasecmp(ua->argk[i], NT_("drive")) && ua->argv[i]) {
         drive = atoi(ua->argv[i]);

      } else if (bstrcasecmp(ua->argk[i], NT_("action")) &&
                 is_name_valid(ua->argv[i], NULL)) {
         action=ua->argv[i];
      }
   }

   /* Choose storage */
   ua->jcr->res.wstore = store = get_storage_resource(ua, false);
   if (!store) {
      goto bail_out;
   }

   switch (store->Protocol) {
   case APT_NDMPV2:
   case APT_NDMPV3:
   case APT_NDMPV4:
      ua->warning_msg(_("Storage has non-native protocol.\n"));
      goto bail_out;
   default:
      break;
   }

   if (!open_db(ua)) {
      Dmsg0(100, "Can't open db\n");
      goto bail_out;
   }

   if (!allpools) {
      /* force pool selection */
      pool = get_pool_resource(ua);
      if (!pool) {
         Dmsg0(100, "Can't get pool resource\n");
         goto bail_out;
      }
      bstrncpy(pr.Name, pool->name(), sizeof(pr.Name));
      if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
         Dmsg0(100, "Can't get pool record\n");
         goto bail_out;
      }
      mr.PoolId = pr.PoolId;
   }

   /*
    * Look for all Purged volumes that can be recycled, are enabled and
    *  have more the 10,000 bytes.
    */
   mr.Recycle = 1;
   mr.Enabled = 1;
   mr.VolBytes = 10000;
   set_storageid_in_mr(store, &mr);
   bstrncpy(mr.VolStatus, "Purged", sizeof(mr.VolStatus));
   if (!db_get_media_ids(ua->jcr, ua->db, &mr, &nb, &results)) {
      Dmsg0(100, "No results from db_get_media_ids\n");
      goto bail_out;
   }

   if (!nb) {
      ua->send_msg(_("No Volumes found to perform %s action.\n"), action);
      goto bail_out;
   }

   if ((sd = open_sd_bsock(ua)) == NULL) {
      Dmsg0(100, "Can't open connection to sd\n");
      goto bail_out;
   }

   /*
    * Loop over the candidate Volumes and actually truncate them
    */
   for (int i=0; i < nb; i++) {
      mr.clear();
      mr.MediaId = results[i];
      if (db_get_media_record(ua->jcr, ua->db, &mr)) {
         /* TODO: ask for drive and change Pool */
         if (bstrcasecmp("truncate", action) || bstrcasecmp("all", action)) {
            do_truncate_on_purge(ua, &mr, pr.Name, store->dev_name(), drive, sd);
         }
      } else {
         Dmsg1(0, "Can't find MediaId=%lld\n", (uint64_t) mr.MediaId);
      }
   }

bail_out:
   close_db(ua);
   if (sd) {
      sd->signal(BNET_TERMINATE);
      sd->close();
      ua->jcr->store_bsock = NULL;
   }
   ua->jcr->res.wstore = NULL;
   if (results) {
      free(results);
   }

   return 1;
}