Coverage Report

Created: 2026-04-10 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsapfs/libfsapfs/libfsapfs_extended_attribute.c
Line
Count
Source
1
/*
2
 * Extended attribute functions
3
 *
4
 * Copyright (C) 2018-2025, 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_attributes.h"
28
#include "libfsapfs_data_stream.h"
29
#include "libfsapfs_debug.h"
30
#include "libfsapfs_encryption_context.h"
31
#include "libfsapfs_extended_attribute.h"
32
#include "libfsapfs_file_extent.h"
33
#include "libfsapfs_file_system_btree.h"
34
#include "libfsapfs_io_handle.h"
35
#include "libfsapfs_libbfio.h"
36
#include "libfsapfs_libcerror.h"
37
#include "libfsapfs_libcnotify.h"
38
#include "libfsapfs_libcthreads.h"
39
#include "libfsapfs_libfdata.h"
40
#include "libfsapfs_libfdatetime.h"
41
#include "libfsapfs_types.h"
42
43
/* Creates an extended_attribute
44
 * Make sure the value extended_attribute is referencing, is set to NULL
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libfsapfs_extended_attribute_initialize(
48
     libfsapfs_extended_attribute_t **extended_attribute,
49
     libfsapfs_io_handle_t *io_handle,
50
     libbfio_handle_t *file_io_handle,
51
     libfsapfs_encryption_context_t *encryption_context,
52
     libfsapfs_file_system_btree_t *file_system_btree,
53
     libfsapfs_attribute_values_t *attribute_values,
54
     uint64_t transaction_identifier,
55
     libcerror_error_t **error )
56
68
{
57
68
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
58
68
  static char *function                                                = "libfsapfs_extended_attribute_initialize";
59
60
68
  if( extended_attribute == NULL )
61
0
  {
62
0
    libcerror_error_set(
63
0
     error,
64
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
65
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
66
0
     "%s: invalid extended attribute.",
67
0
     function );
68
69
0
    return( -1 );
70
0
  }
71
68
  if( *extended_attribute != NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
76
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
77
0
     "%s: invalid extended attribute value already set.",
78
0
     function );
79
80
0
    return( -1 );
81
0
  }
82
68
  if( attribute_values == NULL )
83
0
  {
84
0
    libcerror_error_set(
85
0
     error,
86
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
87
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
88
0
     "%s: invalid attribute values.",
89
0
     function );
90
91
0
    return( -1 );
92
0
  }
93
68
  internal_extended_attribute = memory_allocate_structure(
94
68
                                 libfsapfs_internal_extended_attribute_t );
95
96
68
  if( internal_extended_attribute == NULL )
97
0
  {
98
0
    libcerror_error_set(
99
0
     error,
100
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
101
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
102
0
     "%s: unable to create extended attribute.",
103
0
     function );
104
105
0
    goto on_error;
106
0
  }
107
68
  if( memory_set(
108
68
       internal_extended_attribute,
109
68
       0,
110
68
       sizeof( libfsapfs_internal_extended_attribute_t ) ) == NULL )
111
0
  {
112
0
    libcerror_error_set(
113
0
     error,
114
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
115
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
116
0
     "%s: unable to clear extended attribute.",
117
0
     function );
118
119
0
    memory_free(
120
0
     internal_extended_attribute );
121
122
0
    return( -1 );
123
0
  }
124
68
  internal_extended_attribute->io_handle              = io_handle;
125
68
  internal_extended_attribute->file_io_handle         = file_io_handle;
126
68
  internal_extended_attribute->encryption_context     = encryption_context;
127
68
  internal_extended_attribute->file_system_btree      = file_system_btree;
128
68
  internal_extended_attribute->attribute_values       = attribute_values;
129
68
  internal_extended_attribute->transaction_identifier = transaction_identifier;
130
131
68
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSAPFS )
132
68
  if( libcthreads_read_write_lock_initialize(
133
68
       &( internal_extended_attribute->read_write_lock ),
134
68
       error ) != 1 )
135
0
  {
136
0
    libcerror_error_set(
137
0
     error,
138
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
139
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
140
0
     "%s: unable to initialize read/write lock.",
141
0
     function );
142
143
0
    goto on_error;
144
0
  }
145
68
#endif
146
68
  *extended_attribute = (libfsapfs_extended_attribute_t *) internal_extended_attribute;
147
148
68
  return( 1 );
149
150
0
on_error:
151
0
  if( internal_extended_attribute != NULL )
152
0
  {
153
0
    memory_free(
154
0
     internal_extended_attribute );
155
0
  }
156
0
  return( -1 );
157
68
}
158
159
/* Frees an extended attribute
160
 * Returns 1 if successful or -1 on error
161
 */
162
int libfsapfs_extended_attribute_free(
163
     libfsapfs_extended_attribute_t **extended_attribute,
164
     libcerror_error_t **error )
165
68
{
166
68
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
167
68
  static char *function                                                = "libfsapfs_extended_attribute_free";
168
68
  int result                                                           = 1;
169
170
68
  if( extended_attribute == NULL )
171
0
  {
172
0
    libcerror_error_set(
173
0
     error,
174
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
175
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
176
0
     "%s: invalid extended attribute.",
177
0
     function );
178
179
0
    return( -1 );
180
0
  }
181
68
  if( *extended_attribute != NULL )
182
68
  {
183
68
    internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) *extended_attribute;
184
68
    *extended_attribute         = NULL;
185
186
68
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSAPFS )
187
68
    if( libcthreads_read_write_lock_free(
188
68
         &( internal_extended_attribute->read_write_lock ),
189
68
         error ) != 1 )
