Coverage Report

Created: 2025-06-22 07:35

/src/libvsgpt/libvsgpt/libvsgpt_mbr_partition_entry.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The Master Boot Record (MBR) 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_chs_address.h"
28
#include "libvsgpt_debug.h"
29
#include "libvsgpt_definitions.h"
30
#include "libvsgpt_libcerror.h"
31
#include "libvsgpt_libcnotify.h"
32
#include "libvsgpt_mbr_partition_entry.h"
33
#include "libvsgpt_mbr_partition_type.h"
34
35
#include "vsgpt_mbr_partition_entry.h"
36
37
/* Creates a MBR partition entry
38
 * Make sure the value partition_entry is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libvsgpt_mbr_partition_entry_initialize(
42
     libvsgpt_mbr_partition_entry_t **partition_entry,
43
     libcerror_error_t **error )
44
13.4k
{
45
13.4k
  static char *function = "libvsgpt_mbr_partition_entry_initialize";
46
47
13.4k
  if( partition_entry == 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 partition entry.",
54
0
     function );
55
56
0
    return( -1 );
57
0
  }
58
13.4k
  if( *partition_entry != 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 partition entry value already set.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
13.4k
  *partition_entry = memory_allocate_structure(
70
13.4k
                      libvsgpt_mbr_partition_entry_t );
71
72
13.4k
  if( *partition_entry == 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 partition entry.",
79
0
     function );
80
81
0
    goto on_error;
82
0
  }
83
13.4k
  if( memory_set(
84
13.4k
       *partition_entry,
85
13.4k
       0,
86
13.4k
       sizeof( libvsgpt_mbr_partition_entry_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 partition entry.",
93
0
     function );
94
95
0
    goto on_error;
96
0
  }
97
13.4k
  return( 1 );
98
99
0
on_error:
100
0
  if( *partition_entry != NULL )
101
0
  {
102
0
    memory_free(
103
0
     *partition_entry );
104
105
0
    *partition_entry = NULL;
106
0
  }
107
0
  return( -1 );
108
13.4k
}
109
110
/* Frees a MBR partition entry
111
 * Returns 1 if successful or -1 on error
112
 */
113
int libvsgpt_mbr_partition_entry_free(
114
     libvsgpt_mbr_partition_entry_t **partition_entry,
115
     libcerror_error_t **error )
116
13.4k
{
117
13.4k
  static char *function = "libvsgpt_mbr_partition_entry_free";
118
119
13.4k
  if( partition_entry == NULL )
120
0
  {
121
0
    libcerror_error_set(
122
0
     error,
123
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
124
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
125
0
     "%s: invalid partition entry.",
126
0
     function );
127
128
0
    return( -1 );
129
0
  }
130
13.4k
  if( *partition_entry != NULL )
131
13.4k
  {
132
13.4k
    memory_free(
133
13.4k
     *partition_entry );
134
135
13.4k
    *partition_entry = NULL;
136
13.4k
  }
137
13.4k
  return( 1 );
138
13.4k
}
139
140
/* Reads a MBR partition entry
141
 * Returns 1 if successful or -1 on error
142
 */
143
int libvsgpt_mbr_partition_entry_read_data(
144
     libvsgpt_mbr_partition_entry_t *partition_entry,
145
     const uint8_t *data,
146
     size_t data_size,
147
     libcerror_error_t **error )
148
13.4k
{
149
13.4k
  static char *function               = "libvsgpt_mbr_partition_entry_read_data";
150
151
#if defined( HAVE_DEBUG_OUTPUT )
152
  libvsgpt_chs_address_t *chs_address = NULL;
153
  uint32_t value_32bit                = 0;
154
#endif
155
156
13.4k
  if( partition_entry == 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 partition entry.",
163
0
     function );
164
165
0
    return( -1 );
166
0
  }
167
13.4k
  if( data == NULL )
168
0
  {
169
0
    libcerror_error_set(
170
0
     error,
171
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
172
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
173
0
     "%s: invalid data.",
174
0
     function );
175
176
0
    return( -1 );
177
0
  }
178
13.4k
  if( data_size != sizeof( vsgpt_mbr_partition_entry_t ) )
179
0
  {
180
0
    libcerror_error_set(
181
0
     error,
182
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
183
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
184
0
     "%s: data size value out of bounds.",
185
0
     function );
186
187
0
    return( -1 );
188
0
  }
189
#if defined( HAVE_DEBUG_OUTPUT )
190
  if( libcnotify_verbose != 0 )
191
  {
192
    libcnotify_printf(
193
     "%s: entry data:\n",
194
     function );
195
    libcnotify_print_data(
196
     data,
197
     sizeof( vsgpt_mbr_partition_entry_t ),
198
     0 );
199
  }
200
#endif
201
13.4k
  partition_entry->flags = ( (vsgpt_mbr_partition_entry_t *) data )->flags;
202
203
13.4k
  partition_entry->type = ( (vsgpt_mbr_partition_entry_t *) data )->type;
