Coverage Report

Created: 2024-02-11 06:57

/src/libphdi/libphdi/libphdi_sparse_image_header.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Sparse image header functions
3
 *
4
 * Copyright (C) 2015-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libphdi_libbfio.h"
28
#include "libphdi_libcerror.h"
29
#include "libphdi_libcnotify.h"
30
#include "libphdi_sparse_image_header.h"
31
32
#include "phdi_sparse_image_header.h"
33
34
const uint8_t phdi_sparse_image_signature[ 16 ] = {
35
  'W', 'i', 't', 'h', 'o', 'u', 't', 'F', 'r', 'e', 'e', 'S', 'p', 'a', 'c', 'e' };
36
37
/* Creates sparse image header
38
 * Make sure the value sparse_image_header is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libphdi_sparse_image_header_initialize(
42
     libphdi_sparse_image_header_t **sparse_image_header,
43
     libcerror_error_t **error )
44
0
{
45
0
  static char *function = "libphdi_sparse_image_header_initialize";
46
47
0
  if( sparse_image_header == NULL )
48
0
  {
49
0
    libcerror_error_set(
50
0
     error,
51
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
52
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
53
0
     "%s: invalid sparse image header.",
54
0
     function );
55
56
0
    return( -1 );
57
0
  }
58
0
  if( *sparse_image_header != NULL )
59
0
  {
60
0
    libcerror_error_set(
61
0
     error,
62
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
63
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
64
0
     "%s: invalid sparse image header value already set.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
0
  *sparse_image_header = memory_allocate_structure(
70
0
                          libphdi_sparse_image_header_t );
71
72
0
  if( *sparse_image_header == NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
77
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
78
0
     "%s: unable to create sparse image header.",
79
0
     function );
80
81
0
    goto on_error;
82
0
  }
83
0
  if( memory_set(
84
0
       *sparse_image_header,
85
0
       0,
86
0
       sizeof( libphdi_sparse_image_header_t ) ) == NULL )
87
0
  {
88
0
    libcerror_error_set(
89
0
     error,
90
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
91
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
92
0
     "%s: unable to clear sparse image header.",
93
0
     function );
94
95
0
    memory_free(
96
0
     *sparse_image_header );
97
98
0
    *sparse_image_header = NULL;
99
100
0
    return( -1 );
101
0
  }
102
0
  return( 1 );
103
104
0
on_error:
105
0
  if( *sparse_image_header != NULL )
106
0
  {
107
0
    memory_free(
108
0
     *sparse_image_header );
109
110
0
    *sparse_image_header = NULL;
111
0
  }
112
0
  return( -1 );
113
0
}
114
115
/* Frees a sparse image header
116
 * Returns 1 if successful or -1 on error
117
 */
118
int libphdi_sparse_image_header_free(
119
     libphdi_sparse_image_header_t **sparse_image_header,
120
     libcerror_error_t **error )
121
0
{
122
0
  static char *function = "libphdi_sparse_image_header_free";
123
124
0
  if( sparse_image_header == NULL )
125
0
  {
126
0
    libcerror_error_set(
127
0
     error,
128
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
129
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
130
0
     "%s: invalid sparse image header.",
131
0
     function );
132
133
0
    return( -1 );
134
0
  }
135
0
  if( *sparse_image_header != NULL )
136
0
  {
137
0
    memory_free(
138
0
     *sparse_image_header );
139
140
0
    *sparse_image_header = NULL;
141
0
  }
142
0
  return( 1 );
143
0
}
144
145
/* Reads the sparse image header data
146
 * Returns 1 if successful, 0 if the signature does not match or -1 on error
147
 */
148
int libphdi_sparse_image_header_read_data(
149
     libphdi_sparse_image_header_t *sparse_image_header,
150
     const uint8_t *data,
151
     size_t data_size,
152
     libcerror_error_t **error )
