Coverage Report

Created: 2024-06-12 07:07

/src/libvsgpt/libvsgpt/libvsgpt_partition_entry.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The partition entry functions
3
 *
4
 * Copyright (C) 2019-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 "libvsgpt_debug.h"
28
#include "libvsgpt_definitions.h"
29
#include "libvsgpt_libcerror.h"
30
#include "libvsgpt_libcnotify.h"
31
#include "libvsgpt_libfguid.h"
32
#include "libvsgpt_libuna.h"
33
#include "libvsgpt_partition_entry.h"
34
#include "libvsgpt_partition_type_identifier.h"
35
#include "libvsgpt_types.h"
36
37
#include "vsgpt_partition_entry.h"
38
39
/* Creates a partition entry
40
 * Make sure the value partition_entry is referencing, is set to NULL
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libvsgpt_partition_entry_initialize(
44
     libvsgpt_partition_entry_t **partition_entry,
45
     libcerror_error_t **error )
46
836
{
47
836
  static char *function = "libvsgpt_partition_entry_initialize";
48
49
836
  if( partition_entry == NULL )
50
0
  {
51
0
    libcerror_error_set(
52
0
     error,
53
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
54
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
55
0
     "%s: invalid partition entry.",
56
0
     function );
57
58
0
    return( -1 );
59
0
  }
60
836
  if( *partition_entry != NULL )
61
0
  {
62
0
    libcerror_error_set(
63
0
     error,
64
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
65
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
66
0
     "%s: invalid partition entry value already set.",
67
0
     function );
68
69
0
    return( -1 );
70
0
  }
71
836
  *partition_entry = memory_allocate_structure(
72
836
                      libvsgpt_partition_entry_t );
73
74
836
  if( *partition_entry == NULL )
75
0
  {
76
0
    libcerror_error_set(
77
0
     error,
78
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
79
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
80
0
     "%s: unable to create partition entry.",
81
0
     function );
82
83
0
    goto on_error;
84
0
  }
85
836
  if( memory_set(
86
836
       *partition_entry,
87
836
       0,
88
836
       sizeof( libvsgpt_partition_entry_t ) ) == NULL )
89
0
  {
90
0
    libcerror_error_set(
91
0
     error,
92
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
93
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
94
0
     "%s: unable to clear partition entry.",
95
0
     function );
96
97
0
    goto on_error;
98
0
  }
99
836
  return( 1 );
100
101
0
on_error:
102
0
  if( *partition_entry != NULL )
103
0
  {
104
0
    memory_free(
105
0
     *partition_entry );
106
107
0
    *partition_entry = NULL;
108
0
  }
109
0
  return( -1 );
110
836
}
111
112
/* Frees a partition entry
113
 * Returns 1 if successful or -1 on error
114
 */
115
int libvsgpt_partition_entry_free(
116
     libvsgpt_partition_entry_t **partition_entry,
117
     libcerror_error_t **error )
118
836
{
119
836
  static char *function = "libvsgpt_partition_entry_free";
120
121
836
  if( partition_entry == NULL )
122
0
  {
123
0
    libcerror_error_set(
124
0
     error,
125
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
126
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
127
0
     "%s: invalid partition entry.",
128
0
     function );
129
130
0
    return( -1 );
131
0
  }
132
836
  if( *partition_entry != NULL )
133
836
  {
134
836
    memory_free(
135
836
     *partition_entry );
136
137
836
    *partition_entry = NULL;
138
836
  }
139
836
  return( 1 );
140
836
}
141
142
/* Checks if a buffer containing the partition entry is filled with same value bytes (empty-block)
143
 * Returns 1 if a pattern was found, 0 if not or -1 on error
144
 */
145
int libvsgpt_partition_entry_check_for_empty_block(
146
     const uint8_t *data,
147
     size_t data_size,
148
     libcerror_error_t **error )
