Coverage Report

Created: 2025-06-13 06:55

/src/glib/gio/gfileinfo.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
/**
24
 * SECTION:gfileinfo
25
 * @short_description: File Information and Attributes
26
 * @include: gio/gio.h
27
 * @see_also: #GFile, [GFileAttribute][gio-GFileAttribute]
28
 *
29
 * Functionality for manipulating basic metadata for files. #GFileInfo
30
 * implements methods for getting information that all files should
31
 * contain, and allows for manipulation of extended attributes.
32
 *
33
 * See [GFileAttribute][gio-GFileAttribute] for more information on how
34
 * GIO handles file attributes.
35
 *
36
 * To obtain a #GFileInfo for a #GFile, use g_file_query_info() (or its
37
 * async variant). To obtain a #GFileInfo for a file input or output
38
 * stream, use g_file_input_stream_query_info() or
39
 * g_file_output_stream_query_info() (or their async variants).
40
 *
41
 * To change the actual attributes of a file, you should then set the
42
 * attribute in the #GFileInfo and call g_file_set_attributes_from_info()
43
 * or g_file_set_attributes_async() on a GFile.
44
 *
45
 * However, not all attributes can be changed in the file. For instance,
46
 * the actual size of a file cannot be changed via g_file_info_set_size().
47
 * You may call g_file_query_settable_attributes() and
48
 * g_file_query_writable_namespaces() to discover the settable attributes
49
 * of a particular file at runtime.
50
 *
51
 * The direct accessors, such as g_file_info_get_name(), are slightly more
52
 * optimized than the generic attribute accessors, such as
53
 * g_file_info_get_attribute_byte_string().This optimization will matter
54
 * only if calling the API in a tight loop.
55
 *
56
 * It is an error to call these accessors without specifying their required file
57
 * attributes when creating the #GFileInfo. Use g_file_info_has_attribute() or
58
 * g_file_info_list_attributes() to check what attributes are specified for a
59
 * #GFileInfo.
60
 *
61
 * #GFileAttributeMatcher allows for searching through a #GFileInfo for
62
 * attributes.
63
 **/
64
65
#include "config.h"
66
67
#include <string.h>
68
69
#include "gfileinfo.h"
70
#include "gfileinfo-priv.h"
71
#include "gfileattribute-priv.h"
72
#include "gicon.h"
73
#include "glibintl.h"
74
75
76
/* We use this nasty thing, because NULL is a valid attribute matcher (matches nothing) */
77
0
#define NO_ATTRIBUTE_MASK ((GFileAttributeMatcher *)1)
78
79
typedef struct  {
80
  guint32 attribute;
81
  GFileAttributeValue value;
82
} GFileAttribute;
83
84
struct _GFileInfo
85
{
86
  GObject parent_instance;
87
88
  GArray *attributes;
89
  GFileAttributeMatcher *mask;
90
};
91
92
struct _GFileInfoClass
93
{
94
  GObjectClass parent_class;
95
};
96
97
98
G_DEFINE_TYPE (GFileInfo, g_file_info, G_TYPE_OBJECT)
99
100
typedef struct {
101
  guint32 id;
102
  guint32 attribute_id_counter;
103
} NSInfo;
104
105
G_LOCK_DEFINE_STATIC (attribute_hash);
106
static int namespace_id_counter = 0;
107
static GHashTable *ns_hash = NULL;
108
static GHashTable *attribute_hash = NULL;
109
static char ***global_attributes = NULL;
110
111
/* Attribute ids are 32bit, we split it up like this:
112
 * |------------|--------------------|
113
 *   12 bit          20 bit
114
 *   namespace      attribute id
115
 *
116
 * This way the attributes gets sorted in namespace order
117
 */
118
119
0
#define NS_POS 20
120
0
#define NS_MASK ((guint32)((1<<12) - 1))
121
0
#define ID_POS 0
122
0
#define ID_MASK ((guint32)((1<<20) - 1))
123
124
#define GET_NS(_attr_id) \
125
0
    (((guint32) (_attr_id) >> NS_POS) & NS_MASK)
126
#define GET_ID(_attr_id) \
127
0
    (((guint32)(_attr_id) >> ID_POS) & ID_MASK)
128
129
#define MAKE_ATTR_ID(_ns, _id)        \
130
0
    ( ((((guint32) _ns) & NS_MASK) << NS_POS) |   \
131
0
      ((((guint32) _id) & ID_MASK) << ID_POS) )
132
133
static NSInfo *
134
_lookup_namespace (const char *namespace)
135
0
{
136
0
  NSInfo *ns_info;
137
138
0
  ns_info = g_hash_table_lookup (ns_hash, namespace);
139
0
  if (ns_info == NULL)
140
0
    {
141
0
      ns_info = g_new0 (NSInfo, 1);
142
0
      ns_info->id = ++namespace_id_counter;
143
0
      g_hash_table_insert (ns_hash, g_strdup (namespace), ns_info);
144
0
      global_attributes = g_realloc (global_attributes, (ns_info->id + 1) * sizeof (char **));
145
0
      global_attributes[ns_info->id] = g_new (char *, 1);
146
0
      global_attributes[ns_info->id][0] = g_strconcat (namespace, "::*", NULL);
147
0
    }
148
0
  return ns_info;
149
0
}
150
151
static guint32
152
_lookup_attribute (const char *attribute)
153
0
{
154
0
  guint32 attr_id, id;
155
0
  char *ns;
156
0
  const char *colon;
157
0
  NSInfo *ns_info;
158
159
0
  attr_id = GPOINTER_TO_UINT (g_hash_table_lookup (attribute_hash, attribute));
160
161
0
  if (attr_id != 0)
162
0
    return attr_id;
163
164
0
  colon = strstr (attribute, "::");
165
0
  if (colon)
166
0
    ns = g_strndup (attribute, colon - attribute);
167
0
  else
168
0
    ns = g_strdup ("");
169
170
0
  ns_info = _lookup_namespace (ns);
171
0
  g_free (ns);
172
173
0
  id = ++ns_info->attribute_id_counter;
174
0
  global_attributes[ns_info->id] = g_realloc (global_attributes[ns_info->id], (id + 1) * sizeof (char *));
175
0
  global_attributes[ns_info->id][id] = g_strdup (attribute);
176
177
0
  attr_id = MAKE_ATTR_ID (ns_info->id, id);
178
179
0
  g_hash_table_insert (attribute_hash, global_attributes[ns_info->id][id], GUINT_TO_POINTER (attr_id));
180
181
0
  return attr_id;
182
0
}
183
184
static void
185
ensure_attribute_hash (void)
186
0
{
187
0
  if (attribute_hash != NULL)
188
0
    return;
189
190
0
  ns_hash = g_hash_table_new (g_str_hash, g_str_equal);
191
0
  attribute_hash = g_hash_table_new (g_str_hash, g_str_equal);
192
193
0
#define REGISTER_ATTRIBUTE(name) G_STMT_START{\
194
0
  guint _u G_GNUC_UNUSED  /* when compiling with G_DISABLE_ASSERT */; \
195
0
  _u = _lookup_attribute (G_FILE_ATTRIBUTE_ ## name); \
196
  /* use for generating the ID: g_print ("#define G_FILE_ATTRIBUTE_ID_%s (%u + %u)\n", #name + 17, _u & ~ID_MASK, _u & ID_MASK); */ \
197
0
  g_assert (_u == G_FILE_ATTRIBUTE_ID_ ## name); \
198
0
}G_STMT_END
199
200
0
  REGISTER_ATTRIBUTE (STANDARD_TYPE);
201
0
  REGISTER_ATTRIBUTE (STANDARD_IS_HIDDEN);
202
0
  REGISTER_ATTRIBUTE (STANDARD_IS_BACKUP);
203
0
  REGISTER_ATTRIBUTE (STANDARD_IS_SYMLINK);
204
0
  REGISTER_ATTRIBUTE (STANDARD_IS_VIRTUAL);
205
0
  REGISTER_ATTRIBUTE (STANDARD_NAME);
206
0
  REGISTER_ATTRIBUTE (STANDARD_DISPLAY_NAME);
207
0
  REGISTER_ATTRIBUTE (STANDARD_EDIT_NAME);
208
0
  REGISTER_ATTRIBUTE (STANDARD_COPY_NAME);
209
0
  REGISTER_ATTRIBUTE (STANDARD_DESCRIPTION);
210
0
  REGISTER_ATTRIBUTE (STANDARD_ICON);
211
0
  REGISTER_ATTRIBUTE (STANDARD_CONTENT_TYPE);
212
0
  REGISTER_ATTRIBUTE (STANDARD_FAST_CONTENT_TYPE);
213
0
  REGISTER_ATTRIBUTE (STANDARD_SIZE);
214
0
  REGISTER_ATTRIBUTE (STANDARD_ALLOCATED_SIZE);
215
0
  REGISTER_ATTRIBUTE (STANDARD_SYMLINK_TARGET);
216
0
  REGISTER_ATTRIBUTE (STANDARD_TARGET_URI);
217
0
  REGISTER_ATTRIBUTE (STANDARD_SORT_ORDER);
218
0
  REGISTER_ATTRIBUTE (STANDARD_SYMBOLIC_ICON);
219
0
  REGISTER_ATTRIBUTE (STANDARD_IS_VOLATILE);
220
0
  REGISTER_ATTRIBUTE (ETAG_VALUE);
221
0
  REGISTER_ATTRIBUTE (ID_FILE);
222
0
  REGISTER_ATTRIBUTE (ID_FILESYSTEM);
223
0
  REGISTER_ATTRIBUTE (ACCESS_CAN_READ);
224
0
  REGISTER_ATTRIBUTE (ACCESS_CAN_WRITE);
225
0
  REGISTER_ATTRIBUTE (ACCESS_CAN_EXECUTE);
226
0
  REGISTER_ATTRIBUTE (ACCESS_CAN_DELETE);
227
0
  REGISTER_ATTRIBUTE (ACCESS_CAN_TRASH);
228
0
  REGISTER_ATTRIBUTE (ACCESS_CAN_RENAME);
229
0
  REGISTER_ATTRIBUTE (MOUNTABLE_CAN_MOUNT);
230
0
  REGISTER_ATTRIBUTE (MOUNTABLE_CAN_UNMOUNT);
231
0
  REGISTER_ATTRIBUTE (MOUNTABLE_CAN_EJECT);
232
0
  REGISTER_ATTRIBUTE (MOUNTABLE_UNIX_DEVICE);
233
0
  REGISTER_ATTRIBUTE (MOUNTABLE_UNIX_DEVICE_FILE);
234
0
  REGISTER_ATTRIBUTE (MOUNTABLE_HAL_UDI);
235
0
  REGISTER_ATTRIBUTE (MOUNTABLE_CAN_START);
236
0
  REGISTER_ATTRIBUTE (MOUNTABLE_CAN_START_DEGRADED);
237
0
  REGISTER_ATTRIBUTE (MOUNTABLE_CAN_STOP);
238
0
  REGISTER_ATTRIBUTE (MOUNTABLE_START_STOP_TYPE);
239
0
  REGISTER_ATTRIBUTE (MOUNTABLE_CAN_POLL);
240
0
  REGISTER_ATTRIBUTE (MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC);
241
0
  REGISTER_ATTRIBUTE (TIME_MODIFIED);
242
0
  REGISTER_ATTRIBUTE (TIME_MODIFIED_USEC);
243
0
  REGISTER_ATTRIBUTE (TIME_ACCESS);
244
0
  REGISTER_ATTRIBUTE (TIME_ACCESS_USEC);
245
0
  REGISTER_ATTRIBUTE (TIME_CHANGED);
246
0
  REGISTER_ATTRIBUTE (TIME_CHANGED_USEC);
247
0
  REGISTER_ATTRIBUTE (TIME_CREATED);
248
0
  REGISTER_ATTRIBUTE (TIME_CREATED_USEC);
249
0
  REGISTER_ATTRIBUTE (TIME_MODIFIED_NSEC);
250
0
  REGISTER_ATTRIBUTE (TIME_ACCESS_NSEC);
251
0
  REGISTER_ATTRIBUTE (TIME_CREATED_NSEC);
252
0
  REGISTER_ATTRIBUTE (TIME_CHANGED_NSEC);
253
0
  REGISTER_ATTRIBUTE (UNIX_DEVICE);
254
0
  REGISTER_ATTRIBUTE (UNIX_INODE);
255
0
  REGISTER_ATTRIBUTE (UNIX_MODE);
256
0
  REGISTER_ATTRIBUTE (UNIX_NLINK);
257
0
  REGISTER_ATTRIBUTE (UNIX_UID);
258
0
  REGISTER_ATTRIBUTE (UNIX_GID);
259
0
  REGISTER_ATTRIBUTE (UNIX_RDEV);
260
0
  REGISTER_ATTRIBUTE (UNIX_BLOCK_SIZE);
261
0
  REGISTER_ATTRIBUTE (UNIX_BLOCKS);
262
0
  REGISTER_ATTRIBUTE (UNIX_IS_MOUNTPOINT);
263
0
  REGISTER_ATTRIBUTE (DOS_IS_ARCHIVE);
264
0
  REGISTER_ATTRIBUTE (DOS_IS_SYSTEM);
265
0
  REGISTER_ATTRIBUTE (DOS_IS_MOUNTPOINT);
266
0
  REGISTER_ATTRIBUTE (DOS_REPARSE_POINT_TAG);
267
0
  REGISTER_ATTRIBUTE (OWNER_USER);
268
0
  REGISTER_ATTRIBUTE (OWNER_USER_REAL);
269
0
  REGISTER_ATTRIBUTE (OWNER_GROUP);
270
0
  REGISTER_ATTRIBUTE (THUMBNAIL_PATH);
271
0
  REGISTER_ATTRIBUTE (THUMBNAILING_FAILED);
272
0
  REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID);
273
0
  REGISTER_ATTRIBUTE (THUMBNAIL_PATH_NORMAL);
274
0
  REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_NORMAL);
275
0
  REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_NORMAL);
276
0
  REGISTER_ATTRIBUTE (THUMBNAIL_PATH_LARGE);
277
0
  REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_LARGE);
278
0
  REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_LARGE);