153
0
{
154
0
  static char *function   = "libphdi_sparse_image_header_read_data";
155
0
  uint32_t format_version = 0;
156
157
#if defined( HAVE_DEBUG_OUTPUT )
158
  uint32_t value_32bit   = 0;
159
#endif
160
161
0
  if( sparse_image_header == NULL )
162
0
  {
163
0
    libcerror_error_set(
164
0
     error,
165
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
166
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
167
0
     "%s: invalid sparse image header.",
168
0
     function );
169
170
0
    return( -1 );
171
0
  }
172
0
  if( data == NULL )
173
0
  {
174
0
    libcerror_error_set(
175
0
     error,
176
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
177
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
178
0
     "%s: invalid data.",
179
0
     function );
180
181
0
    return( -1 );
182
0
  }
183
0
  if( ( data_size < sizeof( phdi_sparse_image_header_t ) )
184
0
   || ( data_size > (size_t) SSIZE_MAX ) )
185
0
  {
186
0
    libcerror_error_set(
187
0
     error,
188
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
189
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
190
0
     "%s: invalid data size value out of bounds.",
191
0
     function );
192
193
0
    return( -1 );
194
0
  }
195
#if defined( HAVE_DEBUG_OUTPUT )
196
  if( libcnotify_verbose != 0 )
197
  {
198
    libcnotify_printf(
199
     "%s: sparse image header data:\n",
200
     function );
201
    libcnotify_print_data(
202
     data,
203
     sizeof( phdi_sparse_image_header_t ),
204
     0 );
205
  }
206
#endif
207
/* TODO add support for "WithouFreSpacExt" */
208
209
0
  if( memory_compare(
210
0
       ( (phdi_sparse_image_header_t *) data )->signature,
211
0
       phdi_sparse_image_signature,
212
0
       16 ) != 0 )
213
0
  {
214
0
    libcerror_error_set(
215
0
     error,
216
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
217
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
218
0
     "%s: unsupported signature.",
219
0
     function );
220
221
0
    return( -1 );
222
0
  }
223
0
  byte_stream_copy_to_uint32_little_endian(
224
0
   ( (phdi_sparse_image_header_t *) data )->format_version,
225
0
   format_version );
226
227
0
  byte_stream_copy_to_uint32_little_endian(
228
0
   ( (phdi_sparse_image_header_t *) data )->block_size,
229
0
   sparse_image_header->block_size );
230
231
0
  byte_stream_copy_to_uint32_little_endian(
232
0
   ( (phdi_sparse_image_header_t *) data )->number_of_allocation_table_entries,
233
0
   sparse_image_header->number_of_allocation_table_entries );
234
235
0
  byte_stream_copy_to_uint64_little_endian(
236
0
   ( (phdi_sparse_image_header_t *) data )->number_of_sectors,
237
0
   sparse_image_header->number_of_sectors );
238
239
0
  byte_stream_copy_to_uint32_little_endian(
240
0
   ( (phdi_sparse_image_header_t *) data )->data_start_sector,
241
0
   sparse_image_header->data_start_sector );
242
243
#if defined( HAVE_DEBUG_OUTPUT )
244
  if( libcnotify_verbose != 0 )
245
  {
246
    libcnotify_printf(
247
     "%s: signature\t\t\t\t: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
248
     function,
249
     ( (phdi_sparse_image_header_t *) data )->signature[ 0 ],
250
     ( (phdi_sparse_image_header_t *) data )->signature[ 1 ],
251
     ( (phdi_sparse_image_header_t *) data )->signature[ 2 ],
252
     ( (phdi_sparse_image_header_t *) data )->signature[ 3 ],
253
     ( (phdi_sparse_image_header_t *) data )->signature[ 4 ],
254
     ( (phdi_sparse_image_header_t *) data )->signature[ 5 ],
255
     ( (phdi_sparse_image_header_t *) data )->signature[ 6 ],
256
     ( (phdi_sparse_image_header_t *) data )->signature[ 7 ],
257
     ( (phdi_sparse_image_header_t *) data )->signature[ 8 ],
258
     ( (phdi_sparse_image_header_t *) data )->signature[ 9 ],
259
     ( (phdi_sparse_image_header_t *) data )->signature[ 10 ],
260
     ( (phdi_sparse_image_header_t *) data )->signature[ 11 ],
261
     ( (phdi_sparse_image_header_t *) data )->signature[ 12 ],
262
     ( (phdi_sparse_image_header_t *) data )->signature[ 13 ],
263
     ( (phdi_sparse_image_header_t *) data )->signature[ 14 ],
264
     ( (phdi_sparse_image_header_t *) data )->signature[ 15 ] );
265
266
    libcnotify_printf(
267
     "%s: format version\t\t\t\t: %" PRIu32 "\n",
268
     function,
269
     format_version );
270
271
    byte_stream_copy_to_uint32_little_endian(
272
     ( (phdi_sparse_image_header_t *) data )->number_of_heads,
273
     value_32bit );
274
    libcnotify_printf(
275
     "%s: number of heads\t\t\t\t: %" PRIu32 "\n",
276
     function,
277
     value_32bit );
278
279
    byte_stream_copy_to_uint32_little_endian(
280
     ( (phdi_sparse_image_header_t *) data )->number_of_cylinders,
281
     value_32bit );
282
    libcnotify_printf(
283
     "%s: number of cylinders\t\t\t: %" PRIu32 "\n",
284
     function,
285
     value_32bit );
286
287
    libcnotify_printf(
288
     "%s: block size\t\t\t\t: %" PRIu32 "\n",
289
     function,
290
     sparse_image_header->block_size );
291
292
    libcnotify_printf(
293
     "%s: number of allocation table entries\t: %" PRIu32 "\n",
294
     function,
295
     sparse_image_header->number_of_allocation_table_entries );
296
297
    libcnotify_printf(
298
     "%s: number of sectors\t\t\t: %" PRIu64 "\n",
299
     function,
300
     sparse_image_header->number_of_sectors );
301
302
    byte_stream_copy_to_uint32_little_endian(
303
     ( (phdi_sparse_image_header_t *) data )->unknown1,
304
     value_32bit );
305
    libcnotify_printf(
306
     "%s: unknown1\t\t\t\t\t: 0x%08" PRIx32 "\n",
307
     function,
308
     value_32bit );
309
310
    libcnotify_printf(
311
     "%s: data start sector\t\t\t: %" PRIu32 "\n",
312
     function,
313
     sparse_image_header->data_start_sector );
314
315
    libcnotify_printf(
316
     "%s: unknown2:\n",
317
     function );
318
    libcnotify_print_data(
319
     (uint8_t *) ( (phdi_sparse_image_header_t *) data )->unknown2,
320
     12,
321
     0 );
322
  }
323
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
324
325
0
  if( format_version != 2 )
326
0
  {
327
0
    libcerror_error_set(
328
0
     error,
329
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
330
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
331
0
     "%s: unsupported format version: %" PRIu32 ".",
332
0
     function,
333
0
     format_version );
334
335
0
    return( -1 );
336
0
  }
337
0
  if( sparse_image_header->block_size == 0 )
338
0
  {
339
0
    libcerror_error_set(
340
0
     error,
341
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
342
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
343
0
     "%s: invalid block size value out of bounds.",
344
0
     function );
345
346
0
    return( -1 );
347
0
  }
348
0
  return( 1 );
349
0
}
350
351
/* Reads the sparse image header
352
 * Returns 1 if successful, 0 if the signature does not match or -1 on error
353
 */
