Esempio n. 1
0
/*
 * Select a Storage resource from prompt list
 */
STORERES *select_storage_resource(UAContext *ua, bool autochanger_only)
{
   STORERES *store;
   char name[MAX_NAME_LENGTH];

   if (autochanger_only) {
      start_prompt(ua, _("The defined Autochanger Storage resources are:\n"));
   } else {
      start_prompt(ua, _("The defined Storage resources are:\n"));
   }

   LockRes();
   foreach_res(store, R_STORAGE) {
      if (acl_access_ok(ua, Storage_ACL, store->name())) {
         if (autochanger_only && !store->autochanger) {
            continue;
         } else {
            add_prompt(ua, store->name());
         }
      }
   }
   UnlockRes();

   if (do_prompt(ua, _("Storage"),  _("Select Storage resource"), name, sizeof(name)) < 0) {
      return NULL;
   }
   store = (STORERES *)GetResWithName(R_STORAGE, name);

   return store;
}
Esempio n. 2
0
/*
 * Check if this is a cleaning tape by comparing the Volume name
 *  with the Cleaning Prefix. If they match, this is a cleaning
 *  tape.
 */
static inline bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr)
{
   bool retval;

   /*
    * Find Pool resource
    */
   ua->jcr->res.pool = (POOLRES *)GetResWithName(R_POOL, pr->Name);
   if (!ua->jcr->res.pool) {
      ua->error_msg(_("Pool \"%s\" resource not found for volume \"%s\"!\n"),
                    pr->Name, mr->VolumeName);
      return false;
   }

   retval = bstrncmp(mr->VolumeName,
                     ua->jcr->res.pool->cleaning_prefix,
                     strlen(ua->jcr->res.pool->cleaning_prefix));

   Dmsg4(100, "CLNprefix=%s: Vol=%s: len=%d bstrncmp=%s\n",
         ua->jcr->res.pool->cleaning_prefix, mr->VolumeName,
         strlen(ua->jcr->res.pool->cleaning_prefix),
         retval ? "true" : "false");

   return retval;
}
Esempio n. 3
0
/*
 * Get a catalog resource from prompt list
 */
CATRES *get_catalog_resource(UAContext *ua)
{
   CATRES *catalog = NULL;
   char name[MAX_NAME_LENGTH];

   for (int i = 1; i < ua->argc; i++) {
      if (bstrcasecmp(ua->argk[i], NT_("catalog")) && ua->argv[i]) {
         if (acl_access_ok(ua, Catalog_ACL, ua->argv[i])) {
            catalog = (CATRES *)GetResWithName(R_CATALOG, ua->argv[i]);
            break;
         }
      }
   }

   if (ua->gui && !catalog) {
      LockRes();
      catalog = (CATRES *)GetNextRes(R_CATALOG, NULL);
      UnlockRes();

      if (!catalog) {
         ua->error_msg(_("Could not find a Catalog resource\n"));
         return NULL;
      } else if (!acl_access_ok(ua, Catalog_ACL, catalog->name())) {
         ua->error_msg(_("You must specify a \"use <catalog-name>\" command before continuing.\n"));
         return NULL;
      }

      return catalog;
   }

   if (!catalog) {
      start_prompt(ua, _("The defined Catalog resources are:\n"));

      LockRes();
      foreach_res(catalog, R_CATALOG) {
         if (acl_access_ok(ua, Catalog_ACL, catalog->name())) {
            add_prompt(ua, catalog->name());
         }
      }
      UnlockRes();

      if (do_prompt(ua, _("Catalog"),  _("Select Catalog resource"), name, sizeof(name)) < 0) {
         return NULL;
      }

      catalog = (CATRES *)GetResWithName(R_CATALOG, name);
   }
Esempio n. 4
0
/* row: Job.Name, FileSet, Client.Name, FileSetId, ClientId, Type */
static int job_select_handler(void *ctx, int num_fields, char **row)
{
   alist *lst = (alist *)ctx;
   struct accurate_check_ctx *res;
   ASSERT(num_fields == 6);

   /* Quick fix for #5507, avoid locking res_head after db_lock() */

#ifdef bug5507
   /* If this job doesn't exist anymore in the configuration, delete it */
   if (GetResWithName(R_JOB, row[0]) == NULL) {
      return 0;
   }

   /* If this fileset doesn't exist anymore in the configuration, delete it */
   if (GetResWithName(R_FILESET, row[1]) == NULL) {
      return 0;
   }

   /* If this client doesn't exist anymore in the configuration, delete it */
   if (GetResWithName(R_CLIENT, row[2]) == NULL) {
      return 0;
   }
#endif

   /* Don't compute accurate things for Verify jobs */
   if (*row[5] == 'V') {
      return 0;
   }

   res = (struct accurate_check_ctx*) malloc(sizeof(struct accurate_check_ctx));
   res->FileSetId = str_to_int64(row[3]);
   res->ClientId = str_to_int64(row[4]);
   lst->append(res);

// Dmsg2(150, "row=%d val=%d\n", del->num_ids-1, del->JobId[del->num_ids-1]);
   return 0;
}
Esempio n. 5
0
/*
 * Store a resource pointer in an alist. default_value indicates how many
 * times this routine can be called -- i.e. how many alists
 * there are.
 *
 * If we are in pass 2, do a lookup of the resource.
 */
static void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
{
   RES *res;
   int i = 0;
   alist *list;
   URES *res_all = (URES *)my_config->m_res_all;
   int count = str_to_int32(item->default_value);

   if (pass == 2) {
      if (count == 0) {               /* always store in item->value */
         i = 0;
         if ((item->value)[i] == NULL) {
            list = New(alist(10, not_owned_by_alist));
         } else {
            list = (alist *)(item->value)[i];
         }
      } else {
         /*
          * Find empty place to store this directive
          */
         while ((item->value)[i] != NULL && i++ < count) { }
         if (i >= count) {
            scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"),
               lc->str, count, lc->line_no, lc->line);
            return;
         }
         list = New(alist(10, not_owned_by_alist));
      }

      for (;;) {
         lex_get_token(lc, T_NAME);   /* scan next item */
         res = GetResWithName(item->code, lc->str);
         if (res == NULL) {
            scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
               item->name, lc->line_no, lc->line);
            return;
         }
         Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n",
               res, list, list->size(), i, item->name);
         list->append(res);
         (item->value)[i] = (char *)list;
         if (lc->ch != ',') {         /* if no other item follows */
            break;                    /* get out */
         }
         lex_get_token(lc, T_ALL);    /* eat comma */
      }
   }
   scan_to_eol(lc);
   set_bit(index, res_all->hdr.item_present);
}
Esempio n. 6
0
/*
 * Store default values for Resource from xxxDefs
 * If we are in pass 2, do a lookup of the
 * resource and store everything not explicitly set
 * in main resource.
 *
 * Note, here item points to the main resource (e.g. Job, not
 *  the jobdefs, which we look up).
 */
void store_defs(LEX *lc, RES_ITEM *item, int index, int pass)
{
   RES *res;

   lex_get_token(lc, T_NAME);
   if (pass == 2) {
     Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
     res = GetResWithName(item->code, lc->str);
     if (res == NULL) {
        scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
           lc->str, lc->line_no, lc->line);
        return;
     }
   }
   scan_to_eol(lc);
}
Esempio n. 7
0
/*
 * Get storage device name from Storage resource
 */
static bool get_storage_device(char *device, char *storage)
{
   STORERES *store;
   if (storage[0] == 0) {
      return false;
   }
   store = (STORERES *)GetResWithName(R_STORAGE, storage);
   if (!store) {
      return false;
   }
   DEVICERES *dev = (DEVICERES *)(store->device->first());
   if (!dev) {
      return false;
   }
   bstrncpy(device, dev->hdr.name, MAX_NAME_LENGTH);
   return true;
}
Esempio n. 8
0
/*
 * This function compare the given storage name with the
 * the current one. We compare the name and the address:port.
 * Returns true if we use the same storage.
 */
static inline bool is_on_same_storage(JCR *jcr, char *new_one)
{
   STORERES *new_store;

   /*
    * With old FD, we send the whole bootstrap to the storage
    */
   if (jcr->FDVersion < FD_VERSION_2) {
      return true;
   }

   /*
    * We are in init loop ? shoudn't fail here
    */
   if (!*new_one) {
      return true;
   }

   /*
    * Same name
    */
   if (bstrcmp(new_one, jcr->res.rstore->name())) {
      return true;
   }

   new_store = (STORERES *)GetResWithName(R_STORAGE, new_one);
   if (!new_store) {
      Jmsg(jcr, M_WARNING, 0,
           _("Could not get storage resource '%s'.\n"), new_one);
      return true;
   }

   /*
    * If Port and Hostname/IP are same, we are talking to the same
    * Storage Daemon
    */
   if (jcr->res.rstore->SDport != new_store->SDport ||
       !bstrcmp(jcr->res.rstore->address, new_store->address)) {
      return false;
   }

   return true;
}
Esempio n. 9
0
/*********************************************************************
 *
 *         Main Bareos Scheduler
 *
 */
JCR *wait_for_next_job(char *one_shot_job_to_run)
{
   JCR *jcr;
   JOBRES *job;
   RUNRES *run;
   time_t now, prev;
   static bool first = true;
   job_item *next_job = NULL;

   Dmsg0(dbglvl, "Enter wait_for_next_job\n");
   if (first) {
      first = false;
      /* Create scheduled jobs list */
      jobs_to_run = New(dlist(next_job, &next_job->link));
      if (one_shot_job_to_run) {            /* one shot */
         job = (JOBRES *)GetResWithName(R_JOB, one_shot_job_to_run);
         if (!job) {
            Emsg1(M_ABORT, 0, _("Job %s not found\n"), one_shot_job_to_run);
         }
         Dmsg1(5, "Found one_shot_job_to_run %s\n", one_shot_job_to_run);
         jcr = new_jcr(sizeof(JCR), dird_free_jcr);
         set_jcr_defaults(jcr, job);
         return jcr;
      }
   }

   /* Wait until we have something in the
    * next hour or so.
    */
again:
   while (jobs_to_run->empty()) {
      find_runs();
      if (!jobs_to_run->empty()) {
         break;
      }
      bmicrosleep(next_check_secs, 0); /* recheck once per minute */
   }

#ifdef  list_chain
   job_item *je;
   foreach_dlist(je, jobs_to_run) {
      dump_job(je, _("Walk queue"));
   }
Esempio n. 10
0
/*
 * Check if this is a cleaning tape by comparing the Volume name
 *  with the Cleaning Prefix. If they match, this is a cleaning
 *  tape.
 */
static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr)
{
   /* Find Pool resource */
   ua->jcr->pool = (POOL *)GetResWithName(R_POOL, pr->Name);
   if (!ua->jcr->pool) {
      ua->error_msg(_("Pool \"%s\" resource not found for volume \"%s\"!\n"),
         pr->Name, mr->VolumeName);
      return false;
   }
   if (ua->jcr->pool->cleaning_prefix == NULL) {
      return false;
   }
   Dmsg4(100, "CLNprefix=%s: Vol=%s: len=%d strncmp=%d\n",
      ua->jcr->pool->cleaning_prefix, mr->VolumeName,
      strlen(ua->jcr->pool->cleaning_prefix),
      strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
                  strlen(ua->jcr->pool->cleaning_prefix)));
   return strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
                  strlen(ua->jcr->pool->cleaning_prefix)) == 0;
}
Esempio n. 11
0
/* Store a resource at specified address.
 * If we are in pass 2, do a lookup of the
 * resource.
 */
