Coverage Report

Created: 2025-07-23 08:13

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