Coverage Report

Created: 2026-10-14 08:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glib-2.88.3/gio/gfileattribute.c
Line
Count
Source
1
/* GIO - GLib Input, Output and Streaming Library
2
 *
3
 * Copyright (C) 2006-2007 Red Hat, Inc.
4
 *
5
 * SPDX-License-Identifier: LGPL-2.1-or-later
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General
18
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19
 *
20
 * Author: Alexander Larsson <alexl@redhat.com>
21
 */
22
23
#include "config.h"
24
25
#include <stdint.h>
26
#include <string.h>
27
28
#include "gfileattribute.h"
29
#include "gfileattribute-priv.h"
30
#include <glib-object.h>
31
#include "glibintl.h"
32
33
34
/**
35
 * _g_file_attribute_value_free:
36
 * @attr: a #GFileAttributeValue.
37
 *
38
 * Frees the memory used by @attr.
39
 *
40
 **/
41
void
42
_g_file_attribute_value_free (GFileAttributeValue *attr)
43
0
{
44
0
  g_return_if_fail (attr != NULL);
45
46
0
  _g_file_attribute_value_clear (attr);
47
0
  g_free (attr);
48
0
}
49
50
/**
51
 * _g_file_attribute_value_clear:
52
 * @attr: a #GFileAttributeValue.
53
 *
54
 * Clears the value of @attr and sets its type to
55
 * %G_FILE_ATTRIBUTE_TYPE_INVALID.
56
 *
57
 **/
58
void
59
_g_file_attribute_value_clear (GFileAttributeValue *attr)
60
0
{
61
0
  g_return_if_fail (attr != NULL);
62
63
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
64
0
      attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
65
0
    g_free (attr->u.string);
66
67
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV)
68
0
    g_strfreev (attr->u.stringv);
69
70
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
71
0
      attr->u.obj != NULL)
72
0
    g_object_unref (attr->u.obj);
73
74
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
75
0
}
76
77
/**
78
 * g_file_attribute_value_set:
79
 * @attr: a #GFileAttributeValue to set the value in.
80
 * @new_value: a #GFileAttributeValue to get the value from.
81
 *
82
 * Sets an attribute's value from another attribute.
83
 **/
84
void
85
_g_file_attribute_value_set (GFileAttributeValue        *attr,
86
           const GFileAttributeValue *new_value)
87
0
{
88
0
  g_return_if_fail (attr != NULL);
89
0
  g_return_if_fail (new_value != NULL);
90
91
0
  _g_file_attribute_value_clear (attr);
92
0
  *attr = *new_value;
93
94
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
95
0
      attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
96
0
    attr->u.string = g_strdup (attr->u.string);
97
98
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV)
99
0
    attr->u.stringv = g_strdupv (attr->u.stringv);
100
101
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
102
0
      attr->u.obj != NULL)
103
0
    g_object_ref (attr->u.obj);
104
0
}
105
106
/**
107
 * _g_file_attribute_value_new:
108
 *
109
 * Creates a new file attribute.
110
 *
111
 * Returns: a #GFileAttributeValue.
112
 **/
113
GFileAttributeValue *
114
_g_file_attribute_value_new (void)
115
0
{
116
0
  GFileAttributeValue *attr;
117
118
0
  attr = g_new (GFileAttributeValue, 1);
119
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
120
0
  return attr;
121
0
}
122
123
gpointer
124
_g_file_attribute_value_peek_as_pointer (GFileAttributeValue *attr)
125
0
{
126
0
  switch (attr->type) {
127
0
  case G_FILE_ATTRIBUTE_TYPE_STRING:
128
0
  case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
129
0
    return attr->u.string;
130
0
  case G_FILE_ATTRIBUTE_TYPE_STRINGV:
131
0
    return attr->u.stringv;
132
0
  case G_FILE_ATTRIBUTE_TYPE_OBJECT:
133
0
    return attr->u.obj;
134
0
  default:
135
0
    return (gpointer) &attr->u;
136
0
  }
137
0
}
138
139
/**
140
 * g_file_attribute_value_dup:
141
 * @other: a #GFileAttributeValue to duplicate.
142
 *
143
 * Duplicates a file attribute.
144
 *
145
 * Returns: a duplicate of the @other.
146
 **/
