99 TRACE(
"Entering process_ddt_v2(%p, %p, %d)", ctx, entry, *found_user_data_ddt);
102 size_t read_bytes = 0;
104 uint8_t *cmp_data = NULL;
106 size_t lzma_size = 0;
110 uint8_t *buffer = NULL;
115 FATAL(
"Invalid context or image stream.");
117 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_NOT_AARUFORMAT");
125 FATAL(
"Could not seek to %" PRIu64
" as indicated by index entry...", entry->
offset);
127 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
132 TRACE(
"Reading DDT block header at position %" PRIu64, entry->
offset);
137 FATAL(
"Could not read block header at %" PRIu64
"", entry->
offset);
139 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
161 FATAL(
"Compressed DDT payload too small (%" PRIu64
") for LZMA properties.", ddt_header.
cmpLength);
162 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
168 cmp_data = (uint8_t *)malloc(lzma_size);
171 TRACE(
"Cannot allocate memory for DDT, continuing...");
175 buffer = malloc(ddt_header.
length);
178 TRACE(
"Cannot allocate memory for DDT, continuing...");
186 TRACE(
"Could not read LZMA properties, continuing...");
192 read_bytes = fread(cmp_data, 1, lzma_size, ctx->
imageStream);
193 if(read_bytes != lzma_size)
195 TRACE(
"Could not read compressed block, continuing...");
201 read_bytes = ddt_header.
length;
202 TRACE(
"Decompressing block of size %zu bytes", ddt_header.
length);
208 FATAL(
"Got error %d from LZMA, stopping...", error_no);
211 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
215 if(read_bytes != ddt_header.
length)
217 FATAL(
"Error decompressing block, should be {0} bytes but got {1} bytes., stopping...");
220 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
228 if(crc64_context == NULL)
230 FATAL(
"Could not initialize CRC64.");
233 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
241 if(crc64 != ddt_header.
crc64)
243 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
245 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
252 *found_user_data_ddt =
true;
258 FATAL(
"Compressed DDT payload has zero length for zstd.");
259 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
263 cmp_data = (uint8_t *)malloc(ddt_header.
cmpLength);
266 TRACE(
"Cannot allocate memory for DDT, continuing...");
270 buffer = malloc(ddt_header.
length);
273 TRACE(
"Cannot allocate memory for DDT, continuing...");
281 TRACE(
"Could not read compressed block, continuing...");
290 if(read_bytes != ddt_header.
length)
292 FATAL(
"Error decompressing zstd DDT, expected %zu got %zu", ddt_header.
length, read_bytes);
295 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
303 if(crc64_context == NULL)
305 FATAL(
"Could not initialize CRC64.");
307 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
315 if(crc64 != ddt_header.
crc64)
317 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
319 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
326 *found_user_data_ddt =
true;
330 buffer = malloc(ddt_header.
length);
334 TRACE(
"Cannot allocate memory for DDT, continuing...");
338 TRACE(
"Reading DDT of length %zu bytes", ddt_header.
length);
341 if(read_bytes != ddt_header.
length)
344 FATAL(
"Could not read deduplication table, continuing...");
350 if(crc64_context == NULL)
352 FATAL(
"Could not initialize CRC64.");
354 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
362 if(crc64 != ddt_header.
crc64)
364 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
366 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
373 *found_user_data_ddt =
true;
377 TRACE(
"Found unknown compression type %d, continuing...", ddt_header.
compression);
378 *found_user_data_ddt =
false;
388 FATAL(
"Compressed DDT payload too small (%" PRIu64
") for LZMA properties.", ddt_header.
cmpLength);
389 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
395 cmp_data = (uint8_t *)malloc(lzma_size);
398 TRACE(
"Cannot allocate memory for DDT, continuing...");
402 buffer = malloc(ddt_header.
length);
405 TRACE(
"Cannot allocate memory for DDT, continuing...");
413 TRACE(
"Could not read LZMA properties, continuing...");
419 read_bytes = fread(cmp_data, 1, lzma_size, ctx->
imageStream);
420 if(read_bytes != lzma_size)
422 TRACE(
"Could not read compressed block, continuing...");
428 read_bytes = ddt_header.
length;
429 TRACE(
"Decompressing block of size %zu bytes", ddt_header.
length);
435 FATAL(
"Got error %d from LZMA, stopping...", error_no);
438 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
442 if(read_bytes != ddt_header.
length)
444 FATAL(
"Error decompressing block, should be {0} bytes but got {1} bytes., stopping...");
447 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
456 if(crc64_context == NULL)
458 FATAL(
"Could not initialize CRC64.");
460 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
468 if(crc64 != ddt_header.
crc64)
470 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
472 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
487 FATAL(
"Compressed DDT payload has zero length for zstd.");
488 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
492 cmp_data = (uint8_t *)malloc(ddt_header.
cmpLength);
495 TRACE(
"Cannot allocate memory for DDT, continuing...");
499 buffer = malloc(ddt_header.
length);
502 TRACE(
"Cannot allocate memory for DDT, continuing...");
510 TRACE(
"Could not read compressed block, continuing...");
519 if(read_bytes != ddt_header.
length)
521 FATAL(
"Error decompressing zstd DDT, expected %zu got %zu", ddt_header.
length, read_bytes);
524 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
533 if(crc64_context == NULL)
535 FATAL(
"Could not initialize CRC64.");
537 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
545 if(crc64 != ddt_header.
crc64)
547 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
549 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
563 buffer = malloc(ddt_header.
length);
567 TRACE(
"Cannot allocate memory for deduplication table.");
573 if(read_bytes != ddt_header.
length)
576 FATAL(
"Could not read deduplication table, continuing...");
582 if(crc64_context == NULL)
584 FATAL(
"Could not initialize CRC64.");
586 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
594 if(crc64 != ddt_header.
crc64)
596 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
598 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
611 TRACE(
"Found unknown compression type %d, continuing...", ddt_header.
compression);
615 TRACE(
"Exiting process_ddt_v2() = AARUF_STATUS_OK");
664 uint64_t *block_offset, uint8_t *sector_status)
666 TRACE(
"Entering decode_ddt_entry_v2(%p, %" PRIu64
", %d, %llu, %llu, %d)", ctx, sector_address, negative, *offset,
667 *block_offset, *sector_status);
671 FATAL(
"Invalid context or image stream.");
673 TRACE(
"Exiting decode_ddt_entry_v2() = AARUF_ERROR_NOT_AARUFORMAT");
688 uint64_t pos = sa / items;
692 TRACE(
"Attempting EC recovery for DDT secondary at offset %" PRIu64, ddt_off);
693 uint8_t *recovered = NULL;
694 uint32_t rec_size = 0;
701 memcpy(&rec_hdr, recovered,
sizeof(
DdtHeader2));
703 uint8_t *payload = recovered +
sizeof(
DdtHeader2);
704 uint32_t payload_size = rec_size -
sizeof(
DdtHeader2);
705 uint8_t *ddt_data = NULL;
709 ddt_data = (uint8_t *)malloc((
size_t)rec_hdr.
length);
710 if(ddt_data) memcpy(ddt_data, payload, (
size_t)rec_hdr.
length);
714 ddt_data = (uint8_t *)malloc((
size_t)rec_hdr.
length);
717 size_t out_sz = (size_t)rec_hdr.
length;
725 ddt_data = (uint8_t *)malloc((
size_t)rec_hdr.
length);
732 TRACE(
"EC recovery succeeded for DDT secondary, loading into cache");
738 offset, block_offset, sector_status);
806 uint64_t *block_offset, uint8_t *sector_status)
808 TRACE(
"Entering decode_ddt_single_level_v2(%p, %" PRIu64
", %d, %llu, %llu, %d)", ctx, sector_address, negative,
809 *offset, *block_offset, *sector_status);
811 uint64_t ddt_entry = 0;
816 FATAL(
"Invalid context or image stream.");
818 TRACE(
"Exiting decode_ddt_single_level_v2() = AARUF_ERROR_NOT_AARUFORMAT");
825 FATAL(
"DDT table shift is not zero, but we are in single-level DDT decoding.");
826 TRACE(
"Exiting decode_ddt_single_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
843 TRACE(
"Exiting decode_ddt_single_level_v2(%p, %" PRIu64
", %llu, %llu, %d) = AARUF_STATUS_OK", ctx,
844 sector_address, *offset, *block_offset, *sector_status);
848 *sector_status = ddt_entry >> 60;
849 ddt_entry &= 0xFFFFFFFFFFFFFFF;
852 *offset = ddt_entry & offset_mask;
856 TRACE(
"Exiting decode_ddt_single_level_v2(%p, %" PRIu64
", %d, %llu, %llu, %d) = AARUF_STATUS_OK", ctx,
857 sector_address, negative, *offset, *block_offset, *sector_status);
949 uint64_t *block_offset, uint8_t *sector_status)
951 TRACE(
"Entering decode_ddt_multi_level_v2(%p, %" PRIu64
", %d, %llu, %llu, %d)", ctx, sector_address, negative,
952 *offset, *block_offset, *sector_status);
954 uint64_t ddt_entry = 0;
956 size_t lzma_size = 0;
957 uint8_t *cmp_data = NULL;
958 uint8_t *buffer = NULL;
961 int items_per_ddt_entry = 0;
962 uint64_t ddt_position = 0;
963 uint64_t secondary_ddt_offset = 0;
968 FATAL(
"Invalid context or image stream.");
970 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_NOT_AARUFORMAT");
977 FATAL(
"DDT table shift is zero, but we are in multi-level DDT decoding.");
978 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
989 ddt_position = sector_address / items_per_ddt_entry;
998 int32_t error_no = 0;
1005 FATAL(
"Could not read block header at %" PRIu64
"", secondary_ddt_offset);
1006 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1014 FATAL(
"Invalid block header at %" PRIu64
"", secondary_ddt_offset);
1015 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1025 FATAL(
"Compressed DDT payload too small (%" PRIu64
") for LZMA properties.", ddt_header.
cmpLength);
1026 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1032 cmp_data = (uint8_t *)malloc(lzma_size);
1033 if(cmp_data == NULL)
1035 FATAL(
"Cannot allocate memory for DDT, stopping...");
1036 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1040 buffer = malloc(ddt_header.
length);
1043 FATAL(
"Cannot allocate memory for DDT, stopping...");
1051 FATAL(
"Could not read LZMA properties, stopping...");
1054 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1058 read_bytes = fread(cmp_data, 1, lzma_size, ctx->
imageStream);
1059 if(read_bytes != lzma_size)
1061 FATAL(
"Could not read compressed block, stopping...");
1064 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1068 TRACE(
"Decompressing block of size %zu bytes", ddt_header.
length);
1069 read_bytes = ddt_header.
length;
1075 FATAL(
"Got error %d from LZMA, stopping...", error_no);
1078 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1082 if(read_bytes != ddt_header.
length)
1084 FATAL(
"Error decompressing block, should be {0} bytes but got {1} bytes., stopping...");
1087 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1095 if(crc64_context == NULL)
1097 FATAL(
"Could not initialize CRC64.");
1099 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1107 if(crc64 != ddt_header.
crc64)
1109 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
1111 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
1126 FATAL(
"Compressed DDT payload has zero length for zstd.");
1127 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1131 cmp_data = (uint8_t *)malloc(ddt_header.
cmpLength);
1132 if(cmp_data == NULL)
1134 FATAL(
"Cannot allocate memory for DDT, stopping...");
1135 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1139 buffer = malloc(ddt_header.
length);
1142 FATAL(
"Cannot allocate memory for DDT, stopping...");
1150 FATAL(
"Could not read compressed block, stopping...");
1153 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1157 TRACE(
"Decompressing block of size %zu bytes", ddt_header.
length);
1161 if(read_bytes != ddt_header.
length)
1163 FATAL(
"Error decompressing zstd DDT, expected %zu got %zu", ddt_header.
length, read_bytes);
1166 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1174 if(crc64_context == NULL)
1176 FATAL(
"Could not initialize CRC64.");
1178 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1186 if(crc64 != ddt_header.
crc64)
1188 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
1190 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
1203 buffer = malloc(ddt_header.
length);
1207 FATAL(
"Cannot allocate memory for DDT, stopping...");
1208 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1214 if(read_bytes != ddt_header.
length)
1217 FATAL(
"Could not read deduplication table, stopping...");
1218 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1224 if(crc64_context == NULL)
1226 FATAL(
"Could not initialize CRC64.");
1228 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1236 if(crc64 != ddt_header.
crc64)
1238 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
1240 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
1253 FATAL(
"Found unknown compression type %d, stopping...", ddt_header.
compression);
1254 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1267 TRACE(
"Exiting decode_ddt_multi_level_v2(%p, %" PRIu64
", %llu, %llu, %d) = AARUF_STATUS_OK", ctx,
1268 sector_address, *offset, *block_offset, *sector_status);
1272 *sector_status = ddt_entry >> 60;
1273 ddt_entry &= 0x0FFFFFFFFFFFFFFF;
1276 *offset = ddt_entry & offset_mask;
1280 TRACE(
"Exiting decode_ddt_multi_level_v2(%p, %" PRIu64
", %d, %llu, %llu, %d) = AARUF_STATUS_OK", ctx,
1281 sector_address, negative, *offset, *block_offset, *sector_status);
1302 const uint64_t offset,
const uint64_t block_offset,
const uint8_t sector_status,
1303 uint64_t *ddt_entry)
1305 TRACE(
"Entering set_ddt_entry_v2(%p, %" PRIu64
", %d, %llu, %llu, %d)", ctx, sector_address, negative, offset,
1306 block_offset, sector_status);
1311 FATAL(
"Invalid context or image stream.");
1316 return set_ddt_multi_level_v2(ctx, sector_address, negative, offset, block_offset, sector_status, ddt_entry);
1318 return set_ddt_single_level_v2(ctx, sector_address, negative, offset, block_offset, sector_status, ddt_entry);
1338 const uint64_t offset,
const uint64_t block_offset,
const uint8_t sector_status,
1339 uint64_t *ddt_entry)
1341 TRACE(
"Entering set_ddt_single_level_v2(%p, %" PRIu64
", %d, %llu, %llu, %d)", ctx, sector_address, negative,
1342 offset, block_offset, sector_status);
1347 FATAL(
"Invalid context or image stream.");
1348 TRACE(
"Exiting set_ddt_single_level_v2() = false");
1355 FATAL(
"DDT table shift is not zero, but we are in single-level DDT setting.");
1356 TRACE(
"Exiting set_ddt_single_level_v2() = false");
1373 if(*ddt_entry > 0xFFFFFFFFFFFFFFF)
1375 FATAL(
"DDT overflow: media does not fit in big DDT");
1376 TRACE(
"Exiting set_ddt_single_level_v2() = false");
1382 *ddt_entry &= 0x0FFFFFFFFFFFFFFF;
1383 *ddt_entry |= (uint64_t)sector_status << 60;
1385 TRACE(
"Setting big single-level DDT entry %d to %ull", sector_address, (uint64_t)*ddt_entry);
1389 TRACE(
"Exiting set_ddt_single_level_v2() = true");
1410 uint64_t block_offset, uint8_t sector_status, uint64_t *ddt_entry)
1412 TRACE(
"Entering set_ddt_multi_level_v2(%p, %" PRIu64
", %d, %" PRIu64
", %" PRIu64
", %d)", ctx, sector_address,
1413 negative, offset, block_offset, sector_status);
1415 uint64_t items_per_ddt_entry = 0;
1416 uint64_t ddt_position = 0;
1417 uint64_t secondary_ddt_offset = 0;
1418 uint64_t block_index = 0;
1419 uint8_t *buffer = NULL;
1423 size_t written_bytes = 0;
1424 long end_of_file = 0;
1425 bool create_new_table =
false;
1430 FATAL(
"Invalid context or image stream.");
1431 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1438 FATAL(
"DDT table shift is zero, but we are in multi-level DDT setting.");
1439 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1451 ddt_position = sector_address / items_per_ddt_entry;
1468 if(*ddt_entry > 0xFFFFFFFFFFFFFFF)
1470 FATAL(
"DDT overflow: media does not fit in big DDT");
1471 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1477 *ddt_entry &= 0x0FFFFFFFFFFFFFFF;
1478 *ddt_entry |= (uint64_t)sector_status << 60;
1480 TRACE(
"Setting small secondary DDT entry %d to %ull", sector_address % items_per_ddt_entry,
1481 (uint64_t)*ddt_entry);
1485 TRACE(
"Updated cached secondary DDT entry at position %" PRIu64, sector_address % items_per_ddt_entry);
1486 TRACE(
"Exiting set_ddt_multi_level_v2() = true");
1497 TRACE(
"Current secondary DDT in memory belongs to position %" PRIu64
1498 " but requested block needs position %" PRIu64,
1512 end_of_file = end_of_file + alignment_mask & ~alignment_mask;
1526 ddt_header.
blocks = items_per_ddt_entry;
1532 ddt_header.
entries = items_per_ddt_entry;
1536 ddt_header.
length = items_per_ddt_entry *
sizeof(uint64_t);
1540 if(crc64_context == NULL)
1542 FATAL(
"Could not initialize CRC64.");
1543 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1551 ddt_header.
crc64 = crc64;
1553 uint8_t *cmp_buffer = NULL;
1564 cmp_buffer = malloc((
size_t)ddt_header.
length * 2);
1565 if(cmp_buffer == NULL)
1567 TRACE(
"Failed to allocate memory for secondary DDT v2 compression");
1578 if(dst_size == 0) dst_size = ddt_header.
length;
1582 dst_size = (size_t)ddt_header.
length * 2 * 2;
1589 ddt_header.
cmpLength = (uint32_t)dst_size;
1615 if(written_bytes != 1)
1617 FATAL(
"Could not write never-written DDT header to file.");
1618 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1628 FATAL(
"Could not write never-written DDT data to file.");
1629 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1639 new_ddt_entry.
offset = end_of_file;
1643 TRACE(
"Added new DDT index entry for never-written table at offset %" PRIu64, end_of_file);
1659 if(written_bytes != 1)
1661 FATAL(
"Could not flush primary DDT table to file after writing never-written secondary table.");
1662 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1668 ctx->
next_block_position = end_of_file + ddt_total_size + alignment_mask & ~alignment_mask;
1685 TRACE(
"Successfully wrote never-written cached secondary DDT to disk");
1689 TRACE(
"Cached DDT is for the correct block range, using it directly");
1707 end_of_file = end_of_file + alignment_mask & ~alignment_mask;
1720 ddt_header.
blocks = items_per_ddt_entry;
1722 ddt_header.
start = ddt_position * items_per_ddt_entry;
1726 ddt_header.
entries = items_per_ddt_entry;
1730 ddt_header.
length = items_per_ddt_entry *
sizeof(uint64_t);
1734 if(crc64_context == NULL)
1736 FATAL(
"Could not initialize CRC64.");
1737 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1745 ddt_header.
crc64 = crc64;
1747 uint8_t *cmp_buffer = NULL;
1758 cmp_buffer = malloc((
size_t)ddt_header.
length * 2);
1759 if(cmp_buffer == NULL)
1761 TRACE(
"Failed to allocate memory for secondary DDT v2 compression");
1772 if(dst_size == 0) dst_size = ddt_header.
length;
1776 dst_size = (size_t)ddt_header.
length * 2 * 2;
1783 ddt_header.
cmpLength = (uint32_t)dst_size;
1812 if(written_bytes != 1)
1814 FATAL(
"Could not write DDT header to file.");
1815 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1822 if(written_bytes != 1)
1824 FATAL(
"Could not write DDT data to file.");
1825 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1832 TRACE(
"Updating index for evicted secondary DDT");
1841 for(
unsigned int i = 0; i < utarray_len(ctx->
index_entries); i++)
1847 TRACE(
"Found old DDT index entry at position %u, removing", i);
1858 new_ddt_entry.
offset = end_of_file;
1862 TRACE(
"Added new DDT index entry at offset %" PRIu64, end_of_file);
1870 ctx->
user_data_ddt2[ddt_position] = new_secondary_table_block_offset;
1881 if(written_bytes != 1)
1883 FATAL(
"Could not flush primary DDT table to file.");
1884 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1890 ctx->
next_block_position = end_of_file + ddt_total_size + alignment_mask & ~alignment_mask;
1909 if(!create_new_table && secondary_ddt_offset != 0)
1918 FATAL(
"Invalid secondary DDT header at %" PRIu64, secondary_ddt_offset);
1919 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1924 buffer = malloc(ddt_header.
length);
1927 FATAL(
"Cannot allocate memory for secondary DDT.");
1928 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1933 if(read_bytes != ddt_header.
length)
1935 FATAL(
"Could not read secondary DDT data.");
1937 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1943 if(crc64_context == NULL)
1945 FATAL(
"Could not initialize CRC64.");
1947 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1955 if(crc64 != ddt_header.
crc64)
1957 FATAL(
"Secondary DDT CRC mismatch. Expected 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
1959 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1970 if(create_new_table)
1973 size_t table_size = items_per_ddt_entry *
sizeof(uint64_t);
1975 buffer = calloc(1, table_size);
1978 FATAL(
"Cannot allocate memory for new secondary DDT.");
1979 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1987 TRACE(
"Created new secondary DDT for position %" PRIu64, ddt_position);
1998 if(*ddt_entry > 0xFFFFFFFFFFFFFFF)
2000 FATAL(
"DDT overflow: media does not fit in big DDT");
2001 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
2007 *ddt_entry &= 0x0FFFFFFFFFFFFFFF;
2008 *ddt_entry |= (uint64_t)sector_status << 60;
2010 TRACE(
"Setting big secondary DDT entry %d to %ull", sector_address % items_per_ddt_entry, (uint64_t)*ddt_entry);
2014 TRACE(
"Updated secondary DDT entry at position %" PRIu64, sector_address % items_per_ddt_entry);
2015 TRACE(
"Exiting set_ddt_multi_level_v2() = true");
2136 const uint8_t sector_status, uint64_t *ddt_entry)
2138 TRACE(
"Entering set_ddt_tape(%p, %" PRIu64
", %llu, %llu, %d)", ctx, sector_address, offset, block_offset,
2144 FATAL(
"Invalid context or image stream.");
2145 TRACE(
"Exiting set_ddt_tape() = false");
2152 FATAL(
"Image is not tape, wrong function called.");
2153 TRACE(
"Exiting set_ddt_tape() = false");
2163 if(*ddt_entry > 0xFFFFFFFFFFFFFFF)
2165 FATAL(
"DDT overflow: media does not fit in big DDT");
2166 TRACE(
"Exiting set_ddt_tape() = false");
2170 *ddt_entry |= (uint64_t)sector_status << 60;
2176 if(new_entry == NULL)
2178 FATAL(
"Cannot allocate memory for new tape DDT hash entry.");
2179 TRACE(
"Exiting set_ddt_tape() = false");
2183 TRACE(
"Setting tape DDT entry %d to %u", sector_address, (uint32_t)*ddt_entry);
2185 new_entry->
key = sector_address;
2186 new_entry->
value = *ddt_entry;
2189 HASH_REPLACE(hh, ctx->
tape_ddt, key,
sizeof(uint64_t), new_entry, old_entry);
2191 if(old_entry) free(old_entry);
2193 TRACE(
"Exiting set_ddt_tape() = true");
#define LZMA_PROPERTIES_LENGTH
Size in bytes of the fixed LZMA properties header (lc/lp/pb + dictionary size).
int32_t aaruf_lzma_encode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer, size_t src_size, uint8_t *out_props, size_t *out_props_size, int32_t level, uint32_t dict_size, int32_t lc, int32_t lp, int32_t pb, int32_t fb, int32_t num_threads)
Encodes a buffer using LZMA compression.
uint64_t aaruf_crc64_data(const uint8_t *data, uint32_t len)
int32_t aaruf_lzma_decode_buffer(uint8_t *dst_buffer, size_t *dst_size, const uint8_t *src_buffer, size_t *src_size, const uint8_t *props, size_t props_size)
Decodes an LZMA-compressed buffer.
int aaruf_crc64_update(crc64_ctx *ctx, const uint8_t *data, uint32_t len)
Updates the CRC64 context with new data.
size_t aaruf_zstd_encode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer, size_t src_size, int level, int num_threads)
Encodes a buffer using Zstandard compression.
void aaruf_crc64_free(crc64_ctx *ctx)
Frees a CRC64 context.
size_t aaruf_zstd_decode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer, size_t src_size)
Decodes a Zstandard-compressed buffer.
int aaruf_crc64_final(crc64_ctx *ctx, uint64_t *crc)
Computes the final CRC64 value from the context.
crc64_ctx * aaruf_crc64_init(void)
Initializes a CRC64 context.
@ DeDuplicationTableSecondary
Block containing a secondary deduplication table (v2).
@ DeDuplicationTable2
Block containing a deduplication table v2.
@ DeDuplicationTableSAlpha
Block containing a secondary deduplication table (v2) (mistake).
@ SectorStatusNotDumped
Sector(s) not yet acquired during image dumping.
@ kDataTypeCdSectorSuffix
Compact Disc sector suffix (EDC, ECC P, ECC Q).
@ kDataTypeUserData
User (main) data.
@ kDataTypeCdSectorPrefix
Compact Disc sector prefix (sync, header).
@ kCompressionLzma
LZMA compression.
@ kCompressionNone
Not compressed.
@ kCompressionZstd
Zstandard compression.
int32_t ec_recover_ddt_block(aaruformat_context *ctx, uint64_t block_offset, uint8_t **recovered_data, uint32_t *recovered_size)
Attempt to recover a DDT secondary block at a given file offset.
#define AARUF_STATUS_OK
Sector present and read without uncorrectable errors.
#define AARUF_ERROR_NOT_ENOUGH_MEMORY
Memory allocation failure (critical).
#define AARUF_ERROR_CANNOT_READ_BLOCK
Generic block read failure (seek/read error).
#define AARUF_ERROR_INVALID_BLOCK_CRC
CRC64 mismatch indicating corruption.
#define AARUF_ERROR_NOT_AARUFORMAT
Input file/stream failed magic or structural validation.
#define AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK
Decompression routine failed or size mismatch.
bool set_ddt_entry_v2(aaruformat_context *ctx, uint64_t sector_address, bool negative, uint64_t offset, uint64_t block_offset, uint8_t sector_status, uint64_t *ddt_entry)
Sets a DDT v2 entry for a given sector address.
int32_t process_ddt_v2(aaruformat_context *ctx, IndexEntry *entry, bool *found_user_data_ddt)
Processes a DDT v2 block from the image stream.
int32_t aaruf_close_current_block(aaruformat_context *ctx)
Finalizes and writes the current data block to the AaruFormat image file.
int32_t decode_ddt_single_level_v2(aaruformat_context *ctx, uint64_t sector_address, bool negative, uint64_t *offset, uint64_t *block_offset, uint8_t *sector_status)
Decodes a single-level DDT v2 entry for a given sector address.
static int aaruf_fseek(FILE *stream, aaru_off_t offset, int origin)
static aaru_off_t aaruf_ftell(FILE *stream)
bool set_ddt_multi_level_v2(aaruformat_context *ctx, uint64_t sector_address, bool negative, uint64_t offset, uint64_t block_offset, uint8_t sector_status, uint64_t *ddt_entry)
Sets a multi-level DDT v2 entry for a given sector address.
bool set_ddt_single_level_v2(aaruformat_context *ctx, uint64_t sector_address, bool negative, uint64_t offset, uint64_t block_offset, uint8_t sector_status, uint64_t *ddt_entry)
Sets a single-level DDT v2 entry for a given sector address.
int32_t decode_ddt_entry_v2(aaruformat_context *ctx, uint64_t sector_address, bool negative, uint64_t *offset, uint64_t *block_offset, uint8_t *sector_status)
Decodes a DDT v2 entry for a given sector address.
bool set_ddt_tape(aaruformat_context *ctx, uint64_t sector_address, uint64_t offset, uint64_t block_offset, uint8_t sector_status, uint64_t *ddt_entry)
Sets a DDT entry for tape media using a hash-based lookup table.
int32_t decode_ddt_multi_level_v2(aaruformat_context *ctx, uint64_t sector_address, bool negative, uint64_t *offset, uint64_t *block_offset, uint8_t *sector_status)
Decodes a multi-level DDT v2 entry for a given sector address.
#define LZMA_THREADS(ctx)
Clamp num_threads to LZMA's valid range [1, 2].
uint64_t ImageSize
Size of the image payload in bytes (excludes headers/metadata).
uint64_t Sectors
Total count of addressable logical sectors/blocks.
Single index entry describing a block's type, (optional) data classification, and file offset.
uint32_t blockType
Block identifier of the referenced block (value from BlockType).
uint64_t offset
Absolute byte offset in the image where the referenced block header begins.
uint16_t dataType
Data classification (value from DataType) or unused for untyped blocks.
uint64_t key
Key: sector address.
uint64_t value
Value: DDT entry.
Master context representing an open or in‑creation Aaru image.
DdtHeader2 user_data_ddt_header
Active user data DDT v2 header (primary table meta).
bool compression_enabled
True if block compression enabled (writing path).
bool dirty_primary_ddt
True if primary DDT table should be written during close.
bool ec_recovery_in_progress
Recursion guard for recovery (prevents infinite loops).
uint64_t * user_data_ddt2
DDT entries (big variant) primary/secondary current.
uint64_t * sector_suffix_ddt2
CD sector suffix DDT V2.
uint64_t cached_ddt_offset
File offset of currently cached secondary DDT (0=none).
bool is_tape
True if the image is a tape image.
bool in_memory_ddt
True if primary (and possibly secondary) DDT loaded.
bool dirty_index_block
True if index block should be written during close.
TapeDdtHashEntry * tape_ddt
Hash table root for tape DDT entries.
bool dirty_single_level_ddt
True if single-level DDT should be written during close.
int ddt_version
DDT version in use (1=legacy, 2=v2 hierarchical).
uint8_t * writing_buffer
Accumulation buffer for current block data.
uint64_t * sector_prefix_ddt2
CD sector prefix DDT V2.
uint64_t primary_ddt_offset
File offset of the primary DDT v2 table.
uint64_t next_block_position
Absolute file offset where next block will be written.
bool has_zstd_blocks
True if any block was actually written with Zstandard compression.
uint64_t * cached_secondary_ddt2
Cached secondary table (big entries) or NULL.
int zstd_level
Zstandard compression level (writing path, default 19).
FILE * imageStream
Underlying FILE* stream (binary mode).
UT_array * index_entries
Flattened index entries (UT_array of IndexEntry).
int num_threads
Compression worker threads (1 = single-threaded, default).
ImageInfo image_info
Exposed high-level image info summary.
bool use_zstd
Use Zstandard instead of LZMA for data blocks.
bool dirty_secondary_ddt
True if secondary DDT tables should be written during close.
bool dirty_tape_ddt
True if tape DDT should be written during close.
uint32_t lzma_dict_size
LZMA dictionary size (writing path).
uint64_t cached_ddt_position
Position index of cached secondary DDT.
bool ec_recovery_available
True if ECMB loaded and recovery is possible.
Minimal ECMA-182 CRC64 incremental state container (running value only).