279
0
  REGISTER_ATTRIBUTE (THUMBNAIL_PATH_XLARGE);
280
0
  REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_XLARGE);
281
0
  REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_XLARGE);
282
0
  REGISTER_ATTRIBUTE (THUMBNAIL_PATH_XXLARGE);
283
0
  REGISTER_ATTRIBUTE (THUMBNAILING_FAILED_XXLARGE);
284
0
  REGISTER_ATTRIBUTE (THUMBNAIL_IS_VALID_XXLARGE);
285
0
  REGISTER_ATTRIBUTE (PREVIEW_ICON);
286
0
  REGISTER_ATTRIBUTE (FILESYSTEM_SIZE);
287
0
  REGISTER_ATTRIBUTE (FILESYSTEM_FREE);
288
0
  REGISTER_ATTRIBUTE (FILESYSTEM_TYPE);
289
0
  REGISTER_ATTRIBUTE (FILESYSTEM_READONLY);
290
0
  REGISTER_ATTRIBUTE (FILESYSTEM_USE_PREVIEW);
291
0
  REGISTER_ATTRIBUTE (GVFS_BACKEND);
292
0
  REGISTER_ATTRIBUTE (SELINUX_CONTEXT);
293
0
  REGISTER_ATTRIBUTE (TRASH_ITEM_COUNT);
294
0
  REGISTER_ATTRIBUTE (TRASH_ORIG_PATH);
295
0
  REGISTER_ATTRIBUTE (TRASH_DELETION_DATE);
296
297
0
#undef REGISTER_ATTRIBUTE
298
0
}
299
300
static guint32
301
lookup_namespace (const char *namespace)
302
0
{
303
0
  NSInfo *ns_info;
304
0
  guint32 id;
305
306
0
  G_LOCK (attribute_hash);
307
308
0
  ensure_attribute_hash ();
309
310
0
  ns_info = _lookup_namespace (namespace);
311
0
  id = 0;
312
0
  if (ns_info)
313
0
    id = ns_info->id;
314
315
0
  G_UNLOCK (attribute_hash);
316
317
0
  return id;
318
0
}
319
320
static char *
321
get_attribute_for_id (int attribute)
322
0
{
323
0
  char *s;
324
0
  G_LOCK (attribute_hash);
325
0
  s = global_attributes[GET_NS (attribute)][GET_ID (attribute)];
326
0
  G_UNLOCK (attribute_hash);
327
0
  return s;
328
0
}
329
330
static guint32
331
lookup_attribute (const char *attribute)
332
0
{
333
0
  guint32 attr_id;
334
335
0
  G_LOCK (attribute_hash);
336
0
  ensure_attribute_hash ();
337
338
0
  attr_id = _lookup_attribute (attribute);
339
340
0
  G_UNLOCK (attribute_hash);
341
342
0
  return attr_id;
343
0
}
344
345
static void
346
g_file_info_finalize (GObject *object)
347
0
{
348
0
  GFileInfo *info;
349
0
  guint i;
350
0
  GFileAttribute *attrs;
351
352
0
  info = G_FILE_INFO (object);
353
354
0
  attrs = (GFileAttribute *)info->attributes->data;
355
0
  for (i = 0; i < info->attributes->len; i++)
356
0
    _g_file_attribute_value_clear (&attrs[i].value);
357
0
  g_array_free (info->attributes, TRUE);
358
359
0
  if (info->mask != NO_ATTRIBUTE_MASK)
360
0
    g_file_attribute_matcher_unref (info->mask);
361
362
0
  G_OBJECT_CLASS (g_file_info_parent_class)->finalize (object);
363
0
}
364
365
static void
366
g_file_info_class_init (GFileInfoClass *klass)
367
0
{
368
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
369
370
0
  gobject_class->finalize = g_file_info_finalize;
371
0
}
372
373
static void
374
g_file_info_init (GFileInfo *info)
375
0
{
376
0
  info->mask = NO_ATTRIBUTE_MASK;
377
0
  info->attributes = g_array_new (FALSE, FALSE,
378
0
          sizeof (GFileAttribute));
379
0
}
380
381
/**
382
 * g_file_info_new:
383
 *
384
 * Creates a new file info structure.
385
 *
386
 * Returns: a #GFileInfo.
387
 **/
388
GFileInfo *
389
g_file_info_new (void)
390
0
{
391
0
  return g_object_new (G_TYPE_FILE_INFO, NULL);
392
0
}
393
394
/**
395
 * g_file_info_copy_into:
396
 * @src_info: source to copy attributes from.
397
 * @dest_info: destination to copy attributes to.
398
 *
399
 * First clears all of the [GFileAttribute][gio-GFileAttribute] of @dest_info,
400
 * and then copies all of the file attributes from @src_info to @dest_info.
401
 **/
402
void
403
g_file_info_copy_into (GFileInfo *src_info,
404
                       GFileInfo *dest_info)
405
0
{
406
0
  GFileAttribute *source, *dest;
407
0
  guint i;
408
409
0
  g_return_if_fail (G_IS_FILE_INFO (src_info));
410
0
  g_return_if_fail (G_IS_FILE_INFO (dest_info));
411
412
0
  dest = (GFileAttribute *)dest_info->attributes->data;
413
0
  for (i = 0; i < dest_info->attributes->len; i++)
414
0
    _g_file_attribute_value_clear (&dest[i].value);
415
416
0
  g_array_set_size (dest_info->attributes,
417
0
        src_info->attributes->len);
418
419
0
  source = (GFileAttribute *)src_info->attributes->data;
420
0
  dest = (GFileAttribute *)dest_info->attributes->data;
421
422
0
  for (i = 0; i < src_info->attributes->len; i++)
423
0
    {
424
0
      dest[i].attribute = source[i].attribute;
425
0
      dest[i].value.type = G_FILE_ATTRIBUTE_TYPE_INVALID;
426
0
      _g_file_attribute_value_set (&dest[i].value, &source[i].value);
427
0
    }
428
429
0
  if (dest_info->mask != NO_ATTRIBUTE_MASK)
430
0
    g_file_attribute_matcher_unref (dest_info->mask);
431
432
0
  if (src_info->mask == NO_ATTRIBUTE_MASK)
433
0
    dest_info->mask = NO_ATTRIBUTE_MASK;
434
0
  else
435
0
    dest_info->mask = g_file_attribute_matcher_ref (src_info->mask);
436
0
}
437
438
/**
439
 * g_file_info_dup:
440
 * @other: a #GFileInfo.
441
 *
442
 * Duplicates a file info structure.
443
 *
444
 * Returns: (transfer full): a duplicate #GFileInfo of @other.
445
 **/
446
GFileInfo *
447
g_file_info_dup (GFileInfo *other)
448
0
{
449
0
  GFileInfo *new;
450
451
0
  g_return_val_if_fail (G_IS_FILE_INFO (other), NULL);
452
453
0
  new = g_file_info_new ();
454
0
  g_file_info_copy_into (other, new);
455
0
  return new;
456
0
}
457
458
/**
459
 * g_file_info_set_attribute_mask:
460
 * @info: a #GFileInfo.
461
 * @mask: a #GFileAttributeMatcher.
462
 *
463
 * Sets @mask on @info to match specific attribute types.
464
 **/
465
void
466
g_file_info_set_attribute_mask (GFileInfo             *info,
467
        GFileAttributeMatcher *mask)
468
0
{
469
0
  GFileAttribute *attr;
470
0
  guint i;
471
472
0
  g_return_if_fail (G_IS_FILE_INFO (info));
473
474
0
  if (mask != info->mask)
475
0
    {
476
0
      if (info->mask != NO_ATTRIBUTE_MASK)
477
0
  g_file_attribute_matcher_unref (info->mask);
478
0
      info->mask = g_file_attribute_matcher_ref (mask);
479
480
      /* Remove non-matching attributes */
481
0
      for (i = 0; i < info->attributes->len; i++)
482
0
  {
483
0
    attr = &g_array_index (info->attributes, GFileAttribute, i);
484
0
    if (!_g_file_attribute_matcher_matches_id (mask,
485
0
                attr->attribute))
486
0
      {
487
0
        _g_file_attribute_value_clear (&attr->value);
488
0
        g_array_remove_index (info->attributes, i);
489
0
        i--;
490
0
      }
491
0
  }
492
0
    }
493
0
}
494
495
/**
496
 * g_file_info_unset_attribute_mask:
497
 * @info: #GFileInfo.
498
 *
499
 * Unsets a mask set by g_file_info_set_attribute_mask(), if one
500
 * is set.
501
 **/
502
void
503
g_file_info_unset_attribute_mask (GFileInfo *info)
504
0
{
505
0
  g_return_if_fail (G_IS_FILE_INFO (info));
506
507
0
  if (info->mask != NO_ATTRIBUTE_MASK)
508
0
    g_file_attribute_matcher_unref (info->mask);
509
0
  info->mask = NO_ATTRIBUTE_MASK;
510
0
}
511
512
/**
513
 * g_file_info_clear_status:
514
 * @info: a #GFileInfo.
515
 *
516
 * Clears the status information from @info.
517
 **/
518
void
519
g_file_info_clear_status (GFileInfo  *info)
520
0
{
521
0
  GFileAttribute *attrs;
522
0
  guint i;
523
524
0
  g_return_if_fail (G_IS_FILE_INFO (info));
525
526
0
  attrs = (GFileAttribute *)info->attributes->data;
527
0
  for (i = 0; i < info->attributes->len; i++)
528
0
    attrs[i].value.status = G_FILE_ATTRIBUTE_STATUS_UNSET;
529
0
}
530
531
static int
532
g_file_info_find_place (GFileInfo  *info,
533
      guint32     attribute)
534
0
{
535
0
  int min, max, med;
536
0
  GFileAttribute *attrs;
537
  /* Binary search for the place where attribute would be, if it's
538
     in the array */
539
540
0
  min = 0;
541
0
  max = info->attributes->len;
542
543
0
  attrs = (GFileAttribute *)info->attributes->data;
544
545
0
  while (min < max)
546
0
    {
547
0
      med = min + (max - min) / 2;
548
0
      if (attrs[med].attribute == attribute)
549
0
  {
550
0
    min = med;
551
0
    break;
552
0
  }
553
0
      else if (attrs[med].attribute < attribute)
554
0
  min = med + 1;
555
0
      else /* attrs[med].attribute > attribute */
556
0
  max = med;
557
0
    }
558
559
0
  return min;
560
0
}
561
562
static GFileAttributeValue *
563
g_file_info_find_value (GFileInfo *info,
564
      guint32    attr_id)
565
0
{
566
0
  GFileAttribute *attrs;
567
0
  guint i;
568
569
0
  i = g_file_info_find_place (info, attr_id);
570
0
  attrs = (GFileAttribute *)info->attributes->data;
571
0
  if (i < info->attributes->len &&
572
0
      attrs[i].attribute == attr_id)
573
0
    return &attrs[i].value;
574
575
0
  return NULL;
576
0
}
577
578
static GFileAttributeValue *
579
g_file_info_find_value_by_name (GFileInfo  *info,
580
        const char *attribute)
581
0
{
582
0
  guint32 attr_id;
583
584
0
  attr_id = lookup_attribute (attribute);
585
0
  return g_file_info_find_value (info, attr_id);
586
0
}
587
588
/**
589
 * g_file_info_has_attribute:
590
 * @info: a #GFileInfo.
591
 * @attribute: a file attribute key.
592
 *
593
 * Checks if a file info structure has an attribute named @attribute.
594
 *
595
 * Returns: %TRUE if @info has an attribute named @attribute,
596
 *     %FALSE otherwise.
597
 **/
598
gboolean
599
g_file_info_has_attribute (GFileInfo  *info,
600
         const char *attribute)
601
0
{
602
0
  GFileAttributeValue *value;
603
604
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
605
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
606
607
0
  value = g_file_info_find_value_by_name (info, attribute);
608
0
  return value != NULL;
609
0
}
610
611
/**
612
 * g_file_info_has_namespace:
613
 * @info: a #GFileInfo.
614
 * @name_space: a file attribute namespace.
615
 *
616
 * Checks if a file info structure has an attribute in the
617
 * specified @name_space.
618
 *
619
 * Returns: %TRUE if @info has an attribute in @name_space,
620
 *     %FALSE otherwise.
621
 *
622
 * Since: 2.22
623
 **/
624
gboolean
625
g_file_info_has_namespace (GFileInfo  *info,
626
         const char *name_space)
627
0
{
628
0
  GFileAttribute *attrs;
629
0
  guint32 ns_id;
630
0
  guint i;
631
632
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
633
0
  g_return_val_if_fail (name_space != NULL, FALSE);
634
635
0
  ns_id = lookup_namespace (name_space);
636
637
0
  attrs = (GFileAttribute *)info->attributes->data;
638
0
  for (i = 0; i < info->attributes->len; i++)
639
0
    {
640
0
      if (GET_NS (attrs[i].attribute) == ns_id)
641
0
  return TRUE;
642
0
    }
643
644
0
  return FALSE;
645
0
}
646
647
/**
648
 * g_file_info_list_attributes:
649
 * @info: a #GFileInfo.
650
 * @name_space: (nullable): a file attribute key's namespace, or %NULL to list
651
 *   all attributes.
652
 *
653
 * Lists the file info structure's attributes.
654
 *
655
 * Returns: (nullable) (array zero-terminated=1) (transfer full): a
656
 * null-terminated array of strings of all of the possible attribute
657
 * types for the given @name_space, or %NULL on error.
658
 **/
659
char **
660
g_file_info_list_attributes (GFileInfo  *info,
661
           const char *name_space)
662
0
{
663
0
  GPtrArray *names;
664
0
  GFileAttribute *attrs;
665
0
  guint32 attribute;
666
0
  guint32 ns_id = (name_space) ? lookup_namespace (name_space) : 0;
667
0
  guint i;
668
669
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
670
671
0
  names = g_ptr_array_new ();
672
0
  attrs = (GFileAttribute *)info->attributes->data;
673
0
  for (i = 0; i < info->attributes->len; i++)
674
0
    {
675
0
      attribute = attrs[i].attribute;
676
0
      if (ns_id == 0 || GET_NS (attribute) == ns_id)
677
0
        g_ptr_array_add (names, g_strdup (get_attribute_for_id (attribute)));
678
0
    }
679
680
  /* NULL terminate */
681
0
  g_ptr_array_add (names, NULL);
682
683
0
  return (char **)g_ptr_array_free (names, FALSE);
684
0
}
685
686
/**
687
 * g_file_info_get_attribute_type:
688
 * @info: a #GFileInfo.
689
 * @attribute: a file attribute key.
690
 *
691
 * Gets the attribute type for an attribute key.
692
 *
693
 * Returns: a #GFileAttributeType for the given @attribute, or
694
 * %G_FILE_ATTRIBUTE_TYPE_INVALID if the key is not set.
695
 **/