190
0
    {
191
0
      libcerror_error_set(
192
0
       error,
193
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
194
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
195
0
       "%s: unable to free read/write lock.",
196
0
       function );
197
198
0
      result = -1;
199
0
    }
200
68
#endif
201
68
    if( internal_extended_attribute->data_stream != NULL )
202
0
    {
203
0
      if( libfdata_stream_free(
204
0
           &( internal_extended_attribute->data_stream ),
205
0
           error ) != 1 )
206
0
      {
207
0
        libcerror_error_set(
208
0
         error,
209
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
210
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
211
0
         "%s: unable to free data stream.",
212
0
         function );
213
214
0
        result = -1;
215
0
      }
216
0
    }
217
68
    memory_free(
218
68
     internal_extended_attribute );
219
68
  }
220
68
  return( result );
221
68
}
222
223
/* Retrieves the data stream
224
 * Returns 1 if successful or -1 on error
225
 */
226
int libfsapfs_extended_attribute_get_data_stream(
227
     libfsapfs_extended_attribute_t *extended_attribute,
228
     libfdata_stream_t **data_stream,
229
     libcerror_error_t **error )
230
0
{
231
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
232
0
  static char *function                                                = "libfsapfs_extended_attribute_get_data_stream";
233
234
0
  if( extended_attribute == NULL )
235
0
  {
236
0
    libcerror_error_set(
237
0
     error,
238
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
239
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
240
0
     "%s: invalid extended attribute.",
241
0
     function );
242
243
0
    return( -1 );
244
0
  }
245
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
246
247
0
  if( data_stream == NULL )
248
0
  {
249
0
    libcerror_error_set(
250
0
     error,
251
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
252
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
253
0
     "%s: invalid data stream.",
254
0
     function );
255
256
0
    return( -1 );
257
0
  }
258
0
  if( internal_extended_attribute->data_stream == NULL )
259
0
  {
260
0
    if( libfsapfs_internal_extended_attribute_get_data_stream(
261
0
         internal_extended_attribute,
262
0
         error ) != 1 )
263
0
    {
264
0
      libcerror_error_set(
265
0
       error,
266
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
267
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
268
0
       "%s: unable to determine data stream.",
269
0
       function );
270
271
0
      return( -1 );
272
0
    }
273
0
  }
274
0
  *data_stream = internal_extended_attribute->data_stream;
275
276
0
  return( 1 );
277
0
}
278
279
/* Retrieves the identifier
280
 * Returns 1 if successful or -1 on error
281
 */
282
int libfsapfs_extended_attribute_get_identifier(
283
     libfsapfs_extended_attribute_t *extended_attribute,
284
     uint64_t *identifier,
285
     libcerror_error_t **error )
286
0
{
287
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
288
0
  static char *function                                                = "libfsapfs_extended_attribute_get_identifier";
289
290
0
  if( extended_attribute == NULL )
291
0
  {
292
0
    libcerror_error_set(
293
0
     error,
294
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
295
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
296
0
     "%s: invalid extended attribute.",
297
0
     function );
298
299
0
    return( -1 );
300
0
  }
301
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
302
303
0
  if( identifier == NULL )
304
0
  {
305
0
    libcerror_error_set(
306
0
     error,
307
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
308
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
309
0
     "%s: invalid identifier.",
310
0
     function );
311
312
0
    return( -1 );
313
0
  }
314
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
315
0
  if( libcthreads_read_write_lock_grab_for_read(
316
0
       internal_extended_attribute->read_write_lock,
317
0
       error ) != 1 )
318
0
  {
319
0
    libcerror_error_set(
320
0
     error,
321
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
322
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
323
0
     "%s: unable to grab read/write lock for reading.",
324
0
     function );
325
326
0
    return( -1 );
327
0
  }
328
0
#endif
329
0
  *identifier = internal_extended_attribute->identifier;
330
331
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
332
0
  if( libcthreads_read_write_lock_release_for_read(
333
0
       internal_extended_attribute->read_write_lock,
334
0
       error ) != 1 )
335
0
  {
336
0
    libcerror_error_set(
337
0
     error,
338
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
339
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
340
0
     "%s: unable to release read/write lock for reading.",
341
0
     function );
342
343
0
    return( -1 );
344
0
  }
345
0
#endif
346
0
  return( 1 );
347
0
}
348
349
/* Retrieves the size of the UTF-8 encoded name
350
 * The returned size includes the end of string character
351
 * Returns 1 if successful or -1 on error
352
 */
353
int libfsapfs_extended_attribute_get_utf8_name_size(
354
     libfsapfs_extended_attribute_t *extended_attribute,
355
     size_t *utf8_string_size,
356
     libcerror_error_t **error )
