Coverage Report

Created: 2025-06-22 07:35

/src/libfsntfs/libfsntfs/libfsntfs_txf_data_values.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The Transactional NTFS (TxF) data ($TXF_DATA) logged utility stream
3
 * attribute ($LOGGED_UTILITY_STREAM) values functions
4
 *
5
 * Copyright (C) 2010-2024, Joachim Metz <joachim.metz@gmail.com>
6
 *
7
 * Refer to AUTHORS for acknowledgements.
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Lesser General Public License as published by
11
 * the Free Software Foundation, either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
#include <common.h>
24
#include <byte_stream.h>
25
#include <memory.h>
26
#include <types.h>
27
28
#include "libfsntfs_definitions.h"
29
#include "libfsntfs_libcerror.h"
30
#include "libfsntfs_libcnotify.h"
31
#include "libfsntfs_mft_attribute.h"
32
#include "libfsntfs_txf_data_values.h"
33
34
#include "fsntfs_txf_data.h"
35
36
/* Creates TxF data values
37
 * Make sure the value txf_data_values is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libfsntfs_txf_data_values_initialize(
41
     libfsntfs_txf_data_values_t **txf_data_values,
42
     libcerror_error_t **error )
43
0
{
44
0
  static char *function = "libfsntfs_txf_data_values_initialize";
45
46
0
  if( txf_data_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 TxF data values.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
0
  if( *txf_data_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 TxF data values value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
0
  *txf_data_values = memory_allocate_structure(
69
0
                      libfsntfs_txf_data_values_t );
70
71
0
  if( *txf_data_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 TxF data values.",
78
0
     function );
79
80
0
    goto on_error;
81
0
  }
82
0
  if( memory_set(
83
0
       *txf_data_values,
84
0
       0,
85
0
       sizeof( libfsntfs_txf_data_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 TxF data values.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
0
  return( 1 );
97
98
0
on_error:
99
0
  if( *txf_data_values != NULL )
100
0
  {
101
0
    memory_free(
102
0
     *txf_data_values );
103
104
0
    *txf_data_values = NULL;
105
0
  }
106
0
  return( -1 );
107
0
}
108
109
/* Frees TxF data values
110
 * Returns 1 if successful or -1 on error
111
 */
112
int libfsntfs_txf_data_values_free(
113
     libfsntfs_txf_data_values_t **txf_data_values,
114
     libcerror_error_t **error )
115
0
{
116
0
  static char *function = "libfsntfs_txf_data_values_free";
117
118
0
  if( txf_data_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 TxF data values.",
125
0
     function );
126
127
0
    return( -1 );
128
0
  }
129
0
  if( *txf_data_values != NULL )
130
0
  {
131
0
    memory_free(
132
0
     *txf_data_values );
133
134
0
    *txf_data_values = NULL;
135
0
  }
136
0
  return( 1 );
137
0
}
138
139
/* Reads the TxF data values
140
 * Returns 1 if successful or -1 on error
141
 */
142
int libfsntfs_txf_data_values_read_data(
143
     libfsntfs_txf_data_values_t *txf_data_values,
144
     const uint8_t *data,
145
     size_t data_size,
146
     libcerror_error_t **error )
