98 TRACE(
"Entering process_ddt_v2(%p, %p, %d)", ctx, entry, *found_user_data_ddt);
101 size_t read_bytes = 0;
103 uint8_t *cmp_data = NULL;
105 size_t lzma_size = 0;
109 uint8_t *buffer = NULL;
114 FATAL(
"Invalid context or image stream.");
116 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_NOT_AARUFORMAT");
124 FATAL(
"Could not seek to %" PRIu64
" as indicated by index entry...", entry->
offset);
126 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
131 TRACE(
"Reading DDT block header at position %" PRIu64, entry->
offset);
136 FATAL(
"Could not read block header at %" PRIu64
"", entry->
offset);
138 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
160 FATAL(
"Compressed DDT payload too small (%" PRIu64
") for LZMA properties.", ddt_header.
cmpLength);
161 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
167 cmp_data = (uint8_t *)malloc(lzma_size);
170 TRACE(
"Cannot allocate memory for DDT, continuing...");
174 buffer = malloc(ddt_header.
length);
177 TRACE(
"Cannot allocate memory for DDT, continuing...");
185 TRACE(
"Could not read LZMA properties, continuing...");
191 read_bytes = fread(cmp_data, 1, lzma_size, ctx->
imageStream);
192 if(read_bytes != lzma_size)
194 TRACE(
"Could not read compressed block, continuing...");
200 read_bytes = ddt_header.
length;
201 TRACE(
"Decompressing block of size %zu bytes", ddt_header.
length);
207 FATAL(
"Got error %d from LZMA, stopping...", error_no);
210 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
214 if(read_bytes != ddt_header.
length)
216 FATAL(
"Error decompressing block, should be {0} bytes but got {1} bytes., stopping...");
219 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
227 if(crc64_context == NULL)
229 FATAL(
"Could not initialize CRC64.");
232 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
240 if(crc64 != ddt_header.
crc64)
242 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
244 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
251 *found_user_data_ddt =
true;
257 FATAL(
"Compressed DDT payload has zero length for zstd.");
258 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
262 cmp_data = (uint8_t *)malloc(ddt_header.
cmpLength);
265 TRACE(
"Cannot allocate memory for DDT, continuing...");
269 buffer = malloc(ddt_header.
length);
272 TRACE(
"Cannot allocate memory for DDT, continuing...");
280 TRACE(
"Could not read compressed block, continuing...");
289 if(read_bytes != ddt_header.
length)
291 FATAL(
"Error decompressing zstd DDT, expected %zu got %zu", ddt_header.
length, read_bytes);
294 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
302 if(crc64_context == NULL)
304 FATAL(
"Could not initialize CRC64.");
306 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
314 if(crc64 != ddt_header.
crc64)
316 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
318 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
325 *found_user_data_ddt =
true;
329 buffer = malloc(ddt_header.
length);
333 TRACE(
"Cannot allocate memory for DDT, continuing...");
337 TRACE(
"Reading DDT of length %zu bytes", ddt_header.
length);
340 if(read_bytes != ddt_header.
length)
343 FATAL(
"Could not read deduplication table, continuing...");
349 if(crc64_context == NULL)
351 FATAL(
"Could not initialize CRC64.");
353 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
361 if(crc64 != ddt_header.
crc64)
363 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
365 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
372 *found_user_data_ddt =
true;
376 TRACE(
"Found unknown compression type %d, continuing...", ddt_header.
compression);
377 *found_user_data_ddt =
false;
387 FATAL(
"Compressed DDT payload too small (%" PRIu64
") for LZMA properties.", ddt_header.
cmpLength);
388 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
394 cmp_data = (uint8_t *)malloc(lzma_size);
397 TRACE(
"Cannot allocate memory for DDT, continuing...");
401 buffer = malloc(ddt_header.
length);
404 TRACE(
"Cannot allocate memory for DDT, continuing...");
412 TRACE(
"Could not read LZMA properties, continuing...");
418 read_bytes = fread(cmp_data, 1, lzma_size, ctx->
imageStream);
419 if(read_bytes != lzma_size)
421 TRACE(
"Could not read compressed block, continuing...");
427 read_bytes = ddt_header.
length;
428 TRACE(
"Decompressing block of size %zu bytes", ddt_header.
length);
434 FATAL(
"Got error %d from LZMA, stopping...", error_no);
437 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
441 if(read_bytes != ddt_header.
length)
443 FATAL(
"Error decompressing block, should be {0} bytes but got {1} bytes., stopping...");
446 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
455 if(crc64_context == NULL)
457 FATAL(
"Could not initialize CRC64.");
459 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
467 if(crc64 != ddt_header.
crc64)
469 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
471 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
486 FATAL(
"Compressed DDT payload has zero length for zstd.");
487 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
491 cmp_data = (uint8_t *)malloc(ddt_header.
cmpLength);
494 TRACE(
"Cannot allocate memory for DDT, continuing...");
498 buffer = malloc(ddt_header.
length);
501 TRACE(
"Cannot allocate memory for DDT, continuing...");
509 TRACE(
"Could not read compressed block, continuing...");
518 if(read_bytes != ddt_header.
length)
520 FATAL(
"Error decompressing zstd DDT, expected %zu got %zu", ddt_header.
length, read_bytes);
523 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
532 if(crc64_context == NULL)
534 FATAL(
"Could not initialize CRC64.");
536 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
544 if(crc64 != ddt_header.
crc64)
546 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
548 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
562 buffer = malloc(ddt_header.
length);
566 TRACE(
"Cannot allocate memory for deduplication table.");
572 if(read_bytes != ddt_header.
length)
575 FATAL(
"Could not read deduplication table, continuing...");
581 if(crc64_context == NULL)
583 FATAL(
"Could not initialize CRC64.");
585 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
593 if(crc64 != ddt_header.
crc64)
595 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
597 TRACE(
"Exiting process_ddt_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
610 TRACE(
"Found unknown compression type %d, continuing...", ddt_header.
compression);
614 TRACE(
"Exiting process_ddt_v2() = AARUF_STATUS_OK");
663 uint64_t *block_offset, uint8_t *sector_status)
665 TRACE(
"Entering decode_ddt_entry_v2(%p, %" PRIu64
", %d, %llu, %llu, %d)", ctx, sector_address, negative, *offset,
666 *block_offset, *sector_status);
670 FATAL(
"Invalid context or image stream.");
672 TRACE(
"Exiting decode_ddt_entry_v2() = AARUF_ERROR_NOT_AARUFORMAT");
737 uint64_t *block_offset, uint8_t *sector_status)
739 TRACE(
"Entering decode_ddt_single_level_v2(%p, %" PRIu64
", %d, %llu, %llu, %d)", ctx, sector_address, negative,
740 *offset, *block_offset, *sector_status);
742 uint64_t ddt_entry = 0;
747 FATAL(
"Invalid context or image stream.");
749 TRACE(
"Exiting decode_ddt_single_level_v2() = AARUF_ERROR_NOT_AARUFORMAT");
756 FATAL(
"DDT table shift is not zero, but we are in single-level DDT decoding.");
757 TRACE(
"Exiting decode_ddt_single_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
774 TRACE(
"Exiting decode_ddt_single_level_v2(%p, %" PRIu64
", %llu, %llu, %d) = AARUF_STATUS_OK", ctx,
775 sector_address, *offset, *block_offset, *sector_status);
779 *sector_status = ddt_entry >> 60;
780 ddt_entry &= 0xFFFFFFFFFFFFFFF;
783 *offset = ddt_entry & offset_mask;
787 TRACE(
"Exiting decode_ddt_single_level_v2(%p, %" PRIu64
", %d, %llu, %llu, %d) = AARUF_STATUS_OK", ctx,
788 sector_address, negative, *offset, *block_offset, *sector_status);
880 uint64_t *block_offset, uint8_t *sector_status)
882 TRACE(
"Entering decode_ddt_multi_level_v2(%p, %" PRIu64
", %d, %llu, %llu, %d)", ctx, sector_address, negative,
883 *offset, *block_offset, *sector_status);
885 uint64_t ddt_entry = 0;
887 size_t lzma_size = 0;
888 uint8_t *cmp_data = NULL;
889 uint8_t *buffer = NULL;
892 int items_per_ddt_entry = 0;
893 uint64_t ddt_position = 0;
894 uint64_t secondary_ddt_offset = 0;
899 FATAL(
"Invalid context or image stream.");
901 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_NOT_AARUFORMAT");
908 FATAL(
"DDT table shift is zero, but we are in multi-level DDT decoding.");
909 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
920 ddt_position = sector_address / items_per_ddt_entry;
929 int32_t error_no = 0;
936 FATAL(
"Could not read block header at %" PRIu64
"", secondary_ddt_offset);
937 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
945 FATAL(
"Invalid block header at %" PRIu64
"", secondary_ddt_offset);
946 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
956 FATAL(
"Compressed DDT payload too small (%" PRIu64
") for LZMA properties.", ddt_header.
cmpLength);
957 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
963 cmp_data = (uint8_t *)malloc(lzma_size);
966 FATAL(
"Cannot allocate memory for DDT, stopping...");
967 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
971 buffer = malloc(ddt_header.
length);
974 FATAL(
"Cannot allocate memory for DDT, stopping...");
982 FATAL(
"Could not read LZMA properties, stopping...");
985 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
989 read_bytes = fread(cmp_data, 1, lzma_size, ctx->
imageStream);
990 if(read_bytes != lzma_size)
992 FATAL(
"Could not read compressed block, stopping...");
995 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
999 TRACE(
"Decompressing block of size %zu bytes", ddt_header.
length);
1000 read_bytes = ddt_header.
length;
1006 FATAL(
"Got error %d from LZMA, stopping...", error_no);
1009 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1013 if(read_bytes != ddt_header.
length)
1015 FATAL(
"Error decompressing block, should be {0} bytes but got {1} bytes., stopping...");
1018 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1026 if(crc64_context == NULL)
1028 FATAL(
"Could not initialize CRC64.");
1030 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1038 if(crc64 != ddt_header.
crc64)
1040 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
1042 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
1057 FATAL(
"Compressed DDT payload has zero length for zstd.");
1058 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1062 cmp_data = (uint8_t *)malloc(ddt_header.
cmpLength);
1063 if(cmp_data == NULL)
1065 FATAL(
"Cannot allocate memory for DDT, stopping...");
1066 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1070 buffer = malloc(ddt_header.
length);
1073 FATAL(
"Cannot allocate memory for DDT, stopping...");
1081 FATAL(
"Could not read compressed block, stopping...");
1084 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1088 TRACE(
"Decompressing block of size %zu bytes", ddt_header.
length);
1092 if(read_bytes != ddt_header.
length)
1094 FATAL(
"Error decompressing zstd DDT, expected %zu got %zu", ddt_header.
length, read_bytes);
1097 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
1105 if(crc64_context == NULL)
1107 FATAL(
"Could not initialize CRC64.");
1109 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1117 if(crc64 != ddt_header.
crc64)
1119 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
1121 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
1134 buffer = malloc(ddt_header.
length);
1138 FATAL(
"Cannot allocate memory for DDT, stopping...");
1139 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1145 if(read_bytes != ddt_header.
length)
1148 FATAL(
"Could not read deduplication table, stopping...");
1149 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1155 if(crc64_context == NULL)
1157 FATAL(
"Could not initialize CRC64.");
1159 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1167 if(crc64 != ddt_header.
crc64)
1169 FATAL(
"Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
1171 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_INVALID_BLOCK_CRC");
1184 FATAL(
"Found unknown compression type %d, stopping...", ddt_header.
compression);
1185 TRACE(
"Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK");
1198 TRACE(
"Exiting decode_ddt_multi_level_v2(%p, %" PRIu64
", %llu, %llu, %d) = AARUF_STATUS_OK", ctx,
1199 sector_address, *offset, *block_offset, *sector_status);
1203 *sector_status = ddt_entry >> 60;
1204 ddt_entry &= 0x0FFFFFFFFFFFFFFF;
1207 *offset = ddt_entry & offset_mask;
1211 TRACE(
"Exiting decode_ddt_multi_level_v2(%p, %" PRIu64
", %d, %llu, %llu, %d) = AARUF_STATUS_OK", ctx,
1212 sector_address, negative, *offset, *block_offset, *sector_status);
1233 const uint64_t offset,
const uint64_t block_offset,
const uint8_t sector_status,
1234 uint64_t *ddt_entry)
1236 TRACE(
"Entering set_ddt_entry_v2(%p, %" PRIu64
", %d, %llu, %llu, %d)", ctx, sector_address, negative, offset,
1237 block_offset, sector_status);
1242 FATAL(
"Invalid context or image stream.");
1247 return set_ddt_multi_level_v2(ctx, sector_address, negative, offset, block_offset, sector_status, ddt_entry);
1249 return set_ddt_single_level_v2(ctx, sector_address, negative, offset, block_offset, sector_status, ddt_entry);
1269 const uint64_t offset,
const uint64_t block_offset,
const uint8_t sector_status,
1270 uint64_t *ddt_entry)
1272 TRACE(
"Entering set_ddt_single_level_v2(%p, %" PRIu64
", %d, %llu, %llu, %d)", ctx, sector_address, negative,
1273 offset, block_offset, sector_status);
1278 FATAL(
"Invalid context or image stream.");
1279 TRACE(
"Exiting set_ddt_single_level_v2() = false");
1286 FATAL(
"DDT table shift is not zero, but we are in single-level DDT setting.");
1287 TRACE(
"Exiting set_ddt_single_level_v2() = false");
1304 if(*ddt_entry > 0xFFFFFFFFFFFFFFF)
1306 FATAL(
"DDT overflow: media does not fit in big DDT");
1307 TRACE(
"Exiting set_ddt_single_level_v2() = false");
1313 *ddt_entry &= 0x0FFFFFFFFFFFFFFF;
1314 *ddt_entry |= (uint64_t)sector_status << 60;
1316 TRACE(
"Setting big single-level DDT entry %d to %ull", sector_address, (uint64_t)*ddt_entry);
1320 TRACE(
"Exiting set_ddt_single_level_v2() = true");
1341 uint64_t block_offset, uint8_t sector_status, uint64_t *ddt_entry)
1343 TRACE(
"Entering set_ddt_multi_level_v2(%p, %" PRIu64
", %d, %" PRIu64
", %" PRIu64
", %d)", ctx, sector_address,
1344 negative, offset, block_offset, sector_status);
1346 uint64_t items_per_ddt_entry = 0;
1347 uint64_t ddt_position = 0;
1348 uint64_t secondary_ddt_offset = 0;
1349 uint64_t block_index = 0;
1350 uint8_t *buffer = NULL;
1354 size_t written_bytes = 0;
1355 long end_of_file = 0;
1356 bool create_new_table =
false;
1361 FATAL(
"Invalid context or image stream.");
1362 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1369 FATAL(
"DDT table shift is zero, but we are in multi-level DDT setting.");
1370 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1382 ddt_position = sector_address / items_per_ddt_entry;
1399 if(*ddt_entry > 0xFFFFFFFFFFFFFFF)
1401 FATAL(
"DDT overflow: media does not fit in big DDT");
1402 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1408 *ddt_entry &= 0x0FFFFFFFFFFFFFFF;
1409 *ddt_entry |= (uint64_t)sector_status << 60;
1411 TRACE(
"Setting small secondary DDT entry %d to %ull", sector_address % items_per_ddt_entry,
1412 (uint64_t)*ddt_entry);
1416 TRACE(
"Updated cached secondary DDT entry at position %" PRIu64, sector_address % items_per_ddt_entry);
1417 TRACE(
"Exiting set_ddt_multi_level_v2() = true");
1428 TRACE(
"Current secondary DDT in memory belongs to position %" PRIu64
1429 " but requested block needs position %" PRIu64,
1443 end_of_file = end_of_file + alignment_mask & ~alignment_mask;
1457 ddt_header.
blocks = items_per_ddt_entry;
1463 ddt_header.
entries = items_per_ddt_entry;
1467 ddt_header.
length = items_per_ddt_entry *
sizeof(uint64_t);
1471 if(crc64_context == NULL)
1473 FATAL(
"Could not initialize CRC64.");
1474 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1482 ddt_header.
crc64 = crc64;
1484 uint8_t *cmp_buffer = NULL;
1495 cmp_buffer = malloc((
size_t)ddt_header.
length * 2);
1496 if(cmp_buffer == NULL)
1498 TRACE(
"Failed to allocate memory for secondary DDT v2 compression");
1509 if(dst_size == 0) dst_size = ddt_header.
length;
1513 dst_size = (size_t)ddt_header.
length * 2 * 2;
1520 ddt_header.
cmpLength = (uint32_t)dst_size;
1546 if(written_bytes != 1)
1548 FATAL(
"Could not write never-written DDT header to file.");
1549 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1559 FATAL(
"Could not write never-written DDT data to file.");
1560 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1570 new_ddt_entry.
offset = end_of_file;
1574 TRACE(
"Added new DDT index entry for never-written table at offset %" PRIu64, end_of_file);
1590 if(written_bytes != 1)
1592 FATAL(
"Could not flush primary DDT table to file after writing never-written secondary table.");
1593 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1599 ctx->
next_block_position = end_of_file + ddt_total_size + alignment_mask & ~alignment_mask;
1616 TRACE(
"Successfully wrote never-written cached secondary DDT to disk");
1620 TRACE(
"Cached DDT is for the correct block range, using it directly");
1638 end_of_file = end_of_file + alignment_mask & ~alignment_mask;
1651 ddt_header.
blocks = items_per_ddt_entry;
1653 ddt_header.
start = ddt_position * items_per_ddt_entry;
1657 ddt_header.
entries = items_per_ddt_entry;
1661 ddt_header.
length = items_per_ddt_entry *
sizeof(uint64_t);
1665 if(crc64_context == NULL)
1667 FATAL(
"Could not initialize CRC64.");
1668 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1676 ddt_header.
crc64 = crc64;
1678 uint8_t *cmp_buffer = NULL;
1689 cmp_buffer = malloc((
size_t)ddt_header.
length * 2);
1690 if(cmp_buffer == NULL)
1692 TRACE(
"Failed to allocate memory for secondary DDT v2 compression");
1703 if(dst_size == 0) dst_size = ddt_header.
length;
1707 dst_size = (size_t)ddt_header.
length * 2 * 2;
1714 ddt_header.
cmpLength = (uint32_t)dst_size;
1743 if(written_bytes != 1)
1745 FATAL(
"Could not write DDT header to file.");
1746 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1753 if(written_bytes != 1)
1755 FATAL(
"Could not write DDT data to file.");
1756 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1763 TRACE(
"Updating index for evicted secondary DDT");
1772 for(
unsigned int i = 0; i < utarray_len(ctx->
index_entries); i++)
1778 TRACE(
"Found old DDT index entry at position %u, removing", i);
1789 new_ddt_entry.
offset = end_of_file;
1793 TRACE(
"Added new DDT index entry at offset %" PRIu64, end_of_file);
1801 ctx->
user_data_ddt2[ddt_position] = new_secondary_table_block_offset;
1812 if(written_bytes != 1)
1814 FATAL(
"Could not flush primary DDT table to file.");
1815 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1821 ctx->
next_block_position = end_of_file + ddt_total_size + alignment_mask & ~alignment_mask;
1840 if(!create_new_table && secondary_ddt_offset != 0)
1849 FATAL(
"Invalid secondary DDT header at %" PRIu64, secondary_ddt_offset);
1850 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1855 buffer = malloc(ddt_header.
length);
1858 FATAL(
"Cannot allocate memory for secondary DDT.");
1859 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1864 if(read_bytes != ddt_header.
length)
1866 FATAL(
"Could not read secondary DDT data.");
1868 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1874 if(crc64_context == NULL)
1876 FATAL(
"Could not initialize CRC64.");
1878 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1886 if(crc64 != ddt_header.
crc64)
1888 FATAL(
"Secondary DDT CRC mismatch. Expected 0x%16lX but got 0x%16lX.", ddt_header.
crc64, crc64);
1890 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1901 if(create_new_table)
1904 size_t table_size = items_per_ddt_entry *
sizeof(uint64_t);
1906 buffer = calloc(1, table_size);
1909 FATAL(
"Cannot allocate memory for new secondary DDT.");
1910 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1918 TRACE(
"Created new secondary DDT for position %" PRIu64, ddt_position);
1929 if(*ddt_entry > 0xFFFFFFFFFFFFFFF)
1931 FATAL(
"DDT overflow: media does not fit in big DDT");
1932 TRACE(
"Exiting set_ddt_multi_level_v2() = false");
1938 *ddt_entry &= 0x0FFFFFFFFFFFFFFF;
1939 *ddt_entry |= (uint64_t)sector_status << 60;
1941 TRACE(
"Setting big secondary DDT entry %d to %ull", sector_address % items_per_ddt_entry, (uint64_t)*ddt_entry);
1945 TRACE(
"Updated secondary DDT entry at position %" PRIu64, sector_address % items_per_ddt_entry);
1946 TRACE(
"Exiting set_ddt_multi_level_v2() = true");
2067 const uint8_t sector_status, uint64_t *ddt_entry)
2069 TRACE(
"Entering set_ddt_tape(%p, %" PRIu64
", %llu, %llu, %d)", ctx, sector_address, offset, block_offset,
2075 FATAL(
"Invalid context or image stream.");
2076 TRACE(
"Exiting set_ddt_tape() = false");
2083 FATAL(
"Image is not tape, wrong function called.");
2084 TRACE(
"Exiting set_ddt_tape() = false");
2094 if(*ddt_entry > 0xFFFFFFFFFFFFFFF)
2096 FATAL(
"DDT overflow: media does not fit in big DDT");
2097 TRACE(
"Exiting set_ddt_tape() = false");
2101 *ddt_entry |= (uint64_t)sector_status << 60;
2107 if(new_entry == NULL)
2109 FATAL(
"Cannot allocate memory for new tape DDT hash entry.");
2110 TRACE(
"Exiting set_ddt_tape() = false");
2114 TRACE(
"Setting tape DDT entry %d to %u", sector_address, (uint32_t)*ddt_entry);
2116 new_entry->
key = sector_address;
2117 new_entry->
value = *ddt_entry;
2120 HASH_REPLACE(hh, ctx->
tape_ddt, key,
sizeof(uint64_t), new_entry, old_entry);
2122 if(old_entry) free(old_entry);
2124 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 process_ddt_v2(aaruformat_context *ctx, IndexEntry *entry, bool *found_user_data_ddt)
Processes a DDT v2 block from the image stream.
bool set_ddt_tape(aaruformat_context *ctx, uint64_t sector_address, const uint64_t offset, const uint64_t block_offset, const 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_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.
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_entry_v2(aaruformat_context *ctx, const uint64_t sector_address, const bool negative, const uint64_t offset, const uint64_t block_offset, const uint8_t sector_status, uint64_t *ddt_entry)
Sets a DDT v2 entry for a given sector address.
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.
bool set_ddt_single_level_v2(aaruformat_context *ctx, uint64_t sector_address, const bool negative, const uint64_t offset, const uint64_t block_offset, const 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, const 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.
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.
crc64_ctx * aaruf_crc64_init()
Initializes 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.
@ 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.
#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.
int32_t aaruf_close_current_block(aaruformat_context *ctx)
Finalizes and writes the current data block to the AaruFormat image file.
static int aaruf_fseek(FILE *stream, aaru_off_t offset, int origin)
static aaru_off_t aaruf_ftell(FILE *stream)
#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.
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.
Minimal ECMA-182 CRC64 incremental state container (running value only).