Coverage Report

Created: 2025-09-05 06:58

/src/libfsntfs/libfsntfs/libfsntfs_volume_information_values.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Volume information attribute ($VOLUME_INFORMATION) values functions
3
 *
4
 * Copyright (C) 2010-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 "libfsntfs_debug.h"
28
#include "libfsntfs_definitions.h"
29
#include "libfsntfs_libcerror.h"
30
#include "libfsntfs_libcnotify.h"
31
#include "libfsntfs_mft_attribute.h"
32
#include "libfsntfs_volume_information_values.h"
33
34
#include "fsntfs_volume_information.h"
35
36
/* Creates volume information values
37
 * Make sure the value volume_information_values is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libfsntfs_volume_information_values_initialize(
41
     libfsntfs_volume_information_values_t **volume_information_values,
42
     libcerror_error_t **error )
43
0
{
44
0
  static char *function = "libfsntfs_volume_information_values_initialize";
45
46
0
  if( volume_information_values == NULL )
47
0
  {
48
0
    libcerror_error_set(
49
0
     error,
50
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52
0
     "%s: invalid volume information values.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
0
  if( *volume_information_values != NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
62
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63
0
     "%s: invalid volume information values value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
0
  *volume_information_values = memory_allocate_structure(
69
0
                                libfsntfs_volume_information_values_t );
70
71
0
  if( *volume_information_values == NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
76
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
77
0
     "%s: unable to create volume information values.",
78
0
     function );
79
80
0
    goto on_error;
81
0
  }
82
0
  if( memory_set(
83
0
       *volume_information_values,
84
0
       0,
85
0
       sizeof( libfsntfs_volume_information_values_t ) ) == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
90
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
91
0
     "%s: unable to clear volume information values.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
0
  return( 1 );
97
98
0
on_error:
99
0
  if( *volume_information_values != NULL )
100
0
  {
101
0
    memory_free(
102
0
     *volume_information_values );
103
104
0
    *volume_information_values = NULL;
105
0
  }
106
0
  return( -1 );
107
0
}
108
109
/* Frees volume information values
110
 * Returns 1 if successful or -1 on error
111
 */
112
int libfsntfs_volume_information_values_free(
113
     libfsntfs_volume_information_values_t **volume_information_values,
114
     libcerror_error_t **error )
115
0
{
116
0
  static char *function = "libfsntfs_volume_information_values_free";
117
118
0
  if( volume_information_values == NULL )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
123
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
124
0
     "%s: invalid volume information values.",
125
0
     function );
126
127
0
    return( -1 );
128
0
  }
129
0
  if( *volume_information_values != NULL )
130
0
  {
131
0
    memory_free(
132
0
     *volume_information_values );
133
134
0
    *volume_information_values = NULL;
135
0
  }
136
0
  return( 1 );
137
0
}
138
139
/* Reads the volume information values
140
 * Returns 1 if successful or -1 on error
141
 */
142
int libfsntfs_volume_information_values_read_data(
143
     libfsntfs_volume_information_values_t *volume_information_values,
144
     const uint8_t *data,
145
     size_t data_size,
146
     libcerror_error_t **error )
