Coverage Report

Created: 2025-06-13 06:55

/src/glib/gio/gfileattribute.c
Line
Count
Source (jump to first uncovered line)
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 <string.h>
26
27
#include "gfileattribute.h"
28
#include "gfileattribute-priv.h"
29
#include <glib-object.h>
30
#include "glibintl.h"
31
32
33
/**
34
 * SECTION:gfileattribute
35
 * @short_description: Key-Value Paired File Attributes
36
 * @include: gio/gio.h
37
 * @see_also: #GFile, #GFileInfo
38
 *
39
 * File attributes in GIO consist of a list of key-value pairs.
40
 *
41
 * Keys are strings that contain a key namespace and a key name, separated
42
 * by a colon, e.g. "namespace::keyname". Namespaces are included to sort
43
 * key-value pairs by namespaces for relevance. Keys can be retrieved
44
 * using wildcards, e.g. "standard::*" will return all of the keys in the
45
 * "standard" namespace.
46
 *
47
 * The list of possible attributes for a filesystem (pointed to by a #GFile) is
48
 * available as a #GFileAttributeInfoList. This list is queryable by key names
49
 * as indicated earlier.
50
 *
51
 * Information is stored within the list in #GFileAttributeInfo structures.
52
 * The info structure can store different types, listed in the enum
53
 * #GFileAttributeType. Upon creation of a #GFileAttributeInfo, the type will
54
 * be set to %G_FILE_ATTRIBUTE_TYPE_INVALID.
55
 *
56
 * Classes that implement #GFileIface will create a #GFileAttributeInfoList and
57
 * install default keys and values for their given file system, architecture,
58
 * and other possible implementation details (e.g., on a UNIX system, a file
59
 * attribute key will be registered for the user id for a given file).
60
 *
61
 * ## Default Namespaces
62
 *
63
 * - `"standard"`: The "Standard" namespace. General file information that
64
 *   any application may need should be put in this namespace. Examples
65
 *   include the file's name, type, and size.
66
 * - `"etag`: The [Entity Tag][gfile-etag] namespace. Currently, the only key
67
 *   in this namespace is "value", which contains the value of the current
68
 *   entity tag.
69
 * - `"id"`: The "Identification" namespace. This namespace is used by file
70
 *   managers and applications that list directories to check for loops and
71
 *   to uniquely identify files.
72
 * - `"access"`: The "Access" namespace. Used to check if a user has the
73
 *   proper privileges to access files and perform file operations. Keys in
74
 *   this namespace are made to be generic and easily understood, e.g. the
75
 *   "can_read" key is %TRUE if the current user has permission to read the
76
 *   file. UNIX permissions and NTFS ACLs in Windows should be mapped to
77
 *   these values.
78
 * - `"mountable"`: The "Mountable" namespace. Includes simple boolean keys
79
 *   for checking if a file or path supports mount operations, e.g. mount,
80
 *   unmount, eject. These are used for files of type %G_FILE_TYPE_MOUNTABLE.
81
 * - `"time"`: The "Time" namespace. Includes file access, changed, created
82
 *   times.
83
 * - `"unix"`: The "Unix" namespace. Includes UNIX-specific information and
84
 *   may not be available for all files. Examples include the UNIX "UID",
85
 *   "GID", etc.
86
 * - `"dos"`: The "DOS" namespace. Includes DOS-specific information and may
87
 *   not be available for all files. Examples include "is_system" for checking
88
 *   if a file is marked as a system file, and "is_archive" for checking if a
89
 *   file is marked as an archive file.
90
 * - `"owner"`: The "Owner" namespace. Includes information about who owns a
91
 *   file. May not be available for all file systems. Examples include "user"
92
 *   for getting the user name of the file owner. This information is often
93
 *   mapped from some backend specific data such as a UNIX UID.
94
 * - `"thumbnail"`: The "Thumbnail" namespace. Includes information about file
95
 *   thumbnails and their location within the file system. Examples of keys in
96
 *   this namespace include "path" to get the location of a thumbnail, "failed"
97
 *   to check if thumbnailing of the file failed, and "is-valid" to check if
98
 *   the thumbnail is outdated.
99
 * - `"filesystem"`: The "Filesystem" namespace. Gets information about the
100
 *   file system where a file is located, such as its type, how much space is
101
 *   left available, and the overall size of the file system.
102
 * - `"gvfs"`: The "GVFS" namespace. Keys in this namespace contain information
103
 *   about the current GVFS backend in use.
104
 * - `"xattr"`: The "xattr" namespace. Gets information about extended
105
 *   user attributes. See attr(5). The "user." prefix of the extended user
106
 *   attribute name is stripped away when constructing keys in this namespace,
107
 *   e.g. "xattr::mime_type" for the extended attribute with the name
108
 *   "user.mime_type". Note that this information is only available if
109
 *   GLib has been built with extended attribute support.
110
 * - `"xattr-sys"`: The "xattr-sys" namespace. Gets information about
111
 *   extended attributes which are not user-specific. See attr(5). Note
112
 *   that this information is only available if GLib has been built with
113
 *   extended attribute support.
114
 * - `"selinux"`: The "SELinux" namespace. Includes information about the
115
 *   SELinux context of files. Note that this information is only available
116
 *   if GLib has been built with SELinux support.
117
 *
118
 * Please note that these are not all of the possible namespaces.
119
 * More namespaces can be added from GIO modules or by individual applications.
120
 * For more information about writing GIO modules, see #GIOModule.
121
 *
122
 * <!-- TODO: Implementation note about using extended attributes on supported
123
 * file systems -->
124
 *
125
 * ## Default Keys
126
 *
127
 * For a list of the built-in keys and their types, see the
128
 * [GFileInfo][GFileInfo] documentation.
129
 *
130
 * Note that there are no predefined keys in the "xattr" and "xattr-sys"
131
 * namespaces. Keys for the "xattr" namespace are constructed by stripping
132
 * away the "user." prefix from the extended user attribute, and prepending
133
 * "xattr::". Keys for the "xattr-sys" namespace are constructed by
134
 * concatenating "xattr-sys::" with the extended attribute name. All extended
135
 * attribute values are returned as hex-encoded strings in which bytes outside
136
 * the ASCII range are encoded as escape sequences of the form \x`nn`
137
 * where `nn` is a 2-digit hexadecimal number.
138
 */