147
GFileAttributeValue *
148
_g_file_attribute_value_dup (const GFileAttributeValue *other)
149
0
{
150
0
  GFileAttributeValue *attr;
151
152
0
  g_return_val_if_fail (other != NULL, NULL);
153
154
0
  attr = g_new (GFileAttributeValue, 1);
155
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
156
0
  _g_file_attribute_value_set (attr, other);
157
0
  return attr;
158
0
}
159
160
0
G_DEFINE_BOXED_TYPE (GFileAttributeInfoList, g_file_attribute_info_list,
161
0
                     g_file_attribute_info_list_dup,
162
0
                     g_file_attribute_info_list_unref)
163
0
164
0
static gboolean
165
0
valid_char (char c)
166
0
{
167
0
  return c >= 32 && c <= 126 && c != '\\';
168
0
}
169
170
/* Returns NULL on error */
171
static char *
172
escape_byte_string (const char *str)
173
0
{
174
0
  size_t i, len;
175
0
  size_t num_invalid;
176
0
  char *escaped_val, *p;
177
0
  char c;
178
0
  const char hex_digits[] = "0123456789abcdef";
179
180
0
  len = strlen (str);
181
182
0
  num_invalid = 0;
183
0
  for (i = 0; i < len; i++)
184
0
    {
185
0
      if (!valid_char (str[i]))
186
0
  num_invalid++;
187
0
    }
188
189
0
  if (num_invalid == 0)
190
0
    return g_strdup (str);
191
0
  else
192
0
    {
193
      /* Check for overflow. We want to check the inequality:
194
       * !(len + num_invalid * 3 + 1 > SIZE_MAX) */
195
0
      if (num_invalid >= (SIZE_MAX - len) / 3)
196
0
        return NULL;
197
198
0
      escaped_val = g_malloc (len + num_invalid * 3 + 1);
199
200
0
      p = escaped_val;
201
0
      for (i = 0; i < len; i++)
202
0
  {
203
0
    c = str[i];
204
0
    if (valid_char (c))
205
0
      *p++ = c;
206
0
    else
207
0
      {
208
0
        *p++ = '\\';
209
0
        *p++ = 'x';
210
0
        *p++ = hex_digits[(c >> 4) & 0xf];
211
0
        *p++ = hex_digits[c & 0xf];
212
0
      }
213
0
  }
214
0
      *p++ = 0;
215
0
      return escaped_val;
216
0
    }
217
0
}
218
219
/**
220
 * _g_file_attribute_value_as_string:
221
 * @attr: a #GFileAttributeValue.
222
 *
223
 * Converts a #GFileAttributeValue to a string for display.
224
 * The returned string should be freed when no longer needed.
225
 *
226
 * Returns: a string from the @attr, %NULL on error, or "<invalid>"
227
 * if @attr is of type %G_FILE_ATTRIBUTE_TYPE_INVALID.
228
 */
