Coverage Report

Created: 2025-06-24 07:14

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