Exemplo n.º 1
0
/*
 * Store a resource pointer in an alist. default_value indicates how many
 * times this routine can be called -- i.e. how many alists
 * there are.
 *
 * If we are in pass 2, do a lookup of the resource.
 */
static void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass)
{
   RES *res;
   int i = 0;
   alist *list;
   URES *res_all = (URES *)my_config->m_res_all;
   int count = str_to_int32(item->default_value);

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

      for (;;) {
         lex_get_token(lc, T_NAME);   /* scan next item */
         res = GetResWithName(item->code, lc->str);
         if (res == NULL) {
            scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"),
               item->name, lc->line_no, lc->line);
            return;
         }
         Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n",
               res, list, list->size(), i, item->name);
         list->append(res);
         (item->value)[i] = (char *)list;
         if (lc->ch != ',') {         /* if no other item follows */
            break;                    /* get out */
         }
         lex_get_token(lc, T_ALL);    /* eat comma */
      }
   }
   scan_to_eol(lc);
   set_bit(index, res_all->hdr.item_present);
}
Exemplo n.º 2
0
int
str_to_log_date_format (char *str, char *date_format_str)
{
  char *startp;
  char *endp;
  int i;
  int result = 0;
  int val;
  int date_val[DATE_VALUE_COUNT];

  for (i = 0; i < DATE_VALUE_COUNT; i++)
    date_val[i] = 0;

  for (i = 0, startp = str; i < DATE_VALUE_COUNT; i++)
    {
      result = str_to_int32 (&val, &endp, startp, 10);
      if (result != 0)
	{
	  goto error;
	}
      if (val < 0)
	{
	  val = 0;
	}
      else if (val > 999)
	{
	  val = 999;
	}
      date_val[i] = val;
      if (*endp == '\0')
	{
	  break;
	}
      startp = endp + 1;
      if (*startp == '\0')
	{
	  break;
	}
    }

  sprintf (date_format_str, "%02d-%02d-%02d %02d:%02d:%02d.%03d", date_val[0], date_val[1], date_val[2], date_val[3],
	   date_val[4], date_val[5], date_val[6]);
  return 0;

error:
  return -1;
}
Exemplo n.º 3
0
/*
 * Note, we receive the whole attribute record, but we select out only the stat
 * packet, VolSessionId, VolSessionTime, FileIndex, file type, and file name to
 * store in the catalog.
 */