139
140
/**
141
 * _g_file_attribute_value_free:
142
 * @attr: a #GFileAttributeValue.
143
 *
144
 * Frees the memory used by @attr.
145
 *
146
 **/
147
void
148
_g_file_attribute_value_free (GFileAttributeValue *attr)
149
0
{
150
0
  g_return_if_fail (attr != NULL);
151
152
0
  _g_file_attribute_value_clear (attr);
153
0
  g_free (attr);
154
0
}
155
156
/**
157
 * _g_file_attribute_value_clear:
158
 * @attr: a #GFileAttributeValue.
159
 *
160
 * Clears the value of @attr and sets its type to
161
 * %G_FILE_ATTRIBUTE_TYPE_INVALID.
162
 *
163
 **/
164
void
165
_g_file_attribute_value_clear (GFileAttributeValue *attr)
166
0
{
167
0
  g_return_if_fail (attr != NULL);
168
169
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
170
0
      attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
171
0
    g_free (attr->u.string);
172
173
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV)
174
0
    g_strfreev (attr->u.stringv);
175
176
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
177
0
      attr->u.obj != NULL)
178
0
    g_object_unref (attr->u.obj);
179
180
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
181
0
}
182
183
/**
184
 * g_file_attribute_value_set:
185
 * @attr: a #GFileAttributeValue to set the value in.
186
 * @new_value: a #GFileAttributeValue to get the value from.
187
 *
188
 * Sets an attribute's value from another attribute.
189
 **/
190
void
191
_g_file_attribute_value_set (GFileAttributeValue        *attr,
192
           const GFileAttributeValue *new_value)
193
0
{
194
0
  g_return_if_fail (attr != NULL);
195
0
  g_return_if_fail (new_value != NULL);
196
197
0
  _g_file_attribute_value_clear (attr);
198
0
  *attr = *new_value;
199
200
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING ||
201
0
      attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING)
202
0
    attr->u.string = g_strdup (attr->u.string);
203
204
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV)
205
0
    attr->u.stringv = g_strdupv (attr->u.stringv);
206
207
0
  if (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT &&
208
0
      attr->u.obj != NULL)
209
0
    g_object_ref (attr->u.obj);
210
0
}
211
212
/**
213
 * _g_file_attribute_value_new:
214
 *
215
 * Creates a new file attribute.
216
 *
217
 * Returns: a #GFileAttributeValue.
218
 **/