357
0
{
358
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
359
0
  static char *function                                                = "libfsapfs_extended_attribute_get_utf8_name_size";
360
0
  int result                                                           = 1;
361
362
0
  if( extended_attribute == NULL )
363
0
  {
364
0
    libcerror_error_set(
365
0
     error,
366
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
367
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
368
0
     "%s: invalid extended attribute.",
369
0
     function );
370
371
0
    return( -1 );
372
0
  }
373
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
374
375
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
376
0
  if( libcthreads_read_write_lock_grab_for_read(
377
0
       internal_extended_attribute->read_write_lock,
378
0
       error ) != 1 )
379
0
  {
380
0
    libcerror_error_set(
381
0
     error,
382
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
383
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
384
0
     "%s: unable to grab read/write lock for reading.",
385
0
     function );
386
387
0
    return( -1 );
388
0
  }
389
0
#endif
390
0
  if( libfsapfs_attribute_values_get_utf8_name_size(
391
0
       internal_extended_attribute->attribute_values,
392
0
       utf8_string_size,
393
0
       error ) != 1 )
394
0
  {
395
0
    libcerror_error_set(
396
0
     error,
397
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
398
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
399
0
     "%s: unable to retrieve UTF-8 string size.",
400
0
     function );
401
402
0
    result = -1;
403
0
  }
404
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
405
0
  if( libcthreads_read_write_lock_release_for_read(
406
0
       internal_extended_attribute->read_write_lock,
407
0
       error ) != 1 )
408
0
  {
409
0
    libcerror_error_set(
410
0
     error,
411
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
412
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
413
0
     "%s: unable to release read/write lock for reading.",
414
0
     function );
415
416
0
    return( -1 );
417
0
  }
418
0
#endif
419
0
  return( result );
420
0
}
421
422
/* Retrieves the UTF-8 encoded name
423
 * The size should include the end of string character
424
 * Returns 1 if successful or -1 on error
425
 */
426
int libfsapfs_extended_attribute_get_utf8_name(
427
     libfsapfs_extended_attribute_t *extended_attribute,
428
     uint8_t *utf8_string,
429
     size_t utf8_string_size,
430
     libcerror_error_t **error )
431
0
{
432
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
433
0
  static char *function                                                = "libfsapfs_extended_attribute_get_utf8_name";
434
0
  int result                                                           = 1;
435
436
0
  if( extended_attribute == NULL )
437
0
  {
438
0
    libcerror_error_set(
439
0
     error,
440
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
441
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
442
0
     "%s: invalid extended attribute.",
443
0
     function );
444
445
0
    return( -1 );
446
0
  }
447
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
448
449
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
450
0
  if( libcthreads_read_write_lock_grab_for_read(
451
0
       internal_extended_attribute->read_write_lock,
452
0
       error ) != 1 )
453
0
  {
454
0
    libcerror_error_set(
455
0
     error,
456
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
457
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
458
0
     "%s: unable to grab read/write lock for reading.",
459
0
     function );
460
461
0
    return( -1 );
462
0
  }
463
0
#endif
464
0
  if( libfsapfs_attribute_values_get_utf8_name(
465
0
       internal_extended_attribute->attribute_values,
466
0
       utf8_string,
467
0
       utf8_string_size,
468
0
       error ) != 1 )
469
0
  {
470
0
    libcerror_error_set(
471
0
     error,
472
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
473
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
474
0
     "%s: unable to retrieve UTF-8 string.",
475
0
     function );
476
477
0
    result = -1;
478
0
  }
479
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
480
0
  if( libcthreads_read_write_lock_release_for_read(
481
0
       internal_extended_attribute->read_write_lock,
482
0
       error ) != 1 )
483
0
  {
484
0
    libcerror_error_set(
485
0
     error,
486
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
487
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
488
0
     "%s: unable to release read/write lock for reading.",
489
0
     function );
490
491
0
    return( -1 );
492
0
  }
493
0
#endif
494
0
  return( result );
495
0
}
496
497
/* Retrieves the size of the UTF-16 encoded name
498
 * The returned size includes the end of string character
499
 * Returns 1 if successful or -1 on error
500
 */
501
int libfsapfs_extended_attribute_get_utf16_name_size(
502
     libfsapfs_extended_attribute_t *extended_attribute,
503
     size_t *utf16_string_size,
504
     libcerror_error_t **error )
505
0
{
506
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
507
0
  static char *function                                                = "libfsapfs_extended_attribute_get_utf16_name_size";
508
0
  int result                                                           = 1;
509
510
0
  if( extended_attribute == NULL )
511
0
  {
512
0
    libcerror_error_set(
513
0
     error,
514
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
515
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
516
0
     "%s: invalid extended attribute.",
517
0
     function );
518
519
0
    return( -1 );
520
0
  }
521
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
522
523
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
524
0
  if( libcthreads_read_write_lock_grab_for_read(
525
0
       internal_extended_attribute->read_write_lock,
526
0
       error ) != 1 )
527
0
  {
528
0
    libcerror_error_set(
529
0
     error,
530
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
531
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
532
0
     "%s: unable to grab read/write lock for reading.",
533
0
     function );
534
535
0
    return( -1 );
536
0
  }
537
0
#endif
538
0
  if( libfsapfs_attribute_values_get_utf16_name_size(
539
0
       internal_extended_attribute->attribute_values,
540
0
       utf16_string_size,
541
0
       error ) != 1 )
542
0
  {
543
0
    libcerror_error_set(
544
0
     error,
545
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
546
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
547
0
     "%s: unable to retrieve UTF-16 string size.",
548
0
     function );
549
550
0
    result = -1;
551
0
  }
552
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
553
0
  if( libcthreads_read_write_lock_release_for_read(
554
0
       internal_extended_attribute->read_write_lock,
555
0
       error ) != 1 )
556
0
  {
557
0
    libcerror_error_set(
558
0
     error,
559
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
560
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
561
0
     "%s: unable to release read/write lock for reading.",
562
0
     function );
563
564
0
    return( -1 );
565
0
  }
566
0
#endif
567
0
  return( result );
568
0
}
569
570
/* Retrieves the UTF-16 encoded name
571
 * The size should include the end of string character
572
 * Returns 1 if successful or -1 on error
573
 */