696
GFileAttributeType
697
g_file_info_get_attribute_type (GFileInfo  *info,
698
        const char *attribute)
699
0
{
700
0
  GFileAttributeValue *value;
701
702
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_ATTRIBUTE_TYPE_INVALID);
703
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', G_FILE_ATTRIBUTE_TYPE_INVALID);
704
705
0
  value = g_file_info_find_value_by_name (info, attribute);
706
0
  if (value)
707
0
    return value->type;
708
0
  else
709
0
    return G_FILE_ATTRIBUTE_TYPE_INVALID;
710
0
}
711
712
static void
713
g_file_info_remove_value (GFileInfo *info,
714
        guint32 attr_id)
715
0
{
716
0
  GFileAttribute *attrs;
717
0
  guint i;
718
719
0
  if (info->mask != NO_ATTRIBUTE_MASK &&
720
0
      !_g_file_attribute_matcher_matches_id (info->mask, attr_id))
721
0
    return;
722
723
0
  i = g_file_info_find_place (info, attr_id);
724
725
0
  attrs = (GFileAttribute *)info->attributes->data;
726
0
  if (i < info->attributes->len &&
727
0
      attrs[i].attribute == attr_id)
728
0
    {
729
0
      _g_file_attribute_value_clear (&attrs[i].value);
730
0
      g_array_remove_index (info->attributes, i);
731
0
    }
732
0
}
733
734
/**
735
 * g_file_info_remove_attribute:
736
 * @info: a #GFileInfo.
737
 * @attribute: a file attribute key.
738
 *
739
 * Removes all cases of @attribute from @info if it exists.
740
 **/
741
void
742
g_file_info_remove_attribute (GFileInfo  *info,
743
            const char *attribute)
744
0
{
745
0
  guint32 attr_id;
746
747
0
  g_return_if_fail (G_IS_FILE_INFO (info));
748
0
  g_return_if_fail (attribute != NULL && *attribute != '\0');
749
750
0
  attr_id = lookup_attribute (attribute);
751
752
0
  g_file_info_remove_value (info, attr_id);
753
0
}
754
755
/**
756
 * g_file_info_get_attribute_data:
757
 * @info: a #GFileInfo
758
 * @attribute: a file attribute key
759
 * @type: (out) (optional): return location for the attribute type, or %NULL
760
 * @value_pp: (out) (optional) (not nullable): return location for the
761
 *    attribute value, or %NULL; the attribute value will not be %NULL
762
 * @status: (out) (optional): return location for the attribute status, or %NULL
763
 *
764
 * Gets the attribute type, value and status for an attribute key.
765
 *
766
 * Returns: (transfer none): %TRUE if @info has an attribute named @attribute,
767
 *      %FALSE otherwise.
768
 */
769
gboolean
770
g_file_info_get_attribute_data (GFileInfo            *info,
771
        const char           *attribute,
772
        GFileAttributeType   *type,
773
        gpointer             *value_pp,
774
        GFileAttributeStatus *status)
775
0
{
776
0
  GFileAttributeValue *value;
777
778
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
779
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
780
781
0
  value = g_file_info_find_value_by_name (info, attribute);
782
0
  if (value == NULL)
783
0
    return FALSE;
784
785
0
  if (status)
786
0
    *status = value->status;
787
788
0
  if (type)
789
0
    *type = value->type;
790
791
0
  if (value_pp)
792
0
    *value_pp = _g_file_attribute_value_peek_as_pointer (value);
793
794
0
  return TRUE;
795
0
}
796
797
/**
798
 * g_file_info_get_attribute_status:
799
 * @info: a #GFileInfo
800
 * @attribute: a file attribute key
801
 *
802
 * Gets the attribute status for an attribute key.
803
 *
804
 * Returns: a #GFileAttributeStatus for the given @attribute, or
805
 *    %G_FILE_ATTRIBUTE_STATUS_UNSET if the key is invalid.
806
 *
807
 */
808
GFileAttributeStatus
809
g_file_info_get_attribute_status (GFileInfo  *info,
810
          const char *attribute)
811
0
{
812
0
  GFileAttributeValue *val;
813
814
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
815
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
816
817
0
  val = g_file_info_find_value_by_name (info, attribute);
818
0
  if (val)
819
0
    return val->status;
820
821
0
  return G_FILE_ATTRIBUTE_STATUS_UNSET;
822
0
}
823
824
/**
825
 * g_file_info_set_attribute_status:
826
 * @info: a #GFileInfo
827
 * @attribute: a file attribute key
828
 * @status: a #GFileAttributeStatus
829
 *
830
 * Sets the attribute status for an attribute key. This is only
831
 * needed by external code that implement g_file_set_attributes_from_info()
832
 * or similar functions.
833
 *
834
 * The attribute must exist in @info for this to work. Otherwise %FALSE
835
 * is returned and @info is unchanged.
836
 *
837
 * Returns: %TRUE if the status was changed, %FALSE if the key was not set.
838
 *
839
 * Since: 2.22
840
 */
841
gboolean
842
g_file_info_set_attribute_status (GFileInfo  *info,
843
          const char *attribute,
844
          GFileAttributeStatus status)
845
0
{
846
0
  GFileAttributeValue *val;
847
848
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
849
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
850
851
0
  val = g_file_info_find_value_by_name (info, attribute);
852
0
  if (val)
853
0
    {
854
0
      val->status = status;
855
0
      return TRUE;
856
0
    }
857
858
0
  return FALSE;
859
0
}
860
861
GFileAttributeValue *
862
_g_file_info_get_attribute_value (GFileInfo  *info,
863
          const char *attribute)
864
865
0
{
866
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
867
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
868
869
0
  return g_file_info_find_value_by_name (info, attribute);
870
0
}
871
872
/**
873
 * g_file_info_get_attribute_as_string:
874
 * @info: a #GFileInfo.
875
 * @attribute: a file attribute key.
876
 *
877
 * Gets the value of an attribute, formatted as a string.
878
 * This escapes things as needed to make the string valid
879
 * UTF-8.
880
 *
881
 * Returns: (nullable): a UTF-8 string associated with the given @attribute, or
882
 *    %NULL if the attribute wasn’t set.
883
 *    When you're done with the string it must be freed with g_free().
884
 **/
885
char *
886
g_file_info_get_attribute_as_string (GFileInfo  *info,
887
             const char *attribute)
888
0
{
889
0
  GFileAttributeValue *val;
890
0
  val = _g_file_info_get_attribute_value (info, attribute);
891
0
  if (val)
892
0
    return _g_file_attribute_value_as_string (val);
893
0
  return NULL;
894
0
}
895
896
897
/**
898
 * g_file_info_get_attribute_object:
899
 * @info: a #GFileInfo.
900
 * @attribute: a file attribute key.
901
 *
902
 * Gets the value of a #GObject attribute. If the attribute does
903
 * not contain a #GObject, %NULL will be returned.
904
 *
905
 * Returns: (transfer none) (nullable): a #GObject associated with the given @attribute,
906
 * or %NULL otherwise.
907
 **/
908
GObject *
909
g_file_info_get_attribute_object (GFileInfo  *info,
910
          const char *attribute)
911
0
{
912
0
  GFileAttributeValue *value;
913
914
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
915
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
916
917
0
  value = g_file_info_find_value_by_name (info, attribute);
918
0
  return _g_file_attribute_value_get_object (value);
919
0
}
920
921
/**
922
 * g_file_info_get_attribute_string:
923
 * @info: a #GFileInfo.
924
 * @attribute: a file attribute key.
925
 *
926
 * Gets the value of a string attribute. If the attribute does
927
 * not contain a string, %NULL will be returned.
928
 *
929
 * Returns: (nullable): the contents of the @attribute value as a UTF-8 string,
930
 * or %NULL otherwise.
931
 **/
932
const char *
933
g_file_info_get_attribute_string (GFileInfo  *info,
934
          const char *attribute)
935
0
{
936
0
  GFileAttributeValue *value;
937
938
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
939
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
940
941
0
  value = g_file_info_find_value_by_name (info, attribute);
942
0
  return _g_file_attribute_value_get_string (value);
943
0
}
944
945
/**
946
 * g_file_info_get_attribute_byte_string:
947
 * @info: a #GFileInfo.
948
 * @attribute: a file attribute key.
949
 *
950
 * Gets the value of a byte string attribute. If the attribute does
951
 * not contain a byte string, %NULL will be returned.
952
 *
953
 * Returns: (nullable): the contents of the @attribute value as a byte string, or
954
 * %NULL otherwise.
955
 **/
956
const char *
957
g_file_info_get_attribute_byte_string (GFileInfo  *info,
958
               const char *attribute)
959
0
{
960
0
  GFileAttributeValue *value;
961
962
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
963
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
964
965
0
  value = g_file_info_find_value_by_name (info, attribute);
966
0
  return _g_file_attribute_value_get_byte_string (value);
967
0
}
968
969
/**
970
 * g_file_info_get_attribute_file_path:
971
 * @info: a #GFileInfo.
972
 * @attribute: a file attribute key.
973
 *
974
 * Gets the value of a byte string attribute as a file path.
975
 *
976
 * If the attribute does not contain a byte string, `NULL` will be returned.
977
 *
978
 * This function is meant to be used by language bindings that have specific
979
 * handling for Unix paths.
980
 *
981
 * Returns: (type filename) (nullable): the contents of the @attribute value as
982
 * a file path, or %NULL otherwise.
983
 *
984
 * Since: 2.78
985
 **/
986
const char *
987
g_file_info_get_attribute_file_path (GFileInfo  *info,
988
                                     const char *attribute)
989
0
{
990
0
  return g_file_info_get_attribute_byte_string (info, attribute);
991
0
}
992
993
/**
994
 * g_file_info_get_attribute_stringv:
995
 * @info: a #GFileInfo.
996
 * @attribute: a file attribute key.
997
 *
998
 * Gets the value of a stringv attribute. If the attribute does
999
 * not contain a stringv, %NULL will be returned.
1000
 *
1001
 * Returns: (transfer none) (nullable): the contents of the @attribute value as a stringv,
1002
 * or %NULL otherwise. Do not free. These returned strings are UTF-8.
1003
 *
1004
 * Since: 2.22
1005
 **/
1006
char **
1007
g_file_info_get_attribute_stringv (GFileInfo  *info,
1008
           const char *attribute)
1009
0
{
1010
0
  GFileAttributeValue *value;
1011
1012
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1013
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', NULL);
1014
1015
0
  value = g_file_info_find_value_by_name (info, attribute);
1016
0
  return _g_file_attribute_value_get_stringv (value);
1017
0
}
1018
1019
/**
1020
 * g_file_info_get_attribute_boolean:
1021
 * @info: a #GFileInfo.
1022
 * @attribute: a file attribute key.
1023
 *
1024
 * Gets the value of a boolean attribute. If the attribute does not
1025
 * contain a boolean value, %FALSE will be returned.
1026
 *
1027
 * Returns: the boolean value contained within the attribute.
1028
 **/
1029
gboolean
1030
g_file_info_get_attribute_boolean (GFileInfo  *info,
1031
           const char *attribute)
1032
0
{
1033
0
  GFileAttributeValue *value;
1034
1035
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1036
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
1037
1038
0
  value = g_file_info_find_value_by_name (info, attribute);
1039
0
  return _g_file_attribute_value_get_boolean (value);
1040
0
}
1041
1042
/**
1043
 * g_file_info_get_attribute_uint32:
1044
 * @info: a #GFileInfo.
1045
 * @attribute: a file attribute key.
1046
 *
1047
 * Gets an unsigned 32-bit integer contained within the attribute. If the
1048
 * attribute does not contain an unsigned 32-bit integer, or is invalid,
1049
 * 0 will be returned.
1050
 *
1051
 * Returns: an unsigned 32-bit integer from the attribute.
1052
 **/
1053
guint32
1054
g_file_info_get_attribute_uint32 (GFileInfo  *info,
1055
          const char *attribute)
1056
0
{
1057
0
  GFileAttributeValue *value;
1058
1059
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1060
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
1061
1062
0
  value = g_file_info_find_value_by_name (info, attribute);
1063
0
  return _g_file_attribute_value_get_uint32 (value);
1064
0
}
1065
1066
/**
1067
 * g_file_info_get_attribute_int32:
1068
 * @info: a #GFileInfo.
1069
 * @attribute: a file attribute key.
1070
 *
1071
 * Gets a signed 32-bit integer contained within the attribute. If the
1072
 * attribute does not contain a signed 32-bit integer, or is invalid,
1073
 * 0 will be returned.
1074
 *
1075
 * Returns: a signed 32-bit integer from the attribute.
1076
 **/
1077
gint32
1078
g_file_info_get_attribute_int32 (GFileInfo  *info,
1079
         const char *attribute)
1080
0
{
1081
0
  GFileAttributeValue *value;
1082
1083
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1084
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
1085
1086
0
  value = g_file_info_find_value_by_name (info, attribute);
1087
0
  return _g_file_attribute_value_get_int32 (value);
1088
0
}
1089
1090
/**
1091
 * g_file_info_get_attribute_uint64:
1092
 * @info: a #GFileInfo.
1093
 * @attribute: a file attribute key.
1094
 *
1095
 * Gets a unsigned 64-bit integer contained within the attribute. If the
1096
 * attribute does not contain an unsigned 64-bit integer, or is invalid,
1097
 * 0 will be returned.
1098
 *
1099
 * Returns: a unsigned 64-bit integer from the attribute.
1100
 **/
1101
guint64
1102
g_file_info_get_attribute_uint64 (GFileInfo  *info,
1103
          const char *attribute)