219
GFileAttributeValue *
220
_g_file_attribute_value_new (void)
221
0
{
222
0
  GFileAttributeValue *attr;
223
224
0
  attr = g_new (GFileAttributeValue, 1);
225
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
226
0
  return attr;
227
0
}
228
229
gpointer
230
_g_file_attribute_value_peek_as_pointer (GFileAttributeValue *attr)
231
0
{
232
0
  switch (attr->type) {
233
0
  case G_FILE_ATTRIBUTE_TYPE_STRING:
234
0
  case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
235
0
    return attr->u.string;
236
0
  case G_FILE_ATTRIBUTE_TYPE_STRINGV:
237
0
    return attr->u.stringv;
238
0
  case G_FILE_ATTRIBUTE_TYPE_OBJECT:
239
0
    return attr->u.obj;
240
0
  default:
241
0
    return (gpointer) &attr->u;
242
0
  }
243
0
}
244
245
/**
246
 * g_file_attribute_value_dup:
247
 * @other: a #GFileAttributeValue to duplicate.
248
 *
249
 * Duplicates a file attribute.
250
 *
251
 * Returns: a duplicate of the @other.
252
 **/
253
GFileAttributeValue *
254
_g_file_attribute_value_dup (const GFileAttributeValue *other)
255
0
{
256
0
  GFileAttributeValue *attr;
257
258
0
  g_return_val_if_fail (other != NULL, NULL);
259
260
0
  attr = g_new (GFileAttributeValue, 1);
261
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
262
0
  _g_file_attribute_value_set (attr, other);
263
0
  return attr;
264
0
}
265
266
G_DEFINE_BOXED_TYPE (GFileAttributeInfoList, g_file_attribute_info_list,
267
                     g_file_attribute_info_list_dup,
268
                     g_file_attribute_info_list_unref)
269
270
static gboolean
271
valid_char (char c)
272
0
{
273
0
  return c >= 32 && c <= 126 && c != '\\';
274
0
}
275
276
static char *
277
escape_byte_string (const char *str)
278
0
{
279
0
  size_t i, len;
280
0
  int num_invalid;
281
0
  char *escaped_val, *p;
282
0
  unsigned char c;
283
0
  const char hex_digits[] = "0123456789abcdef";
284
285
0
  len = strlen (str);
286
287
0
  num_invalid = 0;
288
0
  for (i = 0; i < len; i++)
289
0
    {
290
0
      if (!valid_char (str[i]))
291
0
  num_invalid++;
292
0
    }
293
294
0
  if (num_invalid == 0)
295
0
    return g_strdup (str);
296
0
  else
297
0
    {
298
0
      escaped_val = g_malloc (len + num_invalid*3 + 1);
299
300
0
      p = escaped_val;
301
0
      for (i = 0; i < len; i++)
302
0
  {
303
0
    c = str[i];
304
0
    if (valid_char (c))
305
0
      *p++ = c;
306
0
    else
307
0
      {
308
0
        *p++ = '\\';
309
0
        *p++ = 'x';
310
0
        *p++ = hex_digits[(c >> 4) & 0xf];
311
0
        *p++ = hex_digits[c & 0xf];
312
0
      }
313
0
  }
314
0
      *p++ = 0;
315
0
      return escaped_val;
316
0
    }
317
0
}
318
319
/**
320
 * _g_file_attribute_value_as_string:
321
 * @attr: a #GFileAttributeValue.
322
 *
323
 * Converts a #GFileAttributeValue to a string for display.
324
 * The returned string should be freed when no longer needed.
325
 *
326
 * Returns: a string from the @attr, %NULL on error, or "<invalid>"
327
 * if @attr is of type %G_FILE_ATTRIBUTE_TYPE_INVALID.
328
 */