229
char *
230
_g_file_attribute_value_as_string (const GFileAttributeValue *attr)
231
0
{
232
0
  GString *s;
233
0
  int i;
234
0
  char *str;
235
236
0
  g_return_val_if_fail (attr != NULL, NULL);
237
238
0
  switch (attr->type)
239
0
    {
240
0
    case G_FILE_ATTRIBUTE_TYPE_STRING:
241
0
      str = g_strdup (attr->u.string);
242
0
      break;
243
0
    case G_FILE_ATTRIBUTE_TYPE_STRINGV:
244
0
      s = g_string_new ("[");
245
0
      for (i = 0; attr->u.stringv[i] != NULL; i++)
246
0
  {
247
0
    g_string_append (s, attr->u.stringv[i]);
248
0
    if (attr->u.stringv[i+1] != NULL)
249
0
      g_string_append (s, ", ");
250
0
  }
251
0
      g_string_append (s, "]");
252
0
      str = g_string_free (s, FALSE);
253
0
      break;
254
0
    case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
255
0
      str = escape_byte_string (attr->u.string);
256
0
      break;
257
0
    case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
258
0
      str = g_strdup_printf ("%s", attr->u.boolean?"TRUE":"FALSE");
259
0
      break;
260
0
    case G_FILE_ATTRIBUTE_TYPE_UINT32:
261
0
      str = g_strdup_printf ("%u", (unsigned int)attr->u.uint32);
262
0
      break;
263
0
    case G_FILE_ATTRIBUTE_TYPE_INT32:
264
0
      str = g_strdup_printf ("%i", (int)attr->u.int32);
265
0
      break;
266
0
    case G_FILE_ATTRIBUTE_TYPE_UINT64:
267
0
      str = g_strdup_printf ("%"G_GUINT64_FORMAT, attr->u.uint64);
268
0
      break;
269
0
    case G_FILE_ATTRIBUTE_TYPE_INT64:
270
0
      str = g_strdup_printf ("%"G_GINT64_FORMAT, attr->u.int64);
271
0
      break;
272
0
    case G_FILE_ATTRIBUTE_TYPE_OBJECT:
273
0
      str = g_strdup_printf ("%s:%p", g_type_name_from_instance
274
0
                                          ((GTypeInstance *) attr->u.obj),
275
0
                                      attr->u.obj);
276
0
      break;
277
0
    case G_FILE_ATTRIBUTE_TYPE_INVALID:
278
0
      str = g_strdup ("<unset>");
279
0
      break;
280
0
    default:
281
0
      g_warning ("Invalid type in GFileInfo attribute");
282
0
      str = g_strdup ("<invalid>");
283
0
      break;
284
0
    }
285
286
0
  return str;
287
0
}
288
289
/**
290
 * _g_file_attribute_value_get_string:
291
 * @attr: a #GFileAttributeValue.
292
 *
293
 * Gets the string from a file attribute value. If the value is not the
294
 * right type then %NULL will be returned.
295
 *
296
 * Returns: the UTF-8 string value contained within the attribute, or %NULL.
297
 */
298
const char *
299
_g_file_attribute_value_get_string (const GFileAttributeValue *attr)
300
0
{
301
0
  if (attr == NULL)
302
0
    return NULL;
303
304
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING, NULL);
305
306
0
  return attr->u.string;
307
0
}
308
309
/**
310
 * _g_file_attribute_value_get_byte_string:
311
 * @attr: a #GFileAttributeValue.
312
 *
313
 * Gets the byte string from a file attribute value. If the value is not the
314
 * right type then %NULL will be returned.
315
 *
316
 * Returns: the byte string contained within the attribute or %NULL.
317
 */
318
const char *
319
_g_file_attribute_value_get_byte_string (const GFileAttributeValue *attr)
320
0
{
321
0
  if (attr == NULL)
322
0
    return NULL;
323
324
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, NULL);
325
326
0
  return attr->u.string;
327
0
}
328
329
char **
330
_g_file_attribute_value_get_stringv (const GFileAttributeValue *attr)
331
0
{
332
0
  if (attr == NULL)
333
0
    return NULL;
334
335
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV, NULL);
336
337
0
  return attr->u.stringv;
338
0
}
339
340
/**
341
 * _g_file_attribute_value_get_boolean:
342
 * @attr: a #GFileAttributeValue.
343
 *
344
 * Gets the boolean value from a file attribute value. If the value is not the
345
 * right type then %FALSE will be returned.
346
 *
347
 * Returns: the boolean value contained within the attribute, or %FALSE.
348
 */
349
gboolean
350
_g_file_attribute_value_get_boolean (const GFileAttributeValue *attr)
351
0
{
352
0
  if (attr == NULL)
353
0
    return FALSE;
354
355
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BOOLEAN, FALSE);
356
357
0
  return attr->u.boolean;
358
0
}
359
360
/**
361
 * _g_file_attribute_value_get_uint32:
362
 * @attr: a #GFileAttributeValue.
363
 *
364
 * Gets the unsigned 32-bit integer from a file attribute value. If the value
365
 * is not the right type then 0 will be returned.
366
 *
367
 * Returns: the unsigned 32-bit integer from the attribute, or 0.
368
 */
369
guint32
370
_g_file_attribute_value_get_uint32 (const GFileAttributeValue *attr)
371
0
{
372
0
  if (attr == NULL)
373
0
    return 0;
374
375
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT32, 0);
376
377
0
  return attr->u.uint32;