static void update_attribute(JCR *jcr, char *msg, int32_t msglen)
{
   unser_declare;
   uint32_t VolSessionId, VolSessionTime;
   int32_t Stream;
   uint32_t FileIndex;
   char *p;
   int len;
   char *fname, *attr;
   ATTR_DBR *ar = NULL;
   uint32_t reclen;

   /*
    * Start transaction allocates jcr->attr and jcr->ar if needed
    */
   db_start_transaction(jcr, jcr->db);     /* start transaction if not already open */
   ar = jcr->ar;

   /*
    * Start by scanning directly in the message buffer to get Stream
    * there may be a cached attr so we cannot yet write into
    * jcr->attr or jcr->ar
    */
   p = msg;
   skip_nonspaces(&p);                /* UpdCat */
   skip_spaces(&p);
   skip_nonspaces(&p);                /* Job=nnn */
   skip_spaces(&p);
   skip_nonspaces(&p);                /* "FileAttributes" */
   p += 1;

   /*
    * The following "SD header" fields are serialized
    */
   unser_begin(p, 0);
   unser_uint32(VolSessionId);        /* VolSessionId */
   unser_uint32(VolSessionTime);      /* VolSessionTime */
   unser_int32(FileIndex);            /* FileIndex */
   unser_int32(Stream);               /* Stream */
   unser_uint32(reclen);              /* Record length */
   p += unser_length(p);              /* Raw record follows */

   /**
    * At this point p points to the raw record, which varies according
    *  to what kind of a record (Stream) was sent.  Note, the integer
    *  fields at the beginning of these "raw" records are in ASCII with
    *  spaces between them so one can use scanf or manual scanning to
    *  extract the fields.
    *
    * File Attributes
    *   File_index
    *   File type
    *   Filename (full path)
    *   Encoded attributes
    *   Link name (if type==FT_LNK or FT_LNKSAVED)
    *   Encoded extended-attributes (for Win32)
    *   Delta sequence number (32 bit int)
    *
    * Restore Object
    *   File_index
    *   File_type
    *   Object_index
    *   Object_len (possibly compressed)
    *   Object_full_len (not compressed)
    *   Object_compression
    *   Plugin_name
    *   Object_name
    *   Binary Object data
    */

   Dmsg1(400, "UpdCat msg=%s\n", msg);
   Dmsg5(400, "UpdCat VolSessId=%d VolSessT=%d FI=%d Strm=%d reclen=%d\n",
         VolSessionId, VolSessionTime, FileIndex, Stream, reclen);

   jcr->SDJobBytes += reclen; /* update number of bytes transferred for quotas */

   /*
    * Depending on the stream we are handling dispatch.
    */
   switch (Stream) {
   case STREAM_UNIX_ATTRIBUTES:
   case STREAM_UNIX_ATTRIBUTES_EX:
      if (jcr->cached_attribute) {
         Dmsg2(400, "Cached attr. Stream=%d fname=%s\n", ar->Stream, ar->fname);
         if (!db_create_attributes_record(jcr, jcr->db, ar)) {
            Jmsg1(jcr, M_FATAL, 0, _("Attribute create error: ERR=%s"), db_strerror(jcr->db));
         }
         jcr->cached_attribute = false;
      }

      /*
       * Any cached attr is flushed so we can reuse jcr->attr and jcr->ar
       */
      jcr->attr = check_pool_memory_size(jcr->attr, msglen);
      memcpy(jcr->attr, msg, msglen);
      p = jcr->attr - msg + p;         /* point p into jcr->attr */
      skip_nonspaces(&p);              /* skip FileIndex */
      skip_spaces(&p);
      ar->FileType = str_to_int32(p);
      skip_nonspaces(&p);              /* skip FileType */
      skip_spaces(&p);
      fname = p;
      len = strlen(fname);             /* length before attributes */
      attr = &fname[len+1];
      ar->DeltaSeq = 0;
      if (ar->FileType == FT_REG) {
         p = attr + strlen(attr) + 1;  /* point to link */
         p = p + strlen(p) + 1;        /* point to extended attributes */
         p = p + strlen(p) + 1;        /* point to delta sequence */
         /*
          * Older FDs don't have a delta sequence, so check if it is there
          */
         if (p - jcr->attr < msglen) {
            ar->DeltaSeq = str_to_int32(p); /* delta_seq */
         }
      }

      Dmsg2(400, "dird<stored: stream=%d %s\n", Stream, fname);
      Dmsg1(400, "dird<stored: attr=%s\n", attr);

      ar->attr = attr;
      ar->fname = fname;
      if (ar->FileType == FT_DELETED) {
         ar->FileIndex = 0;     /* special value */
      } else {
         ar->FileIndex = FileIndex;
      }
      ar->Stream = Stream;
      ar->link = NULL;
      if (jcr->mig_jcr) {
         ar->JobId = jcr->mig_jcr->JobId;
      } else {
         ar->JobId = jcr->JobId;
      }
      ar->Digest = NULL;
      ar->DigestType = CRYPTO_DIGEST_NONE;
      jcr->cached_attribute = true;

      Dmsg2(400, "dird<filed: stream=%d %s\n", Stream, fname);
      Dmsg1(400, "dird<filed: attr=%s\n", attr);
      break;
   case STREAM_RESTORE_OBJECT: {
      ROBJECT_DBR ro;

      memset(&ro, 0, sizeof(ro));
      ro.Stream = Stream;
      ro.FileIndex = FileIndex;
      if (jcr->mig_jcr) {
         ro.JobId = jcr->mig_jcr->JobId;
      } else {
         ro.JobId = jcr->JobId;
      }

      Dmsg1(100, "Robj=%s\n", p);

      skip_nonspaces(&p);                  /* skip FileIndex */
      skip_spaces(&p);
      ro.FileType = str_to_int32(p);        /* FileType */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_index = str_to_int32(p);    /* Object Index */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_len = str_to_int32(p);      /* object length possibly compressed */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_full_len = str_to_int32(p); /* uncompressed object length */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_compression = str_to_int32(p); /* compression */
      skip_nonspaces(&p);
      skip_spaces(&p);

      ro.plugin_name = p;                      /* point to plugin name */
      len = strlen(ro.plugin_name);
      ro.object_name = &ro.plugin_name[len+1]; /* point to object name */
      len = strlen(ro.object_name);
      ro.object = &ro.object_name[len+1];      /* point to object */
      ro.object[ro.object_len] = 0;            /* add zero for those who attempt printing */

      Dmsg7(100, "oname=%s stream=%d FT=%d FI=%d JobId=%d, obj_len=%d\nobj=\"%s\"\n",
            ro.object_name, ro.Stream, ro.FileType, ro.FileIndex, ro.JobId,
            ro.object_len, ro.object);

      /*
       * Store it.
       */
      if (!db_create_restore_object_record(jcr, jcr->db, &ro)) {
         Jmsg1(jcr, M_FATAL, 0, _("Restore object create error. %s"), db_strerror(jcr->db));
      }
      break;
   }
   default:
      if (crypto_digest_stream_type(Stream) != CRYPTO_DIGEST_NONE) {
         fname = p;
         if (ar->FileIndex != FileIndex) {
            Jmsg3(jcr, M_WARNING, 0, _("%s not same File=%d as attributes=%d\n"),
               stream_to_ascii(Stream), FileIndex, ar->FileIndex);
         } else {
            /*
             * Update digest in catalog
             */
            char digestbuf[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
            int len = 0;
            int type = CRYPTO_DIGEST_NONE;

            switch(Stream) {
            case STREAM_MD5_DIGEST:
               len = CRYPTO_DIGEST_MD5_SIZE;
               type = CRYPTO_DIGEST_MD5;
               break;
            case STREAM_SHA1_DIGEST:
               len = CRYPTO_DIGEST_SHA1_SIZE;
               type = CRYPTO_DIGEST_SHA1;
               break;
            case STREAM_SHA256_DIGEST:
               len = CRYPTO_DIGEST_SHA256_SIZE;
               type = CRYPTO_DIGEST_SHA256;
               break;
            case STREAM_SHA512_DIGEST:
               len = CRYPTO_DIGEST_SHA512_SIZE;
               type = CRYPTO_DIGEST_SHA512;
               break;
            default:
               /*
                * Never reached ...
                */
               Jmsg(jcr, M_ERROR, 0, _("Catalog error updating file digest. Unsupported digest stream type: %d"), Stream);
            }

            bin_to_base64(digestbuf, sizeof(digestbuf), fname, len, true);

            Dmsg3(400, "DigestLen=%d Digest=%s type=%d\n", strlen(digestbuf),
                  digestbuf, Stream);

            if (jcr->cached_attribute) {
               ar->Digest = digestbuf;
               ar->DigestType = type;

               Dmsg2(400, "Cached attr with digest. Stream=%d fname=%s\n", ar->Stream, ar->fname);

               /*
                * Update BaseFile table
                */
               if (!db_create_attributes_record(jcr, jcr->db, ar)) {
                  Jmsg1(jcr, M_FATAL, 0, _("attribute create error. %s"), db_strerror(jcr->db));
               }
               jcr->cached_attribute = false;
            } else {
               if (!db_add_digest_to_file_record(jcr, jcr->db, ar->FileId, digestbuf, type)) {
                  Jmsg(jcr, M_ERROR, 0, _("Catalog error updating file digest. %s"), db_strerror(jcr->db));
               }
            }
         }
      }
      break;
   }
}
Exemplo n.º 4
0
/*
 * Find Available Media (Volume) for Pool
 *
 * Find a Volume for a given PoolId, MediaType, and Status.
 * The unwanted_volumes variable lists the VolumeNames which we should skip if any.
 *
 * Returns: 0 on failure
 *          numrows on success
 */
int db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr, const char *unwanted_volumes)
{
   char ed1[50];
   int num_rows = 0;
   SQL_ROW row = NULL;
   bool find_oldest = false;
   bool found_candidate = false;
   char esc_type[MAX_ESCAPE_NAME_LENGTH];
   char esc_status[MAX_ESCAPE_NAME_LENGTH];

   db_lock(mdb);

   mdb->db_escape_string(jcr, esc_type, mr->MediaType, strlen(mr->MediaType));
   mdb->db_escape_string(jcr, esc_status, mr->VolStatus, strlen(mr->VolStatus));

   if (item == -1) {
      find_oldest = true;
      item = 1;
   }

retry_fetch:
   if (find_oldest) {
      /*
       * Find oldest volume(s)
       */
      Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
                     "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
                     "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
                     "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
                     "EndFile,EndBlock,LabelType,LabelDate,StorageId,"
                     "Enabled,LocationId,RecycleCount,InitialWrite,"
                     "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime,"
                     "ActionOnPurge,EncryptionKey,MinBlocksize,MaxBlocksize "
                     "FROM Media WHERE PoolId=%s AND MediaType='%s' AND VolStatus IN ('Full',"
                     "'Recycle','Purged','Used','Append') AND Enabled=1 "
                     "ORDER BY LastWritten LIMIT %d",
           edit_int64(mr->PoolId, ed1), esc_type, item);
   } else {
      POOL_MEM changer(PM_FNAME);
      const char *order;

      /*
       * Find next available volume
       */
      if (InChanger) {
         Mmsg(changer, "AND InChanger=1 AND StorageId=%s", edit_int64(mr->StorageId, ed1));
      }

      if (bstrcmp(mr->VolStatus, "Recycle") ||
          bstrcmp(mr->VolStatus, "Purged")) {
         order = "AND Recycle=1 ORDER BY LastWritten ASC,MediaId";  /* take oldest that can be recycled */
      } else {
         order = sql_media_order_most_recently_written[db_get_type_index(mdb)];    /* take most recently written */
      }

      Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
                     "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
                     "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
                     "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
                     "EndFile,EndBlock,LabelType,LabelDate,StorageId,"
                     "Enabled,LocationId,RecycleCount,InitialWrite,"
                     "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime,"
                     "ActionOnPurge,EncryptionKey,MinBlocksize,MaxBlocksize "
                     "FROM Media WHERE PoolId=%s AND MediaType='%s' AND Enabled=1 "
                     "AND VolStatus='%s' "
                     "%s "
                     "%s LIMIT %d",
           edit_int64(mr->PoolId, ed1), esc_type,
           esc_status, changer.c_str(), order, item);
   }

   Dmsg1(100, "fnextvol=%s\n", mdb->cmd);
   if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
      goto bail_out;
   }

   num_rows = sql_num_rows(mdb);
   if (item > num_rows || item < 1) {
      Dmsg2(050, "item=%d got=%d\n", item, num_rows);
      Mmsg2(&mdb->errmsg, _("Request for Volume item %d greater than max %d or less than 1\n"), item, num_rows);
      num_rows = 0;
      goto bail_out;
   }

   for (int i = 0 ; i < item; i++) {
      if ((row = sql_fetch_row(mdb)) == NULL) {
         Dmsg1(050, "Fail fetch item=%d\n", i);
         Mmsg1(&mdb->errmsg, _("No Volume record found for item %d.\n"), i);
         sql_free_result(mdb);
         num_rows = 0;
         goto bail_out;
      }

      /*
       * See if this is not on the unwanted volumes list.
       */
      if (unwanted_volumes && is_on_unwanted_volumes_list(row[1], unwanted_volumes)) {
         continue;
      }

      /*
       * Return fields in Media Record
       */
      mr->MediaId = str_to_int64(row[0]);
      bstrncpy(mr->VolumeName, (row[1] != NULL) ? row[1] : "", sizeof(mr->VolumeName));
      mr->VolJobs = str_to_int64(row[2]);
      mr->VolFiles = str_to_int64(row[3]);
      mr->VolBlocks = str_to_int64(row[4]);
      mr->VolBytes = str_to_uint64(row[5]);
      mr->VolMounts = str_to_int64(row[6]);
      mr->VolErrors = str_to_int64(row[7]);
      mr->VolWrites = str_to_int64(row[8]);
      mr->MaxVolBytes = str_to_uint64(row[9]);
      mr->VolCapacityBytes = str_to_uint64(row[10]);
      bstrncpy(mr->MediaType, (row[11] != NULL) ? row[11] : "", sizeof(mr->MediaType));
      bstrncpy(mr->VolStatus, (row[12] != NULL) ? row[12] : "", sizeof(mr->VolStatus));
      mr->PoolId = str_to_int64(row[13]);
      mr->VolRetention = str_to_uint64(row[14]);
      mr->VolUseDuration = str_to_uint64(row[15]);
      mr->MaxVolJobs = str_to_int64(row[16]);
      mr->MaxVolFiles = str_to_int64(row[17]);
      mr->Recycle = str_to_int64(row[18]);
      mr->Slot = str_to_int64(row[19]);
      bstrncpy(mr->cFirstWritten, (row[20] != NULL) ? row[20] : "", sizeof(mr->cFirstWritten));
      mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
      bstrncpy(mr->cLastWritten, (row[21] != NULL) ? row[21] : "", sizeof(mr->cLastWritten));
      mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
      mr->InChanger = str_to_uint64(row[22]);
      mr->EndFile = str_to_uint64(row[23]);
      mr->EndBlock = str_to_uint64(row[24]);
      mr->LabelType = str_to_int64(row[25]);
      bstrncpy(mr->cLabelDate, (row[26] != NULL) ? row[26] : "", sizeof(mr->cLabelDate));
      mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
      mr->StorageId = str_to_int64(row[27]);
      mr->Enabled = str_to_int64(row[28]);
      mr->LocationId = str_to_int64(row[29]);
      mr->RecycleCount = str_to_int64(row[30]);
      bstrncpy(mr->cInitialWrite, (row[31] != NULL) ? row[31] : "", sizeof(mr->cInitialWrite));
      mr->InitialWrite = (time_t)str_to_utime(mr->cInitialWrite);
      mr->ScratchPoolId = str_to_int64(row[32]);
      mr->RecyclePoolId = str_to_int64(row[33]);
      mr->VolReadTime = str_to_int64(row[34]);
      mr->VolWriteTime = str_to_int64(row[35]);
      mr->ActionOnPurge = str_to_int64(row[36]);
      bstrncpy(mr->EncrKey, (row[37] != NULL) ? row[37] : "", sizeof(mr->EncrKey));
      mr->MinBlocksize = str_to_int32(row[38]);
      mr->MaxBlocksize = str_to_int32(row[39]);

      sql_free_result(mdb);
      found_candidate = true;
      break;
   }

   if (!found_candidate && find_oldest) {
      item++;
      goto retry_fetch;
   }

