Coverage Report

Created: 2025-07-04 07:01

/src/libfsapfs/libfsapfs/libfsapfs_snapshot.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Snapshot 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 <memory.h>
24
#include <narrow_string.h>
25
#include <types.h>
26
#include <wide_string.h>
27
28
#include "libfsapfs_io_handle.h"
29
#include "libfsapfs_libbfio.h"
30
#include "libfsapfs_libcerror.h"
31
#include "libfsapfs_libcnotify.h"
32
#include "libfsapfs_snapshot.h"
33
#include "libfsapfs_snapshot_metadata.h"
34
#include "libfsapfs_snapshot_metadata_tree.h"
35
#include "libfsapfs_volume_superblock.h"
36
37
/* Creates a snapshot
38
 * Make sure the value snapshot is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libfsapfs_snapshot_initialize(
42
     libfsapfs_snapshot_t **snapshot,
43
     libfsapfs_io_handle_t *io_handle,
44
     libbfio_handle_t *file_io_handle,
45
     libfsapfs_snapshot_metadata_t *snapshot_metadata,
46
     libcerror_error_t **error )
47
0
{
48
0
  libfsapfs_internal_snapshot_t *internal_snapshot = NULL;
49
0
  static char *function                            = "libfsapfs_snapshot_initialize";
50
51
0
  if( snapshot == NULL )
52
0
  {
53
0
    libcerror_error_set(
54
0
     error,
55
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
56
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
57
0
     "%s: invalid snapshot.",
58
0
     function );
59
60
0
    return( -1 );
61
0
  }
62
0
  if( *snapshot != NULL )
63
0
  {
64
0
    libcerror_error_set(
65
0
     error,
66
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
67
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
68
0
     "%s: invalid snapshot value already set.",
69
0
     function );
70
71
0
    return( -1 );
72
0
  }
73
0
  if( io_handle == NULL )
74
0
  {
75
0
    libcerror_error_set(
76
0
     error,
77
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
78
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
79
0
     "%s: invalid IO handle.",
80
0
     function );
81
82
0
    return( -1 );
83
0
  }
84
0
  if( file_io_handle == NULL )
85
0
  {
86
0
    libcerror_error_set(
87
0
     error,
88
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
89
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
90
0
     "%s: invalid file IO handle.",
91
0
     function );
92
93
0
    return( -1 );
94
0
  }
95
0
  if( snapshot_metadata == NULL )
96
0
  {
97
0
    libcerror_error_set(
98
0
     error,
99
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
100
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
101
0
     "%s: invalid snapshot metadata.",
102
0
     function );
103
104
0
    return( -1 );
105
0
  }
106
0
  internal_snapshot = memory_allocate_structure(
107
0
                       libfsapfs_internal_snapshot_t );
108
109
0
  if( internal_snapshot == NULL )
110
0
  {
111
0
    libcerror_error_set(
112
0
     error,
113
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
114
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
115
0
     "%s: unable to create snapshot.",
116
0
     function );
117
118
0
    goto on_error;
119
0
  }
120
0
  if( memory_set(
121
0
       internal_snapshot,
122
0
       0,
123
0
       sizeof( libfsapfs_internal_snapshot_t ) ) == NULL )
124
0
  {
125
0
    libcerror_error_set(
126
0
     error,
127
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
128
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
129
0
     "%s: unable to clear snapshot.",
130
0
     function );
131
132
0
    goto on_error;
133
0
  }
134
/* TODO clone file_io_handle? */
135
0
  internal_snapshot->io_handle         = io_handle;
136
0
  internal_snapshot->file_io_handle    = file_io_handle;
137
0
  internal_snapshot->snapshot_metadata = snapshot_metadata;
138
139
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
140
0
  if( libcthreads_read_write_lock_initialize(
141
0
       &( internal_snapshot->read_write_lock ),
142
0
       error ) != 1 )
