diff options
Diffstat (limited to 'qemu/roms/ipxe/src/net/pccrc.c')
-rw-r--r-- | qemu/roms/ipxe/src/net/pccrc.c | 818 |
1 files changed, 0 insertions, 818 deletions
diff --git a/qemu/roms/ipxe/src/net/pccrc.c b/qemu/roms/ipxe/src/net/pccrc.c deleted file mode 100644 index 4cd82cd1c..000000000 --- a/qemu/roms/ipxe/src/net/pccrc.c +++ /dev/null @@ -1,818 +0,0 @@ -/* - * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <errno.h> -#include <assert.h> -#include <ipxe/uaccess.h> -#include <ipxe/sha256.h> -#include <ipxe/sha512.h> -#include <ipxe/hmac.h> -#include <ipxe/base16.h> -#include <ipxe/pccrc.h> - -/** @file - * - * Peer Content Caching and Retrieval: Content Identification [MS-PCCRC] - * - */ - -/****************************************************************************** - * - * Utility functions - * - ****************************************************************************** - */ - -/** - * Transcribe hash value (for debugging) - * - * @v info Content information - * @v hash Hash value - * @ret string Hash value string - */ -static inline const char * -peerdist_info_hash_ntoa ( const struct peerdist_info *info, const void *hash ) { - static char buf[ ( 2 * PEERDIST_DIGEST_MAX_SIZE ) + 1 /* NUL */ ]; - size_t digestsize = info->digestsize; - - /* Sanity check */ - assert ( info != NULL ); - assert ( digestsize != 0 ); - assert ( base16_encoded_len ( digestsize ) < sizeof ( buf ) ); - - /* Transcribe hash value */ - base16_encode ( hash, digestsize, buf, sizeof ( buf ) ); - return buf; -} - -/** - * Get raw data - * - * @v info Content information - * @v data Data buffer - * @v offset Starting offset - * @v len Length - * @ret rc Return status code - */ -static int peerdist_info_get ( const struct peerdist_info *info, void *data, - size_t offset, size_t len ) { - - /* Sanity check */ - if ( ( offset > info->raw.len ) || - ( len > ( info->raw.len - offset ) ) ) { - DBGC ( info, "PCCRC %p data underrun at [%zx,%zx) of %zx\n", - info, offset, ( offset + len ), info->raw.len ); - return -ERANGE; - } - - /* Copy data */ - copy_from_user ( data, info->raw.data, offset, len ); - - return 0; -} - -/** - * Populate segment hashes - * - * @v segment Content information segment to fill in - * @v hash Segment hash of data - * @v secret Segment secret - */ -static void peerdist_info_segment_hash ( struct peerdist_info_segment *segment, - const void *hash, const void *secret ){ - const struct peerdist_info *info = segment->info; - struct digest_algorithm *digest = info->digest; - uint8_t ctx[digest->ctxsize]; - size_t digestsize = info->digestsize; - size_t secretsize = digestsize; - static const uint16_t magic[] = PEERDIST_SEGMENT_ID_MAGIC; - - /* Sanity check */ - assert ( digestsize <= sizeof ( segment->hash ) ); - assert ( digestsize <= sizeof ( segment->secret ) ); - assert ( digestsize <= sizeof ( segment->id ) ); - - /* Get segment hash of data */ - memcpy ( segment->hash, hash, digestsize ); - - /* Get segment secret */ - memcpy ( segment->secret, secret, digestsize ); - - /* Calculate segment identifier */ - hmac_init ( digest, ctx, segment->secret, &secretsize ); - assert ( secretsize == digestsize ); - hmac_update ( digest, ctx, segment->hash, digestsize ); - hmac_update ( digest, ctx, magic, sizeof ( magic ) ); - hmac_final ( digest, ctx, segment->secret, &secretsize, segment->id ); - assert ( secretsize == digestsize ); -} - -/****************************************************************************** - * - * Content Information version 1 - * - ****************************************************************************** - */ - -/** - * Get number of blocks within a block description - * - * @v info Content information - * @v offset Block description offset - * @ret blocks Number of blocks, or negative error - */ -static int peerdist_info_v1_blocks ( const struct peerdist_info *info, - size_t offset ) { - struct peerdist_info_v1_block raw; - unsigned int blocks; - int rc; - - /* Get block description header */ - if ( ( rc = peerdist_info_get ( info, &raw, offset, - sizeof ( raw ) ) ) != 0 ) - return rc; - - /* Calculate number of blocks */ - blocks = le32_to_cpu ( raw.blocks ); - - return blocks; -} - -/** - * Locate block description - * - * @v info Content information - * @v index Segment index - * @ret offset Block description offset, or negative error - */ -static ssize_t peerdist_info_v1_block_offset ( const struct peerdist_info *info, - unsigned int index ) { - size_t digestsize = info->digestsize; - unsigned int i; - size_t offset; - int blocks; - int rc; - - /* Sanity check */ - assert ( index < info->segments ); - - /* Calculate offset of first block description */ - offset = ( sizeof ( struct peerdist_info_v1 ) + - ( info->segments * - sizeof ( peerdist_info_v1_segment_t ( digestsize ) ) ) ); - - /* Iterate over block descriptions until we find this segment */ - for ( i = 0 ; i < index ; i++ ) { - - /* Get number of blocks */ - blocks = peerdist_info_v1_blocks ( info, offset ); - if ( blocks < 0 ) { - rc = blocks; - DBGC ( info, "PCCRC %p segment %d could not get number " - "of blocks: %s\n", info, i, strerror ( rc ) ); - return rc; - } - - /* Move to next block description */ - offset += sizeof ( peerdist_info_v1_block_t ( digestsize, - blocks ) ); - } - - return offset; -} - -/** - * Populate content information - * - * @v info Content information to fill in - * @ret rc Return status code - */ -static int peerdist_info_v1 ( struct peerdist_info *info ) { - struct peerdist_info_v1 raw; - struct peerdist_info_segment first; - struct peerdist_info_segment last; - size_t first_skip; - size_t last_skip; - size_t last_read; - int rc; - - /* Get raw header */ - if ( ( rc = peerdist_info_get ( info, &raw, 0, sizeof ( raw ) ) ) != 0){ - DBGC ( info, "PCCRC %p could not get V1 content information: " - "%s\n", info, strerror ( rc ) ); - return rc; - } - assert ( raw.version.raw == cpu_to_le16 ( PEERDIST_INFO_V1 ) ); - - /* Determine hash algorithm */ - switch ( raw.hash ) { - case cpu_to_le32 ( PEERDIST_INFO_V1_HASH_SHA256 ) : - info->digest = &sha256_algorithm; - break; - case cpu_to_le32 ( PEERDIST_INFO_V1_HASH_SHA384 ) : - info->digest = &sha384_algorithm; - break; - case cpu_to_le32 ( PEERDIST_INFO_V1_HASH_SHA512 ) : - info->digest = &sha512_algorithm; - break; - default: - DBGC ( info, "PCCRC %p unsupported hash algorithm %#08x\n", - info, le32_to_cpu ( raw.hash ) ); - return -ENOTSUP; - } - info->digestsize = info->digest->digestsize; - assert ( info->digest != NULL ); - DBGC2 ( info, "PCCRC %p using %s[%zd]\n", - info, info->digest->name, ( info->digestsize * 8 ) ); - - /* Calculate number of segments */ - info->segments = le32_to_cpu ( raw.segments ); - - /* Get first segment */ - if ( ( rc = peerdist_info_segment ( info, &first, 0 ) ) != 0 ) - return rc; - - /* Calculate range start offset */ - info->range.start = first.range.start; - - /* Calculate trimmed range start offset */ - first_skip = le32_to_cpu ( raw.first ); - info->trim.start = ( first.range.start + first_skip ); - - /* Get last segment */ - if ( ( rc = peerdist_info_segment ( info, &last, - ( info->segments - 1 ) ) ) != 0 ) - return rc; - - /* Calculate range end offset */ - info->range.end = last.range.end; - - /* Calculate trimmed range end offset */ - if ( raw.last ) { - /* Explicit length to include from last segment is given */ - last_read = le32_to_cpu ( raw.last ); - last_skip = ( last.index ? 0 : first_skip ); - info->trim.end = ( last.range.start + last_skip + last_read ); - } else { - /* No explicit length given: range extends to end of segment */ - info->trim.end = last.range.end; - } - - return 0; -} - -/** - * Populate content information segment - * - * @v segment Content information segment to fill in - * @ret rc Return status code - */ -static int peerdist_info_v1_segment ( struct peerdist_info_segment *segment ) { - const struct peerdist_info *info = segment->info; - size_t digestsize = info->digestsize; - peerdist_info_v1_segment_t ( digestsize ) raw; - ssize_t raw_offset; - int blocks; - int rc; - - /* Sanity checks */ - assert ( segment->index < info->segments ); - - /* Get raw description */ - raw_offset = ( sizeof ( struct peerdist_info_v1 ) + - ( segment->index * sizeof ( raw ) ) ); - if ( ( rc = peerdist_info_get ( info, &raw, raw_offset, - sizeof ( raw ) ) ) != 0 ) { - DBGC ( info, "PCCRC %p segment %d could not get segment " - "description: %s\n", info, segment->index, - strerror ( rc ) ); - return rc; - } - - /* Calculate start offset of this segment */ - segment->range.start = le64_to_cpu ( raw.segment.offset ); - - /* Calculate end offset of this segment */ - segment->range.end = ( segment->range.start + - le32_to_cpu ( raw.segment.len ) ); - - /* Calculate block size of this segment */ - segment->blksize = le32_to_cpu ( raw.segment.blksize ); - - /* Locate block description for this segment */ - raw_offset = peerdist_info_v1_block_offset ( info, segment->index ); - if ( raw_offset < 0 ) { - rc = raw_offset; - return rc; - } - - /* Get number of blocks */ - blocks = peerdist_info_v1_blocks ( info, raw_offset ); - if ( blocks < 0 ) { - rc = blocks; - DBGC ( info, "PCCRC %p segment %d could not get number of " - "blocks: %s\n", info, segment->index, strerror ( rc ) ); - return rc; - } - segment->blocks = blocks; - - /* Calculate segment hashes */ - peerdist_info_segment_hash ( segment, raw.hash, raw.secret ); - - return 0; -} - -/** - * Populate content information block - * - * @v block Content information block to fill in - * @ret rc Return status code - */ -static int peerdist_info_v1_block ( struct peerdist_info_block *block ) { - const struct peerdist_info_segment *segment = block->segment; - const struct peerdist_info *info = segment->info; - size_t digestsize = info->digestsize; - peerdist_info_v1_block_t ( digestsize, segment->blocks ) raw; - ssize_t raw_offset; - int rc; - - /* Sanity checks */ - assert ( block->index < segment->blocks ); - - /* Calculate start offset of this block */ - block->range.start = ( segment->range.start + - ( block->index * segment->blksize ) ); - - /* Calculate end offset of this block */ - block->range.end = ( block->range.start + segment->blksize ); - if ( block->range.end > segment->range.end ) - block->range.end = segment->range.end; - - /* Locate block description */ - raw_offset = peerdist_info_v1_block_offset ( info, segment->index ); - if ( raw_offset < 0 ) { - rc = raw_offset; - return rc; - } - - /* Get block hash */ - raw_offset += offsetof ( typeof ( raw ), hash[block->index] ); - if ( ( rc = peerdist_info_get ( info, block->hash, raw_offset, - digestsize ) ) != 0 ) { - DBGC ( info, "PCCRC %p segment %d block %d could not get " - "hash: %s\n", info, segment->index, block->index, - strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** Content information version 1 operations */ -static struct peerdist_info_operations peerdist_info_v1_operations = { - .info = peerdist_info_v1, - .segment = peerdist_info_v1_segment, - .block = peerdist_info_v1_block, -}; - -/****************************************************************************** - * - * Content Information version 2 - * - ****************************************************************************** - */ - -/** A segment cursor */ -struct peerdist_info_v2_cursor { - /** Raw data offset */ - size_t offset; - /** Number of segments remaining within this chunk */ - unsigned int remaining; - /** Accumulated segment length */ - size_t len; -}; - -/** - * Initialise segment cursor - * - * @v cursor Segment cursor - */ -static inline void -peerdist_info_v2_cursor_init ( struct peerdist_info_v2_cursor *cursor ) { - - /* Initialise cursor */ - cursor->offset = ( sizeof ( struct peerdist_info_v2 ) + - sizeof ( struct peerdist_info_v2_chunk ) ); - cursor->remaining = 0; - cursor->len = 0; -} - -/** - * Update segment cursor to next segment description - * - * @v info Content information - * @v offset Current offset - * @v remaining Number of segments remaining within this chunk - * @ret rc Return status code - */ -static int -peerdist_info_v2_cursor_next ( const struct peerdist_info *info, - struct peerdist_info_v2_cursor *cursor ) { - size_t digestsize = info->digestsize; - peerdist_info_v2_segment_t ( digestsize ) raw; - struct peerdist_info_v2_chunk chunk; - int rc; - - /* Get chunk description if applicable */ - if ( ! cursor->remaining ) { - - /* Get chunk description */ - if ( ( rc = peerdist_info_get ( info, &chunk, - ( cursor->offset - - sizeof ( chunk ) ), - sizeof ( chunk ) ) ) != 0 ) - return rc; - - /* Update number of segments remaining */ - cursor->remaining = ( be32_to_cpu ( chunk.len ) / - sizeof ( raw ) ); - } - - /* Get segment description header */ - if ( ( rc = peerdist_info_get ( info, &raw.segment, cursor->offset, - sizeof ( raw.segment ) ) ) != 0 ) - return rc; - - /* Update cursor */ - cursor->offset += sizeof ( raw ); - cursor->remaining--; - if ( ! cursor->remaining ) - cursor->offset += sizeof ( chunk ); - cursor->len += be32_to_cpu ( raw.segment.len ); - - return 0; -} - -/** - * Get number of segments and total length - * - * @v info Content information - * @v len Length to fill in - * @ret rc Number of segments, or negative error - */ -static int peerdist_info_v2_segments ( const struct peerdist_info *info, - size_t *len ) { - struct peerdist_info_v2_cursor cursor; - unsigned int segments; - int rc; - - /* Iterate over all segments */ - for ( peerdist_info_v2_cursor_init ( &cursor ), segments = 0 ; - cursor.offset < info->raw.len ; segments++ ) { - - /* Update segment cursor */ - if ( ( rc = peerdist_info_v2_cursor_next ( info, - &cursor ) ) != 0 ) { - DBGC ( info, "PCCRC %p segment %d could not update " - "segment cursor: %s\n", - info, segments, strerror ( rc ) ); - return rc; - } - } - - /* Record accumulated length */ - *len = cursor.len; - - return segments; -} - -/** - * Populate content information - * - * @v info Content information to fill in - * @ret rc Return status code - */ -static int peerdist_info_v2 ( struct peerdist_info *info ) { - struct peerdist_info_v2 raw; - size_t len = 0; - int segments; - int rc; - - /* Get raw header */ - if ( ( rc = peerdist_info_get ( info, &raw, 0, sizeof ( raw ) ) ) != 0){ - DBGC ( info, "PCCRC %p could not get V2 content information: " - "%s\n", info, strerror ( rc ) ); - return rc; - } - assert ( raw.version.raw == cpu_to_le16 ( PEERDIST_INFO_V2 ) ); - - /* Determine hash algorithm */ - switch ( raw.hash ) { - case PEERDIST_INFO_V2_HASH_SHA512_TRUNC : - info->digest = &sha512_algorithm; - info->digestsize = ( 256 / 8 ); - break; - default: - DBGC ( info, "PCCRC %p unsupported hash algorithm %#02x\n", - info, raw.hash ); - return -ENOTSUP; - } - assert ( info->digest != NULL ); - DBGC2 ( info, "PCCRC %p using %s[%zd]\n", - info, info->digest->name, ( info->digestsize * 8 ) ); - - /* Calculate number of segments and total length */ - segments = peerdist_info_v2_segments ( info, &len ); - if ( segments < 0 ) { - rc = segments; - DBGC ( info, "PCCRC %p could not get segment count and length: " - "%s\n", info, strerror ( rc ) ); - return rc; - } - info->segments = segments; - - /* Calculate range start offset */ - info->range.start = be64_to_cpu ( raw.offset ); - - /* Calculate trimmed range start offset */ - info->trim.start = ( info->range.start + be32_to_cpu ( raw.first ) ); - - /* Calculate range end offset */ - info->range.end = ( info->range.start + len ); - - /* Calculate trimmed range end offset */ - info->trim.end = ( raw.len ? be64_to_cpu ( raw.len ) : - info->range.end ); - - return 0; -} - -/** - * Populate content information segment - * - * @v segment Content information segment to fill in - * @ret rc Return status code - */ -static int peerdist_info_v2_segment ( struct peerdist_info_segment *segment ) { - const struct peerdist_info *info = segment->info; - size_t digestsize = info->digestsize; - peerdist_info_v2_segment_t ( digestsize ) raw; - struct peerdist_info_v2_cursor cursor; - unsigned int index; - size_t len; - int rc; - - /* Sanity checks */ - assert ( segment->index < info->segments ); - - /* Iterate over all segments before the target segment */ - for ( peerdist_info_v2_cursor_init ( &cursor ), index = 0 ; - index < segment->index ; index++ ) { - - /* Update segment cursor */ - if ( ( rc = peerdist_info_v2_cursor_next ( info, - &cursor ) ) != 0 ) { - DBGC ( info, "PCCRC %p segment %d could not update " - "segment cursor: %s\n", - info, index, strerror ( rc ) ); - return rc; - } - } - - /* Get raw description */ - if ( ( rc = peerdist_info_get ( info, &raw, cursor.offset, - sizeof ( raw ) ) ) != 0 ) { - DBGC ( info, "PCCRC %p segment %d could not get segment " - "description: %s\n", - info, segment->index, strerror ( rc ) ); - return rc; - } - - /* Calculate start offset of this segment */ - segment->range.start = ( info->range.start + cursor.len ); - - /* Calculate end offset of this segment */ - len = be32_to_cpu ( raw.segment.len ); - segment->range.end = ( segment->range.start + len ); - - /* Model as a segment containing a single block */ - segment->blocks = 1; - segment->blksize = len; - - /* Calculate segment hashes */ - peerdist_info_segment_hash ( segment, raw.hash, raw.secret ); - - return 0; -} - -/** - * Populate content information block - * - * @v block Content information block to fill in - * @ret rc Return status code - */ -static int peerdist_info_v2_block ( struct peerdist_info_block *block ) { - const struct peerdist_info_segment *segment = block->segment; - const struct peerdist_info *info = segment->info; - size_t digestsize = info->digestsize; - - /* Sanity checks */ - assert ( block->index < segment->blocks ); - - /* Model as a block covering the whole segment */ - memcpy ( &block->range, &segment->range, sizeof ( block->range ) ); - memcpy ( block->hash, segment->hash, digestsize ); - - return 0; -} - -/** Content information version 2 operations */ -static struct peerdist_info_operations peerdist_info_v2_operations = { - .block = peerdist_info_v2_block, - .segment = peerdist_info_v2_segment, - .info = peerdist_info_v2, -}; - -/****************************************************************************** - * - * Content Information - * - ****************************************************************************** - */ - -/** - * Populate content information - * - * @v data Raw data - * @v len Length of raw data - * @v info Content information to fill in - * @ret rc Return status code - */ -int peerdist_info ( userptr_t data, size_t len, struct peerdist_info *info ) { - union peerdist_info_version version; - int rc; - - /* Initialise structure */ - memset ( info, 0, sizeof ( *info ) ); - info->raw.data = data; - info->raw.len = len; - - /* Get version */ - if ( ( rc = peerdist_info_get ( info, &version, 0, - sizeof ( version ) ) ) != 0 ) { - DBGC ( info, "PCCRC %p could not get version: %s\n", - info, strerror ( rc ) ); - return rc; - } - DBGC2 ( info, "PCCRC %p version %d.%d\n", - info, version.major, version.minor ); - - /* Determine version */ - switch ( version.raw ) { - case cpu_to_le16 ( PEERDIST_INFO_V1 ) : - info->op = &peerdist_info_v1_operations; - break; - case cpu_to_le16 ( PEERDIST_INFO_V2 ) : - info->op = &peerdist_info_v2_operations; - break; - default: - DBGC ( info, "PCCRC %p unsupported version %d.%d\n", - info, version.major, version.minor ); - return -ENOTSUP; - } - assert ( info->op != NULL ); - assert ( info->op->info != NULL ); - - /* Populate content information */ - if ( ( rc = info->op->info ( info ) ) != 0 ) - return rc; - - DBGC2 ( info, "PCCRC %p range [%08zx,%08zx) covers [%08zx,%08zx) with " - "%d segments\n", info, info->range.start, info->range.end, - info->trim.start, info->trim.end, info->segments ); - return 0; -} - -/** - * Populate content information segment - * - * @v info Content information - * @v segment Content information segment to fill in - * @v index Segment index - * @ret rc Return status code - */ -int peerdist_info_segment ( const struct peerdist_info *info, - struct peerdist_info_segment *segment, - unsigned int index ) { - int rc; - - /* Sanity checks */ - assert ( info != NULL ); - assert ( info->op != NULL ); - assert ( info->op->segment != NULL ); - if ( index >= info->segments ) { - DBGC ( info, "PCCRC %p segment %d of [0,%d) out of range\n", - info, index, info->segments ); - return -ERANGE; - } - - /* Initialise structure */ - memset ( segment, 0, sizeof ( *segment ) ); - segment->info = info; - segment->index = index; - - /* Populate content information segment */ - if ( ( rc = info->op->segment ( segment ) ) != 0 ) - return rc; - - DBGC2 ( info, "PCCRC %p segment %d range [%08zx,%08zx) with %d " - "blocks\n", info, segment->index, segment->range.start, - segment->range.end, segment->blocks ); - DBGC2 ( info, "PCCRC %p segment %d digest %s\n", info, segment->index, - peerdist_info_hash_ntoa ( info, segment->hash ) ); - DBGC2 ( info, "PCCRC %p segment %d secret %s\n", info, segment->index, - peerdist_info_hash_ntoa ( info, segment->secret ) ); - DBGC2 ( info, "PCCRC %p segment %d identf %s\n", info, segment->index, - peerdist_info_hash_ntoa ( info, segment->id ) ); - return 0; -} - -/** - * Populate content information block - * - * @v segment Content information segment - * @v block Content information block to fill in - * @v index Block index - * @ret rc Return status code - */ -int peerdist_info_block ( const struct peerdist_info_segment *segment, - struct peerdist_info_block *block, - unsigned int index ) { - const struct peerdist_info *info = segment->info; - size_t start; - size_t end; - int rc; - - /* Sanity checks */ - assert ( segment != NULL ); - assert ( info != NULL ); - assert ( info->op != NULL ); - assert ( info->op->block != NULL ); - if ( index >= segment->blocks ) { - DBGC ( info, "PCCRC %p segment %d block %d of [0,%d) out of " - "range\n", info, segment->index, index, segment->blocks); - return -ERANGE; - } - - /* Initialise structure */ - memset ( block, 0, sizeof ( *block ) ); - block->segment = segment; - block->index = index; - - /* Populate content information block */ - if ( ( rc = info->op->block ( block ) ) != 0 ) - return rc; - - /* Calculate trimmed range */ - start = block->range.start; - if ( start < info->trim.start ) - start = info->trim.start; - end = block->range.end; - if ( end > info->trim.end ) - end = info->trim.end; - if ( end < start ) - end = start; - block->trim.start = start; - block->trim.end = end; - - DBGC2 ( info, "PCCRC %p segment %d block %d hash %s\n", - info, segment->index, block->index, - peerdist_info_hash_ntoa ( info, block->hash ) ); - DBGC2 ( info, "PCCRC %p segment %d block %d range [%08zx,%08zx) covers " - "[%08zx,%08zx)\n", info, segment->index, block->index, - block->range.start, block->range.end, block->trim.start, - block->trim.end ); - return 0; -} |