574
int libfsapfs_extended_attribute_get_utf16_name(
575
     libfsapfs_extended_attribute_t *extended_attribute,
576
     uint16_t *utf16_string,
577
     size_t utf16_string_size,
578
     libcerror_error_t **error )
579
0
{
580
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
581
0
  static char *function                                                = "libfsapfs_extended_attribute_get_utf16_name";
582
0
  int result                                                           = 1;
583
584
0
  if( extended_attribute == NULL )
585
0
  {
586
0
    libcerror_error_set(
587
0
     error,
588
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
589
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
590
0
     "%s: invalid extended attribute.",
591
0
     function );
592
593
0
    return( -1 );
594
0
  }
595
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
596
597
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
598
0
  if( libcthreads_read_write_lock_grab_for_read(
599
0
       internal_extended_attribute->read_write_lock,
600
0
       error ) != 1 )
601
0
  {
602
0
    libcerror_error_set(
603
0
     error,
604
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
605
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
606
0
     "%s: unable to grab read/write lock for reading.",
607
0
     function );
608
609
0
    return( -1 );
610
0
  }
611
0
#endif
612
0
  if( libfsapfs_attribute_values_get_utf16_name(
613
0
       internal_extended_attribute->attribute_values,
614
0
       utf16_string,
615
0
       utf16_string_size,
616
0
       error ) != 1 )
617
0
  {
618
0
    libcerror_error_set(
619
0
     error,
620
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
621
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
622
0
     "%s: unable to retrieve UTF-16 string.",
623
0
     function );
624
625
0
    result = -1;
626
0
  }
627
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
628
0
  if( libcthreads_read_write_lock_release_for_read(
629
0
       internal_extended_attribute->read_write_lock,
630
0
       error ) != 1 )
631
0
  {
632
0
    libcerror_error_set(
633
0
     error,
634
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
635
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
636
0
     "%s: unable to release read/write lock for reading.",
637
0
     function );
638
639
0
    return( -1 );
640
0
  }
641
0
#endif
642
0
  return( result );
643
0
}
644
645
/* Determines the data stream
646
 * Returns 1 if successful or -1 on error
647
 */
648
int libfsapfs_internal_extended_attribute_get_data_stream(
649
     libfsapfs_internal_extended_attribute_t *internal_extended_attribute,
650
     libcerror_error_t **error )
651
0
{
652
0
  static char *function = "libfsapfs_internal_extended_attribute_get_data_stream";
653
654
0
  if( internal_extended_attribute == NULL )
655
0
  {
656
0
    libcerror_error_set(
657
0
     error,
658
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
659
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
660
0
     "%s: invalid extended attribute.",
661
0
     function );
662
663
0
    return( -1 );
664
0
  }
665
0
  if( internal_extended_attribute->data_stream != NULL )
666
0
  {
667
0
    libcerror_error_set(
668
0
     error,
669
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
670
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
671
0
     "%s: invalid extended attribute - data stream value already set.",
672
0
     function );
673
674
0
    return( -1 );
675
0
  }
676
0
  if( libfsapfs_attributes_get_data_stream(
677
0
       internal_extended_attribute->attribute_values,
678
0
       internal_extended_attribute->io_handle,
679
0
       internal_extended_attribute->file_io_handle,
680
0
       internal_extended_attribute->encryption_context,
681
0
       internal_extended_attribute->file_system_btree,
682
0
       internal_extended_attribute->transaction_identifier,
683
0
       &( internal_extended_attribute->data_stream ),
684
0
       error ) != 1 )
685
0
  {
686
0
    libcerror_error_set(
687
0
     error,
688
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
689
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
690
0
     "%s: unable to retrieve attribute value data stream.",
691
0
     function );
692
693
0
    return( -1 );
694
0
  }
695
0
  return( 1 );
696
0
}
697
698
/* Reads data at the current offset into a buffer
699
 * Returns the number of bytes read or -1 on error
700
 */
701
ssize_t libfsapfs_extended_attribute_read_buffer(
702
         libfsapfs_extended_attribute_t *extended_attribute,
703
         void *buffer,
704
         size_t buffer_size,
705
         libcerror_error_t **error )
