Example #1
0
/*
 * Update a media record -- allows you to change the
 *  Volume status. E.g. if you want BAREOS to stop
 *  writing on the volume, set it to anything other
 *  than Append.
 */
static int update_volume(UAContext *ua)
{
   POOLRES *pool;
   POOLMEM *query;
   POOL_MEM ret;
   char buf[1000];
   char ed1[130];
   bool done = false;
   int i;
   const char *kw[] = {
      NT_("VolStatus"),     /* 0 */
      NT_("VolRetention"),  /* 1 */
      NT_("VolUse"),        /* 2 */
      NT_("MaxVolJobs"),    /* 3 */
      NT_("MaxVolFiles"),   /* 4 */
      NT_("MaxVolBytes"),   /* 5 */
      NT_("Recycle"),       /* 6 */
      NT_("InChanger"),     /* 7 */
      NT_("Slot"),          /* 8 */
      NT_("Pool"),          /* 9 */
      NT_("FromPool"),      /* 10 */
      NT_("AllFromPool"),   /* 11 !!! see below !!! */
      NT_("Enabled"),       /* 12 */
      NT_("RecyclePool"),   /* 13 */
      NT_("ActionOnPurge"), /* 14 */
      NULL
   };

#define AllFromPool 11 /* keep this updated with above */

   for (i = 0; kw[i]; i++) {
      int j;
      POOL_DBR pr;
      MEDIA_DBR mr;

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

      if ((j = find_arg_with_value(ua, kw[i])) > 0) {
         /* If all from pool don't select a media record */
         if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
            return 0;
         }
         switch (i) {
         case 0:
            update_volstatus(ua, ua->argv[j], &mr);
            break;
         case 1:
            update_volretention(ua, ua->argv[j], &mr);
            break;
         case 2:
            update_voluseduration(ua, ua->argv[j], &mr);
            break;
         case 3:
            update_volmaxjobs(ua, ua->argv[j], &mr);
            break;
         case 4:
            update_volmaxfiles(ua, ua->argv[j], &mr);
            break;
         case 5:
            update_volmaxbytes(ua, ua->argv[j], &mr);
            break;
         case 6:
            update_volrecycle(ua, ua->argv[j], &mr);
            break;
         case 7:
            update_volinchanger(ua, ua->argv[j], &mr);
            break;
         case 8:
            update_volslot(ua, ua->argv[j], &mr);
            break;
         case 9:
            pr.PoolId = mr.PoolId;
            if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
               ua->error_msg("%s", db_strerror(ua->db));
               break;
            }
            update_vol_pool(ua, ua->argv[j], &mr, &pr);
            break;
         case 10:
            update_vol_from_pool(ua, &mr);
            return 1;
         case 11:
            update_all_vols_from_pool(ua, ua->argv[j]);
            return 1;
         case 12:
            update_volenabled(ua, ua->argv[j], &mr);
            break;
         case 13:
            update_vol_recyclepool(ua, ua->argv[j], &mr);
            break;
         case 14:
            update_vol_actiononpurge(ua, ua->argv[j], &mr);
            break;
         }
         done = true;
      }
   }

   /* Allow user to simply update all volumes */
   if (find_arg(ua, NT_("fromallpools")) > 0) {
      update_all_vols(ua);
      return 1;
   }

   for ( ; !done; ) {
      POOL_DBR pr;
      MEDIA_DBR mr;

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

      start_prompt(ua, _("Parameters to modify:\n"));
      add_prompt(ua, _("Volume Status"));              /* 0 */
      add_prompt(ua, _("Volume Retention Period"));    /* 1 */
      add_prompt(ua, _("Volume Use Duration"));        /* 2 */
      add_prompt(ua, _("Maximum Volume Jobs"));        /* 3 */
      add_prompt(ua, _("Maximum Volume Files"));       /* 4 */
      add_prompt(ua, _("Maximum Volume Bytes"));       /* 5 */
      add_prompt(ua, _("Recycle Flag"));               /* 6 */
      add_prompt(ua, _("Slot"));                       /* 7 */
      add_prompt(ua, _("InChanger Flag"));             /* 8 */
      add_prompt(ua, _("Volume Files"));               /* 9 */
      add_prompt(ua, _("Pool"));                       /* 10 */
      add_prompt(ua, _("Volume from Pool"));           /* 11 */
      add_prompt(ua, _("All Volumes from Pool"));      /* 12 */
      add_prompt(ua, _("All Volumes from all Pools")); /* 13 */
      add_prompt(ua, _("Enabled")),                    /* 14 */
      add_prompt(ua, _("RecyclePool")),                /* 15 */
      add_prompt(ua, _("Action On Purge")),            /* 16 */
      add_prompt(ua, _("Done"));                       /* 17 */
      i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);

      /* For All Volumes, All Volumes from Pool, and Done, we don't need
           * a Volume record */
      if ( i != 12 && i != 13 && i != 17) {
         if (!select_media_dbr(ua, &mr)) {  /* Get Volume record */
            return 0;
         }
         ua->info_msg(_("Updating Volume \"%s\"\n"), mr.VolumeName);
      }
      switch (i) {
      case 0:                         /* Volume Status */
         /* Modify Volume Status */
         ua->info_msg(_("Current Volume status is: %s\n"), mr.VolStatus);
         start_prompt(ua, _("Possible Values are:\n"));
         add_prompt(ua, NT_("Append"));
         add_prompt(ua, NT_("Archive"));
         add_prompt(ua, NT_("Disabled"));
         add_prompt(ua, NT_("Full"));
         add_prompt(ua, NT_("Used"));
         add_prompt(ua, NT_("Cleaning"));
         if (bstrcmp(mr.VolStatus, NT_("Purged"))) {
            add_prompt(ua, NT_("Recycle"));
         }
         add_prompt(ua, NT_("Read-Only"));
         if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
            return 1;
         }
         update_volstatus(ua, ua->cmd, &mr);
         break;
      case 1:                         /* Retention */
         ua->info_msg(_("Current retention period is: %s\n"),
            edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
         if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
            return 0;
         }
         update_volretention(ua, ua->cmd, &mr);
         break;

      case 2:                         /* Use Duration */
         ua->info_msg(_("Current use duration is: %s\n"),
            edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
         if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
            return 0;
         }
         update_voluseduration(ua, ua->cmd, &mr);
         break;

      case 3:                         /* Max Jobs */
         ua->info_msg(_("Current max jobs is: %u\n"), mr.MaxVolJobs);
         if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
            return 0;
         }
         update_volmaxjobs(ua, ua->cmd, &mr);
         break;

      case 4:                         /* Max Files */
         ua->info_msg(_("Current max files is: %u\n"), mr.MaxVolFiles);
         if (!get_pint(ua, _("Enter new Maximum Files: "))) {
            return 0;
         }
         update_volmaxfiles(ua, ua->cmd, &mr);
         break;

      case 5:                         /* Max Bytes */
         ua->info_msg(_("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
         if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
            return 0;
         }
         update_volmaxbytes(ua, ua->cmd, &mr);
         break;


      case 6:                         /* Recycle */
         ua->info_msg(_("Current recycle flag is: %s\n"),
            mr.Recycle==1?_("yes"):_("no"));
         if (!get_yesno(ua, _("Enter new Recycle status: "))) {
            return 0;
         }
         update_volrecycle(ua, ua->cmd, &mr);
         break;

      case 7:                         /* Slot */
         ua->info_msg(_("Current Slot is: %d\n"), mr.Slot);
         if (!get_pint(ua, _("Enter new Slot: "))) {
            return 0;
         }
         update_volslot(ua, ua->cmd, &mr);
         break;

      case 8:                         /* InChanger */
         ua->info_msg(_("Current InChanger flag is: %d\n"), mr.InChanger);
         bsnprintf(buf, sizeof(buf), _("Set InChanger flag for Volume \"%s\": yes/no: "),
            mr.VolumeName);
         if (!get_yesno(ua, buf)) {
            return 0;
         }
         mr.InChanger = ua->pint32_val;
         /*
          * Make sure to use db_update... rather than doing this directly,
          *   so that any Slot is handled correctly.
          */
         set_storageid_in_mr(NULL, &mr);
         if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
            ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
         } else {
            ua->info_msg(_("New InChanger flag is: %d\n"), mr.InChanger);
         }
         break;


      case 9:                         /* Volume Files */
         int32_t VolFiles;
         ua->warning_msg(_("Warning changing Volume Files can result\n"
                        "in loss of data on your Volume\n\n"));
         ua->info_msg(_("Current Volume Files is: %u\n"), mr.VolFiles);
         if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
            return 0;
         }
         VolFiles = ua->pint32_val;
         if (VolFiles != (int)(mr.VolFiles + 1)) {
            ua->warning_msg(_("Normally, you should only increase Volume Files by one!\n"));
            if (!get_yesno(ua, _("Increase Volume Files? (yes/no): ")) || ua->pint32_val == 0) {
               break;
            }
         }
         query = get_pool_memory(PM_MESSAGE);
         Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
            VolFiles, edit_int64(mr.MediaId, ed1));
         if (!db_sql_query(ua->db, query)) {
            ua->error_msg("%s", db_strerror(ua->db));
         } else {
            ua->info_msg(_("New Volume Files is: %u\n"), VolFiles);
         }
         free_pool_memory(query);
         break;

      case 10:                        /* Volume's Pool */
         pr.PoolId = mr.PoolId;
         if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
            ua->error_msg("%s", db_strerror(ua->db));
            return 0;
         }
         ua->info_msg(_("Current Pool is: %s\n"), pr.Name);
         if (!get_cmd(ua, _("Enter new Pool name: "))) {
            return 0;
         }
         update_vol_pool(ua, ua->cmd, &mr, &pr);
         return 1;

      case 11:
         update_vol_from_pool(ua, &mr);
         return 1;
      case 12:
         pool = select_pool_resource(ua);
         if (pool) {
            update_all_vols_from_pool(ua, pool->name());
         }
         return 1;

      case 13:
         update_all_vols(ua);
         return 1;

      case 14:
         ua->info_msg(_("Current Enabled is: %d\n"), mr.Enabled);
         if (!get_cmd(ua, _("Enter new Enabled: "))) {
            return 0;
         }
         if (bstrcasecmp(ua->cmd, "yes") || bstrcasecmp(ua->cmd, "true")) {
            mr.Enabled = 1;
         } else if (bstrcasecmp(ua->cmd, "no") || bstrcasecmp(ua->cmd, "false")) {
            mr.Enabled = 0;
         } else if (bstrcasecmp(ua->cmd, "archived")) {
            mr.Enabled = 2;
         } else {
            mr.Enabled = atoi(ua->cmd);
         }
         update_volenabled(ua, ua->cmd, &mr);
         break;

      case 15:
         pr.PoolId = mr.RecyclePoolId;
         if (db_get_pool_record(ua->jcr, ua->db, &pr)) {
            ua->info_msg(_("Current RecyclePool is: %s\n"), pr.Name);
         } else {
            ua->info_msg(_("No current RecyclePool\n"));
         }
         if (!select_pool_dbr(ua, &pr, NT_("recyclepool"))) {
            return 0;
         }
         update_vol_recyclepool(ua, pr.Name, &mr);
         return 1;

      case 16:
         pm_strcpy(ret, "");
         ua->info_msg(_("Current ActionOnPurge is: %s\n"),
                      action_on_purge_to_string(mr.ActionOnPurge, ret));
         if (!get_cmd(ua, _("Enter new ActionOnPurge (one of: Truncate, None): "))) {
            return 0;
         }

         update_vol_actiononpurge(ua, ua->cmd, &mr);
         break;

      default:                        /* Done or error */
         ua->info_msg(_("Selection terminated.\n"));
         return 1;
      }
   }
   return 1;
}
static inline struct bstr *
parse_object(struct bstr *args, struct bstr *arg, struct tcf_meta_val *obj,
	     unsigned long *dst, struct tcf_meta_val *left)
{
	struct meta_entry *entry;
	unsigned long num;
	struct bstr *a;

	if (arg->quoted) {
		obj->kind = TCF_META_TYPE_VAR << 12;
		obj->kind |= TCF_META_ID_VALUE;
		*dst = (unsigned long) arg;
		return bstr_next(arg);
	}

	num = bstrtoul(arg);
	if (num != ULONG_MAX) {
		obj->kind = TCF_META_TYPE_INT << 12;
		obj->kind |= TCF_META_ID_VALUE;
		*dst = (unsigned long) num;
		return bstr_next(arg);
	}

	entry = lookup_meta_entry(arg);

	if (entry == NULL) {
		PARSE_ERR(arg, "meta: unknown meta id\n");
		return PARSE_FAILURE;
	}

	obj->kind = entry->id | (map_type(entry->mask[0]) << 12);

	if (left) {
		struct tcf_meta_val *right = obj;

		if (TCF_META_TYPE(right->kind) == TCF_META_TYPE(left->kind))
			goto compatible;

		if (can_adopt(left) && !can_adopt(right)) {
			if (is_compatible(left, right))
				left->kind = overwrite_type(left, right);
			else
				goto not_compatible;
		} else if (can_adopt(right) && !can_adopt(left)) {
			if (is_compatible(right, left))
				right->kind = overwrite_type(right, left);
			else
				goto not_compatible;
		} else if (can_adopt(left) && can_adopt(right)) {
			if (is_compatible(left, right))
				left->kind = overwrite_type(left, right);
			else if (is_compatible(right, left))
				right->kind = overwrite_type(right, left);
			else
				goto not_compatible;
		} else
			goto not_compatible;
	}

compatible:

	a = bstr_next(arg);

	while(a) {
		if (!bstrcmp(a, "shift")) {
			unsigned long shift;

			if (a->next == NULL) {
				PARSE_ERR(a, "meta: missing argument");
				return PARSE_FAILURE;
			}
			a = bstr_next(a);

			shift = bstrtoul(a);
			if (shift == ULONG_MAX) {
				PARSE_ERR(a, "meta: invalid shift, must " \
				    "be numeric");
				return PARSE_FAILURE;
			}

			obj->shift = (__u8) shift;
			a = bstr_next(a);
		} else if (!bstrcmp(a, "mask")) {
			unsigned long mask;

			if (a->next == NULL) {
				PARSE_ERR(a, "meta: missing argument");
				return PARSE_FAILURE;
			}
			a = bstr_next(a);

			mask = bstrtoul(a);
			if (mask == ULONG_MAX) {
				PARSE_ERR(a, "meta: invalid mask, must be " \
				    "numeric");
				return PARSE_FAILURE;
			}
			*dst = (unsigned long) mask;
			a = bstr_next(a);
		} else
			break;
	}

	return a;

not_compatible:
	PARSE_ERR(arg, "lvalue and rvalue are not compatible.");
	return PARSE_FAILURE;
}
Example #3
0
void catalog_request(JCR *jcr, BSOCK *bs)
{
   MEDIA_DBR mr, sdmr;
   JOBMEDIA_DBR jm;
   char Job[MAX_NAME_LENGTH];
   char pool_name[MAX_NAME_LENGTH];
   int index, ok, label, writing;
   POOLMEM *omsg;
   POOL_DBR pr;
   uint32_t Stripe, Copy;
   uint64_t MediaId;
   utime_t VolFirstWritten;
   utime_t VolLastWritten;

   memset(&sdmr, 0, sizeof(sdmr));
   memset(&jm, 0, sizeof(jm));
   Dsm_check(100);

   /*
    * Request to find next appendable Volume for this Job
    */
   Dmsg1(100, "catreq %s", bs->msg);
   if (!jcr->db) {
      omsg = get_memory(bs->msglen+1);
      pm_strcpy(omsg, bs->msg);
      bs->fsend(_("1990 Invalid Catalog Request: %s"), omsg);
      Jmsg1(jcr, M_FATAL, 0, _("Invalid Catalog request; DB not open: %s"), omsg);
      free_memory(omsg);
      return;
   }
   /*
    * Find next appendable medium for SD
    */
   if (sscanf(bs->msg, Find_media, &Job, &index, &pool_name, &mr.MediaType) == 4) {
      memset(&pr, 0, sizeof(pr));
      bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
      unbash_spaces(pr.Name);
      ok = db_get_pool_record(jcr, jcr->db, &pr);
      if (ok) {
         mr.PoolId = pr.PoolId;
         set_storageid_in_mr(jcr->res.wstore, &mr);
         mr.ScratchPoolId = pr.ScratchPoolId;
         ok = find_next_volume_for_append(jcr, &mr, index, fnv_create_vol, fnv_prune);
         Dmsg3(050, "find_media ok=%d idx=%d vol=%s\n", ok, index, mr.VolumeName);
      }
      /*
       * Send Find Media response to Storage daemon
       */
      if (ok) {
         send_volume_info_to_storage_daemon(jcr, bs, &mr);
      } else {
         bs->fsend(_("1901 No Media.\n"));
         Dmsg0(500, "1901 No Media.\n");
      }

   /*
    * Request to find specific Volume information
    */
   } else if (sscanf(bs->msg, Get_Vol_Info, &Job, &mr.VolumeName, &writing) == 3) {
      Dmsg1(100, "CatReq GetVolInfo Vol=%s\n", mr.VolumeName);
      /*
       * Find the Volume
       */
      unbash_spaces(mr.VolumeName);
      if (db_get_media_record(jcr, jcr->db, &mr)) {
         const char *reason = NULL;           /* detailed reason for rejection */
         /*
          * If we are reading, accept any volume (reason == NULL)
          * If we are writing, check if the Volume is valid
          *   for this job, and do a recycle if necessary
          */
         if (writing) {
            /*
             * SD wants to write this Volume, so make
             *   sure it is suitable for this job, i.e.
             *   Pool matches, and it is either Append or Recycle
             *   and Media Type matches and Pool allows any volume.
             */
            if (mr.PoolId != jcr->jr.PoolId) {
               reason = _("not in Pool");
            } else if (!bstrcmp(mr.MediaType, jcr->res.wstore->media_type)) {
               reason = _("not correct MediaType");
            } else {
               /*
                * Now try recycling if necessary
                *   reason set non-NULL if we cannot use it
                */
               check_if_volume_valid_or_recyclable(jcr, &mr, &reason);
            }
         }
         if (!reason && mr.Enabled != 1) {
            reason = _("is not Enabled");
         }
         if (reason == NULL) {
            /*
             * Send Find Media response to Storage daemon
             */
            send_volume_info_to_storage_daemon(jcr, bs, &mr);
         } else {
            /* Not suitable volume */
            bs->fsend(_("1998 Volume \"%s\" catalog status is %s, %s.\n"), mr.VolumeName,
               mr.VolStatus, reason);
         }

      } else {
         bs->fsend(_("1997 Volume \"%s\" not in catalog.\n"), mr.VolumeName);
         Dmsg1(100, "1997 Volume \"%s\" not in catalog.\n", mr.VolumeName);
      }

   /*
    * Request to update Media record. Comes typically at the end
    *  of a Storage daemon Job Session, when labeling/relabeling a
    *  Volume, or when an EOF mark is written.
    */
   } else if (sscanf(bs->msg, Update_media, &Job, &sdmr.VolumeName,
                     &sdmr.VolJobs, &sdmr.VolFiles, &sdmr.VolBlocks, &sdmr.VolBytes,
                     &sdmr.VolMounts, &sdmr.VolErrors, &sdmr.VolWrites, &sdmr.MaxVolBytes,
                     &VolLastWritten, &sdmr.VolStatus, &sdmr.Slot, &label, &sdmr.InChanger,
                     &sdmr.VolReadTime, &sdmr.VolWriteTime, &VolFirstWritten) == 18) {
      db_lock(jcr->db);
      Dmsg3(400, "Update media %s oldStat=%s newStat=%s\n", sdmr.VolumeName,
         mr.VolStatus, sdmr.VolStatus);
      bstrncpy(mr.VolumeName, sdmr.VolumeName, sizeof(mr.VolumeName)); /* copy Volume name */
      unbash_spaces(mr.VolumeName);
      if (!db_get_media_record(jcr, jcr->db, &mr)) {
         Jmsg(jcr, M_ERROR, 0, _("Unable to get Media record for Volume %s: ERR=%s\n"),
              mr.VolumeName, db_strerror(jcr->db));
         bs->fsend(_("1991 Catalog Request for vol=%s failed: %s"),
            mr.VolumeName, db_strerror(jcr->db));
         goto bail_out;

      }
      /* Set first written time if this is first job */
      if (mr.FirstWritten == 0) {
         if (VolFirstWritten == 0) {
            mr.FirstWritten = jcr->start_time;   /* use Job start time as first write */
         } else {
            mr.FirstWritten = VolFirstWritten;
         }
         mr.set_first_written = true;
      }
      /* If we just labeled the tape set time */
      if (label || mr.LabelDate == 0) {
         mr.LabelDate = jcr->start_time;
         mr.set_label_date = true;
         if (mr.InitialWrite == 0) {
            mr.InitialWrite = jcr->start_time;
         }
         Dmsg2(400, "label=%d labeldate=%d\n", label, mr.LabelDate);
      } else {
         /*
          * Insanity check for VolFiles get set to a smaller value
          */
         if (sdmr.VolFiles < mr.VolFiles) {
            Jmsg(jcr, M_FATAL, 0, _("Volume Files at %u being set to %u"
                 " for Volume \"%s\". This is incorrect.\n"),
               mr.VolFiles, sdmr.VolFiles, mr.VolumeName);
            bs->fsend(_("1992 Update Media error. VolFiles=%u, CatFiles=%u\n"),
               sdmr.VolFiles, mr.VolFiles);
            goto bail_out;

         }
      }
      Dmsg2(400, "Update media: BefVolJobs=%u After=%u\n", mr.VolJobs, sdmr.VolJobs);

      /*
       * Check if the volume has been written by the job,
       * and update the LastWritten field if needed.
       */
      if (mr.VolBlocks != sdmr.VolBlocks && VolLastWritten != 0) {
         mr.LastWritten = VolLastWritten;
      }

      /*
       * Update to point to the last device used to write the Volume.
       *   However, do so only if we are writing the tape, i.e.
       *   the number of VolWrites has increased.
       */
      if (jcr->res.wstore && sdmr.VolWrites > mr.VolWrites) {
         Dmsg2(050, "Update StorageId old=%d new=%d\n",
               mr.StorageId, jcr->res.wstore->StorageId);
         /* Update StorageId after write */
         set_storageid_in_mr(jcr->res.wstore, &mr);
      } else {
         /* Nothing written, reset same StorageId */
         set_storageid_in_mr(NULL, &mr);
      }

      /* Copy updated values to original media record */
      mr.VolJobs      = sdmr.VolJobs;
      mr.VolFiles     = sdmr.VolFiles;
      mr.VolBlocks    = sdmr.VolBlocks;
      mr.VolBytes     = sdmr.VolBytes;
      mr.VolMounts    = sdmr.VolMounts;
      mr.VolErrors    = sdmr.VolErrors;
      mr.VolWrites    = sdmr.VolWrites;
      mr.Slot         = sdmr.Slot;
      mr.InChanger    = sdmr.InChanger;
      bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus));
      if (sdmr.VolReadTime >= 0) {
         mr.VolReadTime  = sdmr.VolReadTime;
      }
      if (sdmr.VolWriteTime >= 0) {
         mr.VolWriteTime = sdmr.VolWriteTime;
      }

      Dmsg2(400, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName);
      /*
       * Update the database, then before sending the response to the
       *  SD, check if the Volume has expired.
       */
      if (!db_update_media_record(jcr, jcr->db, &mr)) {
         Jmsg(jcr, M_FATAL, 0, _("Catalog error updating Media record. %s"),
            db_strerror(jcr->db));
         bs->fsend(_("1993 Update Media error\n"));
         Dmsg0(400, "send error\n");
      } else {
         (void)has_volume_expired(jcr, &mr);
         send_volume_info_to_storage_daemon(jcr, bs, &mr);
      }