bail_out:
   db_unlock(mdb);
   Dmsg1(050, "Rtn numrows=%d\n", num_rows);

   return num_rows;
}
Exemplo n.º 5
0
int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, int32_t reclen, ATTR *attr)
{
   char *p;
   int object_len;
   /*
    * An Attributes record consists of:
    *    File_index
    *    Type   (FT_types)
    *    Filename
    *    Attributes
    *    Link name (if file linked i.e. FT_LNK)
    *    Extended attributes (Win32)
    *  plus optional values determined by AR_ flags in upper bits of Type
    *    Data_stream
    *
    */
   attr->stream = stream;
   Dmsg1(dbglvl, "Attr: %s\n", rec);
   if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) {
      Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
      Dmsg1(dbglvl, "\nError scanning attributes. %s\n", rec);
      return 0;
   }
   Dmsg2(dbglvl, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
   /*
    * Note AR_DATA_STREAM should never be set since it is encoded
    *  at the end of the attributes.
    */
   if (attr->type & AR_DATA_STREAM) {
      attr->data_stream = 1;
   } else {
      attr->data_stream = 0;
   }
   attr->type &= FT_MASK;             /* keep only type bits */
   p = rec;
   while (*p++ != ' ')               /* skip record file index */
      { }
   while (*p++ != ' ')               /* skip type */
      { }

   attr->fname = p;                   /* set filname position */
   while (*p++ != 0)                  /* skip filename */
      { }
   attr->attr = p;                    /* set attributes position */
   while (*p++ != 0)                  /* skip attributes */
      { }
   attr->lname = p;                   /* set link position */
   while (*p++ != 0)                  /* skip link */
      { }
   attr->delta_seq = 0;
   if (attr->type == FT_RESTORE_FIRST) {
      /* We have an object, so do a binary copy */
      object_len = reclen + rec - p;
      attr->attrEx = check_pool_memory_size(attr->attrEx, object_len + 1);
      memcpy(attr->attrEx, p, object_len);
      /* Add a EOS for those who attempt to print the object */
      p = attr->attrEx + object_len;
      *p = 0;
   } else {
      pm_strcpy(attr->attrEx, p);     /* copy extended attributes, if any */
      if (attr->data_stream) {
         int64_t val;
         while (*p++ != 0)            /* skip extended attributes */
            { }
         from_base64(&val, p);
         attr->data_stream = (int32_t)val;
      } else {
         while (*p++ != 0)            /* skip extended attributes */
            { }
         if (p - rec < reclen) {
            attr->delta_seq = str_to_int32(p); /* delta_seq */
         }
      }
   }
   Dmsg8(dbglvl, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s datastr=%d delta_seq=%d\n",
      attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
      attr->attrEx, attr->data_stream, attr->delta_seq);
   *attr->ofname = 0;
   *attr->olname = 0;
   return 1;
}
Exemplo n.º 6
0
/*
 * Find Available Media (Volume) for Pool
 *
 * Find a Volume for a given PoolId, MediaType, and Status.
 *
 * Returns: 0 on failure
 *          numrows on success
 */