void store_res(LEX *lc, RES_ITEM *item, int index, int pass)
{
   RES *res;

   lex_get_token(lc, T_NAME);
   if (pass == 2) {
      res = GetResWithName(item->code, lc->str);
      if (res == NULL) {
         scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"),
            lc->str, lc->line_no, lc->line);
         return;
      }
      if (*(item->value)) {
         scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"),
            item->name, lc->line_no, lc->line);
         return;
      }
      *(item->value) = (char *)res;
   }
   scan_to_eol(lc);
   set_bit(index, res_all.hdr.item_present);
}
Esempio n. 12
0
/*
 * Select a FileSet resource from prompt list
 */
FILESETRES *select_fileset_resource(UAContext *ua)
{
   FILESETRES *fs;
   char name[MAX_NAME_LENGTH];

   start_prompt(ua, _("The defined FileSet resources are:\n"));

   LockRes();
   foreach_res(fs, R_FILESET) {
      if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
         add_prompt(ua, fs->name());
      }
   }
   UnlockRes();

   if (do_prompt(ua, _("FileSet"), _("Select FileSet resource"), name, sizeof(name)) < 0) {
      return NULL;
   }

   fs = (FILESETRES *)GetResWithName(R_FILESET, name);

   return fs;
}
Esempio n. 13
0
/*
 * Save the new resource by chaining it into the head list for
 * the resource. If this is pass 2, we update any resource
 * pointers (currently only in the Job resource).
 */
bool save_resource(int type, RES_ITEM *items, int pass)
{
   URES *res;
   int rindex = type - R_FIRST;
   int i;
   int error = 0;

   /*
    * Ensure that all required items are present
    */
   for (i = 0; items[i].name; i++) {
      if (items[i].flags & CFG_ITEM_REQUIRED) {
            if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
               Emsg2(M_ABORT, 0, _("%s item is required in %s resource, but not found.\n"),
                 items[i].name, resources[rindex]);
             }
      }
   }

   /*
    * During pass 2, we looked up pointers to all the resources
    * referrenced in the current resource, , now we
    * must copy their address from the static record to the allocated
    * record.
    */
   if (pass == 2) {
      switch (type) {
         case R_CONSOLE:
            if ((res = (URES *)GetResWithName(R_CONSOLE, res_all.res_cons.name())) == NULL) {
               Emsg1(M_ABORT, 0, _("Cannot find Console resource %s\n"), res_all.res_cons.name());
            } else {
               res->res_cons.tls.allowed_cns = res_all.res_cons.tls.allowed_cns;
            }
            break;
         case R_DIRECTOR:
            if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.name())) == NULL) {
               Emsg1(M_ABORT, 0, _("Cannot find Director resource %s\n"), res_all.res_dir.name());
            } else {
               res->res_dir.tls.allowed_cns = res_all.res_dir.tls.allowed_cns;
            }
            break;
         default:
            Emsg1(M_ERROR, 0, _("Unknown resource type %d\n"), type);
            error = 1;
            break;
      }

      /*
       * Note, the resoure name was already saved during pass 1,
       * so here, we can just release it.
       */
      if (res_all.res_dir.hdr.name) {
         free(res_all.res_dir.hdr.name);
         res_all.res_dir.hdr.name = NULL;
      }
      if (res_all.res_dir.hdr.desc) {
         free(res_all.res_dir.hdr.desc);
         res_all.res_dir.hdr.desc = NULL;
      }
      return (error == 0);
   }

   /*
    * Common
    */
   if (!error) {
      res = (URES *)malloc(resources[rindex].size);
      memcpy(res, &res_all, resources[rindex].size);
      if (!res_head[rindex]) {
         res_head[rindex] = (RES *)res; /* store first entry */
      } else {
         RES *next, *last;
         for (last=next=res_head[rindex]; next; next=next->next) {
            last = next;
            if (bstrcmp(next->name, res->res_dir.name())) {
               Emsg2(M_ERROR_TERM, 0,
                     _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
                     resources[rindex].name, res->res_dir.name());
            }
         }
         last->next = (RES *)res;
         Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type), res->res_dir.name());
      }
   }
   return (error == 0);
}
Esempio n. 14
0
int authenticate_user_agent(UAContext *uac)
{
   char name[MAX_NAME_LENGTH];
   int tls_local_need = BNET_TLS_NONE;
   int tls_remote_need = BNET_TLS_NONE;
   bool tls_authenticate;
   int compatible = true;
   CONRES *cons = NULL;
   BSOCK *ua = uac->UA_sock;
   bool auth_success = false;
   TLS_CONTEXT *tls_ctx = NULL;
   alist *verify_list = NULL;

   if (ua->msglen < 16 || ua->msglen >= MAX_NAME_LENGTH + 15) {
      Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Len=%d\n"), ua->who(),
            ua->host(), ua->port(), ua->msglen);
      return 0;
   }

   if (sscanf(ua->msg, "Hello %127s calling\n", name) != 1) {
      ua->msg[100] = 0;               /* terminate string */
      Emsg4(M_ERROR, 0, _("UA Hello from %s:%s:%d is invalid. Got: %s\n"), ua->who(),
            ua->host(), ua->port(), ua->msg);
      return 0;
   }

   name[sizeof(name)-1] = 0;             /* terminate name */
   if (bstrcmp(name, "*UserAgent*")) {  /* default console */
      /* TLS Requirement */
      if (director->tls_enable) {
         if (director->tls_require) {
            tls_local_need = BNET_TLS_REQUIRED;
         } else {
            tls_local_need = BNET_TLS_OK;
         }
      }

      tls_authenticate = director->tls_authenticate;

      if (tls_authenticate) {
         tls_local_need = BNET_TLS_REQUIRED;
      }

      if (director->tls_verify_peer) {
         verify_list = director->tls_allowed_cns;
      }

      auth_success = cram_md5_challenge(ua, director->password, tls_local_need,
                                        compatible) &&
                     cram_md5_respond(ua, director->password, &tls_remote_need, &compatible);
   } else {
      unbash_spaces(name);
      cons = (CONRES *)GetResWithName(R_CONSOLE, name);
      if (cons) {
         /* TLS Requirement */
         if (cons->tls_enable) {
            if (cons->tls_require) {
               tls_local_need = BNET_TLS_REQUIRED;
            } else {
               tls_local_need = BNET_TLS_OK;
            }
         }

         tls_authenticate = cons->tls_authenticate;

         if (tls_authenticate) {
            tls_local_need = BNET_TLS_REQUIRED;
         }

         if (cons->tls_verify_peer) {
            verify_list = cons->tls_allowed_cns;
         }

         auth_success = cram_md5_challenge(ua, cons->password, tls_local_need,
                                           compatible) &&
                     cram_md5_respond(ua, cons->password, &tls_remote_need, &compatible);

         if (auth_success) {
            uac->cons = cons;         /* save console resource pointer */
         }
      } else {
         auth_success = false;
         goto auth_done;
      }
   }


   /* Verify that the remote peer is willing to meet our TLS requirements */
   if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
      Emsg0(M_FATAL, 0, _("Authorization problem:"
            " Remote client did not advertise required TLS support.\n"));
      auth_success = false;
      goto auth_done;
   }

   /* Verify that we are willing to meet the peer's requirements */
   if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
      Emsg0(M_FATAL, 0, _("Authorization problem:"
            " Remote client requires TLS.\n"));
      auth_success = false;
      goto auth_done;
   }

   if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
      if (cons) {
         tls_ctx = cons->tls_ctx;
      } else {
         tls_ctx = director->tls_ctx;
      }

      /* Engage TLS! Full Speed Ahead! */
      if (!bnet_tls_server(tls_ctx, ua, verify_list)) {
         Emsg0(M_ERROR, 0, _("TLS negotiation failed.\n"));
         auth_success = false;
         goto auth_done;
      }
      if (tls_authenticate) {            /* authentication only? */
         ua->free_tls();                 /* stop tls */
      }
   }


/* Authorization Completed */
auth_done:
   if (!auth_success) {
      ua->fsend("%s", _(Dir_sorry));
      Emsg4(M_ERROR, 0, _("Unable to authenticate console \"%s\" at %s:%s:%d.\n"),
            name, ua->who(), ua->host(), ua->port());
      sleep(5);
      return 0;
   }
   ua->fsend(_("1000 OK: %s Version: %s (%s)\n"), my_name, VERSION, BDATE);
   return 1;
}
Esempio n. 15
0
/*
 * Get a message
 *  Call appropriate processing routine
 *  If it is not a Jmsg or a ReqCat message,
 *   return it to the caller.
 *
 *  This routine is called to get the next message from
 *  another daemon. If the message is in canonical message
 *  format and the type is known, it will be dispatched
 *  to the appropriate handler.  If the message is
 *  in any other format, it will be returned.
 *
 *  E.g. any message beginning with a digit will be passed
 *       through to the caller.
 *  All other messages are expected begin with some identifier
 *    -- for the moment only the first character is checked, but
 *    at a later time, the whole identifier (e.g. Jmsg, CatReq, ...)
 *    could be checked. This is followed by Job=Jobname <user-defined>
 *    info. The identifier is used to dispatch the message to the right
 *    place (Job message, catalog request, ...). The Job is used to lookup
 *    the JCR so that the action is performed on the correct jcr, and
 *    the rest of the message is up to the user.  Note, DevUpd uses
 *    *System* for the Job name, and hence no JCR is obtained. This
 *    is a *rare* case where a jcr is not really needed.
 *
 */