bail_out:
      db_unlock(jcr->db);

      Dmsg1(400, ">CatReq response: %s", bs->msg);
      Dmsg1(400, "Leave catreq jcr 0x%x\n", jcr);
      return;
   /*
    * Request to create a JobMedia record
    */
   } else if (sscanf(bs->msg, Create_job_media, &Job,
      &jm.FirstIndex, &jm.LastIndex, &jm.StartFile, &jm.EndFile,
      &jm.StartBlock, &jm.EndBlock, &Copy, &Stripe, &MediaId) == 10) {

      if (jcr->mig_jcr) {
         jm.JobId = jcr->mig_jcr->JobId;
      } else {
         jm.JobId = jcr->JobId;
      }
      jm.MediaId = MediaId;
      Dmsg6(400, "create_jobmedia JobId=%d MediaId=%d SF=%d EF=%d FI=%d LI=%d\n",
         jm.JobId, jm.MediaId, jm.StartFile, jm.EndFile, jm.FirstIndex, jm.LastIndex);
      if (!db_create_jobmedia_record(jcr, jcr->db, &jm)) {
         Jmsg(jcr, M_FATAL, 0, _("Catalog error creating JobMedia record. %s"),
            db_strerror(jcr->db));
         bs->fsend(_("1992 Create JobMedia error\n"));
      } else {
         Dmsg0(400, "JobMedia record created\n");
         bs->fsend(OK_create);
      }

   } else {
      omsg = get_memory(bs->msglen+1);
      pm_strcpy(omsg, bs->msg);
      bs->fsend(_("1990 Invalid Catalog Request: %s"), omsg);
      Jmsg1(jcr, M_FATAL, 0, _("Invalid Catalog request: %s"), omsg);
      free_memory(omsg);
   }

   Dmsg1(400, ">CatReq response: %s", bs->msg);
   Dmsg1(400, "Leave catreq jcr 0x%x\n", jcr);
   return;
}
Example #4
0
static int cpustr_to_cpulist_physical(bstring bcpustr, int* cpulist, int length)
{
    topology_init();
    CpuTopology_t cpuid_topology = get_cpuTopology();
    affinity_init();
    AffinityDomains_t affinity = get_affinityDomains();
    bstring bdomain;
    bstring blist;
    int domainidx = -1;
    if (bstrchrp(bcpustr, ':', 0) != BSTR_ERR)
    {
        struct bstrList* strlist = bstrListCreate();
        strlist = bsplit(bcpustr, ':');
        bdomain = bstrcpy(strlist->entry[0]);
        blist = bstrcpy(strlist->entry[1]);
        bstrListDestroy(strlist);
    }
    else
    {
        bdomain = bformat("N");
        blist = bstrcpy(bcpustr);
    }
    for (int i=0; i<affinity->numberOfAffinityDomains; i++)
    {
        if (bstrcmp(bdomain, affinity->domains[i].tag) == 0)
        {
            domainidx = i;
            break;
        }
    }
    if (domainidx < 0)
    {
        fprintf(stderr, "Cannot find domain %s\n", bdata(bdomain));
        bdestroy(bdomain);
        bdestroy(blist);
        return 0;
    }
    struct bstrList* strlist = bstrListCreate();
    strlist = bsplit(blist, ',');
    int insert = 0;
    for (int i=0;i< strlist->qty; i++)
    {
        if (bstrchrp(strlist->entry[i], '-', 0) != BSTR_ERR)
        {
            struct bstrList* indexlist = bstrListCreate();
            indexlist = bsplit(strlist->entry[i], '-');
            if (atoi(bdata(indexlist->entry[0])) <= atoi(bdata(indexlist->entry[1])))
            {
                for (int j=atoi(bdata(indexlist->entry[0])); j<=atoi(bdata(indexlist->entry[1]));j++)
                {
                    if (cpu_in_domain(domainidx, j))
                    {
                        cpulist[insert] = j;
                        insert++;
                        if (insert == length)
                        {
                            bstrListDestroy(indexlist);
                            goto physical_done;
                        }
                    }
                    else
                    {
                        fprintf(stderr, "CPU %d not in domain %s\n", j, bdata(affinity->domains[domainidx].tag));
                    }
                }
            }
            else
            {
                for (int j=atoi(bdata(indexlist->entry[0])); j>=atoi(bdata(indexlist->entry[1]));j--)
                {
                    if (cpu_in_domain(domainidx, j))
                    {
                        cpulist[insert] = j;
                        insert++;
                        if (insert == length)
                        {
                            bstrListDestroy(indexlist);
                            goto physical_done;
                        }
                    }
                    else
                    {
                        fprintf(stderr, "CPU %d not in domain %s\n", j, bdata(affinity->domains[domainidx].tag));
                    }
                }
            }
            bstrListDestroy(indexlist);
        }
        else
        {
            int cpu = atoi(bdata(strlist->entry[i]));
            if (cpu_in_domain(domainidx, cpu))
            {
                cpulist[insert] = cpu;
                insert++;
                if (insert == length)
                {
                    goto physical_done;
                }
            }
            else
            {
                fprintf(stderr, "CPU %d not in domain %s\n", cpu, bdata(affinity->domains[domainidx].tag));
            }
        }
    }
physical_done:
    bstrListDestroy(strlist);
    bdestroy(bdomain);
    bdestroy(blist);
    return insert;
}
Example #5
0
int main (int argc, char *argv[])
{
   int ch;
   char *jobids = (char *)"1";
   char *path=NULL, *client=NULL;
   uint64_t limit=0;
   bool clean=false;
   setlocale(LC_ALL, "");
   bindtextdomain("bareos", LOCALEDIR);
   textdomain("bareos");
   init_stack_dump();

   Dmsg0(0, "Starting bvfs_test tool\n");

   my_name_is(argc, argv, "bvfs_test");
   init_msg(NULL, NULL);

   OSDependentInit();

   while ((ch = getopt(argc, argv, "h:c:l:d:D:n:P:Su:vf:w:?j:p:f:T")) != -1) {
      switch (ch) {
      case 'd':                    /* debug level */
         if (*optarg == 't') {
            dbg_timestamp = true;
         } else {
            debug_level = atoi(optarg);
            if (debug_level <= 0) {
               debug_level = 1;
            }
         }
         break;

      case 'D':
         db_driver = optarg;
         break;

      case 'l':
         limit = str_to_int64(optarg);
         break;

      case 'c':
         client = optarg;
         break;

      case 'h':
         db_host = optarg;
         break;

      case 'n':
         db_name = optarg;
         break;

      case 'w':
         working_directory = optarg;
         break;

      case 'u':
         db_user = optarg;
         break;

      case 'P':
         db_password = optarg;
         break;

      case 'v':
         verbose++;
         break;

      case 'p':
         path = optarg;
         break;

      case 'f':
         file = optarg;
         break;

      case 'j':
         jobids = optarg;
         break;

      case 'T':
         clean = true;
         break;

      case '?':
      default:
         usage();

      }
   }
   argc -= optind;
   argv += optind;

   if (argc != 0) {
      Pmsg0(0, _("Wrong number of arguments: \n"));
      usage();
   }
   JCR *bjcr = new_jcr(sizeof(JCR), NULL);
   bjcr->JobId = getpid();
   bjcr->setJobType(JT_CONSOLE);
   bjcr->setJobLevel(L_FULL);
   bjcr->JobStatus = JS_Running;
   bjcr->client_name = get_pool_memory(PM_FNAME);
   pm_strcpy(bjcr->client_name, "Dummy.Client.Name");
   bstrncpy(bjcr->Job, "bvfs_test", sizeof(bjcr->Job));

   if ((db = db_init_database(NULL, NULL, db_name, db_user, db_password, db_host, 0, NULL)) == NULL) {
      Emsg0(M_ERROR_TERM, 0, _("Could not init Bareos database\n"));
   }
   Dmsg1(0, "db_type=%s\n", db_get_type(db));

   if (!db_open_database(NULL, db)) {
      Emsg0(M_ERROR_TERM, 0, db_strerror(db));
   }
   Dmsg0(200, "Database opened\n");
   if (verbose) {
      Pmsg2(000, _("Using Database: %s, User: %s\n"), db_name, db_user);
   }

   bjcr->db = db;

   if (clean) {
      Pmsg0(0, "Clean old table\n");
      db_sql_query(db, "DELETE FROM PathHierarchy", NULL, NULL);
      db_sql_query(db, "UPDATE Job SET HasCache=0", NULL, NULL);
      db_sql_query(db, "DELETE FROM PathVisibility", NULL, NULL);
      bvfs_update_cache(bjcr, db);
   }

   Bvfs fs(bjcr, db);
   fs.set_handler(result_handler, &fs);

   fs.set_jobids(jobids);
   fs.update_cache();
   if (limit)
      fs.set_limit(limit);

   if (path) {
      fs.ch_dir(path);
      fs.ls_special_dirs();
      fs.ls_dirs();
      while (fs.ls_files()) {
         fs.next_offset();
      }

      if (fnid && client) {
         Pmsg0(0, "---------------------------------------------\n");
         Pmsg1(0, "Getting file version for %s\n", file);
         fs.get_all_file_versions(fs.get_pwd(), fnid, client);
      }

      exit (0);
   }


   Pmsg0(0, "list /\n");
   fs.ch_dir("/");
   fs.ls_special_dirs();
   fs.ls_dirs();
   fs.ls_files();

   Pmsg0(0, "list /tmp/\n");
   fs.ch_dir("/tmp/");
   fs.ls_special_dirs();
   fs.ls_dirs();
   fs.ls_files();

   Pmsg0(0, "list /tmp/regress/\n");
   fs.ch_dir("/tmp/regress/");
   fs.ls_special_dirs();
   fs.ls_files();
   fs.ls_dirs();

   Pmsg0(0, "list /tmp/regress/build/\n");
   fs.ch_dir("/tmp/regress/build/");
   fs.ls_special_dirs();
   fs.ls_dirs();
   fs.ls_files();

   fs.get_all_file_versions(1, 347, "zog4-fd");

   char p[200];
   strcpy(p, "/tmp/toto/rep/");
   bvfs_parent_dir(p);
   if(!bstrcmp(p, "/tmp/toto/")) {
      Pmsg0(000, "Error in bvfs_parent_dir\n");
   }
   bvfs_parent_dir(p);
   if(!bstrcmp(p, "/tmp/")) {
      Pmsg0(000, "Error in bvfs_parent_dir\n");
   }
   bvfs_parent_dir(p);
   if(!bstrcmp(p, "/")) {
      Pmsg0(000, "Error in bvfs_parent_dir\n");
   }
   bvfs_parent_dir(p);
   if(!bstrcmp(p, "")) {
      Pmsg0(000, "Error in bvfs_parent_dir\n");
   }
   bvfs_parent_dir(p);
   if(!bstrcmp(p, "")) {
      Pmsg0(000, "Error in bvfs_parent_dir\n");
   }

   return 0;
}
Example #6
0
File: expand.c Project: AlD/bareos
/*
 * Search counter variables
 */