378
0
}
379
380
/**
381
 * _g_file_attribute_value_get_int32:
382
 * @attr: a #GFileAttributeValue.
383
 *
384
 * Gets the signed 32-bit integer from a file attribute value. If the value
385
 * is not the right type then 0 will be returned.
386
 *
387
 * Returns: the signed 32-bit integer from the attribute, or 0.
388
 */
389
gint32
390
_g_file_attribute_value_get_int32 (const GFileAttributeValue *attr)
391
0
{
392
0
  if (attr == NULL)
393
0
    return 0;
394
395
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT32, 0);
396
397
0
  return attr->u.int32;
398
0
}
399
400
/**
401
 * _g_file_attribute_value_get_uint64:
402
 * @attr: a #GFileAttributeValue.
403
 *
404
 * Gets the unsigned 64-bit integer from a file attribute value. If the value
405
 * is not the right type then 0 will be returned.
406
 *
407
 * Returns: the unsigned 64-bit integer from the attribute, or 0.
408
 */
409
guint64
410
_g_file_attribute_value_get_uint64 (const GFileAttributeValue *attr)
411
0
{
412
0
  if (attr == NULL)
413
0
    return 0;
414
415
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT64, 0);
416
417
0
  return attr->u.uint64;
418
0
}
419
420
/**
421
 * _g_file_attribute_value_get_int64:
422
 * @attr: a #GFileAttributeValue.
423
 *
424
 * Gets the signed 64-bit integer from a file attribute value. If the value
425
 * is not the right type then 0 will be returned.
426
 *
427
 * Returns: the signed 64-bit integer from the attribute, or 0.
428
 */
429
gint64
430
_g_file_attribute_value_get_int64 (const GFileAttributeValue *attr)
431
0
{
432
0
  if (attr == NULL)
433
0
    return 0;
434
435
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT64, 0);
436
437
0
  return attr->u.int64;
438
0
}
439
440
/**
441
 * _g_file_attribute_value_get_object:
442
 * @attr: a #GFileAttributeValue.
443
 *
444
 * Gets the GObject from a file attribute value. If the value
445
 * is not the right type then %NULL will be returned.
446
 *
447
 * Returns: the GObject from the attribute, or %NULL.
448
 **/
449
GObject *
450
_g_file_attribute_value_get_object (const GFileAttributeValue *attr)
451
0
{
452
0
  if (attr == NULL)
453
0
    return NULL;
454
455
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT, NULL);
456
457
0
  return attr->u.obj;
458
0
}
459
460
461
void
462
_g_file_attribute_value_set_from_pointer (GFileAttributeValue *value,
463
            GFileAttributeType   type,
464
            gpointer             value_p,
465
            gboolean             dup)
466
0
{
467
0
  _g_file_attribute_value_clear (value);
468
0
  value->type = type;
469
0
  switch (type)
470
0
    {
471
0
    case G_FILE_ATTRIBUTE_TYPE_STRING:
472
0
    case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
473
0
      if (dup)
474
0
  value->u.string = g_strdup (value_p);
475
0
      else
476
0
  value->u.string = value_p;
477
0
      break;
478
479
0
    case G_FILE_ATTRIBUTE_TYPE_STRINGV:
480
0
      if (dup)
481
0
  value->u.stringv = g_strdupv (value_p);
482
0
      else
483
0
  value->u.stringv = value_p;
484
0
      break;
485
486
0
    case G_FILE_ATTRIBUTE_TYPE_OBJECT:
487
0
      if (dup)
488
0
  value->u.obj = g_object_ref (value_p);
489
0
      else
490
0
  value->u.obj = value_p;
491
0
      break;
492
493
0
    case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
494
0
      value->u.boolean = *(gboolean *)value_p;
495
0
      break;
496
497
0
    case G_FILE_ATTRIBUTE_TYPE_UINT32:
498
0
      value->u.uint32 = *(guint32 *)value_p;
499
0
      break;
500
501
0
    case G_FILE_ATTRIBUTE_TYPE_INT32:
502
0
      value->u.int32 = *(gint32 *)value_p;
503
0
      break;
504
505
0
    case G_FILE_ATTRIBUTE_TYPE_UINT64:
506
0
      value->u.uint64 = *(guint64 *)value_p;
507
0
      break;
508
509
0
    case G_FILE_ATTRIBUTE_TYPE_INT64:
510
0
      value->u.int64 = *(gint64 *)value_p;
511
0
      break;
512
513
0
    case G_FILE_ATTRIBUTE_TYPE_INVALID:
514
0
      break;
515
516
0
    default:
517
0
      g_warning ("Unknown type specified in g_file_info_set_attribute");
518
0
      break;
519
0
    }
520
0
}
521
522
/**
523
 * _g_file_attribute_value_set_string:
524
 * @attr: a #GFileAttributeValue.
525
 * @string: a UTF-8 string to set within the type.
526
 *
527
 * Sets the attribute value to a given UTF-8 string.
528
 */