149
0
{
150
0
  libvsgpt_aligned_t *aligned_data_index = NULL;
151
0
  libvsgpt_aligned_t *aligned_data_start = NULL;
152
0
  uint8_t *data_index                    = NULL;
153
0
  uint8_t *data_start                    = NULL;
154
0
  static char *function                  = "libvsgpt_partition_entry_check_for_empty_block";
155
156
0
  if( data == NULL )
157
0
  {
158
0
    libcerror_error_set(
159
0
     error,
160
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
161
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
162
0
     "%s: invalid data.",
163
0
     function );
164
165
0
    return( -1 );
166
0
  }
167
0
  if( data_size > (size_t) SSIZE_MAX )
168
0
  {
169
0
    libcerror_error_set(
170
0
     error,
171
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
172
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
173
0
     "%s: invalid data size value exceeds maximum.",
174
0
     function );
175
176
0
    return( -1 );
177
0
  }
178
0
  data_start = (uint8_t *) data;
179
0
  data_index = (uint8_t *) data + 1;
180
0
  data_size -= 1;
181
182
  /* Only optimize for data larger than the alignment
183
   */
184
0
  if( data_size > ( 2 * sizeof( libvsgpt_aligned_t ) ) )
185
0
  {
186
    /* Align the data start
187
     */
188
0
    while( ( (intptr_t) data_start % sizeof( libvsgpt_aligned_t ) ) != 0 )
189
0
    {
190
0
      if( *data_start != *data_index )
191
0
      {
192
0
        return( 0 );
193
0
      }
194
0
      data_start += 1;
195
0
      data_index += 1;
196
0
      data_size  -= 1;
197
0
    }
198
    /* Align the data index
199
     */
200
0
    while( ( (intptr_t) data_index % sizeof( libvsgpt_aligned_t ) ) != 0 )
201
0
    {
202
0
      if( *data_start != *data_index )
203
0
      {
204
0
        return( 0 );
205
0
      }
206
0
      data_index += 1;
207
0
      data_size  -= 1;
208
0
    }
209
0
    aligned_data_start = (libvsgpt_aligned_t *) data_start;
210
0
    aligned_data_index = (libvsgpt_aligned_t *) data_index;
211
212
0
    while( data_size > sizeof( libvsgpt_aligned_t ) )
213
0
    {
214
0
      if( *aligned_data_start != *aligned_data_index )
215
0
      {
216
0
        return( 0 );
217
0
      }
218
0
      aligned_data_index += 1;
219
0
      data_size          -= sizeof( libvsgpt_aligned_t );
220
0
    }
221
0
    data_index = (uint8_t *) aligned_data_index;
222
0
  }
223
0
  while( data_size != 0 )
224
0
  {
225
0
    if( *data_start != *data_index )
226
0
    {
227
0
      return( 0 );
228
0
    }
229
0
    data_index += 1;
230
0
    data_size  -= 1;
231
0
  }
232
0
  return( 1 );
233
0
}
234
235
/* Reads a partition entry
236
 * Returns 1 if successful or -1 on error
237
 */
238
int libvsgpt_partition_entry_read_data(
239
     libvsgpt_partition_entry_t *partition_entry,
240
     const uint8_t *data,
241
     size_t data_size,
242
     libcerror_error_t **error )