static var_rc_t lookup_counter_var(var_t *ctx,
                                   void *my_ctx,
                                   const char *var_ptr,
                                   int var_len,
                                   int var_inc,
                                   int var_index,
                                   const char **val_ptr,
                                   int *val_len,
                                   int *val_size)
{
   COUNTERRES *counter;
   POOL_MEM buf(PM_NAME);
   var_rc_t status = VAR_ERR_UNDEFINED_VARIABLE;

   buf.check_size(var_len + 1);
   pm_memcpy(buf, var_ptr, var_len);
   (buf.c_str())[var_len] = 0;

   LockRes();
   for (counter = NULL; (counter = (COUNTERRES *)GetNextRes(R_COUNTER, (RES *)counter)); ) {
      if (bstrcmp(counter->name(), buf.c_str())) {
         Dmsg2(100, "Counter=%s val=%d\n", buf.c_str(), counter->CurrentValue);
         /*
          * -1 => return size of array
          */
         if (var_index == -1) {
            Mmsg(buf, "%d", counter->CurrentValue);
            *val_len = Mmsg(buf, "%d", strlen(buf.c_str()));
            *val_ptr = bstrdup(buf.c_str());
            *val_size = 0;                  /* don't try to free val_ptr */
            return VAR_OK;
         } else {
            Mmsg(buf, "%d", counter->CurrentValue);
            *val_ptr = bstrdup(buf.c_str());
            *val_len = strlen(buf.c_str());
            *val_size = *val_len + 1;
         }
         if (var_inc) {               /* increment the variable? */
            if (counter->CurrentValue == counter->MaxValue) {
               counter->CurrentValue = counter->MinValue;
            } else {
               counter->CurrentValue++;
            }
            if (counter->Catalog) {   /* update catalog if need be */
               COUNTER_DBR cr;
               JCR *jcr = (JCR *)my_ctx;
               memset(&cr, 0, sizeof(cr));
               bstrncpy(cr.Counter, counter->name(), sizeof(cr.Counter));
               cr.MinValue = counter->MinValue;
               cr.MaxValue = counter->MaxValue;
               cr.CurrentValue = counter->CurrentValue;
               Dmsg1(100, "New value=%d\n", cr.CurrentValue);
               if (counter->WrapCounter) {
                  bstrncpy(cr.WrapCounter, counter->WrapCounter->name(), sizeof(cr.WrapCounter));
               } else {
                  cr.WrapCounter[0] = 0;
               }
               if (!db_update_counter_record(jcr, jcr->db, &cr)) {
                  Jmsg(jcr, M_ERROR, 0, _("Count not update counter %s: ERR=%s\n"),
                     counter->name(), db_strerror(jcr->db));
               }
            }
         }
         status = VAR_OK;
         break;
      }
   }
   UnlockRes();

   return status;
}
Example #7
0
static int cpustr_to_cpulist_expression(bstring bcpustr, int* cpulist, int length)
{
    topology_init();
    CpuTopology_t cpuid_topology = get_cpuTopology();
    affinity_init();
    AffinityDomains_t affinity = get_affinityDomains();
    bstring bdomain;
    int domainidx = -1;
    int count = 0;
    int stride = 0;
    int chunk = 0;
    if (bstrchrp(bcpustr, 'E', 0) != 0)
    {
        fprintf(stderr, "Not a valid CPU expression\n");
        return 0;
    }
    struct bstrList* strlist = bstrListCreate();
    strlist = bsplit(bcpustr, ':');
    if (strlist->qty == 3)
    {
        bdomain = bstrcpy(strlist->entry[1]);
        count = atoi(bdata(strlist->entry[2]));
        stride = 1;
        chunk = 1;
    }
    else if (strlist->qty == 5)
    {
        bdomain = bstrcpy(strlist->entry[1]);
        count = atoi(bdata(strlist->entry[2]));
        chunk = atoi(bdata(strlist->entry[3]));
        stride = atoi(bdata(strlist->entry[4]));
    }
    for (int i=0; i<affinity->numberOfAffinityDomains; i++)
    {
        if (bstrcmp(bdomain, affinity->domains[i].tag) == 0)
        {
            domainidx = i;
            break;
        }
    }
    if (domainidx < 0)
    {
        fprintf(stderr, "Cannot find domain %s\n", bdata(bdomain));
        bstrListDestroy(strlist);
        return 0;
    }
    int offset = 0;
    int insert = 0;
    for (int i=0;i<count;i++)
    {
        for (int j=0;j<chunk && offset+j<affinity->domains[domainidx].numberOfProcessors;j++)
        {
            cpulist[insert] = affinity->domains[domainidx].processorList[offset + j];
            insert++;
            if (insert == length)
                goto expression_done;
        }
        offset += stride;
        if (offset >= affinity->domains[domainidx].numberOfProcessors)
        {
            offset = 0;
        }
        if (insert >= count)
            goto expression_done;
    }
    bstrListDestroy(strlist);
    return 0;
expression_done:
    bstrListDestroy(strlist);
    return insert;
}
Example #8
0
/*
 * Convert a volume name into a slot selection.
 */
