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
85AARU_EXPORT int32_t AARU_CALL 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
253AARU_EXPORT int32_t AARU_CALL aaruf_read_sector(void *context, const uint64_t sector_address, bool negative,
254 uint8_t *data, uint32_t *length, uint8_t *sector_status)
255{
256 const uint32_t initial_length = length == NULL ? 0U : *length;
257
258 TRACE("Entering aaruf_read_sector(%p, %" PRIu64 ", %d, %p, %u)", context, sector_address, negative, data,
259 initial_length);
260
261 aaruformat_context *ctx = NULL;
262 uint64_t offset = 0;
263 uint64_t block_offset = 0;
264 BlockHeader *block_header = NULL;
265 uint8_t *block = NULL;
266 size_t read_bytes = 0;
267 uint8_t lzma_properties[LZMA_PROPERTIES_LENGTH];
268 size_t lzma_size = 0;
269 uint8_t *cmp_data = NULL;
270 int error_no = 0;
271 *sector_status = SectorStatusNotDumped;
272
273 if(context == NULL)
274 {
275 FATAL("Invalid context");
276
277 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_AARUFORMAT");
279 }
280
281 ctx = context;
282
283 if(length == NULL)
284 {
285 FATAL("Invalid length pointer");
286
287 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_INCORRECT_DATA_SIZE");
289 }
290
291 // Not a libaaruformat context
292 if(ctx->magic != AARU_MAGIC)
293 {
294 FATAL("Invalid context");
295
296 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_AARUFORMAT");
298 }
299
300 if(negative && sector_address > ctx->user_data_ddt_header.negative)
301 {
302 FATAL("Sector address out of bounds");
303
304 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
306 }
307
308 if(!negative && sector_address > ctx->image_info.Sectors + ctx->user_data_ddt_header.overflow - 1)
309 {
310 FATAL("Sector address out of bounds");
311
312 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
314 }
315
316 if(ctx->ddt_version == 1)
317 {
318 if(negative)
319 {
320 FATAL("Negative sector addresses not supported in this image");
322 }
323
324 error_no = decode_ddt_entry_v1(ctx, sector_address, &offset, &block_offset, sector_status);
325 }
326 else if(ctx->ddt_version == 2)
327 error_no = decode_ddt_entry_v2(ctx, sector_address, negative, &offset, &block_offset, sector_status);
328
329 if(error_no != AARUF_STATUS_OK)
330 {
331 FATAL("Error %d decoding DDT entry", error_no);
332
333 TRACE("Exiting aaruf_read_sector() = %d", error_no);
334 return error_no;
335 }
336
337 // Partially written image... as we can't know the real sector size just assume it's common :/
338 if(*sector_status == SectorStatusNotDumped)
339 {
340 *length = ctx->image_info.SectorSize;
341
342 TRACE("Exiting aaruf_read_sector() = AARUF_STATUS_SECTOR_NOT_DUMPED");
344 }
345
346 // Check if block header is cached
347 TRACE("Checking if block header is cached");
348 block_header = find_in_cache_uint64(&ctx->block_header_cache, block_offset);
349
350 // Read block header
351 if(block_header == NULL)
352 {
353 TRACE("Allocating memory for block header");
354 block_header = malloc(sizeof(BlockHeader));
355 if(block_header == NULL)
356 {
357 FATAL("Not enough memory for block header");
358
359 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
361 }
362
363 TRACE("Reading block header");
364 if(fseek(ctx->imageStream, block_offset, SEEK_SET) != 0)
365 {
366 FATAL("Could not seek to block header");
367 free(block_header);
368
369 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_READ_HEADER");
371 }
372
373 read_bytes = fread(block_header, 1, sizeof(BlockHeader), ctx->imageStream);
374
375 if(read_bytes != sizeof(BlockHeader))
376 {
377 FATAL("Error reading block header");
378 free(block_header);
379
380 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_READ_HEADER");
382 }
383
384 TRACE("Adding block header to cache");
385 add_to_cache_uint64(&ctx->block_header_cache, block_offset, block_header);
386 }
387 else if(fseek(ctx->imageStream, block_offset + sizeof(BlockHeader), SEEK_SET) != 0)
388 {
389 FATAL("Could not seek past cached block header");
390
391 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_READ_HEADER");
393 }
394
395 if(data == NULL || *length < block_header->sectorSize)
396 {
397 TRACE("Buffer too small for sector, required %u bytes", block_header->sectorSize);
398 *length = block_header->sectorSize;
399
400 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_BUFFER_TOO_SMALL");
402 }
403
404 // Check if block is cached
405 TRACE("Checking if block is cached");
406 block = find_in_cache_uint64(&ctx->block_cache, block_offset);
407
408 if(block != NULL)
409 {
410 TRACE("Getting data from cache");
411 memcpy(data, block + offset * block_header->sectorSize, block_header->sectorSize);
412 *length = block_header->sectorSize;
413
414 TRACE("Exiting aaruf_read_sector() = AARUF_STATUS_OK");
415 return AARUF_STATUS_OK;
416 }
417
418 // Decompress block
419 switch(block_header->compression)
420 {
421 case None:
422 TRACE("Allocating memory for block");
423 block = (uint8_t *)malloc(block_header->length);
424 if(block == NULL)
425 {
426 FATAL("Not enough memory for block");
427
428 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
430 }
431
432 TRACE("Reading block into memory");
433 read_bytes = fread(block, 1, block_header->length, ctx->imageStream);
434
435 if(read_bytes != block_header->length)
436 {
437 FATAL("Could not read block");
438 free(block);
439
440 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_READ_BLOCK");
442 }
443
444 break;
445 case Lzma:
446 if(block_header->cmpLength <= LZMA_PROPERTIES_LENGTH || block_header->length == 0)
447 {
448 FATAL("Invalid LZMA block lengths (cmpLength=%u, length=%u)", block_header->cmpLength,
449 block_header->length);
450
451 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
453 }
454
455 lzma_size = block_header->cmpLength - LZMA_PROPERTIES_LENGTH;
456 TRACE("Allocating memory for compressed data of size %zu bytes", lzma_size);
457 cmp_data = malloc(lzma_size);
458
459 if(cmp_data == NULL)
460 {
461 FATAL("Cannot allocate memory for block...");
462
463 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
465 }
466
467 TRACE("Allocating memory for block of size %zu bytes", block_header->length);
468 block = malloc(block_header->length);
469 if(block == NULL)
470 {
471 FATAL("Cannot allocate memory for block...");
472 free(cmp_data);
473
474 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
476 }
477
478 read_bytes = fread(lzma_properties, 1, LZMA_PROPERTIES_LENGTH, ctx->imageStream);
479
480 if(read_bytes != LZMA_PROPERTIES_LENGTH)
481 {
482 FATAL("Could not read LZMA properties...");
483 free(block);
484 free(cmp_data);
485
486 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
488 }
489
490 read_bytes = fread(cmp_data, 1, lzma_size, ctx->imageStream);
491 if(read_bytes != lzma_size)
492 {
493 FATAL("Could not read compressed block...");
494 free(cmp_data);
495 free(block);
496
497 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
499 }
500
501 TRACE("Decompressing block of size %zu bytes", block_header->length);
502 read_bytes = block_header->length;
503 error_no = aaruf_lzma_decode_buffer(block, &read_bytes, cmp_data, &lzma_size, lzma_properties,
505
506 if(error_no != 0)
507 {
508 FATAL("Got error %d from LZMA...", error_no);
509 free(cmp_data);
510 free(block);
511
512 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
514 }
515
516 if(read_bytes != block_header->length)
517 {
518 FATAL("Error decompressing block, should be {0} bytes but got {1} bytes...");
519 free(cmp_data);
520 free(block);
521
522 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
524 }
525
526 free(cmp_data);
527
528 break;
529 case Flac:
530 TRACE("Allocating memory for compressed data of size %zu bytes", block_header->cmpLength);
531 cmp_data = malloc(block_header->cmpLength);
532
533 if(cmp_data == NULL)
534 {
535 FATAL("Cannot allocate memory for block...");
536
537 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
539 }
540
541 TRACE("Allocating memory for block of size %zu bytes", block_header->length);
542 block = malloc(block_header->length);
543 if(block == NULL)
544 {
545 FATAL("Cannot allocate memory for block...");
546 free(cmp_data);
547
548 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
550 }
551
552 TRACE("Reading compressed data into memory");
553 read_bytes = fread(cmp_data, 1, block_header->cmpLength, ctx->imageStream);
554 if(read_bytes != block_header->cmpLength)
555 {
556 FATAL("Could not read compressed block...");
557 free(cmp_data);
558 free(block);
559
560 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
562 }
563
564 TRACE("Decompressing block of size %zu bytes", block_header->length);
565 read_bytes =
566 aaruf_flac_decode_redbook_buffer(block, block_header->length, cmp_data, block_header->cmpLength);
567
568 if(read_bytes != block_header->length)
569 {
570 FATAL("Error decompressing block, should be {0} bytes but got {1} bytes...");
571 free(cmp_data);
572 free(block);
573
574 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK");
576 }
577
578 free(cmp_data);
579
580 break;
581 default:
582 FATAL("Unsupported compression %d", block_header->compression);
583 TRACE("Exiting aaruf_read_sector() = AARUF_ERROR_UNSUPPORTED_COMPRESSION");
585 }
586
587 // Add block to cache
588 TRACE("Adding block to cache");
589 add_to_cache_uint64(&ctx->block_cache, block_offset, block);
590
591 memcpy(data, block + offset * block_header->sectorSize, block_header->sectorSize);
592 *length = block_header->sectorSize;
593
594 TRACE("Exiting aaruf_read_sector() = AARUF_STATUS_OK");
595 return AARUF_STATUS_OK;
596}
597
670AARU_EXPORT int32_t AARU_CALL aaruf_read_track_sector(void *context, uint8_t *data, const uint64_t sector_address,
671 uint32_t *length, const uint8_t track, uint8_t *sector_status)
672{
673 const uint32_t initial_length = length == NULL ? 0U : *length;
674
675 TRACE("Entering aaruf_read_track_sector(%p, %p, %" PRIu64 ", %u, %d)", context, data, sector_address,
676 initial_length, track);
677
678 if(context == NULL)
679 {
680 FATAL("Invalid context");
681
682 TRACE("Exiting aaruf_read_track_sector() = AARUF_ERROR_NOT_AARUFORMAT");
684 }
685
686 aaruformat_context *ctx = context;
687
688 if(length == NULL)
689 {
690 FATAL("Invalid length pointer");
691
692 TRACE("Exiting aaruf_read_track_sector() = AARUF_ERROR_INCORRECT_DATA_SIZE");
694 }
695
696 // Not a libaaruformat context
697 if(ctx->magic != AARU_MAGIC)
698 {
699 FATAL("Invalid context");
700
701 TRACE("Exiting aaruf_read_track_sector() = AARUF_ERROR_NOT_AARUFORMAT");
703 }
704
706 {
707 FATAL("Incorrect media type %d, expected OpticalDisc", ctx->image_info.MetadataMediaType);
708
709 TRACE("Exiting aaruf_read_track_sector() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
711 }
712
713 for(int i = 0; i < ctx->number_of_data_tracks; i++)
714 if(ctx->data_tracks[i].sequence == track)
715 return aaruf_read_sector(context, ctx->data_tracks[i].start + sector_address, false, data, length,
716 sector_status);
717
718 TRACE("Track %d not found", track);
719 TRACE("Exiting aaruf_read_track_sector() = AARUF_ERROR_TRACK_NOT_FOUND");
721}
722
826AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_long(void *context, const uint64_t sector_address, bool negative,
827 uint8_t *data, uint32_t *length, uint8_t *sector_status)
828{
829 const uint32_t initial_length = length == NULL ? 0U : *length;
830
831 TRACE("Entering aaruf_read_sector_long(%p, %" PRIu64 ", %d, %p, %u)", context, sector_address, data,
832 initial_length);
833
834 const aaruformat_context *ctx = NULL;
835 uint32_t bare_length = 0;
836 uint32_t tag_length = 0;
837 uint8_t *bare_data = NULL;
838 int32_t res = 0;
839 int32_t query_status;
840 TrackEntry trk;
841 int i = 0;
842 bool trk_found = false;
843
844 if(context == NULL)
845 {
846 FATAL("Invalid context");
847
848 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_AARUFORMAT");
850 }
851
852 ctx = context;
853
854 if(length == NULL)
855 {
856 FATAL("Invalid length pointer");
857
858 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE");
860 }
861
862 // Not a libaaruformat context
863 if(ctx->magic != AARU_MAGIC)
864 {
865 FATAL("Invalid context");
866
867 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_AARUFORMAT");
869 }
870
871 if(negative && sector_address > ctx->user_data_ddt_header.negative)
872 {
873 FATAL("Sector address out of bounds");
874
875 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
877 }
878
879 if(!negative && sector_address > ctx->image_info.Sectors + ctx->user_data_ddt_header.overflow - 1)
880 {
881 FATAL("Sector address out of bounds");
882
883 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
885 }
886
887 uint64_t corrected_sector_address = sector_address;
888
889 // Calculate positive or negative sector
890 if(negative)
891 corrected_sector_address = ctx->user_data_ddt_header.negative - sector_address;
892 else
893 corrected_sector_address += ctx->user_data_ddt_header.negative;
894
895 switch(ctx->image_info.MetadataMediaType)
896 {
897 case OpticalDisc:
898 if(ctx->image_info.MediaType == DVDROM || ctx->image_info.MediaType == PS2DVD ||
899 ctx->image_info.MediaType == SACD || ctx->image_info.MediaType == PS3DVD ||
900 ctx->image_info.MediaType == DVDR || ctx->image_info.MediaType == DVDRW ||
905 ctx->image_info.MediaType == Nuon)
906 {
907 if(ctx->sector_id == NULL || ctx->sector_ied == NULL || ctx->sector_cpr_mai == NULL ||
908 ctx->sector_edc == NULL)
909 return aaruf_read_sector(context, sector_address, negative, data, length, sector_status);
910
911 if(*length < 2064 || data == NULL)
912 {
913 *length = 2064;
914 FATAL("Buffer too small for sector, required %u bytes", *length);
915
916 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL");
918 }
919
920 bare_length = 0;
921 query_status = aaruf_read_sector(context, sector_address, negative, NULL, &bare_length, sector_status);
922
923 if(query_status != AARUF_ERROR_BUFFER_TOO_SMALL && query_status != AARUF_STATUS_OK)
924 {
925 TRACE("Exiting aaruf_read_sector_long() = %d", query_status);
926 return query_status;
927 }
928
929 if(bare_length == 0)
930 {
931 FATAL("Invalid bare sector length (0)");
932
933 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE");
935 }
936
937 TRACE("Allocating memory for bare data");
938 bare_data = (uint8_t *)malloc(bare_length);
939
940 if(bare_data == NULL)
941 {
942 FATAL("Could not allocate memory for bare data");
943
944 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
946 }
947
948 res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length, sector_status);
949
950 if(res != AARUF_STATUS_OK)
951 {
952 *length = 2064;
953 free(bare_data);
954
955 TRACE("Exiting aaruf_read_sector_long() = %d", res);
956 return res;
957 }
958
959 memcpy(data, ctx->sector_id + corrected_sector_address * 4, 4);
960 memcpy(data + 4, ctx->sector_ied + corrected_sector_address * 2, 2);
961 memcpy(data + 6, ctx->sector_cpr_mai + corrected_sector_address * 6, 6);
962 memcpy(data + 12, bare_data, 2048);
963 memcpy(data + 2060, ctx->sector_edc + corrected_sector_address * 4, 4);
964
965 *length = 2064;
966
967 free(bare_data);
968 return AARUF_STATUS_OK;
969 }
970
971 if(*length < 2352 || data == NULL)
972 {
973 *length = 2352;
974 FATAL("Buffer too small for sector, required %u bytes", *length);
975
976 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL");
978 }
979
980 if((ctx->sector_suffix == NULL || ctx->sector_prefix == NULL) &&
981 (ctx->sector_suffix_ddt == NULL || ctx->sector_prefix_ddt == NULL) &&
982 (ctx->sector_suffix_ddt2 == NULL || ctx->sector_prefix_ddt2 == NULL))
983 return aaruf_read_sector(context, sector_address, negative, data, length, sector_status);
984
985 bare_length = 0;
986 query_status = aaruf_read_sector(context, sector_address, negative, NULL, &bare_length, sector_status);
987
988 if(query_status != AARUF_ERROR_BUFFER_TOO_SMALL && query_status != AARUF_STATUS_OK)
989 {
990 TRACE("Exiting aaruf_read_sector_long() = %d", query_status);
991 return query_status;
992 }
993
994 if(bare_length == 0)
995 {
996 FATAL("Invalid bare sector length (0)");
997
998 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1000 }
1001
1002 TRACE("Allocating memory for bare data");
1003 bare_data = (uint8_t *)malloc(bare_length);
1004
1005 if(bare_data == NULL)
1006 {
1007 FATAL("Could not allocate memory for bare data");
1008
1009 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1011 }
1012
1013 res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length, sector_status);
1014
1015 if(res != AARUF_STATUS_OK)
1016 {
1017 free(bare_data);
1018
1019 TRACE("Exiting aaruf_read_sector_long() = %d", res);
1020 return res;
1021 }
1022
1023 trk_found = false;
1024
1025 for(i = 0; i < ctx->number_of_data_tracks; i++)
1026 if(sector_address >= ctx->data_tracks[i].start && sector_address <= ctx->data_tracks[i].end)
1027 {
1028 trk_found = true;
1029 trk = ctx->data_tracks[i];
1030 break;
1031 }
1032
1033 if(!trk_found)
1034 {
1035 FATAL("Track not found");
1036 free(bare_data);
1037
1038 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_TRACK_NOT_FOUND");
1040 }
1041
1042 switch(trk.type)
1043 {
1044 case Audio:
1045 case Data:
1046 memcpy(data, bare_data, bare_length);
1047 *length = bare_length;
1048 free(bare_data);
1049 return res;
1050 case CdMode1:
1051 memcpy(data + 16, bare_data, 2048);
1052
1053 if(ctx->sector_prefix_ddt2 != NULL)
1054 {
1055 const uint64_t prefix_ddt_entry = ctx->sector_prefix_ddt2[corrected_sector_address];
1056 const uint32_t prefix_status = prefix_ddt_entry >> 60;
1057 const uint64_t prefix_index = prefix_ddt_entry & 0x0FFFFFFFFFFFFFFF;
1058
1059 if(prefix_status == SectorStatusMode1Correct)
1060 {
1061 aaruf_ecc_cd_reconstruct_prefix(data, trk.type, sector_address);
1062 res = AARUF_STATUS_OK;
1063 }
1064 else if(prefix_status == SectorStatusNotDumped)
1066 else
1067 memcpy(data, ctx->sector_prefix + prefix_index * 16, 16);
1068 }
1069 else if(ctx->sector_prefix != NULL)
1070 memcpy(data, ctx->sector_prefix + corrected_sector_address * 16, 16);
1071 else if(ctx->sector_prefix_ddt != NULL)
1072 {
1073 if((ctx->sector_prefix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Correct)
1074 {
1075 aaruf_ecc_cd_reconstruct_prefix(data, trk.type, sector_address);
1076 res = AARUF_STATUS_OK;
1077 }
1078 else if((ctx->sector_prefix_ddt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped)
1080 else
1081 memcpy(data,
1083 ((ctx->sector_prefix_ddt[corrected_sector_address] & CD_DFIX_MASK) - 1) * 16,
1084 16);
1085 }
1086 else
1087 {
1088 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_REACHED_UNREACHABLE_CODE");
1089 free(bare_data);
1091 }
1092
1093 if(res != AARUF_STATUS_OK)
1094 {
1095 *length = 2352;
1096 free(bare_data);
1097 return res;
1098 }
1099
1100 if(ctx->sector_suffix_ddt2 != NULL)
1101 {
1102 const uint64_t suffix_ddt_entry = ctx->sector_suffix_ddt2[corrected_sector_address];
1103 const uint64_t suffix_status = suffix_ddt_entry >> 60;
1104 const uint64_t suffix_index = suffix_ddt_entry & 0x0FFFFFFFFFFFFFFF;
1105
1106 if(suffix_status == SectorStatusMode1Correct)
1107 {
1109 res = AARUF_STATUS_OK;
1110 }
1111 else if(suffix_status == SectorStatusNotDumped)
1113 else
1114 memcpy(data + 2064, ctx->sector_suffix + suffix_index * 288, 288);
1115 }
1116 else if(ctx->sector_suffix != NULL)
1117 memcpy(data + 2064, ctx->sector_suffix + corrected_sector_address * 288, 288);
1118 else if(ctx->sector_suffix_ddt != NULL)
1119 {
1120 if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Correct)
1121 {
1123 res = AARUF_STATUS_OK;
1124 }
1125 else if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped)
1127 else
1128 memcpy(data + 2064,
1130 ((ctx->sector_suffix_ddt[corrected_sector_address] & CD_DFIX_MASK) - 1) * 288,
1131 288);
1132 }
1133 else
1134 {
1135 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_REACHED_UNREACHABLE_CODE");
1136 free(bare_data);
1138 }
1139
1140 *length = 2352;
1141 free(bare_data);
1142 return res;
1143 case CdMode2Formless:
1144 case CdMode2Form1:
1145 case CdMode2Form2:
1146 if(ctx->sector_prefix_ddt2 != NULL)
1147 {
1148 const uint64_t prefix_ddt_entry = ctx->sector_prefix_ddt2[corrected_sector_address];
1149 const uint64_t prefix_status = prefix_ddt_entry >> 60;
1150 const uint64_t prefix_index = prefix_ddt_entry & 0x0FFFFFFFFFFFFFFF;
1151
1152 if(prefix_status == SectorStatusMode2Form1Ok || prefix_status == SectorStatusMode2Form2Ok)
1153 {
1154 aaruf_ecc_cd_reconstruct_prefix(data, trk.type, sector_address);
1155 res = AARUF_STATUS_OK;
1156 }
1157 else if(prefix_status == SectorStatusNotDumped)
1159 else
1160 memcpy(data, ctx->sector_prefix + prefix_index * 16, 16);
1161 }
1162 else if(ctx->sector_prefix != NULL)
1163 memcpy(data, ctx->sector_prefix + corrected_sector_address * 16, 16);
1164 else if(ctx->sector_prefix_ddt != NULL)
1165 {
1166 if((ctx->sector_prefix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Correct)
1167 {
1168 aaruf_ecc_cd_reconstruct_prefix(data, trk.type, sector_address);
1169 res = AARUF_STATUS_OK;
1170 }
1171 else if((ctx->sector_prefix_ddt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped)
1173 else
1174 memcpy(data,
1176 ((ctx->sector_prefix_ddt[corrected_sector_address] & CD_DFIX_MASK) - 1) * 16,
1177 16);
1178 }
1179 else
1180 {
1181 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_REACHED_UNREACHABLE_CODE");
1182 free(bare_data);
1184 }
1185
1186 if(res != AARUF_STATUS_OK)
1187 {
1188 *length = 2352;
1189 free(bare_data);
1190 return res;
1191 }
1192
1193 if(ctx->mode2_subheaders != NULL && ctx->sector_suffix_ddt2 != NULL)
1194 {
1195 memcpy(data + 16, ctx->mode2_subheaders + corrected_sector_address * 8, 8);
1196 const uint64_t suffix_ddt_entry = ctx->sector_suffix_ddt2[corrected_sector_address];
1197 const uint64_t suffix_status = suffix_ddt_entry >> 60;
1198 const uint64_t suffix_index = suffix_ddt_entry & 0x0FFFFFFFFFFFFFFF;
1199
1200 if(suffix_status == SectorStatusMode2Form1Ok)
1201 {
1202 memcpy(data + 24, bare_data, 2048);
1204 }
1205 else if(suffix_status == SectorStatusMode2Form2Ok ||
1206 suffix_status == SectorStatusMode2Form2NoCrc)
1207 {
1208 memcpy(data + 24, bare_data, 2324);
1209 if(suffix_status == SectorStatusMode2Form2Ok)
1211 }
1212 else if(suffix_status == SectorStatusNotDumped)
1214 else
1215 // Mode 2 where ECC failed
1216 memcpy(data + 24, bare_data, 2328);
1217 }
1218 else if(ctx->mode2_subheaders != NULL && ctx->sector_suffix_ddt != NULL)
1219 {
1220 memcpy(data + 16, ctx->mode2_subheaders + corrected_sector_address * 8, 8);
1221
1222 if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form1Ok)
1223 {
1224 memcpy(data + 24, bare_data, 2048);
1226 }
1227 else if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form2Ok ||
1228 (ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form2NoCrc)
1229 {
1230 memcpy(data + 24, bare_data, 2324);
1231 if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == Mode2Form2Ok)
1233 }
1234 else if((ctx->sector_suffix_ddt[corrected_sector_address] & CD_XFIX_MASK) == NotDumped)
1236 else
1237 // Mode 2 where ECC failed
1238 memcpy(data + 24, bare_data, 2328);
1239 }
1240 else if(ctx->mode2_subheaders != NULL)
1241 {
1242 memcpy(data + 16, ctx->mode2_subheaders + corrected_sector_address * 8, 8);
1243 memcpy(data + 24, bare_data, 2328);
1244 }
1245 else
1246 memcpy(data + 16, bare_data, 2336);
1247
1248 *length = 2352;
1249 free(bare_data);
1250 return res;
1251 default:
1252 FATAL("Invalid track type %d", trk.type);
1253 free(bare_data);
1254
1255 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INVALID_TRACK_FORMAT");
1257 }
1258 case BlockMedia:
1259 switch(ctx->image_info.MediaType)
1260 {
1261 case AppleFileWare:
1262 case AppleProfile:
1263 case AppleSonySS:
1264 case AppleSonyDS:
1265 case AppleWidget:
1266 case PriamDataTower:
1267 if(ctx->sector_subchannel == NULL)
1268 return aaruf_read_sector(context, sector_address, negative, data, length, sector_status);
1269
1270 switch(ctx->image_info.MediaType)
1271 {
1272 case AppleFileWare:
1273 case AppleProfile:
1274 case AppleWidget:
1275 tag_length = 20;
1276 break;
1277 case AppleSonySS:
1278 case AppleSonyDS:
1279 tag_length = 12;
1280 break;
1281 case PriamDataTower:
1282 tag_length = 24;
1283 break;
1284 default:
1285 FATAL("Unsupported media type %d", ctx->image_info.MediaType);
1286
1287 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1289 }
1290
1291 bare_length = 512;
1292
1293 if(*length < tag_length + bare_length || data == NULL)
1294 {
1295 *length = tag_length + bare_length;
1296 FATAL("Buffer too small for sector, required %u bytes", *length);
1297
1298 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_BUFFER_TOO_SMALL");
1300 }
1301
1302 TRACE("Allocating memory for bare data of size %u bytes", bare_length);
1303 bare_data = malloc(bare_length);
1304
1305 if(bare_data == NULL)
1306 {
1307 FATAL("Could not allocate memory for bare data");
1308
1309 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1311 }
1312
1313 res = aaruf_read_sector(context, sector_address, negative, bare_data, &bare_length, sector_status);
1314
1315 if(res != AARUF_STATUS_OK)
1316 {
1317 free(bare_data);
1318
1319 TRACE("Exiting aaruf_read_sector_long() = %d", res);
1320 return res;
1321 }
1322
1323 if(bare_length != 512)
1324 {
1325 FATAL("Bare data length is %u, expected 512", bare_length);
1326 free(bare_data);
1327
1328 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1330 }
1331
1332 memcpy(data + bare_length, ctx->sector_subchannel + corrected_sector_address * tag_length,
1333 tag_length);
1334 memcpy(data, bare_data, bare_length);
1335 *length = tag_length + bare_length;
1336
1337 free(bare_data);
1338
1339 TRACE("Exiting aaruf_read_sector_long() = AARUF_STATUS_OK");
1340 return AARUF_STATUS_OK;
1341 default:
1342 FATAL("Incorrect media type %d for long sector reading", ctx->image_info.MediaType);
1343
1344 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1346 }
1347 default:
1348 FATAL("Incorrect media type %d for long sector reading", ctx->image_info.MediaType);
1349
1350 TRACE("Exiting aaruf_read_sector_long() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1352 }
1353}
1354
1474AARU_EXPORT int32_t AARU_CALL aaruf_read_sector_tag(const void *context, const uint64_t sector_address,
1475 const bool negative, uint8_t *buffer, uint32_t *length,
1476 const int32_t tag)
1477{
1478 const uint32_t initial_length = length == NULL ? 0U : *length;
1479
1480 TRACE("Entering aaruf_read_sector_tag(%p, %" PRIu64 ", %d, %p, %u, %d)", context, sector_address, negative, buffer,
1481 initial_length, tag);
1482
1483 const aaruformat_context *ctx = NULL;
1484
1485 if(context == NULL)
1486 {
1487 FATAL("Invalid context");
1488
1489 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_NOT_AARUFORMAT");
1491 }
1492
1493 ctx = context;
1494
1495 if(length == NULL)
1496 {
1497 FATAL("Invalid length pointer");
1498
1499 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1501 }
1502
1503 // Not a libaaruformat context
1504 if(ctx->magic != AARU_MAGIC)
1505 {
1506 FATAL("Invalid context");
1507
1508 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_NOT_AARUFORMAT");
1510 }
1511
1512 if(negative && sector_address > ctx->user_data_ddt_header.negative)
1513 {
1514 FATAL("Sector address out of bounds");
1515
1516 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
1518 }
1519
1520 if(!negative && sector_address > ctx->image_info.Sectors + ctx->user_data_ddt_header.overflow - 1)
1521 {
1522 FATAL("Sector address out of bounds");
1523
1524 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_OUT_OF_BOUNDS");
1526 }
1527
1528 uint64_t corrected_sector_address = sector_address;
1529
1530 // Calculate positive or negative sector
1531 if(negative)
1532 corrected_sector_address = ctx->user_data_ddt_header.negative - sector_address;
1533 else
1534 corrected_sector_address += ctx->user_data_ddt_header.negative;
1535
1536 switch(tag)
1537 {
1538 case CdTrackFlags:
1540 {
1541 FATAL("Invalid media type for tag");
1542 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1544 }
1545
1546 if(*length != 1 || buffer == NULL)
1547 {
1548 *length = 1;
1549 FATAL("Incorrect tag size");
1550 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1552 }
1553
1554 for(int i = 0; i < ctx->tracks_header.entries; i++)
1555 if(sector_address >= ctx->track_entries[i].start && sector_address <= ctx->track_entries[i].end)
1556 {
1557 buffer[0] = ctx->track_entries[i].flags;
1558 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1559 return AARUF_STATUS_OK;
1560 }
1561
1562 FATAL("Track not found");
1564 case CdTrackIsrc:
1566 {
1567 FATAL("Invalid media type for tag");
1568 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1570 }
1571
1572 if(*length != 12 || buffer == NULL)
1573 {
1574 *length = 12;
1575 FATAL("Incorrect tag size");
1576 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1578 }
1579
1580 for(int i = 0; i < ctx->tracks_header.entries; i++)
1581 if(sector_address >= ctx->track_entries[i].start && sector_address <= ctx->track_entries[i].end)
1582 {
1583 memcpy(buffer, ctx->track_entries[i].isrc, 12);
1584 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1585 return AARUF_STATUS_OK;
1586 }
1587
1588 FATAL("Track not found");
1592 {
1593 FATAL("Invalid media type for tag");
1594 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1596 }
1597
1598 if(*length != 96 || buffer == NULL)
1599 {
1600 *length = 96;
1601 FATAL("Incorrect tag size");
1602 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1604 }
1605
1606 if(ctx->sector_subchannel == NULL)
1607 {
1608 FATAL("Sector tag not found");
1609 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1611 }
1612
1613 memcpy(buffer, ctx->sector_subchannel + corrected_sector_address * 96, 96);
1614 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1615 return AARUF_STATUS_OK;
1616 case DvdCmi:
1618 {
1619 FATAL("Invalid media type for tag");
1620 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1622 }
1623
1624 if(*length != 1 || buffer == NULL)
1625 {
1626 *length = 1;
1627 FATAL("Incorrect tag size");
1628 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1630 }
1631
1632 if(ctx->sector_cpr_mai == NULL)
1633 {
1634 FATAL("Sector tag not found");
1635 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1637 }
1638
1639 memcpy(buffer, ctx->sector_cpr_mai + corrected_sector_address * 6, 1);
1640 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1641 return AARUF_STATUS_OK;
1644 {
1645 FATAL("Invalid media type for tag");
1646 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1648 }
1649
1650 if(*length != 1 || buffer == NULL)
1651 {
1652 *length = 1;
1653 FATAL("Incorrect tag size");
1654 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1656 }
1657
1658 if(ctx->sector_id == NULL)
1659 {
1660 FATAL("Sector tag not found");
1661 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1663 }
1664
1665 memcpy(buffer, ctx->sector_id + corrected_sector_address * 4, 1);
1666 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1667 return AARUF_STATUS_OK;
1668 case DvdSectorNumber:
1670 {
1671 FATAL("Invalid media type for tag");
1672 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1674 }
1675
1676 if(*length != 3 || buffer == NULL)
1677 {
1678 *length = 3;
1679 FATAL("Incorrect tag size");
1680 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1682 }
1683
1684 if(ctx->sector_id == NULL)
1685 {
1686 FATAL("Sector tag not found");
1687 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1689 }
1690
1691 memcpy(buffer, ctx->sector_id + corrected_sector_address * 4 + 1, 3);
1692 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1693 return AARUF_STATUS_OK;
1694 case DvdSectorIedAaru:
1696 {
1697 FATAL("Invalid media type for tag");
1698 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1700 }
1701
1702 if(*length != 2 || buffer == NULL)
1703 {
1704 *length = 2;
1705 FATAL("Incorrect tag size");
1706 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1708 }
1709
1710 if(ctx->sector_ied == NULL)
1711 {
1712 FATAL("Sector tag not found");
1713 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1715 }
1716
1717 memcpy(buffer, ctx->sector_ied + corrected_sector_address * 2, 2);
1718 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1719 return AARUF_STATUS_OK;
1720 case DvdSectorEdcAaru:
1722 {
1723 FATAL("Invalid media type for tag");
1724 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1726 }
1727
1728 if(*length != 4 || buffer == NULL)
1729 {
1730 *length = 4;
1731 FATAL("Incorrect tag size");
1732 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1734 }
1735
1736 if(ctx->sector_edc == NULL)
1737 {
1738 FATAL("Sector tag not found");
1739 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1741 }
1742
1743 memcpy(buffer, ctx->sector_edc + corrected_sector_address * 4, 4);
1744 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1745 return AARUF_STATUS_OK;
1748 {
1749 FATAL("Invalid media type for tag");
1750 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1752 }
1753
1754 if(*length != 5 || buffer == NULL)
1755 {
1756 *length = 5;
1757 FATAL("Incorrect tag size");
1758 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1760 }
1761
1762 if(ctx->sector_decrypted_title_key == NULL)
1763 {
1764 FATAL("Sector tag not found");
1765 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1767 }
1768
1769 memcpy(buffer, ctx->sector_decrypted_title_key + corrected_sector_address * 5, 5);
1770 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1771 return AARUF_STATUS_OK;
1772 case AppleSonyTagAaru:
1774 {
1775 FATAL("Invalid media type for tag");
1776 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1778 }
1779
1780 if(*length != 12 || buffer == NULL)
1781 {
1782 *length = 12;
1783 FATAL("Incorrect tag size");
1784 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1786 }
1787
1788 if(ctx->sector_subchannel == NULL)
1789 {
1790 FATAL("Sector tag not found");
1791 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1793 }
1794
1795 memcpy(buffer, ctx->sector_subchannel + corrected_sector_address * 12, 12);
1796 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1797 return AARUF_STATUS_OK;
1800 {
1801 FATAL("Invalid media type for tag");
1802 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1804 }
1805
1806 if(*length != 20 || buffer == NULL)
1807 {
1808 *length = 20;
1809 FATAL("Incorrect tag size");
1810 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1812 }
1813
1814 if(ctx->sector_subchannel == NULL)
1815 {
1816 FATAL("Sector tag not found");
1817 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1819 }
1820
1821 memcpy(buffer, ctx->sector_subchannel + corrected_sector_address * 20, 20);
1822 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1823 return AARUF_STATUS_OK;
1826 {
1827 FATAL("Invalid media type for tag");
1828 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_MEDIA_TYPE");
1830 }
1831
1832 if(*length != 24 || buffer == NULL)
1833 {
1834 *length = 24;
1835 FATAL("Incorrect tag size");
1836 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_INCORRECT_DATA_SIZE");
1838 }
1839
1840 if(ctx->sector_subchannel == NULL)
1841 {
1842 FATAL("Sector tag not found");
1843 TRACE("Exiting aaruf_read_sector_tag() = AARUF_ERROR_SECTOR_TAG_NOT_PRESENT");
1845 }
1846
1847 memcpy(buffer, ctx->sector_subchannel + corrected_sector_address * 24, 24);
1848 TRACE("Exiting aaruf_read_sector_tag() = AARUF_STATUS_OK");
1849 return AARUF_STATUS_OK;
1850 default:
1851 TRACE("Do not know how to read sector tag %d", tag);
1853 }
1854}
#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
#define AARU_CALL
Definition decls.h:45
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:392
#define AARU_EXPORT
Definition decls.h:54
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:459
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
@ 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
@ DvdSectorIedAaru
DVD sector ID error detection, 2 bytes.
Definition aaru.h:966
@ CdTrackFlags
Track flags (audio/data, copy permitted, pre-emphasis)
Definition aaru.h:959
@ DvdSectorEdcAaru
DVD sector EDC, 4 bytes.
Definition aaru.h:967
@ DvdCmi
DVD Copyright Management Information (CSS)
Definition aaru.h:960
@ CdSectorSubchannelAaru
96 raw subchannel bytes (P-W)
Definition aaru.h:956
@ DvdSectorNumber
DVD sector number, 3 bytes.
Definition aaru.h:965
@ CdTrackIsrc
Track ISRC (12 ASCII chars, no terminator)
Definition aaru.h:957
@ PriamDataTowerTagAaru
Priam DataTower sector tags, 24 bytes.
Definition aaru.h:969
@ AppleProfileTagAaru
Apple's Profile sector tags, 20 bytes.
Definition aaru.h:968
@ DvdSectorInformation
DVD sector information, 1 bytes.
Definition aaru.h:964
@ DvdTitleKeyDecrypted
Decrypted DVD sector title key, 5 bytes.
Definition aaru.h:963
@ AppleSonyTagAaru
Apple's Sony sector tags, 12 bytes (address prolog + checksum)
Definition aaru.h:948
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_sector(void *context, const uint64_t sector_address, bool negative, uint8_t *data, uint32_t *length, uint8_t *sector_status)
Reads a sector from the AaruFormat image.
Definition read.c:253
int32_t aaruf_read_sector_long(void *context, const uint64_t sector_address, bool negative, uint8_t *data, uint32_t *length, uint8_t *sector_status)
Reads a complete sector with all metadata from the AaruFormat image.
Definition read.c:826
int32_t aaruf_read_track_sector(void *context, uint8_t *data, const uint64_t sector_address, uint32_t *length, const uint8_t track, uint8_t *sector_status)
Reads a sector from a specific track in the AaruFormat image.
Definition read.c:670
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:1474
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:933
uint8_t MetadataMediaType
Media type for sidecar generation (internal archival use)
Definition aaru.h:934
uint32_t SectorSize
Size of each logical sector in bytes (512, 2048, 2352, 4096, etc.)
Definition aaru.h:927
uint64_t Sectors
Total count of addressable logical sectors/blocks.
Definition aaru.h:926
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