1104
0
{
1105
0
  GFileAttributeValue *value;
1106
1107
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1108
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
1109
1110
0
  value = g_file_info_find_value_by_name (info, attribute);
1111
0
  return _g_file_attribute_value_get_uint64 (value);
1112
0
}
1113
1114
/**
1115
 * g_file_info_get_attribute_int64:
1116
 * @info: a #GFileInfo.
1117
 * @attribute: a file attribute key.
1118
 *
1119
 * Gets a signed 64-bit integer contained within the attribute. If the
1120
 * attribute does not contain a signed 64-bit integer, or is invalid,
1121
 * 0 will be returned.
1122
 *
1123
 * Returns: a signed 64-bit integer from the attribute.
1124
 **/
1125
gint64
1126
g_file_info_get_attribute_int64  (GFileInfo  *info,
1127
          const char *attribute)
1128
0
{
1129
0
  GFileAttributeValue *value;
1130
1131
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
1132
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', 0);
1133
1134
0
  value = g_file_info_find_value_by_name (info, attribute);
1135
0
  return _g_file_attribute_value_get_int64 (value);
1136
0
}
1137
1138
static GFileAttributeValue *
1139
g_file_info_create_value (GFileInfo *info,
1140
        guint32 attr_id)
1141
0
{
1142
0
  GFileAttribute *attrs;
1143
0
  guint i;
1144
1145
0
  if (info->mask != NO_ATTRIBUTE_MASK &&
1146
0
      !_g_file_attribute_matcher_matches_id (info->mask, attr_id))
1147
0
    return NULL;
1148
1149
0
  i = g_file_info_find_place (info, attr_id);
1150
1151
0
  attrs = (GFileAttribute *)info->attributes->data;
1152
0
  if (i < info->attributes->len &&
1153
0
      attrs[i].attribute == attr_id)
1154
0
    return &attrs[i].value;
1155
0
  else
1156
0
    {
1157
0
      GFileAttribute attr = { 0 };
1158
0
      attr.attribute = attr_id;
1159
0
      g_array_insert_val (info->attributes, i, attr);
1160
1161
0
      attrs = (GFileAttribute *)info->attributes->data;
1162
0
      return &attrs[i].value;
1163
0
    }
1164
0
}
1165
1166
void
1167
_g_file_info_set_attribute_by_id (GFileInfo                 *info,
1168
                                  guint32                    attribute,
1169
                                  GFileAttributeType         type,
1170
                                  gpointer                   value_p)
1171
0
{
1172
0
  GFileAttributeValue *value;
1173
1174
0
  value = g_file_info_create_value (info, attribute);
1175
1176
0
  if (value)
1177
0
    _g_file_attribute_value_set_from_pointer (value, type, value_p, TRUE);
1178
0
}
1179
1180
/**
1181
 * g_file_info_set_attribute:
1182
 * @info: a #GFileInfo.
1183
 * @attribute: a file attribute key.
1184
 * @type: a #GFileAttributeType
1185
 * @value_p: (not nullable): pointer to the value
1186
 *
1187
 * Sets the @attribute to contain the given value, if possible. To unset the
1188
 * attribute, use %G_FILE_ATTRIBUTE_TYPE_INVALID for @type.
1189
 **/
1190
void
1191
g_file_info_set_attribute (GFileInfo                 *info,
1192
         const char                *attribute,
1193
         GFileAttributeType         type,
1194
         gpointer                   value_p)
1195
0
{
1196
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1197
0
  g_return_if_fail (attribute != NULL && *attribute != '\0');
1198
1199
0
  _g_file_info_set_attribute_by_id (info, lookup_attribute (attribute), type, value_p);
1200
0
}
1201
1202
void
1203
_g_file_info_set_attribute_object_by_id (GFileInfo *info,
1204
                                         guint32    attribute,
1205
                 GObject   *attr_value)
1206
0
{
1207
0
  GFileAttributeValue *value;
1208
1209
0
  value = g_file_info_create_value (info, attribute);
1210
0
  if (value)
1211
0
    _g_file_attribute_value_set_object (value, attr_value);
1212
0
}
1213
1214
/**
1215
 * g_file_info_set_attribute_object:
1216
 * @info: a #GFileInfo.
1217
 * @attribute: a file attribute key.
1218
 * @attr_value: a #GObject.
1219
 *
1220
 * Sets the @attribute to contain the given @attr_value,
1221
 * if possible.
1222
 **/
1223
void
1224
g_file_info_set_attribute_object (GFileInfo  *info,
1225
          const char *attribute,
1226
          GObject    *attr_value)
1227
0
{
1228
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1229
0
  g_return_if_fail (attribute != NULL && *attribute != '\0');
1230
0
  g_return_if_fail (G_IS_OBJECT (attr_value));
1231
1232
0
  _g_file_info_set_attribute_object_by_id (info,
1233
0
                                           lookup_attribute (attribute),
1234
0
                                           attr_value);
1235
0
}
1236
1237
void
1238
_g_file_info_set_attribute_stringv_by_id (GFileInfo *info,
1239
                                          guint32    attribute,
1240
                  char     **attr_value)
1241
0
{
1242
0
  GFileAttributeValue *value;
1243
1244
0
  value = g_file_info_create_value (info, attribute);
1245
0
  if (value)
1246
0
    _g_file_attribute_value_set_stringv (value, attr_value);
1247
0
}
1248
1249
/**
1250
 * g_file_info_set_attribute_stringv:
1251
 * @info: a #GFileInfo.
1252
 * @attribute: a file attribute key
1253
 * @attr_value: (array zero-terminated=1) (element-type utf8): a %NULL
1254
 *   terminated array of UTF-8 strings.
1255
 *
1256
 * Sets the @attribute to contain the given @attr_value,
1257
 * if possible.
1258
 *
1259
 * Sinze: 2.22
1260
 **/
1261
void
1262
g_file_info_set_attribute_stringv (GFileInfo  *info,
1263
           const char *attribute,
1264
           char      **attr_value)
1265
0
{
1266
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1267
0
  g_return_if_fail (attribute != NULL && *attribute != '\0');
1268
0
  g_return_if_fail (attr_value != NULL);
1269
1270
0
  _g_file_info_set_attribute_stringv_by_id (info,
1271
0
                                            lookup_attribute (attribute),
1272
0
                                            attr_value);
1273
0
}
1274
1275
void
1276
_g_file_info_set_attribute_string_by_id (GFileInfo  *info,
1277
                                         guint32     attribute,
1278
                 const char *attr_value)
1279
0
{
1280
0
  GFileAttributeValue *value;
1281
1282
0
  value = g_file_info_create_value (info, attribute);
1283
0
  if (value)
1284
0
    _g_file_attribute_value_set_string (value, attr_value);
1285
0
}
1286
1287
/**
1288
 * g_file_info_set_attribute_string:
1289
 * @info: a #GFileInfo.
1290
 * @attribute: a file attribute key.
1291
 * @attr_value: a UTF-8 string.
1292
 *
1293
 * Sets the @attribute to contain the given @attr_value,
1294
 * if possible.
1295
 **/
1296
void
1297
g_file_info_set_attribute_string (GFileInfo  *info,
1298
          const char *attribute,
1299
          const char *attr_value)
1300
0
{
1301
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1302
0
  g_return_if_fail (attribute != NULL && *attribute != '\0');
1303
0
  g_return_if_fail (attr_value != NULL);
1304
1305
0
  _g_file_info_set_attribute_string_by_id (info,
1306
0
                                           lookup_attribute (attribute),
1307
0
                                           attr_value);
1308
0
}
1309
1310
void
1311
_g_file_info_set_attribute_byte_string_by_id (GFileInfo  *info,
1312
                                              guint32     attribute,
1313
                      const char *attr_value)
1314
0
{
1315
0
  GFileAttributeValue *value;
1316
1317
0
  value = g_file_info_create_value (info, attribute);
1318
0
  if (value)
1319
0
    _g_file_attribute_value_set_byte_string (value, attr_value);
1320
0
}
1321
1322
/**
1323
 * g_file_info_set_attribute_byte_string:
1324
 * @info: a #GFileInfo.
1325
 * @attribute: a file attribute key.
1326
 * @attr_value: a byte string.
1327
 *
1328
 * Sets the @attribute to contain the given @attr_value,
1329
 * if possible.
1330
 **/
1331
void
1332
g_file_info_set_attribute_byte_string (GFileInfo  *info,
1333
               const char *attribute,
1334
               const char *attr_value)
1335
0
{
1336
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1337
0
  g_return_if_fail (attribute != NULL && *attribute != '\0');
1338
0
  g_return_if_fail (attr_value != NULL);
1339
1340
0
  _g_file_info_set_attribute_byte_string_by_id (info,
1341
0
                                                lookup_attribute (attribute),
1342
0
                                                attr_value);
1343
0
}
1344
1345
/**
1346
 * g_file_info_set_attribute_file_path:
1347
 * @info: a #GFileInfo.
1348
 * @attribute: a file attribute key.
1349
 * @attr_value: (type filename): a file path.
1350
 *
1351
 * Sets the @attribute to contain the given @attr_value,
1352
 * if possible.
1353
 *
1354
 * This function is meant to be used by language bindings that have specific
1355
 * handling for Unix paths.
1356
 *
1357
 * Since: 2.78
1358
 **/
1359
void
1360
g_file_info_set_attribute_file_path (GFileInfo  *info,
1361
                                     const char *attribute,
1362
                                     const char *attr_value)
1363
0
{
1364
0
  g_file_info_set_attribute_byte_string (info, attribute, attr_value);
1365
0
}
1366
1367
void
1368
_g_file_info_set_attribute_boolean_by_id (GFileInfo *info,
1369
                                          guint32    attribute,
1370
                  gboolean   attr_value)
1371
0
{
1372
0
  GFileAttributeValue *value;
1373
1374
0
  value = g_file_info_create_value (info, attribute);
1375
0
  if (value)
1376
0
    _g_file_attribute_value_set_boolean (value, attr_value);
1377
0
}
1378
1379
/**
1380
 * g_file_info_set_attribute_boolean:
1381
 * @info: a #GFileInfo.
1382
 * @attribute: a file attribute key.
1383
 * @attr_value: a boolean value.
1384
 *
1385
 * Sets the @attribute to contain the given @attr_value,
1386
 * if possible.
1387
 **/
1388
void
1389
g_file_info_set_attribute_boolean (GFileInfo  *info,
1390
           const char *attribute,
1391
           gboolean    attr_value)
1392
0
{
1393
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1394
0
  g_return_if_fail (attribute != NULL && *attribute != '\0');
1395
1396
0
  _g_file_info_set_attribute_boolean_by_id (info,
1397
0
                                            lookup_attribute (attribute),
1398
0
                                            attr_value);
1399
0
}
1400
1401
void
1402
_g_file_info_set_attribute_uint32_by_id (GFileInfo *info,
1403
                                         guint32    attribute,
1404
                 guint32    attr_value)
1405
0
{
1406
0
  GFileAttributeValue *value;
1407
1408
0
  value = g_file_info_create_value (info, attribute);
1409
0
  if (value)
1410
0
    _g_file_attribute_value_set_uint32 (value, attr_value);
1411
0
}
1412
1413
/**
1414
 * g_file_info_set_attribute_uint32:
1415
 * @info: a #GFileInfo.
1416
 * @attribute: a file attribute key.
1417
 * @attr_value: an unsigned 32-bit integer.
1418
 *
1419
 * Sets the @attribute to contain the given @attr_value,
1420
 * if possible.
1421
 **/
1422
void
1423
g_file_info_set_attribute_uint32 (GFileInfo  *info,
1424
          const char *attribute,
1425
          guint32     attr_value)
1426
0
{
1427
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1428
0
  g_return_if_fail (attribute != NULL && *attribute != '\0');
1429
1430
0
  _g_file_info_set_attribute_uint32_by_id (info,
1431
0
                                           lookup_attribute (attribute),
1432
0
                                           attr_value);
1433
0
}
1434
1435
void
1436
_g_file_info_set_attribute_int32_by_id (GFileInfo *info,
1437
                                        guint32    attribute,
1438
                gint32     attr_value)
1439
0
{
1440
0
  GFileAttributeValue *value;
1441
1442
0
  value = g_file_info_create_value (info, attribute);
1443
0
  if (value)
1444
0
    _g_file_attribute_value_set_int32 (value, attr_value);
1445
0
}
1446
1447
/**
1448
 * g_file_info_set_attribute_int32:
1449
 * @info: a #GFileInfo.
1450
 * @attribute: a file attribute key.
1451
 * @attr_value: a signed 32-bit integer
1452
 *
1453
 * Sets the @attribute to contain the given @attr_value,
1454
 * if possible.
1455
 **/
1456
void
1457
g_file_info_set_attribute_int32 (GFileInfo  *info,
1458
                                 const char *attribute,
1459
                                 gint32      attr_value)
1460
0
{
1461
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1462
0
  g_return_if_fail (attribute != NULL && *attribute != '\0');
1463
1464
0
  _g_file_info_set_attribute_int32_by_id (info,
1465
0
                                          lookup_attribute (attribute),
1466
0
                                          attr_value);
1467
0
}
1468
1469
void
1470
_g_file_info_set_attribute_uint64_by_id (GFileInfo *info,
1471
                                         guint32    attribute,
1472
                 guint64    attr_value)
1473
0
{
1474
0
  GFileAttributeValue *value;
1475
1476
0
  value = g_file_info_create_value (info, attribute);
1477
0
  if (value)
1478
0
    _g_file_attribute_value_set_uint64 (value, attr_value);
1479
0
}
1480
1481
/**
1482
 * g_file_info_set_attribute_uint64:
1483
 * @info: a #GFileInfo.
1484
 * @attribute: a file attribute key.
1485
 * @attr_value: an unsigned 64-bit integer.
1486
 *
1487
 * Sets the @attribute to contain the given @attr_value,
1488
 * if possible.
1489
 **/
1490
void
1491
g_file_info_set_attribute_uint64 (GFileInfo  *info,
1492
          const char *attribute,
1493
          guint64     attr_value)