static inline bool get_slot_list_using_volname(UAContext *ua,
                                               const char *volumename,
                                               dlist *vol_list,
                                               char *wanted_slot_list,
                                               char *selected_slot_list,
                                               int max_slots)
{
   vol_list_t *vl1, *vl2;
   bool found = false;

   if (is_name_valid(volumename)) {
      foreach_dlist(vl1, vol_list) {
         /*
          * We only select normal and import/export slots.
          */
         switch (vl1->Type) {
         case slot_type_normal:
         case slot_type_import:
            /*
             * When the source slot list is limited we check to
             * see if this slot should be taken into consideration.
             */
            if (wanted_slot_list && !bit_is_set(vl1->Slot - 1, wanted_slot_list)) {
               continue;
            }

            switch (vl1->Content) {
            case slot_content_full:
               /*
                * See if the wanted volume is loaded in this slot.
                */
               Dmsg3(100, "Checking for volume name in slot %d, wanted %s, found %s\n",
                     vl1->Slot, volumename, (vl1->VolName) ? vl1->VolName : "NULL");
               if (vl1->VolName && bstrcmp(vl1->VolName, volumename)) {
                  found = true;
               }
               break;
            case slot_content_empty:
               /*
                * See if this slot is loaded in drive and drive contains wanted volume
                */
               vl2 = is_loaded_in_drive(vol_list, vl1->Slot);
               if (vl2 != NULL) {
                  Dmsg3(100, "Checking for volume name in drive %d, wanted %s, found %s\n",
                        vl2->Slot, volumename, (vl2->VolName) ? vl2->VolName : "NULL");
                  if (vl2->VolName && bstrcmp(vl2->VolName, volumename)) {
                     found = true;
                  }
               } else {
                  Dmsg1(100, "Skipping empty slot %d\n", vl1->Slot);
               }
               break;
            default:
               break;
            }
            break;
         default:
            break;
         }

         /*
          * If we found a match break the loop.
          */
         if (found) {
            break;
         }
      }

      /*
       * See if we found the wanted volumename in the list
       * of available slots in the autochanger and mark the
       * slot in the slot_list or give a warning when the
       * volumename was not found.
       */
      if (found) {
         set_bit(vl1->Slot - 1, selected_slot_list);
      } else {
         Dmsg1(100, "No volume named %s in changer or in selected source slots.\n", volumename);
         ua->warning_msg(_("No volume named %s in changer or in selected source slots.\n"), volumename);
      }
   } else {
Example #9
0
static bRC getXattr(bpContext *ctx, xattr_pkt *xp)
{
   char *bp;
   bool skip_xattr;
   int status, current_size;
   int32_t xattr_value_length;
   POOL_MEM xattr_value(PM_MESSAGE);
   plugin_ctx *p_ctx = (plugin_ctx *)ctx->pContext;

   if (!p_ctx) {
      return bRC_Error;
   }

   /*
    * See if we need to retrieve the xattr list.
    */
   if (!p_ctx->processing_xattr) {
      while (1) {
         current_size = sizeof_pool_memory(p_ctx->xattr_list);
         status = ceph_llistxattr(p_ctx->cmount, xp->fname, p_ctx->xattr_list, current_size);
         if (status < 0) {
            berrno be;

            switch (status) {
#if defined(ENOTSUP) || defined(EOPNOTSUPP)
#if defined(ENOTSUP)
            case ENOTSUP:
#endif
#if defined(EOPNOTSUPP) && EOPNOTSUPP != ENOTSUP
            case EOPNOTSUPP:
#endif
               return bRC_OK;
#endif
            case -ERANGE:
               /*
                * Not enough room in buffer double its size and retry.
                */
               p_ctx->xattr_list = check_pool_memory_size(p_ctx->xattr_list, current_size * 2);
               continue;
            default:
               Jmsg(ctx, M_ERROR, "ceph_llistxattr(%s) failed: %s\n", xp->fname, be.bstrerror(-status));
               return bRC_Error;
            }
         }

         /*
          * Retrieved the xattr list so break the loop.
          */
         break;
      }

      p_ctx->next_xattr_name = p_ctx->xattr_list;
      p_ctx->processing_xattr = true;
   }

   while (1) {
      /*
       * On some OSes you also get the acls in the extented attribute list.
       * So we check if we are already backing up acls and if we do we
       * don't store the extended attribute with the same info.
       */
      skip_xattr = false;
      if (bit_is_set(FO_ACL, p_ctx->flags)) {
         for (int cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) {
            if (bstrcmp(p_ctx->next_xattr_name, xattr_acl_skiplist[cnt])) {
               skip_xattr = true;
               break;
            }
         }
      }

      if (!skip_xattr) {
         current_size = xattr_value.max_size();
         xattr_value_length = ceph_lgetxattr(p_ctx->cmount, xp->fname, p_ctx->next_xattr_name,
                                             xattr_value.c_str(), current_size);
         if (xattr_value_length < 0) {
            berrno be;

            switch (xattr_value_length) {
#if defined(ENOATTR) || defined(ENODATA)
#if defined(ENOATTR)
            case ENOATTR:
#endif
#if defined(ENODATA) && ENOATTR != ENODATA
            case ENODATA:
#endif
               skip_xattr = true;
               break;
#endif
#if defined(ENOTSUP) || defined(EOPNOTSUPP)
#if defined(ENOTSUP)
            case ENOTSUP:
#endif
#if defined(EOPNOTSUPP) && EOPNOTSUPP != ENOTSUP
            case EOPNOTSUPP:
#endif
               return bRC_OK;
#endif
            case -ERANGE:
               /*
                * Not enough room in buffer double its size and retry.
                */
               xattr_value.check_size(current_size * 2);
               continue;
            default:
               Jmsg(ctx, M_ERROR, "ceph_lgetxattr(%s) failed: %s\n", xp->fname, be.bstrerror(-xattr_value_length));
               return bRC_Error;
            }
         }

         /*
          * Retrieved the xattr so break the loop.
          */
         break;
      } else {
         /*
          * No data to retrieve so break the loop.
          */
         break;
      }
   }

   if (!skip_xattr) {
      xp->name = bstrdup(p_ctx->next_xattr_name);
      xp->name_length = strlen(xp->name) + 1;
      xp->value = (char *)malloc(xattr_value_length);
      memcpy(xp->value, xattr_value.c_str(), xattr_value_length);
      xp->value_length = xattr_value_length;
   }

   /*
    * See if there are more xattr to process.
    */
   bp = strchr(p_ctx->next_xattr_name, '\0');
   if (++bp != '\0') {
      p_ctx->next_xattr_name = bp;
      return bRC_More;
   } else {
      /*
       * No more reset processing_xattr flag.
       */
      p_ctx->processing_xattr = false;
      return bRC_OK;
   }
}
Example #10
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).
 */
void save_resource(int type, RES_ITEM *items, int pass)
{
   URES *res;
   int rindex = type - r_first;
   int i, size;
   int error = 0;

   /*
    * Ensure that all required items are present
    */
   for (i=0; items[i].name; i++) {
      if (items[i].flags & 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) {
         /* Resources not containing a resource */
         case R_CONSOLE:
         case R_DIRECTOR:
            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;
   }

   /* The following code is only executed during pass 1 */
   switch (type) {
   case R_CONSOLE:
      size = sizeof(CONRES);
      break;
   case R_DIRECTOR:
      size = sizeof(DIRRES);
      break;
   default:
      printf(_("Unknown resource type %d\n"), type);
      error = 1;
      size = 1;
      break;
   }
   /* Common */
   if (!error) {
      res = (URES *)malloc(size);
      memcpy(res, &res_all, 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.hdr.name)) {
               Emsg2(M_ERROR_TERM, 0,
                  _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
                  resources[rindex].name, res->res_dir.hdr.name);
            }
         }
         last->next = (RES *)res;
         Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
               res->res_dir.hdr.name);
      }
   }
}
Example #11
0
int reverse_compare(void *a, void *b)
{
  return bstrcmp((bstring)b, (bstring)a);
}
Example #12
0
/*
 * This routine is called only during a Verify
 */
void get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId)
{
   BSOCK *fd;
   int n, len;
   FILE_DBR fdbr;
   struct stat statf;                 /* file stat */
   struct stat statc;                 /* catalog stat */
   POOL_MEM buf(PM_MESSAGE);
   POOLMEM *fname = get_pool_memory(PM_FNAME);
   int do_Digest = CRYPTO_DIGEST_NONE;
   int32_t file_index = 0;

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

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

      if (job_canceled(jcr)) {
         goto bail_out;
      }
      fname = check_pool_memory_size(fname, fd->msglen);
      jcr->fname = check_pool_memory_size(jcr->fname, fd->msglen);
      Dmsg1(200, "Atts+Digest=%s\n", fd->msg);
      if ((len = sscanf(fd->msg, "%ld %d %100s", &file_index, &stream,
            fname)) != 3) {
         Jmsg3(jcr, M_FATAL, 0, _("dird<filed: bad attributes, expected 3 fields got %d\n"
                                  " mslen=%d msg=%s\n"), len, fd->msglen, fd->msg);
         goto bail_out;
      }
      /*
       * We read the Options or Signature into fname
       *  to prevent overrun, now copy it to proper location.
       */
      pm_strcpy(Opts_Digest, fname);
      p = fd->msg;
      skip_nonspaces(&p);             /* skip FileIndex */
      skip_spaces(&p);
      skip_nonspaces(&p);             /* skip Stream */
      skip_spaces(&p);
      skip_nonspaces(&p);             /* skip Opts_Digest */
      p++;                            /* skip space */
      fn = fname;
      while (*p != 0) {
         *fn++ = *p++;                /* copy filename */
      }
      *fn = *p++;                     /* term filename and point to attribs */
      attr = p;

      /*
       * Got attributes stream, decode it
       */
      switch (stream) {
      case STREAM_UNIX_ATTRIBUTES:
      case STREAM_UNIX_ATTRIBUTES_EX:
         int32_t LinkFIf, LinkFIc;
         Dmsg2(400, "file_index=%d attr=%s\n", file_index, attr);
         jcr->JobFiles++;
         jcr->FileIndex = file_index;    /* remember attribute file_index */
         jcr->previous_jr.FileIndex = file_index;
         decode_stat(attr, &statf, sizeof(statf), &LinkFIf);  /* decode file stat packet */
         do_Digest = CRYPTO_DIGEST_NONE;
         jcr->fn_printed = false;
         pm_strcpy(jcr->fname, fname);  /* move filename into JCR */

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

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

         Dmsg3(400, "Found %s in catalog. inx=%d Opts=%s\n",
               jcr->fname, file_index, Opts_Digest.c_str());
         decode_stat(fdbr.LStat, &statc, sizeof(statc), &LinkFIc); /* decode catalog stat */
         /*
          * Loop over options supplied by user and verify the
          * fields he requests.
          */
         for (p = Opts_Digest.c_str(); *p; p++) {
            char ed1[30], ed2[30];
            switch (*p) {
            case 'i':                /* compare INODEs */
               if (statc.st_ino != statf.st_ino) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_ino   differ. Cat: %s File: %s\n"),
                     edit_uint64((uint64_t)statc.st_ino, ed1),
                     edit_uint64((uint64_t)statf.st_ino, ed2));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'p':                /* permissions bits */
               if (statc.st_mode != statf.st_mode) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_mode  differ. Cat: %x File: %x\n"),
                     (uint32_t)statc.st_mode, (uint32_t)statf.st_mode);
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'n':                /* number of links */
               if (statc.st_nlink != statf.st_nlink) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_nlink differ. Cat: %d File: %d\n"),
                     (uint32_t)statc.st_nlink, (uint32_t)statf.st_nlink);
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'u':                /* user id */
               if (statc.st_uid != statf.st_uid) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_uid   differ. Cat: %u File: %u\n"),
                     (uint32_t)statc.st_uid, (uint32_t)statf.st_uid);
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'g':                /* group id */
               if (statc.st_gid != statf.st_gid) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_gid   differ. Cat: %u File: %u\n"),
                     (uint32_t)statc.st_gid, (uint32_t)statf.st_gid);
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 's':                /* size */
               if (statc.st_size != statf.st_size) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_size  differ. Cat: %s File: %s\n"),
                     edit_uint64((uint64_t)statc.st_size, ed1),
                     edit_uint64((uint64_t)statf.st_size, ed2));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'a':                /* access time */
               if (statc.st_atime != statf.st_atime) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_atime differs\n"));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'm':
               if (statc.st_mtime != statf.st_mtime) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_mtime differs\n"));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'c':                /* ctime */
               if (statc.st_ctime != statf.st_ctime) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_ctime differs\n"));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case 'd':                /* file size decrease */
               if (statc.st_size > statf.st_size) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      st_size  decrease. Cat: %s File: %s\n"),
                     edit_uint64((uint64_t)statc.st_size, ed1),
                     edit_uint64((uint64_t)statf.st_size, ed2));
                  jcr->setJobStatus(JS_Differences);
               }
               break;
            case '5':                /* compare MD5 */
               Dmsg1(500, "set Do_MD5 for %s\n", jcr->fname);
               do_Digest = CRYPTO_DIGEST_MD5;
               break;
            case '1':                 /* compare SHA1 */
               do_Digest = CRYPTO_DIGEST_SHA1;
               break;
            case ':':
            case 'V':
            default:
               break;
            }
         }
         break;

      case STREAM_RESTORE_OBJECT:
         Dmsg1(400, "RESTORE_OBJECT %s\n", jcr->fname);
         break;

      default:
         /*
          * Got Digest Signature from Storage daemon
          *  It came across in the Opts_Digest field.
          */
         if (crypto_digest_stream_type(stream) != CRYPTO_DIGEST_NONE) {
            Dmsg2(400, "stream=Digest inx=%d Digest=%s\n", file_index, Opts_Digest.c_str());
            /*
             * When ever we get a digest it MUST have been
             * preceded by an attributes record, which sets attr_file_index
             */
            if (jcr->FileIndex != (uint32_t)file_index) {
               Jmsg2(jcr, M_FATAL, 0, _("MD5/SHA1 index %d not same as attributes %d\n"),
                  file_index, jcr->FileIndex);
               goto bail_out;
            }
            if (do_Digest != CRYPTO_DIGEST_NONE) {
               db_escape_string(jcr, jcr->db, buf.c_str(), Opts_Digest.c_str(), strlen(Opts_Digest.c_str()));
               if (!bstrcmp(buf.c_str(), fdbr.Digest)) {
                  prt_fname(jcr);
                  Jmsg(jcr, M_INFO, 0, _("      %s differs. File=%s Cat=%s\n"),
                       stream_to_ascii(stream), buf.c_str(), fdbr.Digest);
                  jcr->setJobStatus(JS_Differences);
               }
               do_Digest = CRYPTO_DIGEST_NONE;
            }
         }
         break;
      }
      jcr->JobFiles = file_index;
   }

   if (is_bnet_error(fd)) {
      berrno be;
      Jmsg2(jcr, M_FATAL, 0, _("dir<filed: bad attributes from filed n=%d : %s\n"),
                        n, be.bstrerror());
      goto bail_out;
   }

   /* Now find all the files that are missing -- i.e. all files in
    *  the database where the MarkId != current JobId
    */
   jcr->fn_printed = false;
   Mmsg(buf,
      "SELECT Path.Path,Filename.Name FROM File,Path,Filename "
      "WHERE File.JobId=%d AND File.FileIndex > 0 "
      "AND File.MarkId!=%d AND File.PathId=Path.PathId "
      "AND File.FilenameId=Filename.FilenameId",
         JobId, jcr->JobId);
   /* missing_handler is called for each file found */
   db_sql_query(jcr->db, buf.c_str(), missing_handler, (void *)jcr);
   if (jcr->fn_printed) {
      jcr->setJobStatus(JS_Differences);
   }