143
0
  {
144
0
    libcerror_error_set(
145
0
     error,
146
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
147
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
148
0
     "%s: unable to initialize read/write lock.",
149
0
     function );
150
151
0
    goto on_error;
152
0
  }
153
0
#endif
154
0
  *snapshot = (libfsapfs_snapshot_t *) internal_snapshot;
155
156
0
  return( 1 );
157
158
0
on_error:
159
0
  if( internal_snapshot != NULL )
160
0
  {
161
0
    memory_free(
162
0
     internal_snapshot );
163
0
  }
164
0
  return( -1 );
165
0
}
166
167
/* Frees a snapshot
168
 * Returns 1 if successful or -1 on error
169
 */
170
int libfsapfs_snapshot_free(
171
     libfsapfs_snapshot_t **snapshot,
172
     libcerror_error_t **error )
173
0
{
174
0
  libfsapfs_internal_snapshot_t *internal_snapshot = NULL;
175
0
  static char *function                            = "libfsapfs_snapshot_free";
176
0
  int result                                       = 1;
177
178
0
  if( snapshot == NULL )
179
0
  {
180
0
    libcerror_error_set(
181
0
     error,
182
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
183
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
184
0
     "%s: invalid snapshot.",
185
0
     function );
186
187
0
    return( -1 );
188
0
  }
189
0
  if( *snapshot != NULL )
190
0
  {
191
0
    internal_snapshot = (libfsapfs_internal_snapshot_t *) *snapshot;
192
0
    *snapshot         = NULL;
193
194
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
195
0
    if( libcthreads_read_write_lock_free(
196
0
         &( internal_snapshot->read_write_lock ),
197
0
         error ) != 1 )
198
0
    {
199
0
      libcerror_error_set(
200
0
       error,
201
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
202
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
203
0
       "%s: unable to free read/write lock.",
204
0
       function );
205
206
0
      result = -1;
207
0
    }
208
0
#endif
209
0
    memory_free(
210
0
     internal_snapshot );
211
0
  }
212
0
  return( result );
213
0
}
214
215
/* Opens a snapshot for reading
216
 * Returns 1 if successful or -1 on error
217
 */
218
int libfsapfs_internal_snapshot_open_read(
219
     libfsapfs_internal_snapshot_t *internal_snapshot,
220
     libbfio_handle_t *file_io_handle,
221
     off64_t file_offset,
222
     libcerror_error_t **error )
223
0
{
224
0
  static char *function = "libfsapfs_internal_snapshot_open_read";
225
226
0
  if( internal_snapshot == NULL )
227
0
  {
228
0
    libcerror_error_set(
229
0
     error,
230
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
231
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
232
0
     "%s: invalid snapshot.",
233
0
     function );
234
235
0
    return( -1 );
236
0
  }
237
0
  if( internal_snapshot->io_handle == NULL )
238
0
  {
239
0
    libcerror_error_set(
240
0
     error,
241
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
242
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
243
0
     "%s: invalid snapshot - missing IO handle.",
244
0
     function );
245
246
0
    return( -1 );
247
0
  }
248
0
  if( internal_snapshot->volume_superblock != NULL )
249
0
  {
250
0
    libcerror_error_set(
251
0
     error,
252
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
253
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
254
0
     "%s: invalid snapshot - volume superblock map value already set.",
255
0
     function );
256
257
0
    return( -1 );
258
0
  }
259
#if defined( HAVE_DEBUG_OUTPUT )
260
  if( libcnotify_verbose != 0 )
261
  {
262
    libcnotify_printf(
263
     "Reading volume superblock:\n" );
264
  }
265
#endif
266
0
  if( libfsapfs_volume_superblock_initialize(
267
0
       &( internal_snapshot->volume_superblock ),
268
0
       error ) != 1 )
269
0
  {
270
0
    libcerror_error_set(
271
0
     error,
272
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
273
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
274
0
     "%s: unable to create volume superblock.",
275
0
     function );
276
277
0
    goto on_error;
278
0
  }
279
0
  if( libfsapfs_volume_superblock_read_file_io_handle(
280
0
       internal_snapshot->volume_superblock,
281
0
       file_io_handle,
282
0
       file_offset,
283
0
       1,
284
0
       error ) != 1 )
285
0
  {
286
0
    libcerror_error_set(
287
0
     error,
288
0
     LIBCERROR_ERROR_DOMAIN_IO,
289
0
     LIBCERROR_IO_ERROR_READ_FAILED,
290
0
     "%s: unable to read volume superblock at offset: %" PRIi64 " (0x%08" PRIx64 ").",
291
0
     function,
292
0
     file_offset,
293
0
     file_offset );
294
295
0
    goto on_error;
296
0
  }
297
0
  return( 1 );
298
299
0
on_error:
300
0
  return( -1 );
301
0
}
302
303
/* Closes a snapshot
304
 * Returns 0 if successful or -1 on error
305
 */