int bget_dirmsg(BSOCK *bs, bool allow_any_message)
{
   int32_t n = BNET_TERMINATE;
   char Job[MAX_NAME_LENGTH];
   char MsgType[20];
   int type;
   utime_t mtime;                     /* message time */
   JCR *jcr = bs->jcr();
   char *msg;

   for ( ; !bs->is_stop() && !bs->is_timed_out(); ) {
      n = bs->recv();
      Dmsg2(200, "bget_dirmsg %d: %s\n", n, bs->msg);

      if (bs->is_stop() || bs->is_timed_out()) {
         return n;                    /* error or terminate */
      }
      if (n == BNET_SIGNAL) {          /* handle signal */
         /* BNET_SIGNAL (-1) return from bnet_recv() => network signal */
         switch (bs->msglen) {
         case BNET_EOD:            /* end of data */
            return n;
         case BNET_EOD_POLL:
            bs->fsend(OK_msg);/* send response */
            return n;              /* end of data */
         case BNET_TERMINATE:
            bs->set_terminated();
            return n;
         case BNET_POLL:
            bs->fsend(OK_msg); /* send response */
            break;
         case BNET_HEARTBEAT:
//          encode_time(time(NULL), Job);
//          Dmsg1(100, "%s got heartbeat.\n", Job);
            break;
         case BNET_HB_RESPONSE:
            break;
         case BNET_STATUS:
            /* *****FIXME***** Implement more completely */
            bs->fsend("Status OK\n");
            bs->signal(BNET_EOD);
            break;
         case BNET_BTIME:             /* send BAREOS time */
            char ed1[50];
            bs->fsend("btime %s\n", edit_uint64(get_current_btime(),ed1));
            break;
         default:
            Jmsg1(jcr, M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen);
            return n;
         }
         continue;
      }

      /*
       * Handle normal data
       */
      if (n > 0 && B_ISDIGIT(bs->msg[0])) {      /* response? */
         return n;                    /* yes, return it */
      }

      /*
       * If we get here, it must be a request.  Either
       *  a message to dispatch, or a catalog request.
       *  Try to fulfill it.
       */
      if (sscanf(bs->msg, "%020s Job=%127s ", MsgType, Job) != 2) {
         /*
          * If the special flag allow_any_message is given ignore
          * the error and just return it as normal data.
          */
         if (allow_any_message) {
            return n;
         } else {
            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
            continue;
         }
      }

      /*
       * Skip past "Jmsg Job=nnn"
       */
      if (!(msg=find_msg_start(bs->msg))) {
         Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
         continue;
      }

      /*
       * Here we are expecting a message of the following format:
       *   Jmsg Job=nnn type=nnn level=nnn Message-string
       * Note, level should really be mtime, but that changes
       *   the protocol.
       */
      if (bs->msg[0] == 'J') {           /* Job message */
         if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%lld",
                    Job, &type, &mtime) != 3) {
            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
            continue;
         }
         Dmsg1(900, "Got msg: %s\n", bs->msg);
         skip_spaces(&msg);
         skip_nonspaces(&msg);        /* skip type=nnn */
         skip_spaces(&msg);
         skip_nonspaces(&msg);        /* skip level=nnn */
         if (*msg == ' ') {
            msg++;                    /* skip leading space */
         }
         Dmsg1(900, "Dispatch msg: %s", msg);
         dispatch_message(jcr, type, mtime, msg);
         continue;
      }
      /*
       * Here we expact a CatReq message
       *   CatReq Job=nn Catalog-Request-Message
       */
      if (bs->msg[0] == 'C') {        /* Catalog request */
         Dmsg2(900, "Catalog req jcr 0x%x: %s", jcr, bs->msg);
         catalog_request(jcr, bs);
         continue;
      }
      if (bs->msg[0] == 'U') {        /* SD sending attributes */
         Dmsg2(900, "Catalog upd jcr 0x%x: %s", jcr, bs->msg);
         catalog_update(jcr, bs);
         continue;
      }
      if (bs->msg[0] == 'B') {        /* SD sending file spool attributes */
         Dmsg2(100, "Blast attributes jcr 0x%x: %s", jcr, bs->msg);
         char filename[256];
         if (sscanf(bs->msg, "BlastAttr Job=%127s File=%255s",
                    Job, filename) != 2) {
            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
            continue;
         }
         unbash_spaces(filename);
         if (despool_attributes_from_file(jcr, filename)) {
            bs->fsend("1000 OK BlastAttr\n");
         } else {
            bs->fsend("1990 ERROR BlastAttr\n");
         }
         continue;
      }
      if (bs->msg[0] == 'M') {        /* Mount request */
         Dmsg1(900, "Mount req: %s", bs->msg);
         mount_request(jcr, bs, msg);
         continue;
      }
      if (bs->msg[0] == 'S') {       /* Status change */
         int JobStatus;
         char Job[MAX_NAME_LENGTH];
         if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) {
            set_jcr_sd_job_status(jcr, JobStatus); /* current status */
         } else {
            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
         }
         continue;
      }
#ifdef needed
      /* No JCR for Device Updates! */
      if (bs->msg[0] = 'D') {         /* Device update */
         DEVICE *dev;
         POOL_MEM dev_name, changer_name, media_type, volume_name;
         int dev_open, dev_append, dev_read, dev_labeled;
         int dev_offline, dev_autochanger, dev_autoselect;
         int dev_num_writers, dev_max_writers, dev_reserved;
         uint64_t dev_read_time, dev_write_time, dev_write_bytes, dev_read_bytes;
         uint64_t dev_PoolId;
         Dmsg1(100, "<stored: %s", bs->msg);
         if (sscanf(bs->msg, Device_update,
             &Job, dev_name.c_str(),
             &dev_append, &dev_read,
             &dev_num_writers, &dev_open,
             &dev_labeled, &dev_offline, &dev_reserved,
             &dev_max_writers, &dev_autoselect,
             &dev_autochanger,
             changer_name.c_str(), media_type.c_str(),
             volume_name.c_str(),
             &dev_read_time, &dev_write_time, &dev_read_bytes,
             &dev_write_bytes) != 19) {
            Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
         } else {
            unbash_spaces(dev_name);
            dev = (DEVICE *)GetResWithName(R_DEVICE, dev_name.c_str());
            if (!dev) {
               continue;
            }
            unbash_spaces(changer_name);
            unbash_spaces(media_type);
            unbash_spaces(volume_name);
            bstrncpy(dev->ChangerName, changer_name.c_str(), sizeof(dev->ChangerName));
            bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType));
            bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName));
            /* Note, these are copied because they are boolean rather than
             *  integer.
             */
            dev->open = dev_open;
            dev->append = dev_append;
            dev->read = dev_read;
            dev->labeled = dev_labeled;
            dev->offline = dev_offline;
            dev->autoselect = dev_autoselect;
            dev->autochanger = dev_autochanger > 0;
            dev->num_drives = dev_autochanger;    /* does double duty */
            dev->PoolId = dev_PoolId;
            dev->num_writers = dev_num_writers;
            dev->max_writers = dev_max_writers;
            dev->reserved = dev_reserved;
            dev->found = true;
            dev->DevReadTime = dev_read_time; /* TODO : have to update database */
            dev->DevWriteTime = dev_write_time;
            dev->DevReadBytes = dev_read_bytes;
            dev->DevWriteBytes = dev_write_bytes;
         }
         continue;
      }
#endif
      return n;
   }
   return n;
}
Esempio n. 16
0
/*
 *  Displays Resources
 *
 *  show all
 *  show <resource-keyword-name>  e.g. show directors
 *  show <resource-keyword-name>=<name> e.g. show director=HeadMan
 *  show disabled    shows disabled jobs
 *
 */
int show_cmd(UAContext *ua, const char *cmd)
{
   int i, j, type, len;
   int recurse;
   char *res_name;
   RES *res = NULL;

   Dmsg1(20, "show: %s\n", ua->UA_sock->msg);

   LockRes();
   for (i=1; i<ua->argc; i++) {
      if (bstrcasecmp(ua->argk[i], _("disabled"))) {
         show_disabled_jobs(ua);
         goto bail_out;
      }
      type = 0;
      res_name = ua->argk[i];
      if (!ua->argv[i]) {             /* was a name given? */
         /* No name, dump all resources of specified type */
         recurse = 1;
         len = strlen(res_name);
         for (j=0; avail_resources[j].res_name; j++) {
            if (bstrncasecmp(res_name, _(avail_resources[j].res_name), len)) {
               type = avail_resources[j].type;
               if (type > 0) {
                  res = res_head[type-r_first];
               } else {
                  res = NULL;
               }
               break;
            }
         }
      } else {
         /* Dump a single resource with specified name */
         recurse = 0;
         len = strlen(res_name);
         for (j=0; avail_resources[j].res_name; j++) {
            if (bstrncasecmp(res_name, _(avail_resources[j].res_name), len)) {
               type = avail_resources[j].type;
               res = (RES *)GetResWithName(type, ua->argv[i]);
               if (!res) {
                  type = -3;
               }
               break;
            }
         }
      }

      switch (type) {
      case -1:                           /* all */
         for (j=r_first; j<=r_last; j++) {
            dump_resource(j, res_head[j-r_first], bsendmsg, ua);
         }
         break;
      case -2:
         ua->send_msg(_("Keywords for the show command are:\n"));
         for (j=0; avail_resources[j].res_name; j++) {
            ua->error_msg("%s\n", _(avail_resources[j].res_name));
         }
         goto bail_out;
      case -3:
         ua->error_msg(_("%s resource %s not found.\n"), res_name, ua->argv[i]);
         goto bail_out;
      case 0:
         ua->error_msg(_("Resource %s not found\n"), res_name);
         goto bail_out;
      default:
         dump_resource(recurse?type:-type, res, bsendmsg, ua);
         break;
      }
   }
bail_out:
   UnlockRes();
   return 1;
}
Esempio n. 17
0
/*
 * Store Schedule Run information
 *
 * Parse Run statement:
 *
 *  Run <keyword=value ...> [on] 2 january at 23:45
 *
 *   Default Run time is daily at 0:0
 *
 *   There can be multiple run statements, they are simply chained
 *   together.
 *
 */