706
0
{
707
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
708
0
  static char *function                                                = "libfsapfs_extended_attribute_read_buffer";
709
0
  ssize_t read_count                                                   = 0;
710
711
0
  if( extended_attribute == NULL )
712
0
  {
713
0
    libcerror_error_set(
714
0
     error,
715
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
716
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
717
0
     "%s: invalid extended attribute.",
718
0
     function );
719
720
0
    return( -1 );
721
0
  }
722
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
723
724
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
725
0
  if( libcthreads_read_write_lock_grab_for_write(
726
0
       internal_extended_attribute->read_write_lock,
727
0
       error ) != 1 )
728
0
  {
729
0
    libcerror_error_set(
730
0
     error,
731
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
732
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
733
0
     "%s: unable to grab read/write lock for writing.",
734
0
     function );
735
736
0
    return( -1 );
737
0
  }
738
0
#endif
739
0
  if( internal_extended_attribute->data_stream == NULL )
740
0
  {
741
0
    if( libfsapfs_internal_extended_attribute_get_data_stream(
742
0
         internal_extended_attribute,
743
0
         error ) != 1 )
744
0
    {
745
0
      libcerror_error_set(
746
0
       error,
747
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
748
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
749
0
       "%s: unable to determine data stream.",
750
0
       function );
751
752
0
      read_count = -1;
753
0
    }
754
0
  }
755
0
  if( internal_extended_attribute->data_stream != NULL )
756
0
  {
757
0
    read_count = libfdata_stream_read_buffer(
758
0
                  internal_extended_attribute->data_stream,
759
0
                  (intptr_t *) internal_extended_attribute->file_io_handle,
760
0
                  (uint8_t *) buffer,
761
0
                  buffer_size,
762
0
                  0,
763
0
                  error );
764
765
0
    if( read_count < 0 )
766
0
    {
767
0
      libcerror_error_set(
768
0
       error,
769
0
       LIBCERROR_ERROR_DOMAIN_IO,
770
0
       LIBCERROR_IO_ERROR_READ_FAILED,
771
0
       "%s: unable to read buffer from data stream.",
772
0
       function );
773
774
0
      read_count = -1;
775
0
    }
776
0
  }
777
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
778
0
  if( libcthreads_read_write_lock_release_for_write(
779
0
       internal_extended_attribute->read_write_lock,
780
0
       error ) != 1 )
781
0
  {
782
0
    libcerror_error_set(
783
0
     error,
784
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
785
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
786
0
     "%s: unable to release read/write lock for writing.",
787
0
     function );
788
789
0
    return( -1 );
790
0
  }
791
0
#endif
792
0
  return( read_count );
793
0
}
794
795
/* Reads data at a specific offset
796
 * Returns the number of bytes read or -1 on error
797
 */
798
ssize_t libfsapfs_extended_attribute_read_buffer_at_offset(
799
         libfsapfs_extended_attribute_t *extended_attribute,
800
         void *buffer,
801
         size_t buffer_size,
802
         off64_t offset,
803
         libcerror_error_t **error )
804
0
{
805
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
806
0
  static char *function                                                = "libfsapfs_extended_attribute_read_buffer_at_offset";
807
0
  ssize_t read_count                                                   = 0;
808
809
0
  if( extended_attribute == NULL )
810
0
  {
811
0
    libcerror_error_set(
812
0
     error,
813
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
814
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
815
0
     "%s: invalid extended attribute.",
816
0
     function );
817
818
0
    return( -1 );
819
0
  }
820
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
821
822
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
823
0
  if( libcthreads_read_write_lock_grab_for_write(
824
0
       internal_extended_attribute->read_write_lock,
825
0
       error ) != 1 )
826
0
  {
827
0
    libcerror_error_set(
828
0
     error,
829
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
830
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
831
0
     "%s: unable to grab read/write lock for writing.",
832
0
     function );
833
834
0
    return( -1 );
835
0
  }
836
0
#endif
837
0
  if( internal_extended_attribute->data_stream == NULL )
838
0
  {
839
0
    if( libfsapfs_internal_extended_attribute_get_data_stream(
840
0
         internal_extended_attribute,
841
0
         error ) != 1 )
842
0
    {
843
0
      libcerror_error_set(
844
0
       error,
845
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
846
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
847
0
       "%s: unable to determine data stream.",
848
0
       function );
849
850
0
      read_count = -1;
851
0
    }
852
0
  }
853
0
  if( internal_extended_attribute->data_stream != NULL )
854
0
  {
855
0
    read_count = libfdata_stream_read_buffer_at_offset(
856
0
                  internal_extended_attribute->data_stream,
857
0
                  (intptr_t *) internal_extended_attribute->file_io_handle,
858
0
                  (uint8_t *) buffer,
859
0
                  buffer_size,
860
0
                  offset,
861
0
                  0,
862
0
                  error );
863
864
0
    if( read_count < 0 )
865
0
    {
866
0
      libcerror_error_set(
867
0
       error,
868
0
       LIBCERROR_ERROR_DOMAIN_IO,
869
0
       LIBCERROR_IO_ERROR_READ_FAILED,
870
0
       "%s: unable to read buffer at offset from data stream.",
871
0
       function );
872
873
0
      read_count = -1;
874
0
    }
875
0
  }
876
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
877
0
  if( libcthreads_read_write_lock_release_for_write(
878
0
       internal_extended_attribute->read_write_lock,
879
0
       error ) != 1 )
880
0
  {
881
0
    libcerror_error_set(
882
0
     error,
883
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
884
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
885
0
     "%s: unable to release read/write lock for writing.",
886
0
     function );
887
888
0
    return( -1 );
889
0
  }
890
0
#endif
891
0
  return( read_count );
892
0
}
893
894
/* Seeks a certain offset
895
 * Returns the offset if seek is successful or -1 on error
896
 */
