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 free(ctx->dpm_block);
178 ctx->dpm_block = NULL;
179 ctx->dpm_block_length = 0;
180
181 if(ctx->dump_hardware_entries_with_data != NULL)
182 {
183 for(int i = 0; i < ctx->dump_hardware_header.entries; i++)
184 {
203 }
204 free(ctx->dump_hardware_entries_with_data); // Free the array itself
206 }
207
208 free(ctx->readableSectorTags);
209 ctx->readableSectorTags = NULL;
210
212 ctx->ecc_cd_context = NULL;
213
214 free(ctx->checksums.spamsum);
215 ctx->checksums.spamsum = NULL;
216
217 // Free PS3 encryption context
218 if(ctx->ps3_disc_key != NULL)
219 {
220 memset(ctx->ps3_disc_key, 0, 16);
221 free(ctx->ps3_disc_key);
222 ctx->ps3_disc_key = NULL;
223 }
224 free(ctx->ps3_plaintext_regions);
225 ctx->ps3_plaintext_regions = NULL;
227 ctx->ps3_encryption_initialized = false;
228
229 // Free Wii U encryption context
230 if(ctx->wiiu_disc_key != NULL)
231 {
232 memset(ctx->wiiu_disc_key, 0, 16);
233 free(ctx->wiiu_disc_key);
234 ctx->wiiu_disc_key = NULL;
235 }
236 if(ctx->wiiu_partition_regions != NULL)
237 {
238 // Wipe keys from partition regions before freeing
239 uint32_t wiiu_count = ctx->wiiu_partition_region_count;
240 uint8_t *region_mem = (uint8_t *)ctx->wiiu_partition_regions;
241 // Each region entry contains a 16-byte key at offset 8; wipe the entire block
242 memset(region_mem, 0, wiiu_count * 24);
243 free(ctx->wiiu_partition_regions);
244 ctx->wiiu_partition_regions = NULL;
245 }
247 ctx->wiiu_encryption_initialized = false;
249 ctx->wiiu_encrypted_block_cache = NULL;
250 ctx->wiiu_cache_valid = false;
251
252 // Free Nintendo GC/Wii junk map context
253 if(ctx->ngcw_junk_entries != NULL)
254 {
255 free(ctx->ngcw_junk_entries);
256 ctx->ngcw_junk_entries = NULL;
257 }
258 ctx->ngcw_junk_entry_count = 0;
259 ctx->ngcw_junk_seed_size = 0;
260 ctx->ngcw_junk_initialized = false;
261
262 // Free Wii encryption context
263 if(ctx->wii_partition_regions != NULL)
264 {
265 // Wipe keys from partition regions before freeing
266 uint32_t wii_count = ctx->wii_partition_region_count;
267 uint8_t *wii_region = (uint8_t *)ctx->wii_partition_regions;
268 memset(wii_region, 0, wii_count * 24);
269 free(ctx->wii_partition_regions);
270 ctx->wii_partition_regions = NULL;
271 }
273 ctx->wii_encryption_initialized = false;
274 free(ctx->wii_encrypted_group_cache);
275 ctx->wii_encrypted_group_cache = NULL;
276 ctx->wii_cache_valid = false;
277
278 free(ctx->sector_id);
279 free(ctx->sector_ied);
280 free(ctx->sector_cpr_mai);
281 free(ctx->sector_edc);
282
283 // Free DDT allocations (v1 and v2)
284 free(ctx->user_data_ddt); // Legacy v1 DDT
285 free(ctx->user_data_ddt2); // v2 DDT primary/secondary
286 free(ctx->cached_secondary_ddt2); // Cached secondary DDT (read operations)
287
288 // Free erasure coding state
289 ec_free(ctx);
290
291 // Free LRU caches (uses cache->free_func to free cached values)
293 free_cache(&ctx->block_cache);
294
295 free(context);
296
297 TRACE("Exiting aaruf_close() = 0");
298 return 0;
299}
static void aaruf_set_close_error(const int error_code)
Definition close.c:49
#define AARU_MAGIC
Magic identifier for AaruFormat container (ASCII "AARUFRMT").
Definition consts.h:64
#define AARU_CALL
Definition decls.h:46
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
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:934
#define AARUF_STATUS_OK
Sector present and read without uncorrectable errors.
Definition errors.h:82
#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:118
uint8_t * spamsum
SpamSum fuzzy hash (ASCII), allocated length+1 with trailing 0.
Definition context.h:116
uint8_t * firmware
Firmware version string or NULL.
Definition context.h:439
uint8_t * revision
Hardware revision string or NULL.
Definition context.h:438
uint8_t * model
Model string or NULL.
Definition context.h:437
uint8_t * softwareName
Dump software name or NULL.
Definition context.h:441
struct DumpExtent * extents
Array of extents (entry.extents elements) or NULL.
Definition context.h:435
uint8_t * manufacturer
Manufacturer string (UTF-8) or NULL.
Definition context.h:436
uint8_t * softwareVersion
Dump software version or NULL.
Definition context.h:442
uint8_t * serial
Serial number string or NULL.
Definition context.h:440
uint8_t * softwareOperatingSystem
Host operating system string or NULL.
Definition context.h:443
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:178
uint8_t * ps3_disc_key
Cached disc key (16 bytes), NULL if not loaded.
Definition context.h:357
Checksums checksums
Whole-image checksums discovered.
Definition context.h:279
size_t dpm_block_length
Length of dpm_block in bytes, 0 if not present.
Definition context.h:224
void * wiiu_partition_regions
Parsed WiiuPartitionRegion array, NULL if not loaded.
Definition context.h:364
uint8_t * cicm_block
CICM XML payload.
Definition context.h:221
uint8_t * sector_cpr_mai
DVD sector CPR_MAI (6 bytes) if present.
Definition context.h:214
uint32_t ps3_plaintext_region_count
Number of plaintext regions.
Definition context.h:359
uint8_t * sector_prefix_corrected
Corrected variant (post error correction) if stored.
Definition context.h:207
uint64_t * user_data_ddt
Legacy flat DDT pointer (NULL when using v2 mini/big arrays).
Definition context.h:187
uint32_t wiiu_partition_region_count
Number of partition regions.
Definition context.h:365
uint16_t ngcw_junk_seed_size
LFG seed size in uint32 words (expected: 17).
Definition context.h:375
TrackEntry * data_tracks
Filtered list of data tracks (subset of trackEntries).
Definition context.h:253
uint8_t * wiiu_encrypted_block_cache
Cached re-encrypted 0x8000-byte physical sector.
Definition context.h:367
void * ngcw_junk_entries
Parsed NgcwJunkEntry array, NULL if not loaded.
Definition context.h:373
struct CacheHeader block_header_cache
LRU/Cache header for block headers.
Definition context.h:266
uint8_t * sector_ied
DVD sector IED (2 bytes) if present.
Definition context.h:213
uint64_t * user_data_ddt2
DDT entries (big variant) primary/secondary current.
Definition context.h:193
uint8_t * sector_prefix
Raw per-sector prefix (e.g., sync+header) uncorrected.
Definition context.h:206
uint64_t * sector_suffix_ddt2
CD sector suffix DDT V2.
Definition context.h:192
uint8_t * sector_edc
DVD or Blu-ray sector EDC (4 bytes) if present (see DvdSectorEdc / BdSectorEdc data types).
Definition context.h:215
CdEccContext * ecc_cd_context
CD ECC/EDC helper tables (allocated on demand).
Definition context.h:258
struct CacheHeader block_cache
LRU/Cache header for block payloads.
Definition context.h:267
bool ps3_encryption_initialized
Whether lazy init has occurred.
Definition context.h:360
uint32_t * sector_suffix_ddt
Legacy CD sector suffix DDT.
Definition context.h:190
bool in_memory_ddt
True if primary (and possibly secondary) DDT loaded.
Definition context.h:202
uint8_t * sector_suffix
Raw per-sector suffix (EDC/ECC) uncorrected.
Definition context.h:208
uint64_t magic
File magic (AARU_MAGIC) post-open.
Definition context.h:180
uint64_t * sector_prefix_ddt2
CD sector prefix DDT V2.
Definition context.h:191
int32_t(*) finalize_write(struct aaruformat_context *ctx)
Writer finalization hook (NULL for reader).
Definition context.h:306
mediaTagEntry * mediaTags
Hash table of extra media tags (uthash root).
Definition context.h:274
uint8_t * wiiu_disc_key
Cached disc key (16 bytes), NULL if not loaded.
Definition context.h:363
struct DumpHardwareEntriesWithData * dump_hardware_entries_with_data
Array of dump hardware entries + strings.
Definition context.h:219
uint32_t ngcw_junk_entry_count
Number of junk entries.
Definition context.h:374
uint64_t * cached_secondary_ddt2
Cached secondary table (big entries) or NULL.
Definition context.h:194
uint32_t wii_partition_region_count
Number of partition regions.
Definition context.h:380
bool wiiu_encryption_initialized
Whether lazy init has occurred.
Definition context.h:366
bool wii_encryption_initialized
Whether lazy init has occurred.
Definition context.h:381
uint8_t * sector_subchannel
Raw 96-byte subchannel (if captured).
Definition context.h:210
void * wii_partition_regions
Parsed WiiPartitionRegion array, NULL if not loaded.
Definition context.h:379
FILE * imageStream
Underlying FILE* stream (binary mode).
Definition context.h:182
UT_array * index_entries
Flattened index entries (UT_array of IndexEntry).
Definition context.h:262
uint8_t * mode2_subheaders
MODE2 Form1/Form2 8-byte subheaders (concatenated).
Definition context.h:211
bool wii_cache_valid
Whether the encrypted group cache is valid.
Definition context.h:384
uint8_t * sector_id
DVD sector ID (4 bytes) if present.
Definition context.h:212
DumpHardwareHeader dump_hardware_header
Dump hardware header.
Definition context.h:242
void * ps3_plaintext_regions
Parsed Ps3PlaintextRegion array (max 32), NULL if not loaded.
Definition context.h:358
bool * readableSectorTags
Per-sector boolean array (optical tags read successfully?).
Definition context.h:273
uint32_t * sector_prefix_ddt
Legacy CD sector prefix DDT (deprecated by *2).
Definition context.h:189
uint8_t * dpm_block
Data Position Measurement block, header included.
Definition context.h:223
bool wiiu_cache_valid
Whether the encrypted block cache is valid.
Definition context.h:369
TrackEntry * track_entries
Full track list (tracksHeader.entries elements).
Definition context.h:252
uint8_t * sector_suffix_corrected
Corrected suffix if stored separately.
Definition context.h:209
uint8_t * metadata_block
Raw metadata UTF-16LE concatenated strings.
Definition context.h:220
uint8_t * wii_encrypted_group_cache
Cached re-encrypted 0x8000-byte group.
Definition context.h:382
bool ngcw_junk_initialized
Whether junk map has been loaded.
Definition context.h:376
size_t mapped_memory_ddt_size
Length of mmapped DDT if userDataDdt is mmapped.
Definition context.h:199
Hash table entry for an arbitrary media tag (e.g., proprietary drive/medium descriptor).
Definition context.h:125
uint8_t * data
Tag data blob (opaque to library core); length bytes long.
Definition context.h:126