void store_run(LEX *lc, RES_ITEM *item, int index, int pass)
{
   char *p;
   int i, j;
   int options = lc->options;
   int token, state, state2 = 0, code = 0, code2 = 0;
   bool found;
   utime_t utime;
   RES *res;
   RUNRES **run = (RUNRES **)(item->value);
   URES *res_all = (URES *)my_config->m_res_all;

   lc->options |= LOPT_NO_IDENT;      /* Want only "strings" */

   /*
    * Clear local copy of run record
    */
   memset(&lrun, 0, sizeof(lrun));

   /*
    * Scan for Job level "full", "incremental", ...
    */
   for (found = true; found; ) {
      found = false;
      token = lex_get_token(lc, T_NAME);
      for (i = 0; !found && RunFields[i].name; i++) {
         if (bstrcasecmp(lc->str, RunFields[i].name)) {
            found = true;
            if (lex_get_token(lc, T_ALL) != T_EQUALS) {
               scan_err1(lc, _("Expected an equals, got: %s"), lc->str);
               /* NOT REACHED */
            }
            switch (RunFields[i].token) {
            case 's':                 /* Data spooling */
               token = lex_get_token(lc, T_NAME);
               if (bstrcasecmp(lc->str, "yes") || bstrcasecmp(lc->str, "true")) {
                  lrun.spool_data = true;
                  lrun.spool_data_set = true;
               } else if (bstrcasecmp(lc->str, "no") || bstrcasecmp(lc->str, "false")) {
                  lrun.spool_data = false;
                  lrun.spool_data_set = true;
               } else {
                  scan_err1(lc, _("Expect a YES or NO, got: %s"), lc->str);
               }
               break;
            case 'L':                 /* Level */
               token = lex_get_token(lc, T_NAME);
               for (j = 0; joblevels[j].level_name; j++) {
                  if (bstrcasecmp(lc->str, joblevels[j].level_name)) {
                     lrun.level = joblevels[j].level;
                     lrun.job_type = joblevels[j].job_type;
                     j = 0;
                     break;
                  }
               }
               if (j != 0) {
                  scan_err1(lc, _("Job level field: %s not found in run record"), lc->str);
                  /* NOT REACHED */
               }
               break;
            case 'p':                 /* Priority */
               token = lex_get_token(lc, T_PINT32);
               if (pass == 2) {
                  lrun.Priority = lc->pint32_val;
               }
               break;
            case 'P':                 /* Pool */
            case 'f':                 /* FullPool */
            case 'v':                 /* VFullPool */
            case 'i':                 /* IncPool */
            case 'd':                 /* DiffPool */
            case 'n':                 /* NextPool */
               token = lex_get_token(lc, T_NAME);
               if (pass == 2) {
                  res = GetResWithName(R_POOL, lc->str);
                  if (res == NULL) {
                     scan_err1(lc, _("Could not find specified Pool Resource: %s"),
                                lc->str);
                     /* NOT REACHED */
                  }
                  switch(RunFields[i].token) {
                  case 'P':
                     lrun.pool = (POOLRES *)res;
                     break;
                  case 'f':
                     lrun.full_pool = (POOLRES *)res;
                     break;
                  case 'v':
                     lrun.vfull_pool = (POOLRES *)res;
                     break;
                  case 'i':
                     lrun.inc_pool = (POOLRES *)res;
                     break;
                  case 'd':
                     lrun.diff_pool = (POOLRES *)res;
                     break;
                  case 'n':
                     lrun.next_pool = (POOLRES *)res;
                     break;
                  }
               }
               break;
            case 'S':                 /* Storage */
               token = lex_get_token(lc, T_NAME);
               if (pass == 2) {
                  res = GetResWithName(R_STORAGE, lc->str);
                  if (res == NULL) {
                     scan_err1(lc, _("Could not find specified Storage Resource: %s"),
                                lc->str);
                     /* NOT REACHED */
                  }
                  lrun.storage = (STORERES *)res;
               }
               break;
            case 'M':                 /* Messages */
               token = lex_get_token(lc, T_NAME);
               if (pass == 2) {
                  res = GetResWithName(R_MSGS, lc->str);
                  if (res == NULL) {
                     scan_err1(lc, _("Could not find specified Messages Resource: %s"),
                                lc->str);
                     /* NOT REACHED */
                  }
                  lrun.msgs = (MSGSRES *)res;
               }
               break;
            case 'm':                 /* Max run sched time */
               token = lex_get_token(lc, T_QUOTED_STRING);
               if (!duration_to_utime(lc->str, &utime)) {
                  scan_err1(lc, _("expected a time period, got: %s"), lc->str);
                  return;
               }
               lrun.MaxRunSchedTime = utime;
               lrun.MaxRunSchedTime_set = true;
               break;
            case 'a':                 /* Accurate */
               token = lex_get_token(lc, T_NAME);
               if (strcasecmp(lc->str, "yes") == 0 || strcasecmp(lc->str, "true") == 0) {
                  lrun.accurate = true;
                  lrun.accurate_set = true;
               } else if (strcasecmp(lc->str, "no") == 0 || strcasecmp(lc->str, "false") == 0) {
                  lrun.accurate = false;
                  lrun.accurate_set = true;
               } else {
                  scan_err1(lc, _("Expect a YES or NO, got: %s"), lc->str);
               }
               break;
            default:
               scan_err1(lc, _("Expected a keyword name, got: %s"), lc->str);
               /* NOT REACHED */
               break;
            } /* end switch */
         } /* end if bstrcasecmp */
      } /* end for RunFields */

      /*
       * At this point, it is not a keyword. Check for old syle
       * Job Levels without keyword. This form is depreciated!!!
       */
      if (!found) {
         for (j = 0; joblevels[j].level_name; j++) {
            if (bstrcasecmp(lc->str, joblevels[j].level_name)) {
               lrun.level = joblevels[j].level;
               lrun.job_type = joblevels[j].job_type;
               found = true;
               break;
            }
         }
      }
   } /* end for found */

   /*
    * Scan schedule times.
    * Default is: daily at 0:0
    */
   state = s_none;
   set_defaults();

   for (; token != T_EOL; (token = lex_get_token(lc, T_ALL))) {
      int len;
      bool pm = false;
      bool am = false;
      switch (token) {
      case T_NUMBER:
         state = s_mday;
         code = atoi(lc->str) - 1;
         if (code < 0 || code > 30) {
            scan_err0(lc, _("Day number out of range (1-31)"));
         }
         break;
      case T_NAME:                    /* This handles drop through from keyword */
      case T_UNQUOTED_STRING:
         if (strchr(lc->str, (int)'-')) {
            state = s_range;
            break;
         }
         if (strchr(lc->str, (int)':')) {
            state = s_time;
            break;
         }
         if (strchr(lc->str, (int)'/')) {
            state = s_modulo;
            break;
         }
         if (lc->str_len == 3 && (lc->str[0] == 'w' || lc->str[0] == 'W') &&
             is_an_integer(lc->str+1)) {
            code = atoi(lc->str+1);
            if (code < 0 || code > 53) {
               scan_err0(lc, _("Week number out of range (0-53)"));
              /* NOT REACHED */
            }
            state = s_woy;            /* Week of year */
            break;
         }
         /*
          * Everything else must be a keyword
          */
         for (i = 0; keyw[i].name; i++) {
            if (bstrcasecmp(lc->str, keyw[i].name)) {
               state = keyw[i].state;
               code   = keyw[i].code;
               i = 0;
               break;
            }
         }
         if (i != 0) {
            scan_err1(lc, _("Job type field: %s in run record not found"), lc->str);
            /* NOT REACHED */
         }
         break;
      case T_COMMA:
         continue;
      default:
         scan_err2(lc, _("Unexpected token: %d:%s"), token, lc->str);
         /* NOT REACHED */
         break;
      }
      switch (state) {
      case s_none:
         continue;
      case s_mday:                    /* Day of month */
         if (!have_mday) {
            clear_bits(0, 30, lrun.mday);
            have_mday = true;
         }
         set_bit(code, lrun.mday);
         break;
      case s_month:                   /* Month of year */
         if (!have_month) {
            clear_bits(0, 11, lrun.month);
            have_month = true;
         }
         set_bit(code, lrun.month);
         break;
      case s_wday:                    /* Week day */
         if (!have_wday) {
            clear_bits(0, 6, lrun.wday);
            have_wday = true;
         }
         set_bit(code, lrun.wday);
         break;
      case s_wom:                     /* Week of month 1st, ... */
         if (!have_wom) {
            clear_bits(0, 4, lrun.wom);
            have_wom = true;
         }
         set_bit(code, lrun.wom);
         break;
      case s_woy:
         if (!have_woy) {
            clear_bits(0, 53, lrun.woy);
            have_woy = true;
         }
         set_bit(code, lrun.woy);
         break;
      case s_time:                    /* Time */
         if (!have_at) {
            scan_err0(lc, _("Time must be preceded by keyword AT."));
            /* NOT REACHED */
         }
         if (!have_hour) {
            clear_bits(0, 23, lrun.hour);
         }
//       Dmsg1(000, "s_time=%s\n", lc->str);
         p = strchr(lc->str, ':');
         if (!p)  {
            scan_err0(lc, _("Time logic error.\n"));
            /* NOT REACHED */
         }
         *p++ = 0;                    /* Separate two halves */
         code = atoi(lc->str);        /* Pick up hour */
         code2 = atoi(p);             /* Pick up minutes */
         len = strlen(p);
         if (len >= 2) {
            p += 2;
         }
         if (bstrcasecmp(p, "pm")) {
            pm = true;
         } else if (bstrcasecmp(p, "am")) {
            am = true;
         } else if (len != 2) {
            scan_err0(lc, _("Bad time specification."));
            /* NOT REACHED */
         }
         /*
          * Note, according to NIST, 12am and 12pm are ambiguous and
          *  can be defined to anything.  However, 12:01am is the same
          *  as 00:01 and 12:01pm is the same as 12:01, so we define
          *  12am as 00:00 and 12pm as 12:00.
          */
         if (pm) {
            /*
             * Convert to 24 hour time
             */
            if (code != 12) {
               code += 12;
            }
         } else if (am && code == 12) {
            /*
             * AM
             */
            code -= 12;
         }
         if (code < 0 || code > 23 || code2 < 0 || code2 > 59) {
            scan_err0(lc, _("Bad time specification."));
            /* NOT REACHED */
         }
         set_bit(code, lrun.hour);
         lrun.minute = code2;
         have_hour = true;
         break;
      case s_at:
         have_at = true;
         break;
      case s_last:
         lrun.last_set = true;
         if (!have_wom) {
            clear_bits(0, 4, lrun.wom);
            have_wom = true;
         }
         break;
      case s_modulo:
         p = strchr(lc->str, '/');
         if (!p) {
            scan_err0(lc, _("Modulo logic error.\n"));
         }
         *p++ = 0;                 /* Separate two halves */

         if (is_an_integer(lc->str) && is_an_integer(p)) {
            /*
             * Check for day modulo specification.
             */
            code = atoi(lc->str) - 1;
            code2 = atoi(p);
            if (code < 0 || code > 30 || code2 < 0 || code2 > 30) {
               scan_err0(lc, _("Bad day specification in modulo."));
            }
            if (code > code2) {
               scan_err0(lc, _("Bad day specification, offset must always be <= than modulo."));
            }
            if (!have_mday) {
               clear_bits(0, 30, lrun.mday);
               have_mday = true;
            }
            /*
             * Set the bits according to the modulo specification.
             */
            for (i = 0; i < 31; i++) {
               if (i % code2 == 0) {
                  set_bit(i + code, lrun.mday);
               }
            }
         } else if (strlen(lc->str) == 3 && strlen(p) == 3 &&
                   (lc->str[0] == 'w' || lc->str[0] == 'W') &&
                   (p[0] == 'w' || p[0] == 'W') &&
                    is_an_integer(lc->str + 1) &&
                    is_an_integer(p + 1)) {
            /*
             * Check for week modulo specification.
             */
            code = atoi(lc->str + 1);
            code2 = atoi(p + 1);
            if (code < 0 || code > 53 || code2 < 0 || code2 > 53) {
               scan_err0(lc, _("Week number out of range (0-53) in modulo"));
            }
            if (code > code2) {
               scan_err0(lc, _("Bad week number specification in modulo, offset must always be <= than modulo."));
            }
            if (!have_woy) {
               clear_bits(0, 53, lrun.woy);
               have_woy = true;
            }
            /*
             * Set the bits according to the modulo specification.
             */
            for (i = 0; i < 54; i++) {
               if (i % code2 == 0) {
                  set_bit(i + code - 1, lrun.woy);
               }
            }
         } else {
            scan_err0(lc, _("Bad modulo time specification. Format for weekdays is '01/02', for yearweeks is 'w01/w02'."));
         }
         break;
      case s_range:
         p = strchr(lc->str, '-');
         if (!p) {
            scan_err0(lc, _("Range logic error.\n"));
         }
         *p++ = 0;                    /* Separate two halves */

         if (is_an_integer(lc->str) && is_an_integer(p)) {
            /*
             * Check for day range.
             */
            code = atoi(lc->str) - 1;
            code2 = atoi(p) - 1;
            if (code < 0 || code > 30 || code2 < 0 || code2 > 30) {
               scan_err0(lc, _("Bad day range specification."));
            }
            if (!have_mday) {
               clear_bits(0, 30, lrun.mday);
               have_mday = true;
            }
            if (code < code2) {
               set_bits(code, code2, lrun.mday);
            } else {
               set_bits(code, 30, lrun.mday);
               set_bits(0, code2, lrun.mday);
            }
         } else if (strlen(lc->str) == 3 && strlen(p) == 3 &&
                   (lc->str[0] == 'w' || lc->str[0] == 'W') &&
                   (p[0] == 'w' || p[0] == 'W') &&
                    is_an_integer(lc->str + 1) &&
                    is_an_integer(p + 1)) {
            /*
             * Check for week of year range.
             */
            code = atoi(lc->str + 1);
            code2 = atoi(p + 1);
            if (code < 0 || code > 53 || code2 < 0 || code2 > 53) {
               scan_err0(lc, _("Week number out of range (0-53)"));
            }
            if (!have_woy) {
               clear_bits(0, 53, lrun.woy);
               have_woy = true;
            }
            if (code < code2) {
               set_bits(code, code2, lrun.woy);
            } else {
               set_bits(code, 53, lrun.woy);
               set_bits(0, code2, lrun.woy);
            }
         } else {
            /*
             * lookup first half of keyword range (week days or months).
             */
            lcase(lc->str);
            for (i = 0; keyw[i].name; i++) {
               if (bstrcmp(lc->str, keyw[i].name)) {
                  state = keyw[i].state;
                  code = keyw[i].code;
                  i = 0;
                  break;
               }
            }
            if (i != 0 || (state != s_month && state != s_wday && state != s_wom)) {
               scan_err0(lc, _("Invalid month, week or position day range"));
               /* NOT REACHED */
            }

            /*
             * Lookup end of range.
             */
            lcase(p);
            for (i = 0; keyw[i].name; i++) {
               if (bstrcmp(p, keyw[i].name)) {
                  state2 = keyw[i].state;
                  code2 = keyw[i].code;
                  i = 0;
                  break;
               }
            }
            if (i != 0 || state != state2 || code == code2) {
               scan_err0(lc, _("Invalid month, weekday or position range"));
               /* NOT REACHED */
            }
            if (state == s_wday) {
               if (!have_wday) {
                  clear_bits(0, 6, lrun.wday);
                  have_wday = true;
               }
               if (code < code2) {
                  set_bits(code, code2, lrun.wday);
               } else {
                  set_bits(code, 6, lrun.wday);
                  set_bits(0, code2, lrun.wday);
               }
            } else if (state == s_month) {
               if (!have_month) {
                  clear_bits(0, 11, lrun.month);
                  have_month = true;
               }
               if (code < code2) {
                  set_bits(code, code2, lrun.month);
               } else {
                  /*
                   * This is a bit odd, but we accept it anyway
                   */
                  set_bits(code, 11, lrun.month);
                  set_bits(0, code2, lrun.month);
               }
            } else {
               /*
                * Must be position
                */
               if (!have_wom) {
                  clear_bits(0, 4, lrun.wom);
                  have_wom = true;
               }
               if (code < code2) {
                  set_bits(code, code2, lrun.wom);
               } else {
                  set_bits(code, 4, lrun.wom);
                  set_bits(0, code2, lrun.wom);
               }
            }
         }
         break;
      case s_hourly:
         have_hour = true;
         set_bits(0, 23, lrun.hour);
         break;
      case s_weekly:
         have_mday = have_wom = have_woy = true;
         set_bits(0, 30, lrun.mday);
         set_bits(0, 4,  lrun.wom);
         set_bits(0, 53, lrun.woy);
         break;
      case s_daily:
         have_mday = true;
         set_bits(0, 6, lrun.wday);
         break;
      case s_monthly:
         have_month = true;
         set_bits(0, 11, lrun.month);
         break;
      default:
         scan_err0(lc, _("Unexpected run state\n"));
         /* NOT REACHED */
         break;
      }
   }

   /* Allocate run record, copy new stuff into it,
    * and append it to the list of run records
    * in the schedule resource.
    */
   if (pass == 2) {
      RUNRES *tail;

      /* Create new run record */
      RUNRES *nrun = (RUNRES *)malloc(sizeof(RUNRES));
      memcpy(nrun, &lrun, sizeof(RUNRES));
      nrun ->next = NULL;

      if (!*run) {                       /* If empty list */
         *run = nrun;                    /* Add new record */
      } else {
         for (tail = *run; tail->next; tail=tail->next)
            {  }
         tail->next = nrun;
      }
   }

   lc->options = options;                /* Restore scanner options */
   set_bit(index, res_all->res_sch.hdr.item_present);
   clear_bit(index, res_all->hdr.inherit_content);
}
Esempio n. 18
0
   argc -= optind;
   argv += optind;

   config = new_config_parser();
   parse_dir_config(config, configfile, M_ERROR_TERM);

   MSGS *msg;

   foreach_res(msg, R_MSGS)
   {
      init_msg(NULL, msg);
   }

   jcr = new_jcr(sizeof(JCR), NULL);
   jcr->fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);

   if (jcr->fileset == NULL) {
      fprintf(stderr, "%s: Fileset not found\n", fileset_name);

      FILESET *var;

      fprintf(stderr, "Valid FileSets:\n");
      
      foreach_res(var, R_FILESET) {
         fprintf(stderr, "    %s\n", var->hdr.name);
      }

      exit(1);
   }