897
off64_t libfsapfs_extended_attribute_seek_offset(
898
         libfsapfs_extended_attribute_t *extended_attribute,
899
         off64_t offset,
900
         int whence,
901
         libcerror_error_t **error )
902
0
{
903
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
904
0
  static char *function                                                = "libfsapfs_extended_attribute_seek_offset";
905
906
0
  if( extended_attribute == NULL )
907
0
  {
908
0
    libcerror_error_set(
909
0
     error,
910
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
911
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
912
0
     "%s: invalid extended attribute.",
913
0
     function );
914
915
0
    return( -1 );
916
0
  }
917
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
918
919
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
920
0
  if( libcthreads_read_write_lock_grab_for_write(
921
0
       internal_extended_attribute->read_write_lock,
922
0
       error ) != 1 )
923
0
  {
924
0
    libcerror_error_set(
925
0
     error,
926
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
927
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
928
0
     "%s: unable to grab read/write lock for writing.",
929
0
     function );
930
931
0
    return( -1 );
932
0
  }
933
0
#endif
934
0
  if( internal_extended_attribute->data_stream == NULL )
935
0
  {
936
0
    if( libfsapfs_internal_extended_attribute_get_data_stream(
937
0
         internal_extended_attribute,
938
0
         error ) != 1 )
939
0
    {
940
0
      libcerror_error_set(
941
0
       error,
942
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
943
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
944
0
       "%s: unable to determine data stream.",
945
0
       function );
946
947
0
      offset = -1;
948
0
    }
949
0
  }
950
0
  if( internal_extended_attribute->data_stream != NULL )
951
0
  {
952
0
    offset = libfdata_stream_seek_offset(
953
0
              internal_extended_attribute->data_stream,
954
0
              offset,
955
0
              whence,
956
0
              error );
957
958
0
    if( offset < 0 )
959
0
    {
960
0
      libcerror_error_set(
961
0
       error,
962
0
       LIBCERROR_ERROR_DOMAIN_IO,
963
0
       LIBCERROR_IO_ERROR_SEEK_FAILED,
964
0
       "%s: unable to seek offset in data stream.",
965
0
       function );
966
967
0
      offset = -1;
968
0
    }
969
0
  }
970
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
971
0
  if( libcthreads_read_write_lock_release_for_write(
972
0
       internal_extended_attribute->read_write_lock,
973
0
       error ) != 1 )
974
0
  {
975
0
    libcerror_error_set(
976
0
     error,
977
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
978
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
979
0
     "%s: unable to release read/write lock for writing.",
980
0
     function );
981
982
0
    return( -1 );
983
0
  }
984
0
#endif
985
0
  return( offset );
986
0
}
987
988
/* Retrieves the current offset
989
 * Returns the offset if successful or -1 on error
990
 */
991
int libfsapfs_extended_attribute_get_offset(
992
     libfsapfs_extended_attribute_t *extended_attribute,
993
     off64_t *offset,
994
     libcerror_error_t **error )
995
0
{
996
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
997
0
  static char *function                                                = "libfsapfs_extended_attribute_get_offset";
998
0
  int result                                                           = 1;
999
1000
0
  if( extended_attribute == NULL )
1001
0
  {
1002
0
    libcerror_error_set(
1003
0
     error,
1004
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1005
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1006
0
     "%s: invalid extended attribute.",
1007
0
     function );
1008
1009
0
    return( -1 );
1010
0
  }
1011
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1012
1013
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1014
0
  if( libcthreads_read_write_lock_grab_for_write(
1015
0
       internal_extended_attribute->read_write_lock,
1016
0
       error ) != 1 )
1017
0
  {
1018
0
    libcerror_error_set(
1019
0
     error,
1020
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1021
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1022
0
     "%s: unable to grab read/write lock for writing.",
1023
0
     function );
1024
1025
0
    return( -1 );
1026
0
  }
1027
0
#endif
1028
0
  if( internal_extended_attribute->data_stream == NULL )
1029
0
  {
1030
0
    if( libfsapfs_internal_extended_attribute_get_data_stream(
1031
0
         internal_extended_attribute,
1032
0
         error ) != 1 )
1033
0
    {
1034
0
      libcerror_error_set(
1035
0
       error,
1036
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1037
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1038
0
       "%s: unable to determine data stream.",
1039
0
       function );
1040
1041
0
      result = -1;
1042
0
    }
1043
0
  }
1044
0
  if( internal_extended_attribute->data_stream != NULL )
1045
0
  {
1046
0
    if( libfdata_stream_get_offset(
1047
0
         internal_extended_attribute->data_stream,
1048
0
         offset,
1049
0
         error ) != 1 )
1050
0
    {
1051
0
      libcerror_error_set(
1052
0
       error,
1053
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1054
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1055
0
       "%s: unable to retrieve offset from data stream.",
1056
0
       function );
1057
1058
0
      result = -1;
1059
0
    }
1060
0
  }
1061
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1062
0
  if( libcthreads_read_write_lock_release_for_write(
1063
0
       internal_extended_attribute->read_write_lock,
1064
0
       error ) != 1 )
1065
0
  {
1066
0
    libcerror_error_set(
1067
0
     error,
1068
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1069
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1070
0
     "%s: unable to release read/write lock for writing.",
1071
0
     function );
1072
1073
0
    return( -1 );
1074
0
  }
1075
0
#endif
1076
0
  return( result );
1077
0
}
1078
1079
/* Retrieves the size of the data stream object
1080
 * Returns 1 if successful or -1 on error
1081
 */
