libaaruformat 1.0
Aaru Data Preservation Suite - Format Library
Loading...
Searching...
No Matches
tape.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 "aaruformat.h"
20#include "internal.h"
21#include "log.h"
22
128{
129 long pos = 0;
130 size_t read_bytes = 0;
131 TapeFileHeader tape_file_header = {0};
132
133 // Check if the context and image stream are valid
134 if(ctx == NULL || ctx->imageStream == NULL)
135 {
136 FATAL("Invalid context or image stream.");
137 return;
138 }
139
140 // Seek to block
141 pos = aaruf_fseek(ctx->imageStream, (aaru_off_t)entry->offset, SEEK_SET);
142 if(pos < 0 || aaruf_ftell(ctx->imageStream) != (aaru_off_t)entry->offset)
143 {
144 FATAL("Could not seek to %" PRIu64 " as indicated by index entry...", entry->offset);
145
146 return;
147 }
148
149 // Even if those two checks shall have been done before
150 read_bytes = fread(&tape_file_header, 1, sizeof(TapeFileHeader), ctx->imageStream);
151
152 if(read_bytes != sizeof(TapeFileHeader))
153 {
154 TRACE("Could not read tape files header, continuing...");
155 return;
156 }
157
158 if(tape_file_header.identifier != TapeFileBlock)
159 {
160 TRACE("Incorrect identifier for data block at position %" PRIu64 "\n", entry->offset);
161 return;
162 }
163
164 ctx->image_info.ImageSize += sizeof(TapeFileEntry) * tape_file_header.entries;
165
166 uint8_t *buffer = malloc(sizeof(TapeFileEntry) * tape_file_header.entries);
167 if(buffer == NULL)
168 {
169 FATAL("Could not allocate memory for tape files block, continuing...");
170 return;
171 }
172 read_bytes = fread(buffer, sizeof(TapeFileEntry), tape_file_header.entries, ctx->imageStream);
173 if(read_bytes != tape_file_header.entries)
174 {
175 free(buffer);
176 FATAL("Could not read tape files block, continuing...");
177 return;
178 }
179 // Check CRC64
180 uint64_t crc64 = aaruf_crc64_data(buffer, sizeof(TapeFileEntry) * tape_file_header.entries);
181
182 if(crc64 != tape_file_header.crc64)
183 {
184 TRACE("Incorrect CRC found: 0x%" PRIx64 " found, expected 0x%" PRIx64 ", continuing...", crc64,
185 tape_file_header.crc64);
186 free(buffer);
187 return;
188 }
189
190 // Insert entries into UTHASH array indexed by partition << 32 | file number
191 const TapeFileEntry *entries = (TapeFileEntry *)buffer;
192
193 for(uint32_t i = 0; i < tape_file_header.entries; i++)
194 {
195 // Create hash table entry
196 tapeFileHashEntry *hash_entry = malloc(sizeof(tapeFileHashEntry));
197 if(hash_entry == NULL)
198 {
199 FATAL("Could not allocate memory for tape file hash entry");
200 continue;
201 }
202
203 // Create composite key: partition << 32 | file number
204 hash_entry->key = (uint64_t)entries[i].Partition << 32 | entries[i].File;
205
206 // Copy the tape file entry data
207 hash_entry->fileEntry = entries[i];
208
209 // Replace if exists, add if new
210 tapeFileHashEntry *old_entry = NULL;
211 HASH_REPLACE(hh, ctx->tape_files, key, sizeof(uint64_t), hash_entry, old_entry);
212 ctx->dirty_tape_file_block = true; // Mark tape file block as dirty
213
214 // Free old entry if it was replaced
215 if(old_entry != NULL)
216 {
217 TRACE("Replaced existing tape file entry for partition %u, file %u", entries[i].Partition, entries[i].File);
218 free(old_entry);
219 }
220 else
221 TRACE("Added new tape file entry for partition %u, file %u", entries[i].Partition, entries[i].File);
222 }
223
224 free(buffer);
225}
226
349{
350 long pos = 0;
351 size_t read_bytes = 0;
352 TapePartitionHeader tape_partition_header = {0};
353
354 // Check if the context and image stream are valid
355 if(ctx == NULL || ctx->imageStream == NULL)
356 {
357 FATAL("Invalid context or image stream.");
358 return;
359 }
360
361 // Seek to block
362 pos = aaruf_fseek(ctx->imageStream, (aaru_off_t)entry->offset, SEEK_SET);
363 if(pos < 0 || aaruf_ftell(ctx->imageStream) != (aaru_off_t)entry->offset)
364 {
365 FATAL("Could not seek to %" PRIu64 " as indicated by index entry...", entry->offset);
366
367 return;
368 }
369
370 // Even if those two checks shall have been done before
371 read_bytes = fread(&tape_partition_header, 1, sizeof(TapePartitionHeader), ctx->imageStream);
372
373 if(read_bytes != sizeof(TapePartitionHeader))
374 {
375 TRACE("Could not read tape partitions header, continuing...");
376 return;
377 }
378
379 if(tape_partition_header.identifier != TapePartitionBlock)
380 {
381 TRACE("Incorrect identifier for data block at position %" PRIu64 "\n", entry->offset);
382 return;
383 }
384
385 ctx->image_info.ImageSize += sizeof(TapePartitionEntry) * tape_partition_header.entries;
386
387 uint8_t *buffer = malloc(sizeof(TapePartitionEntry) * tape_partition_header.entries);
388 if(buffer == NULL)
389 {
390 FATAL("Could not allocate memory for tape partitions block, continuing...");
391 return;
392 }
393 read_bytes = fread(buffer, sizeof(TapePartitionEntry), tape_partition_header.entries, ctx->imageStream);
394 if(read_bytes != tape_partition_header.entries)
395 {
396 free(buffer);
397 FATAL("Could not read tape partitions block, continuing...");
398 return;
399 }
400 // Check CRC64
401 uint64_t crc64 = aaruf_crc64_data(buffer, sizeof(TapePartitionEntry) * tape_partition_header.entries);
402
403 if(crc64 != tape_partition_header.crc64)
404 {
405 TRACE("Incorrect CRC found: 0x%" PRIx64 " found, expected 0x%" PRIx64 ", continuing...", crc64,
406 tape_partition_header.crc64);
407 free(buffer);
408 return;
409 }
410
411 // Insert entries into UTHASH array indexed by partition
412 const TapePartitionEntry *entries = (TapePartitionEntry *)buffer;
413
414 for(uint32_t i = 0; i < tape_partition_header.entries; i++)
415 {
416 // Create hash table entry
417 TapePartitionHashEntry *hash_entry = malloc(sizeof(TapePartitionHashEntry));
418 if(hash_entry == NULL)
419 {
420 FATAL("Could not allocate memory for tape partition hash entry");
421 continue;
422 }
423
424 // Create key: partition
425 hash_entry->key = entries[i].Number;
426
427 // Copy the tape partition entry data
428 hash_entry->partitionEntry = entries[i];
429
430 // Replace if exists, add if new
431 TapePartitionHashEntry *old_entry = NULL;
432 HASH_REPLACE(hh, ctx->tape_partitions, key, sizeof(uint8_t), hash_entry, old_entry);
433 ctx->dirty_tape_partition_block = true; // Mark tape partition block as dirty
434
435 // Free old entry if it was replaced
436 if(old_entry != NULL)
437 {
438 TRACE("Replaced existing tape partition entry for partition %u", entries[i].Number);
439 free(old_entry);
440 }
441 else
442 TRACE("Added new tape partition entry for partition %u", entries[i].Number);
443 }
444
445 free(buffer);
446}
447
572AARU_EXPORT int32_t AARU_CALL aaruf_get_tape_file(const void *context, const uint8_t partition, const uint32_t file,
573 uint64_t *starting_block, uint64_t *ending_block)
574{
575 TRACE("Entering aaruf_get_tape_file(%p, %d, %d, %llu, %llu)", context, partition, file, *starting_block,
576 *ending_block);
577
578 const aaruformat_context *ctx = NULL;
579
580 if(context == NULL)
581 {
582 FATAL("Invalid context");
583
584 TRACE("Exiting aaruf_get_tape_file() = AARUF_ERROR_NOT_AARUFORMAT");
586 }
587
588 ctx = context;
589
590 // Not a libaaruformat context
591 if(ctx->magic != AARU_MAGIC)
592 {
593 FATAL("Invalid context");
594
595 TRACE("Exiting aaruf_get_tape_file() = AARUF_ERROR_NOT_AARUFORMAT");
597 }
598
599 uint64_t key = (uint64_t)partition << 32 | file;
600 tapeFileHashEntry *entry = NULL;
601 HASH_FIND(hh, ctx->tape_files, &key, sizeof(uint64_t), entry);
602
603 if(entry == NULL)
604 {
605 TRACE("Tape file not found");
607 }
608
609 *starting_block = entry->fileEntry.FirstBlock;
610 *ending_block = entry->fileEntry.LastBlock;
611
612 TRACE("Exiting aaruf_get_tape_file(%p, %d, %d, %llu, %llu) = AARUF_STATUS_OK", context, partition, file,
613 *starting_block, *ending_block);
614 return AARUF_STATUS_OK;
615}
616
773AARU_EXPORT int32_t AARU_CALL aaruf_set_tape_file(void *context, const uint8_t partition, const uint32_t file,
774 const uint64_t starting_block, const uint64_t ending_block)
775{
776 TRACE("Entering aaruf_set_tape_file(%p, %d, %d, %llu, %llu)", context, partition, file, starting_block,
777 ending_block);
778
779 aaruformat_context *ctx = NULL;
780
781 if(context == NULL)
782 {
783 FATAL("Invalid context");
784
785 TRACE("Exiting aaruf_set_tape_file() = AARUF_ERROR_NOT_AARUFORMAT");
787 }
788
789 ctx = context;
790
791 // Not a libaaruformat context
792 if(ctx->magic != AARU_MAGIC)
793 {
794 FATAL("Invalid context");
795
796 TRACE("Exiting aaruf_set_tape_file() = AARUF_ERROR_NOT_AARUFORMAT");
798 }
799
800 // Check we are writing
801 if(!ctx->is_writing)
802 {
803 FATAL("Trying to write a read-only image");
804
805 TRACE("Exiting aaruf_set_tape_file() = AARUF_READ_ONLY");
806 return AARUF_READ_ONLY;
807 }
808
809 // Create hash table entry
810 tapeFileHashEntry *hash_entry = malloc(sizeof(tapeFileHashEntry));
811 if(hash_entry == NULL)
812 {
813 FATAL("Could not allocate memory for tape file hash entry");
814
815 TRACE("Exiting aaruf_set_tape_file() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
817 }
818
819 // Create composite key: partition << 32 | file number
820 hash_entry->key = (uint64_t)partition << 32 | file;
821
822 // Copy the tape file entry data
823 hash_entry->fileEntry.File = file;
824 hash_entry->fileEntry.Partition = partition;
825 hash_entry->fileEntry.FirstBlock = starting_block;
826 hash_entry->fileEntry.LastBlock = ending_block;
827
828 // Replace if exists, add if new
829 tapeFileHashEntry *old_entry = NULL;
830 HASH_REPLACE(hh, ctx->tape_files, key, sizeof(uint64_t), hash_entry, old_entry);
831 ctx->dirty_tape_file_block = true; // Mark tape file block as dirty
832
833 // Free old entry if it was replaced
834 if(old_entry != NULL)
835 {
836 TRACE("Replaced existing tape file entry for partition %u, file %u", partition, file);
837 free(old_entry);
838 }
839 else
840 TRACE("Added new tape file entry for partition %u, file %u", partition, file);
841
842 TRACE("Exiting aaruf_set_tape_file(%p, %d, %d, %llu, %llu) = AARUF_STATUS_OK", context, partition, file,
843 starting_block, ending_block);
844 return AARUF_STATUS_OK;
845}
846
986AARU_EXPORT int32_t AARU_CALL aaruf_get_tape_partition(const void *context, const uint8_t partition,
987 uint64_t *starting_block, uint64_t *ending_block)
988{
989 TRACE("Entering aaruf_get_tape_partition(%p, %d, %llu, %llu)", context, partition, *starting_block, *ending_block);
990
991 const aaruformat_context *ctx = NULL;
992
993 if(context == NULL)
994 {
995 FATAL("Invalid context");
996
997 TRACE("Exiting aaruf_get_tape_partition() = AARUF_ERROR_NOT_AARUFORMAT");
999 }
1000
1001 ctx = context;
1002
1003 // Not a libaaruformat context
1004 if(ctx->magic != AARU_MAGIC)
1005 {
1006 FATAL("Invalid context");
1007
1008 TRACE("Exiting aaruf_get_tape_partition() = AARUF_ERROR_NOT_AARUFORMAT");
1010 }
1011
1012 uint8_t key = partition;
1013 TapePartitionHashEntry *entry = NULL;
1014 HASH_FIND(hh, ctx->tape_partitions, &key, sizeof(uint8_t), entry);
1015
1016 if(entry == NULL)
1017 {
1018 TRACE("Tape partition not found");
1020 }
1021
1022 *starting_block = entry->partitionEntry.FirstBlock;
1023 *ending_block = entry->partitionEntry.LastBlock;
1024
1025 TRACE("Exiting aaruf_get_tape_partition(%p, %d, %llu, %llu) = AARUF_STATUS_OK", context, partition, *starting_block,
1026 *ending_block);
1027 return AARUF_STATUS_OK;
1028}
1029
1200AARU_EXPORT int32_t AARU_CALL aaruf_set_tape_partition(void *context, const uint8_t partition,
1201 const uint64_t starting_block, const uint64_t ending_block)
1202{
1203 TRACE("Entering aaruf_set_tape_partition(%p, %d, %llu, %llu)", context, partition, starting_block, ending_block);
1204
1205 aaruformat_context *ctx = NULL;
1206
1207 if(context == NULL)
1208 {
1209 FATAL("Invalid context");
1210
1211 TRACE("Exiting aaruf_set_tape_partition() = AARUF_ERROR_NOT_AARUFORMAT");
1213 }
1214
1215 ctx = context;
1216
1217 // Not a libaaruformat context
1218 if(ctx->magic != AARU_MAGIC)
1219 {
1220 FATAL("Invalid context");
1221
1222 TRACE("Exiting aaruf_set_tape_partition() = AARUF_ERROR_NOT_AARUFORMAT");
1224 }
1225
1226 // Check we are writing
1227 if(!ctx->is_writing)
1228 {
1229 FATAL("Trying to write a read-only image");
1230
1231 TRACE("Exiting aaruf_set_tape_partition() = AARUF_READ_ONLY");
1232 return AARUF_READ_ONLY;
1233 }
1234
1235 // Create hash table entry
1236 TapePartitionHashEntry *hash_entry = malloc(sizeof(TapePartitionHashEntry));
1237 if(hash_entry == NULL)
1238 {
1239 FATAL("Could not allocate memory for tape partition hash entry");
1240
1241 TRACE("Exiting aaruf_set_tape_partition() = AARUF_ERROR_NOT_ENOUGH_MEMORY");
1243 }
1244
1245 // Create key: partition
1246 hash_entry->key = partition;
1247
1248 // Copy the tape partition entry data
1249 hash_entry->partitionEntry.Number = partition;
1250 hash_entry->partitionEntry.FirstBlock = starting_block;
1251 hash_entry->partitionEntry.LastBlock = ending_block;
1252
1253 // Replace if exists, add if new
1254 TapePartitionHashEntry *old_entry = NULL;
1255 HASH_REPLACE(hh, ctx->tape_partitions, key, sizeof(uint8_t), hash_entry, old_entry);
1256 ctx->dirty_tape_partition_block = true; // Mark tape partition block as dirty
1257
1258 // Free old entry if it was replaced
1259 if(old_entry != NULL)
1260 {
1261 TRACE("Replaced existing tape partition entry for partition %u", partition);
1262 free(old_entry);
1263 }
1264 else
1265 TRACE("Added new tape partition entry for partition %u", partition);
1266
1267 TRACE("Exiting aaruf_set_tape_partition(%p, %d, %llu, %llu) = AARUF_STATUS_OK", context, partition, starting_block,
1268 ending_block);
1269 return AARUF_STATUS_OK;
1270}
1271
1319AARU_EXPORT int32_t AARU_CALL aaruf_get_all_tape_files(const void *context, uint8_t *buffer, size_t *length)
1320{
1321 TRACE("Entering aaruf_get_all_tape_files(%p, %p, %zu)", context, buffer, (length ? *length : 0));
1322
1323 // Check context is correct AaruFormat context
1324 if(context == NULL)
1325 {
1326 FATAL("Invalid context");
1327 TRACE("Exiting aaruf_get_all_tape_files() = AARUF_ERROR_NOT_AARUFORMAT");
1329 }
1330
1331 const aaruformat_context *ctx = context;
1332
1333 // Not a libaaruformat context
1334 if(ctx->magic != AARU_MAGIC)
1335 {
1336 FATAL("Invalid context");
1337 TRACE("Exiting aaruf_get_all_tape_files() = AARUF_ERROR_NOT_AARUFORMAT");
1339 }
1340
1341 if(ctx->tape_files == NULL)
1342 {
1343 FATAL("Image contains no tape files");
1344 TRACE("Exiting aaruf_get_all_tape_files() = AARUF_ERROR_TAPE_FILE_NOT_FOUND");
1346 }
1347
1348 // Iterate all tape files to count how many do we have
1349 const size_t count = HASH_COUNT(ctx->tape_files);
1350 const size_t required_size = count * sizeof(TapeFileEntry);
1351
1352 if(buffer == NULL || length == NULL || *length < required_size)
1353 {
1354 if(length) *length = required_size;
1355 TRACE("Buffer too small for tape files, required %zu bytes", required_size);
1356 TRACE("Exiting aaruf_get_all_tape_files() = AARUF_ERROR_BUFFER_TOO_SMALL");
1358 }
1359
1360 size_t index = 0;
1361 const tapeFileHashEntry *entry;
1362 const tapeFileHashEntry *tmp;
1363 HASH_ITER(hh, ctx->tape_files, entry, tmp)
1364 {
1365 if(index < count)
1366 {
1367 memcpy(&((TapeFileEntry *)buffer)[index], &entry->fileEntry, sizeof(TapeFileEntry));
1368 index++;
1369 }
1370 }
1371 *length = required_size;
1372
1373 TRACE("Exiting aaruf_get_all_tape_files(%p, %p, %zu) = AARUF_STATUS_OK", context, buffer, *length);
1374 return AARUF_STATUS_OK;
1375}
1376
1421AARU_EXPORT int32_t AARU_CALL aaruf_get_all_tape_partitions(const void *context, uint8_t *buffer, size_t *length)
1422{
1423 TRACE("Entering aaruf_get_all_tape_partitions(%p, %p, %zu)", context, buffer, (length ? *length : 0));
1424
1425 // Check context is correct AaruFormat context
1426 if(context == NULL)
1427 {
1428 FATAL("Invalid context");
1429 TRACE("Exiting aaruf_get_all_tape_partitions() = AARUF_ERROR_NOT_AARUFORMAT");
1431 }
1432
1433 const aaruformat_context *ctx = context;
1434
1435 // Not a libaaruformat context
1436 if(ctx->magic != AARU_MAGIC)
1437 {
1438 FATAL("Invalid context");
1439 TRACE("Exiting aaruf_get_all_tape_partitions() = AARUF_ERROR_NOT_AARUFORMAT");
1441 }
1442
1443 if(ctx->tape_partitions == NULL)
1444 {
1445 FATAL("Image contains no tape partitions");
1446 TRACE("Exiting aaruf_get_all_tape_partitions() = AARUF_ERROR_TAPE_PARTITION_NOT_FOUND");
1448 }
1449
1450 // Iterate all tape partitions to count how many do we have
1451 const size_t count = HASH_COUNT(ctx->tape_partitions);
1452 const size_t required_size = count * sizeof(TapePartitionEntry);
1453
1454 if(buffer == NULL || length == NULL || *length < required_size)
1455 {
1456 if(length) *length = required_size;
1457 TRACE("Buffer too small for tape partitions, required %zu bytes", required_size);
1458 TRACE("Exiting aaruf_get_all_tape_partitions() = AARUF_ERROR_BUFFER_TOO_SMALL");
1460 }
1461
1462 size_t index = 0;
1463 const TapePartitionHashEntry *entry;
1464 const TapePartitionHashEntry *tmp;
1465 HASH_ITER(hh, ctx->tape_partitions, entry, tmp)
1466 {
1467 if(index < count)
1468 {
1469 memcpy(&((TapePartitionEntry *)buffer)[index], &entry->partitionEntry, sizeof(TapePartitionEntry));
1470 index++;
1471 }
1472 }
1473 *length = required_size;
1474
1475 TRACE("Exiting aaruf_get_all_tape_partitions(%p, %p, %zu) = AARUF_STATUS_OK", context, buffer, *length);
1476 return AARUF_STATUS_OK;
1477}
#define AARU_MAGIC
Magic identifier for AaruFormat container (ASCII "AARUFRMT").
Definition consts.h:64
struct TapeFileHashEntry tapeFileHashEntry
#define AARU_CALL
Definition decls.h:46
uint64_t aaruf_crc64_data(const uint8_t *data, uint32_t len)
Definition crc64.c:160
#define AARU_EXPORT
Definition decls.h:55
@ TapePartitionBlock
Block containing list of partitions for a tape image.
Definition enums.h:182
@ TapeFileBlock
Block containing list of files for a tape image.
Definition enums.h:181
#define AARUF_ERROR_TAPE_PARTITION_NOT_FOUND
Requested tape partition not present in image.
Definition errors.h:68
#define AARUF_STATUS_OK
Sector present and read without uncorrectable errors.
Definition errors.h:81
#define AARUF_READ_ONLY
Operation requires write mode but context is read-only.
Definition errors.h:61
#define AARUF_ERROR_NOT_ENOUGH_MEMORY
Memory allocation failure (critical).
Definition errors.h:48
#define AARUF_ERROR_TAPE_FILE_NOT_FOUND
Requested tape file number not present in image.
Definition errors.h:67
#define AARUF_ERROR_NOT_AARUFORMAT
Input file/stream failed magic or structural validation.
Definition errors.h:40
#define AARUF_ERROR_BUFFER_TOO_SMALL
Caller-supplied buffer insufficient for data.
Definition errors.h:49
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
int64_t aaru_off_t
Definition internal.h:42
#define FATAL(fmt,...)
Definition log.h:40
#define TRACE(fmt,...)
Definition log.h:25
uint64_t ImageSize
Size of the image payload in bytes (excludes headers/metadata).
Definition aaru.h:937
Single index entry describing a block's type, (optional) data classification, and file offset.
Definition index.h:109
uint64_t offset
Absolute byte offset in the image where the referenced block header begins.
Definition index.h:112
Describes a single logical file on a tape medium.
Definition tape.h:134
uint32_t File
File number (unique within the partition).
Definition tape.h:135
uint64_t LastBlock
Last block of the file (inclusive).
Definition tape.h:142
uint64_t FirstBlock
First block of the file (inclusive).
Definition tape.h:139
uint8_t Partition
Partition number containing this file.
Definition tape.h:137
uint64_t key
Composite key: partition << 32 | file.
Definition context.h:131
TapeFileEntry fileEntry
The actual tape file data.
Definition context.h:132
Header for a tape file metadata block containing file layout information.
Definition tape.h:238
uint32_t entries
Number of file entries following this header.
Definition tape.h:241
uint32_t identifier
Block type identifier.
Definition tape.h:239
uint64_t crc64
CRC64-ECMA checksum of the entry data.
Definition tape.h:245
Describes a single physical partition on a tape medium.
Definition tape.h:320
uint64_t LastBlock
Last block in the partition (inclusive).
Definition tape.h:325
uint64_t FirstBlock
First block in the partition (inclusive).
Definition tape.h:323
uint8_t Number
Partition number (unique identifier for this partition).
Definition tape.h:321
uint8_t key
Key: partition.
Definition context.h:138
TapePartitionEntry partitionEntry
The actual tape partition data.
Definition context.h:139
Header for a tape partition metadata block containing partition layout information.
Definition tape.h:441
uint64_t crc64
CRC64-ECMA checksum of the entry data.
Definition tape.h:448
uint8_t entries
Number of partition entries following this header.
Definition tape.h:444
uint32_t identifier
Block type identifier.
Definition tape.h:442
Master context representing an open or in‑creation Aaru image.
Definition context.h:175
tapeFileHashEntry * tape_files
Hash table root for tape files.
Definition context.h:311
bool dirty_tape_partition_block
True if tape partition block should be written during close.
Definition context.h:338
bool is_writing
True if context opened/created for writing.
Definition context.h:295
uint64_t magic
File magic (AARU_MAGIC) post-open.
Definition context.h:177
FILE * imageStream
Underlying FILE* stream (binary mode).
Definition context.h:179
bool dirty_tape_file_block
True if tape file block should be written during close.
Definition context.h:337
ImageInfo image_info
Exposed high-level image info summary.
Definition context.h:263
TapePartitionHashEntry * tape_partitions
Hash table root for tape partitions.
Definition context.h:312
int32_t aaruf_set_tape_file(void *context, const uint8_t partition, const uint32_t file, const uint64_t starting_block, const uint64_t ending_block)
Sets or updates the block range for a specific tape file in an Aaru tape image.
Definition tape.c:773
int32_t aaruf_get_all_tape_partitions(const void *context, uint8_t *buffer, size_t *length)
Retrieves all tape partition entries from the image.
Definition tape.c:1421
int32_t aaruf_get_tape_file(const void *context, const uint8_t partition, const uint32_t file, uint64_t *starting_block, uint64_t *ending_block)
Retrieves the block range for a specific tape file from an Aaru tape image.
Definition tape.c:572
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
int32_t aaruf_get_tape_partition(const void *context, const uint8_t partition, uint64_t *starting_block, uint64_t *ending_block)
Retrieves the block range for a specific tape partition from an Aaru tape image.
Definition tape.c:986
int32_t aaruf_set_tape_partition(void *context, const uint8_t partition, const uint64_t starting_block, const uint64_t ending_block)
Sets or updates the block range for a specific tape partition in an Aaru tape image.
Definition tape.c:1200
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 aaruf_get_all_tape_files(const void *context, uint8_t *buffer, size_t *length)
Retrieves all tape file entries from the image.
Definition tape.c:1319