243
9.35k
{
244
9.35k
  static char *function = "libvsgpt_partition_entry_read_data";
245
246
9.35k
  if( partition_entry == NULL )
247
0
  {
248
0
    libcerror_error_set(
249
0
     error,
250
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
251
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
252
0
     "%s: invalid partition entry.",
253
0
     function );
254
255
0
    return( -1 );
256
0
  }
257
9.35k
  if( data == NULL )
258
0
  {
259
0
    libcerror_error_set(
260
0
     error,
261
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
262
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
263
0
     "%s: invalid data.",
264
0
     function );
265
266
0
    return( -1 );
267
0
  }
268
9.35k
  if( ( data_size < sizeof( vsgpt_partition_entry_t) )
269
9.35k
   || ( data_size > (size_t) SSIZE_MAX ) )
270
0
  {
271
0
    libcerror_error_set(
272
0
     error,
273
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
274
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
275
0
     "%s: data size value out of bounds.",
276
0
     function );
277
278
0
    return( -1 );
279
0
  }
280
#if defined( HAVE_DEBUG_OUTPUT )
281
  if( libcnotify_verbose != 0 )
282
  {
283
    libcnotify_printf(
284
     "%s: entry data:\n",
285
     function );
286
    libcnotify_print_data(
287
     data,
288
     data_size,
289
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
290
  }
291
#endif
292
9.35k
  if( memory_copy(
293
9.35k
       partition_entry->type_identifier,
294
9.35k
       ( (vsgpt_partition_entry_t *) data )->type_identifier,
295
9.35k
       16 ) == NULL )
296
0
  {
297
0
    libcerror_error_set(
298
0
     error,
299
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
300
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
301
0
     "%s: unable to copy type identifier.",
302
0
     function );
303
304
0
    return( -1 );
305
0
  }
306
9.35k
  if( memory_copy(
307
9.35k
       partition_entry->identifier,
308
9.35k
       ( (vsgpt_partition_entry_t *) data )->identifier,
309
9.35k
       16 ) == NULL )
310
0
  {
311
0
    libcerror_error_set(
312
0
     error,
313
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
314
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
315
0
     "%s: unable to copy identifier.",
316
0
     function );
317
318
0
    return( -1 );
319
0
  }
320
9.35k
  byte_stream_copy_to_uint64_little_endian(
321
9.35k
   ( (vsgpt_partition_entry_t *) data )->start_block_number,
322
9.35k
   partition_entry->start_block_number );
323
324
9.35k
  byte_stream_copy_to_uint64_little_endian(
325
9.35k
   ( (vsgpt_partition_entry_t *) data )->end_block_number,
326
9.35k
   partition_entry->end_block_number );
327
328
9.35k
  byte_stream_copy_to_uint64_little_endian(
329
9.35k
   ( (vsgpt_partition_entry_t *) data )->attribute_flags,
330
9.35k
   partition_entry->attribute_flags );
331
332
9.35k
  if( memory_copy(
333
9.35k
       partition_entry->name,
334
9.35k
       ( (vsgpt_partition_entry_t *) data )->name,
335
9.35k
       72 ) == NULL )
336
0
  {
337
0
    libcerror_error_set(
338
0
     error,
339
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
340
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
341
0
     "%s: unable to copy name.",
342
0
     function );
343
344
0
    return( -1 );
345
0
  }
346
#if defined( HAVE_DEBUG_OUTPUT )
347
  if( libcnotify_verbose != 0 )
348
  {
349
    if( libvsgpt_debug_print_guid_value(
350
         function,
351
         "type identifier\t\t\t",
352
         ( (vsgpt_partition_entry_t *) data )->type_identifier,
353
         16,
354
         LIBFGUID_ENDIAN_LITTLE,
355
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
356
         error ) != 1 )
357
    {
358
      libcerror_error_set(
359
       error,
360
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
361
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
362
       "%s: unable to print GUID value.",
363
       function );
364
365
      return( -1 );
366
    }
367
    libcnotify_printf(
368
     "%s: type identifier description\t\t: %s\n",
369
     function,
370
     libvsgpt_partition_type_identifier_get_description(
371
      ( (vsgpt_partition_entry_t *) data )->type_identifier ) );
372
373
    if( libvsgpt_debug_print_guid_value(
374
         function,
375
         "identifier\t\t\t\t",
376
         ( (vsgpt_partition_entry_t *) data )->identifier,
377
         16,
378
         LIBFGUID_ENDIAN_LITTLE,
379
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
380
         error ) != 1 )
381
    {
382
      libcerror_error_set(
383
       error,
384
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
385
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
386
       "%s: unable to print GUID value.",
387
       function );
388
389
      return( -1 );
390
    }
391
    libcnotify_printf(
392
     "%s: start block number\t\t\t: %" PRIu64 "\n",
393
     function,
394
     partition_entry->start_block_number );
395
396
    libcnotify_printf(
397
     "%s: end block number\t\t\t: %" PRIu64 "\n",
398
     function,
399
     partition_entry->end_block_number );
400
401
    libcnotify_printf(
402
     "%s: attribute flags\t\t\t: %" PRIu64 "\n",
403
     function,
404
     partition_entry->attribute_flags );
405
406
    if( libvsgpt_debug_print_utf16_string_value(
407
         function,
408
         "name\t\t\t\t",
409
         ( (vsgpt_partition_entry_t *) data )->name,
410
         72,
411
         LIBUNA_ENDIAN_LITTLE,
412
         error ) != 1 )
413
    {
414
      libcerror_error_set(
415
       error,
416
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
417
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
418
       "%s: unable to print UTF-16 string value.",
419
       function );
420
421
      return( -1 );
422
    }
423
    libcnotify_printf(
424
     "\n" );
425
  }
426
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
427
428
9.35k
  return( 1 );
429
9.35k
}
430