354
int libphdi_sparse_image_header_read_file_io_handle(
355
     libphdi_sparse_image_header_t *sparse_image_header,
356
     libbfio_handle_t *file_io_handle,
357
     libcerror_error_t **error )
358
0
{
359
0
  uint8_t sparse_image_header_data[ sizeof( phdi_sparse_image_header_t ) ];
360
361
0
  static char *function = "libphdi_sparse_image_header_read_file_io_handle";
362
0
  ssize_t read_count    = 0;
363
364
0
  if( sparse_image_header == NULL )
365
0
  {
366
0
    libcerror_error_set(
367
0
     error,
368
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
369
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
370
0
     "%s: invalid sparse image header.",
371
0
     function );
372
373
0
    return( -1 );
374
0
  }
375
#if defined( HAVE_DEBUG_OUTPUT )
376
  if( libcnotify_verbose != 0 )
377
  {
378
    libcnotify_printf(
379
     "%s: reading sparse image header at offset: 0 (0x00000000)\n",
380
     function );
381
  }
382
#endif
383
0
  read_count = libbfio_handle_read_buffer_at_offset(
384
0
                file_io_handle,
385
0
                sparse_image_header_data,
386
0
                sizeof( phdi_sparse_image_header_t ),
387
0
                0,
388
0
                error );
389
390
0
  if( read_count != (ssize_t) sizeof( phdi_sparse_image_header_t ) )
391
0
  {
392
0
    libcerror_error_set(
393
0
     error,
394
0
     LIBCERROR_ERROR_DOMAIN_IO,
395
0
     LIBCERROR_IO_ERROR_READ_FAILED,
396
0
     "%s: unable to read sparse image header data at offset: 0 (0x00000000).",
397
0
     function );
398
399
0
    return( -1 );
400
0
  }
401
0
  if( libphdi_sparse_image_header_read_data(
402
0
       sparse_image_header,
403
0
       sparse_image_header_data,
404
0
       sizeof( phdi_sparse_image_header_t ),
405
0
       error ) != 1 )
406
0
  {
407
0
    libcerror_error_set(
408
0
     error,
409
0
     LIBCERROR_ERROR_DOMAIN_IO,
410
0
     LIBCERROR_IO_ERROR_READ_FAILED,
411
0
     "%s: unable to read sparse image header.",
412
0
     function );
413
414
0
    return( -1 );
415
0
  }
416
0
  return( 1 );
417
0
}
418
419
/* Retrieves the block size
420
 * Returns 1 if successful or -1 on error
421
 */
422
int libphdi_sparse_image_header_get_block_size(
423
     libphdi_sparse_image_header_t *sparse_image_header,
424
     size64_t *block_size,
425
     libcerror_error_t **error )
426
0
{
427
0
  static char *function = "libphdi_sparse_image_header_get_block_size";
428
429
0
  if( sparse_image_header == NULL )
430
0
  {
431
0
    libcerror_error_set(
432
0
     error,
433
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
434
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
435
0
     "%s: invalid sparse image header.",
436
0
     function );
437
438
0
    return( -1 );
439
0
  }
440
0
  if( block_size == NULL )
441
0
  {
442
0
    libcerror_error_set(
443
0
     error,
444
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
445
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
446
0
     "%s: invalid block size.",
447
0
     function );
448
449
0
    return( -1 );
450
0
  }
451
0
  *block_size = (size64_t) sparse_image_header->block_size * 512;
452
453
0
  return( 1 );
454
0
}
455