1082
int libfsapfs_extended_attribute_get_size(
1083
     libfsapfs_extended_attribute_t *extended_attribute,
1084
     size64_t *size,
1085
     libcerror_error_t **error )
1086
0
{
1087
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1088
0
  static char *function                                                = "libfsapfs_extended_attribute_get_size";
1089
1090
0
  if( extended_attribute == NULL )
1091
0
  {
1092
0
    libcerror_error_set(
1093
0
     error,
1094
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1095
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1096
0
     "%s: invalid extended attribute.",
1097
0
     function );
1098
1099
0
    return( -1 );
1100
0
  }
1101
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1102
1103
0
  if( internal_extended_attribute->attribute_values == NULL )
1104
0
  {
1105
0
    libcerror_error_set(
1106
0
     error,
1107
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1108
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1109
0
     "%s: invalid internal extended attribute - missing attribute values.",
1110
0
     function );
1111
1112
0
    return( -1 );
1113
0
  }
1114
0
  if( size == NULL )
1115
0
  {
1116
0
    libcerror_error_set(
1117
0
     error,
1118
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1119
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1120
0
     "%s: invalid size.",
1121
0
     function );
1122
1123
0
    return( -1 );
1124
0
  }
1125
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1126
0
  if( libcthreads_read_write_lock_grab_for_read(
1127
0
       internal_extended_attribute->read_write_lock,
1128
0
       error ) != 1 )
1129
0
  {
1130
0
    libcerror_error_set(
1131
0
     error,
1132
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1133
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1134
0
     "%s: unable to grab read/write lock for reading.",
1135
0
     function );
1136
1137
0
    return( -1 );
1138
0
  }
1139
0
#endif
1140
0
  *size = internal_extended_attribute->attribute_values->value_data_size;
1141
1142
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1143
0
  if( libcthreads_read_write_lock_release_for_read(
1144
0
       internal_extended_attribute->read_write_lock,
1145
0
       error ) != 1 )
1146
0
  {
1147
0
    libcerror_error_set(
1148
0
     error,
1149
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1150
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1151
0
     "%s: unable to release read/write lock for reading.",
1152
0
     function );
1153
1154
0
    return( -1 );
1155
0
  }
1156
0
#endif
1157
0
  return( 1 );
1158
0
}
1159
1160
/* Retrieves the number of extents
1161
 * Returns 1 if successful or -1 on error
1162
 */
1163
int libfsapfs_extended_attribute_get_number_of_extents(
1164
     libfsapfs_extended_attribute_t *extended_attribute,
1165
     int *number_of_extents,
1166
     libcerror_error_t **error )
1167
0
{
1168
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1169
0
  static char *function                                                = "libfsapfs_extended_attribute_get_number_of_extents";
1170
0
  int result                                                           = 1;
1171
1172
0
  if( extended_attribute == NULL )
1173
0
  {
1174
0
    libcerror_error_set(
1175
0
     error,
1176
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1177
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1178
0
     "%s: invalid extended attribute.",
1179
0
     function );
1180
1181
0
    return( -1 );
1182
0
  }
1183
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1184
1185
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1186
0
  if( libcthreads_read_write_lock_grab_for_write(
1187
0
       internal_extended_attribute->read_write_lock,
1188
0
       error ) != 1 )
1189
0
  {
1190
0
    libcerror_error_set(
1191
0
     error,
1192
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1193
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1194
0
     "%s: unable to grab read/write lock for writing.",
1195
0
     function );
1196
1197
0
    return( -1 );
1198
0
  }
1199
0
#endif
1200
0
  if( internal_extended_attribute->data_stream == NULL )
1201
0
  {
1202
    /* Determining the data stream will initialize the extents array
1203
     */
1204
0
    if( libfsapfs_internal_extended_attribute_get_data_stream(
1205
0
         internal_extended_attribute,
1206
0
         error ) != 1 )
1207
0
    {
1208
0
      libcerror_error_set(
1209
0
       error,
1210
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1211
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1212
0
       "%s: unable to determine data stream.",
1213
0
       function );
1214
1215
0
      result = -1;
1216
0
    }
1217
0
  }
1218
0
  if( result != -1 )
1219
0
  {
1220
0
    if( libfsapfs_attribute_values_get_number_of_extents(
1221
0
         internal_extended_attribute->attribute_values,
1222
0
         number_of_extents,
1223
0
         error ) != 1 )
1224
0
    {
1225
0
      libcerror_error_set(
1226
0
       error,
1227
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1228
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1229
0
       "%s: unable to retrieve number of entries.",
1230
0
       function );
1231
1232
0
      result = -1;
1233
0
    }
1234
0
  }
1235
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1236
0
  if( libcthreads_read_write_lock_release_for_write(
1237
0
       internal_extended_attribute->read_write_lock,
1238
0
       error ) != 1 )
1239
0
  {
1240
0
    libcerror_error_set(
1241
0
     error,
1242
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1243
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1244
0
     "%s: unable to release read/write lock for writing.",
1245
0
     function );
1246
1247
0
    return( -1 );
1248
0
  }
1249
0
#endif
1250
0
  return( result );
1251
0
}
1252
1253
/* Retrieves a specific extent
1254
 * Returns 1 if successful or -1 on error
1255
 */