bail_out:
   free_pool_memory(fname);
}
Example #13
0
static int u32_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
			  struct bstr *args)
{
	struct bstr *a;
	int align, nh_len;
	unsigned long key, mask, offmask = 0, offset;
	struct tc_u32_key u_key;

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

#define PARSE_ERR(CARG, FMT, ARGS...) \
	em_parse_error(EINVAL, args, CARG, &u32_ematch_util, FMT ,##ARGS)

	if (args == NULL)
		return PARSE_ERR(args, "u32: missing arguments");

	if (!bstrcmp(args, "u8"))
		align = 1;
	else if (!bstrcmp(args, "u16"))
		align = 2;
	else if (!bstrcmp(args, "u32"))
		align = 4;
	else
		return PARSE_ERR(args, "u32: invalid alignment");

	a = bstr_next(args);
	if (a == NULL)
		return PARSE_ERR(a, "u32: missing key");

	key = bstrtoul(a);
	if (key == ULONG_MAX)
		return PARSE_ERR(a, "u32: invalid key, must be numeric");

	a = bstr_next(a);
	if (a == NULL)
		return PARSE_ERR(a, "u32: missing mask");

	mask = bstrtoul(a);
	if (mask == ULONG_MAX)
		return PARSE_ERR(a, "u32: invalid mask, must be numeric");

	a = bstr_next(a);
	if (a == NULL || bstrcmp(a, "at") != 0)
		return PARSE_ERR(a, "u32: missing \"at\"");

	a = bstr_next(a);
	if (a == NULL)
		return PARSE_ERR(a, "u32: missing offset");

	nh_len = strlen("nexthdr+");
	if (a->len > nh_len && !memcmp(a->data, "nexthdr+", nh_len)) {
		char buf[a->len - nh_len + 1];
		offmask = -1;
		memcpy(buf, a->data + nh_len, a->len - nh_len);
		offset = strtoul(buf, NULL, 0);
	} else if (!bstrcmp(a, "nexthdr+")) {
		a = bstr_next(a);
		if (a == NULL)
			return PARSE_ERR(a, "u32: missing offset");
		offset = bstrtoul(a);
	} else
		offset = bstrtoul(a);

	if (offset == ULONG_MAX)
		return PARSE_ERR(a, "u32: invalid offset");

	if (a->next)
		return PARSE_ERR(a->next, "u32: unexpected trailer");

	switch (align) {
		case 1:
			if (key > 0xFF)
				return PARSE_ERR(a, "Illegal key (>0xFF)");
			if (mask > 0xFF)
				return PARSE_ERR(a, "Illegal mask (>0xFF)");

			key <<= 24 - ((offset & 3) * 8);
			mask <<= 24 - ((offset & 3) * 8);
			offset &= ~3;
			break;

		case 2:
			if (key > 0xFFFF)
				return PARSE_ERR(a, "Illegal key (>0xFFFF)");
			if (mask > 0xFFFF)
				return PARSE_ERR(a, "Illegal mask (>0xFFFF)");

			if ((offset & 3) == 0) {
				key <<= 16;
				mask <<= 16;
			}
			offset &= ~3;
			break;
	}

	key = htonl(key);
	mask = htonl(mask);

	if (offset % 4)
		return PARSE_ERR(a, "u32: invalid offset alignment, " \
		    "must be aligned to 4.");

	key &= mask;

	u_key.mask = mask;
	u_key.val = key;
	u_key.off = offset;
	u_key.offmask = offmask;

	addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
	addraw_l(n, MAX_MSG, &u_key, sizeof(u_key));

#undef PARSE_ERR
	return 0;
}
Example #14
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)) {
         bool gui = ua->gui;

         /*
          * 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;
         }

         /*
          * If we need to audit this event do it now.
          */
         if (audit_event_wanted(ua, commands[i].audit_event)) {
            log_audit_event_cmdline(ua);
         }

         /*
          * 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, true)) {
            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;
}
Example #15
0
bool DEVICE::scan_dir_for_volume(DCR *dcr)
{
   DIR* dp;
   struct dirent *entry, *result;
   int name_max;
   char *mount_point;
   VOLUME_CAT_INFO dcrVolCatInfo, devVolCatInfo;
   char VolumeName[MAX_NAME_LENGTH];
   struct stat statp;
   bool found = false;
   POOL_MEM fname(PM_FNAME);
   bool need_slash = false;
   int len;

   dcrVolCatInfo = dcr->VolCatInfo;     /* structure assignment */
   devVolCatInfo = VolCatInfo;          /* structure assignment */
   bstrncpy(VolumeName, dcr->VolumeName, sizeof(VolumeName));

   name_max = pathconf(".", _PC_NAME_MAX);
   if (name_max < 1024) {
      name_max = 1024;
   }

   if (device->mount_point) {
      mount_point = device->mount_point;
   } else {
      mount_point = device->device_name;
   }

   if (!(dp = opendir(mount_point))) {
      berrno be;
      dev_errno = errno;
      Dmsg3(29, "scan_dir_for_vol: failed to open dir %s (dev=%s), ERR=%s\n",
            mount_point, print_name(), be.bstrerror());
      goto get_out;
   }

   len = strlen(mount_point);
   if (len > 0) {
      need_slash = !IsPathSeparator(mount_point[len - 1]);
   }
   entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
   for ( ;; ) {
      if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
         dev_errno = EIO;
         Dmsg2(129, "scan_dir_for_vol: failed to find suitable file in dir %s (dev=%s)\n",
               mount_point, print_name());
         break;
      }
      if (bstrcmp(result->d_name, ".") ||
          bstrcmp(result->d_name, "..")) {
         continue;
      }

      if (!is_volume_name_legal(result->d_name)) {
         continue;
      }
      pm_strcpy(fname, mount_point);
      if (need_slash) {
         pm_strcat(fname, "/");
      }
      pm_strcat(fname, result->d_name);
      if (lstat(fname.c_str(), &statp) != 0 ||
          !S_ISREG(statp.st_mode)) {
         continue;                 /* ignore directories & special files */
      }

      /*
       * OK, we got a different volume mounted. First save the
       *  requested Volume info (dcr) structure, then query if
       *  this volume is really OK. If not, put back the desired
       *  volume name, mark it not in changer and continue.
       */
      /* Check if this is a valid Volume in the pool */
      bstrncpy(dcr->VolumeName, result->d_name, sizeof(dcr->VolumeName));
      if (!dcr->dir_get_volume_info(GET_VOL_INFO_FOR_WRITE)) {
         continue;
      }
      /* This was not the volume we expected, but it is OK with
       * the Director, so use it.
       */
      VolCatInfo = dcr->VolCatInfo;       /* structure assignment */
      found = true;
      break;                /* got a Volume */
   }
   free(entry);
   closedir(dp);

get_out:
   if (!found) {
      /* Restore VolumeName we really wanted */
      bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName));
      dcr->VolCatInfo = dcrVolCatInfo;     /* structure assignment */
      VolCatInfo = devVolCatInfo;          /* structure assignment */
   }
   Dsm_check(100);
   return found;
}
Example #16
0
static struct bstr strip_ext(struct bstr str)
{
    int dotpos = bstrrchr(str, '.');
    if (dotpos < 0)
        return str;
    return (struct bstr){str.start, dotpos};
}

static struct bstr get_ext(struct bstr s)
{
    int dotpos = bstrrchr(s, '.');
    if (dotpos < 0)
        return (struct bstr){NULL, 0};
    return bstr_splice(s, dotpos + 1, s.len);
}

bool mp_might_be_subtitle_file(const char *filename)
{
    return is_sub_ext(get_ext(bstr0(filename)));
}

static int compare_sub_filename(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    return strcoll(s1->fname, s2->fname);
}

static int compare_sub_priority(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    if (s1->priority > s2->priority)
        return -1;
    if (s1->priority < s2->priority)
        return 1;
    return strcoll(s1->fname, s2->fname);
}

static struct bstr guess_lang_from_filename(struct bstr name)
{
    if (name.len < 2)
        return (struct bstr){NULL, 0};

    int n = 0;
    int i = name.len - 1;

    if (name.start[i] == ')' || name.start[i] == ']')
        i--;
    while (i >= 0 && isalpha(name.start[i])) {
        n++;
        if (n > 3)
            return (struct bstr){NULL, 0};
        i--;
    }
    if (n < 2)
        return (struct bstr){NULL, 0};
    return (struct bstr){name.start + i + 1, n};
}

/**
 * @brief Append all the subtitles in the given path matching fname
 * @param opts MPlayer options
 * @param slist pointer to the subtitles list tallocated
 * @param nsub pointer to the number of subtitles
 * @param path Look for subtitles in this directory
 * @param fname Subtitle filename (pattern)
 * @param limit_fuzziness Ignore flag when sub_fuziness == 2
 */
static void append_dir_subtitles(struct mpv_global *global,
                                 struct subfn **slist, int *nsub,
                                 struct bstr path, const char *fname,
                                 int limit_fuzziness)
{
    void *tmpmem = talloc_new(NULL);
    struct MPOpts *opts = global->opts;
    struct mp_log *log = mp_log_new(tmpmem, global->log, "find_subfiles");

    if (mp_is_url(bstr0(fname)))
        goto out;

    struct bstr f_fname = bstr0(mp_basename(fname));
    struct bstr f_fname_noext = bstrdup(tmpmem, strip_ext(f_fname));
    bstr_lower(f_fname_noext);
    struct bstr f_fname_trim = bstr_strip(f_fname_noext);

    // 0 = nothing
    // 1 = any subtitle file
    // 2 = any sub file containing movie name
    // 3 = sub file containing movie name and the lang extension
    char *path0 = bstrdup0(tmpmem, path);
    DIR *d = opendir(path0);
    if (!d)
        goto out;
    mp_verbose(log, "Load subtitles in %.*s\n", BSTR_P(path));
    struct dirent *de;
    while ((de = readdir(d))) {
        struct bstr dename = bstr0(de->d_name);
        void *tmpmem2 = talloc_new(tmpmem);

        // retrieve various parts of the filename
        struct bstr tmp_fname_noext = bstrdup(tmpmem2, strip_ext(dename));
        bstr_lower(tmp_fname_noext);
        struct bstr tmp_fname_ext = get_ext(dename);
        struct bstr tmp_fname_trim = bstr_strip(tmp_fname_noext);

        // does it end with a subtitle extension?
        if (!is_sub_ext(tmp_fname_ext))
            goto next_sub;

        // we have a (likely) subtitle file
        int prio = 0;
        char *found_lang = NULL;
        if (opts->sub_lang) {
            if (bstr_startswith(tmp_fname_trim, f_fname_trim)) {
                struct bstr lang = guess_lang_from_filename(tmp_fname_trim);
                if (lang.len) {
                    for (int n = 0; opts->sub_lang[n]; n++) {
                        if (bstr_startswith0(lang, opts->sub_lang[n])) {
                            prio = 4; // matches the movie name + lang extension
                            found_lang = opts->sub_lang[n];
                            break;
                        }
                    }
                }
            }
        }
        if (!prio && bstrcmp(tmp_fname_trim, f_fname_trim) == 0)
            prio = 3; // matches the movie name
        if (!prio && bstr_find(tmp_fname_trim, f_fname_trim) >= 0
            && opts->sub_match_fuzziness >= 1)
            prio = 2; // contains the movie name
        if (!prio) {
            // doesn't contain the movie name
            // don't try in the mplayer subtitle directory
            if (!limit_fuzziness && opts->sub_match_fuzziness >= 2) {
                prio = 1;
            }
        }

        mp_dbg(log, "Potential sub file: \"%s\"  Priority: %d\n", de->d_name, prio);
        if (prio) {
            prio += prio;
            char *subpath = mp_path_join(*slist, path, dename);
            if (mp_path_exists(subpath)) {
                MP_GROW_ARRAY(*slist, *nsub);
                struct subfn *sub = *slist + (*nsub)++;

                // annoying and redundant
                if (strncmp(subpath, "./", 2) == 0)
                    subpath += 2;

                sub->priority = prio;
                sub->fname    = subpath;
                sub->lang     = found_lang;
            } else
                talloc_free(subpath);
        }

    next_sub:
        talloc_free(tmpmem2);
    }
    closedir(d);

 out:
    talloc_free(tmpmem);
}

static bool case_endswith(const char *s, const char *end)
{
    size_t len = strlen(s);
    size_t elen = strlen(end);
    return len >= elen && strcasecmp(s + len - elen, end) == 0;
}

// Drop .sub file if .idx file exists.
// Assumes slist is sorted by compare_sub_filename.
static void filter_subidx(struct subfn **slist, int *nsub)
{
    const char *prev = NULL;
    for (int n = 0; n < *nsub; n++) {
        const char *fname = (*slist)[n].fname;
        if (case_endswith(fname, ".idx")) {
            prev = fname;
        } else if (case_endswith(fname, ".sub")) {
            if (prev && strncmp(prev, fname, strlen(fname) - 4) == 0)
                (*slist)[n].priority = -1;
        }
    }
    for (int n = *nsub - 1; n >= 0; n--) {
        if ((*slist)[n].priority < 0)
            MP_TARRAY_REMOVE_AT(*slist, *nsub, n);
    }
}

// Return a list of subtitles found, sorted by priority.
// Last element is terminated with a fname==NULL entry.
struct subfn *find_text_subtitles(struct mpv_global *global, const char *fname)
{
    struct MPOpts *opts = global->opts;
    struct subfn *slist = talloc_array_ptrtype(NULL, slist, 1);
    int n = 0;

    // Load subtitles from current media directory
    append_dir_subtitles(global, &slist, &n, mp_dirname(fname), fname, 0);

    // Load subtitles in dirs specified by sub-paths option
    if (opts->sub_paths) {
        for (int i = 0; opts->sub_paths[i]; i++) {
            char *path = mp_path_join(slist, mp_dirname(fname),
                                      bstr0(opts->sub_paths[i]));
            append_dir_subtitles(global, &slist, &n, bstr0(path), fname, 0);
        }
    }

    // Load subtitles in ~/.mpv/sub limiting sub fuzziness
    char *mp_subdir = mp_find_user_config_file(NULL, global, "sub/");
    if (mp_subdir)
        append_dir_subtitles(global, &slist, &n, bstr0(mp_subdir), fname, 1);
    talloc_free(mp_subdir);

    // Sort by name for filter_subidx()
    qsort(slist, n, sizeof(*slist), compare_sub_filename);

    filter_subidx(&slist, &n);

    // Sort subs by priority and append them
    qsort(slist, n, sizeof(*slist), compare_sub_priority);

    struct subfn z = {0};
    MP_TARRAY_APPEND(NULL, slist, n, z);

