Coverage Report

Created: 2024-02-25 07:20

/src/libfsapfs/libfsapfs/libfsapfs_file_extent.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * File extent functions
3
 *
4
 * Copyright (C) 2018-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 "libfsapfs_debug.h"
28
#include "libfsapfs_file_extent.h"
29
#include "libfsapfs_libcerror.h"
30
#include "libfsapfs_libcnotify.h"
31
#include "libfsapfs_libfdatetime.h"
32
#include "libfsapfs_libuna.h"
33
34
#include "fsapfs_file_system.h"
35
36
/* Creates a file_extent
37
 * Make sure the value file_extent is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libfsapfs_file_extent_initialize(
41
     libfsapfs_file_extent_t **file_extent,
42
     libcerror_error_t **error )
43
675
{
44
675
  static char *function = "libfsapfs_file_extent_initialize";
45
46
675
  if( file_extent == 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 file extent.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
675
  if( *file_extent != 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 file extent value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
675
  *file_extent = memory_allocate_structure(
69
675
                  libfsapfs_file_extent_t );
70
71
675
  if( *file_extent == 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 file extent.",
78
0
     function );
79
80
0
    goto on_error;
81
0
  }
82
675
  if( memory_set(
83
675
       *file_extent,
84
675
       0,
85
675
       sizeof( libfsapfs_file_extent_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 file extent.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
675
  return( 1 );
97
98
0
on_error:
99
0
  if( *file_extent != NULL )
100
0
  {
101
0
    memory_free(
102
0
     *file_extent );
103
104
0
    *file_extent = NULL;
105
0
  }
106
0
  return( -1 );
107
675
}
108
109
/* Frees a file extent
110
 * Returns 1 if successful or -1 on error
111
 */
112
int libfsapfs_file_extent_free(
113
     libfsapfs_file_extent_t **file_extent,
114
     libcerror_error_t **error )
115
675
{
116
675
  static char *function = "libfsapfs_file_extent_free";
117
118
675
  if( file_extent == 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 file extent.",
125
0
     function );
126
127
0
    return( -1 );
128
0
  }
129
675
  if( *file_extent != NULL )
130
675
  {
131
675
    memory_free(
132
675
     *file_extent );
133
134
675
    *file_extent = NULL;
135
675
  }
136
675
  return( 1 );
137
675
}
138
139
/* Reads the file extent key data
140
 * Returns 1 if successful or -1 on error
141
 */
142
int libfsapfs_file_extent_read_key_data(
143
     libfsapfs_file_extent_t *file_extent,
144
     const uint8_t *data,
145
     size_t data_size,
146
     libcerror_error_t **error )