int db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr)
{
   SQL_ROW row = NULL;
   int num_rows = 0;
   const char *order;
   char esc_type[MAX_ESCAPE_NAME_LENGTH];
   char esc_status[MAX_ESCAPE_NAME_LENGTH];
   char ed1[50];

   db_lock(mdb);
   mdb->db_escape_string(jcr, esc_type, mr->MediaType, strlen(mr->MediaType));
   mdb->db_escape_string(jcr, esc_status, mr->VolStatus, strlen(mr->VolStatus));

   if (item == -1) {       /* find oldest volume */
      /* Find oldest volume */
      Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
         "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
         "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
         "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
         "EndFile,EndBlock,LabelType,LabelDate,StorageId,"
         "Enabled,LocationId,RecycleCount,InitialWrite,"
         "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime,"
         "ActionOnPurge,EncryptionKey,MinBlocksize,MaxBlocksize "
         "FROM Media WHERE PoolId=%s AND MediaType='%s' AND VolStatus IN ('Full',"
         "'Recycle','Purged','Used','Append') AND Enabled=1 "
         "ORDER BY LastWritten LIMIT 1",
         edit_int64(mr->PoolId, ed1), esc_type);
     item = 1;
   } else {
      POOL_MEM changer(PM_FNAME);
      /* Find next available volume */
      if (InChanger) {
         Mmsg(changer, "AND InChanger=1 AND StorageId=%s",
              edit_int64(mr->StorageId, ed1));
      }
      if (bstrcmp(mr->VolStatus, "Recycle") ||
          bstrcmp(mr->VolStatus, "Purged")) {
         order = "AND Recycle=1 ORDER BY LastWritten ASC,MediaId";  /* take oldest that can be recycled */
      } else {
         order = sql_media_order_most_recently_written[db_get_type_index(mdb)];    /* take most recently written */
      }
      Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
         "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
         "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
         "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
         "EndFile,EndBlock,LabelType,LabelDate,StorageId,"
         "Enabled,LocationId,RecycleCount,InitialWrite,"
         "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime,"
         "ActionOnPurge,EncryptionKey,MinBlocksize,MaxBlocksize "
         "FROM Media WHERE PoolId=%s AND MediaType='%s' AND Enabled=1 "
         "AND VolStatus='%s' "
         "%s "
         "%s LIMIT %d",
         edit_int64(mr->PoolId, ed1), esc_type,
         esc_status, changer.c_str(), order, item);
   }
   Dmsg1(100, "fnextvol=%s\n", mdb->cmd);
   if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
      goto bail_out;
   }

   num_rows = sql_num_rows(mdb);
   if (item > num_rows || item < 1) {
      Dmsg2(050, "item=%d got=%d\n", item, num_rows);
      Mmsg2(&mdb->errmsg, _("Request for Volume item %d greater than max %d or less than 1\n"),
         item, num_rows);
      num_rows = 0;
      goto bail_out;
   }

   /* Note, we previously seeked to the row using: sql_data_seek(mdb, item-1);
    * but this failed on PostgreSQL, so now we loop over all the records.
    * This should not be too horrible since the maximum Volumes we look at
    * in any case is 20.
    */
   while (item-- > 0) {
      if ((row = sql_fetch_row(mdb)) == NULL) {
         Dmsg1(050, "Fail fetch item=%d\n", item+1);
         Mmsg1(&mdb->errmsg, _("No Volume record found for item %d.\n"), item);
         sql_free_result(mdb);
         num_rows = 0;
         goto bail_out;
      }
   }

   /* Return fields in Media Record */
   mr->MediaId = str_to_int64(row[0]);
   bstrncpy(mr->VolumeName, (row[1] != NULL) ? row[1] : "", sizeof(mr->VolumeName));
   mr->VolJobs = str_to_int64(row[2]);
   mr->VolFiles = str_to_int64(row[3]);
   mr->VolBlocks = str_to_int64(row[4]);
   mr->VolBytes = str_to_uint64(row[5]);
   mr->VolMounts = str_to_int64(row[6]);
   mr->VolErrors = str_to_int64(row[7]);
   mr->VolWrites = str_to_int64(row[8]);
   mr->MaxVolBytes = str_to_uint64(row[9]);
   mr->VolCapacityBytes = str_to_uint64(row[10]);
   bstrncpy(mr->MediaType, (row[11] != NULL) ? row[11] : "", sizeof(mr->MediaType));
   bstrncpy(mr->VolStatus, (row[12] != NULL) ? row[12] : "", sizeof(mr->VolStatus));
   mr->PoolId = str_to_int64(row[13]);
   mr->VolRetention = str_to_uint64(row[14]);
   mr->VolUseDuration = str_to_uint64(row[15]);
   mr->MaxVolJobs = str_to_int64(row[16]);
   mr->MaxVolFiles = str_to_int64(row[17]);
   mr->Recycle = str_to_int64(row[18]);
   mr->Slot = str_to_int64(row[19]);
   bstrncpy(mr->cFirstWritten, (row[20] != NULL) ? row[20] : "", sizeof(mr->cFirstWritten));
   mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
   bstrncpy(mr->cLastWritten, (row[21] != NULL) ? row[21] : "", sizeof(mr->cLastWritten));
   mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
   mr->InChanger = str_to_uint64(row[22]);
   mr->EndFile = str_to_uint64(row[23]);
   mr->EndBlock = str_to_uint64(row[24]);
   mr->LabelType = str_to_int64(row[25]);
   bstrncpy(mr->cLabelDate, (row[26] != NULL) ? row[26] : "", sizeof(mr->cLabelDate));
   mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
   mr->StorageId = str_to_int64(row[27]);
   mr->Enabled = str_to_int64(row[28]);
   mr->LocationId = str_to_int64(row[29]);
   mr->RecycleCount = str_to_int64(row[30]);
   bstrncpy(mr->cInitialWrite, (row[31] != NULL) ? row[31] : "", sizeof(mr->cInitialWrite));
   mr->InitialWrite = (time_t)str_to_utime(mr->cInitialWrite);
   mr->ScratchPoolId = str_to_int64(row[32]);
   mr->RecyclePoolId = str_to_int64(row[33]);
   mr->VolReadTime = str_to_int64(row[34]);
   mr->VolWriteTime = str_to_int64(row[35]);
   mr->ActionOnPurge = str_to_int64(row[36]);
   bstrncpy(mr->EncrKey, (row[37] != NULL) ? row[37] : "", sizeof(mr->EncrKey));
   mr->MinBlocksize = str_to_int32(row[38]);
   mr->MaxBlocksize = str_to_int32(row[39]);

   sql_free_result(mdb);