Esempio n. 19
0
   argc -= optind;
   argv += optind;

   my_config = new_config_parser();
   parse_dir_config(my_config, configfile, M_ERROR_TERM);

   MSGSRES *msg;

   foreach_res(msg, R_MSGS)
   {
      init_msg(NULL, msg);
   }

   jcr = new_jcr(sizeof(JCR), NULL);
   jcr->res.fileset = (FILESETRES *)GetResWithName(R_FILESET, fileset_name);

   if (jcr->res.fileset == NULL) {
      fprintf(stderr, "%s: Fileset not found\n", fileset_name);

      FILESETRES *var;

      fprintf(stderr, "Valid FileSets:\n");

      foreach_res(var, R_FILESET) {
         fprintf(stderr, "    %s\n", var->hdr.name);
      }

      exit(1);
   }
Esempio n. 20
0
static bool list_nextvol(UAContext *ua, int ndays)
{
   JOBRES *job;
   JCR *jcr;
   USTORERES store;
   RUNRES *run;
   utime_t runtime;
   bool found = false;
   MEDIA_DBR mr;
   POOL_DBR pr;

   int i = find_arg_with_value(ua, "job");
   if (i <= 0) {
      if ((job = select_job_resource(ua)) == NULL) {
         return false;
      }
   } else {
      job = (JOBRES *)GetResWithName(R_JOB, ua->argv[i]);
      if (!job) {
         Jmsg(ua->jcr, M_ERROR, 0, _("%s is not a job name.\n"), ua->argv[i]);
         if ((job = select_job_resource(ua)) == NULL) {
            return false;
         }
      }
   }

   jcr = new_jcr(sizeof(JCR), dird_free_jcr);
   for (run=NULL; (run = find_next_run(run, job, runtime, ndays)); ) {
      if (!complete_jcr_for_job(jcr, job, run->pool)) {
         found = false;
         goto get_out;
      }
      if (!jcr->jr.PoolId) {
         ua->error_msg(_("Could not find Pool for Job %s\n"), job->name());
         continue;
      }
      memset(&pr, 0, sizeof(pr));
      pr.PoolId = jcr->jr.PoolId;
      if (!db_get_pool_record(jcr, jcr->db, &pr)) {
         bstrncpy(pr.Name, "*UnknownPool*", sizeof(pr.Name));
      }
      mr.PoolId = jcr->jr.PoolId;
      get_job_storage(&store, job, run);
      set_storageid_in_mr(store.store, &mr);
      /* no need to set ScratchPoolId, since we use fnv_no_create_vol */
      if (!find_next_volume_for_append(jcr, &mr, 1, fnv_no_create_vol, fnv_prune)) {
         ua->error_msg(_("Could not find next Volume for Job %s (Pool=%s, Level=%s).\n"),
            job->name(), pr.Name, level_to_str(run->level));
      } else {
         ua->send_msg(
            _("The next Volume to be used by Job \"%s\" (Pool=%s, Level=%s) will be %s\n"),
            job->name(), pr.Name, level_to_str(run->level), mr.VolumeName);
         found = true;
      }
   }

get_out:
   if (jcr->db) {
      db_sql_close_pooled_connection(jcr, jcr->db);
      jcr->db = NULL;
   }
   free_jcr(jcr);
   if (!found) {
      ua->error_msg(_("Could not find next Volume for Job %s.\n"),
         job->hdr.name);
      return false;
   }
   return true;
}
Esempio n. 21
0
/*
 * The first step in the restore process is for the user to
 *  select a list of JobIds from which he will subsequently
 *  select which files are to be restored.
 *
 *  Returns:  2  if filename list made
 *            1  if jobid list made
 *            0  on error
 */