306
int libfsapfs_internal_snapshot_close(
307
     libfsapfs_internal_snapshot_t *internal_snapshot,
308
     libcerror_error_t **error )
309
0
{
310
0
  static char *function = "libfsapfs_internal_snapshot_close";
311
0
  int result            = 0;
312
313
0
  if( internal_snapshot == NULL )
314
0
  {
315
0
    libcerror_error_set(
316
0
     error,
317
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
318
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
319
0
     "%s: invalid snapshot.",
320
0
     function );
321
322
0
    return( -1 );
323
0
  }
324
0
  if( internal_snapshot->io_handle == NULL )
325
0
  {
326
0
    libcerror_error_set(
327
0
     error,
328
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
329
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
330
0
     "%s: invalid snapshot - missing IO handle.",
331
0
     function );
332
333
0
    return( -1 );
334
0
  }
335
0
  internal_snapshot->file_io_handle = NULL;
336
337
0
  if( internal_snapshot->volume_superblock != NULL )
338
0
  {
339
0
    if( libfsapfs_volume_superblock_free(
340
0
         &( internal_snapshot->volume_superblock ),
341
0
         error ) != 1 )
342
0
    {
343
0
      libcerror_error_set(
344
0
       error,
345
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
346
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
347
0
       "%s: unable to free volume superblock.",
348
0
       function );
349
350
0
      result = -1;
351
0
    }
352
0
  }
353
/* TODO */
354
0
  return( result );
355
0
}
356
357
/* Retrieves the size of the UTF-8 encoded name
358
 * The returned size includes the end of string character
359
 * Returns 1 if successful or -1 on error
360
 */
361
int libfsapfs_snapshot_get_utf8_name_size(
362
     libfsapfs_snapshot_t *snapshot,
363
     size_t *utf8_string_size,
364
     libcerror_error_t **error )
365
0
{
366
0
  libfsapfs_internal_snapshot_t *internal_snapshot = NULL;
367
0
  static char *function                            = "libfsapfs_snapshot_get_utf8_name_size";
368
0
  int result                                       = 1;
369
370
0
  if( snapshot == NULL )
371
0
  {
372
0
    libcerror_error_set(
373
0
     error,
374
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
375
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
376
0
     "%s: invalid snapshot.",
377
0
     function );
378
379
0
    return( -1 );
380
0
  }
381
0
  internal_snapshot = (libfsapfs_internal_snapshot_t *) snapshot;
382
383
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
384
0
  if( libcthreads_read_write_lock_grab_for_read(
385
0
       internal_snapshot->read_write_lock,
386
0
       error ) != 1 )
387
0
  {
388
0
    libcerror_error_set(
389
0
     error,
390
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
391
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
392
0
     "%s: unable to grab read/write lock for reading.",
393
0
     function );
394
395
0
    return( -1 );
396
0
  }
397
0
#endif
398
0
  if( libfsapfs_snapshot_metadata_get_utf8_name_size(
399
0
       internal_snapshot->snapshot_metadata,
400
0
       utf8_string_size,
401
0
       error ) != 1 )
402
0
  {
403
0
    libcerror_error_set(
404
0
     error,
405
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
406
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
407
0
     "%s: unable to retrieve UTF-8 string size.",
408
0
     function );
409
410
0
    result = -1;
411
0
  }
412
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
413
0
  if( libcthreads_read_write_lock_release_for_read(
414
0
       internal_snapshot->read_write_lock,
415
0
       error ) != 1 )
416
0
  {
417
0
    libcerror_error_set(
418
0
     error,
419
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
420
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
421
0
     "%s: unable to release read/write lock for reading.",
422
0
     function );
423
424
0
    return( -1 );
425
0
  }
426
0
#endif
427
0
  return( result );
428
0
}
429
430
/* Retrieves the UTF-8 encoded name
431
 * The size should include the end of string character
432
 * Returns 1 if successful or -1 on error
433
 */