147
675
{
148
675
  static char *function = "libfsapfs_file_extent_read_key_data";
149
150
#if defined( HAVE_DEBUG_OUTPUT )
151
  uint64_t value_64bit  = 0;
152
#endif
153
154
675
  if( file_extent == NULL )
155
0
  {
156
0
    libcerror_error_set(
157
0
     error,
158
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
159
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
160
0
     "%s: invalid file extent.",
161
0
     function );
162
163
0
    return( -1 );
164
0
  }
165
675
  if( data == NULL )
166
0
  {
167
0
    libcerror_error_set(
168
0
     error,
169
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
170
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
171
0
     "%s: invalid data.",
172
0
     function );
173
174
0
    return( -1 );
175
0
  }
176
675
  if( ( data_size < sizeof( fsapfs_file_system_btree_key_file_extent_t ) )
177
675
   || ( data_size > (size_t) SSIZE_MAX ) )
178
28
  {
179
28
    libcerror_error_set(
180
28
     error,
181
28
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
182
28
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
183
28
     "%s: invalid data size value out of bounds.",
184
28
     function );
185
186
28
    return( -1 );
187
28
  }
188
#if defined( HAVE_DEBUG_OUTPUT )
189
  if( libcnotify_verbose != 0 )
190
  {
191
    libcnotify_printf(
192
     "%s: file extent key data:\n",
193
     function );
194
    libcnotify_print_data(
195
     data,
196
     data_size,
197
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
198
  }
199
#endif
200
647
  byte_stream_copy_to_uint64_little_endian(
201
647
   ( (fsapfs_file_system_btree_key_file_extent_t *) data )->logical_address,
202
647
   file_extent->logical_offset );
203
204
#if defined( HAVE_DEBUG_OUTPUT )
205
  if( libcnotify_verbose != 0 )
206
  {
207
    byte_stream_copy_to_uint64_little_endian(
208
     ( (fsapfs_file_system_btree_key_file_extent_t *) data )->file_system_identifier,
209
     value_64bit );
210
    libcnotify_printf(
211
     "%s: identifier\t\t\t\t: 0x%08" PRIx64 "\n",
212
     function,
213
     value_64bit );
214
215
    libcnotify_printf(
216
     "%s: logical address\t\t\t: 0x%08" PRIx64 "\n",
217
     function,
218
     file_extent->logical_offset );
219
220
    libcnotify_printf(
221
     "\n" );
222
  }
223
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
224
225
647
  return( 1 );
226
675
}
227
228
/* Reads the file extent value data
229
 * Returns 1 if successful or -1 on error
230
 */
231
int libfsapfs_file_extent_read_value_data(
232
     libfsapfs_file_extent_t *file_extent,
233
     const uint8_t *data,
234
     size_t data_size,
235
     libcerror_error_t **error )
236
647
{
237
647
  static char *function = "libfsapfs_file_extent_read_value_data";
238
239
#if defined( HAVE_DEBUG_OUTPUT )
240
  uint64_t value_64bit  = 0;
241
#endif
242
243
647
  if( file_extent == NULL )
244
0
  {
245
0
    libcerror_error_set(
246
0
     error,
247
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
248
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
249
0
     "%s: invalid file extent.",
250
0
     function );
251
252
0
    return( -1 );
253
0
  }
254
647
  if( data == NULL )
255
15
  {
256
15
    libcerror_error_set(
257
15
     error,
258
15
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
259
15
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
260
15
     "%s: invalid data.",
261
15
     function );
262
263
15
    return( -1 );
264
15
  }
265
632
  if( ( data_size < sizeof( fsapfs_file_system_btree_value_file_extent_t ) )
266
632
   || ( data_size > (size_t) SSIZE_MAX ) )
267
36
  {
268
36
    libcerror_error_set(
269
36
     error,
270
36
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
271
36
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
272
36
     "%s: invalid data size value out of bounds.",
273
36
     function );
274
275
36
    return( -1 );
276
36
  }
277
#if defined( HAVE_DEBUG_OUTPUT )
278
  if( libcnotify_verbose != 0 )
279
  {
280
    libcnotify_printf(
281
     "%s: file extent value data:\n",
282
     function );
283
    libcnotify_print_data(
284
     data,
285
     data_size,
286
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
287
  }
288
#endif
289
596
  byte_stream_copy_to_uint64_little_endian(
290
596
   ( (fsapfs_file_system_btree_value_file_extent_t *) data )->data_size_and_flags,
291
596
   file_extent->data_size );
292
293
596
  file_extent->data_size &= 0x00ffffffffffffffUL;
294
295
596
  byte_stream_copy_to_uint64_little_endian(
296
596
   ( (fsapfs_file_system_btree_value_file_extent_t *) data )->physical_block_number,
297
596
   file_extent->physical_block_number );
298
299
596
  byte_stream_copy_to_uint64_little_endian(
300
596
   ( (fsapfs_file_system_btree_value_file_extent_t *) data )->encryption_identifier,
301
596
   file_extent->encryption_identifier );
302
303
#if defined( HAVE_DEBUG_OUTPUT )
304
  if( libcnotify_verbose != 0 )
305
  {
306
    byte_stream_copy_to_uint64_little_endian(
307
     ( (fsapfs_file_system_btree_value_file_extent_t *) data )->data_size_and_flags,
308
     value_64bit );
309
    libcnotify_printf(
310
     "%s: data size and flags\t\t: 0x%08" PRIx64 " (data size: %" PRIu64 ", flags: 0x%02" PRIx64 ")\n",
311
     function,
312
     value_64bit,
313
     file_extent->data_size,
314
     value_64bit >> 56 );
315
316
    libcnotify_printf(
317
     "%s: physical block number\t\t: %" PRIu64 "\n",
318
     function,
319
     file_extent->physical_block_number );
320
321
    libcnotify_printf(
322
     "%s: encryption identifier\t\t: %" PRIu64 "\n",
323
     function,
324
     file_extent->encryption_identifier );
325
326
    libcnotify_printf(
327
     "\n" );
328
  }
329
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
330
331
596
  return( 1 );
332
632
}
333