329
char *
330
_g_file_attribute_value_as_string (const GFileAttributeValue *attr)
331
0
{
332
0
  GString *s;
333
0
  int i;
334
0
  char *str;
335
336
0
  g_return_val_if_fail (attr != NULL, NULL);
337
338
0
  switch (attr->type)
339
0
    {
340
0
    case G_FILE_ATTRIBUTE_TYPE_STRING:
341
0
      str = g_strdup (attr->u.string);
342
0
      break;
343
0
    case G_FILE_ATTRIBUTE_TYPE_STRINGV:
344
0
      s = g_string_new ("[");
345
0
      for (i = 0; attr->u.stringv[i] != NULL; i++)
346
0
  {
347
0
    g_string_append (s, attr->u.stringv[i]);
348
0
    if (attr->u.stringv[i+1] != NULL)
349
0
      g_string_append (s, ", ");
350
0
  }
351
0
      g_string_append (s, "]");
352
0
      str = g_string_free (s, FALSE);
353
0
      break;
354
0
    case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
355
0
      str = escape_byte_string (attr->u.string);
356
0
      break;
357
0
    case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
358
0
      str = g_strdup_printf ("%s", attr->u.boolean?"TRUE":"FALSE");
359
0
      break;
360
0
    case G_FILE_ATTRIBUTE_TYPE_UINT32:
361
0
      str = g_strdup_printf ("%u", (unsigned int)attr->u.uint32);
362
0
      break;
363
0
    case G_FILE_ATTRIBUTE_TYPE_INT32:
364
0
      str = g_strdup_printf ("%i", (int)attr->u.int32);
365
0
      break;
366
0
    case G_FILE_ATTRIBUTE_TYPE_UINT64:
367
0
      str = g_strdup_printf ("%"G_GUINT64_FORMAT, attr->u.uint64);
368
0
      break;
369
0
    case G_FILE_ATTRIBUTE_TYPE_INT64:
370
0
      str = g_strdup_printf ("%"G_GINT64_FORMAT, attr->u.int64);
371
0
      break;
372
0
    case G_FILE_ATTRIBUTE_TYPE_OBJECT:
373
0
      str = g_strdup_printf ("%s:%p", g_type_name_from_instance
374
0
                                          ((GTypeInstance *) attr->u.obj),
375
0
                                      attr->u.obj);
376
0
      break;
377
0
    case G_FILE_ATTRIBUTE_TYPE_INVALID:
378
0
      str = g_strdup ("<unset>");
379
0
      break;
380
0
    default:
381
0
      g_warning ("Invalid type in GFileInfo attribute");
382
0
      str = g_strdup ("<invalid>");
383
0
      break;
384
0
    }
385
386
0
  return str;
387
0
}
388
389
/**
390
 * _g_file_attribute_value_get_string:
391
 * @attr: a #GFileAttributeValue.
392
 *
393
 * Gets the string from a file attribute value. If the value is not the
394
 * right type then %NULL will be returned.
395
 *
396
 * Returns: the UTF-8 string value contained within the attribute, or %NULL.
397
 */
398
const char *
399
_g_file_attribute_value_get_string (const GFileAttributeValue *attr)
400
0
{
401
0
  if (attr == NULL)
402
0
    return NULL;
403
404
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_STRING, NULL);
405
406
0
  return attr->u.string;
407
0
}
408
409
/**
410
 * _g_file_attribute_value_get_byte_string:
411
 * @attr: a #GFileAttributeValue.
412
 *
413
 * Gets the byte string from a file attribute value. If the value is not the
414
 * right type then %NULL will be returned.
415
 *
416
 * Returns: the byte string contained within the attribute or %NULL.
417
 */
418
const char *
419
_g_file_attribute_value_get_byte_string (const GFileAttributeValue *attr)
420
0
{
421
0
  if (attr == NULL)
422
0
    return NULL;
423
424
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, NULL);
425
426
0
  return attr->u.string;
427
0
}
428
429
char **
430
_g_file_attribute_value_get_stringv (const GFileAttributeValue *attr)
431
0
{
432
0
  if (attr == NULL)
433
0
    return NULL;
434
435
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_STRINGV, NULL);
436
437
0
  return attr->u.stringv;
438
0
}
439
440
/**
441
 * _g_file_attribute_value_get_boolean:
442
 * @attr: a #GFileAttributeValue.
443
 *
444
 * Gets the boolean value from a file attribute value. If the value is not the
445
 * right type then %FALSE will be returned.
446
 *
447
 * Returns: the boolean value contained within the attribute, or %FALSE.
448
 */
449
gboolean
450
_g_file_attribute_value_get_boolean (const GFileAttributeValue *attr)
451
0
{
452
0
  if (attr == NULL)
453
0
    return FALSE;
454
455
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_BOOLEAN, FALSE);
456
457
0
  return attr->u.boolean;
458
0
}
459
460
/**
461
 * _g_file_attribute_value_get_uint32:
462
 * @attr: a #GFileAttributeValue.
463
 *
464
 * Gets the unsigned 32-bit integer from a file attribute value. If the value
465
 * is not the right type then 0 will be returned.
466
 *
467
 * Returns: the unsigned 32-bit integer from the attribute, or 0.
468
 */