bail_out:
   db_unlock(mdb);
   Dmsg1(050, "Rtn numrows=%d\n", num_rows);
   return num_rows;
}
Exemplo n.º 7
0
/*
 * Store network addresses.
 *
 *   my tests
 *   positiv
 *   = { ip = { addr = 1.2.3.4; port = 1205; } ipv4 = { addr = 1.2.3.4; port = http; } }
 *   = { ip = {
 *         addr = 1.2.3.4; port = 1205; }
 *     ipv4 = {
 *         addr = 1.2.3.4; port = http; }
 *     ipv6 = {
 *       addr = 1.2.3.4;
 *       port = 1205;
 *     }
 *     ip = {
 *       addr = 1.2.3.4
 *       port = 1205
 *     }
 *     ip = {
 *       addr = 1.2.3.4
 *     }
 *     ip = {
 *       addr = 2001:220:222::2
 *     }
 *     ip = {
 *       addr = bluedot.thun.net
 (     }
 *   }
 *   negativ
 *   = { ip = { } }
 *   = { ipv4 { addr = doof.nowaytoheavenxyz.uhu; } }
 *   = { ipv4 { port = 4711 } }
 */
void store_addresses(LEX * lc, RES_ITEM * item, int index, int pass)
{
   int token;
   int exist;
   int family = 0;
   char errmsg[1024];
   char port_str[128];
   char hostname_str[1024];
   enum {
      EMPTYLINE = 0x0,
      PORTLINE = 0x1,
      ADDRLINE = 0x2
   } next_line = EMPTYLINE;
   int port = str_to_int32(item->default_value);

   token = lex_get_token(lc, T_SKIP_EOL);
   if (token != T_BOB) {
      scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
   }
   token = lex_get_token(lc, T_SKIP_EOL);
   if (token == T_EOB) {
      scan_err0(lc, _("Empty addr block is not allowed"));
   }
   do {
      if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
         scan_err1(lc, _("Expected a string, got: %s"), lc->str);
      }
      if (bstrcasecmp("ip", lc->str) || bstrcasecmp("ipv4", lc->str)) {
         family = AF_INET;
#ifdef HAVE_IPV6
      } else if (bstrcasecmp("ipv6", lc->str)) {
         family = AF_INET6;
      } else {
         scan_err1(lc, _("Expected a string [ip|ipv4|ipv6], got: %s"), lc->str);
      }
#else
      } else {
         scan_err1(lc, _("Expected a string [ip|ipv4], got: %s"), lc->str);
      }
