47static int32_t
grow_arena(uint8_t **arena,
size_t *length,
const size_t needed,
const size_t minimum)
51 size_t new_length = *length * 2;
52 if(new_length < needed) new_length = needed;
53 if(new_length < minimum) new_length = minimum;
55 uint8_t *grown = realloc(*arena, new_length);
58 memset(grown + *length, 0, new_length - *length);
73 for(
int i = 0x0C; i <= 0x0E; i++)
74 if((data[i] >> 4) > 9 || (data[i] & 0x0F) > 9)
return false;
76 const int minute = (data[0x0C] >> 4) * 10 + (data[0x0C] & 0x0F);
77 const int second = (data[0x0D] >> 4) * 10 + (data[0x0D] & 0x0F);
78 const int frame = (data[0x0E] >> 4) * 10 + (data[0x0E] & 0x0F);
80 if(second > 59 || frame > 74)
return false;
82 return (int64_t)minute * 60 * 75 + second * 75 + frame - 150 == lba;
153 const uint8_t *data, uint8_t sector_status, uint32_t length)
155 TRACE(
"Entering aaruf_write_sector(%p, %" PRIu64
", %d, %p, %u, %u)", context, sector_address, negative, data,
156 sector_status, length);
161 FATAL(
"Invalid context");
163 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_AARUFORMAT");
172 FATAL(
"Invalid context");
174 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_AARUFORMAT");
181 FATAL(
"Trying to write a read-only image");
183 TRACE(
"Exiting aaruf_write_sector() = AARUF_READ_ONLY");
190 FATAL(
"Cannot write sector to flux-only image (no user-data DDT)");
192 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_USER_DATA_NOT_PRESENT");
198 FATAL(
"Sector address out of bounds");
200 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
206 FATAL(
"Sector address out of bounds");
208 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
212 if(length > USHRT_MAX)
214 FATAL(
"Sector length too large");
216 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_INVALID_SECTOR_LENGTH");
227 TRACE(
"NGCW sector detected, disabling checksums");
236 else if(sector_address <= ctx->last_written_block)
280 !negative && sector_address <= ctx->image_info.Sectors && !ctx->
writing_long)
285 const uint8_t *write_data = data;
286 uint8_t *decrypted_buffer = NULL;
300 decrypted_buffer = (uint8_t *)malloc(length);
302 if(decrypted_buffer == NULL)
304 FATAL(
"Could not allocate memory for PS3 decryption buffer");
308 memcpy(decrypted_buffer, data, length);
310 write_data = decrypted_buffer;
317 uint64_t ddt_entry_gen = 0;
318 bool ddt_ok_gen =
set_ddt_entry_v2(ctx, sector_address, negative, 0, 0, sector_status, &ddt_entry_gen);
320 free(decrypted_buffer);
324 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_CANNOT_SET_DDT_ENTRY");
328 TRACE(
"Exiting aaruf_write_sector() = AARUF_STATUS_OK (generable)");
338 TRACE(
"Closing current block before writing new data");
343 FATAL(
"Error closing current block: %d", error);
345 TRACE(
"Exiting aaruf_write_sector() = %d", error);
350 uint64_t ddt_entry = 0;
356 TRACE(
"Hashing sector data for deduplication");
357 uint64_t hash = XXH3_64bits(write_data, length);
361 TRACE(
"Block does %s exist in deduplication map", existing ?
"already" :
"not yet");
364 sector_status, &ddt_entry);
367 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_CANNOT_SET_DDT_ENTRY");
373 TRACE(
"Sector exists, so not writing to image");
374 free(decrypted_buffer);
375 TRACE(
"Exiting aaruf_write_sector() = AARUF_STATUS_OK");
379 TRACE(
"Inserting sector hash into deduplication map, proceeding to write into image as normal");
384 sector_status, &ddt_entry);
388 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_CANNOT_SET_DDT_ENTRY");
395 TRACE(
"Creating new writing block");
405 if(sector_address >= ctx->
track_entries[i].
start && sector_address <= ctx->track_entries[i].end)
448 uint32_t max_buffer_size =
450 TRACE(
"Setting max buffer size to %u bytes", max_buffer_size);
452 TRACE(
"Allocating memory for writing buffer");
456 FATAL(
"Could not allocate memory");
458 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
470 free(decrypted_buffer);
472 TRACE(
"Exiting aaruf_write_sector() = AARUF_STATUS_OK");
683 const uint8_t *data, uint8_t sector_status, uint32_t length)
685 TRACE(
"Entering aaruf_write_sector_long(%p, %" PRIu64
", %d, %p, %u, %u)", context, sector_address, negative, data,
686 sector_status, length);
691 FATAL(
"Invalid context");
693 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_AARUFORMAT");
702 FATAL(
"Invalid context");
704 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_AARUFORMAT");
711 FATAL(
"Trying to write a read-only image");
713 TRACE(
"Exiting aaruf_write_sector() = AARUF_READ_ONLY");
720 FATAL(
"Cannot write long sector to flux-only image (no user-data DDT)");
722 TRACE(
"Exiting aaruf_write_sector_long() = AARUF_ERROR_USER_DATA_NOT_PRESENT");
728 FATAL(
"Sector address out of bounds");
730 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
736 FATAL(
"Sector address out of bounds");
738 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
749 if(sector_address >= ctx->
track_entries[i].
start && sector_address <= ctx->track_entries[i].end)
757 uint64_t corrected_sector_address = sector_address;
765 uint64_t total_sectors =
769 const int64_t signed_lba = negative ? -(int64_t)sector_address : (int64_t)sector_address;
786 memcpy(ctx->
sector_id + corrected_sector_address * 4, data, 4);
787 memcpy(ctx->
sector_ied + corrected_sector_address * 2, data + 4, 2);
788 memcpy(ctx->
sector_cpr_mai + corrected_sector_address * 6, data + 6, 6);
789 memcpy(ctx->
sector_edc + corrected_sector_address * 4, data + 2060, 4);
791 return aaruf_write_sector(context, sector_address, negative, data + 12, sector_status, 2048);
802 memcpy(ctx->
sector_id + corrected_sector_address * 4, data, 4);
803 memcpy(ctx->
sector_ied + corrected_sector_address * 2, data + 4, 2);
804 memcpy(ctx->
sector_cpr_mai + corrected_sector_address * 6, data + 2054, 6);
805 memcpy(ctx->
sector_edc + corrected_sector_address * 4, data + 2060, 4);
807 return aaruf_write_sector(context, sector_address, negative, data + 6, sector_status, 2048);
819 memcpy(ctx->
sector_edc + corrected_sector_address * 4, data + 2048, 4);
821 return aaruf_write_sector(context, sector_address, negative, data, sector_status, 2048);
826 FATAL(
"Incorrect sector size");
827 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_INCORRECT_DATA_SIZE");
835 if(sector_address <= ctx->last_written_block)
861 if(ctx->
calculating_md5 && !negative && sector_address <= ctx->image_info.Sectors)
864 if(ctx->
calculating_sha1 && !negative && sector_address <= ctx->image_info.Sectors)
883 return aaruf_write_sector(context, sector_address, negative, data, sector_status, length);
895 FATAL(
"Could not allocate memory for CD sector prefix DDT");
897 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
911 FATAL(
"Could not allocate memory for CD sector prefix DDT");
913 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
926 FATAL(
"Could not allocate memory for CD sector prefix buffer");
928 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
942 FATAL(
"Could not allocate memory for CD sector suffix buffer");
944 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
951 for(
int i = 0; i < length; i++)
968 prefix_correct =
true;
970 if(data[0x00] != 0x00 || data[0x01] != 0xFF || data[0x02] != 0xFF || data[0x03] != 0xFF ||
971 data[0x04] != 0xFF || data[0x05] != 0xFF || data[0x06] != 0xFF || data[0x07] != 0xFF ||
972 data[0x08] != 0xFF || data[0x09] != 0xFF || data[0x0A] != 0xFF || data[0x0B] != 0x00 ||
974 prefix_correct =
false;
986 FATAL(
"Could not allocate memory for CD sector prefix buffer");
988 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1010 FATAL(
"Could not allocate memory for CD sector suffix buffer");
1012 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1040 FATAL(
"Could not allocate memory for CD sector prefix DDT");
1042 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1056 FATAL(
"Could not allocate memory for CD sector prefix DDT");
1058 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1071 FATAL(
"Could not allocate memory for CD sector prefix buffer");
1073 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1087 FATAL(
"Could not allocate memory for CD sector suffix buffer");
1089 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1096 for(
int i = 0; i < length; i++)
1113 const bool form2 = (data[18] & 0x20) == 0x20 || (data[22] & 0x20) == 0x20;
1115 prefix_correct =
true;
1117 if(data[0x00] != 0x00 || data[0x01] != 0xFF || data[0x02] != 0xFF || data[0x03] != 0xFF ||
1118 data[0x04] != 0xFF || data[0x05] != 0xFF || data[0x06] != 0xFF || data[0x07] != 0xFF ||
1119 data[0x08] != 0xFF || data[0x09] != 0xFF || data[0x0A] != 0xFF || data[0x0B] != 0x00 ||
1121 prefix_correct =
false;
1134 FATAL(
"Could not allocate memory for CD sector prefix buffer");
1136 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1156 FATAL(
"Could not allocate memory for CD mode 2 subheader buffer");
1158 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1167 memcpy(&edc, data + 0x92C,
sizeof(edc));
1168 const bool correct_edc = computed_edc == edc;
1182 FATAL(
"Could not allocate memory for CD sector suffix buffer");
1184 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1198 memcpy(ctx->
mode2_subheaders + corrected_sector_address * 8, data + 0x10, 8);
1212 memcpy(&edc, data + 0x818,
sizeof(edc));
1213 const bool correct_edc = computed_edc == edc;
1215 if(correct_ecc && correct_edc)
1223 FATAL(
"Could not allocate memory for CD sector suffix buffer");
1225 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1238 memcpy(ctx->
mode2_subheaders + corrected_sector_address * 8, data + 0x10, 8);
1243 context, sector_address, negative, data + 24,
1262 switch(length - 512)
1284 newTag = malloc(12);
1285 memcpy(newTag, data + 512, 12);
1297 newTag = malloc(20);
1298 memcpy(newTag, data + 512, 20);
1328 newTag = malloc(24);
1329 memcpy(newTag, data + 512, 24);
1345 FATAL(
"Incorrect sector size");
1346 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1351 return aaruf_write_sector(context, sector_address, negative, data, sector_status, 512);
1360 FATAL(
"Could not allocate memory for sector subchannel DDT");
1364 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1369 memcpy(ctx->
sector_subchannel + sector_address * newTagSize, newTag, newTagSize);
1373 return aaruf_write_sector(context, sector_address, negative, data, sector_status, 512);
1379 TRACE(
"Exiting aaruf_write_sector() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1579 TRACE(
"Initializing CRC64 context");
1581 TRACE(
"Updating CRC64");
1586 uint8_t *cmp_buffer = NULL;
1594 if(cmp_buffer == NULL)
1596 FATAL(
"Could not allocate buffer for compressed data");
1605 const long remaining = current_samples % flac_block_size;
1613 flac_block_size,
true,
false,
"hamming", 12, 15,
true,
false, 0, 8,
"Aaru", 4);
1624 if(cmp_buffer == NULL)
1626 FATAL(
"Could not allocate buffer for compressed data");
1646 if(cmp_buffer == NULL)
1648 FATAL(
"Could not allocate buffer for compressed data");
1652 size_t zstd_dst_size =
1656 if(zstd_dst_size == 0)
1678 FATAL(
"Invalid compression type");
1694 TRACE(
"Adding block to index");
1702 TRACE(
"Block added to index at offset %" PRIu64, index_entry.
offset);
1743 const uint8_t *ec_payload;
1744 uint32_t ec_payload_size;
1745 const uint8_t *ec_lzma_props = NULL;
1754 ec_payload = cmp_buffer;
1756 ec_lzma_props = lzma_properties;
1760 ec_payload = cmp_buffer;
1765 ec_payload, ec_payload_size, index_entry.
offset);
2037 const uint32_t length)
2039 TRACE(
"Entering aaruf_write_media_tag(%p, %p, %d, %d)", context, data, type, length);
2044 FATAL(
"Invalid context");
2046 TRACE(
"Exiting aaruf_write_media_tag() = AARUF_ERROR_NOT_AARUFORMAT");
2055 FATAL(
"Invalid context");
2057 TRACE(
"Exiting aaruf_write_media_tag() = AARUF_ERROR_NOT_AARUFORMAT");
2064 FATAL(
"Trying to write a read-only image");
2066 TRACE(
"Exiting aaruf_write_media_tag() = AARUF_READ_ONLY");
2070 if(data == NULL || length == 0)
2072 FATAL(
"Invalid data or length");
2076 uint8_t *new_data = malloc(length);
2078 if(new_data == NULL)
2080 FATAL(
"Could not allocate memory for media tag");
2083 memcpy(new_data, data, length);
2088 if(media_tag == NULL)
2090 TRACE(
"Cannot allocate memory for media tag entry.");
2097 media_tag->
type = type;
2098 media_tag->
data = new_data;
2099 media_tag->
length = length;
2101 HASH_REPLACE_INT(ctx->
mediaTags, type, media_tag, old_media_tag);
2103 if(old_media_tag != NULL)
2105 TRACE(
"Replaced media tag with type %d", old_media_tag->
type);
2106 free(old_media_tag->
data);
2107 free(old_media_tag);
2108 old_media_tag = NULL;
2112 TRACE(
"Exiting aaruf_write_media_tag() = AARUF_STATUS_OK");
2307 const uint8_t *data,
const size_t length,
const int32_t tag)
2309 TRACE(
"Entering aaruf_write_sector_tag(%p, %" PRIu64
", %d, %p, %zu, %d)", context, sector_address, negative, data,
2315 FATAL(
"Invalid context");
2317 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_AARUFORMAT");
2326 FATAL(
"Invalid context");
2328 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_AARUFORMAT");
2335 FATAL(
"Trying to write a read-only image");
2337 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_READ_ONLY");
2344 FATAL(
"Cannot write sector tag to flux-only image (no user-data DDT)");
2346 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_USER_DATA_NOT_PRESENT");
2352 FATAL(
"Sector address out of bounds");
2354 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
2360 FATAL(
"Sector address out of bounds");
2362 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
2366 if(data == NULL || length == 0)
2368 FATAL(
"Invalid data or length");
2372 uint64_t corrected_sector_address = sector_address;
2380 const uint64_t total_sectors =
2388 FATAL(
"Invalid media type for tag");
2389 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2395 FATAL(
"Incorrect tag size");
2396 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2401 if(sector_address >= ctx->
track_entries[i].
start && sector_address <= ctx->track_entries[i].end)
2405 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2409 FATAL(
"Track not found");
2414 FATAL(
"Invalid media type for tag");
2415 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2421 FATAL(
"Incorrect tag size");
2422 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2427 if(sector_address >= ctx->
track_entries[i].
start && sector_address <= ctx->track_entries[i].end)
2431 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2435 FATAL(
"Track not found");
2440 FATAL(
"Invalid media type for tag");
2441 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2447 FATAL(
"Incorrect tag size");
2448 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2456 FATAL(
"Could not allocate memory for sector subchannel");
2458 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
2464 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2469 FATAL(
"Invalid media type for tag");
2470 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2476 FATAL(
"Incorrect tag size");
2477 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2485 FATAL(
"Could not allocate memory for sector CPR/MAI");
2487 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
2491 memcpy(ctx->
sector_cpr_mai + corrected_sector_address * 6, data, 1);
2493 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2498 FATAL(
"Invalid media type for tag");
2499 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2505 FATAL(
"Incorrect tag size");
2506 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2514 FATAL(
"Could not allocate memory for sector ID");
2516 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
2520 memcpy(ctx->
sector_id + corrected_sector_address * 4, data, 1);
2521 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2526 FATAL(
"Invalid media type for tag");
2527 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2533 FATAL(
"Incorrect tag size");
2534 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2542 FATAL(
"Could not allocate memory for sector ID");
2544 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
2548 memcpy(ctx->
sector_id + corrected_sector_address * 4 + 1, data, 3);
2550 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2555 FATAL(
"Invalid media type for tag");
2556 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2562 FATAL(
"Incorrect tag size");
2563 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2571 FATAL(
"Could not allocate memory for sector IED");
2573 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
2577 memcpy(ctx->
sector_ied + corrected_sector_address * 2, data, 2);
2579 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2584 FATAL(
"Invalid media type for tag");
2585 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2591 FATAL(
"Incorrect tag size");
2592 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2600 FATAL(
"Could not allocate memory for sector EDC");
2602 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
2606 memcpy(ctx->
sector_edc + corrected_sector_address * 4, data, 4);
2608 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2613 FATAL(
"Invalid media type for tag");
2614 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2620 FATAL(
"Incorrect tag size");
2621 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2629 FATAL(
"Could not allocate memory for sector decrypted title key");
2631 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
2637 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2642 FATAL(
"Invalid media type for tag");
2643 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2649 FATAL(
"Incorrect tag size");
2650 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2658 FATAL(
"Could not allocate memory for Apple Sony tag");
2660 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
2666 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2671 FATAL(
"Invalid media type for tag");
2672 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2678 FATAL(
"Incorrect tag size");
2679 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2687 FATAL(
"Could not allocate memory for Apple Profile tag");
2689 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
2695 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2700 FATAL(
"Invalid media type for tag");
2701 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2707 FATAL(
"Incorrect tag size");
2708 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2716 FATAL(
"Could not allocate memory for Priam Data Tower tag");
2718 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
2724 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2729 FATAL(
"Invalid media type for tag");
2730 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
2736 FATAL(
"Incorrect tag size");
2737 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
2745 FATAL(
"Could not allocate memory for Blu-ray sector EDC");
2747 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
2751 memcpy(ctx->
sector_edc + corrected_sector_address * 4, data, 4);
2753 TRACE(
"Exiting aaruf_write_sector_tag() = AARUF_STATUS_OK");
2756 TRACE(
"Do not know how to write sector tag %d", tag);
#define MAX_FLAKE_BLOCK
FLAC maximum block size used for encoding audio sectors.
#define LZMA_PROPERTIES_LENGTH
Size in bytes of the fixed LZMA properties header (lc/lp/pb + dictionary size).
#define AARU_MAGIC
Magic identifier for AaruFormat container (ASCII "AARUFRMT").
#define MIN_FLAKE_BLOCK
FLAC minimum block size.
#define SAMPLES_PER_SECTOR
Red Book (CD‑DA) PCM samples per 2352‑byte sector: 44,100 Hz / 75 sectors per second = 588 samples.
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)
size_t aaruf_flac_encode_redbook_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer, size_t src_size, uint32_t blocksize, int32_t do_mid_side_stereo, int32_t loose_mid_side_stereo, const char *apodization, uint32_t max_lpc_order, uint32_t qlp_coeff_precision, int32_t do_qlp_coeff_prec_search, int32_t do_exhaustive_model_search, uint32_t min_residual_partition_order, uint32_t max_residual_partition_order, const char *application_id, uint32_t application_id_len)
Encodes a Red Book audio buffer to FLAC format.
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.
int32_t aaruf_write_sector(void *context, uint64_t sector_address, bool negative, const uint8_t *data, uint8_t sector_status, uint32_t length)
Writes a sector to the AaruFormat image.
int aaruf_spamsum_update(spamsum_ctx *ctx, const uint8_t *data, uint32_t len)
Updates the spamsum context with new data.
uint32_t aaruf_edc_cd_compute(void *context, uint32_t edc, const uint8_t *src, int size, int pos)
Computes the EDC (Error Detection Code) for a CD sector.
int32_t aaruf_write_sector_long(void *context, uint64_t sector_address, bool negative, const uint8_t *data, uint8_t sector_status, uint32_t length)
Writes a full ("long") raw sector from optical or block media, parsing structure and validating conte...
int32_t aaruf_write_sector_tag(void *context, uint64_t sector_address, bool negative, const uint8_t *data, size_t length, int32_t tag)
Writes per-sector tag data (auxiliary metadata) for a specific sector.
void aaruf_md5_update(md5_ctx *ctx, const void *data, unsigned long size)
int32_t aaruf_write_media_tag(void *context, const uint8_t *data, int32_t type, uint32_t length)
Writes a media tag to the AaruFormat image, storing medium-specific metadata and descriptors.
void aaruf_sha256_update(sha256_ctx *ctx, const void *data, unsigned long size)
bool aaruf_ecc_cd_is_suffix_correct_mode2(void *context, const uint8_t *sector)
Checks if the suffix (EDC/ECC) of a CD sector is correct (Mode 2).
void aaruf_sha1_update(sha1_ctx *ctx, const void *data, unsigned long size)
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.
bool aaruf_ecc_cd_is_suffix_correct(void *context, const uint8_t *sector)
Checks if the suffix (EDC/ECC) of a CD sector is correct (Mode 1).
@ DataBlock
Block containing data.
@ SectorStatusNotDumped
Sector(s) not yet acquired during image dumping.
@ SectorStatusGenerable
Content can be generated using a known algorithm.
@ SectorStatusUnencrypted
Content originally encrypted but stored decrypted in image.
@ SectorStatusMode2Form2NoCrc
Suffix matches MODE 2 Form 2 but CRC empty/missing.
@ SectorStatusMode1Correct
Valid MODE 1 data with regenerable suffix/prefix.
@ SectorStatusMode2Form2Ok
Suffix matches MODE 2 Form 2 with valid CRC.
@ SectorStatusErrored
Error during dumping; data may be incomplete or corrupt.
@ SectorStatusMode2Form1Ok
Suffix verified/regenerable for MODE 2 Form 1.
@ OpticalDisc
Purely optical discs.
@ BlockMedia
Media that is physically block-based or abstracted like that.
@ kTrackTypeCdMode2Form2
Compact Disc Mode 2 Form 2 data track.
@ kTrackTypeData
Generic data track (not further specified).
@ kTrackTypeCdMode2Form1
Compact Disc Mode 2 Form 1 data track.
@ kTrackTypeAudio
Audio track.
@ kTrackTypeCdMode2Formless
Compact Disc Mode 2 (formless) data track.
@ kTrackTypeCdMode1
Compact Disc Mode 1 data track.
@ kDataTypeUserData
User (main) data.
@ kCompressionLzma
LZMA compression.
@ kCompressionNone
Not compressed.
@ kCompressionZstd
Zstandard compression.
@ kCompressionFlac
FLAC compression.
void ec_accumulate_data_block(aaruformat_context *ctx, const BlockHeader *block_header, const uint8_t *lzma_props, const uint8_t *payload, uint32_t payload_size, uint64_t file_offset)
Accumulate parity for a data block that was just written to disk.
#define AARUF_ERROR_CANNOT_WRITE_BLOCK_DATA
Failure writing block payload.
#define AARUF_STATUS_OK
Sector present and read without uncorrectable errors.
#define AARUF_READ_ONLY
Operation requires write mode but context is read-only.
#define AARUF_ERROR_INCORRECT_MEDIA_TYPE
Operation incompatible with image media type.
#define AARUF_ERROR_USER_DATA_NOT_PRESENT
Image has no user-data DDT (e.g. flux-only image); sector data is unavailable.
#define AARUF_ERROR_TRACK_NOT_FOUND
Referenced track number not present.
#define AARUF_ERROR_NOT_ENOUGH_MEMORY
Memory allocation failure (critical).
#define AARUF_ERROR_SECTOR_OUT_OF_BOUNDS
Requested logical sector outside media bounds.
#define AARUF_ERROR_INCORRECT_DATA_SIZE
Data size does not match expected size.
#define AARUF_ERROR_CANNOT_SET_DDT_ENTRY
Failed to encode/store a DDT entry (overflow or IO).
#define AARUF_ERROR_NOT_AARUFORMAT
Input file/stream failed magic or structural validation.
#define AARUF_ERROR_INVALID_TAG
Invalid or unsupported media or sector tag format.
#define AARUF_ERROR_INVALID_SECTOR_LENGTH
Sector length is too big.
#define AARUF_ERROR_CANNOT_WRITE_BLOCK_HEADER
Failure writing block header.
bool lookup_map(const hash_map_t *map, uint64_t key, uint64_t *out_value)
Looks up a value by key in the hash map.
bool insert_map(hash_map_t *map, uint64_t key, uint64_t value)
Inserts a key-value pair into the hash map.
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 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)
#define LZMA_THREADS(ctx)
Clamp num_threads to LZMA's valid range [1, 2].
Structure definitions and conversion/serialization function declarations for Lisa family disk tags.
uint8_t * priam_tag_to_bytes(priam_tag tag)
Serialize a priam_tag into a newly allocated 24-byte big-endian on-disk representation.
priam_tag bytes_to_priam_tag(const uint8_t *bytes)
Parse a 24-byte Priam tag record into a priam_tag structure.
sony_tag profile_tag_to_sony(profile_tag tag)
Convert a profile_tag to a sony_tag.
uint8_t * sony_tag_to_bytes(sony_tag tag)
Serialize a sony_tag into a newly allocated 12-byte big-endian on-disk representation.
profile_tag priam_tag_to_profile(priam_tag tag)
Convert a priam_tag to a profile_tag.
uint8_t * profile_tag_to_bytes(profile_tag tag)
Serialize a profile_tag into a newly allocated 20-byte big-endian on-disk representation.
profile_tag sony_tag_to_profile(sony_tag tag)
Convert a sony_tag to a profile_tag representation.
sony_tag bytes_to_sony_tag(const uint8_t *bytes)
Parse a 12-byte Sony tag record into a sony_tag structure.
profile_tag bytes_to_profile_tag(const uint8_t *bytes)
Parse a 20-byte Profile tag record into a profile_tag structure.
priam_tag sony_tag_to_priam(sony_tag tag)
Convert a sony_tag to a priam_tag representation.
priam_tag profile_tag_to_priam(profile_tag tag)
Convert a profile_tag to a priam_tag.
sony_tag priam_tag_to_sony(priam_tag tag)
Convert a priam_tag to a sony_tag.
void ps3_lazy_init(aaruformat_context *ctx)
Lazy-initialize PS3 encryption state from context media tags.
void ps3_decrypt_sector(const uint8_t disc_key[16], uint64_t sector_num, uint8_t *data, uint32_t length)
Decrypt a sector using PS3 disc encryption (AES-128-CBC).
bool ps3_is_sector_encrypted(const Ps3PlaintextRegion *plaintext_regions, uint32_t region_count, uint64_t sector_address)
Check whether a sector is encrypted (i.e., not in any plaintext region).
uint32_t MediaType
Media type identifier (see MediaType enum; 0=Unknown).
uint8_t MetadataMediaType
Media type for sidecar generation (internal archival use).
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.
A plaintext (unencrypted) region on a PS3 disc.
Single optical disc track descriptor (sequence, type, LBAs, session, ISRC, flags).
uint8_t session
Session number (1-based). 1 for single-session discs.
uint8_t flags
Control / attribute bitfield (see file documentation for suggested bit mapping).
int64_t end
Inclusive ending LBA of the track.
uint8_t sequence
Track number (1..99 typical for CD audio/data).
int64_t start
Inclusive starting LBA of the track.
uint8_t type
Track type (value from TrackType).
uint8_t isrc[13]
ISRC raw 13-byte code (no null terminator). All zeros if not present.
Master context representing an open or in‑creation Aaru image.
uint8_t * ps3_disc_key
Cached disc key (16 bytes), NULL if not loaded.
DdtHeader2 user_data_ddt_header
Active user data DDT v2 header (primary table meta).
bool dirty_checksum_block
True if checksum block should be written during close.
bool deduplicate
Storage deduplication active (duplicates coalesce).
size_t sector_suffix_length
Length of sector_suffix.
bool compression_enabled
True if block compression enabled (writing path).
uint64_t last_written_block
Last written block number (write path).
uint8_t * sector_cpr_mai
DVD sector CPR_MAI (6 bytes) if present.
bool dirty_media_tags
True if media tags should be written during close.
hash_map_t * sector_hash_map
Deduplication hash map (fingerprint->entry mapping).
uint32_t ps3_plaintext_region_count
Number of plaintext regions.
sha256_ctx sha256_context
Opaque SHA-256 context for streaming updates.
bool calculating_sha256
True if whole-image SHA-256 being calculated on-the-fly.
uint8_t * sector_ied
DVD sector IED (2 bytes) if present.
md5_ctx md5_context
Opaque MD5 context for streaming updates.
bool dirty_sector_suffix_block
True if sector suffix block should be written during close.
uint8_t * sector_prefix
Raw per-sector prefix (e.g., sync+header) uncorrected.
bool dirty_dvd_title_key_decrypted_block
True if decrypted title key block should be written during close.
uint64_t * sector_suffix_ddt2
CD sector suffix DDT V2.
bool dirty_mode2_subheaders_block
True if MODE2 subheader block should be written during close.
uint8_t * sector_edc
DVD or Blu-ray sector EDC (4 bytes) if present (see DvdSectorEdc / BdSectorEdc data types).
bool calculating_sha1
True if whole-image SHA-1 being calculated on-the-fly.
bool dirty_tracks_block
True if tracks block should be written during close.
CdEccContext * ecc_cd_context
CD ECC/EDC helper tables (allocated on demand).
bool rewinded
True if stream has been rewound after open (write path).
bool ps3_encryption_initialized
Whether lazy init has occurred.
bool dirty_sector_prefix_block
True if sector prefix block should be written during close.
bool dirty_index_block
True if index block should be written during close.
uint8_t * sector_suffix
Raw per-sector suffix (EDC/ECC) uncorrected.
AaruHeaderV2 header
Parsed container header (v2).
int current_block_offset
Logical offset inside block (units: bytes or sectors depending on path).
bool is_writing
True if context opened/created for writing.
spamsum_ctx * spamsum_context
Opaque SpamSum context for streaming updates.
size_t sector_prefix_offset
Current position in sector_prefix.
BlockHeader current_block_header
Header for block currently being assembled (write path).
uint64_t magic
File magic (AARU_MAGIC) post-open.
uint8_t * writing_buffer
Accumulation buffer for current block data.
uint64_t * sector_prefix_ddt2
CD sector prefix DDT V2.
bool calculating_spamsum
True if whole-image SpamSum being calculated on-the-fly.
size_t sector_prefix_length
Length of sector_prefix.
mediaTagEntry * mediaTags
Hash table of extra media tags (uthash root).
blake3_hasher * blake3_context
Opaque BLAKE3 context for streaming updates.
bool calculating_blake3
True if whole-image BLAKE3 being calculated on-the-fly.
uint64_t next_block_position
Absolute file offset where next block will be written.
bool calculating_md5
True if whole-image MD5 being calculated on-the-fly.
bool dirty_sector_suffix_ddt
True if sector suffix DDT should be written during close.
size_t sector_suffix_offset
Current position in sector_suffix.
bool has_zstd_blocks
True if any block was actually written with Zstandard compression.
int zstd_level
Zstandard compression level (writing path, default 19).
uint8_t * sector_decrypted_title_key
DVD decrypted title key (5 bytes) if present.
int writing_buffer_position
Current size / position within writingBuffer.
bool block_zero_written
True if block zero has been written (writing path).
crc64_ctx * crc64_context
Opaque CRC64 context for streaming updates.
uint8_t * sector_subchannel
Raw 96-byte subchannel (if captured).
bool dirty_sector_subchannel_block
True if subchannel block should be written during close.
FILE * imageStream
Underlying FILE* stream (binary mode).
bool dirty_dvd_long_sector_blocks
True if DVD long sector blocks should be written during close.
bool no_user_data_ddt
True if image intentionally has no user-data DDT (e.g. flux-only image). When set,...
bool dirty_sector_prefix_ddt
True if sector prefix DDT should be written during close.
UT_array * index_entries
Flattened index entries (UT_array of IndexEntry).
int num_threads
Compression worker threads (1 = single-threaded, default).
bool ec_enabled
True if erasure coding is active.
uint8_t * mode2_subheaders
MODE2 Form1/Form2 8-byte subheaders (concatenated).
bool dirty_bd_sector_edc_block
True if Blu-ray sector EDC data block should be written during close.
ImageInfo image_info
Exposed high-level image info summary.
uint8_t * sector_id
DVD sector ID (4 bytes) if present.
void * ps3_plaintext_regions
Parsed Ps3PlaintextRegion array (max 32), NULL if not loaded.
bool use_zstd
Use Zstandard instead of LZMA for data blocks.
sha1_ctx sha1_context
Opaque SHA-1 context for streaming updates.
uint32_t lzma_dict_size
LZMA dictionary size (writing path).
TrackEntry * track_entries
Full track list (tracksHeader.entries elements).
uint8_t current_track_type
Current track type (when writing optical images with tracks, needed for block compression type).
bool writing_long
True if writing long sectors.
TracksHeader tracks_header
Tracks header (optical) if present.
Hash table entry for an arbitrary media tag (e.g., proprietary drive/medium descriptor).
uint8_t * data
Tag data blob (opaque to library core); length bytes long.
int32_t type
Numeric type identifier.
uint32_t length
Length in bytes of data.
static int32_t grow_arena(uint8_t **arena, size_t *length, const size_t needed, const size_t minimum)
Ensures a CD sector prefix/suffix arena can hold needed bytes, growing it if required.
static bool cd_header_matches_lba(const uint8_t *data, const int64_t lba)
Checks whether a CD sector header (bytes 0x0C-0x0E) is valid BCD and encodes exactly lba.