434
int libfsapfs_snapshot_get_utf8_name(
435
     libfsapfs_snapshot_t *snapshot,
436
     uint8_t *utf8_string,
437
     size_t utf8_string_size,
438
     libcerror_error_t **error )
439
0
{
440
0
  libfsapfs_internal_snapshot_t *internal_snapshot = NULL;
441
0
  static char *function                            = "libfsapfs_snapshot_get_utf8_name";
442
0
  int result                                       = 1;
443
444
0
  if( snapshot == NULL )
445
0
  {
446
0
    libcerror_error_set(
447
0
     error,
448
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
449
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
450
0
     "%s: invalid snapshot.",
451
0
     function );
452
453
0
    return( -1 );
454
0
  }
455
0
  internal_snapshot = (libfsapfs_internal_snapshot_t *) snapshot;
456
457
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
458
0
  if( libcthreads_read_write_lock_grab_for_read(
459
0
       internal_snapshot->read_write_lock,
460
0
       error ) != 1 )
461
0
  {
462
0
    libcerror_error_set(
463
0
     error,
464
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
465
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
466
0
     "%s: unable to grab read/write lock for reading.",
467
0
     function );
468
469
0
    return( -1 );
470
0
  }
471
0
#endif
472
0
  if( libfsapfs_snapshot_metadata_get_utf8_name(
473
0
       internal_snapshot->snapshot_metadata,
474
0
       utf8_string,
475
0
       utf8_string_size,
476
0
       error ) != 1 )
477
0
  {
478
0
    libcerror_error_set(
479
0
     error,
480
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
481
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
482
0
     "%s: unable to retrieve UTF-8 string.",
483
0
     function );
484
485
0
    result = -1;
486
0
  }
487
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
488
0
  if( libcthreads_read_write_lock_release_for_read(
489
0
       internal_snapshot->read_write_lock,
490
0
       error ) != 1 )
491
0
  {
492
0
    libcerror_error_set(
493
0
     error,
494
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
495
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
496
0
     "%s: unable to release read/write lock for reading.",
497
0
     function );
498
499
0
    return( -1 );
500
0
  }
501
0
#endif
502
0
  return( result );
503
0
}
504
505
/* Retrieves the size of the UTF-16 encoded name
506
 * The returned size includes the end of string character
507
 * Returns 1 if successful or -1 on error
508
 */
509
int libfsapfs_snapshot_get_utf16_name_size(
510
     libfsapfs_snapshot_t *snapshot,
511
     size_t *utf16_string_size,
512
     libcerror_error_t **error )
