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