static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
{
   char *p;
   char date[MAX_TIME_LENGTH];
   bool have_date = false;
   /* Include current second if using current time */
   utime_t now = time(NULL) + 1;
   JobId_t JobId;
   JOB_DBR jr = { (JobId_t)-1 };
   bool done = false;
   int i, j;
   const char *list[] = {
      _("List last 20 Jobs run"),
      _("List Jobs where a given File is saved"),
      _("Enter list of comma separated JobIds to select"),
      _("Enter SQL list command"),
      _("Select the most recent backup for a client"),
      _("Select backup for a client before a specified time"),
      _("Enter a list of files to restore"),
      _("Enter a list of files to restore before a specified time"),
      _("Find the JobIds of the most recent backup for a client"),
      _("Find the JobIds for a backup for a client before a specified time"),
      _("Enter a list of directories to restore for found JobIds"),
      _("Select full restore to a specified Job date"),
      _("Cancel"),
      NULL
   };

   const char *kw[] = {
       /*
        * These keywords are handled in a for loop
        */
      "jobid",         /* 0 */
      "current",       /* 1 */
      "before",        /* 2 */
      "file",          /* 3 */
      "directory",     /* 4 */
      "select",        /* 5 */
      "pool",          /* 6 */
      "all",           /* 7 */

      /*
       * The keyword below are handled by individual arg lookups
       */
      "client",        /* 8 */
      "storage",       /* 9 */
      "fileset",       /* 10 */
      "where",         /* 11 */
      "yes",           /* 12 */
      "bootstrap",     /* 13 */
      "done",          /* 14 */
      "strip_prefix",  /* 15 */
      "add_prefix",    /* 16 */
      "add_suffix",    /* 17 */
      "regexwhere",    /* 18 */
      "restoreclient", /* 19 */
      "copies",        /* 20 */
      "comment",       /* 21 */
      "restorejob",    /* 22 */
      "replace",       /* 23 */
      "pluginoptions", /* 24 */
      NULL
   };

   rx->JobIds[0] = 0;

   for (i = 1; i<ua->argc; i++) {        /* loop through arguments */
      bool found_kw = false;
      for (j = 0; kw[j]; j++) {          /* loop through keywords */
         if (bstrcasecmp(kw[j], ua->argk[i])) {
            found_kw = true;
            break;
         }
      }
      if (!found_kw) {
         ua->error_msg(_("Unknown keyword: %s\n"), ua->argk[i]);
         return 0;
      }
      /* Found keyword in kw[] list, process it */
      switch (j) {
      case 0:                            /* jobid */
         if (!has_value(ua, i)) {
            return 0;
         }
         if (*rx->JobIds != 0) {
            pm_strcat(rx->JobIds, ",");
         }
         pm_strcat(rx->JobIds, ua->argv[i]);
         done = true;
         break;
      case 1:                            /* current */
         /*
          * Note, we add one second here just to include any job
          *  that may have finished within the current second,
          *  which happens a lot in scripting small jobs.
          */
         bstrutime(date, sizeof(date), now);
         have_date = true;
         break;
      case 2:                            /* before */
         if (have_date || !has_value(ua, i)) {
            return 0;
         }
         if (str_to_utime(ua->argv[i]) == 0) {
            ua->error_msg(_("Improper date format: %s\n"), ua->argv[i]);
            return 0;
         }
         bstrncpy(date, ua->argv[i], sizeof(date));
         have_date = true;
         break;
      case 3:                            /* file */
      case 4:                            /* dir */
         if (!has_value(ua, i)) {
            return 0;
         }
         if (!have_date) {
            bstrutime(date, sizeof(date), now);
         }
         if (!get_client_name(ua, rx)) {
            return 0;
         }
         pm_strcpy(ua->cmd, ua->argv[i]);
         insert_one_file_or_dir(ua, rx, date, j==4);
         return 2;
      case 5:                            /* select */
         if (!have_date) {
            bstrutime(date, sizeof(date), now);
         }
         if (!select_backups_before_date(ua, rx, date)) {
            return 0;
         }
         done = true;
         break;
      case 6:                            /* pool specified */
         if (!has_value(ua, i)) {
            return 0;
         }
         rx->pool = (POOLRES *)GetResWithName(R_POOL, ua->argv[i]);
         if (!rx->pool) {
            ua->error_msg(_("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]);
            return 0;
         }
         if (!acl_access_ok(ua, Pool_ACL, ua->argv[i], true)) {
            rx->pool = NULL;
            ua->error_msg(_("Error: Pool resource \"%s\" access not allowed.\n"), ua->argv[i]);
            return 0;
         }
         break;
      case 7:                         /* all specified */
         rx->all = true;
         break;
      default:
         /*
          * All keywords 7 or greater are ignored or handled by a select prompt
          */
         break;
      }
   }

   if (!done) {
      ua->send_msg(_("\nFirst you select one or more JobIds that contain files\n"
                  "to be restored. You will be presented several methods\n"
                  "of specifying the JobIds. Then you will be allowed to\n"
                  "select which files from those JobIds are to be restored.\n\n"));
   }

   /* If choice not already made above, prompt */
   for ( ; !done; ) {
      char *fname;
      int len;
      bool gui_save;
      db_list_ctx jobids;

      start_prompt(ua, _("To select the JobIds, you have the following choices:\n"));
      for (int i=0; list[i]; i++) {
         add_prompt(ua, list[i]);
      }
      done = true;
      switch (do_prompt(ua, "", _("Select item: "), NULL, 0)) {
      case -1:                        /* error or cancel */
         return 0;
      case 0:                         /* list last 20 Jobs run */
         if (!acl_access_ok(ua, Command_ACL, NT_("sqlquery"), true)) {
            ua->error_msg(_("SQL query not authorized.\n"));
            return 0;
         }
         gui_save = ua->jcr->gui;
         ua->jcr->gui = true;
         db_list_sql_query(ua->jcr, ua->db, uar_list_jobs, ua->send, HORZ_LIST, true);
         ua->jcr->gui = gui_save;
         done = false;
         break;
      case 1:                         /* list where a file is saved */
         if (!get_client_name(ua, rx)) {
            return 0;
         }
         if (!get_cmd(ua, _("Enter Filename (no path):"))) {
            return 0;
         }
         len = strlen(ua->cmd);
         fname = (char *)malloc(len * 2 + 1);
         db_escape_string(ua->jcr, ua->db, fname, ua->cmd, len);
         Mmsg(rx->query, uar_file[db_get_type_index(ua->db)], rx->ClientName, fname);
         free(fname);
         gui_save = ua->jcr->gui;
         ua->jcr->gui = true;
         db_list_sql_query(ua->jcr, ua->db, rx->query, ua->send, HORZ_LIST, true);
         ua->jcr->gui = gui_save;
         done = false;
         break;
      case 2:                         /* enter a list of JobIds */
         if (!get_cmd(ua, _("Enter JobId(s), comma separated, to restore: "))) {
            return 0;
         }
         pm_strcpy(rx->JobIds, ua->cmd);
         break;
      case 3:                         /* Enter an SQL list command */
         if (!acl_access_ok(ua, Command_ACL, NT_("sqlquery"), true)) {
            ua->error_msg(_("SQL query not authorized.\n"));
            return 0;
         }
         if (!get_cmd(ua, _("Enter SQL list command: "))) {
            return 0;
         }
         gui_save = ua->jcr->gui;
         ua->jcr->gui = true;
         db_list_sql_query(ua->jcr, ua->db, ua->cmd, ua->send, HORZ_LIST, true);
         ua->jcr->gui = gui_save;
         done = false;
         break;
      case 4:                         /* Select the most recent backups */
         if (!have_date) {
            bstrutime(date, sizeof(date), now);
         }
         if (!select_backups_before_date(ua, rx, date)) {
            return 0;
         }
         break;
      case 5:                         /* select backup at specified time */
         if (!have_date) {
            if (!get_date(ua, date, sizeof(date))) {
               return 0;
            }
         }
         if (!select_backups_before_date(ua, rx, date)) {
            return 0;
         }
         break;
      case 6:                         /* Enter files */
         if (!have_date) {
            bstrutime(date, sizeof(date), now);
         }
         if (!get_client_name(ua, rx)) {
            return 0;
         }
         ua->send_msg(_("Enter file names with paths, or < to enter a filename\n"
                        "containing a list of file names with paths, and terminate\n"
                        "them with a blank line.\n"));
         for ( ;; ) {
            if (!get_cmd(ua, _("Enter full filename: "))) {
               return 0;
            }
            len = strlen(ua->cmd);
            if (len == 0) {
               break;
            }
            insert_one_file_or_dir(ua, rx, date, false);
         }
         return 2;
       case 7:                        /* enter files backed up before specified time */
         if (!have_date) {
            if (!get_date(ua, date, sizeof(date))) {
               return 0;
            }
         }
         if (!get_client_name(ua, rx)) {
            return 0;
         }
         ua->send_msg(_("Enter file names with paths, or < to enter a filename\n"
                        "containing a list of file names with paths, and terminate\n"
                        "them with a blank line.\n"));
         for ( ;; ) {
            if (!get_cmd(ua, _("Enter full filename: "))) {
               return 0;
            }
            len = strlen(ua->cmd);
            if (len == 0) {
               break;
            }
            insert_one_file_or_dir(ua, rx, date, false);
         }
         return 2;

      case 8:                         /* Find JobIds for current backup */
         if (!have_date) {
            bstrutime(date, sizeof(date), now);
         }
         if (!select_backups_before_date(ua, rx, date)) {
            return 0;
         }
         done = false;
         break;

      case 9:                         /* Find JobIds for give date */
         if (!have_date) {
            if (!get_date(ua, date, sizeof(date))) {
               return 0;
            }
         }
         if (!select_backups_before_date(ua, rx, date)) {
            return 0;
         }
         done = false;
         break;

      case 10:                        /* Enter directories */
         if (*rx->JobIds != 0) {
            ua->send_msg(_("You have already selected the following JobIds: %s\n"),
               rx->JobIds);
         } else if (get_cmd(ua, _("Enter JobId(s), comma separated, to restore: "))) {
            if (*rx->JobIds != 0 && *ua->cmd) {
               pm_strcat(rx->JobIds, ",");
            }
            pm_strcat(rx->JobIds, ua->cmd);
         }
         if (*rx->JobIds == 0 || *rx->JobIds == '.') {
            *rx->JobIds = 0;
            return 0;                 /* nothing entered, return */
         }
         if (!have_date) {
            bstrutime(date, sizeof(date), now);
         }
         if (!get_client_name(ua, rx)) {
            return 0;
         }
         ua->send_msg(_("Enter full directory names or start the name\n"
                        "with a < to indicate it is a filename containing a list\n"
                        "of directories and terminate them with a blank line.\n"));
         for ( ;; ) {
            if (!get_cmd(ua, _("Enter directory name: "))) {
               return 0;
            }
            len = strlen(ua->cmd);
            if (len == 0) {
               break;
            }
            /* Add trailing slash to end of directory names */
            if (ua->cmd[0] != '<' && !IsPathSeparator(ua->cmd[len-1])) {
               strcat(ua->cmd, "/");
            }
            insert_one_file_or_dir(ua, rx, date, true);
         }
         return 2;

      case 11:                        /* Choose a jobid and select jobs */
         if (!get_cmd(ua, _("Enter JobId to get the state to restore: ")) ||
             !is_an_integer(ua->cmd))
         {
            return 0;
         }

         memset(&jr, 0, sizeof(jr));
         jr.JobId = str_to_int64(ua->cmd);
         if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
            ua->error_msg(_("Unable to get Job record for JobId=%s: ERR=%s\n"),
                          ua->cmd, db_strerror(ua->db));
            return 0;
         }
         ua->send_msg(_("Selecting jobs to build the Full state at %s\n"),
                      jr.cStartTime);
         jr.JobLevel = L_INCREMENTAL; /* Take Full+Diff+Incr */
         if (!db_accurate_get_jobids(ua->jcr, ua->db, &jr, &jobids)) {
            return 0;
         }
         pm_strcpy(rx->JobIds, jobids.list);
         Dmsg1(30, "Item 12: jobids = %s\n", rx->JobIds);
         break;
      case 12:                        /* Cancel or quit */
         return 0;
      }
   }

   memset(&jr, 0, sizeof(jr));
   POOLMEM *JobIds = get_pool_memory(PM_FNAME);
   *JobIds = 0;
   rx->TotalFiles = 0;
   /*
    * Find total number of files to be restored, and filter the JobId
    *  list to contain only ones permitted by the ACL conditions.
    */
   for (p=rx->JobIds; ; ) {
      char ed1[50];
      int status = get_next_jobid_from_list(&p, &JobId);
      if (status < 0) {
         ua->error_msg(_("Invalid JobId in list.\n"));
         free_pool_memory(JobIds);
         return 0;
      }
      if (status == 0) {
         break;
      }
      if (jr.JobId == JobId) {
         continue;                    /* duplicate of last JobId */
      }
      memset(&jr, 0, sizeof(jr));
      jr.JobId = JobId;
      if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
         ua->error_msg(_("Unable to get Job record for JobId=%s: ERR=%s\n"),
            edit_int64(JobId, ed1), db_strerror(ua->db));
         free_pool_memory(JobIds);
         return 0;
      }
      if (!acl_access_ok(ua, Job_ACL, jr.Name, true)) {
         ua->error_msg(_("Access to JobId=%s (Job \"%s\") not authorized. Not selected.\n"),
            edit_int64(JobId, ed1), jr.Name);
         continue;
      }
      if (*JobIds != 0) {
         pm_strcat(JobIds, ",");
      }
      pm_strcat(JobIds, edit_int64(JobId, ed1));
      rx->TotalFiles += jr.JobFiles;
   }
   free_pool_memory(rx->JobIds);
   rx->JobIds = JobIds;               /* Set ACL filtered list */
   if (*rx->JobIds == 0) {
      ua->warning_msg(_("No Jobs selected.\n"));
      return 0;
   }

   if (strchr(rx->JobIds,',')) {
      ua->info_msg(_("You have selected the following JobIds: %s\n"), rx->JobIds);
   } else {
      ua->info_msg(_("You have selected the following JobId: %s\n"), rx->JobIds);
   }
   return true;
}
Esempio n. 22
0
/*
 * Do a verification of the specified files against the Catlaog
 *
 *  Returns:  false on failure
 *            true  on success
 */