469
guint32
470
_g_file_attribute_value_get_uint32 (const GFileAttributeValue *attr)
471
0
{
472
0
  if (attr == NULL)
473
0
    return 0;
474
475
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT32, 0);
476
477
0
  return attr->u.uint32;
478
0
}
479
480
/**
481
 * _g_file_attribute_value_get_int32:
482
 * @attr: a #GFileAttributeValue.
483
 *
484
 * Gets the signed 32-bit integer from a file attribute value. If the value
485
 * is not the right type then 0 will be returned.
486
 *
487
 * Returns: the signed 32-bit integer from the attribute, or 0.
488
 */
489
gint32
490
_g_file_attribute_value_get_int32 (const GFileAttributeValue *attr)
491
0
{
492
0
  if (attr == NULL)
493
0
    return 0;
494
495
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT32, 0);
496
497
0
  return attr->u.int32;
498
0
}
499
500
/**
501
 * _g_file_attribute_value_get_uint64:
502
 * @attr: a #GFileAttributeValue.
503
 *
504
 * Gets the unsigned 64-bit integer from a file attribute value. If the value
505
 * is not the right type then 0 will be returned.
506
 *
507
 * Returns: the unsigned 64-bit integer from the attribute, or 0.
508
 */
509
guint64
510
_g_file_attribute_value_get_uint64 (const GFileAttributeValue *attr)
511
0
{
512
0
  if (attr == NULL)
513
0
    return 0;
514
515
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_UINT64, 0);
516
517
0
  return attr->u.uint64;
518
0
}
519
520
/**
521
 * _g_file_attribute_value_get_int64:
522
 * @attr: a #GFileAttributeValue.
523
 *
524
 * Gets the signed 64-bit integer from a file attribute value. If the value
525
 * is not the right type then 0 will be returned.
526
 *
527
 * Returns: the signed 64-bit integer from the attribute, or 0.
528
 */
529
gint64
530
_g_file_attribute_value_get_int64 (const GFileAttributeValue *attr)
531
0
{
532
0
  if (attr == NULL)
533
0
    return 0;
534
535
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_INT64, 0);
536
537
0
  return attr->u.int64;
538
0
}
539
540
/**
541
 * _g_file_attribute_value_get_object:
542
 * @attr: a #GFileAttributeValue.
543
 *
544
 * Gets the GObject from a file attribute value. If the value
545
 * is not the right type then %NULL will be returned.
546
 *
547
 * Returns: the GObject from the attribute, or %NULL.
548
 **/
549
GObject *
550
_g_file_attribute_value_get_object (const GFileAttributeValue *attr)
551
0
{
552
0
  if (attr == NULL)
553
0
    return NULL;
554
555
0
  g_return_val_if_fail (attr->type == G_FILE_ATTRIBUTE_TYPE_OBJECT, NULL);
556
557
0
  return attr->u.obj;
558
0
}
559
560
561
void
562
_g_file_attribute_value_set_from_pointer (GFileAttributeValue *value,
563
            GFileAttributeType   type,
564
            gpointer             value_p,
565
            gboolean             dup)
566
0
{
567
0
  _g_file_attribute_value_clear (value);
568
0
  value->type = type;
569
0
  switch (type)
570
0
    {
571
0
    case G_FILE_ATTRIBUTE_TYPE_STRING:
572
0
    case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
573
0
      if (dup)
574
0
  value->u.string = g_strdup (value_p);
575
0
      else
576
0
  value->u.string = value_p;
577
0
      break;
578
579
0
    case G_FILE_ATTRIBUTE_TYPE_STRINGV:
580
0
      if (dup)
581
0
  value->u.stringv = g_strdupv (value_p);
582
0
      else
583
0
  value->u.stringv = value_p;
584
0
      break;
585
586
0
    case G_FILE_ATTRIBUTE_TYPE_OBJECT:
587
0
      if (dup)
588
0
  value->u.obj = g_object_ref (value_p);
589
0
      else
590
0
  value->u.obj = value_p;
591
0
      break;
592
593
0
    case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
594
0
      value->u.boolean = *(gboolean *)value_p;
595
0
      break;
596
597
0
    case G_FILE_ATTRIBUTE_TYPE_UINT32:
598
0
      value->u.uint32 = *(guint32 *)value_p;
599
0
      break;
600
601
0
    case G_FILE_ATTRIBUTE_TYPE_INT32:
602
0
      value->u.int32 = *(gint32 *)value_p;
603
0
      break;
604
605
0
    case G_FILE_ATTRIBUTE_TYPE_UINT64:
606
0
      value->u.uint64 = *(guint64 *)value_p;
607
0
      break;
608
609
0
    case G_FILE_ATTRIBUTE_TYPE_INT64:
610
0
      value->u.int64 = *(gint64 *)value_p;
611
0
      break;
612
613
0
    case G_FILE_ATTRIBUTE_TYPE_INVALID:
614
0
      break;
615
616
0
    default:
617
0
      g_warning ("Unknown type specified in g_file_info_set_attribute");
618
0
      break;
619
0
    }
620
0
}
621
622
/**
623
 * _g_file_attribute_value_set_string:
624
 * @attr: a #GFileAttributeValue.
625
 * @string: a UTF-8 string to set within the type.
626
 *
627
 * Sets the attribute value to a given UTF-8 string.
628
 */
