libaaruformat 1.0
Aaru Data Preservation Suite - Format Library
Loading...
Searching...
No Matches
close.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 */
29
30#include <errno.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34
35#if defined(_WIN32) || defined(_WIN64)
36#include <windows.h>
37#endif
38
39#ifdef __linux__
40#include <sys/mman.h>
41#endif
42
43#include <aaruformat.h>
44
45#include "erasure_internal.h"
46#include "internal.h"
47#include "log.h"
48
49static inline void aaruf_set_close_error(const int error_code)
50{
51 errno = error_code;
52#if defined(_WIN32) || defined(_WIN64)
53 SetLastError((DWORD)error_code);
54#endif
55}
56
81{
82 TRACE("Entering aaruf_close(%p)", context);
84
85 mediaTagEntry *media_tag = NULL;
86 mediaTagEntry *tmp_media_tag = NULL;
87
88 if(context == NULL)
89 {
90 FATAL("Invalid context");
92 return -1;
93 }
94
95 aaruformat_context *ctx = context;
96
97 // Not a libaaruformat context
98 if(ctx->magic != AARU_MAGIC)
99 {
100 FATAL("Invalid context");
101 aaruf_set_close_error(EINVAL);
102 return -1;
103 }
104
105 if(ctx->finalize_write != NULL)
106 {
107 int32_t res = ctx->finalize_write(ctx);
108 if(res != AARUF_STATUS_OK)
109 {
110 aaruf_set_close_error(errno != 0 ? errno : res);
111 return res;
112 }
113 }
114
115 TRACE("Freeing memory pointers");
116 // This may do nothing if imageStream is NULL, but as the behaviour is undefined, better sure than sorry
117 if(ctx->imageStream != NULL)
118 {
119 fclose(ctx->imageStream);
120 ctx->imageStream = NULL;
121 }
122
123 // Free index entries array
124 if(ctx->index_entries != NULL)
125 {
126 utarray_free(ctx->index_entries);
127 ctx->index_entries = NULL;
128 }
129
130 free(ctx->sector_prefix);
131 ctx->sector_prefix = NULL;
132 free(ctx->sector_prefix_corrected);
133 ctx->sector_prefix_corrected = NULL;
134 free(ctx->sector_suffix);
135 ctx->sector_suffix = NULL;
136 free(ctx->sector_suffix_corrected);
137 ctx->sector_suffix_corrected = NULL;
138 free(ctx->sector_subchannel);
139 ctx->sector_subchannel = NULL;
140 free(ctx->mode2_subheaders);
141 ctx->mode2_subheaders = NULL;
142
143 TRACE("Freeing media tags");
144 if(ctx->mediaTags != NULL) HASH_ITER(hh, ctx->mediaTags, media_tag, tmp_media_tag)
145 {
146 HASH_DEL(ctx->mediaTags, media_tag);
147 free(media_tag->data);
148 free(media_tag);
149 }
150
151#ifdef __linux__ // TODO: Implement
152 TRACE("Unmapping user data DDT if it is not in memory");
153 if(!ctx->in_memory_ddt)
154 {
155 munmap(ctx->user_data_ddt, ctx->mapped_memory_ddt_size);
156 ctx->user_data_ddt = NULL;
157 }
158#endif
159
160 free(ctx->sector_prefix_ddt2);
161 ctx->sector_prefix_ddt2 = NULL;
162 free(ctx->sector_prefix_ddt);
163 ctx->sector_prefix_ddt = NULL;
164 free(ctx->sector_suffix_ddt2);
165 ctx->sector_suffix_ddt2 = NULL;
166 free(ctx->sector_suffix_ddt);
167 ctx->sector_suffix_ddt = NULL;
168
169 free(ctx->metadata_block);
170 ctx->metadata_block = NULL;
171 free(ctx->track_entries);
172 ctx->track_entries = NULL;
173 free(ctx->data_tracks);
174 ctx->data_tracks = NULL;
175 free(ctx->cicm_block);
176 ctx->cicm_block = NULL;
177
178 if(ctx->dump_hardware_entries_with_data != NULL)
179 {
180 for(int i = 0; i < ctx->dump_hardware_header.entries; i++)
181 {
200 }
201 free(ctx->dump_hardware_entries_with_data); // Free the array itself
203 }
204
205 free(ctx->readableSectorTags);
206 ctx->readableSectorTags = NULL;
207
209 ctx->ecc_cd_context = NULL;
210
211 free(ctx->checksums.spamsum);
212 ctx->checksums.spamsum = NULL;
213
214 // Free PS3 encryption context
215 if(ctx->ps3_disc_key != NULL)
216 {
217 memset(ctx->ps3_disc_key, 0, 16);
218 free(ctx->ps3_disc_key);
219 ctx->ps3_disc_key = NULL;
220 }
221 free(ctx->ps3_plaintext_regions);
222 ctx->ps3_plaintext_regions = NULL;
224 ctx->ps3_encryption_initialized = false;
225
226 // Free Wii U encryption context
227 if(ctx->wiiu_disc_key != NULL)
228 {
229 memset(ctx->wiiu_disc_key, 0, 16);
230 free(ctx->wiiu_disc_key);
231 ctx->wiiu_disc_key = NULL;
232 }
233 if(ctx->wiiu_partition_regions != NULL)
234 {
235 // Wipe keys from partition regions before freeing
236 uint32_t wiiu_count = ctx->wiiu_partition_region_count;
237 uint8_t *region_mem = (uint8_t *)ctx->wiiu_partition_regions;
238 // Each region entry contains a 16-byte key at offset 8; wipe the entire block
239 memset(region_mem, 0, wiiu_count * 24);
240 free(ctx->wiiu_partition_regions);
241 ctx->wiiu_partition_regions = NULL;
242 }
244 ctx->wiiu_encryption_initialized = false;
246 ctx->wiiu_encrypted_block_cache = NULL;
247 ctx->wiiu_cache_valid = false;
248
249 // Free Nintendo GC/Wii junk map context
250 if(ctx->ngcw_junk_entries != NULL)
251 {
252 free(ctx->ngcw_junk_entries);
253 ctx->ngcw_junk_entries = NULL;
254 }
255 ctx->ngcw_junk_entry_count = 0;
256 ctx->ngcw_junk_seed_size = 0;
257 ctx->ngcw_junk_initialized = false;
258
259 // Free Wii encryption context
260 if(ctx->wii_partition_regions != NULL)
261 {
262 // Wipe keys from partition regions before freeing
263 uint32_t wii_count = ctx->wii_partition_region_count;
264 uint8_t *wii_region = (uint8_t *)ctx->wii_partition_regions;
265 memset(wii_region, 0, wii_count * 24);
266 free(ctx->wii_partition_regions);
267 ctx->wii_partition_regions = NULL;
268 }
270 ctx->wii_encryption_initialized = false;
271 free(ctx->wii_encrypted_group_cache);
272 ctx->wii_encrypted_group_cache = NULL;
273 ctx->wii_cache_valid = false;
274
275 free(ctx->sector_id);
276 free(ctx->sector_ied);
277 free(ctx->sector_cpr_mai);
278 free(ctx->sector_edc);
279
280 // Free DDT allocations (v1 and v2)
281 free(ctx->user_data_ddt); // Legacy v1 DDT
282 free(ctx->user_data_ddt2); // v2 DDT primary/secondary
283 free(ctx->cached_secondary_ddt2); // Cached secondary DDT (read operations)
284
285 // Free erasure coding state
286 ec_free(ctx);
287
288 // Free LRU caches (uses cache->free_func to free cached values)
290 free_cache(&ctx->block_cache);
291
292 free(context);
293
294 TRACE("Exiting aaruf_close() = 0");
295 return 0;
296}
static void aaruf_set_close_error(const int error_code)
Definition close.c:49
int aaruf_close(void *context)
Close an Aaru image context, flushing pending data structures and releasing resources.
Definition close.c:80
#define AARU_MAGIC
Magic identifier for AaruFormat container (ASCII "AARUFRMT").
Definition consts.h:64
#define AARU_CALL
Definition decls.h:46
#define AARU_EXPORT
Definition decls.h:55
void aaruf_ecc_cd_free(void *context)
Frees a Compact Disc ECC context and its internal tables.
Definition ecc_cd.c:99
void ec_free(aaruformat_context *ctx)
Free all erasure coding state from the context.
Definition erasure.c:876
#define AARUF_STATUS_OK
Sector present and read without uncorrectable errors.
Definition errors.h:81
#define FATAL(fmt,...)
Definition log.h:40
#define TRACE(fmt,...)
Definition log.h:25
void free_cache(struct CacheHeader *cache)
Frees all entries in the cache and clears it.
Definition lru.c:82
uint8_t * spamsum
SpamSum fuzzy hash (ASCII), allocated length+1 with trailing 0.
Definition context.h:113
uint8_t * firmware
Firmware version string or NULL.
Definition context.h:418
uint8_t * revision
Hardware revision string or NULL.
Definition context.h:417
uint8_t * model
Model string or NULL.
Definition context.h:416
uint8_t * softwareName
Dump software name or NULL.
Definition context.h:420
struct DumpExtent * extents
Array of extents (entry.extents elements) or NULL.
Definition context.h:414
uint8_t * manufacturer
Manufacturer string (UTF-8) or NULL.
Definition context.h:415
uint8_t * softwareVersion
Dump software version or NULL.
Definition context.h:421
uint8_t * serial
Serial number string or NULL.
Definition context.h:419
uint8_t * softwareOperatingSystem
Host operating system string or NULL.
Definition context.h:422
uint16_t entries
Number of DumpHardwareEntry records that follow.
Definition dump.h:93
Master context representing an open or in‑creation Aaru image.
Definition context.h:175
uint8_t * ps3_disc_key
Cached disc key (16 bytes), NULL if not loaded.
Definition context.h:348
Checksums checksums
Whole-image checksums discovered.
Definition context.h:272
void * wiiu_partition_regions
Parsed WiiuPartitionRegion array, NULL if not loaded.
Definition context.h:355
uint8_t * cicm_block
CICM XML payload.
Definition context.h:217
uint8_t * sector_cpr_mai
DVD sector CPR_MAI (6 bytes) if present.
Definition context.h:210
uint32_t ps3_plaintext_region_count
Number of plaintext regions.
Definition context.h:350
uint8_t * sector_prefix_corrected
Corrected variant (post error correction) if stored.
Definition context.h:203
uint64_t * user_data_ddt
Legacy flat DDT pointer (NULL when using v2 mini/big arrays).
Definition context.h:184
uint32_t wiiu_partition_region_count
Number of partition regions.
Definition context.h:356
uint16_t ngcw_junk_seed_size
LFG seed size in uint32 words (expected: 17).
Definition context.h:366
TrackEntry * data_tracks
Filtered list of data tracks (subset of trackEntries).
Definition context.h:246
uint8_t * wiiu_encrypted_block_cache
Cached re-encrypted 0x8000-byte physical sector.
Definition context.h:358
void * ngcw_junk_entries
Parsed NgcwJunkEntry array, NULL if not loaded.
Definition context.h:364
struct CacheHeader block_header_cache
LRU/Cache header for block headers.
Definition context.h:259
uint8_t * sector_ied
DVD sector IED (2 bytes) if present.
Definition context.h:209
uint64_t * user_data_ddt2
DDT entries (big variant) primary/secondary current.
Definition context.h:190
uint8_t * sector_prefix
Raw per-sector prefix (e.g., sync+header) uncorrected.
Definition context.h:202
uint64_t * sector_suffix_ddt2
CD sector suffix DDT V2.
Definition context.h:189
uint8_t * sector_edc
DVD sector EDC (4 bytes) if present.
Definition context.h:211
CdEccContext * ecc_cd_context
CD ECC/EDC helper tables (allocated on demand).
Definition context.h:251
struct CacheHeader block_cache
LRU/Cache header for block payloads.
Definition context.h:260
bool ps3_encryption_initialized
Whether lazy init has occurred.
Definition context.h:351
uint32_t * sector_suffix_ddt
Legacy CD sector suffix DDT.
Definition context.h:187
bool in_memory_ddt
True if primary (and possibly secondary) DDT loaded.
Definition context.h:199
uint8_t * sector_suffix
Raw per-sector suffix (EDC/ECC) uncorrected.
Definition context.h:204
int32_t(* finalize_write)(struct aaruformat_context *ctx)
Writer finalization hook (NULL for reader).
Definition context.h:299
uint64_t magic
File magic (AARU_MAGIC) post-open.
Definition context.h:177
uint64_t * sector_prefix_ddt2
CD sector prefix DDT V2.
Definition context.h:188
mediaTagEntry * mediaTags
Hash table of extra media tags (uthash root).
Definition context.h:267
uint8_t * wiiu_disc_key
Cached disc key (16 bytes), NULL if not loaded.
Definition context.h:354
struct DumpHardwareEntriesWithData * dump_hardware_entries_with_data
Array of dump hardware entries + strings.
Definition context.h:215
uint32_t ngcw_junk_entry_count
Number of junk entries.
Definition context.h:365
uint64_t * cached_secondary_ddt2
Cached secondary table (big entries) or NULL.
Definition context.h:191
uint32_t wii_partition_region_count
Number of partition regions.
Definition context.h:371
bool wiiu_encryption_initialized
Whether lazy init has occurred.
Definition context.h:357
bool wii_encryption_initialized
Whether lazy init has occurred.
Definition context.h:372
uint8_t * sector_subchannel
Raw 96-byte subchannel (if captured).
Definition context.h:206
void * wii_partition_regions
Parsed WiiPartitionRegion array, NULL if not loaded.
Definition context.h:370
FILE * imageStream
Underlying FILE* stream (binary mode).
Definition context.h:179
UT_array * index_entries
Flattened index entries (UT_array of IndexEntry).
Definition context.h:255
uint8_t * mode2_subheaders
MODE2 Form1/Form2 8-byte subheaders (concatenated).
Definition context.h:207
bool wii_cache_valid
Whether the encrypted group cache is valid.
Definition context.h:375
uint8_t * sector_id
DVD sector ID (4 bytes) if present.
Definition context.h:208
DumpHardwareHeader dump_hardware_header
Dump hardware header.
Definition context.h:235
void * ps3_plaintext_regions
Parsed Ps3PlaintextRegion array (max 32), NULL if not loaded.
Definition context.h:349
bool * readableSectorTags
Per-sector boolean array (optical tags read successfully?).
Definition context.h:266
uint32_t * sector_prefix_ddt
Legacy CD sector prefix DDT (deprecated by *2).
Definition context.h:186
bool wiiu_cache_valid
Whether the encrypted block cache is valid.
Definition context.h:360
TrackEntry * track_entries
Full track list (tracksHeader.entries elements).
Definition context.h:245
uint8_t * sector_suffix_corrected
Corrected suffix if stored separately.
Definition context.h:205
uint8_t * metadata_block
Raw metadata UTF-16LE concatenated strings.
Definition context.h:216
uint8_t * wii_encrypted_group_cache
Cached re-encrypted 0x8000-byte group.
Definition context.h:373
bool ngcw_junk_initialized
Whether junk map has been loaded.
Definition context.h:367
size_t mapped_memory_ddt_size
Length of mmapped DDT if userDataDdt is mmapped.
Definition context.h:196
Hash table entry for an arbitrary media tag (e.g., proprietary drive/medium descriptor).
Definition context.h:122
uint8_t * data
Tag data blob (opaque to library core); length bytes long.
Definition context.h:123