529
void
530
_g_file_attribute_value_set_string (GFileAttributeValue *attr,
531
            const char          *string)
532
0
{
533
0
  g_return_if_fail (attr != NULL);
534
0
  g_return_if_fail (string != NULL);
535
536
0
  _g_file_attribute_value_clear (attr);
537
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_STRING;
538
0
  attr->u.string = g_strdup (string);
539
0
}
540
541
/**
542
 * _g_file_attribute_value_set_byte_string:
543
 * @attr: a #GFileAttributeValue.
544
 * @string: a byte string to set within the type.
545
 *
546
 * Sets the attribute value to a given byte string.
547
 */
548
void
549
_g_file_attribute_value_set_byte_string (GFileAttributeValue *attr,
550
           const char          *string)
551
0
{
552
0
  g_return_if_fail (attr != NULL);
553
0
  g_return_if_fail (string != NULL);
554
555
0
  _g_file_attribute_value_clear (attr);
556
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
557
0
  attr->u.string = g_strdup (string);
558
0
}
559
560
void
561
_g_file_attribute_value_set_stringv (GFileAttributeValue *attr,
562
             char               **value)
563
0
{
564
0
  g_return_if_fail (attr != NULL);
565
0
  g_return_if_fail (value != NULL);
566
567
0
  _g_file_attribute_value_clear (attr);
568
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_STRINGV;
569
0
  attr->u.stringv = g_strdupv (value);
570
0
}
571
572
573
/**
574
 * _g_file_attribute_value_set_boolean:
575
 * @attr: a #GFileAttributeValue.
576
 * @value: a #gboolean to set within the type.
577
 *
578
 * Sets the attribute value to the given boolean value.
579
 */
580
void
581
_g_file_attribute_value_set_boolean (GFileAttributeValue *attr,
582
             gboolean             value)
583
0
{
584
0
  g_return_if_fail (attr != NULL);
585
586
0
  _g_file_attribute_value_clear (attr);
587
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_BOOLEAN;
588
0
  attr->u.boolean = !!value;
589
0
}
590
591
/**
592
 * _g_file_attribute_value_set_uint32:
593
 * @attr: a #GFileAttributeValue.
594
 * @value: a #guint32 to set within the type.
595
 *
596
 * Sets the attribute value to the given unsigned 32-bit integer.
597
 */
598
void
599
_g_file_attribute_value_set_uint32 (GFileAttributeValue *attr,
600
            guint32              value)
601
0
{
602
0
  g_return_if_fail (attr != NULL);
603
604
0
  _g_file_attribute_value_clear (attr);
605
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_UINT32;
606
0
  attr->u.uint32 = value;
607
0
}
608
609
/**
610
 * _g_file_attribute_value_set_int32:
611
 * @attr: a #GFileAttributeValue.
612
 * @value: a #gint32 to set within the type.
613
 *
614
 * Sets the attribute value to the given signed 32-bit integer.
615
 */
616
void
617
_g_file_attribute_value_set_int32 (GFileAttributeValue *attr,
618
           gint32               value)
619
0
{
620
0
  g_return_if_fail (attr != NULL);
621
622
0
  _g_file_attribute_value_clear (attr);
623
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INT32;
624
0
  attr->u.int32 = value;
625
0
}
626
627
/**
628
 * _g_file_attribute_value_set_uint64:
629
 * @attr: a #GFileAttributeValue.
630
 * @value: a #guint64 to set within the type.
631
 *
632
 * Sets the attribute value to a given unsigned 64-bit integer.
633
 */
634
void
635
_g_file_attribute_value_set_uint64 (GFileAttributeValue *attr,
636
            guint64              value)
