FreeBSD/contrib/subversion/subversion/libsvn_fs_x/index.c
/* Read a mapping entry from the phys-to-log index STREAM and append it to
 * RESULT.  *ITEM_INDEX contains the phys offset for the entry and will
 * be moved forward by the size of entry.
 */
Read a mapping entry from the phys-to-log index STREAM and append it to
RESULT.  *ITEM_INDEX contains the phys offset for the entry and will
be moved forward by the size of entry.
Read a mapping entry from the phys - to - log index STREAM and append it to RESULT . * ITEM_INDEX contains the phys offset for the entry and will be moved forward by the size of entry .
static svn_error_t *
read_entry(svn_fs_x__packed_number_stream_t *stream,
           apr_off_t *item_offset,
           svn_revnum_t revision,
           apr_array_header_t *result)
{
  apr_uint64_t value;
  apr_uint64_t number = 0;
  apr_uint32_t sub_item;
  svn_fs_x__p2l_entry_t entry;
  entry.offset = *item_offset;
  SVN_ERR(packed_stream_get(&value, stream));
  entry.size = (apr_off_t)value;
  SVN_ERR(packed_stream_get(&value, stream));
  entry.type = (int)value % 16;
  entry.item_count = (apr_uint32_t)(value / 16);
  if (entry.type > SVN_FS_X__ITEM_TYPE_REPS_CONT)
    return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL,
                            _("Invalid item type in P2L index"));
  SVN_ERR(packed_stream_get(&value, stream));
  entry.fnv1_checksum = (apr_uint32_t)value;
  if (value > APR_UINT32_MAX)
    return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL,
                            _("Invalid FNV1 checksum in P2L index"));
  if (entry.type == SVN_FS_X__ITEM_TYPE_UNUSED)
    if (   entry.fnv1_checksum != 0
        || entry.item_count != 0)
      return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL,
                 _("Unused regions must be empty and have checksum 0"));
  if (entry.item_count == 0)
    {
      entry.items = NULL;
    }
  else
    {
      entry.items
        = apr_pcalloc(result->pool, entry.item_count * sizeof(*entry.items));
      if (   entry.item_count > 1
          && entry.type < SVN_FS_X__ITEM_TYPE_CHANGES_CONT)
        return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL,
                      _("Only containers may have more than one sub-item"));
      for (sub_item = 0; sub_item < entry.item_count; ++sub_item)
        {
          SVN_ERR(packed_stream_get(&value, stream));
          revision += (svn_revnum_t)(value % 2 ? -1 - value / 2 : value / 2);
          entry.items[sub_item].change_set
            = svn_fs_x__change_set_by_rev(revision);
        }
      for (sub_item = 0; sub_item < entry.item_count; ++sub_item)
        {
          SVN_ERR(packed_stream_get(&value, stream));
          number += value % 2 ? -1 - value / 2 : value / 2;
          entry.items[sub_item].number = number;
          if (   (   entry.type == SVN_FS_X__ITEM_TYPE_CHANGES
                  || entry.type == SVN_FS_X__ITEM_TYPE_CHANGES_CONT)
              && number != SVN_FS_X__ITEM_INDEX_CHANGES)
            return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL,
                            _("Changed path list must have item number 1"));
        }
    }
  APR_ARRAY_PUSH(result, svn_fs_x__p2l_entry_t) = entry;
  *item_offset += entry.size;
  return SVN_NO_ERROR;
}
static svn_error_t * read_entry ( svn_fs_x__packed_number_stream_t * stream , apr_off_t * item_offset , svn_revnum_t revision , apr_array_header_t * result ) { apr_uint64_t value ; apr_uint64_t number = 0 ; apr_uint32_t sub_item ; svn_fs_x__p2l_entry_t entry ; entry . offset = * item_offset ; SVN_ERR ( packed_stream_get ( & value , stream ) ) ; entry . size = ( apr_off_t ) value ; SVN_ERR ( packed_stream_get ( & value , stream ) ) ; entry . type = ( int ) value % 16 ; entry . item_count = ( apr_uint32_t ) ( value / 16 ) ; if ( entry . type > SVN_FS_X__ITEM_TYPE_REPS_CONT ) return svn_error_create ( SVN_ERR_FS_INDEX_CORRUPTION , NULL , _ ( " " ) ) ; SVN_ERR ( packed_stream_get ( & value , stream ) ) ; entry . fnv1_checksum = ( apr_uint32_t ) value ; if ( value > APR_UINT32_MAX ) return svn_error_create ( SVN_ERR_FS_INDEX_CORRUPTION , NULL , _ ( " " ) ) ; if ( entry . type == SVN_FS_X__ITEM_TYPE_UNUSED ) if ( entry . fnv1_checksum != 0 || entry . item_count != 0 ) return svn_error_create ( SVN_ERR_FS_INDEX_CORRUPTION , NULL , _ ( " " ) ) ; if ( entry . item_count == 0 ) { entry . items = NULL ; } else { entry . items = apr_pcalloc ( result -> pool , entry . item_count * sizeof ( * entry . items ) ) ; if ( entry . item_count > 1 && entry . type < SVN_FS_X__ITEM_TYPE_CHANGES_CONT ) return svn_error_create ( SVN_ERR_FS_INDEX_CORRUPTION , NULL , _ ( " " ) ) ; for ( sub_item = 0 ; sub_item < entry . item_count ; ++ sub_item ) { SVN_ERR ( packed_stream_get ( & value , stream ) ) ; revision += ( svn_revnum_t ) ( value % 2 ? -1 - value / 2 : value / 2 ) ; entry . items [ sub_item ] . change_set = svn_fs_x__change_set_by_rev ( revision ) ; } for ( sub_item = 0 ; sub_item < entry . item_count ; ++ sub_item ) { SVN_ERR ( packed_stream_get ( & value , stream ) ) ; number += value % 2 ? -1 - value / 2 : value / 2 ; entry . items [ sub_item ] . number = number ; if ( ( entry . type == SVN_FS_X__ITEM_TYPE_CHANGES || entry . type == SVN_FS_X__ITEM_TYPE_CHANGES_CONT ) && number != SVN_FS_X__ITEM_INDEX_CHANGES ) return svn_error_create ( SVN_ERR_FS_INDEX_CORRUPTION , NULL , _ ( " " ) ) ; } } APR_ARRAY_PUSH ( result , svn_fs_x__p2l_entry_t ) = entry ; * item_offset += entry . size ; return SVN_NO_ERROR ; }
Read a mapping entry from the phys-to-log index STREAM and append it to
 RESULT.
Read a mapping entry from the phys - to - log index STREAM and append it to RESULT .
/* Verify item type. */ /* Truncating the checksum to 32 bits may have hidden random data in the
   * unused extra bits of the on-disk representation (7/8 bit representation
   * uses 5 bytes on disk for the 32 bit value, leaving 3 bits unused). */ /* Some of the index data for empty rev / pack file sections will not be
   * used during normal operation.  Thus, we have strict rules for the
   * contents of those unused fields. */