#endif
      token = lex_get_token(lc, T_SKIP_EOL);
      if (token != T_EQUALS) {
         scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
      }
      token = lex_get_token(lc, T_SKIP_EOL);
      if (token != T_BOB) {
         scan_err1(lc, _("Expected a block begin { , got: %s"), lc->str);
      }
      token = lex_get_token(lc, T_SKIP_EOL);
      exist = EMPTYLINE;
      port_str[0] = hostname_str[0] = '\0';
      do {
         if (token != T_IDENTIFIER) {
            scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
         }
         if (bstrcasecmp("port", lc->str)) {
            next_line = PORTLINE;
            if (exist & PORTLINE) {
               scan_err0(lc, _("Only one port per address block"));
            }
            exist |= PORTLINE;
         } else if (bstrcasecmp("addr", lc->str)) {
            next_line = ADDRLINE;
            if (exist & ADDRLINE) {
               scan_err0(lc, _("Only one addr per address block"));
            }
            exist |= ADDRLINE;
         } else {
            scan_err1(lc, _("Expected a identifier [addr|port], got: %s"), lc->str);
         }
         token = lex_get_token(lc, T_SKIP_EOL);
         if (token != T_EQUALS) {
            scan_err1(lc, _("Expected a equal =, got: %s"), lc->str);
         }
         token = lex_get_token(lc, T_SKIP_EOL);
         switch (next_line) {
         case PORTLINE:
            if (!(token == T_UNQUOTED_STRING || token == T_NUMBER || token == T_IDENTIFIER)) {
               scan_err1(lc, _("Expected a number or a string, got: %s"), lc->str);
            }
            bstrncpy(port_str, lc->str, sizeof(port_str));
            break;
         case ADDRLINE:
            if (!(token == T_UNQUOTED_STRING || token == T_IDENTIFIER)) {
               scan_err1(lc, _("Expected an IP number or a hostname, got: %s"),
                         lc->str);
            }
            bstrncpy(hostname_str, lc->str, sizeof(hostname_str));
            break;
         case EMPTYLINE:
            scan_err0(lc, _("State machine missmatch"));
            break;
         }
         token = lex_get_token(lc, T_SKIP_EOL);
      } while (token == T_IDENTIFIER);
      if (token != T_EOB) {
         scan_err1(lc, _("Expected a end of block }, got: %s"), lc->str);
      }
      if (pass == 1 && !add_address((dlist **)(item->value), IPADDR::R_MULTIPLE,
          htons(port), family, hostname_str, port_str, errmsg, sizeof(errmsg))) {
           scan_err3(lc, _("Can't add hostname(%s) and port(%s) to addrlist (%s)"),
                   hostname_str, port_str, errmsg);
      }
      token = scan_to_next_not_eol(lc);
   } while ((token == T_IDENTIFIER || token == T_UNQUOTED_STRING));