629
void
630
_g_file_attribute_value_set_string (GFileAttributeValue *attr,
631
            const char          *string)
632
0
{
633
0
  g_return_if_fail (attr != NULL);
634
0
  g_return_if_fail (string != NULL);
635
636
0
  _g_file_attribute_value_clear (attr);
637
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_STRING;
638
0
  attr->u.string = g_strdup (string);
639
0
}
640
641
/**
642
 * _g_file_attribute_value_set_byte_string:
643
 * @attr: a #GFileAttributeValue.
644
 * @string: a byte string to set within the type.
645
 *
646
 * Sets the attribute value to a given byte string.
647
 */
648
void
649
_g_file_attribute_value_set_byte_string (GFileAttributeValue *attr,
650
           const char          *string)
651
0
{
652
0
  g_return_if_fail (attr != NULL);
653
0
  g_return_if_fail (string != NULL);
654
655
0
  _g_file_attribute_value_clear (attr);
656
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
657
0
  attr->u.string = g_strdup (string);
658
0
}
659
660
void
661
_g_file_attribute_value_set_stringv (GFileAttributeValue *attr,
662
             char               **value)
663
0
{
664
0
  g_return_if_fail (attr != NULL);
665
0
  g_return_if_fail (value != NULL);
666
667
0
  _g_file_attribute_value_clear (attr);
668
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_STRINGV;
669
0
  attr->u.stringv = g_strdupv (value);
670
0
}
671
672
673
/**
674
 * _g_file_attribute_value_set_boolean:
675
 * @attr: a #GFileAttributeValue.
676
 * @value: a #gboolean to set within the type.
677
 *
678
 * Sets the attribute value to the given boolean value.
679
 */
680
void
681
_g_file_attribute_value_set_boolean (GFileAttributeValue *attr,
682
             gboolean             value)
683
0
{
684
0
  g_return_if_fail (attr != NULL);
685
686
0
  _g_file_attribute_value_clear (attr);
687
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_BOOLEAN;
688
0
  attr->u.boolean = !!value;
689
0
}
690
691
/**
692
 * _g_file_attribute_value_set_uint32:
693
 * @attr: a #GFileAttributeValue.
694
 * @value: a #guint32 to set within the type.
695
 *
696
 * Sets the attribute value to the given unsigned 32-bit integer.
697
 */
698
void
699
_g_file_attribute_value_set_uint32 (GFileAttributeValue *attr,
700
            guint32              value)
701
0
{
702
0
  g_return_if_fail (attr != NULL);
703
704
0
  _g_file_attribute_value_clear (attr);
705
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_UINT32;
706
0
  attr->u.uint32 = value;
707
0
}
708
709
/**
710
 * _g_file_attribute_value_set_int32:
711
 * @attr: a #GFileAttributeValue.
712
 * @value: a #gint32 to set within the type.
713
 *
714
 * Sets the attribute value to the given signed 32-bit integer.
715
 */
716
void
717
_g_file_attribute_value_set_int32 (GFileAttributeValue *attr,
718
           gint32               value)
719
0
{
720
0
  g_return_if_fail (attr != NULL);
721
722
0
  _g_file_attribute_value_clear (attr);
723
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INT32;
724
0
  attr->u.int32 = value;
725
0
}
726
727
/**
728
 * _g_file_attribute_value_set_uint64:
729
 * @attr: a #GFileAttributeValue.
730
 * @value: a #guint64 to set within the type.
731
 *
732
 * Sets the attribute value to a given unsigned 64-bit integer.
733
 */