    return slist;
}
Example #17
0
int Route_children_compare(Heap *heap, void *x, void *y)
{
  return bstrcmp(((Route *)x)->name, ((Route *)y)->name);
}
Example #18
0
static int cmp_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
                          struct bstr *args)
{
    struct bstr *a;
    int align, opnd = 0;
    unsigned long offset = 0, layer = TCF_LAYER_NETWORK, mask = 0, value = 0;
    int offset_present = 0, value_present = 0;
    struct tcf_em_cmp cmp;

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

#define PARSE_ERR(CARG, FMT, ARGS...) \
	em_parse_error(EINVAL, args, CARG, &cmp_ematch_util, FMT ,##ARGS)

    if (args == NULL)
        return PARSE_ERR(args, "cmp: missing arguments");

    if (!bstrcmp(args, "u8"))
        align = TCF_EM_ALIGN_U8;
    else if (!bstrcmp(args, "u16"))
        align = TCF_EM_ALIGN_U16;
    else if (!bstrcmp(args, "u32"))
        align = TCF_EM_ALIGN_U32;
    else
        return PARSE_ERR(args, "cmp: invalid alignment");

    for (a = bstr_next(args); a; a = bstr_next(a)) {
        if (!bstrcmp(a, "at")) {
            if (a->next == NULL)
                return PARSE_ERR(a, "cmp: missing argument");
            a = bstr_next(a);

            offset = bstrtoul(a);
            if (offset == ULONG_MAX)
                return PARSE_ERR(a, "cmp: invalid offset, " \
                                 "must be numeric");

            offset_present = 1;
        } else if (!bstrcmp(a, "layer")) {
            if (a->next == NULL)
                return PARSE_ERR(a, "cmp: missing argument");
            a = bstr_next(a);

            layer = parse_layer(a);
            if (layer == INT_MAX) {
                layer = bstrtoul(a);
                if (layer == ULONG_MAX)
                    return PARSE_ERR(a, "cmp: invalid " \
                                     "layer");
            }

            if (layer > TCF_LAYER_MAX)
                return PARSE_ERR(a, "cmp: illegal layer, " \
                                 "must be in 0..%d", TCF_LAYER_MAX);
        } else if (!bstrcmp(a, "mask")) {
            if (a->next == NULL)
                return PARSE_ERR(a, "cmp: missing argument");
            a = bstr_next(a);

            mask = bstrtoul(a);
            if (mask == ULONG_MAX)
                return PARSE_ERR(a, "cmp: invalid mask");
        } else if (!bstrcmp(a, "trans")) {
            cmp.flags |= TCF_EM_CMP_TRANS;
        } else if (!bstrcmp(a, "eq") || !bstrcmp(a, "gt") ||
                   !bstrcmp(a, "lt")) {

            if (!bstrcmp(a, "eq"))
                opnd = TCF_EM_OPND_EQ;
            else if (!bstrcmp(a, "gt"))
                opnd = TCF_EM_OPND_GT;
            else if (!bstrcmp(a, "lt"))
                opnd = TCF_EM_OPND_LT;

            if (a->next == NULL)
                return PARSE_ERR(a, "cmp: missing argument");
            a = bstr_next(a);

            value = bstrtoul(a);
            if (value == ULONG_MAX)
                return PARSE_ERR(a, "cmp: invalid value");

            value_present = 1;
        } else
            return PARSE_ERR(a, "nbyte: unknown parameter");
    }

    if (offset_present == 0 || value_present == 0)
        return PARSE_ERR(a, "cmp: offset and value required");

    cmp.val = (__u32) value;
    cmp.mask = (__u32) mask;
    cmp.off = (__u16) offset;
    cmp.align = (__u8) align;
    cmp.layer = (__u8) layer;
    cmp.opnd = (__u8) opnd;

    addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
    addraw_l(n, MAX_MSG, &cmp, sizeof(cmp));

#undef PARSE_ERR
    return 0;
}
Example #19
0
/*
 * Check for duplicate jobs.
 *  Returns: true  if current job should continue
 *           false if current job should terminate
 */
bool allow_duplicate_job(JCR *jcr)
{
   JCR *djcr;                /* possible duplicate job */
   JOBRES *job = jcr->res.job;
   bool cancel_dup = false;
   bool cancel_me = false;

   /*
    * See if AllowDuplicateJobs is set or
    * if duplicate checking is disabled for this job.
    */
   if (job->AllowDuplicateJobs || jcr->IgnoreDuplicateJobChecking) {
      return true;
   }

   Dmsg0(800, "Enter allow_duplicate_job\n");

   /*
    * After this point, we do not want to allow any duplicate
    * job to run.
    */

   foreach_jcr(djcr) {
      if (jcr == djcr || djcr->JobId == 0) {
         continue;                   /* do not cancel this job or consoles */
      }

      /*
       * See if this Job has the IgnoreDuplicateJobChecking flag set, ignore it
       * for any checking against other jobs.
       */
      if (djcr->IgnoreDuplicateJobChecking) {
         continue;
      }

      if (bstrcmp(job->name(), djcr->res.job->name())) {
         if (job->DuplicateJobProximity > 0) {
            utime_t now = (utime_t)time(NULL);
            if ((now - djcr->start_time) > job->DuplicateJobProximity) {
               continue;               /* not really a duplicate */
            }
         }
         if (job->CancelLowerLevelDuplicates &&
             djcr->getJobType() == 'B' && jcr->getJobType() == 'B') {
            switch (jcr->getJobLevel()) {
            case L_FULL:
               if (djcr->getJobLevel() == L_DIFFERENTIAL ||
                   djcr->getJobLevel() == L_INCREMENTAL) {
                  cancel_dup = true;
               }
               break;
            case L_DIFFERENTIAL:
               if (djcr->getJobLevel() == L_INCREMENTAL) {
                  cancel_dup = true;
               }
               if (djcr->getJobLevel() == L_FULL) {
                  cancel_me = true;
               }
               break;
            case L_INCREMENTAL:
               if (djcr->getJobLevel() == L_FULL ||
                   djcr->getJobLevel() == L_DIFFERENTIAL) {
                  cancel_me = true;
               }
            }
            /*
             * cancel_dup will be done below
             */
            if (cancel_me) {
              /* Zap current job */
              jcr->setJobStatus(JS_Canceled);
              Jmsg(jcr, M_FATAL, 0, _("JobId %d already running. Duplicate job not allowed.\n"),
                 djcr->JobId);
              break;     /* get out of foreach_jcr */
            }
         }

         /*
          * Cancel one of the two jobs (me or dup)
          * If CancelQueuedDuplicates is set do so only if job is queued.
          */
         if (job->CancelQueuedDuplicates) {
             switch (djcr->JobStatus) {
             case JS_Created:
             case JS_WaitJobRes:
             case JS_WaitClientRes:
             case JS_WaitStoreRes:
             case JS_WaitPriority:
             case JS_WaitMaxJobs:
             case JS_WaitStartTime:
                cancel_dup = true;  /* cancel queued duplicate */
                break;
             default:
                break;
             }
         }

         if (cancel_dup || job->CancelRunningDuplicates) {
            /*
             * Zap the duplicated job djcr
             */
            UAContext *ua = new_ua_context(jcr);
            Jmsg(jcr, M_INFO, 0, _("Cancelling duplicate JobId=%d.\n"), djcr->JobId);
            cancel_job(ua, djcr);
            bmicrosleep(0, 500000);
            djcr->setJobStatus(JS_Canceled);
            cancel_job(ua, djcr);
            free_ua_context(ua);
            Dmsg2(800, "Cancel dup %p JobId=%d\n", djcr, djcr->JobId);
         } else {
            /*
             * Zap current job
             */
            jcr->setJobStatus(JS_Canceled);
            Jmsg(jcr, M_FATAL, 0, _("JobId %d already running. Duplicate job not allowed.\n"),
               djcr->JobId);
            Dmsg2(800, "Cancel me %p JobId=%d\n", jcr, jcr->JobId);
         }
         Dmsg4(800, "curJobId=%d use_cnt=%d dupJobId=%d use_cnt=%d\n",
               jcr->JobId, jcr->use_count(), djcr->JobId, djcr->use_count());
         break;                 /* did our work, get out of foreach loop */
      }
   }
   endeach_jcr(djcr);

   return true;
}
Example #20
0
int main (int argc, char *argv[])
{
   int i, ch;
   FILE *fd;
   char line[1000];
   char *VolumeName = NULL;
   char *bsrName = NULL;
   char *DirectorName = NULL;
   bool ignore_label_errors = false;
   DIRRES *director = NULL;

   setlocale(LC_ALL, "");
   bindtextdomain("bareos", LOCALEDIR);
   textdomain("bareos");
   init_stack_dump();
   lmgr_init_thread();

   working_directory = "/tmp";
   my_name_is(argc, argv, "bls");
   init_msg(NULL, NULL);              /* initialize message handler */

   OSDependentInit();

   ff = init_find_files();

   while ((ch = getopt(argc, argv, "b:c:D:d:e:i:jkLpvV:?")) != -1) {
      switch (ch) {
      case 'b':
         bsrName = optarg;
         break;

      case 'c':                    /* specify config file */
         if (configfile != NULL) {
            free(configfile);
         }
         configfile = bstrdup(optarg);
         break;

      case 'D':                    /* specify director name */
         if (DirectorName != NULL) {
            free(DirectorName);
         }
         DirectorName = bstrdup(optarg);
         break;

      case 'd':                    /* debug level */
         if (*optarg == 't') {
            dbg_timestamp = true;
         } else {
            debug_level = atoi(optarg);
            if (debug_level <= 0) {
               debug_level = 1;
            }
         }
         break;

      case 'e':                    /* exclude list */
         if ((fd = fopen(optarg, "rb")) == NULL) {
            berrno be;
            Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"),
               optarg, be.bstrerror());
            exit(1);
         }
         while (fgets(line, sizeof(line), fd) != NULL) {
            strip_trailing_junk(line);
            Dmsg1(100, "add_exclude %s\n", line);
            add_fname_to_exclude_list(ff, line);
         }
         fclose(fd);
         break;

      case 'i':                    /* include list */
         if ((fd = fopen(optarg, "rb")) == NULL) {
            berrno be;
            Pmsg2(0, _("Could not open include file: %s, ERR=%s\n"),
               optarg, be.bstrerror());
            exit(1);
         }
         while (fgets(line, sizeof(line), fd) != NULL) {
            strip_trailing_junk(line);
            Dmsg1(100, "add_include %s\n", line);
            add_fname_to_include_list(ff, 0, line);
         }
         fclose(fd);
         break;

      case 'j':
         list_jobs = true;
         break;

      case 'k':
         list_blocks = true;
         break;

      case 'L':
         dump_label = true;
         break;

      case 'p':
         ignore_label_errors = true;
         forge_on = true;
         break;

      case 'v':
         verbose++;
         break;

      case 'V':                    /* Volume name */
         VolumeName = optarg;
         break;

      case '?':
      default:
         usage();

      } /* end switch */
   } /* end while */
   argc -= optind;
   argv += optind;

   if (!argc) {
      Pmsg0(0, _("No archive name specified\n"));
      usage();
   }

   if (configfile == NULL) {
      configfile = bstrdup(CONFIG_FILE);
   }

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

   if (DirectorName) {
      foreach_res(director, R_DIRECTOR) {
         if (bstrcmp(director->name(), DirectorName)) {
            break;
         }
      }
      if (!director) {
         Emsg2(M_ERROR_TERM, 0, _("No Director resource named %s defined in %s. Cannot continue.\n"),
               DirectorName, configfile);
      }
   }

   load_sd_plugins(me->plugin_directory, me->plugin_names);

   read_crypto_cache(me->working_directory, "bareos-sd",
                     get_first_port_host_order(me->SDaddrs));

   if (ff->included_files_list == NULL) {
      add_fname_to_include_list(ff, 0, "/");
   }

   for (i=0; i < argc; i++) {
      if (bsrName) {
         bsr = parse_bsr(NULL, bsrName);
      }
      dcr = New(DCR);
      jcr = setup_jcr("bls", argv[i], bsr, director, dcr, VolumeName, true); /* read device */
      if (!jcr) {
         exit(1);
      }
      jcr->ignore_label_errors = ignore_label_errors;
      dev = jcr->dcr->dev;
      if (!dev) {
         exit(1);
      }
      dcr = jcr->dcr;
      rec = new_record();
      attr = new_attr(jcr);
      /*
       * Assume that we have already read the volume label.
       * If on second or subsequent volume, adjust buffer pointer
       */
      if (dev->VolHdr.PrevVolumeName[0] != 0) { /* second volume */
         Pmsg1(0, _("\n"
                    "Warning, this Volume is a continuation of Volume %s\n"),
                dev->VolHdr.PrevVolumeName);
      }

      if (list_blocks) {
         do_blocks(argv[i]);
      } else if (list_jobs) {
         do_jobs(argv[i]);
      } else {
         do_ls(argv[i]);
      }
      do_close(jcr);
   }
   if (bsr) {
      free_bsr(bsr);
   }
   term_include_exclude_files(ff);
   term_find_files(ff);
   return 0;
}
Example #21
0
static int cpustr_to_cpulist_logical(bstring bcpustr, int* cpulist, int length)
{
    topology_init();
    CpuTopology_t cpuid_topology = get_cpuTopology();
    affinity_init();
    AffinityDomains_t affinity = get_affinityDomains();
    int domainidx = -1;
    bstring bdomain;
    bstring blist;
    if (bstrchrp(bcpustr, 'L', 0) != 0)
    {
        fprintf(stderr, "Not a valid CPU expression\n");
        return 0;
    }
    struct bstrList* strlist = bstrListCreate();
    strlist = bsplit(bcpustr, ':');
    if (strlist->qty != 3)
    {
        fprintf(stderr, "ERROR: Invalid expression, should look like L:<domain>:<indexlist> or be in a cpuset\n");
        bstrListDestroy(strlist);
        return 0;
    }
    bdomain = bstrcpy(strlist->entry[1]);
    blist = bstrcpy(strlist->entry[2]);
    bstrListDestroy(strlist);
    for (int i=0; i<affinity->numberOfAffinityDomains; i++)
    {
        if (bstrcmp(bdomain, affinity->domains[i].tag) == 0)
        {
            domainidx = i;
            break;
        }
    }
    if (domainidx < 0)
    {
        fprintf(stderr, "Cannot find domain %s\n", bdata(bdomain));
        return 0;
    }
    int *inlist = malloc(affinity->domains[domainidx].numberOfProcessors * sizeof(int));
    if (inlist == NULL)
    {
        return -ENOMEM;
    }
    int ret = cpulist_sort(affinity->domains[domainidx].processorList, inlist, affinity->domains[domainidx].numberOfProcessors);

    strlist = bstrListCreate();
    strlist = bsplit(blist, ',');
    int insert = 0;
    for (int i=0; i< strlist->qty; i++)
    {
        if (bstrchrp(strlist->entry[i], '-', 0) != BSTR_ERR)
        {
            struct bstrList* indexlist = bstrListCreate();
            indexlist = bsplit(strlist->entry[i], '-');
            if (atoi(bdata(indexlist->entry[0])) <= atoi(bdata(indexlist->entry[1])))
            {
                for (int j=atoi(bdata(indexlist->entry[0])); j<=atoi(bdata(indexlist->entry[1]));j++)
                {
                    cpulist[insert] = inlist[j];
                    insert++;
                    if (insert == length)
                    {
                        bstrListDestroy(indexlist);
                        goto logical_done;
                    }
                }
            }
            else
            {
                for (int j=atoi(bdata(indexlist->entry[0])); j>=atoi(bdata(indexlist->entry[1]));j--)
                {
                    cpulist[insert] = inlist[j];
                    insert++;
                    if (insert == length)
                    {
                        bstrListDestroy(indexlist);
                        goto logical_done;
                    }
                }
            }
            bstrListDestroy(indexlist);
        }
        else
        {
            cpulist[insert] = inlist[atoi(bdata(strlist->entry[i]))];
            insert++;
            if (insert == length)
            {
                goto logical_done;
            }
        }
    }
logical_done:
    free(inlist);
    bstrListDestroy(strlist);
    return insert;
}
Example #22
0
/*
 * Read the volume label
 *
 *  If dcr->VolumeName == NULL, we accept any Bareos Volume
 *  If dcr->VolumeName[0] == 0, we accept any Bareos Volume
 *  otherwise dcr->VolumeName must match the Volume.
 *
 *  If VolName given, ensure that it matches
 *
 *  Returns VOL_  code as defined in record.h
 *    VOL_NOT_READ
 *    VOL_OK                          good label found
 *    VOL_NO_LABEL                    volume not labeled
 *    VOL_IO_ERROR                    I/O error reading tape
 *    VOL_NAME_ERROR                  label has wrong name
 *    VOL_CREATE_ERROR                Error creating label
 *    VOL_VERSION_ERROR               label has wrong version
 *    VOL_LABEL_ERROR                 bad label type
 *    VOL_NO_MEDIA                    no media in drive
 *
 *  The dcr block is emptied on return, and the Volume is
 *    rewound.
 */
