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#ifdef USE_SLOG
248#include "slog.h"
249
250 slog_init("aaruformat.log", SLOG_FLAGS_ALL, 0);
251#endif
252
253 TRACE("Logging initialized");
254
255 TRACE("Entering aaruf_open(%s)", filepath);
257
258 TRACE("Allocating memory for context");
259 ctx = (aaruformat_context *)malloc(sizeof(aaruformat_context));
260
261 if(ctx == NULL)
262 {
263 FATAL("Not enough memory to create context");
265
266 TRACE("Exiting aaruf_open() = NULL");
267 return NULL;
268 }
269
270 memset(ctx, 0, sizeof(aaruformat_context));
271
272 TRACE("Opening file %s", filepath);
273 if(resume_mode)
274 ctx->imageStream = fopen(filepath, "r+b");
275 else
276 ctx->imageStream = fopen(filepath, "rb");
277
278 if(ctx->imageStream == NULL)
279 {
280 FATAL("Error %d opening file %s for reading", errno, filepath);
281 error_no = errno;
283 aaruf_set_open_error(error_no);
284
285 TRACE("Exiting aaruf_open() = NULL");
286 return NULL;
287 }
288
289 TRACE("Reading header at position 0");
290 aaruf_fseek(ctx->imageStream, 0, SEEK_SET);
291 read_bytes = fread(&ctx->header, 1, sizeof(AaruHeader), ctx->imageStream);
292
293 if(read_bytes != sizeof(AaruHeader))
294 {
295 FATAL("Could not read header");
298
299 TRACE("Exiting aaruf_open() = NULL");
300 return NULL;
301 }
302
304 {
305 /* Primary header corrupt — try recovery footer backup header */
306 TRACE("Primary header invalid, trying recovery footer backup header");
307
308 aaruf_fseek(ctx->imageStream, 0, SEEK_END);
309 int64_t file_size = aaruf_ftell(ctx->imageStream);
310
311 if(file_size >= (int64_t)sizeof(AaruRecoveryFooter))
312 {
314 (aaru_off_t)(file_size - (int64_t)sizeof(AaruRecoveryFooter)), SEEK_SET);
315 AaruRecoveryFooter recovery_footer;
316 if(fread(&recovery_footer, sizeof(AaruRecoveryFooter), 1, ctx->imageStream) == 1 &&
317 recovery_footer.footerMagic == AARU_RECOVERY_FOOTER_MAGIC)
318 {
319 /* Verify the backup header's CRC matches what was recorded */
320 uint64_t backup_crc = aaruf_crc64_data(
321 (const uint8_t *)&recovery_footer.backupHeader, sizeof(AaruHeaderV2));
322 if(backup_crc == recovery_footer.headerCrc64 &&
323 (recovery_footer.backupHeader.identifier == DIC_MAGIC ||
324 recovery_footer.backupHeader.identifier == AARU_MAGIC))
325 {
326 TRACE("Recovery footer backup header valid, using it");
327 memcpy(&ctx->header, &recovery_footer.backupHeader, sizeof(AaruHeaderV2));
328 /* Seek past the header for the next read */
329 aaruf_fseek(ctx->imageStream, (aaru_off_t)sizeof(AaruHeaderV2), SEEK_SET);
330 }
331 else
332 {
333 FATAL("Recovery footer backup header also invalid");
336 TRACE("Exiting aaruf_open() = NULL");
337 return NULL;
338 }
339 }
340 else
341 {
342 FATAL("No recovery footer found, cannot recover from corrupt header");
345 TRACE("Exiting aaruf_open() = NULL");
346 return NULL;
347 }
348 }
349 else
350 {
351 FATAL("Incorrect identifier for AaruFormat file: %8.8s", (char *)&ctx->header.identifier);
354 TRACE("Exiting aaruf_open() = NULL");
355 return NULL;
356 }
357 }
358
359 if(ctx->header.imageMajorVersion < AARUF_VERSION_V2 && resume_mode)
360 {
361 TRACE("Cannot write to old images");
364 TRACE("Exiting aaruf_open() = NULL");
365 return NULL;
366 }
367
368 // Read new header version
370 {
371 TRACE("Reading new header version at position 0");
372 aaruf_fseek(ctx->imageStream, 0, SEEK_SET);
373 read_bytes = fread(&ctx->header, 1, sizeof(AaruHeaderV2), ctx->imageStream);
374
375 if(read_bytes != sizeof(AaruHeaderV2))
376 {
379
380 return NULL;
381 }
382 }
383
385 {
386 FATAL("Incompatible AaruFormat version %d.%d found, maximum supported is %d.%d", ctx->header.imageMajorVersion,
390
391 TRACE("Exiting aaruf_open() = NULL");
392 return NULL;
393 }
394
395 // Check feature compatibility for V2+ images
397 {
398 uint64_t unknown_incompat = ctx->header.featureIncompatible & ~AARUF_KNOWN_INCOMPAT_FEATURES;
399
400 if(unknown_incompat != 0)
401 {
402 FATAL("Image requires unsupported incompatible features: 0x%016" PRIX64, unknown_incompat);
405
406 TRACE("Exiting aaruf_open() = NULL");
407 return NULL;
408 }
409
410 uint64_t unknown_rocompat = ctx->header.featureCompatibleRo & ~AARUF_KNOWN_ROCOMPAT_FEATURES;
411
412 if(unknown_rocompat != 0)
413 {
414 if(resume_mode)
415 {
416 FATAL("Image has unsupported read-only compatible features: 0x%016" PRIX64 ", cannot open for writing",
417 unknown_rocompat);
420
421 TRACE("Exiting aaruf_open() = NULL");
422 return NULL;
423 }
424
425 TRACE("Image has unsupported read-only compatible features: 0x%016" PRIX64 ", forcing read-only",
426 unknown_rocompat);
427 }
428 }
429
430 TRACE("Opening image version %d.%d", ctx->header.imageMajorVersion, ctx->header.imageMinorVersion);
431
432 TRACE("Allocating memory for readable sector tags bitmap");
433 ctx->readableSectorTags = (bool *)malloc(sizeof(bool) * MaxSectorTag);
434
435 if(ctx->readableSectorTags == NULL)
436 {
437 FATAL("Could not allocate memory for readable sector tags bitmap");
440
441 TRACE("Exiting aaruf_open() = NULL");
442 return NULL;
443 }
444
445 memset(ctx->readableSectorTags, 0, sizeof(bool) * MaxSectorTag);
446
447 TRACE("Setting up image info");
448
449 // Handle application name based on image version
450 memset(ctx->image_info.Application, 0, 64);
451
453 {
454 // Version 2+: application name is UTF-8, direct copy
455 TRACE("Converting application name (v2+): UTF-8 direct copy");
456 size_t copy_len = AARU_HEADER_APP_NAME_LEN < 63 ? AARU_HEADER_APP_NAME_LEN : 63;
457 memcpy(ctx->image_info.Application, ctx->header.application, copy_len);
458 ctx->image_info.Application[63] = '\0';
459 }
460 else
461 {
462 // Version 1: application name is UTF-16LE, convert by taking every other byte
463 TRACE("Converting application name (v1): UTF-16LE to ASCII");
464 int dest_idx = 0;
465 for(int j = 0; j < AARU_HEADER_APP_NAME_LEN && dest_idx < 63; j += 2)
466 // Take the low byte, skip the high byte (assuming it's 0x00 for ASCII)
467 if(ctx->header.application[j] != 0)
468 ctx->image_info.Application[dest_idx++] = ctx->header.application[j];
469 else
470 // Stop at null terminator
471 break;
472 ctx->image_info.Application[dest_idx] = '\0';
473 }
474
475 // Set application version string directly in the fixed-size array
476 memset(ctx->image_info.ApplicationVersion, 0, 32);
479
480 // Set image version string directly in the fixed-size array
481 memset(ctx->image_info.Version, 0, 32);
482 sprintf(ctx->image_info.Version, "%d.%d", ctx->header.imageMajorVersion, ctx->header.imageMinorVersion);
483
485
486 // Read the index header
487 TRACE("Reading index header at position %" PRIu64, ctx->header.indexOffset);
488 if(aaruf_fseek(ctx->imageStream, (aaru_off_t)ctx->header.indexOffset, SEEK_SET) != 0)
489 {
492
493 return NULL;
494 }
495
496 pos = aaruf_ftell(ctx->imageStream);
497 if(pos != ctx->header.indexOffset)
498 {
501
502 return NULL;
503 }
504
505 read_bytes = fread(&signature, 1, sizeof(uint32_t), ctx->imageStream);
506
507 if(read_bytes != sizeof(uint32_t) ||
508 (signature != IndexBlock && signature != IndexBlock2 && signature != IndexBlock3))
509 {
510 FATAL("Could not read index header or incorrect identifier %4.4s", (char *)&signature);
513
514 TRACE("Exiting aaruf_open() = NULL");
515 return NULL;
516 }
517
518 if(signature == IndexBlock)
519 index_entries = process_index_v1(ctx);
520 else if(signature == IndexBlock2)
521 index_entries = process_index_v2(ctx);
522 else if(signature == IndexBlock3)
523 index_entries = process_index_v3(ctx);
524
525 if(index_entries == NULL)
526 {
527 FATAL("Could not process index.");
528 utarray_free(index_entries);
531
532 TRACE("Exiting aaruf_open() = NULL");
533 return NULL;
534 }
535
536 TRACE("Index at %" PRIu64 " contains %d entries", ctx->header.indexOffset, utarray_len(index_entries));
537
538 for(i = 0; i < utarray_len(index_entries); i++)
539 {
540 IndexEntry *entry = utarray_eltptr(index_entries, i);
541 TRACE("Block type %4.4s with data type %d is indexed to be at %" PRIu64 "", (char *)&entry->blockType,
542 entry->dataType, entry->offset);
543 }
544
545 /* Load the erasure coding recovery map from the footer at the end of the file before processing the blocks, so
546 * the blocks found damaged can be recovered while they are processed */
547 ec_load_ecmb(ctx);
548
549 bool found_user_data_ddt = false;
550 bool has_flux_block = false;
551 ctx->image_info.ImageSize = 0;
552 for(i = 0; i < utarray_len(index_entries); i++)
553 {
554 IndexEntry *entry = utarray_eltptr(index_entries, i);
555
556 if(aaruf_fseek(ctx->imageStream, (aaru_off_t)entry->offset, SEEK_SET) != 0 ||
557 aaruf_ftell(ctx->imageStream) != (aaru_off_t)entry->offset)
558 {
559 TRACE("Could not seek to %" PRIu64 " as indicated by index entry %d, continuing...", entry->offset, i);
560
561 continue;
562 }
563
564 TRACE("Processing block type %4.4s with data type %d at position %" PRIu64 "", (char *)&entry->blockType,
565 entry->dataType, entry->offset);
566 switch(entry->blockType)
567 {
568 case DataBlock:
569 if(entry->dataType == kDataTypeUserData && ctx->header.biggestSectorSize > 0) break;
570
571 error_no = process_data_block(ctx, entry);
572
573 if(error_no != AARUF_STATUS_OK)
574 {
575 utarray_free(index_entries);
577 aaruf_set_open_error(error_no);
578
579 return NULL;
580 }
581
582 break;
583
585 error_no = process_ddt_v1(ctx, entry, &found_user_data_ddt);
586
587 if(error_no != AARUF_STATUS_OK)
588 {
589 utarray_free(index_entries);
591 aaruf_set_open_error(error_no);
592
593 return NULL;
594 }
595
596 break;
598 error_no = process_ddt_v2(ctx, entry, &found_user_data_ddt);
599
600 if(error_no != AARUF_STATUS_OK)
601 {
602 utarray_free(index_entries);
604 aaruf_set_open_error(error_no);
605
606 return NULL;
607 }
608
609 switch(entry->dataType)
610 {
615
616 break;
624 break;
625 default:
626 break;
627 }
628
629 break;
630 case GeometryBlock:
631 process_geometry_block(ctx, entry);
632
633 break;
634 case MetadataBlock:
635 process_metadata_block(ctx, entry);
636
637 break;
638 case TracksBlock:
639 process_tracks_block(ctx, entry);
640
641 break;
642 case CicmBlock:
643 process_cicm_block(ctx, entry);
644
645 break;
648
649 break;
651 process_dpm_block(ctx, entry);
652
653 break;
654 // Dump hardware block
656 process_dumphw_block(ctx, entry);
657
658 break;
659 case ChecksumBlock:
660 process_checksum_block(ctx, entry);
661
662 break;
663 case TapeFileBlock:
664 process_tape_files_block(ctx, entry);
665
666 break;
669
670 break;
671 case FluxDataBlock:
672 // Store the FluxDataBlock offset for lazy loading
673 // Don't read flux entries during open - load them on-demand when actually needed
674 // This avoids unnecessary I/O if flux data is never accessed
675 has_flux_block = true;
676 break;
677 default:
678 TRACE("Unhandled block type %4.4s with data type %d is indexed to be at %" PRIu64 "",
679 (char *)&entry->blockType, entry->dataType, entry->offset);
680 break;
681 }
682 }
683
684 ctx->index_entries = index_entries;
685
686 if(!found_user_data_ddt)
687 {
688 if(!has_flux_block)
689 {
690 FATAL("Could not find user data deduplication table or flux data, aborting...");
691 aaruf_close(ctx);
693
694 TRACE("Exiting aaruf_open() = NULL");
695 return NULL;
696 }
697
698 TRACE("No user data DDT found but flux data present, opening as flux-only image");
699 ctx->no_user_data_ddt = true;
700 /* image_info.Sectors stays 0; biggestSectorSize stays 0; sector APIs will reject. */
701 }
702
703 if(ctx->header.biggestSectorSize != 0)
704 {
705 TRACE("Setting sector size to %u bytes", ctx->header.biggestSectorSize);
707 }
708
712
714 {
715 ctx->cylinders = (uint32_t)(ctx->image_info.Sectors / 16 / 63);
716 ctx->heads = 16;
717 ctx->sectors_per_track = 63;
718 }
719
720 // Initialize caches
721 TRACE("Initializing caches");
722 ctx->block_header_cache.cache = NULL;
723 ctx->block_cache.cache = NULL;
724
725 // Set free functions for cached values (both cache malloc'd data)
726 ctx->block_header_cache.free_func = free;
727 ctx->block_cache.free_func = free;
728
729 // Both caches are bounded by bytes held, so no block geometry is needed here. Deriving an
730 // entry count from a block size got this wrong: the divisor used ctx->shift, which is only
731 // ever set for DDT v1 images, so on every DDT v2 image the limit came out ~262144 entries of
732 // up to 8 MiB each and the cache grew until the whole decompressed image was resident.
734 ctx->block_cache.cur_bytes = 0;
737
738 // TODO: Cache tracks and sessions?
739
740 // Initialize ECC for Compact Disc
741 TRACE("Initializing ECC for Compact Disc");
743
744 ctx->magic = AARU_MAGIC;
747
748
749 if(!resume_mode)
750 {
751 TRACE("Exiting aaruf_open() = %p", ctx);
752 return ctx;
753 }
754
755 // Parse the options
756 TRACE("Parsing options");
757 bool table_shift_found = false;
758 const aaru_options parsed_options = parse_options(options, &table_shift_found);
759
762
763 // Calculate aligned next block position. For flux-only images there is no user-data DDT
764 // header, so use the alignment shift recorded in the container header instead.
765 const uint8_t resume_alignment_shift =
767 aaruf_fseek(ctx->imageStream, 0, SEEK_END);
768 const uint64_t alignment_mask = (1ULL << resume_alignment_shift) - 1;
769 ctx->next_block_position = (uint64_t)aaruf_ftell(ctx->imageStream); // Start just after the header
770 ctx->next_block_position = ctx->next_block_position + alignment_mask & ~alignment_mask;
771
772 TRACE("Data blocks will start at position %" PRIu64, ctx->next_block_position);
773
774 // Position file pointer at the data start position
775 if(aaruf_fseek(ctx->imageStream, (aaru_off_t)ctx->next_block_position, SEEK_SET) != 0)
776 {
777 FATAL("Could not seek to data start position");
778 TRACE("Exiting aaruf_open() = NULL");
781 return NULL;
782 }
783
784 // Apply applicable options (we cannot change table or alignment options resuming)
785 ctx->compression_enabled = parsed_options.compress;
786 ctx->lzma_dict_size = parsed_options.dictionary;
787 ctx->deduplicate = parsed_options.deduplicate;
788 /* Flux-only images have no DDT and therefore no sector deduplication map. */
789 if(ctx->deduplicate && !ctx->no_user_data_ddt)
790 ctx->sector_hash_map = create_map(ctx->user_data_ddt_header.blocks * 25 / 100); // 25% of total sectors
791
792 // Loaded CD prefix/suffix arenas are compact (one slot per custom entry). New customs must append after the
793 // existing slots, otherwise they would overwrite them and the DDT indexes would dangle past the rewritten block.
796
797 // Cannot checksum a resumed file
798 ctx->rewinded = true;
799
800 // Is writing
801 ctx->is_writing = true;
803
804 TRACE("Exiting aaruf_open() = %p", ctx);
805 // Return context
806 return ctx;
807}
#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:40
#define TRACE(fmt,...)
Definition log.h:25
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