734
void
735
_g_file_attribute_value_set_uint64 (GFileAttributeValue *attr,
736
            guint64              value)
737
0
{
738
0
  g_return_if_fail (attr != NULL);
739
740
0
  _g_file_attribute_value_clear (attr);
741
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_UINT64;
742
0
  attr->u.uint64 = value;
743
0
}
744
745
/**
746
 * _g_file_attribute_value_set_int64:
747
 * @attr: a #GFileAttributeValue.
748
 * @value: a #gint64 to set within the type.
749
 *
750
 * Sets the attribute value to a given signed 64-bit integer.
751
 */
752
void
753
_g_file_attribute_value_set_int64 (GFileAttributeValue *attr,
754
           gint64               value)
755
0
{
756
0
  g_return_if_fail (attr != NULL);
757
758
0
  _g_file_attribute_value_clear (attr);
759
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_INT64;
760
0
  attr->u.int64 = value;
761
0
}
762
763
/**
764
 * _g_file_attribute_value_set_object:
765
 * @attr: a #GFileAttributeValue.
766
 * @obj: a #GObject.
767
 *
768
 * Sets the attribute to contain the value @obj.
769
 * The @attr references the GObject internally.
770
 */
771
void
772
_g_file_attribute_value_set_object (GFileAttributeValue *attr,
773
            GObject             *obj)
774
0
{
775
0
  g_return_if_fail (attr != NULL);
776
0
  g_return_if_fail (obj != NULL);
777
778
0
  _g_file_attribute_value_clear (attr);
779
0
  attr->type = G_FILE_ATTRIBUTE_TYPE_OBJECT;
780
0
  attr->u.obj = g_object_ref (obj);
781
0
}
782
783
typedef struct {
784
  GFileAttributeInfoList public;
785
  GArray *array;
786
  int ref_count;
787
} GFileAttributeInfoListPriv;
788
789
static void
790
list_update_public (GFileAttributeInfoListPriv *priv)
791
0
{
792
0
  priv->public.infos = (GFileAttributeInfo *)priv->array->data;
793
0
  priv->public.n_infos = priv->array->len;
794
0
}
795
796
/**
797
 * g_file_attribute_info_list_new:
798
 *
799
 * Creates a new file attribute info list.
800
 *
801
 * Returns: a #GFileAttributeInfoList.
802
 */
803
GFileAttributeInfoList *
804
g_file_attribute_info_list_new (void)
805
0
{
806
0
  GFileAttributeInfoListPriv *priv;
807
808
0
  priv = g_new0 (GFileAttributeInfoListPriv, 1);
809
810
0
  priv->ref_count = 1;
811
0
  priv->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
812
813
0
  list_update_public (priv);
814
815
0
  return (GFileAttributeInfoList *)priv;
816
0
}
817
818
/**
819
 * g_file_attribute_info_list_dup:
820
 * @list: a #GFileAttributeInfoList to duplicate.
821
 *
822
 * Makes a duplicate of a file attribute info list.
823
 *
824
 * Returns: a copy of the given @list.
825
 */
826
GFileAttributeInfoList *
827
g_file_attribute_info_list_dup (GFileAttributeInfoList *list)
828
0
{
829
0
  GFileAttributeInfoListPriv *new;
830
0
  int i;
831
832
0
  g_return_val_if_fail (list != NULL, NULL);
833
834
0
  new = g_new0 (GFileAttributeInfoListPriv, 1);
835
0
  new->ref_count = 1;
836
0
  new->array = g_array_new (TRUE, FALSE, sizeof (GFileAttributeInfo));
837
838
0
  g_array_set_size (new->array, list->n_infos);
839
0
  list_update_public (new);
840
0
  for (i = 0; i < list->n_infos; i++)
841
0
    {
842
0
      new->public.infos[i].name = g_strdup (list->infos[i].name);
843
0
      new->public.infos[i].type = list->infos[i].type;
844
0
      new->public.infos[i].flags = list->infos[i].flags;
845
0
    }
846
847
0
  return (GFileAttributeInfoList *)new;
848
0
}
849
850
/**
851
 * g_file_attribute_info_list_ref:
852
 * @list: a #GFileAttributeInfoList to reference.
853
 *
854
 * References a file attribute info list.
855
 *
856
 * Returns: #GFileAttributeInfoList or %NULL on error.
857
 */