204
205
13.4k
  byte_stream_copy_to_uint32_little_endian(
206
13.4k
   ( (vsgpt_mbr_partition_entry_t *) data )->start_address_lba,
207
13.4k
   partition_entry->start_address_lba );
208
209
13.4k
  byte_stream_copy_to_uint32_little_endian(
210
13.4k
   ( (vsgpt_mbr_partition_entry_t *) data )->number_of_sectors,
211
13.4k
   partition_entry->number_of_sectors );
212
213
#if defined( HAVE_DEBUG_OUTPUT )
214
  if( libcnotify_verbose != 0 )
215
  {
216
    if( libvsgpt_chs_address_initialize(
217
         &chs_address,
218
         error ) != 1 )
219
    {
220
      libcerror_error_set(
221
       error,
222
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
223
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
224
       "%s: unable to create CHS address.",
225
       function );
226
227
      goto on_error;
228
    }
229
    libcnotify_printf(
230
     "%s: entry: %" PRIu8 " flags\t\t\t: 0x%02" PRIx8 "\n",
231
     function,
232
     partition_entry->index,
233
     partition_entry->flags );
234
    libvsgpt_debug_print_mbr_partition_entry_flags(
235
     partition_entry->flags );
236
    libcnotify_printf(
237
     "\n" );
238
239
    byte_stream_copy_to_uint24_little_endian(
240
     ( (vsgpt_mbr_partition_entry_t *) data )->start_address_chs,
241
     value_32bit );
242
243
    if( libvsgpt_chs_address_copy_from_byte_stream(
244
         chs_address,
245
         ( (vsgpt_mbr_partition_entry_t *) data )->start_address_chs,
246
         3,
247
         LIBVSGPT_ENDIAN_LITTLE,
248
         error ) != 1 )
249
    {
250
      libcerror_error_set(
251
       error,
252
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
253
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
254
       "%s: unable to copy CHS address from byte stream.",
255
       function );
256
257
      goto on_error;
258
    }
259
    libcnotify_printf(
260
     "%s: entry: %" PRIu8 " CHS start address\t: 0x%06" PRIx32 " (C: %" PRIu16 ", H: %" PRIu8 ", S: %" PRIu8 ")\n",
261
     function,
262
     partition_entry->index,
263
     value_32bit,
264
     chs_address->cylinder,
265
     chs_address->head,
266
     chs_address->sector );
267
268
    libcnotify_printf(
269
     "%s: entry: %" PRIu8 " type\t\t\t: 0x%02" PRIx8 " (%s)\n",
270
     function,
271
     partition_entry->index,
272
     partition_entry->type,
273
     libvsgpt_mbr_partition_type_get_description(
274
      partition_entry->type ) );
275
276
    if( libvsgpt_chs_address_copy_from_byte_stream(
277
         chs_address,
278
         ( (vsgpt_mbr_partition_entry_t *) data )->end_address_chs,
279
         3,
280
         LIBVSGPT_ENDIAN_LITTLE,
281
         error ) != 1 )
282
    {
283
      libcerror_error_set(
284
       error,
285
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
286
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
287
       "%s: unable to copy CHS address from byte stream.",
288
       function );
289
290
      goto on_error;
291
    }
292
    byte_stream_copy_to_uint24_little_endian(
293
     ( (vsgpt_mbr_partition_entry_t *) data )->end_address_chs,
294
     value_32bit );
295
296
    libcnotify_printf(
297
     "%s: entry: %" PRIu8 " CHS end address\t: 0x%06" PRIx32 " (C: %" PRIu16 ", H: %" PRIu8 ", S: %" PRIu8 ")\n",
298
     function,
299
     partition_entry->index,
300
     value_32bit,
301
     chs_address->cylinder,
302
     chs_address->head,
303
     chs_address->sector );
304
305
    libcnotify_printf(
306
     "%s: entry: %" PRIu8 " LBA start address\t: %" PRIu32 " (0x%08" PRIx32 ")\n",
307
     function,
308
     partition_entry->index,
309
     partition_entry->start_address_lba,
310
     partition_entry->start_address_lba );
311
312
    libcnotify_printf(
313
     "%s: entry: %" PRIu8 " number of sectors\t: %" PRIu32 "\n",
314
     function,
315
     partition_entry->index,
316
     partition_entry->number_of_sectors );
317
318
    libcnotify_printf(
319
     "\n" );
320
321
    if( libvsgpt_chs_address_free(
322
         &chs_address,
323
         error ) != 1 )
324
    {
325
      libcerror_error_set(
326
       error,
327
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
328
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
329
       "%s: unable to free CHS address.",
330
       function );
331
332
      goto on_error;
333
    }
334
  }
335
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
336
337
13.4k
  return( 1 );
338
339
#if defined( HAVE_DEBUG_OUTPUT )
340
on_error:
341
  if( chs_address != NULL )
342
  {
343
    libvsgpt_chs_address_free(
344
     &chs_address,
345
     NULL );
346
  }
347
  return( -1 );
348
#endif
349
13.4k
}
350