513
0
{
514
0
  libfsapfs_internal_snapshot_t *internal_snapshot = NULL;
515
0
  static char *function                            = "libfsapfs_snapshot_get_utf16_name_size";
516
0
  int result                                       = 1;
517
518
0
  if( snapshot == NULL )
519
0
  {
520
0
    libcerror_error_set(
521
0
     error,
522
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
523
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
524
0
     "%s: invalid snapshot.",
525
0
     function );
526
527
0
    return( -1 );
528
0
  }
529
0
  internal_snapshot = (libfsapfs_internal_snapshot_t *) snapshot;
530
531
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
532
0
  if( libcthreads_read_write_lock_grab_for_read(
533
0
       internal_snapshot->read_write_lock,
534
0
       error ) != 1 )
535
0
  {
536
0
    libcerror_error_set(
537
0
     error,
538
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
539
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
540
0
     "%s: unable to grab read/write lock for reading.",
541
0
     function );
542
543
0
    return( -1 );
544
0
  }
545
0
#endif
546
0
  if( libfsapfs_snapshot_metadata_get_utf16_name_size(
547
0
       internal_snapshot->snapshot_metadata,
548
0
       utf16_string_size,
549
0
       error ) != 1 )
550
0
  {
551
0
    libcerror_error_set(
552
0
     error,
553
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
554
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
555
0
     "%s: unable to retrieve UTF-16 string size.",
556
0
     function );
557
558
0
    result = -1;
559
0
  }
560
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
561
0
  if( libcthreads_read_write_lock_release_for_read(
562
0
       internal_snapshot->read_write_lock,
563
0
       error ) != 1 )
564
0
  {
565
0
    libcerror_error_set(
566
0
     error,
567
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
568
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
569
0
     "%s: unable to release read/write lock for reading.",
570
0
     function );
571
572
0
    return( -1 );
573
0
  }
574
0
#endif
575
0
  return( result );
576
0
}
577
578
/* Retrieves the UTF-16 encoded name
579
 * The size should include the end of string character
580
 * Returns 1 if successful or -1 on error
581
 */
582
int libfsapfs_snapshot_get_utf16_name(
583
     libfsapfs_snapshot_t *snapshot,
584
     uint16_t *utf16_string,
585
     size_t utf16_string_size,
586
     libcerror_error_t **error )
587
0
{
588
0
  libfsapfs_internal_snapshot_t *internal_snapshot = NULL;
589
0
  static char *function                            = "libfsapfs_snapshot_get_utf16_name";
590
0
  int result                                       = 1;
591
592
0
  if( snapshot == NULL )
593
0
  {
594
0
    libcerror_error_set(
595
0
     error,
596
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
597
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
598
0
     "%s: invalid snapshot.",
599
0
     function );
600
601
0
    return( -1 );
602
0
  }
603
0
  internal_snapshot = (libfsapfs_internal_snapshot_t *) snapshot;
604
605
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
606
0
  if( libcthreads_read_write_lock_grab_for_read(
607
0
       internal_snapshot->read_write_lock,
608
0
       error ) != 1 )
609
0
  {
610
0
    libcerror_error_set(
611
0
     error,
612
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
613
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
614
0
     "%s: unable to grab read/write lock for reading.",
615
0
     function );
616
617
0
    return( -1 );
618
0
  }
619
0
#endif
620
0
  if( libfsapfs_snapshot_metadata_get_utf16_name(
621
0
       internal_snapshot->snapshot_metadata,
622
0
       utf16_string,
623
0
       utf16_string_size,
624
0
       error ) != 1 )
625
0
  {
626
0
    libcerror_error_set(
627
0
     error,
628
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
629
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
630
0
     "%s: unable to retrieve UTF-16 string.",
631
0
     function );
632
633
0
    result = -1;
634
0
  }
635
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
636
0
  if( libcthreads_read_write_lock_release_for_read(
637
0
       internal_snapshot->read_write_lock,
638
0
       error ) != 1 )
639
0
  {
640
0
    libcerror_error_set(
641
0
     error,
642
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
643
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
644
0
     "%s: unable to release read/write lock for reading.",
645
0
     function );
646
647
0
    return( -1 );
648
0
  }
649
0
#endif
650
0
  return( result );
651
0
}
652