int read_dev_volume_label(DCR *dcr)
{
   JCR *jcr = dcr->jcr;
   DEVICE * volatile dev = dcr->dev;
   char *VolName = dcr->VolumeName;
   DEV_RECORD *record;
   bool ok = false;
   DEV_BLOCK *block = dcr->block;
   int status;
   bool want_ansi_label;
   bool have_ansi_label = false;

   Dmsg4(100, "Enter read_volume_label res=%d device=%s vol=%s dev_Vol=%s\n",
      dev->num_reserved(), dev->print_name(), VolName,
      dev->VolHdr.VolumeName[0]?dev->VolHdr.VolumeName:"*NULL*");

   if (!dev->is_open()) {
      if (!dev->open(dcr, OPEN_READ_ONLY)) {
         return VOL_IO_ERROR;
      }
   }

   dev->clear_labeled();
   dev->clear_append();
   dev->clear_read();
   dev->label_type = B_BAREOS_LABEL;

   if (!dev->rewind(dcr)) {
      Mmsg(jcr->errmsg, _("Couldn't rewind device %s: ERR=%s\n"),
         dev->print_name(), dev->print_errmsg());
      Dmsg1(130, "return VOL_NO_MEDIA: %s", jcr->errmsg);
      return VOL_NO_MEDIA;
   }
   bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id));

   /*
    * The stored plugin handling the bsdEventLabelRead event can abort
    * the reading of the label by returning a non bRC_OK.
    */
   if (generate_plugin_event(jcr, bsdEventLabelRead, dcr) != bRC_OK) {
      Dmsg0(200, "Error from bsdEventLabelRead plugin event.\n");
      return VOL_NO_MEDIA;
   }

   /*
    * Read ANSI/IBM label if so requested
    */
   want_ansi_label = dcr->VolCatInfo.LabelType != B_BAREOS_LABEL ||
                     dcr->device->label_type != B_BAREOS_LABEL;
   if (want_ansi_label || dev->has_cap(CAP_CHECKLABELS)) {
      status = read_ansi_ibm_label(dcr);
      /*
       * If we want a label and didn't find it, return error
       */
      if (want_ansi_label && status != VOL_OK) {
         goto bail_out;
      }
      if (status == VOL_NAME_ERROR || status == VOL_LABEL_ERROR) {
         Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
              dev->print_name(), VolName, dev->VolHdr.VolumeName);
         if (!dev->poll && jcr->label_errors++ > 100) {
            Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg);
         }
         goto bail_out;
      }
      if (status != VOL_OK) {        /* Not an ANSI/IBM label, so re-read */
         dev->rewind(dcr);
      } else {
         have_ansi_label = true;
      }
   }

   /*
    * Read the Bareos Volume label block
    */
   record = new_record();
   empty_block(block);

   Dmsg0(130, "Big if statement in read_volume_label\n");
   if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
      Mmsg(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bareos "
           "labeled Volume, because: ERR=%s"), NPRT(VolName),
           dev->print_name(), dev->print_errmsg());
      Dmsg1(130, "%s", jcr->errmsg);
   } else if (!read_record_from_block(dcr, record)) {
      Mmsg(jcr->errmsg, _("Could not read Volume label from block.\n"));
      Dmsg1(130, "%s", jcr->errmsg);
   } else if (!unser_volume_label(dev, record)) {
      Mmsg(jcr->errmsg, _("Could not unserialize Volume label: ERR=%s\n"),
         dev->print_errmsg());
      Dmsg1(130, "%s", jcr->errmsg);
   } else if (!bstrcmp(dev->VolHdr.Id, BareosId) &&
              !bstrcmp(dev->VolHdr.Id, OldBaculaId) &&
              !bstrcmp(dev->VolHdr.Id, OlderBaculaId)) {
      Mmsg(jcr->errmsg, _("Volume Header Id bad: %s\n"), dev->VolHdr.Id);
      Dmsg1(130, "%s", jcr->errmsg);
   } else {
      ok = true;
   }
   free_record(record);              /* finished reading Volume record */

   if (!dev->is_volume_to_unload()) {
      dev->clear_unload();
   }

   if (!ok) {
      if (forge_on || jcr->ignore_label_errors) {
         dev->set_labeled();         /* set has Bareos label */
         Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg);
         goto ok_out;
      }
      Dmsg0(100, "No volume label - bailing out\n");
      status = VOL_NO_LABEL;
      goto bail_out;
   }

   /*
    * At this point, we have read the first Bareos block, and
    * then read the Bareos Volume label. Now we need to
    * make sure we have the right Volume.
    */
   if (dev->VolHdr.VerNum != BareosTapeVersion &&
       dev->VolHdr.VerNum != OldCompatibleBareosTapeVersion1 &&
       dev->VolHdr.VerNum != OldCompatibleBareosTapeVersion2 &&
       dev->VolHdr.VerNum != OldCompatibleBareosTapeVersion3) {
      Mmsg(jcr->errmsg, _("Volume on %s has wrong Bareos version. Wanted %d got %d\n"),
           dev->print_name(), BareosTapeVersion, dev->VolHdr.VerNum);
      Dmsg1(130, "VOL_VERSION_ERROR: %s", jcr->errmsg);
      status = VOL_VERSION_ERROR;
      goto bail_out;
   }

   /*
    * We are looking for either an unused Bareos tape (PRE_LABEL) or
    * a Bareos volume label (VOL_LABEL)
    */
   if (dev->VolHdr.LabelType != PRE_LABEL && dev->VolHdr.LabelType != VOL_LABEL) {
      Mmsg(jcr->errmsg, _("Volume on %s has bad Bareos label type: %x\n"),
          dev->print_name(), dev->VolHdr.LabelType);
      Dmsg1(130, "%s", jcr->errmsg);
      if (!dev->poll && jcr->label_errors++ > 100) {
         Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg);
      }
      Dmsg0(150, "return VOL_LABEL_ERROR\n");
      status = VOL_LABEL_ERROR;
      goto bail_out;
   }

   dev->set_labeled();               /* set has Bareos label */

   /* Compare Volume Names */
   Dmsg2(130, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolumeName);
   if (VolName && *VolName && *VolName != '*' && !bstrcmp(dev->VolHdr.VolumeName, VolName)) {
      Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
           dev->print_name(), VolName, dev->VolHdr.VolumeName);
      Dmsg1(130, "%s", jcr->errmsg);
      /*
       * Cancel Job if too many label errors
       *  => we are in a loop
       */
      if (!dev->poll && jcr->label_errors++ > 100) {
         Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg);
      }
      Dmsg0(150, "return VOL_NAME_ERROR\n");
      status = VOL_NAME_ERROR;
      goto bail_out;
   }

   if (debug_level >= 200) {
      dump_volume_label(dev);
   }

   Dmsg0(130, "Leave read_volume_label() VOL_OK\n");
   /*
    * If we are a streaming device, we only get one chance to read
    */
   if (!dev->has_cap(CAP_STREAM)) {
      dev->rewind(dcr);
      if (have_ansi_label) {
         status = read_ansi_ibm_label(dcr);
         /*
          * If we want a label and didn't find it, return error
          */
         if (status != VOL_OK) {
            goto bail_out;
         }
      }
   }

   Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName);
   if (reserve_volume(dcr, dev->VolHdr.VolumeName) == NULL) {
      Mmsg2(jcr->errmsg, _("Could not reserve volume %s on %s\n"),
           dev->VolHdr.VolumeName, dev->print_name());
      Dmsg2(150, "Could not reserve volume %s on %s\n", dev->VolHdr.VolumeName, dev->print_name());
      status = VOL_NAME_ERROR;
      goto bail_out;
   }

ok_out:
   /*
    * The stored plugin handling the bsdEventLabelVerified event can override
    * the return value e.g. although we think the volume label is ok the plugin
    * has reasons to override that. So when the plugin returns something else
    * then bRC_OK it want to tell us the volume is not OK to use and as
    * such we return VOL_NAME_ERROR as error although it might not be te
    * best error it should be sufficient.
    */
   if (generate_plugin_event(jcr, bsdEventLabelVerified, dcr) != bRC_OK) {
      Dmsg0(200, "Error from bsdEventLabelVerified plugin event.\n");
      status = VOL_NAME_ERROR;
      goto bail_out;
   }
   empty_block(block);
   return VOL_OK;

bail_out:
   empty_block(block);
   dev->rewind(dcr);
   Dmsg1(150, "return %d\n", status);
   return status;
}
Example #23
0
/*
 * (Un)mount the device (For a FILE device)
 */
static bool do_mount(DCR *dcr, bool mount, int dotimeout)
{
   DEVRES *device = dcr->dev->device;
   POOL_MEM ocmd(PM_FNAME);
   POOLMEM *results;
   DIR* dp;
   char *icmd;
   struct dirent *entry, *result;
   int status, tries, name_max, count;
   berrno be;

   Dsm_check(200);
   if (mount) {
      icmd = device->mount_command;
   } else {
      icmd = device->unmount_command;
   }

   dcr->dev->edit_mount_codes(ocmd, icmd);

   Dmsg2(100, "do_mount: cmd=%s mounted=%d\n", ocmd.c_str(), dcr->dev->is_mounted());

   if (dotimeout) {
      /* Try at most 10 times to (un)mount the device. This should perhaps be configurable. */
      tries = 10;
   } else {
      tries = 1;
   }
   results = get_memory(4000);

   /* If busy retry each second */
   Dmsg1(100, "do_mount run_prog=%s\n", ocmd.c_str());
   while ((status = run_program_full_output(ocmd.c_str(), dcr->dev->max_open_wait / 2, results)) != 0) {
      /* Doesn't work with internationalization (This is not a problem) */
      if (mount && fnmatch("*is already mounted on*", results, 0) == 0) {
         break;
      }
      if (!mount && fnmatch("* not mounted*", results, 0) == 0) {
         break;
      }
      if (tries-- > 0) {
         /* Sometimes the device cannot be mounted because it is already mounted.
          * Try to unmount it, then remount it */
         if (mount) {
            Dmsg1(400, "Trying to unmount the device %s...\n", dcr->dev->print_name());
            do_mount(dcr, 0, 0);
         }
         bmicrosleep(1, 0);
         continue;
      }
      Dmsg5(100, "Device %s cannot be %smounted. status=%d result=%s ERR=%s\n", dcr->dev->print_name(),
           (mount ? "" : "un"), status, results, be.bstrerror(status));
      Mmsg(dcr->dev->errmsg, _("Device %s cannot be %smounted. ERR=%s\n"),
           dcr->dev->print_name(), (mount ? "" : "un"), be.bstrerror(status));

      /*
       * Now, just to be sure it is not mounted, try to read the filesystem.
       */
      name_max = pathconf(".", _PC_NAME_MAX);
      if (name_max < 1024) {
         name_max = 1024;
      }

      if (!(dp = opendir(device->mount_point))) {
         berrno be;
         dcr->dev->dev_errno = errno;
         Dmsg3(100, "do_mount: failed to open dir %s (dev=%s), ERR=%s\n",
               device->mount_point, dcr->dev->print_name(), be.bstrerror());
         goto get_out;
      }

      entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
      count = 0;
      while (1) {
         if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
            dcr->dev->dev_errno = EIO;
            Dmsg2(129, "do_mount: failed to find suitable file in dir %s (dev=%s)\n",
                  device->mount_point, dcr->dev->print_name());
            break;
         }
         if (!bstrcmp(result->d_name, ".") && !bstrcmp(result->d_name, "..") && !bstrcmp(result->d_name, ".keep")) {
            count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
            break;
         } else {
            Dmsg2(129, "do_mount: ignoring %s in %s\n", result->d_name, device->mount_point);
         }
      }
      free(entry);
      closedir(dp);

      Dmsg1(100, "do_mount: got %d files in the mount point (not counting ., .. and .keep)\n", count);

      if (count > 0) {
         /* If we got more than ., .. and .keep */
         /*   there must be something mounted */
         if (mount) {
            Dmsg1(100, "Did Mount by count=%d\n", count);
            break;
         } else {
            /* An unmount request. We failed to unmount - report an error */
            free_pool_memory(results);
            Dmsg0(200, "== error mount=1 wanted unmount\n");
            return false;
         }
      }
get_out:
      free_pool_memory(results);
      Dmsg0(200, "============ mount=0\n");
      Dsm_check(200);
      return false;
   }

   free_pool_memory(results);
   Dmsg1(200, "============ mount=%d\n", mount);
   return true;
}
Example #24
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(RUNRES));

   /*
    * 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 '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 '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);
}
Example #25
0
File: tree.c Project: AlD/bareos
/*
 * Insert a node in the tree. This is the main subroutine called when building a tree.
 */
TREE_NODE *insert_tree_node(char *path, char *fname, int type,
                            TREE_ROOT *root, TREE_NODE *parent)
{
   char *p, *q;
   int path_len = strlen(path);
   TREE_NODE *node;

   Dmsg1(100, "insert_tree_node: %s\n", path);

   /*
    * If trailing slash on path, strip it
    */
   if (path_len > 0) {
      q = path + path_len - 1;
      if (IsPathSeparator(*q)) {
         *q = 0;                      /* strip trailing slash */
      } else {
         q = NULL;                    /* no trailing slash */
      }
   } else {
      q = NULL;                       /* no trailing slash */
   }

   /*
    * If no filename, strip last component of path as "filename"
    */
   if (*fname == 0) {
      p = (char *)last_path_separator(path);  /* separate path and filename */
      if (p) {
         fname = p + 1;               /* set new filename */
         *p = '\0';                   /* terminate new path */
      }
   } else {
      p = NULL;
   }

   if (*fname) {
      if (!parent) {                  /* if no parent, we need to make one */
         Dmsg1(100, "make_tree_path for %s\n", path);
         path_len = strlen(path);     /* get new length */
         if (path_len == root->cached_path_len &&
             bstrcmp(path, root->cached_path)) {
            parent = root->cached_parent;
         } else {
            root->cached_path_len = path_len;
            pm_strcpy(&root->cached_path, path);
            parent = make_tree_path(path, root);
            root->cached_parent = parent;
         }
         Dmsg1(100, "parent=%s\n", parent->fname);
      }
   } else {
      fname = path;
      if (!parent) {
         parent = (TREE_NODE *)root;
         type = TN_DIR_NLS;
      }
      Dmsg1(100, "No / found: %s\n", path);
   }

   node = search_and_insert_tree_node(fname, 0, root, parent);

   if (q) {                           /* if trailing slash on entry */
      *q = '/';                       /*  restore it */
   }

   if (p) {                           /* if slash in path trashed */
      *p = '/';                       /* restore full path */
   }

   return node;
}
Example #26
0
int run_scripts(JCR *jcr, alist *runscripts, const char *label, alist *allowed_script_dirs)
{
   RUNSCRIPT *script;
   bool runit;
   int when;

   Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);

   if (strstr(label, NT_("Before"))) {
      when = SCRIPT_Before;
   } else if (bstrcmp(label, NT_("ClientAfterVSS"))) {
      when = SCRIPT_AfterVSS;
   } else {
      when = SCRIPT_After;
   }

   if (runscripts == NULL) {
      Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
      return 0;
   }

   foreach_alist(script, runscripts) {
      Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
      runit = false;

      if ((script->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
         if ((script->on_success && (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created)) ||
             (script->on_failure && (job_canceled(jcr) || jcr->JobStatus == JS_Differences))) {
            Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n",
                  script->command, script->on_success, script->on_failure, jcr->JobStatus );
            runit = true;
         }
      }

      if ((script->when & SCRIPT_AfterVSS) && (when & SCRIPT_AfterVSS)) {
         if ((script->on_success && (jcr->JobStatus == JS_Blocked)) ||
             (script->on_failure && job_canceled(jcr))) {
            Dmsg4(200, "runscript: Run it because SCRIPT_AfterVSS (%s,%i,%i,%c)\n",
                  script->command, script->on_success, script->on_failure, jcr->JobStatus );
            runit = true;
         }
      }

      if ((script->when & SCRIPT_After) && (when & SCRIPT_After)) {
         if ((script->on_success && (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) ||
             (script->on_failure && (job_canceled(jcr) || jcr->JobStatus == JS_Differences))) {
            Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n",
                  script->command, script->on_success, script->on_failure, jcr->JobStatus );
            runit = true;
         }
      }

      if (!script->is_local()) {
         runit = false;
      }

      /*
       * We execute it
       */
      if (runit) {
         if (!script_dir_allowed(jcr, script, allowed_script_dirs)) {
            Dmsg1(200, "runscript: Not running script %s because its not in one of the allowed scripts dirs\n",
                  script->command);
            Jmsg(jcr, M_ERROR, 0, _("Runscript: run %s \"%s\" could not execute, "
                                    "not in one of the allowed scripts dirs\n"), label, script->command);
            jcr->setJobStatus(JS_ErrorTerminated);
            goto bail_out;
         }

         script->run(jcr, label);
      }
   }