637
0
{
638
0
  g_return_if_fail (attr != NULL);
639
640
0
  _g_file_attribute_value_clear (attr);
641
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_UINT64;
642
0
  attr->u.uint64 = value;
643
0
}
644
645
/**
646
 * _g_file_attribute_value_set_int64:
647
 * @attr: a #GFileAttributeValue.
648
 * @value: a #gint64 to set within the type.
649
 *
650
 * Sets the attribute value to a given signed 64-bit integer.
651
 */
652
void
653
_g_file_attribute_value_set_int64 (GFileAttributeValue *attr,
654
           gint64               value)
655
0
{
656
0
  g_return_if_fail (attr != NULL);
657
658
0
  _g_file_attribute_value_clear (attr);
659
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INT64;
660
0
  attr->u.int64 = value;
661
0
}
662
663
/**
664
 * _g_file_attribute_value_set_object:
665
 * @attr: a #GFileAttributeValue.
666
 * @obj: a #GObject.
667
 *
668
 * Sets the attribute to contain the value @obj.
669
 * The @attr references the GObject internally.
670
 */
671
void
672
_g_file_attribute_value_set_object (GFileAttributeValue *attr,
673
            GObject             *obj)
674
0
{
675
0
  g_return_if_fail (attr != NULL);
676
0
  g_return_if_fail (obj != NULL);
677
678
0
  _g_file_attribute_value_clear (attr);
679
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_OBJECT;
680
0
  attr->u.obj = g_object_ref (obj);
681
0
}
682
683
typedef struct {
684
  GFileAttributeInfoList public;
685
  GArray *array;
686
  int ref_count;
687
} GFileAttributeInfoListPriv;
688
689
static void
690
list_update_public (GFileAttributeInfoListPriv *priv)
691
0
{
692
0
  priv->public.infos = (GFileAttributeInfo *)priv->array->data;
693
694
  /* The `n_infos` member should really have type `size_t`, but by a historical
695
   * accident it has type `int` and we can’t change it now because it’s public
696
   * API. It should never end up with a negative value at runtime. */
697
0
  g_assert (priv->array->len <= INT_MAX);
698
0
  priv->public.n_infos = (int) priv->array->len;
699
0
}
700
701
/**
702
 * g_file_attribute_info_list_new:
703
 *
704
 * Creates a new file attribute info list.
705
 *
706
 * Returns: a #GFileAttributeInfoList.
707
 */
708
GFileAttributeInfoList *
709
g_file_attribute_info_list_new (void)
710
0
{
711
0
  GFileAttributeInfoListPriv *priv;
712
713
0
  priv = g_new0 (GFileAttributeInfoListPriv, 1);
714
715
0
  priv->ref_count = 1;
716
0
  priv->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
717
718
0
  list_update_public (priv);
719
720
0
  return (GFileAttributeInfoList *)priv;
721
0
}
722
723
/**
724
 * g_file_attribute_info_list_dup:
725
 * @list: a #GFileAttributeInfoList to duplicate.
726
 *
727
 * Makes a duplicate of a file attribute info list.
728
 *
729
 * Returns: a copy of the given @list.
730
 */
731
GFileAttributeInfoList *
732
g_file_attribute_info_list_dup (GFileAttributeInfoList *list)
733
0
{
734
0
  GFileAttributeInfoListPriv *new;
735
0
  int i;
736
737
0
  g_return_val_if_fail (list != NULL, NULL);
738
739
0
  new = g_new0 (GFileAttributeInfoListPriv, 1);
740
0
  new->ref_count = 1;
741
0
  new->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
742
743
0
  g_array_set_size (new->array, (unsigned int) list->n_infos);
744
0
  list_update_public (new);
745
0
  for (i = 0; i < list->n_infos; i++)
746
0
    {
747
0
      new->public.infos[i].name = g_strdup (list->infos[i].name);
748
0
      new->public.infos[i].type = list->infos[i].type;
749
0
      new->public.infos[i].flags = list->infos[i].flags;
750
0
    }
751
752
0
  return (GFileAttributeInfoList *)new;
753
0
}
754
755
/**
756
 * g_file_attribute_info_list_ref:
757
 * @list: a #GFileAttributeInfoList to reference.
758
 *
759
 * References a file attribute info list.
760
 *
761
 * Returns: #GFileAttributeInfoList or %NULL on error.
762
 */