1494
0
{
1495
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1496
0
  g_return_if_fail (attribute != NULL && *attribute != '\0');
1497
1498
0
  _g_file_info_set_attribute_uint64_by_id (info,
1499
0
                                           lookup_attribute (attribute),
1500
0
                                           attr_value);
1501
0
}
1502
1503
void
1504
_g_file_info_set_attribute_int64_by_id (GFileInfo *info,
1505
                                        guint32    attribute,
1506
                gint64     attr_value)
1507
0
{
1508
0
  GFileAttributeValue *value;
1509
1510
0
  value = g_file_info_create_value (info, attribute);
1511
0
  if (value)
1512
0
    _g_file_attribute_value_set_int64 (value, attr_value);
1513
0
}
1514
1515
/**
1516
 * g_file_info_set_attribute_int64:
1517
 * @info: a #GFileInfo.
1518
 * @attribute: attribute name to set.
1519
 * @attr_value: int64 value to set attribute to.
1520
 *
1521
 * Sets the @attribute to contain the given @attr_value,
1522
 * if possible.
1523
 *
1524
 **/
1525
void
1526
g_file_info_set_attribute_int64  (GFileInfo  *info,
1527
          const char *attribute,
1528
          gint64      attr_value)
1529
0
{
1530
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1531
0
  g_return_if_fail (attribute != NULL && *attribute != '\0');
1532
1533
0
  _g_file_info_set_attribute_int64_by_id (info,
1534
0
                                          lookup_attribute (attribute),
1535
0
                                          attr_value);
1536
0
}
1537
1538
/* Helper getters */
1539
#define get_required_attribute(value_ptr, info, attribute_name, error_value) \
1540
0
  G_STMT_START { \
1541
0
    static guint32 attr = 0; \
1542
0
\
1543
0
    if (attr == 0) \
1544
0
      attr = lookup_attribute (attribute_name); \
1545
0
\
1546
0
    *value_ptr = g_file_info_find_value (info, attr); \
1547
0
    if (G_UNLIKELY (*value_ptr == NULL)) \
1548
0
      { \
1549
0
        g_critical ("GFileInfo created without " attribute_name); \
1550
0
        g_return_val_if_reached (error_value); \
1551
0
      } \
1552
0
  } G_STMT_END
1553
1554
/**
1555
 * g_file_info_get_deletion_date:
1556
 * @info: a #GFileInfo.
1557
 *
1558
 * Returns the #GDateTime representing the deletion date of the file, as
1559
 * available in %G_FILE_ATTRIBUTE_TRASH_DELETION_DATE. If the
1560
 * %G_FILE_ATTRIBUTE_TRASH_DELETION_DATE attribute is unset, %NULL is returned.
1561
 *
1562
 * Returns: (nullable): a #GDateTime, or %NULL.
1563
 *
1564
 * Since: 2.36
1565
 **/
1566
GDateTime *
1567
g_file_info_get_deletion_date (GFileInfo *info)
1568
0
{
1569
0
  static guint32 attr = 0;
1570
0
  GFileAttributeValue *value;
1571
0
  const char *date_str;
1572
0
  GTimeZone *local_tz = NULL;
1573
0
  GDateTime *dt = NULL;
1574
1575
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1576
1577
0
  if (attr == 0)
1578
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_TRASH_DELETION_DATE);
1579
1580
0
  value = g_file_info_find_value (info, attr);
1581
0
  date_str = _g_file_attribute_value_get_string (value);
1582
0
  if (!date_str)
1583
0
    return NULL;
1584
1585
0
  local_tz = g_time_zone_new_local ();
1586
0
  dt = g_date_time_new_from_iso8601 (date_str, local_tz);
1587
0
  g_time_zone_unref (local_tz);
1588
1589
0
  return g_steal_pointer (&dt);
1590
0
}
1591
1592
/**
1593
 * g_file_info_get_file_type:
1594
 * @info: a #GFileInfo.
1595
 *
1596
 * Gets a file's type (whether it is a regular file, symlink, etc).
1597
 * This is different from the file's content type, see g_file_info_get_content_type().
1598
 *
1599
 * It is an error to call this if the #GFileInfo does not contain
1600
 * %G_FILE_ATTRIBUTE_STANDARD_TYPE.
1601
 *
1602
 * Returns: a #GFileType for the given file.
1603
 **/
1604
GFileType
1605
g_file_info_get_file_type (GFileInfo *info)
1606
0
{
1607
0
  GFileAttributeValue *value;
1608
1609
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), G_FILE_TYPE_UNKNOWN);
1610
1611
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_TYPE_UNKNOWN);
1612
0
  return (GFileType)_g_file_attribute_value_get_uint32 (value);
1613
0
}
1614
1615
/**
1616
 * g_file_info_get_is_hidden:
1617
 * @info: a #GFileInfo.
1618
 *
1619
 * Checks if a file is hidden.
1620
 *
1621
 * It is an error to call this if the #GFileInfo does not contain
1622
 * %G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN.
1623
 *
1624
 * Returns: %TRUE if the file is a hidden file, %FALSE otherwise.
1625
 **/
1626
gboolean
1627
g_file_info_get_is_hidden (GFileInfo *info)
1628
0
{
1629
0
  GFileAttributeValue *value;
1630
1631
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1632
1633
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN, FALSE);
1634
0
  return _g_file_attribute_value_get_boolean (value);
1635
0
}
1636
1637
/**
1638
 * g_file_info_get_is_backup:
1639
 * @info: a #GFileInfo.
1640
 *
1641
 * Checks if a file is a backup file.
1642
 *
1643
 * It is an error to call this if the #GFileInfo does not contain
1644
 * %G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP.
1645
 *
1646
 * Returns: %TRUE if file is a backup file, %FALSE otherwise.
1647
 **/
1648
gboolean
1649
g_file_info_get_is_backup (GFileInfo *info)
1650
0
{
1651
0
  GFileAttributeValue *value;
1652
1653
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1654
1655
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP, FALSE);
1656
0
  return _g_file_attribute_value_get_boolean (value);
1657
0
}
1658
1659
/**
1660
 * g_file_info_get_is_symlink:
1661
 * @info: a #GFileInfo.
1662
 *
1663
 * Checks if a file is a symlink.
1664
 *
1665
 * It is an error to call this if the #GFileInfo does not contain
1666
 * %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK.
1667
 *
1668
 * Returns: %TRUE if the given @info is a symlink.
1669
 **/
1670
gboolean
1671
g_file_info_get_is_symlink (GFileInfo *info)
1672
0
{
1673
0
  GFileAttributeValue *value;
1674
1675
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), FALSE);
1676
1677
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK, FALSE);
1678
0
  return _g_file_attribute_value_get_boolean (value);
1679
0
}
1680
1681
/**
1682
 * g_file_info_get_name:
1683
 * @info: a #GFileInfo.
1684
 *
1685
 * Gets the name for a file. This is guaranteed to always be set.
1686
 *
1687
 * It is an error to call this if the #GFileInfo does not contain
1688
 * %G_FILE_ATTRIBUTE_STANDARD_NAME.
1689
 *
1690
 * Returns: (type filename) (not nullable): a string containing the file name.
1691
 **/
1692
const char *
1693
g_file_info_get_name (GFileInfo *info)
1694
0
{
1695
0
  GFileAttributeValue *value;
1696
1697
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1698
1699
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_NAME, NULL);
1700
0
  return _g_file_attribute_value_get_byte_string (value);
1701
0
}
1702
1703
/**
1704
 * g_file_info_get_display_name:
1705
 * @info: a #GFileInfo.
1706
 *
1707
 * Gets a display name for a file. This is guaranteed to always be set.
1708
 *
1709
 * It is an error to call this if the #GFileInfo does not contain
1710
 * %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME.
1711
 *
1712
 * Returns: (not nullable): a string containing the display name.
1713
 **/
1714
const char *
1715
g_file_info_get_display_name (GFileInfo *info)
1716
0
{
1717
0
  GFileAttributeValue *value;
1718
1719
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1720
1721
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, NULL);
1722
0
  return _g_file_attribute_value_get_string (value);
1723
0
}
1724
1725
/**
1726
 * g_file_info_get_edit_name:
1727
 * @info: a #GFileInfo.
1728
 *
1729
 * Gets the edit name for a file.
1730
 *
1731
 * It is an error to call this if the #GFileInfo does not contain
1732
 * %G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME.
1733
 *
1734
 * Returns: a string containing the edit name.
1735
 **/
1736
const char *
1737
g_file_info_get_edit_name (GFileInfo *info)
1738
0
{
1739
0
  GFileAttributeValue *value;
1740
1741
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1742
1743
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME, NULL);
1744
0
  return _g_file_attribute_value_get_string (value);
1745
0
}
1746
1747
/**
1748
 * g_file_info_get_icon:
1749
 * @info: a #GFileInfo.
1750
 *
1751
 * Gets the icon for a file.
1752
 *
1753
 * It is an error to call this if the #GFileInfo does not contain
1754
 * %G_FILE_ATTRIBUTE_STANDARD_ICON.
1755
 *
1756
 * Returns: (nullable) (transfer none): #GIcon for the given @info.
1757
 **/
1758
GIcon *
1759
g_file_info_get_icon (GFileInfo *info)
1760
0
{
1761
0
  GFileAttributeValue *value;
1762
0
  GObject *obj;
1763
1764
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1765
1766
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_ICON, NULL);
1767
1768
0
  obj = _g_file_attribute_value_get_object (value);
1769
0
  if (G_IS_ICON (obj))
1770
0
    return G_ICON (obj);
1771
0
  return NULL;
1772
0
}
1773
1774
/**
1775
 * g_file_info_get_symbolic_icon:
1776
 * @info: a #GFileInfo.
1777
 *
1778
 * Gets the symbolic icon for a file.
1779
 *
1780
 * It is an error to call this if the #GFileInfo does not contain
1781
 * %G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON.
1782
 *
1783
 * Returns: (nullable) (transfer none): #GIcon for the given @info.
1784
 *
1785
 * Since: 2.34
1786
 **/
1787
GIcon *
1788
g_file_info_get_symbolic_icon (GFileInfo *info)
1789
0
{
1790
0
  GFileAttributeValue *value;
1791
0
  GObject *obj;
1792
1793
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1794
1795
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON, NULL);
1796
1797
0
  obj = _g_file_attribute_value_get_object (value);
1798
0
  if (G_IS_ICON (obj))
1799
0
    return G_ICON (obj);
1800
0
  return NULL;
1801
0
}
1802
1803
/**
1804
 * g_file_info_get_content_type:
1805
 * @info: a #GFileInfo.
1806
 *
1807
 * Gets the file's content type.
1808
 *
1809
 * It is an error to call this if the #GFileInfo does not contain
1810
 * %G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE.
1811
 *
1812
 * Returns: (nullable): a string containing the file's content type,
1813
 * or %NULL if unknown.
1814
 **/
1815
const char *
1816
g_file_info_get_content_type (GFileInfo *info)
1817
0
{
1818
0
  GFileAttributeValue *value;
1819
1820
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1821
1822
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, NULL);
1823
0
  return _g_file_attribute_value_get_string (value);
1824
0
}
1825
1826
/**
1827
 * g_file_info_get_size:
1828
 * @info: a #GFileInfo.
1829
 *
1830
 * Gets the file's size (in bytes). The size is retrieved through the value of
1831
 * the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute and is converted
1832
 * from #guint64 to #goffset before returning the result.
1833
 *
1834
 * It is an error to call this if the #GFileInfo does not contain
1835
 * %G_FILE_ATTRIBUTE_STANDARD_SIZE.
1836
 *
1837
 * Returns: a #goffset containing the file's size (in bytes).
1838
 **/
1839
goffset
1840
g_file_info_get_size (GFileInfo *info)
1841
0
{
1842
0
  GFileAttributeValue *value;
1843
1844
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), (goffset) 0);
1845
1846
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SIZE, (goffset) 0);
1847
0
  return (goffset) _g_file_attribute_value_get_uint64 (value);
1848
0
}
1849
1850
/**
1851
 * g_file_info_get_modification_time:
1852
 * @info: a #GFileInfo.
1853
 * @result: (out caller-allocates): a #GTimeVal.
1854
 *
1855
 * Gets the modification time of the current @info and sets it
1856
 * in @result.
1857
 *
1858
 * It is an error to call this if the #GFileInfo does not contain
1859
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED. If %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC is
1860
 * provided it will be used too.
1861
 *
1862
 * Deprecated: 2.62: Use g_file_info_get_modification_date_time() instead, as
1863
 *    #GTimeVal is deprecated due to the year 2038 problem.
1864
 **/
1865
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1866
void
1867
g_file_info_get_modification_time (GFileInfo *info,
1868
           GTimeVal  *result)
1869
0
{
1870
0
  static guint32 attr_mtime = 0, attr_mtime_usec;
1871
0
  GFileAttributeValue *value;
1872
1873
0
  g_return_if_fail (G_IS_FILE_INFO (info));
1874
0
  g_return_if_fail (result != NULL);
1875
1876
0
  if (attr_mtime == 0)
1877
0
    {
1878
0
      attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1879
0
      attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1880
0
    }
1881
1882
0
  value = g_file_info_find_value (info, attr_mtime);
1883
1884
0
  if (G_UNLIKELY (value == NULL))
1885
0
    {
1886
0
      g_critical ("GFileInfo created without " G_FILE_ATTRIBUTE_TIME_MODIFIED);
1887
0
      result->tv_sec = result->tv_usec = 0;
1888
0
      g_return_if_reached ();
1889
0
    }
1890
1891
0
  result->tv_sec = _g_file_attribute_value_get_uint64 (value);
1892
0
  value = g_file_info_find_value (info, attr_mtime_usec);
1893
0
  result->tv_usec = _g_file_attribute_value_get_uint32 (value);
1894
0
}
1895
G_GNUC_END_IGNORE_DEPRECATIONS
1896
1897
/**
1898
 * g_file_info_get_modification_date_time:
1899
 * @info: a #GFileInfo.
1900
 *
1901
 * Gets the modification time of the current @info and returns it as a
1902
 * #GDateTime.
1903
 *
1904
 * It is an error to call this if the #GFileInfo does not contain
1905
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED. If %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC is
1906
 * provided, the resulting #GDateTime will additionally have microsecond
1907
 * precision.
1908
 *
1909
 * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC must
1910
 * be queried separately using g_file_info_get_attribute_uint32().
1911
 *
1912
 * Returns: (transfer full) (nullable): modification time, or %NULL if unknown
1913
 * Since: 2.62
1914
 */