bool do_verify(JCR *jcr)
{
   const char *level;
   BSOCK *fd, *sd;
   int stat;
   char ed1[100];
   JOB_DBR jr;
   JobId_t verify_jobid = 0;
   char *store_address;
   uint32_t store_port;
   const char *Name;

   free_wstorage(jcr);                   /* we don't write */

   memset(&jcr->previous_jr, 0, sizeof(jcr->previous_jr));

   /*
    * Find JobId of last job that ran. Note, we do this when
    *   the job actually starts running, not at schedule time,
    *   so that we find the last job that terminated before
    *   this job runs rather than before it is scheduled. This
    *   permits scheduling a Backup and Verify at the same time,
    *   but with the Verify at a lower priority.
    *
    *   For VERIFY_CATALOG we want the JobId of the last INIT.
    *   For VERIFY_VOLUME_TO_CATALOG, we want the JobId of the
    *       last backup Job.
    */
   if (jcr->getJobLevel() == L_VERIFY_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_DISK_TO_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_DATA) {
      memcpy(&jr, &jcr->jr, sizeof(jr));
      if (jcr->verify_job &&
          (jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG ||
           jcr->getJobLevel() == L_VERIFY_DISK_TO_CATALOG   ||
           jcr->getJobLevel() == L_VERIFY_DATA)) {
         Name = jcr->verify_job->name();
      } else {
         Name = NULL;
      }
      Dmsg1(100, "find last jobid for: %s\n", NPRT(Name));

      /* see if user supplied a jobid= as run argument or from menu */
      if (jcr->RestoreJobId) {
         verify_jobid = jcr->RestoreJobId;
         Dmsg1(100, "Supplied jobid=%d\n", verify_jobid);

      } else {
         if (!db_find_last_jobid(jcr, jcr->db, Name, &jr)) {
            if (jcr->getJobLevel() == L_VERIFY_CATALOG) {
               Jmsg(jcr, M_FATAL, 0, _(
                       "Unable to find JobId of previous InitCatalog Job.\n"
                       "Please run a Verify with Level=InitCatalog before\n"
                       "running the current Job.\n"));
            } else {
               Jmsg(jcr, M_FATAL, 0, _(
                       "Unable to find JobId of previous Job for this client.\n"));
            }
            return false;
         }
         verify_jobid = jr.JobId;
      }
      Dmsg1(100, "Last full jobid=%d\n", verify_jobid);
   }
   /*
    * Now get the job record for the previous backup that interests
    *   us. We use the verify_jobid that we found above.
    */
   if (jcr->getJobLevel() == L_VERIFY_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_DISK_TO_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_DATA) {
      jcr->previous_jr.JobId = verify_jobid;
      if (!db_get_job_record(jcr, jcr->db, &jcr->previous_jr)) {
         Jmsg(jcr, M_FATAL, 0, _("Could not get job record for previous Job. ERR=%s"),
              db_strerror(jcr->db));
         return false;
      }
      if (!(jcr->previous_jr.JobStatus == JS_Terminated ||
            jcr->previous_jr.JobStatus == JS_Warnings)) {
         Jmsg(jcr, M_FATAL, 0, _("Last Job %d did not terminate normally. JobStatus=%c\n"),
            verify_jobid, jcr->previous_jr.JobStatus);
         return false;
      }
      Jmsg(jcr, M_INFO, 0, _("Verifying against JobId=%d Job=%s\n"),
         jcr->previous_jr.JobId, jcr->previous_jr.Job);
   }

   /*
    * If we are verifying a Volume, we need the Storage
    *   daemon, so open a connection, otherwise, just
    *   create a dummy authorization key (passed to
    *   File daemon but not used).
    */
   if (jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG || jcr->getJobLevel() == L_VERIFY_DATA) {
      int stat;
      /*
       * Note: negative status is an error, zero status, means
       *  no files were backed up, so skip calling SD and
       *  client.
       */
      stat = create_restore_bootstrap_file(jcr);
      if (stat < 0) {                      /* error */
         return false;
      } else if (stat == 0) {              /* No files, nothing to do */
         verify_cleanup(jcr, JS_Terminated); /* clean up */
         return true;                      /* get out */
      }
   } else {
      jcr->sd_auth_key = bstrdup("dummy");    /* dummy Storage daemon key */
   }

   /* Pass the original fileset to the client */
   if (jcr->getJobLevel() == L_VERIFY_DATA) {
      FILESET_DBR fdbr;
      memset(&fdbr, 0, sizeof(fdbr));
      fdbr.FileSetId = jcr->previous_jr.FileSetId;
      if (!db_get_fileset_record(jcr, jcr->db, &fdbr)) {
         Jmsg(jcr, M_FATAL, 0,
              _("Could not get fileset record from previous Job. ERR=%s"),
              db_strerror(jcr->db));
         return false;
      }

      jcr->fileset = (FILESET *)GetResWithName(R_FILESET, fdbr.FileSet);
      if (!jcr->fileset) {
         if (jcr->verify_job) {
            jcr->fileset = jcr->verify_job->fileset;
            Jmsg(jcr, M_WARNING, 0,
                 _("Could not find FileSet resource \"%s\" from previous Job\n"),
                 fdbr.FileSet);
            Jmsg(jcr, M_INFO, 0,
                 _("Using FileSet \"%\"\n"), jcr->fileset->name());

         } else {
            Jmsg(jcr, M_FATAL, 0,
                 _("Could not get FileSet resource for verify Job."));
            return false;
         }
      }
      Dmsg1(50, "FileSet = %s\n", jcr->fileset->name());
   }

   /* Pass the current fileset to the client */
   if (jcr->getJobLevel() == L_VERIFY_DISK_TO_CATALOG && jcr->verify_job) {
      jcr->fileset = jcr->verify_job->fileset;
   }
   Dmsg2(100, "ClientId=%u JobLevel=%c\n",
         jcr->previous_jr.ClientId, jcr->getJobLevel());

   if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
      Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
      return false;
   }

   /* Print Job Start message */
   Jmsg(jcr, M_INFO, 0, _("Start Verify JobId=%s Level=%s Job=%s\n"),
      edit_uint64(jcr->JobId, ed1), level_to_str(jcr->getJobLevel()), jcr->Job);

   if (jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_DATA)
   {
      /*
       * Start conversation with Storage daemon
       */
      jcr->setJobStatus(JS_Blocked);
      if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
         return false;
      }
      /*
       * Now start a job with the Storage daemon
       */
      if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
         return false;
      }
      sd = jcr->store_bsock;
      jcr->sd_calls_client = jcr->client->sd_calls_client;
      /*
       * Send the bootstrap file -- what Volumes/files to restore
       */
      if (!send_bootstrap_file(jcr, sd) ||
          !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
         goto bail_out;
      }
      if (!jcr->sd_calls_client) {
         if (!run_storage_and_start_message_thread(jcr, sd)) {
            return false;
         }
      }
   }
   /*
    * OK, now connect to the File daemon
    *  and ask him for the files.
    */
   jcr->setJobStatus(JS_Blocked);
   if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
      goto bail_out;
   }

   jcr->setJobStatus(JS_Running);
   fd = jcr->file_bsock;


   Dmsg0(30, ">filed: Send include list\n");
   if (!send_include_list(jcr)) {
      goto bail_out;
   }

   Dmsg0(30, ">filed: Send exclude list\n");
   if (!send_exclude_list(jcr)) {
      goto bail_out;
   }

   /*
    * Send Level command to File daemon, as well
    *   as the Storage address if appropriate.
    */
   switch (jcr->getJobLevel()) {
   case L_VERIFY_INIT:
      level = "init";
      break;
   case L_VERIFY_CATALOG:
      level = "catalog";
      break;
   case L_VERIFY_DATA:
   case L_VERIFY_VOLUME_TO_CATALOG:
      if (jcr->sd_calls_client) {
         if (jcr->FDVersion < 10) {
            Jmsg(jcr, M_FATAL, 0, _("The File daemon does not support SDCallsClient.\n"));
            goto bail_out;
         }

         if (!send_client_addr_to_sd(jcr)) {
            goto bail_out;
         }

         if (!run_storage_and_start_message_thread(jcr, jcr->store_bsock)) {
            return false;
         }
         store_address = jcr->rstore->address;  /* dummy */
         store_port = 0;           /* flag that SD calls FD */
      } else {
         /*
          * send Storage daemon address to the File daemon
          */
         if (jcr->rstore->SDDport == 0) {
            jcr->rstore->SDDport = jcr->rstore->SDport;
         }

         store_address = get_storage_address(jcr->client, jcr->rstore);
         store_port = jcr->rstore->SDDport;
      }

      if (!send_store_addr_to_fd(jcr, jcr->rstore, store_address, store_port)) {
         goto bail_out;
      }

      if (!jcr->RestoreBootstrap) {
         Jmsg0(jcr, M_FATAL, 0, _("Deprecated feature ... use bootstrap.\n"));
         goto bail_out;
      }
      if (jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG) {
         level = "volume";
      } else {
         level = "data";
      }
      break;
   case L_VERIFY_DISK_TO_CATALOG:
      level="disk_to_catalog";
      break;
   default:
      Jmsg2(jcr, M_FATAL, 0, _("Unimplemented Verify level %d(%c)\n"),
            jcr->getJobLevel(),
            jcr->getJobLevel());
      goto bail_out;
   }

   if (!send_runscripts_commands(jcr)) {
      goto bail_out;
   }

   /*
    * Send verify command/level to File daemon
    */
   fd->fsend(verifycmd, level);
   if (!response(jcr, fd, OKverify, "Verify", DISPLAY_ERROR)) {
      goto bail_out;
   }

   /*
    * Now get data back from File daemon and
    *  compare it to the catalog or store it in the
    *  catalog depending on the run type.
    */
   /* Compare to catalog */
   switch (jcr->getJobLevel()) {
   case L_VERIFY_CATALOG:
      Dmsg0(10, "Verify level=catalog\n");
      jcr->sd_msg_thread_done = true;   /* no SD msg thread, so it is done */
      jcr->SDJobStatus = JS_Terminated;
      get_attributes_and_compare_to_catalog(jcr, jcr->previous_jr.JobId);
      break;

   case L_VERIFY_VOLUME_TO_CATALOG:
      Dmsg0(10, "Verify level=volume\n");
      get_attributes_and_compare_to_catalog(jcr, jcr->previous_jr.JobId);
      break;

   case L_VERIFY_DISK_TO_CATALOG:
      Dmsg0(10, "Verify level=disk_to_catalog\n");
      jcr->sd_msg_thread_done = true;   /* no SD msg thread, so it is done */
      jcr->SDJobStatus = JS_Terminated;
      get_attributes_and_compare_to_catalog(jcr, jcr->previous_jr.JobId);
      break;

   case L_VERIFY_INIT:
      /* Build catalog */
      Dmsg0(10, "Verify level=init\n");
      jcr->sd_msg_thread_done = true;   /* no SD msg thread, so it is done */
      jcr->SDJobStatus = JS_Terminated;
      get_attributes_and_put_in_catalog(jcr);
      db_end_transaction(jcr, jcr->db);   /* terminate any open transaction */
      db_write_batch_file_records(jcr);
      break;

   case L_VERIFY_DATA:
      /* Nothing special to do */
      bget_dirmsg(fd);          /* eat EOD */
      break;
   default:
      Jmsg1(jcr, M_FATAL, 0, _("Unimplemented verify level %d\n"), jcr->getJobLevel());
      goto bail_out;
   }

   stat = wait_for_job_termination(jcr);
   verify_cleanup(jcr, stat);
   return true;