858
GFileAttributeInfoList *
859
g_file_attribute_info_list_ref (GFileAttributeInfoList *list)
860
0
{
861
0
  GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
862
0
  int old_ref_count;
863
864
0
  g_return_val_if_fail (list != NULL, NULL);
865
866
0
  old_ref_count = g_atomic_int_add (&priv->ref_count, 1);
867
0
  g_return_val_if_fail (old_ref_count > 0, NULL);
868
869
0
  return list;
870
0
}
871
872
/**
873
 * g_file_attribute_info_list_unref:
874
 * @list: The #GFileAttributeInfoList to unreference.
875
 *
876
 * Removes a reference from the given @list. If the reference count
877
 * falls to zero, the @list is deleted.
878
 */
879
void
880
g_file_attribute_info_list_unref (GFileAttributeInfoList *list)
881
0
{
882
0
  GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
883
0
  int i;
884
885
0
  g_return_if_fail (list != NULL);
886
0
  g_return_if_fail (priv->ref_count > 0);
887
888
0
  if (g_atomic_int_dec_and_test (&priv->ref_count))
889
0
    {
890
0
      for (i = 0; i < list->n_infos; i++)
891
0
        g_free (list->infos[i].name);
892
0
      g_array_free (priv->array, TRUE);
893
0
      g_free (list);
894
0
    }
895
0
}
896
897
static int
898
g_file_attribute_info_list_bsearch (GFileAttributeInfoList *list,
899
            const char             *name)
900
0
{
901
0
  int start, end, mid;
902
903
0
  start = 0;
904
0
  end = list->n_infos;
905
906
0
  while (start != end)
907
0
    {
908
0
      mid = start + (end - start) / 2;
909
910
0
      if (strcmp (name, list->infos[mid].name) < 0)
911
0
  end = mid;
912
0
      else if (strcmp (name, list->infos[mid].name) > 0)
913
0
  start = mid + 1;
914
0
      else
915
0
  return mid;
916
0
    }
917
0
  return start;
918
0
}
919
920
/**
921
 * g_file_attribute_info_list_lookup:
922
 * @list: a #GFileAttributeInfoList.
923
 * @name: the name of the attribute to look up.
924
 *
925
 * Gets the file attribute with the name @name from @list.
926
 *
927
 * Returns: a #GFileAttributeInfo for the @name, or %NULL if an
928
 * attribute isn't found.
929
 */
930
const GFileAttributeInfo *
931
g_file_attribute_info_list_lookup (GFileAttributeInfoList *list,
932
           const char             *name)
933
0
{
934
0
  int i;
935
936
0
  g_return_val_if_fail (list != NULL, NULL);
937
0
  g_return_val_if_fail (name != NULL, NULL);
938
939
0
  i = g_file_attribute_info_list_bsearch (list, name);
940
941
0
  if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
942
0
    return &list->infos[i];
943
944
0
  return NULL;
945
0
}
946
947
/**
948
 * g_file_attribute_info_list_add:
949
 * @list: a #GFileAttributeInfoList.
950
 * @name: the name of the attribute to add.
951
 * @type: the #GFileAttributeType for the attribute.
952
 * @flags: #GFileAttributeInfoFlags for the attribute.
953
 *
954
 * Adds a new attribute with @name to the @list, setting
955
 * its @type and @flags.
956
 */
957
void
958
g_file_attribute_info_list_add (GFileAttributeInfoList *list,
959
        const char             *name,
960
        GFileAttributeType      type,
961
        GFileAttributeInfoFlags flags)
962
0
{
963
0
  GFileAttributeInfoListPriv *priv = (GFileAttributeInfoListPriv *)list;
964
0
  GFileAttributeInfo info;
965
0
  int i;
966
967
0
  g_return_if_fail (list != NULL);
968
0
  g_return_if_fail (name != NULL);
969
970
0
  i = g_file_attribute_info_list_bsearch (list, name);
971
972
0
  if (i < list->n_infos && strcmp (list->infos[i].name, name) == 0)
973
0
    {
974
0
      list->infos[i].type = type;
975
0
      return;
976
0
    }
977
978
0
  info.name = g_strdup (name);
979
0
  info.type = type;
980
0
  info.flags = flags;
981
0
  g_array_insert_vals (priv->array, i, &info, 1);
982
983
0
  list_update_public (priv);
984
0
}