763
GFileAttributeInfoList *
764
g_file_attribute_info_list_ref (GFileAttributeInfoList *list)
765
0
{
766
0
  GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
767
0
  int old_ref_count;
768
769
0
  g_return_val_if_fail (list != NULL, NULL);
770
771
0
  old_ref_count = g_atomic_int_add (&priv->ref_count, 1);
772
0
  g_return_val_if_fail (old_ref_count > 0, NULL);
773
774
0
  return list;
775
0
}
776
777
/**
778
 * g_file_attribute_info_list_unref:
779
 * @list: The #GFileAttributeInfoList to unreference.
780
 *
781
 * Removes a reference from the given @list. If the reference count
782
 * falls to zero, the @list is deleted.
783
 */
784
void
785
g_file_attribute_info_list_unref (GFileAttributeInfoList *list)
786
0
{
787
0
  GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
788
0
  int i;
789
790
0
  g_return_if_fail (list != NULL);
791
0
  g_return_if_fail (priv->ref_count > 0);
792
793
0
  if (g_atomic_int_dec_and_test (&priv->ref_count))
794
0
    {
795
0
      for (i = 0; i < list->n_infos; i++)
796
0
        g_free (list->infos[i].name);
797
0
      g_array_free (priv->array, TRUE);
798
0
      g_free (list);
799
0
    }
800
0
}
801
802
static int
803
g_file_attribute_info_list_bsearch (GFileAttributeInfoList *list,
804
            const char             *name)
805
0
{
806
0
  int start, end, mid;
807
808
0
  start = 0;
809
0
  end = list->n_infos;
810
811
0
  while (start != end)
812
0
    {
813
0
      mid = start + (end - start) / 2;
814
815
0
      if (strcmp (name, list->infos[mid].name) < 0)
816
0
  end = mid;
817
0
      else if (strcmp (name, list->infos[mid].name) > 0)
818
0
  start = mid + 1;
819
0
      else
820
0
  return mid;
821
0
    }
822
0
  return start;
823
0
}
824
825
/**
826
 * g_file_attribute_info_list_lookup:
827
 * @list: a #GFileAttributeInfoList.
828
 * @name: the name of the attribute to look up.
829
 *
830
 * Gets the file attribute with the name @name from @list.
831
 *
832
 * Returns: a #GFileAttributeInfo for the @name, or %NULL if an
833
 * attribute isn't found.
834
 */
835
const GFileAttributeInfo *
836
g_file_attribute_info_list_lookup (GFileAttributeInfoList *list,
837
           const char             *name)
838
0
{
839
0
  int i;
840
841
0
  g_return_val_if_fail (list != NULL, NULL);
842
0
  g_return_val_if_fail (name != NULL, NULL);
843
844
0
  i = g_file_attribute_info_list_bsearch (list, name);
845
846
0
  if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
847
0
    return &list->infos[i];
848
849
0
  return NULL;
850
0
}
851
852
/**
853
 * g_file_attribute_info_list_add:
854
 * @list: a #GFileAttributeInfoList.
855
 * @name: the name of the attribute to add.
856
 * @type: the #GFileAttributeType for the attribute.
857
 * @flags: #GFileAttributeInfoFlags for the attribute.
858
 *
859
 * Adds a new attribute with @name to the @list, setting
860
 * its @type and @flags.
861
 */
862
void
863
g_file_attribute_info_list_add (GFileAttributeInfoList *list,
864
        const char             *name,
865
        GFileAttributeType      type,
866
        GFileAttributeInfoFlags flags)
867
0
{
868
0
  GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
869
0
  GFileAttributeInfo info;
870
0
  int i;
871
872
0
  g_return_if_fail (list != NULL);
873
0
  g_return_if_fail (name != NULL);
874
875
0
  i = g_file_attribute_info_list_bsearch (list, name);
876
877
0
  if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
878
0
    {
879
0
      list->infos[i].type = type;
880
0
      return;
881
0
    }
882
883
0
  g_assert (i >= 0);
884
885
0
  info.name = g_strdup (name);
886
0
  info.type = type;
887
0
  info.flags = flags;
888
0
  g_array_insert_vals (priv->array, (unsigned int) i, &info, 1);
889
890
0
  list_update_public (priv);
891
0
}