147
0
{
148
0
  static char *function = "libfsntfs_txf_data_values_read_data";
149
150
#if defined( HAVE_DEBUG_OUTPUT )
151
  uint64_t value_64bit  = 0;
152
  uint16_t value_16bit  = 0;
153
#endif
154
155
0
  if( txf_data_values == NULL )
156
0
  {
157
0
    libcerror_error_set(
158
0
     error,
159
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
160
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
161
0
     "%s: invalid TxF data values.",
162
0
     function );
163
164
0
    return( -1 );
165
0
  }
166
0
  if( data == NULL )
167
0
  {
168
0
    libcerror_error_set(
169
0
     error,
170
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
171
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
172
0
     "%s: invalid data.",
173
0
     function );
174
175
0
    return( -1 );
176
0
  }
177
0
  if( data_size > (size_t) SSIZE_MAX )
178
0
  {
179
0
    libcerror_error_set(
180
0
     error,
181
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
182
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
183
0
     "%s: invalid data size value out of bounds.",
184
0
     function );
185
186
0
    return( -1 );
187
0
  }
188
#if defined( HAVE_DEBUG_OUTPUT )
189
  if( libcnotify_verbose != 0 )
190
  {
191
    libcnotify_printf(
192
     "%s: TxF data values:\n",
193
     function );
194
    libcnotify_print_data(
195
     data,
196
     data_size,
197
     0 );
198
  }
199
#endif
200
0
  if( data_size != sizeof( fsntfs_txf_data_t ) )
201
0
  {
202
0
    libcerror_error_set(
203
0
     error,
204
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
205
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
206
0
     "%s: unsupported TxF data values size: %" PRIzd "\n",
207
0
     function,
208
0
     data_size );
209
210
0
    return( -1 );
211
0
  }
212
0
  byte_stream_copy_to_uint64_little_endian(
213
0
   ( (fsntfs_txf_data_t *) data )->rm_root_file_reference,
214
0
   txf_data_values->rm_root_file_reference );
215
216
0
  byte_stream_copy_to_uint64_little_endian(
217
0
   ( (fsntfs_txf_data_t *) data )->file_identifier,
218
0
   txf_data_values->file_identifier );
219
220
0
  byte_stream_copy_to_uint64_little_endian(
221
0
   ( (fsntfs_txf_data_t *) data )->data_lsn,
222
0
   txf_data_values->data_lsn );
223
224
0
  byte_stream_copy_to_uint64_little_endian(
225
0
   ( (fsntfs_txf_data_t *) data )->metadata_lsn,
226
0
   txf_data_values->metadata_lsn );
227
228
0
  byte_stream_copy_to_uint64_little_endian(
229
0
   ( (fsntfs_txf_data_t *) data )->directory_index_lsn,
230
0
   txf_data_values->directory_index_lsn );
231
232
#if defined( HAVE_DEBUG_OUTPUT )
233
  if( libcnotify_verbose != 0 )
234
  {
235
    libcnotify_printf(
236
     "%s: unknown1:\n",
237
     function );
238
    libcnotify_print_data(
239
     ( (fsntfs_txf_data_t *) data )->unknown1,
240
     6,
241
     0 );
242
243
    libcnotify_printf(
244
     "%s: resource manager root file reference\t: %" PRIu64 "- %" PRIu64 "\n",
245
     function,
246
     txf_data_values->rm_root_file_reference & 0xffffffffffffUL,
247
     txf_data_values->rm_root_file_reference >> 48 );
248
249
    byte_stream_copy_to_uint64_little_endian(
250
     ( (fsntfs_txf_data_t *) data )->usn_index,
251
     value_64bit );
252
    libcnotify_printf(
253
     "%s: update sequence number index\t\t: 0x%08" PRIx64 "\n",
254
     function,
255
     value_64bit );
256
257
    libcnotify_printf(
258
     "%s: file identifier\t\t\t\t: 0x%08" PRIx64 "\n",
259
     function,
260
     txf_data_values->file_identifier );
261
262
    libcnotify_printf(
263
     "%s: data log sequence number\t\t\t: 0x%08" PRIx64 "\n",
264
     function,
265
     txf_data_values->data_lsn );
266
267
    libcnotify_printf(
268
     "%s: metadata log sequence number\t\t: 0x%08" PRIx64 "\n",
269
     function,
270
     txf_data_values->metadata_lsn );
271
272
    libcnotify_printf(
273
     "%s: directory index log sequence number\t: 0x%08" PRIx64 "\n",
274
     function,
275
     txf_data_values->directory_index_lsn );
276
277
    byte_stream_copy_to_uint16_little_endian(
278
     ( (fsntfs_txf_data_t *) data )->flags,
279
     value_16bit );
280
    libcnotify_printf(
281
     "%s: flags\t\t\t\t\t: 0x%04" PRIx16 "\n",
282
     function,
283
     value_16bit );
284
285
    libcnotify_printf(
286
     "\n" );
287
  }
288
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
289
290
0
  return( 1 );
291
0
}
292
293
/* Reads the TxF data values from an MFT attribute
294
 * Returns 1 if successful or -1 on error
295
 */
296
int libfsntfs_txf_data_values_read_from_mft_attribute(
297
     libfsntfs_txf_data_values_t *txf_data_values,
298
     libfsntfs_mft_attribute_t *mft_attribute,
299
     libcerror_error_t **error )
300
0
{
301
0
  uint8_t *data           = NULL;
302
0
  static char *function   = "libfsntfs_txf_data_values_read_from_mft_attribute";
303
0
  size_t data_size        = 0;
304
0
  uint32_t attribute_type = 0;
305
0
  int result              = 0;
306
307
0
  if( txf_data_values == NULL )
308
0
  {
309
0
    libcerror_error_set(
310
0
     error,
311
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
312
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
313
0
     "%s: invalid TxF data values.",
314
0
     function );
315
316
0
    return( -1 );
317
0
  }
318
0
  if( libfsntfs_mft_attribute_get_type(
319
0
       mft_attribute,
320
0
       &attribute_type,
321
0
       error ) != 1 )
322
0
  {
323
0
    libcerror_error_set(
324
0
     error,
325
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
326
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
327
0
     "%s: unable to retrieve type from attribute.",
328
0
     function );
329
330
0
    return( -1 );
331
0
  }
332
0
  if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_LOGGED_UTILITY_STREAM )
333
0
  {
334
0
    libcerror_error_set(
335
0
     error,
336
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
337
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
338
0
     "%s: unsupported attribute type.",
339
0
     function );
340
341
0
    return( -1 );
342
0
  }
343
0
  result = libfsntfs_mft_attribute_data_is_resident(
344
0
            mft_attribute,
345
0
            error );
346
347
0
  if( result == -1 )
348
0
  {
349
0
    libcerror_error_set(
350
0
     error,
351
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
352
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
353
0
     "%s: unable to determine if attribute data is resident.",
354
0
     function );
355
356
0
    return( -1 );
357
0
  }
358
0
  else if( result == 0 )
359
0
  {
360
0
    libcerror_error_set(
361
0
     error,
362
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
363
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
364
0
     "%s: unsupported non-resident attribute.",
365
0
     function );
366
367
0
    return( 1 );
368
0
  }
369
0
  if( libfsntfs_mft_attribute_get_resident_data(
370
0
       mft_attribute,
371
0
       &data,
372
0
       &data_size,
373
0
       error ) != 1 )
374
0
  {
375
0
    libcerror_error_set(
376
0
     error,
377
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
378
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
379
0
     "%s: unable to retrieve resident data from attribute.",
380
0
     function );
381
382
0
    return( -1 );
383
0
  }
384
0
  if( libfsntfs_txf_data_values_read_data(
385
0
       txf_data_values,
386
0
       data,
387
0
       data_size,
388
0
       error ) != 1 )
389
0
  {
390
0
    libcerror_error_set(
391
0
     error,
392
0
     LIBCERROR_ERROR_DOMAIN_IO,
393
0
     LIBCERROR_IO_ERROR_READ_FAILED,
394
0
     "%s: unable to read TxF data values.",
395
0
     function );
396
397
0
    return( -1 );
398
0
  }
399
0
  return( 1 );
400
0
}
401