| 225 | } |
| 226 | |
| 227 | int reftable_block_init(struct reftable_block *block, |
| 228 | struct reftable_block_source *source, |
| 229 | uint32_t offset, uint32_t header_size, |
| 230 | uint32_t table_block_size, uint32_t hash_size, |
| 231 | uint8_t want_type) |
| 232 | { |
| 233 | uint32_t guess_block_size = table_block_size ? |
| 234 | table_block_size : DEFAULT_BLOCK_SIZE; |
| 235 | uint32_t full_block_size = table_block_size; |
| 236 | uint16_t restart_count; |
| 237 | uint32_t restart_off; |
| 238 | uint32_t block_size; |
| 239 | uint8_t block_type; |
| 240 | int err; |
| 241 | |
| 242 | err = read_block(source, &block->block_data, offset, guess_block_size); |
| 243 | if (err < 0) |
| 244 | goto done; |
| 245 | |
| 246 | block_type = block->block_data.data[header_size]; |
| 247 | if (!reftable_is_block_type(block_type)) { |
| 248 | err = REFTABLE_FORMAT_ERROR; |
| 249 | goto done; |
| 250 | } |
| 251 | if (want_type != REFTABLE_BLOCK_TYPE_ANY && block_type != want_type) { |
| 252 | err = 1; |
| 253 | goto done; |
| 254 | } |
| 255 | |
| 256 | block_size = reftable_get_be24(block->block_data.data + header_size + 1); |
| 257 | if (block_size > guess_block_size) { |
| 258 | err = read_block(source, &block->block_data, offset, block_size); |
| 259 | if (err < 0) |
| 260 | goto done; |
| 261 | } |
| 262 | |
| 263 | if (block_type == REFTABLE_BLOCK_TYPE_LOG) { |
| 264 | uint32_t block_header_skip = 4 + header_size; |
| 265 | uLong dst_len = block_size - block_header_skip; |
| 266 | uLong src_len = block->block_data.len - block_header_skip; |
| 267 | |
| 268 | /* Log blocks specify the *uncompressed* size in their header. */ |
| 269 | REFTABLE_ALLOC_GROW_OR_NULL(block->uncompressed_data, block_size, |
| 270 | block->uncompressed_cap); |
| 271 | if (!block->uncompressed_data) { |
| 272 | err = REFTABLE_OUT_OF_MEMORY_ERROR; |
| 273 | goto done; |
| 274 | } |
| 275 | |
| 276 | /* Copy over the block header verbatim. It's not compressed. */ |
| 277 | memcpy(block->uncompressed_data, block->block_data.data, block_header_skip); |
| 278 | |
| 279 | if (!block->zstream) { |
| 280 | REFTABLE_CALLOC_ARRAY(block->zstream, 1); |
| 281 | if (!block->zstream) { |
| 282 | err = REFTABLE_OUT_OF_MEMORY_ERROR; |
| 283 | goto done; |
| 284 | } |