147
0
{
148
0
  static char *function = "libfsntfs_volume_information_values_read_data";
149
150
0
  if( volume_information_values == NULL )
151
0
  {
152
0
    libcerror_error_set(
153
0
     error,
154
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
155
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
156
0
     "%s: invalid volume information values.",
157
0
     function );
158
159
0
    return( -1 );
160
0
  }
161
0
  if( data == NULL )
162
0
  {
163
0
    libcerror_error_set(
164
0
     error,
165
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
166
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
167
0
     "%s: invalid data.",
168
0
     function );
169
170
0
    return( -1 );
171
0
  }
172
0
  if( data_size > (size_t) SSIZE_MAX )
173
0
  {
174
0
    libcerror_error_set(
175
0
     error,
176
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
177
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
178
0
     "%s: invalid data size value out of bounds.",
179
0
     function );
180
181
0
    return( -1 );
182
0
  }
183
#if defined( HAVE_DEBUG_OUTPUT )
184
  if( libcnotify_verbose != 0 )
185
  {
186
    libcnotify_printf(
187
     "%s: volume information data:\n",
188
     function );
189
    libcnotify_print_data(
190
     data,
191
     data_size,
192
     0 );
193
  }
194
#endif
195
0
  if( data_size != 12 )
196
0
  {
197
0
    libcerror_error_set(
198
0
     error,
199
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
200
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
201
0
     "%s: unsupported volume information data size: %" PRIzd "\n",
202
0
     function,
203
0
     data_size );
204
205
0
    return( -1 );
206
0
  }
207
0
  volume_information_values->major_version = ( (fsntfs_volume_information_t *) data )->major_version;
208
0
  volume_information_values->minor_version = ( (fsntfs_volume_information_t *) data )->minor_version;
209
210
0
  byte_stream_copy_to_uint16_little_endian(
211
0
   ( (fsntfs_volume_information_t *) data )->flags,
212
0
   volume_information_values->flags );
213
214
#if defined( HAVE_DEBUG_OUTPUT )
215
  if( libcnotify_verbose != 0 )
216
  {
217
    libcnotify_printf(
218
     "%s: unknown1:\n",
219
     function );
220
    libcnotify_print_data(
221
     ( (fsntfs_volume_information_t *) data )->unknown1,
222
     8,
223
     0 );
224
225
    libcnotify_printf(
226
     "%s: major version\t\t: %" PRIu8 "\n",
227
     function,
228
     volume_information_values->major_version );
229
230
    libcnotify_printf(
231
     "%s: minor version\t\t: %" PRIu8 "\n",
232
     function,
233
     volume_information_values->minor_version );
234
235
    libcnotify_printf(
236
     "%s: flags\t\t\t: 0x%04" PRIx16 "\n",
237
     function,
238
     volume_information_values->flags );
239
    libfsntfs_debug_print_volume_information_flags(
240
     volume_information_values->flags );
241
    libcnotify_printf(
242
     "\n" );
243
244
    libcnotify_printf(
245
     "\n" );
246
  }
247
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
248
249
0
  return( 1 );
250
0
}
251
252
/* Reads the volume information values from an MFT attribute
253
 * Returns 1 if successful or -1 on error
254
 */
255
int libfsntfs_volume_information_values_read_from_mft_attribute(
256
     libfsntfs_volume_information_values_t *volume_information_values,
257
     libfsntfs_mft_attribute_t *mft_attribute,
258
     libcerror_error_t **error )
259
0
{
260
0
  uint8_t *data           = NULL;
261
0
  static char *function   = "libfsntfs_volume_information_values_read_from_mft_attribute";
262
0
  size_t data_size        = 0;
263
0
  uint32_t attribute_type = 0;
264
0
  int result              = 0;
265
266
0
  if( volume_information_values == NULL )
267
0
  {
268
0
    libcerror_error_set(
269
0
     error,
270
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
271
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
272
0
     "%s: invalid volume information values.",
273
0
     function );
274
275
0
    return( -1 );
276
0
  }
277
0
  if( libfsntfs_mft_attribute_get_type(
278
0
       mft_attribute,
279
0
       &attribute_type,
280
0
       error ) != 1 )
281
0
  {
282
0
    libcerror_error_set(
283
0
     error,
284
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
285
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
286
0
     "%s: unable to retrieve type from attribute.",
287
0
     function );
288
289
0
    return( -1 );
290
0
  }
291
0
  if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION )
292
0
  {
293
0
    libcerror_error_set(
294
0
     error,
295
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
296
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
297
0
     "%s: unsupported attribute type.",
298
0
     function );
299
300
0
    return( -1 );
301
0
  }
302
0
  result = libfsntfs_mft_attribute_data_is_resident(
303
0
            mft_attribute,
304
0
            error );
305
306
0
  if( result == -1 )
307
0
  {
308
0
    libcerror_error_set(
309
0
     error,
310
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
311
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
312
0
     "%s: unable to determine if attribute data is resident.",
313
0
     function );
314
315
0
    return( -1 );
316
0
  }
317
0
  else if( result == 0 )
318
0
  {
319
0
    libcerror_error_set(
320
0
     error,
321
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
322
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
323
0
     "%s: unsupported non-resident attribute.",
324
0
     function );
325
326
0
    return( 1 );
327
0
  }
328
0
  if( libfsntfs_mft_attribute_get_resident_data(
329
0
       mft_attribute,
330
0
       &data,
331
0
       &data_size,
332
0
       error ) != 1 )
333
0
  {
334
0
    libcerror_error_set(
335
0
     error,
336
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
337
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
338
0
     "%s: unable to retrieve resident data from attribute.",
339
0
     function );
340
341
0
    return( -1 );
342
0
  }
343
0
  if( libfsntfs_volume_information_values_read_data(
344
0
       volume_information_values,
345
0
       data,
346
0
       data_size,
347
0
       error ) != 1 )
348
0
  {
349
0
    libcerror_error_set(
350
0
     error,
351
0
     LIBCERROR_ERROR_DOMAIN_IO,
352
0
     LIBCERROR_IO_ERROR_READ_FAILED,
353
0
     "%s: unable to read volume information values.",
354
0
     function );
355
356
0
    return( -1 );
357
0
  }
358
0
  return( 1 );
359
0
}
360