1256
int libfsapfs_extended_attribute_get_extent_by_index(
1257
     libfsapfs_extended_attribute_t *extended_attribute,
1258
     int extent_index,
1259
     off64_t *extent_offset,
1260
     size64_t *extent_size,
1261
     uint32_t *extent_flags,
1262
     libcerror_error_t **error )
1263
0
{
1264
0
  libfsapfs_file_extent_t *file_extent                                 = NULL;
1265
0
  libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1266
0
  static char *function                                                = "libfsapfs_extended_attribute_get_extent_by_index";
1267
0
  int result                                                           = 1;
1268
1269
0
  if( extended_attribute == NULL )
1270
0
  {
1271
0
    libcerror_error_set(
1272
0
     error,
1273
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1274
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1275
0
     "%s: invalid extended attribute.",
1276
0
     function );
1277
1278
0
    return( -1 );
1279
0
  }
1280
0
  internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1281
1282
0
  if( internal_extended_attribute->io_handle == NULL )
1283
0
  {
1284
0
    libcerror_error_set(
1285
0
     error,
1286
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1287
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1288
0
     "%s: invalid internal extended attribute - missing IO handle.",
1289
0
     function );
1290
1291
0
    return( -1 );
1292
0
  }
1293
0
  if( extent_offset == NULL )
1294
0
  {
1295
0
    libcerror_error_set(
1296
0
     error,
1297
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1298
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1299
0
     "%s: invalid extent offset.",
1300
0
     function );
1301
1302
0
    return( -1 );
1303
0
  }
1304
0
  if( extent_size == NULL )
1305
0
  {
1306
0
    libcerror_error_set(
1307
0
     error,
1308
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1309
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1310
0
     "%s: invalid extent size.",
1311
0
     function );
1312
1313
0
    return( -1 );
1314
0
  }
1315
0
  if( extent_flags == NULL )
1316
0
  {
1317
0
    libcerror_error_set(
1318
0
     error,
1319
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1320
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1321
0
     "%s: invalid extent flags.",
1322
0
     function );
1323
1324
0
    return( -1 );
1325
0
  }
1326
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1327
0
  if( libcthreads_read_write_lock_grab_for_write(
1328
0
       internal_extended_attribute->read_write_lock,
1329
0
       error ) != 1 )
1330
0
  {
1331
0
    libcerror_error_set(
1332
0
     error,
1333
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1334
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1335
0
     "%s: unable to grab read/write lock for writing.",
1336
0
     function );
1337
1338
0
    return( -1 );
1339
0
  }
1340
0
#endif
1341
0
  if( internal_extended_attribute->data_stream == NULL )
1342
0
  {
1343
    /* Determining the data stream will initialize the extents array
1344
     */
1345
0
    if( libfsapfs_internal_extended_attribute_get_data_stream(
1346
0
         internal_extended_attribute,
1347
0
         error ) != 1 )
1348
0
    {
1349
0
      libcerror_error_set(
1350
0
       error,
1351
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1352
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1353
0
       "%s: unable to determine data stream.",
1354
0
       function );
1355
1356
0
      result = -1;
1357
0
    }
1358
0
  }
1359
0
  if( result != -1 )
1360
0
  {
1361
0
    if( libfsapfs_attribute_values_get_extent_by_index(
1362
0
         internal_extended_attribute->attribute_values,
1363
0
         extent_index,
1364
0
         &file_extent,
1365
0
         error ) != 1 )
1366
0
    {
1367
0
      libcerror_error_set(
1368
0
       error,
1369
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1370
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1371
0
       "%s: unable to retrieve file extent: %d.",
1372
0
       function,
1373
0
       extent_index );
1374
1375
0
      result = -1;
1376
0
    }
1377
0
    else if( file_extent == NULL )
1378
0
    {
1379
0
      libcerror_error_set(
1380
0
       error,
1381
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1382
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1383
0
       "%s: missing file extent: %d.",
1384
0
       function,
1385
0
       extent_index );
1386
1387
0
      result = -1;
1388
0
    }
1389
0
    else
1390
0
    {
1391
0
      *extent_offset = file_extent->physical_block_number * internal_extended_attribute->io_handle->block_size;
1392
0
      *extent_size   = file_extent->data_size;
1393
0
      *extent_flags  = 0;
1394
0
    }
1395
0
  }
1396
0
#if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1397
0
  if( libcthreads_read_write_lock_release_for_write(
1398
0
       internal_extended_attribute->read_write_lock,
1399
0
       error ) != 1 )
1400
0
  {
1401
0
    libcerror_error_set(
1402
0
     error,
1403
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1404
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1405
0
     "%s: unable to release read/write lock for writing.",
1406
0
     function );
1407
1408
0
    return( -1 );
1409
0
  }
1410
0
#endif
1411
0
  return( result );
1412
0
}
1413