1915
GDateTime *
1916
g_file_info_get_modification_date_time (GFileInfo *info)
1917
0
{
1918
0
  static guint32 attr_mtime = 0, attr_mtime_usec;
1919
0
  GFileAttributeValue *value, *value_usec;
1920
0
  GDateTime *dt = NULL, *dt2 = NULL;
1921
1922
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1923
1924
0
  if (attr_mtime == 0)
1925
0
    {
1926
0
      attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
1927
0
      attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
1928
0
    }
1929
1930
0
  value = g_file_info_find_value (info, attr_mtime);
1931
0
  if (value == NULL)
1932
0
    return NULL;
1933
1934
0
  dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
1935
1936
0
  value_usec = g_file_info_find_value (info, attr_mtime_usec);
1937
0
  if (value_usec == NULL)
1938
0
    return g_steal_pointer (&dt);
1939
1940
0
  dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
1941
0
  g_date_time_unref (dt);
1942
1943
0
  return g_steal_pointer (&dt2);
1944
0
}
1945
1946
/**
1947
 * g_file_info_get_access_date_time:
1948
 * @info: a #GFileInfo.
1949
 *
1950
 * Gets the access time of the current @info and returns it as a
1951
 * #GDateTime.
1952
 *
1953
 * It is an error to call this if the #GFileInfo does not contain
1954
 * %G_FILE_ATTRIBUTE_TIME_ACCESS. If %G_FILE_ATTRIBUTE_TIME_ACCESS_USEC is
1955
 * provided, the resulting #GDateTime will additionally have microsecond
1956
 * precision.
1957
 *
1958
 * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC must
1959
 * be queried separately using g_file_info_get_attribute_uint32().
1960
 *
1961
 * Returns: (transfer full) (nullable): access time, or %NULL if unknown
1962
 * Since: 2.70
1963
 */
1964
GDateTime *
1965
g_file_info_get_access_date_time (GFileInfo *info)
1966
0
{
1967
0
  static guint32 attr_atime = 0, attr_atime_usec;
1968
0
  GFileAttributeValue *value, *value_usec;
1969
0
  GDateTime *dt = NULL, *dt2 = NULL;
1970
1971
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
1972
1973
0
  if (attr_atime == 0)
1974
0
    {
1975
0
      attr_atime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS);
1976
0
      attr_atime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_USEC);
1977
0
    }
1978
1979
0
  value = g_file_info_find_value (info, attr_atime);
1980
0
  if (value == NULL)
1981
0
    return NULL;
1982
1983
0
  dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
1984
1985
0
  value_usec = g_file_info_find_value (info, attr_atime_usec);
1986
0
  if (value_usec == NULL)
1987
0
    return g_steal_pointer (&dt);
1988
1989
0
  dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
1990
0
  g_date_time_unref (dt);
1991
1992
0
  return g_steal_pointer (&dt2);
1993
0
}
1994
1995
/**
1996
 * g_file_info_get_creation_date_time:
1997
 * @info: a #GFileInfo.
1998
 *
1999
 * Gets the creation time of the current @info and returns it as a
2000
 * #GDateTime.
2001
 *
2002
 * It is an error to call this if the #GFileInfo does not contain
2003
 * %G_FILE_ATTRIBUTE_TIME_CREATED. If %G_FILE_ATTRIBUTE_TIME_CREATED_USEC is
2004
 * provided, the resulting #GDateTime will additionally have microsecond
2005
 * precision.
2006
 *
2007
 * If nanosecond precision is needed, %G_FILE_ATTRIBUTE_TIME_CREATED_NSEC must
2008
 * be queried separately using g_file_info_get_attribute_uint32().
2009
 *
2010
 * Returns: (transfer full) (nullable): creation time, or %NULL if unknown
2011
 * Since: 2.70
2012
 */
2013
GDateTime *
2014
g_file_info_get_creation_date_time (GFileInfo *info)
2015
0
{
2016
0
  static guint32 attr_ctime = 0, attr_ctime_usec;
2017
0
  GFileAttributeValue *value, *value_usec;
2018
0
  GDateTime *dt = NULL, *dt2 = NULL;
2019
2020
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2021
2022
0
  if (attr_ctime == 0)
2023
0
    {
2024
0
      attr_ctime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED);
2025
0
      attr_ctime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_USEC);
2026
0
    }
2027
2028
0
  value = g_file_info_find_value (info, attr_ctime);
2029
0
  if (value == NULL)
2030
0
    return NULL;
2031
2032
0
  dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value));
2033
2034
0
  value_usec = g_file_info_find_value (info, attr_ctime_usec);
2035
0
  if (value_usec == NULL)
2036
0
    return g_steal_pointer (&dt);
2037
2038
0
  dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec));
2039
0
  g_date_time_unref (dt);
2040
2041
0
  return g_steal_pointer (&dt2);
2042
0
}
2043
2044
/**
2045
 * g_file_info_get_symlink_target:
2046
 * @info: a #GFileInfo.
2047
 *
2048
 * Gets the symlink target for a given #GFileInfo.
2049
 *
2050
 * It is an error to call this if the #GFileInfo does not contain
2051
 * %G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET.
2052
 *
2053
 * Returns: (type filename) (nullable): a string containing the symlink target.
2054
 **/
2055
const char *
2056
g_file_info_get_symlink_target (GFileInfo *info)
2057
0
{
2058
0
  GFileAttributeValue *value;
2059
2060
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2061
2062
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET, NULL);
2063
0
  return _g_file_attribute_value_get_byte_string (value);
2064
0
}
2065
2066
/**
2067
 * g_file_info_get_etag:
2068
 * @info: a #GFileInfo.
2069
 *
2070
 * Gets the [entity tag][gfile-etag] for a given
2071
 * #GFileInfo. See %G_FILE_ATTRIBUTE_ETAG_VALUE.
2072
 *
2073
 * It is an error to call this if the #GFileInfo does not contain
2074
 * %G_FILE_ATTRIBUTE_ETAG_VALUE.
2075
 *
2076
 * Returns: (nullable): a string containing the value of the "etag:value" attribute.
2077
 **/
2078
const char *
2079
g_file_info_get_etag (GFileInfo *info)
2080
0
{
2081
0
  GFileAttributeValue *value;
2082
2083
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
2084
2085
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_ETAG_VALUE, NULL);
2086
0
  return _g_file_attribute_value_get_string (value);
2087
0
}
2088
2089
/**
2090
 * g_file_info_get_sort_order:
2091
 * @info: a #GFileInfo.
2092
 *
2093
 * Gets the value of the sort_order attribute from the #GFileInfo.
2094
 * See %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2095
 *
2096
 * It is an error to call this if the #GFileInfo does not contain
2097
 * %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2098
 *
2099
 * Returns: a #gint32 containing the value of the "standard::sort_order" attribute.
2100
 **/
2101
gint32
2102
g_file_info_get_sort_order (GFileInfo *info)
2103
0
{
2104
0
  GFileAttributeValue *value;
2105
2106
0
  g_return_val_if_fail (G_IS_FILE_INFO (info), 0);
2107
2108
0
  get_required_attribute (&value, info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER, 0);
2109
0
  return _g_file_attribute_value_get_int32 (value);
2110
0
}
2111
2112
/* Helper setters: */
2113
/**
2114
 * g_file_info_set_file_type:
2115
 * @info: a #GFileInfo.
2116
 * @type: a #GFileType.
2117
 *
2118
 * Sets the file type in a #GFileInfo to @type.
2119
 * See %G_FILE_ATTRIBUTE_STANDARD_TYPE.
2120
 **/
2121
void
2122
g_file_info_set_file_type (GFileInfo *info,
2123
         GFileType  type)
2124
0
{
2125
0
  static guint32 attr = 0;
2126
0
  GFileAttributeValue *value;
2127
2128
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2129
2130
0
  if (attr == 0)
2131
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_TYPE);
2132
2133
0
  value = g_file_info_create_value (info, attr);
2134
0
  if (value)
2135
0
    _g_file_attribute_value_set_uint32 (value, type);
2136
0
}
2137
2138
/**
2139
 * g_file_info_set_is_hidden:
2140
 * @info: a #GFileInfo.
2141
 * @is_hidden: a #gboolean.
2142
 *
2143
 * Sets the "is_hidden" attribute in a #GFileInfo according to @is_hidden.
2144
 * See %G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN.
2145
 **/
2146
void
2147
g_file_info_set_is_hidden (GFileInfo *info,
2148
         gboolean   is_hidden)
2149
0
{
2150
0
  static guint32 attr = 0;
2151
0
  GFileAttributeValue *value;
2152
2153
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2154
2155
0
  if (attr == 0)
2156
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN);
2157
2158
0
  value = g_file_info_create_value (info, attr);
2159
0
  if (value)
2160
0
    _g_file_attribute_value_set_boolean (value, is_hidden);
2161
0
}
2162
2163
/**
2164
 * g_file_info_set_is_symlink:
2165
 * @info: a #GFileInfo.
2166
 * @is_symlink: a #gboolean.
2167
 *
2168
 * Sets the "is_symlink" attribute in a #GFileInfo according to @is_symlink.
2169
 * See %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK.
2170
 **/
2171
void
2172
g_file_info_set_is_symlink (GFileInfo *info,
2173
          gboolean   is_symlink)
2174
0
{
2175
0
  static guint32 attr = 0;
2176
0
  GFileAttributeValue *value;
2177
2178
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2179
2180
0
  if (attr == 0)
2181
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
2182
2183
0
  value = g_file_info_create_value (info, attr);
2184
0
  if (value)
2185
0
    _g_file_attribute_value_set_boolean (value, is_symlink);
2186
0
}
2187
2188
/**
2189
 * g_file_info_set_name:
2190
 * @info: a #GFileInfo.
2191
 * @name: (type filename): a string containing a name.
2192
 *
2193
 * Sets the name attribute for the current #GFileInfo.
2194
 * See %G_FILE_ATTRIBUTE_STANDARD_NAME.
2195
 **/
2196
void
2197
g_file_info_set_name (GFileInfo  *info,
2198
          const char *name)
2199
0
{
2200
0
  static guint32 attr = 0;
2201
0
  GFileAttributeValue *value;
2202
2203
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2204
0
  g_return_if_fail (name != NULL);
2205
2206
0
  if (attr == 0)
2207
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_NAME);
2208
2209
0
  value = g_file_info_create_value (info, attr);
2210
0
  if (value)
2211
0
    _g_file_attribute_value_set_byte_string (value, name);
2212
0
}
2213
2214
/**
2215
 * g_file_info_set_display_name:
2216
 * @info: a #GFileInfo.
2217
 * @display_name: a string containing a display name.
2218
 *
2219
 * Sets the display name for the current #GFileInfo.
2220
 * See %G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME.
2221
 **/
2222
void
2223
g_file_info_set_display_name (GFileInfo  *info,
2224
            const char *display_name)
2225
0
{
2226
0
  static guint32 attr = 0;
2227
0
  GFileAttributeValue *value;
2228
2229
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2230
0
  g_return_if_fail (display_name != NULL);
2231
2232
0
  if (attr == 0)
2233
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
2234
2235
0
  value = g_file_info_create_value (info, attr);
2236
0
  if (value)
2237
0
    _g_file_attribute_value_set_string (value, display_name);
2238
0
}
2239
2240
/**
2241
 * g_file_info_set_edit_name:
2242
 * @info: a #GFileInfo.
2243
 * @edit_name: a string containing an edit name.
2244
 *
2245
 * Sets the edit name for the current file.
2246
 * See %G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME.
2247
 **/
2248
void
2249
g_file_info_set_edit_name (GFileInfo  *info,
2250
         const char *edit_name)
2251
0
{
2252
0
  static guint32 attr = 0;
2253
0
  GFileAttributeValue *value;
2254
2255
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2256
0
  g_return_if_fail (edit_name != NULL);
2257
2258
0
  if (attr == 0)
2259
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
2260
2261
0
  value = g_file_info_create_value (info, attr);
2262
0
  if (value)
2263
0
    _g_file_attribute_value_set_string (value, edit_name);
2264
0
}
2265
2266
/**
2267
 * g_file_info_set_icon:
2268
 * @info: a #GFileInfo.
2269
 * @icon: a #GIcon.
2270
 *
2271
 * Sets the icon for a given #GFileInfo.
2272
 * See %G_FILE_ATTRIBUTE_STANDARD_ICON.
2273
 **/
2274
void
2275
g_file_info_set_icon (GFileInfo *info,
2276
          GIcon     *icon)
2277
0
{
2278
0
  static guint32 attr = 0;
2279
0
  GFileAttributeValue *value;
2280
2281
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2282
0
  g_return_if_fail (G_IS_ICON (icon));
2283
2284
0
  if (attr == 0)
2285
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_ICON);
2286
2287
0
  value = g_file_info_create_value (info, attr);
2288
0
  if (value)
2289
0
    _g_file_attribute_value_set_object (value, G_OBJECT (icon));
2290
0
}
2291
2292
/**
2293
 * g_file_info_set_symbolic_icon:
2294
 * @info: a #GFileInfo.
2295
 * @icon: a #GIcon.
2296
 *
2297
 * Sets the symbolic icon for a given #GFileInfo.
2298
 * See %G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON.
2299
 *
2300
 * Since: 2.34
2301
 **/
2302
void
2303
g_file_info_set_symbolic_icon (GFileInfo *info,
2304
                               GIcon     *icon)
2305
0
{
2306
0
  static guint32 attr = 0;
2307
0
  GFileAttributeValue *value;
2308
2309
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2310
0
  g_return_if_fail (G_IS_ICON (icon));
2311
2312
0
  if (attr == 0)
2313
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON);
2314
2315
0
  value = g_file_info_create_value (info, attr);
2316
0
  if (value)
2317
0
    _g_file_attribute_value_set_object (value, G_OBJECT (icon));
2318
0
}
2319
2320
/**
2321
 * g_file_info_set_content_type:
2322
 * @info: a #GFileInfo.
2323
 * @content_type: a content type. See [GContentType][gio-GContentType]
2324
 *
2325
 * Sets the content type attribute for a given #GFileInfo.
2326
 * See %G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE.
2327
 **/
