1 /*
2 * The file system data handle functions
3 *
4 * Copyright (C) 2018-2021, 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 <memory.h>
24 #include <types.h>
25
26 #include "libfsapfs_data_block.h"
27 #include "libfsapfs_definitions.h"
28 #include "libfsapfs_encryption_context.h"
29 #include "libfsapfs_file_extent.h"
30 #include "libfsapfs_libbfio.h"
31 #include "libfsapfs_libcdata.h"
32 #include "libfsapfs_libcerror.h"
33 #include "libfsapfs_libfcache.h"
34 #include "libfsapfs_libfdata.h"
35 #include "libfsapfs_profiler.h"
36 #include "libfsapfs_unused.h"
37 #include "libfsapfs_file_system_data_handle.h"
38
39 /* Creates file system data handle
40 * Make sure the value file_system_data_handle is referencing, is set to NULL
41 * Returns 1 if successful or -1 on error
42 */
libfsapfs_file_system_data_handle_initialize(libfsapfs_file_system_data_handle_t ** file_system_data_handle,libfsapfs_io_handle_t * io_handle,libfsapfs_encryption_context_t * encryption_context,libcdata_array_t * file_extents,libcerror_error_t ** error)43 int libfsapfs_file_system_data_handle_initialize(
44 libfsapfs_file_system_data_handle_t **file_system_data_handle,
45 libfsapfs_io_handle_t *io_handle,
46 libfsapfs_encryption_context_t *encryption_context,
47 libcdata_array_t *file_extents,
48 libcerror_error_t **error )
49 {
50 static char *function = "libfsapfs_file_system_data_handle_initialize";
51
52 if( file_system_data_handle == NULL )
53 {
54 libcerror_error_set(
55 error,
56 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
57 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
58 "%s: invalid file system data handle.",
59 function );
60
61 return( -1 );
62 }
63 if( *file_system_data_handle != NULL )
64 {
65 libcerror_error_set(
66 error,
67 LIBCERROR_ERROR_DOMAIN_RUNTIME,
68 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
69 "%s: invalid file system data handle value already set.",
70 function );
71
72 return( -1 );
73 }
74 if( io_handle == NULL )
75 {
76 libcerror_error_set(
77 error,
78 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
79 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
80 "%s: invalid IO handle.",
81 function );
82
83 return( -1 );
84 }
85 *file_system_data_handle = memory_allocate_structure(
86 libfsapfs_file_system_data_handle_t );
87
88 if( *file_system_data_handle == NULL )
89 {
90 libcerror_error_set(
91 error,
92 LIBCERROR_ERROR_DOMAIN_MEMORY,
93 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
94 "%s: unable to create file system data handle.",
95 function );
96
97 goto on_error;
98 }
99 if( memory_set(
100 *file_system_data_handle,
101 0,
102 sizeof( libfsapfs_file_system_data_handle_t ) ) == NULL )
103 {
104 libcerror_error_set(
105 error,
106 LIBCERROR_ERROR_DOMAIN_MEMORY,
107 LIBCERROR_MEMORY_ERROR_SET_FAILED,
108 "%s: unable to clear file system data handle.",
109 function );
110
111 goto on_error;
112 }
113 ( *file_system_data_handle )->io_handle = io_handle;
114 ( *file_system_data_handle )->encryption_context = encryption_context;
115 ( *file_system_data_handle )->file_extents = file_extents;
116
117 return( 1 );
118
119 on_error:
120 if( *file_system_data_handle != NULL )
121 {
122 memory_free(
123 *file_system_data_handle );
124
125 *file_system_data_handle = NULL;
126 }
127 return( -1 );
128 }
129
130 /* Frees file system data handle
131 * Returns 1 if successful or -1 on error
132 */
libfsapfs_file_system_data_handle_free(libfsapfs_file_system_data_handle_t ** file_system_data_handle,libcerror_error_t ** error)133 int libfsapfs_file_system_data_handle_free(
134 libfsapfs_file_system_data_handle_t **file_system_data_handle,
135 libcerror_error_t **error )
136 {
137 static char *function = "libfsapfs_file_system_data_handle_free";
138
139 if( file_system_data_handle == NULL )
140 {
141 libcerror_error_set(
142 error,
143 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
144 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
145 "%s: invalid file system data handle.",
146 function );
147
148 return( -1 );
149 }
150 if( *file_system_data_handle != NULL )
151 {
152 memory_free(
153 *file_system_data_handle );
154
155 *file_system_data_handle = NULL;
156 }
157 return( 1 );
158 }
159
160 /* Reads a data block
161 * Callback function for a data block vector
162 * Returns 1 if successful or -1 on error
163 */
libfsapfs_file_system_data_handle_read_data_block(libfsapfs_file_system_data_handle_t * file_system_data_handle,libbfio_handle_t * file_io_handle,libfdata_vector_t * vector,libfcache_cache_t * cache,int element_index,int element_data_file_index,off64_t element_data_offset,size64_t element_data_size,uint32_t element_data_flags,uint8_t read_flags LIBFSAPFS_ATTRIBUTE_UNUSED,libcerror_error_t ** error)164 int libfsapfs_file_system_data_handle_read_data_block(
165 libfsapfs_file_system_data_handle_t *file_system_data_handle,
166 libbfio_handle_t *file_io_handle,
167 libfdata_vector_t *vector,
168 libfcache_cache_t *cache,
169 int element_index,
170 int element_data_file_index,
171 off64_t element_data_offset,
172 size64_t element_data_size,
173 uint32_t element_data_flags,
174 uint8_t read_flags LIBFSAPFS_ATTRIBUTE_UNUSED,
175 libcerror_error_t **error )
176 {
177 libfsapfs_data_block_t *data_block = NULL;
178 libfsapfs_file_extent_t *file_extent = NULL;
179 static char *function = "libfsapfs_file_system_data_handle_read_data_block";
180 uint64_t encryption_identifier = 0;
181 int64_t file_extent_offset = 0;
182
183 #if defined( HAVE_PROFILER )
184 int64_t profiler_start_timestamp = 0;
185 #endif
186
187 LIBFSAPFS_UNREFERENCED_PARAMETER( read_flags );
188
189 if( file_system_data_handle == NULL )
190 {
191 libcerror_error_set(
192 error,
193 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
194 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
195 "%s: invalid file system data handle.",
196 function );
197
198 return( -1 );
199 }
200 if( file_system_data_handle->io_handle == NULL )
201 {
202 libcerror_error_set(
203 error,
204 LIBCERROR_ERROR_DOMAIN_RUNTIME,
205 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
206 "%s: invalid file system data handle - missing IO handle.",
207 function );
208
209 return( -1 );
210 }
211 if( element_data_size > (size64_t) SSIZE_MAX )
212 {
213 libcerror_error_set(
214 error,
215 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
216 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
217 "%s: invalid element data size value exceeds maximum.",
218 function );
219
220 return( -1 );
221 }
222 if( libfsapfs_data_block_initialize(
223 &data_block,
224 (size_t) element_data_size,
225 error ) != 1 )
226 {
227 libcerror_error_set(
228 error,
229 LIBCERROR_ERROR_DOMAIN_RUNTIME,
230 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
231 "%s: unable to create data block.",
232 function );
233
234 goto on_error;
235 }
236 #if defined( HAVE_PROFILER )
237 if( file_system_data_handle->io_handle->profiler != NULL )
238 {
239 if( libfsapfs_profiler_start_timing(
240 file_system_data_handle->io_handle->profiler,
241 &profiler_start_timestamp,
242 error ) != 1 )
243 {
244 libcerror_error_set(
245 error,
246 LIBCERROR_ERROR_DOMAIN_RUNTIME,
247 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
248 "%s: unable to start timing.",
249 function );
250
251 goto on_error;
252 }
253 }
254 #endif /* defined( HAVE_PROFILER ) */
255
256 if( ( element_data_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 )
257 {
258 if( libfsapfs_data_block_clear_data(
259 data_block,
260 error ) != 1 )
261 {
262 libcerror_error_set(
263 error,
264 LIBCERROR_ERROR_DOMAIN_RUNTIME,
265 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
266 "%s: unable to clear data block.",
267 function );
268
269 goto on_error;
270 }
271 }
272 else
273 {
274 encryption_identifier = element_data_offset / element_data_size;
275
276 if( file_system_data_handle->file_extents != NULL )
277 {
278 if( libcdata_array_get_entry_by_index(
279 file_system_data_handle->file_extents,
280 element_data_file_index,
281 (intptr_t **) &file_extent,
282 error ) != 1 )
283 {
284 libcerror_error_set(
285 error,
286 LIBCERROR_ERROR_DOMAIN_RUNTIME,
287 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
288 "%s: unable to retrieve file extent: %d.",
289 function,
290 element_data_file_index );
291
292 goto on_error;
293 }
294 if( file_extent == NULL )
295 {
296 libcerror_error_set(
297 error,
298 LIBCERROR_ERROR_DOMAIN_RUNTIME,
299 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
300 "%s: missing file extent: %d.",
301 function,
302 element_data_file_index );
303
304 goto on_error;
305 }
306 file_extent_offset = (int64_t) encryption_identifier - (int64_t) file_extent->physical_block_number;
307 encryption_identifier = file_extent->encryption_identifier + file_extent_offset;
308 }
309 if( libfsapfs_data_block_read(
310 data_block,
311 file_system_data_handle->io_handle,
312 file_system_data_handle->encryption_context,
313 file_io_handle,
314 element_data_offset,
315 encryption_identifier,
316 error ) != 1 )
317 {
318 libcerror_error_set(
319 error,
320 LIBCERROR_ERROR_DOMAIN_IO,
321 LIBCERROR_IO_ERROR_READ_FAILED,
322 "%s: unable to read data block.",
323 function );
324
325 goto on_error;
326 }
327 }
328 #if defined( HAVE_PROFILER )
329 if( file_system_data_handle->io_handle->profiler != NULL )
330 {
331 if( libfsapfs_profiler_stop_timing(
332 file_system_data_handle->io_handle->profiler,
333 profiler_start_timestamp,
334 function,
335 element_data_offset,
336 element_data_size,
337 error ) != 1 )
338 {
339 libcerror_error_set(
340 error,
341 LIBCERROR_ERROR_DOMAIN_RUNTIME,
342 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
343 "%s: unable to stop timing.",
344 function );
345
346 goto on_error;
347 }
348 }
349 #endif /* defined( HAVE_PROFILER ) */
350
351 if( libfdata_vector_set_element_value_by_index(
352 vector,
353 (intptr_t *) file_io_handle,
354 (libfdata_cache_t *) cache,
355 element_index,
356 (intptr_t *) data_block,
357 (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_data_block_free,
358 LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
359 error ) != 1 )
360 {
361 libcerror_error_set(
362 error,
363 LIBCERROR_ERROR_DOMAIN_RUNTIME,
364 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
365 "%s: unable to set data block as element value.",
366 function );
367
368 goto on_error;
369 }
370 return( 1 );
371
372 on_error:
373 if( data_block != NULL )
374 {
375 libfsapfs_data_block_free(
376 &data_block,
377 NULL );
378 }
379 return( -1 );
380 }
381
382