Exemplo n.º 8
0
/*
 * Initialize the static structure to zeros, then
 *  apply all the default values.
 */
static inline void init_resource(CONFIG *config, int type, RES_ITEM *items, int pass)
{
   memset(config->m_res_all, 0, config->m_res_all_size);
   res_all.hdr.rcode = type;
   res_all.hdr.refcnt = 1;

   /*
    * Set defaults in each item. We only set defaults in pass 1.
    */
   if (pass == 1) {
      int i;

      for (i = 0; items[i].name; i++) {
         Dmsg3(900, "Item=%s def=%s defval=%s\n", items[i].name,
               (items[i].flags & ITEM_DEFAULT) ? "yes" : "no",
               (items[i].default_value) ? items[i].default_value : "None");

         /*
          * Sanity check.
          *
          * Items with a default value but without the ITEM_DEFAULT flag set
          * are most of the time an indication of a programmers error.
          */
         if (items[i].default_value != NULL && !(items[i].flags & ITEM_DEFAULT)) {
            Pmsg1(000, _("Found config item %s which has default value but no ITEM_DEFAULT flag set\n"),
                  items[i].name);
            items[i].flags |= ITEM_DEFAULT;
         }

         if (items[i].flags & ITEM_DEFAULT && items[i].default_value != NULL) {
            /*
             * First try to handle the generic types.
             */
            if (items[i].handler == store_bit) {
               if (bstrcasecmp(items[i].default_value, "on")) {
                  *(uint32_t *)(items[i].value) |= items[i].code;
               } else if (bstrcasecmp(items[i].default_value, "off")) {
                  *(uint32_t *)(items[i].value) &= ~(items[i].code);
               }
            } else if (items[i].handler == store_bool) {
               if (bstrcasecmp(items[i].default_value, "yes") ||
                   bstrcasecmp(items[i].default_value, "true")) {
                  *(bool *)(items[i].value) = true;
               } else if (bstrcasecmp(items[i].default_value, "no") ||
                          bstrcasecmp(items[i].default_value, "false")) {
                  *(bool *)(items[i].value) = false;
               }
            } else if (items[i].handler == store_pint32 ||
                       items[i].handler == store_int32 ||
                       items[i].handler == store_size32) {
               *(uint32_t *)(items[i].value) = str_to_int32(items[i].default_value);
            } else if (items[i].handler == store_int64) {
               *(int64_t *)(items[i].value) = str_to_int64(items[i].default_value);
            } else if (items[i].handler == store_size64) {
               *(uint64_t *)(items[i].value) = str_to_uint64(items[i].default_value);
            } else if (items[i].handler == store_speed) {
               *(uint64_t *)(items[i].value) = str_to_uint64(items[i].default_value);
            } else if (items[i].handler == store_time) {
               *(utime_t *)(items[i].value) = str_to_int64(items[i].default_value);
            } else if (items[i].handler == store_strname ||
                       items[i].handler == store_str) {
               *items[i].value = bstrdup(items[i].default_value);
            } else if (items[i].handler == store_dir) {
               char pathname[MAXSTRING];

               bstrncpy(pathname, items[i].default_value, sizeof(pathname));
               if (pathname[0] != '|') {
                  do_shell_expansion(pathname, sizeof(pathname));
               }
               *items[i].value = bstrdup(pathname);
            } else if (items[i].handler == store_addresses) {
               init_default_addresses((dlist **)items[i].value, items[i].default_value);
            } else {
               /*
                * None of the generic types fired if there is a registered callback call that now.
                */
               if (config->m_init_res) {
                  config->m_init_res(&items[i]);
               }
            }
         }

         /*
          * If this triggers, take a look at lib/parse_conf.h
          */
         if (i >= MAX_RES_ITEMS) {
            Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[type - r_first]);
         }
      }
   }
}
Exemplo n.º 9
0
/*
 * Initialize the static structure to zeros, then apply all the default values.
 */