2328
void
2329
g_file_info_set_content_type (GFileInfo  *info,
2330
            const char *content_type)
2331
0
{
2332
0
  static guint32 attr = 0;
2333
0
  GFileAttributeValue *value;
2334
2335
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2336
0
  g_return_if_fail (content_type != NULL);
2337
2338
0
  if (attr == 0)
2339
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
2340
2341
0
  value = g_file_info_create_value (info, attr);
2342
0
  if (value)
2343
0
    _g_file_attribute_value_set_string (value, content_type);
2344
0
}
2345
2346
/**
2347
 * g_file_info_set_size:
2348
 * @info: a #GFileInfo.
2349
 * @size: a #goffset containing the file's size.
2350
 *
2351
 * Sets the %G_FILE_ATTRIBUTE_STANDARD_SIZE attribute in the file info
2352
 * to the given size.
2353
 **/
2354
void
2355
g_file_info_set_size (GFileInfo *info,
2356
          goffset    size)
2357
0
{
2358
0
  static guint32 attr = 0;
2359
0
  GFileAttributeValue *value;
2360
2361
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2362
2363
0
  if (attr == 0)
2364
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SIZE);
2365
2366
0
  value = g_file_info_create_value (info, attr);
2367
0
  if (value)
2368
0
    _g_file_attribute_value_set_uint64 (value, size);
2369
0
}
2370
2371
/**
2372
 * g_file_info_set_modification_time:
2373
 * @info: a #GFileInfo.
2374
 * @mtime: a #GTimeVal.
2375
 *
2376
 * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED and
2377
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC attributes in the file info to the
2378
 * given time value.
2379
 *
2380
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC will be cleared.
2381
 *
2382
 * Deprecated: 2.62: Use g_file_info_set_modification_date_time() instead, as
2383
 *    #GTimeVal is deprecated due to the year 2038 problem.
2384
 **/
2385
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2386
void
2387
g_file_info_set_modification_time (GFileInfo *info,
2388
           GTimeVal  *mtime)
2389
0
{
2390
0
  static guint32 attr_mtime = 0, attr_mtime_usec = 0, attr_mtime_nsec = 0;
2391
0
  GFileAttributeValue *value;
2392
2393
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2394
0
  g_return_if_fail (mtime != NULL);
2395
2396
0
  if (attr_mtime == 0)
2397
0
    {
2398
0
      attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
2399
0
      attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
2400
0
      attr_mtime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
2401
0
    }
2402
2403
0
  value = g_file_info_create_value (info, attr_mtime);
2404
0
  if (value)
2405
0
    _g_file_attribute_value_set_uint64 (value, mtime->tv_sec);
2406
0
  value = g_file_info_create_value (info, attr_mtime_usec);
2407
0
  if (value)
2408
0
    _g_file_attribute_value_set_uint32 (value, mtime->tv_usec);
2409
2410
  /* nsecs can’t be known from a #GTimeVal, so remove them */
2411
0
  g_file_info_remove_value (info, attr_mtime_nsec);
2412
0
}
2413
G_GNUC_END_IGNORE_DEPRECATIONS
2414
2415
/**
2416
 * g_file_info_set_modification_date_time:
2417
 * @info: a #GFileInfo.
2418
 * @mtime: (not nullable): a #GDateTime.
2419
 *
2420
 * Sets the %G_FILE_ATTRIBUTE_TIME_MODIFIED and
2421
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC attributes in the file info to the
2422
 * given date/time value.
2423
 *
2424
 * %G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC will be cleared.
2425
 *
2426
 * Since: 2.62
2427
 */
2428
void
2429
g_file_info_set_modification_date_time (GFileInfo *info,
2430
                                        GDateTime *mtime)
2431
0
{
2432
0
  static guint32 attr_mtime = 0, attr_mtime_usec = 0, attr_mtime_nsec = 0;
2433
0
  GFileAttributeValue *value;
2434
2435
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2436
0
  g_return_if_fail (mtime != NULL);
2437
2438
0
  if (attr_mtime == 0)
2439
0
    {
2440
0
      attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED);
2441
0
      attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC);
2442
0
      attr_mtime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
2443
0
    }
2444
2445
0
  value = g_file_info_create_value (info, attr_mtime);
2446
0
  if (value)
2447
0
    _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (mtime));
2448
0
  value = g_file_info_create_value (info, attr_mtime_usec);
2449
0
  if (value)
2450
0
    _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (mtime));
2451
2452
  /* nsecs can’t be known from a #GDateTime, so remove them */
2453
0
  g_file_info_remove_value (info, attr_mtime_nsec);
2454
0
}
2455
2456
/**
2457
 * g_file_info_set_access_date_time:
2458
 * @info: a #GFileInfo.
2459
 * @atime: (not nullable): a #GDateTime.
2460
 *
2461
 * Sets the %G_FILE_ATTRIBUTE_TIME_ACCESS and
2462
 * %G_FILE_ATTRIBUTE_TIME_ACCESS_USEC attributes in the file info to the
2463
 * given date/time value.
2464
 *
2465
 * %G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC will be cleared.
2466
 *
2467
 * Since: 2.70
2468
 */
2469
void
2470
g_file_info_set_access_date_time (GFileInfo *info,
2471
                                  GDateTime *atime)
2472
0
{
2473
0
  static guint32 attr_atime = 0, attr_atime_usec = 0, attr_atime_nsec = 0;
2474
0
  GFileAttributeValue *value;
2475
2476
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2477
0
  g_return_if_fail (atime != NULL);
2478
2479
0
  if (attr_atime == 0)
2480
0
    {
2481
0
      attr_atime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS);
2482
0
      attr_atime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_USEC);
2483
0
      attr_atime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC);
2484
0
    }
2485
2486
0
  value = g_file_info_create_value (info, attr_atime);
2487
0
  if (value)
2488
0
    _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (atime));
2489
0
  value = g_file_info_create_value (info, attr_atime_usec);
2490
0
  if (value)
2491
0
    _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (atime));
2492
2493
  /* nsecs can’t be known from a #GDateTime, so remove them */
2494
0
  g_file_info_remove_value (info, attr_atime_nsec);
2495
0
}
2496
2497
/**
2498
 * g_file_info_set_creation_date_time:
2499
 * @info: a #GFileInfo.
2500
 * @creation_time: (not nullable): a #GDateTime.
2501
 *
2502
 * Sets the %G_FILE_ATTRIBUTE_TIME_CREATED and
2503
 * %G_FILE_ATTRIBUTE_TIME_CREATED_USEC attributes in the file info to the
2504
 * given date/time value.
2505
 *
2506
 * %G_FILE_ATTRIBUTE_TIME_CREATED_NSEC will be cleared.
2507
 *
2508
 * Since: 2.70
2509
 */
2510
void
2511
g_file_info_set_creation_date_time (GFileInfo *info,
2512
                                    GDateTime *creation_time)
2513
0
{
2514
0
  static guint32 attr_ctime = 0, attr_ctime_usec = 0, attr_ctime_nsec = 0;
2515
0
  GFileAttributeValue *value;
2516
2517
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2518
0
  g_return_if_fail (creation_time != NULL);
2519
2520
0
  if (attr_ctime == 0)
2521
0
    {
2522
0
      attr_ctime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED);
2523
0
      attr_ctime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_USEC);
2524
0
      attr_ctime_nsec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_NSEC);
2525
0
    }
2526
2527
0
  value = g_file_info_create_value (info, attr_ctime);
2528
0
  if (value)
2529
0
    _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (creation_time));
2530
0
  value = g_file_info_create_value (info, attr_ctime_usec);
2531
0
  if (value)
2532
0
    _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (creation_time));
2533
2534
  /* nsecs can’t be known from a #GDateTime, so remove them */
2535
0
  g_file_info_remove_value (info, attr_ctime_nsec);
2536
0
}
2537
2538
/**
2539
 * g_file_info_set_symlink_target:
2540
 * @info: a #GFileInfo.
2541
 * @symlink_target: (type filename): a static string containing a path to a symlink target.
2542
 *
2543
 * Sets the %G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET attribute in the file info
2544
 * to the given symlink target.
2545
 **/
2546
void
2547
g_file_info_set_symlink_target (GFileInfo  *info,
2548
        const char *symlink_target)
2549
0
{
2550
0
  static guint32 attr = 0;
2551
0
  GFileAttributeValue *value;
2552
2553
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2554
0
  g_return_if_fail (symlink_target != NULL);
2555
2556
0
  if (attr == 0)
2557
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET);
2558
2559
0
  value = g_file_info_create_value (info, attr);
2560
0
  if (value)
2561
0
    _g_file_attribute_value_set_byte_string (value, symlink_target);
2562
0
}
2563
2564
/**
2565
 * g_file_info_set_sort_order:
2566
 * @info: a #GFileInfo.
2567
 * @sort_order: a sort order integer.
2568
 *
2569
 * Sets the sort order attribute in the file info structure. See
2570
 * %G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER.
2571
 **/
2572
void
2573
g_file_info_set_sort_order (GFileInfo *info,
2574
          gint32     sort_order)
2575
0
{
2576
0
  static guint32 attr = 0;
2577
0
  GFileAttributeValue *value;
2578
2579
0
  g_return_if_fail (G_IS_FILE_INFO (info));
2580
2581
0
  if (attr == 0)
2582
0
    attr = lookup_attribute (G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
2583
2584
0
  value = g_file_info_create_value (info, attr);
2585
0
  if (value)
2586
0
    _g_file_attribute_value_set_int32 (value, sort_order);
2587
0
}
2588
2589
2590
typedef struct {
2591
  guint32 id;
2592
  guint32 mask;
2593
} SubMatcher;
2594
2595
struct _GFileAttributeMatcher {
2596
  gboolean all;
2597
  gint ref;
2598
2599
  GArray *sub_matchers;
2600
2601
  /* Iterator */
2602
  guint32 iterator_ns;
2603
  gint iterator_pos;
2604
};
2605
2606
G_DEFINE_BOXED_TYPE (GFileAttributeMatcher, g_file_attribute_matcher,
2607
                     g_file_attribute_matcher_ref,
2608
                     g_file_attribute_matcher_unref)
2609
2610
static gint
2611
compare_sub_matchers (gconstpointer a,
2612
                      gconstpointer b)
2613
0
{
2614
0
  const SubMatcher *suba = a;
2615
0
  const SubMatcher *subb = b;
2616
0
  int diff;
2617
2618
0
  diff = suba->id - subb->id;
2619
2620
0
  if (diff)
2621
0
    return diff;
2622
2623
0
  return suba->mask - subb->mask;
2624
0
}
2625
2626
static gboolean
2627
sub_matcher_matches (SubMatcher *matcher,
2628
                     SubMatcher *submatcher)
2629
0
{
2630
0
  if ((matcher->mask & submatcher->mask) != matcher->mask)
2631
0
    return FALSE;
2632
  
2633
0
  return matcher->id == (submatcher->id & matcher->mask);
2634
0
}
2635
2636
/* Call this function after modifying a matcher.
2637
 * It will ensure all the invariants other functions rely on.
2638
 */
2639
static GFileAttributeMatcher *
2640
matcher_optimize (GFileAttributeMatcher *matcher)
2641
0
{
2642
0
  SubMatcher *submatcher, *compare;
2643
0
  guint i, j;
2644
2645
  /* remove sub_matchers if we match everything anyway */
2646
0
  if (matcher->all)
2647
0
    {
2648
0
      if (matcher->sub_matchers)
2649
0
        {
2650
0
          g_array_free (matcher->sub_matchers, TRUE);
2651
0
          matcher->sub_matchers = NULL;
2652
0
        }
2653
0
      return matcher;
2654
0
    }
2655
2656
0
  if (matcher->sub_matchers->len == 0)
2657
0
    {
2658
0
      g_file_attribute_matcher_unref (matcher);
2659
0
      return NULL;
2660
0
    }
2661
2662
  /* sort sub_matchers by id (and then mask), so we can bsearch
2663
   * and compare matchers in O(N) instead of O(N²) */
2664
0
  g_array_sort (matcher->sub_matchers, compare_sub_matchers);
2665
2666
  /* remove duplicates and specific matches when we match the whole namespace */
2667
0
  j = 0;
2668
0
  compare = &g_array_index (matcher->sub_matchers, SubMatcher, j);
2669
2670
0
  for (i = 1; i < matcher->sub_matchers->len; i++)
2671
0
    {
2672
0
      submatcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
2673
0
      if (sub_matcher_matches (compare, submatcher))
2674
0
        continue;
2675
2676
0
      j++;
2677
0
      compare++;
2678
2679
0
      if (j < i)
2680
0
        *compare = *submatcher;
2681
0
    }
2682
2683
0
  g_array_set_size (matcher->sub_matchers, j + 1);
2684
2685
0
  return matcher;
2686
0
}
2687
2688
/**
2689
 * g_file_attribute_matcher_new:
2690
 * @attributes: an attribute string to match.
2691
 *
2692
 * Creates a new file attribute matcher, which matches attributes
2693
 * against a given string. #GFileAttributeMatchers are reference
2694
 * counted structures, and are created with a reference count of 1. If
2695
 * the number of references falls to 0, the #GFileAttributeMatcher is
2696
 * automatically destroyed.
2697
 *
2698
 * The @attributes string should be formatted with specific keys separated
2699
 * from namespaces with a double colon. Several "namespace::key" strings may be
2700
 * concatenated with a single comma (e.g. "standard::type,standard::is-hidden").
2701
 * The wildcard "*" may be used to match all keys and namespaces, or
2702
 * "namespace::*" will match all keys in a given namespace.
2703
 *
2704
 * ## Examples of file attribute matcher strings and results
2705
 *
2706
 * - `"*"`: matches all attributes.
2707
 * - `"standard::is-hidden"`: matches only the key is-hidden in the
2708
 *   standard namespace.
2709
 * - `"standard::type,unix::*"`: matches the type key in the standard
2710
 *   namespace and all keys in the unix namespace.
2711
 *
2712
 * Returns: a #GFileAttributeMatcher
2713
 */
2714
GFileAttributeMatcher *
2715
g_file_attribute_matcher_new (const char *attributes)
2716
0
{
2717
0
  char **split;
2718
0
  char *colon;
2719
0
  int i;
2720
0
  GFileAttributeMatcher *matcher;
2721
2722
0
  if (attributes == NULL || *attributes == '\0')
2723
0
    return NULL;
2724
2725
0
  matcher = g_malloc0 (sizeof (GFileAttributeMatcher));
2726
0
  matcher->ref = 1;
2727
0
  matcher->sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
2728
2729
0
  split = g_strsplit (attributes, ",", -1);
2730
2731
0
  for (i = 0; split[i] != NULL; i++)
2732
0
    {
2733
0
      if (strcmp (split[i], "*") == 0)
2734
0
  matcher->all = TRUE;
2735
0
      else
2736
0
  {
2737
0
          SubMatcher s;
2738
2739
0
    colon = strstr (split[i], "::");
2740
0
    if (colon != NULL &&
2741
0
        !(colon[2] == 0 ||
2742
0
    (colon[2] == '*' &&
2743
0
     colon[3] == 0)))
2744
0
      {
2745
0
        s.id = lookup_attribute (split[i]);
2746
0
        s.mask = 0xffffffff;
2747
0
      }
2748
0
    else
2749
0
      {
2750
0
        if (colon)
2751
0
    *colon = 0;
2752
2753
0
        s.id = lookup_namespace (split[i]) << NS_POS;
2754
0
        s.mask = NS_MASK << NS_POS;
2755
0
      }
2756
2757
0
          g_array_append_val (matcher->sub_matchers, s);
2758
0
  }
2759
0
    }
2760
2761
0
  g_strfreev (split);
2762
2763
0
  matcher = matcher_optimize (matcher);
2764
2765
0
  return matcher;
2766
0
}
2767
2768
/**
2769
 * g_file_attribute_matcher_subtract:
2770
 * @matcher: (nullable): Matcher to subtract from 
2771
 * @subtract: (nullable): The matcher to subtract
2772
 *
2773
 * Subtracts all attributes of @subtract from @matcher and returns
2774
 * a matcher that supports those attributes.
2775
 *
2776
 * Note that currently it is not possible to remove a single
2777
 * attribute when the @matcher matches the whole namespace - or remove
2778
 * a namespace or attribute when the matcher matches everything. This
2779
 * is a limitation of the current implementation, but may be fixed
2780
 * in the future.
2781
 *
2782
 * Returns: (nullable): A file attribute matcher matching all attributes of
2783
 *     @matcher that are not matched by @subtract
2784
 **/
2785
GFileAttributeMatcher *
2786
g_file_attribute_matcher_subtract (GFileAttributeMatcher *matcher,
2787
                                   GFileAttributeMatcher *subtract)
2788
0
{
2789
0
  GFileAttributeMatcher *result;
2790
0
  guint mi, si;
2791
0
  SubMatcher *msub, *ssub;
2792
2793
0
  if (matcher == NULL)
2794
0
    return NULL;
2795
0
  if (subtract == NULL)
2796
0
    return g_file_attribute_matcher_ref (matcher);
2797
0
  if (subtract->all)
2798
0
    return NULL;
2799
0
  if (matcher->all)
2800
0
    return g_file_attribute_matcher_ref (matcher);
2801
2802
0
  result = g_malloc0 (sizeof (GFileAttributeMatcher));
2803
0
  result->ref = 1;
2804
0
  result->sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher));