bail_out:
   return false;
}
Esempio n. 23
0
/*
 * .die (seg fault)
 * .dump (sm_dump)
 * .exit (no arg => .quit)
 */
bool dot_admin_cmds(UAContext *ua, const char *cmd)
{
   pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
   STORERES *store = NULL;
   CLIENTRES *client = NULL;
   bool dir=false;
   bool do_deadlock=false;
   const char *remote_cmd;
   int i;
   JCR *jcr = NULL;
   int a;
   if (strncmp(ua->argk[0], ".die", 4) == 0) {
      if (find_arg(ua, "deadlock") > 0) {
         do_deadlock = true;
         remote_cmd = ".die deadlock";
      } else {
         remote_cmd = ".die";
      }
   } else if (strncmp(ua->argk[0], ".dump", 5) == 0) {
      remote_cmd = "sm_dump";
   } else if (strncmp(ua->argk[0], ".exit", 5) == 0) {
      remote_cmd = "exit";
   } else {
      ua->error_msg(_("Unknown command: %s\n"), ua->argk[0]);
      return true;
   }
   /* General debug? */
   for (i = 1; i < ua->argc; i++) {
      if (bstrcasecmp(ua->argk[i], "dir") ||
          bstrcasecmp(ua->argk[i], "director")) {
         dir = true;
      }
      if (bstrcasecmp(ua->argk[i], "client") ||
          bstrcasecmp(ua->argk[i], "fd")) {
         client = NULL;
         if (ua->argv[i]) {
            client = (CLIENTRES *)GetResWithName(R_CLIENT, ua->argv[i]);
         }
         if (!client) {
            client = select_client_resource(ua);
         }
      }

      if (bstrcasecmp(ua->argk[i], NT_("store")) ||
          bstrcasecmp(ua->argk[i], NT_("storage")) ||
          bstrcasecmp(ua->argk[i], NT_("sd"))) {
         store = NULL;
         if (ua->argv[i]) {
            store = (STORERES *)GetResWithName(R_STORAGE, ua->argv[i]);
         }
         if (!store) {
            store = get_storage_resource(ua);
         }
      }
   }

   if (!dir && !store && !client) {
      /*
       * We didn't find an appropriate keyword above, so
       * prompt the user.
       */
      start_prompt(ua, _("Available daemons are: \n"));
      add_prompt(ua, _("Director"));
      add_prompt(ua, _("Storage"));
      add_prompt(ua, _("Client"));
      switch(do_prompt(ua, "", _("Select daemon type to make die"), NULL, 0)) {
      case 0:                         /* Director */
         dir=true;
         break;
      case 1:
         store = get_storage_resource(ua);
         break;
      case 2:
         client = select_client_resource(ua);
         break;
      default:
         break;
      }
   }

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

   if (client) {
      do_client_cmd(ua, client, remote_cmd);
   }

   if (dir) {
      if (strncmp(remote_cmd, ".die", 4) == 0) {
         if (do_deadlock) {
            ua->send_msg(_("The Director will generate a deadlock.\n"));
            P(mutex);
            P(mutex);
         }
         ua->send_msg(_("The Director will segment fault.\n"));
         a = jcr->JobId; /* ref NULL pointer */
         jcr->JobId = 1000; /* another ref NULL pointer */
         jcr->JobId = a;

      } else if (strncmp(remote_cmd, ".dump", 5) == 0) {
         sm_dump(false, true);
      } else if (strncmp(remote_cmd, ".exit", 5) == 0) {
         quit_cmd(ua, cmd);
      }
   }

   return true;
}
Esempio n. 24
0
/*
 * To add a resource during runtime, the following approach is used:
 *
 * - Create a temporary file which contains the new resource.
 * - Use the existing parsing functions to add the new resource to the configured resources.
 *   - on error:
 *     - remove the resource and the temporary file.
 *   - on success:
 *     - move the new temporary resource file to a place, where it will also be loaded on restart
 *       (<CONFIGDIR>/bareos-dir.d/<resourcetype>/<name_of_the_resource>.conf).
 *
 * This way, the existing parsing functionality is used.
 */
static inline bool configure_add_resource(UAContext *ua, int first_parameter, RES_TABLE *res_table)
{
   POOL_MEM resource(PM_MESSAGE);
   POOL_MEM name(PM_MESSAGE);
   POOL_MEM filename_tmp(PM_FNAME);
   POOL_MEM filename(PM_FNAME);
   POOL_MEM temp(PM_FNAME);
   JOBRES *res = NULL;

   if (!configure_create_resource_string(ua, first_parameter, res_table, name, resource)) {
      return false;
   }

   if (GetResWithName(res_table->rcode, name.c_str())) {
      ua->error_msg("Resource \"%s\" with name \"%s\" already exists.\n", res_table->name, name.c_str());
      return false;
   }

   if (!my_config->get_path_of_new_resource(filename, temp, NULL, res_table->name, name.c_str(), true)) {
      ua->error_msg("%s", temp.c_str());
      return false;
   } else {
      filename_tmp.strcpy(temp);
   }

   if (!configure_write_resource(filename_tmp.c_str(), res_table->name, name.c_str(), resource.c_str())) {
      ua->error_msg("failed to write config resource file\n");
      return false;
   }

   if (!my_config->parse_config_file(filename_tmp.c_str(), ua, configure_lex_error_handler, NULL, M_ERROR)) {
      unlink(filename_tmp.c_str());
      my_config->remove_resource(res_table->rcode, name.c_str());
      return false;
   }

   /*
    * parse_config_file has already done some validation.
    * However, it skipped at least some checks for R_JOB
    * (reason: a job can get values from jobdefs,
    * and the value propagation happens after reading the full configuration)
    * therefore we explicitly check the new resource here.
    */
   if ((res_table->rcode == R_JOB) || (res_table->rcode == R_JOBDEFS)) {
      res = (JOBRES *)GetResWithName(res_table->rcode, name.c_str());
      propagate_jobdefs(res_table->rcode, res);
      if (!validate_resource(res_table->rcode, res_table->items, (BRSRES *)res)) {
         ua->error_msg("failed to create config resource \"%s\"\n", name.c_str());
         unlink(filename_tmp.c_str());
         my_config->remove_resource(res_table->rcode, name.c_str());
         return false;
      }
   }

   /*
    * new config resource is working fine. Rename file to its permanent name.
    */
   if (rename(filename_tmp.c_str(), filename.c_str()) != 0 ) {
      ua->error_msg("failed to create config file \"%s\"\n", filename.c_str());
      unlink(filename_tmp.c_str());
      my_config->remove_resource(res_table->rcode, name.c_str());
      return false;
   }

   /*
    * When adding a client, also create the client configuration file.
    */
   if (res_table->rcode==R_CLIENT) {
      configure_create_fd_resource(ua, name.c_str());
   }

   ua->send->object_start("add");
   ua->send->object_key_value("resource", res_table->name);
   ua->send->object_key_value("name", name.c_str());
   ua->send->object_key_value("filename", filename.c_str(), "Created resource config file \"%s\":\n");
   ua->send->object_key_value("content", resource.c_str(), "%s");
   ua->send->object_end("add");

   return true;
}