void CONFIG::init_resource(int type, RES_ITEM *items, int pass)
{
   URES *res_all;

   memset(m_res_all, 0, m_res_all_size);
   res_all = ((URES *)m_res_all);
   res_all->hdr.rcode = type;
   res_all->hdr.refcnt = 1;

   /*
    * See what pass of the config parsing this is.
    */
   switch (pass) {
   case 1: {
      /*
       * Set all defaults for types that are filled in pass 1 of the config parser.
       */
      int i;

      for (i = 0; items[i].name; i++) {
         Dmsg3(900, "Item=%s def=%s defval=%s\n", items[i].name,
               (items[i].flags & CFG_ITEM_DEFAULT) ? "yes" : "no",
               (items[i].default_value) ? items[i].default_value : "None");

         /*
          * Sanity check.
          *
          * Items with a default value but without the CFG_ITEM_DEFAULT flag set
          * are most of the time an indication of a programmers error.
          */
         if (items[i].default_value != NULL && !(items[i].flags & CFG_ITEM_DEFAULT)) {
            Pmsg1(000, _("Found config item %s which has default value but no CFG_ITEM_DEFAULT flag set\n"),
                  items[i].name);
            items[i].flags |= CFG_ITEM_DEFAULT;
         }

         /*
          * See if the CFG_ITEM_DEFAULT flag is set and a default value is available.
          */
         if (items[i].flags & CFG_ITEM_DEFAULT && items[i].default_value != NULL) {
            /*
             * First try to handle the generic types.
             */
            switch (items[i].type) {
            case CFG_TYPE_BIT:
               if (bstrcasecmp(items[i].default_value, "on")) {
                  set_bit(items[i].code, items[i].bitvalue);
               } else if (bstrcasecmp(items[i].default_value, "off")) {
                  clear_bit(items[i].code, items[i].bitvalue);
               }
               break;
            case CFG_TYPE_BOOL:
               if (bstrcasecmp(items[i].default_value, "yes") ||
                   bstrcasecmp(items[i].default_value, "true")) {
                  *(items[i].boolvalue) = true;
               } else if (bstrcasecmp(items[i].default_value, "no") ||
                          bstrcasecmp(items[i].default_value, "false")) {
                  *(items[i].boolvalue) = false;
               }
               break;
            case CFG_TYPE_PINT32:
            case CFG_TYPE_INT32:
            case CFG_TYPE_SIZE32:
               *(items[i].ui32value) = str_to_int32(items[i].default_value);
               break;
            case CFG_TYPE_INT64:
               *(items[i].i64value) = str_to_int64(items[i].default_value);
               break;
            case CFG_TYPE_SIZE64:
               *(items[i].ui64value) = str_to_uint64(items[i].default_value);
               break;
            case CFG_TYPE_SPEED:
               *(items[i].ui64value) = str_to_uint64(items[i].default_value);
               break;
            case CFG_TYPE_TIME:
               *(items[i].utimevalue) = str_to_int64(items[i].default_value);
               break;
            case CFG_TYPE_STRNAME:
            case CFG_TYPE_STR:
               *(items[i].value) = bstrdup(items[i].default_value);
               break;
            case CFG_TYPE_DIR: {
               POOL_MEM pathname(PM_FNAME);

               pm_strcpy(pathname, items[i].default_value);
               if (*pathname.c_str() != '|') {
                  int size;

                  /*
                   * Make sure we have enough room
                   */
                  size = pathname.size() + 1024;
                  pathname.check_size(size);
                  do_shell_expansion(pathname.c_str(), pathname.size());
               }
               *items[i].value = bstrdup(pathname.c_str());
               break;
            }
            case CFG_TYPE_ADDRESSES:
               init_default_addresses(items[i].dlistvalue, items[i].default_value);
               break;
            default:
               /*
                * None of the generic types fired if there is a registered callback call that now.
                */
               if (m_init_res) {
                  m_init_res(&items[i], pass);
               }
               break;
            }

            if (!m_omit_defaults) {
               set_bit(i, res_all->hdr.inherit_content);
            }
         }

         /*
          * If this triggers, take a look at lib/parse_conf.h
          */
         if (i >= MAX_RES_ITEMS) {
            Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), m_resources[type - m_r_first]);
         }
      }
      break;
   }
   case 2: {
      /*
       * Set all defaults for types that are filled in pass 2 of the config parser.
       */
      int i;

      for (i = 0; items[i].name; i++) {
         Dmsg3(900, "Item=%s def=%s defval=%s\n", items[i].name,
               (items[i].flags & CFG_ITEM_DEFAULT) ? "yes" : "no",
               (items[i].default_value) ? items[i].default_value : "None");

         /*
          * See if the CFG_ITEM_DEFAULT flag is set and a default value is available.
          */
         if (items[i].flags & CFG_ITEM_DEFAULT && items[i].default_value != NULL) {
            /*
             * First try to handle the generic types.
             */
            switch (items[i].type) {
            case CFG_TYPE_ALIST_STR:
               if (!*items[i].alistvalue) {
                  *(items[i].alistvalue) = New(alist(10, owned_by_alist));
               }
               (*(items[i].alistvalue))->append(bstrdup(items[i].default_value));
               break;
            case CFG_TYPE_ALIST_DIR: {
               POOL_MEM pathname(PM_FNAME);

               if (!*items[i].alistvalue) {
                  *(items[i].alistvalue) = New(alist(10, owned_by_alist));
               }

               pm_strcpy(pathname, items[i].default_value);
               if (*items[i].default_value != '|') {
                  int size;

                  /*
                   * Make sure we have enough room
                   */
                  size = pathname.size() + 1024;
                  pathname.check_size(size);
                  do_shell_expansion(pathname.c_str(), pathname.size());
               }
               (*(items[i].alistvalue))->append(bstrdup(pathname.c_str()));
               break;
            }
            default:
               /*
                * None of the generic types fired if there is a registered callback call that now.
                */
               if (m_init_res) {
                  m_init_res(&items[i], pass);
               }
               break;
            }

            if (!m_omit_defaults) {
               set_bit(i, res_all->hdr.inherit_content);
            }
         }

         /*
          * If this triggers, take a look at lib/parse_conf.h
          */
         if (i >= MAX_RES_ITEMS) {
            Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), m_resources[type - m_r_first]);
         }
      }
      break;
   }
   default:
      break;
   }
}