libaaruformat 1.0
Aaru Data Preservation Suite - Format Library
Loading...
Searching...
No Matches
open.c
Go to the documentation of this file.
1/*
2 * This file is part of the Aaru Data Preservation Suite.
3 * Copyright (c) 2019-2026 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 <errno.h>
20#include <inttypes.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#if defined(_WIN32) || defined(_WIN64)
26#include <windows.h>
27#endif
28
29#include <aaruformat.h>
30
31#include "erasure_internal.h"
32#include "internal.h"
33#include "log.h"
34#include "utarray.h"
35
36static inline void aaruf_set_open_error(const int error_code)
37{
38 errno = error_code;
39#if defined(_WIN32) || defined(_WIN64)
40 SetLastError((DWORD)error_code);
41#endif
42}
43
45{
46 if(ctx == NULL) return;
47
48 if(ctx->imageStream != NULL)
49 {
50 fclose(ctx->imageStream);
51 ctx->imageStream = NULL;
52 }
53
54 free(ctx->readableSectorTags);
55 ctx->readableSectorTags = NULL;
56
57 free(ctx);
58}
59
236AARU_EXPORT void *AARU_CALL aaruf_open(const char *filepath, const bool resume_mode,
237 const char *options) // NOLINT(readability-function-size)
238{
239 aaruformat_context *ctx = NULL;
240 int error_no = 0;
241 size_t read_bytes = 0;
242 aaru_off_t pos = 0;
243 int i = 0;
244 uint32_t signature = 0;
245 UT_array *index_entries = NULL;
246
247 TRACE("Entering aaruf_open(%s)", filepath);
249
250 TRACE("Allocating memory for context");
251 ctx = (aaruformat_context *)malloc(sizeof(aaruformat_context));
252
253 if(ctx == NULL)
254 {
255 FATAL("Not enough memory to create context");
257
258 TRACE("Exiting aaruf_open() = NULL");
259 return NULL;
260 }
261
262 memset(ctx, 0, sizeof(aaruformat_context));
263
264 TRACE("Opening file %s", filepath);
265 if(resume_mode)
266 ctx->imageStream = fopen(filepath, "r+b");
267 else
268 ctx->imageStream = fopen(filepath, "rb");
269
270 if(ctx->imageStream == NULL)
271 {
272 FATAL("Error %d opening file %s for reading", errno, filepath);
273 error_no = errno;
275 aaruf_set_open_error(error_no);
276
277 TRACE("Exiting aaruf_open() = NULL");
278 return NULL;
279 }
280
281 TRACE("Reading header at position 0");
282 aaruf_fseek(ctx->imageStream, 0, SEEK_SET);
283 read_bytes = fread(&ctx->header, 1, sizeof(AaruHeader), ctx->imageStream);
284
285 if(read_bytes != sizeof(AaruHeader))
286 {
287 FATAL("Could not read header");
290
291 TRACE("Exiting aaruf_open() = NULL");
292 return NULL;
293 }
294
296 {
297 /* Primary header corrupt — try recovery footer backup header */
298 TRACE("Primary header invalid, trying recovery footer backup header");
299
300 aaruf_fseek(ctx->imageStream, 0, SEEK_END);
301 int64_t file_size = aaruf_ftell(ctx->imageStream);
302
303 if(file_size >= (int64_t)sizeof(AaruRecoveryFooter))
304 {
306 (aaru_off_t)(file_size - (int64_t)sizeof(AaruRecoveryFooter)), SEEK_SET);
307 AaruRecoveryFooter recovery_footer;
308 if(fread(&recovery_footer, sizeof(AaruRecoveryFooter), 1, ctx->imageStream) == 1 &&
309 recovery_footer.footerMagic == AARU_RECOVERY_FOOTER_MAGIC)
310 {
311 /* Verify the backup header's CRC matches what was recorded */
312 uint64_t backup_crc = aaruf_crc64_data(
313 (const uint8_t *)&recovery_footer.backupHeader, sizeof(AaruHeaderV2));
314 if(backup_crc == recovery_footer.headerCrc64 &&
315 (recovery_footer.backupHeader.identifier == DIC_MAGIC ||
316 recovery_footer.backupHeader.identifier == AARU_MAGIC))
317 {
318 TRACE("Recovery footer backup header valid, using it");
319 memcpy(&ctx->header, &recovery_footer.backupHeader, sizeof(AaruHeaderV2));
320 /* Seek past the header for the next read */
321 aaruf_fseek(ctx->imageStream, (aaru_off_t)sizeof(AaruHeaderV2), SEEK_SET);
322 }
323 else
324 {
325 FATAL("Recovery footer backup header also invalid");
328 TRACE("Exiting aaruf_open() = NULL");
329 return NULL;
330 }
331 }
332 else
333 {
334 FATAL("No recovery footer found, cannot recover from corrupt header");
337 TRACE("Exiting aaruf_open() = NULL");
338 return NULL;
339 }
340 }
341 else
342 {
343 FATAL("Incorrect identifier for AaruFormat file: %8.8s", (char *)&ctx->header.identifier);
346 TRACE("Exiting aaruf_open() = NULL");
347 return NULL;
348 }
349 }
350
351 if(ctx->header.imageMajorVersion < AARUF_VERSION_V2 && resume_mode)
352 {
353 TRACE("Cannot write to old images");
356 TRACE("Exiting aaruf_open() = NULL");
357 return NULL;
358 }
359
360 // Read new header version
362 {
363 TRACE("Reading new header version at position 0");
364 aaruf_fseek(ctx->imageStream, 0, SEEK_SET);
365 read_bytes = fread(&ctx->header, 1, sizeof(AaruHeaderV2), ctx->imageStream);
366
367 if(read_bytes != sizeof(AaruHeaderV2))
368 {
371
372 return NULL;
373 }
374 }
375
377 {
378 FATAL("Incompatible AaruFormat version %d.%d found, maximum supported is %d.%d", ctx->header.imageMajorVersion,
382
383 TRACE("Exiting aaruf_open() = NULL");
384 return NULL;
385 }
386
387 // Check feature compatibility for V2+ images
389 {
390 uint64_t unknown_incompat = ctx->header.featureIncompatible & ~AARUF_KNOWN_INCOMPAT_FEATURES;
391
392 if(unknown_incompat != 0)
393 {
394 FATAL("Image requires unsupported incompatible features: 0x%016" PRIX64, unknown_incompat);
397
398 TRACE("Exiting aaruf_open() = NULL");
399 return NULL;
400 }
401
402 uint64_t unknown_rocompat = ctx->header.featureCompatibleRo & ~AARUF_KNOWN_ROCOMPAT_FEATURES;
403
404 if(unknown_rocompat != 0)
405 {
406 if(resume_mode)
407 {
408 FATAL("Image has unsupported read-only compatible features: 0x%016" PRIX64 ", cannot open for writing",
409 unknown_rocompat);
412
413 TRACE("Exiting aaruf_open() = NULL");
414 return NULL;
415 }
416
417 TRACE("Image has unsupported read-only compatible features: 0x%016" PRIX64 ", forcing read-only",
418 unknown_rocompat);
419 }
420 }
421
422 TRACE("Opening image version %d.%d", ctx->header.imageMajorVersion, ctx->header.imageMinorVersion);
423
424 TRACE("Allocating memory for readable sector tags bitmap");
425 ctx->readableSectorTags = (bool *)malloc(sizeof(bool) * MaxSectorTag);
426
427 if(ctx->readableSectorTags == NULL)
428 {
429 FATAL("Could not allocate memory for readable sector tags bitmap");
432
433 TRACE("Exiting aaruf_open() = NULL");
434 return NULL;
435 }
436
437 memset(ctx->readableSectorTags, 0, sizeof(bool) * MaxSectorTag);
438
439 TRACE("Setting up image info");
440
441 // Handle application name based on image version
442 memset(ctx->image_info.Application, 0, 64);
443
445 {
446 // Version 2+: application name is UTF-8, direct copy
447 TRACE("Converting application name (v2+): UTF-8 direct copy");
448 size_t copy_len = AARU_HEADER_APP_NAME_LEN < 63 ? AARU_HEADER_APP_NAME_LEN : 63;
449 memcpy(ctx->image_info.Application, ctx->header.application, copy_len);
450 ctx->image_info.Application[63] = '\0';
451 }
452 else
453 {
454 // Version 1: application name is UTF-16LE, convert by taking every other byte
455 TRACE("Converting application name (v1): UTF-16LE to ASCII");
456 int dest_idx = 0;
457 for(int j = 0; j < AARU_HEADER_APP_NAME_LEN && dest_idx < 63; j += 2)
458 // Take the low byte, skip the high byte (assuming it's 0x00 for ASCII)
459 if(ctx->header.application[j] != 0)
460 ctx->image_info.Application[dest_idx++] = ctx->header.application[j];
461 else
462 // Stop at null terminator
463 break;
464 ctx->image_info.Application[dest_idx] = '\0';
465 }
466
467 // Set application version string directly in the fixed-size array
468 memset(ctx->image_info.ApplicationVersion, 0, 32);
471
472 // Set image version string directly in the fixed-size array
473 memset(ctx->image_info.Version, 0, 32);
474 sprintf(ctx->image_info.Version, "%d.%d", ctx->header.imageMajorVersion, ctx->header.imageMinorVersion);
475
477
478 // Read the index header
479 TRACE("Reading index header at position %" PRIu64, ctx->header.indexOffset);
480 if(aaruf_fseek(ctx->imageStream, (aaru_off_t)ctx->header.indexOffset, SEEK_SET) != 0)
481 {
484
485 return NULL;
486 }
487
488 pos = aaruf_ftell(ctx->imageStream);
489 if(pos != ctx->header.indexOffset)
490 {
493
494 return NULL;
495 }
496
497 read_bytes = fread(&signature, 1, sizeof(uint32_t), ctx->imageStream);
498
499 if(read_bytes != sizeof(uint32_t) ||
500 (signature != IndexBlock && signature != IndexBlock2 && signature != IndexBlock3))
501 {
502 FATAL("Could not read index header or incorrect identifier %4.4s", (char *)&signature);
505
506 TRACE("Exiting aaruf_open() = NULL");
507 return NULL;
508 }
509
510 if(signature == IndexBlock)
511 index_entries = process_index_v1(ctx);
512 else if(signature == IndexBlock2)
513 index_entries = process_index_v2(ctx);
514 else if(signature == IndexBlock3)
515 index_entries = process_index_v3(ctx);
516
517 if(index_entries == NULL)
518 {
519 FATAL("Could not process index.");
520 utarray_free(index_entries);
523
524 TRACE("Exiting aaruf_open() = NULL");
525 return NULL;
526 }
527
528 TRACE("Index at %" PRIu64 " contains %d entries", ctx->header.indexOffset, utarray_len(index_entries));
529
530 for(i = 0; i < utarray_len(index_entries); i++)
531 {
532 IndexEntry *entry = utarray_eltptr(index_entries, i);
533 TRACE("Block type %4.4s with data type %d is indexed to be at %" PRIu64 "", (char *)&entry->blockType,
534 entry->dataType, entry->offset);
535 }
536
537 /* Load the erasure coding recovery map from the footer at the end of the file before processing the blocks, so
538 * the blocks found damaged can be recovered while they are processed */
539 ec_load_ecmb(ctx);
540
541 bool found_user_data_ddt = false;
542 bool has_flux_block = false;
543 ctx->image_info.ImageSize = 0;
544 for(i = 0; i < utarray_len(index_entries); i++)
545 {
546 IndexEntry *entry = utarray_eltptr(index_entries, i);
547
548 if(aaruf_fseek(ctx->imageStream, (aaru_off_t)entry->offset, SEEK_SET) != 0 ||
549 aaruf_ftell(ctx->imageStream) != (aaru_off_t)entry->offset)
550 {
551 TRACE("Could not seek to %" PRIu64 " as indicated by index entry %d, continuing...", entry->offset, i);
552
553 continue;
554 }
555
556 TRACE("Processing block type %4.4s with data type %d at position %" PRIu64 "", (char *)&entry->blockType,
557 entry->dataType, entry->offset);
558 switch(entry->blockType)
559 {
560 case DataBlock:
561 if(entry->dataType == kDataTypeUserData && ctx->header.biggestSectorSize > 0) break;
562
563 error_no = process_data_block(ctx, entry);
564
565 if(error_no != AARUF_STATUS_OK)
566 {
567 utarray_free(index_entries);
569 aaruf_set_open_error(error_no);
570
571 return NULL;
572 }
573
574 break;
575
577 error_no = process_ddt_v1(ctx, entry, &found_user_data_ddt);
578
579 if(error_no != AARUF_STATUS_OK)
580 {
581 utarray_free(index_entries);
583 aaruf_set_open_error(error_no);
584
585 return NULL;
586 }
587
588 break;
590 error_no = process_ddt_v2(ctx, entry, &found_user_data_ddt);
591
592 if(error_no != AARUF_STATUS_OK)
593 {
594 utarray_free(index_entries);
596 aaruf_set_open_error(error_no);
597
598 return NULL;
599 }
600
601 switch(entry->dataType)
602 {
607
608 break;
616 break;
617 default:
618 break;
619 }
620
621 break;
622 case GeometryBlock:
623 process_geometry_block(ctx, entry);
624
625 break;
626 case MetadataBlock:
627 process_metadata_block(ctx, entry);
628
629 break;
630 case TracksBlock:
631 process_tracks_block(ctx, entry);
632
633 break;
634 case CicmBlock:
635 process_cicm_block(ctx, entry);
636
637 break;
640
641 break;
643 process_dpm_block(ctx, entry);
644
645 break;
646 // Dump hardware block
648 process_dumphw_block(ctx, entry);
649
650 break;
651 case ChecksumBlock:
652 process_checksum_block(ctx, entry);
653
654 break;
655 case TapeFileBlock:
656 process_tape_files_block(ctx, entry);
657
658 break;
661
662 break;
663 case FluxDataBlock:
664 // Store the FluxDataBlock offset for lazy loading
665 // Don't read flux entries during open - load them on-demand when actually needed
666 // This avoids unnecessary I/O if flux data is never accessed
667 has_flux_block = true;
668 break;
669 default:
670 TRACE("Unhandled block type %4.4s with data type %d is indexed to be at %" PRIu64 "",
671 (char *)&entry->blockType, entry->dataType, entry->offset);
672 break;
673 }
674 }
675
676 ctx->index_entries = index_entries;
677
678 if(!found_user_data_ddt)
679 {
680 if(!has_flux_block)
681 {
682 FATAL("Could not find user data deduplication table or flux data, aborting...");
683 aaruf_close(ctx);
685
686 TRACE("Exiting aaruf_open() = NULL");
687 return NULL;
688 }
689
690 TRACE("No user data DDT found but flux data present, opening as flux-only image");
691 ctx->no_user_data_ddt = true;
692 /* image_info.Sectors stays 0; biggestSectorSize stays 0; sector APIs will reject. */
693 }
694
695 if(ctx->header.biggestSectorSize != 0)
696 {
697 TRACE("Setting sector size to %u bytes", ctx->header.biggestSectorSize);
699 }
700
704
706 {
707 ctx->cylinders = (uint32_t)(ctx->image_info.Sectors / 16 / 63);
708 ctx->heads = 16;
709 ctx->sectors_per_track = 63;
710 }
711
712 // Initialize caches
713 TRACE("Initializing caches");
714 ctx->block_header_cache.cache = NULL;
715 ctx->block_cache.cache = NULL;
716
717 // Set free functions for cached values (both cache malloc'd data)
718 ctx->block_header_cache.free_func = free;
719 ctx->block_cache.free_func = free;
720
721 // Both caches are bounded by bytes held, so no block geometry is needed here. Deriving an
722 // entry count from a block size got this wrong: the divisor used ctx->shift, which is only
723 // ever set for DDT v1 images, so on every DDT v2 image the limit came out ~262144 entries of
724 // up to 8 MiB each and the cache grew until the whole decompressed image was resident.
726 ctx->block_cache.cur_bytes = 0;
729
730 // TODO: Cache tracks and sessions?
731
732 // Initialize ECC for Compact Disc
733 TRACE("Initializing ECC for Compact Disc");
735
736 ctx->magic = AARU_MAGIC;
739
740
741 if(!resume_mode)
742 {
743 TRACE("Exiting aaruf_open() = %p", ctx);
744 return ctx;
745 }
746
747 // Parse the options
748 TRACE("Parsing options");
749 bool table_shift_found = false;
750 const aaru_options parsed_options = parse_options(options, &table_shift_found);
751
754
755 // Calculate aligned next block position. For flux-only images there is no user-data DDT
756 // header, so use the alignment shift recorded in the container header instead.
757 const uint8_t resume_alignment_shift =
759 aaruf_fseek(ctx->imageStream, 0, SEEK_END);
760 const uint64_t alignment_mask = (1ULL << resume_alignment_shift) - 1;
761 ctx->next_block_position = (uint64_t)aaruf_ftell(ctx->imageStream); // Start just after the header
762 ctx->next_block_position = ctx->next_block_position + alignment_mask & ~alignment_mask;
763
764 TRACE("Data blocks will start at position %" PRIu64, ctx->next_block_position);
765
766 // Position file pointer at the data start position
767 if(aaruf_fseek(ctx->imageStream, (aaru_off_t)ctx->next_block_position, SEEK_SET) != 0)
768 {
769 FATAL("Could not seek to data start position");
770 TRACE("Exiting aaruf_open() = NULL");
773 return NULL;
774 }
775
776 // Apply applicable options (we cannot change table or alignment options resuming)
777 ctx->compression_enabled = parsed_options.compress;
778 ctx->lzma_dict_size = parsed_options.dictionary;
779 ctx->deduplicate = parsed_options.deduplicate;
780 /* Flux-only images have no DDT and therefore no sector deduplication map. */
781 if(ctx->deduplicate && !ctx->no_user_data_ddt)
782 ctx->sector_hash_map = create_map(ctx->user_data_ddt_header.blocks * 25 / 100); // 25% of total sectors
783
784 // Loaded CD prefix/suffix arenas are compact (one slot per custom entry). New customs must append after the
785 // existing slots, otherwise they would overwrite them and the DDT indexes would dangle past the rewritten block.
788
789 // Cannot checksum a resumed file
790 ctx->rewinded = true;
791
792 // Is writing
793 ctx->is_writing = true;
795
796 TRACE("Exiting aaruf_open() = %p", ctx);
797 // Return context
798 return ctx;
799}
#define LIBAARUFORMAT_MAJOR_VERSION
Definition aaruformat.h:22
#define LIBAARUFORMAT_MINOR_VERSION
Definition aaruformat.h:23
#define DIC_MAGIC
Magic identifier for legacy DiscImageChef container (ASCII "DICMFRMT").
Definition consts.h:61
#define AARU_RECOVERY_FOOTER_MAGIC
Magic number at the end of the recovery footer: "AVRECMFR" in ASCII little-endian.
Definition consts.h:119
#define AARU_MAGIC
Magic identifier for AaruFormat container (ASCII "AARUFRMT").
Definition consts.h:64
#define MAX_CACHE_SIZE
Maximum read cache size (bytes).
Definition consts.h:79
#define AARUF_KNOWN_ROCOMPAT_FEATURES
Bitmask of all featureCompatibleRo bits understood by this library version.
Definition consts.h:111
#define AARUF_KNOWN_INCOMPAT_FEATURES
Bitmask of all featureIncompatible bits understood by this library version.
Definition consts.h:108
#define AARUF_VERSION_V2
Second on‑disk version (C implementation).
Definition consts.h:75
#define AARUF_VERSION
Current image format major version (incompatible changes bump this).
Definition consts.h:68
#define MAX_HEADER_CACHE_SIZE
Maximum block header cache size (bytes).
Definition consts.h:83
#define AARU_CALL
Definition decls.h:46
uint64_t aaruf_crc64_data(const uint8_t *data, uint32_t len)
Definition crc64.c:160
void * aaruf_ecc_cd_init(void)
Initializes a Compact Disc ECC context.
Definition ecc_cd.c:35
void * aaruf_open(const char *filepath, bool resume_mode, const char *options)
Opens an existing AaruFormat image file.
Definition open.c:236
int aaruf_close(void *context)
Close an Aaru image context, flushing pending data structures and releasing resources.
Definition close.c:80
#define AARU_EXPORT
Definition decls.h:55
int32_t aaruf_get_xml_mediatype(int32_t type)
Definition helpers.c:399
@ IndexBlock3
Block containing the index v3.
Definition enums.h:171
@ ChecksumBlock
Block containing contents checksums.
Definition enums.h:176
@ DataBlock
Block containing data.
Definition enums.h:164
@ TapePartitionBlock
Block containing list of partitions for a tape image.
Definition enums.h:182
@ IndexBlock2
Block containing the index v2.
Definition enums.h:170
@ GeometryBlock
Block containing logical geometry.
Definition enums.h:172
@ AaruMetadataJsonBlock
Block containing JSON version of Aaru Metadata.
Definition enums.h:183
@ CicmBlock
Block containing CICM XML metadata.
Definition enums.h:175
@ IndexBlock
Block containing the index (v1).
Definition enums.h:169
@ DeDuplicationTable2
Block containing a deduplication table v2.
Definition enums.h:166
@ TapeFileBlock
Block containing list of files for a tape image.
Definition enums.h:181
@ DeDuplicationTable
Block containing a deduplication table (v1).
Definition enums.h:165
@ DumpHardwareBlock
Block containing an array of hardware used to create the image.
Definition enums.h:180
@ MetadataBlock
Block containing metadata.
Definition enums.h:173
@ DataPositionMeasurementBlock
Block containing data position measurements (reserved / TODO).
Definition enums.h:177
@ TracksBlock
Block containing optical disc tracks.
Definition enums.h:174
@ FluxDataBlock
Block containing flux data metadata.
Definition enums.h:184
@ BlockMedia
Media that is physically block-based or abstracted like that.
Definition enums.h:247
@ kDataTypeCdSectorSuffix
Compact Disc sector suffix (EDC, ECC P, ECC Q).
Definition enums.h:117
@ kDataTypeCdSectorSuffixCorrected
Compact Disc sector suffix (EDC, ECC P, ECC Q) corrected-only stored.
Definition enums.h:124
@ kDataTypeUserData
User (main) data.
Definition enums.h:48
@ kDataTypeCdSectorPrefix
Compact Disc sector prefix (sync, header).
Definition enums.h:116
@ kDataTypeCdSectorPrefixCorrected
Compact Disc sector prefix (sync, header) corrected-only stored.
Definition enums.h:123
void ec_load_ecmb(aaruformat_context *ctx)
Try to load the ECMB from the recovery footer at EOF.
Definition erasure.c:1046
#define AARUF_ERROR_CANNOT_CREATE_FILE
Output file could not be created / opened for write.
Definition errors.h:58
#define AARUF_STATUS_OK
Sector present and read without uncorrectable errors.
Definition errors.h:82
#define AARUF_ERROR_INCOMPATIBLE_FEATURES
Image requires features not supported by this library.
Definition errors.h:72
#define AARUF_ERROR_NOT_ENOUGH_MEMORY
Memory allocation failure (critical).
Definition errors.h:48
#define AARUF_ERROR_INCOMPATIBLE_VERSION
Image uses a newer incompatible on-disk version.
Definition errors.h:42
#define AARUF_ERROR_CANNOT_READ_INDEX
Index block unreadable / truncated / bad identifier.
Definition errors.h:43
#define AARUF_ERROR_NOT_AARUFORMAT
Input file/stream failed magic or structural validation.
Definition errors.h:40
#define AARUF_ERROR_FILE_TOO_SMALL
File size insufficient for mandatory header / structures.
Definition errors.h:41
@ kSectorTagCdHeader
4-byte CD header (minute, second, frame, mode)
Definition aaru.h:962
@ kSectorTagCdSync
12-byte CD sync pattern (00 FF*10 00)
Definition aaru.h:961
@ kSectorTagCdSubHeader
Mode 2 Form subheader (8 bytes: copy, submode, channel).
Definition aaru.h:963
@ MaxSectorTag
Definition aaru.h:983
@ kSectorTagCdEdc
32-bit CRC (EDC)
Definition aaru.h:964
@ kSectorTagCdEccP
172 bytes Reed-Solomon ECC (P)
Definition aaru.h:965
@ kSectorTagCdEccQ
104 bytes Reed-Solomon ECC (Q)
Definition aaru.h:966
@ kSectorTagCdEcc
Combined P+Q ECC (276 bytes).
Definition aaru.h:967
hash_map_t * create_map(size_t size)
Creates a new hash map with the specified initial size.
Definition hash_map.c:51
#define AARU_HEADER_APP_NAME_LEN
Size in bytes (UTF-16LE) of application name field (32 UTF-16 code units).
Definition header.h:59
void process_dumphw_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes a dump hardware block from the image stream.
Definition dump.c:107
UT_array * process_index_v2(aaruformat_context *ctx)
Processes an index block (version 2) from the image stream.
Definition index_v2.c:82
int32_t process_ddt_v2(aaruformat_context *ctx, IndexEntry *entry, bool *found_user_data_ddt)
Processes a DDT v2 block from the image stream.
Definition ddt_v2.c:97
int32_t process_data_block(aaruformat_context *ctx, IndexEntry *entry)
Processes a data block from the image stream.
Definition data.c:73
uint64_t get_filetime_uint64()
Gets the current time as a 64-bit FILETIME value.
Definition time.c:45
void process_tracks_block(aaruformat_context *ctx, const IndexEntry *entry)
Parse and integrate a Tracks block from the image stream into the context.
Definition optical.c:116
void process_metadata_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes a metadata block from the image stream.
Definition metadata.c:36
void process_checksum_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes a checksum block from the image stream.
Definition checksum.c:40
UT_array * process_index_v1(aaruformat_context *ctx)
Processes an index block (version 1) from the image stream.
Definition index_v1.c:80
void process_cicm_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes a CICM XML metadata block from the image stream.
Definition metadata.c:313
static int aaruf_fseek(FILE *stream, aaru_off_t offset, int origin)
Definition internal.h:46
static aaru_off_t aaruf_ftell(FILE *stream)
Definition internal.h:52
int32_t aaruf_finalize_write(aaruformat_context *ctx)
Finalize a write-mode image: flush all pending blocks, DDTs, and the index.
void process_geometry_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes a logical geometry block from the image stream.
Definition metadata.c:253
void process_tape_files_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes a tape file metadata block from the image stream.
Definition tape.c:127
void process_aaru_metadata_json_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes an Aaru metadata JSON block from the image stream during image opening.
Definition metadata.c:478
void process_dpm_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes a Data Position Measurement block from the image stream.
Definition dpm.c:148
void process_tape_partitions_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes a tape partition metadata block from the image stream.
Definition tape.c:348
int32_t process_ddt_v1(aaruformat_context *ctx, IndexEntry *entry, bool *found_user_data_ddt)
Processes a DDT v1 block from the image stream.
Definition ddt_v1.c:86
aaru_options parse_options(const char *options, bool *table_shift_found)
Parses the options string for AaruFormat image creation/opening.
Definition options.c:47
int64_t aaru_off_t
Definition internal.h:42
UT_array * process_index_v3(aaruformat_context *ctx)
Processes an index block (version 3) from the image stream.
Definition index_v3.c:98
#define FATAL(fmt,...)
Definition log.h:75
#define TRACE(fmt,...)
Definition log.h:69
static void cleanup_open_failure(aaruformat_context *ctx)
Definition open.c:44
static void aaruf_set_open_error(const int error_code)
Definition open.c:36
Version 2 container header with GUID, alignment shifts, and feature negotiation bitmaps.
Definition header.h:107
uint8_t application[64]
UTF-8 creator application name (fixed 64 bytes).
Definition header.h:109
uint8_t applicationMajorVersion
Creator application major version.
Definition header.h:112
uint64_t identifier
File magic (AARU_MAGIC).
Definition header.h:108
uint64_t featureIncompatible
Feature bits: any unimplemented -> abort (cannot open safely).
Definition header.h:123
int64_t lastWrittenTime
Last modification FILETIME (100 ns since 1601-01-01 UTC).
Definition header.h:117
uint64_t indexOffset
Absolute byte offset to primary index block (MUST be > 0; 0 => corrupt/unreadable).
Definition header.h:115
uint8_t applicationMinorVersion
Creator application minor / patch version.
Definition header.h:113
uint32_t mediaType
Media type enumeration (value from MediaType).
Definition header.h:114
uint64_t featureCompatibleRo
Feature bits: unimplemented -> degrade to read-only access.
Definition header.h:122
uint16_t biggestSectorSize
size of biggest sector in the image (in bytes).
Definition header.h:120
uint8_t blockAlignmentShift
log2 block alignment (block size alignment = 2^blockAlignmentShift bytes).
Definition header.h:119
uint8_t imageMinorVersion
Container format minor version.
Definition header.h:111
int64_t creationTime
Creation FILETIME (100 ns since 1601-01-01 UTC).
Definition header.h:116
uint8_t imageMajorVersion
Container format major version.
Definition header.h:110
Version 1 container header placed at offset 0 for legacy / initial format.
Definition header.h:77
Recovery footer written at the very end of the file (last 160 bytes).
Definition erasure.h:117
uint64_t headerCrc64
CRC64-ECMA of the original AaruHeaderV2 (147 bytes at offset 0).
Definition erasure.h:120
uint64_t footerMagic
Must be AARU_RECOVERY_FOOTER_MAGIC (0x52464D4345525641).
Definition erasure.h:122
AaruHeaderV2 backupHeader
Complete copy of AaruHeaderV2 from file offset 0.
Definition erasure.h:121
struct CacheEntry * cache
Hash root (uthash). NULL when empty.
Definition lru.h:54
void(*) free_func(void *)
Optional callback to free cached values. NULL if not needed.
Definition lru.h:55
uint64_t cur_bytes
Bytes currently held by the cached values.
Definition lru.h:53
uint64_t max_bytes
Memory budget in bytes for the cached values. 0 means unlimited.
Definition lru.h:52
Lookup tables and state for Compact Disc EDC/ECC (P/Q) regeneration / verification.
Definition context.h:92
uint64_t blocks
Total internal span (negative + usable + overflow) in logical sectors.
Definition ddt.h:150
uint8_t blockAlignmentShift
2^blockAlignmentShift = block alignment boundary in bytes.
Definition ddt.h:154
uint32_t identifier
Block identifier, must be BlockType::GeometryBlock.
Definition data.h:92
uint32_t MediaType
Media type identifier (see MediaType enum; 0=Unknown).
Definition aaru.h:945
uint8_t MetadataMediaType
Media type for sidecar generation (internal archival use).
Definition aaru.h:946
uint32_t SectorSize
Size of each logical sector in bytes (512, 2048, 2352, 4096, etc.).
Definition aaru.h:939
char Application[64]
Name of application that created the image (NUL-terminated).
Definition aaru.h:941
uint64_t ImageSize
Size of the image payload in bytes (excludes headers/metadata).
Definition aaru.h:937
int64_t CreationTime
Image creation timestamp (Windows FILETIME: 100ns since 1601-01-01 UTC).
Definition aaru.h:943
int64_t LastModificationTime
Last modification timestamp (Windows FILETIME format).
Definition aaru.h:944
char Version[32]
Image format version string (NUL-terminated, e.g., "6.0").
Definition aaru.h:940
uint64_t Sectors
Total count of addressable logical sectors/blocks.
Definition aaru.h:938
char ApplicationVersion[32]
Version of the creating application (NUL-terminated).
Definition aaru.h:942
Single index entry describing a block's type, (optional) data classification, and file offset.
Definition index.h:109
uint32_t blockType
Block identifier of the referenced block (value from BlockType).
Definition index.h:110
uint64_t offset
Absolute byte offset in the image where the referenced block header begins.
Definition index.h:112
uint16_t dataType
Data classification (value from DataType) or unused for untyped blocks.
Definition index.h:111
Parsed user-specified tunables controlling compression, deduplication, hashing and DDT geometry.
Definition options.h:220
bool deduplicate
Storage dedup flag (DDT always exists).
Definition options.h:222
uint32_t dictionary
LZMA dictionary size in bytes (>= 4096 recommended). Default: 33554432 (32 MiB).
Definition options.h:224
bool compress
Enable adaptive compression (LZMA for data blocks, FLAC for audio). Default: true.
Definition options.h:221
Master context representing an open or in‑creation Aaru image.
Definition context.h:178
DdtHeader2 user_data_ddt_header
Active user data DDT v2 header (primary table meta).
Definition context.h:195
uint8_t library_major_version
Linked library major version.
Definition context.h:183
bool deduplicate
Storage deduplication active (duplicates coalesce).
Definition context.h:310
size_t sector_suffix_length
Length of sector_suffix.
Definition context.h:295
bool compression_enabled
True if block compression enabled (writing path).
Definition context.h:311
hash_map_t * sector_hash_map
Deduplication hash map (fingerprint->entry mapping).
Definition context.h:263
uint32_t cylinders
Cylinders of the media represented by the image.
Definition context.h:244
struct CacheHeader block_header_cache
LRU/Cache header for block headers.
Definition context.h:266
CdEccContext * ecc_cd_context
CD ECC/EDC helper tables (allocated on demand).
Definition context.h:258
bool rewinded
True if stream has been rewound after open (write path).
Definition context.h:303
struct CacheHeader block_cache
LRU/Cache header for block payloads.
Definition context.h:267
AaruHeaderV2 header
Parsed container header (v2).
Definition context.h:181
bool is_writing
True if context opened/created for writing.
Definition context.h:302
size_t sector_prefix_offset
Current position in sector_prefix.
Definition context.h:296
uint64_t magic
File magic (AARU_MAGIC) post-open.
Definition context.h:180
int32_t(*) finalize_write(struct aaruformat_context *ctx)
Writer finalization hook (NULL for reader).
Definition context.h:306
size_t sector_prefix_length
Length of sector_prefix.
Definition context.h:294
uint8_t library_minor_version
Linked library minor version;.
Definition context.h:184
uint64_t next_block_position
Absolute file offset where next block will be written.
Definition context.h:292
GeometryBlockHeader geometry_block
Logical geometry block (if present).
Definition context.h:239
size_t sector_suffix_offset
Current position in sector_suffix.
Definition context.h:297
uint32_t sectors_per_track
Sectors per track of the media represented by the image (for variable image, the smallest).
Definition context.h:246
uint32_t heads
Heads of the media represented by the image.
Definition context.h:245
FILE * imageStream
Underlying FILE* stream (binary mode).
Definition context.h:182
bool no_user_data_ddt
True if image intentionally has no user-data DDT (e.g. flux-only image). When set,...
Definition context.h:203
UT_array * index_entries
Flattened index entries (UT_array of IndexEntry).
Definition context.h:262
ImageInfo image_info
Exposed high-level image info summary.
Definition context.h:270
bool * readableSectorTags
Per-sector boolean array (optical tags read successfully?).
Definition context.h:273
uint32_t lzma_dict_size
LZMA dictionary size (writing path).
Definition context.h:309