Example #27
0
static int default_compare(void *a, void *b)
{
    return bstrcmp((bstring) a, (bstring) b);
}
Example #28
0
static int filerecord_cache_lookup(void *data, void *key) {
    bstring request_path = (bstring) key;
    FileRecord *fr = (FileRecord *) data;
    
    return !bstrcmp(fr->request_path, request_path);
}
Example #29
0
/*
 * Common routine for both label and relabel
 */
static int do_label(UAContext *ua, const char *cmd, bool relabel)
{
   USTORERES store;
   BSOCK *sd;
   char dev_name[MAX_NAME_LENGTH];
   MEDIA_DBR mr, omr;
   POOL_DBR pr;
   bool print_reminder = true;
   bool label_barcodes = false;
   bool label_encrypt = false;
   int ok = FALSE;
   int i, j;
   int drive;
   bool media_record_exists = false;
   static const char *barcode_keywords[] = {
      "barcode",
      "barcodes",
      NULL
   };

   if (!open_client_db(ua)) {
      return 1;
   }

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

   /*
    * Look for one of the barcode keywords
    */
   if (!relabel && (i = find_arg_keyword(ua, barcode_keywords)) >= 0) {
      /*
       * Now find the keyword in the list
       */
      if ((j = find_arg(ua, barcode_keywords[i])) > 0) {
         *ua->argk[j] = 0;      /* zap barcode keyword */
      }
      label_barcodes = true;
   }

   /*
    * Look for the encrypt keyword
    */
   if ((i = find_arg(ua, "encrypt")) > 0) {
      *ua->argk[i] = 0;         /* zap encrypt keyword */
      label_encrypt = true;
   }

   store.store = get_storage_resource(ua, true, label_barcodes);
   if (!store.store) {
      return 1;
   }

   switch (store.store->Protocol) {
   case APT_NDMPV2:
   case APT_NDMPV3:
   case APT_NDMPV4:
      /*
       * See if the user selected a NDMP storage device but its
       * handled by a native Bareos storage daemon e.g. we have
       * a paired_storage pointer.
       */
      if (store.store->paired_storage) {
         store.store = store.store->paired_storage;
      } else {
         ua->warning_msg(_("Storage has non-native protocol.\n"));
         return 1;
      }
      break;
   default:
      break;
   }

   pm_strcpy(store.store_source, _("command line"));
   set_wstorage(ua->jcr, &store);
   drive = get_storage_drive(ua, store.store);

   if (label_barcodes) {
      label_from_barcodes(ua, drive, label_encrypt);
      return 1;
   }

   /*
    * If relabel get name of Volume to relabel
    */
   if (relabel) {
      /*
       * Check for oldvolume=name
       */
      i = find_arg_with_value(ua, "oldvolume");
      if (i >= 0) {
         bstrncpy(omr.VolumeName, ua->argv[i], sizeof(omr.VolumeName));
         if (db_get_media_record(ua->jcr, ua->db, &omr)) {
            goto checkVol;
         }
         ua->error_msg("%s", db_strerror(ua->db));
      }
      /*
       * No keyword or Vol not found, ask user to select
       */
      if (!select_media_dbr(ua, &omr)) {
         return 1;
      }

      /*
       * Require Volume to be Purged or Recycled
       */
checkVol:
      if (!bstrcmp(omr.VolStatus, "Purged") && !bstrcmp(omr.VolStatus, "Recycle")) {
         ua->error_msg(_("Volume \"%s\" has VolStatus %s. It must be Purged or Recycled before relabeling.\n"),
            omr.VolumeName, omr.VolStatus);
         return 1;
      }
   }

   /*
    * Check for volume=NewVolume
    */
   i = find_arg_with_value(ua, "volume");
   if (i >= 0) {
      pm_strcpy(ua->cmd, ua->argv[i]);
      goto checkName;
   }

   /*
    * Get a new Volume name
    */
   for ( ;; ) {
      media_record_exists = false;
      if (!get_cmd(ua, _("Enter new Volume name: "))) {
         return 1;
      }
checkName:
      if (!is_volume_name_legal(ua, ua->cmd)) {
         continue;
      }

      /*
       * Search by Media name so set VolumeName and clear MediaId.
       */
      mr.MediaId = 0;
      bstrncpy(mr.VolumeName, ua->cmd, sizeof(mr.VolumeName));

      /*
       * If VolBytes are zero the Volume is not labeled
       */
      if (db_get_media_record(ua->jcr, ua->db, &mr)) {
         if (mr.VolBytes != 0) {
             ua->error_msg(_("Media record for new Volume \"%s\" already exists.\n"),
                mr.VolumeName);
             continue;
          }
          media_record_exists = true;
      }
      break;                          /* Got it */
   }

   /*
    * If autochanger, request slot
    */
   i = find_arg_with_value(ua, "slot");
   if (i >= 0) {
      mr.Slot = atoi(ua->argv[i]);
      if (mr.Slot < 0) {
         mr.Slot = 0;
      }
      mr.InChanger = mr.Slot > 0;  /* if slot give assume in changer */
   } else if (store.store->autochanger) {
      if (!get_pint(ua, _("Enter slot (0 or Enter for none): "))) {
         return 1;
      }
      mr.Slot = ua->pint32_val;
      if (mr.Slot < 0) {
         mr.Slot = 0;
      }
      mr.InChanger = mr.Slot > 0;  /* if slot give assume in changer */
   }
   set_storageid_in_mr(store.store, &mr);

   bstrncpy(mr.MediaType, store.store->media_type, sizeof(mr.MediaType));

   /*
    * Must select Pool if not already done
    */
   if (pr.PoolId == 0) {
      memset(&pr, 0, sizeof(pr));
      if (!select_pool_dbr(ua, &pr)) {
         return 1;
      }
   }

   /*
    * See if we need to generate a new passphrase for hardware encryption.
    */
   if (label_encrypt) {
      ua->info_msg(_("Generating new hardware encryption key\n"));
      if (!generate_new_encryption_key(ua, &mr)) {
         return 1;
      }
   }

   ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists, drive);

   if (ok) {
      sd = ua->jcr->store_bsock;
      if (relabel) {
         /*
          * Delete the old media record
          */
         if (!db_delete_media_record(ua->jcr, ua->db, &omr)) {
            ua->error_msg(_("Delete of Volume \"%s\" failed. ERR=%s"),
               omr.VolumeName, db_strerror(ua->db));
         } else {
            ua->info_msg(_("Old volume \"%s\" deleted from catalog.\n"),
               omr.VolumeName);
            /*
             * Update the number of Volumes in the pool
             */
            pr.NumVols--;
            if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
               ua->error_msg("%s", db_strerror(ua->db));
            }
         }
      }
      if (ua->automount) {
         bstrncpy(dev_name, store.store->dev_name(), sizeof(dev_name));
         ua->info_msg(_("Requesting to mount %s ...\n"), dev_name);
         bash_spaces(dev_name);
         sd->fsend("mount %s drive=%d", dev_name, drive);
         unbash_spaces(dev_name);

         /*
          * We use bget_dirmsg here and not bnet_recv because as part of
          * the mount request the stored can request catalog information for
          * any plugin who listens to the bsdEventLabelVerified event.
          * As we don't want to loose any non protocol data e.g. errors
          * without a 3xxx prefix we set the allow_any_message of
          * bget_dirmsg to true and as such is behaves like a normal
          * bnet_recv for any non protocol messages.
          */
         while (bget_dirmsg(sd, true) >= 0) {
            ua->send_msg("%s", sd->msg);

            /*
             * Here we can get
             *  3001 OK mount. Device=xxx      or
             *  3001 Mounted Volume vvvv
             *  3002 Device "DVD-Writer" (/dev/hdc) is mounted.
             *  3906 is cannot mount non-tape
             * So for those, no need to print a reminder
             */
            if (bstrncmp(sd->msg, "3001 ", 5) ||
                bstrncmp(sd->msg, "3002 ", 5) ||
                bstrncmp(sd->msg, "3906 ", 5)) {
               print_reminder = false;
            }
         }
      }
   }

   if (print_reminder) {
      ua->info_msg(_("Do not forget to mount the drive!!!\n"));
   }

   close_sd_bsock(ua);

   return 1;
}
Example #30
0
int main (int argc, char *argv[])
{
   int ch;
   bool ok;
   char *iVolumeName = NULL;
   char *oVolumeName = NULL;
   char *DirectorName = NULL;
   DIRRES *director = NULL;
   bool ignore_label_errors = false;
   DCR *in_dcr, *out_dcr;

   setlocale(LC_ALL, "");
   bindtextdomain("bareos", LOCALEDIR);
   textdomain("bareos");
   init_stack_dump();

   my_name_is(argc, argv, "bcopy");
   lmgr_init_thread();
   init_msg(NULL, NULL);

   while ((ch = getopt(argc, argv, "b:c:D:d:i:o:pvw:?")) != -1) {
      switch (ch) {
      case 'b':
         bsr = parse_bsr(NULL, optarg);
         break;

      case 'c':                    /* specify config file */
         if (configfile != NULL) {
            free(configfile);
         }
         configfile = bstrdup(optarg);
         break;

      case 'D':                    /* specify director name */
         if (DirectorName != NULL) {
            free(DirectorName);
         }
         DirectorName = bstrdup(optarg);
         break;

      case 'd':                    /* debug level */
         if (*optarg == 't') {
            dbg_timestamp = true;
         } else {
            debug_level = atoi(optarg);
            if (debug_level <= 0) {
               debug_level = 1;
            }
         }
         break;

      case 'i':                    /* input Volume name */
         iVolumeName = optarg;
         break;

      case 'o':                    /* output Volume name */
         oVolumeName = optarg;
         break;

      case 'p':
         ignore_label_errors = true;
         forge_on = true;
         break;

      case 'v':
         verbose++;
         break;

      case 'w':
         wd = optarg;
         break;

      case '?':
      default:
         usage();

      }
   }
   argc -= optind;
   argv += optind;

   if (argc != 2) {
      Pmsg0(0, _("Wrong number of arguments: \n"));
      usage();
   }

   OSDependentInit();

   working_directory = wd;

   if (configfile == NULL) {
      configfile = bstrdup(CONFIG_FILE);
   }

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

   if (DirectorName) {
      foreach_res(director, R_DIRECTOR) {
         if (bstrcmp(director->hdr.name, DirectorName)) {
            break;
         }
      }
      if (!director) {
         Emsg2(M_ERROR_TERM, 0, _("No Director resource named %s defined in %s. Cannot continue.\n"),
               DirectorName, configfile);
      }
   }

   load_sd_plugins(me->plugin_directory, me->plugin_names);

   read_crypto_cache(me->working_directory, "bareos-sd",
                     get_first_port_host_order(me->SDaddrs));

   /*
    * Setup and acquire input device for reading
    */
   Dmsg0(100, "About to setup input jcr\n");

   in_dcr = New(DCR);
   in_jcr = setup_jcr("bcopy", argv[0], bsr, director, in_dcr, iVolumeName, true); /* read device */
   if (!in_jcr) {
      exit(1);
   }

   in_jcr->ignore_label_errors = ignore_label_errors;

   in_dev = in_jcr->dcr->dev;
   if (!in_dev) {
      exit(1);
   }

   /*
    * Setup output device for writing
    */
   Dmsg0(100, "About to setup output jcr\n");

   out_dcr = New(DCR);
   out_jcr = setup_jcr("bcopy", argv[1], bsr, director, out_dcr, oVolumeName, false); /* write device */
   if (!out_jcr) {
      exit(1);
   }

   out_dev = out_jcr->dcr->dev;
   if (!out_dev) {
      exit(1);
   }

   Dmsg0(100, "About to acquire device for writing\n");

   /*
    * For we must now acquire the device for writing
    */
   out_dev->rLock(false);
   if (!out_dev->open(out_jcr->dcr, OPEN_READ_WRITE)) {
      Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
      out_dev->Unlock();
      exit(1);
   }
   out_dev->Unlock();
   if (!acquire_device_for_append(out_jcr->dcr)) {
      free_jcr(in_jcr);
      exit(1);
   }
   out_block = out_jcr->dcr->block;

   ok = read_records(in_jcr->dcr, record_cb, mount_next_read_volume);

   if (ok || out_dev->can_write()) {
      if (!out_jcr->dcr->write_block_to_device()) {
         Pmsg0(000, _("Write of last block failed.\n"));
      }
   }

   Pmsg2(000, _("%u Jobs copied. %u records copied.\n"), jobs, records);

   in_dev->term();
   out_dev->term();

   free_jcr(in_jcr);
   free_jcr(out_jcr);

   return 0;
}