2805
2806
0
  si = 0;
2807
0
  g_assert (subtract->sub_matchers->len > 0);
2808
0
  ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
2809
2810
0
  for (mi = 0; mi < matcher->sub_matchers->len; mi++)
2811
0
    {
2812
0
      msub = &g_array_index (matcher->sub_matchers, SubMatcher, mi);
2813
2814
0
retry:
2815
0
      if (sub_matcher_matches (ssub, msub))
2816
0
        continue;
2817
2818
0
      si++;
2819
0
      if (si >= subtract->sub_matchers->len)
2820
0
        break;
2821
2822
0
      ssub = &g_array_index (subtract->sub_matchers, SubMatcher, si);
2823
0
      if (ssub->id <= msub->id)
2824
0
        goto retry;
2825
2826
0
      g_array_append_val (result->sub_matchers, *msub);
2827
0
    }
2828
2829
0
  if (mi < matcher->sub_matchers->len)
2830
0
    g_array_append_vals (result->sub_matchers,
2831
0
                         &g_array_index (matcher->sub_matchers, SubMatcher, mi),
2832
0
                         matcher->sub_matchers->len - mi);
2833
2834
0
  result = matcher_optimize (result);
2835
2836
0
  return result;
2837
0
}
2838
2839
/**
2840
 * g_file_attribute_matcher_ref:
2841
 * @matcher: a #GFileAttributeMatcher.
2842
 *
2843
 * References a file attribute matcher.
2844
 *
2845
 * Returns: a #GFileAttributeMatcher.
2846
 **/
2847
GFileAttributeMatcher *
2848
g_file_attribute_matcher_ref (GFileAttributeMatcher *matcher)
2849
0
{
2850
0
  if (matcher)
2851
0
    {
2852
0
      g_return_val_if_fail (matcher->ref > 0, NULL);
2853
0
      g_atomic_int_inc (&matcher->ref);
2854
0
    }
2855
0
  return matcher;
2856
0
}
2857
2858
/**
2859
 * g_file_attribute_matcher_unref:
2860
 * @matcher: a #GFileAttributeMatcher.
2861
 *
2862
 * Unreferences @matcher. If the reference count falls below 1,
2863
 * the @matcher is automatically freed.
2864
 *
2865
 **/
2866
void
2867
g_file_attribute_matcher_unref (GFileAttributeMatcher *matcher)
2868
0
{
2869
0
  if (matcher)
2870
0
    {
2871
0
      g_return_if_fail (matcher->ref > 0);
2872
2873
0
      if (g_atomic_int_dec_and_test (&matcher->ref))
2874
0
  {
2875
0
    if (matcher->sub_matchers)
2876
0
      g_array_free (matcher->sub_matchers, TRUE);
2877
2878
0
    g_free (matcher);
2879
0
  }
2880
0
    }
2881
0
}
2882
2883
/**
2884
 * g_file_attribute_matcher_matches_only:
2885
 * @matcher: a #GFileAttributeMatcher.
2886
 * @attribute: a file attribute key.
2887
 *
2888
 * Checks if an attribute matcher only matches a given attribute. Always
2889
 * returns %FALSE if "*" was used when creating the matcher.
2890
 *
2891
 * Returns: %TRUE if the matcher only matches @attribute. %FALSE otherwise.
2892
 **/
2893
gboolean
2894
g_file_attribute_matcher_matches_only (GFileAttributeMatcher *matcher,
2895
               const char            *attribute)
2896
0
{
2897
0
  SubMatcher *sub_matcher;
2898
0
  guint32 id;
2899
2900
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2901
2902
0
  if (matcher == NULL ||
2903
0
      matcher->all)
2904
0
    return FALSE;
2905
2906
0
  if (matcher->sub_matchers->len != 1)
2907
0
    return FALSE;
2908
  
2909
0
  id = lookup_attribute (attribute);
2910
  
2911
0
  sub_matcher = &g_array_index (matcher->sub_matchers, SubMatcher, 0);
2912
  
2913
0
  return sub_matcher->id == id &&
2914
0
         sub_matcher->mask == 0xffffffff;
2915
0
}
2916
2917
static gboolean
2918
matcher_matches_id (GFileAttributeMatcher *matcher,
2919
                    guint32                id)
2920
0
{
2921
0
  SubMatcher *sub_matchers;
2922
0
  guint i;
2923
2924
0
  if (matcher->sub_matchers)
2925
0
    {
2926
0
      sub_matchers = (SubMatcher *)matcher->sub_matchers->data;
2927
0
      for (i = 0; i < matcher->sub_matchers->len; i++)
2928
0
  {
2929
0
    if (sub_matchers[i].id == (id & sub_matchers[i].mask))
2930
0
      return TRUE;
2931
0
  }
2932
0
    }
2933
2934
0
  return FALSE;
2935
0
}
2936
2937
gboolean
2938
_g_file_attribute_matcher_matches_id (GFileAttributeMatcher *matcher,
2939
                                      guint32                id)
2940
0
{
2941
  /* We return a NULL matcher for an empty match string, so handle this */
2942
0
  if (matcher == NULL)
2943
0
    return FALSE;
2944
2945
0
  if (matcher->all)
2946
0
    return TRUE;
2947
2948
0
  return matcher_matches_id (matcher, id);
2949
0
}
2950
2951
/**
2952
 * g_file_attribute_matcher_matches:
2953
 * @matcher: a #GFileAttributeMatcher.
2954
 * @attribute: a file attribute key.
2955
 *
2956
 * Checks if an attribute will be matched by an attribute matcher. If
2957
 * the matcher was created with the "*" matching string, this function
2958
 * will always return %TRUE.
2959
 *
2960
 * Returns: %TRUE if @attribute matches @matcher. %FALSE otherwise.
2961
 **/
2962
gboolean
2963
g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher,
2964
          const char            *attribute)
2965
0
{
2966
0
  g_return_val_if_fail (attribute != NULL && *attribute != '\0', FALSE);
2967
2968
  /* We return a NULL matcher for an empty match string, so handle this */
2969
0
  if (matcher == NULL)
2970
0
    return FALSE;
2971
2972
0
  if (matcher->all)
2973
0
    return TRUE;
2974
2975
0
  return matcher_matches_id (matcher, lookup_attribute (attribute));
2976
0
}
2977
2978
/* return TRUE -> all */
2979
/**
2980
 * g_file_attribute_matcher_enumerate_namespace:
2981
 * @matcher: a #GFileAttributeMatcher.
2982
 * @ns: a string containing a file attribute namespace.
2983
 *
2984
 * Checks if the matcher will match all of the keys in a given namespace.
2985
 * This will always return %TRUE if a wildcard character is in use (e.g. if
2986
 * matcher was created with "standard::*" and @ns is "standard", or if matcher was created
2987
 * using "*" and namespace is anything.)
2988
 *
2989
 * TODO: this is awkwardly worded.
2990
 *
2991
 * Returns: %TRUE if the matcher matches all of the entries
2992
 * in the given @ns, %FALSE otherwise.
2993
 **/
2994
gboolean
2995
g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher,
2996
                const char            *ns)
2997
0
{
2998
0
  SubMatcher *sub_matchers;
2999
0
  guint ns_id;
3000
0
  guint i;
3001
3002
0
  g_return_val_if_fail (ns != NULL && *ns != '\0', FALSE);
3003
3004
  /* We return a NULL matcher for an empty match string, so handle this */
3005
0
  if (matcher == NULL)
3006
0
    return FALSE;
3007
3008
0
  if (matcher->all)
3009
0
    return TRUE;
3010
3011
0
  ns_id = lookup_namespace (ns) << NS_POS;
3012
3013
0
  if (matcher->sub_matchers)
3014
0
    {
3015
0
      sub_matchers = (SubMatcher *)matcher->sub_matchers->data;
3016
0
      for (i = 0; i < matcher->sub_matchers->len; i++)
3017
0
  {
3018
0
    if (sub_matchers[i].id == ns_id)
3019
0
      return TRUE;
3020
0
  }
3021
0
    }
3022
3023
0
  matcher->iterator_ns = ns_id;
3024
0
  matcher->iterator_pos = 0;
3025
3026
0
  return FALSE;
3027
0
}
3028
3029
/**
3030
 * g_file_attribute_matcher_enumerate_next:
3031
 * @matcher: a #GFileAttributeMatcher.
3032
 *
3033
 * Gets the next matched attribute from a #GFileAttributeMatcher.
3034
 *
3035
 * Returns: (nullable): a string containing the next attribute or, %NULL if
3036
 * no more attribute exist.
3037
 **/
3038
const char *
3039
g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher)
3040
0
{
3041
0
  guint i;
3042
0
  SubMatcher *sub_matcher;
3043
3044
  /* We return a NULL matcher for an empty match string, so handle this */
3045
0
  if (matcher == NULL)
3046
0
    return NULL;
3047
3048
0
  while (1)
3049
0
    {
3050
0
      i = matcher->iterator_pos++;
3051
3052
0
      if (matcher->sub_matchers == NULL)
3053
0
        return NULL;
3054
3055
0
      if (i < matcher->sub_matchers->len)
3056
0
        sub_matcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
3057
0
      else
3058
0
        return NULL;
3059
3060
0
      if (sub_matcher->mask == 0xffffffff &&
3061
0
    (sub_matcher->id & (NS_MASK << NS_POS)) == matcher->iterator_ns)
3062
0
  return get_attribute_for_id (sub_matcher->id);
3063
0
    }
3064
0
}
3065
3066
/**
3067
 * g_file_attribute_matcher_to_string:
3068
 * @matcher: (nullable): a #GFileAttributeMatcher.
3069
 *
3070
 * Prints what the matcher is matching against. The format will be 
3071
 * equal to the format passed to g_file_attribute_matcher_new().
3072
 * The output however, might not be identical, as the matcher may
3073
 * decide to use a different order or omit needless parts.
3074
 *
3075
 * Returns: a string describing the attributes the matcher matches
3076
 *   against or %NULL if @matcher was %NULL.
3077
 *
3078
 * Since: 2.32
3079
 **/
3080
char *
3081
g_file_attribute_matcher_to_string (GFileAttributeMatcher *matcher)
3082
0
{
3083
0
  GString *string;
3084
0
  guint i;
3085
3086
0
  if (matcher == NULL)
3087
0
    return NULL;
3088
3089
0
  if (matcher->all)
3090
0
    return g_strdup ("*");
3091
3092
0
  string = g_string_new ("");
3093
0
  for (i = 0; i < matcher->sub_matchers->len; i++)
3094
0
    {
3095
0
      SubMatcher *submatcher = &g_array_index (matcher->sub_matchers, SubMatcher, i);
3096
3097
0
      if (i > 0)
3098
0
        g_string_append_c (string, ',');
3099
3100
0
      g_string_append (string, get_attribute_for_id (submatcher->id));
3101
0
    }
3102
3103
0
  return g_string_free (string, FALSE);
3104
0
}