libaaruformat 1.0
Aaru Data Preservation Suite - Format Library
Loading...
Searching...
No Matches
read.c
Go to the documentation of this file.
1/*
2 * This file is part of the Aaru Data Preservation Suite.
3 * Copyright (c) 2019-2025 Natalia Portillo.
4 *
5 * This library is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as
7 * published by the Free Software Foundation; either version 2.1 of the
8 * License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdlib.h>
20#include <string.h>
21
22#include <aaruformat.h>
23
24#include "internal.h"
25#include "log.h"
26
85int32_t aaruf_read_media_tag(void *context, uint8_t *data, const int32_t tag, uint32_t *length)
86{
87 const uint32_t initial_length = length == NULL ? 0U : *length;
88
89 TRACE("Entering aaruf_read_media_tag(%p, %p, %d, %u)", context, data, tag, initial_length);
90
91 mediaTagEntry *item;
92
93 if(context == NULL)
94 {
95 FATAL("Invalid context");
96 TRACE("Exiting aaruf_read_media_tag() = AARUF_ERROR_NOT_AARUFORMAT");
98 }
99
100 if(length == NULL)
101 {
102 FATAL("Invalid length pointer");
103 TRACE("Exiting aaruf_read_media_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
105 }
106
107 const aaruformat_context *ctx = context;
108
109 // Not a libaaruformat context
110 if(ctx->magic != AARU_MAGIC)
111 {
112 FATAL("Invalid context");
113 TRACE("Exiting aaruf_read_media_tag() = AARUF_ERROR_NOT_AARUFORMAT");
115 }
116
117 TRACE("Finding media tag %d", tag);
118 HASH_FIND_INT(ctx->mediaTags, &tag, item);
119
120 if(item == NULL)
121 {
122 TRACE("Media tag not found");
123 *length = 0;
124
125 TRACE("Exiting aaruf_read_media_tag() = AARUF_ERROR_MEDIA_TAG_NOT_PRESENT");
127 }
128
129 if(data == NULL || *length < item->length)
130 {
131 TRACE("Buffer too small for media tag %d, required %u bytes", tag, item->length);
132 *length = item->length;
133
134 TRACE("Exiting aaruf_read_media_tag() = AARUF_ERROR_BUFFER_TOO_SMALL");
136 }
137
138 *length = item->length;
139 memcpy(data, item->data, item->length);
140
141 TRACE("Media tag %d read successfully, length %u", tag, *length);
142 TRACE("Exiting aaruf_read_media_tag() = AARUF_STATUS_OK");
143 return AARUF_STATUS_OK;
144}
145
250int32_t aaruf_read_sector(void *context, const uint64_t sector_address, bool negative, uint8_t *data, uint32_t *length)
251{
252 const uint32_t initial_length = length == NULL ? 0U : *length;
253
254 TRACE("Entering aaruf_read_sector(%p, %" PRIu64 ", %d, %p, %u)", context, sector_address, negative, data,
255 initial_length);
256
257 aaruformat_context *ctx = NULL;
258 uint64_t offset = 0;
259 uint64_t block_offset = 0;
260 BlockHeader *block_header = NULL;
261 uint8_t *block = NULL;
262 size_t read_bytes = 0;
263 uint8_t lzma_properties[LZMA_PROPERTIES_LENGTH];
264 size_t lzma_size = 0;
265 uint8_t *cmp_data = NULL;
266 int error_no = 0;
267 uint8_t sector_status = 0;
268
269 if(context == NULL)
270 {
271 FATAL("Invalid context");
272
273 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_AARUFORMAT");
275 }
276
277 ctx = context;
278
279 if(length == NULL)
280 {
281 FATAL("Invalid length pointer");
282
283 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_INCORRECT_DATA_SIZE");
285 }
286
287 // Not a libaaruformat context
288 if(ctx->magic != AARU_MAGIC)
289 {
290 FATAL("Invalid context");
291
292 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_AARUFORMAT");
294 }
295
296 if(negative && sector_address > ctx->user_data_ddt_header.negative - 1)
297 {
298 FATAL("Sector address out of bounds");
299
300 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
302 }
303
304 if(!negative && sector_address > ctx->image_info.Sectors + ctx->user_data_ddt_header.overflow - 1)
305 {
306 FATAL("Sector address out of bounds");
307
308 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
310 }
311
312 if(ctx->ddt_version == 1)
313 {
314 if(negative)
315 {
316 FATAL("Negative sector addresses not supported in this image");
318 }
319
320 error_no = decode_ddt_entry_v1(ctx, sector_address, &offset, &block_offset, &sector_status);
321 }
322 else if(ctx->ddt_version == 2)
323 error_no = decode_ddt_entry_v2(ctx, sector_address, negative, &offset, &block_offset, &sector_status);
324
325 if(error_no != AARUF_STATUS_OK)
326 {
327 FATAL("Error %d decoding DDT entry", error_no);
328
329 TRACE("Exiting aaruf_read_sector() = %d", error_no);
330 return error_no;
331 }
332
333 // Partially written image... as we can't know the real sector size just assume it's common :/
334 if(sector_status == SectorStatusNotDumped)
335 {
336 *length = ctx->image_info.SectorSize;
337
338 TRACE("Exiting aaruf_read_sector() = AARUF_STATUS_SECTOR_NOT_DUMPED");
340 }
341
342 // Check if block header is cached
343 TRACE("Checking if block header is cached");
344 block_header = find_in_cache_uint64(&ctx->block_header_cache, block_offset);
345
346 // Read block header
347 if(block_header == NULL)
348 {
349 TRACE("Allocating memory for block header");
350 block_header = malloc(sizeof(BlockHeader));
351 if(block_header == NULL)
352 {
353 FATAL("Not enough memory for block header");
354
355 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
357 }
358
359 TRACE("Reading block header");
360 if(fseek(ctx->imageStream, block_offset, SEEK_SET) != 0)
361 {
362 FATAL("Could not seek to block header");
363 free(block_header);
364
365 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_READ_HEADER");
367 }
368
369 read_bytes = fread(block_header, 1, sizeof(BlockHeader), ctx->imageStream);
370
371 if(read_bytes != sizeof(BlockHeader))
372 {
373 FATAL("Error reading block header");
374 free(block_header);
375
376 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_READ_HEADER");
378 }
379
380 TRACE("Adding block header to cache");
381 add_to_cache_uint64(&ctx->block_header_cache, block_offset, block_header);
382 }
383 else if(fseek(ctx->imageStream, block_offset + sizeof(BlockHeader), SEEK_SET) != 0)
384 {
385 FATAL("Could not seek past cached block header");
386
387 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_READ_HEADER");
389 }
390
391 if(data == NULL || *length < block_header->sectorSize)
392 {
393 TRACE("Buffer too small for sector, required %u bytes", block_header->sectorSize);
394 *length = block_header->sectorSize;
395
396 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_BUFFER_TOO_SMALL");
398 }
399
400 // Check if block is cached
401 TRACE("Checking if block is cached");
402 block = find_in_cache_uint64(&ctx->block_cache, block_offset);
403
404 if(block != NULL)
405 {
406 TRACE("Getting data from cache");
407 memcpy(data, block + offset * block_header->sectorSize, block_header->sectorSize);
408 *length = block_header->sectorSize;
409
410 TRACE("Exiting aaruf_read_sector() = AARUF_STATUS_OK");
411 return AARUF_STATUS_OK;
412 }
413
414 // Decompress block
415 switch(block_header->compression)
416 {
417 case None:
418 TRACE("Allocating memory for block");
419 block = (uint8_t *)malloc(block_header->length);
420 if(block == NULL)
421 {
422 FATAL("Not enough memory for block");
423
424 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
426 }
427
428 TRACE("Reading block into memory");
429 read_bytes = fread(block, 1, block_header->length, ctx->imageStream);
430
431 if(read_bytes != block_header->length)
432 {
433 FATAL("Could not read block");
434 free(block);
435
436 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_READ_BLOCK");
438 }
439
440 break;
441 case Lzma:
442 if(block_header->cmpLength <= LZMA_PROPERTIES_LENGTH || block_header->length == 0)
443 {
444 FATAL("Invalid LZMA block lengths (cmpLength=%u, length=%u)", block_header->cmpLength,
445 block_header->length);
446
447 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
449 }
450
451 lzma_size = block_header->cmpLength - LZMA_PROPERTIES_LENGTH;
452 TRACE("Allocating memory for compressed data of size %zu bytes", lzma_size);
453 cmp_data = malloc(lzma_size);
454
455 if(cmp_data == NULL)
456 {
457 FATAL("Cannot allocate memory for block...");
458
459 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
461 }
462
463 TRACE("Allocating memory for block of size %zu bytes", block_header->length);
464 block = malloc(block_header->length);
465 if(block == NULL)
466 {
467 FATAL("Cannot allocate memory for block...");
468 free(cmp_data);
469
470 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
472 }
473
474 read_bytes = fread(lzma_properties, 1, LZMA_PROPERTIES_LENGTH, ctx->imageStream);
475
476 if(read_bytes != LZMA_PROPERTIES_LENGTH)
477 {
478 FATAL("Could not read LZMA properties...");
479 free(block);
480 free(cmp_data);
481
482 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
484 }
485
486 read_bytes = fread(cmp_data, 1, lzma_size, ctx->imageStream);
487 if(read_bytes != lzma_size)
488 {
489 FATAL("Could not read compressed block...");
490 free(cmp_data);
491 free(block);
492
493 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
495 }
496
497 TRACE("Decompressing block of size %zu bytes", block_header->length);
498 read_bytes = block_header->length;
499 error_no = aaruf_lzma_decode_buffer(block, &read_bytes, cmp_data, &lzma_size, lzma_properties,
501
502 if(error_no != 0)
503 {
504 FATAL("Got error %d from LZMA...", error_no);
505 free(cmp_data);
506 free(block);
507
508 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
510 }
511
512 if(read_bytes != block_header->length)
513 {
514 FATAL("Error decompressing block, should be {0} bytes but got {1} bytes...");
515 free(cmp_data);
516 free(block);
517
518 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
520 }
521
522 free(cmp_data);
523
524 break;
525 case Flac:
526 TRACE("Allocating memory for compressed data of size %zu bytes", block_header->cmpLength);
527 cmp_data = malloc(block_header->cmpLength);
528
529 if(cmp_data == NULL)
530 {
531 FATAL("Cannot allocate memory for block...");
532
533 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
535 }
536
537 TRACE("Allocating memory for block of size %zu bytes", block_header->length);
538 block = malloc(block_header->length);
539 if(block == NULL)
540 {
541 FATAL("Cannot allocate memory for block...");
542 free(cmp_data);
543
544 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
546 }
547
548 TRACE("Reading compressed data into memory");
549 read_bytes = fread(cmp_data, 1, block_header->cmpLength, ctx->imageStream);
550 if(read_bytes != block_header->cmpLength)
551 {
552 FATAL("Could not read compressed block...");
553 free(cmp_data);
554 free(block);
555
556 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
558 }
559
560 TRACE("Decompressing block of size %zu bytes", block_header->length);
561 read_bytes =
562 aaruf_flac_decode_redbook_buffer(block, block_header->length, cmp_data, block_header->cmpLength);
563
564 if(read_bytes != block_header->length)
565 {
566 FATAL("Error decompressing block, should be {0} bytes but got {1} bytes...");
567 free(cmp_data);
568 free(block);
569
570 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
572 }
573
574 free(cmp_data);
575
576 break;
577 default:
578 FATAL("Unsupported compression %d", block_header->compression);
579 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_UNSUPPORTED_COMPRESSION");
581 }
582
583 // Add block to cache
584 TRACE("Adding block to cache");
585 add_to_cache_uint64(&ctx->block_cache, block_offset, block);
586
587 memcpy(data, block + offset * block_header->sectorSize, block_header->sectorSize);
588 *length = block_header->sectorSize;
589
590 TRACE("Exiting aaruf_read_sector() = AARUF_STATUS_OK");
591 return AARUF_STATUS_OK;
592}
593
663int32_t aaruf_read_track_sector(void *context, uint8_t *data, const uint64_t sector_address, uint32_t *length,
664 const uint8_t track)
665{
666 const uint32_t initial_length = length == NULL ? 0U : *length;
667
668 TRACE("Entering aaruf_read_track_sector(%p, %p, %" PRIu64 ", %u, %d)", context, data, sector_address,
669 initial_length, track);
670
671 if(context == NULL)
672 {
673 FATAL("Invalid context");
674
675 TRACE("Exiting aaruf_read_track_sector() = AARUF_ERROR_NOT_AARUFORMAT");
677 }
678
679 aaruformat_context *ctx = context;
680
681 if(length == NULL)
682 {
683 FATAL("Invalid length pointer");
684
685 TRACE("Exiting aaruf_read_track_sector() = AARUF_ERROR_INCORRECT_DATA_SIZE");
687 }
688
689 // Not a libaaruformat context
690 if(ctx->magic != AARU_MAGIC)
691 {
692 FATAL("Invalid context");
693
694 TRACE("Exiting aaruf_read_track_sector() = AARUF_ERROR_NOT_AARUFORMAT");
696 }
697
699 {
700 FATAL("Incorrect media type %d, expected OpticalDisc", ctx->imageInfo.XmlMediaType);
701
702 TRACE("Exiting aaruf_read_track_sector() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
704 }
705
706 for(int i = 0; i < ctx->number_of_data_tracks; i++)
707 if(ctx->data_tracks[i].sequence == track)
708 return aaruf_read_sector(context, ctx->data_tracks[i].start + sector_address, false, data, length);
709
710 TRACE("Track %d not found", track);
711 TRACE("Exiting aaruf_read_track_sector() = AARUF_ERROR_TRACK_NOT_FOUND");
713}
714
815int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, bool negative, uint8_t *data,
816 uint32_t *length)
817{
818 const uint32_t initial_length = length == NULL ? 0U : *length;
819
820 TRACE("Entering aaruf_read_sector_long(%p, %" PRIu64 ", %d, %p, %u)", context, sector_address, data,
821 initial_length);
822
823 const aaruformat_context *ctx = NULL;
824 uint32_t bare_length = 0;
825 uint32_t tag_length = 0;
826 uint8_t *bare_data = NULL;
827 int32_t res = 0;
828 int32_t query_status;
829 TrackEntry trk;
830 int i = 0;
831 bool trk_found = false;
832
833 if(context == NULL)
834 {
835 FATAL("Invalid context");
836
837 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_AARUFORMAT");
839 }
840
841 ctx = context;
842
843 if(length == NULL)
844 {
845 FATAL("Invalid length pointer");
846
847 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE");
849 }
850
851 // Not a libaaruformat context
852 if(ctx->magic != AARU_MAGIC)
853 {
854 FATAL("Invalid context");
855
856 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_AARUFORMAT");
858 }
859
860 if(negative && sector_address > ctx->user_data_ddt_header.negative - 1)
861 {
862 FATAL("Sector address out of bounds");
863
864 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
866 }
867
868 if(!negative && sector_address > ctx->image_info.Sectors + ctx->user_data_ddt_header.overflow - 1)
869 {
870 FATAL("Sector address out of bounds");
871
872 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
874 }
875
876 uint64_t corrected_sector_address = sector_address;
877
878 // Calculate positive or negative sector
879 if(negative)
880 corrected_sector_address -= ctx->user_data_ddt_header.negative;
881 else
882 corrected_sector_address += ctx->user_data_ddt_header.negative;
883
884 switch(ctx->image_info.MetadataMediaType)
885 {
886 case OpticalDisc:
887 if(ctx->image_info.MediaType == DVDROM || ctx->image_info.MediaType == PS2DVD ||
888 ctx->image_info.MediaType == SACD || ctx->image_info.MediaType == PS3DVD ||
889 ctx->image_info.MediaType == DVDR || ctx->image_info.MediaType == DVDRW ||
894 ctx->image_info.MediaType == Nuon)
895 {
896 if(ctx->sector_id == NULL || ctx->sector_ied == NULL || ctx->sector_cpr_mai == NULL ||
897 ctx->sector_edc == NULL)
898 return aaruf_read_sector(context, sector_address, negative, data, length);
899
900 if(*length < 2064 || data == NULL)
901 {
902 *length = 2064;
903 FATAL("Buffer too small for sector, required %u bytes", *length);
904
905 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL");
907 }
908
909 bare_length = 0;
910 query_status = aaruf_read_sector(context, sector_address, negative, NULL, &bare_length);
911
912 if(query_status != AARUF_ERROR_BUFFER_TOO_SMALL && query_status != AARUF_STATUS_OK)
913 {
914 TRACE("Exiting aaruf_read_sector_long() = %d", query_status);
915 return query_status;
916 }
917
918 if(bare_length == 0)
919 {
920 FATAL("Invalid bare sector length (0)");
921
922 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE");
924 }
925
926 TRACE("Allocating memory for bare data");
927 bare_data = (uint8_t *)malloc(bare_length);
928
929 if(bare_data == NULL)
930 {
931 FATAL("Could not allocate memory for bare data");
932
933 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
935 }
936
937 res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length);
938
939 if(res != AARUF_STATUS_OK)
940 {
941 *length = 2064;
942 free(bare_data);
943
944 TRACE("Exiting aaruf_read_sector_long() = %d", res);
945 return res;
946 }
947
948 memcpy(data, ctx->sector_id + corrected_sector_address * 4, 4);
949 memcpy(data + 4, ctx->sector_ied + corrected_sector_address * 2, 2);
950 memcpy(data + 6, ctx->sector_cpr_mai + corrected_sector_address * 6, 6);
951 memcpy(data + 12, bare_data, 2048);
952 memcpy(data + 2060, ctx->sector_edc + corrected_sector_address * 4, 4);
953
954 *length = 2064;
955
956 free(bare_data);
957 return AARUF_STATUS_OK;
958 }
959
960 if(*length < 2352 || data == NULL)
961 {
962 *length = 2352;
963 FATAL("Buffer too small for sector, required %u bytes", *length);
964
965 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL");
967 }
968
969 if((ctx->sector_suffix == NULL || ctx->sector_prefix == NULL) &&
970 (ctx->sector_suffix_ddt == NULL || ctx->sector_prefix_ddt == NULL) &&
971 (ctx->sector_suffix_ddt2 == NULL || ctx->sector_prefix_ddt2 == NULL))
972 return aaruf_read_sector(context, sector_address, negative, data, length);
973
974 bare_length = 0;
975 query_status = aaruf_read_sector(context, sector_address, negative, NULL, &bare_length);
976
977 if(query_status != AARUF_ERROR_BUFFER_TOO_SMALL && query_status != AARUF_STATUS_OK)
978 {
979 TRACE("Exiting aaruf_read_sector_long() = %d", query_status);
980 return query_status;
981 }
982
983 if(bare_length == 0)
984 {
985 FATAL("Invalid bare sector length (0)");
986
987 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE");
989 }
990
991 TRACE("Allocating memory for bare data");
992 bare_data = (uint8_t *)malloc(bare_length);
993
994 if(bare_data == NULL)
995 {
996 FATAL("Could not allocate memory for bare data");
997
998 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1000 }
1001
1002 res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length);
1003
1004 if(res != AARUF_STATUS_OK)
1005 {
1006 free(bare_data);
1007
1008 TRACE("Exiting aaruf_read_sector_long() = %d", res);
1009 return res;
1010 }
1011
1012 trk_found = false;
1013
1014 for(i = 0; i < ctx->number_of_data_tracks; i++)
1015 if(sector_address >= ctx->data_tracks[i].start && sector_address <= ctx->data_tracks[i].end)
1016 {
1017 trk_found = true;
1018 trk = ctx->data_tracks[i];
1019 break;
1020 }
1021
1022 if(!trk_found)
1023 {
1024 FATAL("Track not found");
1025 free(bare_data);
1026
1027 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_TRACK_NOT_FOUND");
1029 }
1030
1031 switch(trk.type)
1032 {
1033 case Audio:
1034 case Data:
1035 memcpy(data, bare_data, bare_length);
1036 *length = bare_length;
1037 free(bare_data);
1038 return res;
1039 case CdMode1:
1040 memcpy(data + 16, bare_data, 2048);
1041
1042 if(ctx->sector_prefix_ddt2 != NULL)
1043 {
1044 const uint64_t prefix_ddt_entry = ctx->sector_prefix_ddt2[corrected_sector_address];
1045 const uint32_t prefix_status = prefix_ddt_entry >> 60;
1046 const uint64_t prefix_index = prefix_ddt_entry & 0x0FFFFFFFFFFFFFFF;
1047
1048 if(prefix_status == SectorStatusMode1Correct)
1049 {
1050 aaruf_ecc_cd_reconstruct_prefix(data, trk.type, sector_address);
1051 res = AARUF_STATUS_OK;
1052 }
1053 else if(prefix_status == SectorStatusNotDumped)
1055 else
1056 memcpy(data, ctx->sector_prefix + prefix_index * 16, 16);
1057 }
1058 else if(ctx->sector_prefix != NULL)
1059 memcpy(data, ctx->sector_prefix + corrected_sector_address * 16, 16);
1060 else if(ctx->sector_prefix_ddt != NULL)
1061 {
1062 if((ctx->sector_prefix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Correct)
1063 {
1064 aaruf_ecc_cd_reconstruct_prefix(data, trk.type, sector_address);
1065 res = AARUF_STATUS_OK;
1066 }
1067 else if((ctx->sector_prefix_ddt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped)
1069 else
1070 memcpy(data,
1072 ((ctx->sector_prefix_ddt[corrected_sector_address] & CD_DFIX_MASK) - 1) * 16,
1073 16);
1074 }
1075 else
1076 {
1077 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_REACHED_UNREACHABLE_CODE");
1078 free(bare_data);
1080 }
1081
1082 if(res != AARUF_STATUS_OK)
1083 {
1084 *length = 2352;
1085 free(bare_data);
1086 return res;
1087 }
1088
1089 if(ctx->sector_suffix_ddt2 != NULL)
1090 {
1091 const uint64_t suffix_ddt_entry = ctx->sector_suffix_ddt2[corrected_sector_address];
1092 const uint64_t suffix_status = suffix_ddt_entry >> 60;
1093 const uint64_t suffix_index = suffix_ddt_entry & 0x0FFFFFFFFFFFFFFF;
1094
1095 if(suffix_status == SectorStatusMode1Correct)
1096 {
1098 res = AARUF_STATUS_OK;
1099 }
1100 else if(suffix_status == SectorStatusNotDumped)
1102 else
1103 memcpy(data + 2064, ctx->sector_suffix + suffix_index * 288, 288);
1104 }
1105 else if(ctx->sector_suffix != NULL)
1106 memcpy(data + 2064, ctx->sector_suffix + corrected_sector_address * 288, 288);
1107 else if(ctx->sector_suffix_ddt != NULL)
1108 {
1109 if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Correct)
1110 {
1112 res = AARUF_STATUS_OK;
1113 }
1114 else if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped)
1116 else
1117 memcpy(data + 2064,
1119 ((ctx->sector_suffix_ddt[corrected_sector_address] & CD_DFIX_MASK) - 1) * 288,
1120 288);
1121 }
1122 else
1123 {
1124 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_REACHED_UNREACHABLE_CODE");
1125 free(bare_data);
1127 }
1128
1129 *length = 2352;
1130 free(bare_data);
1131 return res;
1132 case CdMode2Formless:
1133 case CdMode2Form1:
1134 case CdMode2Form2:
1135 if(ctx->sector_prefix_ddt2 != NULL)
1136 {
1137 const uint64_t prefix_ddt_entry = ctx->sector_prefix_ddt2[corrected_sector_address];
1138 const uint64_t prefix_status = prefix_ddt_entry >> 60;
1139 const uint64_t prefix_index = prefix_ddt_entry & 0x0FFFFFFFFFFFFFFF;
1140
1141 if(prefix_status == SectorStatusMode2Form1Ok || prefix_status == SectorStatusMode2Form2Ok)
1142 {
1143 aaruf_ecc_cd_reconstruct_prefix(data, trk.type, sector_address);
1144 res = AARUF_STATUS_OK;
1145 }
1146 else if(prefix_status == SectorStatusNotDumped)
1148 else
1149 memcpy(data, ctx->sector_prefix + prefix_index * 16, 16);
1150 }
1151 else if(ctx->sector_prefix != NULL)
1152 memcpy(data, ctx->sector_prefix + corrected_sector_address * 16, 16);
1153 else if(ctx->sector_prefix_ddt != NULL)
1154 {
1155 if((ctx->sector_prefix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Correct)
1156 {
1157 aaruf_ecc_cd_reconstruct_prefix(data, trk.type, sector_address);
1158 res = AARUF_STATUS_OK;
1159 }
1160 else if((ctx->sector_prefix_ddt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped)
1162 else
1163 memcpy(data,
1165 ((ctx->sector_prefix_ddt[corrected_sector_address] & CD_DFIX_MASK) - 1) * 16,
1166 16);
1167 }
1168 else
1169 {
1170 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_REACHED_UNREACHABLE_CODE");
1171 free(bare_data);
1173 }
1174
1175 if(res != AARUF_STATUS_OK)
1176 {
1177 *length = 2352;
1178 free(bare_data);
1179 return res;
1180 }
1181
1182 if(ctx->mode2_subheaders != NULL && ctx->sector_suffix_ddt2 != NULL)
1183 {
1184 memcpy(data + 16, ctx->mode2_subheaders + corrected_sector_address * 8, 8);
1185 const uint64_t suffix_ddt_entry = ctx->sector_suffix_ddt2[corrected_sector_address];
1186 const uint64_t suffix_status = suffix_ddt_entry >> 60;
1187 const uint64_t suffix_index = suffix_ddt_entry & 0x0FFFFFFFFFFFFFFF;
1188
1189 if(suffix_status == SectorStatusMode2Form1Ok)
1190 {
1191 memcpy(data + 24, bare_data, 2048);
1193 }
1194 else if(suffix_status == SectorStatusMode2Form2Ok ||
1195 suffix_status == SectorStatusMode2Form2NoCrc)
1196 {
1197 memcpy(data + 24, bare_data, 2324);
1198 if(suffix_status == SectorStatusMode2Form2Ok)
1200 }
1201 else if(suffix_status == SectorStatusNotDumped)
1203 else
1204 // Mode 2 where ECC failed
1205 memcpy(data + 24, bare_data, 2328);
1206 }
1207 else if(ctx->mode2_subheaders != NULL && ctx->sector_suffix_ddt != NULL)
1208 {
1209 memcpy(data + 16, ctx->mode2_subheaders + corrected_sector_address * 8, 8);
1210
1211 if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form1Ok)
1212 {
1213 memcpy(data + 24, bare_data, 2048);
1215 }
1216 else if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form2Ok ||
1217 (ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form2NoCrc)
1218 {
1219 memcpy(data + 24, bare_data, 2324);
1220 if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form2Ok)
1222 }
1223 else if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped)
1225 else
1226 // Mode 2 where ECC failed
1227 memcpy(data + 24, bare_data, 2328);
1228 }
1229 else if(ctx->mode2_subheaders != NULL)
1230 {
1231 memcpy(data + 16, ctx->mode2_subheaders + corrected_sector_address * 8, 8);
1232 memcpy(data + 24, bare_data, 2328);
1233 }
1234 else
1235 memcpy(data + 16, bare_data, 2336);
1236
1237 *length = 2352;
1238 free(bare_data);
1239 return res;
1240 default:
1241 FATAL("Invalid track type %d", trk.type);
1242 free(bare_data);
1243
1244 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INVALID_TRACK_FORMAT");
1246 }
1247 case BlockMedia:
1248 switch(ctx->image_info.MediaType)
1249 {
1250 case AppleFileWare:
1251 case AppleProfile:
1252 case AppleSonySS:
1253 case AppleSonyDS:
1254 case AppleWidget:
1255 case PriamDataTower:
1256 if(ctx->sector_subchannel == NULL)
1257 return aaruf_read_sector(context, sector_address, negative, data, length);
1258
1259 switch(ctx->image_info.MediaType)
1260 {
1261 case AppleFileWare:
1262 case AppleProfile:
1263 case AppleWidget:
1264 tag_length = 20;
1265 break;
1266 case AppleSonySS:
1267 case AppleSonyDS:
1268 tag_length = 12;
1269 break;
1270 case PriamDataTower:
1271 tag_length = 24;
1272 break;
1273 default:
1274 FATAL("Unsupported media type %d", ctx->imageInfo.MediaType);
1275
1276 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1278 }
1279
1280 bare_length = 512;
1281
1282 if(*length < tag_length + bare_length || data == NULL)
1283 {
1284 *length = tag_length + bare_length;
1285 FATAL("Buffer too small for sector, required %u bytes", *length);
1286
1287 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL");
1289 }
1290
1291 TRACE("Allocating memory for bare data of size %u bytes", bare_length);
1292 bare_data = malloc(bare_length);
1293
1294 if(bare_data == NULL)
1295 {
1296 FATAL("Could not allocate memory for bare data");
1297
1298 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1300 }
1301
1302 res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length);
1303
1304 if(res != AARUF_STATUS_OK)
1305 {
1306 free(bare_data);
1307
1308 TRACE("Exiting aaruf_read_sector_long() = %d", res);
1309 return res;
1310 }
1311
1312 if(bare_length != 512)
1313 {
1314 FATAL("Bare data length is %u, expected 512", bare_length);
1315 free(bare_data);
1316
1317 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1319 }
1320
1321 memcpy(data + bare_length, ctx->sector_subchannel + corrected_sector_address * tag_length,
1322 tag_length);
1323 memcpy(data, bare_data, bare_length);
1324 *length = tag_length + bare_length;
1325
1326 free(bare_data);
1327
1328 TRACE("Exiting aaruf_read_sector_long() = AARUF_STATUS_OK");
1329 return AARUF_STATUS_OK;
1330 default:
1331 FATAL("Incorrect media type %d for long sector reading", ctx->imageInfo.MediaType);
1332
1333 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1335 }
1336 default:
1337 FATAL("Incorrect media type %d for long sector reading", ctx->imageInfo.MediaType);
1338
1339 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1341 }
1342}
1343
1463int32_t aaruf_read_sector_tag(const void *context, const uint64_t sector_address, const bool negative, uint8_t *buffer,
1464 uint32_t *length, const int32_t tag)
1465{
1466 const uint32_t initial_length = length == NULL ? 0U : *length;
1467
1468 TRACE("Entering aaruf_read_sector_tag(%p, %" PRIu64 ", %d, %p, %u, %d)", context, sector_address, negative, buffer,
1469 initial_length, tag);
1470
1471 const aaruformat_context *ctx = NULL;
1472
1473 if(context == NULL)
1474 {
1475 FATAL("Invalid context");
1476
1477 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_NOT_AARUFORMAT");
1479 }
1480
1481 ctx = context;
1482
1483 if(length == NULL)
1484 {
1485 FATAL("Invalid length pointer");
1486
1487 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1489 }
1490
1491 // Not a libaaruformat context
1492 if(ctx->magic != AARU_MAGIC)
1493 {
1494 FATAL("Invalid context");
1495
1496 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_NOT_AARUFORMAT");
1498 }
1499
1500 if(negative && sector_address > ctx->user_data_ddt_header.negative - 1)
1501 {
1502 FATAL("Sector address out of bounds");
1503
1504 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
1506 }
1507
1508 if(!negative && sector_address > ctx->image_info.Sectors + ctx->user_data_ddt_header.overflow - 1)
1509 {
1510 FATAL("Sector address out of bounds");
1511
1512 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
1514 }
1515
1516 uint64_t corrected_sector_address = sector_address;
1517
1518 // Calculate positive or negative sector
1519 if(negative)
1520 corrected_sector_address -= ctx->user_data_ddt_header.negative;
1521 else
1522 corrected_sector_address += ctx->user_data_ddt_header.negative;
1523
1524 switch(tag)
1525 {
1526 case CdTrackFlags:
1528 {
1529 FATAL("Invalid media type for tag");
1530 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1532 }
1533
1534 if(*length != 1 || buffer == NULL)
1535 {
1536 *length = 1;
1537 FATAL("Incorrect tag size");
1538 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1540 }
1541
1542 for(int i = 0; i < ctx->tracks_header.entries; i++)
1543 if(sector_address >= ctx->track_entries[i].start && sector_address <= ctx->track_entries[i].end)
1544 {
1545 buffer[0] = ctx->track_entries[i].flags;
1546 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1547 return AARUF_STATUS_OK;
1548 }
1549
1550 FATAL("Track not found");
1552 case CdTrackIsrc:
1554 {
1555 FATAL("Invalid media type for tag");
1556 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1558 }
1559
1560 if(*length != 12 || buffer == NULL)
1561 {
1562 *length = 12;
1563 FATAL("Incorrect tag size");
1564 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1566 }
1567
1568 for(int i = 0; i < ctx->tracks_header.entries; i++)
1569 if(sector_address >= ctx->track_entries[i].start && sector_address <= ctx->track_entries[i].end)
1570 {
1571 memcpy(buffer, ctx->track_entries[i].isrc, 12);
1572 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1573 return AARUF_STATUS_OK;
1574 }
1575
1576 FATAL("Track not found");
1578 case CdSectorSubchannel:
1580 {
1581 FATAL("Invalid media type for tag");
1582 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1584 }
1585
1586 if(*length != 96 || buffer == NULL)
1587 {
1588 *length = 96;
1589 FATAL("Incorrect tag size");
1590 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1592 }
1593
1594 if(ctx->sector_subchannel == NULL)
1595 {
1596 FATAL("Sector tag not found");
1597 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1599 }
1600
1601 memcpy(buffer, ctx->sector_subchannel + corrected_sector_address * 96, 96);
1602 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1603 return AARUF_STATUS_OK;
1604 case DvdCmi:
1606 {
1607 FATAL("Invalid media type for tag");
1608 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1610 }
1611
1612 if(*length != 1 || buffer == NULL)
1613 {
1614 *length = 1;
1615 FATAL("Incorrect tag size");
1616 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1618 }
1619
1620 if(ctx->sector_cpr_mai == NULL)
1621 {
1622 FATAL("Sector tag not found");
1623 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1625 }
1626
1627 memcpy(buffer, ctx->sector_cpr_mai + corrected_sector_address * 6, 1);
1628 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1629 return AARUF_STATUS_OK;
1632 {
1633 FATAL("Invalid media type for tag");
1634 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1636 }
1637
1638 if(*length != 1 || buffer == NULL)
1639 {
1640 *length = 1;
1641 FATAL("Incorrect tag size");
1642 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1644 }
1645
1646 if(ctx->sector_id == NULL)
1647 {
1648 FATAL("Sector tag not found");
1649 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1651 }
1652
1653 memcpy(buffer, ctx->sector_id + corrected_sector_address * 4, 1);
1654 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1655 return AARUF_STATUS_OK;
1656 case DvdSectorNumber:
1658 {
1659 FATAL("Invalid media type for tag");
1660 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1662 }
1663
1664 if(*length != 3 || buffer == NULL)
1665 {
1666 *length = 3;
1667 FATAL("Incorrect tag size");
1668 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1670 }
1671
1672 if(ctx->sector_id == NULL)
1673 {
1674 FATAL("Sector tag not found");
1675 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1677 }
1678
1679 memcpy(buffer, ctx->sector_id + corrected_sector_address * 4 + 1, 3);
1680 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1681 return AARUF_STATUS_OK;
1682 case DvdSectorIed:
1684 {
1685 FATAL("Invalid media type for tag");
1686 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1688 }
1689
1690 if(*length != 2 || buffer == NULL)
1691 {
1692 *length = 2;
1693 FATAL("Incorrect tag size");
1694 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1696 }
1697
1698 if(ctx->sector_ied == NULL)
1699 {
1700 FATAL("Sector tag not found");
1701 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1703 }
1704
1705 memcpy(buffer, ctx->sector_ied + corrected_sector_address * 2, 2);
1706 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1707 return AARUF_STATUS_OK;
1708 case DvdSectorEdc:
1710 {
1711 FATAL("Invalid media type for tag");
1712 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1714 }
1715
1716 if(*length != 4 || buffer == NULL)
1717 {
1718 *length = 4;
1719 FATAL("Incorrect tag size");
1720 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1722 }
1723
1724 if(ctx->sector_edc == NULL)
1725 {
1726 FATAL("Sector tag not found");
1727 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1729 }
1730
1731 memcpy(buffer, ctx->sector_edc + corrected_sector_address * 4, 4);
1732 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1733 return AARUF_STATUS_OK;
1736 {
1737 FATAL("Invalid media type for tag");
1738 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1740 }
1741
1742 if(*length != 5 || buffer == NULL)
1743 {
1744 *length = 5;
1745 FATAL("Incorrect tag size");
1746 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1748 }
1749
1750 if(ctx->sector_decrypted_title_key == NULL)
1751 {
1752 FATAL("Sector tag not found");
1753 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1755 }
1756
1757 memcpy(buffer, ctx->sector_decrypted_title_key + corrected_sector_address * 5, 5);
1758 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1759 return AARUF_STATUS_OK;
1760 case AppleSonyTag:
1762 {
1763 FATAL("Invalid media type for tag");
1764 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1766 }
1767
1768 if(*length != 12 || buffer == NULL)
1769 {
1770 *length = 12;
1771 FATAL("Incorrect tag size");
1772 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1774 }
1775
1776 if(ctx->sector_subchannel == NULL)
1777 {
1778 FATAL("Sector tag not found");
1779 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1781 }
1782
1783 memcpy(buffer, ctx->sector_subchannel + corrected_sector_address * 12, 12);
1784 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1785 return AARUF_STATUS_OK;
1786 case AppleProfileTag:
1788 {
1789 FATAL("Invalid media type for tag");
1790 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1792 }
1793
1794 if(*length != 20 || buffer == NULL)
1795 {
1796 *length = 20;
1797 FATAL("Incorrect tag size");
1798 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1800 }
1801
1802 if(ctx->sector_subchannel == NULL)
1803 {
1804 FATAL("Sector tag not found");
1805 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1807 }
1808
1809 memcpy(buffer, ctx->sector_subchannel + corrected_sector_address * 20, 20);
1810 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1811 return AARUF_STATUS_OK;
1812 case PriamDataTowerTag:
1814 {
1815 FATAL("Invalid media type for tag");
1816 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1818 }
1819
1820 if(*length != 24 || buffer == NULL)
1821 {
1822 *length = 24;
1823 FATAL("Incorrect tag size");
1824 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1826 }
1827
1828 if(ctx->sector_subchannel == NULL)
1829 {
1830 FATAL("Sector tag not found");
1831 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1833 }
1834
1835 memcpy(buffer, ctx->sector_subchannel + corrected_sector_address * 24, 24);
1836 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1837 return AARUF_STATUS_OK;
1838 default:
1839 TRACE("Do not know how to read sector tag %d", tag);
1841 }
1842}
#define CD_DFIX_MASK
Mask for extracting positional index (lower 24 bits) in Compact Disc suffix/prefix deduplicated block...
Definition consts.h:102
#define LZMA_PROPERTIES_LENGTH
Size in bytes of the fixed LZMA properties header (lc/lp/pb + dictionary size).
Definition consts.h:82
#define AARU_MAGIC
Magic identifier for AaruFormat container (ASCII "AARUFRMT").
Definition consts.h:64
#define CD_XFIX_MASK
Mask for extracting correction / fix flags in Compact Disc suffix/prefix DDT entries.
Definition consts.h:100
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.
Definition lzma.c:39
void aaruf_ecc_cd_reconstruct_prefix(uint8_t *sector, uint8_t type, int64_t lba)
Reconstructs the prefix (sync, address, mode) of a CD sector.
Definition ecc_cd.c:388
void aaruf_ecc_cd_reconstruct(void *context, uint8_t *sector, uint8_t type)
Reconstructs the EDC and ECC fields of a CD sector.
Definition ecc_cd.c:455
size_t aaruf_flac_decode_redbook_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer, size_t src_size)
Decodes a FLAC-compressed Red Book audio buffer.
Definition flac.c:48
@ SectorStatusNotDumped
Sector(s) not yet acquired during image dumping.
Definition enums.h:230
@ SectorStatusMode2Form2NoCrc
Suffix matches MODE 2 Form 2 but CRC empty/missing.
Definition enums.h:236
@ SectorStatusMode1Correct
Valid MODE 1 data with regenerable suffix/prefix.
Definition enums.h:233
@ SectorStatusMode2Form2Ok
Suffix matches MODE 2 Form 2 with valid CRC.
Definition enums.h:235
@ SectorStatusMode2Form1Ok
Suffix verified/regenerable for MODE 2 Form 1.
Definition enums.h:234
@ Correct
Sector(s) contain valid MODE 1 data with regenerable suffix/prefix.
Definition enums.h:183
@ Mode2Form2Ok
Sector suffix valid for MODE 2 Form 2 with correct CRC.
Definition enums.h:185
@ Mode2Form1Ok
Sector suffix valid for MODE 2 Form 1; regenerable.
Definition enums.h:184
@ NotDumped
Sector(s) have not yet been dumped.
Definition enums.h:182
@ Mode2Form2NoCrc
Sector suffix valid for MODE 2 Form 2 but CRC absent/empty.
Definition enums.h:186
@ OpticalDisc
Purely optical discs.
Definition enums.h:218
@ BlockMedia
Media that is physically block-based or abstracted like that.
Definition enums.h:219
@ CdMode1
Compact Disc Mode 1 data track.
Definition enums.h:197
@ Data
Generic data track (not further specified).
Definition enums.h:196
@ CdMode2Form2
Compact Disc Mode 2 Form 2 data track.
Definition enums.h:200
@ Audio
Audio track.
Definition enums.h:195
@ CdMode2Form1
Compact Disc Mode 2 Form 1 data track.
Definition enums.h:199
@ CdMode2Formless
Compact Disc Mode 2 (formless) data track.
Definition enums.h:198
@ CdSectorSubchannel
Compact Disc subchannel data.
Definition enums.h:116
@ AppleProfileTag
Apple Profile (20‑byte) tag.
Definition enums.h:117
@ DvdSectorIed
DVD ID Error Detection Code (IED)
Definition enums.h:129
@ AppleSonyTag
Apple Sony (12‑byte) tag.
Definition enums.h:118
@ PriamDataTowerTag
Priam Data Tower (24‑byte) tag.
Definition enums.h:119
@ DvdSectorEdc
DVD Error Detection Code (EDC)
Definition enums.h:130
@ Lzma
LZMA compression.
Definition enums.h:34
@ None
Not compressed.
Definition enums.h:33
@ Flac
FLAC compression.
Definition enums.h:35
#define AARUF_STATUS_OK
Sector present and read without uncorrectable errors.
Definition errors.h:75
#define AARUF_ERROR_INCORRECT_MEDIA_TYPE
Operation incompatible with image media type.
Definition errors.h:51
#define AARUF_ERROR_TRACK_NOT_FOUND
Referenced track number not present.
Definition errors.h:52
#define AARUF_ERROR_CANNOT_READ_HEADER
Failed to read container header.
Definition errors.h:45
#define AARUF_ERROR_NOT_ENOUGH_MEMORY
Memory allocation failure (critical).
Definition errors.h:48
#define AARUF_ERROR_SECTOR_OUT_OF_BOUNDS
Requested logical sector outside media bounds.
Definition errors.h:44
#define AARUF_ERROR_INVALID_TRACK_FORMAT
Track metadata internally inconsistent or malformed.
Definition errors.h:54
#define AARUF_ERROR_CANNOT_READ_BLOCK
Generic block read failure (seek/read error).
Definition errors.h:46
#define AARUF_ERROR_INCORRECT_DATA_SIZE
Data size does not match expected size.
Definition errors.h:65
#define AARUF_ERROR_SECTOR_TAG_NOT_PRESENT
Requested sector tag (e.g. subchannel/prefix) not stored.
Definition errors.h:55
#define AARUF_STATUS_SECTOR_NOT_DUMPED
Sector not captured (gap / missing / intentionally skipped).
Definition errors.h:76
#define AARUF_ERROR_NOT_AARUFORMAT
Input file/stream failed magic or structural validation.
Definition errors.h:40
#define AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK
Decompression routine failed or size mismatch.
Definition errors.h:56
#define AARUF_ERROR_INVALID_TAG
Invalid or unsupported media or sector tag format.
Definition errors.h:66
#define AARUF_ERROR_MEDIA_TAG_NOT_PRESENT
Requested media tag absent.
Definition errors.h:50
#define AARUF_ERROR_BUFFER_TOO_SMALL
Caller-supplied buffer insufficient for data.
Definition errors.h:49
#define AARUF_ERROR_UNSUPPORTED_COMPRESSION
Block marked with unsupported compression algorithm.
Definition errors.h:47
#define AARUF_ERROR_REACHED_UNREACHABLE_CODE
Internal logic assertion hit unexpected path.
Definition errors.h:53
@ AppleProfile
Definition aaru.h:698
@ AppleSonySS
3.5", SS, DD, 80 tracks, 8 to 12 spt, 512 bytes/sector, GCR
Definition aaru.h:247
@ DVDPRWDL
DVD+RW DL.
Definition aaru.h:141
@ DVDRW
DVD-RW.
Definition aaru.h:138
@ DVDRWDL
DVD-RW DL.
Definition aaru.h:145
@ SACD
Super Audio CD (Scarlet Book)
Definition aaru.h:121
@ DVDPRDL
DVD+R DL.
Definition aaru.h:143
@ DVDR
DVD-R.
Definition aaru.h:137
@ PS3DVD
Sony PlayStation 3 game DVD.
Definition aaru.h:206
@ PS2DVD
Sony PlayStation 2 game DVD.
Definition aaru.h:205
@ PriamDataTower
Definition aaru.h:701
@ AppleFileWare
5.25", DS, ?D, ?? tracks, ?? spt, 512 bytes/sector, GCR, opposite side heads, aka Twiggy
Definition aaru.h:249
@ DVDPR
DVD+R.
Definition aaru.h:139
@ AppleWidget
Definition aaru.h:699
@ DVDPRW
DVD+RW.
Definition aaru.h:140
@ Nuon
Nuon (DVD based videogame console)
Definition aaru.h:238
@ DVDDownload
DVD-Download.
Definition aaru.h:146
@ DVDRDL
DVD-R DL.
Definition aaru.h:142
@ AppleSonyDS
3.5", DS, DD, 80 tracks, 8 to 12 spt, 512 bytes/sector, GCR
Definition aaru.h:248
@ DVDROM
DVD-ROM (applies to DVD Video and DVD Audio)
Definition aaru.h:136
@ DVDRAM
DVD-RAM.
Definition aaru.h:144
@ CdTrackFlags
Track flags (audio/data, copy permitted, pre-emphasis)
Definition aaru.h:907
@ DvdCmi
DVD Copyright Management Information (CSS)
Definition aaru.h:908
@ DvdSectorNumber
DVD sector number, 3 bytes.
Definition aaru.h:913
@ CdTrackIsrc
Track ISRC (12 ASCII chars, no terminator)
Definition aaru.h:905
@ DvdSectorInformation
DVD sector information, 1 bytes.
Definition aaru.h:912
@ DvdTitleKeyDecrypted
Decrypted DVD sector title key, 5 bytes.
Definition aaru.h:911
int32_t decode_ddt_entry_v1(aaruformat_context *ctx, uint64_t sector_address, uint64_t *offset, uint64_t *block_offset, uint8_t *sector_status)
Decodes a DDT v1 entry for a given sector address.
Definition ddt_v1.c:405
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.
Definition ddt_v2.c:507
#define FATAL(fmt,...)
Definition log.h:40
#define TRACE(fmt,...)
Definition log.h:25
void add_to_cache_uint64(struct CacheHeader *cache, uint64_t key, void *value)
Adds a value to the cache with a uint64_t key, using string conversion.
Definition lru.c:102
void * find_in_cache_uint64(struct CacheHeader *cache, uint64_t key)
Finds a value in the cache by uint64_t key, using string conversion.
Definition lru.c:88
int32_t aaruf_read_media_tag(void *context, uint8_t *data, const int32_t tag, uint32_t *length)
Reads a media tag from the AaruFormat image.
Definition read.c:85
int32_t aaruf_read_sector_tag(const void *context, const uint64_t sector_address, const bool negative, uint8_t *buffer, uint32_t *length, const int32_t tag)
Reads a specific sector tag from the AaruFormat image.
Definition read.c:1463
int32_t aaruf_read_track_sector(void *context, uint8_t *data, const uint64_t sector_address, uint32_t *length, const uint8_t track)
Reads a sector from a specific track in the AaruFormat image.
Definition read.c:663
int32_t aaruf_read_sector(void *context, const uint64_t sector_address, bool negative, uint8_t *data, uint32_t *length)
Reads a sector from the AaruFormat image.
Definition read.c:250
int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, bool negative, uint8_t *data, uint32_t *length)
Reads a complete sector with all metadata from the AaruFormat image.
Definition read.c:815
Header preceding the compressed data payload of a data block (BlockType::DataBlock).
Definition data.h:71
uint32_t cmpLength
Size in bytes of the compressed payload immediately following this header.
Definition data.h:76
uint32_t length
Size in bytes of the uncompressed payload resulting after decompression.
Definition data.h:77
uint32_t sectorSize
Size in bytes of each logical sector represented in this block.
Definition data.h:75
uint16_t compression
Compression algorithm used (value from CompressionType).
Definition data.h:74
uint16_t overflow
Trailing dumped sectors beyond user area (overflow range), still mapped with entries.
Definition ddt.h:151
uint16_t negative
Leading negative LBA count; added to external L to build internal index.
Definition ddt.h:149
uint32_t MediaType
Media type identifier (see MediaType enum; 0=Unknown)
Definition aaru.h:881
uint8_t MetadataMediaType
Media type for sidecar generation (internal archival use)
Definition aaru.h:882
uint32_t SectorSize
Size of each logical sector in bytes (512, 2048, 2352, 4096, etc.)
Definition aaru.h:875
uint64_t Sectors
Total count of addressable logical sectors/blocks.
Definition aaru.h:874
Single optical disc track descriptor (sequence, type, LBAs, session, ISRC, flags).
Definition optical.h:72
uint8_t flags
Control / attribute bitfield (see file documentation for suggested bit mapping).
Definition optical.h:80
uint8_t sequence
Track number (1..99 typical for CD audio/data). 0 may indicate placeholder/non-standard.
Definition optical.h:73
int64_t start
Inclusive starting LBA of the track.
Definition optical.h:75
uint8_t type
Track type (value from TrackType).
Definition optical.h:74
uint8_t isrc[13]
ISRC raw 13-byte code (no null terminator). All zeros if not present.
Definition optical.h:79
uint16_t entries
Number of TrackEntry records following this header.
Definition optical.h:64
Master context representing an open or in‑creation Aaru image.
Definition context.h:172
DdtHeader2 user_data_ddt_header
Active user data DDT v2 header (primary table meta).
Definition context.h:189
uint8_t * sector_cpr_mai
DVD sector CPR_MAI (6 bytes) if present.
Definition context.h:207
uint8_t * sector_prefix_corrected
Corrected variant (post error correction) if stored.
Definition context.h:200
TrackEntry * data_tracks
Filtered list of data tracks (subset of trackEntries).
Definition context.h:243
struct CacheHeader block_header_cache
LRU/Cache header for block headers.
Definition context.h:256
uint8_t * sector_ied
DVD sector IED (2 bytes) if present.
Definition context.h:206
uint8_t * sector_prefix
Raw per-sector prefix (e.g., sync+header) uncorrected.
Definition context.h:199
uint64_t * sector_suffix_ddt2
CD sector suffix DDT V2.
Definition context.h:186
uint8_t * sector_edc
DVD sector EDC (4 bytes) if present.
Definition context.h:208
CdEccContext * ecc_cd_context
CD ECC/EDC helper tables (allocated on demand).
Definition context.h:248
struct CacheHeader block_cache
LRU/Cache header for block payloads.
Definition context.h:257
uint32_t * sector_suffix_ddt
Legacy CD sector suffix DDT.
Definition context.h:184
uint8_t * sector_suffix
Raw per-sector suffix (EDC/ECC) uncorrected.
Definition context.h:201
int ddt_version
DDT version in use (1=legacy, 2=v2 hierarchical).
Definition context.h:194
uint64_t magic
File magic (AARU_MAGIC) post-open.
Definition context.h:174
uint64_t * sector_prefix_ddt2
CD sector prefix DDT V2.
Definition context.h:185
mediaTagEntry * mediaTags
Hash table of extra media tags (uthash root).
Definition context.h:264
uint8_t * sector_decrypted_title_key
DVD decrypted title key (5 bytes) if present.
Definition context.h:209
uint8_t * sector_subchannel
Raw 96-byte subchannel (if captured).
Definition context.h:203
FILE * imageStream
Underlying FILE* stream (binary mode).
Definition context.h:176
uint8_t * mode2_subheaders
MODE2 Form1/Form2 8-byte subheaders (concatenated).
Definition context.h:204
ImageInfo image_info
Exposed high-level image info summary.
Definition context.h:260
uint8_t * sector_id
DVD sector ID (4 bytes) if present.
Definition context.h:205
uint32_t * sector_prefix_ddt
Legacy CD sector prefix DDT (deprecated by *2).
Definition context.h:183
TrackEntry * track_entries
Full track list (tracksHeader.entries elements).
Definition context.h:242
uint8_t number_of_data_tracks
Count of tracks considered "data" (sequence 1..99 heuristics).
Definition context.h:245
uint8_t * sector_suffix_corrected
Corrected suffix if stored separately.
Definition context.h:202
TracksHeader tracks_header
Tracks header (optical) if present.
Definition context.h:244
Hash table entry for an arbitrary media tag (e.g., proprietary drive/medium descriptor).
Definition context.h:119
uint8_t * data
Tag data blob (opaque to library core); length bytes long.
Definition context.h:120
uint32_t length
Length in bytes of data.
Definition context.h:122